ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERFPhysBCFunct_base Class Reference

#include <ERF_PhysBCFunct.H>

Collaboration diagram for ERFPhysBCFunct_base:

Public Member Functions

 ERFPhysBCFunct_base (const int lev, const amrex::Geometry &geom, const amrex::Vector< amrex::BCRec > &domain_bcs_type, const amrex::Gpu::DeviceVector< amrex::BCRec > &domain_bcs_type_d, std::unique_ptr< amrex::MultiFab > &z_phys_nd, bool moving_terrain)
 
 ~ERFPhysBCFunct_base ()
 
void operator() (amrex::MultiFab &mf, int icomp, int ncomp, amrex::IntVect const &nghost)
 
void impose_lateral_basestate_bcs (const amrex::Array4< amrex::Real > &dest_arr, const amrex::Box &bx, const amrex::Box &domain, int ncomp, const amrex::IntVect &nghost)
 
void impose_vertical_basestate_bcs (const amrex::Array4< amrex::Real > &dest_arr, const amrex::Array4< amrex::Real const > &z_nd, const amrex::Box &bx, const amrex::Box &domain, int ncomp, const amrex::IntVect &nghost)
 

Private Attributes

int m_lev
 
amrex::Geometry m_geom
 
bool m_moving_terrain
 
amrex::Vector< amrex::BCRec > m_domain_bcs_type
 
amrex::Gpu::DeviceVector< amrex::BCRec > m_domain_bcs_type_d
 
amrex::MultiFab * m_z_phys_nd
 

Constructor & Destructor Documentation

◆ ERFPhysBCFunct_base()

ERFPhysBCFunct_base::ERFPhysBCFunct_base ( const int  lev,
const amrex::Geometry &  geom,
const amrex::Vector< amrex::BCRec > &  domain_bcs_type,
const amrex::Gpu::DeviceVector< amrex::BCRec > &  domain_bcs_type_d,
std::unique_ptr< amrex::MultiFab > &  z_phys_nd,
bool  moving_terrain 
)
inline

Construct the base-state physical boundary-condition functor.

Parameters
[in]levlevel index
[in]geomgeometry for the level
[in]domain_bcs_typehost boundary-condition records
[in]domain_bcs_type_ddevice boundary-condition records
[in]z_phys_ndnodal physical height MultiFab
[in]moving_terrainwhether moving terrain is active
486  : m_lev(lev), m_geom(geom),
487  m_moving_terrain(moving_terrain),
488  m_domain_bcs_type(domain_bcs_type),
489  m_domain_bcs_type_d(domain_bcs_type_d),
490  m_z_phys_nd(z_phys_nd.get())
491  {}
amrex::Gpu::DeviceVector< amrex::BCRec > m_domain_bcs_type_d
Definition: ERF_PhysBCFunct.H:541
int m_lev
Definition: ERF_PhysBCFunct.H:537
amrex::MultiFab * m_z_phys_nd
Definition: ERF_PhysBCFunct.H:542
amrex::Geometry m_geom
Definition: ERF_PhysBCFunct.H:538
bool m_moving_terrain
Definition: ERF_PhysBCFunct.H:539
amrex::Vector< amrex::BCRec > m_domain_bcs_type
Definition: ERF_PhysBCFunct.H:540

◆ ~ERFPhysBCFunct_base()

ERFPhysBCFunct_base::~ERFPhysBCFunct_base ( )
inline

Destroy the base-state physical boundary-condition functor.

496 {}

Member Function Documentation

◆ impose_lateral_basestate_bcs()

void ERFPhysBCFunct_base::impose_lateral_basestate_bcs ( const amrex::Array4< amrex::Real > &  dest_arr,
const amrex::Box &  bx,
const amrex::Box &  domain,
int  ncomp,
const amrex::IntVect &  nghost 
)

Impose lateral boundary conditions on base-state variables.

Parameters
[in,out]dest_arrbase-state data to be filled
[in]bxbox holding data to be filled
[in]domainsimulation domain
[in]ncompnumber of components
[in]nghostnumber of ghost cells to be filled

Impose lateral boundary conditions on the base state

Parameters
[in,out]dest_arrcell-centered data to be filled
[in]bxbox holding data to be filled
[in]domainsimulation domain
[in]ncompnumber of base-state components to fill
[in]nghostnumber of ghost cells in each coordinate direction
21 {
22  BL_PROFILE_VAR("impose_lateral_base_bcs()",impose_lateral_base_bcs);
23  //
24  // Note that the "bx" that comes in here has already been grown in the lateral directions
25  // but not in the vertical
26  //
27 
28  const int* bxlo = bx.loVect();
29  const int* bxhi = bx.hiVect();
30 
31  const int* dlo = domain.loVect();
32  const int* dhi = domain.hiVect();
33 
34  const auto& dom_lo = lbound(domain);
35  const auto& dom_hi = ubound(domain);
36 
37  // xlo: ori = 0
38  // ylo: ori = 1
39  // zlo: ori = 2
40  // xhi: ori = 3
41  // yhi: ori = 4
42  // zhi: ori = 5
43 
44  // Based on BCRec for the domain, we need to make BCRec for this Box
45  // 0 is used as starting index for bcrs
46  Vector<BCRec> bcrs(ncomp);
47 
48  int bc_comp = BaseBCVars::rho0_bc_comp;
49 
50  for (int nc = 0; nc < ncomp; nc++)
51  {
52  for (int dir = 0; dir < AMREX_SPACEDIM; dir++)
53  {
54  bcrs[nc].setLo(dir, ( bxlo[dir]<=dlo[dir]
55  ? m_domain_bcs_type[bc_comp].lo(dir) : BCType::int_dir ));
56  bcrs[nc].setHi(dir, ( bxhi[dir]>=dhi[dir]
57  ? m_domain_bcs_type[bc_comp].hi(dir) : BCType::int_dir ));
58  }
59  }
60 
61  Gpu::DeviceVector<BCRec> bcrs_d(ncomp);
62  Gpu::copyAsync(Gpu::hostToDevice, bcrs.begin(), bcrs.end(), bcrs_d.begin());
63  const BCRec* bc_ptr = bcrs_d.data();
64 
65  GeometryData const& geomdata = m_geom.data();
66  bool is_periodic_in_x = geomdata.isPeriodic(0);
67  bool is_periodic_in_y = geomdata.isPeriodic(1);
68 
69  // Do ghost cells in x-direction but not reaching out in y
70  // The corners we miss here will be covered in the y-loop below or by periodicity
71  if (!is_periodic_in_x)
72  {
73  // Populate ghost cells on lo-x and hi-x domain boundaries
74  Box bx_xlo(bx); bx_xlo.setBig (0,dom_lo.x-1);
75  Box bx_xhi(bx); bx_xhi.setSmall(0,dom_hi.x+1);
76 
78  bx_xlo, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n)
79  {
80  int dest_comp = n;
81  int l_bc_type = bc_ptr[n].lo(0);
82  int iflip = dom_lo.x - 1 - i;
83  if (l_bc_type == ERFBCType::foextrap) {
84  dest_arr(i,j,k,dest_comp) = dest_arr(dom_lo.x,j,k,dest_comp);
85  } else if (l_bc_type == ERFBCType::open) {
86  dest_arr(i,j,k,dest_comp) = dest_arr(dom_lo.x,j,k,dest_comp);
87  } else if (l_bc_type == ERFBCType::reflect_even) {
88  dest_arr(i,j,k,dest_comp) = dest_arr(iflip,j,k,dest_comp);
89  }
90  },
91  bx_xhi, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n)
92  {
93  int dest_comp = n;
94  int h_bc_type = bc_ptr[n].hi(0);
95  int iflip = 2*dom_hi.x + 1 - i;
96  if (h_bc_type == ERFBCType::foextrap) {
97  dest_arr(i,j,k,dest_comp) = dest_arr(dom_hi.x,j,k,dest_comp);
98  } else if (h_bc_type == ERFBCType::open) {
99  dest_arr(i,j,k,dest_comp) = dest_arr(dom_hi.x,j,k,dest_comp);
100  } else if (h_bc_type == ERFBCType::reflect_even) {
101  dest_arr(i,j,k,dest_comp) = dest_arr(iflip,j,k,dest_comp);
102  }
103  }
104  );
105  }
106 
107  if (!is_periodic_in_y)
108  {
109  // Populate ghost cells on lo-y and hi-y domain boundaries
110  Box bx_ylo(bx); bx_ylo.setBig (1,dom_lo.y-1);
111  Box bx_yhi(bx); bx_yhi.setSmall(1,dom_hi.y+1);
112  if (bx_ylo.smallEnd(2) != domain.smallEnd(2)) bx_ylo.growLo(2,nghost[2]);
113  if (bx_ylo.bigEnd(2) != domain.bigEnd(2)) bx_ylo.growHi(2,nghost[2]);
114  if (bx_yhi.smallEnd(2) != domain.smallEnd(2)) bx_yhi.growLo(2,nghost[2]);
115  if (bx_yhi.bigEnd(2) != domain.bigEnd(2)) bx_yhi.growHi(2,nghost[2]);
116  ParallelFor(
117  bx_ylo, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n)
118  {
119  int dest_comp = n;
120  int l_bc_type = bc_ptr[n].lo(1);
121  int jflip = dom_lo.y - 1 - j;
122  if (l_bc_type == ERFBCType::foextrap) {
123  dest_arr(i,j,k,dest_comp) = dest_arr(i,dom_lo.y,k,dest_comp);
124  } else if (l_bc_type == ERFBCType::open) {
125  dest_arr(i,j,k,dest_comp) = dest_arr(i,dom_lo.y,k,dest_comp);
126  } else if (l_bc_type == ERFBCType::reflect_even) {
127  dest_arr(i,j,k,dest_comp) = dest_arr(i,jflip,k,dest_comp);
128  }
129 
130  },
131  bx_yhi, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n)
132  {
133  int dest_comp = n;
134  int h_bc_type = bc_ptr[n].hi(1);
135  int jflip = 2*dom_hi.y + 1 - j;
136  if (h_bc_type == ERFBCType::foextrap) {
137  dest_arr(i,j,k,dest_comp) = dest_arr(i,dom_hi.y,k,dest_comp);
138  } else if (h_bc_type == ERFBCType::open) {
139  dest_arr(i,j,k,dest_comp) = dest_arr(i,dom_hi.y,k,dest_comp);
140  } else if (h_bc_type == ERFBCType::reflect_even) {
141  dest_arr(i,j,k,dest_comp) = dest_arr(i,jflip,k,dest_comp);
142  }
143  }
144  );
145  }
146 
147  // Next do ghost cells in x-direction but not reaching out in y
148  // The corners we miss here will be covered in the y-loop below or by periodicity
149  if (!is_periodic_in_x)
150  {
151  // Populate ghost cells on lo-x and hi-x domain boundaries
152  Box bx_xlo(bx); bx_xlo.setBig (0,dom_lo.x-1);
153  Box bx_xhi(bx); bx_xhi.setSmall(0,dom_hi.x+1);
154  if (bx_xlo.smallEnd(2) != domain.smallEnd(2)) bx_xlo.growLo(2,nghost[2]);
155  if (bx_xlo.bigEnd(2) != domain.bigEnd(2)) bx_xlo.growHi(2,nghost[2]);
156  if (bx_xhi.smallEnd(2) != domain.smallEnd(2)) bx_xhi.growLo(2,nghost[2]);
157  if (bx_xhi.bigEnd(2) != domain.bigEnd(2)) bx_xhi.growHi(2,nghost[2]);
158  ParallelFor(
159  bx_xlo, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n)
160  {
161  int dest_comp = n;
162  int l_bc_type = bc_ptr[n].lo(0);
163  int iflip = dom_lo.x - 1 - i;
164  if (l_bc_type == ERFBCType::foextrap) {
165  dest_arr(i,j,k,dest_comp) = dest_arr(dom_lo.x,j,k,dest_comp);
166  } else if (l_bc_type == ERFBCType::open) {
167  dest_arr(i,j,k,dest_comp) = dest_arr(dom_lo.x,j,k,dest_comp);
168  } else if (l_bc_type == ERFBCType::reflect_even) {
169  dest_arr(i,j,k,dest_comp) = dest_arr(iflip,j,k,dest_comp);
170  } else if (l_bc_type == ERFBCType::reflect_odd) {
171  dest_arr(i,j,k,dest_comp) = -dest_arr(iflip,j,k,dest_comp);
172  } else if (l_bc_type == ERFBCType::hoextrap) {
173  Real delta_i = static_cast<Real>(dom_lo.x - i);
174  dest_arr(i,j,k,dest_comp) = (one + delta_i)*dest_arr(dom_lo.x,j,k,dest_comp) - delta_i*dest_arr(dom_lo.x+1,j,k,dest_comp) ;
175  }
176  },
177  bx_xhi, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n)
178  {
179  int dest_comp = n;
180  int h_bc_type = bc_ptr[n].hi(0);
181  int iflip = 2*dom_hi.x + 1 - i;
182  if (h_bc_type == ERFBCType::foextrap) {
183  dest_arr(i,j,k,dest_comp) = dest_arr(dom_hi.x,j,k,dest_comp);
184  } else if (h_bc_type == ERFBCType::open) {
185  dest_arr(i,j,k,dest_comp) = dest_arr(dom_hi.x,j,k,dest_comp);
186  } else if (h_bc_type == ERFBCType::reflect_even) {
187  dest_arr(i,j,k,dest_comp) = dest_arr(iflip,j,k,dest_comp);
188  } else if (h_bc_type == ERFBCType::reflect_odd) {
189  dest_arr(i,j,k,dest_comp) = -dest_arr(iflip,j,k,dest_comp);
190  } else if (h_bc_type == ERFBCType::hoextrap) {
191  Real delta_i = static_cast<Real>(i - dom_hi.x);
192  dest_arr(i,j,k,dest_comp) = (one + delta_i)*dest_arr(dom_hi.x,j,k,dest_comp) - delta_i*dest_arr(dom_hi.x-1,j,k,dest_comp) ;
193  }
194  }
195  );
196  }
197 
198  if (!is_periodic_in_y)
199  {
200  // Populate ghost cells on lo-y and hi-y domain boundaries
201  Box bx_ylo(bx); bx_ylo.setBig (1,dom_lo.y-1);
202  Box bx_yhi(bx); bx_yhi.setSmall(1,dom_hi.y+1);
203  if (bx_ylo.smallEnd(2) != domain.smallEnd(2)) bx_ylo.growLo(2,nghost[2]);
204  if (bx_ylo.bigEnd(2) != domain.bigEnd(2)) bx_ylo.growHi(2,nghost[2]);
205  if (bx_yhi.smallEnd(2) != domain.smallEnd(2)) bx_yhi.growLo(2,nghost[2]);
206  if (bx_yhi.bigEnd(2) != domain.bigEnd(2)) bx_yhi.growHi(2,nghost[2]);
207  ParallelFor(
208  bx_ylo, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n)
209  {
210  int dest_comp = n;
211  int l_bc_type = bc_ptr[n].lo(1);
212  int jflip = dom_lo.y - 1 - j;
213  if (l_bc_type == ERFBCType::foextrap) {
214  dest_arr(i,j,k,dest_comp) = dest_arr(i,dom_lo.y,k,dest_comp);
215  } else if (l_bc_type == ERFBCType::open) {
216  dest_arr(i,j,k,dest_comp) = dest_arr(i,dom_lo.y,k,dest_comp);
217  } else if (l_bc_type == ERFBCType::reflect_even) {
218  dest_arr(i,j,k,dest_comp) = dest_arr(i,jflip,k,dest_comp);
219  } else if (l_bc_type == ERFBCType::reflect_odd) {
220  dest_arr(i,j,k,dest_comp) = -dest_arr(i,jflip,k,dest_comp);
221  } else if (l_bc_type == ERFBCType::hoextrap) {
222  Real delta_j = static_cast<Real>(dom_lo.y - j);
223  dest_arr(i,j,k,dest_comp) = (one + delta_j)*dest_arr(i,dom_lo.y,k,dest_comp) - delta_j*dest_arr(i,dom_lo.y+1,k,dest_comp) ;
224  }
225 
226  },
227  bx_yhi, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n)
228  {
229  int dest_comp = n;
230  int h_bc_type = bc_ptr[n].hi(1);
231  int jflip = 2*dom_hi.y + 1 - j;
232  if (h_bc_type == ERFBCType::foextrap) {
233  dest_arr(i,j,k,dest_comp) = dest_arr(i,dom_hi.y,k,dest_comp);
234  } else if (h_bc_type == ERFBCType::open) {
235  dest_arr(i,j,k,dest_comp) = dest_arr(i,dom_hi.y,k,dest_comp);
236  } else if (h_bc_type == ERFBCType::reflect_even) {
237  dest_arr(i,j,k,dest_comp) = dest_arr(i,jflip,k,dest_comp);
238  } else if (h_bc_type == ERFBCType::reflect_odd) {
239  dest_arr(i,j,k,dest_comp) = -dest_arr(i,jflip,k,dest_comp);
240  } else if (h_bc_type == ERFBCType::hoextrap) {
241  Real delta_j = static_cast<Real>(j - dom_hi.y);
242  dest_arr(i,j,k,dest_comp) = (one + delta_j)*dest_arr(i,dom_hi.y,k,dest_comp) - delta_j*dest_arr(i,dom_hi.y-1,k,dest_comp);
243  }
244  }
245  );
246  }
247  Gpu::streamSynchronize();
248 }
constexpr amrex::Real one
Definition: ERF_Constants.H:9
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);})
amrex::Real Real
Definition: ERF_ShocInterface.H:19
@ rho0_bc_comp
Definition: ERF_IndexDefines.H:113
@ open
Definition: ERF_IndexDefines.H:256
@ reflect_odd
Definition: ERF_IndexDefines.H:245
@ hoextrap
Definition: ERF_IndexDefines.H:250
@ foextrap
Definition: ERF_IndexDefines.H:248
@ int_dir
Definition: ERF_IndexDefines.H:246
@ reflect_even
Definition: ERF_IndexDefines.H:247
@ nc
Definition: ERF_Morrison.H:45
Here is the call graph for this function:

◆ impose_vertical_basestate_bcs()

void ERFPhysBCFunct_base::impose_vertical_basestate_bcs ( const amrex::Array4< amrex::Real > &  dest_arr,
const amrex::Array4< amrex::Real const > &  z_nd,
const amrex::Box &  bx,
const amrex::Box &  domain,
int  ncomp,
const amrex::IntVect &  nghost 
)

Impose vertical boundary conditions on base-state variables.

Parameters
[in,out]dest_arrbase-state data to be filled
[in]z_ndnodal physical height
[in]bxbox holding data to be filled
[in]domainsimulation domain
[in]ncompnumber of components
[in]nghostnumber of ghost cells to be filled

Impose vertical boundary conditions on the base state

Parameters
[in,out]dest_arrcell-centered base-state data to be filled
[in]z_phys_ndheight coordinate at nodes, unused for base-state fills
[in]bxbox holding data to be filled
[in]domainsimulation domain
[in]ncompnumber of base-state components to fill
[in]nghostnumber of ghost cells, unused for base-state fills
266 {
267  BL_PROFILE_VAR("impose_vertical_base_bcs()",impose_vertical_base_bcs);
268 
269  const auto& dom_lo = lbound(domain);
270  const auto& dom_hi = ubound(domain);
271 
272  Box bx_zlo(bx); bx_zlo.setBig(2,dom_lo.z-1);
273  Box bx_zhi(bx); bx_zhi.setSmall(2,dom_hi.z+1);
274  ParallelFor(
275  bx_zlo, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n)
276  {
277  dest_arr(i,j,k,n) = dest_arr(i,j,dom_lo.z,n);
278  },
279  bx_zhi, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n)
280  {
281  dest_arr(i,j,k,n) = dest_arr(i,j,dom_hi.z,n);
282  }
283  );
284 }
Here is the call graph for this function:

◆ operator()()

void ERFPhysBCFunct_base::operator() ( amrex::MultiFab &  mf,
int  icomp,
int  ncomp,
amrex::IntVect const &  nghost 
)

Impose physical boundary conditions at domain boundaries

Parameters
[in,out]mfbase-state MultiFab to be filled
[in]icompstarting component for base-state variables
[in]ncompnumber of components for base-state variables
[in]nghostnumber of ghost cells to be filled

Impose physical boundary conditions on the base state.

Parameters
[in,out]mfbase-state MultiFab to be filled
[in]icompstarting component, unused here
[in]ncompnumber of components
[in]nghostnumber of ghost cells to be filled
361 {
362  BL_PROFILE("ERFPhysBCFunct_base::()");
363 
364  if (m_geom.isAllPeriodic()) return;
365 
366  const auto& domain = m_geom.Domain();
367 
368  // Create a grown domain box containing valid + periodic cells
369  Box gdomain = domain;
370  for (int i = 0; i < AMREX_SPACEDIM; ++i) {
371  if (m_geom.isPeriodic(i)) {
372  gdomain.grow(i, nghost[i]);
373  }
374  }
375 
376  //
377  // We fill all of the interior and periodic ghost cells first, so we can fill
378  // those directly inside the lateral and vertical calls.
379  //
380  mf.FillBoundary(m_geom.periodicity());
381 
382 #ifdef AMREX_USE_OMP
383 #pragma omp parallel if (Gpu::notInLaunchRegion())
384 #endif
385  {
386  for (MFIter mfi(mf,false); mfi.isValid(); ++mfi)
387  {
388  //
389  // This is the box we pass to the different routines
390  // NOTE -- this is the full grid box NOT the tile box
391  //
392  Box bx = mfi.validbox();
393 
394  //
395  // These are the boxes we use to test on relative to the domain
396  //
397  Box cbx1 = bx; cbx1.grow(IntVect(nghost[0],nghost[1],0));
398  Box cbx2 = bx; cbx2.grow(nghost);
399 
400  Array4<const Real> z_nd_arr;
401 
402  if (m_z_phys_nd) {
403  z_nd_arr = m_z_phys_nd->const_array(mfi);
404  }
405 
406  if (!gdomain.contains(cbx2)) {
407  const Array4<Real> base_arr = mf.array(mfi);
408 
409  impose_lateral_basestate_bcs(base_arr,cbx1,domain,ncomp,nghost);
410  if (!m_moving_terrain) { // TODO: I don't know why the CI test fails if this is called
411  impose_vertical_basestate_bcs(base_arr,z_nd_arr,cbx2,domain,ncomp,nghost);
412  }
413  }
414 
415  } // MFIter
416  } // OpenMP
417 } // operator()
void impose_vertical_basestate_bcs(const amrex::Array4< amrex::Real > &dest_arr, const amrex::Array4< amrex::Real const > &z_nd, const amrex::Box &bx, const amrex::Box &domain, int ncomp, const amrex::IntVect &nghost)
Definition: ERF_BoundaryConditionsBaseState.cpp:260
void impose_lateral_basestate_bcs(const amrex::Array4< amrex::Real > &dest_arr, const amrex::Box &bx, const amrex::Box &domain, int ncomp, const amrex::IntVect &nghost)
Definition: ERF_BoundaryConditionsBaseState.cpp:18

Member Data Documentation

◆ m_domain_bcs_type

amrex::Vector<amrex::BCRec> ERFPhysBCFunct_base::m_domain_bcs_type
private

◆ m_domain_bcs_type_d

amrex::Gpu::DeviceVector<amrex::BCRec> ERFPhysBCFunct_base::m_domain_bcs_type_d
private

◆ m_geom

amrex::Geometry ERFPhysBCFunct_base::m_geom
private

◆ m_lev

int ERFPhysBCFunct_base::m_lev
private

◆ m_moving_terrain

bool ERFPhysBCFunct_base::m_moving_terrain
private

◆ m_z_phys_nd

amrex::MultiFab* ERFPhysBCFunct_base::m_z_phys_nd
private

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