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

#include <ERF_PhysBCFunct.H>

Collaboration diagram for ERFPhysBCFunct_u:

Public Member Functions

 ERFPhysBCFunct_u (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, amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NBCVAR_max > bc_extdir_vals, amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NBCVAR_max > bc_neumann_vals, std::unique_ptr< amrex::MultiFab > &z_phys_nd, const bool use_real_bcs, amrex::Real *u_bc_data)
 
 ~ERFPhysBCFunct_u ()
 
void operator() (amrex::MultiFab &mf, amrex::MultiFab &xvel, amrex::MultiFab &yvel, amrex::IntVect const &nghost, const double time, int bccomp, bool do_fb)
 
void impose_lateral_xvel_bcs (const amrex::Array4< amrex::Real > &dest_arr, const amrex::Array4< amrex::Real const > &xvel_arr, const amrex::Array4< amrex::Real const > &yvel_arr, const amrex::Box &bx, const amrex::Box &domain, int bccomp, const double time)
 
void impose_vertical_xvel_bcs (const amrex::Array4< amrex::Real > &dest_arr, const amrex::Box &bx, const amrex::Box &domain, const amrex::Array4< amrex::Real const > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > dxInv, int bccomp, const double time)
 

Private Attributes

int m_lev
 
amrex::Geometry m_geom
 
amrex::Vector< amrex::BCRec > m_domain_bcs_type
 
amrex::Gpu::DeviceVector< amrex::BCRec > m_domain_bcs_type_d
 
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NBCVAR_maxm_bc_extdir_vals
 
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NBCVAR_maxm_bc_neumann_vals
 
amrex::MultiFab * m_z_phys_nd
 
bool m_use_real_bcs
 
amrex::Realm_u_bc_data
 

Constructor & Destructor Documentation

◆ ERFPhysBCFunct_u()

ERFPhysBCFunct_u::ERFPhysBCFunct_u ( 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,
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NBCVAR_max bc_extdir_vals,
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NBCVAR_max bc_neumann_vals,
std::unique_ptr< amrex::MultiFab > &  z_phys_nd,
const bool  use_real_bcs,
amrex::Real u_bc_data 
)
inline

Construct the x-velocity 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]bc_extdir_valsexternal Dirichlet values for boundary faces
[in]bc_neumann_valsNeumann values for boundary faces
[in]z_phys_ndnodal physical height MultiFab
[in]use_real_bcswhether real-data boundary conditions are active
[in]u_bc_dataoptional x-velocity boundary data
156  : m_lev(lev), m_geom(geom),
157  m_domain_bcs_type(domain_bcs_type),
158  m_domain_bcs_type_d(domain_bcs_type_d),
159  m_bc_extdir_vals(bc_extdir_vals),
160  m_bc_neumann_vals(bc_neumann_vals),
161  m_z_phys_nd(z_phys_nd.get()),
162  m_use_real_bcs(use_real_bcs),
163  m_u_bc_data(u_bc_data)
164  { }
amrex::Geometry m_geom
Definition: ERF_PhysBCFunct.H:223
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NBCVAR_max > m_bc_extdir_vals
Definition: ERF_PhysBCFunct.H:226
amrex::Gpu::DeviceVector< amrex::BCRec > m_domain_bcs_type_d
Definition: ERF_PhysBCFunct.H:225
bool m_use_real_bcs
Definition: ERF_PhysBCFunct.H:229
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NBCVAR_max > m_bc_neumann_vals
Definition: ERF_PhysBCFunct.H:227
amrex::Real * m_u_bc_data
Definition: ERF_PhysBCFunct.H:230
int m_lev
Definition: ERF_PhysBCFunct.H:222
amrex::Vector< amrex::BCRec > m_domain_bcs_type
Definition: ERF_PhysBCFunct.H:224
amrex::MultiFab * m_z_phys_nd
Definition: ERF_PhysBCFunct.H:228

◆ ~ERFPhysBCFunct_u()

ERFPhysBCFunct_u::~ERFPhysBCFunct_u ( )
inline

Destroy the x-velocity physical boundary-condition functor.

169 {}

Member Function Documentation

◆ impose_lateral_xvel_bcs()

void ERFPhysBCFunct_u::impose_lateral_xvel_bcs ( const amrex::Array4< amrex::Real > &  dest_arr,
const amrex::Array4< amrex::Real const > &  xvel_arr,
const amrex::Array4< amrex::Real const > &  yvel_arr,
const amrex::Box &  bx,
const amrex::Box &  domain,
int  bccomp,
const double  time 
)

Impose lateral boundary conditions on x velocity.

Parameters
[in,out]dest_arrx-velocity data to be filled
[in]xvel_arrx-velocity used to determine upwind inflow
[in]yvel_arry-velocity used to determine upwind inflow
[in]bxbox holding data to be filled
[in]domainsimulation domain
[in]bccompboundary-condition component
[in]timetime at which data should be filled

Impose lateral boundary conditions on x-component of velocity

Parameters
[in,out]dest_arrArray4 of the quantity to be filled
[in]xvel_arrx-velocity used to determine upwind Dirichlet inflow
[in]yvel_arry-velocity used to determine upwind Dirichlet inflow
[in]bxbox associated with this data
[in]domaincomputational domain
[in]bccompindex into m_domain_bcs_type
[in]timetime at which the data should be filled
23 {
24  BL_PROFILE_VAR("impose_lateral_xvel_bcs()",impose_lateral_xvel_bcs);
25  const auto& dom_lo = lbound(domain);
26  const auto& dom_hi = ubound(domain);
27 
28  // xlo: ori = 0
29  // ylo: ori = 1
30  // zlo: ori = 2
31  // xhi: ori = 3
32  // yhi: ori = 4
33  // zhi: ori = 5
34 
35  // Based on BCRec for the domain, we need to make BCRec for this Box
36  // bccomp is used as starting index for m_domain_bcs_type
37  // 0 is used as starting index for bcrs
38  Vector<BCRec> bcrs(1);
39  setBC(enclosedCells(bx), domain, bccomp, 0, 1, m_domain_bcs_type, bcrs);
40 
41  Gpu::DeviceVector<BCRec> bcrs_d(1);
42  Gpu::copyAsync(Gpu::hostToDevice, bcrs.begin(), bcrs.end(), bcrs_d.begin());
43  const BCRec* bc_ptr = bcrs_d.data();
44 
45  GpuArray<GpuArray<Real, AMREX_SPACEDIM*2>,1> l_bc_extdir_vals_d;
46 
47  for (int ori = 0; ori < 2*AMREX_SPACEDIM; ori++) {
48  l_bc_extdir_vals_d[0][ori] = m_bc_extdir_vals[bccomp][ori];
49  }
50 
51  GeometryData const& geomdata = m_geom.data();
52  bool is_periodic_in_x = geomdata.isPeriodic(0);
53  bool is_periodic_in_y = geomdata.isPeriodic(1);
54 
55  // First do all ext_dir bcs
56  if (!is_periodic_in_x)
57  {
58  Real* xvel_bc_ptr = m_u_bc_data;
59  Box bx_xlo(bx); bx_xlo.setBig (0,dom_lo.x-1);
60  Box bx_xhi(bx); bx_xhi.setSmall(0,dom_hi.x+2);
61  Box bx_xlo_face(bx); bx_xlo_face.setSmall(0,dom_lo.x ); bx_xlo_face.setBig(0,dom_lo.x );
62  Box bx_xhi_face(bx); bx_xhi_face.setSmall(0,dom_hi.x+1); bx_xhi_face.setBig(0,dom_hi.x+1);
63  ParallelFor(bx_xlo, bx_xlo_face,
64  [=] AMREX_GPU_DEVICE (int i, int j, int k)
65  {
66  int iflip = dom_lo.x - i;
67  if (bc_ptr[0].lo(0) == ERFBCType::ext_dir) {
68  dest_arr(i,j,k) = (xvel_bc_ptr) ? xvel_bc_ptr[k] : l_bc_extdir_vals_d[0][0];
69  } else if (bc_ptr[0].lo(0) == ERFBCType::ext_dir_upwind && xvel_arr(dom_lo.x,j,k) >= zero) {
70  dest_arr(i,j,k) = (xvel_bc_ptr) ? xvel_bc_ptr[k] : l_bc_extdir_vals_d[0][0];
71  } else if (bc_ptr[0].lo(0) == ERFBCType::foextrap) {
72  dest_arr(i,j,k) = dest_arr(dom_lo.x,j,k);
73  } else if (bc_ptr[0].lo(0) == ERFBCType::open) {
74  dest_arr(i,j,k) = dest_arr(dom_lo.x,j,k);
75  } else if (bc_ptr[0].lo(0) == ERFBCType::reflect_even) {
76  dest_arr(i,j,k) = dest_arr(iflip,j,k);
77  } else if (bc_ptr[0].lo(0) == ERFBCType::reflect_odd) {
78  dest_arr(i,j,k) = -dest_arr(iflip,j,k);
79  } else if (bc_ptr[0].lo(0) == ERFBCType::neumann_int) {
80  dest_arr(i,j,k) = (Real(4.0)*dest_arr(dom_lo.x+1,j,k) - dest_arr(dom_lo.x+2,j,k))/three;
81  } else if (bc_ptr[0].lo(0) == ERFBCType::hoextrap) {
82  Real delta_i = (dom_lo.x - i);
83  dest_arr(i,j,k) = (one + delta_i)*dest_arr(dom_lo.x,j,k) - delta_i*dest_arr(dom_lo.x+1,j,k);
84  }
85  },
86  // We only set the values on the domain faces themselves if EXT_DIR or neumann_int
87  [=] AMREX_GPU_DEVICE (int i, int j, int k)
88  {
89  if (bc_ptr[0].lo(0) == ERFBCType::ext_dir) {
90  dest_arr(i,j,k) = (xvel_bc_ptr) ? xvel_bc_ptr[k] : l_bc_extdir_vals_d[0][0];
91  } else if (bc_ptr[0].lo(0) == ERFBCType::ext_dir_upwind && xvel_arr(dom_lo.x,j,k) >= zero) {
92  dest_arr(i,j,k) = (xvel_bc_ptr) ? xvel_bc_ptr[k] : l_bc_extdir_vals_d[0][0];
93  } else if (bc_ptr[0].lo(0) == ERFBCType::neumann_int) {
94  dest_arr(i,j,k) = (Real(4.0)*dest_arr(dom_lo.x+1,j,k) - dest_arr(dom_lo.x+2,j,k))/three;
95  }
96  }
97  );
98  ParallelFor(bx_xhi, bx_xhi_face,
99  [=] AMREX_GPU_DEVICE (int i, int j, int k)
100  {
101  int iflip = 2*(dom_hi.x + 1) - i;
102  if (bc_ptr[0].hi(0) == ERFBCType::ext_dir) {
103  dest_arr(i,j,k) = (xvel_bc_ptr) ? xvel_bc_ptr[k] : l_bc_extdir_vals_d[0][3];
104  } else if (bc_ptr[0].hi(0) == ERFBCType::ext_dir_upwind && xvel_arr(dom_hi.x+1,j,k) <= zero) {
105  dest_arr(i,j,k) = (xvel_bc_ptr) ? xvel_bc_ptr[k] : l_bc_extdir_vals_d[0][3];
106  } else if (bc_ptr[0].hi(0) == ERFBCType::foextrap) {
107  dest_arr(i,j,k) = dest_arr(dom_hi.x+1,j,k);
108  } else if (bc_ptr[0].hi(0) == ERFBCType::open) {
109  dest_arr(i,j,k) = dest_arr(dom_hi.x+1,j,k);
110  } else if (bc_ptr[0].hi(0) == ERFBCType::reflect_even) {
111  dest_arr(i,j,k) = dest_arr(iflip,j,k);
112  } else if (bc_ptr[0].hi(0) == ERFBCType::reflect_odd) {
113  dest_arr(i,j,k) = -dest_arr(iflip,j,k);
114  } else if (bc_ptr[0].hi(0) == ERFBCType::neumann_int) {
115  dest_arr(i,j,k) = (Real(4.0)*dest_arr(dom_hi.x,j,k) - dest_arr(dom_hi.x-1,j,k))/three;
116  } else if (bc_ptr[0].hi(0) == ERFBCType::hoextrap) {
117  Real delta_i = (i - dom_hi.x - 1);
118  dest_arr(i,j,k) = (one + delta_i)*dest_arr(dom_hi.x+1,j,k) - delta_i*dest_arr(dom_hi.x,j,k);
119  }
120  },
121  // We only set the values on the domain faces themselves if EXT_DIR or neumann_int
122  [=] AMREX_GPU_DEVICE (int i, int j, int k)
123  {
124  if (bc_ptr[0].hi(0) == ERFBCType::ext_dir) {
125  dest_arr(i,j,k) = (xvel_bc_ptr) ? xvel_bc_ptr[k] : l_bc_extdir_vals_d[0][3];
126  } else if (bc_ptr[0].hi(0) == ERFBCType::ext_dir_upwind && xvel_arr(dom_hi.x+1,j,k) <= zero) {
127  dest_arr(i,j,k) = (xvel_bc_ptr) ? xvel_bc_ptr[k] : l_bc_extdir_vals_d[0][3];
128  } else if (bc_ptr[0].hi(0) == ERFBCType::neumann_int) {
129  dest_arr(i,j,k) = (Real(4.0)*dest_arr(dom_hi.x,j,k) - dest_arr(dom_hi.x-1,j,k))/three;
130  }
131  }
132  );
133  } // not periodic in x
134 
135  if (!is_periodic_in_y)
136  {
137  // Populate ghost cells on lo-y and hi-y domain boundaries
138  Real* xvel_bc_ptr = m_u_bc_data;
139  Box bx_ylo(bx); bx_ylo.setBig (1,dom_lo.y-1);
140  Box bx_yhi(bx); bx_yhi.setSmall(1,dom_hi.y+1);
141  ParallelFor(bx_ylo, bx_yhi,
142  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
143  int jflip = dom_lo.y - 1 - j;
144  if (bc_ptr[0].lo(1) == ERFBCType::ext_dir) {
145  dest_arr(i,j,k) = (xvel_bc_ptr) ? xvel_bc_ptr[k] : l_bc_extdir_vals_d[0][1];
146  } else if (bc_ptr[0].lo(1) == ERFBCType::ext_dir_upwind && yvel_arr(i,dom_lo.y,k) >= zero) {
147  dest_arr(i,j,k) = (xvel_bc_ptr) ? xvel_bc_ptr[k] : l_bc_extdir_vals_d[0][1];
148  } else if (bc_ptr[0].lo(1) == ERFBCType::foextrap) {
149  dest_arr(i,j,k) = dest_arr(i,dom_lo.y,k);
150  } else if (bc_ptr[0].lo(1) == ERFBCType::open) {
151  dest_arr(i,j,k) = dest_arr(i,dom_lo.y,k);
152  } else if (bc_ptr[0].lo(1) == ERFBCType::reflect_even) {
153  dest_arr(i,j,k) = dest_arr(i,jflip,k);
154  } else if (bc_ptr[0].lo(1) == ERFBCType::reflect_odd) {
155  dest_arr(i,j,k) = -dest_arr(i,jflip,k);
156  } else if (bc_ptr[0].lo(1) == ERFBCType::hoextrap) {
157  Real delta_j = (dom_lo.y - j);
158  dest_arr(i,j,k) = (one + delta_j)*dest_arr(i,dom_lo.y,k) - delta_j*dest_arr(i,dom_lo.y+1,k);
159  }
160  },
161  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
162  int jflip = 2*dom_hi.y + 1 - j;
163  if (bc_ptr[0].hi(1) == ERFBCType::ext_dir) {
164  dest_arr(i,j,k) = (xvel_bc_ptr) ? xvel_bc_ptr[k] : l_bc_extdir_vals_d[0][4];
165  } else if (bc_ptr[0].hi(1) == ERFBCType::ext_dir_upwind && yvel_arr(i,dom_hi.y+1,k) <= zero) {
166  dest_arr(i,j,k) = (xvel_bc_ptr) ? xvel_bc_ptr[k] : l_bc_extdir_vals_d[0][4];
167  } else if (bc_ptr[0].hi(1) == ERFBCType::foextrap) {
168  dest_arr(i,j,k) = dest_arr(i,dom_hi.y,k);
169  } else if (bc_ptr[0].hi(1) == ERFBCType::open) {
170  dest_arr(i,j,k) = dest_arr(i,dom_hi.y,k);
171  } else if (bc_ptr[0].hi(1) == ERFBCType::reflect_even) {
172  dest_arr(i,j,k) = dest_arr(i,jflip,k);
173  } else if (bc_ptr[0].hi(1) == ERFBCType::reflect_odd) {
174  dest_arr(i,j,k) = -dest_arr(i,jflip,k);
175  } else if (bc_ptr[0].hi(1) == ERFBCType::hoextrap) {
176  Real delta_j = (j - dom_hi.y);
177  dest_arr(i,j,k) = (one + delta_j)*dest_arr(i,dom_hi.y,k) - delta_j*dest_arr(i,dom_hi.y-1,k);
178  }
179  }
180  );
181  } // not periodic in y
182 
183  Gpu::streamSynchronize();
184 }
constexpr amrex::Real three
Definition: ERF_Constants.H:11
constexpr amrex::Real one
Definition: ERF_Constants.H:9
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
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
void impose_lateral_xvel_bcs(const amrex::Array4< amrex::Real > &dest_arr, const amrex::Array4< amrex::Real const > &xvel_arr, const amrex::Array4< amrex::Real const > &yvel_arr, const amrex::Box &bx, const amrex::Box &domain, int bccomp, const double time)
Definition: ERF_BoundaryConditionsXvel.cpp:18
@ 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
@ ext_dir
Definition: ERF_IndexDefines.H:249
@ ext_dir_upwind
Definition: ERF_IndexDefines.H:257
@ neumann_int
Definition: ERF_IndexDefines.H:255
@ reflect_even
Definition: ERF_IndexDefines.H:247
Here is the call graph for this function:

◆ impose_vertical_xvel_bcs()

void ERFPhysBCFunct_u::impose_vertical_xvel_bcs ( const amrex::Array4< amrex::Real > &  dest_arr,
const amrex::Box &  bx,
const amrex::Box &  domain,
const amrex::Array4< amrex::Real const > &  z_nd,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM >  dxInv,
int  bccomp,
const double  time 
)

Impose vertical boundary conditions on x velocity.

Parameters
[in,out]dest_arrx-velocity data to be filled
[in]bxbox holding data to be filled
[in]domainsimulation domain
[in]z_ndnodal physical height
[in]dxInvinverse cell size
[in]bccompboundary-condition component
[in]timetime at which data should be filled

Impose vertical boundary conditions on x-component of velocity

Parameters
[in,out]dest_arrthe Array4 of the quantity to be filled
[in]bxthe box associated with this data
[in]domainthe computational domain
[in]z_phys_ndheight coordinate at nodes
[in]dxInvinverse cell size array
[in]bccompindex into m_domain_bcs_type
[in]timetime at which the data should be filled
207 {
208  BL_PROFILE_VAR("impose_vertical_xvel_bcs()",impose_vertical_xvel_bcs);
209  const auto& dom_lo = lbound(domain);
210  const auto& dom_hi = ubound(domain);
211 
212  Box per_grown_domain(domain);
213  int growx = (m_geom.isPeriodic(0)) ? 1 : 0;
214  int growy = (m_geom.isPeriodic(1)) ? 1 : 0;
215  per_grown_domain.grow(IntVect(growx,growy,0));
216  const auto& perdom_lo = lbound(per_grown_domain);
217  const auto& perdom_hi = ubound(per_grown_domain);
218 
219  GeometryData const& geomdata = m_geom.data();
220 
221  // Based on BCRec for the domain, we need to make BCRec for this Box
222  // bccomp is used as starting index for m_domain_bcs_type
223  // 0 is used as starting index for bcrs
224  Vector<BCRec> bcrs(1);
225  setBC(enclosedCells(bx), domain, bccomp, 0, 1, m_domain_bcs_type, bcrs);
226 
227  Gpu::DeviceVector<BCRec> bcrs_d(1);
228  Gpu::copyAsync(Gpu::hostToDevice, bcrs.begin(), bcrs.end(), bcrs_d.begin());
229  const BCRec* bc_ptr = bcrs_d.data();
230 
231  GpuArray<GpuArray<Real, AMREX_SPACEDIM*2>,1> l_bc_extdir_vals_d;
232 
233  for (int ori = 0; ori < 2*AMREX_SPACEDIM; ori++) {
234  l_bc_extdir_vals_d[0][ori] = m_bc_extdir_vals[bccomp][ori];
235  }
236 
237  {
238  // Populate ghost cells on lo-z and hi-z domain boundaries
239  Box bx_zlo(bx); bx_zlo.setBig (2,dom_lo.z-1);
240  Box bx_zhi(bx); bx_zhi.setSmall(2,dom_hi.z+1);
241  ParallelFor(bx_zlo, bx_zhi,
242  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
243  int kflip = dom_lo.z - 1 - k;
244  if (bc_ptr[0].lo(2) == ERFBCType::ext_dir) {
245  #ifdef ERF_USE_TERRAIN_VELOCITY
246  dest_arr(i,j,k) = prob->compute_terrain_velocity(time);
247  #else
248  dest_arr(i,j,k) = l_bc_extdir_vals_d[0][2];
249  #endif
250  } else if (bc_ptr[0].lo(2) == ERFBCType::foextrap) {
251  dest_arr(i,j,k) = dest_arr(i,j,dom_lo.z);
252  } else if (bc_ptr[0].lo(2) == ERFBCType::open) {
253  dest_arr(i,j,k) = dest_arr(i,j,dom_lo.z);
254  } else if (bc_ptr[0].lo(2) == ERFBCType::reflect_even) {
255  dest_arr(i,j,k) = dest_arr(i,j,kflip);
256  } else if (bc_ptr[0].lo(2) == ERFBCType::reflect_odd) {
257  dest_arr(i,j,k) = -dest_arr(i,j,kflip);
258  } else if (bc_ptr[0].lo(2) == ERFBCType::hoextrap) {
259  Real delta_k = (dom_lo.z - k);
260  dest_arr(i,j,k) = (one + delta_k)*dest_arr(i,j,dom_lo.z) - delta_k*dest_arr(i,j,dom_lo.z+1);
261  }
262  },
263  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
264  int kflip = 2*dom_hi.z + 1 - k;
265  if (bc_ptr[0].hi(2) == ERFBCType::ext_dir) {
266  dest_arr(i,j,k) = l_bc_extdir_vals_d[0][5];
267  } else if (bc_ptr[0].hi(2) == ERFBCType::foextrap) {
268  dest_arr(i,j,k) = dest_arr(i,j,dom_hi.z);
269  } else if (bc_ptr[0].hi(2) == ERFBCType::open) {
270  dest_arr(i,j,k) = dest_arr(i,j,dom_hi.z);
271  } else if (bc_ptr[0].hi(2) == ERFBCType::reflect_even) {
272  dest_arr(i,j,k) = dest_arr(i,j,kflip);
273  } else if (bc_ptr[0].hi(2) == ERFBCType::reflect_odd) {
274  dest_arr(i,j,k) = -dest_arr(i,j,kflip);
275  } else if (bc_ptr[0].hi(2) == ERFBCType::hoextrap){
276  Real delta_k = (k - dom_hi.z);
277  dest_arr(i,j,k) = (one + delta_k)*dest_arr(i,j,dom_hi.z) - delta_k*dest_arr(i,j,dom_hi.z-1);
278  }
279  }
280  );
281  } // z
282 
283  if (m_z_phys_nd) {
284  const auto& bx_lo = lbound(bx);
285  const auto& bx_hi = ubound(bx);
286 
287  const auto& zphys_lo = lbound(Box(z_phys_nd));
288  const auto& zphys_hi = ubound(Box(z_phys_nd));
289 
290  // Neumann conditions (d<var>/dn = 0) must be aware of the surface normal with terrain.
291  // An additional source term arises from d<var>/dx & d<var>/dy & met_h_xi/eta/zeta.
292  //=====================================================================================
293  // Only modify scalars, U, or V
294  // Loop over each component
295  // Hit for Neumann condition at kmin
296  if (bcrs[0].lo(2) == ERFBCType::foextrap) {
297  // Loop over ghost cells in bottom XY-plane (valid box)
298  Box xybx = bx;
299  xybx.setBig(2,-1);
300  xybx.setSmall(2,bx.smallEnd()[2]);
301  int k0 = 0;
302 
303  // Get the dz cell size
304  Real dz = geomdata.CellSize(2);
305 
306  // Fill all the Neumann srcs with terrain
307  ParallelFor(xybx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
308  {
309  // Clip indices for ghost-cells
310  int ii = amrex::min(amrex::max(i,perdom_lo.x),perdom_hi.x);
311  ii = amrex::min(amrex::max(ii,zphys_lo.x),zphys_hi.x);
312  int jj = amrex::min(amrex::max(j,perdom_lo.y),perdom_hi.y);
313  jj = amrex::min(amrex::max(jj,zphys_lo.y),zphys_hi.y);
314 
315  // Get metrics
316  Real met_h_xi = Compute_h_xi_AtIface (ii, jj, k0, dxInv, z_phys_nd);
317  Real met_h_eta = Compute_h_eta_AtIface (ii, jj, k0, dxInv, z_phys_nd);
318  Real met_h_zeta = Compute_h_zeta_AtIface(ii, jj, k0, dxInv, z_phys_nd);
319 
320  // GradX at IJK location inside domain -- this relies on the assumption that we have
321  // used foextrap for quantities outside the domain to define the gradient as zero
322  Real GradVarx, GradVary;
323  if ( i < dom_lo.x-1 || i > dom_hi.x+1 || (i+1 > bx_hi.x && i-1 < bx_lo.x) ) {
324  GradVarx = zero;
325  } else if (i+1 > bx_hi.x) {
326  GradVarx = dxInv[0] * (dest_arr(i ,j,k0) - dest_arr(i-1,j,k0));
327  } else if (i-1 < bx_lo.x) {
328  GradVarx = dxInv[0] * (dest_arr(i+1,j,k0) - dest_arr(i ,j,k0));
329  } else {
330  GradVarx = myhalf * dxInv[0] * (dest_arr(i+1,j,k0) - dest_arr(i-1,j,k0));
331  }
332 
333  // GradY at IJK location inside domain -- this relies on the assumption that we have
334  // used foextrap for quantities outside the domain to define the gradient as zero
335  if ( j < dom_lo.y-1 || j > dom_hi.y+1 || (j+1 > bx_hi.y && j-1 < bx_lo.y) ) {
336  GradVary = zero;
337  } else if (j+1 > bx_hi.y) {
338  GradVary = dxInv[1] * (dest_arr(i,j ,k0) - dest_arr(i,j-1,k0));
339  } else if (j-1 < bx_lo.y) {
340  GradVary = dxInv[1] * (dest_arr(i,j+1,k0) - dest_arr(i,j ,k0));
341  } else {
342  GradVary = myhalf * dxInv[1] * (dest_arr(i,j+1,k0) - dest_arr(i,j-1,k0));
343  }
344 
345  // Prefactor
346  Real met_fac = met_h_zeta / ( met_h_xi*met_h_xi + met_h_eta*met_h_eta + one );
347 
348  // Accumulate in bottom ghost cell (EXTRAP already populated)
349  dest_arr(i,j,k) -= dz * met_fac * ( met_h_xi * GradVarx + met_h_eta * GradVary );
350  });
351  } // foextrap
352  } //m_z_phys_nd
353  Gpu::streamSynchronize();
354 }
constexpr amrex::Real myhalf
Definition: ERF_Constants.H:13
amrex::GpuArray< Real, AMREX_SPACEDIM > dxInv
Definition: ERF_InitCustomPertVels_ParticleTests.H:17
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_xi_AtIface(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:117
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_zeta_AtIface(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:104
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_eta_AtIface(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:131
void impose_vertical_xvel_bcs(const amrex::Array4< amrex::Real > &dest_arr, const amrex::Box &bx, const amrex::Box &domain, const amrex::Array4< amrex::Real const > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > dxInv, int bccomp, const double time)
Definition: ERF_BoundaryConditionsXvel.cpp:197
@ dz
Definition: ERF_AdvanceWSM6.cpp:104
Here is the call graph for this function:

◆ operator()()

void ERFPhysBCFunct_u::operator() ( amrex::MultiFab &  mf,
amrex::MultiFab &  xvel,
amrex::MultiFab &  yvel,
amrex::IntVect const &  nghost,
const double  time,
int  bccomp,
bool  do_fb 
)

Impose physical boundary conditions at domain boundaries

Parameters
[in,out]mfx-velocity MultiFab to be filled
[in]xvelx-velocity MultiFab used by upwind boundary conditions
[in]yvely-velocity MultiFab used by upwind boundary conditions
[in]nghostnumber of ghost cells to be filled for velocity components
[in]timetime at which the data should be filled
[in]bccompindex into m_domain_bcs_type
[in]do_fbwhether to fill periodic/interior ghost cells first

Impose physical boundary conditions on x velocity.

Parameters
[in,out]mfx-velocity MultiFab to be filled
[in]xvelx-velocity MultiFab used by upwind boundary conditions
[in]yvely-velocity MultiFab used by upwind boundary conditions
[in]nghostnumber of ghost cells to be filled
[in]timetime at which data should be filled
[in]bccompindex into m_domain_bcs_type
[in]do_fbwhether to fill periodic/interior ghost cells first
107 {
108  BL_PROFILE("ERFPhysBCFunct_u::()");
109 
110  //
111  // We fill all of the interior and periodic ghost cells first, so we can fill
112  // those directly inside the lateral and vertical calls.
113  // If triply periodic this is all we do
114  //
115  if (do_fb) {
116  mf.FillBoundary(m_geom.periodicity());
117  }
118 
119  if (m_geom.isAllPeriodic()) return;
120 
121  const auto& domain = m_geom.Domain();
122  const auto dxInv = m_geom.InvCellSizeArray();
123 
124  Box gdomainx = surroundingNodes(domain,0);
125  for (int i = 0; i < AMREX_SPACEDIM; ++i) {
126  if (m_geom.isPeriodic(i)) {
127  gdomainx.grow(i, nghost[i]);
128  }
129  }
130 
131 #ifdef AMREX_USE_OMP
132 #pragma omp parallel if (Gpu::notInLaunchRegion())
133 #endif
134  {
135  for (MFIter mfi(mf,false); mfi.isValid(); ++mfi)
136  {
137  //
138  // This is the box we pass to the different routines
139  // NOTE -- this is the full grid NOT the tile box
140  //
141  Box bx = mfi.validbox();
142 
143  //
144  // These are the boxes we use to test on relative to the domain
145  //
146  Box xbx1 = surroundingNodes(bx,0); xbx1.grow(nghost);
147  if(xbx1.smallEnd(2) < domain.smallEnd(2)) xbx1.setSmall(2,domain.smallEnd(2));
148  if(xbx1.bigEnd(2) > domain.bigEnd(2)) xbx1.setBig(2,domain.bigEnd(2));
149 
150  Box xbx2 = surroundingNodes(bx,0); xbx2.grow(nghost);
151 
152  Array4<const Real> z_nd_arr;
153 
154  if (m_z_phys_nd) {
155  z_nd_arr = m_z_phys_nd->const_array(mfi);
156  }
157 
158  if (!gdomainx.contains(xbx2)) {
159  Array4< Real> const& dest_arr = mf.array(mfi);
160  Array4<const Real> const& velx_arr = xvel.const_array(mfi);
161  Array4<const Real> const& vely_arr = yvel.const_array(mfi);
162 
163  if (!gdomainx.contains(xbx1) && !m_use_real_bcs) {
164  impose_lateral_xvel_bcs(dest_arr,velx_arr,vely_arr,xbx1,domain,bccomp,time);
165  }
166 
167  impose_vertical_xvel_bcs(dest_arr,xbx2,domain,z_nd_arr,dxInv,bccomp,time);
168  }
169  } // MFIter
170  } // OpenMP
171 } // operator()
@ xvel
Definition: ERF_IndexDefines.H:177
@ yvel
Definition: ERF_IndexDefines.H:178

Member Data Documentation

◆ m_bc_extdir_vals

amrex::Array<amrex::Array<amrex::Real, AMREX_SPACEDIM*2>,AMREX_SPACEDIM+NBCVAR_max> ERFPhysBCFunct_u::m_bc_extdir_vals
private

◆ m_bc_neumann_vals

amrex::Array<amrex::Array<amrex::Real, AMREX_SPACEDIM*2>,AMREX_SPACEDIM+NBCVAR_max> ERFPhysBCFunct_u::m_bc_neumann_vals
private

◆ m_domain_bcs_type

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

◆ m_domain_bcs_type_d

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

◆ m_geom

amrex::Geometry ERFPhysBCFunct_u::m_geom
private

◆ m_lev

int ERFPhysBCFunct_u::m_lev
private

◆ m_u_bc_data

amrex::Real* ERFPhysBCFunct_u::m_u_bc_data
private

◆ m_use_real_bcs

bool ERFPhysBCFunct_u::m_use_real_bcs
private

◆ m_z_phys_nd

amrex::MultiFab* ERFPhysBCFunct_u::m_z_phys_nd
private

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