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

1from pySDC.core.convergence_controller import ConvergenceController 

2 

3 

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 """ 

9 

10 def setup(self, controller, params, description, **kwargs): 

11 """ 

12 Define default parameters here. 

13 

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 

18 

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 

35 

36 def dependencies(self, controller, description, **kwargs): 

37 """ 

38 Load the embedded error estimator if needed. 

39 

40 Args: 

41 controller (pySDC.Controller): The controller 

42 description (dict): The description object used to instantiate the controller 

43 

44 Returns: 

45 None 

46 """ 

47 super().dependencies(controller, description) 

48 

49 if self.params.use_e_tol: 

50 from pySDC.implementations.convergence_controller_classes.estimate_embedded_error import ( 

51 EstimateEmbeddedError, 

52 ) 

53 

54 controller.add_convergence_controller( 

55 EstimateEmbeddedError, 

56 description=description, 

57 ) 

58 

59 return None 

60 

61 def post_iteration_processing(self, controller, step, **kwargs): 

62 """ 

63 Change the Newton tolerance after every iteration. 

64 

65 Args: 

66 controller (pySDC.Controller.controller): The controller 

67 step (pySDC.Step): The current step 

68 

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) 

85 

86 def set_tolerance(self, lvl, tol): 

87 """ 

88 Set the tolerance of the Newton solver of the problem. 

89 

90 Args: 

91 lvl (pySDC.Level): The level whose problem to change 

92 tol (float): The new tolerance 

93 

94 Returns: 

95 None 

96 """ 

97 lvl.prob.newton_tol = tol 

98 

99 def set_maxiter(self, description, maxiter): 

100 """ 

101 Set the maximum number of Newton iterations in the problem parameters of the description. 

102 

103 Args: 

104 description (dict): The description object used to instantiate the controller 

105 maxiter (int): The maximum number of Newton iterations 

106 

107 Returns: 

108 None 

109 """ 

110 description['problem_params']['newton_maxiter'] = maxiter