diff --git a/Src/AmrCore/AMReX_FillPatchUtil.H b/Src/AmrCore/AMReX_FillPatchUtil.H index fab29231bf..1956101bc5 100644 --- a/Src/AmrCore/AMReX_FillPatchUtil.H +++ b/Src/AmrCore/AMReX_FillPatchUtil.H @@ -10,6 +10,7 @@ #include #include #include +#include /** * \file AMReX_FillPatchUtil.H @@ -31,890 +32,895 @@ #include #include -namespace amrex -{ - - template - struct NullInterpHook - { - template ::value,int> = 0> - void operator() (MFFAB& /*fab*/, const Box& /*bx*/, int /*icomp*/, int /*ncomp*/) const {} - - template ::value,int> = 0> - void operator() (Array /*fab*/, const Box& /*bx*/, int /*icomp*/, int /*ncomp*/) const {} - - template ::value,int> = 0> - void operator() (MFFAB& /*mf*/, int /*icomp*/, int /*ncomp*/) const {} - }; - - /** - * \brief Test if AMR grids are properly nested. - * - * If grids are not properly nested, FillPatch functions may fail. - * - * \tparam Interp Interpolater type - * - * \param ratio refinement ratio - * \param blocking_factor blocking factor on the fine level - * \param ngrow number of ghost cells of fine MultiFab - * \param boxType index type - * \param mapper an interpolater object - */ - template - bool ProperlyNested (const IntVect& ratio, const IntVect& blocking_factor, int ngrow, - const IndexType& boxType, Interp* mapper); - - /** - * \brief FillPatch with data from the current level - * - * The destination MultiFab/FabArray is on the same AMR level as the - * source MultiFab/FabArray. Usually this can only be used on AMR level - * 0, because filling fine level MF usually requires coarse level - * data. If needed, interpolation in time is performed. - * - * \tparam MF the MultiFab/FabArray type - * \tparam BC functor for filling physical boundaries - * - * \param mf destination MF - * \param nghost number of ghost cells of mf needed to be filled - * \param time time associated with mf - * \param smf source MFs - * \param stime times associated smf - * \param scomp starting component of the source MFs - * \param dcomp starting component of the destination MF - * \param ncomp number of components - * \param geom Geometry for this level - * \param physbcf functor for physical boundaries - * \param bcfcomp starting component for physbcf - */ - template - std::enable_if_t::value> - FillPatchSingleLevel (MF& mf, IntVect const& nghost, Real time, - const Vector& smf, const Vector& stime, - int scomp, int dcomp, int ncomp, - const Geometry& geom, - BC& physbcf, int bcfcomp); - - /** - * \brief FillPatch with data from the current level - * - * The destination MultiFab/FabArray is on the same AMR level as the - * source MultiFab/FabArray. Usually this can only be used on AMR level - * 0, because filling fine level MF usually requires coarse level - * data. If needed, interpolation in time is performed. All ghost cells of - * the destination MF are filled. - * - * \tparam MF the MultiFab/FabArray type - * \tparam BC functor for filling physical boundaries - * - * \param mf destination MF - * \param time time associated with mf - * \param smf source MFs - * \param stime times associated smf - * \param scomp starting component of the source MFs - * \param dcomp starting component of the destination MF - * \param ncomp number of components - * \param geom Geometry for this level - * \param physbcf functor for physical boundaries - * \param bcfcomp starting component for physbcf - */ - template - std::enable_if_t::value> - FillPatchSingleLevel (MF& mf, Real time, - const Vector& smf, const Vector& stime, - int scomp, int dcomp, int ncomp, - const Geometry& geom, - BC& physbcf, int bcfcomp); - - /** - * \brief FillPatch with data from the current level and the level below. - * - * First, we fill the destination MultiFab/FabArray with the current - * level data as much as possible. This may include interpolation in - * time. For the rest of the destination MF, we fill them with the - * coarse level data using interpolation in space (and in time if - * needed). - * - * \tparam MF the MultiFab/FabArray type - * \tparam BC functor for filling physical boundaries - * \tparam Interp spatial interpolater - * \tparam PreInterpHook pre-interpolation hook - * \tparam PostInterpHook post-interpolation hook - * - * \param mf destination MF on the fine level - * \param nghost number of ghost cells of mf needed to be filled - * \param time time associated with mf - * \param cmf source MFs on the coarse level - * \param ct times associated cmf - * \param fmf source MFs on the fine level - * \param ft times associated fmf - * \param scomp starting component of the source MFs - * \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 cbc functor for physical boundaries on the coarse level - * \param cbccomp starting component for cbc - * \param fbc functor for physical boundaries on the fine level - * \param fbccomp starting component for fbc - * \param ratio refinement ratio - * \param mapper spatial interpolater - * \param bcs boundary types for each component. We need this because some interpolaters need it. - * \param bcscomp starting component for bcs - * \param pre_interp pre-interpolation hook - * \param post_interp post-interpolation hook - */ - template , - typename PostInterpHook=NullInterpHook > - std::enable_if_t::value> - FillPatchTwoLevels (MF& mf, IntVect const& nghost, Real time, - const Vector& cmf, const Vector& ct, - const Vector& fmf, const Vector& 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& bcs, int bcscomp, - const PreInterpHook& pre_interp = {}, - const PostInterpHook& post_interp = {}); - - /** - * \brief FillPatch with data from the current level and the level below. - * - * First, we fill the destination MultiFab/FabArray with the current - * level data as much as possible. This may include interpolation in - * time. For the rest of the destination MF, we fill them with the - * coarse level data using interpolation in space (and in time if - * needed). All ghost cells of the destination MF are filled. - * - * \tparam MF the MultiFab/FabArray type - * \tparam BC functor for filling physical boundaries - * \tparam Interp spatial interpolater - * \tparam PreInterpHook pre-interpolation hook - * \tparam PostInterpHook post-interpolation hook - * - * \param mf destination MF on the fine level - * \param time time associated with mf - * \param cmf source MFs on the coarse level - * \param ct times associated cmf - * \param fmf source MFs on the fine level - * \param ft times associated fmf - * \param scomp starting component of the source MFs - * \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 cbc functor for physical boundaries on the coarse level - * \param cbccomp starting component for cbc - * \param fbc functor for physical boundaries on the fine level - * \param fbccomp starting component for fbc - * \param ratio refinement ratio - * \param mapper spatial interpolater - * \param bcs boundary types for each component. We need this because some interpolaters need it. - * \param bcscomp starting component for bcs - * \param pre_interp pre-interpolation hook - * \param post_interp post-interpolation hook - */ - template , - typename PostInterpHook=NullInterpHook > - std::enable_if_t::value> - FillPatchTwoLevels (MF& mf, Real time, - const Vector& cmf, const Vector& ct, - const Vector& fmf, const Vector& 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& bcs, int bcscomp, - const PreInterpHook& pre_interp = {}, - const PostInterpHook& post_interp = {}); - - /** - * \brief FillPatch for face variables with data from the current level - * and the level below. Sometimes, we need to fillpatch all - * AMREX_SPACEDIM face MultiFabs togother to satisfy certain constraint - * such as divergence preserving. - * - * First, we fill the destination MultiFab/FabArray's with the current - * level data as much as possible. This may include interpolation in - * time. For the rest of the destination MFs, we fill them with the - * coarse level data using interpolation in space (and in time if - * needed). - * - * \tparam MF the MultiFab/FabArray type - * \tparam BC functor for filling physical boundaries - * \tparam Interp spatial interpolater - * \tparam PreInterpHook pre-interpolation hook - * \tparam PostInterpHook post-interpolation hook - * - * \param mf destination MFs on the fine level - * \param nghost number of ghost cells of mf needed to be filled - * \param time time associated with mf - * \param cmf source MFs on the coarse level - * \param ct times associated cmf - * \param fmf source MFs on the fine level - * \param ft times associated fmf - * \param scomp starting component of the source MFs - * \param dcomp starting component of the destination MFs - * \param ncomp number of components - * \param cgeom Geometry for the coarse level - * \param fgeom Geometry for the fine level - * \param cbc functor for physical boundaries on the coarse level - * \param cbccomp starting component for cbc - * \param fbc functor for physical boundaries on the fine level - * \param fbccomp starting component for fbc - * \param ratio refinement ratio - * \param mapper spatial interpolater - * \param bcs boundary types for each component. We need this because some interpolaters need it. - * \param bcscomp starting component for bcs - * \param pre_interp pre-interpolation hook - * \param post_interp post-interpolation hook - */ - template , - typename PostInterpHook=NullInterpHook > - std::enable_if_t::value> - FillPatchTwoLevels (Array const& mf, IntVect const& nghost, Real time, - const Vector >& cmf, const Vector& ct, - const Vector >& fmf, const Vector& ft, - int scomp, int dcomp, int ncomp, - const Geometry& cgeom, const Geometry& fgeom, - Array& cbc, const Array& cbccomp, - Array& fbc, const Array& fbccomp, - const IntVect& ratio, - Interp* mapper, - const Array, AMREX_SPACEDIM>& bcs, const Array& bcscomp, - const PreInterpHook& pre_interp = {}, - const PostInterpHook& post_interp = {}); - - /** - * \brief FillPatch for face variables with data from the current level - * and the level below. Sometimes, we need to fillpatch all - * AMREX_SPACEDIM face MultiFabs togother to satisfy certain constraint - * such as divergence preserving. - * - * First, we fill the destination MultiFab/FabArray's with the current - * level data as much as possible. This may include interpolation in - * time. For the rest of the destination MFs, we fill them with the - * coarse level data using interpolation in space (and in time if - * needed). - * - * \tparam MF the MultiFab/FabArray type - * \tparam BC functor for filling physical boundaries - * \tparam Interp spatial interpolater - * \tparam PreInterpHook pre-interpolation hook - * \tparam PostInterpHook post-interpolation hook - * - * \param mf destination MFs on the fine level - * \param nghost number of ghost cells of mf needed to be filled - * \param time time associated with mf - * \param cmf source MFs on the coarse level - * \param ct times associated cmf - * \param fmf source MFs on the fine level - * \param ft times associated fmf - * \param scomp starting component of the source MFs - * \param dcomp starting component of the destination MFs - * \param ncomp number of components - * \param cgeom Geometry for the coarse level - * \param fgeom Geometry for the fine level - * \param cbc functor for physical boundaries on the coarse level - * \param cbccomp starting component for cbc - * \param fbc functor for physical boundaries on the fine level - * \param fbccomp starting component for fbc - * \param ratio refinement ratio - * \param mapper spatial interpolater - * \param bcs boundary types for each component. We need this because some interpolaters need it. - * \param bcscomp starting component for bcs - * \param pre_interp pre-interpolation hook - * \param post_interp post-interpolation hook - */ - template , - typename PostInterpHook=NullInterpHook > - std::enable_if_t::value> - FillPatchTwoLevels (Array const& mf, IntVect const& nghost, Real time, - const Vector >& cmf, const Vector& ct, - const Vector >& fmf, const Vector& ft, - int scomp, int dcomp, int ncomp, - const Geometry& cgeom, const Geometry& fgeom, - Array& cbc, int cbccomp, - Array& fbc, int fbccomp, - const IntVect& ratio, - Interp* mapper, - const Array, AMREX_SPACEDIM>& bcs, int bcscomp, - const PreInterpHook& pre_interp = {}, - const PostInterpHook& post_interp = {}); - - /** - * \brief FillPatch for face variables with data from the current level - * and the level below. Sometimes, we need to fillpatch all - * AMREX_SPACEDIM face MultiFabs togother to satisfy certain constraint - * such as divergence preserving. - * - * First, we fill the destination MultiFab/FabArray's with the current - * level data as much as possible. This may include interpolation in - * time. For the rest of the destination MFs, we fill them with the - * coarse level data using interpolation in space (and in time if - * needed). All ghost cells of the destination MFs are filled. - * - * \tparam MF the MultiFab/FabArray type - * \tparam BC functor for filling physical boundaries - * \tparam Interp spatial interpolater - * \tparam PreInterpHook pre-interpolation hook - * \tparam PostInterpHook post-interpolation hook - * - * \param mf destination MFs on the fine level - * \param time time associated with mf - * \param cmf source MFs on the coarse level - * \param ct times associated cmf - * \param fmf source MFs on the fine level - * \param ft times associated fmf - * \param scomp starting component of the source MFs - * \param dcomp starting component of the destination MFs - * \param ncomp number of components - * \param cgeom Geometry for the coarse level - * \param fgeom Geometry for the fine level - * \param cbc functor for physical boundaries on the coarse level - * \param cbccomp starting component for cbc - * \param fbc functor for physical boundaries on the fine level - * \param fbccomp starting component for fbc - * \param ratio refinement ratio - * \param mapper spatial interpolater - * \param bcs boundary types for each component. We need this because some interpolaters need it. - * \param bcscomp starting component for bcs - * \param pre_interp pre-interpolation hook - * \param post_interp post-interpolation hook - */ - template , - typename PostInterpHook=NullInterpHook > - std::enable_if_t::value> - FillPatchTwoLevels (Array const& mf, Real time, - const Vector >& cmf, const Vector& ct, - const Vector >& fmf, const Vector& ft, - int scomp, int dcomp, int ncomp, - const Geometry& cgeom, const Geometry& fgeom, - Array& cbc, int cbccomp, - Array& fbc, int fbccomp, - const IntVect& ratio, - Interp* mapper, - const Array, AMREX_SPACEDIM>& bcs, int bcscomp, - const PreInterpHook& pre_interp = {}, - const PostInterpHook& post_interp = {}); +namespace amrex { +template +struct NullInterpHook { + template + requires IsBaseFabType + void operator() (MFFAB& /*fab*/, const amrex::Box& /*bx*/, int /*icomp*/, int /*ncomp*/) const {} + + template + requires IsBaseFabType + void operator() (amrex::Array /*fab*/, const amrex::Box& /*bx*/, int /*icomp*/, + int /*ncomp*/) const {} + + template + requires IsFabArrayType + void operator() (MFFAB& /*mf*/, int /*icomp*/, int /*ncomp*/) const {} +}; + +/** + * \brief Test if AMR grids are properly nested. + * + * If grids are not properly nested, FillPatch functions may fail. + * + * \tparam Interp Interpolater type + * + * \param ratio refinement ratio + * \param blocking_factor blocking factor on the fine level + * \param ngrow number of ghost cells of fine MultiFab + * \param boxType index type + * \param mapper an interpolater object + */ +template +bool ProperlyNested (const IntVect& ratio, const IntVect& blocking_factor, int ngrow, + const IndexType& boxType, Interp* mapper); + +/** + * \brief FillPatch with data from the current level + * + * The destination MultiFab/FabArray is on the same AMR level as the + * source MultiFab/FabArray. Usually this can only be used on AMR level + * 0, because filling fine level MF usually requires coarse level + * data. If needed, interpolation in time is performed. + * + * \tparam MF the MultiFab/FabArray type + * \tparam BC functor for filling physical boundaries + * + * \param mf destination MF + * \param nghost number of ghost cells of mf needed to be filled + * \param time time associated with mf + * \param smf source MFs + * \param stime times associated smf + * \param scomp starting component of the source MFs + * \param dcomp starting component of the destination MF + * \param ncomp number of components + * \param geom Geometry for this level + * \param physbcf functor for physical boundaries + * \param bcfcomp starting component for physbcf + */ +template + requires IsFabArrayType +void FillPatchSingleLevel ( + MF& mf, + amrex::IntVect const& nghost, + amrex::Real time, + const amrex::Vector& smf, + const amrex::Vector& stime, + int scomp, int dcomp, int ncomp, + const amrex::Geometry& geom, + BC& physbcf, int bcfcomp +); + +/** + * \brief FillPatch with data from the current level + * + * The destination MultiFab/FabArray is on the same AMR level as the + * source MultiFab/FabArray. Usually this can only be used on AMR level + * 0, because filling fine level MF usually requires coarse level + * data. If needed, interpolation in time is performed. All ghost cells of + * the destination MF are filled. + * + * \tparam MF the MultiFab/FabArray type + * \tparam BC functor for filling physical boundaries + * + * \param mf destination MF + * \param time time associated with mf + * \param smf source MFs + * \param stime times associated smf + * \param scomp starting component of the source MFs + * \param dcomp starting component of the destination MF + * \param ncomp number of components + * \param geom Geometry for this level + * \param physbcf functor for physical boundaries + * \param bcfcomp starting component for physbcf + */ +template + requires IsFabArrayType +void FillPatchSingleLevel (MF& mf, Real time, + const Vector& smf, const Vector& stime, + int scomp, int dcomp, int ncomp, + const Geometry& geom, + BC& physbcf, int bcfcomp); + +/** + * \brief FillPatch with data from the current level and the level below. + * + * First, we fill the destination MultiFab/FabArray with the current + * level data as much as possible. This may include interpolation in + * time. For the rest of the destination MF, we fill them with the + * coarse level data using interpolation in space (and in time if + * needed). + * + * \tparam MF the MultiFab/FabArray type + * \tparam BC functor for filling physical boundaries + * \tparam Interp spatial interpolater + * \tparam PreInterpHook pre-interpolation hook + * \tparam PostInterpHook post-interpolation hook + * + * \param mf destination MF on the fine level + * \param nghost number of ghost cells of mf needed to be filled + * \param time time associated with mf + * \param cmf source MFs on the coarse level + * \param ct times associated cmf + * \param fmf source MFs on the fine level + * \param ft times associated fmf + * \param scomp starting component of the source MFs + * \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 cbc functor for physical boundaries on the coarse level + * \param cbccomp starting component for cbc + * \param fbc functor for physical boundaries on the fine level + * \param fbccomp starting component for fbc + * \param ratio refinement ratio + * \param mapper spatial interpolater + * \param bcs boundary types for each component. We need this because some interpolaters need it. + * \param bcscomp starting component for bcs + * \param pre_interp pre-interpolation hook + * \param post_interp post-interpolation hook + */ +template , + typename PostInterpHook=NullInterpHook > + requires IsFabArrayType +void FillPatchTwoLevels (MF& mf, IntVect const& nghost, Real time, + const Vector& cmf, const Vector& ct, + const Vector& fmf, const Vector& 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& bcs, int bcscomp, + const PreInterpHook& pre_interp = {}, + const PostInterpHook& post_interp = {}); + +/** + * \brief FillPatch with data from the current level and the level below. + * + * First, we fill the destination MultiFab/FabArray with the current + * level data as much as possible. This may include interpolation in + * time. For the rest of the destination MF, we fill them with the + * coarse level data using interpolation in space (and in time if + * needed). All ghost cells of the destination MF are filled. + * + * \tparam MF the MultiFab/FabArray type + * \tparam BC functor for filling physical boundaries + * \tparam Interp spatial interpolater + * \tparam PreInterpHook pre-interpolation hook + * \tparam PostInterpHook post-interpolation hook + * + * \param mf destination MF on the fine level + * \param time time associated with mf + * \param cmf source MFs on the coarse level + * \param ct times associated cmf + * \param fmf source MFs on the fine level + * \param ft times associated fmf + * \param scomp starting component of the source MFs + * \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 cbc functor for physical boundaries on the coarse level + * \param cbccomp starting component for cbc + * \param fbc functor for physical boundaries on the fine level + * \param fbccomp starting component for fbc + * \param ratio refinement ratio + * \param mapper spatial interpolater + * \param bcs boundary types for each component. We need this because some interpolaters need it. + * \param bcscomp starting component for bcs + * \param pre_interp pre-interpolation hook + * \param post_interp post-interpolation hook + */ +template , + typename PostInterpHook=NullInterpHook > + requires IsFabArrayType +void FillPatchTwoLevels (MF& mf, Real time, + const Vector& cmf, const Vector& ct, + const Vector& fmf, const Vector& 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& bcs, int bcscomp, + const PreInterpHook& pre_interp = {}, + const PostInterpHook& post_interp = {}); + +/** + * \brief FillPatch for face variables with data from the current level + * and the level below. Sometimes, we need to fillpatch all + * AMREX_SPACEDIM face MultiFabs togother to satisfy certain constraint + * such as divergence preserving. + * + * First, we fill the destination MultiFab/FabArray's with the current + * level data as much as possible. This may include interpolation in + * time. For the rest of the destination MFs, we fill them with the + * coarse level data using interpolation in space (and in time if + * needed). + * + * \tparam MF the MultiFab/FabArray type + * \tparam BC functor for filling physical boundaries + * \tparam Interp spatial interpolater + * \tparam PreInterpHook pre-interpolation hook + * \tparam PostInterpHook post-interpolation hook + * + * \param mf destination MFs on the fine level + * \param nghost number of ghost cells of mf needed to be filled + * \param time time associated with mf + * \param cmf source MFs on the coarse level + * \param ct times associated cmf + * \param fmf source MFs on the fine level + * \param ft times associated fmf + * \param scomp starting component of the source MFs + * \param dcomp starting component of the destination MFs + * \param ncomp number of components + * \param cgeom Geometry for the coarse level + * \param fgeom Geometry for the fine level + * \param cbc functor for physical boundaries on the coarse level + * \param cbccomp starting component for cbc + * \param fbc functor for physical boundaries on the fine level + * \param fbccomp starting component for fbc + * \param ratio refinement ratio + * \param mapper spatial interpolater + * \param bcs boundary types for each component. We need this because some interpolaters need it. + * \param bcscomp starting component for bcs + * \param pre_interp pre-interpolation hook + * \param post_interp post-interpolation hook + */ +template , + typename PostInterpHook=NullInterpHook > + requires IsFabArrayType +void FillPatchTwoLevels (Array const& mf, IntVect const& nghost, Real time, + const Vector >& cmf, const Vector& ct, + const Vector >& fmf, const Vector& ft, + int scomp, int dcomp, int ncomp, + const Geometry& cgeom, const Geometry& fgeom, + Array& cbc, const Array& cbccomp, + Array& fbc, const Array& fbccomp, + const IntVect& ratio, + Interp* mapper, + const Array, AMREX_SPACEDIM>& bcs, const Array& bcscomp, + const PreInterpHook& pre_interp = {}, + const PostInterpHook& post_interp = {}); + +/** + * \brief FillPatch for face variables with data from the current level + * and the level below. Sometimes, we need to fillpatch all + * AMREX_SPACEDIM face MultiFabs togother to satisfy certain constraint + * such as divergence preserving. + * + * First, we fill the destination MultiFab/FabArray's with the current + * level data as much as possible. This may include interpolation in + * time. For the rest of the destination MFs, we fill them with the + * coarse level data using interpolation in space (and in time if + * needed). + * + * \tparam MF the MultiFab/FabArray type + * \tparam BC functor for filling physical boundaries + * \tparam Interp spatial interpolater + * \tparam PreInterpHook pre-interpolation hook + * \tparam PostInterpHook post-interpolation hook + * + * \param mf destination MFs on the fine level + * \param nghost number of ghost cells of mf needed to be filled + * \param time time associated with mf + * \param cmf source MFs on the coarse level + * \param ct times associated cmf + * \param fmf source MFs on the fine level + * \param ft times associated fmf + * \param scomp starting component of the source MFs + * \param dcomp starting component of the destination MFs + * \param ncomp number of components + * \param cgeom Geometry for the coarse level + * \param fgeom Geometry for the fine level + * \param cbc functor for physical boundaries on the coarse level + * \param cbccomp starting component for cbc + * \param fbc functor for physical boundaries on the fine level + * \param fbccomp starting component for fbc + * \param ratio refinement ratio + * \param mapper spatial interpolater + * \param bcs boundary types for each component. We need this because some interpolaters need it. + * \param bcscomp starting component for bcs + * \param pre_interp pre-interpolation hook + * \param post_interp post-interpolation hook + */ +template , + typename PostInterpHook=NullInterpHook > + requires IsFabArrayType +void FillPatchTwoLevels (Array const& mf, IntVect const& nghost, Real time, + const Vector >& cmf, const Vector& ct, + const Vector >& fmf, const Vector& ft, + int scomp, int dcomp, int ncomp, + const Geometry& cgeom, const Geometry& fgeom, + Array& cbc, int cbccomp, + Array& fbc, int fbccomp, + const IntVect& ratio, + Interp* mapper, + const Array, AMREX_SPACEDIM>& bcs, int bcscomp, + const PreInterpHook& pre_interp = {}, + const PostInterpHook& post_interp = {}); + +/** + * \brief FillPatch for face variables with data from the current level + * and the level below. Sometimes, we need to fillpatch all + * AMREX_SPACEDIM face MultiFabs togother to satisfy certain constraint + * such as divergence preserving. + * + * First, we fill the destination MultiFab/FabArray's with the current + * level data as much as possible. This may include interpolation in + * time. For the rest of the destination MFs, we fill them with the + * coarse level data using interpolation in space (and in time if + * needed). All ghost cells of the destination MFs are filled. + * + * \tparam MF the MultiFab/FabArray type + * \tparam BC functor for filling physical boundaries + * \tparam Interp spatial interpolater + * \tparam PreInterpHook pre-interpolation hook + * \tparam PostInterpHook post-interpolation hook + * + * \param mf destination MFs on the fine level + * \param time time associated with mf + * \param cmf source MFs on the coarse level + * \param ct times associated cmf + * \param fmf source MFs on the fine level + * \param ft times associated fmf + * \param scomp starting component of the source MFs + * \param dcomp starting component of the destination MFs + * \param ncomp number of components + * \param cgeom Geometry for the coarse level + * \param fgeom Geometry for the fine level + * \param cbc functor for physical boundaries on the coarse level + * \param cbccomp starting component for cbc + * \param fbc functor for physical boundaries on the fine level + * \param fbccomp starting component for fbc + * \param ratio refinement ratio + * \param mapper spatial interpolater + * \param bcs boundary types for each component. We need this because some interpolaters need it. + * \param bcscomp starting component for bcs + * \param pre_interp pre-interpolation hook + * \param post_interp post-interpolation hook + */ +template , + typename PostInterpHook=NullInterpHook > + requires IsFabArrayType +void FillPatchTwoLevels (Array const& mf, Real time, + const Vector >& cmf, const Vector& ct, + const Vector >& fmf, const Vector& ft, + int scomp, int dcomp, int ncomp, + const Geometry& cgeom, const Geometry& fgeom, + Array& cbc, int cbccomp, + Array& fbc, int fbccomp, + const IntVect& ratio, + Interp* mapper, + const Array, AMREX_SPACEDIM>& bcs, int bcscomp, + const PreInterpHook& pre_interp = {}, + const PostInterpHook& post_interp = {}); #ifdef AMREX_USE_EB - /** - * \brief FillPatch with data from the current level and the level below. - * - * First, we fill the destination MultiFab/FabArray with the current - * level data as much as possible. This may include interpolation in - * time. For the rest of the destination MF, we fill them with the - * coarse level data using interpolation in space (and in time if - * needed). - * - * \tparam MF the MultiFab/FabArray type - * \tparam BC functor for filling physical boundaries - * \tparam Interp spatial interpolater - * \tparam PreInterpHook pre-interpolation hook - * \tparam PostInterpHook post-interpolation hook - * - * \param mf destination MF on the fine level - * \param nghost number of ghost cells of mf needed to be filled - * \param time time associated with mf - * \param index_space EB IndexSpace - * \param cmf source MFs on the coarse level - * \param ct times associated cmf - * \param fmf source MFs on the fine level - * \param ft times associated fmf - * \param scomp starting component of the source MFs - * \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 cbc functor for physical boundaries on the coarse level - * \param cbccomp starting component for cbc - * \param fbc functor for physical boundaries on the fine level - * \param fbccomp starting component for fbc - * \param ratio refinement ratio - * \param mapper spatial interpolater - * \param bcs boundary types for each component. We need this because some interpolaters need it. - * \param bcscomp starting component for bcs - * \param pre_interp pre-interpolation hook - * \param post_interp post-interpolation hook - */ - template - std::enable_if_t::value> - FillPatchTwoLevels (MF& mf, IntVect const& nghost, Real time, - const EB2::IndexSpace& index_space, - const Vector& cmf, const Vector& ct, - const Vector& fmf, const Vector& 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& bcs, int bcscomp, - const PreInterpHook& pre_interp, - const PostInterpHook& post_interp); - - /** - * \brief FillPatch with data from the current level and the level below. - * - * First, we fill the destination MultiFab/FabArray with the current - * level data as much as possible. This may include interpolation in - * time. For the rest of the destination MF, we fill them with the - * coarse level data using interpolation in space (and in time if - * needed). All ghost cells of the destination MF are filled. - * - * \tparam MF the MultiFab/FabArray type - * \tparam BC functor for filling physical boundaries - * \tparam Interp spatial interpolater - * \tparam PreInterpHook pre-interpolation hook - * \tparam PostInterpHook post-interpolation hook - * - * \param mf destination MF on the fine level - * \param time time associated with mf - * \param index_space EB IndexSpace - * \param cmf source MFs on the coarse level - * \param ct times associated cmf - * \param fmf source MFs on the fine level - * \param ft times associated fmf - * \param scomp starting component of the source MFs - * \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 cbc functor for physical boundaries on the coarse level - * \param cbccomp starting component for cbc - * \param fbc functor for physical boundaries on the fine level - * \param fbccomp starting component for fbc - * \param ratio refinement ratio - * \param mapper spatial interpolater - * \param bcs boundary types for each component. We need this because some interpolaters need it. - * \param bcscomp starting component for bcs - * \param pre_interp pre-interpolation hook - * \param post_interp post-interpolation hook - */ - template - std::enable_if_t::value> - FillPatchTwoLevels (MF& mf, Real time, - const EB2::IndexSpace& index_space, - const Vector& cmf, const Vector& ct, - const Vector& fmf, const Vector& 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& bcs, int bcscomp, - const PreInterpHook& pre_interp, - const PostInterpHook& post_interp); +/** + * \brief FillPatch with data from the current level and the level below. + * + * First, we fill the destination MultiFab/FabArray with the current + * level data as much as possible. This may include interpolation in + * time. For the rest of the destination MF, we fill them with the + * coarse level data using interpolation in space (and in time if + * needed). + * + * \tparam MF the MultiFab/FabArray type + * \tparam BC functor for filling physical boundaries + * \tparam Interp spatial interpolater + * \tparam PreInterpHook pre-interpolation hook + * \tparam PostInterpHook post-interpolation hook + * + * \param mf destination MF on the fine level + * \param nghost number of ghost cells of mf needed to be filled + * \param time time associated with mf + * \param index_space EB IndexSpace + * \param cmf source MFs on the coarse level + * \param ct times associated cmf + * \param fmf source MFs on the fine level + * \param ft times associated fmf + * \param scomp starting component of the source MFs + * \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 cbc functor for physical boundaries on the coarse level + * \param cbccomp starting component for cbc + * \param fbc functor for physical boundaries on the fine level + * \param fbccomp starting component for fbc + * \param ratio refinement ratio + * \param mapper spatial interpolater + * \param bcs boundary types for each component. We need this because some interpolaters need it. + * \param bcscomp starting component for bcs + * \param pre_interp pre-interpolation hook + * \param post_interp post-interpolation hook + */ +template + requires IsFabArrayType +void FillPatchTwoLevels (MF& mf, IntVect const& nghost, Real time, + const EB2::IndexSpace& index_space, + const Vector& cmf, const Vector& ct, + const Vector& fmf, const Vector& 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& bcs, int bcscomp, + const PreInterpHook& pre_interp, + const PostInterpHook& post_interp); + +/** + * \brief FillPatch with data from the current level and the level below. + * + * First, we fill the destination MultiFab/FabArray with the current + * level data as much as possible. This may include interpolation in + * time. For the rest of the destination MF, we fill them with the + * coarse level data using interpolation in space (and in time if + * needed). All ghost cells of the destination MF are filled. + * + * \tparam MF the MultiFab/FabArray type + * \tparam BC functor for filling physical boundaries + * \tparam Interp spatial interpolater + * \tparam PreInterpHook pre-interpolation hook + * \tparam PostInterpHook post-interpolation hook + * + * \param mf destination MF on the fine level + * \param time time associated with mf + * \param index_space EB IndexSpace + * \param cmf source MFs on the coarse level + * \param ct times associated cmf + * \param fmf source MFs on the fine level + * \param ft times associated fmf + * \param scomp starting component of the source MFs + * \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 cbc functor for physical boundaries on the coarse level + * \param cbccomp starting component for cbc + * \param fbc functor for physical boundaries on the fine level + * \param fbccomp starting component for fbc + * \param ratio refinement ratio + * \param mapper spatial interpolater + * \param bcs boundary types for each component. We need this because some interpolaters need it. + * \param bcscomp starting component for bcs + * \param pre_interp pre-interpolation hook + * \param post_interp post-interpolation hook + */ +template + requires IsFabArrayType +void FillPatchTwoLevels (MF& mf, Real time, + const EB2::IndexSpace& index_space, + const Vector& cmf, const Vector& ct, + const Vector& fmf, const Vector& 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& bcs, int bcscomp, + const PreInterpHook& pre_interp, + const PostInterpHook& post_interp); #endif - /** - * \brief Fill with interpolation of coarse level data - * - * All ghost cells of the destination MF are filled. - * - * \tparam MF the MultiFab/FabArray type - * \tparam BC functor for filling physical boundaries - * \tparam Interp spatial interpolater - * \tparam PreInterpHook pre-interpolation hook - * \tparam PostInterpHook post-interpolation hook - * - * \param mf destination MF on the fine level - * \param time time associated with mf - * \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 cbc functor for physical boundaries on the coarse level - * \param cbccomp starting component for cbc - * \param fbc functor for physical boundaries on the fine level - * \param fbccomp starting component for fbc - * \param ratio refinement ratio - * \param mapper spatial interpolater - * \param bcs boundary types for each component. We need this because some interpolaters need it. - * \param bcscomp starting component for bcs - * \param pre_interp pre-interpolation hook - * \param post_interp post-interpolation hook - */ - template , - typename PostInterpHook=NullInterpHook > - std::enable_if_t::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& bcs, int bcscomp, - const PreInterpHook& pre_interp = {}, - const PostInterpHook& post_interp = {}); - - /** - * \brief Fill with interpolation of coarse level data - * - * \tparam MF the MultiFab/FabArray type - * \tparam BC functor for filling physical boundaries - * \tparam Interp spatial interpolater - * \tparam PreInterpHook pre-interpolation hook - * \tparam PostInterpHook post-interpolation hook - * - * \param mf destination MF on the fine level - * \param nghost number of ghost cells of mf needed to be filled - * \param time time associated with mf - * \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 cbc functor for physical boundaries on the coarse level - * \param cbccomp starting component for cbc - * \param fbc functor for physical boundaries on the fine level - * \param fbccomp starting component for fbc - * \param ratio refinement ratio - * \param mapper spatial interpolater - * \param bcs boundary types for each component. We need this because some interpolaters need it. - * \param bcscomp starting component for bcs - * \param pre_interp pre-interpolation hook - * \param post_interp post-interpolation hook - */ - template , - typename PostInterpHook=NullInterpHook > - std::enable_if_t::value> - InterpFromCoarseLevel (MF& mf, IntVect const& nghost, 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& bcs, int bcscomp, - const PreInterpHook& pre_interp = {}, - const PostInterpHook& post_interp = {}); - - /** - * \brief Fill with interpolation of coarse level data - * - * \tparam MF the MultiFab/FabArray type - * \tparam BC functor for filling physical boundaries - * \tparam Interp spatial interpolater - * \tparam PreInterpHook pre-interpolation hook - * \tparam PostInterpHook post-interpolation hook - * - * \param mf destination MF on the fine level - * \param nghost number of ghost cells of mf needed to be filled - * \param time time associated with mf - * \param index_space EB IndexSpace - * \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 cbc functor for physical boundaries on the coarse level - * \param cbccomp starting component for cbc - * \param fbc functor for physical boundaries on the fine level - * \param fbccomp starting component for fbc - * \param ratio refinement ratio - * \param mapper spatial interpolater - * \param bcs boundary types for each component. We need this because some interpolaters need it. - * \param bcscomp starting component for bcs - * \param pre_interp pre-interpolation hook - * \param post_interp post-interpolation hook - */ - template , - typename PostInterpHook=NullInterpHook > - std::enable_if_t::value> - InterpFromCoarseLevel (MF& mf, IntVect const& nghost, Real time, - const EB2::IndexSpace* index_space, - 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& bcs, int bcscomp, - const PreInterpHook& pre_interp = {}, - const PostInterpHook& post_interp = {}); - - /** - * \brief Fill face variables with data from the coarse level. - * Sometimes, we need to fillpatch all AMREX_SPACEDIM face MultiFabs - * together to satisfy certain constraint such as divergence preserving. - * - * \tparam MF the MultiFab/FabArray type - * \tparam BC functor for filling physical boundaries - * \tparam Interp spatial interpolater - * \tparam PreInterpHook pre-interpolation hook - * \tparam PostInterpHook post-interpolation hook - * - * \param mf destination MFs on the fine level - * \param time time associated with mf - * \param cmf source MFs on the coarse level - * \param scomp starting component of the source MFs - * \param dcomp starting component of the destination MFs - * \param ncomp number of components - * \param cgeom Geometry for the coarse level - * \param fgeom Geometry for the fine level - * \param cbc functor for physical boundaries on the coarse level - * \param cbccomp starting component for cbc - * \param fbc functor for physical boundaries on the fine level - * \param fbccomp starting component for fbc - * \param ratio refinement ratio - * \param mapper spatial interpolater - * \param bcs boundary types for each component. We need this because some interpolaters need it. - * \param bcscomp starting component for bcs - * \param pre_interp pre-interpolation hook - * \param post_interp post-interpolation hook - */ - template , - typename PostInterpHook=NullInterpHook > - std::enable_if_t::value> - InterpFromCoarseLevel (Array const& mf, Real time, - const Array& cmf, int scomp, int dcomp, int ncomp, - const Geometry& cgeom, const Geometry& fgeom, - Array& cbc, int cbccomp, - Array& fbc, int fbccomp, - const IntVect& ratio, - Interp* mapper, - const Array, AMREX_SPACEDIM>& bcs, int bcscomp, - const PreInterpHook& pre_interp = {}, - const PostInterpHook& post_interp = {}); - - /** - * \brief Fill face variables with data from the coarse level. - * Sometimes, we need to fillpatch all AMREX_SPACEDIM face MultiFabs - * togother to satisfy certain constraint such as divergence preserving. - * - * \tparam MF the MultiFab/FabArray type - * \tparam BC functor for filling physical boundaries - * \tparam Interp spatial interpolater - * \tparam PreInterpHook pre-interpolation hook - * \tparam PostInterpHook post-interpolation hook - * - * \param mf destination MFs on the fine level - * \param nghost number of ghost cells of mf needed to be filled - * \param time time associated with mf - * \param cmf source MFs on the coarse level - * \param scomp starting component of the source MFs - * \param dcomp starting component of the destination MFs - * \param ncomp number of components - * \param cgeom Geometry for the coarse level - * \param fgeom Geometry for the fine level - * \param cbc functor for physical boundaries on the coarse level - * \param cbccomp starting component for cbc - * \param fbc functor for physical boundaries on the fine level - * \param fbccomp starting component for fbc - * \param ratio refinement ratio - * \param mapper spatial interpolater - * \param bcs boundary types for each component. We need this because some interpolaters need it. - * \param bcscomp starting component for bcs - * \param pre_interp pre-interpolation hook - * \param post_interp post-interpolation hook - */ - template , - typename PostInterpHook=NullInterpHook > - std::enable_if_t::value> - InterpFromCoarseLevel (Array const& mf, IntVect const& nghost, Real time, - const Array& cmf, int scomp, int dcomp, int ncomp, - const Geometry& cgeom, const Geometry& fgeom, - Array& cbc, int cbccomp, - Array& fbc, int fbccomp, - const IntVect& ratio, - Interp* mapper, - const Array, AMREX_SPACEDIM>& bcs, int bcscomp, - 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 - * \param bcscomp starting component for bcs - */ - 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, int bcscomp); - - /** - * \brief FillPatch with data from the current level - * - * In this version of FillPatchSingleLevel, it's the CALLER's - * responsibility to make sure that smf has `snghost` ghost cells - * already filled before calling this function. The destination - * MultiFab/FabArray is on the same AMR level as the source - * MultiFab/FabArray. If needed, interpolation in time is performed. - * - * \tparam MF the MultiFab/FabArray type - * - * \param mf destination MF - * \param nghost number of ghost cells of mf needed to be filled - * \param time time associated with mf - * \param smf source MFs - * \param snghost number of ghost cells in smf with valid data - * \param stime times associated smf - * \param scomp starting component of the source MFs - * \param dcomp starting component of the destination MF - * \param ncomp number of components - * \param geom Geometry for this level - */ - template - std::enable_if_t::value> - FillPatchSingleLevel (MF& mf, IntVect const& nghost, Real time, - const Vector& smf, IntVect const& snghost, - const Vector& stime, int scomp, int dcomp, int ncomp, - const Geometry& geom); - - /** - * \brief FillPatch with data from the current level and the level below. - * - * In this version of FillPatchTwoLevels, 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 time time associated with mf - * \param cmf source MFs on the coarse level - * \param ct times associated cmf - * \param fmf source MFs on the fine level - * \param ft times associated fmf - * \param scomp starting component of the source MFs - * \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 boundary types for each component. - * \param bcscomp starting component for bcs - */ - template - std::enable_if_t::value> - FillPatchTwoLevels (MF& mf, IntVect const& nghost, - IntVect const& nghost_outside_domain, Real time, - const Vector& cmf, const Vector& ct, - const Vector& fmf, const Vector& ft, - int scomp, int dcomp, int ncomp, - const Geometry& cgeom, const Geometry& fgeom, - const IntVect& ratio, Interp* mapper, - const Vector& bcs, int bcscomp); +/** + * \brief Fill with interpolation of coarse level data + * + * All ghost cells of the destination MF are filled. + * + * \tparam MF the MultiFab/FabArray type + * \tparam BC functor for filling physical boundaries + * \tparam Interp spatial interpolater + * \tparam PreInterpHook pre-interpolation hook + * \tparam PostInterpHook post-interpolation hook + * + * \param mf destination MF on the fine level + * \param time time associated with mf + * \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 cbc functor for physical boundaries on the coarse level + * \param cbccomp starting component for cbc + * \param fbc functor for physical boundaries on the fine level + * \param fbccomp starting component for fbc + * \param ratio refinement ratio + * \param mapper spatial interpolater + * \param bcs boundary types for each component. We need this because some interpolaters need it. + * \param bcscomp starting component for bcs + * \param pre_interp pre-interpolation hook + * \param post_interp post-interpolation hook + */ +template , + typename PostInterpHook=NullInterpHook > + requires IsFabArrayType +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& bcs, int bcscomp, + const PreInterpHook& pre_interp = {}, + const PostInterpHook& post_interp = {}); + +/** + * \brief Fill with interpolation of coarse level data + * + * \tparam MF the MultiFab/FabArray type + * \tparam BC functor for filling physical boundaries + * \tparam Interp spatial interpolater + * \tparam PreInterpHook pre-interpolation hook + * \tparam PostInterpHook post-interpolation hook + * + * \param mf destination MF on the fine level + * \param nghost number of ghost cells of mf needed to be filled + * \param time time associated with mf + * \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 cbc functor for physical boundaries on the coarse level + * \param cbccomp starting component for cbc + * \param fbc functor for physical boundaries on the fine level + * \param fbccomp starting component for fbc + * \param ratio refinement ratio + * \param mapper spatial interpolater + * \param bcs boundary types for each component. We need this because some interpolaters need it. + * \param bcscomp starting component for bcs + * \param pre_interp pre-interpolation hook + * \param post_interp post-interpolation hook + */ +template , + typename PostInterpHook=NullInterpHook > + requires IsFabArrayType +void InterpFromCoarseLevel (MF& mf, IntVect const& nghost, 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& bcs, int bcscomp, + const PreInterpHook& pre_interp = {}, + const PostInterpHook& post_interp = {}); + +/** + * \brief Fill with interpolation of coarse level data + * + * \tparam MF the MultiFab/FabArray type + * \tparam BC functor for filling physical boundaries + * \tparam Interp spatial interpolater + * \tparam PreInterpHook pre-interpolation hook + * \tparam PostInterpHook post-interpolation hook + * + * \param mf destination MF on the fine level + * \param nghost number of ghost cells of mf needed to be filled + * \param time time associated with mf + * \param index_space EB IndexSpace + * \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 cbc functor for physical boundaries on the coarse level + * \param cbccomp starting component for cbc + * \param fbc functor for physical boundaries on the fine level + * \param fbccomp starting component for fbc + * \param ratio refinement ratio + * \param mapper spatial interpolater + * \param bcs boundary types for each component. We need this because some interpolaters need it. + * \param bcscomp starting component for bcs + * \param pre_interp pre-interpolation hook + * \param post_interp post-interpolation hook + */ +template , + typename PostInterpHook=NullInterpHook > + requires IsFabArrayType +void InterpFromCoarseLevel (MF& mf, IntVect const& nghost, Real time, + const EB2::IndexSpace* index_space, + 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& bcs, int bcscomp, + const PreInterpHook& pre_interp = {}, + const PostInterpHook& post_interp = {}); + +/** + * \brief Fill face variables with data from the coarse level. + * Sometimes, we need to fillpatch all AMREX_SPACEDIM face MultiFabs + * together to satisfy certain constraint such as divergence preserving. + * + * \tparam MF the MultiFab/FabArray type + * \tparam BC functor for filling physical boundaries + * \tparam Interp spatial interpolater + * \tparam PreInterpHook pre-interpolation hook + * \tparam PostInterpHook post-interpolation hook + * + * \param mf destination MFs on the fine level + * \param time time associated with mf + * \param cmf source MFs on the coarse level + * \param scomp starting component of the source MFs + * \param dcomp starting component of the destination MFs + * \param ncomp number of components + * \param cgeom Geometry for the coarse level + * \param fgeom Geometry for the fine level + * \param cbc functor for physical boundaries on the coarse level + * \param cbccomp starting component for cbc + * \param fbc functor for physical boundaries on the fine level + * \param fbccomp starting component for fbc + * \param ratio refinement ratio + * \param mapper spatial interpolater + * \param bcs boundary types for each component. We need this because some interpolaters need it. + * \param bcscomp starting component for bcs + * \param pre_interp pre-interpolation hook + * \param post_interp post-interpolation hook + */ +template , + typename PostInterpHook=NullInterpHook > + requires IsFabArrayType +void InterpFromCoarseLevel (Array const& mf, Real time, + const Array& cmf, int scomp, int dcomp, int ncomp, + const Geometry& cgeom, const Geometry& fgeom, + Array& cbc, int cbccomp, + Array& fbc, int fbccomp, + const IntVect& ratio, + Interp* mapper, + const Array, AMREX_SPACEDIM>& bcs, int bcscomp, + const PreInterpHook& pre_interp = {}, + const PostInterpHook& post_interp = {}); + +/** + * \brief Fill face variables with data from the coarse level. + * Sometimes, we need to fillpatch all AMREX_SPACEDIM face MultiFabs + * togother to satisfy certain constraint such as divergence preserving. + * + * \tparam MF the MultiFab/FabArray type + * \tparam BC functor for filling physical boundaries + * \tparam Interp spatial interpolater + * \tparam PreInterpHook pre-interpolation hook + * \tparam PostInterpHook post-interpolation hook + * + * \param mf destination MFs on the fine level + * \param nghost number of ghost cells of mf needed to be filled + * \param time time associated with mf + * \param cmf source MFs on the coarse level + * \param scomp starting component of the source MFs + * \param dcomp starting component of the destination MFs + * \param ncomp number of components + * \param cgeom Geometry for the coarse level + * \param fgeom Geometry for the fine level + * \param cbc functor for physical boundaries on the coarse level + * \param cbccomp starting component for cbc + * \param fbc functor for physical boundaries on the fine level + * \param fbccomp starting component for fbc + * \param ratio refinement ratio + * \param mapper spatial interpolater + * \param bcs boundary types for each component. We need this because some interpolaters need it. + * \param bcscomp starting component for bcs + * \param pre_interp pre-interpolation hook + * \param post_interp post-interpolation hook + */ +template , + typename PostInterpHook=NullInterpHook > + requires IsFabArrayType +void InterpFromCoarseLevel (Array const& mf, IntVect const& nghost, Real time, + const Array& cmf, int scomp, int dcomp, int ncomp, + const Geometry& cgeom, const Geometry& fgeom, + Array& cbc, int cbccomp, + Array& fbc, int fbccomp, + const IntVect& ratio, + Interp* mapper, + const Array, AMREX_SPACEDIM>& bcs, int bcscomp, + 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 + * \param bcscomp starting component for bcs + */ +template + requires IsFabArrayType +void 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, int bcscomp); + +/** + * \brief FillPatch with data from the current level + * + * In this version of FillPatchSingleLevel, it's the CALLER's + * responsibility to make sure that smf has `snghost` ghost cells + * already filled before calling this function. The destination + * MultiFab/FabArray is on the same AMR level as the source + * MultiFab/FabArray. If needed, interpolation in time is performed. + * + * \tparam MF the MultiFab/FabArray type + * + * \param mf destination MF + * \param nghost number of ghost cells of mf needed to be filled + * \param time time associated with mf + * \param smf source MFs + * \param snghost number of ghost cells in smf with valid data + * \param stime times associated smf + * \param scomp starting component of the source MFs + * \param dcomp starting component of the destination MF + * \param ncomp number of components + * \param geom Geometry for this level + */ +template + requires IsFabArrayType +void FillPatchSingleLevel (MF& mf, IntVect const& nghost, Real time, + const Vector& smf, IntVect const& snghost, + const Vector& stime, int scomp, int dcomp, int ncomp, + const Geometry& geom); + +/** + * \brief FillPatch with data from the current level and the level below. + * + * In this version of FillPatchTwoLevels, 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 time time associated with mf + * \param cmf source MFs on the coarse level + * \param ct times associated cmf + * \param fmf source MFs on the fine level + * \param ft times associated fmf + * \param scomp starting component of the source MFs + * \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 boundary types for each component. + * \param bcscomp starting component for bcs + */ +template + requires IsFabArrayType +void FillPatchTwoLevels (MF& mf, IntVect const& nghost, + IntVect const& nghost_outside_domain, Real time, + const Vector& cmf, const Vector& ct, + const Vector& fmf, const Vector& ft, + int scomp, int dcomp, int ncomp, + const Geometry& cgeom, const Geometry& fgeom, + const IntVect& ratio, Interp* mapper, + const Vector& bcs, int bcscomp); #ifndef BL_NO_FORT - enum InterpEM_t { InterpE, InterpB}; - - void InterpCrseFineBndryEMfield (InterpEM_t interp_type, - const Array& crse, - Array& fine, - const Geometry& cgeom, const Geometry& fgeom, - int ref_ratio); - - void InterpCrseFineBndryEMfield (InterpEM_t interp_type, - const Array& crse, - const Array& fine, - const Geometry& cgeom, const Geometry& fgeom, - int ref_ratio); +enum InterpEM_t { InterpE, InterpB }; + +void InterpCrseFineBndryEMfield (InterpEM_t interp_type, + const Array& crse, + Array& fine, + const Geometry& cgeom, const Geometry& fgeom, + int ref_ratio); + +void InterpCrseFineBndryEMfield (InterpEM_t interp_type, + const Array& crse, + const Array& fine, + const Geometry& cgeom, const Geometry& fgeom, + int ref_ratio); #endif - /** - * \brief FillPatch with data from AMR levels. - * - * First, we try to fill the destination MultiFab/FabArray with this - * level's data if it's available. For the unfilled region, we try to - * fill with the coarse level below if it's available. Even coarser - * levels will be used if necessary till all regions are filled. This - * function is more expensive than FillPatchTwoLevels. So if one knows - * FillPatchTwoLevels can do the job because grids are properly nested, - * this function should be avoided. - * - * \tparam MF the MultiFab/FabArray type - * \tparam BC functor for filling physical boundaries - * \tparam Interp spatial interpolater - * - * \param mf destination MF - * \param level AMR level associated with mf - * \param nghost number of ghost cells of mf needed to be filled - * \param time time associated with mf - * \param smf source MFs. The outer Vector is for AMR levels, whereas the inner - * Vector is for data at various times. It is not an error if the - * level for the destination MF is finer than data in smf (i.e., - * `level >= smf.size()`). - * \param st times associated smf - * \param scomp starting component of the source MFs - * \param dcomp starting component of the destination MF - * \param ncomp number of components - * \param geom Geometry objects for AMR levels. The size must be big enough - * such that `level < geom.size()`. - * \param bc functors for physical boundaries on AMR levels. The size must be - * big enough such that `level < bc.size()`. - * \param bccomp starting component for bc - * \param ratio refinement ratio for AMR levels. The size must be big enough - * such that `level < bc.size()-1`. - * \param mapper spatial interpolater - * \param bcr boundary types for each component. We need this because some interpolaters need it. - * \param bcrcomp starting component for bcr - */ - template - std::enable_if_t::value> - FillPatchNLevels (MF& mf, int level, const IntVect& nghost, Real time, - const Vector>& smf, const Vector>& st, - int scomp, int dcomp, int ncomp, - const Vector& geom, - Vector& bc, int bccomp, - const Vector& ratio, - Interp* mapper, - const Vector& bcr, int bcrcomp); - +/** + * \brief FillPatch with data from AMR levels. + * + * First, we try to fill the destination MultiFab/FabArray with this + * level's data if it's available. For the unfilled region, we try to + * fill with the coarse level below if it's available. Even coarser + * levels will be used if necessary till all regions are filled. This + * function is more expensive than FillPatchTwoLevels. So if one knows + * FillPatchTwoLevels can do the job because grids are properly nested, + * this function should be avoided. + * + * \tparam MF the MultiFab/FabArray type + * \tparam BC functor for filling physical boundaries + * \tparam Interp spatial interpolater + * + * \param mf destination MF + * \param level AMR level associated with mf + * \param nghost number of ghost cells of mf needed to be filled + * \param time time associated with mf + * \param smf source MFs. The outer Vector is for AMR levels, whereas the inner + * Vector is for data at various times. It is not an error if the + * level for the destination MF is finer than data in smf (i.e., + * `level >= smf.size()`). + * \param st times associated smf + * \param scomp starting component of the source MFs + * \param dcomp starting component of the destination MF + * \param ncomp number of components + * \param geom Geometry objects for AMR levels. The size must be big enough + * such that `level < geom.size()`. + * \param bc functors for physical boundaries on AMR levels. The size must be + * big enough such that `level < bc.size()`. + * \param bccomp starting component for bc + * \param ratio refinement ratio for AMR levels. The size must be big enough + * such that `level < bc.size()-1`. + * \param mapper spatial interpolater + * \param bcr boundary types for each component. We need this because some interpolaters need it. + * \param bcrcomp starting component for bcr + */ +template + requires IsFabArrayType +void FillPatchNLevels (MF& mf, int level, const IntVect& nghost, Real time, + const Vector >& smf, const Vector >& st, + int scomp, int dcomp, int ncomp, + const Vector& geom, + Vector& bc, int bccomp, + const Vector& ratio, + Interp* mapper, + const Vector& bcr, int bcrcomp); } #include diff --git a/Src/AmrCore/AMReX_FillPatchUtil_I.H b/Src/AmrCore/AMReX_FillPatchUtil_I.H index 593f0edee4..09dbac484b 100644 --- a/Src/AmrCore/AMReX_FillPatchUtil_I.H +++ b/Src/AmrCore/AMReX_FillPatchUtil_I.H @@ -3,14 +3,11 @@ #include namespace amrex { - /// \cond DOXYGEN_IGNORE namespace detail { - template auto call_interp_hook (F const& f, MF& mf, int icomp, int ncomp) - -> decltype(f(mf[0],Box(),icomp,ncomp)) -{ + -> decltype(f(mf[0], Box(), icomp, ncomp)) { #ifdef AMREX_USE_OMP #pragma omp parallel if (Gpu::notInLaunchRegion()) #endif @@ -23,18 +20,16 @@ auto call_interp_hook (F const& f, MF& mf, int icomp, int ncomp) template auto call_interp_hook (F const& f, MF& mf, int icomp, int ncomp) - -> decltype(f(mf,icomp,ncomp)) -{ + -> decltype(f(mf, icomp, ncomp)) { f(mf, icomp, ncomp); } - } + /// \endcond template bool ProperlyNested (const IntVect& ratio, const IntVect& blocking_factor, int ngrow, - const IndexType& boxType, Interp* mapper) -{ + const IndexType& boxType, Interp* mapper) { int ratio_max = ratio[0]; #if (AMREX_SPACEDIM > 1) ratio_max = std::max(ratio_max, ratio[1]); @@ -46,11 +41,11 @@ bool ProperlyNested (const IntVect& ratio, const IntVect& blocking_factor, int n // (except at physical boundaries). const IntVect& nbuf = blocking_factor / ratio_max; - Box crse_box(IntVect(AMREX_D_DECL(0 ,0 ,0 )), IntVect(AMREX_D_DECL(4*nbuf[0]-1, - 4*nbuf[1]-1, - 4*nbuf[2]-1))); + Box crse_box(IntVect(AMREX_D_DECL(0, 0, 0)), IntVect(AMREX_D_DECL(4*nbuf[0]-1, + 4*nbuf[1]-1, + 4*nbuf[2]-1))); crse_box.convert(boxType); - Box fine_box(nbuf, IntVect(AMREX_D_DECL(3*nbuf[0]-1,3*nbuf[1]-1,3*nbuf[2]-1))); + Box fine_box(nbuf, IntVect(AMREX_D_DECL(3*nbuf[0]-1, 3*nbuf[1]-1, 3*nbuf[2]-1))); fine_box.convert(boxType); fine_box.refine(ratio_max); fine_box.grow(ngrow); @@ -59,56 +54,50 @@ bool ProperlyNested (const IntVect& ratio, const IntVect& blocking_factor, int n } template -std::enable_if_t::value> -FillPatchSingleLevel (MF& mf, Real time, - const Vector& smf, const Vector& stime, - int scomp, int dcomp, int ncomp, - const Geometry& geom, - BC& physbcf, int bcfcomp) -{ + requires IsFabArrayType +void FillPatchSingleLevel (MF& mf, Real time, + const Vector& smf, const Vector& stime, + int scomp, int dcomp, int ncomp, + const Geometry& geom, + BC& physbcf, int bcfcomp) { FillPatchSingleLevel(mf, mf.nGrowVect(), time, smf, stime, scomp, dcomp, ncomp, geom, physbcf, bcfcomp); } template -std::enable_if_t::value> -FillPatchSingleLevel (MF& mf, IntVect const& nghost, Real time, - const Vector& smf, const Vector& stime, - int scomp, int dcomp, int ncomp, - const Geometry& geom, - BC& physbcf, int bcfcomp) -{ + requires IsFabArrayType +void FillPatchSingleLevel (MF& mf, IntVect const& nghost, Real time, + const Vector& smf, const Vector& stime, + int scomp, int dcomp, int ncomp, + const Geometry& geom, + BC& physbcf, int bcfcomp) { BL_PROFILE("FillPatchSingleLevel"); AMREX_ASSERT((!smf.empty()) && - (scomp+ncomp <= smf[0]->nComp()) && - (dcomp+ncomp <= mf.nComp()) && - (smf.size() == stime.size()) && - nghost.allLE(mf.nGrowVect())); + (scomp+ncomp <= smf[0]->nComp()) && + (dcomp+ncomp <= mf.nComp()) && + (smf.size() == stime.size()) && + nghost.allLE(mf.nGrowVect())); IntVect src_ghost(0); - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { src_ghost = physbcf.fp1_src_ghost; } - if (smf.size() == 1) - { + if (smf.size() == 1) { if (&mf == smf[0] && scomp == dcomp) { mf.FillBoundary(dcomp, ncomp, nghost, geom.periodicity()); } else { mf.ParallelCopy(*smf[0], scomp, dcomp, ncomp, src_ghost, nghost, geom.periodicity()); } - } - else if (smf.size() == 2) - { + } else if (smf.size() == 2) { BL_ASSERT(smf[0]->boxArray() == smf[1]->boxArray()); MF raii; - MF * dmf; + MF* dmf; int destcomp; bool sameba; if (mf.boxArray() == smf[0]->boxArray() && - mf.DistributionMap() == smf[0]->DistributionMap()) - { + mf.DistributionMap() == smf[0]->DistributionMap()) { dmf = &mf; destcomp = dcomp; sameba = true; @@ -121,10 +110,9 @@ FillPatchSingleLevel (MF& mf, IntVect const& nghost, Real time, sameba = false; } - if ((dmf != smf[0] && dmf != smf[1]) || scomp != dcomp) - { + if ((dmf != smf[0] && dmf != smf[1]) || scomp != dcomp) { IntVect interp_ghost(0); - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { interp_ghost = physbcf.fp1_src_ghost; if (sameba) { interp_ghost.min(nghost); @@ -133,61 +121,49 @@ FillPatchSingleLevel (MF& mf, IntVect const& nghost, Real time, #ifdef AMREX_USE_OMP #pragma omp parallel if (Gpu::notInLaunchRegion()) #endif - for (MFIter mfi(*dmf,TilingIfNotGPU()); mfi.isValid(); ++mfi) - { + for (MFIter mfi(*dmf, TilingIfNotGPU()); mfi.isValid(); ++mfi) { const Box& bx = mfi.growntilebox(interp_ghost); const Real t0 = stime[0]; const Real t1 = stime[1]; auto const sfab0 = smf[0]->array(mfi); auto const sfab1 = smf[1]->array(mfi); - auto dfab = dmf->array(mfi); - - if (time == t0) - { - AMREX_HOST_DEVICE_PARALLEL_FOR_4D ( bx, ncomp, i, j, k, n, - { - dfab(i,j,k,n+destcomp) = sfab0(i,j,k,n+scomp); - }); - } - else if (time == t1) - { - AMREX_HOST_DEVICE_PARALLEL_FOR_4D ( bx, ncomp, i, j, k, n, - { - dfab(i,j,k,n+destcomp) = sfab1(i,j,k,n+scomp); - }); - } - else if (! amrex::almostEqual(t0,t1)) - { - Real alpha = (t1-time)/(t1-t0); - Real beta = (time-t0)/(t1-t0); - AMREX_HOST_DEVICE_PARALLEL_FOR_4D ( bx, ncomp, i, j, k, n, - { - dfab(i,j,k,n+destcomp) = alpha*sfab0(i,j,k,n+scomp) - + beta*sfab1(i,j,k,n+scomp); - }); - } - else - { - AMREX_HOST_DEVICE_PARALLEL_FOR_4D ( bx, ncomp, i, j, k, n, - { - dfab(i,j,k,n+destcomp) = sfab0(i,j,k,n+scomp); - }); + auto dfab = dmf->array(mfi); + + if (time == t0) { + AMREX_HOST_DEVICE_PARALLEL_FOR_4D(bx, ncomp, i, j, k, n, + { + dfab(i,j,k,n+destcomp) = sfab0(i,j,k,n+scomp); + }); + } else if (time == t1) { + AMREX_HOST_DEVICE_PARALLEL_FOR_4D(bx, ncomp, i, j, k, n, + { + dfab(i,j,k,n+destcomp) = sfab1(i,j,k,n+scomp); + }); + } else if (!amrex::almostEqual(t0, t1)) { + Real alpha = (t1 - time) / (t1 - t0); + Real beta = (time - t0) / (t1 - t0); + AMREX_HOST_DEVICE_PARALLEL_FOR_4D(bx, ncomp, i, j, k, n, + { + dfab(i,j,k,n+destcomp) = alpha*sfab0(i,j,k,n+scomp) + + beta*sfab1(i,j,k,n+scomp); + }); + } else { + AMREX_HOST_DEVICE_PARALLEL_FOR_4D(bx, ncomp, i, j, k, n, + { + dfab(i,j,k,n+destcomp) = sfab0(i,j,k,n+scomp); + }); } } } - if (sameba) - { + if (sameba) { // Note that when sameba is true mf's BoxArray is nonoverlapping. // So FillBoundary is safe. mf.FillBoundary(dcomp, ncomp, nghost, geom.periodicity()); - } - else - { + } else { mf.ParallelCopy(*dmf, 0, dcomp, ncomp, src_ghost, nghost, geom.periodicity()); } - } - else { + } else { amrex::Abort("FillPatchSingleLevel: high-order interpolation in time not implemented yet"); } @@ -217,30 +193,28 @@ void FillPatchInterp (MultiFab& mf_fine_patch, int fcomp, MultiFab const& mf_crs MFInterpolater* mapper, const Vector& bcs, int bcscomp); template -std::enable_if_t::value && !std::is_same_v> -FillPatchInterp (MF& mf_fine_patch, int fcomp, MF const& mf_crse_patch, int ccomp, - int ncomp, IntVect const& ng, const Geometry& cgeom, const Geometry& fgeom, - Box const& dest_domain, const IntVect& ratio, - Interp* mapper, const Vector& bcs, int bcscomp) -{ + requires IsFabArrayType && IsSpecificInterp +void FillPatchInterp (MF& mf_fine_patch, int fcomp, MF const& mf_crse_patch, int ccomp, + int ncomp, IntVect const& ng, const Geometry& cgeom, const Geometry& fgeom, + Box const& dest_domain, const IntVect& ratio, + Interp* mapper, const Vector& bcs, int bcscomp) { BL_PROFILE("FillPatchInterp(Fab)"); Box const& cdomain = amrex::convert(cgeom.Domain(), mf_fine_patch.ixType()); - int idummy=0; + int idummy = 0; #ifdef AMREX_USE_OMP #pragma omp parallel if (Gpu::notInLaunchRegion()) #endif { Vector bcr(ncomp); - for (MFIter mfi(mf_fine_patch); mfi.isValid(); ++mfi) - { + for (MFIter mfi(mf_fine_patch); mfi.isValid(); ++mfi) { auto& sfab = mf_crse_patch[mfi]; const Box& sbx = sfab.box(); auto& dfab = mf_fine_patch[mfi]; - Box const& dbx = amrex::grow(mfi.validbox(),ng) & dest_domain; + Box const& dbx = amrex::grow(mfi.validbox(), ng) & dest_domain; - amrex::setBC(sbx,cdomain,bcscomp,0,ncomp,bcs,bcr); + amrex::setBC(sbx, cdomain, bcscomp, 0, ncomp, bcs, bcr); mapper->interp(sfab, ccomp, dfab, fcomp, ncomp, dbx, ratio, cgeom, fgeom, bcr, idummy, idummy, RunOn::Gpu); } @@ -248,12 +222,11 @@ FillPatchInterp (MF& mf_fine_patch, int fcomp, MF const& mf_crse_patch, int ccom } template -std::enable_if_t::value> -FillPatchInterp (MF& mf_fine_patch, int fcomp, MF const& mf_crse_patch, int ccomp, - int ncomp, IntVect const& ng, const Geometry& cgeom, const Geometry& fgeom, - Box const& dest_domain, const IntVect& ratio, - InterpBase* mapper, const Vector& bcs, int bcscomp) -{ + requires IsFabArrayType +void FillPatchInterp (MF& mf_fine_patch, int fcomp, MF const& mf_crse_patch, int ccomp, + int ncomp, IntVect const& ng, const Geometry& cgeom, const Geometry& fgeom, + Box const& dest_domain, const IntVect& ratio, + InterpBase* mapper, const Vector& bcs, int bcscomp) { if (dynamic_cast(mapper)) { FillPatchInterp(mf_fine_patch, fcomp, mf_crse_patch, ccomp, ncomp, ng, cgeom, fgeom, dest_domain, ratio, @@ -268,54 +241,49 @@ FillPatchInterp (MF& mf_fine_patch, int fcomp, MF const& mf_crse_patch, int ccom } template -std::enable_if_t::value && !std::is_same_v> -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& bcs) -{ + requires IsFabArrayType && IsSpecificInterp +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& bcs) { Vector bcr(ncomp); Box const& cdomain = amrex::convert(crse_geom.Domain(), mf_crse_patch.ixType()); - for (MFIter mfi(mf_refined_patch);mfi.isValid(); ++mfi) - { + for (MFIter mfi(mf_refined_patch); mfi.isValid(); ++mfi) { auto& sfab = mf_crse_patch[mfi]; const Box& sbx = sfab.box(); auto& dfab = mf_refined_patch[mfi]; Box const& dbx = dfab.box(); auto& ifab = solve_mask[mfi]; - amrex::setBC(sbx,cdomain,bcscomp,0,ncomp,bcs,bcr); - interp->interp_face(sfab,crse_comp,dfab,fine_comp,ncomp, + amrex::setBC(sbx, cdomain, bcscomp, 0, ncomp, bcs, bcr); + interp->interp_face(sfab, crse_comp, dfab, fine_comp, ncomp, dbx, ratio, ifab, crse_geom, fine_geom, bcr, bcscomp, gpu_or_cpu); } } template -std::enable_if_t::value> -InterpFace (InterpBase *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 bccomp, RunOn gpu_or_cpu, - const Vector& bcs) -{ - if (dynamic_cast(interp)){ + requires IsFabArrayType +void InterpFace (InterpBase* 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 bccomp, RunOn gpu_or_cpu, + const Vector& bcs) { + if (dynamic_cast(interp)) { InterpFace(static_cast(interp), - mf_crse_patch, crse_comp,mf_refined_patch, fine_comp, - ncomp, ratio, solve_mask, crse_geom, fine_geom, bccomp, - gpu_or_cpu, bcs); - } - else if (dynamic_cast(interp)){ + mf_crse_patch, crse_comp, mf_refined_patch, fine_comp, + ncomp, ratio, solve_mask, crse_geom, fine_geom, bccomp, + gpu_or_cpu, bcs); + } else if (dynamic_cast(interp)) { InterpFace(static_cast(interp), - mf_crse_patch, crse_comp,mf_refined_patch, fine_comp, - ncomp, ratio, solve_mask, crse_geom, fine_geom, bccomp, - gpu_or_cpu, bcs); - } - else { + mf_crse_patch, crse_comp, mf_refined_patch, fine_comp, + ncomp, ratio, solve_mask, crse_geom, fine_geom, bccomp, + gpu_or_cpu, bcs); + } else { amrex::Abort("InterpFace: unknown InterpBase"); } } @@ -323,763 +291,737 @@ InterpFace (InterpBase *interp, /// \cond DOXYGEN_IGNORE namespace detail { - // ======== FArrayBox - template , - int> = 0> - MF make_mf_crse_patch (FabArrayBase::FPinfo const& fpc, int ncomp) - { - MF mf_crse_patch(fpc.ba_crse_patch, fpc.dm_patch, ncomp, 0, MFInfo(), - *fpc.fact_crse_patch); - return mf_crse_patch; - } +template , + int> = 0> +MF make_mf_crse_patch (FabArrayBase::FPinfo const& fpc, int ncomp) { + MF mf_crse_patch(fpc.ba_crse_patch, fpc.dm_patch, ncomp, 0, MFInfo(), + *fpc.fact_crse_patch); + return mf_crse_patch; +} - template , - int> = 0> - MF make_mf_crse_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type) - { - MF mf_crse_patch(amrex::convert(fpc.ba_crse_patch, idx_type), fpc.dm_patch, - ncomp, 0, MFInfo(), *fpc.fact_crse_patch); - return mf_crse_patch; - } +template , + int> = 0> +MF make_mf_crse_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type) { + MF mf_crse_patch(amrex::convert(fpc.ba_crse_patch, idx_type), fpc.dm_patch, + ncomp, 0, MFInfo(), *fpc.fact_crse_patch); + return mf_crse_patch; +} - template , - int> = 0> - MF make_mf_fine_patch (FabArrayBase::FPinfo const& fpc, int ncomp) - { - MF mf_fine_patch(fpc.ba_fine_patch, fpc.dm_patch, ncomp, 0, MFInfo(), - *fpc.fact_fine_patch); - return mf_fine_patch; - } +template , + int> = 0> +MF make_mf_fine_patch (FabArrayBase::FPinfo const& fpc, int ncomp) { + MF mf_fine_patch(fpc.ba_fine_patch, fpc.dm_patch, ncomp, 0, MFInfo(), + *fpc.fact_fine_patch); + return mf_fine_patch; +} - template , - int> = 0> - MF make_mf_fine_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type) - { - MF mf_fine_patch(amrex::convert(fpc.ba_fine_patch, idx_type), fpc.dm_patch, - ncomp, 0, MFInfo(), *fpc.fact_fine_patch); - return mf_fine_patch; - } +template , + int> = 0> +MF make_mf_fine_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type) { + MF mf_fine_patch(amrex::convert(fpc.ba_fine_patch, idx_type), fpc.dm_patch, + ncomp, 0, MFInfo(), *fpc.fact_fine_patch); + return mf_fine_patch; +} - template , - int> = 0> - MF make_mf_refined_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type, IntVect ratio) - { - MF mf_refined_patch(amrex::convert( amrex::refine( amrex::coarsen(fpc.ba_fine_patch, ratio), ratio), idx_type), - fpc.dm_patch, ncomp, 0, MFInfo(), *fpc.fact_fine_patch); - return mf_refined_patch; - } +template , + int> = 0> +MF make_mf_refined_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type, IntVect ratio) { + MF mf_refined_patch( + amrex::convert(amrex::refine(amrex::coarsen(fpc.ba_fine_patch, ratio), ratio), idx_type), + fpc.dm_patch, ncomp, 0, MFInfo(), *fpc.fact_fine_patch); + return mf_refined_patch; +} - template , - int> = 0> - MF make_mf_crse_mask (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type, IntVect ratio) - { - MF mf_crse_mask(amrex::convert(amrex::coarsen(fpc.ba_fine_patch, ratio), idx_type), - fpc.dm_patch, ncomp, 0, MFInfo(), *fpc.fact_fine_patch); - return mf_crse_mask; - } +template , + int> = 0> +MF make_mf_crse_mask (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type, IntVect ratio) { + MF mf_crse_mask(amrex::convert(amrex::coarsen(fpc.ba_fine_patch, ratio), idx_type), + fpc.dm_patch, ncomp, 0, MFInfo(), *fpc.fact_fine_patch); + return mf_crse_mask; +} - template , - int> = 0> - void mf_set_domain_bndry (MF &mf, Geometry const & geom) - { - mf.setDomainBndry(std::numeric_limits::quiet_NaN(), geom); - } +template , + int> = 0> +void mf_set_domain_bndry (MF& mf, Geometry const& geom) { + mf.setDomainBndry(std::numeric_limits::quiet_NaN(), geom); +} // ======== Not FArrayBox - template , - int> = 0> - MF make_mf_crse_patch (FabArrayBase::FPinfo const& fpc, int ncomp) - { - return MF(fpc.ba_crse_patch, fpc.dm_patch, ncomp, 0); - } - - template , - int> = 0> - MF make_mf_crse_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type) - { - return MF(amrex::convert(fpc.ba_crse_patch, idx_type), fpc.dm_patch, ncomp, 0); - } +template , + int> = 0> +MF make_mf_crse_patch (FabArrayBase::FPinfo const& fpc, int ncomp) { + return MF(fpc.ba_crse_patch, fpc.dm_patch, ncomp, 0); +} - template , - int> = 0> - MF make_mf_fine_patch (FabArrayBase::FPinfo const& fpc, int ncomp) - { - return MF(fpc.ba_fine_patch, fpc.dm_patch, ncomp, 0); - } +template , + int> = 0> +MF make_mf_crse_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type) { + return MF(amrex::convert(fpc.ba_crse_patch, idx_type), fpc.dm_patch, ncomp, 0); +} - template , - int> = 0> - MF make_mf_fine_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type) - { - return MF(amrex::convert(fpc.ba_fine_patch, idx_type), fpc.dm_patch, ncomp, 0); - } +template , + int> = 0> +MF make_mf_fine_patch (FabArrayBase::FPinfo const& fpc, int ncomp) { + return MF(fpc.ba_fine_patch, fpc.dm_patch, ncomp, 0); +} - template , - int> = 0> - MF make_mf_refined_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type, IntVect ratio) - { - return MF(amrex::convert( amrex::refine( amrex::coarsen(fpc.ba_fine_patch, ratio), ratio), idx_type), fpc.dm_patch, ncomp, 0); - } +template , + int> = 0> +MF make_mf_fine_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type) { + return MF(amrex::convert(fpc.ba_fine_patch, idx_type), fpc.dm_patch, ncomp, 0); +} - template , - int> = 0> - MF make_mf_crse_mask (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type, IntVect ratio) - { - return MF(amrex::convert(amrex::coarsen(fpc.ba_fine_patch, ratio), idx_type), fpc.dm_patch, ncomp, 0); - } +template , + int> = 0> +MF make_mf_refined_patch (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type, IntVect ratio) { + return MF(amrex::convert(amrex::refine(amrex::coarsen(fpc.ba_fine_patch, ratio), ratio), idx_type), + fpc.dm_patch, ncomp, 0); +} - template , - int> = 0> - void mf_set_domain_bndry (MF &/*mf*/, Geometry const & /*geom*/) - { - // nothing - } +template , + int> = 0> +MF make_mf_crse_mask (FabArrayBase::FPinfo const& fpc, int ncomp, IndexType idx_type, IntVect ratio) { + return MF(amrex::convert(amrex::coarsen(fpc.ba_fine_patch, ratio), idx_type), fpc.dm_patch, ncomp, 0); +} - template - std::enable_if_t::value,int> - FillPatchTwoLevels_doit (MF& mf, IntVect const& nghost, Real time, - const Vector& cmf, const Vector& ct, - const Vector& fmf, const Vector& 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& bcs, int bcscomp, - const PreInterpHook& pre_interp, - const PostInterpHook& post_interp, - EB2::IndexSpace const* index_space, - bool return_error_code = false) - { - BL_PROFILE("FillPatchTwoLevels"); +template , + int> = 0> +void mf_set_domain_bndry (MF&/*mf*/, Geometry const& /*geom*/) { + // nothing +} - int success_code = return_error_code ? 0 : -1; - int failure_code = 1; +template + requires IsFabArrayType +int +FillPatchTwoLevels_doit (MF& mf, IntVect const& nghost, Real time, + const Vector& cmf, const Vector& ct, + const Vector& fmf, const Vector& 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& bcs, int bcscomp, + const PreInterpHook& pre_interp, + const PostInterpHook& post_interp, + EB2::IndexSpace const* index_space, + bool return_error_code = false) { + BL_PROFILE("FillPatchTwoLevels"); + + int success_code = return_error_code ? 0 : -1; + int failure_code = 1; + + if (nghost.max() > 0 || mf.getBDKey() != fmf[0]->getBDKey()) { + const InterpolaterBoxCoarsener& coarsener = mapper->BoxCoarsener(ratio); + + // Test for Face-centered data + if (AMREX_D_TERM(mf.ixType().nodeCentered(0), + + mf.ixType().nodeCentered(1), + + mf.ixType().nodeCentered(2)) == 1) { + if (!dynamic_cast(mapper)) { + amrex::Abort("This interpolater has not yet implemented a version for face-based data"); + } - if (nghost.max() > 0 || mf.getBDKey() != fmf[0]->getBDKey()) - { - const InterpolaterBoxCoarsener& coarsener = mapper->BoxCoarsener(ratio); + // Convert to cell-centered MF meta-data for FPInfo. + MF mf_cc_dummy(amrex::convert(mf.boxArray(), IntVect::TheZeroVector()), + mf.DistributionMap(), ncomp, nghost, MFInfo().SetAlloc(false)); + MF fmf_cc_dummy(amrex::convert(fmf[0]->boxArray(), IntVect::TheZeroVector()), + fmf[0]->DistributionMap(), ncomp, nghost, MFInfo().SetAlloc(false)); - // Test for Face-centered data - if ( AMREX_D_TERM( mf.ixType().nodeCentered(0), - + mf.ixType().nodeCentered(1), - + mf.ixType().nodeCentered(2) ) == 1 ) - { - if ( !dynamic_cast(mapper) ){ - amrex::Abort("This interpolater has not yet implemented a version for face-based data"); - } + const FabArrayBase::FPinfo& fpc = FabArrayBase::TheFPinfo(fmf_cc_dummy, mf_cc_dummy, + nghost, + coarsener, + fgeom, + cgeom, + index_space); - // Convert to cell-centered MF meta-data for FPInfo. - MF mf_cc_dummy( amrex::convert(mf.boxArray(), IntVect::TheZeroVector()), - mf.DistributionMap(), ncomp, nghost, MFInfo().SetAlloc(false) ); - MF fmf_cc_dummy( amrex::convert(fmf[0]->boxArray(), IntVect::TheZeroVector()), - fmf[0]->DistributionMap(), ncomp, nghost, MFInfo().SetAlloc(false) ); - - const FabArrayBase::FPinfo& fpc = FabArrayBase::TheFPinfo(fmf_cc_dummy, mf_cc_dummy, - nghost, - coarsener, - fgeom, - cgeom, - index_space); - - if ( ! fpc.ba_crse_patch.empty()) - { - if (return_error_code) { - BoxArray const& cba = amrex::convert(cmf[0]->boxArray(), IntVect(0)); - if (!cba.contains(fpc.ba_crse_patch,cgeom.periodicity())) { - return failure_code; - } + if (!fpc.ba_crse_patch.empty()) { + if (return_error_code) { + BoxArray const& cba = amrex::convert(cmf[0]->boxArray(), IntVect(0)); + if (!cba.contains(fpc.ba_crse_patch, cgeom.periodicity())) { + return failure_code; } + } - MF mf_crse_patch = make_mf_crse_patch (fpc, ncomp, mf.boxArray().ixType()); - // Must make sure fine exists under needed coarse faces. - // It stores values for the final (interior) interpolation, - // which is done from this fine MF that's been partially filled - // (with only faces overlying coarse having valid data). - MF mf_refined_patch = make_mf_refined_patch (fpc, ncomp, mf.boxArray().ixType(), ratio); - auto solve_mask = make_mf_crse_mask(fpc, ncomp, mf.boxArray().ixType(), ratio); - - mf_set_domain_bndry(mf_crse_patch, cgeom); - if constexpr (std::is_same_v) { - cbc.fp1_src_ghost = cbc.cghost; - } - FillPatchSingleLevel(mf_crse_patch, time, cmf, ct, scomp, 0, ncomp, - cgeom, cbc, cbccomp); + MF mf_crse_patch = make_mf_crse_patch(fpc, ncomp, mf.boxArray().ixType()); + // Must make sure fine exists under needed coarse faces. + // It stores values for the final (interior) interpolation, + // which is done from this fine MF that's been partially filled + // (with only faces overlying coarse having valid data). + MF mf_refined_patch = make_mf_refined_patch(fpc, ncomp, mf.boxArray().ixType(), ratio); + auto solve_mask = make_mf_crse_mask(fpc, ncomp, mf.boxArray().ixType(), ratio); + + mf_set_domain_bndry(mf_crse_patch, cgeom); + if constexpr (std::is_same_v) { + cbc.fp1_src_ghost = cbc.cghost; + } + FillPatchSingleLevel(mf_crse_patch, time, cmf, ct, scomp, 0, ncomp, + cgeom, cbc, cbccomp); - mf_set_domain_bndry(mf_refined_patch, fgeom); - if constexpr (std::is_same_v) { - fbc.fp1_src_ghost = IntVect(0); - } - FillPatchSingleLevel(mf_refined_patch, time, fmf, ft, scomp, 0, ncomp, - fgeom, fbc, fbccomp); + mf_set_domain_bndry(mf_refined_patch, fgeom); + if constexpr (std::is_same_v) { + fbc.fp1_src_ghost = IntVect(0); + } + FillPatchSingleLevel(mf_refined_patch, time, fmf, ft, scomp, 0, ncomp, + fgeom, fbc, fbccomp); - // Aliased MFs, used to allow CPC caching. - MF mf_known( amrex::coarsen(fmf[0]->boxArray(), ratio), fmf[0]->DistributionMap(), - ncomp, nghost, MFInfo().SetAlloc(false) ); - MF mf_solution( amrex::coarsen(mf_refined_patch.boxArray(), ratio), mf_refined_patch.DistributionMap(), - ncomp, 0, MFInfo().SetAlloc(false) ); + // Aliased MFs, used to allow CPC caching. + MF mf_known(amrex::coarsen(fmf[0]->boxArray(), ratio), fmf[0]->DistributionMap(), + ncomp, nghost, MFInfo().SetAlloc(false)); + MF mf_solution(amrex::coarsen(mf_refined_patch.boxArray(), ratio), + mf_refined_patch.DistributionMap(), + ncomp, 0, MFInfo().SetAlloc(false)); - const FabArrayBase::CPC mask_cpc( mf_solution, IntVect::TheZeroVector(), - mf_known, IntVect::TheZeroVector(), - cgeom.periodicity()); + const FabArrayBase::CPC mask_cpc(mf_solution, IntVect::TheZeroVector(), + mf_known, IntVect::TheZeroVector(), + cgeom.periodicity()); - solve_mask.setVal(1); // Values to solve. - solve_mask.setVal(0, mask_cpc, 0, 1); // Known values. + solve_mask.setVal(1); // Values to solve. + solve_mask.setVal(0, mask_cpc, 0, 1); // Known values. - detail::call_interp_hook(pre_interp, mf_crse_patch, 0, ncomp); + detail::call_interp_hook(pre_interp, mf_crse_patch, 0, ncomp); - InterpFace(mapper, mf_crse_patch, 0, mf_refined_patch, 0, ncomp, - ratio, solve_mask, cgeom, fgeom, bcscomp, RunOn::Gpu, bcs); + InterpFace(mapper, mf_crse_patch, 0, mf_refined_patch, 0, ncomp, + ratio, solve_mask, cgeom, fgeom, bcscomp, RunOn::Gpu, bcs); - detail::call_interp_hook(post_interp, mf_refined_patch, 0, ncomp); + detail::call_interp_hook(post_interp, mf_refined_patch, 0, ncomp); - bool aliasing = false; - for (auto const& fmf_a : fmf) { - aliasing = aliasing || (&mf == fmf_a); - } - if (aliasing) { - mf.ParallelCopyToGhost(mf_refined_patch, 0, dcomp, ncomp, - IntVect{0}, nghost); - } else { - mf.ParallelCopy(mf_refined_patch, 0, dcomp, ncomp, - IntVect{0}, nghost); - } + bool aliasing = false; + for (auto const& fmf_a: fmf) { + aliasing = aliasing || (&mf == fmf_a); + } + if (aliasing) { + mf.ParallelCopyToGhost(mf_refined_patch, 0, dcomp, ncomp, + IntVect{0}, nghost); + } else { + mf.ParallelCopy(mf_refined_patch, 0, dcomp, ncomp, + IntVect{0}, nghost); } } - else - { - const FabArrayBase::FPinfo& fpc = FabArrayBase::TheFPinfo(*fmf[0], mf, - nghost, - coarsener, - fgeom, - cgeom, - index_space); - - if ( ! fpc.ba_crse_patch.empty()) - { - if (return_error_code) { - BoxArray const& cba = cmf[0]->boxArray(); - if (!cba.contains(fpc.ba_crse_patch,cgeom.periodicity())) { - return failure_code; - } + } else { + const FabArrayBase::FPinfo& fpc = FabArrayBase::TheFPinfo(*fmf[0], mf, + nghost, + coarsener, + fgeom, + cgeom, + index_space); + + if (!fpc.ba_crse_patch.empty()) { + if (return_error_code) { + BoxArray const& cba = cmf[0]->boxArray(); + if (!cba.contains(fpc.ba_crse_patch, cgeom.periodicity())) { + return failure_code; } + } - MF mf_crse_patch = make_mf_crse_patch(fpc, ncomp); - mf_set_domain_bndry (mf_crse_patch, cgeom); + MF mf_crse_patch = make_mf_crse_patch(fpc, ncomp); + mf_set_domain_bndry(mf_crse_patch, cgeom); - if constexpr (std::is_same_v) { - cbc.fp1_src_ghost = cbc.cghost; - } - FillPatchSingleLevel(mf_crse_patch, time, cmf, ct, scomp, 0, ncomp, cgeom, cbc, cbccomp); + if constexpr (std::is_same_v) { + cbc.fp1_src_ghost = cbc.cghost; + } + FillPatchSingleLevel(mf_crse_patch, time, cmf, ct, scomp, 0, ncomp, cgeom, cbc, cbccomp); - MF mf_fine_patch = make_mf_fine_patch(fpc, ncomp); + MF mf_fine_patch = make_mf_fine_patch(fpc, ncomp); - detail::call_interp_hook(pre_interp, mf_crse_patch, 0, ncomp); + detail::call_interp_hook(pre_interp, mf_crse_patch, 0, ncomp); - Box fdomain_g( amrex::convert(fgeom.Domain(),mf.ixType()) ); - for (int i = 0; i < AMREX_SPACEDIM; ++i) { - if (fgeom.isPeriodic(i)) { - fdomain_g.grow(i, nghost[i]); - } else { - if constexpr (std::is_same_v - ) { - fdomain_g.grow(i, fbc.nghost_outside_domain[i]); - } + Box fdomain_g(amrex::convert(fgeom.Domain(), mf.ixType())); + for (int i = 0; i < AMREX_SPACEDIM; ++i) { + if (fgeom.isPeriodic(i)) { + fdomain_g.grow(i, nghost[i]); + } else { + if constexpr (std::is_same_v + ) { + fdomain_g.grow(i, fbc.nghost_outside_domain[i]); } } - FillPatchInterp(mf_fine_patch, 0, mf_crse_patch, 0, - ncomp, IntVect(0), cgeom, fgeom, - fdomain_g, ratio, mapper, bcs, bcscomp); + } + FillPatchInterp(mf_fine_patch, 0, mf_crse_patch, 0, + ncomp, IntVect(0), cgeom, fgeom, + fdomain_g, ratio, mapper, bcs, bcscomp); - detail::call_interp_hook(post_interp, mf_fine_patch, 0, ncomp); + detail::call_interp_hook(post_interp, mf_fine_patch, 0, ncomp); - mf.ParallelCopy(mf_fine_patch, 0, dcomp, ncomp, IntVect{0}, nghost); - } + mf.ParallelCopy(mf_fine_patch, 0, dcomp, ncomp, IntVect{0}, nghost); } } - - if constexpr(std::is_same_v) { - fbc.fp1_src_ghost = IntVect(0); - } - FillPatchSingleLevel(mf, nghost, time, fmf, ft, scomp, dcomp, ncomp, - fgeom, fbc, fbccomp); - - return success_code; } - template - std::enable_if_t::value> - FillPatchTwoLevels_doit (Array const& mf, IntVect const& nghost, Real time, - const Vector >& cmf, const Vector& ct, - const Vector >& fmf, const Vector& ft, - int scomp, int dcomp, int ncomp, - const Geometry& cgeom, const Geometry& fgeom, - Array& cbc, const Array& cbccomp, - Array& fbc, const Array& fbccomp, - const IntVect& ratio, - Interp* mapper, - const Array, AMREX_SPACEDIM>& bcs, const Array& bcscomp, - const PreInterpHook& pre_interp, - const PostInterpHook& post_interp, - EB2::IndexSpace const* index_space) - { - BL_PROFILE("FillPatchTwoLevels (Array)"); - - using FAB = typename MF::FABType::value_type; - using iFAB = typename iMultiFab::FABType::value_type; - - AMREX_ASSERT(AMREX_D_TERM(mf[0]->ixType().nodeCentered(0), - && mf[1]->ixType().nodeCentered(1), - && mf[2]->ixType().nodeCentered(2))); - - // These need to be true: (ba[0] == ba[1] == ba[2]) & (dm[0] == dm[1] == dm[2]). - // Debatable whether these are required, or will be enforced elsewhere prior to this func. - AMREX_ASSERT(AMREX_D_TERM(true, - && BoxArray::SameRefs(mf[0]->boxArray(), mf[1]->boxArray()), - && BoxArray::SameRefs(mf[0]->boxArray(), mf[2]->boxArray()))); -/* - AMREX_ASSERT(AMREX_D_TERM(true, - && DistributionMapping::SameRefs(mf[0]->DistributionMap(), mf[1]->DistributionMap()), - && DistributionMapping::SameRefs(mf[0]->DistributionMap(), mf[2]->DistributionMap()))); -*/ - - - // Test all of them? - if (nghost.max() > 0 || mf[0]->getBDKey() != fmf[0][0]->getBDKey()) - { - const InterpolaterBoxCoarsener& coarsener = mapper->BoxCoarsener(ratio); + if constexpr (std::is_same_v) { + fbc.fp1_src_ghost = IntVect(0); + } + FillPatchSingleLevel(mf, nghost, time, fmf, ft, scomp, dcomp, ncomp, + fgeom, fbc, fbccomp); - // Convert to cell-centered MF meta-data for FPInfo. - MF mf_cc_dummy( amrex::convert(mf[0]->boxArray(), IntVect::TheZeroVector()), - mf[0]->DistributionMap(), ncomp, nghost, MFInfo().SetAlloc(false) ); - MF fmf_cc_dummy( amrex::convert(fmf[0][0]->boxArray(), IntVect::TheZeroVector()), - fmf[0][0]->DistributionMap(), ncomp, nghost, MFInfo().SetAlloc(false) ); + return success_code; +} - const FabArrayBase::FPinfo& fpc = FabArrayBase::TheFPinfo(fmf_cc_dummy, mf_cc_dummy, - nghost, - coarsener, - fgeom, - cgeom, - index_space); +template + requires IsFabArrayType +void FillPatchTwoLevels_doit (Array const& mf, IntVect const& nghost, Real time, + const Vector >& cmf, const Vector& ct, + const Vector >& fmf, const Vector& ft, + int scomp, int dcomp, int ncomp, + const Geometry& cgeom, const Geometry& fgeom, + Array& cbc, const Array& cbccomp, + Array& fbc, const Array& fbccomp, + const IntVect& ratio, + Interp* mapper, + const Array, AMREX_SPACEDIM>& bcs, + const Array& bcscomp, + const PreInterpHook& pre_interp, + const PostInterpHook& post_interp, + EB2::IndexSpace const* index_space) { + BL_PROFILE("FillPatchTwoLevels (Array)"); - if ( !fpc.ba_crse_patch.empty() ) - { - Array mf_crse_patch; - Array mf_refined_patch; - Array solve_mask; + using FAB = typename MF::FABType::value_type; + using iFAB = typename iMultiFab::FABType::value_type; - for (int d=0; d (fpc, ncomp, mf[d]->boxArray().ixType()); - mf_refined_patch[d] = make_mf_refined_patch (fpc, ncomp, mf[d]->boxArray().ixType(), ratio); - solve_mask[d] = make_mf_crse_mask(fpc, ncomp, mf[d]->boxArray().ixType(), ratio); + AMREX_ASSERT(AMREX_D_TERM(mf[0]->ixType().nodeCentered(0), + && mf[1]->ixType().nodeCentered(1), + && mf[2]->ixType().nodeCentered(2))); - mf_set_domain_bndry(mf_crse_patch[d], cgeom); - Vector cmf_time; - for (const auto & mfab : cmf) - { cmf_time.push_back(mfab[d]); } + // These need to be true: (ba[0] == ba[1] == ba[2]) & (dm[0] == dm[1] == dm[2]). + // Debatable whether these are required, or will be enforced elsewhere prior to this func. + AMREX_ASSERT(AMREX_D_TERM(true, + && BoxArray::SameRefs(mf[0]->boxArray(), mf[1]->boxArray()), + && BoxArray::SameRefs(mf[0]->boxArray(), mf[2]->boxArray()))); + /* + AMREX_ASSERT(AMREX_D_TERM(true, + && DistributionMapping::SameRefs(mf[0]->DistributionMap(), mf[1]->DistributionMap()), + && DistributionMapping::SameRefs(mf[0]->DistributionMap(), mf[2]->DistributionMap()))); + */ + + + // Test all of them? + if (nghost.max() > 0 || mf[0]->getBDKey() != fmf[0][0]->getBDKey()) { + const InterpolaterBoxCoarsener& coarsener = mapper->BoxCoarsener(ratio); + + // Convert to cell-centered MF meta-data for FPInfo. + MF mf_cc_dummy(amrex::convert(mf[0]->boxArray(), IntVect::TheZeroVector()), + mf[0]->DistributionMap(), ncomp, nghost, MFInfo().SetAlloc(false)); + MF fmf_cc_dummy(amrex::convert(fmf[0][0]->boxArray(), IntVect::TheZeroVector()), + fmf[0][0]->DistributionMap(), ncomp, nghost, MFInfo().SetAlloc(false)); + + const FabArrayBase::FPinfo& fpc = FabArrayBase::TheFPinfo(fmf_cc_dummy, mf_cc_dummy, + nghost, + coarsener, + fgeom, + cgeom, + index_space); + + if (!fpc.ba_crse_patch.empty()) { + Array mf_crse_patch; + Array mf_refined_patch; + Array solve_mask; + + for (int d = 0; d < AMREX_SPACEDIM; ++d) { + mf_crse_patch[d] = make_mf_crse_patch(fpc, ncomp, mf[d]->boxArray().ixType()); + mf_refined_patch[d] = make_mf_refined_patch(fpc, ncomp, mf[d]->boxArray().ixType(), ratio); + solve_mask[d] = make_mf_crse_mask(fpc, ncomp, mf[d]->boxArray().ixType(), ratio); + + mf_set_domain_bndry(mf_crse_patch[d], cgeom); + Vector cmf_time; + for (const auto& mfab: cmf) { + cmf_time.push_back(mfab[d]); + } - FillPatchSingleLevel(mf_crse_patch[d], time, cmf_time, ct, scomp, 0, ncomp, - cgeom, cbc[d], cbccomp[d]); + FillPatchSingleLevel(mf_crse_patch[d], time, cmf_time, ct, scomp, 0, ncomp, + cgeom, cbc[d], cbccomp[d]); - mf_set_domain_bndry(mf_refined_patch[d], fgeom); - Vector fmf_time; - for (const auto & mfab : fmf) - { fmf_time.push_back(mfab[d]); } + mf_set_domain_bndry(mf_refined_patch[d], fgeom); + Vector fmf_time; + for (const auto& mfab: fmf) { + fmf_time.push_back(mfab[d]); + } - FillPatchSingleLevel(mf_refined_patch[d], time, fmf_time, ft, scomp, 0, ncomp, - fgeom, fbc[d], fbccomp[d]); + FillPatchSingleLevel(mf_refined_patch[d], time, fmf_time, ft, scomp, 0, ncomp, + fgeom, fbc[d], fbccomp[d]); - // Aliased MFs, used to allow CPC caching. - MF mf_known( amrex::coarsen(fmf[0][d]->boxArray(), ratio), fmf[0][d]->DistributionMap(), - ncomp, nghost, MFInfo().SetAlloc(false) ); - MF mf_solution( amrex::coarsen(mf_refined_patch[d].boxArray(), ratio), mf_refined_patch[d].DistributionMap(), - ncomp, 0, MFInfo().SetAlloc(false) ); + // Aliased MFs, used to allow CPC caching. + MF mf_known(amrex::coarsen(fmf[0][d]->boxArray(), ratio), fmf[0][d]->DistributionMap(), + ncomp, nghost, MFInfo().SetAlloc(false)); + MF mf_solution(amrex::coarsen(mf_refined_patch[d].boxArray(), ratio), + mf_refined_patch[d].DistributionMap(), + ncomp, 0, MFInfo().SetAlloc(false)); - const FabArrayBase::CPC mask_cpc( mf_solution, IntVect::TheZeroVector(), - mf_known, IntVect::TheZeroVector(), - cgeom.periodicity() ); + const FabArrayBase::CPC mask_cpc(mf_solution, IntVect::TheZeroVector(), + mf_known, IntVect::TheZeroVector(), + cgeom.periodicity()); - solve_mask[d].setVal(1); // Values to solve. - solve_mask[d].setVal(0, mask_cpc, 0, 1); // Known values. - } + solve_mask[d].setVal(1); // Values to solve. + solve_mask[d].setVal(0, mask_cpc, 0, 1); // Known values. + } - int idummy=0; + int idummy = 0; #ifdef AMREX_USE_OMP -// bool cc = fpc.ba_crse_patch.ixType().cellCentered(); - bool cc = false; // can anything be done to allow threading, or can the OpenMP just be removed? + // bool cc = fpc.ba_crse_patch.ixType().cellCentered(); + bool cc = false; // can anything be done to allow threading, or can the OpenMP just be removed? #pragma omp parallel if (cc && Gpu::notInLaunchRegion() ) #endif - { - Vector > bcr(ncomp); - for (MFIter mfi(mf_refined_patch[0]); mfi.isValid(); ++mfi) - { - Array sfab{ AMREX_D_DECL( &(mf_crse_patch[0][mfi]), - &(mf_crse_patch[1][mfi]), - &(mf_crse_patch[2][mfi]) )}; - Array dfab{ AMREX_D_DECL( &(mf_refined_patch[0][mfi]), - &(mf_refined_patch[1][mfi]), - &(mf_refined_patch[2][mfi]) )}; - Array mfab{ AMREX_D_DECL( &(solve_mask[0][mfi]), - &(solve_mask[1][mfi]), - &(solve_mask[2][mfi]) )}; - - const Box& sbx_cc = amrex::convert(sfab[0]->box(), IntVect::TheZeroVector()); - const Box& dbx_cc = amrex::convert(dfab[0]->box(), IntVect::TheZeroVector()); - - for (int d=0; d bcr_d(ncomp); - - amrex::setBC(sfab[d]->box(), amrex::convert(cgeom.Domain(), mf[d]->ixType()), - bcscomp[d],0,ncomp,bcs[d],bcr_d); - - for (int n=0; n > bcr(ncomp); + for (MFIter mfi(mf_refined_patch[0]); mfi.isValid(); ++mfi) { + Array sfab{ + AMREX_D_DECL(&(mf_crse_patch[0][mfi]), + &(mf_crse_patch[1][mfi]), + &(mf_crse_patch[2][mfi])) + }; + Array dfab{ + AMREX_D_DECL(&(mf_refined_patch[0][mfi]), + &(mf_refined_patch[1][mfi]), + &(mf_refined_patch[2][mfi])) + }; + Array mfab{ + AMREX_D_DECL(&(solve_mask[0][mfi]), + &(solve_mask[1][mfi]), + &(solve_mask[2][mfi])) + }; + + const Box& sbx_cc = amrex::convert(sfab[0]->box(), IntVect::TheZeroVector()); + const Box& dbx_cc = amrex::convert(dfab[0]->box(), IntVect::TheZeroVector()); + + for (int d = 0; d < AMREX_SPACEDIM; ++d) { + Vector bcr_d(ncomp); + + amrex::setBC(sfab[d]->box(), amrex::convert(cgeom.Domain(), mf[d]->ixType()), + bcscomp[d], 0, ncomp, bcs[d], bcr_d); + + for (int n = 0; n < ncomp; ++n) { + bcr[n][d] = bcr_d[n]; } + } - pre_interp(sfab, sbx_cc, 0, ncomp); + pre_interp(sfab, sbx_cc, 0, ncomp); - mapper->interp_arr(sfab, 0, dfab, 0, ncomp, dbx_cc, ratio, mfab, - cgeom, fgeom, bcr, idummy, idummy, RunOn::Gpu); + mapper->interp_arr(sfab, 0, dfab, 0, ncomp, dbx_cc, ratio, mfab, + cgeom, fgeom, bcr, idummy, idummy, RunOn::Gpu); - post_interp(dfab, dbx_cc, 0, ncomp); - } + post_interp(dfab, dbx_cc, 0, ncomp); } + } - for (int d=0; dParallelCopyToGhost(mf_refined_patch[d], 0, dcomp, ncomp, - IntVect{0}, nghost); - } else { - mf[d]->ParallelCopy(mf_refined_patch[d], 0, dcomp, ncomp, - IntVect{0}, nghost); - } + for (int d = 0; d < AMREX_SPACEDIM; ++d) { + bool aliasing = false; + for (auto const& fmf_a: fmf) { + aliasing = aliasing || (mf[d] == fmf_a[d]); + } + if (aliasing) { + mf[d]->ParallelCopyToGhost(mf_refined_patch[d], 0, dcomp, ncomp, + IntVect{0}, nghost); + } else { + mf[d]->ParallelCopy(mf_refined_patch[d], 0, dcomp, ncomp, + IntVect{0}, nghost); } } } + } - for (int d=0; d fmf_time; - for (auto const& ffab : fmf) - { fmf_time.push_back(ffab[d]); } - - FillPatchSingleLevel(*mf[d], nghost, time, fmf_time, ft, scomp, dcomp, ncomp, - fgeom, fbc[d], fbccomp[d]); + for (int d = 0; d < AMREX_SPACEDIM; ++d) { + Vector fmf_time; + for (auto const& ffab: fmf) { + fmf_time.push_back(ffab[d]); } - } + FillPatchSingleLevel(*mf[d], nghost, time, fmf_time, ft, scomp, dcomp, ncomp, + fgeom, fbc[d], fbccomp[d]); + } +} } // namespace detail /// \endcond template -std::enable_if_t::value> -FillPatchTwoLevels (MF& mf, IntVect const& nghost, Real time, - const Vector& cmf, const Vector& ct, - const Vector& fmf, const Vector& 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& bcs, int bcscomp, - const PreInterpHook& pre_interp, - const PostInterpHook& post_interp) -{ + requires IsFabArrayType +void FillPatchTwoLevels (MF& mf, IntVect const& nghost, Real time, + const Vector& cmf, const Vector& ct, + const Vector& fmf, const Vector& 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& bcs, int bcscomp, + const PreInterpHook& pre_interp, + const PostInterpHook& post_interp) { #ifdef AMREX_USE_EB EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent(); #else EB2::IndexSpace const* index_space = nullptr; #endif - detail::FillPatchTwoLevels_doit(mf,nghost,time,cmf,ct,fmf,ft, - scomp,dcomp,ncomp,cgeom,fgeom, - cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp, - pre_interp,post_interp,index_space); + detail::FillPatchTwoLevels_doit(mf, nghost, time, cmf, ct, fmf, ft, + scomp, dcomp, ncomp, cgeom, fgeom, + cbc, cbccomp, fbc, fbccomp, ratio, mapper, bcs, bcscomp, + pre_interp, post_interp, index_space); } template -std::enable_if_t::value> -FillPatchTwoLevels (MF& mf, Real time, - const Vector& cmf, const Vector& ct, - const Vector& fmf, const Vector& 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& bcs, int bcscomp, - const PreInterpHook& pre_interp, - const PostInterpHook& post_interp) -{ + requires IsFabArrayType +void FillPatchTwoLevels (MF& mf, Real time, + const Vector& cmf, const Vector& ct, + const Vector& fmf, const Vector& 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& bcs, int bcscomp, + const PreInterpHook& pre_interp, + const PostInterpHook& post_interp) { #ifdef AMREX_USE_EB EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent(); #else EB2::IndexSpace const* index_space = nullptr; #endif - detail::FillPatchTwoLevels_doit(mf,mf.nGrowVect(),time,cmf,ct,fmf,ft, - scomp,dcomp,ncomp,cgeom,fgeom, - cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp, - pre_interp,post_interp,index_space); + detail::FillPatchTwoLevels_doit(mf, mf.nGrowVect(), time, cmf, ct, fmf, ft, + scomp, dcomp, ncomp, cgeom, fgeom, + cbc, cbccomp, fbc, fbccomp, ratio, mapper, bcs, bcscomp, + pre_interp, post_interp, index_space); } template -std::enable_if_t::value> -FillPatchTwoLevels (Array const& mf, IntVect const& nghost, Real time, - const Vector >& cmf, const Vector& ct, - const Vector >& fmf, const Vector& ft, - int scomp, int dcomp, int ncomp, - const Geometry& cgeom, const Geometry& fgeom, - Array& cbc, const Array& cbccomp, - Array& fbc, const Array& fbccomp, - const IntVect& ratio, - Interp* mapper, - const Array, AMREX_SPACEDIM>& bcs, const Array& bcscomp, - const PreInterpHook& pre_interp, - const PostInterpHook& post_interp) -{ + requires IsFabArrayType +void FillPatchTwoLevels (Array const& mf, IntVect const& nghost, Real time, + const Vector >& cmf, const Vector& ct, + const Vector >& fmf, const Vector& ft, + int scomp, int dcomp, int ncomp, + const Geometry& cgeom, const Geometry& fgeom, + Array& cbc, const Array& cbccomp, + Array& fbc, const Array& fbccomp, + const IntVect& ratio, + Interp* mapper, + const Array, AMREX_SPACEDIM>& bcs, const Array& bcscomp, + const PreInterpHook& pre_interp, + const PostInterpHook& post_interp) { #ifdef AMREX_USE_EB EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent(); #else EB2::IndexSpace const* index_space = nullptr; #endif - detail::FillPatchTwoLevels_doit(mf,nghost,time,cmf,ct,fmf,ft, - scomp,dcomp,ncomp,cgeom,fgeom, - cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp, - pre_interp,post_interp,index_space); + detail::FillPatchTwoLevels_doit(mf, nghost, time, cmf, ct, fmf, ft, + scomp, dcomp, ncomp, cgeom, fgeom, + cbc, cbccomp, fbc, fbccomp, ratio, mapper, bcs, bcscomp, + pre_interp, post_interp, index_space); } template -std::enable_if_t::value> -FillPatchTwoLevels (Array const& mf, IntVect const& nghost, Real time, - const Vector >& cmf, const Vector& ct, - const Vector >& fmf, const Vector& ft, - int scomp, int dcomp, int ncomp, - const Geometry& cgeom, const Geometry& fgeom, - Array& cbc, int cbccomp, - Array& fbc, int fbccomp, - const IntVect& ratio, - Interp* mapper, - const Array, AMREX_SPACEDIM>& bcs, int bcscomp, - const PreInterpHook& pre_interp, - const PostInterpHook& post_interp) -{ + requires IsFabArrayType +void FillPatchTwoLevels (Array const& mf, IntVect const& nghost, Real time, + const Vector >& cmf, const Vector& ct, + const Vector >& fmf, const Vector& ft, + int scomp, int dcomp, int ncomp, + const Geometry& cgeom, const Geometry& fgeom, + Array& cbc, int cbccomp, + Array& fbc, int fbccomp, + const IntVect& ratio, + Interp* mapper, + const Array, AMREX_SPACEDIM>& bcs, int bcscomp, + const PreInterpHook& pre_interp, + const PostInterpHook& post_interp) { #ifdef AMREX_USE_EB EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent(); #else EB2::IndexSpace const* index_space = nullptr; #endif - Array cbccomp_arr = {AMREX_D_DECL(cbccomp,cbccomp,cbccomp)}; - Array fbccomp_arr = {AMREX_D_DECL(fbccomp,fbccomp,fbccomp)}; - Array bcscomp_arr = {AMREX_D_DECL(bcscomp,bcscomp,bcscomp)}; + Array cbccomp_arr = {AMREX_D_DECL(cbccomp, cbccomp, cbccomp)}; + Array fbccomp_arr = {AMREX_D_DECL(fbccomp, fbccomp, fbccomp)}; + Array bcscomp_arr = {AMREX_D_DECL(bcscomp, bcscomp, bcscomp)}; - detail::FillPatchTwoLevels_doit(mf,nghost,time,cmf,ct,fmf,ft, - scomp,dcomp,ncomp,cgeom,fgeom, - cbc,cbccomp_arr,fbc,fbccomp_arr,ratio,mapper,bcs,bcscomp_arr, - pre_interp,post_interp,index_space); + detail::FillPatchTwoLevels_doit(mf, nghost, time, cmf, ct, fmf, ft, + scomp, dcomp, ncomp, cgeom, fgeom, + cbc, cbccomp_arr, fbc, fbccomp_arr, ratio, mapper, bcs, bcscomp_arr, + pre_interp, post_interp, index_space); } template -std::enable_if_t::value> -FillPatchTwoLevels (Array const& mf, Real time, - const Vector >& cmf, const Vector& ct, - const Vector >& fmf, const Vector& ft, - int scomp, int dcomp, int ncomp, - const Geometry& cgeom, const Geometry& fgeom, - Array& cbc, int cbccomp, - Array& fbc, int fbccomp, - const IntVect& ratio, - Interp* mapper, - const Array, AMREX_SPACEDIM>& bcs, int bcscomp, - const PreInterpHook& pre_interp, - const PostInterpHook& post_interp) -{ + requires IsFabArrayType +void FillPatchTwoLevels (Array const& mf, Real time, + const Vector >& cmf, const Vector& ct, + const Vector >& fmf, const Vector& ft, + int scomp, int dcomp, int ncomp, + const Geometry& cgeom, const Geometry& fgeom, + Array& cbc, int cbccomp, + Array& fbc, int fbccomp, + const IntVect& ratio, + Interp* mapper, + const Array, AMREX_SPACEDIM>& bcs, int bcscomp, + const PreInterpHook& pre_interp, + const PostInterpHook& post_interp) { #ifdef AMREX_USE_EB EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent(); #else EB2::IndexSpace const* index_space = nullptr; #endif - Array cbccomp_arr = {AMREX_D_DECL(cbccomp,cbccomp,cbccomp)}; - Array fbccomp_arr = {AMREX_D_DECL(fbccomp,fbccomp,fbccomp)}; - Array bcscomp_arr = {AMREX_D_DECL(bcscomp,bcscomp,bcscomp)}; + Array cbccomp_arr = {AMREX_D_DECL(cbccomp, cbccomp, cbccomp)}; + Array fbccomp_arr = {AMREX_D_DECL(fbccomp, fbccomp, fbccomp)}; + Array bcscomp_arr = {AMREX_D_DECL(bcscomp, bcscomp, bcscomp)}; - detail::FillPatchTwoLevels_doit(mf,mf[0]->nGrowVect(),time,cmf,ct,fmf,ft, - scomp,dcomp,ncomp,cgeom,fgeom, - cbc,cbccomp_arr,fbc,fbccomp_arr,ratio,mapper,bcs,bcscomp_arr, - pre_interp,post_interp,index_space); + detail::FillPatchTwoLevels_doit(mf, mf[0]->nGrowVect(), time, cmf, ct, fmf, ft, + scomp, dcomp, ncomp, cgeom, fgeom, + cbc, cbccomp_arr, fbc, fbccomp_arr, ratio, mapper, bcs, bcscomp_arr, + pre_interp, post_interp, index_space); } #ifdef AMREX_USE_EB template -std::enable_if_t::value> -FillPatchTwoLevels (MF& mf, IntVect const& nghost, Real time, - const EB2::IndexSpace& index_space, - const Vector& cmf, const Vector& ct, - const Vector& fmf, const Vector& 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& bcs, int bcscomp, - const PreInterpHook& pre_interp, - const PostInterpHook& post_interp) -{ - detail::FillPatchTwoLevels_doit(mf,nghost,time,cmf,ct,fmf,ft, - scomp,dcomp,ncomp,cgeom,fgeom, - cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp, - pre_interp,post_interp,&index_space); + requires IsFabArrayType +void FillPatchTwoLevels (MF& mf, IntVect const& nghost, Real time, + const EB2::IndexSpace& index_space, + const Vector& cmf, const Vector& ct, + const Vector& fmf, const Vector& 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& bcs, int bcscomp, + const PreInterpHook& pre_interp, + const PostInterpHook& post_interp) { + detail::FillPatchTwoLevels_doit(mf, nghost, time, cmf, ct, fmf, ft, + scomp, dcomp, ncomp, cgeom, fgeom, + cbc, cbccomp, fbc, fbccomp, ratio, mapper, bcs, bcscomp, + pre_interp, post_interp, &index_space); } template -std::enable_if_t::value> -FillPatchTwoLevels (MF& mf, Real time, - const EB2::IndexSpace& index_space, - const Vector& cmf, const Vector& ct, - const Vector& fmf, const Vector& 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& bcs, int bcscomp, - const PreInterpHook& pre_interp, - const PostInterpHook& post_interp) -{ - detail::FillPatchTwoLevels_doit(mf,mf.nGrowVect(),time,cmf,ct,fmf,ft, - scomp,dcomp,ncomp,cgeom,fgeom, - cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp, - pre_interp,post_interp,&index_space); + requires IsFabArrayType +void FillPatchTwoLevels (MF& mf, Real time, + const EB2::IndexSpace& index_space, + const Vector& cmf, const Vector& ct, + const Vector& fmf, const Vector& 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& bcs, int bcscomp, + const PreInterpHook& pre_interp, + const PostInterpHook& post_interp) { + detail::FillPatchTwoLevels_doit(mf, mf.nGrowVect(), time, cmf, ct, fmf, ft, + scomp, dcomp, ncomp, cgeom, fgeom, + cbc, cbccomp, fbc, fbccomp, ratio, mapper, bcs, bcscomp, + pre_interp, post_interp, &index_space); } #endif template -std::enable_if_t::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& bcs, int bcscomp, - const PreInterpHook& pre_interp, - const PostInterpHook& post_interp) -{ + requires IsFabArrayType +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& bcs, int bcscomp, + const PreInterpHook& pre_interp, + const PostInterpHook& post_interp) { #ifdef AMREX_USE_EB EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent(); #else EB2::IndexSpace const* index_space = nullptr; #endif - InterpFromCoarseLevel(mf,mf.nGrowVect(),time,index_space,cmf,scomp,dcomp,ncomp,cgeom,fgeom, - cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp, - pre_interp,post_interp); + InterpFromCoarseLevel(mf, mf.nGrowVect(), time, index_space, cmf, scomp, dcomp, ncomp, cgeom, fgeom, + cbc, cbccomp, fbc, fbccomp, ratio, mapper, bcs, bcscomp, + pre_interp, post_interp); } template -std::enable_if_t::value> -InterpFromCoarseLevel (Array const& mf, Real time, - const Array& cmf, int scomp, int dcomp, int ncomp, - const Geometry& cgeom, const Geometry& fgeom, - Array& cbc, int cbccomp, - Array& fbc, int fbccomp, - const IntVect& ratio, - Interp* mapper, - const Array, AMREX_SPACEDIM>& bcs, int bcscomp, - const PreInterpHook& pre_interp, - const PostInterpHook& post_interp) -{ - InterpFromCoarseLevel(mf,mf[0]->nGrowVect(),time,cmf,scomp,dcomp,ncomp,cgeom,fgeom, - cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp, - pre_interp,post_interp); + requires IsFabArrayType +void InterpFromCoarseLevel (Array const& mf, Real time, + const Array& cmf, int scomp, int dcomp, int ncomp, + const Geometry& cgeom, const Geometry& fgeom, + Array& cbc, int cbccomp, + Array& fbc, int fbccomp, + const IntVect& ratio, + Interp* mapper, + const Array, AMREX_SPACEDIM>& bcs, int bcscomp, + const PreInterpHook& pre_interp, + const PostInterpHook& post_interp) { + InterpFromCoarseLevel(mf, mf[0]->nGrowVect(), time, cmf, scomp, dcomp, ncomp, cgeom, fgeom, + cbc, cbccomp, fbc, fbccomp, ratio, mapper, bcs, bcscomp, + pre_interp, post_interp); } template -std::enable_if_t::value> -InterpFromCoarseLevel (MF& mf, IntVect const& nghost, 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& bcs, int bcscomp, - const PreInterpHook& pre_interp, - const PostInterpHook& post_interp) -{ + requires IsFabArrayType +void InterpFromCoarseLevel (MF& mf, IntVect const& nghost, 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& bcs, int bcscomp, + const PreInterpHook& pre_interp, + const PostInterpHook& post_interp) { #ifdef AMREX_USE_EB EB2::IndexSpace const* index_space = EB2::TopIndexSpaceIfPresent(); #else EB2::IndexSpace const* index_space = nullptr; #endif - InterpFromCoarseLevel(mf,nghost,time,index_space,cmf,scomp,dcomp,ncomp,cgeom,fgeom, - cbc,cbccomp,fbc,fbccomp,ratio,mapper,bcs,bcscomp, - pre_interp,post_interp); + InterpFromCoarseLevel(mf, nghost, time, index_space, cmf, scomp, dcomp, ncomp, cgeom, fgeom, + cbc, cbccomp, fbc, fbccomp, ratio, mapper, bcs, bcscomp, + pre_interp, post_interp); } template -std::enable_if_t::value> -InterpFromCoarseLevel (MF& mf, IntVect const& nghost, Real time, - const EB2::IndexSpace* index_space, - 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& bcs, int bcscomp, - const PreInterpHook& pre_interp, - const PostInterpHook& post_interp) -{ + requires IsFabArrayType +void InterpFromCoarseLevel (MF& mf, IntVect const& nghost, Real time, + const EB2::IndexSpace* index_space, + 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& bcs, int bcscomp, + const PreInterpHook& pre_interp, + const PostInterpHook& post_interp) { BL_PROFILE("InterpFromCoarseLevel"); using FAB = typename MF::FABType::value_type; @@ -1093,7 +1035,7 @@ InterpFromCoarseLevel (MF& mf, IntVect const& nghost, Real time, BL_ASSERT(typ == cmf.boxArray().ixType()); - Box fdomain_g( amrex::convert(fgeom.Domain(),mf.ixType()) ); + Box fdomain_g(amrex::convert(fgeom.Domain(), mf.ixType())); for (int i = 0; i < AMREX_SPACEDIM; ++i) { if (fgeom.isPeriodic(i)) { fdomain_g.grow(i, nghost[i]); @@ -1107,15 +1049,15 @@ InterpFromCoarseLevel (MF& mf, IntVect const& nghost, Real time, MF mf_crse_patch; IntVect send_ghost(0), recv_ghost(0); if constexpr (std::is_same_v) { - mf_crse_patch.define(amrex::coarsen(ba,ratio), dm, ncomp, fbc.src_ghost); + mf_crse_patch.define(amrex::coarsen(ba, ratio), dm, ncomp, fbc.src_ghost); send_ghost = fbc.cghost; recv_ghost = fbc.src_ghost; } else { BoxArray ba_crse_patch(ba.size()); - { // TODO: later we might want to cache this - for (int i = 0, N = ba.size(); i < N; ++i) - { - Box bx = amrex::convert(amrex::grow(ba[i],nghost), typ); + { + // TODO: later we might want to cache this + for (int i = 0, N = ba.size(); i < N; ++i) { + Box bx = amrex::convert(amrex::grow(ba[i], nghost), typ); bx &= fdomain_g; ba_crse_patch.set(i, coarsener.doit(bx)); } @@ -1126,14 +1068,14 @@ InterpFromCoarseLevel (MF& mf, IntVect const& nghost, Real time, #else if (index_space) { auto factory = makeEBFabFactory(index_space, cgeom, ba_crse_patch, dm, - {0,0,0}, EBSupport::basic); + {0, 0, 0}, EBSupport::basic); mf_crse_patch.define(ba_crse_patch, dm, ncomp, 0, MFInfo(), *factory); } else #endif { mf_crse_patch.define(ba_crse_patch, dm, ncomp, 0); } - detail::mf_set_domain_bndry (mf_crse_patch, cgeom); + detail::mf_set_domain_bndry(mf_crse_patch, cgeom); } mf_crse_patch.ParallelCopy(cmf, scomp, 0, ncomp, send_ghost, recv_ghost, @@ -1149,11 +1091,10 @@ InterpFromCoarseLevel (MF& mf, IntVect const& nghost, Real time, #ifdef AMREX_USE_OMP #pragma omp parallel if (Gpu::notInLaunchRegion()) #endif - for (MFIter mfi(mf); mfi.isValid(); ++mfi) - { - FAB& dfab = mf[mfi]; + for (MFIter mfi(mf); mfi.isValid(); ++mfi) { + FAB& dfab = mf[mfi]; Box dfab_bx = dfab.box(); - dfab_bx.grow(nghost-mf.nGrowVect()); + dfab_bx.grow(nghost - mf.nGrowVect()); const Box& dbx = dfab_bx & fdomain_g; post_interp(dfab, dbx, dcomp, ncomp); @@ -1163,18 +1104,17 @@ InterpFromCoarseLevel (MF& mf, IntVect const& nghost, Real time, } template -std::enable_if_t::value> -InterpFromCoarseLevel (Array const& mf, IntVect const& nghost, Real time, - const Array& cmf, int scomp, int dcomp, int ncomp, - const Geometry& cgeom, const Geometry& fgeom, - Array& cbc, int cbccomp, - Array& fbc, int fbccomp, - const IntVect& ratio, - Interp* mapper, - const Array, AMREX_SPACEDIM>& bcs, int bcscomp, - const PreInterpHook& pre_interp, - const PostInterpHook& post_interp) -{ + requires IsFabArrayType +void InterpFromCoarseLevel (Array const& mf, IntVect const& nghost, Real time, + const Array& cmf, int scomp, int dcomp, int ncomp, + const Geometry& cgeom, const Geometry& fgeom, + Array& cbc, int cbccomp, + Array& fbc, int fbccomp, + const IntVect& ratio, + Interp* mapper, + const Array, AMREX_SPACEDIM>& bcs, int bcscomp, + const PreInterpHook& pre_interp, + const PostInterpHook& post_interp) { BL_PROFILE("InterpFromCoarseLevel(array)"); using FAB = typename MF::FABType::value_type; @@ -1185,23 +1125,23 @@ InterpFromCoarseLevel (Array const& mf, IntVect const& ngho const DistributionMapping& dm = mf[0]->DistributionMap(); AMREX_ASSERT(AMREX_D_TERM(mf[0]->ixType().nodeCentered(0), - && mf[1]->ixType().nodeCentered(1), - && mf[2]->ixType().nodeCentered(2))); + && mf[1]->ixType().nodeCentered(1), + && mf[2]->ixType().nodeCentered(2))); // These need to be true: (ba[0] == ba[1] == ba[2]) & (dm[0] == dm[1] == dm[2]). // Debatable whether these are required, or will be enforced elsewhere prior to this func. AMREX_ASSERT(AMREX_D_TERM(true, - && BoxArray::SameRefs(mf[0]->boxArray(), mf[1]->boxArray()), - && BoxArray::SameRefs(mf[0]->boxArray(), mf[2]->boxArray()))); -/* - AMREX_ASSERT(AMREX_D_TERM(true, - && DistributionMapping::SameRefs(mf[0]->DistributionMap(), mf[1]->DistributionMap()), - && DistributionMapping::SameRefs(mf[0]->DistributionMap(), mf[2]->DistributionMap()))); -*/ + && BoxArray::SameRefs(mf[0]->boxArray(), mf[1]->boxArray()), + && BoxArray::SameRefs(mf[0]->boxArray(), mf[2]->boxArray()))); + /* + AMREX_ASSERT(AMREX_D_TERM(true, + && DistributionMapping::SameRefs(mf[0]->DistributionMap(), mf[1]->DistributionMap()), + && DistributionMapping::SameRefs(mf[0]->DistributionMap(), mf[2]->DistributionMap()))); + */ // If needed, adjust to fully overlap the coarse cells. IntVect nghost_adj = nghost; - for (int d=0; d const& mf, IntVect const& ngho Array mf_local = mf; int dcomp_adj = dcomp; Array, AMREX_SPACEDIM> mf_temp; - if (! nghost.allGE(nghost_adj)) { - for (int d=0; d(mf[d]->boxArray(), mf[d]->DistributionMap(), ncomp, nghost_adj); mf_local[d] = mf_temp[d].get(); @@ -1225,15 +1165,15 @@ InterpFromCoarseLevel (Array const& mf, IntVect const& ngho Box fdomain_g(fdomain); for (int d = 0; d < AMREX_SPACEDIM; ++d) { if (fgeom.isPeriodic(d)) { - fdomain_g.grow(d,nghost_adj[d]); + fdomain_g.grow(d, nghost_adj[d]); } } // Build patches, using domain to account for periodic bcs. BoxArray ba_crse_patch(ba.size()); - { // TODO: later we might want to cache this - for (int i = 0, N = ba.size(); i < N; ++i) - { + { + // TODO: later we might want to cache this + for (int i = 0, N = ba.size(); i < N; ++i) { Box bx = amrex::convert(amrex::grow(ba[i], nghost_adj), IntVect::TheZeroVector()); bx &= fdomain_g; ba_crse_patch.set(i, coarsener.doit(bx)); @@ -1241,13 +1181,12 @@ InterpFromCoarseLevel (Array const& mf, IntVect const& ngho } Array mf_crse_patch; - for (int d = 0; dboxArray().ixType(); BoxArray ba_crse_idxed = amrex::convert(ba_crse_patch, typ); #ifdef AMREX_USE_EB - auto crse_factory = makeEBFabFactory(cgeom, ba_crse_idxed, dm, {0,0,0}, EBSupport::basic); + auto crse_factory = makeEBFabFactory(cgeom, ba_crse_idxed, dm, {0, 0, 0}, EBSupport::basic); mf_crse_patch[d].define(ba_crse_idxed, dm, ncomp, 0, MFInfo(), *crse_factory); #else mf_crse_patch[d].define(ba_crse_idxed, dm, ncomp, 0); @@ -1258,7 +1197,7 @@ InterpFromCoarseLevel (Array const& mf, IntVect const& ngho cbc[d](mf_crse_patch[d], 0, ncomp, mf_crse_patch[d].nGrowVect(), time, cbccomp); } - int idummy1=0, idummy2=0; + int idummy1 = 0, idummy2 = 0; #ifdef AMREX_USE_OMP #pragma omp parallel if (Gpu::notInLaunchRegion()) #endif @@ -1266,31 +1205,34 @@ InterpFromCoarseLevel (Array const& mf, IntVect const& ngho Vector > bcr(ncomp); // Empty containers describing that all points must be solved (no mask). - Array mfab{ AMREX_D_DECL( nullptr, nullptr, nullptr ) }; - - for (MFIter mfi(mf_crse_patch[0]); mfi.isValid(); ++mfi) - { - Array sfab{ AMREX_D_DECL( &(mf_crse_patch[0][mfi]), - &(mf_crse_patch[1][mfi]), - &(mf_crse_patch[2][mfi]) )}; - Array dfab{ AMREX_D_DECL( &(*mf_local[0])[mfi], - &(*mf_local[1])[mfi], - &(*mf_local[2])[mfi] )}; + Array mfab{AMREX_D_DECL(nullptr, nullptr, nullptr)}; + + for (MFIter mfi(mf_crse_patch[0]); mfi.isValid(); ++mfi) { + Array sfab{ + AMREX_D_DECL(&(mf_crse_patch[0][mfi]), + &(mf_crse_patch[1][mfi]), + &(mf_crse_patch[2][mfi])) + }; + Array dfab{ + AMREX_D_DECL(&(*mf_local[0])[mfi], + &(*mf_local[1])[mfi], + &(*mf_local[2])[mfi]) + }; const Box& sbx_cc = amrex::convert(sfab[0]->box(), IntVect::TheZeroVector()); Box dfab_cc = amrex::convert(dfab[0]->box(), IntVect::TheZeroVector()); const Box& dbx_cc = dfab_cc & fdomain_g; - for (int d=0; d bcr_d(ncomp); amrex::setBC(sfab[d]->box(), amrex::convert(cgeom.Domain(), sfab[d]->box().ixType()), - bcscomp,0,ncomp,bcs[d],bcr_d); + bcscomp, 0, ncomp, bcs[d], bcr_d); - for (int n=0; n const& mf, IntVect const& ngho } } - for (int d=0; d 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, int bcscomp) -{ - PhysBCFunctUseCoarseGhost erfbc(cmf,nghost,nghost_outside_domain,ratio,mapper); + requires IsFabArrayType +void 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, int bcscomp) { + PhysBCFunctUseCoarseGhost erfbc(cmf, nghost, nghost_outside_domain, ratio, mapper); InterpFromCoarseLevel(mf, nghost, Real(0.0), cmf, scomp, dcomp, ncomp, cgeom, fgeom, erfbc, 0, erfbc, 0, ratio, mapper, bcs, bcscomp); } template -std::enable_if_t::value> -FillPatchSingleLevel (MF& mf, IntVect const& nghost, Real time, - const Vector& smf, IntVect const& snghost, - const Vector& stime, int scomp, int dcomp, int ncomp, - const Geometry& geom) -{ + requires IsFabArrayType +void FillPatchSingleLevel (MF& mf, IntVect const& nghost, Real time, + const Vector& smf, IntVect const& snghost, + const Vector& stime, int scomp, int dcomp, int ncomp, + const Geometry& geom) { PhysBCFunctUseCoarseGhost erfbc(snghost); FillPatchSingleLevel(mf, nghost, time, smf, stime, scomp, dcomp, ncomp, geom, erfbc, 0); } template -std::enable_if_t::value> -FillPatchTwoLevels (MF& mf, IntVect const& nghost, - IntVect const& nghost_outside_domain, Real time, - const Vector& cmf, const Vector& ct, - const Vector& fmf, const Vector& ft, - int scomp, int dcomp, int ncomp, - const Geometry& cgeom, const Geometry& fgeom, - const IntVect& ratio, Interp* mapper, - const Vector& bcs, int bcscomp) -{ + requires IsFabArrayType +void FillPatchTwoLevels (MF& mf, IntVect const& nghost, + IntVect const& nghost_outside_domain, Real time, + const Vector& cmf, const Vector& ct, + const Vector& fmf, const Vector& ft, + int scomp, int dcomp, int ncomp, + const Geometry& cgeom, const Geometry& fgeom, + const IntVect& ratio, Interp* mapper, + const Vector& bcs, int bcscomp) { AMREX_ALWAYS_ASSERT_WITH_MESSAGE(nghost_outside_domain == 0, "TODO"); PhysBCFunctUseCoarseGhost erfbc(*cmf[0], nghost, nghost_outside_domain, ratio, mapper); @@ -1359,16 +1297,15 @@ FillPatchTwoLevels (MF& mf, IntVect const& nghost, } template -std::enable_if_t::value> -FillPatchNLevels (MF& mf, int level, const IntVect& nghost, Real time, - const Vector>& smf, const Vector>& st, - int scomp, int dcomp, int ncomp, - const Vector& geom, - Vector& bc, int bccomp, - const Vector& ratio, - Interp* mapper, - const Vector& bcr, int bcrcomp) -{ + requires IsFabArrayType +void FillPatchNLevels (MF& mf, int level, const IntVect& nghost, Real time, + const Vector >& smf, const Vector >& st, + int scomp, int dcomp, int ncomp, + const Vector& geom, + Vector& bc, int bccomp, + const Vector& ratio, + Interp* mapper, + const Vector& bcr, int bcrcomp) { BL_PROFILE("FillPatchNLevels"); // FillPatchTwolevels relies on that mf's valid region is inside the @@ -1377,26 +1314,25 @@ FillPatchNLevels (MF& mf, int level, const IntVect& nghost, Real time, // requirement. If that happens, we need to create a second version of // the boxarray that is safe for FillPatchTwolevels. - auto get_clayout = [&] () -> std::tuple - { + auto get_clayout = [&] () -> std::tuple { if (level == 0) { - return std::make_tuple(BoxArray(),BoxArray(),DistributionMapping()); + return std::make_tuple(BoxArray(), BoxArray(), DistributionMapping()); } else { BoxArray const& ba = mf.boxArray(); auto const& typ = ba.ixType(); - std::map> extra_boxes_map; + std::map > extra_boxes_map; BoxList cbl(typ); cbl.reserve(ba.size()); for (int i = 0, N = int(ba.size()); i < N; ++i) { - Box const& cbox = mapper->CoarseBox(amrex::grow(ba[i],nghost),ratio[level-1]); + Box const& cbox = mapper->CoarseBox(amrex::grow(ba[i], nghost), ratio[level - 1]); cbl.push_back(cbox); - Box gdomain = geom[level-1].growNonPeriodicDomain(cbox.length()); + Box gdomain = geom[level - 1].growNonPeriodicDomain(cbox.length()); gdomain.convert(typ); if (!gdomain.contains(cbox)) { auto& extra_boxes = extra_boxes_map[i]; - auto const& pshift = geom[level-1].periodicity().shiftIntVect(); - for (auto const& piv : pshift) { - auto const& ibox = amrex::shift(cbox,piv) & gdomain; + auto const& pshift = geom[level - 1].periodicity().shiftIntVect(); + for (auto const& piv: pshift) { + auto const& ibox = amrex::shift(cbox, piv) & gdomain; if (ibox.ok()) { extra_boxes.push_back(ibox); } @@ -1411,7 +1347,7 @@ FillPatchNLevels (MF& mf, int level, const IntVect& nghost, Real time, auto& lbox = cbl2.data(); DistributionMapping const& dm = mf.DistributionMap(); Vector procmap2 = dm.ProcessorMap(); - for (auto const& [i, vb] : extra_boxes_map) { + for (auto const& [i, vb]: extra_boxes_map) { lbox[i] = vb[0]; for (int j = 1, nj = int(vb.size()); j < nj; ++j) { lbox.push_back(vb[j]); @@ -1433,24 +1369,23 @@ FillPatchNLevels (MF& mf, int level, const IntVect& nghost, Real time, #endif AMREX_ALWAYS_ASSERT(level < int(geom.size()) && - level < int(bc.size()) && - level < int(ratio.size()+1)); + level < int(bc.size()) && + level < int(ratio.size()+1)); if (level == 0) { FillPatchSingleLevel(mf, nghost, time, smf[0], st[0], scomp, dcomp, ncomp, geom[0], bc[0], bccomp); - } else if (level >= int(smf.size())) - { + } else if (level >= int(smf.size())) { auto const& [ba1, ba2, dm2] = get_clayout(); MF cmf1, cmf2; #ifdef AMREX_USE_EB if (index_space) { - auto factory = makeEBFabFactory(index_space, geom[level-1], ba1, - mf.DistributionMap(), {0,0,0}, + auto factory = makeEBFabFactory(index_space, geom[level - 1], ba1, + mf.DistributionMap(), {0, 0, 0}, EBSupport::basic); cmf1.define(ba1, mf.DistributionMap(), ncomp, 0, MFInfo(), *factory); if (!ba2.empty()) { - auto factory2 = makeEBFabFactory(index_space, geom[level-1], ba2, - dm2, {0,0,0}, + auto factory2 = makeEBFabFactory(index_space, geom[level - 1], ba2, + dm2, {0, 0, 0}, EBSupport::basic); cmf2.define(ba2, dm2, ncomp, 0, MFInfo(), *factory2); } @@ -1464,25 +1399,25 @@ FillPatchNLevels (MF& mf, int level, const IntVect& nghost, Real time, } MF* p_mf_inside = (ba2.empty()) ? &cmf1 : &cmf2; - FillPatchNLevels(*p_mf_inside, level-1, IntVect(0), time, smf, st, scomp, 0, ncomp, + FillPatchNLevels(*p_mf_inside, level - 1, IntVect(0), time, smf, st, scomp, 0, ncomp, geom, bc, bccomp, ratio, mapper, bcr, bcrcomp); if (&cmf1 != p_mf_inside) { - cmf1.ParallelCopy(*p_mf_inside, geom[level-1].periodicity()); + cmf1.ParallelCopy(*p_mf_inside, geom[level - 1].periodicity()); } Box domain_g = geom[level].growPeriodicDomain(nghost); domain_g.convert(mf.ixType()); - FillPatchInterp(mf, dcomp, cmf1, 0, ncomp, nghost, geom[level-1], geom[level], - domain_g, ratio[level-1], mapper, bcr, bcrcomp); + FillPatchInterp(mf, dcomp, cmf1, 0, ncomp, nghost, geom[level - 1], geom[level], + domain_g, ratio[level - 1], mapper, bcr, bcrcomp); } else { NullInterpHook hook{}; int error_code = detail::FillPatchTwoLevels_doit(mf, nghost, time, - smf[level-1], st[level-1], - smf[level ], st[level ], + smf[level - 1], st[level - 1], + smf[level], st[level], scomp, dcomp, ncomp, - geom[level-1], geom[level], - bc[level-1], bccomp, - bc[level ], bccomp, - ratio[level-1], mapper, bcr, bcrcomp, + geom[level - 1], geom[level], + bc[level - 1], bccomp, + bc[level], bccomp, + ratio[level - 1], mapper, bcr, bcrcomp, hook, hook, index_space, true); if (error_code == 0) { return; } @@ -1491,13 +1426,13 @@ FillPatchNLevels (MF& mf, int level, const IntVect& nghost, Real time, #ifdef AMREX_USE_EB if (index_space) { if (ba2.empty()) { - auto factory = makeEBFabFactory(index_space, geom[level-1], ba1, - mf.DistributionMap(), {0,0,0}, + auto factory = makeEBFabFactory(index_space, geom[level - 1], ba1, + mf.DistributionMap(), {0, 0, 0}, EBSupport::basic); cmf_tmp.define(ba1, mf.DistributionMap(), ncomp, 0, MFInfo(), *factory); } else { - auto factory = makeEBFabFactory(index_space, geom[level-1], ba2, - dm2, {0,0,0}, + auto factory = makeEBFabFactory(index_space, geom[level - 1], ba2, + dm2, {0, 0, 0}, EBSupport::basic); cmf_tmp.define(ba2, dm2, ncomp, 0, MFInfo(), *factory); } @@ -1511,18 +1446,18 @@ FillPatchNLevels (MF& mf, int level, const IntVect& nghost, Real time, } } - FillPatchNLevels(cmf_tmp, level-1, IntVect(0), time, smf, st, scomp, 0, ncomp, + FillPatchNLevels(cmf_tmp, level - 1, IntVect(0), time, smf, st, scomp, 0, ncomp, geom, bc, bccomp, ratio, mapper, bcr, bcrcomp); Vector cmf{&cmf_tmp}; Vector fmf = smf[level]; Vector fmf_raii; if (scomp != 0) { - for (auto const* p : fmf) { - fmf_raii.emplace_back(*p, amrex::make_alias, scomp, ncomp); + for (auto const* p: fmf) { + fmf_raii.emplace_back(*p, amrex::make_alias, scomp, ncomp); } fmf.clear(); - for (auto& a : fmf_raii) { + for (auto& a: fmf_raii) { fmf.push_back(&a); } } @@ -1531,14 +1466,13 @@ FillPatchNLevels (MF& mf, int level, const IntVect& nghost, Real time, cmf, {time}, fmf, st[level], 0, dcomp, ncomp, - geom[level-1], geom[level], - bc[level-1], bccomp, - bc[level ], bccomp, - ratio[level-1], mapper, bcr, bcrcomp, + geom[level - 1], geom[level], + bc[level - 1], bccomp, + bc[level], bccomp, + ratio[level - 1], mapper, bcr, bcrcomp, hook, hook, index_space); } } - } #endif diff --git a/Src/Base/AMReX_Concepts.H b/Src/Base/AMReX_Concepts.H new file mode 100644 index 0000000000..a886efb1ba --- /dev/null +++ b/Src/Base/AMReX_Concepts.H @@ -0,0 +1,27 @@ +#ifndef AMREX_CONCEPTS_H_ +#define AMREX_CONCEPTS_H_ + +#include +#include +#include + +namespace amrex { +/** + * \brief Checks if a type is derived from amrex::BaseFab. + */ +template +concept IsBaseFabType = amrex::IsBaseFab::value; + +/** + * \brief Checks if a type is an amrex::FabArray (like MultiFab). + */ +template +concept IsFabArrayType = amrex::IsFabArray::value; + +/** + * \brief Checks if a Interpolation is not generic MFInterpolater. + */ +template +concept IsSpecificInterp = !std::is_same_v; +} // namespace amrex +#endif diff --git a/Src/Base/CMakeLists.txt b/Src/Base/CMakeLists.txt index c1fbf44a43..d6088bc715 100644 --- a/Src/Base/CMakeLists.txt +++ b/Src/Base/CMakeLists.txt @@ -92,6 +92,7 @@ foreach(D IN LISTS AMReX_SPACEDIM) AMReX_NFiles.cpp AMReX_parstream.H AMReX_parstream.cpp + AMReX_Concepts.H # I/O stuff -------------------------------------------------------------- AMReX_ANSIEscCode.H AMReX_FabConv.H diff --git a/Src/Base/Make.package b/Src/Base/Make.package index 5ec492ce5a..ab4fb34dca 100644 --- a/Src/Base/Make.package +++ b/Src/Base/Make.package @@ -124,6 +124,9 @@ C$(AMREX_BASE)_headers += AMReX_CTOParallelForImpl.H C$(AMREX_BASE)_headers += AMReX_ParReduce.H +C$(AMREX_BASE)_headers += AMReX_Concepts.H + + # # I/O stuff. #