Skip to content

Commit e6f3dc3

Browse files
committed
Merge branch 'correct_residual'
2 parents 558b2b4 + c6c41a9 commit e6f3dc3

File tree

9 files changed

+211
-224
lines changed

9 files changed

+211
-224
lines changed

playgrounds/HeatEquation/periodic_playground.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,19 @@ def main():
2525
level_params = dict()
2626
level_params['restol'] = 1E-08
2727
level_params['dt'] = 1.0 / num_proc
28-
level_params['nsweeps'] = [3, 1]
28+
level_params['nsweeps'] = [3]
2929

3030
# initialize sweeper parameters
3131
sweeper_params = dict()
3232
sweeper_params['collocation_class'] = CollGaussRadau_Right
3333
sweeper_params['num_nodes'] = [3]
34-
sweeper_params['QI'] = ['LU2', 'LU'] # For the IMEX sweeper, the LU-trick can be activated for the implicit part
34+
sweeper_params['QI'] = ['LU'] # For the IMEX sweeper, the LU-trick can be activated for the implicit part
3535

3636
# initialize problem parameters
3737
problem_params = dict()
3838
problem_params['nu'] = 0.1 # diffusion coefficient
3939
problem_params['freq'] = -1 # frequency for the test value
40-
problem_params['nvars'] = [128, 64] # number of degrees of freedom for each level
40+
problem_params['nvars'] = [128] # number of degrees of freedom for each level
4141

4242
# initialize step parameters
4343
step_params = dict()

pySDC/core/Hooks.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ def post_sweep(self, step, level_number):
123123

124124
L = step.levels[level_number]
125125

126-
self.logger.info('Process %2i on time %8.6f at stage %15s: Level: %s -- Iteration: %2i -- Residual: %12.8e',
126+
self.logger.info('Process %2i on time %8.6f at stage %15s: Level: %s -- Iteration: %2i -- '
127+
'lagged residual: %12.8e',
127128
step.status.slot, L.time, step.status.stage, L.level_index, step.status.iter,
128129
L.status.residual)
129130

pySDC/implementations/controller_classes/allinclusive_classic_MPI.py

Lines changed: 41 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ def __init__(self, controller_params, description, comm):
4343

4444
num_levels = len(self.S.levels)
4545

46+
assert not (num_procs > 1 and num_levels == 1), "ERROR: classic cannot do MSSDC"
47+
4648
if num_procs > 1 and num_levels > 1:
4749
for L in self.S.levels:
4850
if not L.sweep.coll.right_is_node or L.sweep.params.do_coll_update:
@@ -136,7 +138,7 @@ def restart_block(self, size, time, u0):
136138
self.S.init_step(u0)
137139
# reset some values
138140
self.S.status.done = False
139-
self.S.status.iter = 1
141+
self.S.status.iter = 0
140142
self.S.status.stage = 'SPREAD'
141143
for l in self.S.levels:
142144
l.tag = None
@@ -237,67 +239,33 @@ def pfasst(self, comm, num_procs):
237239
# update stage
238240
if len(self.S.levels) > 1 and self.params.predict: # MLSDC or PFASST with predict
239241
self.S.status.stage = 'PREDICT'
240-
elif len(self.S.levels) > 1: # MLSDC or PFASST without predict
241-
self.hooks.pre_iteration(step=self.S, level_number=0)
242-
self.S.status.stage = 'IT_FINE'
243-
elif num_procs > 1: # MSSDC
244-
self.hooks.pre_iteration(step=self.S, level_number=0)
245-
self.S.status.stage = 'IT_COARSE'
246-
elif num_procs == 1: # SDC
247-
self.hooks.pre_iteration(step=self.S, level_number=0)
248-
self.S.status.stage = 'IT_FINE'
249242
else:
250-
raise ControllerError("Don't know what to do after spread, aborting")
243+
self.S.status.stage = 'IT_CHECK'
251244

252245
elif stage == 'PREDICT':
253246

254247
# call predictor (serial)
255248

256249
self.predictor(comm)
257250

258-
# update stage
259-
self.hooks.pre_iteration(step=self.S, level_number=0)
260-
self.S.status.stage = 'IT_FINE'
261-
262-
elif stage == 'IT_FINE':
263-
264-
# do fine sweep
265-
266-
# standard sweep workflow: update nodes, compute residual, log progress
267-
self.hooks.pre_sweep(step=self.S, level_number=0)
268-
for k in range(self.S.levels[0].params.nsweeps):
269-
self.S.levels[0].sweep.update_nodes()
270-
self.S.levels[0].sweep.compute_residual()
271-
self.hooks.post_sweep(step=self.S, level_number=0)
272-
273-
# wait for pending sends before computing uend, if any
274-
if len(self.req_send) > 0 and not self.S.status.last and self.params.fine_comm:
275-
self.req_send[0].wait()
276-
277-
self.S.levels[0].sweep.compute_end_point()
278-
279-
if not self.S.status.last and self.params.fine_comm:
280-
self.logger.debug('isend data: process %s, stage %s, time %s, target %s, tag %s, iter %s' %
281-
(self.S.status.slot, self.S.status.stage, self.S.time, self.S.next,
282-
0, self.S.status.iter))
283-
self.req_send.append(comm.isend(self.S.levels[0].uend, dest=self.S.next, tag=0))
284-
285251
# update stage
286252
self.S.status.stage = 'IT_CHECK'
287253

288254
elif stage == 'IT_CHECK':
289255

290256
# check whether to stop iterating (parallel)
291257

292-
self.hooks.post_iteration(step=self.S, level_number=0)
293-
294258
# check if an open request of the status send is pending
295259
if self.req_status is not None:
296260
self.req_status.wait()
297261

298262
# check for convergence or abort
263+
self.S.levels[0].sweep.compute_residual()
299264
self.S.status.done = self.check_convergence(self.S)
300265

266+
if self.S.status.iter > 0:
267+
self.hooks.post_iteration(step=self.S, level_number=0)
268+
301269
# send status forward
302270
if not self.S.status.last:
303271
self.logger.debug('isend status: status %s, process %s, time %s, target %s, tag %s, iter %s' %
@@ -318,21 +286,43 @@ def pfasst(self, comm, num_procs):
318286
# increment iteration count here (and only here)
319287
self.S.status.iter += 1
320288
self.hooks.pre_iteration(step=self.S, level_number=0)
321-
# multi-level or single-level?
322-
if len(self.S.levels) > 1: # MLSDC or PFASST
323-
self.S.status.stage = 'IT_UP'
324-
elif num_procs > 1: # MSSDC
325-
self.S.status.stage = 'IT_COARSE_RECV'
326-
elif num_procs == 1: # SDC
327-
self.S.status.stage = 'IT_FINE'
328-
else:
329-
raise ControllerError("Weird stage in IT_CHECK")
289+
self.S.status.stage = 'IT_FINE'
330290

331291
else:
332292
self.S.levels[0].sweep.compute_end_point()
333293
self.hooks.post_step(step=self.S, level_number=0)
334294
self.S.status.stage = 'DONE'
335295

296+
elif stage == 'IT_FINE':
297+
298+
# do fine sweep
299+
300+
# standard sweep workflow: update nodes, compute residual, log progress
301+
self.hooks.pre_sweep(step=self.S, level_number=0)
302+
for k in range(self.S.levels[0].params.nsweeps):
303+
self.S.levels[0].sweep.update_nodes()
304+
self.S.levels[0].sweep.compute_residual()
305+
self.hooks.post_sweep(step=self.S, level_number=0)
306+
307+
# wait for pending sends before computing uend, if any
308+
if len(self.req_send) > 0 and not self.S.status.last and self.params.fine_comm:
309+
self.req_send[0].wait()
310+
311+
self.S.levels[0].sweep.compute_end_point()
312+
313+
if not self.S.status.last and self.params.fine_comm:
314+
self.logger.debug('isend data: process %s, stage %s, time %s, target %s, tag %s, iter %s' %
315+
(self.S.status.slot, self.S.status.stage, self.S.time, self.S.next,
316+
0, self.S.status.iter))
317+
self.req_send.append(comm.isend(self.S.levels[0].uend, dest=self.S.next, tag=0))
318+
319+
# update stage
320+
# multi-level or single-level?
321+
if len(self.S.levels) > 1: # MLSDC or PFASST
322+
self.S.status.stage = 'IT_UP'
323+
else: # SDC
324+
self.S.status.stage = 'IT_CHECK'
325+
336326
elif stage == 'IT_UP':
337327

338328
# go up the hierarchy from finest to coarsest level (parallel)
@@ -397,10 +387,7 @@ def pfasst(self, comm, num_procs):
397387
self.send(source=self.S.levels[-1], target=self.S.next, tag=len(self.S.levels) - 1, comm=comm)
398388

399389
# update stage
400-
if len(self.S.levels) > 1: # MLSDC or PFASST
401-
self.S.status.stage = 'IT_DOWN'
402-
else: # MSSDC
403-
self.S.status.stage = 'IT_CHECK'
390+
self.S.status.stage = 'IT_DOWN'
404391

405392
elif stage == 'IT_DOWN':
406393

@@ -427,7 +414,7 @@ def pfasst(self, comm, num_procs):
427414
self.hooks.post_sweep(step=self.S, level_number=l - 1)
428415

429416
# update stage
430-
self.S.status.stage = 'IT_FINE'
417+
self.S.status.stage = 'IT_CHECK'
431418

432419
else:
433420

pySDC/implementations/controller_classes/allinclusive_classic_nonMPI.py

Lines changed: 39 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ def __init__(self, num_procs, controller_params, description):
3030
for p in range(num_procs):
3131
self.MS.append(stepclass.step(description))
3232

33+
assert not (len(self.MS) > 1 and len(self.MS[0].levels) == 1), "ERROR: classic cannot do MSSDC"
34+
3335
if self.params.dump_setup:
3436
self.dump_setup(step=self.MS[0], controller_params=controller_params, description=description)
3537

@@ -144,7 +146,7 @@ def restart_block(self, active_slots, time, u0):
144146
# reset some values
145147
self.MS[p].status.done = False
146148
self.MS[p].status.pred_cnt = active_slots.index(p) + 1
147-
self.MS[p].status.iter = 1
149+
self.MS[p].status.iter = 0
148150
self.MS[p].status.stage = 'SPREAD'
149151
for l in self.MS[p].levels:
150152
l.tag = False
@@ -216,17 +218,8 @@ def pfasst(self, S, num_procs):
216218
# update stage
217219
if len(S.levels) > 1 and self.params.predict: # MLSDC or PFASST with predict
218220
S.status.stage = 'PREDICT_RESTRICT'
219-
elif len(S.levels) > 1: # MLSDC or PFASST without predict
220-
self.hooks.pre_iteration(step=S, level_number=0)
221-
S.status.stage = 'IT_FINE_SWEEP'
222-
elif num_procs > 1: # MSSDC
223-
self.hooks.pre_iteration(step=S, level_number=0)
224-
S.status.stage = 'IT_COARSE_SWEEP'
225-
elif num_procs == 1: # SDC
226-
self.hooks.pre_iteration(step=S, level_number=0)
227-
S.status.stage = 'IT_FINE_SWEEP'
228-
else:
229-
raise ControllerError("Don't know what to do after spread, aborting")
221+
else: # SDC
222+
S.status.stage = 'IT_CHECK'
230223

231224
return S
232225

@@ -292,8 +285,34 @@ def pfasst(self, S, num_procs):
292285
S.transfer(source=S.levels[l], target=S.levels[l - 1])
293286

294287
# update stage and return
295-
self.hooks.pre_iteration(step=S, level_number=0)
296-
S.status.stage = 'IT_FINE_SWEEP'
288+
S.status.stage = 'IT_CHECK'
289+
return S
290+
291+
elif stage == 'IT_CHECK':
292+
293+
# check whether to stop iterating
294+
295+
S.levels[0].sweep.compute_residual()
296+
S.status.done = self.check_convergence(S)
297+
298+
if S.status.iter > 0:
299+
self.hooks.post_iteration(step=S, level_number=0)
300+
301+
# if the previous step is still iterating but I am done, un-do me to still forward values
302+
if not S.status.first and S.status.done and (S.prev.status.done is not None and not S.prev.status.done):
303+
S.status.done = False
304+
305+
# if I am done, signal accordingly, otherwise proceed
306+
if S.status.done:
307+
S.levels[0].sweep.compute_end_point()
308+
self.hooks.post_step(step=S, level_number=0)
309+
S.status.stage = 'DONE'
310+
else:
311+
# increment iteration count here (and only here)
312+
S.status.iter += 1
313+
self.hooks.pre_iteration(step=S, level_number=0)
314+
S.status.stage = 'IT_FINE_SWEEP'
315+
# return
297316
return S
298317

299318
elif stage == 'IT_FINE_SWEEP':
@@ -321,39 +340,12 @@ def pfasst(self, S, num_procs):
321340
self.logger.debug('Process %2i provides data on level %2i with tag %s'
322341
% (S.status.slot, 0, True))
323342
self.send(S.levels[0], tag=True)
324-
S.status.stage = 'IT_CHECK'
325-
else:
326-
S.status.stage = 'IT_FINE_SEND'
327-
# return
328-
return S
329-
330-
elif stage == 'IT_CHECK':
331-
332-
# check whether to stop iterating
333-
334-
self.hooks.post_iteration(step=S, level_number=0)
335-
336-
S.status.done = self.check_convergence(S)
337-
338-
# if the previous step is still iterating but I am done, un-do me to still forward values
339-
if not S.status.first and S.status.done and (S.prev.status.done is not None and not S.prev.status.done):
340-
S.status.done = False
341-
342-
# if I am done, signal accordingly, otherwise proceed
343-
if S.status.done:
344-
S.levels[0].sweep.compute_end_point()
345-
self.hooks.post_step(step=S, level_number=0)
346-
S.status.stage = 'DONE'
347-
else:
348-
# increment iteration count here (and only here)
349-
S.status.iter += 1
350-
self.hooks.pre_iteration(step=S, level_number=0)
351343
if len(S.levels) > 1:
352344
S.status.stage = 'IT_UP'
353-
elif num_procs > 1: # MSSDC
354-
S.status.stage = 'IT_COARSE_RECV'
355-
elif num_procs == 1: # SDC
356-
S.status.stage = 'IT_FINE_SWEEP'
345+
else: # SDC
346+
S.status.stage = 'IT_CHECK'
347+
else:
348+
S.status.stage = 'IT_FINE_SEND'
357349
# return
358350
return S
359351

@@ -422,7 +414,6 @@ def pfasst(self, S, num_procs):
422414
for k in range(S.levels[-1].params.nsweeps):
423415
S.levels[-1].sweep.update_nodes()
424416
S.levels[-1].sweep.compute_residual()
425-
426417
self.hooks.post_sweep(step=S, level_number=len(S.levels) - 1)
427418

428419
# update stage and return
@@ -438,10 +429,7 @@ def pfasst(self, S, num_procs):
438429
% (S.status.slot, len(S.levels) - 1, True))
439430
self.send(S.levels[-1], tag=True)
440431
# update stage
441-
if len(S.levels) > 1: # MLSDC or PFASST
442-
S.status.stage = 'IT_DOWN'
443-
else: # MSSDC
444-
S.status.stage = 'IT_CHECK'
432+
S.status.stage = 'IT_DOWN'
445433
else:
446434
S.status.stage = 'IT_COARSE_SEND'
447435
# return
@@ -475,7 +463,7 @@ def pfasst(self, S, num_procs):
475463
self.hooks.post_sweep(step=S, level_number=l - 1)
476464

477465
# update stage and return
478-
S.status.stage = 'IT_FINE_SWEEP'
466+
S.status.stage = 'IT_CHECK'
479467
return S
480468

481469
else:

0 commit comments

Comments
 (0)