Skip to content

Commit f7ea1d0

Browse files
authored
Merge pull request #998 from parthenon-hpc-lab/mg/tensor_indices
tensor indices added to sparse pack
2 parents a97831a + 3fd7a46 commit f7ea1d0

File tree

3 files changed

+112
-5
lines changed

3 files changed

+112
-5
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Current develop
44

55
### Added (new features/APIs/variables/...)
6+
- [[PR 998]](https://github.com/parthenon-hpc-lab/parthenon/pull/998) tensor indices added to sparse pack
67
- [[PR 999]](https://github.com/parthenon-hpc-lab/parthenon/pull/999) Add a post-initialization hook
78
- [[PR 987]](https://github.com/parthenon-hpc-lab/parthenon/pull/987) New tasking infrastructure and capabilities
89
- [[PR 969]](https://github.com/parthenon-hpc-lab/parthenon/pull/969) New macro-based auto-naming of profiling regions and kernels

src/interface/sparse_pack.hpp

+39-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//========================================================================================
2-
// (C) (or copyright) 2020-2023. Triad National Security, LLC. All rights reserved.
2+
// (C) (or copyright) 2020-2024. Triad National Security, LLC. All rights reserved.
33
//
44
// This program was produced under U.S. Government contract 89233218CNA000001 for Los
55
// Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC
@@ -90,6 +90,7 @@ KOKKOS_INLINE_FUNCTION PackIdx operator+(T offset, PackIdx idx) {
9090
// device
9191
namespace variable_names {
9292
// Struct that all variable_name types should inherit from
93+
constexpr int ANYDIM = -1234; // ANYDIM must be a slowest-moving index
9394
template <bool REGEX, int... NCOMP>
9495
struct base_t {
9596
KOKKOS_INLINE_FUNCTION
@@ -98,6 +99,21 @@ struct base_t {
9899
KOKKOS_INLINE_FUNCTION
99100
explicit base_t(int idx1) : idx(idx1) {}
100101

102+
/*
103+
for 2D:, (M, N),
104+
idx(m, n) = N*m + n
105+
for 3D: (L, M, N)
106+
idx(l, m, n) = (M*l + m)*N + n
107+
= l*M*N + m*N + n
108+
*/
109+
template <typename... Args, REQUIRES(all_implement<integral(Args...)>::value),
110+
REQUIRES(sizeof...(Args) == sizeof...(NCOMP))>
111+
KOKKOS_INLINE_FUNCTION explicit base_t(Args... args)
112+
: idx(GetIndex_(std::forward<Args>(args)...)) {
113+
static_assert(CheckArgs_(NCOMP...),
114+
"All dimensions must be strictly positive, "
115+
"except the first (slowest), which may be ANYDIM.");
116+
}
101117
virtual ~base_t() = default;
102118

103119
// All of these are just static methods so that there is no
@@ -106,6 +122,11 @@ struct base_t {
106122
PARTHENON_FAIL("Need to implement your own name method.");
107123
return "error";
108124
}
125+
template <int idx>
126+
static constexpr auto GetDim() {
127+
return std::get<sizeof...(NCOMP) - idx>(std::make_tuple(NCOMP...));
128+
}
129+
static std::vector<int> GetShape() { return std::vector<int>{NCOMP...}; }
109130
KOKKOS_INLINE_FUNCTION
110131
static bool regex() { return REGEX; }
111132
KOKKOS_INLINE_FUNCTION
@@ -114,6 +135,23 @@ struct base_t {
114135
static int size() { return multiply<NCOMP...>::value; }
115136

116137
const int idx;
138+
139+
private:
140+
template <typename... Tail, REQUIRES(all_implement<integral(Tail...)>::value)>
141+
static constexpr bool CheckArgs_(int head, Tail... tail) {
142+
return (... && (tail > 0));
143+
}
144+
template <class... Args>
145+
KOKKOS_INLINE_FUNCTION static auto GetIndex_(Args... args) {
146+
int idx = 0;
147+
(
148+
[&] {
149+
idx *= NCOMP;
150+
idx += args;
151+
}(),
152+
...);
153+
return idx;
154+
}
117155
};
118156

119157
// An example variable name type that selects all variables available

tst/unit/test_sparse_pack.cpp

+72-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//========================================================================================
2-
// (C) (or copyright) 2020-2023. Triad National Security, LLC. All rights reserved.
2+
// (C) (or copyright) 2020-2024. Triad National Security, LLC. All rights reserved.
33
//
44
// This program was produced under U.S. Government contract 89233218CNA000001 for Los
55
// Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC
@@ -77,13 +77,80 @@ struct v5 : public parthenon::variable_names::base_t<false> {
7777
static std::string name() { return "v5"; }
7878
};
7979

80+
using parthenon::variable_names::ANYDIM;
81+
struct v7 : public parthenon::variable_names::base_t<false, ANYDIM, 3> {
82+
template <class... Ts>
83+
KOKKOS_INLINE_FUNCTION v7(Ts &&...args)
84+
: parthenon::variable_names::base_t<false, ANYDIM, 3>(std::forward<Ts>(args)...) {}
85+
static std::string name() { return "v7"; }
86+
};
87+
8088
} // namespace
8189

8290
TEST_CASE("Test behavior of sparse packs", "[SparsePack]") {
91+
constexpr int N = 6;
92+
constexpr int NDIM = 3;
93+
constexpr int NBLOCKS = 9;
94+
95+
GIVEN("A tensor variable on a mesh") {
96+
const std::vector<int> tensor_shape{N, N, N, 3, 3};
97+
Metadata m_tensor({Metadata::Independent}, tensor_shape);
98+
auto pkg = std::make_shared<StateDescriptor>("Test package");
99+
pkg->AddField<v7>(m_tensor);
100+
BlockList_t block_list = MakeBlockList(pkg, NBLOCKS, N, NDIM);
101+
102+
MeshData<Real> mesh_data("base");
103+
mesh_data.Set(block_list, nullptr);
104+
105+
WHEN("We initialize the independent variables by hand and deallocate one") {
106+
auto ib = block_list[0]->cellbounds.GetBoundsI(IndexDomain::entire);
107+
auto jb = block_list[0]->cellbounds.GetBoundsJ(IndexDomain::entire);
108+
auto kb = block_list[0]->cellbounds.GetBoundsK(IndexDomain::entire);
109+
for (int b = 0; b < NBLOCKS; ++b) {
110+
auto &pmb = block_list[b];
111+
auto &pmbd = pmb->meshblock_data.Get();
112+
auto var = pmbd->Get("v7");
113+
auto var5 = var.data.Get<5>();
114+
int slower_rank = var5.GetDim(5);
115+
int faster_rank = var5.GetDim(4);
116+
par_for(
117+
loop_pattern_mdrange_tag, "initializev7", DevExecSpace(), kb.s, kb.e, jb.s,
118+
jb.e, ib.s, ib.e, KOKKOS_LAMBDA(int k, int j, int i) {
119+
for (int l = 0; l < slower_rank; ++l) {
120+
for (int m = 0; m < faster_rank; ++m) {
121+
Real n = m + 1e1 * l;
122+
var5(l, m, k, j, i) = n;
123+
}
124+
}
125+
});
126+
}
127+
THEN("A sparse pack can correctly index into tensor types") {
128+
auto desc = parthenon::MakePackDescriptor<v7>(pkg.get());
129+
auto sparse_pack = desc.GetPack(&mesh_data);
130+
int nwrong = 0;
131+
int nl = tensor_shape[4];
132+
int nm = tensor_shape[3];
133+
par_reduce(
134+
loop_pattern_mdrange_tag, "check vector", DevExecSpace(), 0,
135+
sparse_pack.GetNBlocks() - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e,
136+
KOKKOS_LAMBDA(int b, int k, int j, int i, int &ltot) {
137+
// 0-th is ANYDIM, 1st is 3.
138+
for (int l = 0; l < nl; ++l) {
139+
for (int m = 0; m < nm; ++m) {
140+
Real n = m + 1e1 * l;
141+
if (sparse_pack(b, v7(l, m), k, j, i) != n) {
142+
ltot += 1;
143+
}
144+
}
145+
}
146+
},
147+
nwrong);
148+
REQUIRE(nwrong == 0);
149+
}
150+
}
151+
}
152+
83153
GIVEN("A set of meshblocks and meshblock and mesh data") {
84-
constexpr int N = 6;
85-
constexpr int NDIM = 3;
86-
constexpr int NBLOCKS = 9;
87154
const std::vector<int> scalar_shape{N, N, N};
88155
const std::vector<int> vector_shape{N, N, N, 3};
89156

@@ -122,6 +189,7 @@ TEST_CASE("Test behavior of sparse packs", "[SparsePack]") {
122189
});
123190
}
124191
}
192+
125193
// Deallocate a variable on an arbitrary block
126194
block_list[2]->DeallocateSparse("v3");
127195

0 commit comments

Comments
 (0)