Merge pull request #23494 from marioalexis84/fem-calculix_default_time_increment

Fem: Use default CalculiX time increments for thermo-mechanical steady state analysis
This commit is contained in:
Chris Hennes
2025-09-07 20:31:06 -05:00
committed by GitHub
8 changed files with 188 additions and 181 deletions

View File

@@ -302,16 +302,16 @@
</spacer>
</item>
<item row="5" column="0">
<widget class="QLabel" name="l_ccx_initial_time_step">
<widget class="QLabel" name="l_ccx_initial_time_increment">
<property name="text">
<string>Initial time step</string>
<string>Initial time increment</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="l_ccx_analysis_time">
<widget class="QLabel" name="l_ccx_time_period">
<property name="text">
<string>End time</string>
<string>Time period</string>
</property>
</widget>
</item>
@@ -427,38 +427,10 @@
</widget>
</item>
<item row="8" column="2">
<widget class="Gui::PrefDoubleSpinBox" name="dsb_ccx_maximum_time_step">
<widget class="Gui::PrefDoubleSpinBox" name="dsb_ccx_maximum_time_increment">
<property name="contextMenuPolicy">
<enum>Qt::DefaultContextMenu</enum>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="suffix">
<string notr="true"> s</string>
</property>
<property name="decimals">
<number>9</number>
</property>
<property name="minimum">
<double>0.000000001000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
<property name="prefEntry" stdset="0">
<cstring>AnalysisTimeMaximumStep</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Fem/Ccx</cstring>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="Gui::PrefDoubleSpinBox" name="dsb_ccx_analysis_time">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
@@ -478,7 +450,35 @@
<double>1.000000000000000</double>
</property>
<property name="prefEntry" stdset="0">
<cstring>AnalysisTime</cstring>
<cstring>TimeMaximumIncrement</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Fem/Ccx</cstring>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="Gui::PrefDoubleSpinBox" name="dsb_ccx_time_period">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="suffix">
<string notr="true"> s</string>
</property>
<property name="decimals">
<number>9</number>
</property>
<property name="minimum">
<double>0.000000001000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
<property name="prefEntry" stdset="0">
<cstring>TimePeriod</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Fem/Ccx</cstring>
@@ -516,16 +516,16 @@
</spacer>
</item>
<item row="4" column="0">
<widget class="QLabel" name="l_ccx_max_iterations">
<widget class="QLabel" name="l_ccx_max_increments">
<property name="text">
<string>Maximum number of iterations</string>
<string>Maximum number of increments</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="l_ccx_minimum_time_step">
<widget class="QLabel" name="l_ccx_minimum_time_increment">
<property name="text">
<string>Minimum time step</string>
<string>Minimum time increment</string>
</property>
</widget>
</item>
@@ -543,7 +543,7 @@
</spacer>
</item>
<item row="7" column="2">
<widget class="Gui::PrefDoubleSpinBox" name="dsb_ccx_minimum_time_step">
<widget class="Gui::PrefDoubleSpinBox" name="dsb_ccx_minimum_time_increment">
<property name="contextMenuPolicy">
<enum>Qt::DefaultContextMenu</enum>
</property>
@@ -566,7 +566,7 @@
<double>0.000010000000000</double>
</property>
<property name="prefEntry" stdset="0">
<cstring>AnalysisTimeMinimumStep</cstring>
<cstring>TimeMinimumIncrement</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Fem/Ccx</cstring>
@@ -590,7 +590,7 @@
</widget>
</item>
<item row="5" column="2">
<widget class="Gui::PrefDoubleSpinBox" name="dsb_ccx_initial_time_step">
<widget class="Gui::PrefDoubleSpinBox" name="dsb_ccx_initial_time_increment">
<property name="contextMenuPolicy">
<enum>Qt::DefaultContextMenu</enum>
</property>
@@ -610,10 +610,10 @@
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.010000000000000</double>
<double>1.000000000000000</double>
</property>
<property name="prefEntry" stdset="0">
<cstring>AnalysisTimeInitialStep</cstring>
<cstring>TimeInitialIncrement</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Fem/Ccx</cstring>
@@ -628,7 +628,7 @@
</widget>
</item>
<item row="4" column="2">
<widget class="Gui::PrefSpinBox" name="sb_ccx_max_iterations">
<widget class="Gui::PrefSpinBox" name="sb_ccx_max_increments">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
@@ -645,7 +645,7 @@
<number>2000</number>
</property>
<property name="prefEntry" stdset="0">
<cstring>AnalysisMaxIterations</cstring>
<cstring>StepMaxIncrements</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Fem/Ccx</cstring>
@@ -653,9 +653,9 @@
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="l_ccx_maximum_time_step">
<widget class="QLabel" name="l_ccx_maximum_time_increment">
<property name="text">
<string>Maximum time step</string>
<string>Maximum time increment</string>
</property>
</widget>
</item>

View File

@@ -43,8 +43,8 @@ DlgSettingsFemCcxImp::DlgSettingsFemCcxImp(QWidget* parent)
{
ui->setupUi(this);
// set ranges
ui->dsb_ccx_analysis_time->setMaximum(std::numeric_limits<float>::max());
ui->dsb_ccx_initial_time_step->setMaximum(std::numeric_limits<float>::max());
ui->dsb_ccx_time_period->setMaximum(std::numeric_limits<float>::max());
ui->dsb_ccx_initial_time_increment->setMaximum(std::numeric_limits<float>::max());
connect(ui->fc_ccx_binary_path,
&Gui::PrefFileChooser::fileNameChanged,
@@ -67,11 +67,11 @@ void DlgSettingsFemCcxImp::saveSettings()
ui->cb_use_iterations_param->onSave();
ui->cb_static->onSave();
ui->sb_ccx_max_iterations->onSave(); // Max number of iterations
ui->dsb_ccx_initial_time_step->onSave(); // Initial time step
ui->dsb_ccx_analysis_time->onSave(); // Analysis time
ui->dsb_ccx_minimum_time_step->onSave(); // Minimum time step
ui->dsb_ccx_maximum_time_step->onSave(); // Maximum time step
ui->sb_ccx_max_increments->onSave(); // Max number of increments
ui->dsb_ccx_initial_time_increment->onSave(); // Initial time increment
ui->dsb_ccx_time_period->onSave(); // Step time period
ui->dsb_ccx_minimum_time_increment->onSave(); // Minimum time increment
ui->dsb_ccx_maximum_time_increment->onSave(); // Maximum time increment
ui->ckb_pipeline_result->onSave();
ui->ckb_result_format->onSave();
@@ -96,11 +96,11 @@ void DlgSettingsFemCcxImp::loadSettings()
ui->cb_use_iterations_param->onRestore();
ui->cb_static->onRestore();
ui->sb_ccx_max_iterations->onRestore(); // Max number of iterations
ui->dsb_ccx_initial_time_step->onRestore(); // Initial time step
ui->dsb_ccx_analysis_time->onRestore(); // Analysis time
ui->dsb_ccx_minimum_time_step->onRestore(); // Minimum time step
ui->dsb_ccx_maximum_time_step->onRestore(); // Maximum time step
ui->sb_ccx_max_increments->onRestore(); // Max number of increments
ui->dsb_ccx_initial_time_increment->onRestore(); // Initial time increment
ui->dsb_ccx_time_period->onRestore(); // Step time period
ui->dsb_ccx_minimum_time_increment->onRestore(); // Minimum time increment
ui->dsb_ccx_maximum_time_increment->onRestore(); // Maximum time increment
ui->ckb_pipeline_result->onRestore();
ui->ckb_result_format->onRestore();

View File

@@ -962,26 +962,26 @@ class _SolverCalculixContextManager:
)
)
FreeCADGui.doCommand(
"{}.IterationsMaximum = {}".format(
self.cli_name, ccx_prefs.GetInt("AnalysisMaxIterations", 2000)
"{}.IncrementsMaximum = {}".format(
self.cli_name, ccx_prefs.GetInt("StepMaxIncrements", 2000)
)
)
FreeCADGui.doCommand(
"{}.TimeInitialStep = {}".format(
self.cli_name, ccx_prefs.GetFloat("AnalysisTimeInitialStep", 1.0)
"{}.TimeInitialIncrement = {}".format(
self.cli_name, ccx_prefs.GetFloat("TimeInitialIncrement", 1.0)
)
)
FreeCADGui.doCommand(
"{}.TimeEnd = {}".format(self.cli_name, ccx_prefs.GetFloat("AnalysisTime", 1.0))
"{}.TimePeriod = {}".format(self.cli_name, ccx_prefs.GetFloat("TimePeriod", 1.0))
)
FreeCADGui.doCommand(
"{}.TimeMinimumStep = {}".format(
self.cli_name, ccx_prefs.GetFloat("AnalysisTimeMinimumStep", 0.00001)
"{}.TimeMinimumIncrement = {}".format(
self.cli_name, ccx_prefs.GetFloat("TimeMinimumIncrement", 0.00001)
)
)
FreeCADGui.doCommand(
"{}.TimeMaximumStep = {}".format(
self.cli_name, ccx_prefs.GetFloat("AnalysisTimeMaximumStep", 1.0)
"{}.TimeMaximumIncrement = {}".format(
self.cli_name, ccx_prefs.GetFloat("TimeMaximumIncrement", 1.0)
)
)
FreeCADGui.doCommand(

View File

@@ -146,7 +146,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver_obj.MatrixSolverType = "default"
solver_obj.MatrixSolverType = "spooles" # thomas
solver_obj.SplitInputWriter = False
solver_obj.IterationsMaximum = 2000
solver_obj.IncrementsMaximum = 2000
# solver_obj.IterationsControlParameterTimeUse = True # thermomech spine
analysis.addObject(solver_obj)

View File

@@ -53,7 +53,7 @@ class SolverCalculiX(base_fempythonobject.BaseFemPythonObject):
_PropHelper(
type="App::PropertyEnumeration",
name="AnalysisType",
group="Solver",
group="AnalysisType",
doc="Type of the analysis",
value=["static", "frequency", "thermomech", "check", "buckling", "electromagnetic"],
)
@@ -106,10 +106,11 @@ class SolverCalculiX(base_fempythonobject.BaseFemPythonObject):
prop.append(
_PropHelper(
type="App::PropertyIntegerConstraint",
name="IterationsMaximum",
group="Solver",
doc="Maximum Number of iterations in each time step before stopping jobs",
value=2000,
name="IncrementsMaximum",
group="TimeIncrement",
doc="Maximum Number of increments in each CalculiX step.\n"
+ "Set to 0 to use CalculiX default value",
value={"value": 2000, "min": 0},
)
)
prop.append(
@@ -124,36 +125,36 @@ class SolverCalculiX(base_fempythonobject.BaseFemPythonObject):
prop.append(
_PropHelper(
type="App::PropertyTime",
name="TimeInitialStep",
group="Solver",
doc="Initial time steps",
value=0.01,
)
)
prop.append(
_PropHelper(
type="App::PropertyTime",
name="TimeEnd",
group="Solver",
doc="End time analysis",
name="TimeInitialIncrement",
group="TimeIncrement",
doc="Initial time increment",
value=1.0,
)
)
prop.append(
_PropHelper(
type="App::PropertyTime",
name="TimeMinimumStep",
group="Solver",
doc="Minimum time step",
name="TimePeriod",
group="TimeIncrement",
doc="Time period of the CalculiX step",
value=1.0,
)
)
prop.append(
_PropHelper(
type="App::PropertyTime",
name="TimeMinimumIncrement",
group="TimeIncrement",
doc="Minimum time increment",
value=0.00001,
)
)
prop.append(
_PropHelper(
type="App::PropertyTime",
name="TimeMaximumStep",
group="Solver",
doc="Maximum time step",
name="TimeMaximumIncrement",
group="TimeIncrement",
doc="Maximum time increment",
value=1.0,
)
)
@@ -161,7 +162,7 @@ class SolverCalculiX(base_fempythonobject.BaseFemPythonObject):
_PropHelper(
type="App::PropertyBool",
name="ThermoMechSteadyState",
group="Solver",
group="AnalysisType",
doc="Choose between steady state thermo mech or transient thermo mech analysis",
value=True,
)
@@ -225,21 +226,12 @@ class SolverCalculiX(base_fempythonobject.BaseFemPythonObject):
prop.append(
_PropHelper(
type="App::PropertyBool",
name="IterationsUserDefinedIncrementations",
group="Solver",
doc="Set to True to switch off the ccx automatic incrementation completely\n"
+ "(ccx parameter DIRECT). Use with care. Analysis may not converge!",
value=False,
)
)
prop.append(
_PropHelper(
type="App::PropertyBool",
name="IterationsUserDefinedTimeStepLength",
group="Solver",
doc="Set to True to use the user defined time steps.\n"
+ "They are set with TimeInitialStep, TimeEnd, TimeMinimum and TimeMaximum",
value=False,
name="AutomaticIncrementation",
group="TimeIncrement",
doc="If False, switch off automatic incrementation via `DIRECT`\n"
+ "parameter and ignore minimum and maximum time increments.\n"
+ "Analysis may not converge!",
value=True,
)
)
prop.append(
@@ -271,7 +263,7 @@ class SolverCalculiX(base_fempythonobject.BaseFemPythonObject):
_PropHelper(
type="App::PropertyBool",
name="BeamReducedIntegration",
group="Solver",
group="ElementModel",
doc="Set to True to use beam elements with reduced integration",
value=True,
)
@@ -289,7 +281,7 @@ class SolverCalculiX(base_fempythonobject.BaseFemPythonObject):
_PropHelper(
type="App::PropertyEnumeration",
name="ModelSpace",
group="Solver",
group="ElementModel",
doc="Type of model space",
value=["3D", "plane stress", "plane strain", "axisymmetric"],
)
@@ -298,7 +290,7 @@ class SolverCalculiX(base_fempythonobject.BaseFemPythonObject):
_PropHelper(
type="App::PropertyEnumeration",
name="ThermoMechType",
group="Solver",
group="AnalysisType",
doc="Type of thermomechanical analysis",
value=["coupled", "uncoupled", "pure heat transfer"],
)
@@ -316,7 +308,7 @@ class SolverCalculiX(base_fempythonobject.BaseFemPythonObject):
_PropHelper(
type="App::PropertyEnumeration",
name="ElectromagneticMode",
group="Solver",
group="AnalysisType",
doc="Electromagnetic mode",
value=["electrostatic"],
)
@@ -325,7 +317,7 @@ class SolverCalculiX(base_fempythonobject.BaseFemPythonObject):
_PropHelper(
type="App::PropertyBool",
name="ExcludeBendingStiffness",
group="Solver",
group="ElementModel",
doc="Exclude bending stiffness to replace shells with membranes or beams with trusses",
value=False,
)
@@ -348,3 +340,37 @@ class SolverCalculiX(base_fempythonobject.BaseFemPythonObject):
obj.getPropertyByName(prop.name)
except Base.PropertyError:
prop.add_to_object(obj)
# remove old properties
try:
obj.AutomaticIncrementation = not obj.getPropertyByName(
"IterationsUserDefinedIncrementations"
)
obj.setPropertyStatus("IterationsUserDefinedIncrementations", "-LockDynamic")
obj.removeProperty("IterationsUserDefinedIncrementations")
obj.setPropertyStatus("IterationsUserDefinedTimeStepLength", "-LockDynamic")
obj.removeProperty("IterationsUserDefinedTimeStepLength")
obj.TimeInitialIncrement = obj.getPropertyByName("TimeInitialStep")
obj.setPropertyStatus("TimeInitialStep", "-LockDynamic")
obj.removeProperty("TimeInitialStep")
obj.TimePeriod = obj.getPropertyByName("TimeEnd")
obj.setPropertyStatus("TimeEnd", "-LockDynamic")
obj.removeProperty("TimeEnd")
obj.TimeMaximumIncrement = obj.getPropertyByName("TimeMaximumStep")
obj.setPropertyStatus("TimeMaximumStep", "-LockDynamic")
obj.removeProperty("TimeMaximumStep")
obj.TimeMinimumIncrement = obj.getPropertyByName("TimeMinimumStep")
obj.setPropertyStatus("TimeMinimumStep", "-LockDynamic")
obj.removeProperty("TimeMinimumStep")
obj.IncrementsMaximum = obj.getPropertyByName("IterationsMaximum")
obj.setPropertyStatus("IterationsMaximum", "-LockDynamic")
obj.removeProperty("IterationsMaximum")
except Base.PropertyError:
# do nothing
pass

View File

@@ -29,13 +29,11 @@ __url__ = "https://www.freecad.org"
# \ingroup FEM
# \brief solver calculix ccx tools object
import FreeCAD
from . import base_fempythonobject
from femsolver.calculix.solver import _BaseSolverCalculix
from .base_fempythonobject import _PropHelper
from .solver_calculix import SolverCalculiX
class SolverCcxTools(base_fempythonobject.BaseFemPythonObject, _BaseSolverCalculix):
class SolverCcxTools(SolverCalculiX):
"""The Fem::FemSolver's Proxy python type, add solver specific properties"""
Type = "Fem::SolverCcxTools"
@@ -43,18 +41,26 @@ class SolverCcxTools(base_fempythonobject.BaseFemPythonObject, _BaseSolverCalcul
def __init__(self, obj):
super().__init__(obj)
# implemented in framework calculix solver module
self.add_attributes(obj)
def _get_properties(self):
prop = super()._get_properties()
obj.addProperty(
"App::PropertyPath",
"WorkingDir",
"Fem",
"Working directory for calculations, will only be used it is left blank in preferences",
# set analysis types supported by CcxTools solver
for p in prop:
if p.name == "AnalysisType":
p.value = ["static", "frequency", "thermomech", "check", "buckling"]
# remove unused properties
prop = list(filter(lambda p: p.name != "ElectromagneticMode", prop))
prop.append(
_PropHelper(
type="App::PropertyPath",
name="WorkingDir",
group="Solver",
doc="Working directory for calculations.\n"
+ "Will only be used it is left blank in preferences",
value="",
)
)
obj.setPropertyStatus("WorkingDir", "LockDynamic")
# the working directory is not set, the solver working directory is
# only used if the preferences working directory is left blank
def onDocumentRestored(self, obj):
self.on_restore_of_document(obj)
return prop

View File

@@ -37,7 +37,7 @@ def write_step_equation(f, ccxwriter):
# build STEP line
step = "*STEP"
if ccxwriter.solver_obj.GeometricalNonlinearity == "nonlinear":
if ccxwriter.analysis_type == "static" or ccxwriter.analysis_type == "thermomech":
if ccxwriter.analysis_type in ["static", "thermomech"]:
# https://www.comsol.com/blogs/what-is-geometric-nonlinearity
step += ", NLGEOM"
elif ccxwriter.analysis_type == "frequency":
@@ -45,12 +45,11 @@ def write_step_equation(f, ccxwriter):
"Analysis type frequency and geometrical nonlinear "
"analysis are not allowed together, linear is used instead!\n"
)
if ccxwriter.solver_obj.IterationsMaximum:
if ccxwriter.analysis_type == "thermomech" or ccxwriter.analysis_type == "static":
step += f", INC={ccxwriter.solver_obj.IterationsMaximum}"
elif ccxwriter.analysis_type == "frequency" or ccxwriter.analysis_type == "buckling":
# parameter is for thermomechanical analysis only, see ccx manual *STEP
pass
if ccxwriter.solver_obj.IncrementsMaximum:
if ccxwriter.analysis_type in ["static", "thermomech", "electromagnetic"]:
step += f", INC={ccxwriter.solver_obj.IncrementsMaximum}"
# write STEP line
f.write(step + "\n")
@@ -63,6 +62,7 @@ def write_step_equation(f, ccxwriter):
# ANALYSIS type line
# analysis line --> analysis type
analysis_type = ""
if ccxwriter.analysis_type == "static":
analysis_type = "*STATIC"
elif ccxwriter.analysis_type == "frequency":
@@ -74,12 +74,16 @@ def write_step_equation(f, ccxwriter):
analysis_type = "*UNCOUPLED TEMPERATURE-DISPLACEMENT"
elif ccxwriter.solver_obj.ThermoMechType == "pure heat transfer":
analysis_type = "*HEAT TRANSFER"
if ccxwriter.solver_obj.ThermoMechSteadyState:
analysis_type += ", STEADY STATE"
elif ccxwriter.analysis_type == "check":
analysis_type = "*NO ANALYSIS"
elif ccxwriter.analysis_type == "buckling":
analysis_type = "*BUCKLE"
elif ccxwriter.analysis_type == "electromagnetic":
analysis_type = "*HEAT TRANSFER, STEADY STATE"
if ccxwriter.solver_obj.ElectromagneticMode == "electrostatic":
analysis_type = "*HEAT TRANSFER, STEADY STATE"
# analysis line --> solver type
# https://forum.freecad.org/viewtopic.php?f=18&t=43178
if ccxwriter.solver_obj.MatrixSolverType == "default":
@@ -94,45 +98,22 @@ def write_step_equation(f, ccxwriter):
analysis_type += ", SOLVER=ITERATIVE SCALING"
elif ccxwriter.solver_obj.MatrixSolverType == "iterativecholesky":
analysis_type += ", SOLVER=ITERATIVE CHOLESKY"
# analysis line --> user defined incrementations --> parameter DIRECT
# --> completely switch off ccx automatic incrementation
if ccxwriter.solver_obj.IterationsUserDefinedIncrementations:
# analysis line --> automatic incrementation --> parameter DIRECT
# completely switch off ccx automatic incrementation
if not ccxwriter.solver_obj.AutomaticIncrementation:
if ccxwriter.analysis_type in ["static", "thermomech", "electromagnetic"]:
analysis_type += ", DIRECT"
elif ccxwriter.analysis_type == "frequency":
FreeCAD.Console.PrintMessage(
"Analysis type frequency and IterationsUserDefinedIncrementations "
"are not allowed together, it is ignored\n"
)
# analysis line --> steadystate --> thermomech only
if ccxwriter.solver_obj.ThermoMechSteadyState:
# bernd: I do not know if STEADY STATE is allowed with DIRECT
# but since time steps are 1.0 it makes no sense IMHO
if ccxwriter.analysis_type == "thermomech":
analysis_type += ", STEADY STATE"
# Set time to 1 and ignore user inputs for steady state
ccxwriter.solver_obj.TimeInitialStep = 1.0
ccxwriter.solver_obj.TimeEnd = 1.0
elif (
ccxwriter.analysis_type == "static"
or ccxwriter.analysis_type == "frequency"
or ccxwriter.analysis_type == "buckling"
):
pass # not supported for static and frequency!
# ANALYSIS parameter line
analysis_parameter = ""
if ccxwriter.analysis_type == "static" or ccxwriter.analysis_type == "check":
if (
ccxwriter.solver_obj.IterationsUserDefinedIncrementations is True
or ccxwriter.solver_obj.IterationsUserDefinedTimeStepLength is True
):
analysis_parameter = "{},{},{},{}".format(
ccxwriter.solver_obj.TimeInitialStep.getValueAs("s").Value,
ccxwriter.solver_obj.TimeEnd.getValueAs("s").Value,
ccxwriter.solver_obj.TimeMinimumStep.getValueAs("s").Value,
ccxwriter.solver_obj.TimeMaximumStep.getValueAs("s").Value,
)
if ccxwriter.analysis_type in ["static", "thermomech", "electromagnetic"]:
analysis_parameter = "{},{},{},{}".format(
ccxwriter.solver_obj.TimeInitialIncrement.getValueAs("s").Value,
ccxwriter.solver_obj.TimePeriod.getValueAs("s").Value,
ccxwriter.solver_obj.TimeMinimumIncrement.getValueAs("s").Value,
ccxwriter.solver_obj.TimeMaximumIncrement.getValueAs("s").Value,
)
elif ccxwriter.analysis_type == "frequency":
if (
ccxwriter.solver_obj.EigenmodeLowLimit == 0.0
@@ -145,19 +126,13 @@ def write_step_equation(f, ccxwriter):
ccxwriter.solver_obj.EigenmodeLowLimit.getValueAs("Hz").Value,
ccxwriter.solver_obj.EigenmodeHighLimit.getValueAs("Hz").Value,
)
elif ccxwriter.analysis_type == "thermomech":
# OvG: 1.0 increment, total time 1 for steady state will cut back automatically
analysis_parameter = "{},{},{},{}".format(
ccxwriter.solver_obj.TimeInitialStep.getValueAs("s").Value,
ccxwriter.solver_obj.TimeEnd.getValueAs("s").Value,
ccxwriter.solver_obj.TimeMinimumStep.getValueAs("s").Value,
ccxwriter.solver_obj.TimeMaximumStep.getValueAs("s").Value,
)
elif ccxwriter.analysis_type == "buckling":
analysis_parameter = "{},{}".format(
ccxwriter.solver_obj.BucklingFactors,
ccxwriter.solver_obj.BucklingAccuracy,
)
elif ccxwriter.analysis_type == "check":
analysis_parameter = ""
# write analysis type line, analysis parameter line
f.write(analysis_type + "\n")

View File

@@ -7087,7 +7087,7 @@ Nall,273.0
***********************************************************
** At least one step is needed to run an CalculiX analysis of FreeCAD
*STEP, INC=2000
*COUPLED TEMPERATURE-DISPLACEMENT, SOLVER=SPOOLES, STEADY STATE
*COUPLED TEMPERATURE-DISPLACEMENT, STEADY STATE, SOLVER=SPOOLES
1.0,1.0,1e-05,1.0
***********************************************************