Skip to content

Commit d8f68e5

Browse files
author
Thomas Baumann
committed
Added a test for fault insertion in Schroedinger problem and fixed
textwidth in plotting script
1 parent c8aacbe commit d8f68e5

File tree

5 files changed

+63
-10
lines changed

5 files changed

+63
-10
lines changed

pySDC/projects/Resilience/fault_injection.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,39 @@ def __init__(self):
127127
self.rnd_params = {}
128128
self.random_generator = np.random.RandomState(2187) # number of the cell in which Princess Leia is held
129129

130+
@classmethod
131+
def generate_fault_stuff_single_fault(cls, bit=0, iteration=1, problem_pos=None, level_number=0, node=1, time=None):
132+
"""
133+
Generate a fault stuff object which will insert a single fault at the supplied parameters. Because there will
134+
be some parameter set for everything, there is no randomization anymore.
135+
136+
Args:
137+
bit (int): Which bit to flip
138+
iteration (int): After which iteration to flip
139+
problem_pos: Where in the problem to flip a bit, type depends on the problem
140+
level_number (int): In which level you want to flip
141+
node (int): In which node to flip
142+
time (float): The bitflip will occur in the time step after this time is reached
143+
144+
Returns:
145+
dict: Can be supplied to the run functions in the resilience project to generate the single fault
146+
"""
147+
assert problem_pos is not None, "Please supply a spatial position for the fault as `problem_pos`!"
148+
assert time is not None, "Please supply a time for the fault as `time`!"
149+
fault_stuff = {
150+
'rng': np.random.RandomState(0),
151+
'args': {
152+
'bit': bit,
153+
'iteration': iteration,
154+
'level_number': level_number,
155+
'problem_pos': problem_pos,
156+
'node': node,
157+
'time': time,
158+
},
159+
}
160+
fault_stuff['rnd_args'] = fault_stuff['args']
161+
return fault_stuff
162+
130163
def add_fault(self, args, rnd_args):
131164
if type(self.random_generator) == int:
132165
self.add_fault_from_combination(args, rnd_args)
@@ -320,7 +353,6 @@ def pre_step(self, step, level_number):
320353
Returns:
321354
None
322355
'''
323-
324356
super(FaultInjector, self).pre_step(step, level_number)
325357

326358
self.timestep_idx += 1
-36.2 KB
Loading
-13.2 KB
Loading

pySDC/projects/Resilience/paper_plots.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818

1919
cm = 1 / 2.5
20+
TEXTWIDTH = 11.9446244611 * cm
2021

2122

2223
def get_stats(problem, path='data/stats'):
@@ -50,7 +51,7 @@ def get_stats(problem, path='data/stats'):
5051

5152
def my_setup_mpl(**kwargs):
5253
setup_mpl(reset=True, font_size=8)
53-
mpl.rcParams.update({'lines.markersize': 8})
54+
mpl.rcParams.update({'lines.markersize': 6})
5455

5556

5657
def savefig(fig, name, format='pdf', base_path='data/paper'): # pragma: no cover
@@ -98,7 +99,7 @@ def compare_strategies(stats_analyser, **kwargs): # pragma: no cover
9899
None
99100
"""
100101
my_setup_mpl()
101-
fig, ax = plt.subplots(figsize=(16 * cm, 7 * cm))
102+
fig, ax = plt.subplots(figsize=(TEXTWIDTH, 5 * cm))
102103
stats_analyser.compare_strategies(ax=ax)
103104
savefig(fig, 'compare_strategies', **kwargs)
104105

@@ -114,7 +115,7 @@ def plot_recovery_rate(stats_analyser, **kwargs): # pragma: no cover
114115
None
115116
"""
116117
my_setup_mpl()
117-
fig, axs = plt.subplots(1, 2, figsize=(16 * cm, 7 * cm), sharex=True, sharey=True)
118+
fig, axs = plt.subplots(1, 2, figsize=(TEXTWIDTH, 5 * cm), sharex=True, sharey=True)
118119
stats_analyser.plot_things_per_things(
119120
'recovered', 'bit', False, op=stats_analyser.rec_rate, args={'ylabel': 'recovery rate'}, ax=axs[0]
120121
)
@@ -167,7 +168,7 @@ def compare_recovery_rate_problems(): # pragma no cover
167168
titles = ['Van der Pol', 'Lorenz attractor', r'Schr\"odinger']
168169

169170
my_setup_mpl()
170-
fig, axs = plt.subplots(1, 3, figsize=(16 * cm, 5.5 * cm), sharex=False, sharey=True)
171+
fig, axs = plt.subplots(1, 3, figsize=(TEXTWIDTH, 4 * cm), sharex=False, sharey=True)
171172

172173
plot_recovery_rate_recoverable_only(vdp_stats, fig, axs[0], ylabel='recovery rate')
173174
plot_recovery_rate_recoverable_only(lorenz_stats, fig, axs[1], ylabel='', xlabel='')
@@ -206,13 +207,14 @@ def plot_efficiency_polar(problem, path='data/stats'): # pragma no cover
206207
mask = stats_analyser.get_mask() # get empty mask, potentially put in some other mask later
207208

208209
my_setup_mpl()
209-
fig, ax = plt.subplots(subplot_kw={'projection': 'polar'}, figsize=(8 * cm, 8 * cm))
210+
fig, ax = plt.subplots(subplot_kw={'projection': 'polar'}, figsize=(7 * cm, 7 * cm))
210211

211212
res = {}
212213
for strategy in stats_analyser.strategies:
213214
dat = stats_analyser.load(strategy=strategy, faults=True)
214215
dat_no_faults = stats_analyser.load(strategy=strategy, faults=False)
215216

217+
mask = stats_analyser.get_fixable_faults_only(strategy=strategy)
216218
fail_rate = 1.0 - stats_analyser.rec_rate(dat, dat_no_faults, 'recovered', mask)
217219
iterations_no_faults = np.mean(dat_no_faults['total_iteration'])
218220

@@ -259,7 +261,7 @@ def plot_adaptivity_stuff(): # pragma no cover
259261
stats_analyser = get_stats(run_vdp, 'data/stats')
260262

261263
my_setup_mpl()
262-
fig, axs = plt.subplots(3, 1, figsize=(10 * cm, 11 * cm), sharex=True, sharey=False)
264+
fig, axs = plt.subplots(3, 1, figsize=(TEXTWIDTH, TEXTWIDTH), sharex=True, sharey=False)
263265

264266
def plot_error(stats, ax, iter_ax, strategy, **kwargs):
265267
"""
@@ -328,9 +330,9 @@ def plot_fault_vdp(bit=0): # pragma no cover
328330
)
329331

330332
my_setup_mpl()
331-
fig, ax = plt.subplots(1, 1, figsize=(10 * cm, 7 * cm))
333+
fig, ax = plt.subplots(1, 1, figsize=(TEXTWIDTH * 3.0 / 4.0, 5 * cm))
332334
colors = ['blue', 'red', 'magenta']
333-
ls = ['--', '--', '-', '-']
335+
ls = ['--', '-']
334336
markers = ['*', '.', 'y']
335337
do_faults = [False, True]
336338
superscripts = ['*', '']

pySDC/tests/test_projects/test_resilience/test_schroedinger.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33

44
@pytest.mark.mpi4py
5-
def test_schroedinger():
5+
def test_schroedinger_solution():
66
from mpi4py import MPI
77
import numpy as np
88
from pySDC.projects.Resilience.Schroedinger import run_Schroedinger
@@ -13,3 +13,22 @@ def test_schroedinger():
1313
assert (
1414
k_mean < 17
1515
), f"Got too many iterations in Schroedinger test! Expected less then 17 on average, but got {k_mean:.2f}!"
16+
17+
18+
@pytest.mark.mpi4py
19+
def test_schroedinger_fault_insertion():
20+
from mpi4py import MPI
21+
import numpy as np
22+
from pySDC.projects.Resilience.Schroedinger import run_Schroedinger
23+
from pySDC.projects.Resilience.fault_injection import FaultInjector
24+
from pySDC.helpers.stats_helper import get_sorted
25+
26+
fault_stuff = FaultInjector.generate_fault_stuff_single_fault(
27+
bit=0, iteration=5, problem_pos=[20, 30], level_number=0, node=3, time=0.1
28+
)
29+
30+
stats, _, _ = run_Schroedinger(space_comm=MPI.COMM_WORLD, fault_stuff=fault_stuff)
31+
k_mean = np.mean([me[1] for me in get_sorted(stats, type='k')])
32+
assert (
33+
k_mean > 17
34+
), f"Got too few iterations in Schroedinger test! Expected more then 17 on average because we need to fix the fault, but got {k_mean:.2f}!"

0 commit comments

Comments
 (0)