Coverage for pySDC/projects/parallelSDC/AllenCahn_parallel.py: 85%

112 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-04-29 09:02 +0000

1import subprocess 

2import os 

3 

4import numpy as np 

5from mpi4py import MPI 

6 

7from pySDC.helpers.stats_helper import get_sorted 

8 

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.projects.parallelSDC.BaseTransfer_MPI import base_transfer_MPI 

15from pySDC.implementations.sweeper_classes.generic_implicit_MPI import generic_implicit_MPI 

16 

17 

18# http://www.personal.psu.edu/qud2/Res/Pre/dz09sisc.pdf 

19 

20 

21def run_variant(variant=None): 

22 """ 

23 Routine to run a particular variant 

24 

25 Args: 

26 variant (str): string describing the variant 

27 

28 """ 

29 

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 

35 

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' 

41 

42 # This comes as read-in for the problem class 

43 problem_params = dict() 

44 problem_params['nu'] = 2 

45 

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 

52 

53 # initialize step parameters 

54 step_params = dict() 

55 step_params['maxiter'] = 50 

56 

57 # initialize controller parameters 

58 controller_params = dict() 

59 controller_params['logger_level'] = 30 

60 controller_params['hook_class'] = monitor 

61 

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 

67 

68 do_print = True 

69 

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) 

110 

111 if do_print: 

112 out = 'Working on %s variant...' % variant 

113 print(out) 

114 

115 # setup parameters "in time" 

116 t0 = 0 

117 Tend = 0.004 

118 

119 # instantiate controller 

120 controller = controller_nonMPI(num_procs=1, controller_params=controller_params, description=description) 

121 

122 # get initial values on finest level 

123 P = controller.MS[0].levels[0].prob 

124 uinit = P.u_exact(t0) 

125 

126 # call main function to get things done... 

127 uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) 

128 

129 # filter statistics by variant (number of iterations) 

130 iter_counts = get_sorted(stats, type='niter', sortby='time') 

131 

132 # compute and print statistics 

133 niters = np.array([item[1] for item in iter_counts]) 

134 

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) 

151 

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 ) 

157 

158 timing = get_sorted(stats, type='timing_run', sortby='time') 

159 

160 print('Time to solution: %6.4f sec.' % timing[0][1]) 

161 

162 return None 

163 

164 

165def main(): 

166 """ 

167 Main driver 

168 

169 """ 

170 

171 run_variant(variant='sl_serial') 

172 print() 

173 run_variant(variant='ml_serial') 

174 print() 

175 

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) 

190 

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) 

202 

203 

204if __name__ == "__main__": 

205 main()