ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_FireGrid.H File Reference

Fire grid data structure and construction. More...

#include <AMReX_BoxArray.H>
#include <AMReX_DistributionMapping.H>
#include <AMReX_Geometry.H>
#include <AMReX_MultiFab.H>
#include <AMReX_MFIter.H>
Include dependency graph for ERF_FireGrid.H:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  FireGrid
 2D horizontal fire computational grid More...
 

Functions

FireGrid create_fire_grid (const amrex::BoxArray &ba_atm, const amrex::DistributionMapping &dm_atm, const amrex::Geometry &geom_atm, int C)
 Construct a refined 2D fire grid over one atmospheric level's boxes. More...
 
void fire_fill_boundary (amrex::MultiFab &mf, const amrex::Geometry &geom)
 
void fill_fire_from_atm_k0 (amrex::MultiFab &fire_mf, const amrex::MultiFab &atm_k0, const FireGrid &fg)
 

Detailed Description

Fire grid data structure and construction.

Defines a 2D grid for fire simulation on the horizontal plane, refined by factor C relative to one atmospheric AMR level (erf.fire.anchor_level, the finest level by default). The fire grid covers that level's boxes, keeps their x-y decomposition and their MPI owners, and its index space starts at zero at the lower corner of the region they cover.

Function Documentation

◆ create_fire_grid()

FireGrid create_fire_grid ( const amrex::BoxArray &  ba_atm,
const amrex::DistributionMapping &  dm_atm,
const amrex::Geometry &  geom_atm,
int  C 
)

Construct a refined 2D fire grid over one atmospheric level's boxes.

Parameters
[in]ba_atmBoxArray of the atmospheric level
[in]dm_atmDistributionMapping of the atmospheric level
[in]geom_atmGeometry of the atmospheric level
[in]CRefinement factor (erf.fire.grid_ratio)
Returns
FireGrid over the region the boxes cover; its lev is left at 0 for the caller to set.

Algorithm:

  1. Take the k = 0 slab of each box in ba_atm, keeping the box order.
  2. The region is their bounding rectangle, which must be covered exactly (aborts otherwise); atm_lo is its lower corner.
  3. Shift the slabs by -atm_lo and refine by {C, C, 1}; box n keeps the owner of atmospheric box n, so dm_atm is reused.
  4. The Geometry spans the region: index space 0 to C * size - 1, the physical extent of the region (the domain's own bounds where the region spans the domain), periodic only in a direction the region spans.

◆ fill_fire_from_atm_k0()

void fill_fire_from_atm_k0 ( amrex::MultiFab &  fire_mf,
const amrex::MultiFab &  atm_k0,
const FireGrid &  fg 
)
inline

Copy a k = 0 atmospheric field onto the fire grid: every fire cell takes the value of the atmospheric column it lies in, (i / C + atm_lo[0], j / C + atm_lo[1]). Box n of the fire grid refines box n of the atmospheric level and has the same owner, so one MFIter serves both MultiFabs.

117 {
118  const int C = fg.C;
119  const int lo_x = fg.atm_lo[0];
120  const int lo_y = fg.atm_lo[1];
121  for (amrex::MFIter mfi(fire_mf, false); mfi.isValid(); ++mfi) {
122  auto f = fire_mf.array(mfi);
123  auto a = atm_k0.const_array(mfi);
124  amrex::ParallelFor(mfi.tilebox(), [=] AMREX_GPU_DEVICE (const amrex::IntVect& iv) noexcept
125  {
126  f(iv[0], iv[1], 0) = a(iv[0] / C + lo_x, iv[1] / C + lo_y, 0);
127  });
128  }
129 }
ParallelFor(fab_box, [=] AMREX_GPU_DEVICE(int i, int j, int k) { qrcuten_arr(i, j, k)=Real(0);qscuten_arr(i, j, k)=Real(0);qicuten_arr(i, j, k)=Real(0);})
@ fg
Definition: ERF_AdvanceMorrison.cpp:111
Here is the call graph for this function:

◆ fire_fill_boundary()

void fire_fill_boundary ( amrex::MultiFab &  mf,
const amrex::Geometry &  geom 
)
inline

Exchange the ghost cells of a fire-grid MultiFab and fill the ones outside a non-periodic face of the domain by copying the nearest interior value.

FillBoundary alone leaves those cells untouched, so with an inflow-outflow atmosphere (the fire grid inherits its periodicity) the gradient stencil of the level set read whatever the allocator had left there. Whether that was benign depended on the box layout: one box per rank happened to run, two boxes on a rank blew the level set up at the inflow face within three steps. Every fire-grid exchange goes through here.

83 {
84  mf.FillBoundary(geom.periodicity());
85  const auto ng = mf.nGrowVect();
86  const bool px = geom.isPeriodic(0) || ng[0] == 0;
87  const bool py = geom.isPeriodic(1) || ng[1] == 0;
88  const bool pz = geom.isPeriodic(2) || ng[2] == 0;
89  if (px && py && pz) { return; } // nothing outside a non-periodic face to fill
90  const amrex::Box& dom = geom.Domain();
91  const auto dlo = dom.smallEnd();
92  const auto dhi = dom.bigEnd();
93  const int ncomp = mf.nComp();
94  for (amrex::MFIter mfi(mf); mfi.isValid(); ++mfi) {
95  const amrex::Box& gbx = mfi.fabbox();
96  if (dom.contains(gbx)) { continue; }
97  auto a = mf.array(mfi);
98  amrex::ParallelFor(gbx, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) noexcept
99  {
100  int ic = i, jc = j, kc = k;
101  if (!px) { ic = amrex::min(amrex::max(i, dlo[0]), dhi[0]); }
102  if (!py) { jc = amrex::min(amrex::max(j, dlo[1]), dhi[1]); }
103  if (!pz) { kc = amrex::min(amrex::max(k, dlo[2]), dhi[2]); }
104  if (ic != i || jc != j || kc != k) { a(i, j, k, n) = a(ic, jc, kc, n); }
105  });
106  }
107 }
@ ng
Definition: ERF_Morrison.H:51

Referenced by FireCoupler::read_checkpoint(), and FireCoupler::update_flux_buffer().

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