Skip to content

Commit e1ad059

Browse files
brownbaerchenThomas Baumann
authored andcommitted
Resilience experiments with Rayleigh-Benard convection (Parallel-in-Time#495)
* Added basic infrastructure for Rayleigh-Benard in resilience project * Verified order and added configurations for dt-adaptivity and base strategy * Implemented configurations for faults in RBC * Added plot of RBC solution * Limit fault targets in space index * Fix * Fixed fault insertion time for Hot Rod * Changed colormap for RBC plots in the paper * Fixed bug in reference solution * Changed RBC configurations * A few more changes to RBC config * Implemented some tests * Restored behaviour of work_precision script * Small fixes #!!!!!! WARNING: FLAKEHEAVEN FAILED !!!!!!: #:
1 parent 655829f commit e1ad059

File tree

13 files changed

+693
-34
lines changed

13 files changed

+693
-34
lines changed

pySDC/helpers/plot_helper.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,13 @@ def figsize_by_journal(journal, scale, ratio): # pragma: no cover
4343
'JSC_beamer': 426.79135,
4444
'Springer_Numerical_Algorithms': 338.58778,
4545
'JSC_thesis': 434.26027,
46+
'TUHH_thesis': 426.79135,
4647
}
4748
# store text height in points here, get this from LaTeX using \the\textheight
4849
textheights = {
4950
'JSC_beamer': 214.43411,
5051
'JSC_thesis': 635.5,
52+
'TUHH_thesis': 631.65118,
5153
}
5254
assert (
5355
journal in textwidths.keys()

pySDC/helpers/pysdc_helper.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class FrozenClass(object):
1515

1616
def __setattr__(self, key, value):
1717
"""
18-
Function called when setting arttributes
18+
Function called when setting attributes
1919
2020
Args:
2121
key: the attribute
@@ -35,7 +35,7 @@ def __getattr__(self, key):
3535
if key in self.attrs:
3636
return None
3737
else:
38-
super().__getattr__(key)
38+
super().__getattribute__(key)
3939

4040
@classmethod
4141
def add_attr(cls, key, raise_error_if_exists=False):

pySDC/implementations/convergence_controller_classes/step_size_limiter.py

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,75 @@ def get_new_step_size(self, controller, S, **kwargs):
146146
S,
147147
)
148148
L.status.dt_new = dt_new
149-
elif abs(L.status.dt_new / L.params.dt - 1) < self.params.dt_rel_min_slope:
149+
elif abs(L.status.dt_new / L.params.dt - 1) < self.params.dt_rel_min_slope and not S.status.restart:
150150
L.status.dt_new = L.params.dt
151151
self.log(
152152
f"Step size did not change sufficiently to warrant step size change, keeping {L.status.dt_new:.2e}",
153153
S,
154154
)
155155

156156
return None
157+
158+
159+
class StepSizeRounding(ConvergenceController):
160+
"""
161+
Class to round step size when using adaptive step size selection.
162+
"""
163+
164+
def setup(self, controller, params, description, **kwargs):
165+
"""
166+
Define parameters here
167+
168+
Args:
169+
controller (pySDC.Controller): The controller
170+
params (dict): The params passed for this specific convergence controller
171+
description (dict): The description object used to instantiate the controller
172+
173+
Returns:
174+
(dict): The updated params dictionary
175+
"""
176+
defaults = {
177+
"control_order": +93,
178+
"digits": 1,
179+
"fac": 5,
180+
}
181+
return {**defaults, **super().setup(controller, params, description, **kwargs)}
182+
183+
@staticmethod
184+
def _round_step_size(dt, fac, digits):
185+
dt_rounded = None
186+
exponent = np.log10(dt) // 1
187+
188+
dt_norm = dt / 10 ** (exponent - digits)
189+
dt_norm_round = (dt_norm // fac) * fac
190+
dt_rounded = dt_norm_round * 10 ** (exponent - digits)
191+
return dt_rounded
192+
193+
def get_new_step_size(self, controller, S, **kwargs):
194+
"""
195+
Enforce an upper and lower limit to the step size here.
196+
Be aware that this is only tested when a new step size has been determined. That means if you set an initial
197+
value for the step size outside of the limits, and you don't do any further step size control, that value will
198+
go through.
199+
Also, the final step is adjusted such that we reach Tend as best as possible, which might give step sizes below
200+
the lower limit set here.
201+
202+
Args:
203+
controller (pySDC.Controller): The controller
204+
S (pySDC.Step): The current step
205+
206+
Returns:
207+
None
208+
"""
209+
for L in S.levels:
210+
if L.status.dt_new is not None:
211+
dt_rounded = self._round_step_size(L.status.dt_new, self.params.fac, self.params.digits)
212+
213+
if L.status.dt_new != dt_rounded:
214+
self.log(
215+
f"Step size rounded from {L.status.dt_new:.6e} to {dt_rounded:.6e}",
216+
S,
217+
)
218+
L.status.dt_new = dt_rounded
219+
220+
return None

pySDC/implementations/problem_classes/generic_spectral.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,3 +391,25 @@ def compute_residual_DAE_MPI(self, stage=None):
391391
L.status.updated = False
392392

393393
return None
394+
395+
396+
def get_extrapolated_error_DAE(self, S, **kwargs):
397+
"""
398+
The extrapolation estimate combines values of u and f from multiple steps to extrapolate and compare to the
399+
solution obtained by the time marching scheme. This function can be used in `EstimateExtrapolationError`.
400+
401+
Args:
402+
S (pySDC.Step): The current step
403+
404+
Returns:
405+
None
406+
"""
407+
u_ex = self.get_extrapolated_solution(S)
408+
diff_mask = S.levels[0].prob.diff_mask
409+
if u_ex is not None:
410+
S.levels[0].status.error_extrapolation_estimate = (
411+
abs((u_ex - S.levels[0].u[-1])[diff_mask]) * self.coeff.prefactor
412+
)
413+
# print([abs(me) for me in (u_ex - S.levels[0].u[-1]) * self.coeff.prefactor])
414+
else:
415+
S.levels[0].status.error_extrapolation_estimate = None

pySDC/implementations/sweeper_classes/Runge_Kutta.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -441,9 +441,12 @@ def update_nodes(self):
441441
rhs += lvl.dt * (self.QI[m + 1, j] * lvl.f[j].impl + self.QE[m + 1, j] * lvl.f[j].expl)
442442

443443
# implicit solve with prefactor stemming from the diagonal of Qd, use previous stage as initial guess
444-
lvl.u[m + 1][:] = prob.solve_system(
445-
rhs, lvl.dt * self.QI[m + 1, m + 1], lvl.u[m], lvl.time + lvl.dt * self.coll.nodes[m + 1]
446-
)
444+
if self.QI[m + 1, m + 1] != 0:
445+
lvl.u[m + 1][:] = prob.solve_system(
446+
rhs, lvl.dt * self.QI[m + 1, m + 1], lvl.u[m], lvl.time + lvl.dt * self.coll.nodes[m + 1]
447+
)
448+
else:
449+
lvl.u[m + 1][:] = rhs[:]
447450

448451
# update function values (we don't usually need to evaluate the RHS at the solution of the step)
449452
if m < M - self.coll.num_solution_stages or self.params.eval_rhs_at_right_boundary:

0 commit comments

Comments
 (0)