PLUTO
LevelPluto.cpp
Go to the documentation of this file.
1 #ifdef CH_LANG_CC
2 /*
3  * _______ __
4  * / ___/ / ___ __ _ / / ___
5  * / /__/ _ \/ _ \/ V \/ _ \/ _ \
6  * \___/_//_/\___/_/_/_/_.__/\___/
7  * Please refer to Copyright.txt, in Chombo's root directory.
8  */
9 #endif
10 
11 #include <cstdio>
12 
13 #include "LevelPluto.H"
14 #include "BoxIterator.H"
15 #include "AMRIO.H"
16 #include "SPMD.H"
17 #include "LoHiSide.H"
18 
19 #include "CH_Timer.H"
20 
21 #include "NamespaceHeader.H"
22 
23 // Constructor - set up some defaults
24 LevelPluto::LevelPluto()
25 {
26  m_dx = 0.0;
27  m_dl_min = 1.e30;
28  m_refineCoarse = 0;
29  m_patchPluto = NULL;
30  m_isDefined = false;
31 }
32 
33 // Destructor - free up storage
34 LevelPluto::~LevelPluto()
35 {
36  if (m_patchPluto != NULL)
37  {
38  delete m_patchPluto;
39  }
40 }
41 
42 // Define the object so that time stepping can begin
43 void LevelPluto::define(const DisjointBoxLayout& a_thisDisjointBoxLayout,
44  const DisjointBoxLayout& a_coarserDisjointBoxLayout,
45  const ProblemDomain& a_domain,
46  const int& a_refineCoarse,
47  const int& a_level,
48  const Real& a_dx,
49  const PatchPluto* a_patchPlutoFactory,
50  const bool& a_hasCoarser,
51  const bool& a_hasFiner)
52 {
53  CH_TIME("LevelPluto::define");
54 
55  // Sanity checks
56  CH_assert(a_refineCoarse > 0);
57  CH_assert(a_dx > 0.0);
58 
59  // Make a copy of the current grids
60  m_grids = a_thisDisjointBoxLayout;
61 
62  // Cache data
63  m_dx = a_dx;
64  m_level = a_level;
65  m_domain = a_domain;
66  m_refineCoarse = a_refineCoarse;
67  m_hasCoarser = a_hasCoarser;
68  m_hasFiner = a_hasFiner;
69 
70  // Remove old patch integrator (if any), create a new one, and initialize
71  if (m_patchPluto != NULL)
72  {
73  delete m_patchPluto;
74  }
75 
76  // Determing the number of ghost cells necessary here
77  m_numGhost = GetNghost();
78 
79  m_patchPluto = a_patchPlutoFactory->new_patchPluto();
80  m_patchPluto->define(m_domain,m_dx,m_level,m_numGhost);
81 
82  // Set the grid for the entire level
83  setGridLevel();
84 
85  // Get the number of conserved variable and face centered fluxes
86  m_numCons = m_patchPluto->numConserved();
87  m_numFluxes = m_patchPluto->numFluxes();
88 
89  m_exchangeCopier.exchangeDefine(a_thisDisjointBoxLayout,
90  m_numGhost*IntVect::Unit);
91 
92  // Setup an interval corresponding to the conserved variables
93  Interval UInterval(0,m_numCons-1);
94 
95  #if (TIME_STEPPING == RK2)
96  // Create temporary storage with a layer of "m_numGhost" ghost cells
97  // for the flags passing from predictor to corrector (RK2 only)
98  m_Flags.define(m_grids,1,m_numGhost*IntVect::Unit);
99  m_Utmp.define(m_grids,m_numCons,m_numGhost*IntVect::Unit);
100  #endif
101 
102  // Create temporary storage with a layer of "m_numGhost" ghost cells
103  {
104  CH_TIME("setup::Udefine");
105  m_U.define(m_grids,m_numCons,m_numGhost*IntVect::Unit);
106  }
107 
108  // Set up the interpolator if there is a coarser level
109  if (m_hasCoarser)
110  {
111  m_patcher.define(a_thisDisjointBoxLayout,
112  a_coarserDisjointBoxLayout,
113  m_numCons,
114  coarsen(a_domain,a_refineCoarse),
115  a_refineCoarse,
116  m_dx,
117  m_numGhost);
118  }
119 
120  // Everything is defined
121  m_isDefined = true;
122 }
123 
124 // Advance the solution by "a_dt" by using an unsplit method.
125 // "a_finerFluxRegister" is the flux register with the next finer level.
126 // "a_coarseFluxRegister" is flux register with the next coarser level.
127 // If source terms do not exist, "a_S" should be null constructed and not
128 // defined (i.e. its define() should not be called).
129 Real LevelPluto::step(LevelData<FArrayBox>& a_U,
130  LevelData<FArrayBox> a_flux[CH_SPACEDIM],
131  LevelFluxRegister& a_finerFluxRegister,
132  LevelFluxRegister& a_coarserFluxRegister,
133  LevelData<FArrayBox>& a_split_tags,
134  const LevelData<FArrayBox>& a_UCoarseOld,
135  const Real& a_TCoarseOld,
136  const LevelData<FArrayBox>& a_UCoarseNew,
137  const Real& a_TCoarseNew,
138  const Real& a_time,
139  const Real& a_dt,
140  const Real& a_cfl)
141 {
142  CH_TIMERS("LevelPluto::step");
143 
144  CH_TIMER("LevelPluto::step::setup" ,timeSetup);
145  CH_TIMER("LevelPluto::step::update" ,timeUpdate);
146  CH_TIMER("LevelPluto::step::reflux" ,timeReflux);
147  CH_TIMER("LevelPluto::step::conclude",timeConclude);
148 
149  // Make sure everything is defined
150  CH_assert(m_isDefined);
151 
152  CH_START(timeSetup);
153 
154  // Clear flux registers with next finer level
155  if (m_hasFiner && (g_intStage == 1))
156  {
157  a_finerFluxRegister.setToZero();
158  }
159 
160  // Setup an interval corresponding to the conserved variables
161  Interval UInterval(0,m_numCons-1);
162 
163  {
164  CH_TIME("setup::localU");
165  for (DataIterator dit = m_U.dataIterator(); dit.ok(); ++dit)
166  {
167  m_U[dit].setVal(0.0); // Gets rid of denormalized crap.
168  m_U[dit].copy(a_U[dit]);
169  }
170 
171  m_U.exchange(m_exchangeCopier);
172  }
173 
174  // Fill m_U's ghost cells using fillInterp
175  if (m_hasCoarser)
176  {
177  // Fraction "a_time" falls between the old and the new coarse times
178  Real alpha = (a_time - a_TCoarseOld) / (a_TCoarseNew - a_TCoarseOld);
179 
180  // Truncate the fraction to the range [0,1] to remove floating-point
181  // subtraction roundoff effects
182  Real eps = 0.04 * a_dt / m_refineCoarse;
183 
184  if (Abs(alpha) < eps) alpha = 0.0;
185  if (Abs(1.0-alpha) < eps) alpha = 1.0;
186 
187  // Current time before old coarse time
188  if (alpha < 0.0)
189  {
190  MayDay::Error( "LevelPluto::step: alpha < 0.0");
191  }
192 
193  // Current time after new coarse time
194  if (alpha > 1.0)
195  {
196  MayDay::Error( "LevelPluto::step: alpha > 1.0");
197  }
198 
199  // Interpolate ghost cells from next coarser level using both space
200  // and time interpolation
201  m_patcher.fillInterp(m_U,
202  a_UCoarseOld,
203  a_UCoarseNew,
204  alpha,
205  0,0,m_numCons);
206  }
207 
208  // Potentially used in boundary conditions
209  m_patchPluto->setCurrentTime(a_time);
210 
211  // Use to restrict maximum wave speed away from zero
212  Real maxWaveSpeed = 1.e-12;
213  Real minDtCool = 1.e38;
214 
215  // The grid structure
216  Grid *grid;
217  static Time_Step Dts;
218  Real inv_dt;
219 
220  #ifdef GLM_MHD
221  glm_ch = g_coeff_dl_min*m_dx/(a_dt + 1.e-16)*a_cfl;
222 // glm_ch = g_coeff_dl_min/(a_dt + 1.e-16)*a_cfl; /* If subcycling is turned off */
223  glm_ch = MIN(glm_ch,glm_ch_max*g_coeff_dl_min);
224  #endif
225 
226  CH_STOP(timeSetup);
227  g_level_dx = m_dx;
228 
229  // Beginning of loop through patches/grids.
230  for (DataIterator dit = m_grids.dataIterator(); dit.ok(); ++dit){
231  CH_START(timeUpdate);
232 
233  // The current box
234  Box curBox = m_grids.get(dit());
235 
236  // The current grid of conserved variables
237  FArrayBox& curU = m_U[dit];
238 
239  // The current grid of volumes
240  #if GEOMETRY != CARTESIAN
241  const FArrayBox& curdV = m_dV[dit()];
242  #else
243  const FArrayBox curdV;
244  #endif
245 
246  #ifdef SKIP_SPLIT_CELLS
247  // The current grid of split/unsplit tags
248  FArrayBox& split_tags = a_split_tags[dit];
249  #else
250  FArrayBox split_tags;
251  #endif
252 
253  #if (TIME_STEPPING == RK2)
254  // The current storage for flags (RK2 only)
255  BaseFab<unsigned char>& flags = m_Flags[dit];
256  // Local temporary storage for conserved variables
257  FArrayBox& curUtmp = m_Utmp[dit];
258  #else
259  BaseFab<unsigned char> flags;
260  FArrayBox curUtmp;
261  #endif
262 
263  // The fluxes computed for this grid - used for refluxing and returning
264  // other face centered quantities
265  FluxBox flux;
266 
267  // Set the current box for the patch integrator
268  m_patchPluto->setCurrentBox(curBox);
269 
270  Real minDtCoolGrid;
271 
272  grid = m_structs_grid[dit].getGrid();
273 
274  IBEG = grid[IDIR].lbeg; IEND = grid[IDIR].lend;
275  JBEG = grid[JDIR].lbeg; JEND = grid[JDIR].lend;
276  KBEG = grid[KDIR].lbeg; KEND = grid[KDIR].lend;
277 
278  NX1 = grid[IDIR].np_int;
279  NX2 = grid[JDIR].np_int;
280  NX3 = grid[KDIR].np_int;
281 
282  NX1_TOT = grid[IDIR].np_tot;
283  NX2_TOT = grid[JDIR].np_tot;
284  NX3_TOT = grid[KDIR].np_tot;
285 
286  SetRBox(); /* RBox structures must be redefined for each patch */
287 
288  g_dt = a_dt;
289  g_time = a_time;
290  g_maxRiemannIter = 0;
291  PLM_CoefficientsSet (grid); /* -- these may be needed by
292  shock flattening algorithms */
293  #if RECONSTRUCTION == PARABOLIC
294  PPM_CoefficientsSet (grid);
295  #endif
296 
297  // reset time step coefficients
298  if (Dts.cmax == NULL) Dts.cmax = ARRAY_1D(NMAX_POINT, double);
299  int id;
300  Dts.inv_dta = 1.e-18;
301  Dts.inv_dtp = 1.e-18;
302  Dts.dt_cool = 1.e18;
303  Dts.cfl = a_cfl;
304  Where(-1, grid); /* -- store grid for subsequent calls -- */
305 
306  // Take one step
307  m_patchPluto->advanceStep (curU, curUtmp, curdV, split_tags, flags, flux,
308  &Dts, curBox, grid);
309 
310  inv_dt = Dts.inv_dta + 2.0*Dts.inv_dtp;
311  maxWaveSpeed = Max(maxWaveSpeed, inv_dt); // Now the inverse of the timestep
312 
313  minDtCool = Min(minDtCool, Dts.dt_cool/a_cfl);
314 
315  CH_STOP(timeUpdate);
316 
317  CH_START(timeReflux);
318 
319  // Do flux register updates
320  for (int idir = 0; idir < SpaceDim; idir++) {
321  // Increment coarse flux register between this level and the next
322  // finer level - this level is the next coarser level with respect
323  // to the next finer level
324  if (m_hasFiner) {
325  a_finerFluxRegister.incrementCoarse(flux[idir],a_dt,dit(),
326  UInterval, UInterval,idir);
327  }
328 
329  // Increment fine flux registers between this level and the next
330  // coarser level - this level is the next finer level with respect
331  // to the next coarser level
332  if (m_hasCoarser) {
333  a_coarserFluxRegister.incrementFine(flux[idir],a_dt,dit(),
334  UInterval, UInterval,idir);
335  }
336  }
337 
338  CH_STOP(timeReflux);
339  }
340 
341  CH_START(timeConclude);
342 
343  {
344  CH_TIME("conclude::copyU");
345  // Now that we have completed the updates of all the patches, we copy the
346  // contents of temporary storage, U, into the permanent storage, a_U.
347  for(DataIterator dit = m_U.dataIterator(); dit.ok(); ++dit){
348  a_U[dit].copy(m_U[dit]);
349  }
350  }
351 
352  // Find the minimum of dt's over this level
353  Real local_dtNew = 1. / maxWaveSpeed;
354  local_dtNew = Min(local_dtNew,minDtCool);
355  Real dtNew;
356 
357  {
358  CH_TIME("conclude::getDt");
359  #ifdef CH_MPI
360  #if (TIME_STEPPING == RK2) && (COOLING == NO)
361  if (g_intStage == 1) {
362  #endif
363  int result = MPI_Allreduce(&local_dtNew, &dtNew, 1, MPI_CH_REAL,
364  MPI_MIN, Chombo_MPI::comm);
365  if(result != MPI_SUCCESS){ //bark!!!
366  MayDay::Error("sorry, but I had a communcation error on new dt");
367  }
368  #if (TIME_STEPPING == RK2) && (COOLING == NO)
369  } else {
370  dtNew = local_dtNew;
371  }
372  #endif
373  #else
374  dtNew = local_dtNew;
375  #endif
376  }
377 
378  CH_STOP(timeConclude);
379 
380  // Return the maximum stable time step
381  return dtNew;
382 }
383 
384 void LevelPluto::setGridLevel()
385 {
386 
387  CH_TIME("LevelPluto::setGrid");
388 
389  m_structs_grid.define(m_grids);
390 
391  #if GEOMETRY != CARTESIAN
392  m_dV.define(m_grids,CHOMBO_NDV,m_numGhost*IntVect::Unit);
393  #endif
394 
395  Real dlMinLoc = 1.e30;
396 
397  for (DataIterator dit = m_grids.dataIterator(); dit.ok(); ++dit)
398  {
399  // The current box
400  Box curBox = m_grids.get(dit());
401  struct GRID* grid = m_structs_grid[dit].getGrid();
402 
403  #if GEOMETRY != CARTESIAN
404  FArrayBox& curdV = m_dV[dit()];
405  #else
406  FArrayBox curdV;
407  #endif
408 
409  m_patchPluto->setGrid(curBox, grid, curdV);
410 
411  for (int idir = 0; idir < SpaceDim; idir++) dlMinLoc = Min(dlMinLoc,grid[idir].dl_min);
412  }
413 
414 #if (GEOMETRY == CARTESIAN) || (GEOMETRY == CYLINDRICAL)
415 
416  D_EXPAND(m_dl_min = m_dx; ,
417  m_dl_min = MIN(m_dl_min,m_dx*g_x2stretch); ,
418  m_dl_min = MIN(m_dl_min,m_dx*g_x3stretch); )
419 #else
420 
421  #ifdef CH_MPI
422  Real dlMin;
423  int result = MPI_Allreduce(&dlMinLoc, &dlMin, 1, MPI_CH_REAL,
424  MPI_MIN, Chombo_MPI::comm);
425  if(result != MPI_SUCCESS){ //bark!!!
426  MayDay::Error("sorry, but I had a communcation error on dlMin");
427  }
428  m_dl_min = dlMin;
429  #else
430  m_dl_min = dlMinLoc;
431  #endif
432 
433 #endif
434 
435 }
436 
437 #if GEOMETRY != CARTESIAN
438 const LevelData<FArrayBox>& LevelPluto::getdV() const
439 {
440  return m_dV;
441 }
442 #endif
443 
444 Real LevelPluto::getDlMin()
445 {
446 
447  CH_TIME("LevelPluto::getDlMin");
448 
449  return m_dl_min / m_dx;
450 // return m_dl_min; /* If subcycling is turned off */
451 
452 
453 }
454 
455 #include "NamespaceFooter.H"
static double alpha
Definition: init.c:3
void PPM_CoefficientsSet(Grid *grid)
Definition: ppm_coeffs.c:58
int GetNghost(void)
Definition: get_nghost.c:18
long int NX1
Number of interior zones in the X1 directions (boundaries excluded) for the local processor...
Definition: globals.h:48
long int NX2_TOT
Total number of zones in the X2 direction (boundaries included) for the local processor.
Definition: globals.h:57
int g_intStage
Gives the current integration stage of the time stepping method (predictor = 0, 1st corrector = 1...
Definition: globals.h:98
int g_maxRiemannIter
Maximum number of iterations for iterative Riemann Solver.
Definition: globals.h:93
double g_dt
The current integration time step.
Definition: globals.h:118
int lend
Local end index for the local array.
Definition: structs.h:118
int lbeg
Local start index for the local array.
Definition: structs.h:117
double * cmax
Maximum signal velocity for hyperbolic eqns.
Definition: structs.h:214
#define KDIR
Definition: pluto.h:195
double inv_dtp
Inverse of diffusion (parabolic) time step .
Definition: structs.h:217
#define MIN(a, b)
Definition: macros.h:104
double inv_dta
Inverse of advection (hyperbolic) time step, .
Definition: structs.h:215
double dt_cool
Cooling time step.
Definition: structs.h:219
#define eps
long int NX2
Number of interior zones in the X2 directions (boundaries excluded) for the local processor...
Definition: globals.h:50
#define IDIR
Definition: pluto.h:193
void PLM_CoefficientsSet(Grid *grid)
Definition: plm_coeffs.c:30
Definition: structs.h:78
long int NX3_TOT
Total number of zones in the X3 direction (boundaries included) for the local processor.
Definition: globals.h:59
long int IEND
Upper grid index of the computational domain in the the X1 direction for the local processor...
Definition: globals.h:37
void Where(int, Grid *)
Definition: tools.c:235
double dl_min
minimum cell length (e.g.
Definition: structs.h:94
void SetRBox(void)
Definition: rbox.c:33
double cfl
Courant number for advection.
Definition: structs.h:220
#define ARRAY_1D(nx, type)
Definition: prototypes.h:170
D_EXPAND(tot/[n]=(double) grid[IDIR].np_int_glob;, tot/[n]=(double) grid[JDIR].np_int_glob;, tot/[n]=(double) grid[KDIR].np_int_glob;)
Definition: analysis.c:27
long int NMAX_POINT
Maximum number of points among the three directions, boundaries excluded.
Definition: globals.h:62
double g_time
The current integration time.
Definition: globals.h:117
long int KBEG
Lower grid index of the computational domain in the the X3 direction for the local processor...
Definition: globals.h:43
int np_tot
Total number of points in the local domain (boundaries included).
Definition: structs.h:100
long int KEND
Upper grid index of the computational domain in the the X3 direction for the local processor...
Definition: globals.h:45
double glm_ch
The propagation speed of divergence error.
Definition: glm.c:21
#define JDIR
Definition: pluto.h:194
long int JBEG
Lower grid index of the computational domain in the the X2 direction for the local processor...
Definition: globals.h:39
long int JEND
Upper grid index of the computational domain in the the X2 direction for the local processor...
Definition: globals.h:41
long int NX1_TOT
Total number of zones in the X1 direction (boundaries included) for the local processor.
Definition: globals.h:55
long int NX3
Number of interior zones in the X3 directions (boundaries excluded) for the local processor...
Definition: globals.h:52
long int IBEG
Lower grid index of the computational domain in the the X1 direction for the local processor...
Definition: globals.h:35
int np_int
Total number of points in the local domain (boundaries excluded).
Definition: structs.h:102