Merge pull request #18807 from marioalexis84/fem-netgen_object_constraint
Fem: Use property constraints on mesh netgen object
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
#include <Base/Quantity.h>
|
||||
#include <Base/Stream.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <Base/PyWrapParseTupleAndKeywords.h>
|
||||
|
||||
#include "PropertyStandard.h"
|
||||
#include "Application.h"
|
||||
@@ -663,7 +664,7 @@ long PropertyIntegerConstraint::getMinimum() const
|
||||
return _ConstStruct->LowerBound;
|
||||
}
|
||||
// return the min of int, not long
|
||||
return std::numeric_limits<int>::min();
|
||||
return std::numeric_limits<int>::lowest();
|
||||
}
|
||||
|
||||
long PropertyIntegerConstraint::getMaximum() const
|
||||
@@ -700,41 +701,64 @@ void PropertyIntegerConstraint::setPyObject(PyObject* value)
|
||||
_lValue = temp;
|
||||
hasSetValue();
|
||||
}
|
||||
else if (PyTuple_Check(value) && PyTuple_Size(value) == 4) {
|
||||
long values[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
PyObject* item;
|
||||
item = PyTuple_GetItem(value, i);
|
||||
if (PyLong_Check(item)) {
|
||||
values[i] = PyLong_AsLong(item);
|
||||
else {
|
||||
long valConstr[] = {0,
|
||||
std::numeric_limits<int>::lowest(),
|
||||
std::numeric_limits<int>::max(),
|
||||
1};
|
||||
|
||||
if (PyDict_Check(value)) {
|
||||
Py::Tuple dummy;
|
||||
static const std::array<const char*, 5> kw = {"value",
|
||||
"min",
|
||||
"max",
|
||||
"step",
|
||||
nullptr};
|
||||
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(dummy.ptr(),
|
||||
value,
|
||||
"l|lll",
|
||||
kw,
|
||||
&(valConstr[0]),
|
||||
&(valConstr[1]),
|
||||
&(valConstr[2]),
|
||||
&(valConstr[3]))) {
|
||||
throw Py::Exception();
|
||||
}
|
||||
else {
|
||||
throw Base::TypeError("Type in tuple must be int");
|
||||
}
|
||||
else if (PyTuple_Check(value)) {
|
||||
if (!PyArg_ParseTuple(value,
|
||||
"llll",
|
||||
&(valConstr[0]),
|
||||
&(valConstr[1]),
|
||||
&(valConstr[2]),
|
||||
&(valConstr[3]))) {
|
||||
throw Py::Exception();
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type must be int, dict or tuple, not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
|
||||
Constraints* c = new Constraints();
|
||||
c->setDeletable(true);
|
||||
c->LowerBound = values[1];
|
||||
c->UpperBound = values[2];
|
||||
c->StepSize = std::max<long>(1, values[3]);
|
||||
if (values[0] > c->UpperBound) {
|
||||
values[0] = c->UpperBound;
|
||||
c->LowerBound = valConstr[1];
|
||||
c->UpperBound = valConstr[2];
|
||||
c->StepSize = std::max<long>(1, valConstr[3]);
|
||||
if (valConstr[0] > c->UpperBound) {
|
||||
valConstr[0] = c->UpperBound;
|
||||
}
|
||||
else if (values[0] < c->LowerBound) {
|
||||
values[0] = c->LowerBound;
|
||||
else if (valConstr[0] < c->LowerBound) {
|
||||
valConstr[0] = c->LowerBound;
|
||||
}
|
||||
setConstraints(c);
|
||||
|
||||
aboutToSetValue();
|
||||
_lValue = values[0];
|
||||
_lValue = valConstr[0];
|
||||
hasSetValue();
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type must be int, not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
@@ -1122,7 +1146,7 @@ double PropertyFloatConstraint::getMinimum() const
|
||||
if (_ConstStruct) {
|
||||
return _ConstStruct->LowerBound;
|
||||
}
|
||||
return std::numeric_limits<double>::min();
|
||||
return std::numeric_limits<double>::lowest();
|
||||
}
|
||||
|
||||
double PropertyFloatConstraint::getMaximum() const
|
||||
@@ -1159,7 +1183,7 @@ void PropertyFloatConstraint::setPyObject(PyObject* value)
|
||||
hasSetValue();
|
||||
}
|
||||
else if (PyLong_Check(value)) {
|
||||
double temp = (double)PyLong_AsLong(value);
|
||||
double temp = static_cast<double>(PyLong_AsLong(value));
|
||||
if (_ConstStruct) {
|
||||
if (temp > _ConstStruct->UpperBound) {
|
||||
temp = _ConstStruct->UpperBound;
|
||||
@@ -1173,23 +1197,48 @@ void PropertyFloatConstraint::setPyObject(PyObject* value)
|
||||
_dValue = temp;
|
||||
hasSetValue();
|
||||
}
|
||||
else if (PyTuple_Check(value) && PyTuple_Size(value) == 4) {
|
||||
double values[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
PyObject* item;
|
||||
item = PyTuple_GetItem(value, i);
|
||||
if (PyFloat_Check(item)) {
|
||||
values[i] = PyFloat_AsDouble(item);
|
||||
}
|
||||
else if (PyLong_Check(item)) {
|
||||
values[i] = PyLong_AsLong(item);
|
||||
}
|
||||
else {
|
||||
throw Base::TypeError("Type in tuple must be float or int");
|
||||
else {
|
||||
double valConstr[] = {0.0,
|
||||
std::numeric_limits<double>::lowest(),
|
||||
std::numeric_limits<double>::max(),
|
||||
1.0};
|
||||
|
||||
if (PyDict_Check(value)) {
|
||||
Py::Tuple dummy;
|
||||
static const std::array<const char*, 5> kw = {"value",
|
||||
"min",
|
||||
"max",
|
||||
"step",
|
||||
nullptr};
|
||||
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(dummy.ptr(),
|
||||
value,
|
||||
"d|ddd",
|
||||
kw,
|
||||
&(valConstr[0]),
|
||||
&(valConstr[1]),
|
||||
&(valConstr[2]),
|
||||
&(valConstr[3]))) {
|
||||
throw Py::Exception();
|
||||
}
|
||||
}
|
||||
else if (PyTuple_Check(value)) {
|
||||
if (!PyArg_ParseTuple(value,
|
||||
"dddd",
|
||||
&(valConstr[0]),
|
||||
&(valConstr[1]),
|
||||
&(valConstr[2]),
|
||||
&(valConstr[3]))) {
|
||||
throw Py::Exception();
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type must be float, dict or tuple, not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
|
||||
double stepSize = values[3];
|
||||
double stepSize = valConstr[3];
|
||||
// need a value > 0
|
||||
if (stepSize < DBL_EPSILON) {
|
||||
throw Base::ValueError("Step size must be greater than zero");
|
||||
@@ -1197,26 +1246,21 @@ void PropertyFloatConstraint::setPyObject(PyObject* value)
|
||||
|
||||
Constraints* c = new Constraints();
|
||||
c->setDeletable(true);
|
||||
c->LowerBound = values[1];
|
||||
c->UpperBound = values[2];
|
||||
c->LowerBound = valConstr[1];
|
||||
c->UpperBound = valConstr[2];
|
||||
c->StepSize = stepSize;
|
||||
if (values[0] > c->UpperBound) {
|
||||
values[0] = c->UpperBound;
|
||||
if (valConstr[0] > c->UpperBound) {
|
||||
valConstr[0] = c->UpperBound;
|
||||
}
|
||||
else if (values[0] < c->LowerBound) {
|
||||
values[0] = c->LowerBound;
|
||||
else if (valConstr[0] < c->LowerBound) {
|
||||
valConstr[0] = c->LowerBound;
|
||||
}
|
||||
setConstraints(c);
|
||||
|
||||
aboutToSetValue();
|
||||
_dValue = values[0];
|
||||
_dValue = valConstr[0];
|
||||
hasSetValue();
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type must be float, not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
|
||||
@@ -77,11 +77,11 @@ class MeshNetgen(base_fempythonobject.BaseFemPythonObject):
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyInteger",
|
||||
type="App::PropertyIntegerConstraint",
|
||||
name="OptimizationSteps3d",
|
||||
group="Mesh Parameters",
|
||||
doc="Number of 3d optimization steps",
|
||||
value=3,
|
||||
value={"value": 3, "min": 0},
|
||||
)
|
||||
)
|
||||
prop.append(
|
||||
@@ -98,11 +98,11 @@ class MeshNetgen(base_fempythonobject.BaseFemPythonObject):
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyInteger",
|
||||
type="App::PropertyIntegerConstraint",
|
||||
name="OptimizationSteps2d",
|
||||
group="Mesh Parameters",
|
||||
doc="Number of 2d optimization steps",
|
||||
value=3,
|
||||
value={"value": 3, "min": 0},
|
||||
)
|
||||
)
|
||||
prop.append(
|
||||
@@ -134,20 +134,20 @@ class MeshNetgen(base_fempythonobject.BaseFemPythonObject):
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyFloat",
|
||||
type="App::PropertyFloatConstraint",
|
||||
name="Safety",
|
||||
group="Mesh Parameters",
|
||||
doc="Radius of local environment (times h)",
|
||||
value=5.0,
|
||||
value={"value": 5.0, "min": 0, "step": 0.1},
|
||||
)
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyFloat",
|
||||
type="App::PropertyFloatConstraint",
|
||||
name="RelinnerSafety",
|
||||
group="Mesh Parameters",
|
||||
doc="Radius of active environment (times h)",
|
||||
value=3.0,
|
||||
value={"value": 3.0, "min": 0, "step": 0.1},
|
||||
)
|
||||
)
|
||||
prop.append(
|
||||
@@ -170,11 +170,11 @@ class MeshNetgen(base_fempythonobject.BaseFemPythonObject):
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyFloat",
|
||||
type="App::PropertyFloatConstraint",
|
||||
name="GrowthRate",
|
||||
group="Mesh Parameters",
|
||||
doc="Grading for local h",
|
||||
value=0.3,
|
||||
value={"value": 0.3, "min": 0, "step": 0.1},
|
||||
)
|
||||
)
|
||||
prop.append(
|
||||
@@ -215,11 +215,11 @@ class MeshNetgen(base_fempythonobject.BaseFemPythonObject):
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyFloat",
|
||||
type="App::PropertyFloatConstraint",
|
||||
name="CloseEdgeFactor",
|
||||
group="Mesh Parameters",
|
||||
doc="Factor to restrict meshing based on close edges",
|
||||
value=2.0,
|
||||
value={"value": 2.0, "min": 0, "step": 0.1},
|
||||
)
|
||||
)
|
||||
prop.append(
|
||||
@@ -260,29 +260,29 @@ class MeshNetgen(base_fempythonobject.BaseFemPythonObject):
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyFloat",
|
||||
type="App::PropertyFloatConstraint",
|
||||
name="CurvatureSafety",
|
||||
group="Mesh Parameters",
|
||||
doc="Safety factor for curvatures (elements per radius)",
|
||||
value=2.0,
|
||||
value={"value": 2.0, "min": 0, "step": 0.1},
|
||||
)
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyFloat",
|
||||
type="App::PropertyFloatConstraint",
|
||||
name="SegmentsPerEdge",
|
||||
group="Mesh Parameters",
|
||||
doc="Minimal number of segments per edge",
|
||||
value=2.0,
|
||||
value={"value": 2.0, "min": 0, "step": 0.1},
|
||||
)
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyFloat",
|
||||
type="App::PropertyFloatConstraint",
|
||||
name="ElementSizeWeight",
|
||||
group="Mesh Parameters",
|
||||
doc="Weight of element size respect to element shape",
|
||||
value=0.2,
|
||||
doc="Weight of element size respect to element shape",
|
||||
value={"value": 0.2, "min": 0, "step": 0.1},
|
||||
)
|
||||
)
|
||||
|
||||
@@ -316,47 +316,47 @@ class MeshNetgen(base_fempythonobject.BaseFemPythonObject):
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyInteger",
|
||||
type="App::PropertyIntegerConstraint",
|
||||
name="GiveUpTolerance2d",
|
||||
group="Mesh Parameters",
|
||||
doc="Give up quality class, 2d meshing",
|
||||
value=200,
|
||||
value={"value": 200, "min": 0},
|
||||
)
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyInteger",
|
||||
type="App::PropertyIntegerConstraint",
|
||||
name="GiveUpTolerance",
|
||||
group="Mesh Parameters",
|
||||
doc="Give up quality class, 3d meshing",
|
||||
value=10,
|
||||
value={"value": 10, "min": 0},
|
||||
)
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyInteger",
|
||||
type="App::PropertyIntegerConstraint",
|
||||
name="GiveUpToleranceOpenQuads",
|
||||
group="Mesh Parameters",
|
||||
doc="Give up quality class, for closing open quads, greater than 100 for free pyramids",
|
||||
value=15,
|
||||
value={"value": 15, "min": 0},
|
||||
)
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyInteger",
|
||||
type="App::PropertyIntegerConstraint",
|
||||
name="MaxOuterSteps",
|
||||
group="Mesh Parameters",
|
||||
doc="Maximal outer steps",
|
||||
value=10,
|
||||
value={"value": 10, "min": 0},
|
||||
)
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyInteger",
|
||||
type="App::PropertyIntegerConstraint",
|
||||
name="StarShapeClass",
|
||||
group="Mesh Parameters",
|
||||
doc="Class starting star-shape filling",
|
||||
value=5,
|
||||
value={"value": 5, "min": 0},
|
||||
)
|
||||
)
|
||||
prop.append(
|
||||
@@ -370,20 +370,20 @@ class MeshNetgen(base_fempythonobject.BaseFemPythonObject):
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyInteger",
|
||||
type="App::PropertyIntegerConstraint",
|
||||
name="Sloppy",
|
||||
group="Mesh Parameters",
|
||||
doc="Quality tolerances are handled less careful",
|
||||
value=10,
|
||||
value={"value": 10, "min": 0},
|
||||
)
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyFloat",
|
||||
type="App::PropertyFloatConstraint",
|
||||
name="BadElementLimit",
|
||||
group="Mesh Parameters",
|
||||
doc="Limit for max element angle (150-180)",
|
||||
value=175,
|
||||
value={"value": 175, "min": 0},
|
||||
)
|
||||
)
|
||||
prop.append(
|
||||
@@ -424,11 +424,11 @@ class MeshNetgen(base_fempythonobject.BaseFemPythonObject):
|
||||
)
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyInteger",
|
||||
type="App::PropertyIntegerConstraint",
|
||||
name="ElementOrder",
|
||||
group="Mesh Parameters",
|
||||
doc="High order element curvature",
|
||||
value=False,
|
||||
value={"value": 1, "min": 1},
|
||||
)
|
||||
)
|
||||
prop.append(
|
||||
|
||||
Reference in New Issue
Block a user