Skip to content

Commit 94caccd

Browse files
lroberts36pgretejonahm-LANL
authored
Functionality for Indexer masking (#901)
* Start on in one AMR * Fix MPI bug * Make things work w/o MPI * small * update changelog * Make AMR helper functions free to alleviate compilation issues on GPU * Fix MPI compilation error * Actually compile with MPI... * Fix indexing bug * Remove unused vars * Fix indexing bug * Make things work for tensor variables * CellVariable to Variable * Respond to Philipp's comments * Maybe fix compiler issues * Second half of fix * Add fence back * Update copyright dates * Pass dealloc count when sending same to same * Almost working, but differs on step 301 after remesh * Add deletion check * Fix a bunch of bugs with a couple changes * Format, lint, changelog * Remove debugging MPI Barrier * Add maximum number of iterations for deletion check * Remove commented lines and clean up * Fix MPI AMR bug related to not passing dereference count when nothing is allocated on a block * format and lint * Fix bug when sparse is disabled * overloads to create packs with meshdata * Always apply fine boundary conditions * Split pack descriptor into separate header * Actually include meshdata and Meshblockdata * more includes * more includes * Reworking neighbor finding * Start on adding morton numbers * Make stuff private * format and lint * Add real comparison operators * Split out morton number * Fix bug when shift is larger than bit size * Add some more functionality to logical location * Start on unit test * Actually compare Morton numbers * Add neighbor check, untested * Fix TE neighbor finding and add tests * Update copyrights * Add logical location to NeighborBlock * add interleave constant test and fix bug * Add bit interleave test * update changelog * Explicitly start at zero * Add routines for calculating ownership and tests * Remove comments * Add another ownership test * Format and lint * Add mask and start testing * switch to bits * Separate logical location header * Switch to class * reserve * Seemingly working masking code * Somewhat more extensive tests * Add ownership to neighbor blocks * Update to mask and run over all indices, still some bug were some neighbor block ownership is not being set * Ownership model passing for cell centered vars * format and lint * Fix errors hidden by MPI ifdef * Remove printf * Add sparse seed nans flag to output * changelog * change signaling NaN to quiet NaN * format * format and lint * Deal with coarse to fine corner issue * changelog * Format and lint * Remove commented out code * Mask prolongation and restriction * Add MakePackDescriptor overload * Add possible neighbors on periodic boundaries * Deal with periodic boundaries * Explicitly deal with periodic vs non-periodic directions * format and lint * Actually pass base grid information * Act on Philipp's comments * Fix linter error --------- Co-authored-by: Philipp Grete <[email protected]> Co-authored-by: Jonah Maxwell Miller <[email protected]>
1 parent badd6f4 commit 94caccd

24 files changed

+482
-106
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
- [[PR 890]](https://github.com/parthenon-hpc-lab/parthenon/pull/890) Fix bugs in sparse communication and prolongation
2525

2626
### Infrastructure (changes irrelevant to downstream codes)
27+
- [[PR 901]](https://github.com/parthenon-hpc-lab/parthenon/pull/901) Implement shared element ownership model
2728

2829
### Removed (removing behavior/API/varaibles/...)
2930

src/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ add_library(parthenon
135135
interface/swarm.hpp
136136
interface/swarm_boundaries.hpp
137137
interface/swarm_device_context.hpp
138+
interface/make_pack_descriptor.hpp
138139
interface/metadata.cpp
139140
interface/metadata.hpp
140141
interface/packages.hpp

src/bvals/boundary_conditions_generic.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <vector>
2222

2323
#include "basic_types.hpp"
24+
#include "interface/make_pack_descriptor.hpp"
2425
#include "interface/meshblock_data.hpp"
2526
#include "interface/sparse_pack.hpp"
2627
#include "mesh/domain.hpp"

src/bvals/bvals.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ class BoundaryBase {
9090
RegionSize block_size_;
9191
ParArrayND<Real> sarea_[2];
9292

93+
void SetNeighborOwnership();
94+
9395
private:
9496
// calculate 3x shared static data members when constructing only the 1st class instance
9597
// int maxneighbor_=BufferID() computes ni[] and then calls bufid[]=CreateBufferID()

src/bvals/bvals_base.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ void BoundaryBase::SearchAndSetNeighbors(MeshBlockTree &tree, int *ranklist,
368368
}
369369
}
370370
if (block_size_.nx2 == 1) {
371+
SetNeighborOwnership();
371372
Kokkos::Profiling::popRegion(); // SearchAndSetNeighbors
372373
return;
373374
}
@@ -502,6 +503,7 @@ void BoundaryBase::SearchAndSetNeighbors(MeshBlockTree &tree, int *ranklist,
502503
}
503504

504505
if (block_size_.nx3 == 1) {
506+
SetNeighborOwnership();
505507
Kokkos::Profiling::popRegion(); // SearchAndSetNeighbors
506508
return;
507509
}
@@ -623,7 +625,25 @@ void BoundaryBase::SearchAndSetNeighbors(MeshBlockTree &tree, int *ranklist,
623625
}
624626
}
625627
}
628+
629+
SetNeighborOwnership();
626630
Kokkos::Profiling::popRegion(); // SearchAndSetNeighbors
627631
}
628632

633+
void BoundaryBase::SetNeighborOwnership() {
634+
// Set neighbor block ownership
635+
std::set<LogicalLocation> allowed_neighbors;
636+
allowed_neighbors.insert(loc); // Insert the location of this block
637+
for (int n = 0; n < nneighbor; ++n)
638+
allowed_neighbors.insert(neighbor[n].loc);
639+
// Although the neighbor blocks abut more blocks than are contained in this
640+
// list, the unaccounted for blocks cannot impact the ownership of elements
641+
// that are shared with *this
642+
RootGridInfo rg_info = pmy_mesh_->GetRootGridInfo();
643+
for (int n = 0; n < nneighbor; ++n) {
644+
neighbor[n].ownership =
645+
DetermineOwnership(neighbor[n].loc, allowed_neighbors, rg_info);
646+
neighbor[n].ownership.initialized = true;
647+
}
648+
}
629649
} // namespace parthenon

src/bvals/bvals_interfaces.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ struct NeighborBlock { // aggregate and POD type. Inheritance breaks standard-la
143143
int bufid, eid, targetid;
144144
BoundaryFace fid;
145145
LogicalLocation loc;
146+
block_ownership_t ownership;
147+
146148
void SetNeighbor(LogicalLocation inloc, int irank, int ilevel, int igid, int ilid,
147149
int iox1, int iox2, int iox3, NeighborConnect itype, int ibid,
148150
int itargetid, int ifi1 = 0, int ifi2 = 0);

src/bvals/comms/bnd_info.cpp

+50-28
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ enum class InterfaceType { SameToSame, CoarseToFine, FineToCoarse };
4141
namespace parthenon {
4242

4343
template <InterfaceType INTERFACE>
44-
Indexer6D CalcLoadIndices(const NeighborIndexes &ni, TopologicalElement el,
45-
std::array<int, 3> tensor_shape,
46-
const parthenon::IndexShape &shape) {
44+
SpatiallyMaskedIndexer6D CalcLoadIndices(const NeighborIndexes &ni, TopologicalElement el,
45+
std::array<int, 3> tensor_shape,
46+
const parthenon::IndexShape &shape) {
4747
IndexDomain interior = IndexDomain::interior;
4848
std::array<IndexRange, 3> bounds{shape.GetBoundsI(interior, el),
4949
shape.GetBoundsJ(interior, el),
@@ -82,25 +82,30 @@ Indexer6D CalcLoadIndices(const NeighborIndexes &ni, TopologicalElement el,
8282
// offset in some direction
8383
} else if (block_offset[dir] > 0) {
8484
s[dir] = bounds[dir].e - Globals::nghost + 1 - top_offset[dir];
85-
e[dir] = bounds[dir].e - top_offset[dir];
85+
e[dir] = bounds[dir].e;
8686
} else {
87-
s[dir] = bounds[dir].s + top_offset[dir];
87+
s[dir] = bounds[dir].s;
8888
e[dir] = bounds[dir].s + Globals::nghost - 1 + top_offset[dir];
8989
}
9090
}
91-
return Indexer6D({0, tensor_shape[0] - 1}, {0, tensor_shape[1] - 1},
92-
{0, tensor_shape[2] - 1}, {s[2], e[2]}, {s[1], e[1]}, {s[0], e[0]});
91+
block_ownership_t owns(true);
92+
return SpatiallyMaskedIndexer6D(owns, {0, tensor_shape[0] - 1},
93+
{0, tensor_shape[1] - 1}, {0, tensor_shape[2] - 1},
94+
{s[2], e[2]}, {s[1], e[1]}, {s[0], e[0]});
9395
}
9496

9597
template <InterfaceType INTERFACE, bool PROLONGATEORRESTRICT = false>
96-
Indexer6D CalcSetIndices(const NeighborIndexes &ni, LogicalLocation loc,
97-
TopologicalElement el, std::array<int, 3> tensor_shape,
98-
const parthenon::IndexShape &shape) {
98+
SpatiallyMaskedIndexer6D
99+
CalcSetIndices(const NeighborBlock &nb, LogicalLocation loc, TopologicalElement el,
100+
std::array<int, 3> tensor_shape, const parthenon::IndexShape &shape) {
101+
const auto &ni = nb.ni;
99102
IndexDomain interior = IndexDomain::interior;
100103
std::array<IndexRange, 3> bounds{shape.GetBoundsI(interior, el),
101104
shape.GetBoundsJ(interior, el),
102105
shape.GetBoundsK(interior, el)};
103106

107+
std::array<int, 3> top_offset{TopologicalOffsetI(el), TopologicalOffsetJ(el),
108+
TopologicalOffsetK(el)};
104109
std::array<int, 3> block_offset{ni.ox1, ni.ox2, ni.ox3};
105110
// This is gross, but the face offsets do not contain the correct
106111
// information for going from coarse to fine and the neighbor block
@@ -128,15 +133,28 @@ Indexer6D CalcSetIndices(const NeighborIndexes &ni, LogicalLocation loc,
128133
}
129134
++off_idx;
130135
} else if (block_offset[dir] > 0) {
131-
s[dir] = bounds[dir].e + 1;
136+
s[dir] = bounds[dir].e + 1 - top_offset[dir];
132137
e[dir] = bounds[dir].e + ghosts;
133138
} else {
134139
s[dir] = bounds[dir].s - ghosts;
135-
e[dir] = bounds[dir].s - 1;
140+
e[dir] = bounds[dir].s - 1 + top_offset[dir];
136141
}
137142
}
138-
return Indexer6D({0, tensor_shape[0] - 1}, {0, tensor_shape[1] - 1},
139-
{0, tensor_shape[2] - 1}, {s[2], e[2]}, {s[1], e[1]}, {s[0], e[0]});
143+
int sox1 = -ni.ox1;
144+
int sox2 = -ni.ox2;
145+
int sox3 = -ni.ox3;
146+
if (INTERFACE == InterfaceType::CoarseToFine) {
147+
// For coarse to fine interfaces, we are passing zones from only an
148+
// interior corner of the cell, never an entire face or edge
149+
if (sox1 == 0) sox1 = logic_loc[0] % 2 == 1 ? 1 : -1;
150+
if (sox2 == 0) sox2 = logic_loc[1] % 2 == 1 ? 1 : -1;
151+
if (sox3 == 0) sox3 = logic_loc[2] % 2 == 1 ? 1 : -1;
152+
}
153+
block_ownership_t owns =
154+
GetIndexRangeMaskFromOwnership(el, nb.ownership, sox1, sox2, sox3);
155+
return SpatiallyMaskedIndexer6D(owns, {0, tensor_shape[0] - 1},
156+
{0, tensor_shape[1] - 1}, {0, tensor_shape[2] - 1},
157+
{s[2], e[2]}, {s[1], e[1]}, {s[0], e[0]});
140158
}
141159

142160
int GetBufferSize(std::shared_ptr<MeshBlock> pmb, const NeighborBlock &nb,
@@ -152,9 +170,9 @@ int GetBufferSize(std::shared_ptr<MeshBlock> pmb, const NeighborBlock &nb,
152170
const int isize = cb.ie(in) - cb.is(in) + 2;
153171
const int jsize = cb.je(in) - cb.js(in) + 2;
154172
const int ksize = cb.ke(in) - cb.ks(in) + 2;
155-
return (nb.ni.ox1 == 0 ? isize : Globals::nghost) *
156-
(nb.ni.ox2 == 0 ? jsize : Globals::nghost) *
157-
(nb.ni.ox3 == 0 ? ksize : Globals::nghost) * v->GetDim(6) * v->GetDim(5) *
173+
return (nb.ni.ox1 == 0 ? isize : Globals::nghost + 1) *
174+
(nb.ni.ox2 == 0 ? jsize : Globals::nghost + 1) *
175+
(nb.ni.ox3 == 0 ? ksize : Globals::nghost + 1) * v->GetDim(6) * v->GetDim(5) *
158176
v->GetDim(4) * topo_comp;
159177
}
160178

@@ -262,29 +280,29 @@ BndInfo BndInfo::GetSetBndInfo(std::shared_ptr<MeshBlock> pmb, const NeighborBlo
262280
if (nb.snb.level == mylevel) {
263281
out.var = v->data.Get();
264282
out.idxer[idx] = CalcSetIndices<InterfaceType::SameToSame>(
265-
nb.ni, pmb->loc, el, {Nt, Nu, Nv}, pmb->cellbounds);
283+
nb, pmb->loc, el, {Nt, Nu, Nv}, pmb->cellbounds);
266284
if (restricted) {
267285
out.refinement_op = RefinementOp_t::Restriction;
268286
out.prores_idxer[static_cast<int>(el)] =
269287
CalcSetIndices<InterfaceType::SameToSame, true>(
270-
nb.ni, pmb->loc, el, {Nt, Nu, Nv}, pmb->c_cellbounds);
288+
nb, pmb->loc, el, {Nt, Nu, Nv}, pmb->c_cellbounds);
271289
}
272290
} else if (nb.snb.level < mylevel) {
273291
out.idxer[idx] = CalcSetIndices<InterfaceType::CoarseToFine>(
274-
nb.ni, pmb->loc, el, {Nt, Nu, Nv}, pmb->c_cellbounds);
292+
nb, pmb->loc, el, {Nt, Nu, Nv}, pmb->c_cellbounds);
275293
out.var = v->coarse_s.Get();
276294
out.refinement_op = RefinementOp_t::Prolongation;
277295
out.prores_idxer[idx] = CalcSetIndices<InterfaceType::CoarseToFine, true>(
278-
nb.ni, pmb->loc, el, {Nt, Nu, Nv}, pmb->c_cellbounds);
296+
nb, pmb->loc, el, {Nt, Nu, Nv}, pmb->c_cellbounds);
279297
} else {
280298
out.var = v->data.Get();
281299
out.idxer[idx] = CalcSetIndices<InterfaceType::FineToCoarse>(
282-
nb.ni, pmb->loc, el, {Nt, Nu, Nv}, pmb->cellbounds);
300+
nb, pmb->loc, el, {Nt, Nu, Nv}, pmb->cellbounds);
283301
if (restricted) {
284302
out.refinement_op = RefinementOp_t::Restriction;
285303
out.prores_idxer[static_cast<int>(el)] =
286304
CalcSetIndices<InterfaceType::FineToCoarse, true>(
287-
nb.ni, pmb->loc, el, {Nt, Nu, Nv}, pmb->c_cellbounds);
305+
nb, pmb->loc, el, {Nt, Nu, Nv}, pmb->c_cellbounds);
288306
}
289307
}
290308
}
@@ -302,7 +320,7 @@ BndInfo BndInfo::GetSetBndInfo(std::shared_ptr<MeshBlock> pmb, const NeighborBlo
302320
for (auto el : {TE::CC, TE::F1, TE::F2, TE::F3, TE::E1, TE::E2, TE::E3, TE::NN}) {
303321
out.prores_idxer[static_cast<int>(el)] =
304322
CalcSetIndices<InterfaceType::CoarseToFine, true>(
305-
nb.ni, pmb->loc, el, {Nt, Nu, Nv}, pmb->c_cellbounds);
323+
nb, pmb->loc, el, {Nt, Nu, Nv}, pmb->c_cellbounds);
306324
}
307325
}
308326

@@ -359,8 +377,10 @@ BndInfo BndInfo::GetSendCCFluxCor(std::shared_ptr<MeshBlock> pmb, const Neighbor
359377

360378
out.var = v->flux[out.dir];
361379
out.coords = pmb->coords;
362-
out.idxer[0] = Indexer6D({0, out.var.GetDim(6) - 1}, {0, out.var.GetDim(5) - 1},
363-
{0, out.var.GetDim(4) - 1}, {sk, ek}, {sj, ej}, {si, ei});
380+
block_ownership_t owns(true);
381+
out.idxer[0] = SpatiallyMaskedIndexer6D(
382+
owns, {0, out.var.GetDim(6) - 1}, {0, out.var.GetDim(5) - 1},
383+
{0, out.var.GetDim(4) - 1}, {sk, ek}, {sj, ej}, {si, ei});
364384
return out;
365385
}
366386

@@ -435,8 +455,10 @@ BndInfo BndInfo::GetSetCCFluxCor(std::shared_ptr<MeshBlock> pmb, const NeighborB
435455
out.var = v->flux[out.dir];
436456

437457
out.coords = pmb->coords;
438-
out.idxer[0] = Indexer6D({0, out.var.GetDim(6) - 1}, {0, out.var.GetDim(5) - 1},
439-
{0, out.var.GetDim(4) - 1}, {sk, ek}, {sj, ej}, {si, ei});
458+
block_ownership_t owns(true);
459+
out.idxer[0] = SpatiallyMaskedIndexer6D(
460+
owns, {0, out.var.GetDim(6) - 1}, {0, out.var.GetDim(5) - 1},
461+
{0, out.var.GetDim(4) - 1}, {sk, ek}, {sj, ej}, {si, ei});
440462
return out;
441463
}
442464

src/bvals/comms/bnd_info.hpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@ class Variable;
4242

4343
struct BndInfo {
4444
int ntopological_elements = 1;
45-
Indexer6D idxer[3];
46-
Indexer6D prores_idxer[10]; // Has to be large enough to allow for maximum integer
47-
// conversion of TopologicalElements
45+
SpatiallyMaskedIndexer6D idxer[3];
46+
SpatiallyMaskedIndexer6D
47+
prores_idxer[10]; // Has to be large enough to allow for maximum integer
48+
// conversion of TopologicalElements
4849

4950
CoordinateDirection dir;
5051
bool allocated = true;

src/bvals/comms/boundary_communication.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,9 @@ TaskStatus SetBounds(std::shared_ptr<MeshData<Real>> &md) {
228228
Kokkos::parallel_for(Kokkos::TeamThreadRange<>(team_member, idxer.size()),
229229
[&](const int idx) {
230230
const auto [t, u, v, k, j, i] = idxer(idx);
231-
bnd_info(b).var(iel, t, u, v, k, j, i) =
232-
bnd_info(b).buf(idx + idx_offset);
231+
if (idxer.IsActive(k, j, i))
232+
bnd_info(b).var(iel, t, u, v, k, j, i) =
233+
bnd_info(b).buf(idx + idx_offset);
233234
});
234235
} else if (bnd_info(b).allocated) {
235236
const Real default_val = bnd_info(b).var.sparse_default_val;
+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
//========================================================================================
2+
// (C) (or copyright) 2020-2023. Triad National Security, LLC. All rights reserved.
3+
//
4+
// This program was produced under U.S. Government contract 89233218CNA000001 for Los
5+
// Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC
6+
// for the U.S. Department of Energy/National Nuclear Security Administration. All rights
7+
// in the program are reserved by Triad National Security, LLC, and the U.S. Department
8+
// of Energy/National Nuclear Security Administration. The Government is granted for
9+
// itself and others acting on its behalf a nonexclusive, paid-up, irrevocable worldwide
10+
// license in this material to reproduce, prepare derivative works, distribute copies to
11+
// the public, perform publicly and display publicly, and to permit others to do so.
12+
//========================================================================================
13+
#ifndef INTERFACE_MAKE_PACK_DESCRIPTOR_HPP_
14+
#define INTERFACE_MAKE_PACK_DESCRIPTOR_HPP_
15+
16+
#include <algorithm>
17+
#include <functional>
18+
#include <limits>
19+
#include <map>
20+
#include <memory>
21+
#include <regex>
22+
#include <set>
23+
#include <string>
24+
#include <tuple>
25+
#include <type_traits>
26+
#include <utility>
27+
#include <vector>
28+
29+
#include "interface/mesh_data.hpp"
30+
#include "interface/meshblock_data.hpp"
31+
#include "interface/metadata.hpp"
32+
#include "interface/sparse_pack.hpp"
33+
#include "interface/state_descriptor.hpp"
34+
#include "mesh/mesh.hpp"
35+
36+
namespace parthenon {
37+
38+
inline auto MakePackDescriptor(StateDescriptor *psd, const std::vector<std::string> &vars,
39+
const std::vector<bool> &use_regex,
40+
const std::vector<MetadataFlag> &flags = {},
41+
const std::set<PDOpt> &options = {}) {
42+
PARTHENON_REQUIRE(vars.size() == use_regex.size(),
43+
"Vargroup names and use_regex need to be the same size.");
44+
auto selector = [&](int vidx, const VarID &id, const Metadata &md) {
45+
if (flags.size() > 0) {
46+
for (const auto &flag : flags) {
47+
if (!md.IsSet(flag)) return false;
48+
}
49+
}
50+
51+
if (use_regex[vidx]) {
52+
if (std::regex_match(std::string(id.label()), std::regex(vars[vidx]))) return true;
53+
} else {
54+
if (vars[vidx] == id.label()) return true;
55+
if (vars[vidx] == id.base_name && id.sparse_id != InvalidSparseID) return true;
56+
}
57+
return false;
58+
};
59+
60+
impl::PackDescriptor base_desc(psd, vars, selector, options);
61+
return typename SparsePack<>::Descriptor(base_desc);
62+
}
63+
64+
template <class... Ts>
65+
inline auto MakePackDescriptor(StateDescriptor *psd,
66+
const std::vector<MetadataFlag> &flags = {},
67+
const std::set<PDOpt> &options = {}) {
68+
static_assert(sizeof...(Ts) > 0, "Must have at least one variable type for type pack");
69+
70+
std::vector<std::string> vars{Ts::name()...};
71+
std::vector<bool> use_regex{Ts::regex()...};
72+
73+
return typename SparsePack<Ts...>::Descriptor(static_cast<impl::PackDescriptor>(
74+
MakePackDescriptor(psd, vars, use_regex, flags, options)));
75+
}
76+
77+
inline auto MakePackDescriptor(StateDescriptor *psd, const std::vector<std::string> &vars,
78+
const std::vector<MetadataFlag> &flags = {},
79+
const std::set<PDOpt> &options = {}) {
80+
return MakePackDescriptor(psd, vars, std::vector<bool>(vars.size(), false), flags,
81+
options);
82+
}
83+
84+
template <class... Ts>
85+
inline auto MakePackDescriptor(MeshBlockData<Real> *pmbd,
86+
const std::vector<MetadataFlag> &flags = {},
87+
const std::set<PDOpt> &options = {}) {
88+
return MakePackDescriptor<Ts...>(
89+
pmbd->GetBlockPointer()->pmy_mesh->resolved_packages.get(), flags, options);
90+
}
91+
92+
template <class... Ts>
93+
inline auto MakePackDescriptor(MeshData<Real> *pmd,
94+
const std::vector<MetadataFlag> &flags = {},
95+
const std::set<PDOpt> &options = {}) {
96+
return MakePackDescriptor<Ts...>(pmd->GetMeshPointer()->resolved_packages.get(), flags,
97+
options);
98+
}
99+
100+
template <class... Ts>
101+
inline auto MakePackDescriptor(SparsePack<Ts...> pack, StateDescriptor *psd,
102+
const std::vector<MetadataFlag> &flags = {},
103+
const std::set<PDOpt> &options = {}) {
104+
return parthenon::MakePackDescriptor<Ts...>(psd, flags, options);
105+
}
106+
107+
inline auto MakePackDescriptor(
108+
StateDescriptor *psd, const std::vector<std::pair<std::string, bool>> &var_regexes,
109+
const std::vector<MetadataFlag> &flags = {}, const std::set<PDOpt> &options = {}) {
110+
std::vector<std::string> vars;
111+
std::vector<bool> use_regex;
112+
for (const auto &[v, r] : var_regexes) {
113+
vars.push_back(v);
114+
use_regex.push_back(r);
115+
}
116+
return MakePackDescriptor(psd, vars, use_regex, flags, options);
117+
}
118+
119+
} // namespace parthenon
120+
121+
#endif // INTERFACE_MAKE_PACK_DESCRIPTOR_HPP_

0 commit comments

Comments
 (0)