diff --git a/Src/AmrCore/AMReX_FillPatchUtil.H b/Src/AmrCore/AMReX_FillPatchUtil.H index e740ccce0d..11a8eb560e 100644 --- a/Src/AmrCore/AMReX_FillPatchUtil.H +++ b/Src/AmrCore/AMReX_FillPatchUtil.H @@ -694,6 +694,40 @@ namespace amrex const PreInterpHook& pre_interp = {}, const PostInterpHook& post_interp = {}); + /** + * \brief Fill with interpolation of coarse level data + * + * It's the CALLER's responsibility to make sure all ghost cells of the + * coarse MF needed for interpolation are filled already before calling + * this function. It's assumed that the fine level MultiFab mf's + * BoxArray is coarsenable by the refinement ratio. There is no support + * for EB. + * + * \tparam MF the MultiFab/FabArray type + * \tparam Interp spatial interpolater + * + * \param mf destination MF on the fine level + * \param nghost number of ghost cells of mf inside domain needed to be filled + * \param nghost_outside_domain number of ghost cells of mf outside domain needed to be filled + * \param cmf source MF on the coarse level + * \param scomp starting component of the source MF + * \param dcomp starting component of the destination MF + * \param ncomp number of components + * \param cgeom Geometry for the coarse level + * \param fgeom Geometry for the fine level + * \param ratio refinement ratio + * \param mapper spatial interpolater + * \param bcs boundar types for each component + */ + template + std::enable_if_t::value> + InterpFromCoarseLevel (MF& mf, IntVect const& nghost, + IntVect const& nghost_outside_domain, + const MF& cmf, int scomp, int dcomp, int ncomp, + const Geometry& cgeom, const Geometry& fgeom, + const IntVect& ratio, Interp* mapper, + const Vector& bcs); + #ifndef BL_NO_FORT enum InterpEM_t { InterpE, InterpB}; diff --git a/Src/AmrCore/AMReX_FillPatchUtil_I.H b/Src/AmrCore/AMReX_FillPatchUtil_I.H index 190566a7fa..fa26cc5ea9 100644 --- a/Src/AmrCore/AMReX_FillPatchUtil_I.H +++ b/Src/AmrCore/AMReX_FillPatchUtil_I.H @@ -1210,6 +1210,45 @@ InterpFromCoarseLevel (Array const& mf, IntVect const& ngho } } +template +std::enable_if_t::value> +InterpFromCoarseLevel (MF& mf, IntVect const& nghost, + IntVect const& nghost_outside_domain, + const MF& cmf, int scomp, int dcomp, int ncomp, + const Geometry& cgeom, const Geometry& fgeom, + const IntVect& ratio, Interp* mapper, + const Vector& bcs) +{ + const BoxArray& ba = mf.boxArray(); + const DistributionMapping& dm = mf.DistributionMap(); + + const IndexType& typ = ba.ixType(); + BL_ASSERT(typ == cmf.boxArray().ixType()); + + const InterpolaterBoxCoarsener& coarsener = mapper->BoxCoarsener(ratio); + Box tmp(-nghost, IntVect(32), typ); + Box tmp2 = coarsener.doit(tmp); + IntVect src_ghost = -tmp2.smallEnd(); + + tmp = Box(-nghost_outside_domain, IntVect(32), typ); + tmp2 = coarsener.doit(tmp); + IntVect src_ghost_outside_domain = -tmp2.smallEnd(); + + IntVect cghost = cmf.nGrowVect(); + cghost.min(src_ghost); + + AMREX_ALWAYS_ASSERT(cghost.allGE(src_ghost_outside_domain)); + + MF mf_crse_patch(amrex::coarsen(ba,ratio), dm, ncomp, src_ghost); + mf_crse_patch.ParallelCopy(cmf, scomp, 0, ncomp, cghost, src_ghost, + cgeom.periodicity()); + + Box fdomain_g = amrex::convert(fgeom.Domain(),typ); + fdomain_g.grow(nghost_outside_domain); + FillPatchInterp(mf, dcomp, mf_crse_patch, 0, ncomp, nghost, cgeom, fgeom, + fdomain_g, ratio, mapper, bcs, 0); +} + template std::enable_if_t::value> FillPatchNLevels (MF& mf, int level, const IntVect& nghost, Real time,