Coverage for pySDC/tutorial/step_7/C_pySDC_with_PETSc.py: 97%

95 statements  

« prev     ^ index     » next       coverage.py v7.6.9, created at 2024-12-20 14:51 +0000

1import sys 

2from pathlib import Path 

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_MPI import controller_MPI 

10from pySDC.implementations.problem_classes.HeatEquation_2D_PETSc_forced import heat2d_petsc_forced 

11from pySDC.implementations.sweeper_classes.imex_1st_order import imex_1st_order 

12from pySDC.implementations.transfer_classes.TransferPETScDMDA import mesh_to_mesh_petsc_dmda 

13 

14 

15def main(): 

16 """ 

17 Program to demonstrate usage of PETSc data structures and spatial parallelization, 

18 combined with parallelization in time. 

19 """ 

20 # set MPI communicator 

21 comm = MPI.COMM_WORLD 

22 

23 world_rank = comm.Get_rank() 

24 world_size = comm.Get_size() 

25 

26 # split world communicator to create space-communicators 

27 if len(sys.argv) >= 2: 

28 color = int(world_rank / int(sys.argv[1])) 

29 else: 

30 color = int(world_rank / 1) 

31 space_comm = comm.Split(color=color) 

32 space_rank = space_comm.Get_rank() 

33 

34 # split world communicator to create time-communicators 

35 if len(sys.argv) >= 2: 

36 color = int(world_rank % int(sys.argv[1])) 

37 else: 

38 color = int(world_rank / world_size) 

39 time_comm = comm.Split(color=color) 

40 time_rank = time_comm.Get_rank() 

41 

42 # initialize level parameters 

43 level_params = dict() 

44 level_params['restol'] = 1e-08 

45 level_params['dt'] = 0.125 

46 level_params['nsweeps'] = [1] 

47 

48 # initialize sweeper parameters 

49 sweeper_params = dict() 

50 sweeper_params['quad_type'] = 'RADAU-RIGHT' 

51 sweeper_params['num_nodes'] = [3] 

52 sweeper_params['QI'] = ['LU'] # For the IMEX sweeper, the LU-trick can be activated for the implicit part 

53 sweeper_params['initial_guess'] = 'zero' 

54 

55 # initialize problem parameters 

56 problem_params = dict() 

57 problem_params['nu'] = 1.0 # diffusion coefficient 

58 problem_params['freq'] = 2 # frequency for the test value 

59 problem_params['cnvars'] = [(65, 65)] # number of degrees of freedom for the coarsest level 

60 problem_params['refine'] = [1, 0] # number of refinements 

61 problem_params['comm'] = space_comm # pass space-communicator to problem class 

62 problem_params['sol_tol'] = 1e-12 # set tolerance to PETSc' linear solver 

63 

64 # initialize step parameters 

65 step_params = dict() 

66 step_params['maxiter'] = 50 

67 

68 # initialize space transfer parameters 

69 space_transfer_params = dict() 

70 space_transfer_params['rorder'] = 2 

71 space_transfer_params['iorder'] = 2 

72 space_transfer_params['periodic'] = False 

73 

74 # initialize controller parameters 

75 controller_params = dict() 

76 controller_params['logger_level'] = 20 if space_rank == 0 else 99 # set level depending on rank 

77 controller_params['dump_setup'] = False 

78 

79 # fill description dictionary for easy step instantiation 

80 description = dict() 

81 description['problem_class'] = heat2d_petsc_forced # pass problem class 

82 description['problem_params'] = problem_params # pass problem parameters 

83 description['sweeper_class'] = imex_1st_order # pass sweeper (see part B) 

84 description['sweeper_params'] = sweeper_params # pass sweeper parameters 

85 description['level_params'] = level_params # pass level parameters 

86 description['step_params'] = step_params # pass step parameters 

87 description['space_transfer_class'] = mesh_to_mesh_petsc_dmda # pass spatial transfer class 

88 description['space_transfer_params'] = space_transfer_params # pass parameters for spatial transfer 

89 

90 # set time parameters 

91 t0 = 0.0 

92 Tend = 0.25 

93 

94 # instantiate controller 

95 controller = controller_MPI(controller_params=controller_params, description=description, comm=time_comm) 

96 

97 # get initial values on finest level 

98 P = controller.S.levels[0].prob 

99 uinit = P.u_exact(t0) 

100 

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

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

103 

104 # compute exact solution and compare 

105 uex = P.u_exact(Tend) 

106 err = abs(uex - uend) 

107 

108 # filter statistics by type (number of iterations) 

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

110 

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

112 

113 # limit output to space-rank 0 (as before when setting the logger level) 

114 if space_rank == 0: 

115 if len(sys.argv) == 3: 

116 fname = str(sys.argv[2]) 

117 else: 

118 fname = 'step_7_C_out.txt' 

119 Path("data").mkdir(parents=True, exist_ok=True) 

120 f = open('data/' + fname, 'a+') 

121 

122 out = 'This is time-rank %i...' % time_rank 

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

124 print(out) 

125 

126 # compute and print statistics 

127 for item in iter_counts: 

128 out = 'Number of iterations for time %4.2f: %2i' % item 

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

130 print(out) 

131 

132 out = ' Mean number of iterations: %4.2f' % np.mean(niters) 

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

134 print(out) 

135 out = ' Range of values for number of iterations: %2i ' % np.ptp(niters) 

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

137 print(out) 

138 out = ' Position of max/min number of iterations: %2i -- %2i' % ( 

139 int(np.argmax(niters)), 

140 int(np.argmin(niters)), 

141 ) 

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

143 print(out) 

144 out = ' Std and var for number of iterations: %4.2f -- %4.2f' % (float(np.std(niters)), float(np.var(niters))) 

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

146 print(out) 

147 

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

149 

150 out = 'Time to solution: %6.4f sec.' % timing[0][1] 

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

152 print(out) 

153 out = 'Error vs. PDE solution: %6.4e' % err 

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

155 print(out) 

156 

157 f.close() 

158 

159 assert err < 2e-04, 'ERROR: did not match error tolerance, got %s' % err 

160 assert np.mean(niters) <= 12, 'ERROR: number of iterations is too high, got %s' % np.mean(niters) 

161 

162 space_comm.Free() 

163 time_comm.Free() 

164 

165 

166if __name__ == "__main__": 

167 main()