Skip to content

Commit 31eb63d

Browse files
committed
Verified order and added configurations for dt-adaptivity and base
strategy
1 parent 4d10733 commit 31eb63d

File tree

3 files changed

+160
-32
lines changed

3 files changed

+160
-32
lines changed

pySDC/implementations/problem_classes/generic_spectral.py

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

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

pySDC/projects/Resilience/RBC.py

Lines changed: 121 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,59 @@
11
# script to run a Rayleigh-Benard Convection problem
2-
from pySDC.implementations.problem_classes.generic_spectral import compute_residual_DAE
2+
from pySDC.implementations.problem_classes.generic_spectral import compute_residual_DAE, get_extrapolated_error_DAE
33
from pySDC.implementations.problem_classes.RayleighBenard import RayleighBenard
44
from pySDC.implementations.controller_classes.controller_nonMPI import controller_nonMPI
55
from pySDC.projects.Resilience.hook import hook_collection, LogData
66
from pySDC.projects.Resilience.strategies import merge_descriptions
77
from pySDC.implementations.sweeper_classes.imex_1st_order import imex_1st_order
88
from pySDC.core.convergence_controller import ConvergenceController
9+
from pySDC.implementations.convergence_controller_classes.estimate_extrapolation_error import (
10+
EstimateExtrapolationErrorNonMPI,
11+
)
912

1013
from pySDC.core.errors import ConvergenceError
1114

15+
import numpy as np
16+
17+
18+
def u_exact(self, t, u_init=None, t_init=None, recompute=False):
19+
import pickle
20+
import os
21+
22+
path = f'data/stats/RBC-u_init-{t:.8f}.pickle'
23+
if os.path.exists(path) and not recompute and t_init is None:
24+
with open(path, 'rb') as file:
25+
data = pickle.load(file)
26+
else:
27+
from pySDC.helpers.stats_helper import get_sorted
28+
from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
29+
30+
convergence_controllers = {
31+
Adaptivity: {'e_tol': 1e-8, 'dt_rel_min_slope': 0.25},
32+
}
33+
desc = {'convergence_controllers': convergence_controllers}
34+
35+
u0 = self._u_exact(0) if u_init is None else u_init
36+
t0 = 0 if t_init is None else t_init
37+
38+
if t == t0:
39+
return u0
40+
else:
41+
stats, _, _ = run_RBC(Tend=t, u0=u0, t0=t0, custom_description=desc)
42+
43+
u = get_sorted(stats, type='u', recomputed=False)[-1]
44+
data = u[1]
45+
46+
if t0 == 0:
47+
with open(path, 'wb') as file:
48+
pickle.dump(data, file)
49+
50+
return data
51+
52+
53+
RayleighBenard._u_exact = RayleighBenard.u_exact
54+
RayleighBenard.u_exact = u_exact
55+
EstimateExtrapolationErrorNonMPI.get_extrapolated_error = get_extrapolated_error_DAE
56+
1257

1358
class ReachTendExactly(ConvergenceController):
1459

@@ -21,7 +66,9 @@ def setup(self, controller, params, description, **kwargs):
2166

2267
def get_new_step_size(self, controller, step, **kwargs):
2368
L = step.levels[0]
24-
L.status.dt_new = min([L.params.dt, self.params.Tend - L.time - L.dt])
69+
dt = L.status.dt_new if L.status.dt_new else L.params.dt
70+
if self.params.Tend - L.time - L.dt < dt:
71+
L.status.dt_new = min([dt, self.params.Tend - L.time - L.dt])
2572

2673

2774
def run_RBC(
@@ -32,7 +79,7 @@ def run_RBC(
3279
fault_stuff=None,
3380
custom_controller_params=None,
3481
u0=None,
35-
t0=10,
82+
t0=11,
3683
use_MPI=False,
3784
**kwargs,
3885
):
@@ -54,7 +101,7 @@ def run_RBC(
54101
bool: If the code crashed
55102
"""
56103
level_params = {}
57-
level_params['dt'] = 5e-4
104+
level_params['dt'] = 1e-3
58105
level_params['restol'] = -1
59106

60107
sweeper_params = {}
@@ -63,7 +110,9 @@ def run_RBC(
63110
sweeper_params['QI'] = 'LU'
64111
sweeper_params['QE'] = 'PIC'
65112

66-
problem_params = {}
113+
from mpi4py import MPI
114+
115+
problem_params = {'comm': MPI.COMM_SELF}
67116

68117
step_params = {}
69118
step_params['maxiter'] = 5
@@ -81,16 +130,14 @@ def run_RBC(
81130

82131
imex_1st_order.compute_residual = compute_residual_DAE
83132

84-
RayleighBenard._u_exact = RayleighBenard.u_exact
85-
RayleighBenard.u_exact = u_exact
86-
87133
description = {}
88134
description['problem_class'] = RayleighBenard
89135
description['problem_params'] = problem_params
90136
description['sweeper_class'] = imex_1st_order
91137
description['sweeper_params'] = sweeper_params
92138
description['level_params'] = level_params
93139
description['step_params'] = step_params
140+
description['convergence_controllers'] = convergence_controllers
94141

95142
if custom_description is not None:
96143
description = merge_descriptions(description, custom_description)
@@ -128,38 +175,81 @@ def run_RBC(
128175
return stats, controller, crash
129176

130177

131-
def u_exact(self, t, u_init=None, t_init=None, recompute=False):
178+
def generate_data_for_fault_stats():
179+
prob = RayleighBenard()
180+
for t in [11.0, 14.0]:
181+
prob.u_exact(t)
182+
183+
184+
def plot_order(t, dt, steps, num_nodes, e_tol=1e-9, restol=1e-9, ax=None, recompute=False):
185+
from pySDC.implementations.hooks.log_errors import LogGlobalErrorPostRun
186+
from pySDC.implementations.hooks.log_work import LogSDCIterations, LogWork
187+
from pySDC.helpers.stats_helper import get_sorted
132188
import pickle
133189
import os
134190

135-
path = f'data/stats/RBC-u_init-{t}.pickle'
136-
if os.path.exists(path) and not recompute and t_init is None:
137-
with open(path, 'rb') as file:
138-
data = pickle.load(file)
139-
else:
140-
from pySDC.helpers.stats_helper import get_sorted
141-
from pySDC.implementations.convergence_controller_classes.adaptivity import Adaptivity
191+
sweeper_params = {'num_nodes': num_nodes}
192+
level_params = {'e_tol': e_tol, 'restol': restol}
193+
step_params = {'maxiter': 99}
142194

143-
convergence_controllers = {
144-
Adaptivity: {'e_tol': 1e-8, 'dt_rel_min_slope': 0.25},
145-
}
146-
desc = {'convergence_controllers': convergence_controllers}
195+
errors = []
196+
dts = []
197+
for i in range(steps):
198+
dts += [dt / 2**i]
147199

148-
u0 = RayleighBenard()._u_exact(0) if u_init is None else u_init
149-
t0 = 0 if t_init is None else t_init
150-
stats, _, _ = run_RBC(Tend=t, u0=u0, t0=t0, custom_description=desc)
200+
path = f'data/stats/RBC-u_order-{t:.8f}-{dts[-1]:.8e}-{num_nodes}-{e_tol:.2e}-{restol:.2e}.pickle'
151201

152-
u = get_sorted(stats, type='u', recomputed=False)[-1]
153-
data = u[1]
202+
if os.path.exists(path) and not recompute:
203+
with open(path, 'rb') as file:
204+
stats = pickle.load(file)
205+
else:
206+
207+
level_params['dt'] = dts[-1]
208+
209+
desc = {'sweeper_params': sweeper_params, 'level_params': level_params, 'step_params': step_params}
210+
211+
stats, _, _ = run_RBC(
212+
Tend=t + dt,
213+
t0=t,
214+
custom_description=desc,
215+
hook_class=[LogGlobalErrorPostRun, LogSDCIterations, LogWork],
216+
)
154217

155-
if t0 == 0:
156218
with open(path, 'wb') as file:
157-
pickle.dump(data, file)
219+
pickle.dump(stats, file)
158220

159-
return data
221+
e = get_sorted(stats, type='e_global_post_run')
222+
# k = get_sorted(stats, type='k')
160223

224+
errors += [e[-1][1]]
161225

162-
if __name__ == '__main__':
163-
from pySDC.implementations.hooks.log_errors import LogLocalErrorPostStep
226+
errors = np.array(errors)
227+
dts = np.array(dts)
228+
mask = np.isfinite(errors)
229+
max_error = np.nanmax(errors)
230+
231+
errors = errors[mask]
232+
dts = dts[mask]
233+
ax.loglog(dts, errors, label=f'{num_nodes} nodes')
234+
ax.loglog(
235+
dts, [max_error * (me / dts[0]) ** (2 * num_nodes - 1) for me in dts], ls='--', label=f'order {2*num_nodes-1}'
236+
)
237+
ax.set_xlabel(r'$\Delta t$')
238+
ax.set_ylabel(r'global error')
239+
ax.legend(frameon=False)
240+
241+
242+
def test_order(t=14, dt=1e-1, steps=6):
164243

165-
stats, _, _ = run_RBC(hook_class=LogLocalErrorPostStep)
244+
import matplotlib.pyplot as plt
245+
246+
fig, ax = plt.subplots(1, 1)
247+
for num_nodes in [1, 2, 3, 4]:
248+
plot_order(t=t, dt=dt, steps=steps, num_nodes=num_nodes, ax=ax)
249+
plt.show()
250+
251+
252+
if __name__ == '__main__':
253+
generate_data_for_fault_stats()
254+
test_order()
255+
# stats, _, _ = run_RBC()

pySDC/projects/Resilience/strategies.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ def get_fault_args(self, problem, num_procs):
130130
args['time'] = 0.3
131131
elif problem.__name__ == "run_AC":
132132
args['time'] = 1e-2
133+
elif problem.__name__ == "run_RBC":
134+
args['time'] = 11.5
133135

134136
return args
135137

@@ -150,7 +152,7 @@ def get_random_params(self, problem, num_procs):
150152
rnd_params['iteration'] = base_params['step_params']['maxiter']
151153
rnd_params['rank'] = num_procs
152154

153-
if problem.__name__ in ['run_Schroedinger', 'run_quench', 'run_AC']:
155+
if problem.__name__ in ['run_Schroedinger', 'run_quench', 'run_AC', 'run_RBC']:
154156
rnd_params['min_node'] = 1
155157

156158
if problem.__name__ == "run_quench":
@@ -206,6 +208,8 @@ def get_Tend(cls, problem, num_procs=1):
206208
return 500.0
207209
elif problem.__name__ == "run_AC":
208210
return 0.025
211+
elif problem.__name__ == "run_RBC":
212+
return 14
209213
else:
210214
raise NotImplementedError('I don\'t have a final time for your problem!')
211215

@@ -269,6 +273,9 @@ def get_base_parameters(self, problem, num_procs=1):
269273
'nu': 2,
270274
}
271275
custom_description['level_params'] = {'restol': -1, 'dt': 0.1 * eps**2}
276+
elif problem.__name__ == 'run_RBC':
277+
custom_description['level_params']['dt'] = 5e-3
278+
custom_description['step_params'] = {'maxiter': 5}
272279

273280
custom_description['convergence_controllers'] = {
274281
# StepSizeLimiter: {'dt_min': self.get_Tend(problem=problem, num_procs=num_procs) / self.max_steps}
@@ -287,6 +294,7 @@ def get_base_parameters(self, problem, num_procs=1):
287294
'run_Schroedinger': 150,
288295
'run_quench': 150,
289296
'run_AC': 150,
297+
'run_RBC': 500,
290298
}
291299

292300
custom_description['convergence_controllers'][StopAtMaxRuntime] = {
@@ -521,6 +529,7 @@ def get_custom_description(self, problem, num_procs):
521529

522530
dt_max = np.inf
523531
dt_slope_max = np.inf
532+
dt_slope_min = 0
524533

525534
if problem.__name__ == "run_piline":
526535
e_tol = 1e-7
@@ -545,6 +554,9 @@ def get_custom_description(self, problem, num_procs):
545554
elif problem.__name__ == "run_AC":
546555
e_tol = 1e-7
547556
# dt_max = 0.1 * base_params['problem_params']['eps'] ** 2
557+
elif problem.__name__ == 'run_RBC':
558+
e_tol = 1e-3
559+
dt_slope_min = 0.25
548560

549561
else:
550562
raise NotImplementedError(
@@ -555,6 +567,7 @@ def get_custom_description(self, problem, num_procs):
555567
custom_description['convergence_controllers'][Adaptivity] = {
556568
'e_tol': e_tol,
557569
'dt_slope_max': dt_slope_max,
570+
'dt_rel_min_slope': dt_slope_min,
558571
}
559572
custom_description['convergence_controllers'][StepSizeLimiter] = {
560573
'dt_max': dt_max,
@@ -928,6 +941,9 @@ def get_custom_description(self, problem, num_procs):
928941
elif problem.__name__ == 'run_AC':
929942
HotRod_tol = 9.564437e-06
930943
maxiter = 6
944+
elif problem.__name__ == 'run_RBC':
945+
HotRod_tol = 1e0 # 1.#4e-1
946+
maxiter = 6
931947
else:
932948
raise NotImplementedError(
933949
'I don\'t have a tolerance for Hot Rod for your problem. Please add one to the\

0 commit comments

Comments
 (0)