diff --git a/src/Mod/Fem/Gui/Resources/ui/SolverCalculix.ui b/src/Mod/Fem/Gui/Resources/ui/SolverCalculix.ui
index e3ec2c2d91af..8af431ab64e8 100644
--- a/src/Mod/Fem/Gui/Resources/ui/SolverCalculix.ui
+++ b/src/Mod/Fem/Gui/Resources/ui/SolverCalculix.ui
@@ -61,17 +61,21 @@
9
- -
-
+
-
+
- Static
+ Thermo mechanical
-
- true
+
+
+ -
+
+
+ Check Mesh
- -
+
-
Frequency
@@ -79,16 +83,19 @@
-
-
+
- Thermo mechanical
+ Static
+
+
+ true
- -
-
+
-
+
- Check Mesh
+ Buckling
diff --git a/src/Mod/Fem/femsolver/calculix/solver.py b/src/Mod/Fem/femsolver/calculix/solver.py
index faa63c4026e7..07ccc29b5557 100644
--- a/src/Mod/Fem/femsolver/calculix/solver.py
+++ b/src/Mod/Fem/femsolver/calculix/solver.py
@@ -41,7 +41,7 @@
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",
diff --git a/src/Mod/Fem/femsolver/calculix/writer.py b/src/Mod/Fem/femsolver/calculix/writer.py
index 092a6d0e9cd5..cb2fe19cb52c 100644
--- a/src/Mod/Fem/femsolver/calculix/writer.py
+++ b/src/Mod/Fem/femsolver/calculix/writer.py
@@ -880,7 +880,7 @@ def write_constraints_initialtemperature(self, f):
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 @@ def write_constraints_selfweight(self, f):
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 @@ def write_nodeloads_constraints_force(self, f):
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 @@ def write_step_begin(self, f):
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 @@ def write_step_begin(self, f):
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 @@ def write_step_begin(self, f):
# 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 @@ def write_step_begin(self, f):
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 @@ def write_materials(self, f):
# 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"]
diff --git a/src/Mod/Fem/femtaskpanels/task_solver_ccxtools.py b/src/Mod/Fem/femtaskpanels/task_solver_ccxtools.py
index 44edb0668b05..583aacca999a 100644
--- a/src/Mod/Fem/femtaskpanels/task_solver_ccxtools.py
+++ b/src/Mod/Fem/femtaskpanels/task_solver_ccxtools.py
@@ -114,6 +114,11 @@ def __init__(self, solver_object):
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 @@ def update(self):
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 @@ def select_thermomech_analysis(self):
def select_check_mesh(self):
self.select_analysis_type("check")
+
+ def select_buckling_analysis(self):
+ self.select_analysis_type("buckling")
+