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, 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
286  : m_lev(lev), m_geom(geom),
287  m_moving_terrain(moving_terrain),
288  m_domain_bcs_type(domain_bcs_type),
289  m_domain_bcs_type_d(domain_bcs_type_d),
290  m_z_phys_nd(z_phys_nd.get())
291  {}
amrex::Gpu::DeviceVector< amrex::BCRec > m_domain_bcs_type_d
Definition: ERF_PhysBCFunct.H:319
int m_lev
Definition: ERF_PhysBCFunct.H:315
amrex::MultiFab * m_z_phys_nd
Definition: ERF_PhysBCFunct.H:320
amrex::Geometry m_geom
Definition: ERF_PhysBCFunct.H:316
bool m_moving_terrain
Definition: ERF_PhysBCFunct.H:317
amrex::Vector< amrex::BCRec > m_domain_bcs_type
Definition: ERF_PhysBCFunct.H:318

◆ ~ERFPhysBCFunct_base()

ERFPhysBCFunct_base::~ERFPhysBCFunct_base ( )
inline
293 {}

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

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

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: