Skip to content

Commit 4d29d9a

Browse files
committed
started GS (WIP)
1 parent cb6f5d4 commit 4d29d9a

File tree

5 files changed

+331
-2
lines changed

5 files changed

+331
-2
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Full code: `projects/node_failure/grayscott_example.py <https://github.com/Parallel-in-Time/pySDC/blob/pySDC_v2/projects/node_failure/grayscott_example.py>`_
2+
3+
.. literalinclude:: ../../../projects/node_failure/grayscott_example.py
4+
5+
Results:
6+
7+
.. image:: ../../../data/GRAYSCOTT_steps_vs_iteration_hf_SPREAD.png
8+
:width: 19%
9+
10+
.. image:: ../../../data/GRAYSCOTT_steps_vs_iteration_hf_SPREAD_PREDICT.png
11+
:width: 19%
12+
13+
.. image:: ../../../data/GRAYSCOTT_steps_vs_iteration_hf_INTERP.png
14+
:width: 19%
15+
16+
.. image:: ../../../data/GRAYSCOTT_steps_vs_iteration_hf_INTERP_PREDICT.png
17+
:width: 19%
18+
19+
.. image:: ../../../data/GRAYSCOTT_steps_vs_iteration_hf_INTERP_PREDICT.png
20+
:width: 19%
21+
22+
.. image:: ../../../data/GRAYSCOTT_Kadd_vs_NOFAULT_hf.png
23+
:width: 33%

projects/node_failure/README.rst

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Failure injectation as well as the different strategies are contained in ``emula
77
We test our ideas for two simple toy problems and two more complex show cases.
88
This project contains the code for the publication `Toward fault-tolerant parallel-in-time integration with PFASST <https://arxiv.org/abs/1510.08334>`_ of pySDC v2,
99
while the original code can be found under `pySDC: Fault-tolerant PFASST <https://doi.org/10.5281/zenodo.32765>`_.
10-
Note that due to the long runtime, the results are not generated via Travis. Only the visualization is tested.
10+
Note that due to the long runtime, the results are not generated via Travis. Only the visualization (and therefore the existence of the data files) is tested.
1111

1212
Propagation of a single node failure
1313
------------------------------------
@@ -38,11 +38,19 @@ Heat maps generated by ``postproc_hard_faults_test`` then show how many more ite
3838
The Boussinesq test case
3939
------------------------
4040

41-
A first, more complex test case is the semi-implicit 2D Boussinesq system (order-coarsening only).
41+
A first, more complex test case is the semi-implicit 2D Boussinesq system (order-coarsening only), see ``boussinesq_example``.
4242
We inject faults randomly with a rate of 3%, i.e. in 3% of all fine sweeps a node fails.
4343
To ensure comparability, we define these fails a priori, so that each run has to deal with the same failures.
44+
The ``postproc_boussinesq`` script visualizes the results.
4445

4546
.. include:: doc_node_failure_boussinesq.rst
4647

4748
The Gray-Scott test case
4849
------------------------
50+
51+
Another test case is the 1D Gray-Scott reaction diffusion model, see ``grayscott_example``.
52+
With spatial coarsening enabled, this application plays well with PFASST and the goal of this part is to see how fault injections and recovery impact the convergence.
53+
We again inject faults randomly, but in a pre-defined way with a rate of 3%.
54+
The ``postproc_grayscott`` script visualizes the results.
55+
56+
.. include:: doc_node_failure_grayscott.rst
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
2+
from pySDC.core import CollocationClasses as collclass
3+
4+
from examples.fenics_grayscott.ProblemClass import fenics_grayscott
5+
from pySDC.core.datatype_classes.fenics_mesh import fenics_mesh
6+
from examples.fenics_grayscott.TransferClass import mesh_to_mesh_fenics
7+
# from examples.fenics_grayscott.HookClass import fenics_output
8+
from pySDC.core.sweeper_classes.generic_LU import generic_LU
9+
# import pySDC.PFASST_blockwise as mp
10+
import pySDC.core.PFASST_stepwise as mp
11+
from pySDC.core import Log
12+
from pySDC.core.Stats import grep_stats, sort_stats
13+
14+
import dolfin as df
15+
import numpy as np
16+
17+
import pySDC.helpers.fault_tolerance as ft
18+
19+
20+
if __name__ == "__main__":
21+
22+
# set global logger (remove this if you do not want the output at all)
23+
logger = Log.setup_custom_logger('root')
24+
25+
num_procs = 32
26+
27+
# assert num_procs == 1,'turn on predictor!'
28+
29+
# This comes as read-in for the level class
30+
lparams = {}
31+
lparams['restol'] = 1E-07
32+
33+
sparams = {}
34+
sparams['maxiter'] = 50
35+
sparams['fine_comm'] = True
36+
37+
# This comes as read-in for the problem class
38+
pparams = {}
39+
# pparams['Du'] = 1.0
40+
# pparams['Dv'] = 0.01
41+
# pparams['A'] = 0.01
42+
# pparams['B'] = 0.10
43+
# splitting pulses until steady state
44+
# pparams['Du'] = 1.0
45+
# pparams['Dv'] = 0.01
46+
# pparams['A'] = 0.02
47+
# pparams['B'] = 0.079
48+
# splitting pulses until steady state
49+
pparams['Du'] = 1.0
50+
pparams['Dv'] = 0.01
51+
pparams['A'] = 0.09
52+
pparams['B'] = 0.086
53+
54+
pparams['t0'] = 0.0 # ugly, but necessary to set up ProblemClass
55+
# pparams['c_nvars'] = [(16,16)]
56+
pparams['c_nvars'] = [512]
57+
pparams['family'] = 'CG'
58+
pparams['order'] = [4]
59+
pparams['refinements'] = [1,0]
60+
61+
62+
# This comes as read-in for the transfer operations
63+
tparams = {}
64+
tparams['finter'] = True
65+
66+
# Fill description dictionary for easy hierarchy creation
67+
description = {}
68+
description['problem_class'] = fenics_grayscott
69+
description['problem_params'] = pparams
70+
description['dtype_u'] = fenics_mesh
71+
description['dtype_f'] = fenics_mesh
72+
description['collocation_class'] = collclass.CollGaussRadau_Right
73+
description['num_nodes'] = 3
74+
description['sweeper_class'] = generic_LU
75+
description['level_params'] = lparams
76+
description['transfer_class'] = mesh_to_mesh_fenics
77+
description['transfer_params'] = tparams
78+
# description['hook_class'] = fenics_output
79+
80+
ft.hard_random = 0.03
81+
82+
# strategies = ['NOFAULT']
83+
# strategies = ['SPREAD','INTERP','INTERP_PREDICT','SPREAD_PREDICT']
84+
strategies = ['INTERP', 'INTERP_PREDICT']
85+
86+
for strategy in strategies:
87+
88+
print('------------------------------------------ working on strategy ',strategy)
89+
ft.strategy = strategy
90+
91+
# read in reference data from clean run, will provide reproducable locations for faults
92+
if not strategy is 'NOFAULT':
93+
reffile = np.load('PFASST_GRAYSCOTT_stats_hf_NOFAULT_P32.npz')
94+
ft.refdata = reffile['hard_stats']
95+
96+
# quickly generate block of steps
97+
MS = mp.generate_steps(num_procs,sparams,description)
98+
99+
# setup parameters "in time"
100+
t0 = MS[0].levels[0].prob.t0
101+
dt = 2.0
102+
Tend = 1280.0
103+
104+
# get initial values on finest level
105+
P = MS[0].levels[0].prob
106+
uinit = P.u_exact(t0)
107+
108+
# call main function to get things done...
109+
uend,stats = mp.run_pfasst(MS,u0=uinit,t0=t0,dt=dt,Tend=Tend)
110+
111+
# stats magic: get all residuals
112+
extract_stats = grep_stats(stats,level=-1,type='residual')
113+
114+
# find boundaries
115+
maxsteps = 0
116+
maxiter = 0
117+
minres = 0
118+
maxres = -99
119+
for k,v in extract_stats.items():
120+
maxsteps = max(maxsteps,getattr(k,'step'))
121+
maxiter = max(maxiter,getattr(k,'iter'))
122+
minres = min(minres,np.log10(v))
123+
maxres = max(maxres,np.log10(v))
124+
125+
# fill residual array
126+
residual = np.zeros((maxiter,maxsteps+1))
127+
residual[:] = 0
128+
for k,v in extract_stats.items():
129+
step = getattr(k,'step')
130+
iter = getattr(k,'iter')
131+
if iter is not -1:
132+
residual[iter-1,step] = v
133+
134+
# stats magic: get niter (probably redundant with maxiter)
135+
extract_stats = grep_stats(stats,iter=-1,type='niter')
136+
iter_count = np.zeros(maxsteps+1)
137+
for k,v in extract_stats.items():
138+
step = getattr(k,'step')
139+
iter_count[step] = v
140+
print(iter_count)
141+
142+
np.savez('PFASST_GRAYSCOTT_stats_hf_'+ft.strategy+'_P'+str(num_procs)+'_cN512',residual=residual,iter_count=iter_count,hard_stats=ft.hard_stats)
143+
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import numpy as np
2+
# import os
3+
import matplotlib.pyplot as plt
4+
from pylab import rcParams
5+
6+
axis_font = {'fontname': 'Arial', 'size': '8', 'family': 'serif'}
7+
fs = 8
8+
ms = 8
9+
lw = 2
10+
11+
12+
def create_plots(cwd=''):
13+
"""
14+
Function to visualize the results of the Gray-Scott show case
15+
16+
Args:
17+
cwd: current working directory
18+
"""
19+
20+
ref = 'PFASST_GRAYSCOTT_stats_hf_NOFAULT_P32.npz'
21+
22+
list = [('PFASST_GRAYSCOTT_stats_hf_SPREAD_P32.npz', 'SPREAD', '1-sided', 'red', 's'),
23+
('PFASST_GRAYSCOTT_stats_hf_INTERP_P32.npz', 'INTERP', '2-sided', 'orange', 'o'),
24+
('PFASST_GRAYSCOTT_stats_hf_SPREAD_PREDICT_P32.npz', 'SPREAD_PREDICT', '1-sided+corr', 'blue', '^'),
25+
('PFASST_GRAYSCOTT_stats_hf_INTERP_PREDICT_P32.npz', 'INTERP_PREDICT', '2-sided+corr', 'green', 'd'),
26+
('PFASST_GRAYSCOTT_stats_hf_NOFAULT_P32.npz', 'NOFAULT', 'no fault', 'black', 'v')]
27+
# list = [('PFASST_GRAYSCOTT_stats_hf_INTERP_P32_cN512.npz', 'INTERP', '2-sided', 'orange', 'o'),
28+
# ('PFASST_GRAYSCOTT_stats_hf_INTERP_PREDICT_P32_cN512.npz', 'INTERP_PREDICT', '2-sided+corr', 'green', 'd'),
29+
# ('PFASST_GRAYSCOTT_stats_hf_NOFAULT_P32.npz', 'NOFAULT', 'no fault', 'black', 'v')]
30+
31+
nprocs = 32
32+
33+
xtick_dist = 16
34+
35+
minstep = 288
36+
maxstep = 384
37+
# minstep = 0
38+
# maxstep = 640
39+
40+
nblocks = int(640 / nprocs)
41+
42+
# maxiter = 14
43+
nsteps = 0
44+
maxiter = 0
45+
vmax = -99
46+
for file, strategy, label, color, marker in list:
47+
data = np.load(cwd + 'data/' + file)
48+
49+
iter_count = data['iter_count'][minstep:maxstep]
50+
residual = data['residual'][:, minstep:maxstep]
51+
52+
residual[residual <= 0] = 1E-99
53+
residual = np.log10(residual)
54+
vmin = -9
55+
vmax = max(vmax, int(np.amax(residual)))
56+
57+
maxiter = max(maxiter, int(max(iter_count)))
58+
nsteps = max(nsteps, len(iter_count))
59+
60+
data = np.load(cwd + 'data/' + ref)
61+
ref_iter_count = data['iter_count'][nprocs - 1::nprocs]
62+
63+
rcParams['figure.figsize'] = 6.0, 2.5
64+
fig, ax = plt.subplots()
65+
66+
plt.plot(range(nblocks), [0] * nblocks, 'k-', linewidth=2)
67+
68+
ymin = 99
69+
ymax = 0
70+
for file, strategy, label, color, marker in list:
71+
72+
if file is not ref:
73+
data = np.load(cwd + 'data/' + file)
74+
iter_count = data['iter_count'][nprocs - 1::nprocs]
75+
76+
ymin = min(ymin, min(iter_count - ref_iter_count))
77+
ymax = max(ymax, max(iter_count - ref_iter_count))
78+
79+
plt.plot(range(nblocks), iter_count - ref_iter_count, color=color, label=label, marker=marker, linestyle='',
80+
linewidth=lw, markersize=ms)
81+
82+
plt.xlabel('block', **axis_font)
83+
plt.ylabel('$K_\\mathrm{add}$', **axis_font)
84+
plt.title('ALL')
85+
plt.xlim(-1, nblocks)
86+
plt.ylim(-1 + ymin, ymax + 1)
87+
plt.legend(loc=2, numpoints=1, fontsize=fs)
88+
plt.tick_params(axis='both', which='major', labelsize=fs)
89+
ax.xaxis.labelpad = -0.5
90+
ax.yaxis.labelpad = -1
91+
# plt.tight_layout()
92+
93+
fname = 'data/GRAYSCOTT_Kadd_vs_NOFAULT_hf.png'
94+
plt.savefig(fname, bbox_inches='tight', rasterize=True)
95+
# os.system('pdfcrop ' + fname + ' ' + fname)
96+
97+
for file, strategy, label, color, marker in list:
98+
99+
data = np.load(cwd + 'data/' + file)
100+
101+
residual = data['residual'][:, minstep:maxstep]
102+
stats = data['hard_stats']
103+
104+
residual[residual <= 0] = 1E-99
105+
residual = np.log10(residual)
106+
107+
rcParams['figure.figsize'] = 8.0, 2.0
108+
fig, ax = plt.subplots()
109+
110+
cmap = plt.get_cmap('Reds', vmax - vmin + 1)
111+
pcol = plt.pcolor(residual, cmap=cmap, vmin=vmin, vmax=vmax)
112+
pcol.set_edgecolor('face')
113+
114+
if file is not ref:
115+
for item in stats:
116+
if item[0] in range(minstep, maxstep):
117+
plt.text(item[0] + 0.5 - (maxstep - nsteps), item[1] - 1 + 0.5, 'x', horizontalalignment='center',
118+
verticalalignment='center')
119+
120+
plt.axis([0, nsteps, 0, maxiter])
121+
122+
ticks = np.arange(vmin, vmax + 1, 2)
123+
tickpos = np.linspace(ticks[0] + 0.5, ticks[-1] - 0.5, len(ticks))
124+
cax = plt.colorbar(pcol, ticks=tickpos, pad=0.02)
125+
cax.set_ticklabels(ticks)
126+
cax.ax.tick_params(labelsize=fs)
127+
128+
cax.set_label('log10(residual)', **axis_font)
129+
plt.tick_params(axis='both', which='major', labelsize=fs)
130+
ax.xaxis.labelpad = -0.5
131+
ax.yaxis.labelpad = -0.5
132+
133+
ax.set_xlabel('step', **axis_font)
134+
ax.set_ylabel('iteration', **axis_font)
135+
136+
ax.set_yticks(np.arange(1, maxiter, 2) + 0.5, minor=False)
137+
ax.set_xticks(np.arange(0, nsteps, xtick_dist) + 0.5, minor=False)
138+
ax.set_yticklabels(np.arange(1, maxiter, 2) + 1, minor=False)
139+
ax.set_xticklabels(np.arange(minstep, maxstep, xtick_dist), minor=False)
140+
141+
plt.title(strategy)
142+
# plt.tight_layout()
143+
144+
fname = 'data/GRAYSCOTT_steps_vs_iteration_hf_' + strategy + '.png'
145+
plt.savefig(fname, bbox_inches='tight', rasterize=True)
146+
# os.system('pdfcrop ' + fname + ' ' + fname)
147+
148+
149+
if __name__ == "__main__":
150+
create_plots()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from projects.node_failure.postproc_grayscott import create_plots
2+
3+
4+
def test_create_plots():
5+
create_plots(cwd='projects/node_failure/')

0 commit comments

Comments
 (0)