Coverage for pySDC/tutorial/step_8/HookClass_error_output.py: 100%

30 statements  

« prev     ^ index     » next       coverage.py v7.17.0, created at 2026-11-02 12:30 +0000

1from pySDC.core.hooks import Hooks 

2from pySDC.implementations.controller_classes.controller_nonMPI import controller_nonMPI 

3from pySDC.implementations.problem_classes.Auzinger_implicit import auzinger 

4 

5 

6class error_output(Hooks): 

7 """ 

8 Hook class to add output of error 

9 """ 

10 

11 def __init__(self): 

12 super(error_output, self).__init__() 

13 self.uex = None 

14 

15 def pre_step(self, step, level_number): 

16 """ 

17 Default routine called before each step 

18 Args: 

19 step: the current step 

20 level_number: the current level number 

21 """ 

22 super(error_output, self).pre_step(step, level_number) 

23 

24 L = step.levels[level_number] 

25 

26 # This is a bit black magic: we are going to run pySDC within the hook to check the error against the "exact" 

27 # solution of the collocation problem 

28 # copies: this hook runs in every step, and the outer run's parameters must stay as they are 

29 description = dict(step.params.description) 

30 description['level_params'] = {**description['level_params'], 'restol': 1e-14} 

31 if type(L.prob) != auzinger: 

32 description['problem_params'] = {**description['problem_params'], 'solver_type': 'direct'} 

33 # without this, the iteration estimator would stop the "exact" solve as early as the run it is checking 

34 description['convergence_controllers'] = {} 

35 

36 controller_params = dict(step.params.controller_params) 

37 del controller_params['hook_class'] # get rid of the hook, otherwise this will be an endless recursion.. 

38 controller_params['logger_level'] = 90 

39 

40 controller = controller_nonMPI(num_procs=1, description=description, controller_params=controller_params) 

41 self.uex, _ = controller.run(u0=L.u[0], t0=L.time, Tend=L.time + L.dt) 

42 

43 def post_step(self, step, level_number): 

44 """ 

45 Default routine called after each step 

46 Args: 

47 step: the current step 

48 level_number: the current level number 

49 """ 

50 

51 super(error_output, self).post_step(step, level_number) 

52 

53 # some abbreviations 

54 L = step.levels[level_number] 

55 P = L.prob 

56 

57 L.sweep.compute_end_point() 

58 

59 # compute and save errors 

60 upde = P.u_exact(step.time + step.dt) 

61 pde_err = abs(upde - L.uend) 

62 coll_err = abs(self.uex - L.uend) 

63 

64 self.add_to_stats( 

65 process=step.status.slot, 

66 time=L.time + L.dt, 

67 level=L.level_index, 

68 iter=step.status.iter, 

69 sweep=L.status.sweep, 

70 type='PDE_error_after_step', 

71 value=pde_err, 

72 ) 

73 self.add_to_stats( 

74 process=step.status.slot, 

75 time=L.time + L.dt, 

76 level=L.level_index, 

77 iter=step.status.iter, 

78 sweep=L.status.sweep, 

79 type='coll_error_after_step', 

80 value=coll_err, 

81 )