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 MF raii;
106 MF * dmf;
107 int destcomp;
108 bool sameba;
109 if (mf.boxArray() == smf[0]->boxArray() &&
110 mf.DistributionMap() == smf[0]->DistributionMap())
111 {
112 dmf = &mf;
113 destcomp = dcomp;
114 sameba = true;
115 } else {
116 raii.define(smf[0]->boxArray(), smf[0]->DistributionMap(), ncomp, src_ghost,
117 MFInfo(), smf[0]->Factory());
118
119 dmf = &raii;
120 destcomp = 0;
121 sameba = false;
122 }
123
124 if ((dmf != smf[0] && dmf != smf[1]) || scomp != dcomp)
125 {
126 IntVect interp_ghost(0);
127 if constexpr (std::is_same_v<BC,PhysBCFunctUseCoarseGhost>) {
128 interp_ghost = physbcf.fp1_src_ghost;
129 if (sameba) {
130 interp_ghost.min(nghost);
131 }
132 }
133#ifdef AMREX_USE_OMP
134#pragma omp parallel if (Gpu::notInLaunchRegion())
135#endif
136 for (MFIter mfi(*dmf,TilingIfNotGPU()); mfi.isValid(); ++mfi)
137 {
138 const Box& bx = mfi.growntilebox(interp_ghost);
139 const Real t0 = stime[0];
140 const Real t1 = stime[1];
141 auto const sfab0 = smf[0]->array(mfi);
142 auto const sfab1 = smf[1]->array(mfi);
143 auto dfab = dmf->array(mfi);
144
145 if (time == t0)
146 {
147 AMREX_HOST_DEVICE_PARALLEL_FOR_4D ( bx, ncomp, i, j, k, n,
148 {
149 dfab(i,j,k,n+destcomp) = sfab0(i,j,k,n+scomp);
150 });
151 }
152 else if (time == t1)
153 {
154 AMREX_HOST_DEVICE_PARALLEL_FOR_4D ( bx, ncomp, i, j, k, n,
155 {
156 dfab(i,j,k,n+destcomp) = sfab1(i,j,k,n+scomp);
157 });
158 }
159 else if (! amrex::almostEqual(t0,t1))
160 {
161 Real alpha = (t1-time)/(t1-t0);
162 Real beta = (time-t0)/(t1-t0);
163 AMREX_HOST_DEVICE_PARALLEL_FOR_4D ( bx, ncomp, i, j, k, n,
164 {
165 dfab(i,j,k,n+destcomp) = alpha*sfab0(i,j,k,n+scomp)
166 + beta*sfab1(i,j,k,n+scomp);
167 });
168 }
169 else
170 {
171 AMREX_HOST_DEVICE_PARALLEL_FOR_4D ( bx, ncomp, i, j, k, n,
172 {
173 dfab(i,j,k,n+destcomp) = sfab0(i,j,k,n+scomp);
174 });
175 }
176 }
177 }
178
179 if (sameba)
180 {
181 // Note that when sameba is true mf's BoxArray is nonoverlapping.
182 // So FillBoundary is safe.
183 mf.FillBoundary(dcomp, ncomp, nghost, geom.periodicity());
184 }
185 else
186 {
187 mf.ParallelCopy(*dmf, 0, dcomp, ncomp, src_ghost, nghost, geom.periodicity());
188 }
189 }
190 else {
191 amrex::Abort("FillPatchSingleLevel: high-order interpolation in time not implemented yet");
192 }
193
194 physbcf(mf, dcomp, ncomp, nghost, time, bcfcomp);
195}
196
214void FillPatchInterp (MultiFab& mf_fine_patch, int fcomp, MultiFab const& mf_crse_patch, int ccomp,
215 int ncomp, IntVect const& ng, const Geometry& cgeom, const Geometry& fgeom,
216 Box const& dest_domain, const IntVect& ratio,
217 MFInterpolater* mapper, const Vector<BCRec>& bcs, int bcscomp);
218
219template <FabArrayType MF, typename Interp>
220requires (!std::is_same_v<Interp, MFInterpolater>)
221void
222FillPatchInterp (MF& mf_fine_patch, int fcomp, MF const& mf_crse_patch, int ccomp,
223 int ncomp, IntVect const& ng, const Geometry& cgeom, const Geometry& fgeom,
224 Box const& dest_domain, const IntVect& ratio,
225 Interp* mapper, const Vector<BCRec>& bcs, int bcscomp)
226{
227 BL_PROFILE("FillPatchInterp(Fab)");
228
229 Box const& cdomain = amrex::convert(cgeom.Domain(), mf_fine_patch.ixType());
230 int idummy=0;
231#ifdef AMREX_USE_OMP
232#pragma omp parallel if (Gpu::notInLaunchRegion())
233#endif
234 {
235 Vector<BCRec> bcr(ncomp);
236 for (MFIter mfi(mf_fine_patch); mfi.isValid(); ++mfi)
237 {
238 auto& sfab = mf_crse_patch[mfi];
239 const Box& sbx = sfab.box();
240
241 auto& dfab = mf_fine_patch[mfi];
242 Box const& dbx = amrex::grow(mfi.validbox(),ng) & dest_domain;
243
244 amrex::setBC(sbx,cdomain,bcscomp,0,ncomp,bcs,bcr);
245 mapper->interp(sfab, ccomp, dfab, fcomp, ncomp, dbx, ratio,
246 cgeom, fgeom, bcr, idummy, idummy, RunOn::Gpu);
247 }
248 }
249}
250
251template <FabArrayType MF>
252void
253FillPatchInterp (MF& mf_fine_patch, int fcomp, MF const& mf_crse_patch, int ccomp,
254 int ncomp, IntVect const& ng, const Geometry& cgeom, const Geometry& fgeom,
255 Box const& dest_domain, const IntVect& ratio,
256 InterpBase* mapper, const Vector<BCRec>& bcs, int bcscomp)
257{
258 if (dynamic_cast<MFInterpolater*>(mapper)) {
259 FillPatchInterp(mf_fine_patch, fcomp, mf_crse_patch, ccomp,
260 ncomp, ng, cgeom, fgeom, dest_domain, ratio,
261 static_cast<MFInterpolater*>(mapper), bcs, bcscomp);
262 } else if (dynamic_cast<Interpolater*>(mapper)) {
263 FillPatchInterp(mf_fine_patch, fcomp, mf_crse_patch, ccomp,
264 ncomp, ng, cgeom, fgeom, dest_domain, ratio,
265 static_cast<Interpolater*>(mapper), bcs, bcscomp);
266 } else {
267 amrex::Abort("FillPatchInterp: unknown InterpBase");
268 }
269}
270
271template <FabArrayType MF, typename iMF, typename Interp>
272requires (!std::is_same_v<Interp, MFInterpolater>)
273void
274InterpFace (Interp *interp,
275 MF const& mf_crse_patch, int crse_comp,
276 MF& mf_refined_patch, int fine_comp,
277 int ncomp, const IntVect& ratio,
278 const iMF& solve_mask, const Geometry& crse_geom, const Geometry& fine_geom,
279 int bcscomp, RunOn gpu_or_cpu,
280 const Vector<BCRec>& bcs)
281{
282 Vector<BCRec> bcr(ncomp);
283 Box const& cdomain = amrex::convert(crse_geom.Domain(), mf_crse_patch.ixType());
284 for (MFIter mfi(mf_refined_patch);mfi.isValid(); ++mfi)
285 {
286 auto& sfab = mf_crse_patch[mfi];
287 const Box& sbx = sfab.box();
288 auto& dfab = mf_refined_patch[mfi];
289 Box const& dbx = dfab.box();
290 auto& ifab = solve_mask[mfi];
291 amrex::setBC(sbx,cdomain,bcscomp,0,ncomp,bcs,bcr);
292 interp->interp_face(sfab,crse_comp,dfab,fine_comp,ncomp,
293 dbx, ratio, ifab, crse_geom, fine_geom,
294 bcr, bcscomp, gpu_or_cpu);
295 }
296}
297
298template <FabArrayType MF, typename iMF>
299void
301 MF const& mf_crse_patch, int crse_comp,
302 MF& mf_refined_patch, int fine_comp,
303 int ncomp, const IntVect& ratio,
304 const iMF& solve_mask, const Geometry& crse_geom, const Geometry& fine_geom,
305 int bccomp, RunOn gpu_or_cpu,
306 const Vector<BCRec>& bcs)
307{
308 if (dynamic_cast<MFInterpolater*>(interp)){
309 InterpFace(static_cast<MFInterpolater*>(interp),
310 mf_crse_patch, crse_comp,mf_refined_patch, fine_comp,
311 ncomp, ratio, solve_mask, crse_geom, fine_geom, bccomp,
312 gpu_or_cpu, bcs);
313 }
314 else if (dynamic_cast<Interpolater*>(interp)){
315 InterpFace(static_cast<Interpolater*>(interp),
316 mf_crse_patch, crse_comp,mf_refined_patch, fine_comp,
317 ncomp, ratio, solve_mask, crse_geom, fine_geom, bccomp,
318 gpu_or_cpu, bcs);
319 }
320 else {
321 amrex::Abort("InterpFace: unknown InterpBase");
322 }
323}
324
325
327namespace detail {
328
329// ======== FArrayBox
330
331 template <MultiFabLike MF>
332 requires (std::same_as<typename MF::FABType::value_type, FArrayBox>)
333 MF make_mf_crse_patch (FabArrayBase::FPinfo const& fpc, int ncomp)
334 {
335 MF mf_crse_patch(fpc.ba_crse_patch, fpc.dm_patch, ncomp, 0, MFInfo(),
336 *fpc.fact_crse_patch);
337 return mf_crse_patch;
338 }
339
340 template <MultiFabLike MF>
341 requires (std::same_as<typename MF::FABType::value_type, FArrayBox>)
342 MF make_mf_crse_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type)
343 {
344 MF mf_crse_patch(amrex::convert(fpc.ba_crse_patch, idx_type), fpc.dm_patch,
345 ncomp, 0, MFInfo(), *fpc.fact_crse_patch);
346 return mf_crse_patch;
347 }
348
349 template <MultiFabLike MF>
350 requires (std::same_as<typename MF::FABType::value_type, FArrayBox>)
351 MF make_mf_fine_patch (FabArrayBase::FPinfo const& fpc, int ncomp)
352 {
353 MF mf_fine_patch(fpc.ba_fine_patch, fpc.dm_patch, ncomp, 0, MFInfo(),
354 *fpc.fact_fine_patch);
355 return mf_fine_patch;
356 }
357
358 template <MultiFabLike MF>
359 requires (std::same_as<typename MF::FABType::value_type, FArrayBox>)
360 MF make_mf_fine_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type)
361 {
362 MF mf_fine_patch(amrex::convert(fpc.ba_fine_patch, idx_type), fpc.dm_patch,
363 ncomp, 0, MFInfo(), *fpc.fact_fine_patch);
364 return mf_fine_patch;
365 }
366
367 template <MultiFabLike MF>
368 requires (std::same_as<typename MF::FABType::value_type, FArrayBox>)
369 MF make_mf_refined_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type, IntVect ratio)
370 {
371 MF mf_refined_patch(amrex::convert( amrex::refine( amrex::coarsen(fpc.ba_fine_patch, ratio), ratio), idx_type),
372 fpc.dm_patch, ncomp, 0, MFInfo(), *fpc.fact_fine_patch);
373 return mf_refined_patch;
374 }
375
376 template <MultiFabLike MF>
377 requires (std::same_as<typename MF::FABType::value_type, FArrayBox>)
378 MF make_mf_crse_mask (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type, IntVect ratio)
379 {
380 MF mf_crse_mask(amrex::convert(amrex::coarsen(fpc.ba_fine_patch, ratio), idx_type),
381 fpc.dm_patch, ncomp, 0, MFInfo(), *fpc.fact_fine_patch);
382 return mf_crse_mask;
383 }
384
385 template <MultiFabLike MF>
386 requires (std::same_as<typename MF::FABType::value_type, FArrayBox>)
387 void mf_set_domain_bndry (MF &mf, Geometry const & geom)
388 {
389 mf.setDomainBndry(std::numeric_limits<Real>::quiet_NaN(), geom);
390 }
391
392
393// ======== Not FArrayBox
394
395 template <MultiFabLike MF>
396 requires (!std::same_as<typename MF::FABType::value_type, FArrayBox>)
397 MF make_mf_crse_patch (FabArrayBase::FPinfo const& fpc, int ncomp)
398 {
399 return MF(fpc.ba_crse_patch, fpc.dm_patch, ncomp, 0);
400 }
401
402 template <MultiFabLike MF>
403 requires (!std::same_as<typename MF::FABType::value_type, FArrayBox>)
404 MF make_mf_crse_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type)
405 {
406 return MF(amrex::convert(fpc.ba_crse_patch, idx_type), fpc.dm_patch, ncomp, 0);
407 }
408
409 template <MultiFabLike MF>
410 requires (!std::same_as<typename MF::FABType::value_type, FArrayBox>)
411 MF make_mf_fine_patch (FabArrayBase::FPinfo const& fpc, int ncomp)
412 {
413 return MF(fpc.ba_fine_patch, fpc.dm_patch, ncomp, 0);
414 }
415
416 template <MultiFabLike MF>
417 requires (!std::same_as<typename MF::FABType::value_type, FArrayBox>)
418 MF make_mf_fine_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type)
419 {
420 return MF(amrex::convert(fpc.ba_fine_patch, idx_type), fpc.dm_patch, ncomp, 0);
421 }
422
423 template <MultiFabLike MF>
424 requires (!std::same_as<typename MF::FABType::value_type, FArrayBox>)
425 MF make_mf_refined_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type, IntVect ratio)
426 {
427 return MF(amrex::convert( amrex::refine( amrex::coarsen(fpc.ba_fine_patch, ratio), ratio), idx_type), fpc.dm_patch, ncomp, 0);
428 }
429
430 template <MultiFabLike MF>
431 requires (!std::same_as<typename MF::FABType::value_type, FArrayBox>)
432 MF make_mf_crse_mask (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type, IntVect ratio)
433 {
434 return MF(amrex::convert(amrex::coarsen(fpc.ba_fine_patch, ratio), idx_type), fpc.dm_patch, ncomp, 0);
435 }
436
437 template <MultiFabLike MF>
438 requires (!std::same_as<typename MF::FABType::value_type, FArrayBox>)
439 void mf_set_domain_bndry (MF &/*mf*/, Geometry const & /*geom*/)
440 {
441 // nothing
442 }
443
444 template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
445 int
446 FillPatchTwoLevels_doit (MF& mf, IntVect const& nghost, Real time,
447 const Vector<MF*>& cmf, const Vector<Real>& ct,
448 const Vector<MF*>& fmf, const Vector<Real>& ft,
449 int scomp, int dcomp, int ncomp,
450 const Geometry& cgeom, const Geometry& fgeom,
451 BC& cbc, int cbccomp,
452 BC& fbc, int fbccomp,
453 const IntVect& ratio,
454 Interp* mapper,
455 const Vector<BCRec>& bcs, int bcscomp,
456 const PreInterpHook& pre_interp,
457 const PostInterpHook& post_interp,
458 EB2::IndexSpace const* index_space,
459 bool return_error_code = false)
460 {
461 BL_PROFILE("FillPatchTwoLevels");
462
463 int success_code = return_error_code ? 0 : -1;
464 int failure_code = 1;
465
466 if (nghost.max() > 0 || mf.getBDKey() != fmf[0]->getBDKey())
467 {
468 const InterpolaterBoxCoarsener& coarsener = mapper->BoxCoarsener(ratio);
469
470 // Test for Face-centered data. In 1D, face and nodal index types
471 // are the same, and we treat the data as nodal.
472 if ( mf.ixType() != IndexType::TheNodeType() &&
473 AMREX_D_TERM( mf.ixType().nodeCentered(0),
474 + mf.ixType().nodeCentered(1),
475 + mf.ixType().nodeCentered(2) ) == 1 )
476 {
477 if ( !dynamic_cast<Interpolater*>(mapper) ){
478 amrex::Abort("This interpolater has not yet implemented a version for face-based data");
479 }
480
481 // Convert to cell-centered MF meta-data for FPInfo.
482 MF mf_cc_dummy( amrex::convert(mf.boxArray(), IntVect::TheZeroVector()),
483 mf.DistributionMap(), ncomp, nghost, MFInfo().SetAlloc(false) );
484 MF fmf_cc_dummy( amrex::convert(fmf[0]->boxArray(), IntVect::TheZeroVector()),
485 fmf[0]->DistributionMap(), ncomp, nghost, MFInfo().SetAlloc(false) );
486
487 const FabArrayBase::FPinfo& fpc = FabArrayBase::TheFPinfo(fmf_cc_dummy, mf_cc_dummy,
488 nghost,
489 coarsener,
490 fgeom,
491 cgeom,
492 index_space);
493
494 if ( ! fpc.ba_crse_patch.empty())
495 {
496 if (return_error_code) {
497 BoxArray const& cba = amrex::convert(cmf[0]->boxArray(), IntVect(0));
498 if (!cba.contains(fpc.ba_crse_patch,cgeom.periodicity())) {
499 return failure_code;
500 }
501 }
502
503 MF mf_crse_patch = make_mf_crse_patch<MF> (fpc, ncomp, mf.boxArray().ixType());
504 // Must make sure fine exists under needed coarse faces.
505 // It stores values for the final (interior) interpolation,
506 // which is done from this fine MF that's been partially filled
507 // (with only faces overlying coarse having valid data).
508 MF mf_refined_patch = make_mf_refined_patch<MF> (fpc, ncomp, mf.boxArray().ixType(), ratio);
509 auto solve_mask = make_mf_crse_mask<iMultiFab>(fpc, ncomp, mf.boxArray().ixType(), ratio);
510
511 mf_set_domain_bndry(mf_crse_patch, cgeom);
512 if constexpr (std::is_same_v<BC,PhysBCFunctUseCoarseGhost>) {
513 cbc.fp1_src_ghost = cbc.cghost;
514 }
515 FillPatchSingleLevel(mf_crse_patch, time, cmf, ct, scomp, 0, ncomp,
516 cgeom, cbc, cbccomp);
517
518 mf_set_domain_bndry(mf_refined_patch, fgeom);
519 if constexpr (std::is_same_v<BC,PhysBCFunctUseCoarseGhost>) {
520 fbc.fp1_src_ghost = IntVect(0);
521 }
522 FillPatchSingleLevel(mf_refined_patch, time, fmf, ft, scomp, 0, ncomp,
523 fgeom, fbc, fbccomp);
524
525 // Aliased MFs, used to allow CPC caching.
526 MF mf_known( amrex::coarsen(fmf[0]->boxArray(), ratio), fmf[0]->DistributionMap(),
527 ncomp, nghost, MFInfo().SetAlloc(false) );
528 MF mf_solution( amrex::coarsen(mf_refined_patch.boxArray(), ratio), mf_refined_patch.DistributionMap(),
529 ncomp, 0, MFInfo().SetAlloc(false) );
530
531 const FabArrayBase::CPC mask_cpc( mf_solution, IntVect::TheZeroVector(),
532 mf_known, IntVect::TheZeroVector(),
533 cgeom.periodicity());
534
535 solve_mask.setVal(1); // Values to solve.
536 solve_mask.setVal(0, mask_cpc, 0, ncomp); // Known values.
537
538 detail::call_interp_hook(pre_interp, mf_crse_patch, 0, ncomp);
539
540 InterpFace(mapper, mf_crse_patch, 0, mf_refined_patch, 0, ncomp,
541 ratio, solve_mask, cgeom, fgeom, bcscomp, RunOn::Gpu, bcs);
542
543 detail::call_interp_hook(post_interp, mf_refined_patch, 0, ncomp);
544
545 bool aliasing = false;
546 for (auto const& fmf_a : fmf) {
547 aliasing = aliasing || (&mf == fmf_a);
548 }
549 if (aliasing) {
550 mf.ParallelCopyToGhost(mf_refined_patch, 0, dcomp, ncomp,
551 IntVect{0}, nghost);
552 } else {
553 mf.ParallelCopy(mf_refined_patch, 0, dcomp, ncomp,
554 IntVect{0}, nghost);
555 }
556 }
557 }
558 else
559 {
560 const FabArrayBase::FPinfo& fpc = FabArrayBase::TheFPinfo(*fmf[0], mf,
561 nghost,
562 coarsener,
563 fgeom,
564 cgeom,
565 index_space);
566
567 if ( ! fpc.ba_crse_patch.empty())
568 {
569 if (return_error_code) {
570 BoxArray const& cba = cmf[0]->boxArray();
571 if (!cba.contains(fpc.ba_crse_patch,cgeom.periodicity())) {
572 return failure_code;
573 }
574 }
575
576 MF mf_crse_patch = make_mf_crse_patch<MF>(fpc, ncomp);
577 mf_set_domain_bndry (mf_crse_patch, cgeom);
578
579 if constexpr (std::is_same_v<BC,PhysBCFunctUseCoarseGhost>) {
580 cbc.fp1_src_ghost = cbc.cghost;
581 }
582 FillPatchSingleLevel(mf_crse_patch, time, cmf, ct, scomp, 0, ncomp, cgeom, cbc, cbccomp);
583
584 MF mf_fine_patch = make_mf_fine_patch<MF>(fpc, ncomp);
585
586 detail::call_interp_hook(pre_interp, mf_crse_patch, 0, ncomp);
587
588 Box fdomain_g( amrex::convert(fgeom.Domain(),mf.ixType()) );
589 for (int i = 0; i < AMREX_SPACEDIM; ++i) {
590 if (fgeom.isPeriodic(i)) {
591 fdomain_g.grow(i, nghost[i]);
592 } else {
593 if constexpr (std::is_same_v
594 <BC, PhysBCFunctUseCoarseGhost>) {
595 fdomain_g.grow(i, fbc.nghost_outside_domain[i]);
596 }
597 }
598 }
599 FillPatchInterp(mf_fine_patch, 0, mf_crse_patch, 0,
600 ncomp, IntVect(0), cgeom, fgeom,
601 fdomain_g, ratio, mapper, bcs, bcscomp);
602
603 detail::call_interp_hook(post_interp, mf_fine_patch, 0, ncomp);
604
605 mf.ParallelCopy(mf_fine_patch, 0, dcomp, ncomp, IntVect{0}, nghost);
606 }
607 }
608 }
609
610 if constexpr(std::is_same_v<BC, PhysBCFunctUseCoarseGhost>) {
611 fbc.fp1_src_ghost = IntVect(0);
612 }
613 FillPatchSingleLevel(mf, nghost, time, fmf, ft, scomp, dcomp, ncomp,
614 fgeom, fbc, fbccomp);
615
616 return success_code;
617 }
618
619 template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
620 void
621 FillPatchTwoLevels_doit (Array<MF*, AMREX_SPACEDIM> const& mf, IntVect const& nghost, Real time,
622 const Vector<Array<MF*, AMREX_SPACEDIM> >& cmf, const Vector<Real>& ct,
623 const Vector<Array<MF*, AMREX_SPACEDIM> >& fmf, const Vector<Real>& ft,
624 int scomp, int dcomp, int ncomp,
625 const Geometry& cgeom, const Geometry& fgeom,
626 Array<BC, AMREX_SPACEDIM>& cbc, const Array<int, AMREX_SPACEDIM>& cbccomp,
627 Array<BC, AMREX_SPACEDIM>& fbc, const Array<int, AMREX_SPACEDIM>& fbccomp,
628 const IntVect& ratio,
629 Interp* mapper,
630 const Array<Vector<BCRec>, AMREX_SPACEDIM>& bcs, const Array<int, AMREX_SPACEDIM>& bcscomp,
631 const PreInterpHook& pre_interp,
632 const PostInterpHook& post_interp,
633 EB2::IndexSpace const* index_space)
634 {
635 BL_PROFILE("FillPatchTwoLevels (Array<MF*>)");
636
637 using FAB = typename MF::FABType::value_type;
638 using iFAB = typename iMultiFab::FABType::value_type;
639
640 AMREX_ASSERT(AMREX_D_TERM(mf[0]->ixType().nodeCentered(0),
641 && mf[1]->ixType().nodeCentered(1),
642 && mf[2]->ixType().nodeCentered(2)));
643
644 // These need to be true: (ba[0] == ba[1] == ba[2]) & (dm[0] == dm[1] == dm[2]).
645 // Debatable whether these are required, or will be enforced elsewhere prior to this func.
647 && BoxArray::SameRefs(mf[0]->boxArray(), mf[1]->boxArray()),
648 && BoxArray::SameRefs(mf[0]->boxArray(), mf[2]->boxArray())));
649/*
650 AMREX_ASSERT(AMREX_D_TERM(true,
651 && DistributionMapping::SameRefs(mf[0]->DistributionMap(), mf[1]->DistributionMap()),
652 && DistributionMapping::SameRefs(mf[0]->DistributionMap(), mf[2]->DistributionMap())));
653*/
654
655
656 // Test all of them?
657 if (nghost.max() > 0 || mf[0]->getBDKey() != fmf[0][0]->getBDKey())
658 {
659 const InterpolaterBoxCoarsener& coarsener = mapper->BoxCoarsener(ratio);
660
661 // Convert to cell-centered MF meta-data for FPInfo.
662 MF mf_cc_dummy( amrex::convert(mf[0]->boxArray(), IntVect::TheZeroVector()),
663 mf[0]->DistributionMap(), ncomp, nghost, MFInfo().SetAlloc(false) );
664 MF fmf_cc_dummy( amrex::convert(fmf[0][0]->boxArray(), IntVect::TheZeroVector()),
665 fmf[0][0]->DistributionMap(), ncomp, nghost, MFInfo().SetAlloc(false) );
666
667 const FabArrayBase::FPinfo& fpc = FabArrayBase::TheFPinfo(fmf_cc_dummy, mf_cc_dummy,
668 nghost,
669 coarsener,
670 fgeom,
671 cgeom,
672 index_space);
673
674 if ( !fpc.ba_crse_patch.empty() )
675 {
676 Array<MF, AMREX_SPACEDIM> mf_crse_patch;
677 Array<MF, AMREX_SPACEDIM> mf_refined_patch;
678 Array<iMultiFab, AMREX_SPACEDIM> solve_mask;
679
680 for (int d=0; d<AMREX_SPACEDIM; ++d)
681 {
682 mf_crse_patch[d] = make_mf_crse_patch<MF> (fpc, ncomp, mf[d]->boxArray().ixType());
683 mf_refined_patch[d] = make_mf_refined_patch<MF> (fpc, ncomp, mf[d]->boxArray().ixType(), ratio);
684 solve_mask[d] = make_mf_crse_mask<iMultiFab>(fpc, ncomp, mf[d]->boxArray().ixType(), ratio);
685
686 mf_set_domain_bndry(mf_crse_patch[d], cgeom);
687 Vector<MF*> cmf_time;
688 for (const auto & mfab : cmf)
689 { cmf_time.push_back(mfab[d]); }
690
691 FillPatchSingleLevel(mf_crse_patch[d], time, cmf_time, ct, scomp, 0, ncomp,
692 cgeom, cbc[d], cbccomp[d]);
693
694 mf_set_domain_bndry(mf_refined_patch[d], fgeom);
695 Vector<MF*> fmf_time;
696 for (const auto & mfab : fmf)
697 { fmf_time.push_back(mfab[d]); }
698
699 FillPatchSingleLevel(mf_refined_patch[d], time, fmf_time, ft, scomp, 0, ncomp,
700 fgeom, fbc[d], fbccomp[d]);
701
702
703 // Aliased MFs, used to allow CPC caching.
704 MF mf_known( amrex::coarsen(fmf[0][d]->boxArray(), ratio), fmf[0][d]->DistributionMap(),
705 ncomp, nghost, MFInfo().SetAlloc(false) );
706 MF mf_solution( amrex::coarsen(mf_refined_patch[d].boxArray(), ratio), mf_refined_patch[d].DistributionMap(),
707 ncomp, 0, MFInfo().SetAlloc(false) );
708
709 const FabArrayBase::CPC mask_cpc( mf_solution, IntVect::TheZeroVector(),
710 mf_known, IntVect::TheZeroVector(),
711 cgeom.periodicity() );
712
713 solve_mask[d].setVal(1); // Values to solve.
714 solve_mask[d].setVal(0, mask_cpc, 0, ncomp); // Known values.
715 }
716
717 int idummy=0;
718#ifdef AMREX_USE_OMP
719// bool cc = fpc.ba_crse_patch.ixType().cellCentered();
720 bool cc = false; // can anything be done to allow threading, or can the OpenMP just be removed?
721#pragma omp parallel if (cc && Gpu::notInLaunchRegion() )
722#endif
723 {
724 Vector<Array<BCRec, AMREX_SPACEDIM> > bcr(ncomp);
725 for (MFIter mfi(mf_refined_patch[0]); mfi.isValid(); ++mfi)
726 {
727 Array<FAB*, AMREX_SPACEDIM> sfab{ AMREX_D_DECL( &(mf_crse_patch[0][mfi]),
728 &(mf_crse_patch[1][mfi]),
729 &(mf_crse_patch[2][mfi]) )};
730 Array<FAB*, AMREX_SPACEDIM> dfab{ AMREX_D_DECL( &(mf_refined_patch[0][mfi]),
731 &(mf_refined_patch[1][mfi]),
732 &(mf_refined_patch[2][mfi]) )};
733 Array<iFAB*, AMREX_SPACEDIM> mfab{ AMREX_D_DECL( &(solve_mask[0][mfi]),
734 &(solve_mask[1][mfi]),
735 &(solve_mask[2][mfi]) )};
736
737 const Box& sbx_cc = amrex::convert(sfab[0]->box(), IntVect::TheZeroVector());
738 const Box& dbx_cc = amrex::convert(dfab[0]->box(), IntVect::TheZeroVector());
739
740 for (int d=0; d<AMREX_SPACEDIM; ++d)
741 {
742 Vector<BCRec> bcr_d(ncomp);
743
744 amrex::setBC(sfab[d]->box(), amrex::convert(cgeom.Domain(), mf[d]->ixType()),
745 bcscomp[d],0,ncomp,bcs[d],bcr_d);
746
747 for (int n=0; n<ncomp; ++n)
748 { bcr[n][d] = bcr_d[n]; }
749 }
750
751 pre_interp(sfab, sbx_cc, 0, ncomp);
752
753 mapper->interp_arr(sfab, 0, dfab, 0, ncomp, dbx_cc, ratio, mfab,
754 cgeom, fgeom, bcr, idummy, idummy, RunOn::Gpu);
755
756 post_interp(dfab, dbx_cc, 0, ncomp);
757 }
758 }
759
760 for (int d=0; d<AMREX_SPACEDIM; ++d)
761 {
762 bool aliasing = false;
763 for (auto const& fmf_a : fmf) {
764 aliasing = aliasing || (mf[d] == fmf_a[d]);
765 }
766 if (aliasing) {
767 mf[d]->ParallelCopyToGhost(mf_refined_patch[d], 0, dcomp, ncomp,
768 IntVect{0}, nghost);
769 } else {
770 mf[d]->ParallelCopy(mf_refined_patch[d], 0, dcomp, ncomp,
771 IntVect{0}, nghost);
772 }
773 }
774 }
775 }
776
777 for (int d=0; d<AMREX_SPACEDIM; ++d)
778 {
779 Vector<MF*> fmf_time;
780 for (auto const& ffab : fmf)
781 { fmf_time.push_back(ffab[d]); }
782
783 FillPatchSingleLevel(*mf[d], nghost, time, fmf_time, ft, scomp, dcomp, ncomp,
784 fgeom, fbc[d], fbccomp[d]);
785 }
786 }
787
788} // namespace detail
790
791template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
792void
793FillPatchTwoLevels (MF& mf, IntVect const& nghost, Real time,
794 const Vector<MF*>& cmf, const Vector<Real>& ct,
795 const Vector<MF*>& fmf, const Vector<Real>& ft,
796 int scomp, int dcomp, int ncomp,
797 const Geometry& cgeom, const Geometry& fgeom,
798 BC& cbc, int cbccomp,
799 BC& fbc, int fbccomp,
800 const IntVect& ratio,
801 Interp* mapper,
802 const Vector<BCRec>& bcs, int bcscomp,
803 const PreInterpHook& pre_interp,
804 const PostInterpHook& post_interp)
805{
806#ifdef AMREX_USE_EB
807 EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent();
808#else
809 EB2::IndexSpace const* index_space = nullptr;
810#endif
811 detail::FillPatchTwoLevels_doit(mf,nghost,time,cmf,ct,fmf,ft,
812 scomp,dcomp,ncomp,cgeom,fgeom,
813 cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp,
814 pre_interp,post_interp,index_space);
815}
816
817template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
818void
820 const Vector<MF*>& cmf, const Vector<Real>& ct,
821 const Vector<MF*>& fmf, const Vector<Real>& ft,
822 int scomp, int dcomp, int ncomp,
823 const Geometry& cgeom, const Geometry& fgeom,
824 BC& cbc, int cbccomp,
825 BC& fbc, int fbccomp,
826 const IntVect& ratio,
827 Interp* mapper,
828 const Vector<BCRec>& bcs, int bcscomp,
829 const PreInterpHook& pre_interp,
830 const PostInterpHook& post_interp)
831{
832#ifdef AMREX_USE_EB
833 EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent();
834#else
835 EB2::IndexSpace const* index_space = nullptr;
836#endif
837
838 detail::FillPatchTwoLevels_doit(mf,mf.nGrowVect(),time,cmf,ct,fmf,ft,
839 scomp,dcomp,ncomp,cgeom,fgeom,
840 cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp,
841 pre_interp,post_interp,index_space);
842}
843
844template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
845void
847 const Vector<Array<MF*, AMREX_SPACEDIM> >& cmf, const Vector<Real>& ct,
848 const Vector<Array<MF*, AMREX_SPACEDIM> >& fmf, const Vector<Real>& ft,
849 int scomp, int dcomp, int ncomp,
850 const Geometry& cgeom, const Geometry& fgeom,
853 const IntVect& ratio,
854 Interp* mapper,
855 const Array<Vector<BCRec>, AMREX_SPACEDIM>& bcs, const Array<int, AMREX_SPACEDIM>& bcscomp,
856 const PreInterpHook& pre_interp,
857 const PostInterpHook& post_interp)
858{
859#ifdef AMREX_USE_EB
860 EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent();
861#else
862 EB2::IndexSpace const* index_space = nullptr;
863#endif
864
865 detail::FillPatchTwoLevels_doit(mf,nghost,time,cmf,ct,fmf,ft,
866 scomp,dcomp,ncomp,cgeom,fgeom,
867 cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp,
868 pre_interp,post_interp,index_space);
869}
870
871template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
872void
874 const Vector<Array<MF*, AMREX_SPACEDIM> >& cmf, const Vector<Real>& ct,
875 const Vector<Array<MF*, AMREX_SPACEDIM> >& fmf, const Vector<Real>& ft,
876 int scomp, int dcomp, int ncomp,
877 const Geometry& cgeom, const Geometry& fgeom,
878 Array<BC, AMREX_SPACEDIM>& cbc, int cbccomp,
879 Array<BC, AMREX_SPACEDIM>& fbc, int fbccomp,
880 const IntVect& ratio,
881 Interp* mapper,
882 const Array<Vector<BCRec>, AMREX_SPACEDIM>& bcs, int bcscomp,
883 const PreInterpHook& pre_interp,
884 const PostInterpHook& post_interp)
885{
886#ifdef AMREX_USE_EB
887 EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent();
888#else
889 EB2::IndexSpace const* index_space = nullptr;
890#endif
891
892 Array<int, AMREX_SPACEDIM> cbccomp_arr = {AMREX_D_DECL(cbccomp,cbccomp,cbccomp)};
893 Array<int, AMREX_SPACEDIM> fbccomp_arr = {AMREX_D_DECL(fbccomp,fbccomp,fbccomp)};
894 Array<int, AMREX_SPACEDIM> bcscomp_arr = {AMREX_D_DECL(bcscomp,bcscomp,bcscomp)};
895
896 detail::FillPatchTwoLevels_doit(mf,nghost,time,cmf,ct,fmf,ft,
897 scomp,dcomp,ncomp,cgeom,fgeom,
898 cbc,cbccomp_arr,fbc,fbccomp_arr,ratio,mapper,bcs,bcscomp_arr,
899 pre_interp,post_interp,index_space);
900}
901
902template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
903void
905 const Vector<Array<MF*, AMREX_SPACEDIM> >& cmf, const Vector<Real>& ct,
906 const Vector<Array<MF*, AMREX_SPACEDIM> >& fmf, const Vector<Real>& ft,
907 int scomp, int dcomp, int ncomp,
908 const Geometry& cgeom, const Geometry& fgeom,
909 Array<BC, AMREX_SPACEDIM>& cbc, int cbccomp,
910 Array<BC, AMREX_SPACEDIM>& fbc, int fbccomp,
911 const IntVect& ratio,
912 Interp* mapper,
913 const Array<Vector<BCRec>, AMREX_SPACEDIM>& bcs, int bcscomp,
914 const PreInterpHook& pre_interp,
915 const PostInterpHook& post_interp)
916{
917#ifdef AMREX_USE_EB
918 EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent();
919#else
920 EB2::IndexSpace const* index_space = nullptr;
921#endif
922
923 Array<int, AMREX_SPACEDIM> cbccomp_arr = {AMREX_D_DECL(cbccomp,cbccomp,cbccomp)};
924 Array<int, AMREX_SPACEDIM> fbccomp_arr = {AMREX_D_DECL(fbccomp,fbccomp,fbccomp)};
925 Array<int, AMREX_SPACEDIM> bcscomp_arr = {AMREX_D_DECL(bcscomp,bcscomp,bcscomp)};
926
927 detail::FillPatchTwoLevels_doit(mf,mf[0]->nGrowVect(),time,cmf,ct,fmf,ft,
928 scomp,dcomp,ncomp,cgeom,fgeom,
929 cbc,cbccomp_arr,fbc,fbccomp_arr,ratio,mapper,bcs,bcscomp_arr,
930 pre_interp,post_interp,index_space);
931}
932
933#ifdef AMREX_USE_EB
934template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
935void
936FillPatchTwoLevels (MF& mf, IntVect const& nghost, Real time,
937 const EB2::IndexSpace& index_space,
938 const Vector<MF*>& cmf, const Vector<Real>& ct,
939 const Vector<MF*>& fmf, const Vector<Real>& ft,
940 int scomp, int dcomp, int ncomp,
941 const Geometry& cgeom, const Geometry& fgeom,
942 BC& cbc, int cbccomp,
943 BC& fbc, int fbccomp,
944 const IntVect& ratio,
945 Interp* mapper,
946 const Vector<BCRec>& bcs, int bcscomp,
947 const PreInterpHook& pre_interp,
948 const PostInterpHook& post_interp)
949{
950 detail::FillPatchTwoLevels_doit(mf,nghost,time,cmf,ct,fmf,ft,
951 scomp,dcomp,ncomp,cgeom,fgeom,
952 cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp,
953 pre_interp,post_interp,&index_space);
954}
955
956template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
957void
959 const EB2::IndexSpace& index_space,
960 const Vector<MF*>& cmf, const Vector<Real>& ct,
961 const Vector<MF*>& fmf, const Vector<Real>& ft,
962 int scomp, int dcomp, int ncomp,
963 const Geometry& cgeom, const Geometry& fgeom,
964 BC& cbc, int cbccomp,
965 BC& fbc, int fbccomp,
966 const IntVect& ratio,
967 Interp* mapper,
968 const Vector<BCRec>& bcs, int bcscomp,
969 const PreInterpHook& pre_interp,
970 const PostInterpHook& post_interp)
971{
972 detail::FillPatchTwoLevels_doit(mf,mf.nGrowVect(),time,cmf,ct,fmf,ft,
973 scomp,dcomp,ncomp,cgeom,fgeom,
974 cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp,
975 pre_interp,post_interp,&index_space);
976}
977#endif
978
979template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
980void
982 const MF& cmf, int scomp, int dcomp, int ncomp,
983 const Geometry& cgeom, const Geometry& fgeom,
984 BC& cbc, int cbccomp,
985 BC& fbc, int fbccomp,
986 const IntVect& ratio,
987 Interp* mapper,
988 const Vector<BCRec>& bcs, int bcscomp,
989 const PreInterpHook& pre_interp,
990 const PostInterpHook& post_interp)
991{
992#ifdef AMREX_USE_EB
993 EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent();
994#else
995 EB2::IndexSpace const* index_space = nullptr;
996#endif
997
998 InterpFromCoarseLevel(mf,mf.nGrowVect(),time,index_space,cmf,scomp,dcomp,ncomp,cgeom,fgeom,
999 cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp,
1000 pre_interp,post_interp);
1001}
1002
1003template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
1004void
1006 const Array<MF*, AMREX_SPACEDIM>& cmf, int scomp, int dcomp, int ncomp,
1007 const Geometry& cgeom, const Geometry& fgeom,
1008 Array<BC, AMREX_SPACEDIM>& cbc, int cbccomp,
1009 Array<BC, AMREX_SPACEDIM>& fbc, int fbccomp,
1010 const IntVect& ratio,
1011 Interp* mapper,
1012 const Array<Vector<BCRec>, AMREX_SPACEDIM>& bcs, int bcscomp,
1013 const PreInterpHook& pre_interp,
1014 const PostInterpHook& post_interp)
1015{
1016 InterpFromCoarseLevel(mf,mf[0]->nGrowVect(),time,cmf,scomp,dcomp,ncomp,cgeom,fgeom,
1017 cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp,
1018 pre_interp,post_interp);
1019}
1020
1021template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
1022void
1023InterpFromCoarseLevel (MF& mf, IntVect const& nghost, Real time,
1024 const MF& cmf, int scomp, int dcomp, int ncomp,
1025 const Geometry& cgeom, const Geometry& fgeom,
1026 BC& cbc, int cbccomp,
1027 BC& fbc, int fbccomp,
1028 const IntVect& ratio,
1029 Interp* mapper,
1030 const Vector<BCRec>& bcs, int bcscomp,
1031 const PreInterpHook& pre_interp,
1032 const PostInterpHook& post_interp)
1033{
1034#ifdef AMREX_USE_EB
1035 EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent();
1036#else
1037 EB2::IndexSpace const* index_space = nullptr;
1038#endif
1039
1040 InterpFromCoarseLevel(mf,nghost,time,index_space,cmf,scomp,dcomp,ncomp,cgeom,fgeom,
1041 cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp,
1042 pre_interp,post_interp);
1043}
1044
1045template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
1046void
1047InterpFromCoarseLevel (MF& mf, IntVect const& nghost, Real time,
1048 const EB2::IndexSpace* index_space,
1049 const MF& cmf, int scomp, int dcomp, int ncomp,
1050 const Geometry& cgeom, const Geometry& fgeom,
1051 BC& cbc, int cbccomp,
1052 BC& fbc, int fbccomp,
1053 const IntVect& ratio,
1054 Interp* mapper,
1055 const Vector<BCRec>& bcs, int bcscomp,
1056 const PreInterpHook& pre_interp,
1057 const PostInterpHook& post_interp)
1058{
1059 BL_PROFILE("InterpFromCoarseLevel");
1060
1061 using FAB = typename MF::FABType::value_type;
1062
1063 const InterpolaterBoxCoarsener& coarsener = mapper->BoxCoarsener(ratio);
1064
1065 const BoxArray& ba = mf.boxArray();
1066 const DistributionMapping& dm = mf.DistributionMap();
1067
1068 const IndexType& typ = ba.ixType();
1069
1070 BL_ASSERT(typ == cmf.boxArray().ixType());
1071
1072 Box fdomain_g( amrex::convert(fgeom.Domain(),mf.ixType()) );
1073 for (int i = 0; i < AMREX_SPACEDIM; ++i) {
1074 if (fgeom.isPeriodic(i)) {
1075 fdomain_g.grow(i, nghost[i]);
1076 } else {
1077 if constexpr (std::is_same_v<BC, PhysBCFunctUseCoarseGhost>) {
1078 fdomain_g.grow(i, fbc.nghost_outside_domain[i]);
1079 }
1080 }
1081 }
1082
1083 MF mf_crse_patch;
1084 IntVect send_ghost(0), recv_ghost(0);
1085 if constexpr (std::is_same_v<BC, PhysBCFunctUseCoarseGhost>) {
1086 mf_crse_patch.define(amrex::coarsen(ba,ratio), dm, ncomp, fbc.src_ghost);
1087 send_ghost = fbc.cghost;
1088 recv_ghost = fbc.src_ghost;
1089 } else {
1090 BoxArray ba_crse_patch(ba.size());
1091 { // TODO: later we might want to cache this
1092 for (int i = 0, N = ba.size(); i < N; ++i)
1093 {
1094 Box bx = amrex::convert(amrex::grow(ba[i],nghost), typ);
1095 bx &= fdomain_g;
1096 ba_crse_patch.set(i, coarsener.doit(bx));
1097 }
1098 }
1099
1100#ifndef AMREX_USE_EB
1101 amrex::ignore_unused(index_space);
1102#else
1103 if (index_space) {
1104 auto factory = makeEBFabFactory(index_space, cgeom, ba_crse_patch, dm,
1105 {0,0,0}, EBSupport::basic);
1106 mf_crse_patch.define(ba_crse_patch, dm, ncomp, 0, MFInfo(), *factory);
1107 } else
1108#endif
1109 {
1110 mf_crse_patch.define(ba_crse_patch, dm, ncomp, 0);
1111 }
1112 detail::mf_set_domain_bndry (mf_crse_patch, cgeom);
1113 }
1114
1115 mf_crse_patch.ParallelCopy(cmf, scomp, 0, ncomp, send_ghost, recv_ghost,
1116 cgeom.periodicity());
1117
1118 cbc(mf_crse_patch, 0, ncomp, mf_crse_patch.nGrowVect(), time, cbccomp);
1119
1120 detail::call_interp_hook(pre_interp, mf_crse_patch, 0, ncomp);
1121
1122 FillPatchInterp(mf, dcomp, mf_crse_patch, 0, ncomp, nghost, cgeom, fgeom, fdomain_g,
1123 ratio, mapper, bcs, bcscomp);
1124
1125#ifdef AMREX_USE_OMP
1126#pragma omp parallel if (Gpu::notInLaunchRegion())
1127#endif
1128 for (MFIter mfi(mf); mfi.isValid(); ++mfi)
1129 {
1130 FAB& dfab = mf[mfi];
1131 Box dfab_bx = dfab.box();
1132 dfab_bx.grow(nghost-mf.nGrowVect());
1133 const Box& dbx = dfab_bx & fdomain_g;
1134
1135 post_interp(dfab, dbx, dcomp, ncomp);
1136 }
1137
1138 fbc(mf, dcomp, ncomp, nghost, time, fbccomp);
1139}
1140
1141template <FabArrayType MF, typename BC, typename Interp, typename PreInterpHook, typename PostInterpHook>
1142void
1144 const Array<MF*, AMREX_SPACEDIM>& cmf, int scomp, int dcomp, int ncomp,
1145 const Geometry& cgeom, const Geometry& fgeom,
1146 Array<BC, AMREX_SPACEDIM>& cbc, int cbccomp,
1147 Array<BC, AMREX_SPACEDIM>& fbc, int fbccomp,
1148 const IntVect& ratio,
1149 Interp* mapper,
1150 const Array<Vector<BCRec>, AMREX_SPACEDIM>& bcs, int bcscomp,
1151 const PreInterpHook& pre_interp,
1152 const PostInterpHook& post_interp)
1153{
1154 BL_PROFILE("InterpFromCoarseLevel(array)");
1155
1156 using FAB = typename MF::FABType::value_type;
1157 using iFAB = typename iMultiFab::FABType::value_type;
1158
1159 const InterpolaterBoxCoarsener& coarsener = mapper->BoxCoarsener(ratio);
1160 const BoxArray& ba = mf[0]->boxArray();
1161 const DistributionMapping& dm = mf[0]->DistributionMap();
1162
1163 AMREX_ASSERT(AMREX_D_TERM(mf[0]->ixType().nodeCentered(0),
1164 && mf[1]->ixType().nodeCentered(1),
1165 && mf[2]->ixType().nodeCentered(2)));
1166
1167 // These need to be true: (ba[0] == ba[1] == ba[2]) & (dm[0] == dm[1] == dm[2]).
1168 // Debatable whether these are required, or will be enforced elsewhere prior to this func.
1170 && BoxArray::SameRefs(mf[0]->boxArray(), mf[1]->boxArray()),
1171 && BoxArray::SameRefs(mf[0]->boxArray(), mf[2]->boxArray())));
1172/*
1173 AMREX_ASSERT(AMREX_D_TERM(true,
1174 && DistributionMapping::SameRefs(mf[0]->DistributionMap(), mf[1]->DistributionMap()),
1175 && DistributionMapping::SameRefs(mf[0]->DistributionMap(), mf[2]->DistributionMap())));
1176*/
1177
1178 // If needed, adjust to fully overlap the coarse cells.
1179 IntVect nghost_adj = nghost;
1180 for (int d=0; d<AMREX_SPACEDIM; ++d) {
1181 if (nghost[d] % ratio[d] != 0) {
1182 nghost_adj[d] += ratio[d] - (nghost[d] % ratio[d]);
1183 }
1184 }
1185
1186 Array<MF*, AMREX_SPACEDIM> mf_local = mf;
1187 int dcomp_adj = dcomp;
1188 Array<std::unique_ptr<MF>, AMREX_SPACEDIM> mf_temp;
1189 if (! nghost.allGE(nghost_adj)) {
1190 for (int d=0; d<AMREX_SPACEDIM; ++d) {
1191 mf_temp[d] = std::make_unique<MF>(mf[d]->boxArray(),
1192 mf[d]->DistributionMap(), ncomp, nghost_adj);
1193 mf_local[d] = mf_temp[d].get();
1194 }
1195 dcomp_adj = 0;
1196 }
1197
1198 // Create a cell-centered boxArray of the region to interp.
1199 // Convert this boxArray and domain as needed.
1200 Box fdomain = amrex::convert(fgeom.Domain(), IntVect::TheZeroVector());
1201 Box fdomain_g(fdomain);
1202 for (int d = 0; d < AMREX_SPACEDIM; ++d) {
1203 if (fgeom.isPeriodic(d)) {
1204 fdomain_g.grow(d,nghost_adj[d]);
1205 }
1206 }
1207
1208 // Build patches, using domain to account for periodic bcs.
1209 BoxArray ba_crse_patch(ba.size());
1210 { // TODO: later we might want to cache this
1211 for (int i = 0, N = ba.size(); i < N; ++i)
1212 {
1213 Box bx = amrex::convert(amrex::grow(ba[i], nghost_adj), IntVect::TheZeroVector());
1214 bx &= fdomain_g;
1215 ba_crse_patch.set(i, coarsener.doit(bx));
1216 }
1217 }
1218
1219 Array<MF, AMREX_SPACEDIM> mf_crse_patch;
1220 for (int d = 0; d<AMREX_SPACEDIM; ++d)
1221 {
1222 IndexType typ = mf[d]->boxArray().ixType();
1223 BoxArray ba_crse_idxed = amrex::convert(ba_crse_patch, typ);
1224
1225#ifdef AMREX_USE_EB
1226 auto crse_factory = makeEBFabFactory(cgeom, ba_crse_idxed, dm, {0,0,0}, EBSupport::basic);
1227 mf_crse_patch[d].define(ba_crse_idxed, dm, ncomp, 0, MFInfo(), *crse_factory);
1228#else
1229 mf_crse_patch[d].define(ba_crse_idxed, dm, ncomp, 0);
1230#endif
1231 detail::mf_set_domain_bndry(mf_crse_patch[d], cgeom);
1232
1233 mf_crse_patch[d].ParallelCopy(*(cmf[d]), scomp, 0, ncomp, cgeom.periodicity());
1234 cbc[d](mf_crse_patch[d], 0, ncomp, mf_crse_patch[d].nGrowVect(), time, cbccomp);
1235 }
1236
1237 int idummy1=0, idummy2=0;
1238#ifdef AMREX_USE_OMP
1239#pragma omp parallel if (Gpu::notInLaunchRegion())
1240#endif
1241 {
1243
1244 // Empty containers describing that all points must be solved (no mask).
1245 Array<iFAB*, AMREX_SPACEDIM> mfab{ AMREX_D_DECL( nullptr, nullptr, nullptr ) };
1246
1247 for (MFIter mfi(mf_crse_patch[0]); mfi.isValid(); ++mfi)
1248 {
1249 Array<FAB*, AMREX_SPACEDIM> sfab{ AMREX_D_DECL( &(mf_crse_patch[0][mfi]),
1250 &(mf_crse_patch[1][mfi]),
1251 &(mf_crse_patch[2][mfi]) )};
1252 Array<FAB*, AMREX_SPACEDIM> dfab{ AMREX_D_DECL( &(*mf_local[0])[mfi],
1253 &(*mf_local[1])[mfi],
1254 &(*mf_local[2])[mfi] )};
1255
1256 const Box& sbx_cc = amrex::convert(sfab[0]->box(), IntVect::TheZeroVector());
1257 // Interpolate only over the region the coarse patch was built from.
1258 Box dfab_cc = amrex::convert(amrex::grow(ba[mfi.index()], nghost_adj),
1260 const Box& dbx_cc = dfab_cc & fdomain_g;
1261
1262 for (int d=0; d<AMREX_SPACEDIM; ++d)
1263 {
1264 Vector<BCRec> bcr_d(ncomp);
1265
1266 amrex::setBC(sfab[d]->box(),
1267 amrex::convert(cgeom.Domain(), sfab[d]->box().ixType()),
1268 bcscomp,0,ncomp,bcs[d],bcr_d);
1269
1270 for (int n=0; n<ncomp; ++n)
1271 { bcr[n][d] = bcr_d[n]; }
1272 }
1273
1274 pre_interp(sfab, sbx_cc, 0, ncomp);
1275
1276 mapper->interp_arr(sfab, 0, dfab, dcomp_adj, ncomp, dbx_cc, ratio, mfab,
1277 cgeom, fgeom, bcr, idummy1, idummy2, RunOn::Gpu);
1278
1279 post_interp(dfab, dbx_cc, dcomp_adj, ncomp);
1280 }
1281 }
1282
1283 for (int d=0; d<AMREX_SPACEDIM; ++d)
1284 {
1285 if (mf[d] != mf_local[d]) {
1286 amrex::Copy(*mf[d], *mf_local[d], 0, dcomp, ncomp, nghost);
1287 }
1288
1289 fbc[d](*mf[d], dcomp, ncomp, nghost, time, fbccomp);
1290 }
1291}
1292
1293template <FabArrayType MF, typename Interp>
1294void
1295InterpFromCoarseLevel (MF& mf, IntVect const& nghost,
1296 IntVect const& nghost_outside_domain,
1297 const MF& cmf, int scomp, int dcomp, int ncomp,
1298 const Geometry& cgeom, const Geometry& fgeom,
1299 const IntVect& ratio, Interp* mapper,
1300 const Vector<BCRec>& bcs, int bcscomp)
1301{
1302 PhysBCFunctUseCoarseGhost erfbc(cmf,nghost,nghost_outside_domain,ratio,mapper);
1303 InterpFromCoarseLevel(mf, nghost, Real(0.0), cmf, scomp, dcomp, ncomp,
1304 cgeom, fgeom, erfbc, 0, erfbc, 0, ratio, mapper,
1305 bcs, bcscomp);
1306}
1307
1308template <FabArrayType MF>
1309void
1310FillPatchSingleLevel (MF& mf, IntVect const& nghost, Real time,
1311 const Vector<MF*>& smf, IntVect const& snghost,
1312 const Vector<Real>& stime, int scomp, int dcomp, int ncomp,
1313 const Geometry& geom)
1314{
1315 PhysBCFunctUseCoarseGhost erfbc(snghost);
1316 FillPatchSingleLevel(mf, nghost, time, smf, stime, scomp, dcomp, ncomp, geom,
1317 erfbc, 0);
1318}
1319
1320template <FabArrayType MF, typename Interp>
1321void
1322FillPatchTwoLevels (MF& mf, IntVect const& nghost,
1323 IntVect const& nghost_outside_domain, Real time,
1324 const Vector<MF*>& cmf, const Vector<Real>& ct,
1325 const Vector<MF*>& fmf, const Vector<Real>& ft,
1326 int scomp, int dcomp, int ncomp,
1327 const Geometry& cgeom, const Geometry& fgeom,
1328 const IntVect& ratio, Interp* mapper,
1329 const Vector<BCRec>& bcs, int bcscomp)
1330{
1331 AMREX_ALWAYS_ASSERT_WITH_MESSAGE(nghost_outside_domain == 0, "TODO");
1332 PhysBCFunctUseCoarseGhost erfbc(*cmf[0], nghost, nghost_outside_domain, ratio,
1333 mapper);
1334 FillPatchTwoLevels(mf, nghost, time, cmf, ct, fmf, ft, scomp, dcomp, ncomp,
1335 cgeom, fgeom, erfbc, 0, erfbc, 0, ratio, mapper,
1336 bcs, bcscomp);
1337}
1338
1339template <FabArrayType MF, typename BC, typename Interp>
1340void
1341FillPatchNLevels (MF& mf, int level, const IntVect& nghost, Real time,
1342 const Vector<Vector<MF*>>& smf, const Vector<Vector<Real>>& st,
1343 int scomp, int dcomp, int ncomp,
1344 const Vector<Geometry>& geom,
1345 Vector<BC>& bc, int bccomp,
1346 const Vector<IntVect>& ratio,
1347 Interp* mapper,
1348 const Vector<BCRec>& bcr, int bcrcomp)
1349{
1350 BL_PROFILE("FillPatchNLevels");
1351
1352 // FillPatchTwolevels relies on that mf's valid region is inside the
1353 // domain at periodic boundaries. But when we create coarsen boxarray
1354 // using mapper->CoarseBox, the resulting boxarray might violate the
1355 // requirement. If that happens, we need to create a second version of
1356 // the boxarray that is safe for FillPatchTwolevels.
1357
1358 auto get_clayout = [&] () -> std::tuple<BoxArray,BoxArray,DistributionMapping>
1359 {
1360 if (level == 0) {
1361 return std::make_tuple(BoxArray(),BoxArray(),DistributionMapping());
1362 } else {
1363 BoxArray const& ba = mf.boxArray();
1364 auto const& typ = ba.ixType();
1365 std::map<int,Vector<Box>> extra_boxes_map;
1366 BoxList cbl(typ);
1367 cbl.reserve(ba.size());
1368 for (int i = 0, N = int(ba.size()); i < N; ++i) {
1369 Box const& cbox = mapper->CoarseBox(amrex::grow(ba[i],nghost),ratio[level-1]);
1370 cbl.push_back(cbox);
1371 Box gdomain = geom[level-1].growNonPeriodicDomain(cbox.length());
1372 gdomain.convert(typ);
1373 if (!gdomain.contains(cbox)) {
1374 auto& extra_boxes = extra_boxes_map[i];
1375 auto const& pshift = geom[level-1].periodicity().shiftIntVect();
1376 for (auto const& piv : pshift) {
1377 auto const& ibox = amrex::shift(cbox,piv) & gdomain;
1378 if (ibox.ok()) {
1379 extra_boxes.push_back(ibox);
1380 }
1381 }
1382 }
1383 }
1384
1385 BoxArray cba2;
1387 if (!extra_boxes_map.empty()) {
1388 BoxList cbl2 = cbl;
1389 auto& lbox = cbl2.data();
1390 DistributionMapping const& dm = mf.DistributionMap();
1391 Vector<int> procmap2 = dm.ProcessorMap();
1392 for (auto const& [i, vb] : extra_boxes_map) {
1393 lbox[i] = vb[0];
1394 for (int j = 1, nj = int(vb.size()); j < nj; ++j) {
1395 lbox.push_back(vb[j]);
1396 procmap2.push_back(dm[i]);
1397 }
1398 }
1399 cba2 = BoxArray(std::move(cbl2));
1400 dm2 = DistributionMapping(std::move(procmap2));
1401 }
1402
1403 return std::make_tuple(BoxArray(std::move(cbl)), cba2, dm2);
1404 }
1405 };
1406
1407#ifdef AMREX_USE_EB
1408 EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent();
1409#else
1410 EB2::IndexSpace const* index_space = nullptr;
1411#endif
1412
1413 AMREX_ALWAYS_ASSERT(level < int(geom.size()) &&
1414 level < int(bc.size()) &&
1415 level < int(ratio.size()+1));
1416 if (level == 0) {
1417 FillPatchSingleLevel(mf, nghost, time, smf[0], st[0], scomp, dcomp, ncomp, geom[0],
1418 bc[0], bccomp);
1419 } else if (level >= int(smf.size()))
1420 {
1421 auto const& [ba1, ba2, dm2] = get_clayout();
1422 MF cmf1, cmf2;
1423#ifdef AMREX_USE_EB
1424 if (index_space) {
1425 auto factory = makeEBFabFactory(index_space, geom[level-1], ba1,
1426 mf.DistributionMap(), {0,0,0},
1428 cmf1.define(ba1, mf.DistributionMap(), ncomp, 0, MFInfo(), *factory);
1429 if (!ba2.empty()) {
1430 auto factory2 = makeEBFabFactory(index_space, geom[level-1], ba2,
1431 dm2, {0,0,0},
1433 cmf2.define(ba2, dm2, ncomp, 0, MFInfo(), *factory2);
1434 }
1435 } else
1436#endif
1437 {
1438 cmf1.define(ba1, mf.DistributionMap(), ncomp, 0);
1439 if (!ba2.empty()) {
1440 cmf2.define(ba2, dm2, ncomp, 0);
1441 }
1442 }
1443
1444 MF* p_mf_inside = (ba2.empty()) ? &cmf1 : &cmf2;
1445 FillPatchNLevels(*p_mf_inside, level-1, IntVect(0), time, smf, st, scomp, 0, ncomp,
1446 geom, bc, bccomp, ratio, mapper, bcr, bcrcomp);
1447 if (&cmf1 != p_mf_inside) {
1448 cmf1.ParallelCopy(*p_mf_inside, geom[level-1].periodicity());
1449 }
1450 Box domain_g = geom[level].growPeriodicDomain(nghost);
1451 domain_g.convert(mf.ixType());
1452 FillPatchInterp(mf, dcomp, cmf1, 0, ncomp, nghost, geom[level-1], geom[level],
1453 domain_g, ratio[level-1], mapper, bcr, bcrcomp);
1454 } else {
1456 int error_code = detail::FillPatchTwoLevels_doit(mf, nghost, time,
1457 smf[level-1], st[level-1],
1458 smf[level ], st[level ],
1459 scomp, dcomp, ncomp,
1460 geom[level-1], geom[level],
1461 bc[level-1], bccomp,
1462 bc[level ], bccomp,
1463 ratio[level-1], mapper, bcr, bcrcomp,
1464 hook, hook, index_space, true);
1465 if (error_code == 0) { return; }
1466
1467 auto const& [ba1, ba2, dm2] = get_clayout();
1468 MF cmf_tmp;
1469#ifdef AMREX_USE_EB
1470 if (index_space) {
1471 if (ba2.empty()) {
1472 auto factory = makeEBFabFactory(index_space, geom[level-1], ba1,
1473 mf.DistributionMap(), {0,0,0},
1475 cmf_tmp.define(ba1, mf.DistributionMap(), ncomp, 0, MFInfo(), *factory);
1476 } else {
1477 auto factory = makeEBFabFactory(index_space, geom[level-1], ba2,
1478 dm2, {0,0,0},
1480 cmf_tmp.define(ba2, dm2, ncomp, 0, MFInfo(), *factory);
1481 }
1482 } else
1483#endif
1484 {
1485 if (ba2.empty()) {
1486 cmf_tmp.define(ba1, mf.DistributionMap(), ncomp, 0);
1487 } else {
1488 cmf_tmp.define(ba2, dm2, ncomp, 0);
1489 }
1490 }
1491
1492 FillPatchNLevels(cmf_tmp, level-1, IntVect(0), time, smf, st, scomp, 0, ncomp,
1493 geom, bc, bccomp, ratio, mapper, bcr, bcrcomp);
1494
1495 Vector<MF*> cmf{&cmf_tmp};
1496 Vector<MF*> fmf = smf[level];
1497 Vector<MF> fmf_raii;
1498 if (scomp != 0) {
1499 for (auto const* p : fmf) {
1500 fmf_raii.emplace_back(*p, amrex::make_alias, scomp, ncomp);
1501 }
1502 fmf.clear();
1503 for (auto& a : fmf_raii) {
1504 fmf.push_back(&a);
1505 }
1506 }
1507
1508 detail::FillPatchTwoLevels_doit(mf, nghost, time,
1509 cmf, {time},
1510 fmf, st[level],
1511 0, dcomp, ncomp,
1512 geom[level-1], geom[level],
1513 bc[level-1], bccomp,
1514 bc[level ], bccomp,
1515 ratio[level-1], mapper, bcr, bcrcomp,
1516 hook, hook, index_space);
1517 }
1518}
1519
1520}
1521
1522#endif
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:562
#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
GpuArray< Real, 3 > beta
Definition AMReX_MLEBNodeFDLaplacian.cpp:1099
#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
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:2074
Rectangular problem domain geometry.
Definition AMReX_Geometry.H:85
const Box & Domain() const noexcept
Returns our rectangular domain.
Definition AMReX_Geometry.H:244
Periodicity periodicity() const noexcept
Return the Periodicity based on the length of the domain.
Definition AMReX_Geometry.H:424
bool isPeriodic(int dir) const noexcept
Is the domain periodic in the specified direction?
Definition AMReX_Geometry.H:397
__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
This static member function returns an IndexTypeND object of value IndexTypeND::NODE....
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
This static member function returns a reference to a constant IntVectND object, all of whose dim argu...
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:34
Definition AMReX_InterpBase.H:20
Box doit(const Box &fine) const override
Apply the coarse-box logic to the supplied fine box.
Definition AMReX_InterpBase.cpp:10
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:1630
__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:1469
__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:1548
__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:1326
__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:1510
std::array< T, N > Array
Definition AMReX_Array.H:31
__host__ __device__ bool almostEqual(T x, T y, int ulp=2)
Definition AMReX_Algorithm.H:139
const IndexSpace * TopIndexSpaceIfPresent() noexcept
Return the top IndexSpace if one has been built (nullptr otherwise).
Definition AMReX_EB2.cpp:93
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:259
void Copy(FabArray< DFAB > &dst, FabArray< SFAB > const &src, int srccomp, int dstcomp, int numcomp, int nghost)
Definition AMReX_FabArray.H:192
BoxArray const & boxArray(FabArrayBase const &fa)
Convenience wrapper that forwards to fa.boxArray().
Definition AMReX_FabArrayBase.cpp:2870
DistributionMapping const & DistributionMap(FabArrayBase const &fa)
Convenience wrapper that forwards to fa.DistributionMap().
Definition AMReX_FabArrayBase.cpp:2875
RunOn
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.
IndexTypeND< 3 > IndexType
IndexType is an alias for amrex::IndexTypeND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:41
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:274
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
IntVectND< 3 > IntVect
IntVect is an alias for amrex::IntVectND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:38
IntVect nGrowVect(FabArrayBase const &fa)
Convenience wrapper that forwards to fa.nGrowVect().
Definition AMReX_FabArrayBase.cpp:2865
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:981
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:242
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:793
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:1341
FabArray memory allocation information.
Definition AMReX_FabArray.H:73
Definition AMReX_FillPatchUtil.H:39