Coverage for pySDC/tutorial/step_7/B_pySDC_with_mpi4pyfft.py: 100%

88 statements  

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

1import numpy as np 

2from pathlib import Path 

3from mpi4py import MPI 

4 

5from pySDC.helpers.stats_helper import get_sorted 

6 

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 

11 

12 

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 

16 

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 """ 

22 

23 comm = MPI.COMM_WORLD 

24 rank = comm.Get_rank() 

25 

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] 

31 

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' 

38 

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 

47 

48 # initialize step parameters 

49 step_params = dict() 

50 step_params['maxiter'] = 50 

51 

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' 

56 

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 

66 

67 # set time parameters 

68 t0 = 0.0 

69 Tend = 1.0 

70 

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) 

78 

79 # instantiate controller 

80 controller = controller_nonMPI(num_procs=num_procs, controller_params=controller_params, description=description) 

81 

82 # get initial values on finest level 

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

84 uinit = P.u_exact(t0) 

85 

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) 

90 

91 if rank == 0: 

92 # filter statistics by type (number of iterations) 

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

94 

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) 

114 

115 out = f'Error: {err:6.4e}' 

116 f.write(out + '\n') 

117 print(out) 

118 

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) 

123 

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) 

133 

134 f.write('\n') 

135 print() 

136 f.close() 

137 

138 

139def main(): 

140 """ 

141 Little helper routine to run the whole thing 

142 

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) 

151 

152 

153if __name__ == "__main__": 

154 main()