Coverage for pySDC/projects/AsympConv/PFASST_conv_Linf.py: 96%
157 statements
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-20 14:51 +0000
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-20 14:51 +0000
1import csv
2import os
4# import matplotlib
5# matplotlib.use('Agg')
6import matplotlib.pyplot as plt
7import numpy as np
9from pySDC.helpers.stats_helper import get_sorted
11from pySDC.implementations.controller_classes.controller_nonMPI import controller_nonMPI
12from pySDC.implementations.problem_classes.AdvectionEquation_ND_FD import advectionNd
13from pySDC.implementations.problem_classes.HeatEquation_ND_FD import heatNd_unforced
14from pySDC.implementations.sweeper_classes.generic_implicit import generic_implicit
15from pySDC.implementations.transfer_classes.TransferMesh import mesh_to_mesh
18def main():
19 """
20 Main driver running diffusion and advection tests
21 """
22 QI = 'LU'
23 run_diffusion(QI=QI)
24 run_advection(QI=QI)
26 QI = 'LU2'
27 run_diffusion(QI=QI)
28 run_advection(QI=QI)
30 plot_results()
33def run_diffusion(QI, max_proc_exp=13):
34 """
35 A simple test program to test PFASST convergence for the heat equation with random initial data
37 Args:
38 QI: preconditioner
39 max_proc_exp: max number of processors will be 2^max_proc_exp
40 """
42 # initialize level parameters
43 level_params = dict()
44 level_params['restol'] = 1e-08
45 level_params['nsweeps'] = [3, 1]
47 # initialize sweeper parameters
48 sweeper_params = dict()
49 sweeper_params['quad_type'] = 'RADAU-RIGHT'
50 sweeper_params['num_nodes'] = [3]
51 sweeper_params['QI'] = [QI, 'LU']
52 sweeper_params['initial_guess'] = 'zero'
54 # initialize problem parameters
55 problem_params = dict()
56 problem_params['nu'] = 0.1 # diffusion coefficient
57 problem_params['freq'] = 2 # frequency for the test value
58 problem_params['nvars'] = [127, 63] # number of degrees of freedom for each level
59 problem_params['bc'] = 'dirichlet-zero' # boundary conditions
61 # initialize step parameters
62 step_params = dict()
63 step_params['maxiter'] = 200
65 # initialize space transfer parameters
66 space_transfer_params = dict()
67 space_transfer_params['rorder'] = 2
68 space_transfer_params['iorder'] = 2
69 space_transfer_params['periodic'] = False
71 # initialize controller parameters
72 controller_params = dict()
73 controller_params['logger_level'] = 30
75 # fill description dictionary for easy step instantiation
76 description = dict()
77 description['problem_class'] = heatNd_unforced # pass problem class
78 description['problem_params'] = problem_params # pass problem parameters
79 description['sweeper_class'] = generic_implicit # pass sweeper (see part B)
80 description['sweeper_params'] = sweeper_params # pass sweeper parameters
81 description['step_params'] = step_params # pass step parameters
82 description['space_transfer_class'] = mesh_to_mesh # pass spatial transfer class
83 description['space_transfer_params'] = space_transfer_params # pass paramters for spatial transfer
85 # set time parameters
86 t0 = 0.0
87 Tend = 1.0
89 # set up number of parallel time-steps to run PFASST with
91 fname = 'data/results_conv_diffusion_Linf_QI' + str(QI) + '.txt'
92 file = open(fname, 'w')
93 writer = csv.writer(file)
94 writer.writerow(('num_proc', 'niter'))
95 file.close()
97 for i in range(0, max_proc_exp):
98 num_proc = 2**i
99 level_params['dt'] = (Tend - t0) / num_proc
100 description['level_params'] = level_params # pass level parameters
102 out = 'Working on num_proc = %5i' % num_proc
103 print(out)
104 cfl = problem_params['nu'] * level_params['dt'] / (1.0 / (problem_params['nvars'][0] + 1)) ** 2
105 out = ' CFL number: %4.2e' % cfl
106 print(out)
108 # instantiate controller
109 controller = controller_nonMPI(num_procs=num_proc, controller_params=controller_params, description=description)
111 # get initial values on finest level
112 P = controller.MS[0].levels[0].prob
113 uinit = P.u_exact(t0)
115 # call main function to get things done...
116 uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend)
118 # filter statistics by type (number of iterations)
119 iter_counts = get_sorted(stats, type='niter', sortby='time')
121 niters = np.array([item[1] for item in iter_counts])
123 out = ' Mean number of iterations: %4.2f' % np.mean(niters)
124 print(out)
126 file = open(fname, 'a')
127 writer = csv.writer(file)
128 writer.writerow((num_proc, np.mean(niters)))
129 file.close()
131 assert os.path.isfile(fname), 'ERROR: pickle did not create file'
134def run_advection(QI, max_proc_exp=7):
135 """
136 A simple test program to test PFASST convergence for the periodic advection equation
138 Args:
139 QI: preconditioner
140 max_proc_exp: max number of processors will be 2^max_proc_exp
141 """
143 # initialize level parameters
144 level_params = dict()
145 level_params['restol'] = 1e-08
146 level_params['nsweeps'] = [3, 1]
148 # initialize sweeper parameters
149 sweeper_params = dict()
150 sweeper_params['quad_type'] = 'RADAU-RIGHT'
151 sweeper_params['num_nodes'] = [3]
152 sweeper_params['QI'] = [QI, 'LU'] # For the IMEX sweeper, the LU-trick can be activated for the implicit part
153 sweeper_params['initial_guess'] = 'zero'
155 # initialize problem parameters
156 problem_params = dict()
157 problem_params['freq'] = 64 # frequency for the test value
158 problem_params['nvars'] = [128, 64] # number of degrees of freedom for each level
159 problem_params['order'] = 2
160 problem_params['stencil_type'] = 'center'
161 problem_params['c'] = 0.1
162 problem_params['bc'] = 'periodic' # boundary conditions
164 # initialize step parameters
165 step_params = dict()
166 step_params['maxiter'] = 200
168 # initialize space transfer parameters
169 space_transfer_params = dict()
170 space_transfer_params['rorder'] = 2
171 space_transfer_params['iorder'] = 2
172 space_transfer_params['periodic'] = True
174 # initialize controller parameters
175 controller_params = dict()
176 controller_params['logger_level'] = 30
178 # fill description dictionary for easy step instantiation
179 description = dict()
180 description['problem_class'] = advectionNd # pass problem class
181 description['problem_params'] = problem_params # pass problem parameters
182 description['sweeper_class'] = generic_implicit # pass sweeper (see part B)
183 description['sweeper_params'] = sweeper_params # pass sweeper parameters
184 description['step_params'] = step_params # pass step parameters
185 description['space_transfer_class'] = mesh_to_mesh # pass spatial transfer class
186 description['space_transfer_params'] = space_transfer_params # pass paramters for spatial transfer
188 # set time parameters
189 t0 = 0.0
190 Tend = 1.0
192 # set up number of parallel time-steps to run PFASST with
194 fname = 'data/results_conv_advection_Linf_QI' + str(QI) + '.txt'
195 file = open(fname, 'w')
196 writer = csv.writer(file)
197 writer.writerow(('num_proc', 'niter'))
198 file.close()
200 for i in range(0, max_proc_exp):
201 num_proc = 2**i
202 level_params['dt'] = (Tend - t0) / num_proc
203 description['level_params'] = level_params # pass level parameters
205 out = 'Working on num_proc = %5i' % num_proc
206 print(out)
207 cfl = problem_params['c'] * level_params['dt'] / (1.0 / problem_params['nvars'][0])
208 out = ' CFL number: %4.2e' % cfl
209 print(out)
211 # instantiate controller
212 controller = controller_nonMPI(num_procs=num_proc, controller_params=controller_params, description=description)
214 # get initial values on finest level
215 P = controller.MS[0].levels[0].prob
216 uinit = P.u_exact(t0)
218 # call main function to get things done...
219 uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend)
221 # filter statistics by type (number of iterations)
222 iter_counts = get_sorted(stats, type='niter', sortby='time')
224 niters = np.array([item[1] for item in iter_counts])
226 out = ' Mean number of iterations: %4.2f' % np.mean(niters)
227 print(out)
229 file = open(fname, 'a')
230 writer = csv.writer(file)
231 writer.writerow((num_proc, np.mean(niters)))
232 file.close()
234 assert os.path.isfile(fname), 'ERROR: pickle did not create file'
237def plot_results(cwd=''):
238 """
239 Plotting routine for iteration counts
241 Args:
242 cwd: current working directory
243 """
245 setups = [('diffusion', 'LU', 'LU2'), ('advection', 'LU', 'LU2')]
247 for type, QI1, QI2 in setups:
248 fname = cwd + 'data/results_conv_' + type + '_Linf_QI' + QI1 + '.txt'
249 file = open(fname, 'r')
250 reader = csv.DictReader(file, delimiter=',')
251 xvalues_1 = []
252 niter_1 = []
253 for row in reader:
254 xvalues_1.append(int(row['num_proc']))
255 niter_1.append(float(row['niter']))
256 file.close()
258 fname = cwd + 'data/results_conv_' + type + '_Linf_QI' + QI2 + '.txt'
259 file = open(fname, 'r')
260 reader = csv.DictReader(file, delimiter=',')
261 xvalues_2 = []
262 niter_2 = []
263 for row in reader:
264 xvalues_2.append(int(row['num_proc']))
265 niter_2.append(float(row['niter']))
266 file.close()
268 # set up plotting parameters
269 params = {
270 'legend.fontsize': 20,
271 'figure.figsize': (12, 8),
272 'axes.labelsize': 20,
273 'axes.titlesize': 20,
274 'xtick.labelsize': 16,
275 'ytick.labelsize': 16,
276 'lines.linewidth': 3,
277 }
278 plt.rcParams.update(params)
280 # set up figure
281 plt.figure()
282 plt.xlabel('number of time-steps (L)')
283 plt.ylabel('no. of iterations')
284 plt.xlim(min(xvalues_1 + xvalues_2) / 2.0, max(xvalues_1 + xvalues_2) * 2.0)
285 plt.ylim(min(niter_1 + niter_2) - 1, max(niter_1 + niter_2) + 1)
286 plt.grid()
288 # plot
289 plt.semilogx(xvalues_1, niter_1, 'r-', marker='s', markersize=10, label=QI1)
290 plt.semilogx(xvalues_2, niter_2, 'b-', marker='o', markersize=10, label=QI2)
292 plt.legend(loc=2, ncol=1, numpoints=1)
294 # save plot, beautify
295 fname = 'data/conv_test_niter_Linf_' + type + '.png'
296 plt.savefig(fname, bbox_inches='tight')
298 assert os.path.isfile(fname), 'ERROR: plotting did not create file'
301if __name__ == "__main__":
302 main()