Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
971d124
Started tests for fault injection by testing float to binary conversion
Dec 23, 2022
ccbfb76
Fixed a lot of typos
Dec 23, 2022
570b0e9
Merge remote-tracking branch 'upstream/master' into test_faults
Dec 23, 2022
7a3f848
Added test for recovery rate
Jan 2, 2023
c910905
Added a test for fault injection and moved the test for fault stats to
Jan 2, 2023
bd9c71f
Cleaned up the test such that we get a useful error message if one test
Jan 2, 2023
e07a18f
Merge remote-tracking branch 'upstream/master' into test_faults
Jan 2, 2023
06d23f6
Fixed one more typo
Jan 2, 2023
17d64b3
Added an mpi barrier in the hope that the bug which I don't understand
Jan 2, 2023
8cdb46d
Added a print statement to hopefully find out what's wrong...
Jan 2, 2023
d4dd5b3
Added some more output for debugging
Jan 2, 2023
d31c21a
Tried fixing the behaviour of numpy when encountering overflows
Jan 3, 2023
5f03dcb
Merge remote-tracking branch 'upstream/master' into test_faults
Jan 16, 2023
d6f5b03
Adapted the fault injection hook to new hook API
Jan 16, 2023
09befef
Fixed the dtype to numpy.float64. Maybe that helps...
Jan 16, 2023
b440aa5
Forgot a hook in advection problem
Jan 16, 2023
070d16e
Fix
Jan 17, 2023
323ac6a
Trying `stop_at_nan=False`
Jan 17, 2023
5b2455c
Tried removing crashed runs
Jan 17, 2023
4368ada
One more try
Jan 17, 2023
9fd0308
Fixed adaptivity notebook
Jan 17, 2023
7a7f2c9
Fixed resilience notebook
Jan 17, 2023
a925897
Linting
Jan 17, 2023
b159455
coverage...?
Jan 17, 2023
b61f106
Reverted CI pipeline
Jan 17, 2023
507096e
Merge remote-tracking branch 'upstream/master' into test_faults
Jan 18, 2023
301e4e0
Merge remote-tracking branch 'upstream/master' into test_faults
Jan 20, 2023
68f3111
Fixed merge in other direction as well
Jan 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions pySDC/implementations/hooks/log_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,33 @@
from pySDC.core.Hooks import hooks


class LogGlobalError(hooks):
"""
Log the global error with respect to `u_exact` defined in the problem class as "e_global".
Be aware that this requires the problems to be compatible with this. We need some kind of "exact" solution for this
to work, be it a reference solution or something analytical.
"""

def post_step(self, step, level_number):

super(LogGlobalError, self).post_step(step, level_number)

# some abbreviations
L = step.levels[level_number]

L.sweep.compute_end_point()

self.add_to_stats(
process=step.status.slot,
time=L.time + L.dt,
level=L.level_index,
iter=step.status.iter,
sweep=L.status.sweep,
type='e_global',
value=abs(L.prob.u_exact(t=L.time + L.dt) - L.uend),
)


class LogGlobalErrorPostRun(hooks):
"""
Compute the global error once after the run is finished.
Expand Down Expand Up @@ -60,3 +87,30 @@ def post_run(self, step, level_number):
type='e_global',
value=e_glob,
)


class LogLocalError(hooks):
"""
Log the local error with respect to `u_exact` defined in the problem class as "e_local".
Be aware that this requires the problems to be compatible with this. In particular, a reference solution needs to
be made available from the initial conditions of the step, not of the run. Otherwise you compute the global error.
"""

def post_step(self, step, level_number):

super(LogLocalError, self).post_step(step, level_number)

# some abbreviations
L = step.levels[level_number]

L.sweep.compute_end_point()

self.add_to_stats(
process=step.status.slot,
time=L.time + L.dt,
level=L.level_index,
iter=step.status.iter,
sweep=L.status.sweep,
type='e_local',
value=abs(L.prob.u_exact(t=L.time + L.dt, u_init=L.u[0], t_init=L.time) - L.uend),
)
32 changes: 32 additions & 0 deletions pySDC/implementations/hooks/log_solution.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,35 @@ def post_step(self, step, level_number):
type='u',
value=L.uend,
)


class LogSolutionAfterIteration(hooks):
"""
Store the solution at the end of each iteration as "u".
"""

def post_iteration(self, step, level_number):
"""
Record solution at the end of the iteration

Args:
step (pySDC.Step.step): the current step
level_number (int): the current level number

Returns:
None
"""
super().post_iteration(step, level_number)

L = step.levels[level_number]
L.sweep.compute_end_point()

self.add_to_stats(
process=step.status.slot,
time=L.time + L.dt,
level=L.level_index,
iter=step.status.iter,
sweep=L.status.sweep,
type='u',
value=L.uend,
)
11 changes: 6 additions & 5 deletions pySDC/projects/Resilience/Adaptivity.ipynb

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions pySDC/projects/Resilience/Lorenz.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
from pySDC.implementations.controller_classes.controller_nonMPI import controller_nonMPI
from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
from pySDC.core.Errors import ProblemError
from pySDC.projects.Resilience.hook import log_data, hook_collection
from pySDC.projects.Resilience.hook import LogData, hook_collection


def run_Lorenz(
custom_description=None,
num_procs=1,
Tend=1.0,
hook_class=log_data,
hook_class=LogData,
fault_stuff=None,
custom_controller_params=None,
custom_problem_params=None,
Expand Down Expand Up @@ -181,12 +181,12 @@ def main(plotting=True):

custom_description = {}
custom_description['convergence_controllers'] = {Adaptivity: {'e_tol': 1e-5}}
custom_controller_params = {'logger_level': 15}
custom_controller_params = {'logger_level': 30}
stats, controller, _ = run_Lorenz(
custom_description=custom_description,
custom_controller_params=custom_controller_params,
Tend=10,
hook_class=[log_data, LogGlobalErrorPostRun],
hook_class=[LogData, LogGlobalErrorPostRun],
)
check_solution(stats, controller, 5e-4)
if plotting: # pragma: no cover
Expand Down
32 changes: 16 additions & 16 deletions pySDC/projects/Resilience/ResilienceStatistics.ipynb

Large diffs are not rendered by default.

50 changes: 12 additions & 38 deletions pySDC/projects/Resilience/accuracy_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,16 @@
EstimateExtrapolationErrorNonMPI,
)
from pySDC.core.Hooks import hooks
from pySDC.implementations.hooks.log_errors import LogLocalError

import pySDC.helpers.plot_helper as plt_helper
from pySDC.projects.Resilience.piline import run_piline


class do_nothing(hooks):
class DoNothing(hooks):
pass


class log_errors(hooks):
"""
A hook that only logs errors, but includes a local error that is not estimated during runtime.
What that means is problem specific. If an analytical solution is available, the local error is exact,
otherwise it is estimated using a reference solution generated with scipy.
"""

def post_step(self, step, level_number):

super(log_errors, self).post_step(step, level_number)

# some abbreviations
L = step.levels[level_number]

L.sweep.compute_end_point()

self.add_to_stats(
process=step.status.slot,
time=L.time,
level=L.level_index,
iter=0,
sweep=L.status.sweep,
type='e_loc',
value=abs(L.prob.u_exact(t=L.time + L.dt, u_init=L.u[0], t_init=L.time) - L.u[-1]),
)


def setup_mpl(font_size=8):
"""
Setup matplotlib to fit in with TeX scipt.
Expand All @@ -66,7 +40,7 @@ def setup_mpl(font_size=8):
mpl.rcParams.update(style_options)


def get_results_from_stats(stats, var, val, hook_class=log_errors):
def get_results_from_stats(stats, var, val, hook_class=LogLocalError):
"""
Extract results from the stats are used to compute the order.

Expand All @@ -86,16 +60,16 @@ def get_results_from_stats(stats, var, val, hook_class=log_errors):
var: val,
}

if hook_class == log_errors:
if hook_class == LogLocalError:
e_extrapolated = np.array(get_sorted(stats, type='error_extrapolation_estimate'))[:, 1]
e_embedded = np.array(get_sorted(stats, type='error_embedded_estimate'))[:, 1]
e_loc = np.array(get_sorted(stats, type='e_loc'))[:, 1]
e_local = np.array(get_sorted(stats, type='e_local'))[:, 1]

if len(e_extrapolated[e_extrapolated != [None]]) > 0:
results['e_extrapolated'] = e_extrapolated[e_extrapolated != [None]][-1]

if len(e_loc[e_loc != [None]]) > 0:
results['e'] = max([e_loc[e_loc != [None]][-1], np.finfo(float).eps])
if len(e_local[e_local != [None]]) > 0:
results['e'] = max([e_local[e_local != [None]][-1], np.finfo(float).eps])

if len(e_embedded[e_embedded != [None]]) > 0:
results['e_embedded'] = e_embedded[e_embedded != [None]][-1]
Expand All @@ -110,7 +84,7 @@ def multiple_runs(
custom_description=None,
prob=run_piline,
dt_list=None,
hook_class=log_errors,
hook_class=LogLocalError,
custom_controller_params=None,
var='dt',
avoid_restarts=False,
Expand Down Expand Up @@ -176,11 +150,11 @@ def multiple_runs(

level = controller.MS[-1].levels[-1]
e_glob = abs(level.prob.u_exact(t=level.time + level.dt) - level.u[-1])
e_loc = abs(level.prob.u_exact(t=level.time + level.dt, u_init=level.u[0], t_init=level.time) - level.u[-1])
e_local = abs(level.prob.u_exact(t=level.time + level.dt, u_init=level.u[0], t_init=level.time) - level.u[-1])

res_ = get_results_from_stats(stats, var, dt_list[i], hook_class)
res_['e_glob'] = e_glob
res_['e_loc'] = e_loc
res_['e_local'] = e_local

if i == 0:
res = res_.copy()
Expand All @@ -206,7 +180,7 @@ def plot_order(res, ax, k):
"""
color = plt.rcParams['axes.prop_cycle'].by_key()['color'][k - 2]

key = 'e_loc'
key = 'e_local'
order = get_accuracy_order(res, key=key, thresh=1e-11)
label = f'k={k}, p={np.mean(order):.2f}'
ax.loglog(res['dt'], res[key], color=color, ls='-', label=label)
Expand Down Expand Up @@ -332,7 +306,7 @@ def plot_orders(
custom_description=custom_description,
prob=prob,
dt_list=dt_list,
hook_class=do_nothing,
hook_class=DoNothing,
custom_controller_params=custom_controller_params,
)
plot_order(res, ax, k)
Expand Down
66 changes: 38 additions & 28 deletions pySDC/projects/Resilience/advection.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,29 @@
from pySDC.implementations.problem_classes.AdvectionEquation_ND_FD import advectionNd
from pySDC.implementations.sweeper_classes.generic_implicit import generic_implicit
from pySDC.implementations.controller_classes.controller_nonMPI import controller_nonMPI
from pySDC.core.Hooks import hooks
from pySDC.helpers.stats_helper import get_sorted
import numpy as np
from pySDC.projects.Resilience.hook import log_data
from pySDC.projects.Resilience.hook import LogData, hook_collection
from pySDC.projects.Resilience.fault_injection import prepare_controller_for_faults


def plot_embedded(stats, ax):
u = get_sorted(stats, type='u', recomputed=False)
uold = get_sorted(stats, type='uold', recomputed=False)
t = [get_sorted(stats, type='u', recomputed=False)[i][0] for i in range(len(u))]
e_em = np.array(get_sorted(stats, type='e_embedded', recomputed=False))[:, 1]
t = [me[0] for me in u]
e_em = get_sorted(stats, type='error_embedded_estimate', recomputed=False)
e_em_semi_glob = [abs(u[i][1] - uold[i][1]) for i in range(len(u))]
ax.plot(t, e_em_semi_glob, label=r'$\|u^{\left(k-1\right)}-u^{\left(k\right)}\|$')
ax.plot(t, e_em, linestyle='--', label=r'$\epsilon$')
ax.plot([me[0] for me in e_em], [me[1] for me in e_em], linestyle='--', label=r'$\epsilon$')
ax.set_xlabel(r'$t$')
ax.legend(frameon=False)


class log_every_iteration(hooks):
def post_iteration(self, step, level_number):
if step.status.iter == step.params.maxiter - 1:
L = step.levels[level_number]
L.sweep.compute_end_point()
self.add_to_stats(
process=step.status.slot,
time=L.time + L.dt,
level=L.level_index,
iter=0,
sweep=L.status.sweep,
type='uold',
value=L.uold[-1],
)


def run_advection(
custom_description=None,
num_procs=1,
Tend=2e-1,
hook_class=log_data,
hook_class=LogData,
fault_stuff=None,
custom_controller_params=None,
custom_problem_params=None,
Expand Down Expand Up @@ -69,7 +53,7 @@ def run_advection(
# initialize controller parameters
controller_params = dict()
controller_params['logger_level'] = 30
controller_params['hook_class'] = hook_class
controller_params['hook_class'] = hook_collection + (hook_class if type(hook_class) == list else [hook_class])
controller_params['mssdc_jac'] = False

if custom_controller_params is not None:
Expand Down Expand Up @@ -99,11 +83,14 @@ def run_advection(

# insert faults
if fault_stuff is not None:
controller.hooks.random_generator = fault_stuff['rng']
controller.hooks.add_fault(
rnd_args={'iteration': 5, **fault_stuff.get('rnd_params', {})},
args={'time': 1e-1, 'target': 0, **fault_stuff.get('args', {})},
)
rnd_args = {
'iteration': 5,
}
args = {
'time': 1e-1,
'target': 0,
}
prepare_controller_for_faults(controller, fault_stuff, rnd_args, args)

# get initial values on finest level
P = controller.MS[0].levels[0].prob
Expand All @@ -112,3 +99,26 @@ def run_advection(
# call main function to get things done...
uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend)
return stats, controller, Tend


if __name__ == '__main__':
import matplotlib.pyplot as plt
from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
from pySDC.projects.Resilience.hook import LogUold

adaptivity_params = dict()
adaptivity_params['e_tol'] = 1e-8

convergence_controllers = dict()
convergence_controllers[Adaptivity] = adaptivity_params

description = dict()
description['convergence_controllers'] = convergence_controllers

fig, axs = plt.subplots(1, 2, figsize=(12, 4), sharex=True, sharey=True)
plot_embedded(run_advection(description, 1, hook_class=LogUold)[0], axs[0])
plot_embedded(run_advection(description, 4, hook_class=LogUold)[0], axs[1])
axs[0].set_title('1 process')
axs[1].set_title('4 processes')
fig.tight_layout()
plt.show()
Loading