ThunderEgg  1.0.0
View.h
Go to the documentation of this file.
1 /***************************************************************************
2  * ThunderEgg, a library for solvers on adaptively refined block-structured
3  * Cartesian grids.
4  *
5  * Copyright (c) 2020-2021 Scott Aiton
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <https://www.gnu.org/licenses/>.
19  ***************************************************************************/
20 
21 #ifndef THUNDEREGG_VIEW_H
22 #define THUNDEREGG_VIEW_H
23 
28 #include <ThunderEgg/Config.h>
29 #include <ThunderEgg/Loops.h>
31 #include <array>
32 #include <memory>
33 namespace ThunderEgg {
39 template<typename T, int D>
40 class View
41 {
42 public:
43  using T_ptr = typename std::add_pointer<T>::type;
44 
45 private:
49  T_ptr data = nullptr;
53  std::array<int, D> strides;
57  std::array<int, D> ghost_start;
61  std::array<int, D> start;
65  std::array<int, D> end;
69  std::array<int, D> ghost_end;
70 
77  void checkCoordIsInBounds(const std::array<int, D>& coord) const
78  {
79  bool is_valid_coord = true;
80  for (int i = 0; i < D; i++) {
81  is_valid_coord = is_valid_coord && (coord[i] >= ghost_start[i] && coord[i] <= ghost_end[i]);
82  }
83  if (!is_valid_coord) {
84  // oob coord
85  throw RuntimeError("index for view is out of bounds");
86  }
87  }
88 
89 protected:
90  inline int getIndex(const std::array<int, D>& coord) const
91  {
92  int idx = 0;
93  Loop::Unroll<0, D - 1>([&](int i) { idx += strides[i] * coord[i]; });
94  return idx;
95  }
96 
97  T_ptr getData() const { return data; }
98 
99 public:
104  {
105  strides.fill(0);
106  ghost_start.fill(0);
107  start.fill(0);
108  end.fill(-1);
109  ghost_end.fill(-1);
110  }
120  View(T_ptr data,
121  const std::array<int, D>& strides,
122  const std::array<int, D>& ghost_start,
123  const std::array<int, D>& start,
124  const std::array<int, D>& end,
125  const std::array<int, D>& ghost_end)
126  : strides(strides)
127  , ghost_start(ghost_start)
128  , start(start)
129  , end(end)
130  , ghost_end(ghost_end)
131  {
132  this->data = data - this->getIndex(ghost_start);
133  }
134 
141  inline T& operator[](const std::array<int, D>& coord) const
142  {
143  if constexpr (ENABLE_DEBUG) {
144  this->checkCoordIsInBounds(coord);
145  }
146  return data[this->getIndex(coord)];
147  }
148 
158  template<class... Types>
159  inline T& operator()(Types... args) const
160  {
161  static_assert(sizeof...(args) == D, "incorrect number of arguments");
162  if constexpr (ENABLE_DEBUG) {
163  this->checkCoordIsInBounds({ args... });
164  }
165  return data[this->getIndex({ args... })];
166  }
167 
174  inline void set(const std::array<int, D>& coord, T value) const
175  {
176  if constexpr (std::is_const<T>::value) {
177  if constexpr (ENABLE_DEBUG) {
178  // check that only ghost cells are being modified
179  bool is_interior_coord = true;
180  for (int i = 0; i < D; i++) {
181  is_interior_coord = is_interior_coord && (coord[i] >= start[i] && coord[i] <= end[i]);
182  }
183  if (is_interior_coord) {
184  // intertior coord
185  throw RuntimeError("interior value of const view is being modified");
186  }
187  checkCoordIsInBounds(coord);
188  }
189  int idx = 0;
190  Loop::Unroll<0, D - 1>([&](int i) { idx += strides[i] * coord[i]; });
191  const_cast<double*>(data)[idx] = value;
192  } else {
193  if constexpr (ENABLE_DEBUG) {
194  this->checkCoordIsInBounds(coord);
195  }
196  data[this->getIndex(coord)] = value;
197  }
198  }
199 
203  const std::array<int, D>& getStrides() const { return strides; }
207  const std::array<int, D>& getStart() const { return start; }
211  const std::array<int, D>& getEnd() const { return end; }
215  const std::array<int, D>& getGhostStart() const { return ghost_start; }
219  const std::array<int, D>& getGhostEnd() const { return ghost_end; }
220 
221  operator View<std::add_const_t<T>, D>() const
222  {
223  return View<std::add_const_t<T>, D>(
224  data + getIndex(getGhostStart()), strides, ghost_start, start, end, ghost_end);
225  }
226 };
227 extern template class View<double, 1>;
228 extern template class View<double, 2>;
229 extern template class View<double, 3>;
230 extern template class View<double, 4>;
231 extern template class View<const double, 1>;
232 extern template class View<const double, 2>;
233 extern template class View<const double, 3>;
234 extern template class View<const double, 4>;
235 } // namespace ThunderEgg
236 #endif
RuntimeError.h
RuntimeError struct.
ThunderEgg::View
Array for acessing data of a patch. It supports variable striding.
Definition: View.h:40
ThunderEgg::Loop::Unroll
static void Unroll(T lambda)
Unroll a fixed-length loop.
Definition: Loops.h:72
ThunderEgg::View::getStrides
const std::array< int, D > & getStrides() const
Get the strides of the patch in each direction.
Definition: View.h:203
ThunderEgg::View::getGhostStart
const std::array< int, D > & getGhostStart() const
Get the coordinate of the first ghost cell element.
Definition: View.h:215
ThunderEgg::View::View
View(T_ptr data, const std::array< int, D > &strides, const std::array< int, D > &ghost_start, const std::array< int, D > &start, const std::array< int, D > &end, const std::array< int, D > &ghost_end)
Construct a new View object.
Definition: View.h:120
ThunderEgg
The ThunderEgg namespace.
Definition: BiLinearGhostFiller.h:31
ThunderEgg::View::getEnd
const std::array< int, D > & getEnd() const
Get the coordinate of the last element.
Definition: View.h:211
ThunderEgg::View::operator[]
T & operator[](const std::array< int, D > &coord) const
Get a reference to the element at the specified coordinate.
Definition: View.h:141
ThunderEgg::View::View
View()
Constructs a view of size 0.
Definition: View.h:103
Loops.h
Loop templates.
ThunderEgg::View::set
void set(const std::array< int, D > &coord, T value) const
Set the value at a coordinate to the specified value.
Definition: View.h:174
ThunderEgg::View::getGhostEnd
const std::array< int, D > & getGhostEnd() const
Get the coordinate of the last ghost cell element.
Definition: View.h:219
ThunderEgg::View::getStart
const std::array< int, D > & getStart() const
Get the coordinate of the first element.
Definition: View.h:207
ThunderEgg::View::operator()
T & operator()(Types... args) const
Get a reference to the element at the specified coordinate.
Definition: View.h:159
ThunderEgg::RuntimeError
ThunderEgg runtime exception.
Definition: RuntimeError.h:36