diff --git a/src/Mod/Fem/Gui/DlgSettingsFemCcx.ui b/src/Mod/Fem/Gui/DlgSettingsFemCcx.ui index 21004d7437..9288fc4351 100644 --- a/src/Mod/Fem/Gui/DlgSettingsFemCcx.ui +++ b/src/Mod/Fem/Gui/DlgSettingsFemCcx.ui @@ -302,16 +302,16 @@ - + - Initial time step + Initial time increment - + - End time + Time period @@ -427,38 +427,10 @@ - + Qt::DefaultContextMenu - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - s - - - 9 - - - 0.000000001000000 - - - 1.000000000000000 - - - 1.000000000000000 - - - AnalysisTimeMaximumStep - - - Mod/Fem/Ccx - - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -478,7 +450,35 @@ 1.000000000000000 - AnalysisTime + TimeMaximumIncrement + + + Mod/Fem/Ccx + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + s + + + 9 + + + 0.000000001000000 + + + 1.000000000000000 + + + 1.000000000000000 + + + TimePeriod Mod/Fem/Ccx @@ -516,16 +516,16 @@ - + - Maximum number of iterations + Maximum number of increments - + - Minimum time step + Minimum time increment @@ -543,7 +543,7 @@ - + Qt::DefaultContextMenu @@ -566,7 +566,7 @@ 0.000010000000000 - AnalysisTimeMinimumStep + TimeMinimumIncrement Mod/Fem/Ccx @@ -590,7 +590,7 @@ - + Qt::DefaultContextMenu @@ -610,10 +610,10 @@ 0.010000000000000 - 0.010000000000000 + 1.000000000000000 - AnalysisTimeInitialStep + TimeInitialIncrement Mod/Fem/Ccx @@ -628,7 +628,7 @@ - + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -645,7 +645,7 @@ 2000 - AnalysisMaxIterations + StepMaxIncrements Mod/Fem/Ccx @@ -653,9 +653,9 @@ - + - Maximum time step + Maximum time increment diff --git a/src/Mod/Fem/Gui/DlgSettingsFemCcxImp.cpp b/src/Mod/Fem/Gui/DlgSettingsFemCcxImp.cpp index 145a392acf..e668dce16b 100644 --- a/src/Mod/Fem/Gui/DlgSettingsFemCcxImp.cpp +++ b/src/Mod/Fem/Gui/DlgSettingsFemCcxImp.cpp @@ -43,8 +43,8 @@ DlgSettingsFemCcxImp::DlgSettingsFemCcxImp(QWidget* parent) { ui->setupUi(this); // set ranges - ui->dsb_ccx_analysis_time->setMaximum(std::numeric_limits::max()); - ui->dsb_ccx_initial_time_step->setMaximum(std::numeric_limits::max()); + ui->dsb_ccx_time_period->setMaximum(std::numeric_limits::max()); + ui->dsb_ccx_initial_time_increment->setMaximum(std::numeric_limits::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(); diff --git a/src/Mod/Fem/femcommands/commands.py b/src/Mod/Fem/femcommands/commands.py index 8e4d08039f..56231cfb19 100644 --- a/src/Mod/Fem/femcommands/commands.py +++ b/src/Mod/Fem/femcommands/commands.py @@ -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( diff --git a/src/Mod/Fem/femexamples/thermomech_bimetal.py b/src/Mod/Fem/femexamples/thermomech_bimetal.py index a83b79d65f..f7725a343e 100644 --- a/src/Mod/Fem/femexamples/thermomech_bimetal.py +++ b/src/Mod/Fem/femexamples/thermomech_bimetal.py @@ -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) diff --git a/src/Mod/Fem/femobjects/solver_calculix.py b/src/Mod/Fem/femobjects/solver_calculix.py index 28480050b0..68825f1652 100644 --- a/src/Mod/Fem/femobjects/solver_calculix.py +++ b/src/Mod/Fem/femobjects/solver_calculix.py @@ -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 diff --git a/src/Mod/Fem/femobjects/solver_ccxtools.py b/src/Mod/Fem/femobjects/solver_ccxtools.py index 2e9c06f148..138893d42a 100644 --- a/src/Mod/Fem/femobjects/solver_ccxtools.py +++ b/src/Mod/Fem/femobjects/solver_ccxtools.py @@ -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 diff --git a/src/Mod/Fem/femsolver/calculix/write_step_equation.py b/src/Mod/Fem/femsolver/calculix/write_step_equation.py index 83a97692b5..146ab5a040 100644 --- a/src/Mod/Fem/femsolver/calculix/write_step_equation.py +++ b/src/Mod/Fem/femsolver/calculix/write_step_equation.py @@ -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") diff --git a/src/Mod/Fem/femtest/data/calculix/thermomech_bimetal.inp b/src/Mod/Fem/femtest/data/calculix/thermomech_bimetal.inp index 370b8d3712..a38614fb78 100644 --- a/src/Mod/Fem/femtest/data/calculix/thermomech_bimetal.inp +++ b/src/Mod/Fem/femtest/data/calculix/thermomech_bimetal.inp @@ -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 ***********************************************************