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
8PhysBCFunctNoOp null_bc;
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
30REMORA::FillPatch (int lev, Real time, MultiFab& mf_to_fill, Vector<MultiFab*> const& mfs,
31 const int bccomp,
32#ifdef REMORA_USE_NETCDF
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,
41#ifdef REMORA_USE_NETCDF
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))) {
68 FPr_c[lev-1].FillSet(mf_to_fill, time, null_bc, domain_bcs_type);
69 } else if (cf_set_width >= 0) {
70 if (!is_2d) {
71 if (mf_box.ixType() == IndexType(IntVect(1,0,0))) {
72 FPr_u[lev-1].FillSet(mf_to_fill, time, null_bc, domain_bcs_type);
73 } else if (mf_box.ixType() == IndexType(IntVect(0,1,0))) {
74 FPr_v[lev-1].FillSet(mf_to_fill, time, null_bc, domain_bcs_type);
75 } else if (mf_box.ixType() == IndexType(IntVect(0,0,1))) {
76 FPr_w[lev-1].FillSet(mf_to_fill, time, null_bc, domain_bcs_type);
77 }
78 } else {
79 if (mf_box.ixType() == IndexType(IntVect(1,0,0))) {
80 FPr_ubar[lev-1].FillSet(mf_to_fill, time, null_bc, domain_bcs_type);
81 } else if (mf_box.ixType() == IndexType(IntVect(0,1,0))) {
82 FPr_vbar[lev-1].FillSet(mf_to_fill, time, null_bc, domain_bcs_type);
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 {
97 mapper = &cell_cons_interp;
98 mask = vec_mskr[lev].get();
99 }
100 else if (mf_box.ixType() == IndexType(IntVect(1,0,0)))
101 {
102 mapper = &face_cons_linear_interp;
103 mask = vec_msku[lev].get();
104 }
105 else if (mf_box.ixType() == IndexType(IntVect(0,1,0)))
106 {
107 mapper = &face_cons_linear_interp;
108 mask = vec_mskv[lev].get();
109 }
110 else {
111 mapper = &face_cons_linear_interp;
112 mask = vec_mskr[lev].get();
113 }
114
115 if (lev == 0)
116 {
117 Vector<MultiFab*> fmf = {mfs[lev], mfs[lev]};
118 Vector<Real> ftime = {t_old[lev], t_new[lev]};
119 amrex::FillPatchSingleLevel(mf_to_fill, time, fmf, ftime, icomp, icomp, ncomp,
120 geom[lev], null_bc, bccomp);
121 }
122 else
123 {
124 Vector<MultiFab*> fmf = {mfs[lev], mfs[lev]};
125 Vector<Real> ftime = {t_old[lev], t_new[lev]};
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),
135 mapper, domain_bcs_type, bccomp);
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
146 (*physbcs[lev])(mf_to_fill,*mask,icomp,ncomp,mf_to_fill.nGrowVect(),time,bccomp,n_not_fill,mf_calc,
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
151 if ( (solverChoice.boundary_from_netcdf) && (bdy_var_type != BdyVars::null) )
152 {
153 fill_from_bdyfiles(lev, mf_to_fill,*mask,time,bccomp,bdy_var_type, icomp,icomp_calc,mf_calc,dt_lev);
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()) {
171 Array4<Real> vel_arr = mf_to_fill.array(mfi);
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
199REMORA::FillPatchNoBC (int lev, Real time, MultiFab& mf_to_fill, Vector<MultiFab*> const& mfs,
200#ifdef REMORA_USE_NETCDF
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))) {
229 FPr_c[lev-1].FillSet(mf_to_fill, time, null_bc, domain_bcs_type);
230 } else if (cf_set_width >= 0) {
231 if (!is_2d) {
232 if (mf_box.ixType() == IndexType(IntVect(1,0,0))) {
233 FPr_u[lev-1].FillSet(mf_to_fill, time, null_bc, domain_bcs_type);
234 } else if (mf_box.ixType() == IndexType(IntVect(0,1,0))) {
235 FPr_v[lev-1].FillSet(mf_to_fill, time, null_bc, domain_bcs_type);
236 } else if (mf_box.ixType() == IndexType(IntVect(0,0,1))) {
237 FPr_w[lev-1].FillSet(mf_to_fill, time, null_bc, domain_bcs_type);
238 }
239 } else {
240 if (mf_box.ixType() == IndexType(IntVect(1,0,0))) {
241 FPr_ubar[lev-1].FillSet(mf_to_fill, time, null_bc, domain_bcs_type);
242 } else if (mf_box.ixType() == IndexType(IntVect(0,1,0))) {
243 FPr_vbar[lev-1].FillSet(mf_to_fill, time, null_bc, domain_bcs_type);
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;
259 mapper = &cell_cons_interp;
260 }
261 else if (mf_box.ixType() == IndexType(IntVect(1,0,0)))
262 {
263 bccomp = BCVars::xvel_bc;
264 mapper = &face_cons_linear_interp;
265 }
266 else if (mf_box.ixType() == IndexType(IntVect(0,1,0)))
267 {
268 bccomp = BCVars::yvel_bc;
269 mapper = &face_cons_linear_interp;
270 }
271 else {
272 bccomp = BCVars::zvel_bc;
273 mapper = &face_cons_linear_interp;
274 }
275
276 if (lev == 0)
277 {
278 Vector<MultiFab*> fmf = {mfs[lev], mfs[lev]};
279 Vector<Real> ftime = {t_old[lev], t_new[lev]};
280 amrex::FillPatchSingleLevel(mf_to_fill, time, fmf, ftime, icomp, icomp, ncomp,
281 geom[lev], null_bc, bccomp);
282 }
283 else
284 {
285 Vector<MultiFab*> fmf = {mfs[lev], mfs[lev]};
286 Vector<Real> ftime = {t_old[lev], t_new[lev]};
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),
296 mapper, domain_bcs_type, bccomp);
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(),
332 vars_new[lev][i].DistributionMap(),
333 vars_new[lev][i].nComp(), vars_new[lev][i].nGrowVect());
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
377REMORA::FillCoarsePatchPC (int lev, Real time, MultiFab* mf_to_fill,
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;
388 FillCoarsePatchMap(lev, time, mf_to_fill, mf_crse, bccomp, bdy_var_type,icomp,
389 fill_all, n_not_fill, icomp_calc, dt_lev, mf_calc, mapper);
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
411REMORA::FillCoarsePatch (int lev, Real time, MultiFab* mf_to_fill,
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;
422 FillCoarsePatchMap(lev, time, mf_to_fill, mf_crse, bccomp, bdy_var_type,icomp,
423 fill_all, n_not_fill, icomp_calc, dt_lev, mf_calc, mapper);
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,
447#ifdef REMORA_USE_NETCDF
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,
455#ifdef REMORA_USE_NETCDF
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 {
501 mapper = &cell_cons_interp;
502 }
503 else if (box_mf.ixType() == IndexType(IntVect(1,0,0)))
504 {
505 mapper = &face_cons_linear_interp;
506 }
507 else if (box_mf.ixType() == IndexType(IntVect(0,1,0)))
508 {
509 mapper = &face_cons_linear_interp;
510 }
511 else if (box_mf.ixType() == IndexType(IntVect(0,0,1)))
512 {
513 mapper = &face_cons_linear_interp;
514 } else {
515 amrex::Abort("Dont recognize this box type in REMORA_FillPatch");
516 }
517 }
518
519#if 0
520 TimeInterpolatedData cdata = GetDataAtTime(lev-1, time);
521 TimeInterpolatedData fdata = GetDataAtTime(lev , time);
522 Vector<Real> ctime = {cdata.get_time()};
523
524 Vector<MultiFab*> cmf = {mf_crse};
525 Vector<Real> ctime = {time};
526
527 REMORAPhysBCFunct cphysbc(lev-1,geom[lev-1],
529 cdata,
531#ifdef REMORA_USE_NETCDF
532 ,ic_type,bdy_data_xlo,bdy_data_xhi,
533 bdy_data_ylo,bdy_data_yhi,bdy_time_interval
534#endif
535 );
536 REMORAPhysBCFunct fphysbc(lev,geom[lev],
538 fdata,
540#ifdef REMORA_USE_NETCDF
541 ,ic_type,bdy_data_xlo,bdy_data_xhi,
542 bdy_data_ylo,bdy_data_yhi,bdy_time_interval
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),
552 mapper, domain_bcs_type, bccomp);
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(),
560 time,bccomp,n_not_fill,mf_calc,
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
565 if ( (solverChoice.boundary_from_netcdf) && (bdy_var_type != BdyVars::null) )
566 {
567 fill_from_bdyfiles(lev, *mf_to_fill,*mask,time,bccomp,bdy_var_type, icomp,icomp_calc,mf_calc,dt_lev);
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()) {
585 Array4<Real> vel_arr = mf_to_fill->array(mfi);
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
596/**
597 * @param[in ] lev level to fill at
598 * @param[in ] lev MultiFab of cell-centered velocities
599 */
600void
601REMORA::FillBdyCCVels (int lev, MultiFab& mf_cc_vel)
602{
603 // Impose bc's at domain boundaries
604// for (int lev = 0; lev <= finest_level; ++lev)
605// {
606 Box domain(Geom(lev).Domain());
607
608 int ihi = domain.bigEnd(0);
609 int jhi = domain.bigEnd(1);
610 int khi = domain.bigEnd(2);
611
612 // Impose periodicity first
613 mf_cc_vel.FillBoundary(geom[lev].periodicity());
614
615#ifdef _OPENMP
616#pragma omp parallel if (Gpu::notInLaunchRegion())
617#endif
618 for (MFIter mfi(mf_cc_vel, TilingIfNotGPU()); mfi.isValid(); ++mfi)
619 {
620 // Note that we don't fill corners here -- only the cells that share a face
621 // with interior cells -- this is all that is needed to calculate vorticity
622 const Box& bx = mfi.tilebox();
623 const Array4<Real>& vel_arr = mf_cc_vel.array(mfi);
624
625 if (!Geom(lev).isPeriodic(0)) {
626 // Low-x side
627 if (bx.smallEnd(0) <= domain.smallEnd(0)) {
628 Real mult = (phys_bc_type[BCVars::xvel_bc][0] == REMORA_BC::no_slip_wall) ? -1. : 1.;
629 ParallelFor(makeSlab(bx,0,0), [=] AMREX_GPU_DEVICE(int , int j, int k) noexcept
630 {
631 vel_arr(-1,j,k,1) = mult*vel_arr(0,j,k,1); // v
632 vel_arr(-1,j,k,2) = mult*vel_arr(0,j,k,2); // w
633 });
634 }
635
636 // High-x side
637 if (bx.bigEnd(0) >= domain.bigEnd(0)) {
638 Real mult = (phys_bc_type[BCVars::xvel_bc][3] == REMORA_BC::no_slip_wall) ? -1. : 1.;
639 ParallelFor(makeSlab(bx,0,0), [=] AMREX_GPU_DEVICE(int , int j, int k) noexcept
640 {
641 vel_arr(ihi+1,j,k,1) = mult*vel_arr(ihi,j,k,1); // v
642 vel_arr(ihi+1,j,k,2) = mult*vel_arr(ihi,j,k,2); // w
643 });
644 }
645 } // !periodic
646
647 if (!Geom(lev).isPeriodic(1)) {
648 // Low-y side
649 if (bx.smallEnd(1) <= domain.smallEnd(1)) {
650 Real mult = (phys_bc_type[BCVars::yvel_bc][1] == REMORA_BC::no_slip_wall) ? -1. : 1.;
651 ParallelFor(makeSlab(bx,1,0), [=] AMREX_GPU_DEVICE(int i, int , int k) noexcept
652 {
653 vel_arr(i,-1,k,0) = mult*vel_arr(i,0,k,0); // u
654 vel_arr(i,-1,k,2) = mult*vel_arr(i,0,k,2); // w
655 });
656 }
657
658 // High-y side
659 if (bx.bigEnd(1) >= domain.bigEnd(1)) {
660 Real mult = (phys_bc_type[BCVars::yvel_bc][4] == REMORA_BC::no_slip_wall) ? -1. : 1.;
661 ParallelFor(makeSlab(bx,1,0), [=] AMREX_GPU_DEVICE(int i, int , int k) noexcept
662 {
663 vel_arr(i,jhi+1,k,0) = mult*vel_arr(i,jhi,k,0); // u
664 vel_arr(i,jhi+1,k,2) = mult*-vel_arr(i,jhi,k,2); // w
665 });
666 }
667 } // !periodic
668
669 if (!Geom(lev).isPeriodic(2)) {
670 // Low-z side
671 if (bx.smallEnd(2) <= domain.smallEnd(2)) {
672 Real mult = (phys_bc_type[BCVars::zvel_bc][2] == REMORA_BC::no_slip_wall) ? -1. : 1.;
673 ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE(int i, int j, int) noexcept
674 {
675 vel_arr(i,j,-1,0) = mult*vel_arr(i,j,0,0); // u
676 vel_arr(i,j,-1,1) = mult*vel_arr(i,j,0,1); // v
677 });
678 }
679
680 // High-z side
681 if (bx.bigEnd(2) >= domain.bigEnd(2)) {
682 Real mult = (phys_bc_type[BCVars::zvel_bc][5] == REMORA_BC::no_slip_wall) ? -1. : 1.;
683 ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE(int i, int j, int) noexcept
684 {
685 vel_arr(i,j,khi+1,0) = mult*vel_arr(i,j,khi,0); // u
686 vel_arr(i,j,khi+1,1) = mult*vel_arr(i,j,khi,1); // v
687 });
688 }
689 } // !periodic
690 } // MFIter
691
692// } // lev
693}
PhysBCFunctNoOp null_bc
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=amrex::Real(0.0), const amrex::MultiFab &mf_calc=amrex::MultiFab())
fill an entire multifab by interpolating from the coarser level using the piecewise constant interpol...
amrex::Vector< amrex::BCRec > domain_bcs_type
vector (over BCVars) of BCRecs
Definition REMORA.H:1196
amrex::Vector< REMORAFillPatcher > FPr_v
Vector over levels of FillPatchers for v (3D)
Definition REMORA.H:1131
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=amrex::Real(0.0), const amrex::MultiFab &mf_calc=amrex::MultiFab())
fill an entire multifab by interpolating from the coarser level
amrex::GpuArray< amrex::GpuArray< REMORA_BC, AMREX_SPACEDIM *2 >, BCVars::NumTypes > phys_bc_type
Array holding the "physical" boundary condition types (e.g. "inflow")
Definition REMORA.H:1207
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskr
land/sea mask at cell centers (2D)
Definition REMORA.H:375
amrex::Vector< REMORAFillPatcher > FPr_u
Vector over levels of FillPatchers for u (3D)
Definition REMORA.H:1129
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_msku
land/sea mask at x-faces (2D)
Definition REMORA.H:377
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=true)
Fill a new MultiFab by copying in phi from valid region and filling ghost cells without applying boun...
amrex::Real bdy_time_interval
Interval between boundary data times.
Definition REMORA.H:1073
amrex::Vector< REMORAFillPatcher > FPr_vbar
Vector over levels of FillPatchers for vbar (2D)
Definition REMORA.H:1139
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskv
land/sea mask at y-faces (2D)
Definition REMORA.H:379
amrex::Vector< std::unique_ptr< REMORAPhysBCFunct > > physbcs
Vector (over level) of functors to apply physical boundary conditions.
Definition REMORA.H:1184
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=true, const int n_not_fill=0, const int icomp_calc=0, const amrex::Real dt=amrex::Real(0.0), const amrex::MultiFab &mf_calc=amrex::MultiFab())
Fill a new MultiFab by copying in phi from valid region and filling ghost cells.
void FillBdyCCVels(int lev, amrex::MultiFab &mf_cc_vel)
Fill the physical boundary conditions for cell-centered velocity (diagnostic only)
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=amrex::Real(0.0))
Fill boundary data from netcdf file.
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:1127
amrex::Vector< REMORAFillPatcher > FPr_w
Vector over levels of FillPatchers for w.
Definition REMORA.H:1133
amrex::Vector< amrex::Real > t_new
new time at each level
Definition REMORA.H:1174
static SolverChoice solverChoice
Container for algorithmic choices.
Definition REMORA.H:1299
int cf_set_width
Width for fixing values at coarse-fine interface.
Definition REMORA.H:1124
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=amrex::Real(0.0), 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::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NCONS+8 > m_bc_extdir_vals
Array holding the Dirichlet values at walls which need them.
Definition REMORA.H:1204
amrex::Vector< REMORAFillPatcher > FPr_ubar
Vector over levels of FillPatchers for ubar (2D)
Definition REMORA.H:1137
amrex::Vector< amrex::Real > t_old
old time at each level
Definition REMORA.H:1176
amrex::Gpu::DeviceVector< amrex::BCRec > domain_bcs_type_d
GPU vector (over BCVars) of BCRecs.
Definition REMORA.H:1198
void set_time(amrex::Real time)
void add_var(amrex::MultiFab *var_data, int own_data)
amrex::MultiFab & get_var(int var_idx)