Coverage for pySDC/projects/Resilience/strategies.py: 66%

909 statements  

« prev     ^ index     » next       coverage.py v7.6.9, created at 2024-12-20 14:51 +0000

1import numpy as np 

2from matplotlib.colors import TABLEAU_COLORS 

3 

4cmap = TABLEAU_COLORS 

5 

6 

7def merge_descriptions(descA, descB): 

8 """ 

9 Merge two dictionaries that may contain dictionaries, which happens when merging descriptions, for instance. 

10 

11 Keys that occur in both dictionaries will be overwritten by the ones from `descB` and `descA` will be modified, not 

12 copied! 

13 

14 Args: 

15 descA (dict): Dictionary that you want to merge into 

16 descB (dict): Dictionary you want to merge from 

17 

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 

27 

28 

29class Strategy: 

30 ''' 

31 Abstract class for resilience strategies 

32 ''' 

33 

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 

40 

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] 

47 

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 ) 

59 

60 self.stop_at_nan = stop_at_nan 

61 

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'] = {} 

69 

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 ] 

85 

86 # stuff for work-precision diagrams 

87 self.precision_parameter = None 

88 self.precision_parameter_loc = [] 

89 

90 def __str__(self): 

91 return self.name 

92 

93 def get_controller_params(self, **kwargs): 

94 return {'all_to_done': False} 

95 

96 def get_description_for_tolerance(self, problem, param, **kwargs): 

97 return {} 

98 

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 

103 

104 Returns: 

105 list: Dictionary of parameters 

106 """ 

107 return self.fixable 

108 

109 def get_fault_args(self, problem, num_procs): 

110 ''' 

111 Routine to get arguments for the faults that are exempt from randomization 

112 

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 

116 

117 Returns: 

118 dict: Arguments for the faults that are exempt from randomization 

119 ''' 

120 args = {} 

121 args['target'] = 0 

122 

123 if problem.__name__ == "run_vdp": 

124 args['time'] = 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 

136 return args 

137 

138 def get_random_params(self, problem, num_procs): 

139 ''' 

140 Routine to get parameters for the randomization of faults 

141 

142 Args: 

143 problem: A function that runs a pySDC problem, see imports for available problems 

144 num_procs (int): Number of processes you intend to run with 

145 

146 Returns: 

147 dict: Randomization parameters 

148 ''' 

149 base_params = self.get_base_parameters(problem, num_procs) 

150 

151 rnd_params = {} 

152 rnd_params['iteration'] = base_params['step_params']['maxiter'] 

153 rnd_params['rank'] = num_procs 

154 

155 if problem.__name__ in ['run_Schroedinger', 'run_quench', 'run_AC', 'run_RBC']: 

156 rnd_params['min_node'] = 1 

157 

158 if problem.__name__ == "run_quench": 

159 rnd_params['iteration'] = 5 

160 elif problem.__name__ == 'run_Lorenz': 

161 rnd_params['iteration'] = 5 

162 elif problem.__name__ == 'run_RBC': 

163 rnd_params['problem_pos'] = [3, 16, 16] 

164 

165 return rnd_params 

166 

167 @property 

168 def style(self): 

169 """ 

170 Get the plotting parameters for the strategy. 

171 Supply them to a plotting function using `**` 

172 

173 Returns: 

174 (dict): The plotting parameters as a dictionary 

175 """ 

176 return { 

177 'marker': self.marker, 

178 'label': self.label, 

179 'color': self.color, 

180 'ls': self.linestyle, 

181 } 

182 

183 @property 

184 def label(self): 

185 """ 

186 Get a label for plotting 

187 """ 

188 return self.name 

189 

190 @classmethod 

191 def get_Tend(cls, problem, num_procs=1): 

192 ''' 

193 Get the final time of runs for fault stats based on the problem 

194 

195 Args: 

196 problem (function): A problem to run 

197 num_procs (int): Number of processes 

198 

199 Returns: 

200 float: Tend to put into the run 

201 ''' 

202 if problem.__name__ == "run_vdp": 

203 return 20 # 11.5 

204 elif problem.__name__ == "run_piline": 

205 return 20.0 

206 elif problem.__name__ == "run_Lorenz": 

207 return 20 

208 elif problem.__name__ == "run_Schroedinger": 

209 return 1.0 

210 elif problem.__name__ == "run_quench": 

211 return 500.0 

212 elif problem.__name__ == "run_AC": 

213 return 0.025 

214 elif problem.__name__ == "run_RBC": 

215 return 21 

216 else: 

217 raise NotImplementedError('I don\'t have a final time for your problem!') 

218 

219 def get_base_parameters(self, problem, num_procs=1): 

220 ''' 

221 Get a base parameters for the problems independent of the strategy. 

222 

223 Args: 

224 problem (function): A problem to run 

225 num_procs (int): Number of processes 

226 

227 Returns: 

228 dict: Custom description 

229 ''' 

230 from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeLimiter 

231 

232 custom_description = {} 

233 custom_description['step_params'] = {} 

234 custom_description['level_params'] = {} 

235 custom_description['problem_params'] = {} 

236 

237 if problem.__name__ == "run_vdp": 

238 custom_description['step_params'] = {'maxiter': 3} 

239 custom_description['problem_params'] = { 

240 'u0': np.array([1.1, 0], dtype=np.float64), 

241 'mu': 1000, 

242 'crash_at_maxiter': False, 

243 'newton_tol': 1e-11, 

244 'stop_at_nan': False, 

245 } 

246 custom_description['level_params'] = {'dt': 1e-4} 

247 

248 elif problem.__name__ == "run_Lorenz": 

249 custom_description['step_params'] = {'maxiter': 5} 

250 custom_description['level_params'] = {'dt': 1e-3} 

251 custom_description['problem_params'] = {'stop_at_nan': False} 

252 elif problem.__name__ == "run_Schroedinger": 

253 custom_description['step_params'] = {'maxiter': 5} 

254 custom_description['level_params'] = {'dt': 1e-2, 'restol': -1} 

255 custom_description['problem_params']['nvars'] = (256, 256) 

256 elif problem.__name__ == "run_quench": 

257 custom_description['level_params'] = {'restol': -1, 'dt': 8.0} 

258 custom_description['step_params'] = {'maxiter': 5} 

259 custom_description['problem_params'] = { 

260 'newton_maxiter': 29, 

261 'newton_tol': 1e-7, 

262 'nvars': 2**6, 

263 'direct_solver': False, 

264 'lintol': 1e-8, 

265 'liniter': 29, 

266 'order': 6, 

267 } 

268 elif problem.__name__ == "run_AC": 

269 eps = 4e-2 

270 custom_description['step_params'] = {'maxiter': 5} 

271 custom_description['problem_params'] = { 

272 'nvars': (128,) * 2, 

273 'init_type': 'circle', 

274 'eps': eps, 

275 'radius': 0.25, 

276 'nu': 2, 

277 } 

278 custom_description['level_params'] = {'restol': -1, 'dt': 0.1 * eps**2} 

279 elif problem.__name__ == 'run_RBC': 

280 custom_description['level_params']['dt'] = 5e-2 

281 custom_description['step_params'] = {'maxiter': 5} 

282 

283 custom_description['convergence_controllers'] = { 

284 # StepSizeLimiter: {'dt_min': self.get_Tend(problem=problem, num_procs=num_procs) / self.max_steps} 

285 } 

286 

287 if self.stop_at_nan: 

288 from pySDC.implementations.convergence_controller_classes.crash import StopAtNan 

289 

290 custom_description['convergence_controllers'][StopAtNan] = {'thresh': 1e20} 

291 

292 from pySDC.implementations.convergence_controller_classes.crash import StopAtMaxRuntime 

293 

294 max_runtime = { 

295 'run_vdp': 1000, 

296 'run_Lorenz': 500, 

297 'run_Schroedinger': 150, 

298 'run_quench': 150, 

299 'run_AC': 150, 

300 'run_RBC': 1000, 

301 } 

302 

303 custom_description['convergence_controllers'][StopAtMaxRuntime] = { 

304 'max_runtime': max_runtime.get(problem.__name__, 100) 

305 } 

306 return custom_description 

307 

308 def get_custom_description(self, problem, num_procs=1): 

309 ''' 

310 Get a custom description based on the problem 

311 

312 Args: 

313 problem (function): A problem to run 

314 num_procs (int): Number of processes 

315 

316 Returns: 

317 dict: Custom description 

318 ''' 

319 custom_description = self.get_base_parameters(problem, num_procs) 

320 return merge_descriptions(custom_description, self.custom_description) 

321 

322 def get_custom_description_for_faults(self, *args, **kwargs): 

323 ''' 

324 Get a custom description based on the problem to run the fault stuff 

325 

326 Returns: 

327 dict: Custom description 

328 ''' 

329 return self.get_custom_description(*args, **kwargs) 

330 

331 def get_reference_value(self, problem, key, op, num_procs=1): 

332 """ 

333 Get a reference value for a given problem for testing in CI. 

334 

335 Args: 

336 problem: A function that runs a pySDC problem, see imports for available problems 

337 key (str): The name of the variable you want to compare 

338 op (function): The operation you want to apply to the data 

339 num_procs (int): Number of processes 

340 

341 Returns: 

342 The reference value 

343 """ 

344 raise NotImplementedError( 

345 f'The reference value you are looking for is not implemented for {type(self).__name__} strategy!' 

346 ) 

347 

348 

349class InexactBaseStrategy(Strategy): 

350 """ 

351 Base class for inexact strategies. 

352 """ 

353 

354 def __init__( 

355 self, double_adaptivity=False, newton_inexactness=True, linear_inexactness=True, SDC_maxiter=16, **kwargs 

356 ): 

357 kwargs = {**kwargs, 'skip_residual_computation': 'most'} 

358 super().__init__(**kwargs) 

359 self.double_adaptivity = double_adaptivity 

360 self.newton_inexactness = newton_inexactness 

361 self.linear_inexactness = linear_inexactness 

362 self.SDC_maxiter = SDC_maxiter 

363 

364 def get_controller_params(self, **kwargs): 

365 return {'all_to_done': True} 

366 

367 def get_custom_description(self, problem, num_procs=1): 

368 from pySDC.implementations.convergence_controller_classes.inexactness import NewtonInexactness 

369 

370 preconditioner = 'MIN-SR-NS' if problem.__name__ in ['run_Lorenz'] else 'MIN-SR-S' 

371 

372 desc = {} 

373 desc['sweeper_params'] = {'QI': preconditioner} 

374 desc['step_params'] = {'maxiter': self.SDC_maxiter} 

375 desc['problem_params'] = {} 

376 desc['level_params'] = {'restol': 1e-8, 'residual_type': 'last_abs'} 

377 desc['convergence_controllers'] = {} 

378 

379 inexactness_params = { 

380 'min_tol': 1e-12, 

381 'ratio': 1e-2, 

382 'max_tol': 1e-4, 

383 'use_e_tol': False, 

384 'maxiter': 15, 

385 } 

386 

387 if self.newton_inexactness and problem.__name__ not in ['run_Schroedinger', 'run_AC', 'run_RBC']: 

388 if problem.__name__ == 'run_quench': 

389 inexactness_params['ratio'] = 1e-1 

390 inexactness_params['min_tol'] = 1e-11 

391 inexactness_params['maxiter'] = 5 

392 elif problem.__name__ == "run_vdp": 

393 inexactness_params['ratio'] = 1e-5 

394 inexactness_params['min_tol'] = 1e-15 

395 inexactness_params['maxiter'] = 9 

396 desc['convergence_controllers'][NewtonInexactness] = inexactness_params 

397 

398 if problem.__name__ in ['run_vdp']: 

399 desc['problem_params']['stop_at_nan'] = False 

400 

401 if self.linear_inexactness and problem.__name__ in ['run_quench']: 

402 desc['problem_params']['inexact_linear_ratio'] = 1e-1 

403 if problem.__name__ in ['run_quench']: 

404 desc['problem_params']['direct_solver'] = False 

405 desc['problem_params']['liniter'] = 9 

406 desc['problem_params']['min_lintol'] = 1e-11 

407 

408 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting 

409 

410 desc['convergence_controllers'][BasicRestarting.get_implementation(useMPI=self.useMPI)] = { 

411 'max_restarts': 29, 

412 'crash_after_max_restarts': True, 

413 } 

414 return merge_descriptions(super().get_custom_description(problem, num_procs), desc) 

415 

416 

417class BaseStrategy(Strategy): 

418 ''' 

419 Do a fixed iteration count 

420 ''' 

421 

422 def __init__(self, skip_residual_computation='all', **kwargs): 

423 ''' 

424 Initialization routine 

425 ''' 

426 super().__init__(skip_residual_computation=skip_residual_computation, **kwargs) 

427 self.color = list(cmap.values())[0] 

428 self.marker = 'o' 

429 self.name = 'base' 

430 self.bar_plot_x_label = 'base' 

431 self.precision_parameter = 'dt' 

432 self.precision_parameter_loc = ['level_params', 'dt'] 

433 

434 @property 

435 def label(self): 

436 return r'fixed' 

437 

438 def get_custom_description(self, problem, num_procs): 

439 desc = super().get_custom_description(problem, num_procs) 

440 if problem.__name__ == "run_AC": 

441 desc['level_params']['dt'] = 1e-2 * desc['problem_params']['eps'] ** 2 

442 return desc 

443 

444 def get_custom_description_for_faults(self, problem, *args, **kwargs): 

445 desc = self.get_custom_description(problem, *args, **kwargs) 

446 if problem.__name__ == "run_quench": 

447 desc['level_params']['dt'] = 5.0 

448 elif problem.__name__ == "run_AC": 

449 desc['level_params']['dt'] = 8e-5 

450 return desc 

451 

452 def get_reference_value(self, problem, key, op, num_procs=1): 

453 """ 

454 Get a reference value for a given problem for testing in CI. 

455 

456 Args: 

457 problem: A function that runs a pySDC problem, see imports for available problems 

458 key (str): The name of the variable you want to compare 

459 op (function): The operation you want to apply to the data 

460 num_procs (int): Number of processes 

461 

462 Returns: 

463 The reference value 

464 """ 

465 if problem.__name__ == "run_Lorenz": 

466 if key == 'work_newton' and op == sum: 

467 return 12350 

468 elif key == 'e_global_post_run' and op == max: 

469 return 1.3527453646133836e-07 

470 

471 super().get_reference_value(problem, key, op, num_procs) 

472 

473 

474class AdaptivityStrategy(Strategy): 

475 ''' 

476 Adaptivity as a resilience strategy 

477 ''' 

478 

479 def __init__(self, **kwargs): 

480 ''' 

481 Initialization routine 

482 ''' 

483 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity 

484 

485 kwargs['skip_residual_computation'] = 'all' 

486 super().__init__(**kwargs) 

487 self.color = list(cmap.values())[1] 

488 self.marker = '*' 

489 self.name = 'adaptivity' 

490 self.bar_plot_x_label = 'adaptivity' 

491 self.precision_parameter = 'e_tol' 

492 self.precision_parameter_loc = ['convergence_controllers', Adaptivity, 'e_tol'] 

493 

494 @property 

495 def label(self): 

496 return r'$\Delta t$-adaptivity' 

497 

498 def get_fixable_params(self, maxiter, **kwargs): 

499 """ 

500 Here faults occurring in the last iteration cannot be fixed. 

501 

502 Args: 

503 maxiter (int): Max. iterations until convergence is declared 

504 

505 Returns: 

506 (list): Contains dictionaries of keyword arguments for `FaultStats.get_mask` 

507 """ 

508 self.fixable += [ 

509 { 

510 'key': 'iteration', 

511 'op': 'lt', 

512 'val': maxiter, 

513 } 

514 ] 

515 return self.fixable 

516 

517 def get_custom_description(self, problem, num_procs): 

518 ''' 

519 Routine to get a custom description that adds adaptivity 

520 

521 Args: 

522 problem: A function that runs a pySDC problem, see imports for available problems 

523 num_procs (int): Number of processes you intend to run with 

524 

525 Returns: 

526 The custom descriptions you can supply to the problem when running it 

527 ''' 

528 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity 

529 from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeLimiter 

530 

531 base_params = super().get_custom_description(problem, num_procs) 

532 custom_description = {} 

533 custom_description['convergence_controllers'] = {} 

534 

535 dt_max = np.inf 

536 dt_slope_max = np.inf 

537 dt_slope_min = 0 

538 

539 if problem.__name__ == "run_piline": 

540 e_tol = 1e-7 

541 elif problem.__name__ == "run_vdp": 

542 e_tol = 2e-5 

543 elif problem.__name__ == "run_Lorenz": 

544 e_tol = 1e-7 

545 elif problem.__name__ == "run_Schroedinger": 

546 e_tol = 4e-7 

547 elif problem.__name__ == "run_quench": 

548 e_tol = 1e-8 

549 custom_description['problem_params'] = { 

550 'newton_tol': 1e-10, 

551 'lintol': 1e-11, 

552 } 

553 

554 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting 

555 

556 custom_description['convergence_controllers'][BasicRestarting.get_implementation(useMPI=self.useMPI)] = { 

557 'max_restarts': 99, 

558 } 

559 elif problem.__name__ == "run_AC": 

560 e_tol = 1e-7 

561 # dt_max = 0.1 * base_params['problem_params']['eps'] ** 2 

562 elif problem.__name__ == 'run_RBC': 

563 e_tol = 1e-4 

564 dt_slope_min = 1 

565 

566 else: 

567 raise NotImplementedError( 

568 'I don\'t have a tolerance for adaptivity for your problem. Please add one to the\ 

569 strategy' 

570 ) 

571 

572 custom_description['convergence_controllers'][Adaptivity] = { 

573 'e_tol': e_tol, 

574 'dt_slope_max': dt_slope_max, 

575 'dt_rel_min_slope': dt_slope_min, 

576 } 

577 custom_description['convergence_controllers'][StepSizeLimiter] = { 

578 'dt_max': dt_max, 

579 } 

580 return merge_descriptions(base_params, custom_description) 

581 

582 def get_reference_value(self, problem, key, op, num_procs=1): 

583 """ 

584 Get a reference value for a given problem for testing in CI. 

585 

586 Args: 

587 problem: A function that runs a pySDC problem, see imports for available problems 

588 key (str): The name of the variable you want to compare 

589 op (function): The operation you want to apply to the data 

590 num_procs (int): Number of processes 

591 

592 Returns: 

593 The reference value 

594 """ 

595 if problem.__name__ == 'run_Lorenz': 

596 if key == 'work_newton' and op == sum: 

597 return 2989 

598 elif key == 'e_global_post_run' and op == max: 

599 return 5.636767497207984e-08 

600 

601 super().get_reference_value(problem, key, op, num_procs) 

602 

603 def get_custom_description_for_faults(self, problem, num_procs, *args, **kwargs): 

604 from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeLimiter 

605 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity 

606 

607 desc = self.get_custom_description(problem, num_procs, *args, **kwargs) 

608 if problem.__name__ == "run_quench": 

609 desc['level_params']['dt'] = 1.1e1 

610 desc['convergence_controllers'][Adaptivity]['e_tol'] = 1e-6 

611 elif problem.__name__ == "run_AC": 

612 desc['convergence_controllers'][Adaptivity]['e_tol'] = 1e-5 

613 return desc 

614 

615 

616class AdaptivityRestartFirstStep(AdaptivityStrategy): 

617 def __init__(self, **kwargs): 

618 super().__init__(**kwargs) 

619 self.color = 'teal' 

620 self.name = 'adaptivityRestartFirstStep' 

621 

622 def get_custom_description(self, problem, num_procs): 

623 ''' 

624 Add the other version of basic restarting. 

625 

626 Args: 

627 problem: A function that runs a pySDC problem, see imports for available problems 

628 num_procs (int): Number of processes you intend to run with 

629 

630 Returns: 

631 The custom descriptions you can supply to the problem when running it 

632 ''' 

633 custom_description = super().get_custom_description(problem, num_procs) 

634 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting 

635 

636 custom_description['convergence_controllers'][BasicRestarting.get_implementation(useMPI=self.useMPI)] = { 

637 'max_restarts': 15, 

638 'restart_from_first_step': True, 

639 } 

640 return custom_description 

641 

642 @property 

643 def label(self): 

644 return f'{super().label} restart from first step' 

645 

646 

647class AdaptiveHotRodStrategy(Strategy): 

648 ''' 

649 Adaptivity + Hot Rod as a resilience strategy 

650 ''' 

651 

652 def __init__(self, **kwargs): 

653 ''' 

654 Initialization routine 

655 ''' 

656 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity 

657 

658 kwargs['skip_residual_computation'] = 'all' 

659 super().__init__(**kwargs) 

660 self.color = list(cmap.values())[4] 

661 self.marker = '.' 

662 self.name = 'adaptive Hot Rod' 

663 self.bar_plot_x_label = 'adaptive\nHot Rod' 

664 self.precision_parameter = 'e_tol' 

665 self.precision_parameter_loc = ['convergence_controllers', Adaptivity, 'e_tol'] 

666 

667 def get_custom_description(self, problem, num_procs): 

668 ''' 

669 Routine to get a custom description that adds adaptivity and Hot Rod 

670 

671 Args: 

672 problem: A function that runs a pySDC problem, see imports for available problems 

673 num_procs (int): Number of processes you intend to run with 

674 

675 Returns: 

676 The custom description you can supply to the problem when running it 

677 ''' 

678 from pySDC.implementations.convergence_controller_classes.hotrod import HotRod 

679 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity 

680 

681 if problem.__name__ == "run_vdp": 

682 e_tol = 3e-7 

683 dt_min = 1e-3 

684 maxiter = 4 

685 HotRod_tol = 2e-6 

686 elif problem.__name__ == "run_Lorenz": 

687 e_tol = 3e-7 

688 dt_min = 1e-3 

689 maxiter = 4 

690 HotRod_tol = 2e-6 

691 else: 

692 raise NotImplementedError( 

693 'I don\'t have a tolerance for adaptive Hot Rod for your problem. Please add one \ 

694to the strategy' 

695 ) 

696 

697 no_storage = num_procs > 1 

698 

699 custom_description = { 

700 'convergence_controllers': { 

701 HotRod: {'HotRod_tol': HotRod_tol, 'no_storage': no_storage}, 

702 Adaptivity: {'e_tol': e_tol, 'dt_min': dt_min, 'embedded_error_flavor': 'linearized'}, 

703 }, 

704 'step_params': {'maxiter': maxiter}, 

705 } 

706 

707 return merge_descriptions(super().get_custom_description(problem, num_procs), custom_description) 

708 

709 def get_reference_value(self, problem, key, op, num_procs=1): 

710 """ 

711 Get a reference value for a given problem for testing in CI. 

712 

713 Args: 

714 problem: A function that runs a pySDC problem, see imports for available problems 

715 key (str): The name of the variable you want to compare 

716 op (function): The operation you want to apply to the data 

717 num_procs (int): Number of processes 

718 

719 Returns: 

720 The reference value 

721 """ 

722 if problem.__name__ == "run_Lorenz": 

723 if key == 'work_newton' and op == sum: 

724 return 5092 

725 elif key == 'e_global_post_run' and op == max: 

726 return 4.107116318152748e-06 

727 

728 super().get_reference_value(problem, key, op, num_procs) 

729 

730 

731class IterateStrategy(Strategy): 

732 ''' 

733 Iterate for as much as you want 

734 ''' 

735 

736 def __init__(self, **kwargs): 

737 ''' 

738 Initialization routine 

739 ''' 

740 kwargs['skip_residual_computation'] = 'most' 

741 super().__init__(**kwargs) 

742 self.color = list(cmap.values())[2] 

743 self.marker = 'v' 

744 self.name = 'iterate' 

745 self.bar_plot_x_label = 'iterate' 

746 self.precision_parameter = 'restol' 

747 self.precision_parameter_loc = ['level_params', 'restol'] 

748 

749 @property 

750 def label(self): 

751 return r'$k$-adaptivity' 

752 

753 def get_custom_description(self, problem, num_procs): 

754 ''' 

755 Routine to get a custom description that allows for adaptive iteration counts 

756 

757 Args: 

758 problem: A function that runs a pySDC problem, see imports for available problems 

759 num_procs (int): Number of processes you intend to run with 

760 

761 Returns: 

762 The custom description you can supply to the problem when running it 

763 ''' 

764 restol = -1 

765 e_tol = -1 

766 

767 if problem.__name__ == "run_piline": 

768 restol = 2.3e-8 

769 elif problem.__name__ == "run_vdp": 

770 restol = 9e-7 

771 elif problem.__name__ == "run_Lorenz": 

772 restol = 16e-7 

773 elif problem.__name__ == "run_Schroedinger": 

774 restol = 6.5e-7 

775 elif problem.__name__ == "run_quench": 

776 restol = 1e-7 

777 elif problem.__name__ == "run_AC": 

778 restol = 1e-11 

779 elif problem.__name__ == "run_RBC": 

780 restol = 1e-4 

781 else: 

782 raise NotImplementedError( 

783 'I don\'t have a residual tolerance for your problem. Please add one to the \ 

784strategy' 

785 ) 

786 

787 custom_description = { 

788 'step_params': {'maxiter': 99}, 

789 'level_params': {'restol': restol, 'e_tol': e_tol}, 

790 } 

791 

792 if problem.__name__ == "run_quench": 

793 custom_description['level_params']['dt'] = 1.0 

794 

795 return merge_descriptions(super().get_custom_description(problem, num_procs), custom_description) 

796 

797 def get_random_params(self, problem, num_procs): 

798 ''' 

799 Routine to get parameters for the randomization of faults 

800 

801 Args: 

802 problem: A function that runs a pySDC problem, see imports for available problems 

803 num_procs (int): Number of processes you intend to run with 

804 

805 Returns: 

806 dict: Randomization parameters 

807 ''' 

808 

809 rnd_params = super().get_random_params(problem, num_procs) 

810 if problem.__name__ == "run_quench": 

811 rnd_params['iteration'] = 1 

812 return rnd_params 

813 

814 def get_reference_value(self, problem, key, op, num_procs=1): 

815 """ 

816 Get a reference value for a given problem for testing in CI. 

817 

818 Args: 

819 problem: A function that runs a pySDC problem, see imports for available problems 

820 key (str): The name of the variable you want to compare 

821 op (function): The operation you want to apply to the data 

822 num_procs (int): Number of processes 

823 

824 Returns: 

825 The reference value 

826 """ 

827 if problem.__name__ == "run_Lorenz": 

828 if key == 'work_newton' and op == sum: 

829 return 9200 

830 elif key == 'e_global_post_run' and op == max: 

831 return 2.139863344829962e-05 

832 

833 super().get_reference_value(problem, key, op, num_procs) 

834 

835 

836class kAdaptivityStrategy(IterateStrategy): 

837 def __init__(self, **kwargs): 

838 super().__init__(**kwargs) 

839 self.precision_parameter = 'dt' 

840 self.precision_parameter_loc = ['level_params', 'dt'] 

841 

842 def get_custom_description(self, problem, num_procs, *args, **kwargs): 

843 desc = super().get_custom_description(problem, num_procs, *args, **kwargs) 

844 desc['level_params']['restol'] = 1e-9 

845 if problem.__name__ == "run_quench": 

846 desc['problem_params']['newton_tol'] = 1e-9 

847 desc['problem_params']['lintol'] = 1e-9 

848 desc['level_params']['dt'] = 2.5 

849 elif problem.__name__ == "run_AC": 

850 desc['level_params']['restol'] = 1e-11 

851 desc['level_params']['dt'] = 0.4 * desc['problem_params']['eps'] ** 2 / 8.0 

852 elif problem.__name__ == "run_RBC": 

853 desc['level_params']['dt'] = 7e-2 

854 desc['level_params']['restol'] = 1e-9 

855 return desc 

856 

857 def get_custom_description_for_faults(self, problem, *args, **kwargs): 

858 desc = self.get_custom_description(problem, *args, **kwargs) 

859 if problem.__name__ == 'run_quench': 

860 desc['level_params']['dt'] = 5.0 

861 elif problem.__name__ == 'run_AC': 

862 desc['level_params']['dt'] = 5e-4 

863 elif problem.__name__ == 'run_RBC': 

864 desc['level_params']['restol'] = 1e-6 

865 return desc 

866 

867 def get_reference_value(self, problem, key, op, num_procs=1): 

868 """ 

869 Get a reference value for a given problem for testing in CI. 

870 

871 Args: 

872 problem: A function that runs a pySDC problem, see imports for available problems 

873 key (str): The name of the variable you want to compare 

874 op (function): The operation you want to apply to the data 

875 num_procs (int): Number of processes 

876 

877 Returns: 

878 The reference value 

879 """ 

880 if problem.__name__ == "run_Lorenz": 

881 if key == 'work_newton' and op == sum: 

882 return 12350 

883 elif key == 'e_global_post_run' and op == max: 

884 return 1.3527453646133836e-07 

885 

886 super().get_reference_value(problem, key, op, num_procs) 

887 

888 

889class HotRodStrategy(Strategy): 

890 ''' 

891 Hot Rod as a resilience strategy 

892 ''' 

893 

894 def __init__(self, **kwargs): 

895 ''' 

896 Initialization routine 

897 ''' 

898 kwargs['skip_residual_computation'] = 'all' 

899 super().__init__(**kwargs) 

900 self.color = list(cmap.values())[3] 

901 self.marker = '^' 

902 self.name = 'Hot Rod' 

903 self.bar_plot_x_label = 'Hot Rod' 

904 self.precision_parameter = 'dt' 

905 self.precision_parameter_loc = ['level_params', 'dt'] 

906 

907 def get_custom_description(self, problem, num_procs): 

908 ''' 

909 Routine to get a custom description that adds Hot Rod 

910 

911 Args: 

912 problem: A function that runs a pySDC problem, see imports for available problems 

913 num_procs (int): Number of processes you intend to run with 

914 

915 Returns: 

916 The custom description you can supply to the problem when running it 

917 ''' 

918 from pySDC.implementations.convergence_controller_classes.hotrod import HotRod 

919 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestartingNonMPI 

920 

921 base_params = super().get_custom_description(problem, num_procs) 

922 if problem.__name__ == "run_vdp": 

923 if num_procs == 4: 

924 HotRod_tol = 1.800804e-04 

925 elif num_procs == 5: 

926 HotRod_tol = 9.329361e-05 

927 else: # 1 process 

928 HotRod_tol = 1.347949e-06 

929 HotRod_tol = 7e-6 if num_procs > 1 else 5e-7 

930 maxiter = 4 

931 elif problem.__name__ == "run_Lorenz": 

932 if num_procs == 5: 

933 HotRod_tol = 9.539348e-06 

934 elif num_procs == 4: 

935 HotRod_tol = 3.201e-6 

936 else: 

937 HotRod_tol = 7.720589e-07 

938 maxiter = 6 

939 elif problem.__name__ == "run_Schroedinger": 

940 if num_procs == 5: 

941 HotRod_tol = 2.497697e-06 

942 elif num_procs == 4: 

943 HotRod_tol = 1.910405e-06 

944 else: 

945 HotRod_tol = 4.476790e-07 

946 maxiter = 6 

947 elif problem.__name__ == "run_quench": 

948 if num_procs == 5: 

949 HotRod_tol = 1.017534e-03 

950 elif num_procs == 4: 

951 HotRod_tol = 1.017534e-03 

952 else: 

953 HotRod_tol = 5.198620e-04 

954 maxiter = 6 

955 elif problem.__name__ == 'run_AC': 

956 HotRod_tol = 9.564437e-06 

957 maxiter = 6 

958 elif problem.__name__ == 'run_RBC': 

959 HotRod_tol = 6.34e-6 

960 maxiter = 6 

961 else: 

962 raise NotImplementedError( 

963 'I don\'t have a tolerance for Hot Rod for your problem. Please add one to the\ 

964 strategy' 

965 ) 

966 

967 no_storage = False # num_procs > 1 

968 

969 custom_description = { 

970 'convergence_controllers': { 

971 HotRod: {'HotRod_tol': HotRod_tol, 'no_storage': no_storage}, 

972 BasicRestartingNonMPI: { 

973 'max_restarts': 2, 

974 'crash_after_max_restarts': False, 

975 'restart_from_first_step': True, 

976 }, 

977 }, 

978 'step_params': {'maxiter': maxiter}, 

979 'level_params': {}, 

980 } 

981 if problem.__name__ == "run_AC": 

982 custom_description['level_params']['dt'] = 8e-5 

983 return merge_descriptions(base_params, custom_description) 

984 

985 def get_custom_description_for_faults(self, problem, *args, **kwargs): 

986 desc = self.get_custom_description(problem, *args, **kwargs) 

987 if problem.__name__ == "run_quench": 

988 desc['level_params']['dt'] = 5.0 

989 return desc 

990 

991 def get_reference_value(self, problem, key, op, num_procs=1): 

992 """ 

993 Get a reference value for a given problem for testing in CI. 

994 

995 Args: 

996 problem: A function that runs a pySDC problem, see imports for available problems 

997 key (str): The name of the variable you want to compare 

998 op (function): The operation you want to apply to the data 

999 num_procs (int): Number of processes 

1000 

1001 Returns: 

1002 The reference value 

1003 """ 

1004 if problem.__name__ == "run_Lorenz": 

1005 if key == 'work_newton' and op == sum: 

1006 return 12350 

1007 elif key == 'e_global_post_run' and op == max: 

1008 return 1.3527453646133836e-07 

1009 

1010 super().get_reference_value(problem, key, op, num_procs) 

1011 

1012 

1013class AdaptivityCollocationStrategy(InexactBaseStrategy): 

1014 ''' 

1015 Adaptivity based on collocation as a resilience strategy 

1016 ''' 

1017 

1018 def __init__(self, **kwargs): 

1019 ''' 

1020 Initialization routine 

1021 ''' 

1022 kwargs = { 

1023 'skip_residual_computation': 'most', 

1024 **kwargs, 

1025 } 

1026 

1027 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityCollocation 

1028 

1029 self.restol = None 

1030 super().__init__(**kwargs) 

1031 self.color = list(cmap.values())[1] 

1032 self.marker = '*' 

1033 self.name = 'adaptivity_coll' 

1034 self.bar_plot_x_label = 'adaptivity collocation' 

1035 self.precision_parameter = 'e_tol' 

1036 self.adaptive_coll_params = {} 

1037 self.precision_parameter_loc = ['convergence_controllers', AdaptivityCollocation, 'e_tol'] 

1038 

1039 def get_custom_description(self, problem, num_procs): 

1040 ''' 

1041 Routine to get a custom description that adds adaptivity 

1042 

1043 Args: 

1044 problem: A function that runs a pySDC problem, see imports for available problems 

1045 num_procs (int): Number of processes you intend to run with 

1046 

1047 Returns: 

1048 The custom descriptions you can supply to the problem when running it 

1049 ''' 

1050 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityCollocation 

1051 

1052 custom_description = {} 

1053 

1054 dt_max = np.inf 

1055 dt_min = 1e-5 

1056 

1057 if problem.__name__ == "run_piline": 

1058 e_tol = 1e-7 

1059 dt_min = 1e-2 

1060 elif problem.__name__ == "run_vdp": 

1061 e_tol = 2e-5 

1062 dt_min = 1e-3 

1063 elif problem.__name__ == "run_Lorenz": 

1064 e_tol = 2e-5 

1065 dt_min = 1e-3 

1066 elif problem.__name__ == "run_Schroedinger": 

1067 e_tol = 4e-6 

1068 dt_min = 1e-3 

1069 elif problem.__name__ == "run_quench": 

1070 e_tol = 1e-5 

1071 dt_min = 1e-3 

1072 dt_max = 1e2 

1073 elif problem.__name__ == "run_AC": 

1074 e_tol = 1e-4 

1075 else: 

1076 raise NotImplementedError( 

1077 'I don\'t have a tolerance for adaptivity for your problem. Please add one to the\ 

1078 strategy' 

1079 ) 

1080 

1081 custom_description['convergence_controllers'] = { 

1082 AdaptivityCollocation: { 

1083 'e_tol': e_tol, 

1084 'dt_min': dt_min, 

1085 'dt_max': dt_max, 

1086 'adaptive_coll_params': self.adaptive_coll_params, 

1087 'restol_rel': 1e-2, 

1088 } 

1089 } 

1090 return merge_descriptions(super().get_custom_description(problem, num_procs), custom_description) 

1091 

1092 

1093class AdaptivityCollocationTypeStrategy(AdaptivityCollocationStrategy): 

1094 def __init__(self, **kwargs): 

1095 super().__init__(**kwargs) 

1096 self.color = list(cmap.values())[4] 

1097 self.marker = '.' 

1098 self.adaptive_coll_params = { 

1099 'quad_type': ['RADAU-RIGHT', 'GAUSS'], 

1100 'do_coll_update': [False, True], 

1101 } 

1102 

1103 @property 

1104 def label(self): 

1105 return 'adaptivity type' 

1106 

1107 def get_reference_value(self, problem, key, op, num_procs=1): 

1108 """ 

1109 Get a reference value for a given problem for testing in CI. 

1110 

1111 Args: 

1112 problem: A function that runs a pySDC problem, see imports for available problems 

1113 key (str): The name of the variable you want to compare 

1114 op (function): The operation you want to apply to the data 

1115 num_procs (int): Number of processes 

1116 

1117 Returns: 

1118 The reference value 

1119 """ 

1120 if problem.__name__ == "run_Lorenz": 

1121 if key == 'work_newton' and op == sum: 

1122 return 1025 

1123 elif key == 'e_global_post_run' and op == max: 

1124 return 4.266975256683736e-06 

1125 

1126 super().get_reference_value(problem, key, op, num_procs) 

1127 

1128 

1129class AdaptivityCollocationRefinementStrategy(AdaptivityCollocationStrategy): 

1130 def __init__(self, **kwargs): 

1131 super().__init__(**kwargs) 

1132 self.color = list(cmap.values())[5] 

1133 self.marker = '^' 

1134 self.adaptive_coll_params = { 

1135 'num_nodes': [2, 3], 

1136 'quad_type': ['GAUSS', 'RADAU-RIGHT'], 

1137 'do_coll_update': [True, False], 

1138 } 

1139 

1140 @property 

1141 def label(self): 

1142 return 'adaptivity refinement' 

1143 

1144 def get_reference_value(self, problem, key, op, num_procs=1): 

1145 """ 

1146 Get a reference value for a given problem for testing in CI. 

1147 

1148 Args: 

1149 problem: A function that runs a pySDC problem, see imports for available problems 

1150 key (str): The name of the variable you want to compare 

1151 op (function): The operation you want to apply to the data 

1152 num_procs (int): Number of processes 

1153 

1154 Returns: 

1155 The reference value 

1156 """ 

1157 if problem.__name__ == "run_Lorenz": 

1158 if key == 'work_newton' and op == sum: 

1159 return 917 

1160 elif key == 'e_global_post_run' and op == max: 

1161 return 1.0874929465387595e-05 

1162 

1163 super().get_reference_value(problem, key, op, num_procs) 

1164 

1165 

1166class AdaptivityCollocationDerefinementStrategy(AdaptivityCollocationStrategy): 

1167 def __init__(self, **kwargs): 

1168 super().__init__(**kwargs) 

1169 self.color = list(cmap.values())[6] 

1170 self.marker = '^' 

1171 self.adaptive_coll_params = {'num_nodes': [4, 3]} 

1172 

1173 @property 

1174 def label(self): 

1175 return 'adaptivity de-refinement' 

1176 

1177 def get_reference_value(self, problem, key, op, num_procs=1): 

1178 """ 

1179 Get a reference value for a given problem for testing in CI. 

1180 

1181 Args: 

1182 problem: A function that runs a pySDC problem, see imports for available problems 

1183 key (str): The name of the variable you want to compare 

1184 op (function): The operation you want to apply to the data 

1185 num_procs (int): Number of processes 

1186 

1187 Returns: 

1188 The reference value 

1189 """ 

1190 if problem.__name__ == 'run_Lorenz': 

1191 if key == 'work_newton' and op == sum: 

1192 return 1338 

1193 elif key == 'e_global_post_run' and op == max: 

1194 return 0.0001013999955041811 

1195 

1196 super().get_reference_value(problem, key, op, num_procs) 

1197 

1198 

1199class DIRKStrategy(AdaptivityStrategy): 

1200 ''' 

1201 DIRK4(3) 

1202 ''' 

1203 

1204 def __init__(self, **kwargs): 

1205 ''' 

1206 Initialization routine 

1207 ''' 

1208 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK 

1209 

1210 super().__init__(**kwargs) 

1211 self.color = list(cmap.values())[7] 

1212 self.marker = '^' 

1213 self.name = 'DIRK' 

1214 self.bar_plot_x_label = 'DIRK4(3)' 

1215 self.precision_parameter = 'e_tol' 

1216 self.precision_parameter_loc = ['convergence_controllers', AdaptivityRK, 'e_tol'] 

1217 self.max_steps = 1e5 

1218 

1219 @property 

1220 def label(self): 

1221 return 'DIRK4(3)' 

1222 

1223 def get_custom_description(self, problem, num_procs): 

1224 ''' 

1225 Routine to get a custom description that adds adaptivity 

1226 

1227 Args: 

1228 problem: A function that runs a pySDC problem, see imports for available problems 

1229 num_procs (int): Number of processes you intend to run with 

1230 

1231 Returns: 

1232 The custom descriptions you can supply to the problem when running it 

1233 ''' 

1234 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK, Adaptivity 

1235 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting 

1236 from pySDC.implementations.sweeper_classes.Runge_Kutta import DIRK43 

1237 

1238 adaptivity_description = super().get_custom_description(problem, num_procs) 

1239 

1240 e_tol = adaptivity_description['convergence_controllers'][Adaptivity]['e_tol'] 

1241 adaptivity_description['convergence_controllers'].pop(Adaptivity, None) 

1242 adaptivity_description.pop('sweeper_params', None) 

1243 

1244 rk_params = { 

1245 'step_params': {'maxiter': 1}, 

1246 'sweeper_class': DIRK43, 

1247 'convergence_controllers': { 

1248 AdaptivityRK: {'e_tol': e_tol}, 

1249 BasicRestarting.get_implementation(useMPI=self.useMPI): { 

1250 'max_restarts': 49, 

1251 'crash_after_max_restarts': False, 

1252 }, 

1253 }, 

1254 } 

1255 

1256 custom_description = merge_descriptions(adaptivity_description, rk_params) 

1257 

1258 return custom_description 

1259 

1260 def get_reference_value(self, problem, key, op, num_procs=1): 

1261 """ 

1262 Get a reference value for a given problem for testing in CI. 

1263 

1264 Args: 

1265 problem: A function that runs a pySDC problem, see imports for available problems 

1266 key (str): The name of the variable you want to compare 

1267 op (function): The operation you want to apply to the data 

1268 num_procs (int): Number of processes 

1269 

1270 Returns: 

1271 The reference value 

1272 """ 

1273 if problem.__name__ == "run_Lorenz": 

1274 if key == 'work_newton' and op == sum: 

1275 return 5467 

1276 elif key == 'e_global_post_run' and op == max: 

1277 return 7.049480537091313e-07 

1278 

1279 super().get_reference_value(problem, key, op, num_procs) 

1280 

1281 def get_random_params(self, problem, num_procs): 

1282 ''' 

1283 Routine to get parameters for the randomization of faults 

1284 

1285 Args: 

1286 problem: A function that runs a pySDC problem, see imports for available problems 

1287 num_procs (int): Number of processes you intend to run with 

1288 

1289 Returns: 

1290 dict: Randomization parameters 

1291 ''' 

1292 rnd_params = super().get_random_params(problem, num_procs) 

1293 rnd_params['iteration'] = 1 

1294 rnd_params['min_node'] = 5 

1295 

1296 return rnd_params 

1297 

1298 

1299class ARKStrategy(AdaptivityStrategy): 

1300 ''' 

1301 ARK5(4) 

1302 ''' 

1303 

1304 def __init__(self, **kwargs): 

1305 ''' 

1306 Initialization routine 

1307 ''' 

1308 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK 

1309 

1310 super().__init__(**kwargs) 

1311 self.color = list(cmap.values())[7] 

1312 self.marker = 'P' 

1313 self.name = 'ARK' 

1314 self.bar_plot_x_label = 'ARK5(4)' 

1315 self.precision_parameter = 'e_tol' 

1316 self.precision_parameter_loc = ['convergence_controllers', AdaptivityRK, 'e_tol'] 

1317 self.max_steps = 1e5 

1318 

1319 @property 

1320 def label(self): 

1321 return 'ARK5(4)' 

1322 

1323 def get_custom_description(self, problem, num_procs): 

1324 ''' 

1325 Routine to get a custom description that adds adaptivity 

1326 

1327 Args: 

1328 problem: A function that runs a pySDC problem, see imports for available problems 

1329 num_procs (int): Number of processes you intend to run with 

1330 

1331 Returns: 

1332 The custom descriptions you can supply to the problem when running it 

1333 ''' 

1334 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK, Adaptivity 

1335 from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeSlopeLimiter 

1336 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting 

1337 from pySDC.implementations.sweeper_classes.Runge_Kutta import ARK548L2SA 

1338 

1339 adaptivity_description = super().get_custom_description(problem, num_procs) 

1340 

1341 e_tol = adaptivity_description['convergence_controllers'][Adaptivity]['e_tol'] / 20.0 

1342 adaptivity_description['convergence_controllers'].pop(Adaptivity, None) 

1343 adaptivity_description.pop('sweeper_params', None) 

1344 

1345 rk_params = { 

1346 'step_params': {'maxiter': 1}, 

1347 'sweeper_class': ARK548L2SA, 

1348 'convergence_controllers': { 

1349 AdaptivityRK: {'e_tol': e_tol}, 

1350 BasicRestarting.get_implementation(useMPI=self.useMPI): { 

1351 'max_restarts': 49, 

1352 'crash_after_max_restarts': False, 

1353 }, 

1354 }, 

1355 } 

1356 

1357 if problem.__name__ == "run_RBC": 

1358 rk_params['convergence_controllers'][StepSizeSlopeLimiter] = {'dt_rel_min_slope': 0.25} 

1359 

1360 custom_description = merge_descriptions(adaptivity_description, rk_params) 

1361 

1362 return custom_description 

1363 

1364 def get_reference_value(self, problem, key, op, num_procs=1): 

1365 """ 

1366 Get a reference value for a given problem for testing in CI. 

1367 

1368 Args: 

1369 problem: A function that runs a pySDC problem, see imports for available problems 

1370 key (str): The name of the variable you want to compare 

1371 op (function): The operation you want to apply to the data 

1372 num_procs (int): Number of processes 

1373 

1374 Returns: 

1375 The reference value 

1376 """ 

1377 if problem.__name__ == "run_Schroedinger": 

1378 if key == 'work_newton' and op == sum: 

1379 return 0 

1380 elif key == 'e_global_post_run' and op == max: 

1381 return 3.1786601531890356e-08 

1382 

1383 super().get_reference_value(problem, key, op, num_procs) 

1384 

1385 

1386class ESDIRKStrategy(AdaptivityStrategy): 

1387 ''' 

1388 ESDIRK5(3) 

1389 ''' 

1390 

1391 def __init__(self, **kwargs): 

1392 ''' 

1393 Initialization routine 

1394 ''' 

1395 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK 

1396 

1397 super().__init__(**kwargs) 

1398 self.color = 'violet' 

1399 self.marker = '^' 

1400 self.name = 'ESDIRK' 

1401 self.bar_plot_x_label = 'ESDIRK5(3)' 

1402 self.precision_parameter = 'e_tol' 

1403 self.precision_parameter_loc = ['convergence_controllers', AdaptivityRK, 'e_tol'] 

1404 self.max_steps = 1e5 

1405 

1406 @property 

1407 def label(self): 

1408 return 'ESDIRK5(3)' 

1409 

1410 def get_description_for_tolerance(self, problem, param, **kwargs): 

1411 desc = {} 

1412 if problem.__name__ == 'run_Schroedinger': 

1413 desc['problem_params'] = {'lintol': param} 

1414 return desc 

1415 

1416 def get_custom_description(self, problem, num_procs): 

1417 ''' 

1418 Routine to get a custom description that adds adaptivity 

1419 

1420 Args: 

1421 problem: A function that runs a pySDC problem, see imports for available problems 

1422 num_procs (int): Number of processes you intend to run with 

1423 

1424 Returns: 

1425 The custom descriptions you can supply to the problem when running it 

1426 ''' 

1427 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityRK, Adaptivity 

1428 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting 

1429 from pySDC.implementations.sweeper_classes.Runge_Kutta import ESDIRK53 

1430 

1431 adaptivity_description = super().get_custom_description(problem, num_procs) 

1432 

1433 e_tol = adaptivity_description['convergence_controllers'][Adaptivity]['e_tol'] 

1434 adaptivity_description['convergence_controllers'].pop(Adaptivity, None) 

1435 adaptivity_description.pop('sweeper_params', None) 

1436 

1437 mod = 1e1 if problem.__name__ == 'run_quench' else 1.0 

1438 

1439 rk_params = { 

1440 'step_params': {'maxiter': 1}, 

1441 'sweeper_class': ESDIRK53, 

1442 'convergence_controllers': { 

1443 AdaptivityRK: {'e_tol': e_tol * mod}, 

1444 BasicRestarting.get_implementation(useMPI=self.useMPI): { 

1445 'max_restarts': 49, 

1446 'crash_after_max_restarts': False, 

1447 }, 

1448 }, 

1449 } 

1450 

1451 custom_description = merge_descriptions(adaptivity_description, rk_params) 

1452 

1453 return custom_description 

1454 

1455 def get_reference_value(self, problem, key, op, num_procs=1): 

1456 """ 

1457 Get a reference value for a given problem for testing in CI. 

1458 

1459 Args: 

1460 problem: A function that runs a pySDC problem, see imports for available problems 

1461 key (str): The name of the variable you want to compare 

1462 op (function): The operation you want to apply to the data 

1463 num_procs (int): Number of processes 

1464 

1465 Returns: 

1466 The reference value 

1467 """ 

1468 if problem.__name__ == "run_Lorenz": 

1469 if key == 'work_newton' and op == sum: 

1470 return 2963 

1471 elif key == 'e_global_post_run' and op == max: 

1472 return 4.126039954144289e-09 

1473 

1474 super().get_reference_value(problem, key, op, num_procs) 

1475 

1476 def get_random_params(self, problem, num_procs): 

1477 ''' 

1478 Routine to get parameters for the randomization of faults 

1479 

1480 Args: 

1481 problem: A function that runs a pySDC problem, see imports for available problems 

1482 num_procs (int): Number of processes you intend to run with 

1483 

1484 Returns: 

1485 dict: Randomization parameters 

1486 ''' 

1487 rnd_params = super().get_random_params(problem, num_procs) 

1488 rnd_params['iteration'] = 1 

1489 rnd_params['min_node'] = 6 

1490 

1491 return rnd_params 

1492 

1493 

1494class ERKStrategy(DIRKStrategy): 

1495 """ 

1496 Explicit embedded RK using Cash-Karp's method 

1497 """ 

1498 

1499 def __init__(self, **kwargs): 

1500 ''' 

1501 Initialization routine 

1502 ''' 

1503 super().__init__(**kwargs) 

1504 self.color = list(cmap.values())[8] 

1505 self.marker = 'x' 

1506 self.name = 'ERK' 

1507 self.bar_plot_x_label = 'ERK5(4)' 

1508 

1509 def get_description_for_tolerance(self, problem, param, **kwargs): 

1510 desc = {} 

1511 if problem.__name__ == 'run_Schroedinger': 

1512 desc['problem_params'] = {'lintol': param} 

1513 

1514 return desc 

1515 

1516 @property 

1517 def label(self): 

1518 return 'CP5(4)' 

1519 

1520 def get_random_params(self, problem, num_procs): 

1521 ''' 

1522 Routine to get parameters for the randomization of faults 

1523 

1524 Args: 

1525 problem: A function that runs a pySDC problem, see imports for available problems 

1526 num_procs (int): Number of processes you intend to run with 

1527 

1528 Returns: 

1529 dict: Randomization parameters 

1530 ''' 

1531 rnd_params = super().get_random_params(problem, num_procs) 

1532 rnd_params['min_node'] = 7 

1533 

1534 return rnd_params 

1535 

1536 def get_custom_description(self, problem, num_procs=1): 

1537 from pySDC.implementations.sweeper_classes.Runge_Kutta import Cash_Karp 

1538 

1539 desc = super().get_custom_description(problem, num_procs) 

1540 desc['sweeper_class'] = Cash_Karp 

1541 

1542 if problem.__name__ == "run_AC": 

1543 desc['level_params']['dt'] = 2e-5 

1544 return desc 

1545 

1546 def get_reference_value(self, problem, key, op, num_procs=1): 

1547 """ 

1548 Get a reference value for a given problem for testing in CI. 

1549 

1550 Args: 

1551 problem: A function that runs a pySDC problem, see imports for available problems 

1552 key (str): The name of the variable you want to compare 

1553 op (function): The operation you want to apply to the data 

1554 num_procs (int): Number of processes 

1555 

1556 Returns: 

1557 The reference value 

1558 """ 

1559 if problem.__name__ == "run_Lorenz": 

1560 if key == 'work_newton' and op == sum: 

1561 return 0 

1562 elif key == 'e_global_post_run' and op == max: 

1563 return 1.509206128957885e-07 

1564 

1565 super().get_reference_value(problem, key, op, num_procs) 

1566 

1567 

1568class DoubleAdaptivityStrategy(AdaptivityStrategy): 

1569 ''' 

1570 Adaptivity based both on embedded estimate and on residual 

1571 ''' 

1572 

1573 def __init__(self, **kwargs): 

1574 ''' 

1575 Initialization routine 

1576 ''' 

1577 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity 

1578 

1579 kwargs['skip_residual_computation'] = 'all' 

1580 super().__init__(**kwargs) 

1581 self.color = list(cmap.values())[7] 

1582 self.marker = '^' 

1583 self.name = 'double_adaptivity' 

1584 self.bar_plot_x_label = 'double adaptivity' 

1585 self.precision_parameter = 'e_tol' 

1586 self.precision_parameter_loc = ['convergence_controllers', Adaptivity, 'e_tol'] 

1587 self.residual_e_tol_ratio = 1.0 

1588 self.residual_e_tol_abs = None 

1589 

1590 @property 

1591 def label(self): 

1592 return 'double adaptivity' 

1593 

1594 def get_custom_description(self, problem, num_procs): 

1595 ''' 

1596 Routine to get a custom description that adds adaptivity 

1597 

1598 Args: 

1599 problem: A function that runs a pySDC problem, see imports for available problems 

1600 num_procs (int): Number of processes you intend to run with 

1601 

1602 Returns: 

1603 The custom descriptions you can supply to the problem when running it 

1604 ''' 

1605 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityResidual, Adaptivity 

1606 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting 

1607 

1608 custom_description = super().get_custom_description(problem, num_procs) 

1609 

1610 if self.residual_e_tol_abs: 

1611 e_tol = self.residual_e_tol_abs 

1612 else: 

1613 e_tol = custom_description['convergence_controllers'][Adaptivity]['e_tol'] * self.residual_e_tol_ratio 

1614 custom_description['convergence_controllers'][AdaptivityResidual] = { 

1615 'e_tol': e_tol, 

1616 'allowed_modifications': ['decrease'], 

1617 } 

1618 

1619 custom_description['convergence_controllers'][BasicRestarting.get_implementation(useMPI=self.useMPI)] = { 

1620 'max_restarts': 15 

1621 } 

1622 

1623 return custom_description 

1624 

1625 def get_reference_value(self, problem, key, op, num_procs=1): 

1626 """ 

1627 Get a reference value for a given problem for testing in CI. 

1628 

1629 Args: 

1630 problem: A function that runs a pySDC problem, see imports for available problems 

1631 key (str): The name of the variable you want to compare 

1632 op (function): The operation you want to apply to the data 

1633 num_procs (int): Number of processes 

1634 

1635 Returns: 

1636 The reference value 

1637 """ 

1638 if problem.__name__ == 'run_Lorenz': 

1639 if key == 'work_newton' and op == sum: 

1640 return 2989 

1641 elif key == 'e_global_post_run' and op == max: 

1642 return 5.636763944494305e-08 

1643 

1644 super().get_reference_value(problem, key, op, num_procs) 

1645 

1646 

1647class AdaptivityAvoidRestartsStrategy(AdaptivityStrategy): 

1648 """ 

1649 Adaptivity with the avoid restarts option 

1650 """ 

1651 

1652 @property 

1653 def label(self): 

1654 return 'adaptivity (avoid restarts)' 

1655 

1656 def get_custom_description(self, problem, num_procs): 

1657 ''' 

1658 Routine to get a custom description that adds adaptivity 

1659 

1660 Args: 

1661 problem: A function that runs a pySDC problem, see imports for available problems 

1662 num_procs (int): Number of processes you intend to run with 

1663 

1664 Returns: 

1665 The custom descriptions you can supply to the problem when running it 

1666 ''' 

1667 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity 

1668 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting 

1669 

1670 custom_description = super().get_custom_description(problem, num_procs) 

1671 

1672 custom_description['convergence_controllers'][Adaptivity]['avoid_restarts'] = True 

1673 

1674 custom_description['convergence_controllers'][BasicRestarting.get_implementation(useMPI=self.useMPI)] = { 

1675 'max_restarts': 15 

1676 } 

1677 

1678 return custom_description 

1679 

1680 def get_reference_value(self, problem, key, op, num_procs=1): 

1681 """ 

1682 Get a reference value for a given problem for testing in CI. 

1683 

1684 Args: 

1685 problem: A function that runs a pySDC problem, see imports for available problems 

1686 key (str): The name of the variable you want to compare 

1687 op (function): The operation you want to apply to the data 

1688 num_procs (int): Number of processes 

1689 

1690 Returns: 

1691 The reference value 

1692 """ 

1693 if problem.__name__ == "run_Lorenz": 

1694 if key == 'work_newton' and op == sum: 

1695 return 2989 

1696 elif key == 'e_global_post_run' and op == max: 

1697 return 5.636763944494305e-08 

1698 

1699 super().get_reference_value(problem, key, op, num_procs) 

1700 

1701 

1702class AdaptivityInterpolationStrategy(AdaptivityStrategy): 

1703 """ 

1704 Adaptivity with interpolation between restarts 

1705 """ 

1706 

1707 @property 

1708 def label(self): 

1709 return 'adaptivity+interpolation' 

1710 

1711 def get_custom_description(self, problem, num_procs): 

1712 ''' 

1713 Routine to get a custom description that adds adaptivity 

1714 

1715 Args: 

1716 problem: A function that runs a pySDC problem, see imports for available problems 

1717 num_procs (int): Number of processes you intend to run with 

1718 

1719 Returns: 

1720 The custom descriptions you can supply to the problem when running it 

1721 ''' 

1722 from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity 

1723 from pySDC.implementations.convergence_controller_classes.interpolate_between_restarts import ( 

1724 InterpolateBetweenRestarts, 

1725 ) 

1726 from pySDC.implementations.convergence_controller_classes.basic_restarting import BasicRestarting 

1727 

1728 custom_description = super().get_custom_description(problem, num_procs) 

1729 

1730 custom_description['convergence_controllers'][Adaptivity]['avoid_restarts'] = False 

1731 custom_description['convergence_controllers'][InterpolateBetweenRestarts] = {} 

1732 

1733 custom_description['convergence_controllers'][BasicRestarting.get_implementation(useMPI=self.useMPI)] = { 

1734 'max_restarts': 15 

1735 } 

1736 

1737 return custom_description 

1738 

1739 def get_reference_value(self, problem, key, op, num_procs=1): 

1740 """ 

1741 Get a reference value for a given problem for testing in CI. 

1742 

1743 Args: 

1744 problem: A function that runs a pySDC problem, see imports for available problems 

1745 key (str): The name of the variable you want to compare 

1746 op (function): The operation you want to apply to the data 

1747 num_procs (int): Number of processes 

1748 

1749 Returns: 

1750 The reference value 

1751 """ 

1752 if problem.__name__ == "run_Lorenz": 

1753 if key == 'work_newton' and op == sum: 

1754 return 6659 

1755 elif key == 'e_global_post_run' and op == max: 

1756 return 2.9780002756552015e-06 

1757 

1758 super().get_reference_value(problem, key, op, num_procs) 

1759 

1760 

1761class AdaptivityExtrapolationWithinQStrategy(InexactBaseStrategy): 

1762 ''' 

1763 Adaptivity based on extrapolation between collocation nodes as a resilience strategy 

1764 ''' 

1765 

1766 def __init__(self, **kwargs): 

1767 ''' 

1768 Initialization routine 

1769 ''' 

1770 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityExtrapolationWithinQ 

1771 

1772 self.restol = None 

1773 super().__init__(**kwargs) 

1774 self.color = list(cmap.values())[8] 

1775 self.marker = '*' 

1776 self.name = 'adaptivity_extraQ' 

1777 self.bar_plot_x_label = 'adaptivity Q' 

1778 self.precision_parameter = 'e_tol' 

1779 self.adaptive_coll_params = {} 

1780 self.precision_parameter_loc = ['convergence_controllers', AdaptivityExtrapolationWithinQ, 'e_tol'] 

1781 

1782 def get_custom_description(self, problem, num_procs): 

1783 ''' 

1784 Routine to get a custom description that adds adaptivity 

1785 

1786 Args: 

1787 problem: A function that runs a pySDC problem, see imports for available problems 

1788 num_procs (int): Number of processes you intend to run with 

1789 

1790 Returns: 

1791 The custom descriptions you can supply to the problem when running it 

1792 ''' 

1793 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityExtrapolationWithinQ 

1794 

1795 custom_description = {} 

1796 

1797 dt_max = np.inf 

1798 dt_min = 1e-5 

1799 

1800 if problem.__name__ == "run_vdp": 

1801 e_tol = 2e-5 

1802 dt_min = 1e-3 

1803 elif problem.__name__ == "run_piline": 

1804 e_tol = 1e-7 

1805 dt_min = 1e-2 

1806 elif problem.__name__ == "run_Lorenz": 

1807 e_tol = 2e-5 

1808 dt_min = 1e-3 

1809 elif problem.__name__ == "run_Schroedinger": 

1810 e_tol = 4e-6 

1811 dt_min = 1e-3 

1812 elif problem.__name__ == "run_quench": 

1813 e_tol = 1e-5 

1814 dt_min = 1e-3 

1815 dt_max = 1e2 

1816 elif problem.__name__ == "run_AC": 

1817 e_tol = 1e-4 

1818 else: 

1819 raise NotImplementedError( 

1820 'I don\'t have a tolerance for adaptivity for your problem. Please add one to the\ 

1821 strategy' 

1822 ) 

1823 

1824 custom_description['convergence_controllers'] = { 

1825 AdaptivityExtrapolationWithinQ: { 

1826 'e_tol': e_tol, 

1827 'dt_min': dt_min, 

1828 'dt_max': dt_max, 

1829 'restol_rel': 1e-2, 

1830 'restart_at_maxiter': True, 

1831 } 

1832 } 

1833 return merge_descriptions(super().get_custom_description(problem, num_procs), custom_description) 

1834 

1835 def get_reference_value(self, problem, key, op, num_procs=1): 

1836 """ 

1837 Get a reference value for a given problem for testing in CI. 

1838 

1839 Args: 

1840 problem: A function that runs a pySDC problem, see imports for available problems 

1841 key (str): The name of the variable you want to compare 

1842 op (function): The operation you want to apply to the data 

1843 num_procs (int): Number of processes 

1844 

1845 Returns: 

1846 The reference value 

1847 """ 

1848 if problem.__name__ == "run_Lorenz": 

1849 if key == 'work_newton' and op == sum: 

1850 return 2198 

1851 elif key == 'e_global_post_run' and op == max: 

1852 return 5.412657451131508e-07 

1853 

1854 super().get_reference_value(problem, key, op, num_procs) 

1855 

1856 

1857class AdaptivityPolynomialError(InexactBaseStrategy): 

1858 ''' 

1859 Adaptivity based on extrapolation between collocation nodes as a resilience strategy 

1860 ''' 

1861 

1862 def __init__(self, interpolate_between_restarts=False, use_restol_rel=True, max_slope=4, **kwargs): 

1863 ''' 

1864 Initialization routine 

1865 ''' 

1866 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityPolynomialError 

1867 

1868 self.restol = None 

1869 super().__init__(**kwargs) 

1870 self.color = list(cmap.values())[9] 

1871 self.marker = '+' 

1872 self.name = 'adaptivity-inter' 

1873 self.bar_plot_x_label = 'adaptivity Q' 

1874 self.precision_parameter = 'e_tol' 

1875 self.adaptive_coll_params = {} 

1876 self.precision_parameter_loc = ['convergence_controllers', AdaptivityPolynomialError, 'e_tol'] 

1877 self.interpolate_between_restarts = interpolate_between_restarts 

1878 self.use_restol_rel = use_restol_rel 

1879 self.max_slope = max_slope 

1880 

1881 def get_custom_description(self, problem, num_procs): 

1882 ''' 

1883 Routine to get a custom description that adds adaptivity 

1884 

1885 Args: 

1886 problem: A function that runs a pySDC problem, see imports for available problems 

1887 num_procs (int): Number of processes you intend to run with 

1888 

1889 Returns: 

1890 The custom descriptions you can supply to the problem when running it 

1891 ''' 

1892 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityPolynomialError 

1893 from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeLimiter 

1894 from pySDC.implementations.convergence_controller_classes.check_convergence import CheckConvergence 

1895 

1896 base_params = super().get_custom_description(problem, num_procs) 

1897 custom_description = {} 

1898 

1899 dt_max = np.inf 

1900 restol_rel = 1e-4 

1901 restol_min = 1e-12 

1902 restol_max = 1e-5 

1903 dt_slope_min = 0 

1904 dt_min = 0 

1905 abort_at_growing_residual = True 

1906 level_params = {} 

1907 problem_params = {} 

1908 

1909 if problem.__name__ == "run_vdp": 

1910 e_tol = 6e-4 

1911 level_params['dt'] = 0.1 

1912 restol_rel = 1e-5 

1913 restol_min = 1e-12 

1914 dt_min = 1e-7 

1915 problem_params['newton_tol'] = 1e-14 

1916 elif problem.__name__ == "run_piline": 

1917 e_tol = 1e-7 

1918 elif problem.__name__ == "run_Lorenz": 

1919 e_tol = 2e-4 

1920 elif problem.__name__ == "run_Schroedinger": 

1921 e_tol = 3e-5 

1922 elif problem.__name__ == "run_quench": 

1923 e_tol = 1e-7 

1924 level_params['dt'] = 50.0 

1925 restol_min = 1e-11 

1926 restol_rel = 1e-1 

1927 elif problem.__name__ == "run_AC": 

1928 e_tol = 1.0e-4 

1929 restol_rel = 1e-3 

1930 # dt_max = 0.1 * base_params['problem_params']['eps'] ** 2 

1931 elif problem.__name__ == "run_RBC": 

1932 e_tol = 5e-3 

1933 dt_slope_min = 1.0 

1934 abort_at_growing_residual = False 

1935 restol_rel = 1e-3 

1936 restol_max = 1e-1 

1937 restol_min = 5e-7 

1938 self.max_slope = 4 

1939 else: 

1940 raise NotImplementedError( 

1941 'I don\'t have a tolerance for adaptivity for your problem. Please add one to the\ 

1942 strategy' 

1943 ) 

1944 

1945 custom_description['convergence_controllers'] = { 

1946 AdaptivityPolynomialError: { 

1947 'e_tol': e_tol, 

1948 'restol_rel': restol_rel if self.use_restol_rel else 1e-11, 

1949 'restol_min': restol_min if self.use_restol_rel else 1e-12, 

1950 'restol_max': restol_max if self.use_restol_rel else 1e-5, 

1951 'restart_at_maxiter': True, 

1952 'factor_if_not_converged': self.max_slope, 

1953 'interpolate_between_restarts': self.interpolate_between_restarts, 

1954 'abort_at_growing_residual': abort_at_growing_residual, 

1955 }, 

1956 StepSizeLimiter: { 

1957 'dt_max': dt_max, 

1958 'dt_slope_max': self.max_slope, 

1959 'dt_min': dt_min, 

1960 'dt_rel_min_slope': dt_slope_min, 

1961 }, 

1962 } 

1963 custom_description['level_params'] = level_params 

1964 custom_description['problem_params'] = problem_params 

1965 return merge_descriptions(base_params, custom_description) 

1966 

1967 def get_custom_description_for_faults(self, problem, *args, **kwargs): 

1968 desc = self.get_custom_description(problem, *args, **kwargs) 

1969 if problem.__name__ == "run_quench": 

1970 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityPolynomialError 

1971 

1972 desc['convergence_controllers'][AdaptivityPolynomialError]['e_tol'] = 1e-7 * 11 

1973 desc['level_params']['dt'] = 4.0 

1974 elif problem.__name__ == "run_AC": 

1975 from pySDC.implementations.convergence_controller_classes.adaptivity import AdaptivityPolynomialError 

1976 

1977 desc['convergence_controllers'][AdaptivityPolynomialError]['e_tol'] = 1e-3 

1978 return desc 

1979 

1980 def get_random_params(self, problem, num_procs): 

1981 ''' 

1982 Routine to get parameters for the randomization of faults 

1983 

1984 Args: 

1985 problem: A function that runs a pySDC problem, see imports for available problems 

1986 num_procs (int): Number of processes you intend to run with 

1987 

1988 Returns: 

1989 dict: Randomization parameters 

1990 ''' 

1991 

1992 rnd_params = super().get_random_params(problem, num_procs) 

1993 if problem.__name__ == "run_quench": 

1994 rnd_params['iteration'] = 1 

1995 elif problem.__name__ == 'run_Lorenz': 

1996 rnd_params['iteration'] = 4 

1997 return rnd_params 

1998 

1999 def get_reference_value(self, problem, key, op, num_procs=1): 

2000 """ 

2001 Get a reference value for a given problem for testing in CI. 

2002 

2003 Args: 

2004 problem: A function that runs a pySDC problem, see imports for available problems 

2005 key (str): The name of the variable you want to compare 

2006 op (function): The operation you want to apply to the data 

2007 num_procs (int): Number of processes 

2008 

2009 Returns: 

2010 The reference value 

2011 """ 

2012 if problem.__name__ == "run_Lorenz": 

2013 if key == 'work_newton' and op == sum: 

2014 return 2123 

2015 elif key == 'e_global_post_run' and op == max: 

2016 return 7.931560830343187e-08 

2017 

2018 super().get_reference_value(problem, key, op, num_procs) 

2019 

2020 @property 

2021 def label(self): 

2022 return r'$\Delta t$-$k$-adaptivity'