Part B: Odd temporal distribution#

Accidentally, the numbers of parallel processes used in Part A are always divisors of the number of steps. Yet, this does not need to be the case. All controllers can handle odd distributions, e.g. too few or too many processes for the steps, or for the last block. We run the multi-level setup of Part A again, with 3, 5, 7 and 9 processes for the 8 time steps.

import matplotlib.pyplot as plt

from pySDC.tutorial.step_6.pfasst_setup import run_pfasst

iterations = run_pfasst(num_proc_list=[3, 5, 7, 9], fname='step_6_B_out.txt', multi_level=True)
Working with  3 processes...
Error vs. exact solution: 2.87358935e-07
Number of iterations for time 0.00: 5 
Number of iterations for time 0.12: 5 
Number of iterations for time 0.25: 5 
Number of iterations for time 0.38: 4 
Number of iterations for time 0.50: 4 
Number of iterations for time 0.62: 4 
Number of iterations for time 0.75: 4 
Number of iterations for time 0.88: 4 

Working with  5 processes...
Error vs. exact solution: 2.87358097e-07
Number of iterations for time 0.00: 6 
Number of iterations for time 0.12: 6 
Number of iterations for time 0.25: 6 
Number of iterations for time 0.38: 6 
Number of iterations for time 0.50: 6 
Number of iterations for time 0.62: 4 
Number of iterations for time 0.75: 4 
Number of iterations for time 0.88: 4 

Working with  7 processes...
Error vs. exact solution: 2.87271747e-07
Number of iterations for time 0.00: 7 
Number of iterations for time 0.12: 7 
Number of iterations for time 0.25: 7 
Number of iterations for time 0.38: 7 
Number of iterations for time 0.50: 7 
Number of iterations for time 0.62: 7 
Number of iterations for time 0.75: 7 
Number of iterations for time 0.88: 3 

Working with  9 processes...
Error vs. exact solution: 2.87290945e-07
Number of iterations for time 0.00: 7 
Number of iterations for time 0.12: 7 
Number of iterations for time 0.25: 7 
Number of iterations for time 0.38: 7 
Number of iterations for time 0.50: 7 
Number of iterations for time 0.62: 7 
Number of iterations for time 0.75: 7 
Number of iterations for time 0.88: 7 

Hide code cell source

fig, ax = plt.subplots(figsize=(8, 2.2), constrained_layout=True)
image = ax.imshow(list(iterations.values()), cmap='viridis', aspect='auto', vmin=0)
ax.set_yticks(range(len(iterations)))
ax.set_yticklabels(list(iterations))
ax.set_ylabel('processes')
ax.set_xlabel('time step')
fig.colorbar(image, label='iterations')
<matplotlib.colorbar.Colorbar at 0x7fd0a33a5550>
../../_images/c68642d3236acd9686a42cc0f55a5e7a8ce56824e0b7023d142f0e046bd3db4b.png

With 3 processes, the 8 steps come in blocks of 3, 3 and 2, and with 9 processes, one process has nothing to do. The controllers check which steps are currently active, and only those compute the next block.

Important things to note

  • This capability becomes useful with adaptive time stepping, where the number of steps is not known in advance.

  • It also works for SDC and MLSDC, where with varying time-step sizes the overall number of steps is not given at the beginning either.

The check the tests run is inside run_pfasst: no step needs more than 8 iterations.