REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_FillPatch.cpp
Go to the documentation of this file.
1#include <REMORA.H>
5
6using namespace amrex;
7
9
10/**
11 * Fill valid and ghost data in the MultiFab "mf"
12 * This version fills the MultiFab mf_to_fill in valid regions with
13 * the "state data" at the given time;
14 * values in mf when it is passed in are *not* used.
15 *
16 * @param[in ] lev level to FillPatch on
17 * @param[in ] time current time
18 * @param[inout] mf_to_fill MultiFab to fill
19 * @param[in ] mfs vector over levels of multifabs associated with mf_to_fill
20 * @param[in ] bccomp index into domain_bcs_type
21 * @param[in ] bdy_var_type when filling from NetCDF, which boundary data
22 * @param[in ] icomp component to fill
23 * @param[in ] fill_all whether to fill all components
24 * @param[in ] fill_set whether to use FillPatchers
25 * @param[in ] icomp_calc component to use in RHS boundary calculation
26 * @param[in ] dt_lev time step at this level
27 * @param[in ] mf_calc data to use in RHS boundary calculation
28 */
29void
31 const int bccomp,
33 const int bdy_var_type,
34#else
35 const int /*bdy_var_type*/,
36#endif
37 const int icomp,
38 const bool fill_all,
39 const bool fill_set,
40 const int n_not_fill,
42 const int icomp_calc,
43 const Real dt_lev,
44#else
45 const int /*icomp_calc*/,
46 const Real /*dt_lev*/,
47#endif
48 const MultiFab& mf_calc,
51{
52 BL_PROFILE_VAR("REMORA::FillPatch()",REMORA_FillPatch);
53 amrex::Interpolater* mapper = nullptr;
54
55 Box mf_box(mf_to_fill.boxArray()[0]);
56 bool is_2d = mf_box.length(2) == 1;
57
58 MultiFab* mask;
59
60 //
61 // ***************************************************************************
62 // The first thing we do is interpolate the momenta on the "valid" faces of
63 // the fine grids (where the interface is coarse/fine not fine/fine) -- this
64 // will not be over-written below because the FillPatch operators see these as
65 // valid faces.
66 // ***************************************************************************
67 if (lev>0 && fill_set) {
68 if (cf_set_width > 0 &&
69 mf_box.ixType() == IndexType(IntVect(0,0,0))) {
71 } else if (cf_set_width >= 0) {
72 if (!is_2d) {
73 if (mf_box.ixType() == IndexType(IntVect(1,0,0))) {
75 } else if (mf_box.ixType() == IndexType(IntVect(0,1,0))) {
77 } else if (mf_box.ixType() == IndexType(IntVect(0,0,1))) {
79 }
80 } else {
81 if (mf_box.ixType() == IndexType(IntVect(1,0,0))) {
83 } else if (mf_box.ixType() == IndexType(IntVect(0,1,0))) {
85 }
86 }
87 }
88 }
89
90 int ncomp;
91 if (fill_all) {
92 ncomp = mf_to_fill.nComp();
93 } else {
94 ncomp = 1;
95 }
96
97 if (mf_box.ixType() == IndexType(IntVect(0,0,0)))
98 {
100 mask = vec_mskr[lev].get();
101 }
102 else if (mf_box.ixType() == IndexType(IntVect(1,0,0)))
103 {
105 mask = vec_msku[lev].get();
106 }
107 else if (mf_box.ixType() == IndexType(IntVect(0,1,0)))
108 {
110 mask = vec_mskv[lev].get();
111 }
112 else {
114 mask = vec_mskr[lev].get();
115 }
116
117 if (lev == 0)
118 {
121 amrex::FillPatchSingleLevel(mf_to_fill, time, fmf, ftime, icomp, icomp, ncomp,
123 }
124 else
125 {
128 // A subcycled fine level asks for times inside the parent's step, so the coarse
129 // contribution has to be interpolated. Passing one MultiFab twice makes
130 // FillPatchTwoLevels return it whatever the time: fine in lockstep, wrong for
131 // subcycling.
132 Vector<MultiFab*> cmf = {mfs[lev-1], mfs[lev-1]};
134 if (do_substep && int(mfs_crse_old.size()) >= lev && int(mfs_crse_new.size()) >= lev) {
136 ctime = {t_old[lev-1], t_new[lev-1]};
137 mfs_crse_old[lev-1]->FillBoundary(geom[lev-1].periodicity());
138 mfs_crse_new[lev-1]->FillBoundary(geom[lev-1].periodicity());
139 }
140
141 mfs[lev-1]->FillBoundary(geom[lev-1].periodicity());
142 amrex::FillPatchTwoLevels(mf_to_fill, mf_to_fill.nGrowVect(), IntVect(0,0,0),
143 time, cmf, ctime, fmf, ftime,
144 icomp, icomp, ncomp, geom[lev-1], geom[lev],
145 //null_bc, bccomp, null_bc, bccomp,
146 refRatio(lev-1),
148 } // lev > 0
149
150 // This is currently unconditionally true, but do_bc flag should actually be passed in
151 const bool do_bc=true;
152 if (do_bc) {
153 // ***************************************************************************
154 // Physical bc's at domain boundary
155 // ***************************************************************************
156
157 // Enforce physical boundary conditions
159 *vec_msku[lev].get(), *vec_mskv[lev].get());
160
161#ifdef REMORA_USE_NETCDF
162 // Fill the data which is stored in the boundary data read from netcdf files
164 {
166 }
167#endif
168 // Fill corners of the domain with periodic data
169 if ( mf_box.ixType() == IndexType(IntVect(0,0,0)) ) {
170 mf_to_fill.EnforcePeriodicity(geom[lev].periodicity());
171 }
172
173 // Also enforce free-slip at top boundary (on xvel or yvel)
174 if ( (mf_box.ixType() == IndexType(IntVect(1,0,0))) ||
175 (mf_box.ixType() == IndexType(IntVect(0,1,0))) )
176 {
177 int khi = geom[lev].Domain().bigEnd(2);
178 for (MFIter mfi(mf_to_fill); mfi.isValid(); ++mfi)
179 {
180 Box gbx = mfi.growntilebox(); // Note this is face-centered since vel is
181 gbx.setSmall(2,khi+1);
182 if (gbx.ok()) {
184 ParallelFor(gbx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
185 {
186 vel_arr(i,j,k) = vel_arr(i,j,khi);
187 });
188 }
189 }
190 }
191 }
192}
193
194/**
195 * Fill valid and ghost data in the MultiFab "mf"
196 * This version fills the MultiFab mf_to_fill in valid regions with
197 * the "state data" at the given time;
198 * values in mf when it is passed in are *not* used.
199 * Unlike FillPatch, FillPatchNoBC does not apply boundary conditions
200 *
201 * @param[in ] lev level to FillPatch on
202 * @param[in ] time current time
203 * @param[inout] mf_to_fill MultiFab to fill
204 * @param[in ] mfs vector over levels of multifabs associated with mf_to_fill
205 * @param[in ] bdy_var_type when filling from NetCDF, which boundary data
206 * @param[in ] icomp component to fill
207 * @param[in ] fill_all whether to fill all components
208 * @param[in ] fill_set whether to use FillPatchers
209 */
210void
213 const int /*bdy_var_type*/,
214#else
215 const int /*bdy_var_type*/,
216#endif
217 const int icomp,
218 const bool fill_all,
219 const bool fill_set,
222{
223 // HACK: Note that this is hacky; should be able to have a single call to FillPatch with a
224 // flag for bcs, but for some reason it was acting weird, so we're splitting this out into
225 // two functions with repeated code for the time being
226 BL_PROFILE_VAR("REMORA::FillPatchNoBC()",REMORA_FillPatch);
227 int bccomp;
228 amrex::Interpolater* mapper = nullptr;
229
230 Box mf_box(mf_to_fill.boxArray()[0]);
231 bool is_2d = mf_box.length(2) == 1;
232
233 //
234 // ***************************************************************************
235 // The first thing we do is interpolate the momenta on the "valid" faces of
236 // the fine grids (where the interface is coarse/fine not fine/fine) -- this
237 // will not be over-written below because the FillPatch operators see these as
238 // valid faces.
239 // ***************************************************************************
240 if (lev>0 && fill_set) {
241 if (cf_set_width > 0 &&
242 mf_box.ixType() == IndexType(IntVect(0,0,0))) {
244 } else if (cf_set_width >= 0) {
245 if (!is_2d) {
246 if (mf_box.ixType() == IndexType(IntVect(1,0,0))) {
248 } else if (mf_box.ixType() == IndexType(IntVect(0,1,0))) {
250 } else if (mf_box.ixType() == IndexType(IntVect(0,0,1))) {
252 }
253 } else {
254 if (mf_box.ixType() == IndexType(IntVect(1,0,0))) {
256 } else if (mf_box.ixType() == IndexType(IntVect(0,1,0))) {
258 }
259 }
260 }
261 }
262
263 int ncomp;
264 if (fill_all) {
265 ncomp = mf_to_fill.nComp();
266 } else {
267 ncomp = 1;
268 }
269
270 if (mf_box.ixType() == IndexType(IntVect(0,0,0)))
271 {
272 bccomp = 0;
274 }
275 else if (mf_box.ixType() == IndexType(IntVect(1,0,0)))
276 {
277 bccomp = xvel_bc();
279 }
280 else if (mf_box.ixType() == IndexType(IntVect(0,1,0)))
281 {
282 bccomp = yvel_bc();
284 }
285 else {
286 bccomp = zvel_bc();
288 }
289
290 if (lev == 0)
291 {
294 amrex::FillPatchSingleLevel(mf_to_fill, time, fmf, ftime, icomp, icomp, ncomp,
296 }
297 else
298 {
301 // A subcycled fine level asks for times inside the parent's step, so the coarse
302 // contribution has to be interpolated. Passing one MultiFab twice makes
303 // FillPatchTwoLevels return it whatever the time: fine in lockstep, wrong for
304 // subcycling.
305 Vector<MultiFab*> cmf = {mfs[lev-1], mfs[lev-1]};
307 if (do_substep && int(mfs_crse_old.size()) >= lev && int(mfs_crse_new.size()) >= lev) {
309 ctime = {t_old[lev-1], t_new[lev-1]};
310 mfs_crse_old[lev-1]->FillBoundary(geom[lev-1].periodicity());
311 mfs_crse_new[lev-1]->FillBoundary(geom[lev-1].periodicity());
312 }
313
314 mfs[lev-1]->FillBoundary(geom[lev-1].periodicity());
315 amrex::FillPatchTwoLevels(mf_to_fill, mf_to_fill.nGrowVect(), IntVect(0,0,0),
316 time, cmf, ctime, fmf, ftime,
317 icomp, icomp, ncomp, geom[lev-1], geom[lev],
318 //null_bc, bccomp, null_bc, bccomp,
319 refRatio(lev-1),
321 } // lev > 0
322}
323
324
325// utility to copy in data from old/new data into a struct that holds data for FillPatching
327REMORA::GetDataAtTime (int /*lev*/, Real /*time*/)
328{
329 BL_PROFILE_VAR("GetDataAtTime()",GetDataAtTime);
331
332// HACK HACK HACK
333#if 0
334 const Real teps = (t_new[lev] - t_old[lev]) * 1.e-3_rt;
335
336 if (time > t_new[lev] - teps && time < t_new[lev] + teps)
337 {
338 for (int i = 0; i < Vars::NumTypes; ++i) {
339 data.add_var(&vars_new[lev][i], data.non_owning);
340 }
341 data.set_time(t_new[lev]);
342 }
343 else if (time > t_old[lev] - teps && time < t_old[lev] + teps)
344 {
345 for (int i = 0; i < Vars::NumTypes; ++i) {
346 data.add_var(&vars_old[lev][i], data.non_owning);
347 }
348 data.set_time(t_old[lev]);
349 }
350 else if (time > t_old[lev] && time < t_new[lev])
351 {
352 // do first order interpolation in time between [t_old[lev], t_new[lev]]
353 // time interpolation includes the ghost cells
354 for (int i = 0; i < Vars::NumTypes; ++i) {
355 MultiFab* mf_tmp = new MultiFab(vars_new[lev][i].boxArray(),
358 mf_tmp->setVal(0.0_rt);
359
360 const Real dt_fraction = (time - t_old[lev]) / (t_new[lev] - t_old[lev]);
361 MultiFab::Saxpy(*mf_tmp, 1.0_rt - dt_fraction, vars_old[lev][i], 0, 0, mf_tmp->nComp(), mf_tmp->nGrowVect());
362 MultiFab::Saxpy(*mf_tmp, dt_fraction, vars_new[lev][i], 0, 0, mf_tmp->nComp(), mf_tmp->nGrowVect());
363
364 data.add_var(mf_tmp, data.owning);
365 }
366 data.set_time(time);
367 }
368 else
369 {
370 amrex::Error("Requested data at a time outside the interval [t_old, t_new]");
371 }
372
373 // We need to make sure to fill these before we compute the viscosity
374 for (int i = 0; i < Vars::NumTypes; ++i) {
375 data.get_var(Vars::xvel).FillBoundary(geom[lev].periodicity());
376 data.get_var(Vars::yvel).FillBoundary(geom[lev].periodicity());
377 data.get_var(Vars::zvel).FillBoundary(geom[lev].periodicity());
378 data.get_var(Vars::cons).FillBoundary(geom[lev].periodicity());
379 }
380#endif
381 return data;
382}
383
384
385/**
386 * Like FillCoarsePatch but uses piecewise constant interpolater
387 *
388 * @param[in ] lev level to FillPatch on
389 * @param[in ] time current time
390 * @param[inout] mf_to_fill MultiFab to fill
391 * @param[inout] mf_crse MultiFab of coarse data
392 * @param[in ] bccomp index into domain_bcs_type
393 * @param[in ] bdy_var_type when filling from NetCDF, which boundary data
394 * @param[in ] icomp component to fill
395 * @param[in ] fill_all whether to fill all components
396 * @param[in ] icomp_calc component to use in RHS boundary calculation
397 * @param[in ] dt_lev time step at this level
398 * @param[in ] mf_calc data to use in RHS boundary calculation
399 */
400void
402 MultiFab* mf_crse,
403 const int bccomp,
404 const int bdy_var_type,
405 const int icomp,
406 const bool fill_all,
407 const int n_not_fill,
408 const int icomp_calc,
409 const Real dt_lev,
410 const MultiFab& mf_calc) {
411 amrex::Interpolater* mapper = &pc_interp;
414}
415
416/**
417 * Fill an entire multifab by interpolating from the coarser level --
418 * this is used only when a new level of refinement is being created
419 * during a run (i.e not at initialization)
420 * This will never be used with static refinement.
421 *
422 * @param[in ] lev level to FillPatch on
423 * @param[in ] time current time
424 * @param[inout] mf_to_fill MultiFab to fill
425 * @param[inout] mf_crse MultiFab of coarse data
426 * @param[in ] bccomp index into domain_bcs_type
427 * @param[in ] bdy_var_type when filling from NetCDF, which boundary data
428 * @param[in ] icomp component to fill
429 * @param[in ] fill_all whether to fill all components
430 * @param[in ] icomp_calc component to use in RHS boundary calculation
431 * @param[in ] dt_lev time step at this level
432 * @param[in ] mf_calc data to use in RHS boundary calculation
433 */
434void
436 MultiFab* mf_crse,
437 const int bccomp,
438 const int bdy_var_type,
439 const int icomp,
440 const bool fill_all,
441 const int n_not_fill,
442 const int icomp_calc,
443 const Real dt_lev,
444 const MultiFab& mf_calc) {
445 amrex::Interpolater* mapper = nullptr;
448}
449
450/**
451 * Fill an entire multifab by interpolating from the coarser level --
452 * this is used only when a new level of refinement is being created
453 * during a run (i.e not at initialization)
454 * This will never be used with static refinement.
455 *
456 * @param[in ] lev level to FillPatch on
457 * @param[in ] time current time
458 * @param[inout] mf_to_fill MultiFab to fill
459 * @param[inout] mf_crse MultiFab of coarse data
460 * @param[in ] bccomp index into domain_bcs_type
461 * @param[in ] bdy_var_type when filling from NetCDF, which boundary data
462 * @param[in ] icomp component to fill
463 * @param[in ] fill_all whether to fill all components
464 * @param[in ] icomp_calc component to use in RHS boundary calculation
465 * @param[in ] dt_lev time step at this level
466 * @param[in ] mf_calc data to use in RHS boundary calculation
467 */
468void
469REMORA::FillCoarsePatchMap (int lev, Real time, MultiFab* mf_to_fill, MultiFab* mf_crse,
470 const int bccomp,
472 const int bdy_var_type,
473#else
474 const int /*bdy_var_type*/,
475#endif
476 const int icomp,
477 const bool fill_all,
478 const int n_not_fill,
480 const int icomp_calc,
481 const Real dt_lev,
482#else
483 const int /*icomp_calc*/,
484 const Real /*dt_lev*/,
485#endif
486 const MultiFab& mf_calc,
487 amrex::Interpolater* mapper)
488{
489 BL_PROFILE_VAR("FillCoarsePatch()",FillCoarsePatch);
490 AMREX_ASSERT(lev > 0);
491
492 MultiFab* mask = nullptr;
493
494 int ncomp;
495 if (fill_all) {
496 ncomp = mf_to_fill->nComp();
497 } else {
498 ncomp = 1;
499 }
500
501 Box box_mf(mf_to_fill->boxArray()[0]);
502
503 if (box_mf.ixType() == IndexType(IntVect(0,0,0)))
504 {
505 mask = vec_mskr[lev].get();
506 }
507 else if (box_mf.ixType() == IndexType(IntVect(1,0,0)))
508 {
509 mask = vec_msku[lev].get();
510 }
511 else if (box_mf.ixType() == IndexType(IntVect(0,1,0)))
512 {
513 mask = vec_mskv[lev].get();
514 }
515 else if (box_mf.ixType() == IndexType(IntVect(0,0,1)))
516 {
517 mask = vec_mskr[lev].get();
518 } else {
519 amrex::Abort("Dont recognize this box type in REMORA_FillPatch");
520 }
521
522 if (mapper == nullptr) {
523 if (box_mf.ixType() == IndexType(IntVect(0,0,0)))
524 {
526 }
527 else if (box_mf.ixType() == IndexType(IntVect(1,0,0)))
528 {
530 }
531 else if (box_mf.ixType() == IndexType(IntVect(0,1,0)))
532 {
534 }
535 else if (box_mf.ixType() == IndexType(IntVect(0,0,1)))
536 {
538 } else {
539 amrex::Abort("Dont recognize this box type in REMORA_FillPatch");
540 }
541 }
542
543 mf_crse->FillBoundary(geom[lev-1].periodicity());
544 amrex::InterpFromCoarseLevel(*mf_to_fill, mf_to_fill->nGrowVect(), IntVect(0,0,0),
545 *mf_crse, 0, icomp, ncomp, geom[lev-1], geom[lev],
546 refRatio(lev-1),
548
549 // ***************************************************************************
550 // Physical bc's at domain boundary
551 // ***************************************************************************
552
553 // Enforce physical boundary conditions
554 (*physbcs[lev])(*mf_to_fill,*mask,icomp,ncomp,mf_to_fill->nGrowVect(),
556 *vec_msku[lev].get(), *vec_mskv[lev].get());
557
558#ifdef REMORA_USE_NETCDF
559 // Fill the data which is stored in the boundary data read from netcdf files
561 {
563 }
564#endif
565 // Fill corners of the domain with periodic data
566 if ( box_mf.ixType() == IndexType(IntVect(0,0,0)) ) {
567 mf_to_fill->EnforcePeriodicity(geom[lev].periodicity());
568 } else {
569 // The face-centred analogue. InterpFromCoarseLevel fills a periodic ghost from the
570 // coarse level, which for a face tangential to the periodic direction does not
571 // reproduce the fine value it wraps to: on a new level of Channel_Test, vbar's x
572 // ghosts at the seam differed from their images by 2e-4 to 6e-4 where zeta's,
573 // corrected above, were exact. The first barotropic substep then sees different vbar
574 // at the two copies of the periodic u-face, and that one-shot asymmetry amplifies into
575 // a blow-up. Copying the ghosts from this level's own valid data, as every later
576 // FillPatch does, removes it.
577 mf_to_fill->FillBoundary(geom[lev].periodicity());
578 }
579
580 // Enforce free-slip at top boundary (on xvel or yvel)
581 if ( (box_mf.ixType() == IndexType(IntVect(1,0,0))) ||
582 (box_mf.ixType() == IndexType(IntVect(0,1,0))) )
583 {
584 int khi = geom[lev].Domain().bigEnd(2);
585 for (MFIter mfi(*mf_to_fill); mfi.isValid(); ++mfi)
586 {
587 Box gbx = mfi.growntilebox(); // Note this is face-centered since vel is
588 gbx.setSmall(2,khi+1);
589 if (gbx.ok()) {
591 ParallelFor(gbx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
592 {
593 vel_arr(i,j,k) = vel_arr(i,j,khi);
594 });
595 }
596 }
597 }
598
599}
600
601namespace {
602/**
603 * Sign for reflecting one cell-centered velocity component into a ghost cell.
604 * The normal velocity vanishes at a wall or symmetry plane; only a no-slip wall
605 * zeroes the tangential ones too. Anything else copies the adjacent valid cell.
606 *
607 * @param[in ] bc physical BC type for that component on that face
608 * @param[in ] is_normal whether the component is normal to the face
609 */
610Real
612{
613 if (is_normal) {
614 return ( (bc == REMORA_BC::slip_wall ) ||
616 (bc == REMORA_BC::symmetry ) ) ? -one : one;
617 }
618 return (bc == REMORA_BC::no_slip_wall) ? -one : one;
619}
620} // namespace
621
622/**
623 * Fill boundary ghost cells for cell-centered velocities. Each component takes
624 * the sign implied by its own BC, which with remora.boundary_per_variable can
625 * differ between u, v and w on one face.
626 *
627 * @param[in ] lev level to fill at
628 * @param[inout] mf_cc_vel MultiFab of cell-centered velocities
629 */
630void
632{
633 // Impose bc's at domain boundaries
634 Box domain(Geom(lev).Domain());
635
636 int ihi = domain.bigEnd(0);
637 int jhi = domain.bigEnd(1);
638 int khi = domain.bigEnd(2);
639
640 // Impose periodicity first
641 mf_cc_vel.FillBoundary(geom[lev].periodicity());
642
643 // Sign multipliers per face, per velocity component
645 for (OrientationIter oit; oit; ++oit) {
646 Orientation ori = oit();
647 for (int n = 0; n < AMREX_SPACEDIM; ++n) {
649 n == ori.coordDir());
650 }
651 }
652
653 // Callers pass different ghost widths (the plotfile ones carry none in z)
654 const IntVect ng = mf_cc_vel.nGrowVect();
655
656#ifdef _OPENMP
657#pragma omp parallel if (Gpu::notInLaunchRegion())
658#endif
659 for (MFIter mfi(mf_cc_vel, TilingIfNotGPU()); mfi.isValid(); ++mfi)
660 {
661 // Note that we don't fill corners here -- only the cells that share a face
662 // with interior cells -- this is all that is needed to calculate vorticity
663 const Box& bx = mfi.tilebox();
664 const Array4<Real>& vel_arr = mf_cc_vel.array(mfi);
665
666 if (!Geom(lev).isPeriodic(0) && ng[0] > 0) {
667 // Low-x side
668 if (bx.smallEnd(0) <= domain.smallEnd(0)) {
669 auto const m = mult[Orientation(Direction::x,Orientation::low)];
670 ParallelFor(makeSlab(bx,0,0), [=] AMREX_GPU_DEVICE(int , int j, int k) noexcept
671 {
672 vel_arr(-1,j,k,0) = m[0]*vel_arr(0,j,k,0); // u
673 vel_arr(-1,j,k,1) = m[1]*vel_arr(0,j,k,1); // v
674 vel_arr(-1,j,k,2) = m[2]*vel_arr(0,j,k,2); // w
675 });
676 }
677
678 // High-x side
679 if (bx.bigEnd(0) >= domain.bigEnd(0)) {
680 auto const m = mult[Orientation(Direction::x,Orientation::high)];
681 ParallelFor(makeSlab(bx,0,0), [=] AMREX_GPU_DEVICE(int , int j, int k) noexcept
682 {
683 vel_arr(ihi+1,j,k,0) = m[0]*vel_arr(ihi,j,k,0); // u
684 vel_arr(ihi+1,j,k,1) = m[1]*vel_arr(ihi,j,k,1); // v
685 vel_arr(ihi+1,j,k,2) = m[2]*vel_arr(ihi,j,k,2); // w
686 });
687 }
688 } // !periodic
689
690 if (!Geom(lev).isPeriodic(1) && ng[1] > 0) {
691 // Low-y side
692 if (bx.smallEnd(1) <= domain.smallEnd(1)) {
693 auto const m = mult[Orientation(Direction::y,Orientation::low)];
694 ParallelFor(makeSlab(bx,1,0), [=] AMREX_GPU_DEVICE(int i, int , int k) noexcept
695 {
696 vel_arr(i,-1,k,0) = m[0]*vel_arr(i,0,k,0); // u
697 vel_arr(i,-1,k,1) = m[1]*vel_arr(i,0,k,1); // v
698 vel_arr(i,-1,k,2) = m[2]*vel_arr(i,0,k,2); // w
699 });
700 }
701
702 // High-y side
703 if (bx.bigEnd(1) >= domain.bigEnd(1)) {
704 auto const m = mult[Orientation(Direction::y,Orientation::high)];
705 ParallelFor(makeSlab(bx,1,0), [=] AMREX_GPU_DEVICE(int i, int , int k) noexcept
706 {
707 vel_arr(i,jhi+1,k,0) = m[0]*vel_arr(i,jhi,k,0); // u
708 vel_arr(i,jhi+1,k,1) = m[1]*vel_arr(i,jhi,k,1); // v
709 vel_arr(i,jhi+1,k,2) = m[2]*vel_arr(i,jhi,k,2); // w
710 });
711 }
712 } // !periodic
713
714 if (!Geom(lev).isPeriodic(2) && ng[2] > 0) {
715 // Low-z side
716 if (bx.smallEnd(2) <= domain.smallEnd(2)) {
717 auto const m = mult[Orientation(Direction::z,Orientation::low)];
718 ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE(int i, int j, int) noexcept
719 {
720 vel_arr(i,j,-1,0) = m[0]*vel_arr(i,j,0,0); // u
721 vel_arr(i,j,-1,1) = m[1]*vel_arr(i,j,0,1); // v
722 vel_arr(i,j,-1,2) = m[2]*vel_arr(i,j,0,2); // w
723 });
724 }
725
726 // High-z side
727 if (bx.bigEnd(2) >= domain.bigEnd(2)) {
728 auto const m = mult[Orientation(Direction::z,Orientation::high)];
729 ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE(int i, int j, int) noexcept
730 {
731 vel_arr(i,j,khi+1,0) = m[0]*vel_arr(i,j,khi,0); // u
732 vel_arr(i,j,khi+1,1) = m[1]*vel_arr(i,j,khi,1); // v
733 vel_arr(i,j,khi+1,2) = m[2]*vel_arr(i,j,khi,2); // w
734 });
735 }
736 } // !periodic
737 } // MFIter
738}
constexpr amrex::Real one
PhysBCFunctNoOp null_bc
mf_h setVal(geomdata.ProbHi(2))
int zvel_bc() const noexcept
Definition REMORA.H:1450
int xvel_bc() const noexcept
Definition REMORA.H:1448
amrex::Vector< amrex::BCRec > domain_bcs_type
vector (over BCVars) of BCRecs
Definition REMORA.H:1728
void FillCoarsePatchMap(int lev, amrex::Real time, amrex::MultiFab *mf_fine, amrex::MultiFab *mf_crse, const int bccomp, const int bdy_var_type=BdyVars::null, const int icomp=0, const bool fill_all=true, const int n_not_fill=0, const int icomp_calc=0, const amrex::Real dt=zero, const amrex::MultiFab &mf_calc=amrex::MultiFab(), amrex::Interpolater *mapper=nullptr)
fill an entire multifab by interpolating from the coarser level, explicitly specifying interpolator t...
amrex::Vector< REMORAFillPatcher > FPr_v
Vector over levels of FillPatchers for v (3D)
Definition REMORA.H:1646
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskr
land/sea mask at cell centers (2D)
Definition REMORA.H:584
int do_substep
Whether to substep fine levels in time.
Definition REMORA.H:1831
int yvel_bc() const noexcept
Definition REMORA.H:1449
void fill_from_bdyfiles(int lev, amrex::MultiFab &mf_to_fill, const amrex::MultiFab &mf_mask, const amrex::Real time, const int bccomp, const int bdy_var_type, const int icomp_to_fill, const int icomp_calc=0, const amrex::MultiFab &mf_calc=amrex::MultiFab(), const amrex::Real=zero)
Fill boundary data from netcdf file.
amrex::Vector< REMORAFillPatcher > FPr_u
Vector over levels of FillPatchers for u (3D)
Definition REMORA.H:1644
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_msku
land/sea mask at x-faces (2D)
Definition REMORA.H:586
amrex::Vector< amrex::GpuArray< REMORA_BC, AMREX_SPACEDIM *2 > > phys_bc_type
Array holding the "physical" boundary condition types (e.g. "inflow")
Definition REMORA.H:1739
amrex::Vector< REMORAFillPatcher > FPr_vbar
Vector over levels of FillPatchers for vbar (2D)
Definition REMORA.H:1654
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskv
land/sea mask at y-faces (2D)
Definition REMORA.H:588
amrex::Vector< std::unique_ptr< REMORAPhysBCFunct > > physbcs
Vector (over level) of functors to apply physical boundary conditions.
Definition REMORA.H:1710
void FillCoarsePatch(int lev, amrex::Real time, amrex::MultiFab *mf_fine, amrex::MultiFab *mf_crse, const int bccomp, const int bdy_var_type=BdyVars::null, const int icomp=0, const bool fill_all=true, const int n_not_fill=0, const int icomp_calc=0, const amrex::Real dt=zero, const amrex::MultiFab &mf_calc=amrex::MultiFab())
fill an entire multifab by interpolating from the coarser level
void FillBdyCCVels(int lev, amrex::MultiFab &mf_cc_vel)
Fill the physical boundary conditions for cell-centered velocity (diagnostic only)
TimeInterpolatedData GetDataAtTime(int lev, amrex::Real time)
utility to copy in data from old and/or new state into another multifab
amrex::Vector< REMORAFillPatcher > FPr_c
Vector over levels of FillPatchers for scalars.
Definition REMORA.H:1642
amrex::Vector< REMORAFillPatcher > FPr_w
Vector over levels of FillPatchers for w.
Definition REMORA.H:1648
amrex::Vector< amrex::Real > t_new
new time at each level, in seconds since start_time
Definition REMORA.H:1700
static SolverChoice solverChoice
Container for algorithmic choices.
Definition REMORA.H:1949
int cf_set_width
Width for fixing values at coarse-fine interface.
Definition REMORA.H:1639
void FillPatchNoBC(int lev, amrex::Real time, amrex::MultiFab &mf_to_be_filled, amrex::Vector< amrex::MultiFab * > const &mfs, const int bdy_var_type=BdyVars::null, const int icomp=0, const bool fill_all=true, const bool fill_set=false, amrex::Vector< amrex::MultiFab * > const &mfs_crse_old={}, amrex::Vector< amrex::MultiFab * > const &mfs_crse_new={})
Fill a new MultiFab by copying in phi from valid region and filling ghost cells without applying boun...
void FillCoarsePatchPC(int lev, amrex::Real time, amrex::MultiFab *mf_fine, amrex::MultiFab *mf_crse, const int bccomp, const int bdy_var_type=BdyVars::null, const int icomp=0, const bool fill_all=true, const int n_not_fill=0, const int icomp_calc=0, const amrex::Real dt=zero, const amrex::MultiFab &mf_calc=amrex::MultiFab())
fill an entire multifab by interpolating from the coarser level using the piecewise constant interpol...
void FillPatch(int lev, amrex::Real time, amrex::MultiFab &mf_to_be_filled, amrex::Vector< amrex::MultiFab * > const &mfs, const int bccomp, const int bdy_var_type=BdyVars::null, const int icomp=0, const bool fill_all=true, const bool fill_set=false, const int n_not_fill=0, const int icomp_calc=0, const amrex::Real dt=zero, const amrex::MultiFab &mf_calc=amrex::MultiFab(), amrex::Vector< amrex::MultiFab * > const &mfs_crse_old={}, amrex::Vector< amrex::MultiFab * > const &mfs_crse_new={})
Fill a new MultiFab by copying in phi from valid region and filling ghost cells.
amrex::Vector< REMORAFillPatcher > FPr_ubar
Vector over levels of FillPatchers for ubar (2D)
Definition REMORA.H:1652
amrex::Vector< amrex::Real > t_old
old time at each level, in seconds since start_time
Definition REMORA.H:1702
static constexpr int null