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

98 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-04-29 09:02 +0000

1import os 

2from pathlib import Path 

3 

4 

5from pySDC.helpers.stats_helper import get_sorted 

6from pySDC.helpers.visualization_tools import show_residual_across_simulation 

7 

8from pySDC.implementations.controller_classes.controller_nonMPI import controller_nonMPI 

9from pySDC.implementations.problem_classes.HeatEquation_ND_FD import heatNd_unforced 

10from pySDC.implementations.sweeper_classes.generic_implicit import generic_implicit 

11from pySDC.implementations.transfer_classes.TransferMesh import mesh_to_mesh 

12 

13 

14def main(): 

15 """ 

16 A simple test program to do compare PFASST with multi-step SDC 

17 """ 

18 

19 # initialize level parameters 

20 level_params = dict() 

21 level_params['restol'] = 5e-10 

22 level_params['dt'] = 0.125 

23 

24 # initialize sweeper parameters 

25 sweeper_params = dict() 

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

27 sweeper_params['num_nodes'] = [3] 

28 sweeper_params['QI'] = 'LU' 

29 

30 # initialize problem parameters 

31 problem_params = dict() 

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

33 problem_params['freq'] = 2 # frequency for the test value 

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

35 

36 # initialize step parameters 

37 step_params = dict() 

38 step_params['maxiter'] = 50 

39 

40 # initialize space transfer parameters 

41 space_transfer_params = dict() 

42 space_transfer_params['rorder'] = 2 

43 space_transfer_params['iorder'] = 6 

44 

45 # initialize controller parameters 

46 controller_params = dict() 

47 controller_params['logger_level'] = 40 

48 

49 # fill description dictionary for easy step instantiation 

50 description = dict() 

51 description['problem_class'] = heatNd_unforced 

52 description['sweeper_class'] = generic_implicit 

53 description['sweeper_params'] = sweeper_params 

54 description['level_params'] = level_params 

55 description['step_params'] = step_params 

56 description['space_transfer_class'] = mesh_to_mesh 

57 description['space_transfer_params'] = space_transfer_params 

58 

59 # set up parameters for PFASST run 

60 problem_params['nvars'] = [63, 31] 

61 description['problem_params'] = problem_params.copy() 

62 description_pfasst = description.copy() 

63 

64 # set up parameters for MSSDC run 

65 problem_params['nvars'] = [63] 

66 description['problem_params'] = problem_params.copy() 

67 description_mssdc = description.copy() 

68 

69 controller_params['mssdc_jac'] = True 

70 controller_params_jac = controller_params.copy() 

71 controller_params['mssdc_jac'] = False 

72 controller_params_gs = controller_params.copy() 

73 

74 # set time parameters 

75 t0 = 0.0 

76 Tend = 1.0 

77 

78 # set up list of parallel time-steps to run PFASST/MSSDC with 

79 num_proc = 8 

80 

81 # instantiate controllers 

82 controller_mssdc_jac = controller_nonMPI( 

83 num_procs=num_proc, controller_params=controller_params_jac, description=description_mssdc 

84 ) 

85 controller_mssdc_gs = controller_nonMPI( 

86 num_procs=num_proc, controller_params=controller_params_gs, description=description_mssdc 

87 ) 

88 controller_pfasst = controller_nonMPI( 

89 num_procs=num_proc, controller_params=controller_params, description=description_pfasst 

90 ) 

91 

92 # get initial values on finest level 

93 P = controller_mssdc_jac.MS[0].levels[0].prob 

94 uinit = P.u_exact(t0) 

95 

96 # call main functions to get things done... 

97 uend_pfasst, stats_pfasst = controller_pfasst.run(u0=uinit, t0=t0, Tend=Tend) 

98 uend_mssdc_jac, stats_mssdc_jac = controller_mssdc_jac.run(u0=uinit, t0=t0, Tend=Tend) 

99 uend_mssdc_gs, stats_mssdc_gs = controller_mssdc_gs.run(u0=uinit, t0=t0, Tend=Tend) 

100 

101 # compute exact solution and compare for both runs 

102 uex = P.u_exact(Tend) 

103 err_mssdc_jac = abs(uex - uend_mssdc_jac) 

104 err_mssdc_gs = abs(uex - uend_mssdc_gs) 

105 err_pfasst = abs(uex - uend_pfasst) 

106 diff_jac = abs(uend_mssdc_jac - uend_pfasst) 

107 diff_gs = abs(uend_mssdc_gs - uend_pfasst) 

108 diff_jac_gs = abs(uend_mssdc_gs - uend_mssdc_jac) 

109 

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

111 f = open('data/step_8_B_out.txt', 'w') 

112 

113 out = 'Error PFASST: %12.8e' % err_pfasst 

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

115 print(out) 

116 out = 'Error parallel MSSDC: %12.8e' % err_mssdc_jac 

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

118 print(out) 

119 out = 'Error serial MSSDC: %12.8e' % err_mssdc_gs 

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

121 print(out) 

122 out = 'Diff PFASST vs. parallel MSSDC: %12.8e' % diff_jac 

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

124 print(out) 

125 out = 'Diff PFASST vs. serial MSSDC: %12.8e' % diff_gs 

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

127 print(out) 

128 out = 'Diff parallel vs. serial MSSDC: %12.8e' % diff_jac_gs 

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

130 print(out) 

131 

132 # convert filtered statistics to list of iterations count, sorted by process 

133 iter_counts_pfasst = get_sorted(stats_pfasst, type='niter', sortby='time') 

134 iter_counts_mssdc_jac = get_sorted(stats_mssdc_jac, type='niter', sortby='time') 

135 iter_counts_mssdc_gs = get_sorted(stats_mssdc_gs, type='niter', sortby='time') 

136 

137 # compute and print statistics 

138 for item_pfasst, item_mssdc_jac, item_mssdc_gs in zip( 

139 iter_counts_pfasst, iter_counts_mssdc_jac, iter_counts_mssdc_gs 

140 ): 

141 out = 'Number of iterations for time %4.2f (PFASST/parMSSDC/serMSSDC): %2i / %2i / %2i' % ( 

142 item_pfasst[0], 

143 item_pfasst[1], 

144 item_mssdc_jac[1], 

145 item_mssdc_gs[1], 

146 ) 

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

148 print(out) 

149 

150 f.close() 

151 

152 # call helper routine to produce residual plot 

153 show_residual_across_simulation(stats_mssdc_jac, 'data/step_8_residuals_mssdc_jac.png') 

154 show_residual_across_simulation(stats_mssdc_gs, 'data/step_8_residuals_mssdc_gs.png') 

155 

156 assert os.path.isfile('data/step_8_residuals_mssdc_jac.png') 

157 assert os.path.isfile('data/step_8_residuals_mssdc_gs.png') 

158 assert diff_jac < 3.1e-10, ( 

159 "ERROR: difference between PFASST and parallel MSSDC controller is too large, got %s" % diff_jac 

160 ) 

161 assert diff_gs < 3.1e-10, ( 

162 "ERROR: difference between PFASST and serial MSSDC controller is too large, got %s" % diff_gs 

163 ) 

164 assert diff_jac_gs < 3.1e-10, ( 

165 "ERROR: difference between parallel and serial MSSDC controller is too large, got %s" % diff_jac_gs 

166 ) 

167 

168 

169if __name__ == "__main__": 

170 main()