Block-Structured AMR Software Framework
Loading...
Searching...
No Matches
AMReX_FillPatchUtil_I.H
Go to the documentation of this file.
1#ifndef AMREX_FillPatchUtil_I_H_
2#define AMREX_FillPatchUtil_I_H_
3#include <AMReX_Config.H>
4
5namespace amrex {
6
8namespace detail {
9
10template <typename F, typename MF>
11auto call_interp_hook (F const& f, MF& mf, int icomp, int ncomp)
12 -> decltype(f(mf[0],Box(),icomp,ncomp))
13{
14#ifdef AMREX_USE_OMP
15#pragma omp parallel if (Gpu::notInLaunchRegion())
16#endif
17 for (MFIter mfi(mf); mfi.isValid(); ++mfi) {
18 auto& dfab = mf[mfi];
19 const Box& dbx = dfab.box();
20 f(dfab, dbx, icomp, ncomp);
21 }
22}
23
24template <typename F, typename MF>
25auto call_interp_hook (F const& f, MF& mf, int icomp, int ncomp)
26 -> decltype(f(mf,icomp,ncomp))
27{
28 f(mf, icomp, ncomp);
29}
30
31}
33
34template <typename Interp>
35bool ProperlyNested (const IntVect& ratio, const IntVect& blocking_factor, int ngrow,
36 const IndexType& boxType, Interp* mapper)
37{
38 int ratio_max = ratio[0];
39#if (AMREX_SPACEDIM > 1)
40 ratio_max = std::max(ratio_max, ratio[1]);
41#endif
42#if (AMREX_SPACEDIM == 3)
43 ratio_max = std::max(ratio_max, ratio[2]);
44#endif
45 // There are at least this many coarse cells outside fine grids
46 // (except at physical boundaries).
47 const IntVect& nbuf = blocking_factor / ratio_max;
48
49 Box crse_box(IntVect(AMREX_D_DECL(0 ,0 ,0 )), IntVect(AMREX_D_DECL(4*nbuf[0]-1,
50 4*nbuf[1]-1,
51 4*nbuf[2]-1)));
52 crse_box.convert(boxType);
53 Box fine_box(nbuf, IntVect(AMREX_D_DECL(3*nbuf[0]-1,3*nbuf[1]-1,3*nbuf[2]-1)));
54 fine_box.convert(boxType);
55 fine_box.refine(ratio_max);
56 fine_box.grow(ngrow);
57 const Box& fine_box_coarsened = mapper->CoarseBox(fine_box, ratio_max);
58 return crse_box.contains(fine_box_coarsened);
59}
60
61template <FabArrayType MF, typename BC>
62void
64 const Vector<MF*>& smf, const Vector<Real>& stime,
65 int scomp, int dcomp, int ncomp,
66 const Geometry& geom,
67 BC& physbcf, int bcfcomp)
68{
69 FillPatchSingleLevel(mf, mf.nGrowVect(), time, smf, stime, scomp, dcomp, ncomp,
70 geom, physbcf, bcfcomp);
71}
72
73template <FabArrayType MF, typename BC>
74void
75FillPatchSingleLevel (MF& mf, IntVect const& nghost, Real time,
76 const Vector<MF*>& smf, const Vector<Real>& stime,
77 int scomp, int dcomp, int ncomp,
78 const Geometry& geom,
79 BC& physbcf, int bcfcomp)
80{
81 BL_PROFILE("FillPatchSingleLevel");
82
83 AMREX_ASSERT((!smf.empty()) &&
84 (scomp+ncomp <= smf[0]->nComp()) &&
85 (dcomp+ncomp <= mf.nComp()) &&
86 (smf.size() == stime.size()) &&
87 nghost.allLE(mf.nGrowVect()));
88
89 IntVect src_ghost(0);
90 if constexpr (std::is_same_v<BC,PhysBCFunctUseCoarseGhost>) {
91 src_ghost = physbcf.fp1_src_ghost;
92 }
93
94 if (smf.size() == 1)
95 {
96 if (&mf == smf[0] && scomp == dcomp) {
97 mf.FillBoundary(dcomp, ncomp, nghost, geom.periodicity());
98 } else {
99 mf.ParallelCopy(*smf[0], scomp, dcomp, ncomp, src_ghost, nghost, geom.periodicity());
100 }
101 }
102 else if (smf.size() == 2)
103 {
104 BL_ASSERT(smf[0]->boxArray() == smf[1]->boxArray());
105 const Real t0 = stime[0];
106 const Real t1 = stime[1];
107 MF raii;
108 MF * dmf;
109 int destcomp;
110 bool sameba;
111 bool fill_dmf;
112 if (mf.boxArray() == smf[0]->boxArray() &&
113 mf.DistributionMap() == smf[0]->DistributionMap())
114 {
115 dmf = &mf;
116 destcomp = dcomp;
117 sameba = true;
118 fill_dmf = (&mf != smf[0] && &mf != smf[1]) || scomp != dcomp;
119 }
120 else if (time == t0 || time == t1 || amrex::almostEqual(t0,t1))
121 {
122 dmf = smf[(time != t0 && time == t1) ? 1 : 0];
123 destcomp = scomp;
124 sameba = false;
125 fill_dmf = false;
126 }
127 else
128 {
129 raii.define(smf[0]->boxArray(), smf[0]->DistributionMap(), ncomp, src_ghost,
130 MFInfo().SetArena(The_Async_Arena()), smf[0]->Factory());
131
132 dmf = &raii;
133 destcomp = 0;
134 sameba = false;
135 fill_dmf = true;
136 }
137
138 if (fill_dmf)
139 {
140 IntVect interp_ghost(0);
141 if constexpr (std::is_same_v<BC,PhysBCFunctUseCoarseGhost>) {
142 interp_ghost = physbcf.fp1_src_ghost;
143 if (sameba) {
144 interp_ghost.min(nghost);
145 }
146 }
147
148 // Patch case: interpolate only the cells the ParallelCopy below reads,
149 // i.e. the hull of the local and send tags of each source FAB. Not with
150 // MPI teams, whose members work on each other's FABs but only have the
151 // send tags of their own.
152 const bool use_hull = !sameba && ParallelDescriptor::TeamSize() == 1;
153 Vector<Box> hull;
154 if (use_hull) {
155 hull.resize(raii.local_size());
156 if (!mf.empty() && !raii.empty()) {
157 auto const& cpc = mf.getCPC(nghost, raii, src_ghost, geom.periodicity());
158 for (auto const& tag : *cpc.m_LocTags) {
159 Box& h = hull[raii.localindex(tag.srcIndex)];
160 h = h.ok() ? amrex::minBox(h, tag.sbox) : tag.sbox;
161 }
162 for (auto const& kv : *cpc.m_SndTags) {
163 for (auto const& tag : kv.second) {
164 Box& h = hull[raii.localindex(tag.srcIndex)];
165 h = h.ok() ? amrex::minBox(h, tag.sbox) : tag.sbox;
166 }
167 }
168 }
169 }
170
171#ifdef AMREX_USE_OMP
172#pragma omp parallel if (Gpu::notInLaunchRegion())
173#endif
174 for (MFIter mfi(*dmf,TilingIfNotGPU()); mfi.isValid(); ++mfi)
175 {
176 Box bx = mfi.growntilebox(interp_ghost);
177 if (use_hull) {
178 const Box& hbx = hull[mfi.LocalIndex()];
179 if (!hbx.ok()) { continue; }
180 bx &= hbx;
181 }
182 auto const sfab0 = smf[0]->array(mfi);
183 auto const sfab1 = smf[1]->array(mfi);
184 auto dfab = dmf->array(mfi);
185
186 if (time == t0)
187 {
188 AMREX_HOST_DEVICE_PARALLEL_FOR_4D ( bx, ncomp, i, j, k, n,
189 {
190 dfab(i,j,k,n+destcomp) = sfab0(i,j,k,n+scomp);
191 });
192 }
193 else if (time == t1)
194 {
195 AMREX_HOST_DEVICE_PARALLEL_FOR_4D ( bx, ncomp, i, j, k, n,
196 {
197 dfab(i,j,k,n+destcomp) = sfab1(i,j,k,n+scomp);
198 });
199 }
200 else if (! amrex::almostEqual(t0,t1))
201 {
202 Real alpha = (t1-time)/(t1-t0);
203 Real beta = (time-t0)/(t1-t0);
204 AMREX_HOST_DEVICE_PARALLEL_FOR_4D ( bx, ncomp, i, j, k, n,
205 {
206 dfab(i,j,k,n+destcomp) = alpha*sfab0(i,j,k,n+scomp)
207 + beta*sfab1(i,j,k,n+scomp);
208 });
209 }
210 else
211 {
212 AMREX_HOST_DEVICE_PARALLEL_FOR_4D ( bx, ncomp, i, j, k, n,
213 {
214 dfab(i,j,k,n+destcomp) = sfab0(i,j,k,n+scomp);
215 });
216 }
217 }
218 }
219
220 if (sameba)
221 {
222 // Note that when sameba is true mf's BoxArray is nonoverlapping.
223 // So FillBoundary is safe.
224 mf.FillBoundary(dcomp, ncomp, nghost, geom.periodicity());
225 }
226 else
227 {
228 mf.ParallelCopy(*dmf, destcomp, dcomp, ncomp, src_ghost, nghost, geom.periodicity());
229 }
230 }
231 else {
232 amrex::Abort("FillPatchSingleLevel: high-order interpolation in time not implemented yet");
233 }
234
235 physbcf(mf, dcomp, ncomp, nghost, time, bcfcomp);
236}
237
255void FillPatchInterp (MultiFab& mf_fine_patch, int fcomp, MultiFab const& mf_crse_patch, int ccomp,
256 int ncomp, IntVect const& ng, const Geometry& cgeom, const Geometry& fgeom,
257 Box const& dest_domain, const IntVect& ratio,
258 MFInterpolater* mapper, const Vector<BCRec>& bcs, int bcscomp);
259
260template <FabArrayType MF, typename Interp>
261requires (!std::is_same_v<Interp, MFInterpolater>)
262void
263FillPatchInterp (MF& mf_fine_patch, int fcomp, MF const& mf_crse_patch, int ccomp,
264 int ncomp, IntVect const& ng, const Geometry& cgeom, const Geometry& fgeom,
265 Box const& dest_domain, const IntVect& ratio,
266 Interp* mapper, const Vector<BCRec>& bcs, int bcscomp)
267{
268 BL_PROFILE("FillPatchInterp(Fab)");
269
270 Box const& cdomain = amrex::convert(cgeom.Domain(), mf_fine_patch.ixType());
271 int idummy=0;
272#ifdef AMREX_USE_OMP
273#pragma omp parallel if (Gpu::notInLaunchRegion())
274#endif
275 {
276 Vector<BCRec> bcr(ncomp);
277 for (MFIter mfi(mf_fine_patch); mfi.isValid(); ++mfi)
278 {
279 auto& sfab = mf_crse_patch[mfi];
280 const Box& sbx = sfab.box();
281
282 auto& dfab = mf_fine_patch[mfi];
283 Box const& dbx = amrex::grow(mfi.validbox(),ng) & dest_domain;
284
285 amrex::setBC(sbx,cdomain,bcscomp,0,ncomp,bcs,bcr);
286 mapper->interp(sfab, ccomp, dfab, fcomp, ncomp, dbx, ratio,
287 cgeom, fgeom, bcr, idummy, idummy, RunOn::Gpu);
288 }
289 }
290}
291
292template <FabArrayType MF>
293void
294FillPatchInterp (MF& mf_fine_patch, int fcomp, MF const& mf_crse_patch, int ccomp,
295 int ncomp, IntVect const& ng, const Geometry& cgeom, const Geometry& fgeom,
296 Box const& dest_domain, const IntVect& ratio,
297 InterpBase* mapper, const Vector<BCRec>& bcs, int bcscomp)
298{
299 if (dynamic_cast<MFInterpolater*>(mapper)) {
300 FillPatchInterp(mf_fine_patch, fcomp, mf_crse_patch, ccomp,
301 ncomp, ng, cgeom, fgeom, dest_domain, ratio,
302 static_cast<MFInterpolater*>(mapper), bcs, bcscomp);
303 } else if (dynamic_cast<Interpolater*>(mapper)) {
304 FillPatchInterp(mf_fine_patch, fcomp, mf_crse_patch, ccomp,
305 ncomp, ng, cgeom, fgeom, dest_domain, ratio,
306 static_cast<Interpolater*>(mapper), bcs, bcscomp);
307 } else {
308 amrex::Abort("FillPatchInterp: unknown InterpBase");
309 }
310}
311
312template <FabArrayType MF, typename iMF, typename Interp>
313requires (!std::is_same_v<Interp, MFInterpolater>)
314void
315InterpFace (Interp *interp,
316 MF const& mf_crse_patch, int crse_comp,
317 MF& mf_refined_patch, int fine_comp,
318 int ncomp, const IntVect& ratio,
319 const iMF& solve_mask, const Geometry& crse_geom, const Geometry& fine_geom,
320 int bcscomp, RunOn gpu_or_cpu,
321 const Vector<BCRec>& bcs)
322{
323 Vector<BCRec> bcr(ncomp);
324 Box const& cdomain = amrex::convert(crse_geom.Domain(), mf_crse_patch.ixType());
325 for (MFIter mfi(mf_refined_patch);mfi.isValid(); ++mfi)
326 {
327 auto& sfab = mf_crse_patch[mfi];
328 const Box& sbx = sfab.box();
329 auto& dfab = mf_refined_patch[mfi];
330 Box const& dbx = dfab.box();
331 auto& ifab = solve_mask[mfi];
332 amrex::setBC(sbx,cdomain,bcscomp,0,ncomp,bcs,bcr);
333 interp->interp_face(sfab,crse_comp,dfab,fine_comp,ncomp,
334 dbx, ratio, ifab, crse_geom, fine_geom,
335 bcr, bcscomp, gpu_or_cpu);
336 }
337}
338
339template <FabArrayType MF, typename iMF>
340void
342 MF const& mf_crse_patch, int crse_comp,
343 MF& mf_refined_patch, int fine_comp,
344 int ncomp, const IntVect& ratio,
345 const iMF& solve_mask, const Geometry& crse_geom, const Geometry& fine_geom,
346 int bccomp, RunOn gpu_or_cpu,
347 const Vector<BCRec>& bcs)
348{
349 if (dynamic_cast<MFInterpolater*>(interp)){
350 InterpFace(static_cast<MFInterpolater*>(interp),
351 mf_crse_patch, crse_comp,mf_refined_patch, fine_comp,
352 ncomp, ratio, solve_mask, crse_geom, fine_geom, bccomp,
353 gpu_or_cpu, bcs);
354 }
355 else if (dynamic_cast<Interpolater*>(interp)){
356 InterpFace(static_cast<Interpolater*>(interp),
357 mf_crse_patch, crse_comp,mf_refined_patch, fine_comp,
358 ncomp, ratio, solve_mask, crse_geom, fine_geom, bccomp,
359 gpu_or_cpu, bcs);
360 }
361 else {
362 amrex::Abort("InterpFace: unknown InterpBase");
363 }
364}
365
366
368namespace detail {
369
370// ======== FArrayBox
371
372 template <MultiFabLike MF>
373 requires (std::same_as<typename MF::FABType::value_type, FArrayBox>)
374 MF make_mf_crse_patch (FabArrayBase::FPinfo const& fpc, int ncomp)
375 {
376 MF mf_crse_patch(fpc.ba_crse_patch, fpc.dm_patch, ncomp, 0, MFInfo(),
377 *fpc.fact_crse_patch);
378 return mf_crse_patch;
379 }
380
381 template <MultiFabLike MF>
382 requires (std::same_as<typename MF::FABType::value_type, FArrayBox>)
383 MF make_mf_crse_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type)
384 {
385 MF mf_crse_patch(amrex::convert(fpc.ba_crse_patch, idx_type), fpc.dm_patch,
386 ncomp, 0, MFInfo(), *fpc.fact_crse_patch);
387 return mf_crse_patch;
388 }
389
390 template <MultiFabLike MF>
391 requires (std::same_as<typename MF::FABType::value_type, FArrayBox>)
392 MF make_mf_fine_patch (FabArrayBase::FPinfo const& fpc, int ncomp)
393 {
394 MF mf_fine_patch(fpc.ba_fine_patch, fpc.dm_patch, ncomp, 0, MFInfo(),
395 *fpc.fact_fine_patch);
396 return mf_fine_patch;
397 }
398
399 template <MultiFabLike MF>
400 requires (std::same_as<typename MF::FABType::value_type, FArrayBox>)
401 MF make_mf_fine_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type)
402 {
403 MF mf_fine_patch(amrex::convert(fpc.ba_fine_patch, idx_type), fpc.dm_patch,
404 ncomp, 0, MFInfo(), *fpc.fact_fine_patch);
405 return mf_fine_patch;
406 }
407
408 template <MultiFabLike MF>
409 requires (std::same_as<typename MF::FABType::value_type, FArrayBox>)
410 MF make_mf_refined_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type, IntVect ratio)
411 {
412 MF mf_refined_patch(amrex::convert( amrex::refine( amrex::coarsen(fpc.ba_fine_patch, ratio), ratio), idx_type),
413 fpc.dm_patch, ncomp, 0, MFInfo(), *fpc.fact_fine_patch);
414 return mf_refined_patch;
415 }
416
417 template <MultiFabLike MF>
418 requires (std::same_as<typename MF::FABType::value_type, FArrayBox>)
419 MF make_mf_crse_mask (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type, IntVect ratio)
420 {
421 MF mf_crse_mask(amrex::convert(amrex::coarsen(fpc.ba_fine_patch, ratio), idx_type),
422 fpc.dm_patch, ncomp, 0, MFInfo(), *fpc.fact_fine_patch);
423 return mf_crse_mask;
424 }
425
426 template <MultiFabLike MF>
427 requires (std::same_as<typename MF::FABType::value_type, FArrayBox>)
428 void mf_set_domain_bndry (MF &mf, Geometry const & geom)
429 {
430 mf.setDomainBndry(std::numeric_limits<Real>::quiet_NaN(), geom);
431 }
432
433
434// ======== Not FArrayBox
435
436 template <MultiFabLike MF>
437 requires (!std::same_as<typename MF::FABType::value_type, FArrayBox>)
438 MF make_mf_crse_patch (FabArrayBase::FPinfo const& fpc, int ncomp)
439 {
440 return MF(fpc.ba_crse_patch, fpc.dm_patch, ncomp, 0);
441 }
442
443 template <MultiFabLike MF>
444 requires (!std::same_as<typename MF::FABType::value_type, FArrayBox>)
445 MF make_mf_crse_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type)
446 {
447 return MF(amrex::convert(fpc.ba_crse_patch, idx_type), fpc.dm_patch, ncomp, 0);
448 }
449
450 template <MultiFabLike MF>
451 requires (!std::same_as<typename MF::FABType::value_type, FArrayBox>)
452 MF make_mf_fine_patch (FabArrayBase::FPinfo const& fpc, int ncomp)
453 {
454 return MF(fpc.ba_fine_patch, fpc.dm_patch, ncomp, 0);
455 }
456
457 template <MultiFabLike MF>
458 requires (!std::same_as<typename MF::FABType::value_type, FArrayBox>)
459 MF make_mf_fine_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type)
460 {
461 return MF(amrex::convert(fpc.ba_fine_patch, idx_type), fpc.dm_patch, ncomp, 0);
462 }
463
464 template <MultiFabLike MF>
465 requires (!std::same_as<typename MF::FABType::value_type, FArrayBox>)
466 MF make_mf_refined_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type, IntVect ratio)
467 {
468 return MF(amrex::convert( amrex::refine( amrex::coarsen(fpc.ba_fine_patch, ratio), ratio), idx_type), fpc.dm_patch, ncomp, 0);
469 }
470
471 template <MultiFabLike MF>
472 requires (!std::same_as<typename MF::FABType::value_type, FArrayBox>)
473 MF make_mf_crse_mask (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type, IntVect ratio)
474 {
475 return MF(amrex::convert(amrex::coarsen(fpc.ba_fine_patch, ratio), idx_type), fpc.dm_patch, ncomp, 0);
476 }
477
478 template <MultiFabLike MF>
479 requires (!std::same_as<typename MF::FABType::value_type, FArrayBox>)
480 void mf_set_domain_bndry (MF &/*mf*/, Geometry const & /*geom*/)
481 {
482 // nothing
483 }
484
485 template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
486 int
487 FillPatchTwoLevels_doit (MF& mf, IntVect const& nghost, Real time,
488 const Vector<MF*>& cmf, const Vector<Real>& ct,
489 const Vector<MF*>& fmf, const Vector<Real>& ft,
490 int scomp, int dcomp, int ncomp,
491 const Geometry& cgeom, const Geometry& fgeom,
492 BC& cbc, int cbccomp,
493 BC& fbc, int fbccomp,
494 const IntVect& ratio,
495 Interp* mapper,
496 const Vector<BCRec>& bcs, int bcscomp,
497 const PreInterpHook& pre_interp,
498 const PostInterpHook& post_interp,
499 EB2::IndexSpace const* index_space,
500 bool return_error_code = false)
501 {
502 BL_PROFILE("FillPatchTwoLevels");
503
504 int success_code = return_error_code ? 0 : -1;
505 int failure_code = 1;
506
507 if (nghost.max() > 0 || mf.getBDKey() != fmf[0]->getBDKey())
508 {
509 const InterpolaterBoxCoarsener& coarsener = mapper->BoxCoarsener(ratio);
510
511 // Test for Face-centered data. In 1D, face and nodal index types
512 // are the same, and we treat the data as nodal.
513 if ( mf.ixType() != IndexType::TheNodeType() &&
514 AMREX_D_TERM( mf.ixType().nodeCentered(0),
515 + mf.ixType().nodeCentered(1),
516 + mf.ixType().nodeCentered(2) ) == 1 )
517 {
518 if ( !dynamic_cast<Interpolater*>(mapper) ){
519 amrex::Abort("This interpolater has not yet implemented a version for face-based data");
520 }
521
522 // Convert to cell-centered MF meta-data for FPInfo.
523 MF mf_cc_dummy( amrex::convert(mf.boxArray(), IntVect::TheZeroVector()),
524 mf.DistributionMap(), ncomp, nghost, MFInfo().SetAlloc(false) );
525 MF fmf_cc_dummy( amrex::convert(fmf[0]->boxArray(), IntVect::TheZeroVector()),
526 fmf[0]->DistributionMap(), ncomp, nghost, MFInfo().SetAlloc(false) );
527
528 const FabArrayBase::FPinfo& fpc = FabArrayBase::TheFPinfo(fmf_cc_dummy, mf_cc_dummy,
529 nghost,
530 coarsener,
531 fgeom,
532 cgeom,
533 index_space);
534
535 if ( ! fpc.ba_crse_patch.empty())
536 {
537 if (return_error_code) {
538 BoxArray const& cba = amrex::convert(cmf[0]->boxArray(), IntVect(0));
539 if (!cba.contains(fpc.ba_crse_patch,cgeom.periodicity())) {
540 return failure_code;
541 }
542 }
543
544 MF mf_crse_patch = make_mf_crse_patch<MF> (fpc, ncomp, mf.boxArray().ixType());
545 // Must make sure fine exists under needed coarse faces.
546 // It stores values for the final (interior) interpolation,
547 // which is done from this fine MF that's been partially filled
548 // (with only faces overlying coarse having valid data).
549 MF mf_refined_patch = make_mf_refined_patch<MF> (fpc, ncomp, mf.boxArray().ixType(), ratio);
550 auto solve_mask = make_mf_crse_mask<iMultiFab>(fpc, ncomp, mf.boxArray().ixType(), ratio);
551
552 mf_set_domain_bndry(mf_crse_patch, cgeom);
553 if constexpr (std::is_same_v<BC,PhysBCFunctUseCoarseGhost>) {
554 cbc.fp1_src_ghost = cbc.cghost;
555 }
556 FillPatchSingleLevel(mf_crse_patch, time, cmf, ct, scomp, 0, ncomp,
557 cgeom, cbc, cbccomp);
558
559 mf_set_domain_bndry(mf_refined_patch, fgeom);
560 if constexpr (std::is_same_v<BC,PhysBCFunctUseCoarseGhost>) {
561 fbc.fp1_src_ghost = IntVect(0);
562 }
563 FillPatchSingleLevel(mf_refined_patch, time, fmf, ft, scomp, 0, ncomp,
564 fgeom, fbc, fbccomp);
565
566 // Aliased MFs, used to allow CPC caching.
567 MF mf_known( amrex::coarsen(fmf[0]->boxArray(), ratio), fmf[0]->DistributionMap(),
568 ncomp, nghost, MFInfo().SetAlloc(false) );
569 MF mf_solution( amrex::coarsen(mf_refined_patch.boxArray(), ratio), mf_refined_patch.DistributionMap(),
570 ncomp, 0, MFInfo().SetAlloc(false) );
571
572 const FabArrayBase::CPC mask_cpc( mf_solution, IntVect::TheZeroVector(),
573 mf_known, IntVect::TheZeroVector(),
574 cgeom.periodicity());
575
576 solve_mask.setVal(1); // Values to solve.
577 solve_mask.setVal(0, mask_cpc, 0, ncomp); // Known values.
578
579 detail::call_interp_hook(pre_interp, mf_crse_patch, 0, ncomp);
580
581 InterpFace(mapper, mf_crse_patch, 0, mf_refined_patch, 0, ncomp,
582 ratio, solve_mask, cgeom, fgeom, bcscomp, RunOn::Gpu, bcs);
583
584 detail::call_interp_hook(post_interp, mf_refined_patch, 0, ncomp);
585
586 bool aliasing = false;
587 for (auto const& fmf_a : fmf) {
588 aliasing = aliasing || (&mf == fmf_a);
589 }
590 if (aliasing) {
591 mf.ParallelCopyToGhost(mf_refined_patch, 0, dcomp, ncomp,
592 IntVect{0}, nghost);
593 } else {
594 mf.ParallelCopy(mf_refined_patch, 0, dcomp, ncomp,
595 IntVect{0}, nghost);
596 }
597 }
598 }
599 else
600 {
601 const FabArrayBase::FPinfo& fpc = FabArrayBase::TheFPinfo(*fmf[0], mf,
602 nghost,
603 coarsener,
604 fgeom,
605 cgeom,
606 index_space);
607
608 if ( ! fpc.ba_crse_patch.empty())
609 {
610 if (return_error_code) {
611 BoxArray const& cba = cmf[0]->boxArray();
612 if (!cba.contains(fpc.ba_crse_patch,cgeom.periodicity())) {
613 return failure_code;
614 }
615 }
616
617 MF mf_crse_patch = make_mf_crse_patch<MF>(fpc, ncomp);
618 mf_set_domain_bndry (mf_crse_patch, cgeom);
619
620 if constexpr (std::is_same_v<BC,PhysBCFunctUseCoarseGhost>) {
621 cbc.fp1_src_ghost = cbc.cghost;
622 }
623 FillPatchSingleLevel(mf_crse_patch, time, cmf, ct, scomp, 0, ncomp, cgeom, cbc, cbccomp);
624
625 MF mf_fine_patch = make_mf_fine_patch<MF>(fpc, ncomp);
626
627 detail::call_interp_hook(pre_interp, mf_crse_patch, 0, ncomp);
628
629 Box fdomain_g( amrex::convert(fgeom.Domain(),mf.ixType()) );
630 for (int i = 0; i < AMREX_SPACEDIM; ++i) {
631 if (fgeom.isPeriodic(i)) {
632 fdomain_g.grow(i, nghost[i]);
633 } else {
634 if constexpr (std::is_same_v
635 <BC, PhysBCFunctUseCoarseGhost>) {
636 fdomain_g.grow(i, fbc.nghost_outside_domain[i]);
637 }
638 }
639 }
640 FillPatchInterp(mf_fine_patch, 0, mf_crse_patch, 0,
641 ncomp, IntVect(0), cgeom, fgeom,
642 fdomain_g, ratio, mapper, bcs, bcscomp);
643
644 detail::call_interp_hook(post_interp, mf_fine_patch, 0, ncomp);
645
646 mf.ParallelCopy(mf_fine_patch, 0, dcomp, ncomp, IntVect{0}, nghost);
647 }
648 }
649 }
650
651 if constexpr(std::is_same_v<BC, PhysBCFunctUseCoarseGhost>) {
652 fbc.fp1_src_ghost = IntVect(0);
653 }
654 FillPatchSingleLevel(mf, nghost, time, fmf, ft, scomp, dcomp, ncomp,
655 fgeom, fbc, fbccomp);
656
657 return success_code;
658 }
659
660 template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
661 void
662 FillPatchTwoLevels_doit (Array<MF*, AMREX_SPACEDIM> const& mf, IntVect const& nghost, Real time,
663 const Vector<Array<MF*, AMREX_SPACEDIM> >& cmf, const Vector<Real>& ct,
664 const Vector<Array<MF*, AMREX_SPACEDIM> >& fmf, const Vector<Real>& ft,
665 int scomp, int dcomp, int ncomp,
666 const Geometry& cgeom, const Geometry& fgeom,
669 const IntVect& ratio,
670 Interp* mapper,
671 const Array<Vector<BCRec>, AMREX_SPACEDIM>& bcs, const Array<int, AMREX_SPACEDIM>& bcscomp,
672 const PreInterpHook& pre_interp,
673 const PostInterpHook& post_interp,
674 EB2::IndexSpace const* index_space)
675 {
676 BL_PROFILE("FillPatchTwoLevels (Array<MF*>)");
677
678 using FAB = typename MF::FABType::value_type;
679 using iFAB = typename iMultiFab::FABType::value_type;
680
681 AMREX_ASSERT(AMREX_D_TERM(mf[0]->ixType().nodeCentered(0),
682 && mf[1]->ixType().nodeCentered(1),
683 && mf[2]->ixType().nodeCentered(2)));
684
685 // These need to be true: (ba[0] == ba[1] == ba[2]) & (dm[0] == dm[1] == dm[2]).
686 // Debatable whether these are required, or will be enforced elsewhere prior to this func.
688 && BoxArray::SameRefs(mf[0]->boxArray(), mf[1]->boxArray()),
689 && BoxArray::SameRefs(mf[0]->boxArray(), mf[2]->boxArray())));
690/*
691 AMREX_ASSERT(AMREX_D_TERM(true,
692 && DistributionMapping::SameRefs(mf[0]->DistributionMap(), mf[1]->DistributionMap()),
693 && DistributionMapping::SameRefs(mf[0]->DistributionMap(), mf[2]->DistributionMap())));
694*/
695
696
697 // Test all of them?
698 if (nghost.max() > 0 || mf[0]->getBDKey() != fmf[0][0]->getBDKey())
699 {
700 const InterpolaterBoxCoarsener& coarsener = mapper->BoxCoarsener(ratio);
701
702 // Convert to cell-centered MF meta-data for FPInfo.
703 MF mf_cc_dummy( amrex::convert(mf[0]->boxArray(), IntVect::TheZeroVector()),
704 mf[0]->DistributionMap(), ncomp, nghost, MFInfo().SetAlloc(false) );
705 MF fmf_cc_dummy( amrex::convert(fmf[0][0]->boxArray(), IntVect::TheZeroVector()),
706 fmf[0][0]->DistributionMap(), ncomp, nghost, MFInfo().SetAlloc(false) );
707
708 const FabArrayBase::FPinfo& fpc = FabArrayBase::TheFPinfo(fmf_cc_dummy, mf_cc_dummy,
709 nghost,
710 coarsener,
711 fgeom,
712 cgeom,
713 index_space);
714
715 if ( !fpc.ba_crse_patch.empty() )
716 {
717 Array<MF, AMREX_SPACEDIM> mf_crse_patch;
718 Array<MF, AMREX_SPACEDIM> mf_refined_patch;
720
721 for (int d=0; d<AMREX_SPACEDIM; ++d)
722 {
723 mf_crse_patch[d] = make_mf_crse_patch<MF> (fpc, ncomp, mf[d]->boxArray().ixType());
724 mf_refined_patch[d] = make_mf_refined_patch<MF> (fpc, ncomp, mf[d]->boxArray().ixType(), ratio);
725 solve_mask[d] = make_mf_crse_mask<iMultiFab>(fpc, ncomp, mf[d]->boxArray().ixType(), ratio);
726
727 mf_set_domain_bndry(mf_crse_patch[d], cgeom);
728 Vector<MF*> cmf_time;
729 for (const auto & mfab : cmf)
730 { cmf_time.push_back(mfab[d]); }
731
732 FillPatchSingleLevel(mf_crse_patch[d], time, cmf_time, ct, scomp, 0, ncomp,
733 cgeom, cbc[d], cbccomp[d]);
734
735 mf_set_domain_bndry(mf_refined_patch[d], fgeom);
736 Vector<MF*> fmf_time;
737 for (const auto & mfab : fmf)
738 { fmf_time.push_back(mfab[d]); }
739
740 FillPatchSingleLevel(mf_refined_patch[d], time, fmf_time, ft, scomp, 0, ncomp,
741 fgeom, fbc[d], fbccomp[d]);
742
743
744 // Aliased MFs, used to allow CPC caching.
745 MF mf_known( amrex::coarsen(fmf[0][d]->boxArray(), ratio), fmf[0][d]->DistributionMap(),
746 ncomp, nghost, MFInfo().SetAlloc(false) );
747 MF mf_solution( amrex::coarsen(mf_refined_patch[d].boxArray(), ratio), mf_refined_patch[d].DistributionMap(),
748 ncomp, 0, MFInfo().SetAlloc(false) );
749
750 const FabArrayBase::CPC mask_cpc( mf_solution, IntVect::TheZeroVector(),
751 mf_known, IntVect::TheZeroVector(),
752 cgeom.periodicity() );
753
754 solve_mask[d].setVal(1); // Values to solve.
755 solve_mask[d].setVal(0, mask_cpc, 0, ncomp); // Known values.
756 }
757
758 int idummy=0;
759#ifdef AMREX_USE_OMP
760// bool cc = fpc.ba_crse_patch.ixType().cellCentered();
761 bool cc = false; // can anything be done to allow threading, or can the OpenMP just be removed?
762#pragma omp parallel if (cc && Gpu::notInLaunchRegion() )
763#endif
764 {
765 Vector<Array<BCRec, AMREX_SPACEDIM> > bcr(ncomp);
766 for (MFIter mfi(mf_refined_patch[0]); mfi.isValid(); ++mfi)
767 {
768 Array<FAB*, AMREX_SPACEDIM> sfab{ AMREX_D_DECL( &(mf_crse_patch[0][mfi]),
769 &(mf_crse_patch[1][mfi]),
770 &(mf_crse_patch[2][mfi]) )};
771 Array<FAB*, AMREX_SPACEDIM> dfab{ AMREX_D_DECL( &(mf_refined_patch[0][mfi]),
772 &(mf_refined_patch[1][mfi]),
773 &(mf_refined_patch[2][mfi]) )};
774 Array<iFAB*, AMREX_SPACEDIM> mfab{ AMREX_D_DECL( &(solve_mask[0][mfi]),
775 &(solve_mask[1][mfi]),
776 &(solve_mask[2][mfi]) )};
777
778 const Box& sbx_cc = amrex::convert(sfab[0]->box(), IntVect::TheZeroVector());
779 const Box& dbx_cc = amrex::convert(dfab[0]->box(), IntVect::TheZeroVector());
780
781 for (int d=0; d<AMREX_SPACEDIM; ++d)
782 {
783 Vector<BCRec> bcr_d(ncomp);
784
785 amrex::setBC(sfab[d]->box(), amrex::convert(cgeom.Domain(), mf[d]->ixType()),
786 bcscomp[d],0,ncomp,bcs[d],bcr_d);
787
788 for (int n=0; n<ncomp; ++n)
789 { bcr[n][d] = bcr_d[n]; }
790 }
791
792 pre_interp(sfab, sbx_cc, 0, ncomp);
793
794 mapper->interp_arr(sfab, 0, dfab, 0, ncomp, dbx_cc, ratio, mfab,
795 cgeom, fgeom, bcr, idummy, idummy, RunOn::Gpu);
796
797 post_interp(dfab, dbx_cc, 0, ncomp);
798 }
799 }
800
801 for (int d=0; d<AMREX_SPACEDIM; ++d)
802 {
803 bool aliasing = false;
804 for (auto const& fmf_a : fmf) {
805 aliasing = aliasing || (mf[d] == fmf_a[d]);
806 }
807 if (aliasing) {
808 mf[d]->ParallelCopyToGhost(mf_refined_patch[d], 0, dcomp, ncomp,
809 IntVect{0}, nghost);
810 } else {
811 mf[d]->ParallelCopy(mf_refined_patch[d], 0, dcomp, ncomp,
812 IntVect{0}, nghost);
813 }
814 }
815 }
816 }
817
818 for (int d=0; d<AMREX_SPACEDIM; ++d)
819 {
820 Vector<MF*> fmf_time;
821 for (auto const& ffab : fmf)
822 { fmf_time.push_back(ffab[d]); }
823
824 FillPatchSingleLevel(*mf[d], nghost, time, fmf_time, ft, scomp, dcomp, ncomp,
825 fgeom, fbc[d], fbccomp[d]);
826 }
827 }
828
829} // namespace detail
831
832template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
833void
834FillPatchTwoLevels (MF& mf, IntVect const& nghost, Real time,
835 const Vector<MF*>& cmf, const Vector<Real>& ct,
836 const Vector<MF*>& fmf, const Vector<Real>& ft,
837 int scomp, int dcomp, int ncomp,
838 const Geometry& cgeom, const Geometry& fgeom,
839 BC& cbc, int cbccomp,
840 BC& fbc, int fbccomp,
841 const IntVect& ratio,
842 Interp* mapper,
843 const Vector<BCRec>& bcs, int bcscomp,
844 const PreInterpHook& pre_interp,
845 const PostInterpHook& post_interp)
846{
847#ifdef AMREX_USE_EB
848 EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent();
849#else
850 EB2::IndexSpace const* index_space = nullptr;
851#endif
852 detail::FillPatchTwoLevels_doit(mf,nghost,time,cmf,ct,fmf,ft,
853 scomp,dcomp,ncomp,cgeom,fgeom,
854 cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp,
855 pre_interp,post_interp,index_space);
856}
857
858template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
859void
861 const Vector<MF*>& cmf, const Vector<Real>& ct,
862 const Vector<MF*>& fmf, const Vector<Real>& ft,
863 int scomp, int dcomp, int ncomp,
864 const Geometry& cgeom, const Geometry& fgeom,
865 BC& cbc, int cbccomp,
866 BC& fbc, int fbccomp,
867 const IntVect& ratio,
868 Interp* mapper,
869 const Vector<BCRec>& bcs, int bcscomp,
870 const PreInterpHook& pre_interp,
871 const PostInterpHook& post_interp)
872{
873#ifdef AMREX_USE_EB
874 EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent();
875#else
876 EB2::IndexSpace const* index_space = nullptr;
877#endif
878
879 detail::FillPatchTwoLevels_doit(mf,mf.nGrowVect(),time,cmf,ct,fmf,ft,
880 scomp,dcomp,ncomp,cgeom,fgeom,
881 cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp,
882 pre_interp,post_interp,index_space);
883}
884
885template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
886void
888 const Vector<Array<MF*, AMREX_SPACEDIM> >& cmf, const Vector<Real>& ct,
889 const Vector<Array<MF*, AMREX_SPACEDIM> >& fmf, const Vector<Real>& ft,
890 int scomp, int dcomp, int ncomp,
891 const Geometry& cgeom, const Geometry& fgeom,
894 const IntVect& ratio,
895 Interp* mapper,
896 const Array<Vector<BCRec>, AMREX_SPACEDIM>& bcs, const Array<int, AMREX_SPACEDIM>& bcscomp,
897 const PreInterpHook& pre_interp,
898 const PostInterpHook& post_interp)
899{
900#ifdef AMREX_USE_EB
901 EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent();
902#else
903 EB2::IndexSpace const* index_space = nullptr;
904#endif
905
906 detail::FillPatchTwoLevels_doit(mf,nghost,time,cmf,ct,fmf,ft,
907 scomp,dcomp,ncomp,cgeom,fgeom,
908 cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp,
909 pre_interp,post_interp,index_space);
910}
911
912template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
913void
915 const Vector<Array<MF*, AMREX_SPACEDIM> >& cmf, const Vector<Real>& ct,
916 const Vector<Array<MF*, AMREX_SPACEDIM> >& fmf, const Vector<Real>& ft,
917 int scomp, int dcomp, int ncomp,
918 const Geometry& cgeom, const Geometry& fgeom,
919 Array<BC, AMREX_SPACEDIM>& cbc, int cbccomp,
920 Array<BC, AMREX_SPACEDIM>& fbc, int fbccomp,
921 const IntVect& ratio,
922 Interp* mapper,
923 const Array<Vector<BCRec>, AMREX_SPACEDIM>& bcs, int bcscomp,
924 const PreInterpHook& pre_interp,
925 const PostInterpHook& post_interp)
926{
927#ifdef AMREX_USE_EB
928 EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent();
929#else
930 EB2::IndexSpace const* index_space = nullptr;
931#endif
932
933 Array<int, AMREX_SPACEDIM> cbccomp_arr = {AMREX_D_DECL(cbccomp,cbccomp,cbccomp)};
934 Array<int, AMREX_SPACEDIM> fbccomp_arr = {AMREX_D_DECL(fbccomp,fbccomp,fbccomp)};
935 Array<int, AMREX_SPACEDIM> bcscomp_arr = {AMREX_D_DECL(bcscomp,bcscomp,bcscomp)};
936
937 detail::FillPatchTwoLevels_doit(mf,nghost,time,cmf,ct,fmf,ft,
938 scomp,dcomp,ncomp,cgeom,fgeom,
939 cbc,cbccomp_arr,fbc,fbccomp_arr,ratio,mapper,bcs,bcscomp_arr,
940 pre_interp,post_interp,index_space);
941}
942
943template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
944void
946 const Vector<Array<MF*, AMREX_SPACEDIM> >& cmf, const Vector<Real>& ct,
947 const Vector<Array<MF*, AMREX_SPACEDIM> >& fmf, const Vector<Real>& ft,
948 int scomp, int dcomp, int ncomp,
949 const Geometry& cgeom, const Geometry& fgeom,
950 Array<BC, AMREX_SPACEDIM>& cbc, int cbccomp,
951 Array<BC, AMREX_SPACEDIM>& fbc, int fbccomp,
952 const IntVect& ratio,
953 Interp* mapper,
954 const Array<Vector<BCRec>, AMREX_SPACEDIM>& bcs, int bcscomp,
955 const PreInterpHook& pre_interp,
956 const PostInterpHook& post_interp)
957{
958#ifdef AMREX_USE_EB
959 EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent();
960#else
961 EB2::IndexSpace const* index_space = nullptr;
962#endif
963
964 Array<int, AMREX_SPACEDIM> cbccomp_arr = {AMREX_D_DECL(cbccomp,cbccomp,cbccomp)};
965 Array<int, AMREX_SPACEDIM> fbccomp_arr = {AMREX_D_DECL(fbccomp,fbccomp,fbccomp)};
966 Array<int, AMREX_SPACEDIM> bcscomp_arr = {AMREX_D_DECL(bcscomp,bcscomp,bcscomp)};
967
968 detail::FillPatchTwoLevels_doit(mf,mf[0]->nGrowVect(),time,cmf,ct,fmf,ft,
969 scomp,dcomp,ncomp,cgeom,fgeom,
970 cbc,cbccomp_arr,fbc,fbccomp_arr,ratio,mapper,bcs,bcscomp_arr,
971 pre_interp,post_interp,index_space);
972}
973
974#ifdef AMREX_USE_EB
975template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
976void
977FillPatchTwoLevels (MF& mf, IntVect const& nghost, Real time,
978 const EB2::IndexSpace& index_space,
979 const Vector<MF*>& cmf, const Vector<Real>& ct,
980 const Vector<MF*>& fmf, const Vector<Real>& ft,
981 int scomp, int dcomp, int ncomp,
982 const Geometry& cgeom, const Geometry& fgeom,
983 BC& cbc, int cbccomp,
984 BC& fbc, int fbccomp,
985 const IntVect& ratio,
986 Interp* mapper,
987 const Vector<BCRec>& bcs, int bcscomp,
988 const PreInterpHook& pre_interp,
989 const PostInterpHook& post_interp)
990{
991 detail::FillPatchTwoLevels_doit(mf,nghost,time,cmf,ct,fmf,ft,
992 scomp,dcomp,ncomp,cgeom,fgeom,
993 cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp,
994 pre_interp,post_interp,&index_space);
995}
996
997template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
998void
1000 const EB2::IndexSpace& index_space,
1001 const Vector<MF*>& cmf, const Vector<Real>& ct,
1002 const Vector<MF*>& fmf, const Vector<Real>& ft,
1003 int scomp, int dcomp, int ncomp,
1004 const Geometry& cgeom, const Geometry& fgeom,
1005 BC& cbc, int cbccomp,
1006 BC& fbc, int fbccomp,
1007 const IntVect& ratio,
1008 Interp* mapper,
1009 const Vector<BCRec>& bcs, int bcscomp,
1010 const PreInterpHook& pre_interp,
1011 const PostInterpHook& post_interp)
1012{
1013 detail::FillPatchTwoLevels_doit(mf,mf.nGrowVect(),time,cmf,ct,fmf,ft,
1014 scomp,dcomp,ncomp,cgeom,fgeom,
1015 cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp,
1016 pre_interp,post_interp,&index_space);
1017}
1018#endif
1019
1020template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
1021void
1023 const MF& cmf, int scomp, int dcomp, int ncomp,
1024 const Geometry& cgeom, const Geometry& fgeom,
1025 BC& cbc, int cbccomp,
1026 BC& fbc, int fbccomp,
1027 const IntVect& ratio,
1028 Interp* mapper,
1029 const Vector<BCRec>& bcs, int bcscomp,
1030 const PreInterpHook& pre_interp,
1031 const PostInterpHook& post_interp)
1032{
1033#ifdef AMREX_USE_EB
1034 EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent();
1035#else
1036 EB2::IndexSpace const* index_space = nullptr;
1037#endif
1038
1039 InterpFromCoarseLevel(mf,mf.nGrowVect(),time,index_space,cmf,scomp,dcomp,ncomp,cgeom,fgeom,
1040 cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp,
1041 pre_interp,post_interp);
1042}
1043
1044template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
1045void
1047 const Array<MF*, AMREX_SPACEDIM>& cmf, int scomp, int dcomp, int ncomp,
1048 const Geometry& cgeom, const Geometry& fgeom,
1049 Array<BC, AMREX_SPACEDIM>& cbc, int cbccomp,
1050 Array<BC, AMREX_SPACEDIM>& fbc, int fbccomp,
1051 const IntVect& ratio,
1052 Interp* mapper,
1053 const Array<Vector<BCRec>, AMREX_SPACEDIM>& bcs, int bcscomp,
1054 const PreInterpHook& pre_interp,
1055 const PostInterpHook& post_interp)
1056{
1057 InterpFromCoarseLevel(mf,mf[0]->nGrowVect(),time,cmf,scomp,dcomp,ncomp,cgeom,fgeom,
1058 cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp,
1059 pre_interp,post_interp);
1060}
1061
1062template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
1063void
1064InterpFromCoarseLevel (MF& mf, IntVect const& nghost, Real time,
1065 const MF& cmf, int scomp, int dcomp, int ncomp,
1066 const Geometry& cgeom, const Geometry& fgeom,
1067 BC& cbc, int cbccomp,
1068 BC& fbc, int fbccomp,
1069 const IntVect& ratio,
1070 Interp* mapper,
1071 const Vector<BCRec>& bcs, int bcscomp,
1072 const PreInterpHook& pre_interp,
1073 const PostInterpHook& post_interp)
1074{
1075#ifdef AMREX_USE_EB
1076 EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent();
1077#else
1078 EB2::IndexSpace const* index_space = nullptr;
1079#endif
1080
1081 InterpFromCoarseLevel(mf,nghost,time,index_space,cmf,scomp,dcomp,ncomp,cgeom,fgeom,
1082 cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp,
1083 pre_interp,post_interp);
1084}
1085
1086template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
1087void
1088InterpFromCoarseLevel (MF& mf, IntVect const& nghost, Real time,
1089 const EB2::IndexSpace* index_space,
1090 const MF& cmf, int scomp, int dcomp, int ncomp,
1091 const Geometry& cgeom, const Geometry& fgeom,
1092 BC& cbc, int cbccomp,
1093 BC& fbc, int fbccomp,
1094 const IntVect& ratio,
1095 Interp* mapper,
1096 const Vector<BCRec>& bcs, int bcscomp,
1097 const PreInterpHook& pre_interp,
1098 const PostInterpHook& post_interp)
1099{
1100 BL_PROFILE("InterpFromCoarseLevel");
1101
1102 using FAB = typename MF::FABType::value_type;
1103
1104 const InterpolaterBoxCoarsener& coarsener = mapper->BoxCoarsener(ratio);
1105
1106 const BoxArray& ba = mf.boxArray();
1107 const DistributionMapping& dm = mf.DistributionMap();
1108
1109 const IndexType& typ = ba.ixType();
1110
1111 BL_ASSERT(typ == cmf.boxArray().ixType());
1112
1113 Box fdomain_g( amrex::convert(fgeom.Domain(),mf.ixType()) );
1114 for (int i = 0; i < AMREX_SPACEDIM; ++i) {
1115 if (fgeom.isPeriodic(i)) {
1116 fdomain_g.grow(i, nghost[i]);
1117 } else {
1118 if constexpr (std::is_same_v<BC, PhysBCFunctUseCoarseGhost>) {
1119 fdomain_g.grow(i, fbc.nghost_outside_domain[i]);
1120 }
1121 }
1122 }
1123
1124 MF mf_crse_patch;
1125 IntVect send_ghost(0), recv_ghost(0);
1126 if constexpr (std::is_same_v<BC, PhysBCFunctUseCoarseGhost>) {
1127 mf_crse_patch.define(amrex::coarsen(ba,ratio), dm, ncomp, fbc.src_ghost);
1128 send_ghost = fbc.cghost;
1129 recv_ghost = fbc.src_ghost;
1130 } else {
1131 BoxArray ba_crse_patch(ba.size());
1132 { // TODO: later we might want to cache this
1133 for (int i = 0, N = ba.size(); i < N; ++i)
1134 {
1135 Box bx = amrex::convert(amrex::grow(ba[i],nghost), typ);
1136 bx &= fdomain_g;
1137 ba_crse_patch.set(i, coarsener.doit(bx));
1138 }
1139 }
1140
1141#ifndef AMREX_USE_EB
1142 amrex::ignore_unused(index_space);
1143#else
1144 if (index_space) {
1145 auto factory = makeEBFabFactory(index_space, cgeom, ba_crse_patch, dm,
1146 {0,0,0}, EBSupport::basic);
1147 mf_crse_patch.define(ba_crse_patch, dm, ncomp, 0, MFInfo(), *factory);
1148 } else
1149#endif
1150 {
1151 mf_crse_patch.define(ba_crse_patch, dm, ncomp, 0);
1152 }
1153 detail::mf_set_domain_bndry (mf_crse_patch, cgeom);
1154 }
1155
1156 mf_crse_patch.ParallelCopy(cmf, scomp, 0, ncomp, send_ghost, recv_ghost,
1157 cgeom.periodicity());
1158
1159 cbc(mf_crse_patch, 0, ncomp, mf_crse_patch.nGrowVect(), time, cbccomp);
1160
1161 detail::call_interp_hook(pre_interp, mf_crse_patch, 0, ncomp);
1162
1163 FillPatchInterp(mf, dcomp, mf_crse_patch, 0, ncomp, nghost, cgeom, fgeom, fdomain_g,
1164 ratio, mapper, bcs, bcscomp);
1165
1166#ifdef AMREX_USE_OMP
1167#pragma omp parallel if (Gpu::notInLaunchRegion())
1168#endif
1169 for (MFIter mfi(mf); mfi.isValid(); ++mfi)
1170 {
1171 FAB& dfab = mf[mfi];
1172 Box dfab_bx = dfab.box();
1173 dfab_bx.grow(nghost-mf.nGrowVect());
1174 const Box& dbx = dfab_bx & fdomain_g;
1175
1176 post_interp(dfab, dbx, dcomp, ncomp);
1177 }
1178
1179 fbc(mf, dcomp, ncomp, nghost, time, fbccomp);
1180}
1181
1182template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
1183void
1185 const Array<MF*, AMREX_SPACEDIM>& cmf, int scomp, int dcomp, int ncomp,
1186 const Geometry& cgeom, const Geometry& fgeom,
1187 Array<BC, AMREX_SPACEDIM>& cbc, int cbccomp,
1188 Array<BC, AMREX_SPACEDIM>& fbc, int fbccomp,
1189 const IntVect& ratio,
1190 Interp* mapper,
1191 const Array<Vector<BCRec>, AMREX_SPACEDIM>& bcs, int bcscomp,
1192 const PreInterpHook& pre_interp,
1193 const PostInterpHook& post_interp)
1194{
1195 BL_PROFILE("InterpFromCoarseLevel(array)");
1196
1197 using FAB = typename MF::FABType::value_type;
1198 using iFAB = typename iMultiFab::FABType::value_type;
1199
1200 const InterpolaterBoxCoarsener& coarsener = mapper->BoxCoarsener(ratio);
1201 const BoxArray& ba = mf[0]->boxArray();
1202 const DistributionMapping& dm = mf[0]->DistributionMap();
1203
1204 AMREX_ASSERT(AMREX_D_TERM(mf[0]->ixType().nodeCentered(0),
1205 && mf[1]->ixType().nodeCentered(1),
1206 && mf[2]->ixType().nodeCentered(2)));
1207
1208 // These need to be true: (ba[0] == ba[1] == ba[2]) & (dm[0] == dm[1] == dm[2]).
1209 // Debatable whether these are required, or will be enforced elsewhere prior to this func.
1211 && BoxArray::SameRefs(mf[0]->boxArray(), mf[1]->boxArray()),
1212 && BoxArray::SameRefs(mf[0]->boxArray(), mf[2]->boxArray())));
1213/*
1214 AMREX_ASSERT(AMREX_D_TERM(true,
1215 && DistributionMapping::SameRefs(mf[0]->DistributionMap(), mf[1]->DistributionMap()),
1216 && DistributionMapping::SameRefs(mf[0]->DistributionMap(), mf[2]->DistributionMap())));
1217*/
1218
1219 // If needed, adjust to fully overlap the coarse cells.
1220 IntVect nghost_adj = nghost;
1221 for (int d=0; d<AMREX_SPACEDIM; ++d) {
1222 if (nghost[d] % ratio[d] != 0) {
1223 nghost_adj[d] += ratio[d] - (nghost[d] % ratio[d]);
1224 }
1225 }
1226
1227 Array<MF*, AMREX_SPACEDIM> mf_local = mf;
1228 int dcomp_adj = dcomp;
1229 Array<std::unique_ptr<MF>, AMREX_SPACEDIM> mf_temp;
1230 if (! nghost.allGE(nghost_adj)) {
1231 for (int d=0; d<AMREX_SPACEDIM; ++d) {
1232 mf_temp[d] = std::make_unique<MF>(mf[d]->boxArray(),
1233 mf[d]->DistributionMap(), ncomp, nghost_adj);
1234 mf_local[d] = mf_temp[d].get();
1235 }
1236 dcomp_adj = 0;
1237 }
1238
1239 // Create a cell-centered boxArray of the region to interp.
1240 // Convert this boxArray and domain as needed.
1241 Box fdomain = amrex::convert(fgeom.Domain(), IntVect::TheZeroVector());
1242 Box fdomain_g(fdomain);
1243 for (int d = 0; d < AMREX_SPACEDIM; ++d) {
1244 if (fgeom.isPeriodic(d)) {
1245 fdomain_g.grow(d,nghost_adj[d]);
1246 }
1247 }
1248
1249 // Build patches, using domain to account for periodic bcs.
1250 BoxArray ba_crse_patch(ba.size());
1251 { // TODO: later we might want to cache this
1252 for (int i = 0, N = ba.size(); i < N; ++i)
1253 {
1254 Box bx = amrex::convert(amrex::grow(ba[i], nghost_adj), IntVect::TheZeroVector());
1255 bx &= fdomain_g;
1256 ba_crse_patch.set(i, coarsener.doit(bx));
1257 }
1258 }
1259
1260 Array<MF, AMREX_SPACEDIM> mf_crse_patch;
1261 for (int d = 0; d<AMREX_SPACEDIM; ++d)
1262 {
1263 IndexType typ = mf[d]->boxArray().ixType();
1264 BoxArray ba_crse_idxed = amrex::convert(ba_crse_patch, typ);
1265
1266#ifdef AMREX_USE_EB
1267 auto crse_factory = makeEBFabFactory(cgeom, ba_crse_idxed, dm, {0,0,0}, EBSupport::basic);
1268 mf_crse_patch[d].define(ba_crse_idxed, dm, ncomp, 0, MFInfo(), *crse_factory);
1269#else
1270 mf_crse_patch[d].define(ba_crse_idxed, dm, ncomp, 0);
1271#endif
1272 detail::mf_set_domain_bndry(mf_crse_patch[d], cgeom);
1273
1274 mf_crse_patch[d].ParallelCopy(*(cmf[d]), scomp, 0, ncomp, cgeom.periodicity());
1275 cbc[d](mf_crse_patch[d], 0, ncomp, mf_crse_patch[d].nGrowVect(), time, cbccomp);
1276 }
1277
1278 int idummy1=0, idummy2=0;
1279#ifdef AMREX_USE_OMP
1280#pragma omp parallel if (Gpu::notInLaunchRegion())
1281#endif
1282 {
1284
1285 // Empty containers describing that all points must be solved (no mask).
1286 Array<iFAB*, AMREX_SPACEDIM> mfab{ AMREX_D_DECL( nullptr, nullptr, nullptr ) };
1287
1288 for (MFIter mfi(mf_crse_patch[0]); mfi.isValid(); ++mfi)
1289 {
1290 Array<FAB*, AMREX_SPACEDIM> sfab{ AMREX_D_DECL( &(mf_crse_patch[0][mfi]),
1291 &(mf_crse_patch[1][mfi]),
1292 &(mf_crse_patch[2][mfi]) )};
1293 Array<FAB*, AMREX_SPACEDIM> dfab{ AMREX_D_DECL( &(*mf_local[0])[mfi],
1294 &(*mf_local[1])[mfi],
1295 &(*mf_local[2])[mfi] )};
1296
1297 const Box& sbx_cc = amrex::convert(sfab[0]->box(), IntVect::TheZeroVector());
1298 // Interpolate only over the region the coarse patch was built from.
1299 Box dfab_cc = amrex::convert(amrex::grow(ba[mfi.index()], nghost_adj),
1301 const Box& dbx_cc = dfab_cc & fdomain_g;
1302
1303 for (int d=0; d<AMREX_SPACEDIM; ++d)
1304 {
1305 Vector<BCRec> bcr_d(ncomp);
1306
1307 amrex::setBC(sfab[d]->box(),
1308 amrex::convert(cgeom.Domain(), sfab[d]->box().ixType()),
1309 bcscomp,0,ncomp,bcs[d],bcr_d);
1310
1311 for (int n=0; n<ncomp; ++n)
1312 { bcr[n][d] = bcr_d[n]; }
1313 }
1314
1315 pre_interp(sfab, sbx_cc, 0, ncomp);
1316
1317 mapper->interp_arr(sfab, 0, dfab, dcomp_adj, ncomp, dbx_cc, ratio, mfab,
1318 cgeom, fgeom, bcr, idummy1, idummy2, RunOn::Gpu);
1319
1320 post_interp(dfab, dbx_cc, dcomp_adj, ncomp);
1321 }
1322 }
1323
1324 for (int d=0; d<AMREX_SPACEDIM; ++d)
1325 {
1326 if (mf[d] != mf_local[d]) {
1327 amrex::Copy(*mf[d], *mf_local[d], 0, dcomp, ncomp, nghost);
1328 }
1329
1330 fbc[d](*mf[d], dcomp, ncomp, nghost, time, fbccomp);
1331 }
1332}
1333
1334template <FabArrayType MF, typename Interp>
1335void
1336InterpFromCoarseLevel (MF& mf, IntVect const& nghost,
1337 IntVect const& nghost_outside_domain,
1338 const MF& cmf, int scomp, int dcomp, int ncomp,
1339 const Geometry& cgeom, const Geometry& fgeom,
1340 const IntVect& ratio, Interp* mapper,
1341 const Vector<BCRec>& bcs, int bcscomp)
1342{
1343 PhysBCFunctUseCoarseGhost erfbc(cmf,nghost,nghost_outside_domain,ratio,mapper);
1344 InterpFromCoarseLevel(mf, nghost, Real(0.0), cmf, scomp, dcomp, ncomp,
1345 cgeom, fgeom, erfbc, 0, erfbc, 0, ratio, mapper,
1346 bcs, bcscomp);
1347}
1348
1349template <FabArrayType MF>
1350void
1351FillPatchSingleLevel (MF& mf, IntVect const& nghost, Real time,
1352 const Vector<MF*>& smf, IntVect const& snghost,
1353 const Vector<Real>& stime, int scomp, int dcomp, int ncomp,
1354 const Geometry& geom)
1355{
1356 PhysBCFunctUseCoarseGhost erfbc(snghost);
1357 FillPatchSingleLevel(mf, nghost, time, smf, stime, scomp, dcomp, ncomp, geom,
1358 erfbc, 0);
1359}
1360
1361template <FabArrayType MF, typename Interp>
1362void
1363FillPatchTwoLevels (MF& mf, IntVect const& nghost,
1364 IntVect const& nghost_outside_domain, Real time,
1365 const Vector<MF*>& cmf, const Vector<Real>& ct,
1366 const Vector<MF*>& fmf, const Vector<Real>& ft,
1367 int scomp, int dcomp, int ncomp,
1368 const Geometry& cgeom, const Geometry& fgeom,
1369 const IntVect& ratio, Interp* mapper,
1370 const Vector<BCRec>& bcs, int bcscomp)
1371{
1372 AMREX_ALWAYS_ASSERT_WITH_MESSAGE(nghost_outside_domain == 0, "TODO");
1373 PhysBCFunctUseCoarseGhost erfbc(*cmf[0], nghost, nghost_outside_domain, ratio,
1374 mapper);
1375 FillPatchTwoLevels(mf, nghost, time, cmf, ct, fmf, ft, scomp, dcomp, ncomp,
1376 cgeom, fgeom, erfbc, 0, erfbc, 0, ratio, mapper,
1377 bcs, bcscomp);
1378}
1379
1380template <FabArrayType MF, typename BC, typename Interp>
1381void
1382FillPatchNLevels (MF& mf, int level, const IntVect& nghost, Real time,
1383 const Vector<Vector<MF*>>& smf, const Vector<Vector<Real>>& st,
1384 int scomp, int dcomp, int ncomp,
1385 const Vector<Geometry>& geom,
1386 Vector<BC>& bc, int bccomp,
1387 const Vector<IntVect>& ratio,
1388 Interp* mapper,
1389 const Vector<BCRec>& bcr, int bcrcomp)
1390{
1391 BL_PROFILE("FillPatchNLevels");
1392
1393 // FillPatchTwolevels relies on that mf's valid region is inside the
1394 // domain at periodic boundaries. But when we create coarsen boxarray
1395 // using mapper->CoarseBox, the resulting boxarray might violate the
1396 // requirement. If that happens, we need to create a second version of
1397 // the boxarray that is safe for FillPatchTwolevels.
1398
1399 auto get_clayout = [&] () -> std::tuple<BoxArray,BoxArray,DistributionMapping>
1400 {
1401 if (level == 0) {
1402 return std::make_tuple(BoxArray(),BoxArray(),DistributionMapping());
1403 } else {
1404 BoxArray const& ba = mf.boxArray();
1405 auto const& typ = ba.ixType();
1406 std::map<int,Vector<Box>> extra_boxes_map;
1407 BoxList cbl(typ);
1408 cbl.reserve(ba.size());
1409 for (int i = 0, N = int(ba.size()); i < N; ++i) {
1410 Box const& cbox = mapper->CoarseBox(amrex::grow(ba[i],nghost),ratio[level-1]);
1411 cbl.push_back(cbox);
1412 Box gdomain = geom[level-1].growNonPeriodicDomain(cbox.length());
1413 gdomain.convert(typ);
1414 if (!gdomain.contains(cbox)) {
1415 auto& extra_boxes = extra_boxes_map[i];
1416 auto const& pshift = geom[level-1].periodicity().shiftIntVect();
1417 for (auto const& piv : pshift) {
1418 auto const& ibox = amrex::shift(cbox,piv) & gdomain;
1419 if (ibox.ok()) {
1420 extra_boxes.push_back(ibox);
1421 }
1422 }
1423 }
1424 }
1425
1426 BoxArray cba2;
1428 if (!extra_boxes_map.empty()) {
1429 BoxList cbl2 = cbl;
1430 auto& lbox = cbl2.data();
1431 DistributionMapping const& dm = mf.DistributionMap();
1432 Vector<int> procmap2 = dm.ProcessorMap();
1433 for (auto const& [i, vb] : extra_boxes_map) {
1434 lbox[i] = vb[0];
1435 for (int j = 1, nj = int(vb.size()); j < nj; ++j) {
1436 lbox.push_back(vb[j]);
1437 procmap2.push_back(dm[i]);
1438 }
1439 }
1440 cba2 = BoxArray(std::move(cbl2));
1441 dm2 = DistributionMapping(std::move(procmap2));
1442 }
1443
1444 return std::make_tuple(BoxArray(std::move(cbl)), cba2, dm2);
1445 }
1446 };
1447
1448#ifdef AMREX_USE_EB
1449 EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent();
1450#else
1451 EB2::IndexSpace const* index_space = nullptr;
1452#endif
1453
1454 AMREX_ALWAYS_ASSERT(level < int(geom.size()) &&
1455 level < int(bc.size()) &&
1456 level < int(ratio.size()+1));
1457 if (level == 0) {
1458 FillPatchSingleLevel(mf, nghost, time, smf[0], st[0], scomp, dcomp, ncomp, geom[0],
1459 bc[0], bccomp);
1460 } else if (level >= int(smf.size()))
1461 {
1462 auto const& [ba1, ba2, dm2] = get_clayout();
1463 MF cmf1, cmf2;
1464#ifdef AMREX_USE_EB
1465 if (index_space) {
1466 auto factory = makeEBFabFactory(index_space, geom[level-1], ba1,
1467 mf.DistributionMap(), {0,0,0},
1469 cmf1.define(ba1, mf.DistributionMap(), ncomp, 0, MFInfo(), *factory);
1470 if (!ba2.empty()) {
1471 auto factory2 = makeEBFabFactory(index_space, geom[level-1], ba2,
1472 dm2, {0,0,0},
1474 cmf2.define(ba2, dm2, ncomp, 0, MFInfo(), *factory2);
1475 }
1476 } else
1477#endif
1478 {
1479 cmf1.define(ba1, mf.DistributionMap(), ncomp, 0);
1480 if (!ba2.empty()) {
1481 cmf2.define(ba2, dm2, ncomp, 0);
1482 }
1483 }
1484
1485 MF* p_mf_inside = (ba2.empty()) ? &cmf1 : &cmf2;
1486 FillPatchNLevels(*p_mf_inside, level-1, IntVect(0), time, smf, st, scomp, 0, ncomp,
1487 geom, bc, bccomp, ratio, mapper, bcr, bcrcomp);
1488 if (&cmf1 != p_mf_inside) {
1489 cmf1.ParallelCopy(*p_mf_inside, geom[level-1].periodicity());
1490 }
1491 Box domain_g = geom[level].growPeriodicDomain(nghost);
1492 domain_g.convert(mf.ixType());
1493 FillPatchInterp(mf, dcomp, cmf1, 0, ncomp, nghost, geom[level-1], geom[level],
1494 domain_g, ratio[level-1], mapper, bcr, bcrcomp);
1495 } else {
1497 int error_code = detail::FillPatchTwoLevels_doit(mf, nghost, time,
1498 smf[level-1], st[level-1],
1499 smf[level ], st[level ],
1500 scomp, dcomp, ncomp,
1501 geom[level-1], geom[level],
1502 bc[level-1], bccomp,
1503 bc[level ], bccomp,
1504 ratio[level-1], mapper, bcr, bcrcomp,
1505 hook, hook, index_space, true);
1506 if (error_code == 0) { return; }
1507
1508 auto const& [ba1, ba2, dm2] = get_clayout();
1509 MF cmf_tmp;
1510#ifdef AMREX_USE_EB
1511 if (index_space) {
1512 if (ba2.empty()) {
1513 auto factory = makeEBFabFactory(index_space, geom[level-1], ba1,
1514 mf.DistributionMap(), {0,0,0},
1516 cmf_tmp.define(ba1, mf.DistributionMap(), ncomp, 0, MFInfo(), *factory);
1517 } else {
1518 auto factory = makeEBFabFactory(index_space, geom[level-1], ba2,
1519 dm2, {0,0,0},
1521 cmf_tmp.define(ba2, dm2, ncomp, 0, MFInfo(), *factory);
1522 }
1523 } else
1524#endif
1525 {
1526 if (ba2.empty()) {
1527 cmf_tmp.define(ba1, mf.DistributionMap(), ncomp, 0);
1528 } else {
1529 cmf_tmp.define(ba2, dm2, ncomp, 0);
1530 }
1531 }
1532
1533 FillPatchNLevels(cmf_tmp, level-1, IntVect(0), time, smf, st, scomp, 0, ncomp,
1534 geom, bc, bccomp, ratio, mapper, bcr, bcrcomp);
1535
1536 Vector<MF*> cmf{&cmf_tmp};
1537 Vector<MF*> fmf = smf[level];
1538 Vector<MF> fmf_raii;
1539 if (scomp != 0) {
1540 for (auto const* p : fmf) {
1541 fmf_raii.emplace_back(*p, amrex::make_alias, scomp, ncomp);
1542 }
1543 fmf.clear();
1544 for (auto& a : fmf_raii) {
1545 fmf.push_back(&a);
1546 }
1547 }
1548
1549 detail::FillPatchTwoLevels_doit(mf, nghost, time,
1550 cmf, {time},
1551 fmf, st[level],
1552 0, dcomp, ncomp,
1553 geom[level-1], geom[level],
1554 bc[level-1], bccomp,
1555 bc[level ], bccomp,
1556 ratio[level-1], mapper, bcr, bcrcomp,
1557 hook, hook, index_space);
1558 }
1559}
1560
1561}
1562
1563#endif
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:593
#define AMREX_ALWAYS_ASSERT_WITH_MESSAGE(EX, MSG)
Definition AMReX_BLassert.H:49
#define BL_ASSERT(EX)
Definition AMReX_BLassert.H:39
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
#define AMREX_HOST_DEVICE_PARALLEL_FOR_4D(...)
Definition AMReX_GpuLaunchMacrosC.nolint.H:111
while parser_exe_t p
Definition AMReX_Parser_Exe_Body.H:33
#define AMREX_D_TERM(a, b, c)
Definition AMReX_SPACE.H:172
#define AMREX_D_DECL(a, b, c)
Definition AMReX_SPACE.H:171
Reference-counted collection of Boxes.
Definition AMReX_BoxArray.H:681
IndexType ixType() const noexcept
Return index type of this BoxArray.
Definition AMReX_BoxArray.H:1268
static bool SameRefs(const BoxArray &lhs, const BoxArray &rhs)
whether two BoxArrays share the same data
Definition AMReX_BoxArray.H:1251
Long size() const noexcept
Return the number of boxes in the BoxArray.
Definition AMReX_BoxArray.H:758
void set(int i, const Box &ibox)
Set element i to ibox if no coarsening transformer is active.
Definition AMReX_BoxArray.cpp:894
A list of Boxes sharing a common IndexType.
Definition AMReX_BoxList.H:109
Vector< Box > & data() noexcept
Returns a reference to the Vector<Box>.
Definition AMReX_BoxList.H:373
void reserve(std::size_t n)
Reserve storage for at least n Boxes.
Definition AMReX_BoxList.H:148
void push_back(const Box &bn)
Append a Box to this BoxList.
Definition AMReX_BoxList.H:151
__host__ __device__ BoxND & grow(int i) noexcept
Grow in all directions by i cells (negative shrinks).
Definition AMReX_Box.H:668
__host__ __device__ IntVectND< dim > length() const noexcept
Return the length of the BoxND.
Definition AMReX_Box.H:167
__host__ __device__ BoxND & convert(IndexTypeND< dim > typ) noexcept
Convert the BoxND from the current type into the argument type. This may change the BoxND coordinates...
Definition AMReX_Box.H:1008
__host__ __device__ bool contains(const IntVectND< dim > &p) const noexcept
Return true if argument is contained within BoxND.
Definition AMReX_Box.H:233
__host__ __device__ IndexTypeND< dim > ixType() const noexcept
Return the indexing type.
Definition AMReX_Box.H:148
__host__ __device__ BoxND & refine(int ref_ratio) noexcept
Refine BoxND by given (positive) refinement ratio. NOTE: if type(dir) = CELL centered: lo <- lo*ratio...
Definition AMReX_Box.H:730
__host__ __device__ bool ok() const noexcept
Return true if high bounds are >= low bounds and the index type is valid.
Definition AMReX_Box.H:229
Calculates the distribution of FABs to MPI processes.
Definition AMReX_DistributionMapping.H:51
const Vector< int > & ProcessorMap() const noexcept
Returns a constant reference to the mapping of boxes in the underlying BoxArray to the CPU that holds...
Definition AMReX_DistributionMapping.cpp:49
Definition AMReX_EB2.H:28
static const FPinfo & TheFPinfo(const FabArrayBase &srcfa, const FabArrayBase &dstfa, const IntVect &dstng, const BoxConverter &coarsener, const Geometry &fgeom, const Geometry &cgeom, const EB2::IndexSpace *)
Definition AMReX_FabArrayBase.cpp:2075
Rectangular problem domain geometry.
Definition AMReX_Geometry.H:87
const Box & Domain() const noexcept
Returns our rectangular domain.
Definition AMReX_Geometry.H:246
Periodicity periodicity() const noexcept
Return the Periodicity based on the length of the domain.
Definition AMReX_Geometry.H:426
bool isPeriodic(int dir) const noexcept
Is the domain periodic in the specified direction?
Definition AMReX_Geometry.H:399
__host__ __device__ constexpr CellIndex ixType(int dir) const noexcept
Returns the CellIndex in direction dir.
Definition AMReX_IndexType.H:117
__host__ static __device__ constexpr IndexTypeND< dim > TheNodeType() noexcept
Definition AMReX_IndexType.H:160
__host__ __device__ constexpr int min() const noexcept
minimum (no absolute values) value
Definition AMReX_IntVect.H:324
__host__ __device__ constexpr bool allGE(const IntVectND< dim > &rhs) const noexcept
Returns true if this is greater than or equal to argument for all components. NOTE: This is NOT a str...
Definition AMReX_IntVect.H:542
__host__ static __device__ constexpr IntVectND< dim > TheZeroVector() noexcept
Definition AMReX_IntVect.H:771
__host__ __device__ constexpr bool allLE(const IntVectND< dim > &rhs) const noexcept
Returns true if this is less than or equal to argument for all components. NOTE: This is NOT a strict...
Definition AMReX_IntVect.H:492
Definition AMReX_InterpBase.H:39
Definition AMReX_InterpBase.H:22
Box doit(const Box &fine) const override
Apply the coarse-box logic to the supplied fine box.
Definition AMReX_InterpBase.cpp:12
Virtual base class for interpolaters.
Definition AMReX_Interpolater.H:32
Definition AMReX_MFInterpolater.H:20
Iterator for looping ever tiles and boxes of amrex::FabArray based containers.
Definition AMReX_MFIter.H:88
bool isValid() const noexcept
Is the iterator valid i.e. is it associated with a FAB?
Definition AMReX_MFIter.H:176
Definition AMReX_PhysBCFunct.H:127
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:29
Long size() const noexcept
Definition AMReX_Vector.H:54
amrex_real Real
Floating Point Type for Fields.
Definition AMReX_REAL.H:80
std::unique_ptr< EBFArrayBoxFactory > makeEBFabFactory(const Geometry &a_geom, const BoxArray &a_ba, const DistributionMapping &a_dm, const Vector< int > &a_ngrow, EBSupport a_support)
Definition AMReX_EBFabFactory.cpp:301
__host__ __device__ BoxND< dim > convert(const BoxND< dim > &b, const IntVectND< dim > &typ) noexcept
Return a copy of b converted to the nodal flags typ.
Definition AMReX_Box.H:1632
__host__ __device__ BoxND< dim > minBox(const BoxND< dim > &b1, const BoxND< dim > &b2) noexcept
Return the minimal BoxND containing both b1 and b2.
Definition AMReX_Box.H:1923
__host__ __device__ BoxND< dim > coarsen(const BoxND< dim > &b, int ref_ratio) noexcept
Return a copy of b coarsened by the isotropic ratio ref_ratio.
Definition AMReX_Box.H:1471
__host__ __device__ BoxND< dim > shift(const BoxND< dim > &b, int dir, int nzones) noexcept
Return a copy of b shifted by nzones cells in direction dir.
Definition AMReX_Box.H:1550
__host__ __device__ BoxND< dim > grow(const BoxND< dim > &b, int i) noexcept
Return a copy of b grown uniformly by i cells in every direction.
Definition AMReX_Box.H:1328
__host__ __device__ BoxND< dim > refine(const BoxND< dim > &b, int ref_ratio) noexcept
Return a copy of b refined by the isotropic ratio ref_ratio.
Definition AMReX_Box.H:1512
std::array< T, N > Array
Definition AMReX_Array.H:31
Arena * The_Async_Arena()
Definition AMReX_Arena.cpp:849
__host__ __device__ bool almostEqual(T x, T y, int ulp=2)
Definition AMReX_Algorithm.H:140
const IndexSpace * TopIndexSpaceIfPresent() noexcept
Return the top IndexSpace if one has been built (nullptr otherwise).
Definition AMReX_EB2.cpp:99
int TeamSize() noexcept
Definition AMReX_ParallelDescriptor.H:310
Definition AMReX_Amr.cpp:50
@ make_alias
Definition AMReX_MakeType.H:7
__host__ __device__ void ignore_unused(const Ts &...)
No-op helper that marks variables as intentionally unused.
Definition AMReX.H:273
void Copy(FabArray< DFAB > &dst, FabArray< SFAB > const &src, int srccomp, int dstcomp, int numcomp, int nghost)
Definition AMReX_FabArray.H:192
@ F
Definition AMReX_Order.H:7
BoxArray const & boxArray(FabArrayBase const &fa)
Convenience wrapper that forwards to fa.boxArray().
Definition AMReX_FabArrayBase.cpp:2990
DistributionMapping const & DistributionMap(FabArrayBase const &fa)
Convenience wrapper that forwards to fa.DistributionMap().
Definition AMReX_FabArrayBase.cpp:2995
RunOn
Definition AMReX_GpuControl.H:65
@ Gpu
Definition AMReX_GpuControl.H:65
bool ProperlyNested(const IntVect &ratio, const IntVect &blocking_factor, int ngrow, const IndexType &boxType, Interp *mapper)
Test if AMR grids are properly nested.
Definition AMReX_FillPatchUtil_I.H:35
BoxND< 3 > Box
Box is an alias for amrex::BoxND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:35
@ basic
EBCellFlag.
Definition AMReX_EBSupport.H:16
void InterpFace(Interp *interp, MF const &mf_crse_patch, int crse_comp, MF &mf_refined_patch, int fine_comp, int ncomp, const IntVect &ratio, const iMF &solve_mask, const Geometry &crse_geom, const Geometry &fine_geom, int bcscomp, RunOn gpu_or_cpu, const Vector< BCRec > &bcs)
Definition AMReX_FillPatchUtil_I.H:315
void FillPatchSingleLevel(MF &mf, IntVect const &nghost, Real time, const Vector< MF * > &smf, const Vector< Real > &stime, int scomp, int dcomp, int ncomp, const Geometry &geom, BC &physbcf, int bcfcomp)
FillPatch with data from the current level.
Definition AMReX_FillPatchUtil_I.H:75
IndexTypeND< 3 > IndexType
IndexType is an alias for amrex::IndexTypeND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:41
IntVect nGrowVect(FabArrayBase const &fa)
Convenience wrapper that forwards to fa.nGrowVect().
Definition AMReX_FabArrayBase.cpp:2985
bool TilingIfNotGPU() noexcept
Definition AMReX_MFIter.H:12
void InterpFromCoarseLevel(MF &mf, Real time, const MF &cmf, int scomp, int dcomp, int ncomp, const Geometry &cgeom, const Geometry &fgeom, BC &cbc, int cbccomp, BC &fbc, int fbccomp, const IntVect &ratio, Interp *mapper, const Vector< BCRec > &bcs, int bcscomp, const PreInterpHook &pre_interp={}, const PostInterpHook &post_interp={})
Fill with interpolation of coarse level data.
Definition AMReX_FillPatchUtil_I.H:1022
IntVectND< 3 > IntVect
IntVect is an alias for amrex::IntVectND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:38
void setBC(const Box &bx, const Box &domain, int src_comp, int dest_comp, int ncomp, const Vector< BCRec > &bc_dom, Vector< BCRec > &bcr) noexcept
Populate a span of BCRec objects based on a domain record.
Definition AMReX_BCRec.cpp:8
void Abort(const std::string &msg)
Print a fatal-error message to stderr and abort execution.
Definition AMReX.cpp:244
void FillPatchTwoLevels(MF &mf, IntVect const &nghost, Real time, const Vector< MF * > &cmf, const Vector< Real > &ct, const Vector< MF * > &fmf, const Vector< Real > &ft, int scomp, int dcomp, int ncomp, const Geometry &cgeom, const Geometry &fgeom, BC &cbc, int cbccomp, BC &fbc, int fbccomp, const IntVect &ratio, Interp *mapper, const Vector< BCRec > &bcs, int bcscomp, const PreInterpHook &pre_interp={}, const PostInterpHook &post_interp={})
FillPatch with data from the current level and the level below.
Definition AMReX_FillPatchUtil_I.H:834
void FillPatchInterp(MultiFab &mf_fine_patch, int fcomp, MultiFab const &mf_crse_patch, int ccomp, int ncomp, IntVect const &ng, const Geometry &cgeom, const Geometry &fgeom, Box const &dest_domain, const IntVect &ratio, MFInterpolater *mapper, const Vector< BCRec > &bcs, int bcscomp)
Helper that applies a MFInterpolater to fill a fine patch from a coarse patch.
Definition AMReX_FillPatchUtil.cpp:138
void FillPatchNLevels(MF &mf, int level, const IntVect &nghost, Real time, const Vector< Vector< MF * > > &smf, const Vector< Vector< Real > > &st, int scomp, int dcomp, int ncomp, const Vector< Geometry > &geom, Vector< BC > &bc, int bccomp, const Vector< IntVect > &ratio, Interp *mapper, const Vector< BCRec > &bcr, int bcrcomp)
FillPatch with data from AMR levels.
Definition AMReX_FillPatchUtil_I.H:1382
FabArray memory allocation information.
Definition AMReX_FabArray.H:73
Definition AMReX_FillPatchUtil.H:39