REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_BoundaryConditions_yvel.cpp
Go to the documentation of this file.
1#include "AMReX_PhysBCFunct.H"
3
4using namespace amrex;
5
6/**
7 * @param[inout] dest_arr data on which to apply BCs
8 * @param[in ] bx box to update on
9 * @param[in ] domain domain box
10 * @param[in ] dxInv pm or pn
11 * @param[in ] mskv land-sea mask on v-points
12 * @param[in ] calc_arr_in data to use in the RHS of calculations
13 * @param[in ] time current time
14 * @param[in ] bccomp index into both domain_bcs_type_bcr and bc_extdir_vals for icomp=0
15 */
16void REMORAPhysBCFunct::impose_yvel_bcs (const Array4<Real>& dest_arr, const Box& bx, const Box& domain,
19 Real /*time*/, int bccomp)
20{
21 BL_PROFILE_VAR("impose_yvel_bcs()",impose_yvel_bcs);
22 const auto& dom_lo = amrex::lbound(domain);
23 const auto& dom_hi = amrex::ubound(domain);
24
25 // Based on BCRec for the domain, we need to make BCRec for this Box
26 // bccomp is used as starting index for m_domain_bcs_type
27 // 0 is used as starting index for bcrs
28 int ncomp = 1;
30 amrex::setBC(bx, domain, bccomp, 0, ncomp, m_domain_bcs_type, bcrs);
31
32 // xlo: ori = 0
33 // ylo: ori = 1
34 // zlo: ori = 2
35 // xhi: ori = 3
36 // yhi: ori = 4
37 // zhi: ori = 5
38
39 amrex::Gpu::DeviceVector<BCRec> bcrs_d(ncomp);
40#ifdef AMREX_USE_GPU
41 Gpu::htod_memcpy_async(bcrs_d.data(), bcrs.data(), sizeof(BCRec)*ncomp);
42#else
43 std::memcpy(bcrs_d.data(), bcrs.data(), sizeof(BCRec)*ncomp);
44#endif
45 const amrex::BCRec* bc_ptr = bcrs_d.data();
46 const auto* bc_extdir_vals_ptr = m_bc_extdir_vals_d.data();
47
48 GeometryData const& geomdata = m_geom.data();
49 bool is_periodic_in_x = geomdata.isPeriodic(0);
50 bool is_periodic_in_y = geomdata.isPeriodic(1);
51 const Real eps= Real(1.0e-20);
52 // If calc_arr isn't passed in, we actually just want to use dest_arr values instead.
53 // That matches ROMS.
55
56 Box dest_arr_box = growHi(convert(Box(dest_arr),IntVect(0,1,0)),1,-1);
57 // First do all ext_dir bcs
59 {
60 // Populate ghost cells on lo-x and hi-x domain boundaries
61 Box bx_xlo(bx); bx_xlo.setBig (0,dom_lo.x-1);
62 Box bx_xhi(bx); bx_xhi.setSmall(0,dom_hi.x+1);
64 grow(bx_xlo,IntVect(0,-1,0)) & dest_arr_box, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) {
65 int iflip = dom_lo.x - 1- i;
66 if (bc_ptr[n].lo(0) == REMORABCType::ext_dir) {
68 } else if (bc_ptr[n].lo(0) == REMORABCType::foextrap || bc_ptr[n].lo(0) == REMORABCType::clamped) {
69 dest_arr(i,j,k) = dest_arr(dom_lo.x,j,k)*mskv(i,j,0);
70 } else if (bc_ptr[n].lo(0) == REMORABCType::orlanski_rad) {
71 Real grad_lo = calc_arr(dom_lo.x ,j+1,k) - calc_arr(dom_lo.x ,j ,k);
72 Real grad_lo_jm1 = calc_arr(dom_lo.x ,j ,k) - calc_arr(dom_lo.x ,j-1,k);
73 Real dVdt = calc_arr(dom_lo.x,j,k) - dest_arr(dom_lo.x ,j,k);
74 Real dVdx = dest_arr(dom_lo.x,j,k) - dest_arr(dom_lo.x+1,j,k);
75 if (dVdt * dVdx < zero) dVdt = zero;
76 Real dVde = (dVdt * (grad_lo_jm1 + grad_lo) > zero) ? grad_lo_jm1 : grad_lo;
77 Real cff = std::max(dVdx*dVdx + dVde*dVde,eps);
78 Real Cx = dVdt * dVdx;
79 dest_arr(i,j,k) = (cff * calc_arr(dom_lo.x-1,j,k) + Cx * dest_arr(dom_lo.x,j,k)) * mskv(i,j,0) / (cff + Cx);
80 } else if (bc_ptr[n].lo(0) == REMORABCType::reflect_even) {
81 dest_arr(i,j,k) = dest_arr(iflip,j,k)*mskv(i,j,0);
82 } else if (bc_ptr[n].lo(0) == REMORABCType::reflect_odd) {
83 dest_arr(i,j,k) = -dest_arr(iflip,j,k)*mskv(i,j,0);
84 }
85 },
86 grow(bx_xhi,IntVect(0,-1,0)) & dest_arr_box, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) {
87 int iflip = 2*dom_hi.x + 1 - i;
88 if (bc_ptr[n].hi(0) == REMORABCType::ext_dir) {
90 } else if (bc_ptr[n].hi(0) == REMORABCType::foextrap || bc_ptr[n].hi(0) == REMORABCType::clamped) {
91 dest_arr(i,j,k) = dest_arr(dom_hi.x,j,k)*mskv(i,j,0);
92 } else if (bc_ptr[n].hi(0) == REMORABCType::orlanski_rad) {
93 Real grad_hi = calc_arr(dom_hi.x ,j+1,k) - calc_arr(dom_hi.x ,j ,k);
94 Real grad_hi_jm1 = calc_arr(dom_hi.x ,j ,k) - calc_arr(dom_hi.x ,j-1,k);
95 Real dVdt = calc_arr(dom_hi.x,j,k) - dest_arr(dom_hi.x ,j,k);
96 Real dVdx = dest_arr(dom_hi.x,j,k) - dest_arr(dom_hi.x-1,j,k);
97 if (dVdt*dVdx < zero) dVdt = zero;
98 Real dVde = (dVdt * (grad_hi_jm1 + grad_hi) > zero) ? grad_hi_jm1 : grad_hi;
99 Real cff = std::max(dVdx*dVdx+dVde*dVde,eps);
100 Real Cx = dVdt * dVdx;
101 dest_arr(i,j,k) = (cff * calc_arr(dom_hi.x+1,j,k) + Cx * dest_arr(dom_hi.x,j,k)) * mskv(i,j,0) / (cff + Cx);
102 } else if (bc_ptr[n].hi(0) == REMORABCType::reflect_even) {
103 dest_arr(i,j,k) = dest_arr(iflip,j,k)*mskv(i,j,0);
104 } else if (bc_ptr[n].hi(0) == REMORABCType::reflect_odd) {
105 dest_arr(i,j,k) = -dest_arr(iflip,j,k)*mskv(i,j,0);
106 }
107 }
108 );
109 }
110
112 {
113 // Populate ghost cells on lo-y and hi-y domain boundaries
114 Box bx_ylo(bx); bx_ylo.setBig (1,dom_lo.y-1);
115 Box bx_yhi(bx); bx_yhi.setSmall(1,dom_hi.y+2);
116 Box bx_ylo_face(bx); bx_ylo_face.setSmall(1,dom_lo.y ); bx_ylo_face.setBig(1,dom_lo.y );
117 Box bx_yhi_face(bx); bx_yhi_face.setSmall(1,dom_hi.y+1); bx_yhi_face.setBig(1,dom_hi.y+1);
118
120 // We only set the values on the domain faces themselves if EXT_DIR or outflow
121 grow(bx_ylo_face,IntVect(-1,0,0)) & dest_arr_box, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) {
122 if (bc_ptr[n].lo(1) == REMORABCType::ext_dir) {
124 } else if (bc_ptr[n].lo(1) == REMORABCType::foextrap) {
125 dest_arr(i,j,k) = dest_arr(i,dom_lo.y+1,k)*mskv(i,j,0);
126 } else if (bc_ptr[n].lo(1) == REMORABCType::orlanski_rad) {
127 Real grad_lo_jp1 = calc_arr(i ,dom_lo.y+1,k) - calc_arr(i-1,dom_lo.y+1,k);
128 Real grad_lo_ijp1 = calc_arr(i+1,dom_lo.y+1,k) - calc_arr(i ,dom_lo.y+1,k);
129 Real dVdt = calc_arr(i,dom_lo.y+1,k) - dest_arr(i,dom_lo.y+1,k);
130 Real dVde = dest_arr(i,dom_lo.y+1,k) - dest_arr(i,dom_lo.y+2,k);
131 if (dVdt*dVde < zero) dVdt = zero;
133 Real cff = std::max(dVdx*dVdx + dVde*dVde, eps);
134 Real Ce = dVdt * dVde;
135 dest_arr(i,j,k) = (cff * calc_arr(i,dom_lo.y,k) + Ce * dest_arr(i,dom_lo.y+1,k)) * mskv(i,j,0) / (cff + Ce);
136 }
137 });
139 grow(bx_ylo,IntVect(-1,0,0)) & dest_arr_box, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) {
140 int jflip = dom_lo.y-j;
141 int inner = (bc_ptr[n].lo(1) == REMORABCType::foextrap) ? 1 : 0;
142 if (bc_ptr[n].lo(1) == REMORABCType::ext_dir) {
144 } else if (bc_ptr[n].lo(1) == REMORABCType::foextrap || bc_ptr[n].lo(1) == REMORABCType::clamped ||
146 dest_arr(i,j,k) = dest_arr(i,dom_lo.y+inner,k)*mskv(i,j,0);
147 } else if (bc_ptr[n].lo(1) == REMORABCType::reflect_even) {
148 dest_arr(i,j,k) = dest_arr(i,jflip,k)*mskv(i,j,0);
149 } else if (bc_ptr[n].lo(1) == REMORABCType::reflect_odd) {
150 dest_arr(i,j,k) = -dest_arr(i,jflip,k)*mskv(i,j,0);
151 }
152 });
154 // We only set the values on the domain faces themselves if EXT_DIR or outflow
155 grow(bx_yhi_face,IntVect(-1,0,0)) & dest_arr_box, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) {
156 if (bc_ptr[n].hi(1) == REMORABCType::ext_dir) {
158 } else if (bc_ptr[n].hi(1) == REMORABCType::foextrap) {
159 dest_arr(i,j,k) = dest_arr(i,dom_hi.y,k)*mskv(i,j,0);
160 } else if (bc_ptr[n].hi(1) == REMORABCType::orlanski_rad) {
161 Real grad_hi = calc_arr(i ,dom_hi.y ,k) - calc_arr(i-1,dom_hi.y ,k);
162 Real grad_hi_ip1 = calc_arr(i+1,dom_hi.y ,k) - calc_arr(i ,dom_hi.y ,k);
163 Real dVdt = calc_arr(i,dom_hi.y,k) - dest_arr(i,dom_hi.y ,k);
164 Real dVde = dest_arr(i,dom_hi.y,k) - dest_arr(i,dom_hi.y-1,k);
165 if (dVdt*dVde < zero) dVdt = zero;
166 Real dVdx = (dVdt * (grad_hi + grad_hi_ip1) > zero) ? grad_hi : grad_hi_ip1;
167 Real cff = std::max(dVdx*dVdx + dVde*dVde, eps);
168 Real Ce = dVdt * dVde;
169 dest_arr(i,j,k) = (cff * calc_arr(i,dom_hi.y+1,k) + Ce * dest_arr(i,dom_hi.y,k)) * mskv(i,j,0) / (cff + Ce);
170 }
171 });
173 grow(bx_yhi,IntVect(-1,0,0)) & dest_arr_box, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) {
174 int jflip = 2*(dom_hi.y + 1) - j;
175 int inner = (bc_ptr[n].hi(1) == REMORABCType::foextrap) ? 1 : 0;
176 if (bc_ptr[n].hi(1) == REMORABCType::ext_dir) {
178 } else if (bc_ptr[n].hi(1) == REMORABCType::foextrap || bc_ptr[n].hi(1) == REMORABCType::clamped ||
180 dest_arr(i,j,k) = dest_arr(i,dom_hi.y+1-inner,k)*mskv(i,j,0);
181 } else if (bc_ptr[n].hi(1) == REMORABCType::reflect_even) {
182 dest_arr(i,j,k) = dest_arr(i,jflip,k)*mskv(i,j,0);
183 } else if (bc_ptr[n].hi(1) == REMORABCType::reflect_odd) {
184 dest_arr(i,j,k) = -dest_arr(i,jflip,k)*mskv(i,j,0);
185 }
186 });
187 }
188
189 {
190 // Populate ghost cells on lo-z and hi-z domain boundaries
191 Box bx_zlo(bx); bx_zlo.setBig (2,dom_lo.z-1);
192 Box bx_zhi(bx); bx_zhi.setSmall(2,dom_hi.z+1);
194 bx_zlo & dest_arr_box, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) {
195 int kflip = dom_lo.z - 1 - k;
196 if (bc_ptr[n].lo(2) == REMORABCType::ext_dir) {
198 } else if (bc_ptr[n].lo(2) == REMORABCType::foextrap) {
199 dest_arr(i,j,k) = dest_arr(i,j,dom_lo.z)*mskv(i,j,0);
200 } else if (bc_ptr[n].lo(2) == REMORABCType::reflect_even) {
201 dest_arr(i,j,k) = dest_arr(i,j,kflip)*mskv(i,j,0);
202 } else if (bc_ptr[n].lo(2) == REMORABCType::reflect_odd) {
203 dest_arr(i,j,k) = -dest_arr(i,j,kflip)*mskv(i,j,0);
204 }
205 },
206 bx_zhi & dest_arr_box, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) {
207 int kflip = 2*dom_hi.z + 1 - k;
208 if (bc_ptr[n].hi(2) == REMORABCType::ext_dir) {
210 } else if (bc_ptr[n].hi(2) == REMORABCType::foextrap) {
211 dest_arr(i,j,k) = dest_arr(i,j,dom_hi.z)*mskv(i,j,0);
212 } else if (bc_ptr[n].hi(2) == REMORABCType::reflect_even) {
213 dest_arr(i,j,k) = dest_arr(i,j,kflip)*mskv(i,j,0);
214 } else if (bc_ptr[n].hi(2) == REMORABCType::reflect_odd) {
215 dest_arr(i,j,k) = -dest_arr(i,j,kflip)*mskv(i,j,0);
216 }
217 }
218 );
219 }
220
223 Box xlo(bx); xlo.setBig (0,dom_lo.x-1);
224 Box xhi(bx); xhi.setSmall(0,dom_hi.x+1);
225 Box ylo(bx); ylo.setBig (1,dom_lo.y );
226 Box yhi(bx); yhi.setSmall(1,dom_hi.y+1);
227 Box xlo_ylo = xlo & ylo;
228 Box xlo_yhi = xlo & yhi;
229 Box xhi_ylo = xhi & ylo;
230 Box xhi_yhi = xhi & yhi;
235
236 if (!clamp_west && !clamp_south) {
237 ParallelFor(xlo_ylo & dest_arr_box, [=] AMREX_GPU_DEVICE (int i, int j, int k)
238 {
239 dest_arr(i,j,k) = Real(0.5) * (dest_arr(i,dom_lo.y+1,k) + dest_arr(dom_lo.x,j,k));
240 });
241 }
242 if (!clamp_west && !clamp_north) {
243 ParallelFor(xlo_yhi & dest_arr_box, [=] AMREX_GPU_DEVICE (int i, int j, int k)
244 {
245 dest_arr(i,j,k) = Real(0.5) * (dest_arr(i,dom_hi.y,k) + dest_arr(dom_lo.x,j,k));
246 });
247 }
248 if (!clamp_east && !clamp_south) {
249 ParallelFor(xhi_ylo & dest_arr_box, [=] AMREX_GPU_DEVICE (int i, int j, int k)
250 {
251 dest_arr(i,j,k) = Real(0.5) * (dest_arr(i,dom_lo.y+1,k) + dest_arr(dom_hi.x,j,k));
252 });
253 }
254 if (!clamp_east && !clamp_north) {
255 ParallelFor(xhi_yhi & dest_arr_box, [=] AMREX_GPU_DEVICE (int i, int j, int k)
256 {
257 dest_arr(i,j,k) = Real(0.5) * (dest_arr(i,dom_hi.y,k) + dest_arr(dom_hi.x,j,k));
258 });
259 }
260 }
261
262 Gpu::streamSynchronize();
263}
constexpr amrex::Real zero
mf_h setVal(geomdata.ProbHi(2))
amrex::Vector< amrex::BCRec > m_domain_bcs_type
amrex::Geometry m_geom
void impose_yvel_bcs(const amrex::Array4< amrex::Real > &dest_arr, const amrex::Box &bx, const amrex::Box &domain, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > dxInv, const amrex::Array4< const amrex::Real > &mskv, const amrex::Array4< const amrex::Real > &calc_arr, amrex::Real time, int bccomp)
apply y-velocity type boundary conditions
amrex::Gpu::DeviceVector< amrex::GpuArray< amrex::Real, AMREX_SPACEDIM *2 > > m_bc_extdir_vals_d
int foextrap_bc(int ncons) noexcept