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

#include <ERF_PhysBCFunct.H>

Collaboration diagram for ERFPhysBCFunct_w:

Public Member Functions

 ERFPhysBCFunct_w (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, const TerrainType &terrain_type, amrex::Vector< std::unique_ptr< amrex::MultiFab >> &mapfac_lev, std::unique_ptr< amrex::MultiFab > &z_phys_nd, const bool use_real_bcs, amrex::Real *w_bc_data)
 
 ~ERFPhysBCFunct_w ()
 
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_zvel_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, const amrex::Array4< amrex::Real const > &mf_u, const amrex::Array4< amrex::Real const > &mf_v, const amrex::Array4< amrex::Real const > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > dxInv, TerrainType terrain_type, int bccomp, const double time)
 
void impose_vertical_zvel_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, const amrex::Array4< amrex::Real const > &mf_u, const amrex::Array4< amrex::Real const > &mf_v, const amrex::Array4< amrex::Real const > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > dxInv, int bccomp_u, int bccomp_v, int bccomp_w, TerrainType terrain_type, 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_max > m_bc_extdir_vals
 
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NBCVAR_max > m_bc_neumann_vals
 
TerrainType m_terrain_type
 
amrex::MultiFab * m_mapfac_u
 
amrex::MultiFab * m_mapfac_v
 
amrex::MultiFab * m_z_phys_nd
 
bool m_use_real_bcs
 
amrex::Real * m_w_bc_data
 

Constructor & Destructor Documentation

◆ ERFPhysBCFunct_w()

ERFPhysBCFunct_w::ERFPhysBCFunct_w ( 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,
const TerrainType &  terrain_type,
amrex::Vector< std::unique_ptr< amrex::MultiFab >> &  mapfac_lev,
std::unique_ptr< amrex::MultiFab > &  z_phys_nd,
const bool  use_real_bcs,
amrex::Real *  w_bc_data 
)
inline

Construct the z-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]terrain_typeterrain type for the level
[in]mapfac_levmap-factor MultiFabs for the level
[in]z_phys_ndnodal physical height MultiFab
[in]use_real_bcswhether real-data boundary conditions are active
[in]w_bc_dataoptional z-velocity boundary data
414  : m_lev(lev),
415  m_geom(geom), m_domain_bcs_type(domain_bcs_type),
416  m_domain_bcs_type_d(domain_bcs_type_d),
417  m_bc_extdir_vals(bc_extdir_vals),
418  m_bc_neumann_vals(bc_neumann_vals),
419  m_terrain_type(terrain_type),
420  m_z_phys_nd(z_phys_nd.get()),
421  m_use_real_bcs(use_real_bcs),
422  m_w_bc_data(w_bc_data)
423  {
424  m_mapfac_u = mapfac_lev[MapFacType::u_x].get();
425  m_mapfac_v = mapfac_lev[MapFacType::v_y].get();
426  }
@ v_y
Definition: ERF_DataStruct.H:38
@ u_x
Definition: ERF_DataStruct.H:37
amrex::Vector< amrex::BCRec > m_domain_bcs_type
Definition: ERF_PhysBCFunct.H:508
amrex::Geometry m_geom
Definition: ERF_PhysBCFunct.H:507
int m_lev
Definition: ERF_PhysBCFunct.H:506
amrex::Real * m_w_bc_data
Definition: ERF_PhysBCFunct.H:517
bool m_use_real_bcs
Definition: ERF_PhysBCFunct.H:516
amrex::Gpu::DeviceVector< amrex::BCRec > m_domain_bcs_type_d
Definition: ERF_PhysBCFunct.H:509
amrex::MultiFab * m_mapfac_v
Definition: ERF_PhysBCFunct.H:514
TerrainType m_terrain_type
Definition: ERF_PhysBCFunct.H:512
amrex::MultiFab * m_z_phys_nd
Definition: ERF_PhysBCFunct.H:515
amrex::MultiFab * m_mapfac_u
Definition: ERF_PhysBCFunct.H:513
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NBCVAR_max > m_bc_neumann_vals
Definition: ERF_PhysBCFunct.H:511
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NBCVAR_max > m_bc_extdir_vals
Definition: ERF_PhysBCFunct.H:510

◆ ~ERFPhysBCFunct_w()

ERFPhysBCFunct_w::~ERFPhysBCFunct_w ( )
inline

Destroy the z-velocity physical boundary-condition functor.

431 {}

Member Function Documentation

◆ impose_lateral_zvel_bcs()

void ERFPhysBCFunct_w::impose_lateral_zvel_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,
const amrex::Array4< amrex::Real const > &  mf_u,
const amrex::Array4< amrex::Real const > &  mf_v,
const amrex::Array4< amrex::Real const > &  z_nd,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM >  dxInv,
TerrainType  terrain_type,
int  bccomp,
const double  time 
)

Impose lateral boundary conditions on z velocity.

Parameters
[in,out]dest_arrz-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]mf_ux map-factor field
[in]mf_vy map-factor field
[in]z_ndnodal physical height
[in]dxInvinverse cell size
[in]terrain_typeterrain representation
[in]bccompboundary-condition component
[in]timetime at which data should be filled

Impose lateral boundary conditions on z-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]mf_umetric-aware x-velocity used to convert omega to w
[in]mf_vmetric-aware y-velocity used to convert omega to w
[in]z_phys_ndheight coordinate at nodes
[in]dxInvinverse cell size array
[in]terrain_typeterrain type used to decide whether omega conversion is needed
[in]bccompindex into m_domain_bcs_type
[in]timetime at which the data should be filled
33 {
34  BL_PROFILE_VAR("impose_lateral_zvel_bcs()",impose_lateral_zvel_bcs);
35  const auto& dom_lo = lbound(domain);
36  const auto& dom_hi = ubound(domain);
37 
38  //
39  // An ext_dir_upwind face decides inflow against the face velocity, but the box we
40  // loop over does not always have a face velocity at every one of its cells: the
41  // state carries one more lateral ghost than the velocities do (ngrow_state =
42  // ComputeGhostCells()+1 against ngrow_vels = ComputeGhostCells()), and a velocity
43  // box is nodal in its own direction where the array being read is cell centered.
44  // Either way the outermost ghost cells have no velocity of their own, so sample
45  // the nearest one that exists. Cells already inside the velocity array are
46  // unaffected; only that outermost layer changes, and it previously read out of
47  // bounds.
48  //
49  const auto& xvel_lo = lbound(xvel_arr);
50  const auto& xvel_hi = ubound(xvel_arr);
51  const auto& yvel_lo = lbound(yvel_arr);
52  const auto& yvel_hi = ubound(yvel_arr);
53 
54  // Based on BCRec for the domain, we need to make BCRec for this Box
55  // bccomp is used as starting index for m_domain_bcs_type
56  // 0 is used as starting index for bcrs
57  Vector<BCRec> bcrs_w(1);
58  setBC(enclosedCells(bx), domain, bccomp, 0, 1, m_domain_bcs_type, bcrs_w);
59 
60  bool l_use_terrain_fitted_coords = ( (terrain_type == TerrainType::StaticFittedMesh) ||
61  (terrain_type == TerrainType::MovingFittedMesh) );
62 
63  // xlo: ori = 0
64  // ylo: ori = 1
65  // zlo: ori = 2
66  // xhi: ori = 3
67  // yhi: ori = 4
68  // zhi: ori = 5
69 
70  Gpu::DeviceVector<BCRec> bcrs_w_d(1);
71  Gpu::copyAsync(Gpu::hostToDevice, bcrs_w.begin(), bcrs_w.end(), bcrs_w_d.begin());
72  const BCRec* bc_ptr_w = bcrs_w_d.data();
73 
74  GpuArray<GpuArray<Real, AMREX_SPACEDIM*2>,1> l_bc_extdir_vals_d;
75 
76  for (int ori = 0; ori < 2*AMREX_SPACEDIM; ori++) {
77  l_bc_extdir_vals_d[0][ori] = m_bc_extdir_vals[bccomp][ori];
78  }
79 
80  GeometryData const& geomdata = m_geom.data();
81  bool is_periodic_in_x = geomdata.isPeriodic(0);
82  bool is_periodic_in_y = geomdata.isPeriodic(1);
83 
84  FArrayBox dhdtfab;
85 
86  // First do all ext_dir bcs
87  if (!is_periodic_in_x)
88  {
89  Real* zvel_bc_ptr = m_w_bc_data;
90  Box bx_xlo(bx); bx_xlo.setBig (0,dom_lo.x-1);
91  Box bx_xhi(bx); bx_xhi.setSmall(0,dom_hi.x+1);
92  ParallelFor(bx_xlo, bx_xhi,
93  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
94  int iflip = dom_lo.x - 1 - i;
95  if ( (bc_ptr_w[0].lo(0) == ERFBCType::ext_dir) ||
96  (bc_ptr_w[0].lo(0) == ERFBCType::ext_dir_upwind && xvel_arr(dom_lo.x,Clamp(j,xvel_lo.y,xvel_hi.y),Clamp(k,xvel_lo.z,xvel_hi.z)) >= zero) )
97  {
98  dest_arr(i,j,k) = (zvel_bc_ptr) ? zvel_bc_ptr[k] : l_bc_extdir_vals_d[0][0];
99  if (l_use_terrain_fitted_coords) {
100  dest_arr(i,j,k) = WFromOmega(i,j,k,dest_arr(i,j,k),
101  xvel_arr,yvel_arr,
102  mf_u,mf_v,z_phys_nd,dxInv);
103  }
104  } else if (bc_ptr_w[0].lo(0) == ERFBCType::foextrap) {
105  dest_arr(i,j,k) = dest_arr(dom_lo.x,j,k);
106  } else if (bc_ptr_w[0].lo(0) == ERFBCType::open) {
107  dest_arr(i,j,k) = dest_arr(dom_lo.x,j,k);
108  } else if (bc_ptr_w[0].lo(0) == ERFBCType::reflect_even) {
109  dest_arr(i,j,k) = dest_arr(iflip,j,k);
110  } else if (bc_ptr_w[0].lo(0) == ERFBCType::reflect_odd) {
111  dest_arr(i,j,k) = -dest_arr(iflip,j,k);
112  }
113  },
114  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
115  int iflip = 2*dom_hi.x + 1 - i;
116  if ( (bc_ptr_w[0].hi(0) == ERFBCType::ext_dir) ||
117  (bc_ptr_w[0].hi(0) == ERFBCType::ext_dir_upwind && xvel_arr(dom_hi.x+1,Clamp(j,xvel_lo.y,xvel_hi.y),Clamp(k,xvel_lo.z,xvel_hi.z)) <= zero) )
118  {
119  dest_arr(i,j,k) = (zvel_bc_ptr) ? zvel_bc_ptr[k] : l_bc_extdir_vals_d[0][3];
120  if (l_use_terrain_fitted_coords) {
121  dest_arr(i,j,k) = WFromOmega(i,j,k,dest_arr(i,j,k),
122  xvel_arr,yvel_arr,
123  mf_u,mf_v,z_phys_nd,dxInv);
124  }
125  } else if (bc_ptr_w[0].hi(0) == ERFBCType::foextrap) {
126  dest_arr(i,j,k) = dest_arr(dom_hi.x,j,k);
127  } else if (bc_ptr_w[0].hi(0) == ERFBCType::open) {
128  dest_arr(i,j,k) = dest_arr(dom_hi.x,j,k);
129  } else if (bc_ptr_w[0].hi(0) == ERFBCType::reflect_even) {
130  dest_arr(i,j,k) = dest_arr(iflip,j,k);
131  } else if (bc_ptr_w[0].hi(0) == ERFBCType::reflect_odd) {
132  dest_arr(i,j,k) = -dest_arr(iflip,j,k);
133  }
134  }
135  );
136  }
137 
138  // First do all ext_dir bcs
139  if (!is_periodic_in_y)
140  {
141  Real* zvel_bc_ptr = m_w_bc_data;
142  Box bx_ylo(bx); bx_ylo.setBig (1,dom_lo.y-1);
143  Box bx_yhi(bx); bx_yhi.setSmall(1,dom_hi.y+1);
144  ParallelFor(bx_ylo, bx_yhi,
145  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
146  int jflip = dom_lo.y - 1 - j;
147  if ( (bc_ptr_w[0].lo(1) == ERFBCType::ext_dir) ||
148  (bc_ptr_w[0].lo(1) == ERFBCType::ext_dir_upwind && yvel_arr(Clamp(i,yvel_lo.x,yvel_hi.x),dom_lo.y,Clamp(k,yvel_lo.z,yvel_hi.z)) >= zero) )
149  {
150  dest_arr(i,j,k) = (zvel_bc_ptr) ? zvel_bc_ptr[k] : l_bc_extdir_vals_d[0][1];
151  if (l_use_terrain_fitted_coords) {
152  dest_arr(i,j,k) = WFromOmega(i,j,k,dest_arr(i,j,k),
153  xvel_arr,yvel_arr,
154  mf_u,mf_v,z_phys_nd,dxInv);
155  }
156  } else if (bc_ptr_w[0].lo(1) == ERFBCType::foextrap) {
157  dest_arr(i,j,k) = dest_arr(i,dom_lo.y,k);
158  } else if (bc_ptr_w[0].lo(1) == ERFBCType::open) {
159  dest_arr(i,j,k) = dest_arr(i,dom_lo.y,k);
160  } else if (bc_ptr_w[0].lo(1) == ERFBCType::reflect_even) {
161  dest_arr(i,j,k) = dest_arr(i,jflip,k);
162  } else if (bc_ptr_w[0].lo(1) == ERFBCType::reflect_odd) {
163  dest_arr(i,j,k) = -dest_arr(i,jflip,k);
164  }
165  },
166  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
167  int jflip = 2*dom_hi.y + 1 - j;
168  if ( (bc_ptr_w[0].hi(1) == ERFBCType::ext_dir) ||
169  (bc_ptr_w[0].hi(1) == ERFBCType::ext_dir_upwind && yvel_arr(Clamp(i,yvel_lo.x,yvel_hi.x),dom_hi.y+1,Clamp(k,yvel_lo.z,yvel_hi.z)) <= zero) )
170  {
171  dest_arr(i,j,k) = (zvel_bc_ptr) ? zvel_bc_ptr[k] : l_bc_extdir_vals_d[0][4];
172  if (l_use_terrain_fitted_coords) {
173  dest_arr(i,j,k) = WFromOmega(i,j,k,dest_arr(i,j,k),
174  xvel_arr,yvel_arr,
175  mf_u,mf_v,z_phys_nd,dxInv);
176  }
177  } else if (bc_ptr_w[0].hi(1) == ERFBCType::foextrap) {
178  dest_arr(i,j,k) = dest_arr(i,dom_hi.y,k);
179  } else if (bc_ptr_w[0].hi(1) == ERFBCType::open) {
180  dest_arr(i,j,k) = dest_arr(i,dom_hi.y,k);
181  } else if (bc_ptr_w[0].hi(1) == ERFBCType::reflect_even) {
182  dest_arr(i,j,k) = dest_arr(i,jflip,k);
183  } else if (bc_ptr_w[0].hi(1) == ERFBCType::reflect_odd) {
184  dest_arr(i,j,k) = -dest_arr(i,jflip,k);
185  }
186  });
187  }
188  Gpu::streamSynchronize();
189 }
amrex::GpuArray< Real, AMREX_SPACEDIM > dxInv
Definition: ERF_InitCustomPertVels_ParticleTests.H:17
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);})
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:36
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real WFromOmega(int &i, int &j, int &k, amrex::Real omega, const amrex::Array4< const amrex::Real > &u_arr, const amrex::Array4< const amrex::Real > &v_arr, const amrex::Array4< const amrex::Real > &mf_u, const amrex::Array4< const amrex::Real > &mf_v, const amrex::Array4< const amrex::Real > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dxInv)
Definition: ERF_TerrainMetrics.H:863
void impose_lateral_zvel_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, const amrex::Array4< amrex::Real const > &mf_u, const amrex::Array4< amrex::Real const > &mf_v, const amrex::Array4< amrex::Real const > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > dxInv, TerrainType terrain_type, int bccomp, const double time)
Definition: ERF_BoundaryConditionsZvel.cpp:23
@ open
Definition: ERF_IndexDefines.H:307
@ reflect_odd
Definition: ERF_IndexDefines.H:296
@ foextrap
Definition: ERF_IndexDefines.H:299
@ ext_dir
Definition: ERF_IndexDefines.H:300
@ ext_dir_upwind
Definition: ERF_IndexDefines.H:308
@ reflect_even
Definition: ERF_IndexDefines.H:298
Here is the call graph for this function:

◆ impose_vertical_zvel_bcs()

void ERFPhysBCFunct_w::impose_vertical_zvel_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,
const amrex::Array4< amrex::Real const > &  mf_u,
const amrex::Array4< amrex::Real const > &  mf_v,
const amrex::Array4< amrex::Real const > &  z_nd,
const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM >  dxInv,
int  bccomp_u,
int  bccomp_v,
int  bccomp_w,
TerrainType  terrain_type,
const double  time 
)

Impose vertical boundary conditions on z velocity.

Parameters
[in,out]dest_arrz-velocity data to be filled
[in]xvel_arrx-velocity used by terrain-aware vertical BCs
[in]yvel_arry-velocity used by terrain-aware vertical BCs
[in]bxbox holding data to be filled
[in]domainsimulation domain
[in]mf_ux map-factor field
[in]mf_vy map-factor field
[in]z_ndnodal physical height
[in]dxInvinverse cell size
[in]bccomp_ux-velocity boundary-condition component
[in]bccomp_vy-velocity boundary-condition component
[in]bccomp_wz-velocity boundary-condition component
[in]terrain_typeterrain representation
[in]timetime at which data should be filled

Impose vertical boundary conditions on z-component of velocity

Parameters
[in,out]dest_arrArray4 of the quantity to be filled
[in]xvel_arrx-velocity used to convert omega to w
[in]yvel_arry-velocity used to convert omega to w
[in]bxbox associated with this data
[in]domaincomputational domain
[in]mf_umetric-aware x-velocity used to convert omega to w
[in]mf_vmetric-aware y-velocity used to convert omega to w
[in]z_phys_ndheight coordinate at nodes
[in]dxInvinverse cell size array
[in]bccomp_uindex into m_domain_bcs_type corresponding to u
[in]bccomp_vindex into m_domain_bcs_type corresponding to v
[in]bccomp_windex into m_domain_bcs_type corresponding to w
[in]terrain_typeif MovingFittedMesh then the terrain is moving; otherwise fixed
[in]timetime at which the data should be filled
221 {
222  BL_PROFILE_VAR("impose_vertical_zvel_bcs()",impose_vertical_zvel_bcs);
223  const auto& dom_lo = lbound(domain);
224  const auto& dom_hi = ubound(domain);
225 
226  // xlo: ori = 0
227  // ylo: ori = 1
228  // zlo: ori = 2
229  // xhi: ori = 3
230  // yhi: ori = 4
231  // zhi: ori = 5
232 
233  // Based on BCRec for the domain, we need to make BCRec for this Box
234  // bccomp is used as starting index for m_domain_bcs_type
235  // 0 is used as starting index for bcrs
236  Vector<BCRec> bcrs_u(1), bcrs_v(1), bcrs_w(1);
237  setBC(enclosedCells(bx), domain, bccomp_u, 0, 1, m_domain_bcs_type, bcrs_u);
238  setBC(enclosedCells(bx), domain, bccomp_v, 0, 1, m_domain_bcs_type, bcrs_v);
239  setBC(enclosedCells(bx), domain, bccomp_w, 0, 1, m_domain_bcs_type, bcrs_w);
240 
241  // We use these for the asserts below
242  const BCRec* bc_ptr_u_h = bcrs_u.data();
243  const BCRec* bc_ptr_v_h = bcrs_v.data();
244  const BCRec* bc_ptr_w_h = bcrs_w.data();
245 
246  bool l_use_terrain_fitted_coords = ( (terrain_type == TerrainType::StaticFittedMesh) ||
247  (terrain_type == TerrainType::MovingFittedMesh) );
248  bool l_moving_terrain = (terrain_type == TerrainType::MovingFittedMesh);
249 
250  GpuArray<GpuArray<Real, AMREX_SPACEDIM*2>,1> l_bc_extdir_vals_d;
251 
252  for (int ori = 0; ori < 2*AMREX_SPACEDIM; ori++) {
253  l_bc_extdir_vals_d[0][ori] = m_bc_extdir_vals[bccomp_w][ori];
254  }
255 
256  // *******************************************************
257  // Bottom boundary
258  // *******************************************************
259 
260  // *******************************************************
261  // Moving terrain
262  // *******************************************************
263  if (l_moving_terrain)
264  {
265  //************************************************************
266  // NOTE: z_t depends on the time interval in which it is
267  // evaluated so we can't arbitrarily define it at a
268  // given time, we must specify an interval
269  //************************************************************
270 
271  // Static terrain
272  } else if (l_use_terrain_fitted_coords) {
273 
274  if (m_lev == 0) {
275  AMREX_ALWAYS_ASSERT( (bc_ptr_u_h[0].lo(2) == ERFBCType::ext_dir && bc_ptr_v_h[0].lo(2) == ERFBCType::ext_dir) ||
276  (bc_ptr_u_h[0].lo(2) != ERFBCType::ext_dir && bc_ptr_v_h[0].lo(2) != ERFBCType::ext_dir) );
277  } else {
278  // If we do not reach to the top or bottom boundary then the z-vel should be
279  // filled by interpolation from the coarser grid using ERF_FillPatcher.
280  }
281  if (bx.smallEnd(2) == dom_lo.z) {
282  ParallelFor(makeSlab(bx,2,dom_lo.z), [=] AMREX_GPU_DEVICE (int i, int j, int k) {
283  dest_arr(i,j,k) = WFromOmega(i,j,k,l_bc_extdir_vals_d[0][2],
284  xvel_arr,yvel_arr,
285  mf_u,mf_v,z_phys_nd,dxInv);
286  });
287  }
288 
289  // No terrain
290  } else {
291  if (bx.smallEnd(2) == dom_lo.z) {
292  ParallelFor(makeSlab(bx,2,dom_lo.z), [=] AMREX_GPU_DEVICE (int i, int j, int k) {
293  dest_arr(i,j,k) = l_bc_extdir_vals_d[0][2];
294  });
295  }
296  }
297 
298  // *******************************************************
299  // Top boundary
300  // *******************************************************
301 
302  // NOTE: if we set SlipWall at top, that generates ERFBCType::ext_dir which sets w=0 here
303  // NOTE: if we set Outflow at top, that generates ERFBCType::foextrap which doesn't touch w here
304  if (bx.bigEnd(2) == dom_hi.z+1) {
305  if (bc_ptr_w_h[0].hi(2) == ERFBCType::ext_dir) {
306  ParallelFor(makeSlab(bx,2,dom_hi.z+1), [=] AMREX_GPU_DEVICE (int i, int j, int k)
307  {
308  if (l_use_terrain_fitted_coords) {
309  dest_arr(i,j,k) = WFromOmega(i,j,k,l_bc_extdir_vals_d[0][5],
310  xvel_arr,yvel_arr,
311  mf_u,mf_v,z_phys_nd,dxInv);
312  } else {
313  dest_arr(i,j,k) = l_bc_extdir_vals_d[0][5];
314  }
315  });
316  } else if (bc_ptr_w_h[0].hi(2) == ERFBCType::neumann_int) {
317  ParallelFor(makeSlab(bx,2,dom_hi.z+1), [=] AMREX_GPU_DEVICE (int i, int j, int k)
318  {
319  dest_arr(i,j,k) = (Real(4.0)*dest_arr(i,j,dom_hi.z) - dest_arr(i,j,dom_hi.z-1))/three;
320  });
321  }
322  }
323  Gpu::streamSynchronize();
324 }
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
constexpr amrex::Real three
Definition: ERF_NumericalConstants.H:39
void impose_vertical_zvel_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, const amrex::Array4< amrex::Real const > &mf_u, const amrex::Array4< amrex::Real const > &mf_v, const amrex::Array4< amrex::Real const > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > dxInv, int bccomp_u, int bccomp_v, int bccomp_w, TerrainType terrain_type, const double time)
Definition: ERF_BoundaryConditionsZvel.cpp:210
@ neumann_int
Definition: ERF_IndexDefines.H:306
Here is the call graph for this function:

◆ operator()()

void ERFPhysBCFunct_w::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]mfz-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 for z velocity
[in]do_fbwhether to fill periodic/interior ghost cells first

Impose physical boundary conditions on z velocity.

Parameters
[in,out]mfz-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]bccomp_windex into m_domain_bcs_type for z velocity
[in]do_fbwhether to fill periodic/interior ghost cells first
357 {
358  BL_PROFILE("ERFPhysBCFunct_w::()");
359 
360  //
361  // We fill all of the interior and periodic ghost cells first, so we can fill
362  // those directly inside the lateral and vertical calls.
363  // If triply periodic this is all we do
364  //
365  if (do_fb) {
366  mf.FillBoundary(m_geom.periodicity());
367  }
368 
369  if (m_geom.isAllPeriodic()) return;
370 
371  int bccomp_u = BCVars::xvel_bc;
372  int bccomp_v = BCVars::yvel_bc;
373 
374  const auto& domain = m_geom.Domain();
375  const auto dxInv = m_geom.InvCellSizeArray();
376 
377  Box gdomainz = surroundingNodes(domain,2);
378  for (int i = 0; i < AMREX_SPACEDIM; ++i) {
379  if (m_geom.isPeriodic(i)) {
380  gdomainz.grow(i, nghost[i]);
381  }
382  }
383  //
384  // We want to make sure we impose the z-vels at k=0 if the box includes k=0
385  //
386  if (gdomainz.smallEnd(2) == 0) gdomainz.setSmall(2,1);
387 
388 #ifdef AMREX_USE_OMP
389 #pragma omp parallel if (Gpu::notInLaunchRegion())
390 #endif
391  {
392  for (MFIter mfi(mf,false); mfi.isValid(); ++mfi)
393  {
394  //
395  // This is the box we pass to the different routines
396  // NOTE -- this is the full grid NOT the tile box
397  //
398  Box bx = mfi.validbox();
399 
400  //
401  // These are the boxes we use to test on relative to the domain
402  //
403  Box zbx = surroundingNodes(bx,2); zbx.grow(nghost);
404  if (zbx.smallEnd(2) < domain.smallEnd(2)) zbx.setSmall(2,domain.smallEnd(2));
405  if (zbx.bigEnd(2) > domain.bigEnd(2)) {
406  zbx.setBig(2,domain.bigEnd(2)+1);
407  } else if (zbx.bigEnd(2) > xvel[mfi].box().bigEnd(2)) {
408  // We do this so if a box at level > 0 doesn't reach the top boundary, we don't go out of bounds
409  // (Note xvel is chosen arbitrarily; we could have used yvel instead)
410  zbx.setBig(2,xvel[mfi].box().bigEnd(2));
411  }
412 
413  Array4<const Real> z_nd_arr;
414  const Array4<const Real>& mf_u = m_mapfac_u->const_array(mfi);
415  const Array4<const Real>& mf_v = m_mapfac_v->const_array(mfi);
416 
417  if (m_z_phys_nd) {
418  z_nd_arr = m_z_phys_nd->const_array(mfi);
419  }
420 
421  //
422  // Recall that gdomainz.smallEnd(2) = 1 not 0!
423  //
424  if (!gdomainz.contains(zbx)) {
425  Array4<const Real> const& velx_arr = xvel.const_array(mfi);
426  Array4<const Real> const& vely_arr = yvel.const_array(mfi);
427  Array4< Real> const& velz_arr = mf.array(mfi);
428 
429  if (!gdomainz.contains(zbx) && !m_use_real_bcs) {
430  impose_lateral_zvel_bcs(velz_arr,velx_arr,vely_arr,zbx,domain,
431  mf_u,mf_v,z_nd_arr,dxInv,m_terrain_type,bccomp_w,time);
432  }
433 
434  impose_vertical_zvel_bcs(velz_arr,velx_arr,vely_arr,zbx,domain,mf_u,mf_v,
435  z_nd_arr,dxInv,bccomp_u, bccomp_v, bccomp_w, m_terrain_type, time);
436  }
437  } // MFIter
438  } // OpenMP
439 } // operator()
@ yvel_bc
Definition: ERF_IndexDefines.H:109
@ xvel_bc
Definition: ERF_IndexDefines.H:108
@ xvel
Definition: ERF_IndexDefines.H:218
@ yvel
Definition: ERF_IndexDefines.H:219

Member Data Documentation

◆ m_bc_extdir_vals

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

◆ m_bc_neumann_vals

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

◆ m_domain_bcs_type

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

◆ m_domain_bcs_type_d

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

◆ m_geom

amrex::Geometry ERFPhysBCFunct_w::m_geom
private

◆ m_lev

int ERFPhysBCFunct_w::m_lev
private

◆ m_mapfac_u

amrex::MultiFab* ERFPhysBCFunct_w::m_mapfac_u
private

Referenced by ERFPhysBCFunct_w().

◆ m_mapfac_v

amrex::MultiFab* ERFPhysBCFunct_w::m_mapfac_v
private

Referenced by ERFPhysBCFunct_w().

◆ m_terrain_type

TerrainType ERFPhysBCFunct_w::m_terrain_type
private

◆ m_use_real_bcs

bool ERFPhysBCFunct_w::m_use_real_bcs
private

◆ m_w_bc_data

amrex::Real* ERFPhysBCFunct_w::m_w_bc_data
private

◆ m_z_phys_nd

amrex::MultiFab* ERFPhysBCFunct_w::m_z_phys_nd
private

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