Schnek
kokkos-storage.hpp
1 /*
2  * kokkos-storage.hpp
3  *
4  * Created on: 17 Nov 2022
5  * Author: Holger Schmitz
6  * Email: holger@notjustphysics.com
7  *
8  * Copyright 2012-2022 Holger Schmitz
9  *
10  * This file is part of Schnek.
11  *
12  * Schnek is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * Schnek is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with Schnek. If not, see <http://www.gnu.org/licenses/>.
24  */
25 
26 #ifndef SCHNEK_GRID_GRIDSTORAGE_KOKKOSSTORAGE_HPP_
27 #define SCHNEK_GRID_GRIDSTORAGE_KOKKOSSTORAGE_HPP_
28 
29 #include "../../config.hpp"
30 
31 #ifdef SCHNEK_HAVE_KOKKOS
32 
33 #include "../../macros.hpp"
34 #include "../array.hpp"
35 #include "../range.hpp"
36 
37 #include <memory>
38 #include <functional>
39 #include <map>
40 
41 #include <Kokkos_Core.hpp>
42 
43 namespace schnek {
44 
45  namespace internal {
46  template<typename T, size_t rank>
47  struct KokkosViewType {
48  typedef typename KokkosViewType<T, rank-1>::type* type;
49  };
50 
51  template<typename T>
52  struct KokkosViewType<T, 1> {
53  typedef T* type;
54  };
55  }
56 
64  template <
65  typename T,
66  size_t rank,
67  class ...ViewProperties
68  >
69  class KokkosGridStorage
70  {
71  public:
73  typedef Array<int, rank> IndexType;
74 
76  typedef Range<int, rank> RangeType;
77  private:
78  typedef std::function<void(const RangeType&)> UpdaterType;
79  typedef std::map<void *, UpdaterType> UpdaterMapType;
80 
82  RangeType range;
83 
85  IndexType dims;
86 
87  Kokkos::View<typename internal::KokkosViewType<T, rank>::type, ViewProperties...> view;
88 
90  std::shared_ptr<UpdaterMapType> updaters;
91  public:
93  KokkosGridStorage();
94 
98  KokkosGridStorage(const KokkosGridStorage &);
99 
106  KokkosGridStorage(const IndexType &lo, const IndexType &hi);
107 
113  KokkosGridStorage(const RangeType &range);
114 
116  ~KokkosGridStorage();
117 
124  SCHNEK_INLINE const T& get(const IndexType &index) const;
125 
132  SCHNEK_INLINE T& get(const IndexType &index);
133 
135  SCHNEK_INLINE const IndexType &getLo() const { return this->range.getLo(); }
136 
138  SCHNEK_INLINE const IndexType &getHi() const { return this->range.getHi(); }
139 
141  SCHNEK_INLINE const RangeType &getRange() const { return this->range; }
142 
144  SCHNEK_INLINE const IndexType &getDims() const { return this->dims; }
145 
147  SCHNEK_INLINE int getLo(int k) const { return this->range.getLo(k); }
148 
150  SCHNEK_INLINE int getHi(int k) const { return this->range.getHi(k); }
151 
153  SCHNEK_INLINE int getDims(int k) const { return this->dims[k]; }
154 
156  SCHNEK_INLINE int getSize() const { return this->size; }
157 
162  void resize(const IndexType &low, const IndexType &high);
163 
167  SCHNEK_INLINE ptrdiff_t stride(size_t dim) const;
168 
169  private:
170  template<std::size_t... I>
171  auto createKokkosViewImpl(const IndexType& a, std::index_sequence<I...>)
172  {
173  Kokkos::View<typename internal::KokkosViewType<T, rank>::type, ViewProperties...> view("schnek", a[I]...);
174  return view;
175  }
176 
177  auto createKokkosView(const IndexType& dims)
178  {
179  return createKokkosViewImpl(dims, std::make_index_sequence<rank>{});
180  }
181 
182  template<std::size_t... I>
183  SCHNEK_INLINE T& getFromViewImpl(const IndexType& pos, std::index_sequence<I...>)
184  {
185  return view(pos[I]...);
186  }
187 
188  template<std::size_t... I>
189  SCHNEK_INLINE const T& getFromViewImpl(const IndexType& pos, std::index_sequence<I...>) const
190  {
191  return view(pos[I]...);
192  }
193 
194  SCHNEK_INLINE T& getFromView(const IndexType& pos)
195  {
196  return getFromViewImpl(pos, std::make_index_sequence<rank>{});
197  }
198 
199  SCHNEK_INLINE const T& getFromView(const IndexType& pos) const
200  {
201  return getFromViewImpl(pos, std::make_index_sequence<rank>{});
202  }
203 
204  void update(const RangeType& range) {
205  for (auto& updater: *updaters) {
206  updater.second(range);
207  }
208  }
209 
210  void updateSizeInfo(const RangeType &range) {
211  this->range = range;
212  for (size_t i = 0; i < rank; ++i)
213  {
214  dims[i] = range.getHi(i) - range.getLo(i) + 1;
215  }
216  }
217  };
218 
219  template<typename T, size_t rank>
220  using KokkosDefaultGridStorage = KokkosGridStorage<T, rank>;
221 
222  //=================================================================
223  //==================== KokkosGridStorage ==========================
224  //=================================================================
225 
226  template <typename T, size_t rank, class ...ViewProperties>
227  KokkosGridStorage<T, rank, ViewProperties...>::KokkosGridStorage()
228  : range{IndexType{0}, IndexType{0}},
229  dims{0},
230  updaters{new UpdaterMapType}
231  {
232  (*updaters)[this] = [this](const RangeType& range) { this->updateSizeInfo(range); };
233  }
234 
235  template <typename T, size_t rank, class ...ViewProperties>
236  KokkosGridStorage<T, rank, ViewProperties...>::KokkosGridStorage(const KokkosGridStorage &other)
237  : range{other.range},
238  dims{other.dims}, view{other.view},
239  updaters{other.updaters}
240  {
241  (*updaters)[this] = [this](const RangeType& range) { this->updateSizeInfo(range); };
242  }
243 
244  template <typename T, size_t rank, class ...ViewProperties>
245  KokkosGridStorage<T, rank, ViewProperties...>::KokkosGridStorage(const IndexType &lo, const IndexType &hi)
246  : range{lo, hi},
247  updaters{new UpdaterMapType}
248  {
249  dims = hi - lo + 1;
250  view = createKokkosView(dims);
251  (*updaters)[this] = [this](const RangeType& range) { this->updateSizeInfo(range); };
252  }
253 
254  template <typename T, size_t rank, class ...ViewProperties>
255  KokkosGridStorage<T, rank, ViewProperties...>::KokkosGridStorage(const RangeType &range)
256  : range{range},
257  updaters{new UpdaterMapType}
258  {
259  dims = range.getHi() - range.getLo() + 1;
260  view = createKokkosView(dims);
261  (*updaters)[this] = [this](const RangeType& range) { this->updateSizeInfo(range); };
262  }
263 
264  template <typename T, size_t rank, class ...ViewProperties>
265  KokkosGridStorage<T, rank, ViewProperties...>::~KokkosGridStorage()
266  {
267  updaters->erase(this);
268  }
269 
270  template <typename T, size_t rank, class ...ViewProperties>
271  SCHNEK_INLINE const T &KokkosGridStorage<T, rank, ViewProperties...>::get(const IndexType &index) const
272  {
273  IndexType pos;
274  for (size_t i=0; i<rank; ++i)
275  {
276  pos[i] = index[i] - range.getLo(i);
277  }
278  return getFromView(pos);
279  }
280 
281  template <typename T, size_t rank, class ...ViewProperties>
282  SCHNEK_INLINE T &KokkosGridStorage<T, rank, ViewProperties...>::get(const IndexType &index)
283  {
284  IndexType pos;
285  for (size_t i=0; i<rank; ++i)
286  {
287  pos[i] = index[i] - range.getLo(i);
288  }
289  return getFromView(pos);
290  }
291 
292  template <typename T, size_t rank, class ...ViewProperties>
293  void KokkosGridStorage<T, rank, ViewProperties...>::resize(const IndexType &lo, const IndexType &hi)
294  {
295  IndexType dims = hi - lo + 1;
296  this->view = createKokkosView(dims);
297  update(RangeType{lo, hi});
298  }
299 
300  template <typename T, size_t rank, class ...ViewProperties>
301  SCHNEK_INLINE ptrdiff_t KokkosGridStorage<T, rank, ViewProperties...>::stride(size_t dim) const
302  {
303  return this->view.stride(dim);
304  }
305 
306 }
307 
308 
309 #endif // SCHNEK_HAVE_KOKKOS
310 
311 #endif // SCHNEK_GRID_GRIDSTORAGE_KOKKOSSTORAGE_HPP_
Definition: algo.hpp:30