REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_prestep_t_advection.cpp
Go to the documentation of this file.
1#include <REMORA.H>
2
3using namespace amrex;
4
5/**
6 * @param[in ] lev level to operate on
7 * @param[in ] tbx tile box
8 * @param[in ] gbx grown tile box
9 * @param[in ] tempold scalar at last time
10 * @param[in ] tempcache cached current time step's scalar value
11 * @param[in ] Hz vertical cell height
12 * @param[in ] Huon u-volume flux
13 * @param[in ] Hvom v-volume flux
14 * @param[in ] Akv vertical viscosity coefficient
15 * @param[inout] W vertical velocity
16 * @param DC temporary
17 * @param FC temporary
18 * @param[ out] tempstore scratch space for calculations on scalars
19 * @param[in ] z_w z coordinates at w points
20 * @param[in ] h bathymetry
21 * @param[in ] pm 1/dx
22 * @param[in ] pn 1/dy
23 * @param[in ] msku land-sea mask on u-points
24 * @param[in ] mskv land-sea mask on v-points
25 * @param[in ] river_pos river positions
26 * @param[in ] river_source river source data to add, if using
27 * @param[in ] iic which time step we're on
28 * @param[in ] ntfirst what is the first time step?
29 * @param[in ] nrhs index of RHS component
30 * @param[in ] N number of vertical levels
31 * @param[in ] dt_lev time step at this level
32 */
33
34void
35REMORA::prestep_t_advection (int lev, const Box& tbx, const Box& gbx,
38 const Array4<Real >& Hz,
39 const Array4<Real >& Huon,
40 const Array4<Real >& Hvom,
41 const Array4<Real >& W ,
42 const Array4<Real >& DC,
43 const Array4<Real >& FC ,
45 const Array4<Real const>& z_w,
46 const Array4<Real const>& h,
53 int iic, int ntfirst, int nrhs, int N,
54 Real dt_lev)
55{
56 BL_PROFILE("REMORA::prestep_t_advection()");
57 const Box& domain = geom[lev].Domain();
58 const auto dlo = amrex::lbound(domain);
59 const auto dhi = amrex::ubound(domain);
60
61 GeometryData const& geomdata = geom[0].data();
62 bool is_periodic_in_x = geomdata.isPeriodic(0);
63 bool is_periodic_in_y = geomdata.isPeriodic(1);
64
65 //copy the tilebox
66 Box gbx1 = tbx;
67 Box gbx2 = tbx;
68 Box tbxp1 = tbx;
69 Box tbxp2 = tbx;
70
71 tbxp1.grow(IntVect(NGROW-1,NGROW-1,0));
72 tbxp2.grow(IntVect(NGROW,NGROW,0));
73
74 int ncomp = 0;
75 int FX_comp = ncomp++;
76 int FE_comp = ncomp++;
77 int curv_comp = ncomp++;
78 int grad_comp = ncomp++;
79
80 FArrayBox fab(tbxp2,ncomp,amrex::The_Async_Arena());
82
83 auto FX=fab.array(FX_comp);
84 auto FE=fab.array(FE_comp);
85 auto curv=fab.array(curv_comp);
86 auto grad=fab.array(grad_comp);
87
88 Box ubx = surroundingNodes(tbx,0);
89 Box vbx = surroundingNodes(tbx,1);
90
93
94 Box gbx3uneven_init(IntVect(AMREX_D_DECL(tbx.smallEnd(0)-3,tbx.smallEnd(1)-3,tbx.smallEnd(2))),
95 IntVect(AMREX_D_DECL(tbx.bigEnd(0)+2,tbx.bigEnd(1)+2,tbx.bigEnd(2))));
96 BoxArray ba_gbx3uneven = intersect(BoxArray(gbx3uneven_init), gbx);
97 AMREX_ASSERT((ba_gbx3uneven.size() == 1));
99
100 gbx2.grow(IntVect(NGROW,NGROW,0));
101 BoxArray ba_gbx2 = intersect(BoxArray(gbx2), gbx);
102 AMREX_ASSERT((ba_gbx2.size() == 1));
103 gbx2 = ba_gbx2[0];
104
105 gbx1.grow(IntVect(NGROW-1,NGROW-1,0));
106 BoxArray ba_gbx1 = intersect(BoxArray(gbx1), gbx);
107 AMREX_ASSERT((ba_gbx1.size() == 1));
108 gbx1 = ba_gbx1[0];
109
110 //------------------------------------------------------------------------
111 // Vertically integrate horizontal mass flux divergence.
112 //------------------------------------------------------------------------
113 //
114 //Should really use gbx3uneven
116 gbx3unevenD.makeSlab(2,0);
117 Box gbx1D = gbx1;
118 gbx1D.makeSlab(2,0);
119
120 // We used to set W(i,j,0) = 0.0, but this should have already been set before passing into the function
122 [=] AMREX_GPU_DEVICE (int i, int j, int , int kk)
123 {
124 // Starting with zero vertical velocity at the bottom, integrate
125 // from the bottom (k=0) to the free-surface (k=N). The w(:,:,N(ng))
126 // contains the vertical velocity at the free-surface, d(zeta)/d(t).
127 // Notice that barotropic mass flux divergence is not used directly.
128 //
129 int k = kk + 1;
130 W(i,j,k) = W(i,j,k-1) - (Huon(i+1,j,k-1)-Huon(i,j,k-1)) - (Hvom(i,j+1,k-1)-Hvom(i,j,k-1));
131 });
132 ParallelFor(gbx1D, [=] AMREX_GPU_DEVICE (int i, int j, int )
133 {
134 W(i,j,N+1)=W(i,j,N+1)/(z_w(i,j,N+1)+h(i,j,0,0)); // wrk_i
135 });
137 [=] AMREX_GPU_DEVICE (int i, int j, int , int kk)
138 {
139 int k = kk + 1;
140 W(i,j,k) = W(i,j,k)- W(i,j,N+1)*(z_w(i,j,k)+h(i,j,0,0));
141 });
142 ParallelFor(gbx1D, [=] AMREX_GPU_DEVICE (int i, int j, int )
143 {
144 W(i,j,N+1) = Real(0.0);
145 });
146
147 //Use FC and DC as intermediate arrays for FX and FE
148 //First pass do centered 2d terms
149
150 ParallelFor(utbxp1, [=] AMREX_GPU_DEVICE (int i, int j, int k)
151 {
152 //should be t index 3
153 FX(i,j,k)=(tempold(i,j,k,nrhs)-tempold(i-1,j,k,nrhs)) * msku(i,j,0);
154 });
155
156 Box utbxp1_slab_lo = makeSlab(utbxp1,0,dlo.x-1) & utbxp1;
157 Box utbxp1_slab_hi = makeSlab(utbxp1,0,dhi.x+1) & utbxp1;
158 if (utbxp1_slab_lo.ok() && !is_periodic_in_x) {
159 ParallelFor(utbxp1_slab_lo, [=] AMREX_GPU_DEVICE (int i, int j, int k)
160 {
161 FX(i,j,k) = FX(i+1,j,k);
162 });
163 }
164 if (utbxp1_slab_hi.ok() && !is_periodic_in_x) {
165 ParallelFor(utbxp1_slab_hi, [=] AMREX_GPU_DEVICE (int i, int j, int k)
166 {
167 FX(i+1,j,k) = FX(i,j,k);
168 });
169 }
170
171 ParallelFor(vtbxp1, [=] AMREX_GPU_DEVICE (int i, int j, int k)
172 {
173 //should be t index 3
174 FE(i,j,k)=(tempold(i,j,k,nrhs)-tempold(i,j-1,k,nrhs)) * mskv(i,j,0);
175 });
176
177 Box vtbxp1_slab_lo = makeSlab(vtbxp1,1,dlo.y-1) & vtbxp1;
178 Box vtbxp1_slab_hi = makeSlab(vtbxp1,1,dhi.y+1) & vtbxp1;
179 if (vtbxp1_slab_lo.ok() && !is_periodic_in_y) {
180 ParallelFor(vtbxp1_slab_lo, [=] AMREX_GPU_DEVICE (int i, int j, int k)
181 {
182 FE(i,j,k) = FE(i,j+1,k);
183 });
184 }
185 if (vtbxp1_slab_hi.ok() && !is_periodic_in_y) {
186 ParallelFor(vtbxp1_slab_hi, [=] AMREX_GPU_DEVICE (int i, int j, int k)
187 {
188 FE(i,j+1,k) = FE(i,j,k);
189 });
190 }
191
192 Real cffa=one/Real(6.0);
193 Real cffb=one/Real(3.0);
195 {
196 ParallelFor(tbxp1, [=] AMREX_GPU_DEVICE (int i, int j, int k)
197 {
198 //Upstream3
199 curv(i,j,k)=-FX(i,j,k)+FX(i+1,j,k);
200 });
201
202 ParallelFor(tbxp1, [=] AMREX_GPU_DEVICE (int i, int j, int k)
203 {
204 Real max_Huon = std::max(Huon(i,j,k),Real(0.0));
205 Real min_Huon = std::min(Huon(i,j,k),Real(0.0));
206
207 FX(i,j,k)=Huon(i,j,k)*Real(0.5)*(tempold(i,j,k)+tempold(i-1,j,k))-
208 cffa*(curv(i,j,k)*min_Huon+ curv(i-1,j,k)*max_Huon);
209 });
210
212
213 ParallelFor(tbxp1, [=] AMREX_GPU_DEVICE (int i, int j, int k)
214 {
215 //Centered4
216 grad(i,j,k)=Real(0.5)*(FX(i,j,k)+FX(i+1,j,k));
217 });
218
219 ParallelFor(ubx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
220 {
221 FX(i,j,k)=Huon(i,j,k)*Real(0.5)*(tempold(i,j,k)+tempold(i-1,j,k)-
222 cffb*(grad(i,j,k)-grad(i-1,j,k)));
223 });
224 } else {
225 Error("Not a valid horizontal advection scheme");
226 }
227
229 {
230 ParallelFor(tbxp1, [=] AMREX_GPU_DEVICE (int i, int j, int k)
231 {
232 curv(i,j,k)=-FE(i,j,k)+FE(i,j+1,k);
233 });
234
235 ParallelFor(tbxp1, [=] AMREX_GPU_DEVICE (int i, int j, int k)
236 {
237 Real max_Hvom = std::max(Hvom(i,j,k),Real(0.0));
238 Real min_Hvom = std::min(Hvom(i,j,k),Real(0.0));
239
240 FE(i,j,k)=Hvom(i,j,k)*Real(0.5)*(tempold(i,j,k)+tempold(i,j-1,k))-
241 cffa*(curv(i,j,k)*min_Hvom+ curv(i,j-1,k)*max_Hvom);
242 });
243
245
246 ParallelFor(tbxp1, [=] AMREX_GPU_DEVICE (int i, int j, int k)
247 {
248 grad(i,j,k)=Real(0.5)*(FE(i,j,k)+FE(i,j+1,k));
249 });
250
251 ParallelFor(vbx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
252 {
253 FE(i,j,k)=Hvom(i,j,k)*Real(0.5)*(tempold(i,j,k)+tempold(i,j-1,k)-
254 cffb*(grad(i,j,k)- grad(i,j-1,k)));
255 });
256 } else {
257 Error("Not a valid horizontal advection scheme");
258 }
259
260 bool do_rivers_cons = (river_source.size() > 0);
263 ParallelFor(tbxp1, [=] AMREX_GPU_DEVICE (int i, int j, int k)
264 {
265 int iriver = river_pos(i,j,0);
266 if (iriver >= 0) {
267 if (river_direction_d[iriver] == 0) {
268 FX(i,j,k) = (!do_rivers_cons) ? Real(0.0) : Huon(i,j,k) * river_source(iriver,0,k);
269 } else {
270 FE(i,j,k) = (!do_rivers_cons) ? Real(0.0) : Hvom(i,j,k) * river_source(iriver,0,k);
271 }
272 }
273 });
274 }
275
276 //Intermediate tracer at 3
277 //
278 // Time-step horizontal advection (m Tunits).
279 //
280 Real cff1 = zero, cff2 = zero, cff;
281
282 Real GammaT = one/Real(6.0);
283
284 if (iic==ntfirst)
285 {
286 cff=Real(0.5)*dt_lev;
287 cff1=one;
288 cff2=zero;
289 } else {
291 cff1=Real(0.5)+GammaT;
292 cff2=Real(0.5)-GammaT;
293 }
294
295 ParallelFor(tbx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
296 {
297 tempstore(i,j,k)=Hz(i,j,k)*( cff1 * tempold(i,j,k)+
298 cff2 * tempcache(i,j,k) )-
299 cff * pm(i,j,0)*pn(i,j,0) * (FX(i+1,j,k)-FX(i,j,k)+
300 FE(i,j+1,k)-FE(i,j,k));
301 });
302
303 Real c1=Real(0.5);
304 Real c2=Real(7.0)/Real(12.0);
305 Real c3=one/Real(12.0);
306
307 //
308 // Time-step vertical advection of tracers (Tunits). Impose artificial
309 // continuity equation.
310 //
311 ParallelFor(growHi(growLo(convert(tbx,IntVect(0,0,1)),2,-2),2,-1), [=] AMREX_GPU_DEVICE (int i, int j, int k)
312 {
313 //-----------------------------------------------------------------------
314 // Add in vertical advection.
315 //-----------------------------------------------------------------------
316
317 FC(i,j,k)=( c2*(tempold(i ,j,k-1,nrhs)+ tempold(i,j,k ,nrhs))
318 -c3*(tempold(i ,j,k-2 ,nrhs)+ tempold(i,j,k+1,nrhs)) )*
319 ( W(i,j,k));
320 });
321 ParallelFor(makeSlab(tbx,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int )
322 {
323 FC(i,j,N+1)=Real(0.0);
324 FC(i,j,N) = ( c2*tempold(i,j,N-1,nrhs)+ c1*tempold(i,j,N,nrhs)-c3*tempold(i,j,N-2,nrhs) )
325 * W(i,j,N);
326 FC(i,j, 1) = ( c2*tempold(i,j, 1,nrhs)+ c1*tempold(i,j,0,nrhs)-c3*tempold(i,j,2,nrhs) )
327 * W(i,j,1);
328 FC(i,j, 0) = Real(0.0);
329 });
330
331 ParallelFor(tbxp1, [=] AMREX_GPU_DEVICE (int i, int j, int k)
332 {
333 DC(i,j,k)=one/(Hz(i,j,k)-
334 cff*pm(i,j,0)*pn(i,j,0)*
335 (Huon(i+1,j,k)-Huon(i,j,k)+
336 Hvom(i,j+1,k)-Hvom(i,j,k)+
337 (W(i,j,k+1)-W(i,j,k))));
338 });
339
341 [=] AMREX_GPU_DEVICE (int i, int j, int k)
342 {
343 Real c_p = cff*pm(i,j,0)*pn(i,j,0);
344
345 Real c4 = FC(i,j,k+1)-FC(i,j,k);
346
347 tempstore(i,j,k) = DC(i,j,k)*(tempstore(i,j,k)-c_p*c4);
348 });
349}
constexpr amrex::Real one
constexpr amrex::Real zero
#define NGROW
mf_h setVal(geomdata.ProbHi(2))
static SolverChoice solverChoice
Container for algorithmic choices.
Definition REMORA.H:1717
amrex::Gpu::DeviceVector< int > river_direction
Vector over rivers of river direction: 0: u-face; 1: v-face; 2: w-face.
Definition REMORA.H:1496
void prestep_t_advection(int lev, const amrex::Box &tbx, const amrex::Box &gbx, const amrex::Array4< amrex::Real > &tempold, const amrex::Array4< amrex::Real > &tempcache, const amrex::Array4< amrex::Real > &Hz, const amrex::Array4< amrex::Real > &Huon, const amrex::Array4< amrex::Real > &Hvom, const amrex::Array4< amrex::Real > &W, const amrex::Array4< amrex::Real > &DC, const amrex::Array4< amrex::Real > &FC, const amrex::Array4< amrex::Real > &sstore, const amrex::Array4< amrex::Real const > &z_w, const amrex::Array4< amrex::Real const > &h, const amrex::Array4< amrex::Real const > &pm, const amrex::Array4< amrex::Real const > &pn, const amrex::Array4< amrex::Real const > &msku, const amrex::Array4< amrex::Real const > &mskv, const amrex::Array4< int const > &river_pos, const amrex::Array4< amrex::Real const > &river_source, int iic, int ntfirst, int nrhs, int N, const amrex::Real dt_lev)
Prestep advection calculations for the tracers.
AdvectionScheme tracer_Hadv_scheme