Coverage for pySDC/implementations/convergence_controller_classes/step_size_limiter.py: 100%
43 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-19 09:13 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-19 09:13 +0000
1import numpy as np
2from pySDC.core.convergence_controller import ConvergenceController
5class StepSizeLimiter(ConvergenceController):
6 """
7 Class to set limits to adaptive step size computation during run time
9 Please supply dt_min or dt_max in the params to limit in either direction
10 """
12 def setup(self, controller, params, description, **kwargs):
13 """
14 Define parameters here
16 Args:
17 controller (pySDC.Controller): The controller
18 params (dict): The params passed for this specific convergence controller
19 description (dict): The description object used to instantiate the controller
21 Returns:
22 (dict): The updated params dictionary
23 """
24 defaults = {
25 "control_order": +92,
26 "dt_min": 0,
27 "dt_max": np.inf,
28 }
29 return {**defaults, **super().setup(controller, params, description, **kwargs)}
31 def dependencies(self, controller, description, **kwargs):
32 """
33 Load the slope limiter if needed.
35 Args:
36 controller (pySDC.Controller): The controller
37 description (dict): The description object used to instantiate the controller
39 Returns:
40 None
41 """
42 slope_limiter_keys = ['dt_slope_min', 'dt_slope_max', 'dt_rel_min_slope']
43 available_keys = [me for me in slope_limiter_keys if me in self.params.__dict__.keys()]
45 if len(available_keys) > 0:
46 slope_limiter_params = {key: self.params.__dict__[key] for key in available_keys}
47 slope_limiter_params['control_order'] = self.params.control_order - 1
48 controller.add_convergence_controller(
49 StepSizeSlopeLimiter, params=slope_limiter_params, description=description
50 )
52 return None
54 def get_new_step_size(self, controller, S, **kwargs):
55 """
56 Enforce an upper and lower limit to the step size here.
57 Be aware that this is only tested when a new step size has been determined. That means if you set an initial
58 value for the step size outside of the limits, and you don't do any further step size control, that value will
59 go through.
60 Also, the final step is adjusted such that we reach Tend as best as possible, which might give step sizes below
61 the lower limit set here.
63 Args:
64 controller (pySDC.Controller): The controller
65 S (pySDC.Step): The current step
67 Returns:
68 None
69 """
70 for L in S.levels:
71 if L.status.dt_new is not None:
72 if L.status.dt_new < self.params.dt_min:
73 self.log(
74 f"Step size is below minimum, increasing from {L.status.dt_new:.2e} \
75 to \
76{self.params.dt_min:.2e}",
77 S,
78 )
79 L.status.dt_new = self.params.dt_min
80 elif L.status.dt_new > self.params.dt_max:
81 self.log(
82 f"Step size exceeds maximum, decreasing from {L.status.dt_new:.2e} to {self.params.dt_max:.2e}",
83 S,
84 )
85 L.status.dt_new = self.params.dt_max
87 return None
90class StepSizeSlopeLimiter(ConvergenceController):
91 """
92 Class to set limits to adaptive step size computation during run time
94 Please supply `dt_slope_min` or `dt_slope_max` in the params to limit in either direction.
95 You can also supply `dt_rel_min_slope` in order to keep the old step size in case the relative change is smaller
96 than this minimum.
97 """
99 def setup(self, controller, params, description, **kwargs):
100 """
101 Define parameters here
103 Args:
104 controller (pySDC.Controller): The controller
105 params (dict): The params passed for this specific convergence controller
106 description (dict): The description object used to instantiate the controller
108 Returns:
109 (dict): The updated params dictionary
110 """
111 defaults = {
112 "control_order": 91,
113 "dt_slope_min": 0,
114 "dt_slope_max": np.inf,
115 "dt_rel_min_slope": 0,
116 }
117 return {**defaults, **super().setup(controller, params, description, **kwargs)}
119 def get_new_step_size(self, controller, S, **kwargs):
120 """
121 Enforce an upper and lower limit to the slope of the step size here.
122 The final step is adjusted such that we reach Tend as best as possible, which might give step sizes below
123 the lower limit set here.
125 Args:
126 controller (pySDC.Controller): The controller
127 S (pySDC.Step): The current step
129 Returns:
130 None
131 """
132 for L in S.levels:
133 if L.status.dt_new is not None:
134 if L.status.dt_new / L.params.dt < self.params.dt_slope_min:
135 dt_new = L.params.dt * self.params.dt_slope_min
136 self.log(
137 f"Step size slope is below minimum, increasing from {L.status.dt_new:.2e} \
138 to \
139{dt_new:.2e}",
140 S,
141 )
142 L.status.dt_new = dt_new
143 elif L.status.dt_new / L.params.dt > self.params.dt_slope_max:
144 dt_new = L.params.dt * self.params.dt_slope_max
145 self.log(
146 f"Step size slope exceeds maximum, decreasing from {L.status.dt_new:.2e} \
147 to \
148{dt_new:.2e}",
149 S,
150 )
151 L.status.dt_new = dt_new
152 elif abs(L.status.dt_new / L.params.dt - 1) < self.params.dt_rel_min_slope:
153 L.status.dt_new = L.params.dt
154 self.log(
155 f"Step size did not change sufficiently to warrant step size change, keeping {L.status.dt_new:.2e}",
156 S,
157 )
159 return None