Coverage for pySDC/tutorial/step_7/B_pySDC_with_mpi4pyfft.py: 100%
88 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 numpy as np
2from pathlib import Path
3from mpi4py import MPI
5from pySDC.helpers.stats_helper import get_sorted
7from pySDC.implementations.controller_classes.controller_nonMPI import controller_nonMPI
8from pySDC.implementations.sweeper_classes.imex_1st_order import imex_1st_order
9from pySDC.implementations.problem_classes.NonlinearSchroedinger_MPIFFT import nonlinearschroedinger_imex
10from pySDC.implementations.transfer_classes.TransferMesh_MPIFFT import fft_to_fft
13def run_simulation(spectral=None, ml=None, num_procs=None):
14 """
15 A test program to do SDC, MLSDC and PFASST runs for the 2D NLS equation
17 Args:
18 spectral (bool): run in real or spectral space
19 ml (bool): single or multiple levels
20 num_procs (int): number of parallel processors
21 """
23 comm = MPI.COMM_WORLD
24 rank = comm.Get_rank()
26 # initialize level parameters
27 level_params = dict()
28 level_params['restol'] = 1e-08
29 level_params['dt'] = 1e-01 / 2
30 level_params['nsweeps'] = [1]
32 # initialize sweeper parameters
33 sweeper_params = dict()
34 sweeper_params['quad_type'] = 'RADAU-RIGHT'
35 sweeper_params['num_nodes'] = [3]
36 sweeper_params['QI'] = ['LU'] # For the IMEX sweeper, the LU-trick can be activated for the implicit part
37 sweeper_params['initial_guess'] = 'zero'
39 # initialize problem parameters
40 problem_params = dict()
41 if ml:
42 problem_params['nvars'] = [(128, 128), (32, 32)]
43 else:
44 problem_params['nvars'] = [(128, 128)]
45 problem_params['spectral'] = spectral
46 problem_params['comm'] = comm
48 # initialize step parameters
49 step_params = dict()
50 step_params['maxiter'] = 50
52 # initialize controller parameters
53 controller_params = dict()
54 controller_params['logger_level'] = 30 if rank == 0 else 99
55 # controller_params['predict_type'] = 'fine_only'
57 # fill description dictionary for easy step instantiation
58 description = dict()
59 description['problem_params'] = problem_params # pass problem parameters
60 description['problem_class'] = nonlinearschroedinger_imex
61 description['sweeper_class'] = imex_1st_order
62 description['sweeper_params'] = sweeper_params # pass sweeper parameters
63 description['level_params'] = level_params # pass level parameters
64 description['step_params'] = step_params # pass step parameters
65 description['space_transfer_class'] = fft_to_fft
67 # set time parameters
68 t0 = 0.0
69 Tend = 1.0
71 f = None
72 if rank == 0:
73 Path("data").mkdir(parents=True, exist_ok=True)
74 f = open('data/step_7_B_out.txt', 'a')
75 out = f'Running with ml={ml} and num_procs={num_procs}...'
76 f.write(out + '\n')
77 print(out)
79 # instantiate controller
80 controller = controller_nonMPI(num_procs=num_procs, controller_params=controller_params, description=description)
82 # get initial values on finest level
83 P = controller.MS[0].levels[0].prob
84 uinit = P.u_exact(t0)
86 # call main function to get things done...
87 uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend)
88 uex = P.u_exact(Tend)
89 err = abs(uex - uend)
91 if rank == 0:
92 # filter statistics by type (number of iterations)
93 iter_counts = get_sorted(stats, type='niter', sortby='time')
95 niters = np.array([item[1] for item in iter_counts])
96 out = (
97 f' Min/Mean/Max number of iterations: '
98 f'{np.min(niters):4.2f} / {np.mean(niters):4.2f} / {np.max(niters):4.2f}'
99 )
100 f.write(out + '\n')
101 print(out)
102 out = ' Range of values for number of iterations: %2i ' % np.ptp(niters)
103 f.write(out + '\n')
104 print(out)
105 out = ' Position of max/min number of iterations: %2i -- %2i' % (
106 int(np.argmax(niters)),
107 int(np.argmin(niters)),
108 )
109 f.write(out + '\n')
110 print(out)
111 out = ' Std and var for number of iterations: %4.2f -- %4.2f' % (float(np.std(niters)), float(np.var(niters)))
112 f.write(out + '\n')
113 print(out)
115 out = f'Error: {err:6.4e}'
116 f.write(out + '\n')
117 print(out)
119 timing = get_sorted(stats, type='timing_run', sortby='time')
120 out = f'Time to solution: {timing[0][1]:6.4f} sec.'
121 f.write(out + '\n')
122 print(out)
124 assert err <= 1.133e-05, 'Error is too high, got %s' % err
125 if ml:
126 if num_procs > 1:
127 maxmean = 12.5
128 else:
129 maxmean = 6.6
130 else:
131 maxmean = 12.7
132 assert np.mean(niters) <= maxmean, 'Mean number of iterations is too high, got %s' % np.mean(niters)
134 f.write('\n')
135 print()
136 f.close()
139def main():
140 """
141 Little helper routine to run the whole thing
143 Note: This can also be run with "mpirun -np 2 python B_pySDC_with_mpi4pyfft.py"
144 """
145 run_simulation(spectral=False, ml=False, num_procs=1)
146 run_simulation(spectral=True, ml=False, num_procs=1)
147 run_simulation(spectral=False, ml=True, num_procs=1)
148 run_simulation(spectral=True, ml=True, num_procs=1)
149 run_simulation(spectral=False, ml=True, num_procs=10)
150 run_simulation(spectral=True, ml=True, num_procs=10)
153if __name__ == "__main__":
154 main()