Coverage for pySDC/tutorial/step_8/B_multistep_SDC.py: 100%
98 statements
« prev ^ index » next coverage.py v7.6.7, created at 2024-11-16 14:51 +0000
« prev ^ index » next coverage.py v7.6.7, created at 2024-11-16 14:51 +0000
1import os
2from pathlib import Path
5from pySDC.helpers.stats_helper import get_sorted
6from pySDC.helpers.visualization_tools import show_residual_across_simulation
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
14def main():
15 """
16 A simple test program to do compare PFASST with multi-step SDC
17 """
19 # initialize level parameters
20 level_params = dict()
21 level_params['restol'] = 5e-10
22 level_params['dt'] = 0.125
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'
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
36 # initialize step parameters
37 step_params = dict()
38 step_params['maxiter'] = 50
40 # initialize space transfer parameters
41 space_transfer_params = dict()
42 space_transfer_params['rorder'] = 2
43 space_transfer_params['iorder'] = 6
45 # initialize controller parameters
46 controller_params = dict()
47 controller_params['logger_level'] = 40
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
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()
64 # set up parameters for MSSDC run
65 problem_params['nvars'] = [63]
66 description['problem_params'] = problem_params.copy()
67 description_mssdc = description.copy()
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()
74 # set time parameters
75 t0 = 0.0
76 Tend = 1.0
78 # set up list of parallel time-steps to run PFASST/MSSDC with
79 num_proc = 8
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 )
92 # get initial values on finest level
93 P = controller_mssdc_jac.MS[0].levels[0].prob
94 uinit = P.u_exact(t0)
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)
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)
110 Path("data").mkdir(parents=True, exist_ok=True)
111 f = open('data/step_8_B_out.txt', 'w')
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)
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')
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)
150 f.close()
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')
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 )
169if __name__ == "__main__":
170 main()