ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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
274  : m_lev(lev), m_geom(geom),
275  m_moving_terrain(moving_terrain),
276  m_domain_bcs_type(domain_bcs_type),
277  m_domain_bcs_type_d(domain_bcs_type_d)
278  {}
amrex::Gpu::DeviceVector< amrex::BCRec > m_domain_bcs_type_d
Definition: ERF_PhysBCFunct.H:305
int m_lev
Definition: ERF_PhysBCFunct.H:301
amrex::Geometry m_geom
Definition: ERF_PhysBCFunct.H:302
bool m_moving_terrain
Definition: ERF_PhysBCFunct.H:303
amrex::Vector< amrex::BCRec > m_domain_bcs_type
Definition: ERF_PhysBCFunct.H:304

◆ ~ERFPhysBCFunct_base()

ERFPhysBCFunct_base::~ERFPhysBCFunct_base ( )
inline
280 {}

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

◆ 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 
)
249 {
250  BL_PROFILE_VAR("impose_vertical_base_bcs()",impose_vertical_base_bcs);
251 
252  const auto& dom_lo = lbound(domain);
253  const auto& dom_hi = ubound(domain);
254 
255  const Real hz = Real(0.5) * m_geom.CellSize(2);
256 
257  Box bx_zlo1(bx); bx_zlo1.setBig(2,dom_lo.z-1); if (bx_zlo1.ok()) bx_zlo1.setSmall(2,dom_lo.z-1);
258  ParallelFor(
259  bx_zlo1, [=] AMREX_GPU_DEVICE (int i, int j, int k)
260  {
261  dest_arr(i,j,k,BaseState::r0_comp) = dest_arr(i,j,dom_lo.z,BaseState::r0_comp);
262  dest_arr(i,j,k,BaseState::p0_comp) = p_0 -
263  dest_arr(i,j,k,BaseState::r0_comp) * hz * CONST_GRAV;
264  dest_arr(i,j,k,BaseState::pi0_comp) = dest_arr(i,j,dom_lo.z,BaseState::pi0_comp);
265  dest_arr(i,j,k,BaseState::th0_comp) = dest_arr(i,j,dom_lo.z,BaseState::th0_comp);
266  }
267  );
268 
269  Box bx_zlo(bx); bx_zlo.setBig(2,dom_lo.z-2);
270  Box bx_zhi(bx); bx_zhi.setSmall(2,dom_hi.z+1);
271  ParallelFor(
272  bx_zlo, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n)
273  {
274  dest_arr(i,j,k,n) = dest_arr(i,j,dom_lo.z-1,n);
275  },
276  bx_zhi, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n)
277  {
278  dest_arr(i,j,k,n) = dest_arr(i,j,dom_hi.z,n);
279  }
280  );
281 }
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 
)
320 {
321  BL_PROFILE("ERFPhysBCFunct_base::()");
322 
323  if (m_geom.isAllPeriodic()) return;
324 
325  const auto& domain = m_geom.Domain();
326 
327  // Create a grown domain box containing valid + periodic cells
328  Box gdomain = domain;
329  for (int i = 0; i < AMREX_SPACEDIM; ++i) {
330  if (m_geom.isPeriodic(i)) {
331  gdomain.grow(i, nghost[i]);
332  }
333  }
334 
335  //
336  // We fill all of the interior and periodic ghost cells first, so we can fill
337  // those directly inside the lateral and vertical calls.
338  //
339  mf.FillBoundary(m_geom.periodicity());
340 
341 #ifdef AMREX_USE_OMP
342 #pragma omp parallel if (Gpu::notInLaunchRegion())
343 #endif
344  {
345  for (MFIter mfi(mf,false); mfi.isValid(); ++mfi)
346  {
347  //
348  // This is the box we pass to the different routines
349  // NOTE -- this is the full grid box NOT the tile box
350  //
351  Box bx = mfi.validbox();
352 
353  //
354  // These are the boxes we use to test on relative to the domain
355  //
356  Box cbx1 = bx; cbx1.grow(IntVect(nghost[0],nghost[1],0));
357  Box cbx2 = bx; cbx2.grow(nghost);
358 
359  if (!gdomain.contains(cbx2))
360  {
361  const Array4<Real> base_arr = mf.array(mfi);
362 
363  impose_lateral_basestate_bcs(base_arr,cbx1,domain,ncomp,nghost);
364  if (!m_moving_terrain) { // TODO: I don't know why the CI test fails if this is called
365  impose_vertical_basestate_bcs(base_arr,cbx2,domain,ncomp,nghost);
366  }
367  }
368 
369  } // MFIter
370  } // OpenMP
371 } // 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:247
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: