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)
49{
50 BL_PROFILE_VAR("REMORA::FillPatch()",REMORA_FillPatch);
51 amrex::Interpolater* mapper = nullptr;
52
53 Box mf_box(mf_to_fill.boxArray()[0]);
54 bool is_2d = mf_box.length(2) == 1;
55
56 MultiFab* mask;
57
58 //
59 // ***************************************************************************
60 // The first thing we do is interpolate the momenta on the "valid" faces of
61 // the fine grids (where the interface is coarse/fine not fine/fine) -- this
62 // will not be over-written below because the FillPatch operators see these as
63 // valid faces.
64 // ***************************************************************************
65 if (lev>0 && fill_set) {
66 if (cf_set_width > 0 &&
67 mf_box.ixType() == IndexType(IntVect(0,0,0))) {
69 } else if (cf_set_width >= 0) {
70 if (!is_2d) {
71 if (mf_box.ixType() == IndexType(IntVect(1,0,0))) {
73 } else if (mf_box.ixType() == IndexType(IntVect(0,1,0))) {
75 } else if (mf_box.ixType() == IndexType(IntVect(0,0,1))) {
77 }
78 } else {
79 if (mf_box.ixType() == IndexType(IntVect(1,0,0))) {
81 } else if (mf_box.ixType() == IndexType(IntVect(0,1,0))) {
83 }
84 }
85 }
86 }
87
88 int ncomp;
89 if (fill_all) {
90 ncomp = mf_to_fill.nComp();
91 } else {
92 ncomp = 1;
93 }
94
95 if (mf_box.ixType() == IndexType(IntVect(0,0,0)))
96 {
98 mask = vec_mskr[lev].get();
99 }
100 else if (mf_box.ixType() == IndexType(IntVect(1,0,0)))
101 {
103 mask = vec_msku[lev].get();
104 }
105 else if (mf_box.ixType() == IndexType(IntVect(0,1,0)))
106 {
108 mask = vec_mskv[lev].get();
109 }
110 else {
112 mask = vec_mskr[lev].get();
113 }
114
115 if (lev == 0)
116 {
119 amrex::FillPatchSingleLevel(mf_to_fill, time, fmf, ftime, icomp, icomp, ncomp,
121 }
122 else
123 {
126 Vector<MultiFab*> cmf = {mfs[lev-1], mfs[lev-1]};
127 Vector<Real> ctime = {t_old[lev-1], t_new[lev-1]};
128
129 mfs[lev-1]->FillBoundary(geom[lev-1].periodicity());
130 amrex::FillPatchTwoLevels(mf_to_fill, mf_to_fill.nGrowVect(), IntVect(0,0,0),
131 time, cmf, ctime, fmf, ftime,
132 icomp, icomp, ncomp, geom[lev-1], geom[lev],
133 //null_bc, bccomp, null_bc, bccomp,
134 refRatio(lev-1),
136 } // lev > 0
137
138 // This is currently unconditionally true, but do_bc flag should actually be passed in
139 const bool do_bc=true;
140 if (do_bc) {
141 // ***************************************************************************
142 // Physical bc's at domain boundary
143 // ***************************************************************************
144
145 // Enforce physical boundary conditions
147 *vec_msku[lev].get(), *vec_mskv[lev].get());
148
149#ifdef REMORA_USE_NETCDF
150 // Fill the data which is stored in the boundary data read from netcdf files
152 {
154 }
155#endif
156 // Fill corners of the domain with periodic data
157 if ( mf_box.ixType() == IndexType(IntVect(0,0,0)) ) {
158 mf_to_fill.EnforcePeriodicity(geom[lev].periodicity());
159 }
160
161 // Also enforce free-slip at top boundary (on xvel or yvel)
162 if ( (mf_box.ixType() == IndexType(IntVect(1,0,0))) ||
163 (mf_box.ixType() == IndexType(IntVect(0,1,0))) )
164 {
165 int khi = geom[lev].Domain().bigEnd(2);
166 for (MFIter mfi(mf_to_fill); mfi.isValid(); ++mfi)
167 {
168 Box gbx = mfi.growntilebox(); // Note this is face-centered since vel is
169 gbx.setSmall(2,khi+1);
170 if (gbx.ok()) {
172 ParallelFor(gbx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
173 {
174 vel_arr(i,j,k) = vel_arr(i,j,khi);
175 });
176 }
177 }
178 }
179 }
180}
181
182/**
183 * Fill valid and ghost data in the MultiFab "mf"
184 * This version fills the MultiFab mf_to_fill in valid regions with
185 * the "state data" at the given time;
186 * values in mf when it is passed in are *not* used.
187 * Unlike FillPatch, FillPatchNoBC does not apply boundary conditions
188 *
189 * @param[in ] lev level to FillPatch on
190 * @param[in ] time current time
191 * @param[inout] mf_to_fill MultiFab to fill
192 * @param[in ] mfs vector over levels of multifabs associated with mf_to_fill
193 * @param[in ] bdy_var_type when filling from NetCDF, which boundary data
194 * @param[in ] icomp component to fill
195 * @param[in ] fill_all whether to fill all components
196 * @param[in ] fill_set whether to use FillPatchers
197 */
198void
201 const int /*bdy_var_type*/,
202#else
203 const int /*bdy_var_type*/,
204#endif
205 const int icomp,
206 const bool fill_all,
207 const bool fill_set)
208{
209 // HACK: Note that this is hacky; should be able to have a single call to FillPatch with a
210 // flag for bcs, but for some reason it was acting weird, so we're splitting this out into
211 // two functions with repeated code for the time being
212 BL_PROFILE_VAR("REMORA::FillPatchNoBC()",REMORA_FillPatch);
213 int bccomp;
214 amrex::Interpolater* mapper = nullptr;
215
216 Box mf_box(mf_to_fill.boxArray()[0]);
217 bool is_2d = mf_box.length(2) == 1;
218
219 //
220 // ***************************************************************************
221 // The first thing we do is interpolate the momenta on the "valid" faces of
222 // the fine grids (where the interface is coarse/fine not fine/fine) -- this
223 // will not be over-written below because the FillPatch operators see these as
224 // valid faces.
225 // ***************************************************************************
226 if (lev>0 && fill_set) {
227 if (cf_set_width > 0 &&
228 mf_box.ixType() == IndexType(IntVect(0,0,0))) {
230 } else if (cf_set_width >= 0) {
231 if (!is_2d) {
232 if (mf_box.ixType() == IndexType(IntVect(1,0,0))) {
234 } else if (mf_box.ixType() == IndexType(IntVect(0,1,0))) {
236 } else if (mf_box.ixType() == IndexType(IntVect(0,0,1))) {
238 }
239 } else {
240 if (mf_box.ixType() == IndexType(IntVect(1,0,0))) {
242 } else if (mf_box.ixType() == IndexType(IntVect(0,1,0))) {
244 }
245 }
246 }
247 }
248
249 int ncomp;
250 if (fill_all) {
251 ncomp = mf_to_fill.nComp();
252 } else {
253 ncomp = 1;
254 }
255
256 if (mf_box.ixType() == IndexType(IntVect(0,0,0)))
257 {
258 bccomp = 0;
260 }
261 else if (mf_box.ixType() == IndexType(IntVect(1,0,0)))
262 {
263 bccomp = xvel_bc();
265 }
266 else if (mf_box.ixType() == IndexType(IntVect(0,1,0)))
267 {
268 bccomp = yvel_bc();
270 }
271 else {
272 bccomp = zvel_bc();
274 }
275
276 if (lev == 0)
277 {
280 amrex::FillPatchSingleLevel(mf_to_fill, time, fmf, ftime, icomp, icomp, ncomp,
282 }
283 else
284 {
287 Vector<MultiFab*> cmf = {mfs[lev-1], mfs[lev-1]};
288 Vector<Real> ctime = {t_old[lev-1], t_new[lev-1]};
289
290 mfs[lev-1]->FillBoundary(geom[lev-1].periodicity());
291 amrex::FillPatchTwoLevels(mf_to_fill, mf_to_fill.nGrowVect(), IntVect(0,0,0),
292 time, cmf, ctime, fmf, ftime,
293 icomp, icomp, ncomp, geom[lev-1], geom[lev],
294 //null_bc, bccomp, null_bc, bccomp,
295 refRatio(lev-1),
297 } // lev > 0
298}
299
300
301// utility to copy in data from old/new data into a struct that holds data for FillPatching
303REMORA::GetDataAtTime (int /*lev*/, Real /*time*/)
304{
305 BL_PROFILE_VAR("GetDataAtTime()",GetDataAtTime);
307
308// HACK HACK HACK
309#if 0
310 const Real teps = (t_new[lev] - t_old[lev]) * 1.e-3_rt;
311
312 if (time > t_new[lev] - teps && time < t_new[lev] + teps)
313 {
314 for (int i = 0; i < Vars::NumTypes; ++i) {
315 data.add_var(&vars_new[lev][i], data.non_owning);
316 }
317 data.set_time(t_new[lev]);
318 }
319 else if (time > t_old[lev] - teps && time < t_old[lev] + teps)
320 {
321 for (int i = 0; i < Vars::NumTypes; ++i) {
322 data.add_var(&vars_old[lev][i], data.non_owning);
323 }
324 data.set_time(t_old[lev]);
325 }
326 else if (time > t_old[lev] && time < t_new[lev])
327 {
328 // do first order interpolation in time between [t_old[lev], t_new[lev]]
329 // time interpolation includes the ghost cells
330 for (int i = 0; i < Vars::NumTypes; ++i) {
331 MultiFab* mf_tmp = new MultiFab(vars_new[lev][i].boxArray(),
334 mf_tmp->setVal(0.0_rt);
335
336 const Real dt_fraction = (time - t_old[lev]) / (t_new[lev] - t_old[lev]);
337 MultiFab::Saxpy(*mf_tmp, 1.0_rt - dt_fraction, vars_old[lev][i], 0, 0, mf_tmp->nComp(), mf_tmp->nGrowVect());
338 MultiFab::Saxpy(*mf_tmp, dt_fraction, vars_new[lev][i], 0, 0, mf_tmp->nComp(), mf_tmp->nGrowVect());
339
340 data.add_var(mf_tmp, data.owning);
341 }
342 data.set_time(time);
343 }
344 else
345 {
346 amrex::Error("Requested data at a time outside the interval [t_old, t_new]");
347 }
348
349 // We need to make sure to fill these before we compute the viscosity
350 for (int i = 0; i < Vars::NumTypes; ++i) {
351 data.get_var(Vars::xvel).FillBoundary(geom[lev].periodicity());
352 data.get_var(Vars::yvel).FillBoundary(geom[lev].periodicity());
353 data.get_var(Vars::zvel).FillBoundary(geom[lev].periodicity());
354 data.get_var(Vars::cons).FillBoundary(geom[lev].periodicity());
355 }
356#endif
357 return data;
358}
359
360
361/**
362 * Like FillCoarsePatch but uses piecewise constant interpolater
363 *
364 * @param[in ] lev level to FillPatch on
365 * @param[in ] time current time
366 * @param[inout] mf_to_fill MultiFab to fill
367 * @param[inout] mf_crse MultiFab of coarse data
368 * @param[in ] bccomp index into domain_bcs_type
369 * @param[in ] bdy_var_type when filling from NetCDF, which boundary data
370 * @param[in ] icomp component to fill
371 * @param[in ] fill_all whether to fill all components
372 * @param[in ] icomp_calc component to use in RHS boundary calculation
373 * @param[in ] dt_lev time step at this level
374 * @param[in ] mf_calc data to use in RHS boundary calculation
375 */
376void
378 MultiFab* mf_crse,
379 const int bccomp,
380 const int bdy_var_type,
381 const int icomp,
382 const bool fill_all,
383 const int n_not_fill,
384 const int icomp_calc,
385 const Real dt_lev,
386 const MultiFab& mf_calc) {
387 amrex::Interpolater* mapper = &pc_interp;
390}
391
392/**
393 * Fill an entire multifab by interpolating from the coarser level --
394 * this is used only when a new level of refinement is being created
395 * during a run (i.e not at initialization)
396 * This will never be used with static refinement.
397 *
398 * @param[in ] lev level to FillPatch on
399 * @param[in ] time current time
400 * @param[inout] mf_to_fill MultiFab to fill
401 * @param[inout] mf_crse MultiFab of coarse data
402 * @param[in ] bccomp index into domain_bcs_type
403 * @param[in ] bdy_var_type when filling from NetCDF, which boundary data
404 * @param[in ] icomp component to fill
405 * @param[in ] fill_all whether to fill all components
406 * @param[in ] icomp_calc component to use in RHS boundary calculation
407 * @param[in ] dt_lev time step at this level
408 * @param[in ] mf_calc data to use in RHS boundary calculation
409 */
410void
412 MultiFab* mf_crse,
413 const int bccomp,
414 const int bdy_var_type,
415 const int icomp,
416 const bool fill_all,
417 const int n_not_fill,
418 const int icomp_calc,
419 const Real dt_lev,
420 const MultiFab& mf_calc) {
421 amrex::Interpolater* mapper = nullptr;
424}
425
426/**
427 * Fill an entire multifab by interpolating from the coarser level --
428 * this is used only when a new level of refinement is being created
429 * during a run (i.e not at initialization)
430 * This will never be used with static refinement.
431 *
432 * @param[in ] lev level to FillPatch on
433 * @param[in ] time current time
434 * @param[inout] mf_to_fill MultiFab to fill
435 * @param[inout] mf_crse MultiFab of coarse data
436 * @param[in ] bccomp index into domain_bcs_type
437 * @param[in ] bdy_var_type when filling from NetCDF, which boundary data
438 * @param[in ] icomp component to fill
439 * @param[in ] fill_all whether to fill all components
440 * @param[in ] icomp_calc component to use in RHS boundary calculation
441 * @param[in ] dt_lev time step at this level
442 * @param[in ] mf_calc data to use in RHS boundary calculation
443 */
444void
445REMORA::FillCoarsePatchMap (int lev, Real time, MultiFab* mf_to_fill, MultiFab* mf_crse,
446 const int bccomp,
448 const int bdy_var_type,
449#else
450 const int /*bdy_var_type*/,
451#endif
452 const int icomp,
453 const bool fill_all,
454 const int n_not_fill,
456 const int icomp_calc,
457 const Real dt_lev,
458#else
459 const int /*icomp_calc*/,
460 const Real /*dt_lev*/,
461#endif
462 const MultiFab& mf_calc,
463 amrex::Interpolater* mapper)
464{
465 BL_PROFILE_VAR("FillCoarsePatch()",FillCoarsePatch);
466 AMREX_ASSERT(lev > 0);
467
468 MultiFab* mask = nullptr;
469
470 int ncomp;
471 if (fill_all) {
472 ncomp = mf_to_fill->nComp();
473 } else {
474 ncomp = 1;
475 }
476
477 Box box_mf(mf_to_fill->boxArray()[0]);
478
479 if (box_mf.ixType() == IndexType(IntVect(0,0,0)))
480 {
481 mask = vec_mskr[lev].get();
482 }
483 else if (box_mf.ixType() == IndexType(IntVect(1,0,0)))
484 {
485 mask = vec_msku[lev].get();
486 }
487 else if (box_mf.ixType() == IndexType(IntVect(0,1,0)))
488 {
489 mask = vec_mskv[lev].get();
490 }
491 else if (box_mf.ixType() == IndexType(IntVect(0,0,1)))
492 {
493 mask = vec_mskr[lev].get();
494 } else {
495 amrex::Abort("Dont recognize this box type in REMORA_FillPatch");
496 }
497
498 if (mapper == nullptr) {
499 if (box_mf.ixType() == IndexType(IntVect(0,0,0)))
500 {
502 }
503 else if (box_mf.ixType() == IndexType(IntVect(1,0,0)))
504 {
506 }
507 else if (box_mf.ixType() == IndexType(IntVect(0,1,0)))
508 {
510 }
511 else if (box_mf.ixType() == IndexType(IntVect(0,0,1)))
512 {
514 } else {
515 amrex::Abort("Dont recognize this box type in REMORA_FillPatch");
516 }
517 }
518
519#if 0
522 Vector<Real> ctime = {cdata.get_time()};
523
526
529 cdata,
532 ,ic_type,bdy_data_xlo,bdy_data_xhi,
534#endif
535 );
538 fdata,
541 ,ic_type,bdy_data_xlo,bdy_data_xhi,
543#endif
544 );
545#endif
546
547
548 mf_crse->FillBoundary(geom[lev-1].periodicity());
549 amrex::InterpFromCoarseLevel(*mf_to_fill, mf_to_fill->nGrowVect(), IntVect(0,0,0),
550 *mf_crse, 0, icomp, ncomp, geom[lev-1], geom[lev],
551 refRatio(lev-1),
553
554 // ***************************************************************************
555 // Physical bc's at domain boundary
556 // ***************************************************************************
557
558 // Enforce physical boundary conditions
559 (*physbcs[lev])(*mf_to_fill,*mask,icomp,ncomp,mf_to_fill->nGrowVect(),
561 *vec_msku[lev].get(), *vec_mskv[lev].get());
562
563#ifdef REMORA_USE_NETCDF
564 // Fill the data which is stored in the boundary data read from netcdf files
566 {
568 }
569#endif
570 // Fill corners of the domain with periodic data
571 if ( box_mf.ixType() == IndexType(IntVect(0,0,0)) ) {
572 mf_to_fill->EnforcePeriodicity(geom[lev].periodicity());
573 }
574
575 // Enforce free-slip at top boundary (on xvel or yvel)
576 if ( (box_mf.ixType() == IndexType(IntVect(1,0,0))) ||
577 (box_mf.ixType() == IndexType(IntVect(0,1,0))) )
578 {
579 int khi = geom[lev].Domain().bigEnd(2);
580 for (MFIter mfi(*mf_to_fill); mfi.isValid(); ++mfi)
581 {
582 Box gbx = mfi.growntilebox(); // Note this is face-centered since vel is
583 gbx.setSmall(2,khi+1);
584 if (gbx.ok()) {
586 ParallelFor(gbx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
587 {
588 vel_arr(i,j,k) = vel_arr(i,j,khi);
589 });
590 }
591 }
592 }
593
594}
595
596namespace {
597/**
598 * Sign for reflecting one cell-centered velocity component into a ghost cell.
599 * The normal velocity vanishes at a wall or symmetry plane; only a no-slip wall
600 * zeroes the tangential ones too. Anything else copies the adjacent valid cell.
601 *
602 * @param[in ] bc physical BC type for that component on that face
603 * @param[in ] is_normal whether the component is normal to the face
604 */
605Real
607{
608 if (is_normal) {
609 return ( (bc == REMORA_BC::slip_wall ) ||
611 (bc == REMORA_BC::symmetry ) ) ? -one : one;
612 }
613 return (bc == REMORA_BC::no_slip_wall) ? -one : one;
614}
615} // namespace
616
617/**
618 * Fill boundary ghost cells for cell-centered velocities. Each component takes
619 * the sign implied by its own BC, which with remora.boundary_per_variable can
620 * differ between u, v and w on one face.
621 *
622 * @param[in ] lev level to fill at
623 * @param[inout] mf_cc_vel MultiFab of cell-centered velocities
624 */
625void
627{
628 // Impose bc's at domain boundaries
629 Box domain(Geom(lev).Domain());
630
631 int ihi = domain.bigEnd(0);
632 int jhi = domain.bigEnd(1);
633 int khi = domain.bigEnd(2);
634
635 // Impose periodicity first
636 mf_cc_vel.FillBoundary(geom[lev].periodicity());
637
638 // Sign multipliers per face, per velocity component
640 for (OrientationIter oit; oit; ++oit) {
641 Orientation ori = oit();
642 for (int n = 0; n < AMREX_SPACEDIM; ++n) {
644 n == ori.coordDir());
645 }
646 }
647
648 // Callers pass different ghost widths (the plotfile ones carry none in z)
649 const IntVect ng = mf_cc_vel.nGrowVect();
650
651#ifdef _OPENMP
652#pragma omp parallel if (Gpu::notInLaunchRegion())
653#endif
654 for (MFIter mfi(mf_cc_vel, TilingIfNotGPU()); mfi.isValid(); ++mfi)
655 {
656 // Note that we don't fill corners here -- only the cells that share a face
657 // with interior cells -- this is all that is needed to calculate vorticity
658 const Box& bx = mfi.tilebox();
659 const Array4<Real>& vel_arr = mf_cc_vel.array(mfi);
660
661 if (!Geom(lev).isPeriodic(0) && ng[0] > 0) {
662 // Low-x side
663 if (bx.smallEnd(0) <= domain.smallEnd(0)) {
664 auto const m = mult[Orientation(Direction::x,Orientation::low)];
665 ParallelFor(makeSlab(bx,0,0), [=] AMREX_GPU_DEVICE(int , int j, int k) noexcept
666 {
667 vel_arr(-1,j,k,0) = m[0]*vel_arr(0,j,k,0); // u
668 vel_arr(-1,j,k,1) = m[1]*vel_arr(0,j,k,1); // v
669 vel_arr(-1,j,k,2) = m[2]*vel_arr(0,j,k,2); // w
670 });
671 }
672
673 // High-x side
674 if (bx.bigEnd(0) >= domain.bigEnd(0)) {
675 auto const m = mult[Orientation(Direction::x,Orientation::high)];
676 ParallelFor(makeSlab(bx,0,0), [=] AMREX_GPU_DEVICE(int , int j, int k) noexcept
677 {
678 vel_arr(ihi+1,j,k,0) = m[0]*vel_arr(ihi,j,k,0); // u
679 vel_arr(ihi+1,j,k,1) = m[1]*vel_arr(ihi,j,k,1); // v
680 vel_arr(ihi+1,j,k,2) = m[2]*vel_arr(ihi,j,k,2); // w
681 });
682 }
683 } // !periodic
684
685 if (!Geom(lev).isPeriodic(1) && ng[1] > 0) {
686 // Low-y side
687 if (bx.smallEnd(1) <= domain.smallEnd(1)) {
688 auto const m = mult[Orientation(Direction::y,Orientation::low)];
689 ParallelFor(makeSlab(bx,1,0), [=] AMREX_GPU_DEVICE(int i, int , int k) noexcept
690 {
691 vel_arr(i,-1,k,0) = m[0]*vel_arr(i,0,k,0); // u
692 vel_arr(i,-1,k,1) = m[1]*vel_arr(i,0,k,1); // v
693 vel_arr(i,-1,k,2) = m[2]*vel_arr(i,0,k,2); // w
694 });
695 }
696
697 // High-y side
698 if (bx.bigEnd(1) >= domain.bigEnd(1)) {
699 auto const m = mult[Orientation(Direction::y,Orientation::high)];
700 ParallelFor(makeSlab(bx,1,0), [=] AMREX_GPU_DEVICE(int i, int , int k) noexcept
701 {
702 vel_arr(i,jhi+1,k,0) = m[0]*vel_arr(i,jhi,k,0); // u
703 vel_arr(i,jhi+1,k,1) = m[1]*vel_arr(i,jhi,k,1); // v
704 vel_arr(i,jhi+1,k,2) = m[2]*vel_arr(i,jhi,k,2); // w
705 });
706 }
707 } // !periodic
708
709 if (!Geom(lev).isPeriodic(2) && ng[2] > 0) {
710 // Low-z side
711 if (bx.smallEnd(2) <= domain.smallEnd(2)) {
712 auto const m = mult[Orientation(Direction::z,Orientation::low)];
713 ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE(int i, int j, int) noexcept
714 {
715 vel_arr(i,j,-1,0) = m[0]*vel_arr(i,j,0,0); // u
716 vel_arr(i,j,-1,1) = m[1]*vel_arr(i,j,0,1); // v
717 vel_arr(i,j,-1,2) = m[2]*vel_arr(i,j,0,2); // w
718 });
719 }
720
721 // High-z side
722 if (bx.bigEnd(2) >= domain.bigEnd(2)) {
723 auto const m = mult[Orientation(Direction::z,Orientation::high)];
724 ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE(int i, int j, int) noexcept
725 {
726 vel_arr(i,j,khi+1,0) = m[0]*vel_arr(i,j,khi,0); // u
727 vel_arr(i,j,khi+1,1) = m[1]*vel_arr(i,j,khi,1); // v
728 vel_arr(i,j,khi+1,2) = m[2]*vel_arr(i,j,khi,2); // w
729 });
730 }
731 } // !periodic
732 } // MFIter
733}
constexpr amrex::Real one
PhysBCFunctNoOp null_bc
mf_h setVal(geomdata.ProbHi(2))
int zvel_bc() const noexcept
Definition REMORA.H:1315
int xvel_bc() const noexcept
Definition REMORA.H:1313
amrex::Vector< amrex::BCRec > domain_bcs_type
vector (over BCVars) of BCRecs
Definition REMORA.H:1578
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:1513
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskr
land/sea mask at cell centers (2D)
Definition REMORA.H:557
int yvel_bc() const noexcept
Definition REMORA.H:1314
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:1511
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_msku
land/sea mask at x-faces (2D)
Definition REMORA.H:559
amrex::Real bdy_time_interval
Interval between boundary data times.
Definition REMORA.H:1439
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:1589
amrex::Vector< REMORAFillPatcher > FPr_vbar
Vector over levels of FillPatchers for vbar (2D)
Definition REMORA.H:1521
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)
Fill a new MultiFab by copying in phi from valid region and filling ghost cells without applying boun...
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskv
land/sea mask at y-faces (2D)
Definition REMORA.H:561
amrex::Vector< std::unique_ptr< REMORAPhysBCFunct > > physbcs
Vector (over level) of functors to apply physical boundary conditions.
Definition REMORA.H:1566
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:1509
amrex::Vector< REMORAFillPatcher > FPr_w
Vector over levels of FillPatchers for w.
Definition REMORA.H:1515
amrex::Vector< amrex::Real > t_new
new time at each level
Definition REMORA.H:1556
static SolverChoice solverChoice
Container for algorithmic choices.
Definition REMORA.H:1717
int cf_set_width
Width for fixing values at coarse-fine interface.
Definition REMORA.H:1506
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...
amrex::Vector< REMORAFillPatcher > FPr_ubar
Vector over levels of FillPatchers for ubar (2D)
Definition REMORA.H:1519
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())
Fill a new MultiFab by copying in phi from valid region and filling ghost cells.
amrex::Vector< amrex::Real > t_old
old time at each level
Definition REMORA.H:1558
amrex::Vector< amrex::GpuArray< amrex::Real, AMREX_SPACEDIM *2 > > m_bc_extdir_vals
Array holding the Dirichlet values at walls which need them.
Definition REMORA.H:1586
amrex::Gpu::DeviceVector< amrex::BCRec > domain_bcs_type_d
GPU vector (over BCVars) of BCRecs.
Definition REMORA.H:1580
static constexpr int null