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
33from pySDC .implementations .problem_classes .RayleighBenard import RayleighBenard
44from pySDC .implementations .controller_classes .controller_nonMPI import controller_nonMPI
55from pySDC .projects .Resilience .hook import hook_collection , LogData
66from pySDC .projects .Resilience .strategies import merge_descriptions
77from pySDC .implementations .sweeper_classes .imex_1st_order import imex_1st_order
88from pySDC .core .convergence_controller import ConvergenceController
9+ from pySDC .implementations .convergence_controller_classes .estimate_extrapolation_error import (
10+ EstimateExtrapolationErrorNonMPI ,
11+ )
912
1013from 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
1358class 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
2774def 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()
0 commit comments