11__doc__ = """Symplectic time steppers and concepts for integrating the kinematic and dynamic equations of rod-like objects. """
22
3- from typing import TYPE_CHECKING , Any
3+ from typing import TYPE_CHECKING , Any , Callable
44
55from itertools import zip_longest
66
77from elastica .typing import (
88 SystemCollectionType ,
9+ SystemType ,
910 StepType ,
1011 SteppersOperatorsType ,
1112)
1213
1314import numpy as np
1415
1516from elastica .systems .protocol import SymplecticSystemProtocol
16- from .protocol import SymplecticStepperProtocol
17+ from .protocol import StepperProtocol
1718
1819"""
1920Developer Note
2526
2627
2728class SymplecticStepperMixin :
28- def __init__ (self : SymplecticStepperProtocol ):
29+ get_steps : Callable [[], list [StepType ]]
30+ get_prefactors : Callable [[], list [StepType ]]
31+
32+ def __init__ (self ) -> None :
2933 self .steps_and_prefactors : SteppersOperatorsType = self .step_methods ()
3034
31- def step_methods (self : SymplecticStepperProtocol ) -> SteppersOperatorsType :
35+ def step_methods (self ) -> SteppersOperatorsType :
3236 # Let the total number of steps for the Symplectic method
3337 # be (2*n + 1) (for time-symmetry).
3438 _steps : list [StepType ] = self .get_steps ()
@@ -56,32 +60,14 @@ def no_operation(*args: Any) -> None:
5660 )
5761
5862 @property
59- def n_stages (self : SymplecticStepperProtocol ) -> int :
63+ def n_stages (self ) -> int :
6064 return len (self .steps_and_prefactors )
6165
6266 def step (
63- self : SymplecticStepperProtocol ,
67+ self ,
6468 SystemCollection : SystemCollectionType ,
6569 time : np .float64 | float ,
6670 dt : np .float64 | float ,
67- ) -> np .float64 :
68- return SymplecticStepperMixin .do_step (
69- self ,
70- self .steps_and_prefactors ,
71- SystemCollection ,
72- np .float64 (time ),
73- np .float64 (dt ),
74- )
75-
76- # TODO: Merge with .step method in the future.
77- # DEPRECATED: Use .step instead.
78- @staticmethod
79- def do_step (
80- TimeStepper : SymplecticStepperProtocol ,
81- steps_and_prefactors : SteppersOperatorsType ,
82- SystemCollection : SystemCollectionType ,
83- time : np .float64 ,
84- dt : np .float64 ,
8571 ) -> np .float64 :
8672 """
8773 Function for doing symplectic stepper over the user defined rods (system).
@@ -92,53 +78,73 @@ def do_step(
9278 The time after the integration step.
9379
9480 """
95- for kin_prefactor , kin_step , dyn_step in steps_and_prefactors [:- 1 ]:
81+ simulation_time = np .float64 (time )
82+ simulation_dt = np .float64 (dt )
9683
84+ for kin_prefactor , kin_step , dyn_step in self .steps_and_prefactors [:- 1 ]:
9785 for system in SystemCollection .final_systems ():
98- kin_step (system , time , dt )
86+ kin_step (system , simulation_time , simulation_dt )
9987
100- time += kin_prefactor (dt )
88+ simulation_time += kin_prefactor (simulation_dt )
10189
10290 # Constrain only values
103- SystemCollection .constrain_values (time )
91+ SystemCollection .constrain_values (simulation_time )
10492
10593 # We need internal forces and torques because they are used by interaction module.
10694 for system in SystemCollection .final_systems ():
107- system .compute_internal_forces_and_torques (time )
95+ system .compute_internal_forces_and_torques (simulation_time )
10896
10997 # Add external forces, controls etc.
110- SystemCollection .synchronize (time )
98+ SystemCollection .synchronize (simulation_time )
11199
112100 for system in SystemCollection .final_systems ():
113- dyn_step (system , time , dt )
101+ dyn_step (system , simulation_time , simulation_dt )
114102
115103 # Constrain only rates
116- SystemCollection .constrain_rates (time )
104+ SystemCollection .constrain_rates (simulation_time )
117105
118106 # Peel the last kinematic step and prefactor alone
119- last_kin_prefactor = steps_and_prefactors [- 1 ][0 ]
120- last_kin_step = steps_and_prefactors [- 1 ][1 ]
107+ last_kin_prefactor = self . steps_and_prefactors [- 1 ][0 ]
108+ last_kin_step = self . steps_and_prefactors [- 1 ][1 ]
121109
122110 for system in SystemCollection .final_systems ():
123- last_kin_step (system , time , dt )
124- time += last_kin_prefactor (dt )
125- SystemCollection .constrain_values (time )
111+ last_kin_step (system , simulation_time , simulation_dt )
112+ simulation_time += last_kin_prefactor (simulation_dt )
113+ SystemCollection .constrain_values (simulation_time )
126114
127115 # Call back function, will call the user defined call back functions and store data
128- SystemCollection .apply_callbacks (time , round (time / dt ))
116+ SystemCollection .apply_callbacks (
117+ simulation_time , round (simulation_time / simulation_dt )
118+ )
129119
130120 # Zero out the external forces and torques
131121 for system in SystemCollection .final_systems ():
132- system .zeroed_out_external_forces_and_torques (time )
122+ system .zeroed_out_external_forces_and_torques (simulation_time )
123+
124+ return simulation_time
125+
126+ @staticmethod
127+ def do_step (
128+ TimeStepper : StepperProtocol ,
129+ steps_and_prefactors : SteppersOperatorsType ,
130+ SystemCollection : SystemCollectionType ,
131+ time : np .float64 ,
132+ dt : np .float64 ,
133+ ) -> np .float64 : # pragma: no cover
134+ from warning import warn
133135
134- return time
136+ warn ("This method is deprecated. Use the instance method .step instead." )
137+ return Timestepper .step (SystemCollection , time , dt ) # type: ignore
135138
136139 def step_single_instance (
137- self : SymplecticStepperProtocol ,
138- System : SymplecticSystemProtocol ,
140+ self ,
141+ System : SystemType ,
139142 time : np .float64 ,
140143 dt : np .float64 ,
141144 ) -> np .float64 :
145+ """
146+ (The function is used for single system instance, mainly for testing purposes.)
147+ """
142148
143149 for kin_prefactor , kin_step , dyn_step in self .steps_and_prefactors [:- 1 ]:
144150 kin_step (System , time , dt )
0 commit comments