FEM: solver calculix, add buckling analysis

Implementation of buckling analysis between the solver Calculix and FreeCAD
This commit is contained in:
Tobias Vaara
2021-02-06 03:35:44 -08:00
committed by Bernd Hahnebach
parent 09f441c93e
commit 8e25fe33dc
4 changed files with 57 additions and 24 deletions

View File

@@ -61,7 +61,28 @@
<property name="bottomMargin">
<number>9</number>
</property>
<item row="0" column="0">
<item row="2" column="0">
<widget class="Gui::PrefRadioButton" name="rb_thermomech_analysis">
<property name="text">
<string>Thermo mechanical</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="Gui::PrefRadioButton" name="rb_check_mesh">
<property name="text">
<string>Check Mesh</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="Gui::PrefRadioButton" name="rb_frequency_analysis">
<property name="text">
<string>Frequency</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="Gui::PrefRadioButton" name="rb_static_analysis">
<property name="text">
<string>Static</string>
@@ -71,24 +92,10 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Gui::PrefRadioButton" name="rb_frequency_analysis">
<item row="3" column="0">
<widget class="Gui::PrefRadioButton" name="rb_buckling_analysis">
<property name="text">
<string>Frequency</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="Gui::PrefRadioButton" name="rb_thermomech_analysis">
<property name="text">
<string>Thermo mechanical</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Gui::PrefRadioButton" name="rb_check_mesh">
<property name="text">
<string>Check Mesh</string>
<string>Buckling</string>
</property>
</widget>
</item>

View File

@@ -41,7 +41,7 @@ from femtools import femutils
if FreeCAD.GuiUp:
import FemGui
ANALYSIS_TYPES = ["static", "frequency", "thermomech", "check"]
ANALYSIS_TYPES = ["static", "frequency", "thermomech", "check", "buckling"]
def create(doc, name="SolverCalculiX"):
@@ -165,6 +165,15 @@ def add_attributes(obj, ccx_prefs):
niter = ccx_prefs.GetInt("AnalysisMaxIterations", 200)
obj.IterationsThermoMechMaximum = niter
obj.addProperty(
"App::PropertyIntegerConstraint",
"BucklingFactors",
"Fem",
"Calculates the lowest buckling modes to the corresponding buckling factors"
)
bckl = ccx_prefs.GetInt("BucklingFactors", 1)
obj.BucklingFactors = bckl
obj.addProperty(
"App::PropertyFloatConstraint",
"TimeInitialStep",

View File

@@ -880,7 +880,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
def write_constraints_selfweight(self, f):
if not self.selfweight_objects:
return
if not (self.analysis_type == "static" or self.analysis_type == "thermomech"):
if not (self.analysis_type == "static" or self.analysis_type == "thermomech" or self.analysis_type == "buckling"):
return
# write constraint to file
@@ -914,7 +914,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
def write_constraints_force(self, f, inpfile_split=None):
if not self.force_objects:
return
if not (self.analysis_type == "static" or self.analysis_type == "thermomech"):
if not (self.analysis_type == "static" or self.analysis_type == "thermomech" or self.analysis_type == "buckling"):
return
# check shape type of reference shape and get node loads
@@ -963,7 +963,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
def write_constraints_pressure(self, f, inpfile_split=None):
if not self.pressure_objects:
return
if not (self.analysis_type == "static" or self.analysis_type == "thermomech"):
if not (self.analysis_type == "static" or self.analysis_type == "thermomech" or self.analysis_type == "buckling"):
return
# get the faces and face numbers
@@ -1176,7 +1176,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
if self.solver_obj.IterationsThermoMechMaximum:
if self.analysis_type == "thermomech":
step += ", INC=" + str(self.solver_obj.IterationsThermoMechMaximum)
elif self.analysis_type == "static" or self.analysis_type == "frequency":
elif self.analysis_type == "static" or self.analysis_type == "frequency" or self.analysis_type == "buckling":
# parameter is for thermomechanical analysis only, see ccx manual *STEP
pass
# write step line
@@ -1197,6 +1197,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
analysis_type = "*COUPLED TEMPERATURE-DISPLACEMENT"
elif self.analysis_type == "check":
analysis_type = "*NO ANALYSIS"
elif self.analysis_type == "buckling":
analysis_type = "*BUCKLE"
# analysis line --> solver type
# https://forum.freecadweb.org/viewtopic.php?f=18&t=43178
if self.solver_obj.MatrixSolverType == "default":
@@ -1228,7 +1230,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
# Set time to 1 and ignore user inputs for steady state
self.solver_obj.TimeInitialStep = 1.0
self.solver_obj.TimeEnd = 1.0
elif self.analysis_type == "static" or self.analysis_type == "frequency":
elif self.analysis_type == "static" or self.analysis_type == "frequency" or self.analysis_type == "buckling":
pass # not supported for static and frequency!
# ANALYSIS parameter line
analysis_parameter = ""
@@ -1255,6 +1257,9 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
self.solver_obj.TimeInitialStep,
self.solver_obj.TimeEnd
)
elif self.analysis_type == "buckling":
analysis_parameter = "{}\n".format(self.solver_obj.BucklingFactors)
# write analysis type line, analysis parameter line
f.write(analysis_type + "\n")
f.write(analysis_parameter + "\n")
@@ -1818,6 +1823,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
# nonlinear material properties
if self.solver_obj.MaterialNonlinearity == "nonlinear":
for nlfemobj in self.material_nonlinear_objects:
# femobj --> dict, FreeCAD document object is nlfemobj["Object"]
nl_mat_obj = nlfemobj["Object"]

View File

@@ -114,6 +114,11 @@ class _TaskPanel:
QtCore.SIGNAL("clicked()"),
self.select_check_mesh
)
QtCore.QObject.connect(
self.form.rb_buckling_analysis,
QtCore.SIGNAL("clicked()"),
self.select_buckling_analysis
)
QtCore.QObject.connect(
self.Calculix,
QtCore.SIGNAL("started()"),
@@ -161,6 +166,8 @@ class _TaskPanel:
self.form.rb_thermomech_analysis.setChecked(True)
elif self.fea.solver.AnalysisType == "check":
self.form.rb_check_mesh.setChecked(True)
elif self.fea.solver.AnalysisType == "buckling":
self.form.rb_buckling_analysis.setChecked(True)
return
def femConsoleMessage(self, message="", color="#000000"):
@@ -386,3 +393,7 @@ class _TaskPanel:
def select_check_mesh(self):
self.select_analysis_type("check")
def select_buckling_analysis(self):
self.select_analysis_type("buckling")