Fem: Improve constraint contact - partial fixes #11653

This commit is contained in:
marioalexis
2024-01-26 01:13:59 -03:00
parent 0b76757b8a
commit 6e75703425
11 changed files with 296 additions and 96 deletions

View File

@@ -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<Base::Vector3d>());
Normals.setValues(std::vector<Base::Vector3d>());
}
@@ -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);
}
}

View File

@@ -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

View File

@@ -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",

View File

@@ -91,14 +91,36 @@ TaskFemConstraintContact::TaskFemConstraintContact(ViewProviderFemConstraintCont
std::vector<App::DocumentObject*> Objects = pcConstraint->References.getValues();
std::vector<std::string> 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<const char*>(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",

View File

@@ -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_TaskFemConstraintContact> ui;
};

View File

@@ -135,56 +135,123 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Contact Stiffness</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::InputField" name="spSlope">
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="maximum">
<double>1000000000.000000000000000</double>
</property>
<property name="unit" stdset="0">
<string notr="true">Pa</string>
</property>
<property name="value" stdset="0">
<double>1000000.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Friction coefficient</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spFriction">
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
</layout>
<widget class="QGroupBox" name="gpbParameter">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string/>
</property>
<property name="title">
<string>Parameters</string>
</property>
<layout class="QFormLayout" name="fltParameters">
<item row="0" column="0">
<widget class="QLabel" name="lblSlope">
<property name="text">
<string>Contact Stiffness</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Gui::QuantitySpinBox" name="spbSlope">
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="maximum">
<double>1000000000.000000000000000</double>
</property>
<property name="unit" stdset="0">
<string notr="true">GPa/m</string>
</property>
<property name="value" stdset="0">
<double>100.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblAdjust">
<property name="text">
<string>Clearance Adjustment</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Gui::QuantitySpinBox" name="spbAdjust">
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="unit" stdset="0">
<string notr="true">mm</string>
</property>
<property name="value" stdset="0">
<double>0.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="ckbFriction">
<property name="text">
<string>Enable Friction</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lblFrictionCoeff">
<property name="text">
<string>Friction Coefficient</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="Gui::DoubleSpinBox" name="spbFrictionCoeff">
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lblStickSlope">
<property name="text">
<string>Stick Slope</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="Gui::QuantitySpinBox" name="spbStickSlope">
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="maximum">
<double>1000000000.000000000000000</double>
</property>
<property name="unit" stdset="0">
<string notr="true">GPa/m</string>
</property>
<property name="value" stdset="0">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
<zorder>lbl_info_2</zorder>
@@ -194,9 +261,14 @@
</widget>
<customwidgets>
<customwidget>
<class>Gui::InputField</class>
<extends>QLineEdit</extends>
<header>Gui/InputField.h</header>
<class>Gui::QuantitySpinBox</class>
<extends>QWidget</extends>
<header>Gui/QuantitySpinBox.h</header>
</customwidget>
<customwidget>
<class>Gui::DoubleSpinBox</class>
<extends>QWidget</extends>
<header>Gui/SpinBox.h</header>
</customwidget>
</customwidgets>
<resources/>

View File

@@ -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

View File

@@ -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

View File

@@ -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))

View File

@@ -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
***********************************************************

View File

@@ -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
***********************************************************