Coverage for pySDC/implementations/hooks/default_hook.py: 100%

93 statements  

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

1import time 

2from pySDC.core.Hooks import hooks 

3 

4 

5class DefaultHooks(hooks): 

6 """ 

7 Hook class to contain the functions called during the controller runs (e.g. for calling user-routines) 

8 

9 Attributes: 

10 __t0_setup (float): private variable to get starting time of setup 

11 __t0_run (float): private variable to get starting time of the run 

12 __t0_predict (float): private variable to get starting time of the predictor 

13 __t0_step (float): private variable to get starting time of the step 

14 __t0_iteration (float): private variable to get starting time of the iteration 

15 __t0_sweep (float): private variable to get starting time of the sweep 

16 __t0_comm (list): private variable to get starting time of the communication 

17 __t1_run (float): private variable to get end time of the run 

18 __t1_predict (float): private variable to get end time of the predictor 

19 __t1_step (float): private variable to get end time of the step 

20 __t1_iteration (float): private variable to get end time of the iteration 

21 __t1_sweep (float): private variable to get end time of the sweep 

22 __t1_setup (float): private variable to get end time of setup 

23 __t1_comm (list): private variable to hold timing of the communication (!) 

24 """ 

25 

26 def __init__(self): 

27 super().__init__() 

28 self.__t0_setup = None 

29 self.__t0_run = None 

30 self.__t0_predict = None 

31 self.__t0_step = None 

32 self.__t0_iteration = None 

33 self.__t0_sweep = None 

34 self.__t0_comm = [] 

35 self.__t1_run = None 

36 self.__t1_predict = None 

37 self.__t1_step = None 

38 self.__t1_iteration = None 

39 self.__t1_sweep = None 

40 self.__t1_setup = None 

41 self.__t1_comm = [] 

42 

43 def pre_setup(self, step, level_number): 

44 """ 

45 Default routine called before setup starts 

46 

47 Args: 

48 step (pySDC.Step.step): the current step 

49 level_number (int): the current level number 

50 """ 

51 super().pre_setup(step, level_number) 

52 self.__t0_setup = time.perf_counter() 

53 

54 def pre_run(self, step, level_number): 

55 """ 

56 Default routine called before time-loop starts 

57 

58 Args: 

59 step (pySDC.Step.step): the current step 

60 level_number (int): the current level number 

61 """ 

62 super().pre_run(step, level_number) 

63 self.__t0_run = time.perf_counter() 

64 

65 def pre_predict(self, step, level_number): 

66 """ 

67 Default routine called before predictor starts 

68 

69 Args: 

70 step (pySDC.Step.step): the current step 

71 level_number (int): the current level number 

72 """ 

73 super().pre_predict(step, level_number) 

74 self.__t0_predict = time.perf_counter() 

75 

76 def pre_step(self, step, level_number): 

77 """ 

78 Hook called before each step 

79 

80 Args: 

81 step (pySDC.Step.step): the current step 

82 level_number (int): the current level number 

83 """ 

84 super().pre_step(step, level_number) 

85 self.__t0_step = time.perf_counter() 

86 

87 def pre_iteration(self, step, level_number): 

88 """ 

89 Default routine called before iteration starts 

90 

91 Args: 

92 step (pySDC.Step.step): the current step 

93 level_number (int): the current level number 

94 """ 

95 super().pre_iteration(step, level_number) 

96 self.__t0_iteration = time.perf_counter() 

97 

98 def pre_sweep(self, step, level_number): 

99 """ 

100 Default routine called before sweep starts 

101 

102 Args: 

103 step (pySDC.Step.step): the current step 

104 level_number (int): the current level number 

105 """ 

106 super().pre_sweep(step, level_number) 

107 self.__t0_sweep = time.perf_counter() 

108 

109 def pre_comm(self, step, level_number): 

110 """ 

111 Default routine called before communication starts 

112 

113 Args: 

114 step (pySDC.Step.step): the current step 

115 level_number (int): the current level number 

116 """ 

117 super().pre_comm(step, level_number) 

118 if len(self.__t0_comm) >= level_number + 1: 

119 self.__t0_comm[level_number] = time.perf_counter() 

120 else: 

121 while len(self.__t0_comm) < level_number: 

122 self.__t0_comm.append(None) 

123 self.__t0_comm.append(time.perf_counter()) 

124 while len(self.__t1_comm) <= level_number: 

125 self.__t1_comm.append(0.0) 

126 assert len(self.__t0_comm) == level_number + 1 

127 assert len(self.__t1_comm) == level_number + 1 

128 

129 def post_comm(self, step, level_number, add_to_stats=False): 

130 """ 

131 Default routine called after each communication 

132 

133 Args: 

134 step (pySDC.Step.step): the current step 

135 level_number (int): the current level number 

136 add_to_stats (bool): set if result should go to stats object 

137 """ 

138 super().post_comm(step, level_number) 

139 assert len(self.__t1_comm) >= level_number + 1 

140 self.__t1_comm[level_number] += time.perf_counter() - self.__t0_comm[level_number] 

141 

142 if add_to_stats: 

143 L = step.levels[level_number] 

144 

145 self.add_to_stats( 

146 process=step.status.slot, 

147 process_sweeper=L.sweep.rank, 

148 time=L.time, 

149 level=L.level_index, 

150 iter=step.status.iter, 

151 sweep=L.status.sweep, 

152 type='timing_comm', 

153 value=self.__t1_comm[level_number], 

154 ) 

155 self.__t1_comm[level_number] = 0.0 

156 

157 def post_sweep(self, step, level_number): 

158 """ 

159 Default routine called after each sweep 

160 

161 Args: 

162 step (pySDC.Step.step): the current step 

163 level_number (int): the current level number 

164 """ 

165 super().post_sweep(step, level_number) 

166 self.__t1_sweep = time.perf_counter() 

167 

168 L = step.levels[level_number] 

169 

170 self.logger.info( 

171 'Process %2i on time %8.6f at stage %15s: Level: %s -- Iteration: %2i -- Sweep: %2i -- ' 'residual: %12.8e', 

172 step.status.slot, 

173 L.time, 

174 step.status.stage, 

175 L.level_index, 

176 step.status.iter, 

177 L.status.sweep, 

178 L.status.residual, 

179 ) 

180 

181 self.add_to_stats( 

182 process=step.status.slot, 

183 process_sweeper=L.sweep.rank, 

184 time=L.time, 

185 level=L.level_index, 

186 iter=step.status.iter, 

187 sweep=L.status.sweep, 

188 type='residual_post_sweep', 

189 value=L.status.residual, 

190 ) 

191 self.add_to_stats( 

192 process=step.status.slot, 

193 process_sweeper=L.sweep.rank, 

194 time=L.time, 

195 level=L.level_index, 

196 iter=step.status.iter, 

197 sweep=L.status.sweep, 

198 type='timing_sweep', 

199 value=self.__t1_sweep - self.__t0_sweep, 

200 ) 

201 

202 def post_iteration(self, step, level_number): 

203 """ 

204 Default routine called after each iteration 

205 

206 Args: 

207 step (pySDC.Step.step): the current step 

208 level_number (int): the current level number 

209 """ 

210 super().post_iteration(step, level_number) 

211 self.__t1_iteration = time.perf_counter() 

212 

213 L = step.levels[level_number] 

214 

215 self.add_to_stats( 

216 process=step.status.slot, 

217 process_sweeper=L.sweep.rank, 

218 time=L.time, 

219 level=-1, 

220 iter=step.status.iter, 

221 sweep=L.status.sweep, 

222 type='residual_post_iteration', 

223 value=L.status.residual, 

224 ) 

225 self.add_to_stats( 

226 process=step.status.slot, 

227 process_sweeper=L.sweep.rank, 

228 time=L.time, 

229 level=L.level_index, 

230 iter=step.status.iter, 

231 sweep=L.status.sweep, 

232 type='timing_iteration', 

233 value=self.__t1_iteration - self.__t0_iteration, 

234 ) 

235 

236 def post_step(self, step, level_number): 

237 """ 

238 Default routine called after each step or block 

239 

240 Args: 

241 step (pySDC.Step.step): the current step 

242 level_number (int): the current level number 

243 """ 

244 super().post_step(step, level_number) 

245 self.__t1_step = time.perf_counter() 

246 

247 L = step.levels[level_number] 

248 

249 self.add_to_stats( 

250 process=step.status.slot, 

251 process_sweeper=L.sweep.rank, 

252 time=L.time, 

253 level=L.level_index, 

254 iter=step.status.iter, 

255 sweep=L.status.sweep, 

256 type='timing_step', 

257 value=self.__t1_step - self.__t0_step, 

258 ) 

259 self.add_to_stats( 

260 process=step.status.slot, 

261 process_sweeper=L.sweep.rank, 

262 time=L.time, 

263 level=-1, 

264 iter=step.status.iter, 

265 sweep=L.status.sweep, 

266 type='niter', 

267 value=step.status.iter, 

268 ) 

269 self.add_to_stats( 

270 process=step.status.slot, 

271 process_sweeper=L.sweep.rank, 

272 time=L.time, 

273 level=L.level_index, 

274 iter=-1, 

275 sweep=L.status.sweep, 

276 type='residual_post_step', 

277 value=L.status.residual, 

278 ) 

279 

280 # record the recomputed quantities at weird positions to make sure there is only one value for each step 

281 for t in [L.time, L.time + L.dt]: 

282 self.add_to_stats( 

283 process=-1, 

284 time=t, 

285 level=-1, 

286 iter=-1, 

287 sweep=-1, 

288 type='_recomputed', 

289 value=step.status.get('restart'), 

290 process_sweeper=-1, 

291 ) 

292 

293 def post_predict(self, step, level_number): 

294 """ 

295 Default routine called after each predictor 

296 

297 Args: 

298 step (pySDC.Step.step): the current step 

299 level_number (int): the current level number 

300 """ 

301 super().post_predict(step, level_number) 

302 self.__t1_predict = time.perf_counter() 

303 

304 L = step.levels[level_number] 

305 

306 self.add_to_stats( 

307 process=step.status.slot, 

308 process_sweeper=L.sweep.rank, 

309 time=L.time, 

310 level=L.level_index, 

311 iter=step.status.iter, 

312 sweep=L.status.sweep, 

313 type='timing_predictor', 

314 value=self.__t1_predict - self.__t0_predict, 

315 ) 

316 

317 def post_run(self, step, level_number): 

318 """ 

319 Default routine called after each run 

320 

321 Args: 

322 step (pySDC.Step.step): the current step 

323 level_number (int): the current level number 

324 """ 

325 super().post_run(step, level_number) 

326 self.__t1_run = time.perf_counter() 

327 

328 L = step.levels[level_number] 

329 

330 self.add_to_stats( 

331 process=step.status.slot, 

332 process_sweeper=L.sweep.rank, 

333 time=L.time, 

334 level=L.level_index, 

335 iter=step.status.iter, 

336 sweep=L.status.sweep, 

337 type='timing_run', 

338 value=self.__t1_run - self.__t0_run, 

339 ) 

340 self.logger.info(f'Finished run after {self.__t1_run - self.__t0_run:.2f}s') 

341 

342 def post_setup(self, step, level_number): 

343 """ 

344 Default routine called after setup 

345 

346 Args: 

347 step (pySDC.Step.step): the current step 

348 level_number (int): the current level number 

349 """ 

350 super().post_setup(step, level_number) 

351 self.__t1_setup = time.perf_counter() 

352 

353 self.add_to_stats( 

354 process=-1, 

355 process_sweeper=-1, 

356 time=-1, 

357 level=-1, 

358 iter=-1, 

359 sweep=-1, 

360 type='timing_setup', 

361 value=self.__t1_setup - self.__t0_setup, 

362 )