Coverage for pySDC/implementations/hooks/default_hook.py: 100%
93 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-20 16:55 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-20 16:55 +0000
1import time
2from pySDC.core.hooks import Hooks
5class DefaultHooks(Hooks):
6 """
7 Hook class to contain the functions called during the controller runs (e.g. for calling user-routines)
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 """
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 = []
43 def pre_setup(self, step, level_number):
44 """
45 Default routine called before setup starts
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()
54 def pre_run(self, step, level_number):
55 """
56 Default routine called before time-loop starts
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()
65 def pre_predict(self, step, level_number):
66 """
67 Default routine called before predictor starts
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()
76 def pre_step(self, step, level_number):
77 """
78 Hook called before each step
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()
87 def pre_iteration(self, step, level_number):
88 """
89 Default routine called before iteration starts
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()
98 def pre_sweep(self, step, level_number):
99 """
100 Default routine called before sweep starts
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()
109 def pre_comm(self, step, level_number):
110 """
111 Default routine called before communication starts
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
129 def post_comm(self, step, level_number, add_to_stats=False):
130 """
131 Default routine called after each communication
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]
142 if add_to_stats:
143 L = step.levels[level_number]
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
157 def post_sweep(self, step, level_number):
158 """
159 Default routine called after each sweep
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()
168 L = step.levels[level_number]
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 )
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 )
202 def post_iteration(self, step, level_number):
203 """
204 Default routine called after each iteration
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()
213 L = step.levels[level_number]
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 )
236 def post_step(self, step, level_number):
237 """
238 Default routine called after each step or block
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()
247 L = step.levels[level_number]
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 )
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 )
293 def post_predict(self, step, level_number):
294 """
295 Default routine called after each predictor
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()
304 L = step.levels[level_number]
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 )
317 def post_run(self, step, level_number):
318 """
319 Default routine called after each run
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()
328 L = step.levels[level_number]
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')
342 def post_setup(self, step, level_number):
343 """
344 Default routine called after setup
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()
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 )