Skip to content

Commit cefdf0e

Browse files
Updated resilience plots with Lorenz attractor (#497)
* Added plots for solution of Lorenz with and without faults * Bugfix * Fixed resilience parameters for Allen-Cahn * Changed parameters for Lorenz * Fixed rest of reference values for test * Updated reference values * Fix tests * Fixes * Hopefully sped up tests somewhat * Split the tests * Removed some lengthy tests * Removed test that is apparently flaky based on hardware
1 parent 28901f1 commit cefdf0e

File tree

5 files changed

+198
-93
lines changed

5 files changed

+198
-93
lines changed

pySDC/projects/Resilience/fault_stats.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,10 @@ def generate_stats(self, strategy=None, runs=1000, reload=True, faults=True, com
271271
dat['bit'][i] = faults_run[0][1][4]
272272
dat['target'][i] = faults_run[0][1][5]
273273
dat['rank'][i] = faults_run[0][1][6]
274+
274275
if crash:
275276
print('Code crashed!')
277+
dat['error'][i] = np.inf
276278
continue
277279

278280
# record the rest of the data
@@ -876,7 +878,7 @@ def plot_things_per_things(
876878
args=None,
877879
strategies=None,
878880
name=None,
879-
store=True,
881+
store=False,
880882
ax=None,
881883
fig=None,
882884
plotting_args=None,
@@ -933,7 +935,7 @@ def plot_things_per_things(
933935
return None
934936

935937
def plot_recovery_thresholds(
936-
self, strategies=None, thresh_range=None, ax=None, mask=None, **kwargs
938+
self, strategies=None, thresh_range=None, ax=None, recoverable_only=False, **kwargs
937939
): # pragma: no cover
938940
'''
939941
Plot the recovery rate for a range of thresholds
@@ -942,7 +944,6 @@ def plot_recovery_thresholds(
942944
strategies (list): List of the strategies you want to plot, if None, all will be plotted
943945
thresh_range (list): thresholds for deciding whether to accept as recovered
944946
ax (Matplotlib.axes): Somewhere to plot
945-
mask (Numpy.ndarray of shape (n)): The mask you want to know about
946947
947948
Returns:
948949
None
@@ -961,16 +962,21 @@ def plot_recovery_thresholds(
961962
fault_free = self.load(strategy=strategy, faults=False)
962963
with_faults = self.load(strategy=strategy, faults=True)
963964

965+
if recoverable_only:
966+
recoverable_mask = self.get_fixable_faults_only(strategy)
967+
else:
968+
recoverable_mask = self.get_mask()
969+
964970
for thresh_idx in range(len(thresh_range)):
965971
rec_mask = self.get_mask(
966972
strategy=strategy,
967973
key='error',
968974
val=(thresh_range[thresh_idx] * fault_free['error'].mean()),
969975
op='gt',
970-
old_mask=mask,
976+
old_mask=recoverable_mask,
971977
)
972978
rec_rates[strategy_idx][thresh_idx] = 1.0 - len(with_faults['error'][rec_mask]) / len(
973-
with_faults['error']
979+
with_faults['error'][recoverable_mask]
974980
)
975981

976982
ax.plot(
@@ -1689,7 +1695,7 @@ def main():
16891695
stats_path='data/stats-jusuf',
16901696
**kwargs,
16911697
)
1692-
stats_analyser.run_stats_generation(runs=kwargs['runs'], step=12)
1698+
stats_analyser.run_stats_generation(runs=kwargs['runs'], step=25)
16931699

16941700
if MPI.COMM_WORLD.rank > 0: # make sure only one rank accesses the data
16951701
return None

pySDC/projects/Resilience/paper_plots.py

Lines changed: 110 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
DIRKStrategy,
2121
ERKStrategy,
2222
AdaptivityPolynomialError,
23+
cmap,
2324
)
2425
from pySDC.helpers.plot_helper import setup_mpl, figsize_by_journal
2526
from pySDC.helpers.stats_helper import get_sorted
@@ -392,6 +393,102 @@ def plot_fault_vdp(bit=0): # pragma: no cover
392393
savefig(fig, f'fault_bit_{bit}')
393394

394395

396+
def plot_fault_Lorenz(bit=0): # pragma: no cover
397+
"""
398+
Make a plot showing the impact of a fault on the Lorenz attractor without any resilience.
399+
The faults are inserted in the last iteration in the last node in x such that you can best see the impact.
400+
401+
Args:
402+
bit (int): The bit that you want to flip
403+
404+
Returns:
405+
None
406+
"""
407+
from pySDC.projects.Resilience.fault_stats import (
408+
FaultStats,
409+
BaseStrategy,
410+
)
411+
from pySDC.projects.Resilience.hook import LogData
412+
413+
stats_analyser = FaultStats(
414+
prob=run_Lorenz,
415+
strategies=[BaseStrategy()],
416+
faults=[False, True],
417+
reload=True,
418+
recovery_thresh=1.1,
419+
num_procs=1,
420+
mode='combination',
421+
)
422+
423+
strategy = BaseStrategy()
424+
425+
my_setup_mpl()
426+
fig, ax = plt.subplots(figsize=figsize_by_journal(JOURNAL, 0.8, 0.5))
427+
colors = ['grey', strategy.color, 'magenta']
428+
ls = ['--', '-']
429+
markers = [None, strategy.marker]
430+
do_faults = [False, True]
431+
superscripts = ['*', '']
432+
labels = ['x', 'x']
433+
434+
run = 19 + 20 * bit
435+
436+
for i in range(len(do_faults)):
437+
stats, controller, Tend = stats_analyser.single_run(
438+
strategy=BaseStrategy(),
439+
run=run,
440+
faults=do_faults[i],
441+
hook_class=[LogData],
442+
)
443+
u = get_sorted(stats, type='u')
444+
faults = get_sorted(stats, type='bitflip')
445+
ax.plot(
446+
[me[0] for me in u],
447+
[me[1][0] for me in u],
448+
ls=ls[i],
449+
color=colors[i],
450+
label=rf'${{{labels[i]}}}^{{{superscripts[i]}}}$',
451+
marker=markers[i],
452+
markevery=500,
453+
)
454+
for idx in range(len(faults)):
455+
ax.axvline(faults[idx][0], color='black', label='Fault', ls=':')
456+
print(
457+
f'Fault at t={faults[idx][0]:.2e}, iter={faults[idx][1][1]}, node={faults[idx][1][2]}, space={faults[idx][1][3]}, bit={faults[idx][1][4]}'
458+
)
459+
ax.set_title(f'Fault in bit {faults[idx][1][4]}')
460+
461+
ax.legend(frameon=True, loc='lower left')
462+
ax.set_xlabel(r'$t$')
463+
savefig(fig, f'fault_bit_{bit}')
464+
465+
466+
def plot_Lorenz_solution(): # pragma: no cover
467+
my_setup_mpl()
468+
469+
fig, axs = plt.subplots(1, 2, figsize=figsize_by_journal(JOURNAL, 1, 0.4), sharex=True)
470+
471+
strategy = BaseStrategy()
472+
desc = strategy.get_custom_description(run_Lorenz, num_procs=1)
473+
stats, controller, _ = run_Lorenz(custom_description=desc, Tend=strategy.get_Tend(run_Lorenz))
474+
475+
u = get_sorted(stats, recomputed=False, type='u')
476+
477+
axs[0].plot([me[1][0] for me in u], [me[1][2] for me in u])
478+
axs[0].set_ylabel('$z$')
479+
axs[0].set_xlabel('$x$')
480+
481+
axs[1].plot([me[1][0] for me in u], [me[1][1] for me in u])
482+
axs[1].set_ylabel('$y$')
483+
axs[1].set_xlabel('$x$')
484+
485+
for ax in axs:
486+
ax.set_box_aspect(1.0)
487+
488+
path = 'data/paper/Lorenz_sol.pdf'
489+
fig.savefig(path, bbox_inches='tight', transparent=True, dpi=200)
490+
491+
395492
def plot_quench_solution(): # pragma: no cover
396493
"""
397494
Plot the solution of Quench problem over time
@@ -586,6 +683,12 @@ def work_precision(): # pragma: no cover
586683
all_problems(**{**all_params, 'work_key': 'param'}, mode='compare_strategies')
587684

588685

686+
def plot_recovery_rate_per_acceptance_threshold(problem): # pragma no cover
687+
stats_analyser = get_stats(problem)
688+
689+
stats_analyser.plot_recovery_thresholds(thresh_range=np.linspace(0.5, 1.5, 1000), recoverable_only=True)
690+
691+
589692
def make_plots_for_TIME_X_website(): # pragma: no cover
590693
global JOURNAL, BASE_PATH
591694
JOURNAL = 'JSC_beamer'
@@ -636,11 +739,14 @@ def make_plots_for_adaptivity_paper(): # pragma: no cover
636739

637740

638741
def make_plots_for_resilience_paper(): # pragma: no cover
639-
compare_recovery_rate_problems(target='resilience', num_procs=1, strategy_type='SDC')
742+
plot_Lorenz_solution()
743+
plot_fault_Lorenz(0)
744+
plot_fault_Lorenz(20)
640745
plot_RBC_solution()
641-
plot_recovery_rate(get_stats(run_vdp))
642-
plot_fault_vdp(0)
643-
plot_fault_vdp(13)
746+
compare_recovery_rate_problems(target='resilience', num_procs=1, strategy_type='SDC')
747+
# plot_recovery_rate(get_stats(run_Lorenz))
748+
# plot_recovery_rate_per_acceptance_threshold(run_Lorenz)
749+
plt.show()
644750

645751

646752
def make_plots_for_notes(): # pragma: no cover

0 commit comments

Comments
 (0)