Coverage for pySDC/tutorial/step_5/B_my_first_PFASST_run.py: 100%

72 statements  

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

1from pathlib import Path 

2import numpy as np 

3 

4from pySDC.helpers.stats_helper import get_sorted 

5 

6from pySDC.implementations.controller_classes.controller_nonMPI import controller_nonMPI 

7from pySDC.implementations.problem_classes.HeatEquation_ND_FD import heatNd_forced 

8from pySDC.implementations.sweeper_classes.imex_1st_order import imex_1st_order 

9from pySDC.implementations.transfer_classes.TransferMesh import mesh_to_mesh 

10 

11 

12def main(): 

13 """ 

14 A simple test program to do PFASST runs for the heat equation 

15 """ 

16 

17 # initialize level parameters 

18 level_params = dict() 

19 level_params['restol'] = 1e-10 

20 level_params['dt'] = 0.25 

21 

22 # initialize sweeper parameters 

23 sweeper_params = dict() 

24 sweeper_params['quad_type'] = 'RADAU-RIGHT' 

25 sweeper_params['num_nodes'] = [3] 

26 sweeper_params['QI'] = 'LU' # For the IMEX sweeper, the LU-trick can be activated for the implicit part 

27 

28 # initialize problem parameters 

29 problem_params = dict() 

30 problem_params['nu'] = 0.1 # diffusion coefficient 

31 problem_params['freq'] = 8 # frequency for the test value 

32 problem_params['nvars'] = [511, 255] # number of degrees of freedom for each level 

33 problem_params['bc'] = 'dirichlet-zero' # boundary conditions 

34 

35 # initialize step parameters 

36 step_params = dict() 

37 step_params['maxiter'] = 50 

38 

39 # initialize space transfer parameters 

40 space_transfer_params = dict() 

41 space_transfer_params['rorder'] = 2 

42 space_transfer_params['iorder'] = 6 

43 

44 # initialize controller parameters 

45 controller_params = dict() 

46 controller_params['logger_level'] = 30 

47 controller_params['predict_type'] = 'pfasst_burnin' 

48 

49 # fill description dictionary for easy step instantiation 

50 description = dict() 

51 description['problem_class'] = heatNd_forced # pass problem class 

52 description['problem_params'] = problem_params # pass problem parameters 

53 description['sweeper_class'] = imex_1st_order # pass sweeper (see part B) 

54 description['sweeper_params'] = sweeper_params # pass sweeper parameters 

55 description['level_params'] = level_params # pass level parameters 

56 description['step_params'] = step_params # pass step parameters 

57 description['space_transfer_class'] = mesh_to_mesh # pass spatial transfer class 

58 description['space_transfer_params'] = space_transfer_params # pass parameters for spatial transfer 

59 

60 # set time parameters 

61 t0 = 0.0 

62 Tend = 4.0 

63 

64 # set up list of parallel time-steps to run PFASST with 

65 nsteps = int(Tend / level_params['dt']) 

66 num_proc_list = [2**i for i in range(int(np.log2(nsteps) + 1))] 

67 

68 Path("data").mkdir(parents=True, exist_ok=True) 

69 f = open('data/step_5_B_out.txt', 'w') 

70 # loop over different number of processes and check results 

71 for num_proc in num_proc_list: 

72 out = 'Working with %2i processes...' % num_proc 

73 f.write(out + '\n') 

74 print(out) 

75 # instantiate controller 

76 controller = controller_nonMPI(num_procs=num_proc, controller_params=controller_params, description=description) 

77 

78 # get initial values on finest level 

79 P = controller.MS[0].levels[0].prob 

80 uinit = P.u_exact(t0) 

81 

82 # call main function to get things done... 

83 uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) 

84 

85 # compute exact solution and compare 

86 uex = P.u_exact(Tend) 

87 err = abs(uex - uend) 

88 

89 # filter statistics by type (number of iterations) 

90 iter_counts = get_sorted(stats, type='niter', sortby='time') 

91 

92 # compute and print statistics 

93 for item in iter_counts: 

94 out = 'Number of iterations for time %4.2f: %2i' % item 

95 f.write(out + '\n') 

96 print(out) 

97 f.write('\n') 

98 print() 

99 niters = np.array([item[1] for item in iter_counts]) 

100 out = ' Mean number of iterations: %4.2f' % np.mean(niters) 

101 f.write(out + '\n') 

102 print(out) 

103 out = ' Range of values for number of iterations: %2i ' % np.ptp(niters) 

104 f.write(out + '\n') 

105 print(out) 

106 out = ' Position of max/min number of iterations: %2i -- %2i' % ( 

107 int(np.argmax(niters)), 

108 int(np.argmin(niters)), 

109 ) 

110 f.write(out + '\n') 

111 print(out) 

112 out = ' Std and var for number of iterations: %4.2f -- %4.2f' % (float(np.std(niters)), float(np.var(niters))) 

113 f.write(out + '\n') 

114 print(out) 

115 

116 f.write('\n\n') 

117 print() 

118 print() 

119 

120 assert err < 1.3505e-04, "ERROR: error is too high, got %s" % err 

121 assert np.ptp(niters) <= 1, "ERROR: range of number of iterations is too high, got %s" % np.ptp(niters) 

122 assert np.mean(niters) <= 5.0, "ERROR: mean number of iterations is too high, got %s" % np.mean(niters) 

123 

124 f.close() 

125 

126 

127if __name__ == "__main__": 

128 main()