1 #ifndef MESHFIELD_FIELD_HPP
2 #define MESHFIELD_FIELD_HPP
4 #include <Kokkos_Array.hpp>
10 #include "MeshField_Fail.hpp"
11 #include "MeshField_Utility.hpp"
12 #include <Kokkos_Core.hpp>
13 #include <Kokkos_StdAlgorithms.hpp>
16 template <
class Field,
class View>
17 void checkExtents(Field &field, View &view, std::string key) {
19 for (
int i = 0; i < Field::Rank; i++) {
20 matches = matches && (view.extent(i) == field.size(i));
23 MeshField::fail(
"%s: the extents of the view does not match the field\n",
46 template <
class Slice>
class Field {
49 typedef typename Slice::Type Type;
50 typedef typename std::remove_pointer<Type>::type type_rank1;
51 typedef typename std::remove_pointer<type_rank1>::type type_rank2;
52 typedef typename std::remove_pointer<type_rank2>::type type_rank3;
53 typedef typename std::remove_pointer<type_rank3>::type type_rank4;
54 typedef typename std::remove_pointer<type_rank4>::type type_rank5;
55 typedef type_rank5 base_type;
57 using ExecutionSpace =
typename Slice::ExecutionSpace;
59 const Kokkos::Array<size_t, Slice::RANK> divisors;
67 auto computeDivisors() {
68 Kokkos::Array<size_t, Rank> div;
69 for (
int r = 0; r < Rank; r++) {
71 for (
int i = r + 1; i < Rank; ++i) {
87 KOKKOS_INLINE_FUNCTION
88 auto linearIdxToTensorIdx(
size_t index)
const {
89 Kokkos::Array<size_t, Rank> multiIndex;
90 for (
int i = 0; i < Rank; ++i) {
91 multiIndex[i] = index / divisors[i];
92 assert(multiIndex[i] <
size(i));
101 KOKKOS_INLINE_FUNCTION
102 auto totalSize()
const {
return size(0) * divisors[0]; }
105 static const int MAX_RANK = Slice::MAX_RANK;
106 static const int Rank = Slice::RANK;
107 using BaseType = base_type;
109 Field(Slice s) : slice(s), divisors(computeDivisors()) {}
117 KOKKOS_INLINE_FUNCTION
118 size_t size(
int i)
const {
return slice.size(i); }
123 KOKKOS_INLINE_FUNCTION
126 KOKKOS_INLINE_FUNCTION
127 auto &
operator()(
int s,
int a)
const {
return slice(s, a); }
129 KOKKOS_INLINE_FUNCTION
130 auto &
operator()(
int s,
int a,
int i)
const {
return slice(s, a, i); }
132 KOKKOS_INLINE_FUNCTION
133 auto &
operator()(
int s,
int a,
int i,
int j)
const {
134 return slice(s, a, i, j);
136 KOKKOS_INLINE_FUNCTION
137 auto &
operator()(
int s,
int a,
int i,
int j,
int k)
const {
138 return slice(s, a, i, j, k);
141 void serialize_impl(Kokkos::View<base_type *> &serial)
const {
142 assert(serial.size() == totalSize());
143 Kokkos::parallel_for(
144 "field serializer", serial.size(),
145 KOKKOS_CLASS_LAMBDA(
const int index) {
146 constexpr std::size_t rank = Rank;
147 auto serial_data = serial;
148 auto sIndex = linearIdxToTensorIdx(index);
149 if constexpr (rank == 1) {
150 serial_data(index) = slice(index);
151 }
else if constexpr (rank == 2) {
152 serial_data(index) = slice(sIndex[0], sIndex[1]);
153 }
else if constexpr (rank == 3) {
154 serial_data(index) = slice(sIndex[0], sIndex[1], sIndex[2]);
155 }
else if constexpr (rank == 4) {
157 slice(sIndex[0], sIndex[1], sIndex[2], sIndex[3]);
158 }
else if constexpr (rank == 5) {
160 slice(sIndex[0], sIndex[1], sIndex[2], sIndex[3], sIndex[4]);
173 auto N = totalSize();
174 Kokkos::View<base_type *> serial(
"serialized field", N);
175 serialize_impl(serial);
176 return std::move(serial);
187 void serialize(Kokkos::View<base_type *> &serial)
const {
188 const size_t N = totalSize();
189 assert(N == serial.size());
190 serialize_impl(serial);
200 void deserialize(
const Kokkos::View<const base_type *> &serialized) {
201 const size_t N = totalSize();
202 assert(N == serialized.size());
203 Kokkos::parallel_for(
204 "field deserializer", N, KOKKOS_CLASS_LAMBDA(
const int index) {
205 auto serialized_data = serialized;
207 constexpr std::size_t rank = Rank;
208 auto sIndex = linearIdxToTensorIdx(index);
209 if constexpr (rank == 1) {
210 slice(index) = serialized_data(index);
211 }
else if constexpr (rank == 2) {
212 slice(sIndex[0], sIndex[1]) = serialized_data(index);
213 }
else if constexpr (rank == 3) {
214 slice(sIndex[0], sIndex[1], sIndex[2]) = serialized_data(index);
215 }
else if constexpr (rank == 4) {
216 slice(sIndex[0], sIndex[1], sIndex[2], sIndex[3]) =
217 serialized_data(index);
218 }
else if constexpr (rank == 5) {
219 slice(sIndex[0], sIndex[1], sIndex[2], sIndex[3], sIndex[4]) =
220 serialized_data(index);
225 template <
class View>
void setRankOne(View &view) {
226 Kokkos::RangePolicy<ExecutionSpace> p(0,
size(0));
227 Kokkos::parallel_for(
228 p, KOKKOS_CLASS_LAMBDA(
const int &i) {
operator()(i) = view(i); });
230 template <
class View>
void setRankTwo(View &view) {
231 Kokkos::Array a = MeshFieldUtil::to_kokkos_array<Field::Rank>({0, 0});
233 MeshFieldUtil::to_kokkos_array<Field::Rank>({
size(0),
size(1)});
234 Kokkos::MDRangePolicy<Kokkos::Rank<Field::Rank>, ExecutionSpace> p(a, b);
235 Kokkos::parallel_for(
236 p, KOKKOS_CLASS_LAMBDA(
const int &i,
const int &j) {
240 template <
class View>
void setRankThree(View &view) {
241 Kokkos::Array a = MeshFieldUtil::to_kokkos_array<Field::Rank>({0, 0, 0});
242 Kokkos::Array b = MeshFieldUtil::to_kokkos_array<Field::Rank>(
244 Kokkos::MDRangePolicy<Kokkos::Rank<Field::Rank>, ExecutionSpace> p(a, b);
245 Kokkos::parallel_for(
246 p, KOKKOS_CLASS_LAMBDA(
const int &i,
const int &j,
const int &k) {
250 template <
class View>
void setRankFour(View &view) {
251 Kokkos::Array a = MeshFieldUtil::to_kokkos_array<Field::Rank>({0, 0, 0, 0});
252 Kokkos::Array b = MeshFieldUtil::to_kokkos_array<Field::Rank>(
254 Kokkos::MDRangePolicy<Kokkos::Rank<Field::Rank>, ExecutionSpace> p(a, b);
255 Kokkos::parallel_for(
256 p, KOKKOS_CLASS_LAMBDA(
const int &i,
const int &j,
const int &k,
261 template <
class View>
void setRankFive(View &view) {
263 MeshFieldUtil::to_kokkos_array<Field::Rank>({0, 0, 0, 0, 0});
264 Kokkos::Array b = MeshFieldUtil::to_kokkos_array<Field::Rank>(
266 Kokkos::MDRangePolicy<Kokkos::Rank<Field::Rank>, ExecutionSpace> p(a, b);
267 Kokkos::parallel_for(
268 p, KOKKOS_CLASS_LAMBDA(
const int &i,
const int &j,
const int &k,
269 const int &l,
const int &m) {
270 operator()(i, j, k, l, m) = view(i, j, k, l, m);
278 template <
class View>
void set(View &view) {
279 constexpr std::size_t view_rank = View::rank;
280 constexpr std::size_t field_rank = Slice::RANK;
281 static_assert(field_rank <= Slice::MAX_RANK);
282 static_assert(view_rank == field_rank);
283 checkExtents(*
this, view, __func__);
284 if constexpr (field_rank == 1) {
286 }
else if constexpr (field_rank == 2) {
288 }
else if constexpr (field_rank == 3) {
290 }
else if constexpr (field_rank == 4) {
292 }
else if constexpr (field_rank == 5) {
295 fail(
"Field::set error: field rank is %d, it must be [1:5]\n",
310 template <
class Controller, std::
size_t index>
311 auto makeField(Controller controller) {
312 auto slice = controller.template makeSlice<index>();
313 return Field(std::move(slice));
Provides access to individual entries of a single Field provided by MeshField::makeField and helper f...
KOKKOS_INLINE_FUNCTION auto & operator()(int s) const
void deserialize(const Kokkos::View< const base_type * > &serialized)
copy the given Kokkos View into the Field
KOKKOS_INLINE_FUNCTION size_t size(int i) const
get the size/extent of the specified rank
void serialize(Kokkos::View< base_type * > &serial) const
copy the Field into a given Kokkos View
Kokkos::View< base_type * > serialize() const
copy the Field into a single rank Kokkos View