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