ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
MRISplitIntegrator< T > Class Template Reference

#include <ERF_MRI.H>

Inheritance diagram for MRISplitIntegrator< T >:
Collaboration diagram for MRISplitIntegrator< T >:

Public Member Functions

 MRISplitIntegrator ()=default
 
 MRISplitIntegrator (const T &S_data)
 
void initialize (const T &S_data) override
 
 ~MRISplitIntegrator () override=default
 
 MRISplitIntegrator (MRISplitIntegrator &&) noexcept=default
 
MRISplitIntegratoroperator= (MRISplitIntegrator &&other) noexcept=default
 
 MRISplitIntegrator (const MRISplitIntegrator &other)=delete
 
MRISplitIntegratoroperator= (const MRISplitIntegrator &other)=delete
 
void setNcompCons (int _ncomp_cons)
 
void setIncompressible (int _incompressible)
 
void setNoSubstepping (int _no_substepping)
 
void setForceFirstStageSingleSubstep (int _force_stage1_single_substep)
 
void set_slow_rhs_pre (std::function< void(T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const int)> F)
 
void set_slow_rhs_inc (std::function< void(T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const int)> F)
 
void set_slow_rhs_post (std::function< void(T &, T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const int)> F)
 
void set_fast_rhs (std::function< void(int, int, int, T &, const T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const amrex::Real)> F)
 
void set_slow_fast_timestep_ratio (const int timestep_ratio=1)
 
int get_slow_fast_timestep_ratio ()
 
void set_pre_update (std::function< void(T &, int)> F)
 
void set_post_update (std::function< void(T &, amrex::Real, int, int)> F)
 
void set_no_substep (std::function< void(T &, T &, T &, amrex::Real, amrex::Real, int)> F)
 
std::function< void(T &, const T &, const amrex::Real, int)> get_rhs ()
 
amrex::Real advance (T &S_old, T &S_new, amrex::Real time, const amrex::Real time_step) override
 
void time_interpolate (const T &, const T &, amrex::Real, T &) override
 
void map_data (std::function< void(T &)> Map) override
 

Private Member Functions

void initialize_data (const T &S_data)
 

Private Attributes

std::function< void(T &, const T &, const amrex::Real, const amrex::Real)> rhs
 rhs is the right-hand-side function the integrator will use. More...
 
std::function< void(T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const int)> slow_rhs_pre
 
std::function< void(T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const int)> slow_rhs_inc
 
std::function< void(T &, T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const int)> slow_rhs_post
 
std::function< void(int, int, int, T &, const T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const amrex::Real)> fast_rhs
 
amrex::Real timestep
 Integrator timestep size (Real) More...
 
int slow_fast_timestep_ratio = 0
 The ratio of slow timestep size / fast timestep size (int) More...
 
int no_substepping
 Should we not do acoustic substepping. More...
 
int incompressible
 Should we use the incompressible integrator. More...
 
int ncomp_cons
 How many components in the cell-centered MultiFab. More...
 
int force_stage1_single_substep
 Do we follow the recommendation to only perform a single substep in the first RK stage. More...
 
std::function< void(T &, int)> pre_update
 The pre_update function is called by the integrator on stage data before using it to evaluate a right-hand side. More...
 
std::function< void(T &, amrex::Real, int, int)> post_update
 
std::function< void(T &, T &, T &, amrex::Real, amrex::Real, int)> no_substep
 
amrex::Vector< std::unique_ptr< T > > T_store
 
T * S_sum
 
T * S_scratch
 
T * F_slow
 

Constructor & Destructor Documentation

◆ MRISplitIntegrator() [1/4]

template<class T >
MRISplitIntegrator< T >::MRISplitIntegrator ( )
default

◆ MRISplitIntegrator() [2/4]

template<class T >
MRISplitIntegrator< T >::MRISplitIntegrator ( const T &  S_data)
inline
89  {
90  initialize_data(S_data);
91  }
void initialize_data(const T &S_data)
Definition: ERF_MRI.H:72
Here is the call graph for this function:

◆ ~MRISplitIntegrator()

template<class T >
MRISplitIntegrator< T >::~MRISplitIntegrator ( )
overridedefault

◆ MRISplitIntegrator() [3/4]

template<class T >
MRISplitIntegrator< T >::MRISplitIntegrator ( MRISplitIntegrator< T > &&  )
defaultnoexcept

◆ MRISplitIntegrator() [4/4]

template<class T >
MRISplitIntegrator< T >::MRISplitIntegrator ( const MRISplitIntegrator< T > &  other)
delete

Member Function Documentation

◆ advance()

template<class T >
amrex::Real MRISplitIntegrator< T >::advance ( T &  S_old,
T &  S_new,
amrex::Real  time,
const amrex::Real  time_step 
)
inlineoverride
188  {
189  BL_PROFILE_REGION("MRI_advance");
190  using namespace amrex;
191 
192  // *******************************************************************************
193  // version == 0: we only update the fast variables every fast timestep, then update
194  // the slow variables after the acoustic sub-stepping. This has
195  // two calls to slow_rhs so that we can update the slow variables
196  // with the velocity field after the acoustic substepping using
197  // the time-averaged velocity from the substepping
198  // version == 1: we don't do any acoustic subcyling so we only make one call per RK
199  // stage to slow_rhs
200  // *******************************************************************************
201  int version = no_substepping ? 1 : 0;
202 
203  timestep = time_step;
204 
205  const int substep_ratio = get_slow_fast_timestep_ratio();
206 
207  AMREX_ALWAYS_ASSERT(substep_ratio > 1 && substep_ratio % 2 == 0);
208 
209  const amrex::Real sub_timestep = timestep / substep_ratio;
210 
211  // Assume before advance() that S_old is valid data at the current time ("time" argument)
212  // And that if data is a MultiFab, both S_old and S_new contain ghost cells for evaluating a stencil based RHS
213  // We need this from S_old. This is convenient for S_new to have so we can use it
214  // as scratch space for stage values without creating a new scratch MultiFab with ghost cells.
215 
216  // NOTE: In the following, we use S_new to hold S*, S**, and finally, S^(n+1) at the new time
217  // DEFINITIONS:
218  // S_old = S^n
219  // S_sum = S(t)
220  // F_slow = F(S_stage)
221 
222  int n_data = IntVars::NumTypes;
223 
224  /**********************************************/
225  /* RK3 Integration with Acoustic Sub-stepping */
226  /**********************************************/
227  Vector<int> num_vars = {ncomp_cons, 1, 1, 1};
228  for (int i(0); i<n_data; ++i)
229  {
230  // Copy old -> new
231  MultiFab::Copy(S_new[i],S_old[i],0,0,num_vars[i],S_old[i].nGrowVect());
232  }
233 
234  // Timestep taken by the fast integrator
235  amrex::Real dtau;
236 
237  // How many timesteps taken by the fast integrator
238  int nsubsteps;
239 
240  // This is the final time of the full timestep (also the 3rd RK stage)
241  // Real new_time = time + timestep;
242 
243  amrex::Real time_stage = time;
244  amrex::Real old_time_stage;
245 
246  if (!incompressible) {
247  // RK3 for compressible integrator
248  for (int nrk = 0; nrk < 3; nrk++)
249  {
250  // amrex::Print() << "Starting RK3: Step " << nrk+1 << std::endl;
251 
252  // Capture the time we got to in the previous RK step
253  old_time_stage = time_stage;
254 
255  if (nrk == 0) {
257  { nsubsteps = 1; dtau = timestep / 3.0; time_stage = time + timestep / 3.0;}
258  else
259  { nsubsteps = substep_ratio/3; dtau = sub_timestep ; time_stage = time + timestep / 3.0;}
260  }
261  if (nrk == 1) { nsubsteps = substep_ratio/2; dtau = sub_timestep ; time_stage = time + timestep / 2.0;}
262  if (nrk == 2) { nsubsteps = substep_ratio; dtau = sub_timestep ; time_stage = time + timestep ;}
263 
264  // step 1 starts with S_stage = S^n and we always start substepping at the old time
265  // step 2 starts with S_stage = S^* and we always start substepping at the old time
266  // step 3 starts with S_stage = S^** and we always start substepping at the old time
267 
268  // All pre_update does is call cons_to_prim, and we have done this with the old
269  // data already before starting the RK steps
270  if (nrk > 0) {
271  pre_update(S_new, S_new[IntVars::cons].nGrow());
272  }
273 
274  // S_scratch also holds the average momenta over the fast iterations --
275  // to be used to update the slow variables -- we will initialize with
276  // the momenta used in the first call to the slow_rhs, then update
277  // inside fast_rhs, then use these values in the later call to slow_rhs
278 
279  slow_rhs_pre(*F_slow, S_old, S_new, *S_scratch, time, old_time_stage, time_stage, nrk);
280 
281  amrex::Real inv_fac = 1.0 / static_cast<amrex::Real>(nsubsteps);
282 
283  // ****************************************************
284  // Acoustic substepping
285  // ****************************************************
286  if (version == 0)
287  {
288  // *******************************************************************************
289  // Update the fast variables
290  // *******************************************************************************
291  for (int ks = 0; ks < nsubsteps; ++ks)
292  {
293  fast_rhs(ks, nsubsteps, nrk, *F_slow, S_old, S_new, *S_sum, *S_scratch, dtau, inv_fac,
294  time + ks*dtau, time + (ks+1) * dtau);
295 
296  } // ks
297 
298  } else {
299  no_substep(*S_sum, S_old, *F_slow, time + nsubsteps*dtau, nsubsteps*dtau, nrk);
300  }
301 
302  // ****************************************************
303  // Evaluate F_slow(S_stage) only for the slow variables
304  // Note that we are using the current stage versions (in S_new) of the slow variables
305  // (because we didn't update the slow variables in the substepping)
306  // but we are using the "new" versions (in S_sum) of the velocities
307  // (because we did update the fast variables in the substepping)
308  // ****************************************************
309  slow_rhs_post(*F_slow, S_old, S_new, *S_sum, *S_scratch, time, old_time_stage, time_stage, nrk);
310 
311  // Call the post-update hook for S_new after all the fast steps completed
312  // This will update S_prim that is used in the slow RHS
313  post_update(S_new, time + nsubsteps*dtau, S_new[IntVars::cons].nGrow(), S_new[IntVars::xmom].nGrow());
314  } // nrk
315 
316  } else {
317  // RK2 for incompressible integrator
318  for (int nrk = 0; nrk < 2; nrk++)
319  {
320  // Capture the time we got to in the previous RK step
321  old_time_stage = time_stage;
322 
323  if (nrk == 0) { nsubsteps = 1; dtau = timestep; time_stage = time; }
324  if (nrk == 1) { nsubsteps = 1; dtau = timestep; time_stage = time + timestep; }
325 
326  // All pre_update does is call cons_to_prim, and we have done this with the old
327  // data already before starting the RK steps
328  if (nrk > 0) {
329  pre_update(S_new, S_new[IntVars::cons].nGrow());
330  }
331 
332  // S_scratch also holds the average momenta over the fast iterations --
333  // to be used to update the slow variables -- we will initialize with
334  // the momenta used in the first call to the slow_rhs, then update
335  // inside fast_rhs, then use these values in the later call to slow_rhs
336 
337  slow_rhs_inc(*F_slow, S_old, S_new, *S_scratch, time, old_time_stage, time_stage, nrk);
338 
339  no_substep(*S_sum, S_old, *F_slow, time + nsubsteps*dtau, nsubsteps*dtau, nrk);
340 
341  slow_rhs_post(*F_slow, S_old, S_new, *S_sum, *S_scratch, time, old_time_stage, time_stage, nrk);
342 
343  post_update(S_new, time + nsubsteps*dtau, S_new[IntVars::cons].nGrow(), S_new[IntVars::xmom].nGrow());
344  } // nrk
345  }
346 
347  // Return timestep
348  return timestep;
349  }
std::function< void(T &, amrex::Real, int, int)> post_update
Definition: ERF_MRI.H:63
T * F_slow
Definition: ERF_MRI.H:70
int incompressible
Should we use the incompressible integrator.
Definition: ERF_MRI.H:46
std::function< void(T &, T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const int)> slow_rhs_post
Definition: ERF_MRI.H:24
amrex::Real timestep
Integrator timestep size (Real)
Definition: ERF_MRI.H:31
std::function< void(T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const int)> slow_rhs_pre
Definition: ERF_MRI.H:22
int force_stage1_single_substep
Do we follow the recommendation to only perform a single substep in the first RK stage.
Definition: ERF_MRI.H:56
std::function< void(T &, int)> pre_update
The pre_update function is called by the integrator on stage data before using it to evaluate a right...
Definition: ERF_MRI.H:62
int ncomp_cons
How many components in the cell-centered MultiFab.
Definition: ERF_MRI.H:51
T * S_scratch
Definition: ERF_MRI.H:69
std::function< void(T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const int)> slow_rhs_inc
Definition: ERF_MRI.H:23
std::function< void(int, int, int, T &, const T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const amrex::Real)> fast_rhs
Definition: ERF_MRI.H:26
int get_slow_fast_timestep_ratio()
Definition: ERF_MRI.H:162
std::function< void(T &, T &, T &, amrex::Real, amrex::Real, int)> no_substep
Definition: ERF_MRI.H:64
T * S_sum
Definition: ERF_MRI.H:68
int no_substepping
Should we not do acoustic substepping.
Definition: ERF_MRI.H:41
@ NumTypes
Definition: IndexDefines.H:113
@ cons
Definition: IndexDefines.H:109
@ xmom
Definition: IndexDefines.H:110
Definition: console_io.cpp:12

Referenced by ERF::advance_dycore().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_rhs()

template<class T >
std::function<void(T&, const T&, const amrex::Real, int)> MRISplitIntegrator< T >::get_rhs ( )
inline
183  {
184  return rhs;
185  }
std::function< void(T &, const T &, const amrex::Real, const amrex::Real)> rhs
rhs is the right-hand-side function the integrator will use.
Definition: ERF_MRI.H:21

◆ get_slow_fast_timestep_ratio()

template<class T >
int MRISplitIntegrator< T >::get_slow_fast_timestep_ratio ( )
inline
163  {
165  }
int slow_fast_timestep_ratio
The ratio of slow timestep size / fast timestep size (int)
Definition: ERF_MRI.H:36

Referenced by MRISplitIntegrator< T >::advance().

Here is the caller graph for this function:

◆ initialize()

template<class T >
void MRISplitIntegrator< T >::initialize ( const T &  S_data)
inlineoverride
94  {
95  initialize_data(S_data);
96  }
Here is the call graph for this function:

◆ initialize_data()

template<class T >
void MRISplitIntegrator< T >::initialize_data ( const T &  S_data)
inlineprivate
73  {
74  // TODO: We can optimize memory by making the cell-centered part of S_sum, S_scratch
75  // have only 2 components, not ncomp_cons components
76  const bool include_ghost = true;
77  amrex::IntegratorOps<T>::CreateLike(T_store, S_data, include_ghost);
78  S_sum = T_store[0].get();
79  amrex::IntegratorOps<T>::CreateLike(T_store, S_data, include_ghost);
80  S_scratch = T_store[1].get();
81  amrex::IntegratorOps<T>::CreateLike(T_store, S_data, include_ghost);
82  F_slow = T_store[2].get();
83  }
amrex::Vector< std::unique_ptr< T > > T_store
Definition: ERF_MRI.H:67

Referenced by MRISplitIntegrator< T >::initialize(), and MRISplitIntegrator< T >::MRISplitIntegrator().

Here is the caller graph for this function:

◆ map_data()

template<class T >
void MRISplitIntegrator< T >::map_data ( std::function< void(T &)>  Map)
inlineoverride
354  {
355  for (auto& F : T_store) {
356  Map(*F);
357  }
358  }

◆ operator=() [1/2]

template<class T >
MRISplitIntegrator& MRISplitIntegrator< T >::operator= ( const MRISplitIntegrator< T > &  other)
delete

◆ operator=() [2/2]

template<class T >
MRISplitIntegrator& MRISplitIntegrator< T >::operator= ( MRISplitIntegrator< T > &&  other)
defaultnoexcept

◆ set_fast_rhs()

template<class T >
void MRISplitIntegrator< T >::set_fast_rhs ( std::function< void(int, int, int, T &, const T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const amrex::Real)>  F)
inline
153  {
154  fast_rhs = F;
155  }

Referenced by ERF::advance_dycore().

Here is the caller graph for this function:

◆ set_no_substep()

template<class T >
void MRISplitIntegrator< T >::set_no_substep ( std::function< void(T &, T &, T &, amrex::Real, amrex::Real, int)>  F)
inline
178  {
179  no_substep = F;
180  }

Referenced by ERF::advance_dycore().

Here is the caller graph for this function:

◆ set_post_update()

template<class T >
void MRISplitIntegrator< T >::set_post_update ( std::function< void(T &, amrex::Real, int, int)>  F)
inline
173  {
174  post_update = F;
175  }

Referenced by ERF::advance_dycore().

Here is the caller graph for this function:

◆ set_pre_update()

template<class T >
void MRISplitIntegrator< T >::set_pre_update ( std::function< void(T &, int)>  F)
inline
168  {
169  pre_update = F;
170  }

Referenced by ERF::advance_dycore().

Here is the caller graph for this function:

◆ set_slow_fast_timestep_ratio()

template<class T >
void MRISplitIntegrator< T >::set_slow_fast_timestep_ratio ( const int  timestep_ratio = 1)
inline
158  {
159  slow_fast_timestep_ratio = timestep_ratio;
160  }

Referenced by ERF::advance_dycore().

Here is the caller graph for this function:

◆ set_slow_rhs_inc()

template<class T >
void MRISplitIntegrator< T >::set_slow_rhs_inc ( std::function< void(T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const int)>  F)
inline
142  {
143  slow_rhs_inc = F;
144  }

Referenced by ERF::advance_dycore().

Here is the caller graph for this function:

◆ set_slow_rhs_post()

template<class T >
void MRISplitIntegrator< T >::set_slow_rhs_post ( std::function< void(T &, T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const int)>  F)
inline
146  {
147  slow_rhs_post = F;
148  }

Referenced by ERF::advance_dycore().

Here is the caller graph for this function:

◆ set_slow_rhs_pre()

template<class T >
void MRISplitIntegrator< T >::set_slow_rhs_pre ( std::function< void(T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const int)>  F)
inline
138  {
139  slow_rhs_pre = F;
140  }

Referenced by ERF::advance_dycore().

Here is the caller graph for this function:

◆ setForceFirstStageSingleSubstep()

template<class T >
void MRISplitIntegrator< T >::setForceFirstStageSingleSubstep ( int  _force_stage1_single_substep)
inline
133  {
134  force_stage1_single_substep = _force_stage1_single_substep;
135  }

◆ setIncompressible()

template<class T >
void MRISplitIntegrator< T >::setIncompressible ( int  _incompressible)
inline
123  {
124  incompressible = _incompressible;
125  }

◆ setNcompCons()

template<class T >
void MRISplitIntegrator< T >::setNcompCons ( int  _ncomp_cons)
inline
118  {
119  ncomp_cons = _ncomp_cons;
120  }

◆ setNoSubstepping()

template<class T >
void MRISplitIntegrator< T >::setNoSubstepping ( int  _no_substepping)
inline
128  {
129  no_substepping = _no_substepping;
130  }

◆ time_interpolate()

template<class T >
void MRISplitIntegrator< T >::time_interpolate ( const T &  ,
const T &  ,
amrex::Real  ,
T &   
)
inlineoverride
351 {}

Member Data Documentation

◆ F_slow

template<class T >
T* MRISplitIntegrator< T >::F_slow
private

◆ fast_rhs

template<class T >
std::function<void(int, int, int, T&, const T&, T&, T&, T&, const amrex::Real, const amrex::Real, const amrex::Real, const amrex::Real)> MRISplitIntegrator< T >::fast_rhs
private

◆ force_stage1_single_substep

template<class T >
int MRISplitIntegrator< T >::force_stage1_single_substep
private

Do we follow the recommendation to only perform a single substep in the first RK stage.

Referenced by MRISplitIntegrator< T >::advance(), and MRISplitIntegrator< T >::setForceFirstStageSingleSubstep().

◆ incompressible

template<class T >
int MRISplitIntegrator< T >::incompressible
private

Should we use the incompressible integrator.

Referenced by MRISplitIntegrator< T >::advance(), and MRISplitIntegrator< T >::setIncompressible().

◆ ncomp_cons

template<class T >
int MRISplitIntegrator< T >::ncomp_cons
private

How many components in the cell-centered MultiFab.

Referenced by MRISplitIntegrator< T >::advance(), and MRISplitIntegrator< T >::setNcompCons().

◆ no_substep

template<class T >
std::function<void (T&, T&, T&, amrex::Real, amrex::Real, int)> MRISplitIntegrator< T >::no_substep
private

◆ no_substepping

template<class T >
int MRISplitIntegrator< T >::no_substepping
private

Should we not do acoustic substepping.

Referenced by MRISplitIntegrator< T >::advance(), and MRISplitIntegrator< T >::setNoSubstepping().

◆ post_update

template<class T >
std::function<void (T&, amrex::Real, int, int)> MRISplitIntegrator< T >::post_update
private

◆ pre_update

template<class T >
std::function<void (T&, int)> MRISplitIntegrator< T >::pre_update
private

The pre_update function is called by the integrator on stage data before using it to evaluate a right-hand side.

The post_update function is called by the integrator on stage data at the end of the stage

Referenced by MRISplitIntegrator< T >::advance(), and MRISplitIntegrator< T >::set_pre_update().

◆ rhs

template<class T >
std::function<void(T&, const T&, const amrex::Real, const amrex::Real )> MRISplitIntegrator< T >::rhs
private

rhs is the right-hand-side function the integrator will use.

Referenced by MRISplitIntegrator< T >::get_rhs().

◆ S_scratch

template<class T >
T* MRISplitIntegrator< T >::S_scratch
private

◆ S_sum

template<class T >
T* MRISplitIntegrator< T >::S_sum
private

◆ slow_fast_timestep_ratio

template<class T >
int MRISplitIntegrator< T >::slow_fast_timestep_ratio = 0
private

The ratio of slow timestep size / fast timestep size (int)

Referenced by MRISplitIntegrator< T >::get_slow_fast_timestep_ratio(), and MRISplitIntegrator< T >::set_slow_fast_timestep_ratio().

◆ slow_rhs_inc

template<class T >
std::function<void(T&, T&, T&, T&, const amrex::Real, const amrex::Real, const amrex::Real, const int)> MRISplitIntegrator< T >::slow_rhs_inc
private

◆ slow_rhs_post

template<class T >
std::function<void(T&, T&, T&, T&, T&, const amrex::Real, const amrex::Real, const amrex::Real, const int )> MRISplitIntegrator< T >::slow_rhs_post
private

◆ slow_rhs_pre

template<class T >
std::function<void(T&, T&, T&, T&, const amrex::Real, const amrex::Real, const amrex::Real, const int)> MRISplitIntegrator< T >::slow_rhs_pre
private

◆ T_store

template<class T >
amrex::Vector<std::unique_ptr<T> > MRISplitIntegrator< T >::T_store
private

◆ timestep

template<class T >
amrex::Real MRISplitIntegrator< T >::timestep
private

Integrator timestep size (Real)

Referenced by MRISplitIntegrator< T >::advance().


The documentation for this class was generated from the following file: