From 8e25fe33dc5a81ac32febedd09143eea52573064 Mon Sep 17 00:00:00 2001 From: Tobias Vaara Date: Sat, 6 Feb 2021 03:35:44 -0800 Subject: [PATCH] FEM: solver calculix, add buckling analysis Implementation of buckling analysis between the solver Calculix and FreeCAD --- .../Fem/Gui/Resources/ui/SolverCalculix.ui | 29 ++++++++++++------- src/Mod/Fem/femsolver/calculix/solver.py | 11 ++++++- src/Mod/Fem/femsolver/calculix/writer.py | 16 ++++++---- .../Fem/femtaskpanels/task_solver_ccxtools.py | 11 +++++++ 4 files changed, 50 insertions(+), 17 deletions(-) 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") +