1+ from argparse import ArgumentParser
2+ import numpy as np
3+ from mpi4py import MPI
4+
5+ from pySDC .helpers .stats_helper import filter_stats , sort_stats
6+ from pySDC .implementations .collocation_classes .gauss_radau_right import CollGaussRadau_Right
7+ from pySDC .implementations .controller_classes .controller_nonMPI import controller_nonMPI
8+ from pySDC .implementations .sweeper_classes .imex_1st_order import imex_1st_order
9+ from pySDC .implementations .problem_classes .AllenCahn_Temp_MPIFFT import allencahn_temp_imex
10+
11+ from pySDC .projects .AllenCahn_Bayreuth .AllenCahn_dump import dump
12+
13+
14+ def run_simulation (name = '' , spectral = None , nprocs_space = None ):
15+ """
16+ A test program to create reference data for the AC equation with temporal forcing
17+ Args:
18+ name (str): name of the run, will be used to distinguish different setups
19+ spectral (bool): run in real or spectral space
20+ nprocs_space (int): number of processors in space (None if serial)
21+ """
22+
23+ # set MPI communicator
24+ comm = MPI .COMM_WORLD
25+
26+ world_rank = comm .Get_rank ()
27+ world_size = comm .Get_size ()
28+
29+ # split world communicator to create space-communicators
30+ if nprocs_space is not None :
31+ color = int (world_rank / nprocs_space )
32+ else :
33+ color = int (world_rank / 1 )
34+ space_comm = comm .Split (color = color )
35+ space_rank = space_comm .Get_rank ()
36+ space_size = space_comm .Get_size ()
37+
38+ assert world_size == space_size , 'This script cannot run parallel-in-time with MPI, only spatial parallelism'
39+
40+ # initialize level parameters
41+ level_params = dict ()
42+ level_params ['restol' ] = 1E-12
43+ level_params ['dt' ] = 1E-03
44+ level_params ['nsweeps' ] = [1 ]
45+
46+ # initialize sweeper parameters
47+ sweeper_params = dict ()
48+ sweeper_params ['collocation_class' ] = CollGaussRadau_Right
49+ sweeper_params ['num_nodes' ] = [7 ]
50+ sweeper_params ['QI' ] = ['LU' ] # For the IMEX sweeper, the LU-trick can be activated for the implicit part
51+ sweeper_params ['initial_guess' ] = 'spread'
52+
53+ # initialize problem parameters
54+ problem_params = dict ()
55+ problem_params ['L' ] = 1.0
56+ problem_params ['nvars' ] = [(128 , 128 )]
57+ problem_params ['eps' ] = [0.03 ]
58+ problem_params ['radius' ] = 0.35682
59+ problem_params ['TM' ] = 1.0
60+ problem_params ['D' ] = 10.0
61+ problem_params ['dw' ] = [1.0 ]
62+ problem_params ['comm' ] = space_comm
63+ problem_params ['name' ] = name
64+ problem_params ['init_type' ] = 'circle'
65+ problem_params ['spectral' ] = spectral
66+
67+ # initialize step parameters
68+ step_params = dict ()
69+ step_params ['maxiter' ] = 50
70+
71+ # initialize controller parameters
72+ controller_params = dict ()
73+ controller_params ['logger_level' ] = 20 if space_rank == 0 else 99 # set level depending on rank
74+ controller_params ['hook_class' ] = dump
75+
76+ # fill description dictionary for easy step instantiation
77+ description = dict ()
78+ description ['problem_params' ] = problem_params # pass problem parameters
79+ description ['sweeper_class' ] = imex_1st_order
80+ description ['sweeper_params' ] = sweeper_params # pass sweeper parameters
81+ description ['level_params' ] = level_params # pass level parameters
82+ description ['step_params' ] = step_params # pass step parameters
83+ description ['problem_class' ] = allencahn_temp_imex
84+
85+ # set time parameters
86+ t0 = 0.0
87+ Tend = 100 * 0.001
88+
89+ if space_rank == 0 :
90+ out = f'---------> Running { name } with spectral={ spectral } and { space_size } process(es) in space...'
91+ print (out )
92+
93+ # instantiate controller
94+ controller = controller_nonMPI (num_procs = 1 , controller_params = controller_params , description = description )
95+
96+ # get initial values on finest level
97+ P = controller .MS [0 ].levels [0 ].prob
98+ uinit = P .u_exact (t0 )
99+
100+ # call main function to get things done...
101+ uend , stats = controller .run (u0 = uinit , t0 = t0 , Tend = Tend )
102+
103+ if space_rank == 0 :
104+
105+ print ()
106+
107+ # convert filtered statistics of iterations count, sorted by time
108+ iter_counts = sort_stats (filter_stats (stats , type = 'niter' ), sortby = 'time' )
109+ niters = np .mean (np .array ([item [1 ] for item in iter_counts ]))
110+ out = f'Mean number of iterations: { niters :.4f} '
111+ print (out )
112+
113+ # get setup time
114+ timing = sort_stats (filter_stats (stats , type = 'timing_setup' ), sortby = 'time' )
115+ out = f'Setup time: { timing [0 ][1 ]:.4f} sec.'
116+ print (out )
117+
118+ # get running time
119+ timing = sort_stats (filter_stats (stats , type = 'timing_run' ), sortby = 'time' )
120+ out = f'Time to solution: { timing [0 ][1 ]:.4f} sec.'
121+ print (out )
122+
123+ out = '...Done <---------\n '
124+ print (out )
125+
126+
127+ def main (nprocs_space = None ):
128+ """
129+ Little helper routine to run the whole thing
130+ Args:
131+ nprocs_space (int): number of processors in space (None if serial)
132+ """
133+ name = 'AC-realistic-tempforce'
134+ run_simulation (name = name , spectral = False , nprocs_space = nprocs_space )
135+ # run_simulation(name=name, spectral=True, nprocs_space=nprocs_space)
136+
137+
138+ if __name__ == "__main__" :
139+
140+ # Add parser to get number of processors in space (have to do this here to enable automatic testing)
141+ parser = ArgumentParser ()
142+ parser .add_argument ("-n" , "--nprocs_space" , help = 'Specifies the number of processors in space' , type = int )
143+ args = parser .parse_args ()
144+
145+ main (nprocs_space = args .nprocs_space )
0 commit comments