diff --git a/CHANGELOG.md b/CHANGELOG.md index d701b171d18b..1c50ceb1d021 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Changed (changing behavior/API/variables/...) +- [[PR 1239]](https://github.com/parthenon-hpc-lab/parthenon/pull/1239) Automatically cache PackDescriptors in Mesh - [[PR 1242]](https://github.com/parthenon-hpc-lab/parthenon/pull/1242) Move to Kokkos 4.6.01 (for AMD APU support) - [[PR 1253]](https://github.com/parthenon-hpc-lab/parthenon/pull/1253) Add support for uint64 swarm variables and add default id diff --git a/doc/sphinx/src/particles.rst b/doc/sphinx/src/particles.rst index 76ab67b284d7..5ec1f76b3448 100644 --- a/doc/sphinx/src/particles.rst +++ b/doc/sphinx/src/particles.rst @@ -155,7 +155,7 @@ Similarly to grid variables, particle swarms support This also supports ``FlatIdx`` for indexing; see the ``particle_leapfrog`` example for usage. -. _swarm_packs: +.. _swarm_packs: ``SwarmPack``\ s ---------------- diff --git a/doc/sphinx/src/sparse_packs.rst b/doc/sphinx/src/sparse_packs.rst index 8e378cbaccf2..6d79901e0b72 100644 --- a/doc/sphinx/src/sparse_packs.rst +++ b/doc/sphinx/src/sparse_packs.rst @@ -16,7 +16,7 @@ etc. within a kernel. ``SparsePack``\ s *work for all types of variables (both dense and sparse). They were originally implemented to support sparse variables and to supersede the older* ``VariablePack``\ s *and* ``VariableFluxPack``\ s *and picked up the* ``Sparse`` *modifier to differentiate them. The latter have not been removed from ``Parthenon`` because some downstream codes still rely on them, but they are deprecated and will be removed eventually.* -*If you want to deal with particle fields, you will need to use* ``SwarmPack``\ s, *which are described at :ref:`swarm_packs`.* +*If you want to deal with particle fields, you will need to use* ``SwarmPack``\ *s, which are described at* :ref:`swarm_packs`. Type-based Packing ------------------ @@ -64,7 +64,7 @@ Building and Using a ``SparsePack`` return TaskStatus::complete; } -``PackDescriptor``\ *s are somewhat expensive to build and are not currently cached. As a result, it is often beneficial to mark them as ``static`` where possible.* +``PackDescriptor``\ s can be somewhat expensive to build because they require searching through all fields in simulation. Therefore, they are automatically cached in the ``StateDescriptor`` where possible. Additionally, it is often possible to declare ``PackDescriptors`` that are created in task functions to be ``static``. ``PackDescriptor`` takes a ``std::set`` of ``PDOpt`` options to determine what to include in the pack: diff --git a/doc/sphinx/src/utilities.rst b/doc/sphinx/src/utilities.rst index f613f5b5a2d6..8e9b3fb17e06 100644 --- a/doc/sphinx/src/utilities.rst +++ b/doc/sphinx/src/utilities.rst @@ -1,10 +1,13 @@ +Utilities +========= + ``TypeList``\ s -=============== +--------------- Provides a wrapper class around a variadic pack of types to simplify performing compile time operations on the pack. There are templated types defined giving the type at a particular index in the pack, types -for extracting sub-``TypeList``s of the original type list, and ``constexpr`` +for extracting sub-``TypeList``\ s of the original type list, and ``constexpr`` functions for getting the index of the first instance of a type in the pack. Additionally it provides a capability for iterating an ``auto`` lambda over the type list, which can be useful for calling a ``static`` function @@ -19,20 +22,20 @@ lists of types associated with field variables that are used in type based ``SparsePack``\ s. Robust -====== +------ Provides a number of functions for doing operations on floating point numbers that are bounded, avoid division by zero, etc. C++11 Style Concepts Implementation -=================================== +----------------------------------- *This documentation needs to be written (see issue #695), but there are extensive comments in src/utlils/concepts_lite.hpp and examples of useage in tst/unit/test_concepts_lite.hpp* ``Indexer`` -=========== +----------- Provides functionality for iterating over an arbitrary dimensional hyper-rectangular index space using a flattened loop. Specific diff --git a/example/fine_advection/advection_driver.cpp b/example/fine_advection/advection_driver.cpp index ca55c04f8278..a15141695664 100644 --- a/example/fine_advection/advection_driver.cpp +++ b/example/fine_advection/advection_driver.cpp @@ -103,19 +103,16 @@ TaskCollection AdvectionDriver::MakeTaskCollection(BlockList_t &blocks, const in // to the Stokes update routines, so that they can internally create variable // packs that operate on only the desired set of variables. using namespace advection_package::Conserved; - static auto desc = parthenon::MakePackDescriptor( - pmesh->resolved_packages.get(), {parthenon::Metadata::WithFluxes}, - {parthenon::PDOpt::WithFluxes}); + auto desc = parthenon::MakePackDescriptor( + pmesh, {parthenon::Metadata::WithFluxes}, {parthenon::PDOpt::WithFluxes}); using pack_desc_t = decltype(desc); - static auto desc_fine = parthenon::MakePackDescriptor( - pmesh->resolved_packages.get(), {parthenon::Metadata::WithFluxes}, - {parthenon::PDOpt::WithFluxes}); + auto desc_fine = parthenon::MakePackDescriptor( + pmesh, {parthenon::Metadata::WithFluxes}, {parthenon::PDOpt::WithFluxes}); using pack_desc_fine_t = decltype(desc_fine); - static auto desc_vec = parthenon::MakePackDescriptor( - pmesh->resolved_packages.get(), {parthenon::Metadata::WithFluxes}, - {parthenon::PDOpt::WithFluxes}); + auto desc_vec = parthenon::MakePackDescriptor( + pmesh, {parthenon::Metadata::WithFluxes}, {parthenon::PDOpt::WithFluxes}); using TT = parthenon::TopologicalType; using TE = parthenon::TopologicalElement; diff --git a/example/fine_advection/advection_package.cpp b/example/fine_advection/advection_package.cpp index a134d3202ef1..742041684334 100644 --- a/example/fine_advection/advection_package.cpp +++ b/example/fine_advection/advection_package.cpp @@ -130,7 +130,7 @@ void CheckRefinementMesh(MeshData *md, parthenon::ParArray1D &amr_ auto do_regular_advection = pkg->Param("do_regular_advection"); if (do_regular_advection) { // refine on advected, for example. could also be a derived quantity - static auto desc = parthenon::MakePackDescriptor(md); + auto desc = parthenon::MakePackDescriptor(md); auto pack = desc.GetPack(md); const auto &refine_tol = pkg->Param("refine_tol"); @@ -179,7 +179,7 @@ Real EstimateTimestep(MeshData *md) { const auto &vy = pkg->Param("vy"); const auto &vz = pkg->Param("vz"); - static auto desc = parthenon::MakePackDescriptor(md); + auto desc = parthenon::MakePackDescriptor(md); auto pack = desc.GetPack(md); IndexRange ib = md->GetBoundsI(IndexDomain::interior); @@ -206,7 +206,7 @@ Real EstimateTimestep(MeshData *md) { } TaskStatus FillDerived(MeshData *md) { - static auto desc = + auto desc = parthenon::MakePackDescriptor( diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d8aec06b725c..35a7b5f6d7bf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -211,6 +211,7 @@ add_library(parthenon pack/block_selector.hpp pack/make_pack_descriptor.hpp + pack/make_pack_descriptor.cpp pack/make_swarm_pack_descriptor.hpp pack/pack_descriptor.cpp pack/pack_descriptor.hpp diff --git a/src/amr_criteria/refinement_package.cpp b/src/amr_criteria/refinement_package.cpp index f2b56a9891b1..549099f49157 100644 --- a/src/amr_criteria/refinement_package.cpp +++ b/src/amr_criteria/refinement_package.cpp @@ -101,8 +101,7 @@ void FirstDerivative(const AMRBounds &bnds, MeshData *md, const std::strin const int &idx, ParArray1D &amr_tags, const Real refine_criteria_, const Real derefine_criteria_, const int max_level_) { - const auto desc = - MakePackDescriptor(md->GetMeshPointer()->resolved_packages.get(), {field}); + const auto desc = MakePackDescriptor(md, {field}); auto pack = desc.GetPack(md); const int ndim = md->GetMeshPointer()->ndim; const int nvars = pack.GetMaxNumberOfVars(); @@ -156,8 +155,7 @@ void SecondDerivative(const AMRBounds &bnds, MeshData *md, const std::stri const int &idx, ParArray1D &amr_tags, const Real refine_criteria_, const Real derefine_criteria_, const int max_level_) { - const auto desc = - MakePackDescriptor(md->GetMeshPointer()->resolved_packages.get(), {field}); + const auto desc = MakePackDescriptor(md, {field}); auto pack = desc.GetPack(md); const int ndim = md->GetMeshPointer()->ndim; const int nvars = pack.GetMaxNumberOfVars(); diff --git a/src/bvals/boundary_conditions_generic.hpp b/src/bvals/boundary_conditions_generic.hpp index 7e73f986bc2c..3ee64b0be40f 100644 --- a/src/bvals/boundary_conditions_generic.hpp +++ b/src/bvals/boundary_conditions_generic.hpp @@ -137,40 +137,6 @@ void GenericSwarmBC(std::shared_ptr &swarm) { }); } -namespace impl { -using desc_key_t = std::tuple; -template -using map_bc_pack_descriptor_t = - std::unordered_map::Descriptor, - tuple_hash>; - -template -map_bc_pack_descriptor_t -GetPackDescriptorMap(std::shared_ptr> &rc) { - std::vector> elements{ - {TopologicalType::Cell, Metadata::Cell}, - {TopologicalType::Face, Metadata::Face}, - {TopologicalType::Edge, Metadata::Edge}, - {TopologicalType::Node, Metadata::Node}}; - map_bc_pack_descriptor_t my_map; - for (auto [tt, md] : elements) { - std::vector flags{Metadata::FillGhost}; - flags.push_back(md); - std::set opts{PDOpt::Coarse}; - my_map.emplace(std::make_pair(desc_key_t{true, false, tt}, - MakePackDescriptor(rc.get(), flags, opts))); - my_map.emplace(std::make_pair(desc_key_t{false, false, tt}, - MakePackDescriptor(rc.get(), flags))); - flags.push_back(Metadata::Fine); - my_map.emplace(std::make_pair(desc_key_t{true, true, tt}, - MakePackDescriptor(rc.get(), flags, opts))); - my_map.emplace(std::make_pair(desc_key_t{false, true, tt}, - MakePackDescriptor(rc.get(), flags))); - } - return my_map; -} -} // namespace impl - template void GenericBC(std::shared_ptr> &rc, bool coarse, TopologicalElement el, Real val) { @@ -183,10 +149,29 @@ void GenericBC(std::shared_ptr> &rc, bool coarse, constexpr bool X3 = (DIR == X3DIR); constexpr bool INNER = (SIDE == BCSide::Inner); - static auto descriptors = impl::GetPackDescriptorMap(rc); + const auto ttFlag = [el] { + const auto tt = GetTopologicalType(el); + switch (tt) { + case (TopologicalType::Cell): + return Metadata::Cell; + case (TopologicalType::Face): + return Metadata::Face; + case (TopologicalType::Edge): + return Metadata::Edge; + case (TopologicalType::Node): + return Metadata::Node; + default: + PARTHENON_FAIL("Unknown topological type") + } + }(); + + // static auto descriptors = impl::GetPackDescriptorMap(rc); for (auto fine : {false, true}) { - auto q = descriptors[impl::desc_key_t{coarse, fine, GetTopologicalType(el)}].GetPack( - rc.get()); + std::vector flags{Metadata::FillGhost, ttFlag}; + if (fine) flags.push_back(Metadata::Fine); + std::set opts = coarse ? std::set{PDOpt::Coarse} : std::set{}; + const auto desc = MakePackDescriptor(rc.get(), flags, opts); + auto q = desc.GetPack(rc.get()); const int b = 0; const int lstart = q.GetLowerBoundHost(b); const int lend = q.GetUpperBoundHost(b); diff --git a/src/interface/metadata.hpp b/src/interface/metadata.hpp index 0f72cc94fe27..25e060ea0ea3 100644 --- a/src/interface/metadata.hpp +++ b/src/interface/metadata.hpp @@ -177,6 +177,7 @@ class MetadataFlag { std::string const &Name() const; + int Flag() const { return flag_; } #ifdef CATCH_VERSION_MAJOR // Should never be used for application code - only exposed for testing. constexpr int InternalFlagValue() const { return flag_; } @@ -705,4 +706,11 @@ Set_t GetByFlag(const Metadata::FlagCollection &flags, NameMap_t &nameMap, } // namespace MetadataUtils } // namespace parthenon +template <> +struct std::hash { + std::size_t operator()(const parthenon::MetadataFlag &flag) const { + return flag.Flag(); + } +}; + #endif // INTERFACE_METADATA_HPP_ diff --git a/src/interface/state_descriptor.hpp b/src/interface/state_descriptor.hpp index a516f6be8821..407a2c4f1d8d 100644 --- a/src/interface/state_descriptor.hpp +++ b/src/interface/state_descriptor.hpp @@ -43,6 +43,7 @@ template class MeshData; class AMRCriteria; class Packages_t; +class PackDescriptorCacheBase; /// A little container class owning refinement function properties /// needed for the state descriptor. @@ -403,6 +404,10 @@ class StateDescriptor { std::array, BOUNDARY_NFACES> UserBoundaryFunctions; std::array, BOUNDARY_NFACES> UserSwarmBoundaryFunctions; + // Caches for PackDescriptors associated with this StateDescriptor + std::unordered_map> + pack_desc_cache_map; + protected: // internal function to add dense/sparse fields. Private because outside classes must // use the public interface below diff --git a/src/interface/update.cpp b/src/interface/update.cpp index cbbd3eaa09fa..1f765c8b79b4 100644 --- a/src/interface/update.cpp +++ b/src/interface/update.cpp @@ -151,8 +151,7 @@ TaskStatus SparseDealloc(MeshData *md) { const IndexRange kb = md->GetBoundsK(IndexDomain::entire); auto control_vars = md->GetMeshPointer()->resolved_packages->GetControlVariables(); - auto desc = MakePackDescriptor(md->GetMeshPointer()->resolved_packages.get(), - control_vars, {Metadata::Sparse}); + auto desc = MakePackDescriptor(md, control_vars, {Metadata::Sparse}); auto pack = desc.GetPack(md); auto packIdx = desc.GetMap(); diff --git a/src/interface/update.hpp b/src/interface/update.hpp index 561f857171d8..44a19a201a97 100644 --- a/src/interface/update.hpp +++ b/src/interface/update.hpp @@ -329,8 +329,8 @@ TaskStatus InitNewlyAllocatedVars(T *rc) { // This pack will always be freshly built, since we only get here if sparse data // was allocated and hasn't been initialized, which in turn implies the cached // pack must be stale. - auto desc = parthenon::MakePackDescriptor( - rc->GetMeshPointer()->resolved_packages.get(), {Metadata::Sparse}); + auto desc = + parthenon::MakePackDescriptor(rc, {Metadata::Sparse}); auto v = desc.GetPack(rc); Kokkos::parallel_for( diff --git a/src/mesh/mesh.hpp b/src/mesh/mesh.hpp index 25ce423572fe..c960342c3ef4 100644 --- a/src/mesh/mesh.hpp +++ b/src/mesh/mesh.hpp @@ -48,6 +48,7 @@ #include "mesh/forest/forest_topology.hpp" #include "mesh/meshblock_pack.hpp" #include "outputs/io_wrapper.hpp" +#include "pack/pack_descriptor.hpp" #include "parameter_input.hpp" #include "parthenon_arrays.hpp" #include "utils/communication_buffer.hpp" @@ -68,6 +69,8 @@ class RestartReader; // Map from LogicalLocation to (gid, rank) pair of location using LogicalLocMap_t = std::map>; +// Base class to allow cacheing of different types of PackDescriptors + //---------------------------------------------------------------------------------------- //! \class Mesh // \brief data/functions associated with the overall mesh @@ -240,8 +243,7 @@ class Mesh { using channel_key_t = std::tuple; using comm_buf_t = CommBuffer::owner_t>; std::unordered_map> pool_map; - using comm_buf_map_t = - std::unordered_map>; + using comm_buf_map_t = std::unordered_map; comm_buf_map_t boundary_comm_map; TagMap tag_map; diff --git a/src/pack/make_pack_descriptor.cpp b/src/pack/make_pack_descriptor.cpp new file mode 100644 index 000000000000..53ce93156398 --- /dev/null +++ b/src/pack/make_pack_descriptor.cpp @@ -0,0 +1,106 @@ +//======================================================================================== +// (C) (or copyright) 2020-2025. Triad National Security, LLC. All rights reserved. +// +// This program was produced under U.S. Government contract 89233218CNA000001 for Los +// Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC +// for the U.S. Department of Energy/National Nuclear Security Administration. All rights +// in the program are reserved by Triad National Security, LLC, and the U.S. Department +// of Energy/National Nuclear Security Administration. The Government is granted for +// itself and others acting on its behalf a nonexclusive, paid-up, irrevocable worldwide +// license in this material to reproduce, prepare derivative works, distribute copies to +// the public, perform publicly and display publicly, and to permit others to do so. +//======================================================================================== + +#include +#include +#include +#include +#include +#include +#include + +#include "mesh/meshblock.hpp" +#include "pack/make_pack_descriptor.hpp" + +namespace parthenon { +namespace impl { + +PackDescriptor MakePackDescriptorBase(StateDescriptor *psd, + const std::vector &vars, + const std::vector &use_regex, + const std::vector &flags, + const std::set &options) { + const std::string cache_label{"normal"}; + using PDCache = PackDescCache, std::vector, + std::vector, std::set>; + auto optional_pd = + PDCache::CheckForKey(psd, cache_label, vars, use_regex, flags, options); + if (optional_pd) return *optional_pd; + + PARTHENON_REQUIRE(vars.size() == use_regex.size(), + "Vargroup names and use_regex need to be the same size."); + auto selector = [&](int vidx, const VarID &id, const Metadata &md) { + for (const auto &flag : flags) { + if (!md.IsSet(flag)) return false; + } + + if (use_regex[vidx]) { + if (std::regex_match(std::string(id.label()), std::regex(vars[vidx]))) return true; + } else { + if (vars[vidx] == id.label()) return true; + if (vars[vidx] == id.base_name && id.sparse_id != InvalidSparseID) return true; + } + return false; + }; + + auto pd = PackDescriptor(psd, vars, selector, options); + PDCache::CachePackDescriptor(psd, cache_label, pd, vars, use_regex, flags, options); + return pd; +} + +PackDescriptor MakePackDescriptorBase(StateDescriptor *psd, + const std::vector &var_ids, + const std::vector &flags, + const std::set &options) { + const std::string cache_label{"uid"}; + using PDCache = + PackDescCache, std::vector, std::set>; + auto optional_pd = PDCache::CheckForKey(psd, cache_label, var_ids, flags, options); + if (optional_pd) return *optional_pd; + + auto selector = [&](int vidx, const VarID &id, const Metadata &md) { + for (const auto &flag : flags) { + if (!md.IsSet(flag)) return false; + } + if (Variable::GetUniqueID(id.label()) == var_ids[vidx]) return true; + return false; + }; + + auto pd = PackDescriptor(psd, var_ids, selector, options); + PDCache::CachePackDescriptor(psd, cache_label, pd, var_ids, flags, options); + return PackDescriptor(psd, var_ids, selector, options); +} + +template +StateDescriptor *GetStateDescriptor(MT *pmd) { + if constexpr (std::is_same_v> || + std::is_same_v>) { + return pmd->GetMeshPointer()->resolved_packages.get(); + } else if constexpr (std::is_same_v) { + return pmd->pmy_mesh->resolved_packages.get(); + } else if constexpr (std::is_same_v) { + return pmd->resolved_packages.get(); + } else if constexpr (std::is_same_v) { + return pmd; + } +} + +template StateDescriptor *GetStateDescriptor>(MeshData *pmd); +template StateDescriptor * +GetStateDescriptor>(MeshBlockData *pmd); +template StateDescriptor *GetStateDescriptor(Mesh *pmd); +template StateDescriptor *GetStateDescriptor(MeshBlock *pmd); +template StateDescriptor *GetStateDescriptor(StateDescriptor *pmd); + +} // namespace impl +} // namespace parthenon diff --git a/src/pack/make_pack_descriptor.hpp b/src/pack/make_pack_descriptor.hpp index d25642a50f40..ee1d361eccea 100644 --- a/src/pack/make_pack_descriptor.hpp +++ b/src/pack/make_pack_descriptor.hpp @@ -13,104 +13,76 @@ #ifndef PACK_MAKE_PACK_DESCRIPTOR_HPP_ #define PACK_MAKE_PACK_DESCRIPTOR_HPP_ -#include -#include -#include -#include #include -#include #include #include #include -#include +#include #include #include -#include "interface/mesh_data.hpp" -#include "interface/meshblock_data.hpp" #include "interface/metadata.hpp" #include "interface/state_descriptor.hpp" -#include "interface/variable.hpp" #include "mesh/mesh.hpp" +#include "pack/pack_descriptor.hpp" #include "pack/sparse_pack.hpp" #include "utils/type_list.hpp" namespace parthenon { +namespace impl { +PackDescriptor MakePackDescriptorBase(StateDescriptor *psd, + const std::vector &vars, + const std::vector &use_regex, + const std::vector &flags, + const std::set &options); +PackDescriptor MakePackDescriptorBase(StateDescriptor *psd, + const std::vector &var_ids, + const std::vector &flags, + const std::set &options); +template +StateDescriptor *GetStateDescriptor(MT *pmd); +} // namespace impl inline auto MakeDefaultPackDescriptor() { return typename SparsePack<>::Descriptor(); } -inline auto MakePackDescriptor(StateDescriptor *psd, const std::vector &vars, +template +inline auto MakePackDescriptor(MT *pmd, const std::vector &vars, const std::vector &use_regex, const std::vector &flags = {}, const std::set &options = {}) { - PARTHENON_REQUIRE(vars.size() == use_regex.size(), - "Vargroup names and use_regex need to be the same size."); - auto selector = [&](int vidx, const VarID &id, const Metadata &md) { - if (flags.size() > 0) { - for (const auto &flag : flags) { - if (!md.IsSet(flag)) return false; - } - } - - if (use_regex[vidx]) { - if (std::regex_match(std::string(id.label()), std::regex(vars[vidx]))) return true; - } else { - if (vars[vidx] == id.label()) return true; - if (vars[vidx] == id.base_name && id.sparse_id != InvalidSparseID) return true; - } - return false; - }; - - impl::PackDescriptor base_desc(psd, vars, selector, options); - return typename SparsePack<>::Descriptor(base_desc); -} - -template -inline auto MakePackDescriptor(StateDescriptor *psd, - const std::vector &flags = {}, - const std::set &options = {}) { - static_assert(sizeof...(Ts) > 0, "Must have at least one variable type for type pack"); - - std::vector vars{Ts::name()...}; - std::vector use_regex{Ts::regex()...}; - - return typename SparsePack::Descriptor(static_cast( - MakePackDescriptor(psd, vars, use_regex, flags, options))); + return typename SparsePack<>::Descriptor(impl::MakePackDescriptorBase( + impl::GetStateDescriptor(pmd), vars, use_regex, flags, options)); } -inline auto MakePackDescriptor(StateDescriptor *psd, const std::vector &vars, +template +inline auto MakePackDescriptor(MT *pmd, const std::vector &vars, const std::vector &flags = {}, const std::set &options = {}) { - return MakePackDescriptor(psd, vars, std::vector(vars.size(), false), flags, + return MakePackDescriptor(pmd, vars, std::vector(vars.size(), false), flags, options); } -template -inline auto MakePackDescriptor(MeshBlockData *pmbd, - const std::vector &flags = {}, +template +inline auto MakePackDescriptor(MT *pmd, const std::vector &flags = {}, const std::set &options = {}) { - return MakePackDescriptor( - pmbd->GetBlockPointer()->pmy_mesh->resolved_packages.get(), flags, options); -} - -template -inline auto MakePackDescriptor(MeshData *pmd, - const std::vector &flags = {}, - const std::set &options = {}) { - return MakePackDescriptor(pmd->GetMeshPointer()->resolved_packages.get(), flags, - options); + const std::vector vars{Ts::name()...}; + const std::vector use_regex{Ts::regex()...}; + return typename SparsePack::Descriptor(static_cast( + MakePackDescriptor(pmd, vars, use_regex, flags, options))); } -template -inline auto MakePackDescriptor(SparsePack pack, StateDescriptor *psd, +template +inline auto MakePackDescriptor(SparsePack pack, MT *pmd, const std::vector &flags = {}, const std::set &options = {}) { - return parthenon::MakePackDescriptor(psd, flags, options); + return parthenon::MakePackDescriptor(pmd, flags, options); } -inline auto MakePackDescriptor( - StateDescriptor *psd, const std::vector> &var_regexes, - const std::vector &flags = {}, const std::set &options = {}) { +template +inline auto +MakePackDescriptor(MT *psd, const std::vector> &var_regexes, + const std::vector &flags = {}, + const std::set &options = {}) { std::vector vars; std::vector use_regex; for (const auto &[v, r] : var_regexes) { @@ -120,21 +92,12 @@ inline auto MakePackDescriptor( return MakePackDescriptor(psd, vars, use_regex, flags, options); } -inline auto MakePackDescriptor(StateDescriptor *psd, const std::vector &var_ids, +template +inline auto MakePackDescriptor(MT *pmd, const std::vector &var_ids, const std::vector &flags = {}, const std::set &options = {}) { - auto selector = [&](int vidx, const VarID &id, const Metadata &md) { - if (flags.size() > 0) { - for (const auto &flag : flags) { - if (!md.IsSet(flag)) return false; - } - } - if (Variable::GetUniqueID(id.label()) == var_ids[vidx]) return true; - return false; - }; - - impl::PackDescriptor base_desc(psd, var_ids, selector, options); - return typename SparsePack<>::Descriptor(base_desc); + return typename SparsePack<>::Descriptor(impl::MakePackDescriptorBase( + impl::GetStateDescriptor(pmd), var_ids, flags, options)); } template