Coverage for pySDC/projects/Resilience/reachTendExactly.py: 100%
19 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-02-20 10:09 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-02-20 10:09 +0000
1import numpy as np
2from pySDC.core.convergence_controller import ConvergenceController
3from pySDC.implementations.convergence_controller_classes.check_convergence import CheckConvergence
6class ReachTendExactly(ConvergenceController):
7 """
8 This convergence controller will adapt the step size of (hopefully) the last step such that `Tend` is reached very closely.
9 Please pass the same `Tend` that you pass to the controller to the params for this to work.
10 """
12 def setup(self, controller, params, description, **kwargs):
13 defaults = {
14 "control_order": +94,
15 "Tend": None,
16 'min_step_size': 1e-10,
17 }
18 return {**defaults, **super().setup(controller, params, description, **kwargs)}
20 def get_new_step_size(self, controller, step, **kwargs):
21 L = step.levels[0]
22 time_size = step.status.time_size
24 if not CheckConvergence.check_convergence(step):
25 return None
27 dt = L.status.dt_new if L.status.dt_new else L.params.dt
28 time_left = self.params.Tend - L.time - L.dt
30 if (
31 time_left <= (dt + self.params.min_step_size) * time_size
32 and not step.status.restart
33 and time_left > 0
34 and step.status.last
35 ):
36 dt_new = (
37 min([(dt + self.params.min_step_size) * time_size, max([time_left, self.params.min_step_size])])
38 + time_size * np.finfo('float').eps * 10
39 ) / time_size
41 if dt_new != L.status.dt_new:
42 L.status.dt_new = dt_new
43 self.log(
44 f'Changing step size from {dt:12e} to {L.status.dt_new:.12e} because there is only {time_left:.12e} left.',
45 step,
46 )