diff --git a/src/Mod/Fem/App/FemConstraintContact.cpp b/src/Mod/Fem/App/FemConstraintContact.cpp index d49c67c262..f4d4fa5268 100644 --- a/src/Mod/Fem/App/FemConstraintContact.cpp +++ b/src/Mod/Fem/App/FemConstraintContact.cpp @@ -33,9 +33,31 @@ PROPERTY_SOURCE(Fem::ConstraintContact, Fem::Constraint) ConstraintContact::ConstraintContact() { /*Note: Initialise parameters here*/ - ADD_PROPERTY(Slope, (0.0)); - ADD_PROPERTY(Friction, (0.0)); - /* */ + ADD_PROPERTY_TYPE(Slope, + (0.0), + "ConstraintContact", + App::PropertyType(App::Prop_None), + "Contact stiffness"); + ADD_PROPERTY_TYPE(Adjust, + (0.0), + "ConstraintContact", + App::PropertyType(App::Prop_None), + "Node clearance adjustment limit"); + ADD_PROPERTY_TYPE(Friction, + (false), + "ConstraintContact", + App::PropertyType(App::Prop_None), + "Enable friction interaction"); + ADD_PROPERTY_TYPE(FrictionCoefficient, + (0.0), + "ConstraintContact", + App::PropertyType(App::Prop_None), + "Friction coefficient"); + ADD_PROPERTY_TYPE(StickSlope, + (0.0), + "ConstraintContact", + App::PropertyType(App::Prop_None), + "Stick slope"); ADD_PROPERTY_TYPE(Points, (Base::Vector3d()), @@ -47,6 +69,7 @@ ConstraintContact::ConstraintContact() "ConstraintContact", App::PropertyType(App::Prop_ReadOnly | App::Prop_Output), "Normals where symbols are drawn"); + /* */ Points.setValues(std::vector()); Normals.setValues(std::vector()); } @@ -77,3 +100,28 @@ void ConstraintContact::onChanged(const App::Property* prop) } } } + +void ConstraintContact::handleChangedPropertyType(Base::XMLReader& reader, + const char* typeName, + App::Property* prop) +{ + if (prop == &Slope && strcmp(typeName, "App::PropertyFloat") == 0) { + App::PropertyFloat oldSlope; + oldSlope.Restore(reader); + // old slope value stored as MPa/mm equivalent to 1e3 kg/(mm^2*s^2) + Slope.setValue(oldSlope.getValue() * 1000); + + // stick slope internally generated as slope/10 + StickSlope.setValue(Slope.getValue() / 10); + } + else if (prop == &Friction && strcmp(typeName, "App::PropertyFloat") == 0) { + App::PropertyFloat oldFriction; + oldFriction.Restore(reader); + FrictionCoefficient.setValue(oldFriction.getValue()); + + Friction.setValue(oldFriction.getValue() > 0 ? true : false); + } + else { + Constraint::handleChangedPropertyType(reader, typeName, prop); + } +} diff --git a/src/Mod/Fem/App/FemConstraintContact.h b/src/Mod/Fem/App/FemConstraintContact.h index 60c82cfbf9..68b17eef8b 100644 --- a/src/Mod/Fem/App/FemConstraintContact.h +++ b/src/Mod/Fem/App/FemConstraintContact.h @@ -50,8 +50,11 @@ public: * This is only the definitions of the variables ******/ // ex. - App::PropertyFloat Slope; - App::PropertyFloat Friction; + App::PropertyStiffnessDensity Slope; + App::PropertyLength Adjust; + App::PropertyBool Friction; + App::PropertyFloat FrictionCoefficient; + App::PropertyStiffnessDensity StickSlope; // etc /* */ @@ -64,6 +67,9 @@ public: protected: void onChanged(const App::Property* prop) override; + void handleChangedPropertyType(Base::XMLReader& reader, + const char* typeName, + App::Property* prop) override; }; } // namespace Fem diff --git a/src/Mod/Fem/Gui/Command.cpp b/src/Mod/Fem/Gui/Command.cpp index 82f82e1a3f..0f5f1d8d1c 100644 --- a/src/Mod/Fem/Gui/Command.cpp +++ b/src/Mod/Fem/Gui/Command.cpp @@ -250,10 +250,19 @@ void CmdFemConstraintContact::activated(int) "App.activeDocument().addObject(\"Fem::ConstraintContact\",\"%s\")", FeatName.c_str()); doCommand(Doc, - "App.activeDocument().%s.Slope = 1000000.00", + "App.activeDocument().%s.Slope = \"1e6 GPa/m\"", FeatName.c_str()); // OvG: set default not equal to 0 doCommand(Doc, - "App.activeDocument().%s.Friction = 0.0", + "App.activeDocument().%s.Adjust = 0.0", + FeatName.c_str()); // OvG: set default equal to 0 + doCommand(Doc, + "App.activeDocument().%s.Friction = False", + FeatName.c_str()); // OvG: set default equal to 0 + doCommand(Doc, + "App.activeDocument().%s.FrictionCoefficient = 0.0", + FeatName.c_str()); // OvG: set default equal to 0 + doCommand(Doc, + "App.activeDocument().%s.StickSlope = \"1e4 GPa/m\"", FeatName.c_str()); // OvG: set default not equal to 0 doCommand(Doc, "App.activeDocument().%s.Scale = 1", diff --git a/src/Mod/Fem/Gui/TaskFemConstraintContact.cpp b/src/Mod/Fem/Gui/TaskFemConstraintContact.cpp index cc15da6dbb..d515c44438 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintContact.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintContact.cpp @@ -91,14 +91,36 @@ TaskFemConstraintContact::TaskFemConstraintContact(ViewProviderFemConstraintCont std::vector Objects = pcConstraint->References.getValues(); std::vector SubElements = pcConstraint->References.getSubValues(); - double slope = pcConstraint->Slope.getValue(); - double friction = pcConstraint->Friction.getValue(); + + bool friction = pcConstraint->Friction.getValue(); // Fill data into dialog elements - ui->spSlope->setMinimum(1.0); - ui->spSlope->setValue(slope); - ui->spFriction->setValue(friction); + ui->spbSlope->setUnit(pcConstraint->Slope.getUnit()); + ui->spbSlope->setMinimum(0); + ui->spbSlope->setMaximum(FLOAT_MAX); + ui->spbSlope->setValue(pcConstraint->Slope.getQuantityValue()); + ui->spbSlope->bind(pcConstraint->Slope); + ui->spbAdjust->setUnit(pcConstraint->Adjust.getUnit()); + ui->spbAdjust->setMinimum(0); + ui->spbAdjust->setMaximum(FLOAT_MAX); + ui->spbAdjust->setValue(pcConstraint->Adjust.getQuantityValue()); + ui->spbAdjust->bind(pcConstraint->Adjust); + + ui->ckbFriction->setChecked(friction); + + ui->spbFrictionCoeff->setMinimum(0); + ui->spbFrictionCoeff->setMaximum(FLOAT_MAX); + ui->spbFrictionCoeff->setValue(pcConstraint->FrictionCoefficient.getValue()); + ui->spbFrictionCoeff->setEnabled(friction); + ui->spbFrictionCoeff->bind(pcConstraint->FrictionCoefficient); + + ui->spbStickSlope->setUnit(pcConstraint->StickSlope.getUnit()); + ui->spbStickSlope->setMinimum(0); + ui->spbStickSlope->setMaximum(FLOAT_MAX); + ui->spbStickSlope->setValue(pcConstraint->StickSlope.getQuantityValue()); + ui->spbStickSlope->setEnabled(friction); + ui->spbStickSlope->bind(pcConstraint->StickSlope); /* */ ui->lw_referencesMaster->clear(); @@ -136,6 +158,11 @@ TaskFemConstraintContact::TaskFemConstraintContact(ViewProviderFemConstraintCont this, &TaskFemConstraintContact::removeFromSelectionMaster); + connect(ui->ckbFriction, + &QCheckBox::toggled, + this, + &TaskFemConstraintContact::onFrictionChanged); + updateUI(); } @@ -428,6 +455,12 @@ void TaskFemConstraintContact::onReferenceDeletedMaster() TaskFemConstraintContact::removeFromSelectionMaster(); } +void TaskFemConstraintContact::onFrictionChanged(bool state) +{ + ui->spbFrictionCoeff->setEnabled(state); + ui->spbStickSlope->setEnabled(state); +} + const std::string TaskFemConstraintContact::getReferences() const { int rowsSlave = ui->lw_referencesSlave->model()->rowCount(); @@ -443,15 +476,29 @@ const std::string TaskFemConstraintContact::getReferences() const return TaskFemConstraint::getReferences(items); } -/* Note: */ -double TaskFemConstraintContact::get_Slope() const +const std::string TaskFemConstraintContact::getSlope() const { - return ui->spSlope->rawValue(); + return ui->spbSlope->value().getSafeUserString().toStdString(); } -double TaskFemConstraintContact::get_Friction() const +const std::string TaskFemConstraintContact::getAdjust() const { - return ui->spFriction->value(); + return ui->spbAdjust->value().getSafeUserString().toStdString(); +} + +bool TaskFemConstraintContact::getFriction() const +{ + return ui->ckbFriction->isChecked(); +} + +double TaskFemConstraintContact::getFrictionCoeff() const +{ + return ui->spbFrictionCoeff->value(); +} + +const std::string TaskFemConstraintContact::getStickSlope() const +{ + return ui->spbStickSlope->value().getSafeUserString().toStdString(); } void TaskFemConstraintContact::changeEvent(QEvent*) @@ -478,7 +525,7 @@ void TaskDlgFemConstraintContact::open() // a transaction is already open at creation time of the panel if (!Gui::Command::hasPendingCommand()) { QString msg = QObject::tr("Contact constraint"); - Gui::Command::openCommand((const char*)msg.toUtf8()); + Gui::Command::openCommand(static_cast(msg.toUtf8())); ConstraintView->setVisible(true); Gui::Command::runCommand( Gui::Command::Doc, @@ -497,13 +544,25 @@ bool TaskDlgFemConstraintContact::accept() try { Gui::Command::doCommand(Gui::Command::Doc, - "App.ActiveDocument.%s.Slope = %f", + "App.ActiveDocument.%s.Slope = \"%s\"", name.c_str(), - parameterContact->get_Slope()); + parameterContact->getSlope().c_str()); Gui::Command::doCommand(Gui::Command::Doc, - "App.ActiveDocument.%s.Friction = %f", + "App.ActiveDocument.%s.Adjust = \"%s\"", name.c_str(), - parameterContact->get_Friction()); + parameterContact->getAdjust().c_str()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.Friction = %s", + name.c_str(), + parameterContact->getFriction() ? "True" : "False"); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.FrictionCoefficient = %f", + name.c_str(), + parameterContact->getFrictionCoeff()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.StickSlope = \"%s\"", + name.c_str(), + parameterContact->getStickSlope().c_str()); std::string scale = parameterContact->getScale(); // OvG: determine modified scale Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.Scale = %s", diff --git a/src/Mod/Fem/Gui/TaskFemConstraintContact.h b/src/Mod/Fem/Gui/TaskFemConstraintContact.h index cc7891a667..b5f78a6ec2 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintContact.h +++ b/src/Mod/Fem/Gui/TaskFemConstraintContact.h @@ -46,8 +46,11 @@ public: QWidget* parent = nullptr); ~TaskFemConstraintContact() override; const std::string getReferences() const override; - double get_Slope() const; - double get_Friction() const; + const std::string getAdjust() const; + const std::string getSlope() const; + bool getFriction() const; + const std::string getStickSlope() const; + double getFrictionCoeff() const; private Q_SLOTS: void onReferenceDeletedSlave(); @@ -56,12 +59,12 @@ private Q_SLOTS: void removeFromSelectionSlave(); void addToSelectionMaster(); void removeFromSelectionMaster(); + void onFrictionChanged(bool); protected: void changeEvent(QEvent* e) override; private: - // void onSelectionChanged(const Gui::SelectionChanges& msg); void updateUI(); std::unique_ptr ui; }; diff --git a/src/Mod/Fem/Gui/TaskFemConstraintContact.ui b/src/Mod/Fem/Gui/TaskFemConstraintContact.ui index 0d86b655fe..3fca07dde2 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintContact.ui +++ b/src/Mod/Fem/Gui/TaskFemConstraintContact.ui @@ -135,56 +135,123 @@ + - - - - - Contact Stiffness - - - - - - - 1.000000000000000 - - - 1000000000.000000000000000 - - - Pa - - - 1000000.000000000000000 - - - - - - - - - - - Friction coefficient - - - - - - - 2 - - - 1.000000000000000 - - - 0.100000000000000 - - - - + + + + 0 + 0 + + + + + + + Parameters + + + + + + Contact Stiffness + + + + + + + 1.000000000000000 + + + 1000000000.000000000000000 + + + GPa/m + + + 100.000000000000000 + + + + + + + Clearance Adjustment + + + + + + + 0.000000000000000 + + + mm + + + 0.000000000000000 + + + 0.100000000000000 + + + + + + + Enable Friction + + + + + + + Friction Coefficient + + + + + + + 2 + + + 0.000000000000000 + + + 0.000000000000000 + + + 0.100000000000000 + + + + + + + Stick Slope + + + + + + + 1.000000000000000 + + + 1000000000.000000000000000 + + + GPa/m + + + 1.000000000000000 + + + + + lbl_info_2 @@ -194,9 +261,14 @@ - Gui::InputField - QLineEdit -
Gui/InputField.h
+ Gui::QuantitySpinBox + QWidget +
Gui/QuantitySpinBox.h
+
+ + Gui::DoubleSpinBox + QWidget +
Gui/SpinBox.h
diff --git a/src/Mod/Fem/femexamples/constraint_contact_shell_shell.py b/src/Mod/Fem/femexamples/constraint_contact_shell_shell.py index 3e6464a041..2d2b42af80 100644 --- a/src/Mod/Fem/femexamples/constraint_contact_shell_shell.py +++ b/src/Mod/Fem/femexamples/constraint_contact_shell_shell.py @@ -193,9 +193,8 @@ def setup(doc=None, solvertype="ccxtools"): (lower_tube, "Face1"), (upper_tube, "Face1"), ] - con_contact.Friction = 0.0 - # con_contact.Slope = "1000000.0 kg/(mm*s^2)" # contact stiffness - con_contact.Slope = 1000000.0 # should be 1000000.0 kg/(mm*s^2) + con_contact.Friction = False + con_contact.Slope = "1000000.0 GPa/m" analysis.addObject(con_contact) # mesh diff --git a/src/Mod/Fem/femexamples/constraint_contact_solid_solid.py b/src/Mod/Fem/femexamples/constraint_contact_solid_solid.py index c3efe9b189..d2392d1d2a 100644 --- a/src/Mod/Fem/femexamples/constraint_contact_solid_solid.py +++ b/src/Mod/Fem/femexamples/constraint_contact_solid_solid.py @@ -177,8 +177,8 @@ def setup(doc=None, solvertype="ccxtools"): (geom_obj, "Face7"), # first seams slave face, TODO proof in writer code! (geom_obj, "Face3"), # second seams master face, TODO proof in writer code! ] - con_contact.Friction = 0.0 - con_contact.Slope = 1000000.0 # contact stiffness 1000000.0 kg/(mm*s^2) + con_contact.Friction = False + con_contact.Slope = "1000000.0 GPa/m" analysis.addObject(con_contact) # mesh diff --git a/src/Mod/Fem/femsolver/calculix/write_constraint_contact.py b/src/Mod/Fem/femsolver/calculix/write_constraint_contact.py index c8527975f6..a9c0bcc9dd 100644 --- a/src/Mod/Fem/femsolver/calculix/write_constraint_contact.py +++ b/src/Mod/Fem/femsolver/calculix/write_constraint_contact.py @@ -68,20 +68,24 @@ def write_meshdata_constraint(f, femobj, contact_obj, ccxwriter): def write_constraint(f, femobj, contact_obj, ccxwriter): # floats read from ccx should use {:.13G}, see comment in writer module + adjust = "" + if contact_obj.Adjust.Value > 0: + adjust = ", ADJUST={:.13G}".format( + contact_obj.Adjust.getValueAs("mm").Value) f.write( - "*CONTACT PAIR, INTERACTION=INT{},TYPE=SURFACE TO SURFACE\n" - .format(contact_obj.Name) + "*CONTACT PAIR, INTERACTION=INT{}, TYPE=SURFACE TO SURFACE{}\n" + .format(contact_obj.Name, adjust) ) ind_surf = "IND" + contact_obj.Name dep_surf = "DEP" + contact_obj.Name - f.write("{},{}\n".format(dep_surf, ind_surf)) + f.write("{}, {}\n".format(dep_surf, ind_surf)) f.write("*SURFACE INTERACTION, NAME=INT{}\n".format(contact_obj.Name)) - f.write("*SURFACE BEHAVIOR,PRESSURE-OVERCLOSURE=LINEAR\n") - slope = contact_obj.Slope + f.write("*SURFACE BEHAVIOR, PRESSURE-OVERCLOSURE=LINEAR\n") + slope = contact_obj.Slope.getValueAs("MPa/mm").Value f.write("{:.13G}\n".format(slope)) - friction = contact_obj.Friction - if friction > 0: - f.write("*FRICTION \n") - stick = (slope / 10.0) + if contact_obj.Friction: + f.write("*FRICTION\n") + friction = contact_obj.FrictionCoefficient + stick = contact_obj.StickSlope.getValueAs("MPa/mm").Value f.write("{:.13G}, {:.13G}\n".format(friction, stick)) diff --git a/src/Mod/Fem/femtest/data/calculix/constraint_contact_shell_shell.inp b/src/Mod/Fem/femtest/data/calculix/constraint_contact_shell_shell.inp index 437d5c7feb..4f696b5b7d 100644 --- a/src/Mod/Fem/femtest/data/calculix/constraint_contact_shell_shell.inp +++ b/src/Mod/Fem/femtest/data/calculix/constraint_contact_shell_shell.inp @@ -38365,10 +38365,10 @@ Efaces *********************************************************** ** Contact Constraints ** ConstraintContact -*CONTACT PAIR, INTERACTION=INTConstraintContact,TYPE=SURFACE TO SURFACE -DEPConstraintContact,INDConstraintContact +*CONTACT PAIR, INTERACTION=INTConstraintContact, TYPE=SURFACE TO SURFACE +DEPConstraintContact, INDConstraintContact *SURFACE INTERACTION, NAME=INTConstraintContact -*SURFACE BEHAVIOR,PRESSURE-OVERCLOSURE=LINEAR +*SURFACE BEHAVIOR, PRESSURE-OVERCLOSURE=LINEAR 1000000 *********************************************************** diff --git a/src/Mod/Fem/femtest/data/calculix/constraint_contact_solid_solid.inp b/src/Mod/Fem/femtest/data/calculix/constraint_contact_solid_solid.inp index 883a37b530..5d315d93ad 100644 --- a/src/Mod/Fem/femtest/data/calculix/constraint_contact_solid_solid.inp +++ b/src/Mod/Fem/femtest/data/calculix/constraint_contact_solid_solid.inp @@ -5572,10 +5572,10 @@ Evolumes *********************************************************** ** Contact Constraints ** ConstraintContact -*CONTACT PAIR, INTERACTION=INTConstraintContact,TYPE=SURFACE TO SURFACE +*CONTACT PAIR, INTERACTION=INTConstraintContact, TYPE=SURFACE TO SURFACE DEPConstraintContact,INDConstraintContact *SURFACE INTERACTION, NAME=INTConstraintContact -*SURFACE BEHAVIOR,PRESSURE-OVERCLOSURE=LINEAR +*SURFACE BEHAVIOR, PRESSURE-OVERCLOSURE=LINEAR 1000000 ***********************************************************