Fem: Remove dependency of calculix solver classes on user parameters - fixes #13383

This commit is contained in:
marioalexis
2024-06-07 13:35:33 -03:00
committed by Chris Hennes
parent 55dd8076cc
commit 3d7d5ab785
3 changed files with 450 additions and 394 deletions

View File

@@ -1044,6 +1044,110 @@ class _ResultsPurge(CommandManager):
import femresult.resulttools as resulttools
resulttools.purge_results(self.active_analysis)
class _SolverCalculixContextManager:
def __init__(self, make_name, cli_obj_ref_name):
self.make_name = make_name
self.cli_name = cli_obj_ref_name
def __enter__(self):
ccx_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Ccx")
FreeCAD.ActiveDocument.openTransaction("Create SolverCalculix")
FreeCADGui.addModule("ObjectsFem")
FreeCADGui.addModule("FemGui")
FreeCADGui.doCommand(
"{} = ObjectsFem.{}(FreeCAD.ActiveDocument)".format(
self.cli_name, self.make_name
)
)
FreeCADGui.doCommand(
"{}.AnalysisType = {}".format(
self.cli_name, ccx_prefs.GetInt("AnalysisType", 0)
)
)
FreeCADGui.doCommand(
"{}.EigenmodesCount = {}".format(
self.cli_name, ccx_prefs.GetInt("EigenmodesCount", 10)
)
)
FreeCADGui.doCommand(
"{}.EigenmodeLowLimit = {}".format(
self.cli_name, ccx_prefs.GetFloat("EigenmodeLowLimit", 0.0)
)
)
FreeCADGui.doCommand(
"{}.EigenmodeHighLimit = {}".format(
self.cli_name, ccx_prefs.GetFloat("EigenmodeHighLimit", 1000000.0)
)
)
FreeCADGui.doCommand(
"{}.IterationsMaximum = {}".format(
self.cli_name, ccx_prefs.GetInt("AnalysisMaxIterations", 2000)
)
)
FreeCADGui.doCommand(
"{}.TimeInitialStep = {}".format(
self.cli_name, ccx_prefs.GetFloat("AnalysisTimeInitialStep", 1.0)
)
)
FreeCADGui.doCommand(
"{}.TimeEnd = {}".format(
self.cli_name, ccx_prefs.GetFloat("AnalysisTime", 1.0)
)
)
FreeCADGui.doCommand(
"{}.TimeMinimumStep = {}".format(
self.cli_name, ccx_prefs.GetFloat("AnalysisTimeMinimumStep", 0.00001)
)
)
FreeCADGui.doCommand(
"{}.TimeMaximumStep = {}".format(
self.cli_name, ccx_prefs.GetFloat("AnalysisTimeMaximumStep", 1.0)
)
)
FreeCADGui.doCommand(
"{}.ThermoMechSteadyState = {}".format(
self.cli_name, ccx_prefs.GetBool("StaticAnalysis", True)
)
)
FreeCADGui.doCommand(
"{}.IterationsControlParameterTimeUse = {}".format(
self.cli_name, ccx_prefs.GetInt("UseNonCcxIterationParam", False)
)
)
FreeCADGui.doCommand(
"{}.SplitInputWriter = {}".format(
self.cli_name, ccx_prefs.GetBool("SplitInputWriter", False)
)
)
FreeCADGui.doCommand(
"{}.MatrixSolverType = {}".format(
self.cli_name, ccx_prefs.GetInt("Solver", 0)
)
)
FreeCADGui.doCommand(
"{}.BeamShellResultOutput3D = {}".format(
self.cli_name, ccx_prefs.GetBool("BeamShellOutput", True)
)
)
FreeCADGui.doCommand(
"{}.GeometricalNonlinearity = \"{}\"".format(
self.cli_name,
"nonlinear" if ccx_prefs.GetBool("NonlinearGeometry", False) else "linear"
)
)
return self
def __exit__(self, exc_type, exc_value, trace):
FreeCADGui.doCommand(
"FemGui.getActiveAnalysis().addObject({})".format(self.cli_name)
)
FreeCAD.ActiveDocument.commitTransaction()
# expand analysis object in tree view
expandParentObject()
FreeCAD.ActiveDocument.recompute()
class _SolverCcxTools(CommandManager):
"The FEM_SolverCalculix ccx tools command definition"
@@ -1063,29 +1167,19 @@ class _SolverCcxTools(CommandManager):
self.is_active = "with_analysis"
def Activated(self):
has_nonlinear_material_obj = False
for m in self.active_analysis.Group:
if is_of_type(m, "Fem::MaterialMechanicalNonlinear"):
has_nonlinear_material_obj = True
FreeCAD.ActiveDocument.openTransaction("Create SolverCalculix")
FreeCADGui.addModule("ObjectsFem")
FreeCADGui.addModule("FemGui")
if has_nonlinear_material_obj:
FreeCADGui.doCommand(
"solver = ObjectsFem.makeSolverCalculiXCcxTools(FreeCAD.ActiveDocument)"
)
FreeCADGui.doCommand("solver.GeometricalNonlinearity = 'nonlinear'")
FreeCADGui.doCommand("solver.MaterialNonlinearity = 'nonlinear'")
FreeCADGui.doCommand("FemGui.getActiveAnalysis().addObject(solver)")
else:
FreeCADGui.doCommand(
"FemGui.getActiveAnalysis().addObject(ObjectsFem."
"makeSolverCalculiXCcxTools(FreeCAD.ActiveDocument))"
)
FreeCAD.ActiveDocument.commitTransaction()
# expand analysis object in tree view
expandParentObject()
FreeCAD.ActiveDocument.recompute()
with _SolverCalculixContextManager("makeSolverCalculiXCcxTools", "solver") as cm:
has_nonlinear_material_obj = False
for m in self.active_analysis.Group:
if is_of_type(m, "Fem::MaterialMechanicalNonlinear"):
has_nonlinear_material_obj = True
if has_nonlinear_material_obj:
FreeCADGui.doCommand(
"{}.GeometricalNonlinearity = 'nonlinear'".format(cm.cli_name)
)
FreeCADGui.doCommand(
"{}.MaterialNonlinearity = 'nonlinear'".format(cm.cli_name)
)
class _SolverCalculix(CommandManager):
@@ -1104,8 +1198,21 @@ class _SolverCalculix(CommandManager):
"Creates a FEM solver CalculiX new framework (less result error handling)"
)
self.is_active = "with_analysis"
self.is_active = "with_analysis"
self.do_activated = "add_obj_on_gui_expand_noset_edit"
def Activated(self):
with _SolverCalculixContextManager("makeSolverCalculix", "solver") as cm:
has_nonlinear_material_obj = False
for m in self.active_analysis.Group:
if is_of_type(m, "Fem::MaterialMechanicalNonlinear"):
has_nonlinear_material_obj = True
if has_nonlinear_material_obj:
FreeCADGui.doCommand(
"{}.GeometricalNonlinearity = 'nonlinear'".format(cm.cli_name)
)
FreeCADGui.doCommand(
"{}.MaterialNonlinearity = 'nonlinear'".format(cm.cli_name)
)
class _SolverControl(CommandManager):

View File

@@ -32,11 +32,10 @@ __url__ = "https://www.freecad.org"
import FreeCAD
from . import base_fempythonobject
from femsolver.calculix.solver import add_attributes
from femsolver.calculix.solver import on_restore_of_document
from femsolver.calculix.solver import _BaseSolverCalculix
class SolverCcxTools(base_fempythonobject.BaseFemPythonObject):
class SolverCcxTools(base_fempythonobject.BaseFemPythonObject, _BaseSolverCalculix):
"""The Fem::FemSolver's Proxy python type, add solver specific properties
"""
@@ -45,11 +44,8 @@ class SolverCcxTools(base_fempythonobject.BaseFemPythonObject):
def __init__(self, obj):
super(SolverCcxTools, self).__init__(obj)
ccx_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Ccx")
# add attributes
# implemented in framework calculix solver module
add_attributes(obj, ccx_prefs)
self.add_attributes(obj)
obj.addProperty(
"App::PropertyPath",
@@ -62,8 +58,4 @@ class SolverCcxTools(base_fempythonobject.BaseFemPythonObject):
# only used if the preferences working directory is left blank
def onDocumentRestored(self, obj):
ccx_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Ccx")
# implemented in framework calculix solver module
on_restore_of_document(obj, ccx_prefs)
self.on_restore_of_document(obj)

View File

@@ -49,7 +49,318 @@ def create(doc, name="SolverCalculiX"):
doc, name, Proxy, ViewProxy)
class Proxy(solverbase.Proxy):
class _BaseSolverCalculix:
def on_restore_of_document(self, obj):
temp_analysis_type = obj.AnalysisType
obj.AnalysisType = ANALYSIS_TYPES
if temp_analysis_type in ANALYSIS_TYPES:
obj.AnalysisType = temp_analysis_type
else:
FreeCAD.Console.PrintWarning(
"Analysis type {} not found. Standard is used.\n"
.format(temp_analysis_type)
)
obj.AnalysisType = ANALYSIS_TYPES[0]
self.add_attributes(obj)
def add_attributes(self, obj):
if not hasattr(obj, "AnalysisType"):
obj.addProperty(
"App::PropertyEnumeration",
"AnalysisType",
"Fem",
"Type of the analysis"
)
obj.AnalysisType = ANALYSIS_TYPES
obj.AnalysisType = ANALYSIS_TYPES[0]
if not hasattr(obj, "GeometricalNonlinearity"):
choices_geom_nonlinear = ["linear", "nonlinear"]
obj.addProperty(
"App::PropertyEnumeration",
"GeometricalNonlinearity",
"Fem",
"Set geometrical nonlinearity"
)
obj.GeometricalNonlinearity = choices_geom_nonlinear
obj.GeometricalNonlinearity = choices_geom_nonlinear[0]
if not hasattr(obj, "MaterialNonlinearity"):
choices_material_nonlinear = ["linear", "nonlinear"]
obj.addProperty(
"App::PropertyEnumeration",
"MaterialNonlinearity",
"Fem",
"Set material nonlinearity"
)
obj.MaterialNonlinearity = choices_material_nonlinear
obj.MaterialNonlinearity = choices_material_nonlinear[0]
if not hasattr(obj, "EigenmodesCount"):
obj.addProperty(
"App::PropertyIntegerConstraint",
"EigenmodesCount",
"Fem",
"Number of modes for frequency calculations"
)
obj.EigenmodesCount = (10, 1, 100, 1)
if not hasattr(obj, "EigenmodeLowLimit"):
obj.addProperty(
"App::PropertyFloatConstraint",
"EigenmodeLowLimit",
"Fem",
"Low frequency limit for eigenmode calculations"
)
obj.EigenmodeLowLimit = (0.0, 0.0, 1000000.0, 10000.0)
if not hasattr(obj, "EigenmodeHighLimit"):
obj.addProperty(
"App::PropertyFloatConstraint",
"EigenmodeHighLimit",
"Fem",
"High frequency limit for eigenmode calculations"
)
obj.EigenmodeHighLimit = (1000000.0, 0.0, 1000000.0, 10000.0)
if not hasattr(obj, "IterationsMaximum"):
help_string_IterationsMaximum = (
"Maximum Number of iterations "
"in each time step before stopping jobs"
)
obj.addProperty(
"App::PropertyIntegerConstraint",
"IterationsMaximum",
"Fem",
help_string_IterationsMaximum
)
obj.IterationsMaximum = 2000
if hasattr(obj, "IterationsThermoMechMaximum"):
obj.IterationsMaximum = obj.IterationsThermoMechMaximum
obj.removeProperty("IterationsThermoMechMaximum")
if not hasattr(obj, "BucklingFactors"):
obj.addProperty(
"App::PropertyIntegerConstraint",
"BucklingFactors",
"Fem",
"Calculates the lowest buckling modes to the corresponding buckling factors"
)
obj.BucklingFactors = 1
if not hasattr(obj, "TimeInitialStep"):
obj.addProperty(
"App::PropertyFloatConstraint",
"TimeInitialStep",
"Fem",
"Initial time steps"
)
obj.TimeInitialStep = 0.01
if not hasattr(obj, "TimeEnd"):
obj.addProperty(
"App::PropertyFloatConstraint",
"TimeEnd",
"Fem",
"End time analysis"
)
obj.TimeEnd = 1.0
if not hasattr(obj, "TimeMinimumStep"):
obj.addProperty(
"App::PropertyFloatConstraint",
"TimeMinimumStep",
"Fem",
"Minimum time step"
)
obj.TimeMinimumStep = 0.00001
if not hasattr(obj, "TimeMaximumStep"):
obj.addProperty(
"App::PropertyFloatConstraint",
"TimeMaximumStep",
"Fem",
"Maximum time step"
)
obj.TimeMaximumStep = 1.0
if not hasattr(obj, "ThermoMechSteadyState"):
obj.addProperty(
"App::PropertyBool",
"ThermoMechSteadyState",
"Fem",
"Choose between steady state thermo mech or transient thermo mech analysis"
)
obj.ThermoMechSteadyState = True
if not hasattr(obj, "IterationsControlParameterTimeUse"):
obj.addProperty(
"App::PropertyBool",
"IterationsControlParameterTimeUse",
"Fem",
"Use the user defined time incrementation control parameter"
)
obj.IterationsControlParameterTimeUse = False
if not hasattr(obj, "SplitInputWriter"):
obj.addProperty(
"App::PropertyBool",
"SplitInputWriter",
"Fem",
"Split writing of ccx input file"
)
obj.SplitInputWriter = False
if not hasattr(obj, "IterationsControlParameterIter"):
control_parameter_iterations = (
"{I_0},{I_R},{I_P},{I_C},{I_L},{I_G},{I_S},{I_A},{I_J},{I_T}".format(
I_0=4,
I_R=8,
I_P=9,
I_C=200, # ccx default = 16
I_L=10,
I_G=400, # ccx default = 4
I_S="",
I_A=200, # ccx default = 5
I_J="",
I_T="",
)
)
obj.addProperty(
"App::PropertyString",
"IterationsControlParameterIter",
"Fem",
"User defined time incrementation iterations control parameter"
)
obj.IterationsControlParameterIter = control_parameter_iterations
if not hasattr(obj, "IterationsControlParameterCutb"):
control_parameter_cutback = (
"{D_f},{D_C},{D_B},{D_A},{D_S},{D_H},{D_D},{W_G}".format(
D_f=0.25,
D_C=0.5,
D_B=0.75,
D_A=0.85,
D_S="",
D_H="",
D_D=1.5,
W_G="",
)
)
obj.addProperty(
"App::PropertyString",
"IterationsControlParameterCutb",
"Fem",
"User defined time incrementation cutbacks control parameter"
)
obj.IterationsControlParameterCutb = control_parameter_cutback
if not hasattr(obj, "IterationsUserDefinedIncrementations"):
stringIterationsUserDefinedIncrementations = (
"Set to True to switch off the ccx automatic incrementation completely "
"(ccx parameter DIRECT). Use with care. Analysis may not converge!"
)
obj.addProperty(
"App::PropertyBool",
"IterationsUserDefinedIncrementations",
"Fem",
stringIterationsUserDefinedIncrementations
)
obj.IterationsUserDefinedIncrementations = False
if not hasattr(obj, "IterationsUserDefinedTimeStepLength"):
help_string_IterationsUserDefinedTimeStepLength = (
"Set to True to use the user defined time steps. "
"They are set with TimeInitialStep, TimeEnd, TimeMinimum and TimeMaximum"
)
obj.addProperty(
"App::PropertyBool",
"IterationsUserDefinedTimeStepLength",
"Fem",
help_string_IterationsUserDefinedTimeStepLength
)
obj.IterationsUserDefinedTimeStepLength = False
if not hasattr(obj, "MatrixSolverType"):
known_ccx_solver_types = [
"default",
"pastix",
"pardiso",
"spooles",
"iterativescaling",
"iterativecholesky"
]
obj.addProperty(
"App::PropertyEnumeration",
"MatrixSolverType",
"Fem",
"Type of solver to use"
)
obj.MatrixSolverType = known_ccx_solver_types
obj.MatrixSolverType = known_ccx_solver_types[0]
if not hasattr(obj, "BeamShellResultOutput3D"):
obj.addProperty(
"App::PropertyBool",
"BeamShellResultOutput3D",
"Fem",
"Output 3D results for 1D and 2D analysis "
)
obj.BeamShellResultOutput3D = True
if not hasattr(obj, "BeamReducedIntegration"):
obj.addProperty(
"App::PropertyBool",
"BeamReducedIntegration",
"Fem",
"Set to True to use beam elements with reduced integration"
)
obj.BeamReducedIntegration = True
if not hasattr(obj, "OutputFrequency"):
obj.addProperty(
"App::PropertyIntegerConstraint",
"OutputFrequency",
"Fem",
"Set the output frequency in increments"
)
obj.OutputFrequency = 1
if not hasattr(obj, "ModelSpace"):
model_space_types = [
"3D",
"plane stress",
"plane strain",
"axisymmetric"
]
obj.addProperty(
"App::PropertyEnumeration",
"ModelSpace",
"Fem",
"Type of model space"
)
obj.ModelSpace = model_space_types
if not hasattr(obj, "ThermoMechType"):
thermomech_types = [
"coupled",
"uncoupled",
"pure heat transfer"
]
obj.addProperty(
"App::PropertyEnumeration",
"ThermoMechType",
"Fem",
"Type of thermomechanical analysis"
)
obj.ThermoMechType = thermomech_types
class Proxy(solverbase.Proxy, _BaseSolverCalculix):
"""The Fem::FemSolver's Proxy python type, add solver specific properties
"""
@@ -58,15 +369,10 @@ class Proxy(solverbase.Proxy):
def __init__(self, obj):
super(Proxy, self).__init__(obj)
obj.Proxy = self
ccx_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Ccx")
add_attributes(obj, ccx_prefs)
self.add_attributes(obj)
def onDocumentRestored(self, obj):
ccx_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Ccx")
# since it is needed for the ccxtools solver too
# the method is implemented outside of the class
# thus we need to pass the prefs
on_restore_of_document(obj, ccx_prefs)
self.on_restore_of_document(obj)
def createMachine(self, obj, directory, testmode=False):
return run.Machine(
@@ -94,355 +400,6 @@ class ViewProxy(solverbase.ViewProxy):
pass
# ************************************************************************************************
# helper
# these methods are outside of the class to be able
# to use them from framework solver and ccxtools solver
def on_restore_of_document(obj, ccx_prefs):
# ANALYSIS_TYPES
# They have been extended. If file was saved with a old FC version
# not all enum types are available, because they are saved in the FC file
# thus refresh the list of known ANALYSIS_TYPES
# print("onRestoredFromSuperClass")
# print(obj.AnalysisType)
# print(obj.getEnumerationsOfProperty("AnalysisType"))
temp_analysis_type = obj.AnalysisType
# self.add_properties(obj)
obj.AnalysisType = ANALYSIS_TYPES
if temp_analysis_type in ANALYSIS_TYPES:
obj.AnalysisType = temp_analysis_type
else:
FreeCAD.Console.PrintWarning(
"Analysis type {} not found. Standard is used.\n"
.format(temp_analysis_type)
)
analysis_type = ccx_prefs.GetInt("AnalysisType", 0)
obj.AnalysisType = ANALYSIS_TYPES[analysis_type]
# add missing properties
# for example BucklingFactors will be added
# for all files created before buckle analysis was introduced
add_attributes(obj, ccx_prefs)
def add_attributes(obj, ccx_prefs):
if not hasattr(obj, "AnalysisType"):
obj.addProperty(
"App::PropertyEnumeration",
"AnalysisType",
"Fem",
"Type of the analysis"
)
obj.AnalysisType = ANALYSIS_TYPES
analysis_type = ccx_prefs.GetInt("AnalysisType", 0)
obj.AnalysisType = ANALYSIS_TYPES[analysis_type]
if not hasattr(obj, "GeometricalNonlinearity"):
choices_geom_nonlinear = ["linear", "nonlinear"]
obj.addProperty(
"App::PropertyEnumeration",
"GeometricalNonlinearity",
"Fem",
"Set geometrical nonlinearity"
)
obj.GeometricalNonlinearity = choices_geom_nonlinear
nonlinear_geom = ccx_prefs.GetBool("NonlinearGeometry", False)
if nonlinear_geom is True:
obj.GeometricalNonlinearity = choices_geom_nonlinear[1] # nonlinear
else:
obj.GeometricalNonlinearity = choices_geom_nonlinear[0] # linear
if not hasattr(obj, "MaterialNonlinearity"):
choices_material_nonlinear = ["linear", "nonlinear"]
obj.addProperty(
"App::PropertyEnumeration",
"MaterialNonlinearity",
"Fem",
"Set material nonlinearity"
)
obj.MaterialNonlinearity = choices_material_nonlinear
obj.MaterialNonlinearity = choices_material_nonlinear[0]
if not hasattr(obj, "EigenmodesCount"):
obj.addProperty(
"App::PropertyIntegerConstraint",
"EigenmodesCount",
"Fem",
"Number of modes for frequency calculations"
)
noem = ccx_prefs.GetInt("EigenmodesCount", 10)
obj.EigenmodesCount = (noem, 1, 100, 1)
if not hasattr(obj, "EigenmodeLowLimit"):
obj.addProperty(
"App::PropertyFloatConstraint",
"EigenmodeLowLimit",
"Fem",
"Low frequency limit for eigenmode calculations"
)
ell = ccx_prefs.GetFloat("EigenmodeLowLimit", 0.0)
obj.EigenmodeLowLimit = (ell, 0.0, 1000000.0, 10000.0)
if not hasattr(obj, "EigenmodeHighLimit"):
obj.addProperty(
"App::PropertyFloatConstraint",
"EigenmodeHighLimit",
"Fem",
"High frequency limit for eigenmode calculations"
)
ehl = ccx_prefs.GetFloat("EigenmodeHighLimit", 1000000.0)
obj.EigenmodeHighLimit = (ehl, 0.0, 1000000.0, 10000.0)
if not hasattr(obj, "IterationsMaximum"):
help_string_IterationsMaximum = (
"Maximum Number of iterations "
"in each time step before stopping jobs"
)
obj.addProperty(
"App::PropertyIntegerConstraint",
"IterationsMaximum",
"Fem",
help_string_IterationsMaximum
)
niter = ccx_prefs.GetInt("AnalysisMaxIterations", 2000)
obj.IterationsMaximum = niter
if hasattr(obj, "IterationsThermoMechMaximum"):
obj.IterationsMaximum = obj.IterationsThermoMechMaximum
obj.removeProperty("IterationsThermoMechMaximum")
if not hasattr(obj, "BucklingFactors"):
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
if not hasattr(obj, "TimeInitialStep"):
obj.addProperty(
"App::PropertyFloatConstraint",
"TimeInitialStep",
"Fem",
"Initial time steps"
)
ini = ccx_prefs.GetFloat("AnalysisTimeInitialStep", 1.0)
obj.TimeInitialStep = ini
if not hasattr(obj, "TimeEnd"):
obj.addProperty(
"App::PropertyFloatConstraint",
"TimeEnd",
"Fem",
"End time analysis"
)
eni = ccx_prefs.GetFloat("AnalysisTime", 1.0)
obj.TimeEnd = eni
if not hasattr(obj, "TimeMinimumStep"):
obj.addProperty(
"App::PropertyFloatConstraint",
"TimeMinimumStep",
"Fem",
"Minimum time step"
)
mini = ccx_prefs.GetFloat("AnalysisTimeMinimumStep", 0.00001)
obj.TimeMinimumStep = mini
if not hasattr(obj, "TimeMaximumStep"):
obj.addProperty(
"App::PropertyFloatConstraint",
"TimeMaximumStep",
"Fem",
"Maximum time step"
)
maxi = ccx_prefs.GetFloat("AnalysisTimeMaximumStep", 1.0)
obj.TimeMaximumStep = maxi
if not hasattr(obj, "ThermoMechSteadyState"):
obj.addProperty(
"App::PropertyBool",
"ThermoMechSteadyState",
"Fem",
"Choose between steady state thermo mech or transient thermo mech analysis"
)
sted = ccx_prefs.GetBool("StaticAnalysis", True)
obj.ThermoMechSteadyState = sted
if not hasattr(obj, "IterationsControlParameterTimeUse"):
obj.addProperty(
"App::PropertyBool",
"IterationsControlParameterTimeUse",
"Fem",
"Use the user defined time incrementation control parameter"
)
use_non_ccx_iterations_param = ccx_prefs.GetInt("UseNonCcxIterationParam", False)
obj.IterationsControlParameterTimeUse = use_non_ccx_iterations_param
if not hasattr(obj, "SplitInputWriter"):
obj.addProperty(
"App::PropertyBool",
"SplitInputWriter",
"Fem",
"Split writing of ccx input file"
)
split = ccx_prefs.GetBool("SplitInputWriter", False)
obj.SplitInputWriter = split
if not hasattr(obj, "IterationsControlParameterIter"):
control_parameter_iterations = (
"{I_0},{I_R},{I_P},{I_C},{I_L},{I_G},{I_S},{I_A},{I_J},{I_T}".format(
I_0=4,
I_R=8,
I_P=9,
I_C=200, # ccx default = 16
I_L=10,
I_G=400, # ccx default = 4
I_S="",
I_A=200, # ccx default = 5
I_J="",
I_T="",
)
)
obj.addProperty(
"App::PropertyString",
"IterationsControlParameterIter",
"Fem",
"User defined time incrementation iterations control parameter"
)
obj.IterationsControlParameterIter = control_parameter_iterations
if not hasattr(obj, "IterationsControlParameterCutb"):
control_parameter_cutback = (
"{D_f},{D_C},{D_B},{D_A},{D_S},{D_H},{D_D},{W_G}".format(
D_f=0.25,
D_C=0.5,
D_B=0.75,
D_A=0.85,
D_S="",
D_H="",
D_D=1.5,
W_G="",
)
)
obj.addProperty(
"App::PropertyString",
"IterationsControlParameterCutb",
"Fem",
"User defined time incrementation cutbacks control parameter"
)
obj.IterationsControlParameterCutb = control_parameter_cutback
if not hasattr(obj, "IterationsUserDefinedIncrementations"):
stringIterationsUserDefinedIncrementations = (
"Set to True to switch off the ccx automatic incrementation completely "
"(ccx parameter DIRECT). Use with care. Analysis may not converge!"
)
obj.addProperty(
"App::PropertyBool",
"IterationsUserDefinedIncrementations",
"Fem",
stringIterationsUserDefinedIncrementations
)
obj.IterationsUserDefinedIncrementations = False
if not hasattr(obj, "IterationsUserDefinedTimeStepLength"):
help_string_IterationsUserDefinedTimeStepLength = (
"Set to True to use the user defined time steps. "
"They are set with TimeInitialStep, TimeEnd, TimeMinimum and TimeMaximum"
)
obj.addProperty(
"App::PropertyBool",
"IterationsUserDefinedTimeStepLength",
"Fem",
help_string_IterationsUserDefinedTimeStepLength
)
obj.IterationsUserDefinedTimeStepLength = False
if not hasattr(obj, "MatrixSolverType"):
known_ccx_solver_types = [
"default",
"pastix",
"pardiso",
"spooles",
"iterativescaling",
"iterativecholesky"
]
obj.addProperty(
"App::PropertyEnumeration",
"MatrixSolverType",
"Fem",
"Type of solver to use"
)
obj.MatrixSolverType = known_ccx_solver_types
solver_type = ccx_prefs.GetInt("Solver", 0)
obj.MatrixSolverType = known_ccx_solver_types[solver_type]
if not hasattr(obj, "BeamShellResultOutput3D"):
obj.addProperty(
"App::PropertyBool",
"BeamShellResultOutput3D",
"Fem",
"Output 3D results for 1D and 2D analysis "
)
dimout = ccx_prefs.GetBool("BeamShellOutput", True)
obj.BeamShellResultOutput3D = dimout
if not hasattr(obj, "BeamReducedIntegration"):
obj.addProperty(
"App::PropertyBool",
"BeamReducedIntegration",
"Fem",
"Set to True to use beam elements with reduced integration"
)
obj.BeamReducedIntegration = True
if not hasattr(obj, "OutputFrequency"):
obj.addProperty(
"App::PropertyIntegerConstraint",
"OutputFrequency",
"Fem",
"Set the output frequency in increments"
)
obj.OutputFrequency = 1
if not hasattr(obj, "ModelSpace"):
model_space_types = [
"3D",
"plane stress",
"plane strain",
"axisymmetric"
]
obj.addProperty(
"App::PropertyEnumeration",
"ModelSpace",
"Fem",
"Type of model space"
)
obj.ModelSpace = model_space_types
if not hasattr(obj, "ThermoMechType"):
thermomech_types = [
"coupled",
"uncoupled",
"pure heat transfer"
]
obj.addProperty(
"App::PropertyEnumeration",
"ThermoMechType",
"Fem",
"Type of thermomechanical analysis"
)
obj.ThermoMechType = thermomech_types
"""
Should there be some equation object for Calculix too?