@@ -31,6 +31,12 @@ NEML2ModelExecutor::actionParams()
3131 "List of NEML2 variables to skip error checking when setting up the model input. If an "
3232 "input variable is skipped, its value will stay zero. If a required input variable is "
3333 "not skipped, an error will be raised." );
34+ params .addParam < bool > (
35+ "advance_step_on_device" ,
36+ false,
37+ "Keep state and forces on the device and advance it to old_state and old_forces without a "
38+ "roundtrip through MOOSE materials. This is only recommended for explicit time integration "
39+ "or when absolutely no restepping occurs (e.g. failed timesteps)." );
3440 return params ;
3541}
3642
@@ -68,6 +74,7 @@ NEML2ModelExecutor::NEML2ModelExecutor(const InputParameters & params)
6874#ifdef NEML2_ENABLED
6975 ,
7076 _batch_index_generator (getUserObject < NEML2BatchIndexGenerator > ("batch_index_generator" )),
77+ _advance_step_on_device (getParam < bool > ("advance_step_on_device" )),
7178 _output_ready (false),
7279 _error_message ("" )
7380#endif
@@ -167,6 +174,20 @@ NEML2ModelExecutor::initialSetup()
167174 "those called `NEML2To*MOOSEMaterialProperty`." );
168175}
169176
177+ void
178+ NEML2ModelExecutor ::timestepSetup ()
179+ {
180+ if (_advance_step_on_device && _t_step > 0 )
181+ {
182+ // Set old state variables and old forces
183+ if (model ().input_axis ().has_subaxis ("old_state" ) && model ().output_axis ().has_subaxis ("state" ))
184+ _in .slice ("old_state" ).fill (_out .slice ("state" ));
185+ if (model ().input_axis ().has_subaxis ("old_forces" ) &&
186+ model ().input_axis ().has_subaxis ("forces" ))
187+ _in .slice ("old_forces" ).fill (_in .slice ("forces" ));
188+ }
189+ }
190+
170191std ::size_t
171192NEML2ModelExecutor ::getBatchIndex (dof_id_type elem_id ) const
172193{
0 commit comments