Coverage for pySDC/implementations/convergence_controller_classes/inexactness.py: 88%
26 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-02 12:30 +0000
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-02 12:30 +0000
1from pySDC.core.convergence_controller import ConvergenceController
4class NewtonInexactness(ConvergenceController):
5 """
6 Gradually refine Newton tolerance based on SDC residual.
7 Be aware that the problem needs a parameter called "newton_tol" which controls the tolerance for the Newton solver for this to work!
8 """
10 def setup(self, controller, params, description, **kwargs):
11 """
12 Define default parameters here.
14 Args:
15 controller (pySDC.Controller): The controller
16 params (dict): The params passed for this specific convergence controller
17 description (dict): The description object used to instantiate the controller
19 Returns:
20 (dict): The updated params dictionary
21 """
22 defaults = {
23 "control_order": 500,
24 "ratio": 1e-2,
25 "min_tol": 0,
26 "max_tol": 1e99,
27 "maxiter": None,
28 "use_e_tol": 'e_tol' in description['level_params'].keys(),
29 "initial_tol": 1e-3,
30 **super().setup(controller, params, description, **kwargs),
31 }
32 if defaults['maxiter']:
33 self.set_maxiter(description, defaults['maxiter'])
34 return defaults
36 def dependencies(self, controller, description, **kwargs):
37 """
38 Load the embedded error estimator if needed.
40 Args:
41 controller (pySDC.Controller): The controller
42 description (dict): The description object used to instantiate the controller
44 Returns:
45 None
46 """
47 super().dependencies(controller, description)
49 if self.params.use_e_tol:
50 from pySDC.implementations.convergence_controller_classes.estimate_embedded_error import (
51 EstimateEmbeddedError,
52 )
54 controller.add_convergence_controller(
55 EstimateEmbeddedError,
56 description=description,
57 )
59 return None
61 def post_iteration_processing(self, controller, step, **kwargs):
62 """
63 Change the Newton tolerance after every iteration.
65 Args:
66 controller (pySDC.Controller.controller): The controller
67 step (pySDC.Step): The current step
69 Returns:
70 None
71 """
72 for lvl in step.levels:
73 # the controller computes the residual on the finest level only, so ask for it on the others
74 if lvl is not step.levels[0]:
75 lvl.sweep.compute_residual()
76 SDC_accuracy = (
77 lvl.status.get('error_embedded_estimate', lvl.status.residual)
78 if self.params.use_e_tol
79 else lvl.status.residual
80 )
81 SDC_accuracy = self.params.initial_tol if SDC_accuracy is None else SDC_accuracy
82 tol = max([min([SDC_accuracy * self.params.ratio, self.params.max_tol]), self.params.min_tol])
83 self.set_tolerance(lvl, tol)
84 self.log(f'Changed tolerance to {tol:.2e}', step)
86 def set_tolerance(self, lvl, tol):
87 """
88 Set the tolerance of the Newton solver of the problem.
90 Args:
91 lvl (pySDC.Level): The level whose problem to change
92 tol (float): The new tolerance
94 Returns:
95 None
96 """
97 lvl.prob.newton_tol = tol
99 def set_maxiter(self, description, maxiter):
100 """
101 Set the maximum number of Newton iterations in the problem parameters of the description.
103 Args:
104 description (dict): The description object used to instantiate the controller
105 maxiter (int): The maximum number of Newton iterations
107 Returns:
108 None
109 """
110 description['problem_params']['newton_maxiter'] = maxiter