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_maxm_bc_extdir_vals
 
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NBCVAR_maxm_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::Realm_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
362  : m_lev(lev),
363  m_geom(geom), m_domain_bcs_type(domain_bcs_type),
364  m_domain_bcs_type_d(domain_bcs_type_d),
365  m_bc_extdir_vals(bc_extdir_vals),
366  m_bc_neumann_vals(bc_neumann_vals),
367  m_terrain_type(terrain_type),
368  m_z_phys_nd(z_phys_nd.get()),
369  m_use_real_bcs(use_real_bcs),
370  m_w_bc_data(w_bc_data)
371  {
372  m_mapfac_u = mapfac_lev[MapFacType::u_x].get();
373  m_mapfac_v = mapfac_lev[MapFacType::v_y].get();
374  }
@ v_y
Definition: ERF_DataStruct.H:28
@ u_x
Definition: ERF_DataStruct.H:27
amrex::Vector< amrex::BCRec > m_domain_bcs_type
Definition: ERF_PhysBCFunct.H:456
amrex::Geometry m_geom
Definition: ERF_PhysBCFunct.H:455
int m_lev
Definition: ERF_PhysBCFunct.H:454
amrex::Real * m_w_bc_data
Definition: ERF_PhysBCFunct.H:465
bool m_use_real_bcs
Definition: ERF_PhysBCFunct.H:464
amrex::Gpu::DeviceVector< amrex::BCRec > m_domain_bcs_type_d
Definition: ERF_PhysBCFunct.H:457
amrex::MultiFab * m_mapfac_v
Definition: ERF_PhysBCFunct.H:462
TerrainType m_terrain_type
Definition: ERF_PhysBCFunct.H:460
amrex::MultiFab * m_z_phys_nd
Definition: ERF_PhysBCFunct.H:463
amrex::MultiFab * m_mapfac_u
Definition: ERF_PhysBCFunct.H:461
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NBCVAR_max > m_bc_neumann_vals
Definition: ERF_PhysBCFunct.H:459
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NBCVAR_max > m_bc_extdir_vals
Definition: ERF_PhysBCFunct.H:458

◆ ~ERFPhysBCFunct_w()

ERFPhysBCFunct_w::~ERFPhysBCFunct_w ( )
inline

Destroy the z-velocity physical boundary-condition functor.

379 {}

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  // Based on BCRec for the domain, we need to make BCRec for this Box
39  // bccomp is used as starting index for m_domain_bcs_type
40  // 0 is used as starting index for bcrs
41  Vector<BCRec> bcrs_w(1);
42  setBC(enclosedCells(bx), domain, bccomp, 0, 1, m_domain_bcs_type, bcrs_w);
43 
44  bool l_use_terrain_fitted_coords = ( (terrain_type == TerrainType::StaticFittedMesh) ||
45  (terrain_type == TerrainType::MovingFittedMesh) );
46 
47  // xlo: ori = 0
48  // ylo: ori = 1
49  // zlo: ori = 2
50  // xhi: ori = 3
51  // yhi: ori = 4
52  // zhi: ori = 5
53 
54  Gpu::DeviceVector<BCRec> bcrs_w_d(1);
55  Gpu::copyAsync(Gpu::hostToDevice, bcrs_w.begin(), bcrs_w.end(), bcrs_w_d.begin());
56  const BCRec* bc_ptr_w = bcrs_w_d.data();
57 
58  GpuArray<GpuArray<Real, AMREX_SPACEDIM*2>,1> l_bc_extdir_vals_d;
59 
60  for (int ori = 0; ori < 2*AMREX_SPACEDIM; ori++) {
61  l_bc_extdir_vals_d[0][ori] = m_bc_extdir_vals[bccomp][ori];
62  }
63 
64  GeometryData const& geomdata = m_geom.data();
65  bool is_periodic_in_x = geomdata.isPeriodic(0);
66  bool is_periodic_in_y = geomdata.isPeriodic(1);
67 
68  FArrayBox dhdtfab;
69 
70  // First do all ext_dir bcs
71  if (!is_periodic_in_x)
72  {
73  Real* zvel_bc_ptr = m_w_bc_data;
74  Box bx_xlo(bx); bx_xlo.setBig (0,dom_lo.x-1);
75  Box bx_xhi(bx); bx_xhi.setSmall(0,dom_hi.x+1);
76  ParallelFor(bx_xlo, bx_xhi,
77  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
78  int iflip = dom_lo.x - 1 - i;
79  if ( (bc_ptr_w[0].lo(0) == ERFBCType::ext_dir) ||
80  (bc_ptr_w[0].lo(0) == ERFBCType::ext_dir_upwind && xvel_arr(dom_lo.x,j,k) >= zero) )
81  {
82  dest_arr(i,j,k) = (zvel_bc_ptr) ? zvel_bc_ptr[k] : l_bc_extdir_vals_d[0][0];
83  if (l_use_terrain_fitted_coords) {
84  dest_arr(i,j,k) = WFromOmega(i,j,k,dest_arr(i,j,k),
85  xvel_arr,yvel_arr,
86  mf_u,mf_v,z_phys_nd,dxInv);
87  }
88  } else if (bc_ptr_w[0].lo(0) == ERFBCType::foextrap) {
89  dest_arr(i,j,k) = dest_arr(dom_lo.x,j,k);
90  } else if (bc_ptr_w[0].lo(0) == ERFBCType::open) {
91  dest_arr(i,j,k) = dest_arr(dom_lo.x,j,k);
92  } else if (bc_ptr_w[0].lo(0) == ERFBCType::reflect_even) {
93  dest_arr(i,j,k) = dest_arr(iflip,j,k);
94  } else if (bc_ptr_w[0].lo(0) == ERFBCType::reflect_odd) {
95  dest_arr(i,j,k) = -dest_arr(iflip,j,k);
96  }
97  },
98  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
99  int iflip = 2*dom_hi.x + 1 - i;
100  if ( (bc_ptr_w[0].hi(0) == ERFBCType::ext_dir) ||
101  (bc_ptr_w[0].hi(0) == ERFBCType::ext_dir_upwind && xvel_arr(dom_hi.x+1,j,k) <= zero) )
102  {
103  dest_arr(i,j,k) = (zvel_bc_ptr) ? zvel_bc_ptr[k] : l_bc_extdir_vals_d[0][3];
104  if (l_use_terrain_fitted_coords) {
105  dest_arr(i,j,k) = WFromOmega(i,j,k,dest_arr(i,j,k),
106  xvel_arr,yvel_arr,
107  mf_u,mf_v,z_phys_nd,dxInv);
108  }
109  } else if (bc_ptr_w[0].hi(0) == ERFBCType::foextrap) {
110  dest_arr(i,j,k) = dest_arr(dom_hi.x,j,k);
111  } else if (bc_ptr_w[0].hi(0) == ERFBCType::open) {
112  dest_arr(i,j,k) = dest_arr(dom_hi.x,j,k);
113  } else if (bc_ptr_w[0].hi(0) == ERFBCType::reflect_even) {
114  dest_arr(i,j,k) = dest_arr(iflip,j,k);
115  } else if (bc_ptr_w[0].hi(0) == ERFBCType::reflect_odd) {
116  dest_arr(i,j,k) = -dest_arr(iflip,j,k);
117  }
118  }
119  );
120  }
121 
122  // First do all ext_dir bcs
123  if (!is_periodic_in_y)
124  {
125  Real* zvel_bc_ptr = m_w_bc_data;
126  Box bx_ylo(bx); bx_ylo.setBig (1,dom_lo.y-1);
127  Box bx_yhi(bx); bx_yhi.setSmall(1,dom_hi.y+1);
128  ParallelFor(bx_ylo, bx_yhi,
129  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
130  int jflip = dom_lo.y - 1 - j;
131  if ( (bc_ptr_w[0].lo(1) == ERFBCType::ext_dir) ||
132  (bc_ptr_w[0].lo(1) == ERFBCType::ext_dir_upwind && yvel_arr(i,dom_lo.y,k) >= zero) )
133  {
134  dest_arr(i,j,k) = (zvel_bc_ptr) ? zvel_bc_ptr[k] : l_bc_extdir_vals_d[0][1];
135  if (l_use_terrain_fitted_coords) {
136  dest_arr(i,j,k) = WFromOmega(i,j,k,dest_arr(i,j,k),
137  xvel_arr,yvel_arr,
138  mf_u,mf_v,z_phys_nd,dxInv);
139  }
140  } else if (bc_ptr_w[0].lo(1) == ERFBCType::foextrap) {
141  dest_arr(i,j,k) = dest_arr(i,dom_lo.y,k);
142  } else if (bc_ptr_w[0].lo(1) == ERFBCType::open) {
143  dest_arr(i,j,k) = dest_arr(i,dom_lo.y,k);
144  } else if (bc_ptr_w[0].lo(1) == ERFBCType::reflect_even) {
145  dest_arr(i,j,k) = dest_arr(i,jflip,k);
146  } else if (bc_ptr_w[0].lo(1) == ERFBCType::reflect_odd) {
147  dest_arr(i,j,k) = -dest_arr(i,jflip,k);
148  }
149  },
150  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
151  int jflip = 2*dom_hi.y + 1 - j;
152  if ( (bc_ptr_w[0].hi(1) == ERFBCType::ext_dir) ||
153  (bc_ptr_w[0].hi(1) == ERFBCType::ext_dir_upwind && yvel_arr(i,dom_hi.y+1,k) <= zero) )
154  {
155  dest_arr(i,j,k) = (zvel_bc_ptr) ? zvel_bc_ptr[k] : l_bc_extdir_vals_d[0][4];
156  if (l_use_terrain_fitted_coords) {
157  dest_arr(i,j,k) = WFromOmega(i,j,k,dest_arr(i,j,k),
158  xvel_arr,yvel_arr,
159  mf_u,mf_v,z_phys_nd,dxInv);
160  }
161  } else if (bc_ptr_w[0].hi(1) == ERFBCType::foextrap) {
162  dest_arr(i,j,k) = dest_arr(i,dom_hi.y,k);
163  } else if (bc_ptr_w[0].hi(1) == ERFBCType::open) {
164  dest_arr(i,j,k) = dest_arr(i,dom_hi.y,k);
165  } else if (bc_ptr_w[0].hi(1) == ERFBCType::reflect_even) {
166  dest_arr(i,j,k) = dest_arr(i,jflip,k);
167  } else if (bc_ptr_w[0].hi(1) == ERFBCType::reflect_odd) {
168  dest_arr(i,j,k) = -dest_arr(i,jflip,k);
169  }
170  });
171  }
172  Gpu::streamSynchronize();
173 }
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
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);})
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:464
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:256
@ reflect_odd
Definition: ERF_IndexDefines.H:245
@ foextrap
Definition: ERF_IndexDefines.H:248
@ ext_dir
Definition: ERF_IndexDefines.H:249
@ ext_dir_upwind
Definition: ERF_IndexDefines.H:257
@ reflect_even
Definition: ERF_IndexDefines.H:247
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
205 {
206  BL_PROFILE_VAR("impose_vertical_zvel_bcs()",impose_vertical_zvel_bcs);
207  const auto& dom_lo = lbound(domain);
208  const auto& dom_hi = ubound(domain);
209 
210  // xlo: ori = 0
211  // ylo: ori = 1
212  // zlo: ori = 2
213  // xhi: ori = 3
214  // yhi: ori = 4
215  // zhi: ori = 5
216 
217  // Based on BCRec for the domain, we need to make BCRec for this Box
218  // bccomp is used as starting index for m_domain_bcs_type
219  // 0 is used as starting index for bcrs
220  Vector<BCRec> bcrs_u(1), bcrs_v(1), bcrs_w(1);
221  setBC(enclosedCells(bx), domain, bccomp_u, 0, 1, m_domain_bcs_type, bcrs_u);
222  setBC(enclosedCells(bx), domain, bccomp_v, 0, 1, m_domain_bcs_type, bcrs_v);
223  setBC(enclosedCells(bx), domain, bccomp_w, 0, 1, m_domain_bcs_type, bcrs_w);
224 
225  // We use these for the asserts below
226  const BCRec* bc_ptr_u_h = bcrs_u.data();
227  const BCRec* bc_ptr_v_h = bcrs_v.data();
228  const BCRec* bc_ptr_w_h = bcrs_w.data();
229 
230  bool l_use_terrain_fitted_coords = ( (terrain_type == TerrainType::StaticFittedMesh) ||
231  (terrain_type == TerrainType::MovingFittedMesh) );
232  bool l_moving_terrain = (terrain_type == TerrainType::MovingFittedMesh);
233 
234  GpuArray<GpuArray<Real, AMREX_SPACEDIM*2>,1> l_bc_extdir_vals_d;
235 
236  for (int ori = 0; ori < 2*AMREX_SPACEDIM; ori++) {
237  l_bc_extdir_vals_d[0][ori] = m_bc_extdir_vals[bccomp_w][ori];
238  }
239 
240  // *******************************************************
241  // Bottom boundary
242  // *******************************************************
243 
244  // *******************************************************
245  // Moving terrain
246  // *******************************************************
247  if (l_moving_terrain)
248  {
249  //************************************************************
250  // NOTE: z_t depends on the time interval in which it is
251  // evaluated so we can't arbitrarily define it at a
252  // given time, we must specify an interval
253  //************************************************************
254 
255  // Static terrain
256  } else if (l_use_terrain_fitted_coords) {
257 
258  if (m_lev == 0) {
259  AMREX_ALWAYS_ASSERT( (bc_ptr_u_h[0].lo(2) == ERFBCType::ext_dir && bc_ptr_v_h[0].lo(2) == ERFBCType::ext_dir) ||
260  (bc_ptr_u_h[0].lo(2) != ERFBCType::ext_dir && bc_ptr_v_h[0].lo(2) != ERFBCType::ext_dir) );
261  } else {
262  // If we do not reach to the top or bottom boundary then the z-vel should be
263  // filled by interpolation from the coarser grid using ERF_FillPatcher.
264  }
265  if (bx.smallEnd(2) == dom_lo.z) {
266  ParallelFor(makeSlab(bx,2,dom_lo.z), [=] AMREX_GPU_DEVICE (int i, int j, int k) {
267  dest_arr(i,j,k) = WFromOmega(i,j,k,l_bc_extdir_vals_d[0][2],
268  xvel_arr,yvel_arr,
269  mf_u,mf_v,z_phys_nd,dxInv);
270  });
271  }
272 
273  // No terrain
274  } else {
275  if (bx.smallEnd(2) == dom_lo.z) {
276  ParallelFor(makeSlab(bx,2,dom_lo.z), [=] AMREX_GPU_DEVICE (int i, int j, int k) {
277  dest_arr(i,j,k) = l_bc_extdir_vals_d[0][2];
278  });
279  }
280  }
281 
282  // *******************************************************
283  // Top boundary
284  // *******************************************************
285 
286  // NOTE: if we set SlipWall at top, that generates ERFBCType::ext_dir which sets w=0 here
287  // NOTE: if we set Outflow at top, that generates ERFBCType::foextrap which doesn't touch w here
288  if (bx.bigEnd(2) == dom_hi.z+1) {
289  if (bc_ptr_w_h[0].hi(2) == ERFBCType::ext_dir) {
290  ParallelFor(makeSlab(bx,2,dom_hi.z+1), [=] AMREX_GPU_DEVICE (int i, int j, int k)
291  {
292  if (l_use_terrain_fitted_coords) {
293  dest_arr(i,j,k) = WFromOmega(i,j,k,l_bc_extdir_vals_d[0][5],
294  xvel_arr,yvel_arr,
295  mf_u,mf_v,z_phys_nd,dxInv);
296  } else {
297  dest_arr(i,j,k) = l_bc_extdir_vals_d[0][5];
298  }
299  });
300  } else if (bc_ptr_w_h[0].hi(2) == ERFBCType::neumann_int) {
301  ParallelFor(makeSlab(bx,2,dom_hi.z+1), [=] AMREX_GPU_DEVICE (int i, int j, int k)
302  {
303  dest_arr(i,j,k) = (Real(4.0)*dest_arr(i,j,dom_hi.z) - dest_arr(i,j,dom_hi.z-1))/three;
304  });
305  }
306  }
307  Gpu::streamSynchronize();
308 }
constexpr amrex::Real three
Definition: ERF_Constants.H:11
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
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:194
@ neumann_int
Definition: ERF_IndexDefines.H:255
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
268 {
269  BL_PROFILE("ERFPhysBCFunct_w::()");
270 
271  //
272  // We fill all of the interior and periodic ghost cells first, so we can fill
273  // those directly inside the lateral and vertical calls.
274  // If triply periodic this is all we do
275  //
276  if (do_fb) {
277  mf.FillBoundary(m_geom.periodicity());
278  }
279 
280  if (m_geom.isAllPeriodic()) return;
281 
282  int bccomp_u = BCVars::xvel_bc;
283  int bccomp_v = BCVars::yvel_bc;
284 
285  const auto& domain = m_geom.Domain();
286  const auto dxInv = m_geom.InvCellSizeArray();
287 
288  Box gdomainz = surroundingNodes(domain,2);
289  for (int i = 0; i < AMREX_SPACEDIM; ++i) {
290  if (m_geom.isPeriodic(i)) {
291  gdomainz.grow(i, nghost[i]);
292  }
293  }
294  //
295  // We want to make sure we impose the z-vels at k=0 if the box includes k=0
296  //
297  if (gdomainz.smallEnd(2) == 0) gdomainz.setSmall(2,1);
298 
299 #ifdef AMREX_USE_OMP
300 #pragma omp parallel if (Gpu::notInLaunchRegion())
301 #endif
302  {
303  for (MFIter mfi(mf,false); mfi.isValid(); ++mfi)
304  {
305  //
306  // This is the box we pass to the different routines
307  // NOTE -- this is the full grid NOT the tile box
308  //
309  Box bx = mfi.validbox();
310 
311  //
312  // These are the boxes we use to test on relative to the domain
313  //
314  Box zbx = surroundingNodes(bx,2); zbx.grow(nghost);
315  if (zbx.smallEnd(2) < domain.smallEnd(2)) zbx.setSmall(2,domain.smallEnd(2));
316  if (zbx.bigEnd(2) > domain.bigEnd(2)) {
317  zbx.setBig(2,domain.bigEnd(2)+1);
318  } else if (zbx.bigEnd(2) > xvel[mfi].box().bigEnd(2)) {
319  // We do this so if a box at level > 0 doesn't reach the top boundary, we don't go out of bounds
320  // (Note xvel is chosen arbitrarily; we could have used yvel instead)
321  zbx.setBig(2,xvel[mfi].box().bigEnd(2));
322  }
323 
324  Array4<const Real> z_nd_arr;
325  const Array4<const Real>& mf_u = m_mapfac_u->const_array(mfi);
326  const Array4<const Real>& mf_v = m_mapfac_v->const_array(mfi);
327 
328  if (m_z_phys_nd) {
329  z_nd_arr = m_z_phys_nd->const_array(mfi);
330  }
331 
332  //
333  // Recall that gdomainz.smallEnd(2) = 1 not 0!
334  //
335  if (!gdomainz.contains(zbx)) {
336  Array4<const Real> const& velx_arr = xvel.const_array(mfi);
337  Array4<const Real> const& vely_arr = yvel.const_array(mfi);
338  Array4< Real> const& velz_arr = mf.array(mfi);
339 
340  if (!gdomainz.contains(zbx) && !m_use_real_bcs) {
341  impose_lateral_zvel_bcs(velz_arr,velx_arr,vely_arr,zbx,domain,
342  mf_u,mf_v,z_nd_arr,dxInv,m_terrain_type,bccomp_w,time);
343  }
344 
345  impose_vertical_zvel_bcs(velz_arr,velx_arr,vely_arr,zbx,domain,mf_u,mf_v,
346  z_nd_arr,dxInv,bccomp_u, bccomp_v, bccomp_w, m_terrain_type, time);
347  }
348  } // MFIter
349  } // OpenMP
350 } // operator()
@ yvel_bc
Definition: ERF_IndexDefines.H:103
@ xvel_bc
Definition: ERF_IndexDefines.H:102
@ 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_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: