Coverage for pySDC / projects / Resilience / strategies.py: 60%
1011 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-27 07:06 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-27 07:06 +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('I don\'t have a tolerance for adaptivity for your problem. Please add one to the\
613 strategy')
615 custom_description['convergence_controllers'][Adaptivity] = {
616 'e_tol': e_tol,
617 'dt_slope_max': dt_slope_max,
618 'dt_rel_min_slope': dt_slope_min,
619 'beta': beta,
620 }
621 custom_description['convergence_controllers'][StepSizeLimiter] = {
622 'dt_max': dt_max,
623 }
624 return merge_descriptions(base_params, custom_description)
626 def get_reference_value(self, problem, key, op, num_procs=1):
627 """
628 Get a reference value for a given problem for testing in CI.
630 Args:
631 problem: A function that runs a pySDC problem, see imports for available problems
632 key (str): The name of the variable you want to compare
633 op (function): The operation you want to apply to the data
634 num_procs (int): Number of processes
636 Returns:
637 The reference value
638 """
639 if problem.__name__ == 'run_Lorenz':
640 if key == 'work_newton' and op == sum:
641 return 2989
642 elif key == 'e_global_post_run' and op == max:
643 return 5.636767497207984e-08
645 super().get_reference_value(problem, key, op, num_procs)
647 def get_custom_description_for_faults(self, problem, num_procs, *args, **kwargs):
648 from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeLimiter
649 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
650 from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeSlopeLimiter
651 from pySDC.projects.Resilience.RBC import ReachTendExactly
653 desc = self.get_custom_description(problem, num_procs, *args, **kwargs)
654 if problem.__name__ == "run_quench":
655 desc['level_params']['dt'] = 1.1e1
656 desc['convergence_controllers'][Adaptivity]['e_tol'] = 1e-6
657 elif problem.__name__ == "run_AC":
658 desc['convergence_controllers'][Adaptivity]['e_tol'] = 1e-5
659 elif problem.__name__ == "run_GS":
660 desc['convergence_controllers'][Adaptivity]['e_tol'] = 2e-6
661 elif problem.__name__ == "run_vdp":
662 desc['step_params'] = {'maxiter': 5}
663 desc['sweeper_params'] = {'num_nodes': 3, 'QI': 'LU'}
664 desc['problem_params'] = {
665 'u0': np.array([2.0, 0], dtype=np.float64),
666 'mu': 5,
667 'crash_at_maxiter': True,
668 'newton_tol': 1e-8,
669 'stop_at_nan': True,
670 'relative_tolerance': False,
671 }
672 desc['level_params'] = {'dt': 8e-3}
673 desc['convergence_controllers'][Adaptivity]['e_tol'] = 2e-7
674 desc['convergence_controllers'][ReachTendExactly] = {'Tend': 11.5}
675 # desc['convergence_controllers'][StepSizeSlopeLimiter] = {'dt_slope_min': 1/4, 'dt_slope_max': 4}
676 return desc
679class AdaptivityRestartFirstStep(AdaptivityStrategy):
680 def __init__(self, **kwargs):
681 super().__init__(**kwargs)
682 self.color = 'teal'
683 self.name = 'adaptivityRestartFirstStep'
685 def get_custom_description(self, problem, num_procs):
686 '''
687 Add the other version of basic restarting.
689 Args:
690 problem: A function that runs a pySDC problem, see imports for available problems
691 num_procs (int): Number of processes you intend to run with
693 Returns:
694 The custom descriptions you can supply to the problem when running it
695 '''
696 custom_description = super().get_custom_description(problem, num_procs)
697 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
699 custom_description['convergence_controllers'][BasicRestarting.get_implementation(useMPI=self.useMPI)] = {
700 'max_restarts': 15,
701 'restart_from_first_step': True,
702 }
703 return custom_description
705 @property
706 def label(self):
707 return f'{super().label} restart from first step'
710class AdaptiveHotRodStrategy(Strategy):
711 '''
712 Adaptivity + Hot Rod as a resilience strategy
713 '''
715 def __init__(self, **kwargs):
716 '''
717 Initialization routine
718 '''
719 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
721 kwargs['skip_residual_computation'] = 'all'
722 super().__init__(**kwargs)
723 self.color = list(cmap.values())[4]
724 self.marker = '.'
725 self.name = 'adaptive Hot Rod'
726 self.bar_plot_x_label = 'adaptive\nHot Rod'
727 self.precision_parameter = 'e_tol'
728 self.precision_parameter_loc = ['convergence_controllers', Adaptivity, 'e_tol']
730 def get_custom_description(self, problem, num_procs):
731 '''
732 Routine to get a custom description that adds adaptivity and Hot Rod
734 Args:
735 problem: A function that runs a pySDC problem, see imports for available problems
736 num_procs (int): Number of processes you intend to run with
738 Returns:
739 The custom description you can supply to the problem when running it
740 '''
741 from pySDC.implementations.convergence_controller_classes.hotrod import HotRod
742 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
744 if problem.__name__ == "run_vdp":
745 e_tol = 3e-7
746 dt_min = 1e-3
747 maxiter = 4
748 HotRod_tol = 2e-6
749 elif problem.__name__ == "run_Lorenz":
750 e_tol = 3e-7
751 dt_min = 1e-3
752 maxiter = 4
753 HotRod_tol = 2e-6
754 else:
755 raise NotImplementedError('I don\'t have a tolerance for adaptive Hot Rod for your problem. Please add one \
756to the strategy')
758 no_storage = num_procs > 1
760 custom_description = {
761 'convergence_controllers': {
762 HotRod: {'HotRod_tol': HotRod_tol, 'no_storage': no_storage},
763 Adaptivity: {'e_tol': e_tol, 'dt_min': dt_min, 'embedded_error_flavor': 'linearized'},
764 },
765 'step_params': {'maxiter': maxiter},
766 }
768 return merge_descriptions(super().get_custom_description(problem, num_procs), custom_description)
770 def get_reference_value(self, problem, key, op, num_procs=1):
771 """
772 Get a reference value for a given problem for testing in CI.
774 Args:
775 problem: A function that runs a pySDC problem, see imports for available problems
776 key (str): The name of the variable you want to compare
777 op (function): The operation you want to apply to the data
778 num_procs (int): Number of processes
780 Returns:
781 The reference value
782 """
783 if problem.__name__ == "run_Lorenz":
784 if key == 'work_newton' and op == sum:
785 return 5092
786 elif key == 'e_global_post_run' and op == max:
787 return 4.107116318152748e-06
789 super().get_reference_value(problem, key, op, num_procs)
792class IterateStrategy(Strategy):
793 '''
794 Iterate for as much as you want
795 '''
797 def __init__(self, **kwargs):
798 '''
799 Initialization routine
800 '''
801 kwargs['skip_residual_computation'] = 'most'
802 super().__init__(**kwargs)
803 self.color = list(cmap.values())[2]
804 self.marker = 'v'
805 self.name = 'iterate'
806 self.bar_plot_x_label = 'iterate'
807 self.precision_parameter = 'restol'
808 self.precision_parameter_loc = ['level_params', 'restol']
810 @property
811 def label(self):
812 return r'$k$-adaptivity'
814 def get_custom_description(self, problem, num_procs):
815 '''
816 Routine to get a custom description that allows for adaptive iteration counts
818 Args:
819 problem: A function that runs a pySDC problem, see imports for available problems
820 num_procs (int): Number of processes you intend to run with
822 Returns:
823 The custom description you can supply to the problem when running it
824 '''
825 restol = -1
826 e_tol = -1
828 if problem.__name__ == "run_piline":
829 restol = 2.3e-8
830 elif problem.__name__ == "run_vdp":
831 restol = 9e-7
832 elif problem.__name__ == "run_Lorenz":
833 restol = 16e-7
834 elif problem.__name__ == "run_Schroedinger":
835 restol = 6.5e-7
836 elif problem.__name__ == "run_quench":
837 restol = 1e-7
838 elif problem.__name__ == "run_AC":
839 restol = 1e-11
840 elif problem.__name__ == "run_RBC":
841 restol = 1e-4
842 elif problem.__name__ == "run_GS":
843 restol = 1e-4
844 else:
845 raise NotImplementedError('I don\'t have a residual tolerance for your problem. Please add one to the \
846strategy')
848 custom_description = {
849 'step_params': {'maxiter': 99},
850 'level_params': {'restol': restol, 'e_tol': e_tol},
851 }
853 if problem.__name__ == "run_quench":
854 custom_description['level_params']['dt'] = 1.0
856 return merge_descriptions(super().get_custom_description(problem, num_procs), custom_description)
858 def get_random_params(self, problem, num_procs):
859 '''
860 Routine to get parameters for the randomization of faults
862 Args:
863 problem: A function that runs a pySDC problem, see imports for available problems
864 num_procs (int): Number of processes you intend to run with
866 Returns:
867 dict: Randomization parameters
868 '''
870 rnd_params = super().get_random_params(problem, num_procs)
871 if problem.__name__ == "run_quench":
872 rnd_params['iteration'] = 1
873 return rnd_params
875 def get_reference_value(self, problem, key, op, num_procs=1):
876 """
877 Get a reference value for a given problem for testing in CI.
879 Args:
880 problem: A function that runs a pySDC problem, see imports for available problems
881 key (str): The name of the variable you want to compare
882 op (function): The operation you want to apply to the data
883 num_procs (int): Number of processes
885 Returns:
886 The reference value
887 """
888 if problem.__name__ == "run_Lorenz":
889 if key == 'work_newton' and op == sum:
890 return 9200
891 elif key == 'e_global_post_run' and op == max:
892 return 2.139863344829962e-05
894 super().get_reference_value(problem, key, op, num_procs)
897class kAdaptivityStrategy(IterateStrategy):
898 def __init__(self, **kwargs):
899 super().__init__(**kwargs)
900 self.precision_parameter = 'dt'
901 self.precision_parameter_loc = ['level_params', 'dt']
903 def get_custom_description(self, problem, num_procs, *args, **kwargs):
904 desc = super().get_custom_description(problem, num_procs, *args, **kwargs)
905 desc['level_params']['restol'] = 1e-9
906 if problem.__name__ == "run_quench":
907 desc['problem_params']['newton_tol'] = 1e-9
908 desc['problem_params']['lintol'] = 1e-9
909 desc['level_params']['dt'] = 2.5
910 elif problem.__name__ == "run_AC":
911 desc['level_params']['restol'] = 1e-11
912 desc['level_params']['dt'] = 0.4 * desc['problem_params']['eps'] ** 2 / 8.0
913 elif problem.__name__ == "run_RBC":
914 desc['level_params']['dt'] = 7e-2
915 desc['level_params']['restol'] = 1e-6
916 desc['level_params']['e_tol'] = 1e-7
917 elif problem.__name__ == "run_GS":
918 desc['level_params']['dt'] = 1.0
919 desc['level_params']['restol'] = 1e-9
920 return desc
922 def get_custom_description_for_faults(self, problem, num_procs, *args, **kwargs):
923 desc = self.get_custom_description(problem, num_procs, *args, **kwargs)
924 if problem.__name__ == 'run_quench':
925 desc['level_params']['dt'] = 5.0
926 elif problem.__name__ == 'run_AC':
927 desc['level_params']['dt'] = 4e-4 if num_procs == 4 else 5e-4
928 desc['level_params']['restol'] = 1e-5 if num_procs == 4 else 1e-11
929 elif problem.__name__ == 'run_RBC':
930 desc['level_params']['restol'] = 1e-3 if num_procs == 4 else 1e-6
931 elif problem.__name__ == 'run_Lorenz':
932 desc['level_params']['dt'] = 8e-3
933 elif problem.__name__ == "run_vdp":
934 desc['sweeper_params'] = {'num_nodes': 3}
935 desc['problem_params'] = {
936 'u0': np.array([2.0, 0], dtype=np.float64),
937 'mu': 5,
938 'crash_at_maxiter': False,
939 'newton_tol': 1e-11,
940 'stop_at_nan': False,
941 }
942 desc['level_params'] = {'dt': 4.0e-2, 'restol': 1e-7}
943 return desc
945 def get_reference_value(self, problem, key, op, num_procs=1):
946 """
947 Get a reference value for a given problem for testing in CI.
949 Args:
950 problem: A function that runs a pySDC problem, see imports for available problems
951 key (str): The name of the variable you want to compare
952 op (function): The operation you want to apply to the data
953 num_procs (int): Number of processes
955 Returns:
956 The reference value
957 """
958 if problem.__name__ == "run_Lorenz":
959 if key == 'work_newton' and op == sum:
960 return 12350
961 elif key == 'e_global_post_run' and op == max:
962 return 1.3527453646133836e-07
964 super().get_reference_value(problem, key, op, num_procs)
967class HotRodStrategy(Strategy):
968 '''
969 Hot Rod as a resilience strategy
970 '''
972 def __init__(self, **kwargs):
973 '''
974 Initialization routine
975 '''
976 kwargs['skip_residual_computation'] = 'all'
977 super().__init__(**kwargs)
978 self.color = list(cmap.values())[3]
979 self.marker = '^'
980 self.name = 'Hot Rod'
981 self.bar_plot_x_label = 'Hot Rod'
982 self.precision_parameter = 'dt'
983 self.precision_parameter_loc = ['level_params', 'dt']
985 def get_custom_description(self, problem, num_procs):
986 '''
987 Routine to get a custom description that adds Hot Rod
989 Args:
990 problem: A function that runs a pySDC problem, see imports for available problems
991 num_procs (int): Number of processes you intend to run with
993 Returns:
994 The custom description you can supply to the problem when running it
995 '''
996 from pySDC.implementations.convergence_controller_classes.hotrod import HotRod
997 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestartingNonMPI
999 base_params = super().get_custom_description(problem, num_procs)
1000 if problem.__name__ == "run_vdp":
1001 # if num_procs == 4:
1002 # HotRod_tol = 1.800804e-04
1003 # elif num_procs == 5:
1004 # HotRod_tol = 9.329361e-05
1005 # else: # 1 process
1006 # HotRod_tol = 1.347949e-06
1007 # HotRod_tol = 7e-6 if num_procs > 1 else 5e-7
1008 HotRod_tol = 7.2e-05
1009 maxiter = 6
1010 elif problem.__name__ == "run_Lorenz":
1011 if num_procs == 5:
1012 HotRod_tol = 9.539348e-06
1013 elif num_procs == 4:
1014 HotRod_tol = 3.201e-6
1015 else:
1016 HotRod_tol = 7.720589e-07
1017 maxiter = 6
1018 elif problem.__name__ == "run_Schroedinger":
1019 if num_procs == 5:
1020 HotRod_tol = 2.497697e-06
1021 elif num_procs == 4:
1022 HotRod_tol = 1.910405e-06
1023 else:
1024 HotRod_tol = 4.476790e-07
1025 maxiter = 6
1026 elif problem.__name__ == "run_quench":
1027 if num_procs == 5:
1028 HotRod_tol = 1.017534e-03
1029 elif num_procs == 4:
1030 HotRod_tol = 1.017534e-03
1031 else:
1032 HotRod_tol = 5.198620e-04
1033 maxiter = 6
1034 elif problem.__name__ == 'run_AC':
1035 HotRod_tol = 9.564437e-06
1036 maxiter = 6
1037 elif problem.__name__ == 'run_RBC':
1038 HotRod_tol = 3e-4 if num_procs == 4 else 6.34e-6
1039 maxiter = 6
1040 elif problem.__name__ == 'run_GS':
1041 HotRod_tol = 3.22e-5
1042 maxiter = 6
1043 else:
1044 raise NotImplementedError('I don\'t have a tolerance for Hot Rod for your problem. Please add one to the\
1045 strategy')
1047 no_storage = False # num_procs > 1
1049 custom_description = {
1050 'convergence_controllers': {
1051 HotRod: {'HotRod_tol': HotRod_tol, 'no_storage': no_storage},
1052 BasicRestartingNonMPI: {
1053 'max_restarts': 2,
1054 'crash_after_max_restarts': False,
1055 'restart_from_first_step': True,
1056 },
1057 },
1058 'step_params': {'maxiter': maxiter},
1059 'level_params': {},
1060 }
1061 if problem.__name__ == "run_AC":
1062 custom_description['level_params']['dt'] = 8e-5
1063 return merge_descriptions(base_params, custom_description)
1065 def get_custom_description_for_faults(self, problem, *args, **kwargs):
1066 desc = self.get_custom_description(problem, *args, **kwargs)
1067 if problem.__name__ == "run_quench":
1068 desc['level_params']['dt'] = 5.0
1069 elif problem.__name__ == "run_AC":
1070 desc['level_params']['dt'] = 8e-5
1071 elif problem.__name__ == "run_GS":
1072 desc['level_params']['dt'] = 4e-1
1073 elif problem.__name__ == "run_vdp":
1074 desc['step_params'] = {'maxiter': 6}
1075 desc['problem_params'] = {
1076 'u0': np.array([2.0, 0], dtype=np.float64),
1077 'mu': 5,
1078 'crash_at_maxiter': False,
1079 'newton_tol': 1e-11,
1080 'stop_at_nan': False,
1081 }
1082 desc['level_params'] = {'dt': 4.5e-2}
1083 return desc
1085 def get_reference_value(self, problem, key, op, num_procs=1):
1086 """
1087 Get a reference value for a given problem for testing in CI.
1089 Args:
1090 problem: A function that runs a pySDC problem, see imports for available problems
1091 key (str): The name of the variable you want to compare
1092 op (function): The operation you want to apply to the data
1093 num_procs (int): Number of processes
1095 Returns:
1096 The reference value
1097 """
1098 if problem.__name__ == "run_Lorenz":
1099 if key == 'work_newton' and op == sum:
1100 return 12350
1101 elif key == 'e_global_post_run' and op == max:
1102 return 1.3527453646133836e-07
1104 super().get_reference_value(problem, key, op, num_procs)
1107class AdaptivityCollocationStrategy(InexactBaseStrategy):
1108 '''
1109 Adaptivity based on collocation as a resilience strategy
1110 '''
1112 def __init__(self, **kwargs):
1113 '''
1114 Initialization routine
1115 '''
1116 kwargs = {
1117 'skip_residual_computation': 'most',
1118 **kwargs,
1119 }
1121 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityCollocation
1123 self.restol = None
1124 super().__init__(**kwargs)
1125 self.color = list(cmap.values())[1]
1126 self.marker = '*'
1127 self.name = 'adaptivity_coll'
1128 self.bar_plot_x_label = 'adaptivity collocation'
1129 self.precision_parameter = 'e_tol'
1130 self.adaptive_coll_params = {}
1131 self.precision_parameter_loc = ['convergence_controllers', AdaptivityCollocation, 'e_tol']
1133 def get_custom_description(self, problem, num_procs):
1134 '''
1135 Routine to get a custom description that adds adaptivity
1137 Args:
1138 problem: A function that runs a pySDC problem, see imports for available problems
1139 num_procs (int): Number of processes you intend to run with
1141 Returns:
1142 The custom descriptions you can supply to the problem when running it
1143 '''
1144 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityCollocation
1146 custom_description = {}
1148 dt_max = np.inf
1149 dt_min = 1e-5
1151 if problem.__name__ == "run_piline":
1152 e_tol = 1e-7
1153 dt_min = 1e-2
1154 elif problem.__name__ == "run_vdp":
1155 e_tol = 2e-5
1156 dt_min = 1e-3
1157 elif problem.__name__ == "run_Lorenz":
1158 e_tol = 2e-5
1159 dt_min = 1e-3
1160 elif problem.__name__ == "run_Schroedinger":
1161 e_tol = 4e-6
1162 dt_min = 1e-3
1163 elif problem.__name__ == "run_quench":
1164 e_tol = 1e-5
1165 dt_min = 1e-3
1166 dt_max = 1e2
1167 elif problem.__name__ == "run_AC":
1168 e_tol = 1e-4
1169 else:
1170 raise NotImplementedError('I don\'t have a tolerance for adaptivity for your problem. Please add one to the\
1171 strategy')
1173 custom_description['convergence_controllers'] = {
1174 AdaptivityCollocation: {
1175 'e_tol': e_tol,
1176 'dt_min': dt_min,
1177 'dt_max': dt_max,
1178 'adaptive_coll_params': self.adaptive_coll_params,
1179 'restol_rel': 1e-2,
1180 }
1181 }
1182 return merge_descriptions(super().get_custom_description(problem, num_procs), custom_description)
1185class AdaptivityCollocationTypeStrategy(AdaptivityCollocationStrategy):
1186 def __init__(self, **kwargs):
1187 super().__init__(**kwargs)
1188 self.color = list(cmap.values())[4]
1189 self.marker = '.'
1190 self.adaptive_coll_params = {
1191 'quad_type': ['RADAU-RIGHT', 'GAUSS'],
1192 'do_coll_update': [False, True],
1193 }
1195 @property
1196 def label(self):
1197 return 'adaptivity type'
1199 def get_reference_value(self, problem, key, op, num_procs=1):
1200 """
1201 Get a reference value for a given problem for testing in CI.
1203 Args:
1204 problem: A function that runs a pySDC problem, see imports for available problems
1205 key (str): The name of the variable you want to compare
1206 op (function): The operation you want to apply to the data
1207 num_procs (int): Number of processes
1209 Returns:
1210 The reference value
1211 """
1212 if problem.__name__ == "run_Lorenz":
1213 if key == 'work_newton' and op == sum:
1214 return 1025
1215 elif key == 'e_global_post_run' and op == max:
1216 return 4.266975256683736e-06
1218 super().get_reference_value(problem, key, op, num_procs)
1221class AdaptivityCollocationRefinementStrategy(AdaptivityCollocationStrategy):
1222 def __init__(self, **kwargs):
1223 super().__init__(**kwargs)
1224 self.color = list(cmap.values())[5]
1225 self.marker = '^'
1226 self.adaptive_coll_params = {
1227 'num_nodes': [2, 3],
1228 'quad_type': ['GAUSS', 'RADAU-RIGHT'],
1229 'do_coll_update': [True, False],
1230 }
1232 @property
1233 def label(self):
1234 return 'adaptivity refinement'
1236 def get_reference_value(self, problem, key, op, num_procs=1):
1237 """
1238 Get a reference value for a given problem for testing in CI.
1240 Args:
1241 problem: A function that runs a pySDC problem, see imports for available problems
1242 key (str): The name of the variable you want to compare
1243 op (function): The operation you want to apply to the data
1244 num_procs (int): Number of processes
1246 Returns:
1247 The reference value
1248 """
1249 if problem.__name__ == "run_Lorenz":
1250 if key == 'work_newton' and op == sum:
1251 return 917
1252 elif key == 'e_global_post_run' and op == max:
1253 return 1.0874929465387595e-05
1255 super().get_reference_value(problem, key, op, num_procs)
1258class AdaptivityCollocationDerefinementStrategy(AdaptivityCollocationStrategy):
1259 def __init__(self, **kwargs):
1260 super().__init__(**kwargs)
1261 self.color = list(cmap.values())[6]
1262 self.marker = '^'
1263 self.adaptive_coll_params = {'num_nodes': [4, 3]}
1265 @property
1266 def label(self):
1267 return 'adaptivity de-refinement'
1269 def get_reference_value(self, problem, key, op, num_procs=1):
1270 """
1271 Get a reference value for a given problem for testing in CI.
1273 Args:
1274 problem: A function that runs a pySDC problem, see imports for available problems
1275 key (str): The name of the variable you want to compare
1276 op (function): The operation you want to apply to the data
1277 num_procs (int): Number of processes
1279 Returns:
1280 The reference value
1281 """
1282 if problem.__name__ == 'run_Lorenz':
1283 if key == 'work_newton' and op == sum:
1284 return 1338
1285 elif key == 'e_global_post_run' and op == max:
1286 return 0.0001013999955041811
1288 super().get_reference_value(problem, key, op, num_procs)
1291class DIRKStrategy(AdaptivityStrategy):
1292 '''
1293 DIRK4(3)
1294 '''
1296 def __init__(self, **kwargs):
1297 '''
1298 Initialization routine
1299 '''
1300 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK
1302 super().__init__(**kwargs)
1303 self.color = list(cmap.values())[7]
1304 self.marker = '^'
1305 self.name = 'DIRK'
1306 self.bar_plot_x_label = 'DIRK4(3)'
1307 self.precision_parameter = 'e_tol'
1308 self.precision_parameter_loc = ['convergence_controllers', AdaptivityRK, 'e_tol']
1309 self.max_steps = 1e5
1311 @property
1312 def label(self):
1313 return 'DIRK4(3)'
1315 def get_custom_description(self, problem, num_procs):
1316 '''
1317 Routine to get a custom description that adds adaptivity
1319 Args:
1320 problem: A function that runs a pySDC problem, see imports for available problems
1321 num_procs (int): Number of processes you intend to run with
1323 Returns:
1324 The custom descriptions you can supply to the problem when running it
1325 '''
1326 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK, Adaptivity
1327 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
1328 from pySDC.implementations.sweeper_classes.Runge_Kutta import DIRK43
1330 adaptivity_description = super().get_custom_description(problem, num_procs)
1332 e_tol = adaptivity_description['convergence_controllers'][Adaptivity]['e_tol']
1333 adaptivity_description['convergence_controllers'].pop(Adaptivity, None)
1334 adaptivity_description.pop('sweeper_params', None)
1336 rk_params = {
1337 'step_params': {'maxiter': 1},
1338 'sweeper_class': DIRK43,
1339 'convergence_controllers': {
1340 AdaptivityRK: {'e_tol': e_tol},
1341 BasicRestarting.get_implementation(useMPI=self.useMPI): {
1342 'max_restarts': 49,
1343 'crash_after_max_restarts': False,
1344 },
1345 },
1346 }
1348 custom_description = merge_descriptions(adaptivity_description, rk_params)
1350 return custom_description
1352 def get_reference_value(self, problem, key, op, num_procs=1):
1353 """
1354 Get a reference value for a given problem for testing in CI.
1356 Args:
1357 problem: A function that runs a pySDC problem, see imports for available problems
1358 key (str): The name of the variable you want to compare
1359 op (function): The operation you want to apply to the data
1360 num_procs (int): Number of processes
1362 Returns:
1363 The reference value
1364 """
1365 if problem.__name__ == "run_Lorenz":
1366 if key == 'work_newton' and op == sum:
1367 return 5467
1368 elif key == 'e_global_post_run' and op == max:
1369 return 7.049480537091313e-07
1371 super().get_reference_value(problem, key, op, num_procs)
1373 def get_random_params(self, problem, num_procs):
1374 '''
1375 Routine to get parameters for the randomization of faults
1377 Args:
1378 problem: A function that runs a pySDC problem, see imports for available problems
1379 num_procs (int): Number of processes you intend to run with
1381 Returns:
1382 dict: Randomization parameters
1383 '''
1384 rnd_params = super().get_random_params(problem, num_procs)
1385 rnd_params['iteration'] = 1
1386 rnd_params['min_node'] = 5
1388 return rnd_params
1391class ARKStrategy(AdaptivityStrategy):
1392 '''
1393 ARK5(4)
1394 '''
1396 def __init__(self, **kwargs):
1397 '''
1398 Initialization routine
1399 '''
1400 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK
1402 super().__init__(**kwargs)
1403 self.color = list(cmap.values())[7]
1404 self.marker = 'P'
1405 self.name = 'ARK'
1406 self.bar_plot_x_label = 'ARK5(4)'
1407 self.precision_parameter = 'e_tol'
1408 self.precision_parameter_loc = ['convergence_controllers', AdaptivityRK, 'e_tol']
1409 self.max_steps = 1e5
1411 @property
1412 def label(self):
1413 return 'ARK5(4)'
1415 def get_custom_description(self, problem, num_procs):
1416 '''
1417 Routine to get a custom description that adds adaptivity
1419 Args:
1420 problem: A function that runs a pySDC problem, see imports for available problems
1421 num_procs (int): Number of processes you intend to run with
1423 Returns:
1424 The custom descriptions you can supply to the problem when running it
1425 '''
1426 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK, Adaptivity
1427 from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeSlopeLimiter
1428 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
1429 from pySDC.implementations.sweeper_classes.Runge_Kutta import ARK548L2SA
1431 adaptivity_description = super().get_custom_description(problem, num_procs)
1433 e_tol = adaptivity_description['convergence_controllers'][Adaptivity]['e_tol'] / 20.0
1434 adaptivity_description['convergence_controllers'].pop(Adaptivity, None)
1435 adaptivity_description.pop('sweeper_params', None)
1437 rk_params = {
1438 'step_params': {'maxiter': 1},
1439 'sweeper_class': ARK548L2SA,
1440 'convergence_controllers': {
1441 AdaptivityRK: {'e_tol': e_tol},
1442 BasicRestarting.get_implementation(useMPI=self.useMPI): {
1443 'max_restarts': 49,
1444 'crash_after_max_restarts': False,
1445 },
1446 },
1447 }
1449 if problem.__name__ == "run_RBC":
1450 rk_params['convergence_controllers'][StepSizeSlopeLimiter] = {'dt_rel_min_slope': 0.25}
1452 custom_description = merge_descriptions(adaptivity_description, rk_params)
1454 return custom_description
1456 def get_reference_value(self, problem, key, op, num_procs=1):
1457 """
1458 Get a reference value for a given problem for testing in CI.
1460 Args:
1461 problem: A function that runs a pySDC problem, see imports for available problems
1462 key (str): The name of the variable you want to compare
1463 op (function): The operation you want to apply to the data
1464 num_procs (int): Number of processes
1466 Returns:
1467 The reference value
1468 """
1469 if problem.__name__ == "run_Schroedinger":
1470 if key == 'work_newton' and op == sum:
1471 return 0
1472 elif key == 'e_global_post_run' and op == max:
1473 return 3.1786601531890356e-08
1475 super().get_reference_value(problem, key, op, num_procs)
1478class ARK3_CFL_Strategy(BaseStrategy):
1479 """
1480 This is special for RBC with CFL number for accuracy
1481 """
1483 def __init__(self, **kwargs):
1484 '''
1485 Initialization routine
1486 '''
1487 from pySDC.implementations.problem_classes.RayleighBenard import CFLLimit
1489 super().__init__(**kwargs)
1490 self.color = 'maroon'
1491 self.marker = '<'
1492 self.name = 'ARK3'
1493 self.bar_plot_x_label = 'ARK3'
1494 self.precision_parameter = 'cfl'
1495 self.precision_parameter_loc = ['convergence_controllers', CFLLimit, 'cfl']
1496 self.max_steps = 1e5
1498 @property
1499 def label(self):
1500 return 'ARK3'
1502 def get_custom_description(self, problem, num_procs):
1503 '''
1504 Args:
1505 problem: A function that runs a pySDC problem, see imports for available problems
1506 num_procs (int): Number of processes you intend to run with
1508 Returns:
1509 The custom descriptions you can supply to the problem when running it
1510 '''
1511 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
1512 from pySDC.implementations.sweeper_classes.Runge_Kutta import ARK3
1513 from pySDC.implementations.problem_classes.RayleighBenard import CFLLimit
1514 from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeSlopeLimiter
1516 desc = super().get_custom_description(problem, num_procs)
1518 rk_params = {
1519 'step_params': {'maxiter': 1},
1520 'sweeper_class': ARK3,
1521 'convergence_controllers': {
1522 CFLLimit: {
1523 'cfl': 0.5,
1524 'dt_max': 1.0,
1525 },
1526 StepSizeSlopeLimiter: {'dt_rel_min_slope': 0.2},
1527 },
1528 }
1530 custom_description = merge_descriptions(desc, rk_params)
1532 return custom_description
1535class ESDIRKStrategy(AdaptivityStrategy):
1536 '''
1537 ESDIRK5(3)
1538 '''
1540 def __init__(self, **kwargs):
1541 '''
1542 Initialization routine
1543 '''
1544 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK
1546 super().__init__(**kwargs)
1547 self.color = 'violet'
1548 self.marker = '^'
1549 self.name = 'ESDIRK'
1550 self.bar_plot_x_label = 'ESDIRK5(3)'
1551 self.precision_parameter = 'e_tol'
1552 self.precision_parameter_loc = ['convergence_controllers', AdaptivityRK, 'e_tol']
1553 self.max_steps = 1e5
1555 @property
1556 def label(self):
1557 return 'ESDIRK5(3)'
1559 def get_description_for_tolerance(self, problem, param, **kwargs):
1560 desc = {}
1561 if problem.__name__ == 'run_Schroedinger':
1562 desc['problem_params'] = {'lintol': param}
1563 return desc
1565 def get_custom_description(self, problem, num_procs):
1566 '''
1567 Routine to get a custom description that adds adaptivity
1569 Args:
1570 problem: A function that runs a pySDC problem, see imports for available problems
1571 num_procs (int): Number of processes you intend to run with
1573 Returns:
1574 The custom descriptions you can supply to the problem when running it
1575 '''
1576 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK, Adaptivity
1577 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
1578 from pySDC.implementations.sweeper_classes.Runge_Kutta import ESDIRK53
1580 adaptivity_description = super().get_custom_description(problem, num_procs)
1582 e_tol = adaptivity_description['convergence_controllers'][Adaptivity]['e_tol']
1583 adaptivity_description['convergence_controllers'].pop(Adaptivity, None)
1584 adaptivity_description.pop('sweeper_params', None)
1586 mod = 1e1 if problem.__name__ == 'run_quench' else 1.0
1588 rk_params = {
1589 'step_params': {'maxiter': 1},
1590 'sweeper_class': ESDIRK53,
1591 'convergence_controllers': {
1592 AdaptivityRK: {'e_tol': e_tol * mod},
1593 BasicRestarting.get_implementation(useMPI=self.useMPI): {
1594 'max_restarts': 49,
1595 'crash_after_max_restarts': False,
1596 },
1597 },
1598 }
1600 custom_description = merge_descriptions(adaptivity_description, rk_params)
1602 return custom_description
1604 def get_reference_value(self, problem, key, op, num_procs=1):
1605 """
1606 Get a reference value for a given problem for testing in CI.
1608 Args:
1609 problem: A function that runs a pySDC problem, see imports for available problems
1610 key (str): The name of the variable you want to compare
1611 op (function): The operation you want to apply to the data
1612 num_procs (int): Number of processes
1614 Returns:
1615 The reference value
1616 """
1617 if problem.__name__ == "run_Lorenz":
1618 if key == 'work_newton' and op == sum:
1619 return 2963
1620 elif key == 'e_global_post_run' and op == max:
1621 return 4.126039954144289e-09
1623 super().get_reference_value(problem, key, op, num_procs)
1625 def get_random_params(self, problem, num_procs):
1626 '''
1627 Routine to get parameters for the randomization of faults
1629 Args:
1630 problem: A function that runs a pySDC problem, see imports for available problems
1631 num_procs (int): Number of processes you intend to run with
1633 Returns:
1634 dict: Randomization parameters
1635 '''
1636 rnd_params = super().get_random_params(problem, num_procs)
1637 rnd_params['iteration'] = 1
1638 rnd_params['min_node'] = 6
1640 return rnd_params
1643class ERKStrategy(DIRKStrategy):
1644 """
1645 Explicit embedded RK using Cash-Karp's method
1646 """
1648 def __init__(self, **kwargs):
1649 '''
1650 Initialization routine
1651 '''
1652 super().__init__(**kwargs)
1653 self.color = list(cmap.values())[8]
1654 self.marker = 'x'
1655 self.name = 'ERK'
1656 self.bar_plot_x_label = 'ERK5(4)'
1658 def get_description_for_tolerance(self, problem, param, **kwargs):
1659 desc = {}
1660 if problem.__name__ == 'run_Schroedinger':
1661 desc['problem_params'] = {'lintol': param}
1663 return desc
1665 @property
1666 def label(self):
1667 return 'CK5(4)'
1669 def get_random_params(self, problem, num_procs):
1670 '''
1671 Routine to get parameters for the randomization of faults
1673 Args:
1674 problem: A function that runs a pySDC problem, see imports for available problems
1675 num_procs (int): Number of processes you intend to run with
1677 Returns:
1678 dict: Randomization parameters
1679 '''
1680 rnd_params = super().get_random_params(problem, num_procs)
1681 rnd_params['min_node'] = 7
1683 return rnd_params
1685 def get_custom_description(self, problem, num_procs=1):
1686 from pySDC.implementations.sweeper_classes.Runge_Kutta import Cash_Karp
1688 desc = super().get_custom_description(problem, num_procs)
1689 desc['sweeper_class'] = Cash_Karp
1691 if problem.__name__ == "run_AC":
1692 desc['level_params']['dt'] = 2e-5
1693 return desc
1695 def get_reference_value(self, problem, key, op, num_procs=1):
1696 """
1697 Get a reference value for a given problem for testing in CI.
1699 Args:
1700 problem: A function that runs a pySDC problem, see imports for available problems
1701 key (str): The name of the variable you want to compare
1702 op (function): The operation you want to apply to the data
1703 num_procs (int): Number of processes
1705 Returns:
1706 The reference value
1707 """
1708 if problem.__name__ == "run_Lorenz":
1709 if key == 'work_newton' and op == sum:
1710 return 0
1711 elif key == 'e_global_post_run' and op == max:
1712 return 1.509206128957885e-07
1714 super().get_reference_value(problem, key, op, num_procs)
1717class DoubleAdaptivityStrategy(AdaptivityStrategy):
1718 '''
1719 Adaptivity based both on embedded estimate and on residual
1720 '''
1722 def __init__(self, **kwargs):
1723 '''
1724 Initialization routine
1725 '''
1726 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
1728 kwargs['skip_residual_computation'] = 'all'
1729 super().__init__(**kwargs)
1730 self.color = list(cmap.values())[7]
1731 self.marker = '^'
1732 self.name = 'double_adaptivity'
1733 self.bar_plot_x_label = 'double adaptivity'
1734 self.precision_parameter = 'e_tol'
1735 self.precision_parameter_loc = ['convergence_controllers', Adaptivity, 'e_tol']
1736 self.residual_e_tol_ratio = 1.0
1737 self.residual_e_tol_abs = None
1739 @property
1740 def label(self):
1741 return 'double adaptivity'
1743 def get_custom_description(self, problem, num_procs):
1744 '''
1745 Routine to get a custom description that adds adaptivity
1747 Args:
1748 problem: A function that runs a pySDC problem, see imports for available problems
1749 num_procs (int): Number of processes you intend to run with
1751 Returns:
1752 The custom descriptions you can supply to the problem when running it
1753 '''
1754 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityResidual, Adaptivity
1755 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
1757 custom_description = super().get_custom_description(problem, num_procs)
1759 if self.residual_e_tol_abs:
1760 e_tol = self.residual_e_tol_abs
1761 else:
1762 e_tol = custom_description['convergence_controllers'][Adaptivity]['e_tol'] * self.residual_e_tol_ratio
1763 custom_description['convergence_controllers'][AdaptivityResidual] = {
1764 'e_tol': e_tol,
1765 'allowed_modifications': ['decrease'],
1766 }
1768 custom_description['convergence_controllers'][BasicRestarting.get_implementation(useMPI=self.useMPI)] = {
1769 'max_restarts': 15
1770 }
1772 return custom_description
1774 def get_reference_value(self, problem, key, op, num_procs=1):
1775 """
1776 Get a reference value for a given problem for testing in CI.
1778 Args:
1779 problem: A function that runs a pySDC problem, see imports for available problems
1780 key (str): The name of the variable you want to compare
1781 op (function): The operation you want to apply to the data
1782 num_procs (int): Number of processes
1784 Returns:
1785 The reference value
1786 """
1787 if problem.__name__ == 'run_Lorenz':
1788 if key == 'work_newton' and op == sum:
1789 return 2989
1790 elif key == 'e_global_post_run' and op == max:
1791 return 5.636763944494305e-08
1793 super().get_reference_value(problem, key, op, num_procs)
1796class AdaptivityAvoidRestartsStrategy(AdaptivityStrategy):
1797 """
1798 Adaptivity with the avoid restarts option
1799 """
1801 @property
1802 def label(self):
1803 return 'adaptivity (avoid restarts)'
1805 def get_custom_description(self, problem, num_procs):
1806 '''
1807 Routine to get a custom description that adds adaptivity
1809 Args:
1810 problem: A function that runs a pySDC problem, see imports for available problems
1811 num_procs (int): Number of processes you intend to run with
1813 Returns:
1814 The custom descriptions you can supply to the problem when running it
1815 '''
1816 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
1817 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
1819 custom_description = super().get_custom_description(problem, num_procs)
1821 custom_description['convergence_controllers'][Adaptivity]['avoid_restarts'] = True
1823 custom_description['convergence_controllers'][BasicRestarting.get_implementation(useMPI=self.useMPI)] = {
1824 'max_restarts': 15
1825 }
1827 return custom_description
1829 def get_reference_value(self, problem, key, op, num_procs=1):
1830 """
1831 Get a reference value for a given problem for testing in CI.
1833 Args:
1834 problem: A function that runs a pySDC problem, see imports for available problems
1835 key (str): The name of the variable you want to compare
1836 op (function): The operation you want to apply to the data
1837 num_procs (int): Number of processes
1839 Returns:
1840 The reference value
1841 """
1842 if problem.__name__ == "run_Lorenz":
1843 if key == 'work_newton' and op == sum:
1844 return 2989
1845 elif key == 'e_global_post_run' and op == max:
1846 return 5.636763944494305e-08
1848 super().get_reference_value(problem, key, op, num_procs)
1851class AdaptivityInterpolationStrategy(AdaptivityStrategy):
1852 """
1853 Adaptivity with interpolation between restarts
1854 """
1856 @property
1857 def label(self):
1858 return 'adaptivity+interpolation'
1860 def get_custom_description(self, problem, num_procs):
1861 '''
1862 Routine to get a custom description that adds adaptivity
1864 Args:
1865 problem: A function that runs a pySDC problem, see imports for available problems
1866 num_procs (int): Number of processes you intend to run with
1868 Returns:
1869 The custom descriptions you can supply to the problem when running it
1870 '''
1871 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
1872 from pySDC.implementations.convergence_controller_classes.interpolate_between_restarts import (
1873 InterpolateBetweenRestarts,
1874 )
1875 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting
1877 custom_description = super().get_custom_description(problem, num_procs)
1879 custom_description['convergence_controllers'][Adaptivity]['avoid_restarts'] = False
1880 custom_description['convergence_controllers'][InterpolateBetweenRestarts] = {}
1882 custom_description['convergence_controllers'][BasicRestarting.get_implementation(useMPI=self.useMPI)] = {
1883 'max_restarts': 15
1884 }
1886 return custom_description
1888 def get_reference_value(self, problem, key, op, num_procs=1):
1889 """
1890 Get a reference value for a given problem for testing in CI.
1892 Args:
1893 problem: A function that runs a pySDC problem, see imports for available problems
1894 key (str): The name of the variable you want to compare
1895 op (function): The operation you want to apply to the data
1896 num_procs (int): Number of processes
1898 Returns:
1899 The reference value
1900 """
1901 if problem.__name__ == "run_Lorenz":
1902 if key == 'work_newton' and op == sum:
1903 return 6659
1904 elif key == 'e_global_post_run' and op == max:
1905 return 2.9780002756552015e-06
1907 super().get_reference_value(problem, key, op, num_procs)
1910class AdaptivityExtrapolationWithinQStrategy(InexactBaseStrategy):
1911 '''
1912 Adaptivity based on extrapolation between collocation nodes as a resilience strategy
1913 '''
1915 def __init__(self, **kwargs):
1916 '''
1917 Initialization routine
1918 '''
1919 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityExtrapolationWithinQ
1921 self.restol = None
1922 super().__init__(**kwargs)
1923 self.color = list(cmap.values())[8]
1924 self.marker = '*'
1925 self.name = 'adaptivity_extraQ'
1926 self.bar_plot_x_label = 'adaptivity Q'
1927 self.precision_parameter = 'e_tol'
1928 self.adaptive_coll_params = {}
1929 self.precision_parameter_loc = ['convergence_controllers', AdaptivityExtrapolationWithinQ, 'e_tol']
1931 def get_custom_description(self, problem, num_procs):
1932 '''
1933 Routine to get a custom description that adds adaptivity
1935 Args:
1936 problem: A function that runs a pySDC problem, see imports for available problems
1937 num_procs (int): Number of processes you intend to run with
1939 Returns:
1940 The custom descriptions you can supply to the problem when running it
1941 '''
1942 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityExtrapolationWithinQ
1944 custom_description = {}
1946 dt_max = np.inf
1947 dt_min = 1e-5
1949 if problem.__name__ == "run_vdp":
1950 e_tol = 2e-5
1951 dt_min = 1e-3
1952 elif problem.__name__ == "run_piline":
1953 e_tol = 1e-7
1954 dt_min = 1e-2
1955 elif problem.__name__ == "run_Lorenz":
1956 e_tol = 2e-5
1957 dt_min = 1e-3
1958 elif problem.__name__ == "run_Schroedinger":
1959 e_tol = 4e-6
1960 dt_min = 1e-3
1961 elif problem.__name__ == "run_quench":
1962 e_tol = 1e-5
1963 dt_min = 1e-3
1964 dt_max = 1e2
1965 elif problem.__name__ == "run_AC":
1966 e_tol = 1e-4
1967 else:
1968 raise NotImplementedError('I don\'t have a tolerance for adaptivity for your problem. Please add one to the\
1969 strategy')
1971 custom_description['convergence_controllers'] = {
1972 AdaptivityExtrapolationWithinQ: {
1973 'e_tol': e_tol,
1974 'dt_min': dt_min,
1975 'dt_max': dt_max,
1976 'restol_rel': 1e-2,
1977 'restart_at_maxiter': True,
1978 }
1979 }
1980 return merge_descriptions(super().get_custom_description(problem, num_procs), custom_description)
1982 def get_reference_value(self, problem, key, op, num_procs=1):
1983 """
1984 Get a reference value for a given problem for testing in CI.
1986 Args:
1987 problem: A function that runs a pySDC problem, see imports for available problems
1988 key (str): The name of the variable you want to compare
1989 op (function): The operation you want to apply to the data
1990 num_procs (int): Number of processes
1992 Returns:
1993 The reference value
1994 """
1995 if problem.__name__ == "run_Lorenz":
1996 if key == 'work_newton' and op == sum:
1997 return 2198
1998 elif key == 'e_global_post_run' and op == max:
1999 return 5.412657451131508e-07
2001 super().get_reference_value(problem, key, op, num_procs)
2004class AdaptivityPolynomialError(InexactBaseStrategy):
2005 '''
2006 Adaptivity based on extrapolation between collocation nodes as a resilience strategy
2007 '''
2009 def __init__(self, interpolate_between_restarts=False, use_restol_rel=True, max_slope=4, **kwargs):
2010 '''
2011 Initialization routine
2012 '''
2013 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityPolynomialError
2015 self.restol = None
2016 super().__init__(**kwargs)
2017 self.color = list(cmap.values())[9]
2018 self.marker = '+'
2019 self.name = 'adaptivity-inter'
2020 self.bar_plot_x_label = 'adaptivity Q'
2021 self.precision_parameter = 'e_tol'
2022 self.adaptive_coll_params = {}
2023 self.precision_parameter_loc = ['convergence_controllers', AdaptivityPolynomialError, 'e_tol']
2024 self.interpolate_between_restarts = interpolate_between_restarts
2025 self.use_restol_rel = use_restol_rel
2026 self.max_slope = max_slope
2028 def get_custom_description(self, problem, num_procs):
2029 '''
2030 Routine to get a custom description that adds adaptivity
2032 Args:
2033 problem: A function that runs a pySDC problem, see imports for available problems
2034 num_procs (int): Number of processes you intend to run with
2036 Returns:
2037 The custom descriptions you can supply to the problem when running it
2038 '''
2039 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityPolynomialError
2040 from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeLimiter
2041 from pySDC.implementations.convergence_controller_classes.check_convergence import CheckConvergence
2043 base_params = super().get_custom_description(problem, num_procs)
2044 custom_description = {}
2046 dt_max = np.inf
2047 restol_rel = 1e-4
2048 restol_min = 1e-12
2049 restol_max = 1e-5
2050 dt_slope_min = 0
2051 dt_min = 0
2052 abort_at_growing_residual = True
2053 level_params = {}
2054 problem_params = {}
2055 beta = 0.9
2057 if problem.__name__ == "run_vdp":
2058 e_tol = 6e-4
2059 level_params['dt'] = 0.1
2060 restol_rel = 1e-5
2061 restol_min = 1e-12
2062 dt_min = 1e-7
2063 problem_params['newton_tol'] = 1e-14
2064 elif problem.__name__ == "run_piline":
2065 e_tol = 1e-7
2066 elif problem.__name__ == "run_Lorenz":
2067 e_tol = 2e-4
2068 elif problem.__name__ == "run_Schroedinger":
2069 e_tol = 3e-5
2070 elif problem.__name__ == "run_quench":
2071 e_tol = 1e-7
2072 level_params['dt'] = 50.0
2073 restol_min = 1e-11
2074 restol_rel = 1e-1
2075 elif problem.__name__ == "run_AC":
2076 e_tol = 1.0e-4
2077 restol_rel = 1e-3 if num_procs == 4 else 1e-3
2078 # dt_max = 0.1 * base_params['problem_params']['eps'] ** 2
2079 elif problem.__name__ == "run_RBC":
2080 e_tol = 5e-2 if num_procs == 4 else 5e-3
2081 dt_slope_min = 1.0
2082 abort_at_growing_residual = False
2083 restol_rel = 1e-2 if num_procs == 4 else 1e-4
2084 restol_max = 1e-1
2085 restol_min = 5e-8
2086 self.max_slope = 4
2087 beta = 0.5
2088 level_params['e_tol'] = 1e-5
2089 elif problem.__name__ == 'run_GS':
2090 e_tol = 1e-4
2091 restol_rel = 4e-3
2092 restol_max = 1e-4
2093 restol_min = 1e-9
2094 else:
2095 raise NotImplementedError('I don\'t have a tolerance for adaptivity for your problem. Please add one to the\
2096 strategy')
2098 custom_description['convergence_controllers'] = {
2099 AdaptivityPolynomialError: {
2100 'e_tol': e_tol,
2101 'restol_rel': restol_rel if self.use_restol_rel else 1e-11,
2102 'restol_min': restol_min if self.use_restol_rel else 1e-12,
2103 'restol_max': restol_max if self.use_restol_rel else 1e-5,
2104 'restart_at_maxiter': True,
2105 'factor_if_not_converged': self.max_slope,
2106 'interpolate_between_restarts': self.interpolate_between_restarts,
2107 'abort_at_growing_residual': abort_at_growing_residual,
2108 'beta': beta,
2109 },
2110 StepSizeLimiter: {
2111 'dt_max': dt_max,
2112 'dt_slope_max': self.max_slope,
2113 'dt_min': dt_min,
2114 'dt_rel_min_slope': dt_slope_min,
2115 },
2116 }
2117 custom_description['level_params'] = level_params
2118 custom_description['problem_params'] = problem_params
2120 return merge_descriptions(base_params, custom_description)
2122 def get_custom_description_for_faults(self, problem, num_procs, *args, **kwargs):
2123 desc = self.get_custom_description(problem, num_procs, *args, **kwargs)
2124 if problem.__name__ == "run_quench":
2125 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityPolynomialError
2127 desc['convergence_controllers'][AdaptivityPolynomialError]['e_tol'] = 1e-7 * 11
2128 desc['level_params']['dt'] = 4.0
2129 elif problem.__name__ == "run_AC":
2130 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityPolynomialError
2132 desc['convergence_controllers'][AdaptivityPolynomialError]['e_tol'] = 6e-3 if num_procs == 4 else 1e-3
2133 if num_procs == 4:
2134 desc['step_params'] = {'maxiter': 50}
2135 elif problem.__name__ == "run_Lorenz":
2136 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityPolynomialError
2138 desc['convergence_controllers'][AdaptivityPolynomialError]['e_tol'] = 2e-4
2139 desc['convergence_controllers'][AdaptivityPolynomialError]['restol_min'] = 1e-11
2140 desc['convergence_controllers'][AdaptivityPolynomialError]['restol_rel'] = 1e-11
2141 elif problem.__name__ == "run_vdp":
2142 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityPolynomialError
2143 from pySDC.implementations.convergence_controller_classes.inexactness import NewtonInexactness
2145 desc['step_params'] = {'maxiter': 16}
2146 desc['problem_params'] = {
2147 'u0': np.array([2.0, 0], dtype=np.float64),
2148 'mu': 5,
2149 'crash_at_maxiter': False,
2150 'newton_tol': 1e-11,
2151 'stop_at_nan': False,
2152 }
2153 desc['convergence_controllers'][AdaptivityPolynomialError]['e_tol'] = 5e-4
2154 desc['convergence_controllers'][AdaptivityPolynomialError]['restol_rel'] = 8e-5
2155 desc['convergence_controllers'].pop(NewtonInexactness)
2156 desc['level_params'] = {'dt': 4.5e-2}
2157 return desc
2159 def get_random_params(self, problem, num_procs):
2160 '''
2161 Routine to get parameters for the randomization of faults
2163 Args:
2164 problem: A function that runs a pySDC problem, see imports for available problems
2165 num_procs (int): Number of processes you intend to run with
2167 Returns:
2168 dict: Randomization parameters
2169 '''
2171 rnd_params = super().get_random_params(problem, num_procs)
2172 if problem.__name__ == "run_quench":
2173 rnd_params['iteration'] = 1
2174 elif problem.__name__ == 'run_Lorenz':
2175 rnd_params['iteration'] = 5
2176 return rnd_params
2178 def get_reference_value(self, problem, key, op, num_procs=1):
2179 """
2180 Get a reference value for a given problem for testing in CI.
2182 Args:
2183 problem: A function that runs a pySDC problem, see imports for available problems
2184 key (str): The name of the variable you want to compare
2185 op (function): The operation you want to apply to the data
2186 num_procs (int): Number of processes
2188 Returns:
2189 The reference value
2190 """
2191 if problem.__name__ == "run_Lorenz":
2192 if key == 'work_newton' and op == sum:
2193 return 2123
2194 elif key == 'e_global_post_run' and op == max:
2195 return 7.931560830343187e-08
2197 super().get_reference_value(problem, key, op, num_procs)
2199 @property
2200 def label(self):
2201 return r'$\Delta t$-$k$-adaptivity'