Coverage for pySDC/implementations/convergence_controller_classes/step_size_limiter.py: 100%

40 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-04-29 09:02 +0000

1import numpy as np 

2from pySDC.core.ConvergenceController import ConvergenceController 

3 

4 

5class StepSizeLimiter(ConvergenceController): 

6 """ 

7 Class to set limits to adaptive step size computation during run time 

8 

9 Please supply dt_min or dt_max in the params to limit in either direction 

10 """ 

11 

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

13 """ 

14 Define parameters here 

15 

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 

20 

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)} 

30 

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

32 """ 

33 Load the slope limiter if needed. 

34 

35 Args: 

36 controller (pySDC.Controller): The controller 

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

38 

39 Returns: 

40 None 

41 """ 

42 slope_limiter_keys = ['dt_slope_min', 'dt_slope_max'] 

43 available_keys = [me for me in slope_limiter_keys if me in self.params.__dict__.keys()] 

44 

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 ) 

51 

52 return None 

53 

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. 

62 

63 Args: 

64 controller (pySDC.Controller): The controller 

65 S (pySDC.Step): The current step 

66 

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 

86 

87 return None 

88 

89 

90class StepSizeSlopeLimiter(ConvergenceController): 

91 """ 

92 Class to set limits to adaptive step size computation during run time 

93 

94 Please supply dt_min or dt_max in the params to limit in either direction 

95 """ 

96 

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

98 """ 

99 Define parameters here 

100 

101 Args: 

102 controller (pySDC.Controller): The controller 

103 params (dict): The params passed for this specific convergence controller 

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

105 

106 Returns: 

107 (dict): The updated params dictionary 

108 """ 

109 defaults = { 

110 "control_order": 91, 

111 "dt_slope_min": 0, 

112 "dt_slope_max": np.inf, 

113 } 

114 return {**defaults, **super().setup(controller, params, description, **kwargs)} 

115 

116 def get_new_step_size(self, controller, S, **kwargs): 

117 """ 

118 Enforce an upper and lower limit to the slope of the step size here. 

119 The final step is adjusted such that we reach Tend as best as possible, which might give step sizes below 

120 the lower limit set here. 

121 

122 Args: 

123 controller (pySDC.Controller): The controller 

124 S (pySDC.Step): The current step 

125 

126 Returns: 

127 None 

128 """ 

129 for L in S.levels: 

130 if L.status.dt_new is not None: 

131 if L.status.dt_new / L.params.dt < self.params.dt_slope_min: 

132 dt_new = L.params.dt * self.params.dt_slope_min 

133 self.log( 

134 f"Step size slope is below minimum, increasing from {L.status.dt_new:.2e} \ 

135 to \ 

136{dt_new:.2e}", 

137 S, 

138 ) 

139 L.status.dt_new = dt_new 

140 elif L.status.dt_new / L.params.dt > self.params.dt_slope_max: 

141 dt_new = L.params.dt * self.params.dt_slope_max 

142 self.log( 

143 f"Step size slope exceeds maximum, decreasing from {L.status.dt_new:.2e} \ 

144 to \ 

145{dt_new:.2e}", 

146 S, 

147 ) 

148 L.status.dt_new = dt_new 

149 

150 return None