From 50ccefc45e27c6291e0297b4ed3df7d6dacb54d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20Iraz=C3=A1bal=20Gonz=C3=A1lez?= Date: Tue, 3 Nov 2026 08:29:18 +0100 Subject: [PATCH 1/6] Add initial-state save/load processes and validation to Dam interface - Implement initial-state save/load functionality in writeProjectParameters.tcl - Introduce new XML procedures for handling initial-state file values - Enhance process validation to prevent conflicts between initial-state and legacy mappings - Update UI elements in Procs.spd and Utilities.spd for initial-state options --- kratos.gid/apps/Dam/python/MainKratos.py | 44 +++ .../apps/Dam/write/writeProjectParameters.tcl | 292 +++++++++++++++++- kratos.gid/apps/Dam/xml/Procs.spd | 6 + kratos.gid/apps/Dam/xml/Utilities.spd | 43 ++- kratos.gid/apps/Dam/xml/XmlController.tcl | 26 ++ 5 files changed, 403 insertions(+), 8 deletions(-) diff --git a/kratos.gid/apps/Dam/python/MainKratos.py b/kratos.gid/apps/Dam/python/MainKratos.py index 713c571ca..fa7c333dd 100644 --- a/kratos.gid/apps/Dam/python/MainKratos.py +++ b/kratos.gid/apps/Dam/python/MainKratos.py @@ -165,6 +165,50 @@ def Initialize(self): self.list_of_processes += KratosMultiphysics.process_factory.KratosProcessFactory(self.model).ConstructListOfProcesses( self.ProjectParameters["temperature_by_device_list"] ) self.list_of_processes += KratosMultiphysics.process_factory.KratosProcessFactory(self.model).ConstructListOfProcesses( self.ProjectParameters["output_device_list"] ) + # The initial-state import must be the only mechanism that assigns each + # imported field. These checks reproduce the DamAnalysis guards (and + # also reject any legacy mapping combined with a new initial-state + # import) so that projects launched from GiD fail early and clearly. + for attribute in ("transfers_initial_stress", + "transfers_initial_temperature", + "transfers_reference_temperature"): + transferring_processes = [ + process for process in self.list_of_processes + if getattr(process, attribute, False)] + if len(transferring_processes) > 1: + raise RuntimeError( + "More than one process transfers the same initial-state field " + "('{}'). Use only one initial-state processor per field.".format( + attribute)) + + if any(getattr(process, "transfers_reference_temperature", False) + for process in self.list_of_processes): + reference_process_classes = ( + "ImposeNodalReferenceTemperatureProcess", + "ImposeGroutingReferenceTemperatureProcess") + reference_processes = [ + process for process in self.list_of_processes + if (getattr(process, "assigns_reference_temperature", False) or + isinstance( + process, + KratosDam.DamNodalReferenceTemperatureProcess) or + type(process).__name__ in reference_process_classes)] + if reference_processes: + raise RuntimeError( + "Cannot import NODAL_REFERENCE_TEMPERATURE while a process " + "that assigns it is active. Remove or disable the " + "reference-temperature process for this analysis.") + + if self.add_previous_results and any( + getattr(process, "transfers_initial_stress", False) or + getattr(process, "transfers_initial_temperature", False) or + getattr(process, "transfers_reference_temperature", False) + for process in self.list_of_processes): + raise RuntimeError( + "An initial-state transfer process cannot be combined with " + "'transfer_results_process.add_previous_results'. Use only one " + "initial-state transfer mechanism per analysis.") + # Print list of constructed processes if(self.echo_level>1): for self.process in self.list_of_processes: diff --git a/kratos.gid/apps/Dam/write/writeProjectParameters.tcl b/kratos.gid/apps/Dam/write/writeProjectParameters.tcl index 4ecbe9fa1..227aec4fa 100644 --- a/kratos.gid/apps/Dam/write/writeProjectParameters.tcl +++ b/kratos.gid/apps/Dam/write/writeProjectParameters.tcl @@ -32,7 +32,11 @@ proc ::Dam::write::getParametersDict { } { ### Load processes set mechanical_load_process_list [::write::getConditionsParametersDict DamLoads] set thermal_load_process_list [::write::getConditionsParametersDict DamThermalLoads] - dict set projectParametersDict loads_process_list [Dam::write::ChangeFileNameforTableid [concat $mechanical_load_process_list $thermal_load_process_list]] + set condition_load_process_list [Dam::write::ChangeFileNameforTableid [concat $mechanical_load_process_list $thermal_load_process_list]] + # Initial-state save/load processes are global (not condition-based), so they + # are appended after the table-id conversion applied to condition processes. + set initial_state_process_list [Dam::write::GetInitialStateProcessList] + dict set projectParametersDict loads_process_list [concat $condition_load_process_list $initial_state_process_list] ### Construction processes dict set projectParametersDict construction_process [Dam::write::GetConstructionDomainProcessDict] @@ -919,6 +923,292 @@ proc ::Dam::write::GetConstructionDomainProcessDict { } { return $construction_dict } +# Returns the Kratos model-part name for a Dam part group. The sub-model-part +# catalog is already populated when ProjectParameters is written (the .mdpa is +# written first), so the resolved identifier is used whenever available. +proc ::Dam::write::GetInitialStateModelPartName { group } { + if {$group eq ""} {return ""} + + # Match the name used when the part sub-model-part was written. + set group [write::GetWriteGroupName $group] + + set subModelPartId 0 + catch {set subModelPartId [write::getSubModelPartId "Parts" $group]} + if {$subModelPartId eq "" || $subModelPartId eq 0} { + set subModelPartId "Parts_[write::transformGroupName $group]" + } + return [write::GetModelPartNameWithParent $subModelPartId] +} + +# File-handler values use "- No file - ..." as the empty selection. +proc ::Dam::write::IsNoInitialStateFile { value } { + set value [string trim $value] + return [expr {$value eq "" || [string match "- No file*" $value]}] +} + +# Resolves a user-provided initial-state path for local validation. Relative +# paths are interpreted from the GiD project directory, which is the working +# directory used when Kratos is launched from GiD. +proc ::Dam::write::ResolveInitialStatePath { value } { + set value [string trim $value] + if {[Dam::write::IsNoInitialStateFile $value]} {return ""} + + if {[file pathtype $value] eq "absolute"} {return $value} + + set baseDir "" + catch {set baseDir [write::GetConfigurationAttribute dir]} + if {$baseDir eq ""} {return $value} + return [file join $baseDir $value] +} + +proc ::Dam::write::GetSaveInitialStateProcessDict { } { + if {![write::isBooleanTrue [write::getValue DamSaveInitialState]]} {return ""} + + set group [write::getValue DamSaveInitialStatePart] + set saveStresses [write::isBooleanTrue [write::getValue DamSaveInitialStresses]] + set saveTemperature [write::isBooleanTrue [write::getValue DamSaveInitialTemperature]] + set saveReferenceTemperature [write::isBooleanTrue [write::getValue DamSaveInitialReferenceTemperature]] + set stressSource [write::getValue DamInitialStateStressSource] + if {$stressSource eq ""} {set stressSource "current_cauchy"} + set outputFile [string trim [write::getValue DamInitialStateOutputFile]] + + set parametersDict [dict create] + dict set parametersDict model_part_name [Dam::write::GetInitialStateModelPartName $group] + if {$saveStresses} { + dict set parametersDict save_initial_stresses true + } else { + dict set parametersDict save_initial_stresses false + } + if {$saveTemperature} { + dict set parametersDict save_initial_temperature true + } else { + dict set parametersDict save_initial_temperature false + } + if {$saveReferenceTemperature} { + dict set parametersDict save_reference_temperature true + } else { + dict set parametersDict save_reference_temperature false + } + dict set parametersDict stress_source $stressSource + dict set parametersDict output_file_name $outputFile + + set processDict [dict create] + dict set processDict python_module "save_dam_initial_state_process" + dict set processDict kratos_module "KratosMultiphysics.DamApplication" + dict set processDict Parameters $parametersDict + return $processDict +} + +proc ::Dam::write::GetLoadInitialStateProcessDict { } { + if {![write::isBooleanTrue [write::getValue DamLoadInitialState]]} {return ""} + + set group [write::getValue DamLoadInitialStatePart] + set inputFile [string trim [write::getValue DamLoadInitialStateFile]] + set transferStresses [write::isBooleanTrue [write::getValue DamTransferInitialStresses]] + set transferTemperature [write::isBooleanTrue [write::getValue DamTransferInitialTemperature]] + set transferReferenceTemperature [write::isBooleanTrue [write::getValue DamTransferInitialReferenceTemperature]] + set referencePolicy [write::getValue DamReferenceTemperaturePolicy] + if {$referencePolicy eq ""} {set referencePolicy "preserve"} + + set parametersDict [dict create] + dict set parametersDict model_part_name [Dam::write::GetInitialStateModelPartName $group] + dict set parametersDict input_file_name $inputFile + if {$transferStresses} { + dict set parametersDict transfer_initial_stresses true + } else { + dict set parametersDict transfer_initial_stresses false + } + if {$transferTemperature} { + dict set parametersDict transfer_initial_temperature true + } else { + dict set parametersDict transfer_initial_temperature false + } + if {$transferReferenceTemperature} { + dict set parametersDict transfer_reference_temperature true + } else { + dict set parametersDict transfer_reference_temperature false + } + dict set parametersDict reference_temperature_policy $referencePolicy + + set processDict [dict create] + dict set processDict python_module "load_dam_initial_state_process" + dict set processDict kratos_module "KratosMultiphysics.DamApplication" + dict set processDict Parameters $parametersDict + return $processDict +} + +# The load process runs before the first solution step and the save process at +# finalization, so both can coexist in the same calculation. Keep the load +# process first for a predictable lifecycle order. +proc ::Dam::write::GetInitialStateProcessList { } { + set processList [list] + set loadProcess [Dam::write::GetLoadInitialStateProcessDict] + if {$loadProcess ne ""} {lappend processList $loadProcess} + set saveProcess [Dam::write::GetSaveInitialStateProcessDict] + if {$saveProcess ne ""} {lappend processList $saveProcess} + return $processList +} + +# Returns the active Dam conditions that assign NODAL_REFERENCE_TEMPERATURE. +# Both the explicit nodal reference-temperature condition and the construction +# grouting-reference condition are reported. +proc ::Dam::write::GetActiveReferenceTemperatureConditions { } { + set conditionList [list] + set thermalLoadsRoute [spdAux::getRoute DamThermalLoads] + if {$thermalLoadsRoute eq ""} {return $conditionList} + + set root [customlib::GetBaseRoot] + foreach conditionId [list NodalReferenceTemperature2D NodalReferenceTemperature3D GroutingTime2D GroutingTime3D] { + set groups [$root selectNodes "$thermalLoadsRoute/condition\[@n='$conditionId'\]/group"] + if {$groups ne ""} {lappend conditionList $conditionId} + } + return $conditionList +} + +# Application-level validation. Returning a nonzero first element aborts the +# write and displays every message in the GiD warning window. +proc ::Dam::write::writeValidateEvent { } { + set problem 0 + set messages [list] + set legacyMapping [write::isBooleanTrue [write::getValue DamPreviousResults AddPreviousResults]] + set damTypeofProblem [write::getValue DamTypeofProblem] + set hasThermalFields [expr {$damTypeofProblem in [list "Thermo-Mechanical" "UP_Thermo-Mechanical"]}] + + set saveEnabled [write::isBooleanTrue [write::getValue DamSaveInitialState]] + if {$saveEnabled} { + set saveStresses [write::isBooleanTrue [write::getValue DamSaveInitialStresses]] + set saveTemperature [write::isBooleanTrue [write::getValue DamSaveInitialTemperature]] + set saveReferenceTemperature [write::isBooleanTrue [write::getValue DamSaveInitialReferenceTemperature]] + + if {!$saveStresses && !$saveTemperature && !$saveReferenceTemperature} { + incr problem + lappend messages "Save initial state: select at least one field to save (initial stresses, initial temperature or reference temperature)." + } + + set group [write::getValue DamSaveInitialStatePart] + if {$group eq ""} { + incr problem + lappend messages "Save initial state: select the target part." + } + + if {$saveStresses} { + set stressSource [write::getValue DamInitialStateStressSource] + if {$stressSource ni [list "current_cauchy" "stored_initial_stress"]} { + incr problem + lappend messages "Save initial state: unsupported stress source '$stressSource'. Select 'Current Cauchy stress' or 'Stored initial stress'." + } elseif {$legacyMapping && $stressSource eq "stored_initial_stress"} { + incr problem + lappend messages "Save initial state: 'Stored initial stress' cannot be combined with the legacy result mapping ('Add previous results'), because the legacy mapping does not populate the constitutive InitialState. Use 'Current Cauchy stress' or disable the legacy mapping." + } + } + + if {!$hasThermalFields} { + if {$saveTemperature} { + incr problem + lappend messages "Save initial state: the analysis type '$damTypeofProblem' does not define nodal TEMPERATURE. Disable 'Save initial temperature' or use a thermo-mechanical analysis." + } + if {$saveReferenceTemperature} { + incr problem + lappend messages "Save initial state: the analysis type '$damTypeofProblem' does not define nodal NODAL_REFERENCE_TEMPERATURE. Disable 'Save reference temperature' or use a thermo-mechanical analysis." + } + } + + set outputFile [string trim [write::getValue DamInitialStateOutputFile]] + if {$outputFile eq ""} { + incr problem + lappend messages "Save initial state: the output file is empty." + } elseif {![regexp {\.json(\.gz)?$} $outputFile]} { + incr problem + lappend messages "Save initial state: the output file '$outputFile' must end with '.json' or '.json.gz'." + } elseif {[file isdirectory [Dam::write::ResolveInitialStatePath $outputFile]]} { + incr problem + lappend messages "Save initial state: the output path '$outputFile' is an existing directory; provide a file name." + } + } + + set loadEnabled [write::isBooleanTrue [write::getValue DamLoadInitialState]] + if {$loadEnabled} { + set transferStresses [write::isBooleanTrue [write::getValue DamTransferInitialStresses]] + set transferTemperature [write::isBooleanTrue [write::getValue DamTransferInitialTemperature]] + set transferReferenceTemperature [write::isBooleanTrue [write::getValue DamTransferInitialReferenceTemperature]] + set referencePolicy [write::getValue DamReferenceTemperaturePolicy] + if {$referencePolicy eq ""} {set referencePolicy "preserve"} + + if {!$transferStresses && !$transferTemperature && !$transferReferenceTemperature} { + incr problem + lappend messages "Load initial state: select at least one field to transfer (initial stresses, initial temperature or reference temperature)." + } + + if {!$hasThermalFields} { + if {$transferTemperature} { + incr problem + lappend messages "Load initial state: the analysis type '$damTypeofProblem' does not define nodal TEMPERATURE. Disable 'Transfer initial temperature' or use a thermo-mechanical analysis." + } + if {$transferReferenceTemperature} { + incr problem + lappend messages "Load initial state: the analysis type '$damTypeofProblem' does not define nodal NODAL_REFERENCE_TEMPERATURE. Disable 'Transfer reference temperature' or use a thermo-mechanical analysis." + } + } + + set group [write::getValue DamLoadInitialStatePart] + if {$group eq ""} { + incr problem + lappend messages "Load initial state: select the target part." + } + + set inputFile [string trim [write::getValue DamLoadInitialStateFile]] + if {[Dam::write::IsNoInitialStateFile $inputFile]} { + incr problem + lappend messages "Load initial state: select an input .json or .json.gz file." + } else { + set resolvedInput [Dam::write::ResolveInitialStatePath $inputFile] + if {![file isfile $resolvedInput]} { + incr problem + lappend messages "Load initial state: the input file '$inputFile' does not exist (resolved to '$resolvedInput'). Select it with the File handler toolbar or use a valid path." + } elseif {![regexp {\.json(\.gz)?$} $resolvedInput]} { + incr problem + lappend messages "Load initial state: the input file '$inputFile' must end with '.json' or '.json.gz'." + } + } + + if {$referencePolicy ni [list "preserve" "initial_temperature"]} { + incr problem + lappend messages "Load initial state: unsupported reference temperature policy '$referencePolicy'." + } + + if {$referencePolicy eq "initial_temperature"} { + if {!$transferTemperature} { + incr problem + lappend messages "Load initial state: the policy 'Use initial temperature as reference' requires transferring the initial temperature." + } + if {$transferReferenceTemperature} { + incr problem + lappend messages "Load initial state: 'Transfer reference temperature' and the policy 'Use initial temperature as reference' cannot be enabled at the same time. Disable one of them." + } + } + + if {$transferReferenceTemperature || $referencePolicy eq "initial_temperature"} { + set referenceConditions [Dam::write::GetActiveReferenceTemperatureConditions] + if {[llength $referenceConditions] > 0} { + if {$referencePolicy eq "initial_temperature"} { + set conflictAction "Disable or remove those conditions, or do not use the 'Use initial temperature as reference' policy." + } else { + set conflictAction "Disable or remove those conditions, or disable 'Transfer reference temperature'." + } + incr problem + lappend messages "Load initial state: the imported NODAL_REFERENCE_TEMPERATURE would be overwritten by the active reference-temperature condition(s): [join $referenceConditions {, }]. $conflictAction The interface does not remove them automatically." + } + } + + if {$legacyMapping} { + incr problem + lappend messages "Load initial state: the legacy result mapping ('Add previous results') cannot be combined with 'Load initial state'. Disable one of the two mechanisms. The legacy mapping transfers nodal fields and is not equivalent to the constitutive initial-state transfer." + } + } + + return [list $problem $messages] +} + # This process write the transfer results process in case is selected proc ::Dam::write::GetTransferResultsDict { } { set transfer_results_dict [dict create] diff --git a/kratos.gid/apps/Dam/xml/Procs.spd b/kratos.gid/apps/Dam/xml/Procs.spd index 2310d31b5..33c7eaad7 100644 --- a/kratos.gid/apps/Dam/xml/Procs.spd +++ b/kratos.gid/apps/Dam/xml/Procs.spd @@ -81,4 +81,10 @@ ]]> + + + + diff --git a/kratos.gid/apps/Dam/xml/Utilities.spd b/kratos.gid/apps/Dam/xml/Utilities.spd index db4954348..288768021 100644 --- a/kratos.gid/apps/Dam/xml/Utilities.spd +++ b/kratos.gid/apps/Dam/xml/Utilities.spd @@ -43,22 +43,51 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + - - + + - + diff --git a/kratos.gid/apps/Dam/xml/XmlController.tcl b/kratos.gid/apps/Dam/xml/XmlController.tcl index a814a28f1..84071b029 100644 --- a/kratos.gid/apps/Dam/xml/XmlController.tcl +++ b/kratos.gid/apps/Dam/xml/XmlController.tcl @@ -427,3 +427,29 @@ proc ::Dam::xml::ProcAddResultsState {domNode args} { if {$ActivateAddResults} {set state normal} return $state } + +# File-handler list for the initial-state input. In addition to the files added +# through the File handler toolbar, a user-provided path is kept in the list so +# absolute paths and paths relative to the GiD project directory can be typed +# directly. Values that do not look like a path fall back to the empty entry. +proc ::Dam::xml::ProcGetInitialStateFileValues {domNode args} { + customlib::UpdateDocument + spdAux::LoadModelFiles + + set values [list $::spdAux::no_file_string] + lappend values {*}[FileSelector::GetAllFiles] + + set current [get_domnode_attribute $domNode v] + if {$current ni $values} { + set looksLikePath [expr { + [string first "/" $current] >= 0 || + [string first "\\" $current] >= 0 || + [regexp {\.json(\.gz)?$} $current]}] + if {$looksLikePath} { + lappend values $current + } else { + $domNode setAttribute v [lindex $values 0] + } + } + return [join $values ","] +} From 36c39d4ccff3f2239f50fda56df74fb5d5caaa37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20Iraz=C3=A1bal=20Gonz=C3=A1lez?= Date: Tue, 3 Nov 2026 10:40:52 +0100 Subject: [PATCH 2/6] Enhance initial-state transfer mechanisms and file handling - Implement checks in the Solution class to ensure only one initial-state transfer process is active at a time. - Update write.tcl to assign a default thickness for 2D solid parts when initial-state transfer is enabled. - Modify writeProjectParameters.tcl to include initial-state processes in the project parameters. - Add new procedures in Procs.spd and Utilities.spd for handling initial-state file transfers and validations. - Extend XmlController.tcl to manage file paths for transfer input files, allowing user-defined paths. --- kratos.gid/apps/Dam/write/write.tcl | 14 ++ .../apps/Dam/write/writeProjectParameters.tcl | 235 +++++++++++++++--- kratos.gid/apps/Dam/xml/Procs.spd | 4 +- kratos.gid/apps/Dam/xml/Utilities.spd | 11 +- kratos.gid/apps/Dam/xml/XmlController.tcl | 13 +- 5 files changed, 234 insertions(+), 43 deletions(-) diff --git a/kratos.gid/apps/Dam/write/write.tcl b/kratos.gid/apps/Dam/write/write.tcl index bced35d02..d1c54bcb9 100644 --- a/kratos.gid/apps/Dam/write/write.tcl +++ b/kratos.gid/apps/Dam/write/write.tcl @@ -95,6 +95,20 @@ proc ::Dam::write::UpdateMaterials { } { dict set matdict $mat CONSTITUTIVE_LAW_NAME $newconstlaw } + + # The Dam initial-state file format and the restart-based selective stress + # utility require THICKNESS on 2D solid parts. Plane-strain laws do not + # define it themselves, so provide the standard unit thickness only when an + # initial-state transfer is enabled. This keeps unrelated analyses unchanged. + if {[Dam::write::IsInitialStateTransferEnabled] && + [string match "2D*" [write::getValue nDim]]} { + foreach mat [dict keys $matdict] { + if {![dict exists $matdict $mat THICKNESS]} { + dict set matdict $mat THICKNESS 1.0 + } + } + } + write::setMatDict $matdict } diff --git a/kratos.gid/apps/Dam/write/writeProjectParameters.tcl b/kratos.gid/apps/Dam/write/writeProjectParameters.tcl index 227aec4fa..f8c3ed34b 100644 --- a/kratos.gid/apps/Dam/write/writeProjectParameters.tcl +++ b/kratos.gid/apps/Dam/write/writeProjectParameters.tcl @@ -923,10 +923,10 @@ proc ::Dam::write::GetConstructionDomainProcessDict { } { return $construction_dict } -# Returns the Kratos model-part name for a Dam part group. The sub-model-part +# Returns the sub-model-part name for a Dam part group. The sub-model-part # catalog is already populated when ProjectParameters is written (the .mdpa is # written first), so the resolved identifier is used whenever available. -proc ::Dam::write::GetInitialStateModelPartName { group } { +proc ::Dam::write::GetInitialStateSubModelPartName { group } { if {$group eq ""} {return ""} # Match the name used when the part sub-model-part was written. @@ -937,9 +937,32 @@ proc ::Dam::write::GetInitialStateModelPartName { group } { if {$subModelPartId eq "" || $subModelPartId eq 0} { set subModelPartId "Parts_[write::transformGroupName $group]" } + return $subModelPartId +} + +# Returns the full Kratos model-part name for a Dam part group. +proc ::Dam::write::GetInitialStateModelPartName { group } { + set subModelPartId [Dam::write::GetInitialStateSubModelPartName $group] + if {$subModelPartId eq ""} {return ""} return [write::GetModelPartNameWithParent $subModelPartId] } +# Safe getter for the new initial-state values. Old projects may not contain the +# new tree nodes until the interface updates their tree; missing nodes must be +# treated as disabled instead of breaking legacy configurations. +proc ::Dam::write::GetInitialStateValue { name { it "" } } { + if {[spdAux::getRoute $name] eq ""} {return ""} + return [write::getValue $name $it] +} + +# True when any of the initial-state transfer mechanisms is enabled. +proc ::Dam::write::IsInitialStateTransferEnabled { } { + if {[write::isBooleanTrue [Dam::write::GetInitialStateValue DamSaveInitialState]]} {return 1} + if {[write::isBooleanTrue [Dam::write::GetInitialStateValue DamLoadInitialState]]} {return 1} + if {[write::isBooleanTrue [Dam::write::GetInitialStateValue DamRestartInitialStresses]]} {return 1} + return 0 +} + # File-handler values use "- No file - ..." as the empty selection. proc ::Dam::write::IsNoInitialStateFile { value } { set value [string trim $value] @@ -962,15 +985,15 @@ proc ::Dam::write::ResolveInitialStatePath { value } { } proc ::Dam::write::GetSaveInitialStateProcessDict { } { - if {![write::isBooleanTrue [write::getValue DamSaveInitialState]]} {return ""} + if {![write::isBooleanTrue [Dam::write::GetInitialStateValue DamSaveInitialState]]} {return ""} - set group [write::getValue DamSaveInitialStatePart] - set saveStresses [write::isBooleanTrue [write::getValue DamSaveInitialStresses]] - set saveTemperature [write::isBooleanTrue [write::getValue DamSaveInitialTemperature]] - set saveReferenceTemperature [write::isBooleanTrue [write::getValue DamSaveInitialReferenceTemperature]] - set stressSource [write::getValue DamInitialStateStressSource] + set group [Dam::write::GetInitialStateValue DamSaveInitialStatePart] + set saveStresses [write::isBooleanTrue [Dam::write::GetInitialStateValue DamSaveInitialStresses]] + set saveTemperature [write::isBooleanTrue [Dam::write::GetInitialStateValue DamSaveInitialTemperature]] + set saveReferenceTemperature [write::isBooleanTrue [Dam::write::GetInitialStateValue DamSaveInitialReferenceTemperature]] + set stressSource [Dam::write::GetInitialStateValue DamInitialStateStressSource] if {$stressSource eq ""} {set stressSource "current_cauchy"} - set outputFile [string trim [write::getValue DamInitialStateOutputFile]] + set outputFile [string trim [Dam::write::GetInitialStateValue DamInitialStateOutputFile]] set parametersDict [dict create] dict set parametersDict model_part_name [Dam::write::GetInitialStateModelPartName $group] @@ -1000,14 +1023,14 @@ proc ::Dam::write::GetSaveInitialStateProcessDict { } { } proc ::Dam::write::GetLoadInitialStateProcessDict { } { - if {![write::isBooleanTrue [write::getValue DamLoadInitialState]]} {return ""} - - set group [write::getValue DamLoadInitialStatePart] - set inputFile [string trim [write::getValue DamLoadInitialStateFile]] - set transferStresses [write::isBooleanTrue [write::getValue DamTransferInitialStresses]] - set transferTemperature [write::isBooleanTrue [write::getValue DamTransferInitialTemperature]] - set transferReferenceTemperature [write::isBooleanTrue [write::getValue DamTransferInitialReferenceTemperature]] - set referencePolicy [write::getValue DamReferenceTemperaturePolicy] + if {![write::isBooleanTrue [Dam::write::GetInitialStateValue DamLoadInitialState]]} {return ""} + + set group [Dam::write::GetInitialStateValue DamLoadInitialStatePart] + set inputFile [string trim [Dam::write::GetInitialStateValue DamLoadInitialStateFile]] + set transferStresses [write::isBooleanTrue [Dam::write::GetInitialStateValue DamTransferInitialStresses]] + set transferTemperature [write::isBooleanTrue [Dam::write::GetInitialStateValue DamTransferInitialTemperature]] + set transferReferenceTemperature [write::isBooleanTrue [Dam::write::GetInitialStateValue DamTransferInitialReferenceTemperature]] + set referencePolicy [Dam::write::GetInitialStateValue DamReferenceTemperaturePolicy] if {$referencePolicy eq ""} {set referencePolicy "preserve"} set parametersDict [dict create] @@ -1037,13 +1060,72 @@ proc ::Dam::write::GetLoadInitialStateProcessDict { } { return $processDict } -# The load process runs before the first solution step and the save process at -# finalization, so both can coexist in the same calculation. Keep the load -# process first for a predictable lifecycle order. +# Splits a restart file name such as MainModelPart_1.0.rest into the base path +# expected by RestartUtility and the file label. Returns an empty pair when the +# name does not follow the _