Coverage for pySDC/projects/Resilience/strategies.py: 60%
1011 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-04 07:15 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-04 07:15 +0000
1import numpy as np
2from matplotlib.colors import TABLEAU_COLORS
4cmap = TABLEAU_COLORS
7def merge_descriptions(descA, descB):
8 """
9 Merge two dictionaries that may contain dictionaries, which happens when merging descriptions, for instance.
11 Keys that occur in both dictionaries will be overwritten by the ones from `descB` and `descA` will be modified, not
12 copied!
14 Args:
15 descA (dict): Dictionary that you want to merge into
16 descB (dict): Dictionary you want to merge from
18 Returns:
19 dict: decsA with updated parameters
20 """
21 for key in descB.keys():
22 if type(descB[key]) == dict:
23 descA[key] = merge_descriptions(descA.get(key, {}), descB[key])
24 else:
25 descA[key] = descB[key]
26 return descA
29class Strategy:
30 '''
31 Abstract class for resilience strategies
32 '''
34 def __init__(self, useMPI=False, skip_residual_computation='none', stop_at_nan=True, **kwargs):
35 '''
36 Initialization routine
37 '''
38 self.useMPI = useMPI
39 self.max_steps = 1e5
41 # set default values for plotting
42 self.linestyle = '-'
43 self.marker = '.'
44 self.name = ''
45 self.bar_plot_x_label = ''
46 self.color = list(cmap.values())[0]
48 # parameters for computational efficiency
49 if skip_residual_computation == 'all':
50 self.skip_residual_computation = ('IT_CHECK', 'IT_DOWN', 'IT_UP', 'IT_FINE', 'IT_COARSE')
51 elif skip_residual_computation == 'most':
52 self.skip_residual_computation = ('IT_DOWN', 'IT_UP', 'IT_FINE', 'IT_COARSE')
53 elif skip_residual_computation == 'none':
54 self.skip_residual_computation = ()
55 else:
56 raise NotImplementedError(
57 f'Don\'t know when to skip residual computation with rule \"{skip_residual_computation}\"'
58 )
60 self.stop_at_nan = stop_at_nan
62 # setup custom descriptions
63 self.custom_description = {}
64 self.custom_description['sweeper_params'] = {'skip_residual_computation': self.skip_residual_computation}
65 self.custom_description['level_params'] = {}
66 self.custom_description['problem_params'] = {}
67 self.custom_description['step_params'] = {}
68 self.custom_description['convergence_controllers'] = {}
70 # prepare parameters for masks to identify faults that cannot be fixed by this strategy
71 self.fixable = []
72 self.fixable += [
73 {
74 'key': 'node',
75 'op': 'gt',
76 'val': 0,
77 }
78 ]
79 self.fixable += [
80 {
81 'key': 'error',
82 'op': 'isfinite',
83 }
84 ]
86 # stuff for work-precision diagrams
87 self.precision_parameter = None
88 self.precision_parameter_loc = []
90 def __str__(self):
91 return self.name
93 def get_controller_params(self, **kwargs):
94 return {'all_to_done': False}
96 def get_description_for_tolerance(self, problem, param, **kwargs):
97 return {}
99 def get_fixable_params(self, **kwargs):
100 """
101 Return a list containing dictionaries which can be passed to `FaultStats.get_mask` as keyword arguments to
102 obtain a mask of faults that can be fixed
104 Returns:
105 list: Dictionary of parameters
106 """
107 return self.fixable
109 def get_fault_args(self, problem, num_procs):
110 '''
111 Routine to get arguments for the faults that are exempt from randomization
113 Args:
114 problem: A function that runs a pySDC problem, see imports for available problems
115 num_procs (int): Number of processes you intend to run with
117 Returns:
118 dict: Arguments for the faults that are exempt from randomization
119 '''
120 args = {}
121 args['target'] = 0
123 if problem.__name__ == "run_vdp":
124 args['time'] = 5.5 # 25
125 elif problem.__name__ == "run_Schroedinger":
126 args['time'] = 0.3
127 elif problem.__name__ == "run_quench":
128 args['time'] = 41.0
129 elif problem.__name__ == "run_Lorenz":
130 args['time'] = 10
131 elif problem.__name__ == "run_AC":
132 args['time'] = 1e-2
133 elif problem.__name__ == "run_RBC":
134 args['time'] = 20.19
135 elif problem.__name__ == "run_GS":
136 args['time'] = 100.0
138 return args
140 def get_random_params(self, problem, num_procs):
141 '''
142 Routine to get parameters for the randomization of faults
144 Args:
145 problem: A function that runs a pySDC problem, see imports for available problems
146 num_procs (int): Number of processes you intend to run with
148 Returns:
149 dict: Randomization parameters
150 '''
151 base_params = self.get_base_parameters(problem, num_procs)
153 rnd_params = {}
154 rnd_params['iteration'] = base_params['step_params']['maxiter']
155 rnd_params['rank'] = num_procs
157 if problem.__name__ in ['run_Schroedinger', 'run_quench', 'run_AC', 'run_RBC', 'run_GS']:
158 rnd_params['min_node'] = 1
160 if problem.__name__ == "run_quench":
161 rnd_params['iteration'] = 5
162 elif problem.__name__ == 'run_Lorenz':
163 rnd_params['iteration'] = 5
164 elif problem.__name__ == 'run_RBC':
165 rnd_params['problem_pos'] = [3, 16, 16]
166 elif problem.__name__ == 'run_vdp':
167 rnd_params['iteration'] = 5
169 return rnd_params
171 @property
172 def style(self):
173 """
174 Get the plotting parameters for the strategy.
175 Supply them to a plotting function using `**`
177 Returns:
178 (dict): The plotting parameters as a dictionary
179 """
180 return {
181 'marker': self.marker,
182 'label': self.label,
183 'color': self.color,
184 'ls': self.linestyle,
185 }
187 @property
188 def label(self):
189 """
190 Get a label for plotting
191 """
192 return self.name
194 @classmethod
195 def get_Tend(cls, problem, num_procs=1, resilience_experiment=False):
196 '''
197 Get the final time of runs for fault stats based on the problem
199 Args:
200 problem (function): A problem to run
201 num_procs (int): Number of processes
203 Returns:
204 float: Tend to put into the run
205 '''
206 if problem.__name__ == "run_vdp":
207 if resilience_experiment:
208 return 11.5
209 else:
210 return 20
211 elif problem.__name__ == "run_piline":
212 return 20.0
213 elif problem.__name__ == "run_Lorenz":
214 return 20
215 elif problem.__name__ == "run_Schroedinger":
216 return 1.0
217 elif problem.__name__ == "run_quench":
218 return 500.0
219 elif problem.__name__ == "run_AC":
220 return 0.025
221 elif problem.__name__ == "run_RBC":
222 return 21
223 elif problem.__name__ == "run_GS":
224 return 500
225 else:
226 raise NotImplementedError('I don\'t have a final time for your problem!')
228 def get_base_parameters(self, problem, num_procs=1):
229 '''
230 Get a base parameters for the problems independent of the strategy.
232 Args:
233 problem (function): A problem to run
234 num_procs (int): Number of processes
236 Returns:
237 dict: Custom description
238 '''
239 from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeLimiter
241 custom_description = {}
242 custom_description['step_params'] = {}
243 custom_description['level_params'] = {}
244 custom_description['problem_params'] = {}
246 if problem.__name__ == "run_vdp":
247 custom_description['step_params'] = {'maxiter': 3}
248 custom_description['problem_params'] = {
249 'u0': np.array([1.1, 0], dtype=np.float64),
250 'mu': 1000,
251 'crash_at_maxiter': False,
252 'newton_tol': 1e-11,
253 'stop_at_nan': False,
254 }
255 custom_description['level_params'] = {'dt': 1e-4}
257 elif problem.__name__ == "run_Lorenz":
258 custom_description['step_params'] = {'maxiter': 5}
259 custom_description['level_params'] = {'dt': 1e-3}
260 custom_description['problem_params'] = {'stop_at_nan': False}
261 elif problem.__name__ == "run_Schroedinger":
262 custom_description['step_params'] = {'maxiter': 5}
263 custom_description['level_params'] = {'dt': 1e-2, 'restol': -1}
264 custom_description['problem_params']['nvars'] = (256, 256)
265 elif problem.__name__ == "run_quench":
266 custom_description['level_params'] = {'restol': -1, 'dt': 8.0}
267 custom_description['step_params'] = {'maxiter': 5}
268 custom_description['problem_params'] = {
269 'newton_maxiter': 29,
270 'newton_tol': 1e-7,
271 'nvars': 2**6,
272 'direct_solver': False,
273 'lintol': 1e-8,
274 'liniter': 29,
275 'order': 6,
276 }
277 elif problem.__name__ == "run_AC":
278 eps = 4e-2
279 custom_description['step_params'] = {'maxiter': 5}
280 custom_description['problem_params'] = {
281 'nvars': (128,) * 2,
282 'init_type': 'circle',
283 'eps': eps,
284 'radius': 0.25,
285 'nu': 2,
286 }
287 custom_description['level_params'] = {'restol': -1, 'dt': 0.1 * eps**2}
288 elif problem.__name__ == 'run_RBC':
289 custom_description['level_params']['dt'] = 2.5e-2 if num_procs == 4 else 5e-2
290 custom_description['step_params'] = {'maxiter': 5}
291 elif problem.__name__ == 'run_GS':
292 custom_description['level_params']['dt'] = 1.0
293 custom_description['step_params'] = {'maxiter': 5}
295 custom_description['convergence_controllers'] = {
296 # StepSizeLimiter: {'dt_min': self.get_Tend(problem=problem, num_procs=num_procs) / self.max_steps}
297 }
299 if self.stop_at_nan:
300 from pySDC.implementations.convergence_controller_classes.crash import StopAtNan
302 custom_description['convergence_controllers'][StopAtNan] = {'thresh': 1e20}
304 from pySDC.implementations.convergence_controller_classes.crash import StopAtMaxRuntime
306 max_runtime = {
307 'run_vdp': 1000,
308 'run_Lorenz': 500,
309 'run_Schroedinger': 150,
310 'run_quench': 150,
311 'run_AC': 150,
312 'run_RBC': 1000,
313 'run_GS': 100,
314 }
316 custom_description['convergence_controllers'][StopAtMaxRuntime] = {
317 'max_runtime': max_runtime.get(problem.__name__, 100)
318 }
319 return custom_description
321 def get_custom_description(self, problem, num_procs=1):
322 '''
323 Get a custom description based on the problem
325 Args:
326 problem (function): A problem to run
327 num_procs (int): Number of processes
329 Returns:
330 dict: Custom description
331 '''
332 custom_description = self.get_base_parameters(problem, num_procs)
333 return merge_descriptions(custom_description, self.custom_description)
335 def get_custom_description_for_faults(self, problem, *args, **kwargs):
336 '''
337 Get a custom description based on the problem to run the fault stuff
339 Returns:
340 dict: Custom description
341 '''
342 custom_description = self.get_custom_description(problem, *args, **kwargs)
343 if problem.__name__ == "run_vdp":
344 custom_description['step_params'] = {'maxiter': 5}
345 custom_description['problem_params'] = {
346 'u0': np.array([2.0, 0], dtype=np.float64),
347 'mu': 5,
348 'crash_at_maxiter': False,
349 'newton_tol': 1e-11,
350 'stop_at_nan': False,
351 }
352 custom_description['level_params'] = {'dt': 1e-2}
353 return custom_description
355 def get_reference_value(self, problem, key, op, num_procs=1):
356 """
357 Get a reference value for a given problem for testing in CI.
359 Args:
360 problem: A function that runs a pySDC problem, see imports for available problems
361 key (str): The name of the variable you want to compare
362 op (function): The operation you want to apply to the data
363 num_procs (int): Number of processes
365 Returns:
366 The reference value
367 """
368 raise NotImplementedError(
369 f'The reference value you are looking for is not implemented for {type(self).__name__} strategy!'
370 )
373class InexactBaseStrategy(Strategy):
374 """
375 Base class for inexact strategies.
376 """
378 def __init__(
379 self, double_adaptivity=False, newton_inexactness=True, linear_inexactness=True, SDC_maxiter=16, **kwargs
380 ):
381 kwargs = {**kwargs, 'skip_residual_computation': 'most'}
382 super().__init__(**kwargs)
383 self.double_adaptivity = double_adaptivity
384 self.newton_inexactness = newton_inexactness
385 self.linear_inexactness = linear_inexactness
386 self.SDC_maxiter = SDC_maxiter
388 def get_controller_params(self, **kwargs):
389 return {'all_to_done': True}
391 def get_custom_description(self, problem, num_procs=1):
392 from pySDC.implementations.convergence_controller_classes.inexactness import NewtonInexactness
394 preconditioner = {
395 'run_Lorenz': 'MIN-SR-NS',
396 }.get(problem.__name__, 'MIN-SR-S')
398 desc = {}
399 desc['sweeper_params'] = {'QI': preconditioner}
400 desc['step_params'] = {'maxiter': self.SDC_maxiter}
401 desc['problem_params'] = {}
402 desc['level_params'] = {'restol': 1e-8, 'residual_type': 'last_abs'}
403 desc['convergence_controllers'] = {}
405 inexactness_params = {
406 'min_tol': 1e-12,
407 'ratio': 1e-2,
408 'max_tol': 1e-4,
409 'use_e_tol': False,
410 'maxiter': 15,
411 }
413 if self.newton_inexactness and problem.__name__ not in ['run_Schroedinger', 'run_AC', 'run_RBC', 'run_GS']:
414 if problem.__name__ == 'run_quench':
415 inexactness_params['ratio'] = 1e-1
416 inexactness_params['min_tol'] = 1e-11
417 inexactness_params['maxiter'] = 5
418 elif problem.__name__ == "run_vdp":
419 inexactness_params['ratio'] = 1e-5
420 inexactness_params['min_tol'] = 1e-15
421 inexactness_params['maxiter'] = 9
422 desc['convergence_controllers'][NewtonInexactness] = inexactness_params
424 if problem.__name__ in ['run_vdp']:
425 desc['problem_params']['stop_at_nan'] = False
427 if self.linear_inexactness and problem.__name__ in ['run_quench']:
428 desc['problem_params']['inexact_linear_ratio'] = 1e-1
429 if problem.__name__ in ['run_quench']:
430 desc['problem_params']['direct_solver'] = False
431 desc['problem_params']['liniter'] = 9
432 desc['problem_params']['min_lintol'] = 1e-11
434 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
436 desc['convergence_controllers'][BasicRestarting.get_implementation(useMPI=self.useMPI)] = {
437 'max_restarts': 29,
438 'crash_after_max_restarts': True,
439 }
440 return merge_descriptions(super().get_custom_description(problem, num_procs), desc)
443class BaseStrategy(Strategy):
444 '''
445 Do a fixed iteration count
446 '''
448 def __init__(self, skip_residual_computation='all', **kwargs):
449 '''
450 Initialization routine
451 '''
452 super().__init__(skip_residual_computation=skip_residual_computation, **kwargs)
453 self.color = list(cmap.values())[0]
454 self.marker = 'o'
455 self.name = 'base'
456 self.bar_plot_x_label = 'base'
457 self.precision_parameter = 'dt'
458 self.precision_parameter_loc = ['level_params', 'dt']
460 @property
461 def label(self):
462 return r'fixed'
464 def get_custom_description(self, problem, num_procs):
465 desc = super().get_custom_description(problem, num_procs)
466 if problem.__name__ == "run_AC":
467 desc['level_params']['dt'] = 1e-2 * desc['problem_params']['eps'] ** 2
468 return desc
470 def get_custom_description_for_faults(self, problem, num_procs, *args, **kwargs):
471 desc = self.get_custom_description(problem, num_procs, *args, **kwargs)
472 if problem.__name__ == "run_quench":
473 desc['level_params']['dt'] = 5.0
474 elif problem.__name__ == "run_AC":
475 desc['level_params']['dt'] = 4e-5 if num_procs == 4 else 8e-5
476 elif problem.__name__ == "run_GS":
477 desc['level_params']['dt'] = 4e-1
478 elif problem.__name__ == "run_vdp":
479 desc['step_params'] = {'maxiter': 5}
480 desc['problem_params'] = {
481 'u0': np.array([2.0, 0], dtype=np.float64),
482 'mu': 5,
483 'crash_at_maxiter': False,
484 'newton_tol': 1e-11,
485 'stop_at_nan': False,
486 }
487 desc['level_params'] = {'dt': 4.5e-2}
488 return desc
490 def get_reference_value(self, problem, key, op, num_procs=1):
491 """
492 Get a reference value for a given problem for testing in CI.
494 Args:
495 problem: A function that runs a pySDC problem, see imports for available problems
496 key (str): The name of the variable you want to compare
497 op (function): The operation you want to apply to the data
498 num_procs (int): Number of processes
500 Returns:
501 The reference value
502 """
503 if problem.__name__ == "run_Lorenz":
504 if key == 'work_newton' and op == sum:
505 return 12350
506 elif key == 'e_global_post_run' and op == max:
507 return 1.3527453646133836e-07
509 super().get_reference_value(problem, key, op, num_procs)
512class AdaptivityStrategy(Strategy):
513 '''
514 Adaptivity as a resilience strategy
515 '''
517 def __init__(self, **kwargs):
518 '''
519 Initialization routine
520 '''
521 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
523 kwargs['skip_residual_computation'] = 'all'
524 super().__init__(**kwargs)
525 self.color = list(cmap.values())[1]
526 self.marker = '*'
527 self.name = 'adaptivity'
528 self.bar_plot_x_label = 'adaptivity'
529 self.precision_parameter = 'e_tol'
530 self.precision_parameter_loc = ['convergence_controllers', Adaptivity, 'e_tol']
532 @property
533 def label(self):
534 return r'$\Delta t$-adaptivity'
536 # def get_fixable_params(self, maxiter, **kwargs):
537 # """
538 # Here faults occurring in the last iteration cannot be fixed.
540 # Args:
541 # maxiter (int): Max. iterations until convergence is declared
543 # Returns:
544 # (list): Contains dictionaries of keyword arguments for `FaultStats.get_mask`
545 # """
546 # self.fixable += [
547 # {
548 # 'key': 'iteration',
549 # 'op': 'lt',
550 # 'val': maxiter,
551 # }
552 # ]
553 # return self.fixable
555 def get_custom_description(self, problem, num_procs):
556 '''
557 Routine to get a custom description that adds adaptivity
559 Args:
560 problem: A function that runs a pySDC problem, see imports for available problems
561 num_procs (int): Number of processes you intend to run with
563 Returns:
564 The custom descriptions you can supply to the problem when running it
565 '''
566 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
567 from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeLimiter
569 base_params = super().get_custom_description(problem, num_procs)
570 custom_description = {}
571 custom_description['convergence_controllers'] = {}
573 dt_max = np.inf
574 dt_slope_max = np.inf
575 dt_slope_min = 0
576 beta = 0.9
578 if problem.__name__ == "run_piline":
579 e_tol = 1e-7
580 elif problem.__name__ == "run_vdp":
581 e_tol = 2e-5
582 elif problem.__name__ == "run_Lorenz":
583 e_tol = 1e-6 if num_procs == 4 else 1e-7
584 elif problem.__name__ == "run_Schroedinger":
585 e_tol = 4e-7
586 elif problem.__name__ == "run_quench":
587 e_tol = 1e-8
588 custom_description['problem_params'] = {
589 'newton_tol': 1e-10,
590 'lintol': 1e-11,
591 }
593 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
595 custom_description['convergence_controllers'][BasicRestarting.get_implementation(useMPI=self.useMPI)] = {
596 'max_restarts': 99,
597 }
598 elif problem.__name__ == "run_AC":
599 e_tol = 1e-7
600 # dt_max = 0.1 * base_params['problem_params']['eps'] ** 2
601 elif problem.__name__ == 'run_RBC':
602 if num_procs == 4:
603 e_tol = 2e-2
604 else:
605 e_tol = 1e-4
606 dt_slope_min = 1
607 beta = 0.5
608 elif problem.__name__ == 'run_GS':
609 e_tol = 1e-5
611 else:
612 raise NotImplementedError(
613 'I don\'t have a tolerance for adaptivity for your problem. Please add one to the\
614 strategy'
615 )
617 custom_description['convergence_controllers'][Adaptivity] = {
618 'e_tol': e_tol,
619 'dt_slope_max': dt_slope_max,
620 'dt_rel_min_slope': dt_slope_min,
621 'beta': beta,
622 }
623 custom_description['convergence_controllers'][StepSizeLimiter] = {
624 'dt_max': dt_max,
625 }
626 return merge_descriptions(base_params, custom_description)
628 def get_reference_value(self, problem, key, op, num_procs=1):
629 """
630 Get a reference value for a given problem for testing in CI.
632 Args:
633 problem: A function that runs a pySDC problem, see imports for available problems
634 key (str): The name of the variable you want to compare
635 op (function): The operation you want to apply to the data
636 num_procs (int): Number of processes
638 Returns:
639 The reference value
640 """
641 if problem.__name__ == 'run_Lorenz':
642 if key == 'work_newton' and op == sum:
643 return 2989
644 elif key == 'e_global_post_run' and op == max:
645 return 5.636767497207984e-08
647 super().get_reference_value(problem, key, op, num_procs)
649 def get_custom_description_for_faults(self, problem, num_procs, *args, **kwargs):
650 from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeLimiter
651 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
652 from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeSlopeLimiter
653 from pySDC.projects.Resilience.RBC import ReachTendExactly
655 desc = self.get_custom_description(problem, num_procs, *args, **kwargs)
656 if problem.__name__ == "run_quench":
657 desc['level_params']['dt'] = 1.1e1
658 desc['convergence_controllers'][Adaptivity]['e_tol'] = 1e-6
659 elif problem.__name__ == "run_AC":
660 desc['convergence_controllers'][Adaptivity]['e_tol'] = 1e-5
661 elif problem.__name__ == "run_GS":
662 desc['convergence_controllers'][Adaptivity]['e_tol'] = 2e-6
663 elif problem.__name__ == "run_vdp":
664 desc['step_params'] = {'maxiter': 5}
665 desc['sweeper_params'] = {'num_nodes': 3, 'QI': 'LU'}
666 desc['problem_params'] = {
667 'u0': np.array([2.0, 0], dtype=np.float64),
668 'mu': 5,
669 'crash_at_maxiter': True,
670 'newton_tol': 1e-8,
671 'stop_at_nan': True,
672 'relative_tolerance': False,
673 }
674 desc['level_params'] = {'dt': 8e-3}
675 desc['convergence_controllers'][Adaptivity]['e_tol'] = 2e-7
676 desc['convergence_controllers'][ReachTendExactly] = {'Tend': 11.5}
677 # desc['convergence_controllers'][StepSizeSlopeLimiter] = {'dt_slope_min': 1/4, 'dt_slope_max': 4}
678 return desc
681class AdaptivityRestartFirstStep(AdaptivityStrategy):
682 def __init__(self, **kwargs):
683 super().__init__(**kwargs)
684 self.color = 'teal'
685 self.name = 'adaptivityRestartFirstStep'
687 def get_custom_description(self, problem, num_procs):
688 '''
689 Add the other version of basic restarting.
691 Args:
692 problem: A function that runs a pySDC problem, see imports for available problems
693 num_procs (int): Number of processes you intend to run with
695 Returns:
696 The custom descriptions you can supply to the problem when running it
697 '''
698 custom_description = super().get_custom_description(problem, num_procs)
699 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
701 custom_description['convergence_controllers'][BasicRestarting.get_implementation(useMPI=self.useMPI)] = {
702 'max_restarts': 15,
703 'restart_from_first_step': True,
704 }
705 return custom_description
707 @property
708 def label(self):
709 return f'{super().label} restart from first step'
712class AdaptiveHotRodStrategy(Strategy):
713 '''
714 Adaptivity + Hot Rod as a resilience strategy
715 '''
717 def __init__(self, **kwargs):
718 '''
719 Initialization routine
720 '''
721 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
723 kwargs['skip_residual_computation'] = 'all'
724 super().__init__(**kwargs)
725 self.color = list(cmap.values())[4]
726 self.marker = '.'
727 self.name = 'adaptive Hot Rod'
728 self.bar_plot_x_label = 'adaptive\nHot Rod'
729 self.precision_parameter = 'e_tol'
730 self.precision_parameter_loc = ['convergence_controllers', Adaptivity, 'e_tol']
732 def get_custom_description(self, problem, num_procs):
733 '''
734 Routine to get a custom description that adds adaptivity and Hot Rod
736 Args:
737 problem: A function that runs a pySDC problem, see imports for available problems
738 num_procs (int): Number of processes you intend to run with
740 Returns:
741 The custom description you can supply to the problem when running it
742 '''
743 from pySDC.implementations.convergence_controller_classes.hotrod import HotRod
744 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
746 if problem.__name__ == "run_vdp":
747 e_tol = 3e-7
748 dt_min = 1e-3
749 maxiter = 4
750 HotRod_tol = 2e-6
751 elif problem.__name__ == "run_Lorenz":
752 e_tol = 3e-7
753 dt_min = 1e-3
754 maxiter = 4
755 HotRod_tol = 2e-6
756 else:
757 raise NotImplementedError(
758 'I don\'t have a tolerance for adaptive Hot Rod for your problem. Please add one \
759to the strategy'
760 )
762 no_storage = num_procs > 1
764 custom_description = {
765 'convergence_controllers': {
766 HotRod: {'HotRod_tol': HotRod_tol, 'no_storage': no_storage},
767 Adaptivity: {'e_tol': e_tol, 'dt_min': dt_min, 'embedded_error_flavor': 'linearized'},
768 },
769 'step_params': {'maxiter': maxiter},
770 }
772 return merge_descriptions(super().get_custom_description(problem, num_procs), custom_description)
774 def get_reference_value(self, problem, key, op, num_procs=1):
775 """
776 Get a reference value for a given problem for testing in CI.
778 Args:
779 problem: A function that runs a pySDC problem, see imports for available problems
780 key (str): The name of the variable you want to compare
781 op (function): The operation you want to apply to the data
782 num_procs (int): Number of processes
784 Returns:
785 The reference value
786 """
787 if problem.__name__ == "run_Lorenz":
788 if key == 'work_newton' and op == sum:
789 return 5092
790 elif key == 'e_global_post_run' and op == max:
791 return 4.107116318152748e-06
793 super().get_reference_value(problem, key, op, num_procs)
796class IterateStrategy(Strategy):
797 '''
798 Iterate for as much as you want
799 '''
801 def __init__(self, **kwargs):
802 '''
803 Initialization routine
804 '''
805 kwargs['skip_residual_computation'] = 'most'
806 super().__init__(**kwargs)
807 self.color = list(cmap.values())[2]
808 self.marker = 'v'
809 self.name = 'iterate'
810 self.bar_plot_x_label = 'iterate'
811 self.precision_parameter = 'restol'
812 self.precision_parameter_loc = ['level_params', 'restol']
814 @property
815 def label(self):
816 return r'$k$-adaptivity'
818 def get_custom_description(self, problem, num_procs):
819 '''
820 Routine to get a custom description that allows for adaptive iteration counts
822 Args:
823 problem: A function that runs a pySDC problem, see imports for available problems
824 num_procs (int): Number of processes you intend to run with
826 Returns:
827 The custom description you can supply to the problem when running it
828 '''
829 restol = -1
830 e_tol = -1
832 if problem.__name__ == "run_piline":
833 restol = 2.3e-8
834 elif problem.__name__ == "run_vdp":
835 restol = 9e-7
836 elif problem.__name__ == "run_Lorenz":
837 restol = 16e-7
838 elif problem.__name__ == "run_Schroedinger":
839 restol = 6.5e-7
840 elif problem.__name__ == "run_quench":
841 restol = 1e-7
842 elif problem.__name__ == "run_AC":
843 restol = 1e-11
844 elif problem.__name__ == "run_RBC":
845 restol = 1e-4
846 elif problem.__name__ == "run_GS":
847 restol = 1e-4
848 else:
849 raise NotImplementedError(
850 'I don\'t have a residual tolerance for your problem. Please add one to the \
851strategy'
852 )
854 custom_description = {
855 'step_params': {'maxiter': 99},
856 'level_params': {'restol': restol, 'e_tol': e_tol},
857 }
859 if problem.__name__ == "run_quench":
860 custom_description['level_params']['dt'] = 1.0
862 return merge_descriptions(super().get_custom_description(problem, num_procs), custom_description)
864 def get_random_params(self, problem, num_procs):
865 '''
866 Routine to get parameters for the randomization of faults
868 Args:
869 problem: A function that runs a pySDC problem, see imports for available problems
870 num_procs (int): Number of processes you intend to run with
872 Returns:
873 dict: Randomization parameters
874 '''
876 rnd_params = super().get_random_params(problem, num_procs)
877 if problem.__name__ == "run_quench":
878 rnd_params['iteration'] = 1
879 return rnd_params
881 def get_reference_value(self, problem, key, op, num_procs=1):
882 """
883 Get a reference value for a given problem for testing in CI.
885 Args:
886 problem: A function that runs a pySDC problem, see imports for available problems
887 key (str): The name of the variable you want to compare
888 op (function): The operation you want to apply to the data
889 num_procs (int): Number of processes
891 Returns:
892 The reference value
893 """
894 if problem.__name__ == "run_Lorenz":
895 if key == 'work_newton' and op == sum:
896 return 9200
897 elif key == 'e_global_post_run' and op == max:
898 return 2.139863344829962e-05
900 super().get_reference_value(problem, key, op, num_procs)
903class kAdaptivityStrategy(IterateStrategy):
904 def __init__(self, **kwargs):
905 super().__init__(**kwargs)
906 self.precision_parameter = 'dt'
907 self.precision_parameter_loc = ['level_params', 'dt']
909 def get_custom_description(self, problem, num_procs, *args, **kwargs):
910 desc = super().get_custom_description(problem, num_procs, *args, **kwargs)
911 desc['level_params']['restol'] = 1e-9
912 if problem.__name__ == "run_quench":
913 desc['problem_params']['newton_tol'] = 1e-9
914 desc['problem_params']['lintol'] = 1e-9
915 desc['level_params']['dt'] = 2.5
916 elif problem.__name__ == "run_AC":
917 desc['level_params']['restol'] = 1e-11
918 desc['level_params']['dt'] = 0.4 * desc['problem_params']['eps'] ** 2 / 8.0
919 elif problem.__name__ == "run_RBC":
920 desc['level_params']['dt'] = 7e-2
921 desc['level_params']['restol'] = 1e-6
922 desc['level_params']['e_tol'] = 1e-7
923 elif problem.__name__ == "run_GS":
924 desc['level_params']['dt'] = 1.0
925 desc['level_params']['restol'] = 1e-9
926 return desc
928 def get_custom_description_for_faults(self, problem, num_procs, *args, **kwargs):
929 desc = self.get_custom_description(problem, num_procs, *args, **kwargs)
930 if problem.__name__ == 'run_quench':
931 desc['level_params']['dt'] = 5.0
932 elif problem.__name__ == 'run_AC':
933 desc['level_params']['dt'] = 4e-4 if num_procs == 4 else 5e-4
934 desc['level_params']['restol'] = 1e-5 if num_procs == 4 else 1e-11
935 elif problem.__name__ == 'run_RBC':
936 desc['level_params']['restol'] = 1e-3 if num_procs == 4 else 1e-6
937 elif problem.__name__ == 'run_Lorenz':
938 desc['level_params']['dt'] = 8e-3
939 elif problem.__name__ == "run_vdp":
940 desc['sweeper_params'] = {'num_nodes': 3}
941 desc['problem_params'] = {
942 'u0': np.array([2.0, 0], dtype=np.float64),
943 'mu': 5,
944 'crash_at_maxiter': False,
945 'newton_tol': 1e-11,
946 'stop_at_nan': False,
947 }
948 desc['level_params'] = {'dt': 4.0e-2, 'restol': 1e-7}
949 return desc
951 def get_reference_value(self, problem, key, op, num_procs=1):
952 """
953 Get a reference value for a given problem for testing in CI.
955 Args:
956 problem: A function that runs a pySDC problem, see imports for available problems
957 key (str): The name of the variable you want to compare
958 op (function): The operation you want to apply to the data
959 num_procs (int): Number of processes
961 Returns:
962 The reference value
963 """
964 if problem.__name__ == "run_Lorenz":
965 if key == 'work_newton' and op == sum:
966 return 12350
967 elif key == 'e_global_post_run' and op == max:
968 return 1.3527453646133836e-07
970 super().get_reference_value(problem, key, op, num_procs)
973class HotRodStrategy(Strategy):
974 '''
975 Hot Rod as a resilience strategy
976 '''
978 def __init__(self, **kwargs):
979 '''
980 Initialization routine
981 '''
982 kwargs['skip_residual_computation'] = 'all'
983 super().__init__(**kwargs)
984 self.color = list(cmap.values())[3]
985 self.marker = '^'
986 self.name = 'Hot Rod'
987 self.bar_plot_x_label = 'Hot Rod'
988 self.precision_parameter = 'dt'
989 self.precision_parameter_loc = ['level_params', 'dt']
991 def get_custom_description(self, problem, num_procs):
992 '''
993 Routine to get a custom description that adds Hot Rod
995 Args:
996 problem: A function that runs a pySDC problem, see imports for available problems
997 num_procs (int): Number of processes you intend to run with
999 Returns:
1000 The custom description you can supply to the problem when running it
1001 '''
1002 from pySDC.implementations.convergence_controller_classes.hotrod import HotRod
1003 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestartingNonMPI
1005 base_params = super().get_custom_description(problem, num_procs)
1006 if problem.__name__ == "run_vdp":
1007 # if num_procs == 4:
1008 # HotRod_tol = 1.800804e-04
1009 # elif num_procs == 5:
1010 # HotRod_tol = 9.329361e-05
1011 # else: # 1 process
1012 # HotRod_tol = 1.347949e-06
1013 # HotRod_tol = 7e-6 if num_procs > 1 else 5e-7
1014 HotRod_tol = 7.2e-05
1015 maxiter = 6
1016 elif problem.__name__ == "run_Lorenz":
1017 if num_procs == 5:
1018 HotRod_tol = 9.539348e-06
1019 elif num_procs == 4:
1020 HotRod_tol = 3.201e-6
1021 else:
1022 HotRod_tol = 7.720589e-07
1023 maxiter = 6
1024 elif problem.__name__ == "run_Schroedinger":
1025 if num_procs == 5:
1026 HotRod_tol = 2.497697e-06
1027 elif num_procs == 4:
1028 HotRod_tol = 1.910405e-06
1029 else:
1030 HotRod_tol = 4.476790e-07
1031 maxiter = 6
1032 elif problem.__name__ == "run_quench":
1033 if num_procs == 5:
1034 HotRod_tol = 1.017534e-03
1035 elif num_procs == 4:
1036 HotRod_tol = 1.017534e-03
1037 else:
1038 HotRod_tol = 5.198620e-04
1039 maxiter = 6
1040 elif problem.__name__ == 'run_AC':
1041 HotRod_tol = 9.564437e-06
1042 maxiter = 6
1043 elif problem.__name__ == 'run_RBC':
1044 HotRod_tol = 3e-4 if num_procs == 4 else 6.34e-6
1045 maxiter = 6
1046 elif problem.__name__ == 'run_GS':
1047 HotRod_tol = 3.22e-5
1048 maxiter = 6
1049 else:
1050 raise NotImplementedError(
1051 'I don\'t have a tolerance for Hot Rod for your problem. Please add one to the\
1052 strategy'
1053 )
1055 no_storage = False # num_procs > 1
1057 custom_description = {
1058 'convergence_controllers': {
1059 HotRod: {'HotRod_tol': HotRod_tol, 'no_storage': no_storage},
1060 BasicRestartingNonMPI: {
1061 'max_restarts': 2,
1062 'crash_after_max_restarts': False,
1063 'restart_from_first_step': True,
1064 },
1065 },
1066 'step_params': {'maxiter': maxiter},
1067 'level_params': {},
1068 }
1069 if problem.__name__ == "run_AC":
1070 custom_description['level_params']['dt'] = 8e-5
1071 return merge_descriptions(base_params, custom_description)
1073 def get_custom_description_for_faults(self, problem, *args, **kwargs):
1074 desc = self.get_custom_description(problem, *args, **kwargs)
1075 if problem.__name__ == "run_quench":
1076 desc['level_params']['dt'] = 5.0
1077 elif problem.__name__ == "run_AC":
1078 desc['level_params']['dt'] = 8e-5
1079 elif problem.__name__ == "run_GS":
1080 desc['level_params']['dt'] = 4e-1
1081 elif problem.__name__ == "run_vdp":
1082 desc['step_params'] = {'maxiter': 6}
1083 desc['problem_params'] = {
1084 'u0': np.array([2.0, 0], dtype=np.float64),
1085 'mu': 5,
1086 'crash_at_maxiter': False,
1087 'newton_tol': 1e-11,
1088 'stop_at_nan': False,
1089 }
1090 desc['level_params'] = {'dt': 4.5e-2}
1091 return desc
1093 def get_reference_value(self, problem, key, op, num_procs=1):
1094 """
1095 Get a reference value for a given problem for testing in CI.
1097 Args:
1098 problem: A function that runs a pySDC problem, see imports for available problems
1099 key (str): The name of the variable you want to compare
1100 op (function): The operation you want to apply to the data
1101 num_procs (int): Number of processes
1103 Returns:
1104 The reference value
1105 """
1106 if problem.__name__ == "run_Lorenz":
1107 if key == 'work_newton' and op == sum:
1108 return 12350
1109 elif key == 'e_global_post_run' and op == max:
1110 return 1.3527453646133836e-07
1112 super().get_reference_value(problem, key, op, num_procs)
1115class AdaptivityCollocationStrategy(InexactBaseStrategy):
1116 '''
1117 Adaptivity based on collocation as a resilience strategy
1118 '''
1120 def __init__(self, **kwargs):
1121 '''
1122 Initialization routine
1123 '''
1124 kwargs = {
1125 'skip_residual_computation': 'most',
1126 **kwargs,
1127 }
1129 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityCollocation
1131 self.restol = None
1132 super().__init__(**kwargs)
1133 self.color = list(cmap.values())[1]
1134 self.marker = '*'
1135 self.name = 'adaptivity_coll'
1136 self.bar_plot_x_label = 'adaptivity collocation'
1137 self.precision_parameter = 'e_tol'
1138 self.adaptive_coll_params = {}
1139 self.precision_parameter_loc = ['convergence_controllers', AdaptivityCollocation, 'e_tol']
1141 def get_custom_description(self, problem, num_procs):
1142 '''
1143 Routine to get a custom description that adds adaptivity
1145 Args:
1146 problem: A function that runs a pySDC problem, see imports for available problems
1147 num_procs (int): Number of processes you intend to run with
1149 Returns:
1150 The custom descriptions you can supply to the problem when running it
1151 '''
1152 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityCollocation
1154 custom_description = {}
1156 dt_max = np.inf
1157 dt_min = 1e-5
1159 if problem.__name__ == "run_piline":
1160 e_tol = 1e-7
1161 dt_min = 1e-2
1162 elif problem.__name__ == "run_vdp":
1163 e_tol = 2e-5
1164 dt_min = 1e-3
1165 elif problem.__name__ == "run_Lorenz":
1166 e_tol = 2e-5
1167 dt_min = 1e-3
1168 elif problem.__name__ == "run_Schroedinger":
1169 e_tol = 4e-6
1170 dt_min = 1e-3
1171 elif problem.__name__ == "run_quench":
1172 e_tol = 1e-5
1173 dt_min = 1e-3
1174 dt_max = 1e2
1175 elif problem.__name__ == "run_AC":
1176 e_tol = 1e-4
1177 else:
1178 raise NotImplementedError(
1179 'I don\'t have a tolerance for adaptivity for your problem. Please add one to the\
1180 strategy'
1181 )
1183 custom_description['convergence_controllers'] = {
1184 AdaptivityCollocation: {
1185 'e_tol': e_tol,
1186 'dt_min': dt_min,
1187 'dt_max': dt_max,
1188 'adaptive_coll_params': self.adaptive_coll_params,
1189 'restol_rel': 1e-2,
1190 }
1191 }
1192 return merge_descriptions(super().get_custom_description(problem, num_procs), custom_description)
1195class AdaptivityCollocationTypeStrategy(AdaptivityCollocationStrategy):
1196 def __init__(self, **kwargs):
1197 super().__init__(**kwargs)
1198 self.color = list(cmap.values())[4]
1199 self.marker = '.'
1200 self.adaptive_coll_params = {
1201 'quad_type': ['RADAU-RIGHT', 'GAUSS'],
1202 'do_coll_update': [False, True],
1203 }
1205 @property
1206 def label(self):
1207 return 'adaptivity type'
1209 def get_reference_value(self, problem, key, op, num_procs=1):
1210 """
1211 Get a reference value for a given problem for testing in CI.
1213 Args:
1214 problem: A function that runs a pySDC problem, see imports for available problems
1215 key (str): The name of the variable you want to compare
1216 op (function): The operation you want to apply to the data
1217 num_procs (int): Number of processes
1219 Returns:
1220 The reference value
1221 """
1222 if problem.__name__ == "run_Lorenz":
1223 if key == 'work_newton' and op == sum:
1224 return 1025
1225 elif key == 'e_global_post_run' and op == max:
1226 return 4.266975256683736e-06
1228 super().get_reference_value(problem, key, op, num_procs)
1231class AdaptivityCollocationRefinementStrategy(AdaptivityCollocationStrategy):
1232 def __init__(self, **kwargs):
1233 super().__init__(**kwargs)
1234 self.color = list(cmap.values())[5]
1235 self.marker = '^'
1236 self.adaptive_coll_params = {
1237 'num_nodes': [2, 3],
1238 'quad_type': ['GAUSS', 'RADAU-RIGHT'],
1239 'do_coll_update': [True, False],
1240 }
1242 @property
1243 def label(self):
1244 return 'adaptivity refinement'
1246 def get_reference_value(self, problem, key, op, num_procs=1):
1247 """
1248 Get a reference value for a given problem for testing in CI.
1250 Args:
1251 problem: A function that runs a pySDC problem, see imports for available problems
1252 key (str): The name of the variable you want to compare
1253 op (function): The operation you want to apply to the data
1254 num_procs (int): Number of processes
1256 Returns:
1257 The reference value
1258 """
1259 if problem.__name__ == "run_Lorenz":
1260 if key == 'work_newton' and op == sum:
1261 return 917
1262 elif key == 'e_global_post_run' and op == max:
1263 return 1.0874929465387595e-05
1265 super().get_reference_value(problem, key, op, num_procs)
1268class AdaptivityCollocationDerefinementStrategy(AdaptivityCollocationStrategy):
1269 def __init__(self, **kwargs):
1270 super().__init__(**kwargs)
1271 self.color = list(cmap.values())[6]
1272 self.marker = '^'
1273 self.adaptive_coll_params = {'num_nodes': [4, 3]}
1275 @property
1276 def label(self):
1277 return 'adaptivity de-refinement'
1279 def get_reference_value(self, problem, key, op, num_procs=1):
1280 """
1281 Get a reference value for a given problem for testing in CI.
1283 Args:
1284 problem: A function that runs a pySDC problem, see imports for available problems
1285 key (str): The name of the variable you want to compare
1286 op (function): The operation you want to apply to the data
1287 num_procs (int): Number of processes
1289 Returns:
1290 The reference value
1291 """
1292 if problem.__name__ == 'run_Lorenz':
1293 if key == 'work_newton' and op == sum:
1294 return 1338
1295 elif key == 'e_global_post_run' and op == max:
1296 return 0.0001013999955041811
1298 super().get_reference_value(problem, key, op, num_procs)
1301class DIRKStrategy(AdaptivityStrategy):
1302 '''
1303 DIRK4(3)
1304 '''
1306 def __init__(self, **kwargs):
1307 '''
1308 Initialization routine
1309 '''
1310 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK
1312 super().__init__(**kwargs)
1313 self.color = list(cmap.values())[7]
1314 self.marker = '^'
1315 self.name = 'DIRK'
1316 self.bar_plot_x_label = 'DIRK4(3)'
1317 self.precision_parameter = 'e_tol'
1318 self.precision_parameter_loc = ['convergence_controllers', AdaptivityRK, 'e_tol']
1319 self.max_steps = 1e5
1321 @property
1322 def label(self):
1323 return 'DIRK4(3)'
1325 def get_custom_description(self, problem, num_procs):
1326 '''
1327 Routine to get a custom description that adds adaptivity
1329 Args:
1330 problem: A function that runs a pySDC problem, see imports for available problems
1331 num_procs (int): Number of processes you intend to run with
1333 Returns:
1334 The custom descriptions you can supply to the problem when running it
1335 '''
1336 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK, Adaptivity
1337 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
1338 from pySDC.implementations.sweeper_classes.Runge_Kutta import DIRK43
1340 adaptivity_description = super().get_custom_description(problem, num_procs)
1342 e_tol = adaptivity_description['convergence_controllers'][Adaptivity]['e_tol']
1343 adaptivity_description['convergence_controllers'].pop(Adaptivity, None)
1344 adaptivity_description.pop('sweeper_params', None)
1346 rk_params = {
1347 'step_params': {'maxiter': 1},
1348 'sweeper_class': DIRK43,
1349 'convergence_controllers': {
1350 AdaptivityRK: {'e_tol': e_tol},
1351 BasicRestarting.get_implementation(useMPI=self.useMPI): {
1352 'max_restarts': 49,
1353 'crash_after_max_restarts': False,
1354 },
1355 },
1356 }
1358 custom_description = merge_descriptions(adaptivity_description, rk_params)
1360 return custom_description
1362 def get_reference_value(self, problem, key, op, num_procs=1):
1363 """
1364 Get a reference value for a given problem for testing in CI.
1366 Args:
1367 problem: A function that runs a pySDC problem, see imports for available problems
1368 key (str): The name of the variable you want to compare
1369 op (function): The operation you want to apply to the data
1370 num_procs (int): Number of processes
1372 Returns:
1373 The reference value
1374 """
1375 if problem.__name__ == "run_Lorenz":
1376 if key == 'work_newton' and op == sum:
1377 return 5467
1378 elif key == 'e_global_post_run' and op == max:
1379 return 7.049480537091313e-07
1381 super().get_reference_value(problem, key, op, num_procs)
1383 def get_random_params(self, problem, num_procs):
1384 '''
1385 Routine to get parameters for the randomization of faults
1387 Args:
1388 problem: A function that runs a pySDC problem, see imports for available problems
1389 num_procs (int): Number of processes you intend to run with
1391 Returns:
1392 dict: Randomization parameters
1393 '''
1394 rnd_params = super().get_random_params(problem, num_procs)
1395 rnd_params['iteration'] = 1
1396 rnd_params['min_node'] = 5
1398 return rnd_params
1401class ARKStrategy(AdaptivityStrategy):
1402 '''
1403 ARK5(4)
1404 '''
1406 def __init__(self, **kwargs):
1407 '''
1408 Initialization routine
1409 '''
1410 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK
1412 super().__init__(**kwargs)
1413 self.color = list(cmap.values())[7]
1414 self.marker = 'P'
1415 self.name = 'ARK'
1416 self.bar_plot_x_label = 'ARK5(4)'
1417 self.precision_parameter = 'e_tol'
1418 self.precision_parameter_loc = ['convergence_controllers', AdaptivityRK, 'e_tol']
1419 self.max_steps = 1e5
1421 @property
1422 def label(self):
1423 return 'ARK5(4)'
1425 def get_custom_description(self, problem, num_procs):
1426 '''
1427 Routine to get a custom description that adds adaptivity
1429 Args:
1430 problem: A function that runs a pySDC problem, see imports for available problems
1431 num_procs (int): Number of processes you intend to run with
1433 Returns:
1434 The custom descriptions you can supply to the problem when running it
1435 '''
1436 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK, Adaptivity
1437 from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeSlopeLimiter
1438 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
1439 from pySDC.implementations.sweeper_classes.Runge_Kutta import ARK548L2SA
1441 adaptivity_description = super().get_custom_description(problem, num_procs)
1443 e_tol = adaptivity_description['convergence_controllers'][Adaptivity]['e_tol'] / 20.0
1444 adaptivity_description['convergence_controllers'].pop(Adaptivity, None)
1445 adaptivity_description.pop('sweeper_params', None)
1447 rk_params = {
1448 'step_params': {'maxiter': 1},
1449 'sweeper_class': ARK548L2SA,
1450 'convergence_controllers': {
1451 AdaptivityRK: {'e_tol': e_tol},
1452 BasicRestarting.get_implementation(useMPI=self.useMPI): {
1453 'max_restarts': 49,
1454 'crash_after_max_restarts': False,
1455 },
1456 },
1457 }
1459 if problem.__name__ == "run_RBC":
1460 rk_params['convergence_controllers'][StepSizeSlopeLimiter] = {'dt_rel_min_slope': 0.25}
1462 custom_description = merge_descriptions(adaptivity_description, rk_params)
1464 return custom_description
1466 def get_reference_value(self, problem, key, op, num_procs=1):
1467 """
1468 Get a reference value for a given problem for testing in CI.
1470 Args:
1471 problem: A function that runs a pySDC problem, see imports for available problems
1472 key (str): The name of the variable you want to compare
1473 op (function): The operation you want to apply to the data
1474 num_procs (int): Number of processes
1476 Returns:
1477 The reference value
1478 """
1479 if problem.__name__ == "run_Schroedinger":
1480 if key == 'work_newton' and op == sum:
1481 return 0
1482 elif key == 'e_global_post_run' and op == max:
1483 return 3.1786601531890356e-08
1485 super().get_reference_value(problem, key, op, num_procs)
1488class ARK3_CFL_Strategy(BaseStrategy):
1489 """
1490 This is special for RBC with CFL number for accuracy
1491 """
1493 def __init__(self, **kwargs):
1494 '''
1495 Initialization routine
1496 '''
1497 from pySDC.implementations.problem_classes.RayleighBenard import CFLLimit
1499 super().__init__(**kwargs)
1500 self.color = 'maroon'
1501 self.marker = '<'
1502 self.name = 'ARK3'
1503 self.bar_plot_x_label = 'ARK3'
1504 self.precision_parameter = 'cfl'
1505 self.precision_parameter_loc = ['convergence_controllers', CFLLimit, 'cfl']
1506 self.max_steps = 1e5
1508 @property
1509 def label(self):
1510 return 'ARK3'
1512 def get_custom_description(self, problem, num_procs):
1513 '''
1514 Args:
1515 problem: A function that runs a pySDC problem, see imports for available problems
1516 num_procs (int): Number of processes you intend to run with
1518 Returns:
1519 The custom descriptions you can supply to the problem when running it
1520 '''
1521 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
1522 from pySDC.implementations.sweeper_classes.Runge_Kutta import ARK3
1523 from pySDC.implementations.problem_classes.RayleighBenard import CFLLimit
1524 from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeSlopeLimiter
1526 desc = super().get_custom_description(problem, num_procs)
1528 rk_params = {
1529 'step_params': {'maxiter': 1},
1530 'sweeper_class': ARK3,
1531 'convergence_controllers': {
1532 CFLLimit: {
1533 'cfl': 0.5,
1534 'dt_max': 1.0,
1535 },
1536 StepSizeSlopeLimiter: {'dt_rel_min_slope': 0.2},
1537 },
1538 }
1540 custom_description = merge_descriptions(desc, rk_params)
1542 return custom_description
1545class ESDIRKStrategy(AdaptivityStrategy):
1546 '''
1547 ESDIRK5(3)
1548 '''
1550 def __init__(self, **kwargs):
1551 '''
1552 Initialization routine
1553 '''
1554 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK
1556 super().__init__(**kwargs)
1557 self.color = 'violet'
1558 self.marker = '^'
1559 self.name = 'ESDIRK'
1560 self.bar_plot_x_label = 'ESDIRK5(3)'
1561 self.precision_parameter = 'e_tol'
1562 self.precision_parameter_loc = ['convergence_controllers', AdaptivityRK, 'e_tol']
1563 self.max_steps = 1e5
1565 @property
1566 def label(self):
1567 return 'ESDIRK5(3)'
1569 def get_description_for_tolerance(self, problem, param, **kwargs):
1570 desc = {}
1571 if problem.__name__ == 'run_Schroedinger':
1572 desc['problem_params'] = {'lintol': param}
1573 return desc
1575 def get_custom_description(self, problem, num_procs):
1576 '''
1577 Routine to get a custom description that adds adaptivity
1579 Args:
1580 problem: A function that runs a pySDC problem, see imports for available problems
1581 num_procs (int): Number of processes you intend to run with
1583 Returns:
1584 The custom descriptions you can supply to the problem when running it
1585 '''
1586 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK, Adaptivity
1587 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
1588 from pySDC.implementations.sweeper_classes.Runge_Kutta import ESDIRK53
1590 adaptivity_description = super().get_custom_description(problem, num_procs)
1592 e_tol = adaptivity_description['convergence_controllers'][Adaptivity]['e_tol']
1593 adaptivity_description['convergence_controllers'].pop(Adaptivity, None)
1594 adaptivity_description.pop('sweeper_params', None)
1596 mod = 1e1 if problem.__name__ == 'run_quench' else 1.0
1598 rk_params = {
1599 'step_params': {'maxiter': 1},
1600 'sweeper_class': ESDIRK53,
1601 'convergence_controllers': {
1602 AdaptivityRK: {'e_tol': e_tol * mod},
1603 BasicRestarting.get_implementation(useMPI=self.useMPI): {
1604 'max_restarts': 49,
1605 'crash_after_max_restarts': False,
1606 },
1607 },
1608 }
1610 custom_description = merge_descriptions(adaptivity_description, rk_params)
1612 return custom_description
1614 def get_reference_value(self, problem, key, op, num_procs=1):
1615 """
1616 Get a reference value for a given problem for testing in CI.
1618 Args:
1619 problem: A function that runs a pySDC problem, see imports for available problems
1620 key (str): The name of the variable you want to compare
1621 op (function): The operation you want to apply to the data
1622 num_procs (int): Number of processes
1624 Returns:
1625 The reference value
1626 """
1627 if problem.__name__ == "run_Lorenz":
1628 if key == 'work_newton' and op == sum:
1629 return 2963
1630 elif key == 'e_global_post_run' and op == max:
1631 return 4.126039954144289e-09
1633 super().get_reference_value(problem, key, op, num_procs)
1635 def get_random_params(self, problem, num_procs):
1636 '''
1637 Routine to get parameters for the randomization of faults
1639 Args:
1640 problem: A function that runs a pySDC problem, see imports for available problems
1641 num_procs (int): Number of processes you intend to run with
1643 Returns:
1644 dict: Randomization parameters
1645 '''
1646 rnd_params = super().get_random_params(problem, num_procs)
1647 rnd_params['iteration'] = 1
1648 rnd_params['min_node'] = 6
1650 return rnd_params
1653class ERKStrategy(DIRKStrategy):
1654 """
1655 Explicit embedded RK using Cash-Karp's method
1656 """
1658 def __init__(self, **kwargs):
1659 '''
1660 Initialization routine
1661 '''
1662 super().__init__(**kwargs)
1663 self.color = list(cmap.values())[8]
1664 self.marker = 'x'
1665 self.name = 'ERK'
1666 self.bar_plot_x_label = 'ERK5(4)'
1668 def get_description_for_tolerance(self, problem, param, **kwargs):
1669 desc = {}
1670 if problem.__name__ == 'run_Schroedinger':
1671 desc['problem_params'] = {'lintol': param}
1673 return desc
1675 @property
1676 def label(self):
1677 return 'CK5(4)'
1679 def get_random_params(self, problem, num_procs):
1680 '''
1681 Routine to get parameters for the randomization of faults
1683 Args:
1684 problem: A function that runs a pySDC problem, see imports for available problems
1685 num_procs (int): Number of processes you intend to run with
1687 Returns:
1688 dict: Randomization parameters
1689 '''
1690 rnd_params = super().get_random_params(problem, num_procs)
1691 rnd_params['min_node'] = 7
1693 return rnd_params
1695 def get_custom_description(self, problem, num_procs=1):
1696 from pySDC.implementations.sweeper_classes.Runge_Kutta import Cash_Karp
1698 desc = super().get_custom_description(problem, num_procs)
1699 desc['sweeper_class'] = Cash_Karp
1701 if problem.__name__ == "run_AC":
1702 desc['level_params']['dt'] = 2e-5
1703 return desc
1705 def get_reference_value(self, problem, key, op, num_procs=1):
1706 """
1707 Get a reference value for a given problem for testing in CI.
1709 Args:
1710 problem: A function that runs a pySDC problem, see imports for available problems
1711 key (str): The name of the variable you want to compare
1712 op (function): The operation you want to apply to the data
1713 num_procs (int): Number of processes
1715 Returns:
1716 The reference value
1717 """
1718 if problem.__name__ == "run_Lorenz":
1719 if key == 'work_newton' and op == sum:
1720 return 0
1721 elif key == 'e_global_post_run' and op == max:
1722 return 1.509206128957885e-07
1724 super().get_reference_value(problem, key, op, num_procs)
1727class DoubleAdaptivityStrategy(AdaptivityStrategy):
1728 '''
1729 Adaptivity based both on embedded estimate and on residual
1730 '''
1732 def __init__(self, **kwargs):
1733 '''
1734 Initialization routine
1735 '''
1736 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
1738 kwargs['skip_residual_computation'] = 'all'
1739 super().__init__(**kwargs)
1740 self.color = list(cmap.values())[7]
1741 self.marker = '^'
1742 self.name = 'double_adaptivity'
1743 self.bar_plot_x_label = 'double adaptivity'
1744 self.precision_parameter = 'e_tol'
1745 self.precision_parameter_loc = ['convergence_controllers', Adaptivity, 'e_tol']
1746 self.residual_e_tol_ratio = 1.0
1747 self.residual_e_tol_abs = None
1749 @property
1750 def label(self):
1751 return 'double adaptivity'
1753 def get_custom_description(self, problem, num_procs):
1754 '''
1755 Routine to get a custom description that adds adaptivity
1757 Args:
1758 problem: A function that runs a pySDC problem, see imports for available problems
1759 num_procs (int): Number of processes you intend to run with
1761 Returns:
1762 The custom descriptions you can supply to the problem when running it
1763 '''
1764 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityResidual, Adaptivity
1765 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
1767 custom_description = super().get_custom_description(problem, num_procs)
1769 if self.residual_e_tol_abs:
1770 e_tol = self.residual_e_tol_abs
1771 else:
1772 e_tol = custom_description['convergence_controllers'][Adaptivity]['e_tol'] * self.residual_e_tol_ratio
1773 custom_description['convergence_controllers'][AdaptivityResidual] = {
1774 'e_tol': e_tol,
1775 'allowed_modifications': ['decrease'],
1776 }
1778 custom_description['convergence_controllers'][BasicRestarting.get_implementation(useMPI=self.useMPI)] = {
1779 'max_restarts': 15
1780 }
1782 return custom_description
1784 def get_reference_value(self, problem, key, op, num_procs=1):
1785 """
1786 Get a reference value for a given problem for testing in CI.
1788 Args:
1789 problem: A function that runs a pySDC problem, see imports for available problems
1790 key (str): The name of the variable you want to compare
1791 op (function): The operation you want to apply to the data
1792 num_procs (int): Number of processes
1794 Returns:
1795 The reference value
1796 """
1797 if problem.__name__ == 'run_Lorenz':
1798 if key == 'work_newton' and op == sum:
1799 return 2989
1800 elif key == 'e_global_post_run' and op == max:
1801 return 5.636763944494305e-08
1803 super().get_reference_value(problem, key, op, num_procs)
1806class AdaptivityAvoidRestartsStrategy(AdaptivityStrategy):
1807 """
1808 Adaptivity with the avoid restarts option
1809 """
1811 @property
1812 def label(self):
1813 return 'adaptivity (avoid restarts)'
1815 def get_custom_description(self, problem, num_procs):
1816 '''
1817 Routine to get a custom description that adds adaptivity
1819 Args:
1820 problem: A function that runs a pySDC problem, see imports for available problems
1821 num_procs (int): Number of processes you intend to run with
1823 Returns:
1824 The custom descriptions you can supply to the problem when running it
1825 '''
1826 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
1827 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
1829 custom_description = super().get_custom_description(problem, num_procs)
1831 custom_description['convergence_controllers'][Adaptivity]['avoid_restarts'] = True
1833 custom_description['convergence_controllers'][BasicRestarting.get_implementation(useMPI=self.useMPI)] = {
1834 'max_restarts': 15
1835 }
1837 return custom_description
1839 def get_reference_value(self, problem, key, op, num_procs=1):
1840 """
1841 Get a reference value for a given problem for testing in CI.
1843 Args:
1844 problem: A function that runs a pySDC problem, see imports for available problems
1845 key (str): The name of the variable you want to compare
1846 op (function): The operation you want to apply to the data
1847 num_procs (int): Number of processes
1849 Returns:
1850 The reference value
1851 """
1852 if problem.__name__ == "run_Lorenz":
1853 if key == 'work_newton' and op == sum:
1854 return 2989
1855 elif key == 'e_global_post_run' and op == max:
1856 return 5.636763944494305e-08
1858 super().get_reference_value(problem, key, op, num_procs)
1861class AdaptivityInterpolationStrategy(AdaptivityStrategy):
1862 """
1863 Adaptivity with interpolation between restarts
1864 """
1866 @property
1867 def label(self):
1868 return 'adaptivity+interpolation'
1870 def get_custom_description(self, problem, num_procs):
1871 '''
1872 Routine to get a custom description that adds adaptivity
1874 Args:
1875 problem: A function that runs a pySDC problem, see imports for available problems
1876 num_procs (int): Number of processes you intend to run with
1878 Returns:
1879 The custom descriptions you can supply to the problem when running it
1880 '''
1881 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
1882 from pySDC.implementations.convergence_controller_classes.interpolate_between_restarts import (
1883 InterpolateBetweenRestarts,
1884 )
1885 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
1887 custom_description = super().get_custom_description(problem, num_procs)
1889 custom_description['convergence_controllers'][Adaptivity]['avoid_restarts'] = False
1890 custom_description['convergence_controllers'][InterpolateBetweenRestarts] = {}
1892 custom_description['convergence_controllers'][BasicRestarting.get_implementation(useMPI=self.useMPI)] = {
1893 'max_restarts': 15
1894 }
1896 return custom_description
1898 def get_reference_value(self, problem, key, op, num_procs=1):
1899 """
1900 Get a reference value for a given problem for testing in CI.
1902 Args:
1903 problem: A function that runs a pySDC problem, see imports for available problems
1904 key (str): The name of the variable you want to compare
1905 op (function): The operation you want to apply to the data
1906 num_procs (int): Number of processes
1908 Returns:
1909 The reference value
1910 """
1911 if problem.__name__ == "run_Lorenz":
1912 if key == 'work_newton' and op == sum:
1913 return 6659
1914 elif key == 'e_global_post_run' and op == max:
1915 return 2.9780002756552015e-06
1917 super().get_reference_value(problem, key, op, num_procs)
1920class AdaptivityExtrapolationWithinQStrategy(InexactBaseStrategy):
1921 '''
1922 Adaptivity based on extrapolation between collocation nodes as a resilience strategy
1923 '''
1925 def __init__(self, **kwargs):
1926 '''
1927 Initialization routine
1928 '''
1929 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityExtrapolationWithinQ
1931 self.restol = None
1932 super().__init__(**kwargs)
1933 self.color = list(cmap.values())[8]
1934 self.marker = '*'
1935 self.name = 'adaptivity_extraQ'
1936 self.bar_plot_x_label = 'adaptivity Q'
1937 self.precision_parameter = 'e_tol'
1938 self.adaptive_coll_params = {}
1939 self.precision_parameter_loc = ['convergence_controllers', AdaptivityExtrapolationWithinQ, 'e_tol']
1941 def get_custom_description(self, problem, num_procs):
1942 '''
1943 Routine to get a custom description that adds adaptivity
1945 Args:
1946 problem: A function that runs a pySDC problem, see imports for available problems
1947 num_procs (int): Number of processes you intend to run with
1949 Returns:
1950 The custom descriptions you can supply to the problem when running it
1951 '''
1952 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityExtrapolationWithinQ
1954 custom_description = {}
1956 dt_max = np.inf
1957 dt_min = 1e-5
1959 if problem.__name__ == "run_vdp":
1960 e_tol = 2e-5
1961 dt_min = 1e-3
1962 elif problem.__name__ == "run_piline":
1963 e_tol = 1e-7
1964 dt_min = 1e-2
1965 elif problem.__name__ == "run_Lorenz":
1966 e_tol = 2e-5
1967 dt_min = 1e-3
1968 elif problem.__name__ == "run_Schroedinger":
1969 e_tol = 4e-6
1970 dt_min = 1e-3
1971 elif problem.__name__ == "run_quench":
1972 e_tol = 1e-5
1973 dt_min = 1e-3
1974 dt_max = 1e2
1975 elif problem.__name__ == "run_AC":
1976 e_tol = 1e-4
1977 else:
1978 raise NotImplementedError(
1979 'I don\'t have a tolerance for adaptivity for your problem. Please add one to the\
1980 strategy'
1981 )
1983 custom_description['convergence_controllers'] = {
1984 AdaptivityExtrapolationWithinQ: {
1985 'e_tol': e_tol,
1986 'dt_min': dt_min,
1987 'dt_max': dt_max,
1988 'restol_rel': 1e-2,
1989 'restart_at_maxiter': True,
1990 }
1991 }
1992 return merge_descriptions(super().get_custom_description(problem, num_procs), custom_description)
1994 def get_reference_value(self, problem, key, op, num_procs=1):
1995 """
1996 Get a reference value for a given problem for testing in CI.
1998 Args:
1999 problem: A function that runs a pySDC problem, see imports for available problems
2000 key (str): The name of the variable you want to compare
2001 op (function): The operation you want to apply to the data
2002 num_procs (int): Number of processes
2004 Returns:
2005 The reference value
2006 """
2007 if problem.__name__ == "run_Lorenz":
2008 if key == 'work_newton' and op == sum:
2009 return 2198
2010 elif key == 'e_global_post_run' and op == max:
2011 return 5.412657451131508e-07
2013 super().get_reference_value(problem, key, op, num_procs)
2016class AdaptivityPolynomialError(InexactBaseStrategy):
2017 '''
2018 Adaptivity based on extrapolation between collocation nodes as a resilience strategy
2019 '''
2021 def __init__(self, interpolate_between_restarts=False, use_restol_rel=True, max_slope=4, **kwargs):
2022 '''
2023 Initialization routine
2024 '''
2025 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityPolynomialError
2027 self.restol = None
2028 super().__init__(**kwargs)
2029 self.color = list(cmap.values())[9]
2030 self.marker = '+'
2031 self.name = 'adaptivity-inter'
2032 self.bar_plot_x_label = 'adaptivity Q'
2033 self.precision_parameter = 'e_tol'
2034 self.adaptive_coll_params = {}
2035 self.precision_parameter_loc = ['convergence_controllers', AdaptivityPolynomialError, 'e_tol']
2036 self.interpolate_between_restarts = interpolate_between_restarts
2037 self.use_restol_rel = use_restol_rel
2038 self.max_slope = max_slope
2040 def get_custom_description(self, problem, num_procs):
2041 '''
2042 Routine to get a custom description that adds adaptivity
2044 Args:
2045 problem: A function that runs a pySDC problem, see imports for available problems
2046 num_procs (int): Number of processes you intend to run with
2048 Returns:
2049 The custom descriptions you can supply to the problem when running it
2050 '''
2051 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityPolynomialError
2052 from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeLimiter
2053 from pySDC.implementations.convergence_controller_classes.check_convergence import CheckConvergence
2055 base_params = super().get_custom_description(problem, num_procs)
2056 custom_description = {}
2058 dt_max = np.inf
2059 restol_rel = 1e-4
2060 restol_min = 1e-12
2061 restol_max = 1e-5
2062 dt_slope_min = 0
2063 dt_min = 0
2064 abort_at_growing_residual = True
2065 level_params = {}
2066 problem_params = {}
2067 beta = 0.9
2069 if problem.__name__ == "run_vdp":
2070 e_tol = 6e-4
2071 level_params['dt'] = 0.1
2072 restol_rel = 1e-5
2073 restol_min = 1e-12
2074 dt_min = 1e-7
2075 problem_params['newton_tol'] = 1e-14
2076 elif problem.__name__ == "run_piline":
2077 e_tol = 1e-7
2078 elif problem.__name__ == "run_Lorenz":
2079 e_tol = 2e-4
2080 elif problem.__name__ == "run_Schroedinger":
2081 e_tol = 3e-5
2082 elif problem.__name__ == "run_quench":
2083 e_tol = 1e-7
2084 level_params['dt'] = 50.0
2085 restol_min = 1e-11
2086 restol_rel = 1e-1
2087 elif problem.__name__ == "run_AC":
2088 e_tol = 1.0e-4
2089 restol_rel = 1e-3 if num_procs == 4 else 1e-3
2090 # dt_max = 0.1 * base_params['problem_params']['eps'] ** 2
2091 elif problem.__name__ == "run_RBC":
2092 e_tol = 5e-2 if num_procs == 4 else 5e-3
2093 dt_slope_min = 1.0
2094 abort_at_growing_residual = False
2095 restol_rel = 1e-2 if num_procs == 4 else 1e-4
2096 restol_max = 1e-1
2097 restol_min = 5e-8
2098 self.max_slope = 4
2099 beta = 0.5
2100 level_params['e_tol'] = 1e-5
2101 elif problem.__name__ == 'run_GS':
2102 e_tol = 1e-4
2103 restol_rel = 4e-3
2104 restol_max = 1e-4
2105 restol_min = 1e-9
2106 else:
2107 raise NotImplementedError(
2108 'I don\'t have a tolerance for adaptivity for your problem. Please add one to the\
2109 strategy'
2110 )
2112 custom_description['convergence_controllers'] = {
2113 AdaptivityPolynomialError: {
2114 'e_tol': e_tol,
2115 'restol_rel': restol_rel if self.use_restol_rel else 1e-11,
2116 'restol_min': restol_min if self.use_restol_rel else 1e-12,
2117 'restol_max': restol_max if self.use_restol_rel else 1e-5,
2118 'restart_at_maxiter': True,
2119 'factor_if_not_converged': self.max_slope,
2120 'interpolate_between_restarts': self.interpolate_between_restarts,
2121 'abort_at_growing_residual': abort_at_growing_residual,
2122 'beta': beta,
2123 },
2124 StepSizeLimiter: {
2125 'dt_max': dt_max,
2126 'dt_slope_max': self.max_slope,
2127 'dt_min': dt_min,
2128 'dt_rel_min_slope': dt_slope_min,
2129 },
2130 }
2131 custom_description['level_params'] = level_params
2132 custom_description['problem_params'] = problem_params
2134 return merge_descriptions(base_params, custom_description)
2136 def get_custom_description_for_faults(self, problem, num_procs, *args, **kwargs):
2137 desc = self.get_custom_description(problem, num_procs, *args, **kwargs)
2138 if problem.__name__ == "run_quench":
2139 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityPolynomialError
2141 desc['convergence_controllers'][AdaptivityPolynomialError]['e_tol'] = 1e-7 * 11
2142 desc['level_params']['dt'] = 4.0
2143 elif problem.__name__ == "run_AC":
2144 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityPolynomialError
2146 desc['convergence_controllers'][AdaptivityPolynomialError]['e_tol'] = 6e-3 if num_procs == 4 else 1e-3
2147 if num_procs == 4:
2148 desc['step_params'] = {'maxiter': 50}
2149 elif problem.__name__ == "run_Lorenz":
2150 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityPolynomialError
2152 desc['convergence_controllers'][AdaptivityPolynomialError]['e_tol'] = 2e-4
2153 desc['convergence_controllers'][AdaptivityPolynomialError]['restol_min'] = 1e-11
2154 desc['convergence_controllers'][AdaptivityPolynomialError]['restol_rel'] = 1e-11
2155 elif problem.__name__ == "run_vdp":
2156 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityPolynomialError
2157 from pySDC.implementations.convergence_controller_classes.inexactness import NewtonInexactness
2159 desc['step_params'] = {'maxiter': 16}
2160 desc['problem_params'] = {
2161 'u0': np.array([2.0, 0], dtype=np.float64),
2162 'mu': 5,
2163 'crash_at_maxiter': False,
2164 'newton_tol': 1e-11,
2165 'stop_at_nan': False,
2166 }
2167 desc['convergence_controllers'][AdaptivityPolynomialError]['e_tol'] = 5e-4
2168 desc['convergence_controllers'][AdaptivityPolynomialError]['restol_rel'] = 8e-5
2169 desc['convergence_controllers'].pop(NewtonInexactness)
2170 desc['level_params'] = {'dt': 4.5e-2}
2171 return desc
2173 def get_random_params(self, problem, num_procs):
2174 '''
2175 Routine to get parameters for the randomization of faults
2177 Args:
2178 problem: A function that runs a pySDC problem, see imports for available problems
2179 num_procs (int): Number of processes you intend to run with
2181 Returns:
2182 dict: Randomization parameters
2183 '''
2185 rnd_params = super().get_random_params(problem, num_procs)
2186 if problem.__name__ == "run_quench":
2187 rnd_params['iteration'] = 1
2188 elif problem.__name__ == 'run_Lorenz':
2189 rnd_params['iteration'] = 5
2190 return rnd_params
2192 def get_reference_value(self, problem, key, op, num_procs=1):
2193 """
2194 Get a reference value for a given problem for testing in CI.
2196 Args:
2197 problem: A function that runs a pySDC problem, see imports for available problems
2198 key (str): The name of the variable you want to compare
2199 op (function): The operation you want to apply to the data
2200 num_procs (int): Number of processes
2202 Returns:
2203 The reference value
2204 """
2205 if problem.__name__ == "run_Lorenz":
2206 if key == 'work_newton' and op == sum:
2207 return 2123
2208 elif key == 'e_global_post_run' and op == max:
2209 return 7.931560830343187e-08
2211 super().get_reference_value(problem, key, op, num_procs)
2213 @property
2214 def label(self):
2215 return r'$\Delta t$-$k$-adaptivity'