Coverage for pySDC/projects/parallelSDC/AllenCahn_parallel.py: 85%
112 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 subprocess
2import os
4import numpy as np
5from mpi4py import MPI
7from pySDC.helpers.stats_helper import get_sorted
9from pySDC.implementations.controller_classes.controller_nonMPI import controller_nonMPI
10from pySDC.implementations.problem_classes.AllenCahn_2D_FD import allencahn_fullyimplicit
11from pySDC.implementations.sweeper_classes.generic_implicit import generic_implicit
12from pySDC.implementations.transfer_classes.TransferMesh_FFT2D import mesh_to_mesh_fft2d
13from pySDC.playgrounds.Allen_Cahn.AllenCahn_monitor import monitor
14from pySDC.implementations.transfer_classes.BaseTransferMPI import base_transfer_MPI
15from pySDC.implementations.sweeper_classes.generic_implicit_MPI import generic_implicit_MPI
18# http://www.personal.psu.edu/qud2/Res/Pre/dz09sisc.pdf
21def run_variant(variant=None):
22 """
23 Routine to run a particular variant
25 Args:
26 variant (str): string describing the variant
28 """
30 # initialize level parameters
31 level_params = dict()
32 level_params['restol'] = 1e-07
33 level_params['dt'] = 1e-03 / 2
34 level_params['nsweeps'] = 1
36 # initialize sweeper parameters
37 sweeper_params = dict()
38 sweeper_params['quad_type'] = 'RADAU-RIGHT'
39 sweeper_params['num_nodes'] = 3
40 sweeper_params['initial_guess'] = 'zero'
42 # This comes as read-in for the problem class
43 problem_params = dict()
44 problem_params['nu'] = 2
46 problem_params['eps'] = 0.04
47 problem_params['newton_maxiter'] = 100
48 problem_params['newton_tol'] = 1e-08
49 problem_params['lin_tol'] = 1e-09
50 problem_params['lin_maxiter'] = 100
51 problem_params['radius'] = 0.25
53 # initialize step parameters
54 step_params = dict()
55 step_params['maxiter'] = 50
57 # initialize controller parameters
58 controller_params = dict()
59 controller_params['logger_level'] = 30
60 controller_params['hook_class'] = monitor
62 # fill description dictionary for easy step instantiation
63 description = dict()
64 description['problem_class'] = allencahn_fullyimplicit
65 description['level_params'] = level_params # pass level parameters
66 description['step_params'] = step_params # pass step parameters
68 do_print = True
70 # add stuff based on variant
71 if variant == 'sl_serial':
72 maxmeaniters = 5.0
73 sweeper_params['QI'] = ['LU']
74 problem_params['nvars'] = [(128, 128)]
75 description['problem_params'] = problem_params # pass problem parameters
76 description['sweeper_class'] = generic_implicit # pass sweeper
77 description['sweeper_params'] = sweeper_params # pass sweeper parameters
78 elif variant == 'sl_parallel':
79 maxmeaniters = 5.125
80 assert MPI.COMM_WORLD.Get_size() == sweeper_params['num_nodes']
81 sweeper_params['QI'] = ['MIN3']
82 sweeper_params['comm'] = MPI.COMM_WORLD
83 problem_params['nvars'] = [(128, 128)]
84 description['problem_params'] = problem_params # pass problem parameters
85 description['sweeper_class'] = generic_implicit_MPI # pass sweeper
86 description['sweeper_params'] = sweeper_params # pass sweeper parameters
87 do_print = MPI.COMM_WORLD.Get_rank() == 0
88 elif variant == 'ml_serial':
89 maxmeaniters = 3.125
90 sweeper_params['QI'] = ['LU']
91 problem_params['nvars'] = [(128, 128), (64, 64)]
92 description['space_transfer_class'] = mesh_to_mesh_fft2d
93 description['problem_params'] = problem_params # pass problem parameters
94 description['sweeper_class'] = generic_implicit # pass sweeper
95 description['sweeper_params'] = sweeper_params # pass sweeper parameters
96 elif variant == 'ml_parallel':
97 assert MPI.COMM_WORLD.Get_size() == sweeper_params['num_nodes']
98 maxmeaniters = 4.25
99 sweeper_params['QI'] = ['MIN3']
100 sweeper_params['comm'] = MPI.COMM_WORLD
101 problem_params['nvars'] = [(128, 128), (64, 64)]
102 description['problem_params'] = problem_params # pass problem parameters
103 description['sweeper_class'] = generic_implicit_MPI # pass sweeper
104 description['sweeper_params'] = sweeper_params # pass sweeper parameters
105 description['space_transfer_class'] = mesh_to_mesh_fft2d
106 description['base_transfer_class'] = base_transfer_MPI
107 do_print = MPI.COMM_WORLD.Get_rank() == 0
108 else:
109 raise NotImplementedError('Wrong variant specified, got %s' % variant)
111 if do_print:
112 out = 'Working on %s variant...' % variant
113 print(out)
115 # setup parameters "in time"
116 t0 = 0
117 Tend = 0.004
119 # instantiate controller
120 controller = controller_nonMPI(num_procs=1, controller_params=controller_params, description=description)
122 # get initial values on finest level
123 P = controller.MS[0].levels[0].prob
124 uinit = P.u_exact(t0)
126 # call main function to get things done...
127 uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend)
129 # filter statistics by variant (number of iterations)
130 iter_counts = get_sorted(stats, type='niter', sortby='time')
132 # compute and print statistics
133 niters = np.array([item[1] for item in iter_counts])
135 if do_print:
136 out = ' Mean number of iterations: %4.2f' % np.mean(niters)
137 assert np.mean(niters) <= maxmeaniters, 'ERROR: number of iterations is too high, got %s instead of %s' % (
138 np.mean(niters),
139 maxmeaniters,
140 )
141 print(out)
142 out = ' Range of values for number of iterations: %2i ' % np.ptp(niters)
143 print(out)
144 out = ' Position of max/min number of iterations: %2i -- %2i' % (
145 int(np.argmax(niters)),
146 int(np.argmin(niters)),
147 )
148 print(out)
149 out = ' Std and var for number of iterations: %4.2f -- %4.2f' % (float(np.std(niters)), float(np.var(niters)))
150 print(out)
152 print(' Iteration count (nonlinear/linear): %i / %i' % (P.newton_itercount, P.lin_itercount))
153 print(
154 ' Mean Iteration count per call: %4.2f / %4.2f'
155 % (P.newton_itercount / max(P.newton_ncalls, 1), P.lin_itercount / max(P.lin_ncalls, 1))
156 )
158 timing = get_sorted(stats, type='timing_run', sortby='time')
160 print('Time to solution: %6.4f sec.' % timing[0][1])
162 return None
165def main():
166 """
167 Main driver
169 """
171 run_variant(variant='sl_serial')
172 print()
173 run_variant(variant='ml_serial')
174 print()
176 my_env = os.environ.copy()
177 my_env['PYTHONPATH'] = '../../..:.'
178 my_env['COVERAGE_PROCESS_START'] = 'pyproject.toml'
179 cmd = (
180 "mpirun -np 3 python -c \"from pySDC.projects.parallelSDC.AllenCahn_parallel import *; "
181 "run_variant(\'sl_parallel\');\""
182 )
183 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
184 p.wait()
185 for line in p.stdout:
186 print(line)
187 for line in p.stderr:
188 print(line)
189 assert p.returncode == 0, 'ERROR: did not get return code 0, got %s' % (p.returncode)
191 cmd = (
192 "mpirun -np 3 python -c \"from pySDC.projects.parallelSDC.AllenCahn_parallel import *; "
193 "run_variant(\'ml_parallel\');\""
194 )
195 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
196 p.wait()
197 for line in p.stdout:
198 print(line)
199 for line in p.stderr:
200 print(line)
201 assert p.returncode == 0, 'ERROR: did not get return code 0, got %s' % (p.returncode)
204if __name__ == "__main__":
205 main()