Fem: Change ConstraintPressure::Force property to App::PropertyForce

This commit is contained in:
Uwe
2023-10-03 21:13:17 -03:00
committed by marioalexis
parent bb97f4e4f3
commit af684644ab
11 changed files with 76 additions and 71 deletions

View File

@@ -42,6 +42,9 @@ ConstraintForce::ConstraintForce()
"ConstraintForce",
(App::PropertyType)(App::Prop_None),
"Element giving direction of constraint");
// RefDispl must get a global scope, see
Direction.setScope(App::LinkScope::Global);
ADD_PROPERTY(Reversed, (0));
ADD_PROPERTY_TYPE(Points,
(Base::Vector3d()),
@@ -53,8 +56,9 @@ ConstraintForce::ConstraintForce()
"ConstraintForce",
App::PropertyType(App::Prop_ReadOnly | App::Prop_Output),
"Direction of arrows");
naturalDirectionVector =
Base::Vector3d(0, 0, 0); // by default use the null vector to indicate an invalid value
// by default use the null vector to indicate an invalid value
naturalDirectionVector = Base::Vector3d(0, 0, 0);
Points.setValues(std::vector<Base::Vector3d>());
}
@@ -63,6 +67,21 @@ App::DocumentObjectExecReturn* ConstraintForce::execute()
return Constraint::execute();
}
void ConstraintForce::handleChangedPropertyType(Base::XMLReader& reader,
const char* TypeName,
App::Property* prop)
{
// property Force had App::PropertyFloat, was changed to App::PropertyForce
if (prop == &Force && strcmp(TypeName, "App::PropertyFloat") == 0) {
App::PropertyFloat ForceProperty;
// restore the PropertyFloat to be able to set its value
ForceProperty.Restore(reader);
// force uses m while FreeCAD uses internally mm thus
// e.g. "2.5" must become 2500 to result in 2.5 N
Force.setValue(ForceProperty.getValue() * 1000);
}
}
void ConstraintForce::onChanged(const App::Property* prop)
{
// Note: If we call this at the end, then the arrows are not oriented correctly initially

View File

@@ -38,7 +38,7 @@ public:
/// Constructor
ConstraintForce();
App::PropertyFloat Force;
App::PropertyForce Force;
App::PropertyLinkSub Direction;
App::PropertyBool Reversed;
// Read-only (calculated values). These trigger changes in the ViewProvider
@@ -55,6 +55,9 @@ public:
}
protected:
void handleChangedPropertyType(Base::XMLReader& reader,
const char* TypeName,
App::Property* prop) override;
void onChanged(const App::Property* prop) override;
private:

View File

@@ -57,35 +57,12 @@ TaskFemConstraintForce::TaskFemConstraintForce(ViewProviderFemConstraintForce* C
ui->setupUi(proxy);
QMetaObject::connectSlotsByName(this);
// create a context menu for the listview of the references
createDeleteAction(ui->listReferences);
connect(deleteAction, &QAction::triggered, this, &TaskFemConstraintForce::onReferenceDeleted);
connect(ui->spinForce,
qOverload<double>(&Gui::QuantitySpinBox::valueChanged),
this,
&TaskFemConstraintForce::onForceChanged);
connect(ui->buttonDirection,
&QToolButton::clicked,
this,
&TaskFemConstraintForce::onButtonDirection);
connect(ui->checkReverse, &QCheckBox::toggled, this, &TaskFemConstraintForce::onCheckReverse);
connect(ui->listReferences,
&QListWidget::itemClicked,
this,
&TaskFemConstraintForce::setSelection);
this->groupLayout()->addWidget(proxy);
// Temporarily prevent unnecessary feature recomputes
ui->spinForce->blockSignals(true);
ui->listReferences->blockSignals(true);
ui->buttonDirection->blockSignals(true);
ui->checkReverse->blockSignals(true);
// Get the feature data
Fem::ConstraintForce* pcConstraint =
static_cast<Fem::ConstraintForce*>(ConstraintView->getObject());
double f = pcConstraint->Force.getValue();
auto force = pcConstraint->Force.getQuantityValue();
std::vector<App::DocumentObject*> Objects = pcConstraint->References.getValues();
std::vector<std::string> SubElements = pcConstraint->References.getSubValues();
std::vector<std::string> dirStrings = pcConstraint->Direction.getSubValues();
@@ -96,9 +73,10 @@ TaskFemConstraintForce::TaskFemConstraintForce(ViewProviderFemConstraintForce* C
bool reversed = pcConstraint->Reversed.getValue();
// Fill data into dialog elements
ui->spinForce->setUnit(pcConstraint->Force.getUnit());
ui->spinForce->setMinimum(0);
ui->spinForce->setMaximum(FLOAT_MAX);
ui->spinForce->setValue(f);
ui->spinForce->setValue(force);
ui->listReferences->clear();
for (std::size_t i = 0; i < Objects.size(); i++) {
ui->listReferences->addItem(makeRefText(Objects[i], SubElements[i]));
@@ -109,15 +87,25 @@ TaskFemConstraintForce::TaskFemConstraintForce(ViewProviderFemConstraintForce* C
ui->lineDirection->setText(dir.isEmpty() ? QString() : dir);
ui->checkReverse->setChecked(reversed);
ui->spinForce->blockSignals(false);
ui->listReferences->blockSignals(false);
ui->buttonDirection->blockSignals(false);
ui->checkReverse->blockSignals(false);
// create a context menu for the listview of the references
createDeleteAction(ui->listReferences);
connect(deleteAction, &QAction::triggered, this, &TaskFemConstraintForce::onReferenceDeleted);
connect(ui->buttonDirection,
&QToolButton::clicked,
this,
&TaskFemConstraintForce::onButtonDirection);
connect(ui->checkReverse, &QCheckBox::toggled, this, &TaskFemConstraintForce::onCheckReverse);
connect(ui->listReferences,
&QListWidget::itemClicked,
this,
&TaskFemConstraintForce::setSelection);
// Selection buttons
buttonGroup->addButton(ui->btnAdd, (int)SelectionChangeModes::refAdd);
buttonGroup->addButton(ui->btnRemove, (int)SelectionChangeModes::refRemove);
ui->spinForce->bind(pcConstraint->Force);
updateUI();
}
@@ -259,13 +247,6 @@ void TaskFemConstraintForce::removeFromSelection()
updateUI();
}
void TaskFemConstraintForce::onForceChanged(double f)
{
Fem::ConstraintForce* pcConstraint =
static_cast<Fem::ConstraintForce*>(ConstraintView->getObject());
pcConstraint->Force.setValue(f);
}
void TaskFemConstraintForce::onReferenceDeleted()
{
TaskFemConstraintForce::removeFromSelection(); // OvG: On right-click face is automatically
@@ -359,9 +340,9 @@ void TaskFemConstraintForce::onCheckReverse(const bool pressed)
pcConstraint->Reversed.setValue(pressed);
}
double TaskFemConstraintForce::getForce() const
const std::string TaskFemConstraintForce::getForce() const
{
return ui->spinForce->value().getValue();
return ui->spinForce->value().getSafeUserString().toStdString();
}
const std::string TaskFemConstraintForce::getReferences() const
@@ -467,21 +448,10 @@ bool TaskDlgFemConstraintForce::accept()
static_cast<const TaskFemConstraintForce*>(parameter);
try {
// Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "FEM force constraint changed"));
if (parameterForce->getForce() <= 0) {
QMessageBox::warning(parameter,
tr("Input error"),
tr("Please specify a force greater than 0"));
return false;
}
else {
QByteArray num = QByteArray::number(parameterForce->getForce());
Gui::Command::doCommand(Gui::Command::Doc,
"App.ActiveDocument.%s.Force = %s",
name.c_str(),
num.data());
}
Gui::Command::doCommand(Gui::Command::Doc,
"App.ActiveDocument.%s.Force = \"%s\"",
name.c_str(),
parameterForce->getForce().c_str());
std::string dirname = parameterForce->getDirectionName().data();
std::string dirobj = parameterForce->getDirectionObject().data();

View File

@@ -55,7 +55,7 @@ public:
explicit TaskFemConstraintForce(ViewProviderFemConstraintForce* ConstraintView,
QWidget* parent = nullptr);
~TaskFemConstraintForce() override;
double getForce() const;
const std::string getForce() const;
const std::string getReferences() const override;
const std::string getDirectionName() const;
const std::string getDirectionObject() const;
@@ -63,7 +63,6 @@ public:
private Q_SLOTS:
void onReferenceDeleted();
void onForceChanged(double);
void onButtonDirection(const bool pressed = false);
void onCheckReverse(bool);
void addToSelection() override;

View File

@@ -90,12 +90,18 @@
<item>
<widget class="QLabel" name="labelForce">
<property name="text">
<string>Load [N]</string>
<string>Force</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::QuantitySpinBox" name="spinForce">
<property name="unit" stdset="0">
<string>N</string>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="value">
<double>500.000000000000000</double>
</property>

View File

@@ -803,7 +803,8 @@ def get_force_obj_vertex_nodeload_table(
# ("refshape_name.elemname", node_load_table)
# ]
force_obj_node_load_table = []
node_load = frc_obj.Force / len(frc_obj.References)
force_quantity = FreeCAD.Units.Quantity(frc_obj.Force.getValueAs("N"))
node_load = force_quantity / len(frc_obj.References)
for o, elem_tup in frc_obj.References:
node_count = len(elem_tup)
for elem in elem_tup:
@@ -863,7 +864,8 @@ def get_force_obj_edge_nodeload_table(
)
sum_ref_edge_length += ref_edge.Length
if sum_ref_edge_length != 0:
force_per_sum_ref_edge_length = frc_obj.Force / sum_ref_edge_length
force_quantity = FreeCAD.Units.Quantity(frc_obj.Force.getValueAs("N"))
force_per_sum_ref_edge_length = force_quantity / sum_ref_edge_length
for o, elem_tup in frc_obj.References:
for elem in elem_tup:
ref_edge = o.Shape.getElement(elem)
@@ -907,7 +909,8 @@ def get_force_obj_edge_nodeload_table(
for node in ref_shape[1]:
sum_node_load += ref_shape[1][node] # for debugging
ratio = sum_node_load / frc_obj.Force
force_quantity = FreeCAD.Units.Quantity(frc_obj.Force.getValueAs("N"))
ratio = sum_node_load / force_quantity
if ratio < 0.99 or ratio > 1.01:
FreeCAD.Console.PrintMessage(
"Deviation sum_node_load to frc_obj.Force is more than 1% : {}\n"
@@ -927,7 +930,7 @@ def get_force_obj_edge_nodeload_table(
)
FreeCAD.Console.PrintMessage(
" frc_obj.Force: {}\n"
.format(frc_obj.Force)
.format(force_quantity)
)
FreeCAD.Console.PrintMessage(
" the reason could be simply a circle length --> "
@@ -1135,7 +1138,8 @@ def get_force_obj_face_nodeload_table(
)
sum_ref_face_area += ref_face.Area
if sum_ref_face_area != 0:
force_per_sum_ref_face_area = frc_obj.Force / sum_ref_face_area
force_quantity = FreeCAD.Units.Quantity(frc_obj.Force.getValueAs("N"))
force_per_sum_ref_face_area = force_quantity / sum_ref_face_area
for o, elem_tup in frc_obj.References:
for elem in elem_tup:
ref_face = o.Shape.getElement(elem)
@@ -1178,7 +1182,8 @@ def get_force_obj_face_nodeload_table(
for node in ref_shape[1]:
sum_node_load += ref_shape[1][node] # for debugging
ratio = sum_node_load / frc_obj.Force
force_quantity = FreeCAD.Units.Quantity(frc_obj.Force.getValueAs("N"))
ratio = sum_node_load / force_quantity
if ratio < 0.99 or ratio > 1.01:
FreeCAD.Console.PrintMessage(
"Deviation sum_node_load to frc_obj.Force is more than 1% : {}\n"
@@ -1198,7 +1203,7 @@ def get_force_obj_face_nodeload_table(
)
FreeCAD.Console.PrintMessage(
" frc_obj.Force: {}\n"
.format(frc_obj.Force)
.format(force_quantity)
)
FreeCAD.Console.PrintMessage(
" the reason could be simply a circle area --> "

View File

@@ -54,14 +54,15 @@ def write_meshdata_constraint(f, femobj, force_obj, ccxwriter):
f.write("** {}\n".format(ref_shape[0]))
for n in sorted(ref_shape[1]):
node_load = ref_shape[1][n]
# the loads in ref_shape[1][n] are without unit
if abs(direction_vec.x) > dir_zero_tol:
v1 = "{:.13E}".format(direction_vec.x * node_load)
v1 = "{}".format(direction_vec.x * node_load)
f.write("{},1,{}\n".format(n, v1))
if abs(direction_vec.y) > dir_zero_tol:
v2 = "{:.13E}".format(direction_vec.y * node_load)
v2 = "{}".format(direction_vec.y * node_load)
f.write("{},2,{}\n".format(n, v2))
if abs(direction_vec.z) > dir_zero_tol:
v3 = "{:.13E}".format(direction_vec.z * node_load)
v3 = "{}".format(direction_vec.z * node_load)
f.write("{},3,{}\n".format(n, v3))
f.write("\n")
f.write("\n")

View File

@@ -97,7 +97,7 @@ class DeformationWriter:
for obj in self.write.getMember("Fem::ConstraintForce"):
if obj.References:
for name in obj.References[0][1]:
force = self.write.getFromUi(obj.Force, "N", "M*L*T^-2")
force = float(obj.Force.getValueAs("N"))
self.write.boundary(name, "Force 1", obj.DirectionVector.x * force)
self.write.boundary(name, "Force 2", obj.DirectionVector.y * force)
self.write.boundary(name, "Force 3", obj.DirectionVector.z * force)

View File

@@ -313,7 +313,7 @@ class ElasticityWriter:
for obj in self.write.getMember("Fem::ConstraintForce"):
if obj.References:
for name in obj.References[0][1]:
force = self.write.getFromUi(obj.Force, "N", "M*L*T^-2")
force = float(obj.Force.getValueAs("N"))
self.write.boundary(name, "Force 1", obj.DirectionVector.x * force)
self.write.boundary(name, "Force 2", obj.DirectionVector.y * force)
self.write.boundary(name, "Force 3", obj.DirectionVector.z * force)

View File

@@ -50,6 +50,7 @@ def add_con_force(f, model, mystran_writer):
for ref_shape in femobj["NodeLoadTable"]:
force_code += "# {}\n".format(ref_shape[0])
for n in sorted(ref_shape[1]):
# the loads in ref_shape[1][n] are without unit
node_load = ref_shape[1][n]
force_code += (
"model.add_force(sid={}, node={}, mag={}, xyz=({}, {}, {}))\n"

View File

@@ -157,6 +157,7 @@ class FemInputWriterZ88(writerbase.FemInputWriter):
direction_vec = femobj["Object"].DirectionVector
for ref_shape in femobj["NodeLoadTable"]:
for n in sorted(ref_shape[1]):
# the loads in ref_shape[1][n] are without unit
node_load = ref_shape[1][n]
if (direction_vec.x != 0.0):
v1 = direction_vec.x * node_load