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, 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::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
 

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,
bool  moving_terrain 
)
inline
267  : m_lev(lev), m_geom(geom),
268  m_moving_terrain(moving_terrain),
269  m_domain_bcs_type(domain_bcs_type),
270  m_domain_bcs_type_d(domain_bcs_type_d)
271  {}
amrex::Gpu::DeviceVector< amrex::BCRec > m_domain_bcs_type_d
Definition: ERF_PhysBCFunct.H:298
int m_lev
Definition: ERF_PhysBCFunct.H:294
amrex::Geometry m_geom
Definition: ERF_PhysBCFunct.H:295
bool m_moving_terrain
Definition: ERF_PhysBCFunct.H:296
amrex::Vector< amrex::BCRec > m_domain_bcs_type
Definition: ERF_PhysBCFunct.H:297

◆ ~ERFPhysBCFunct_base()

ERFPhysBCFunct_base::~ERFPhysBCFunct_base ( )
inline
273 {}

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

◆ impose_vertical_basestate_bcs()

void ERFPhysBCFunct_base::impose_vertical_basestate_bcs ( const amrex::Array4< amrex::Real > &  dest_arr,
const amrex::Box &  bx,
const amrex::Box &  domain,
int  ncomp,
const amrex::IntVect &  nghost 
)
248 {
249  BL_PROFILE_VAR("impose_vertical_base_bcs()",impose_vertical_base_bcs);
250 
251  const auto& dom_lo = lbound(domain);
252  const auto& dom_hi = ubound(domain);
253 
254  const Real hz = Real(0.5) * m_geom.CellSize(2);
255 
256  Box bx_zlo1(bx); bx_zlo1.setBig(2,dom_lo.z-1); if (bx_zlo1.ok()) bx_zlo1.setSmall(2,dom_lo.z-1);
257  ParallelFor(
258  bx_zlo1, [=] AMREX_GPU_DEVICE (int i, int j, int k)
259  {
260  dest_arr(i,j,k,BaseState::r0_comp) = dest_arr(i,j,dom_lo.z,BaseState::r0_comp);
261  dest_arr(i,j,k,BaseState::p0_comp) = p_0 -
262  dest_arr(i,j,k,BaseState::r0_comp) * hz * CONST_GRAV;
263  dest_arr(i,j,k,BaseState::pi0_comp) = dest_arr(i,j,dom_lo.z,BaseState::pi0_comp);
264  dest_arr(i,j,k,BaseState::th0_comp) = dest_arr(i,j,dom_lo.z,BaseState::th0_comp);
265  }
266  );
267 
268  Box bx_zlo(bx); bx_zlo.setBig(2,dom_lo.z-2);
269  Box bx_zhi(bx); bx_zhi.setSmall(2,dom_hi.z+1);
270  ParallelFor(
271  bx_zlo, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n)
272  {
273  dest_arr(i,j,k,n) = dest_arr(i,j,dom_lo.z-1,n);
274  },
275  bx_zhi, 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_hi.z,n);
278  }
279  );
280 }
constexpr amrex::Real p_0
Definition: ERF_Constants.H:18
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:21
@ pi0_comp
Definition: ERF_IndexDefines.H:65
@ p0_comp
Definition: ERF_IndexDefines.H:64
@ th0_comp
Definition: ERF_IndexDefines.H:66
@ r0_comp
Definition: ERF_IndexDefines.H:63

◆ operator()()

void ERFPhysBCFunct_base::operator() ( amrex::MultiFab &  mf,
int  icomp,
int  ncomp,
amrex::IntVect const &  nghost 
)
312 {
313  BL_PROFILE("ERFPhysBCFunct_base::()");
314 
315  if (m_geom.isAllPeriodic()) return;
316 
317  if (m_moving_terrain) {
318  mf.FillBoundary(m_geom.periodicity());
319  return;
320  }
321 
322  const auto& domain = m_geom.Domain();
323 
324  // Create a grown domain box containing valid + periodic cells
325  Box gdomain = domain;
326  for (int i = 0; i < AMREX_SPACEDIM; ++i) {
327  if (m_geom.isPeriodic(i)) {
328  gdomain.grow(i, nghost[i]);
329  }
330  }
331 
332  //
333  // We fill all of the interior and periodic ghost cells first, so we can fill
334  // those directly inside the lateral and vertical calls.
335  //
336  mf.FillBoundary(m_geom.periodicity());
337 
338 #ifdef AMREX_USE_OMP
339 #pragma omp parallel if (Gpu::notInLaunchRegion())
340 #endif
341  {
342  for (MFIter mfi(mf,false); mfi.isValid(); ++mfi)
343  {
344  //
345  // This is the box we pass to the different routines
346  // NOTE -- this is the full grid box NOT the tile box
347  //
348  Box bx = mfi.validbox();
349 
350  //
351  // These are the boxes we use to test on relative to the domain
352  //
353  Box cbx1 = bx; cbx1.grow(IntVect(nghost[0],nghost[1],0));
354  Box cbx2 = bx; cbx2.grow(nghost);
355 
356  if (!gdomain.contains(cbx2))
357  {
358  const Array4<Real> base_arr = mf.array(mfi);
359 
360  impose_lateral_basestate_bcs(base_arr,cbx1,domain,ncomp,nghost);
361  impose_vertical_basestate_bcs(base_arr,cbx2,domain,ncomp,nghost);
362  }
363 
364  } // MFIter
365  } // OpenMP
366 } // operator()
void impose_vertical_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:246
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:15

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

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