Finite Volume Solver  prototype
A framework to build finite volume solvers for the AG Klein at the Freie Universität Berlin.
PatchDataView.hpp
Go to the documentation of this file.
1 // Copyright (c) 2019 Maikel Nadolski
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20 
21 #ifndef FUB_PATCH_DATA_VIEW_HPP
22 #define FUB_PATCH_DATA_VIEW_HPP
23 
24 #include "fub/Direction.hpp"
25 #include "fub/core/mdspan.hpp"
26 
27 #include <array>
28 #include <functional>
29 #include <tuple>
30 #include <utility>
31 
32 namespace fub {
33 template <int Rank>
34 using Index = std::array<std::ptrdiff_t, static_cast<std::size_t>(Rank)>;
35 
36 template <std::size_t N>
37 std::array<std::ptrdiff_t, N> Shift(const std::array<std::ptrdiff_t, N>& idx,
38  Direction dir, std::ptrdiff_t shift) {
39  auto shifted(idx);
40  shifted[static_cast<std::size_t>(dir)] += shift;
41  return shifted;
42 }
43 
44 template <std::size_t N>
45 std::array<std::ptrdiff_t, N> LeftTo(const std::array<std::ptrdiff_t, N>& idx,
46  Direction dir, std::ptrdiff_t shift = 1) {
47  return Shift(idx, dir, -shift);
48 }
49 
50 template <std::size_t N>
51 std::array<std::ptrdiff_t, N> RightTo(const std::array<std::ptrdiff_t, N>& idx,
52  Direction dir, std::ptrdiff_t shift = 1) {
53  return Shift(idx, dir, shift - 1);
54 }
55 
56 template <int Rank> struct IndexBox {
57  static_assert(Rank >= 0);
60 };
61 
62 template <int Rank>
63 bool operator==(const IndexBox<Rank>& b1, const IndexBox<Rank>& b2) {
64  return b1.lower == b2.lower && b1.upper == b2.upper;
65 }
66 
67 template <int Rank>
68 bool operator!=(const IndexBox<Rank>& b1, const IndexBox<Rank>& b2) {
69  return !(b1 == b2);
70 }
71 
72 template <int Rank>
73 bool Contains(const IndexBox<Rank>& b1, const IndexBox<Rank>& b2) {
74  return std::equal(b1.lower.begin(), b1.lower.end(), b2.lower.begin(),
75  std::less_equal<>{}) &&
76  std::equal(b2.upper.begin(), b2.upper.end(), b1.upper.begin(),
77  std::less_equal<>{});
78 }
79 
80 template <int Rank>
81 bool Contains(const IndexBox<Rank>& box, const Index<Rank>& index) {
82  Index<Rank> upper;
83  std::transform(index.begin(), index.end(), upper.begin(),
84  [](std::ptrdiff_t i) { return i + 1; });
85  return Contains(box, IndexBox<Rank>{index, upper});
86 }
87 
88 template <int Rank>
90  constexpr std::size_t sRank = static_cast<std::size_t>(Rank);
91  std::array<std::ptrdiff_t, sRank> lower;
92  std::transform(
93  b1.lower.begin(), b1.lower.end(), b2.lower.begin(), lower.begin(),
94  [](std::ptrdiff_t l1, std::ptrdiff_t l2) { return std::max(l1, l2); });
95  std::array<std::ptrdiff_t, sRank> upper;
96  std::transform(
97  b1.upper.begin(), b1.upper.end(), b2.upper.begin(), upper.begin(),
98  [](std::ptrdiff_t u1, std::ptrdiff_t u2) { return std::min(u1, u2); });
99  std::transform(
100  lower.begin(), lower.end(), upper.begin(), upper.begin(),
101  [](std::ptrdiff_t l, std::ptrdiff_t u) { return std::max(l, u); });
102  return IndexBox<Rank>{lower, upper};
103 }
104 
105 template <int Rank>
107  const std::array<std::ptrdiff_t, 2>& shifts) {
108  assert(static_cast<int>(dir) < Rank);
109  constexpr std::size_t sRank = static_cast<std::size_t>(Rank);
110  std::array<std::ptrdiff_t, sRank> lower = box.lower;
111  lower[static_cast<std::size_t>(dir)] -= shifts[0];
112  std::array<std::ptrdiff_t, sRank> upper = box.upper;
113  upper[static_cast<std::size_t>(dir)] += shifts[1];
114  return IndexBox<Rank>{lower, upper};
115 }
116 
117 template <int Rank>
119  const std::array<std::ptrdiff_t, 2>& shifts) {
120  assert(static_cast<int>(dir) < Rank);
121  constexpr std::size_t sRank = static_cast<std::size_t>(Rank);
122  std::array<std::ptrdiff_t, sRank> lower = box.lower;
123  lower[static_cast<std::size_t>(dir)] += shifts[0];
124  std::array<std::ptrdiff_t, sRank> upper = box.upper;
125  upper[static_cast<std::size_t>(dir)] -= shifts[1];
126  return IndexBox<Rank>{lower, upper};
127 }
128 
129 template <int Rank>
131  const std::array<std::ptrdiff_t, 2>& limits) {
132  constexpr std::size_t sRank = static_cast<std::size_t>(Rank);
133  std::array<std::ptrdiff_t, sRank> lower;
134  std::copy_n(box.lower.begin(), Rank - 1, lower.begin());
135  lower[Rank - 1] = limits[0];
136  std::array<std::ptrdiff_t, sRank> upper;
137  std::copy_n(box.upper.begin(), Rank - 1, upper.begin());
138  upper[Rank - 1] = limits[1];
139  return IndexBox<Rank>{lower, upper};
140 }
141 
142 template <int Rank, int OtherRank>
144  constexpr std::size_t sRank = static_cast<std::size_t>(Rank);
145  std::array<std::ptrdiff_t, sRank> lower;
146  std::copy_n(box.lower.begin(), Rank, lower.begin());
147  std::array<std::ptrdiff_t, sRank> upper;
148  std::copy_n(box.upper.begin(), Rank, upper.begin());
149  return IndexBox<Rank>{lower, upper};
150 }
151 
152 template <typename Extents>
153 constexpr std::array<std::ptrdiff_t, Extents::rank()>
154 AsArray(Extents e) noexcept {
155  std::array<std::ptrdiff_t, Extents::rank()> array{};
156  for (std::size_t r = 0; r < Extents::rank(); ++r) {
157  array[r] = e.extent(r);
158  }
159  return array;
160 }
161 
162 template <typename T, int Rank, typename Layout = layout_left>
163 struct PatchDataView;
164 
165 template <typename T, int Rank, typename Layout> struct PatchDataViewBase {
166  static constexpr std::size_t sRank = static_cast<std::size_t>(Rank);
167 
168  PatchDataViewBase() = default;
171 
173  const std::array<std::ptrdiff_t, sRank>& origin)
174  : mdspan_{data}, origin_{origin} {}
175 
177  std::array<std::ptrdiff_t, sRank> origin_;
178 };
179 
180 template <typename T, int Rank, typename Layout>
181 struct PatchDataViewBase<const T, Rank, Layout> {
182  static constexpr std::size_t sRank = static_cast<std::size_t>(Rank);
183 
184  PatchDataViewBase() = default;
185 
188 
190  : mdspan_{other.MdSpan()}, origin_{other.Origin()} {}
191 
193  const std::array<std::ptrdiff_t, sRank>& origin)
194  : mdspan_{data}, origin_{origin} {}
195 
197  std::array<std::ptrdiff_t, sRank> origin_;
198 };
199 
200 template <typename T, int R, typename Layout>
201 struct PatchDataView : public PatchDataViewBase<T, R, Layout> {
202  static constexpr std::size_t sRank = static_cast<std::size_t>(R);
203 
205 
206  const mdspan<T, sRank, Layout>& MdSpan() const noexcept {
207  return this->mdspan_;
208  }
209 
210  const std::array<std::ptrdiff_t, sRank>& Origin() const noexcept {
211  return this->origin_;
212  }
213 
214  dynamic_extents<sRank> Extents() const noexcept {
215  return this->mdspan_.extents();
216  }
217 
218  typename Layout::template mapping<dynamic_extents<sRank>>
219  Mapping() const noexcept {
220  return this->mdspan_.mapping();
221  }
222 
223  static constexpr int Rank() noexcept { return R; }
224  static constexpr int rank() noexcept { return R; }
225 
226  span<T> Span() const noexcept { return this->mdspan_.get_span(); }
227 
228  std::ptrdiff_t Stride(std::size_t n) const { return this->mdspan_.stride(n); }
229 
230  std::ptrdiff_t Extent(std::size_t n) const { return this->mdspan_.extent(n); }
231 
232  IndexBox<R> Box() const noexcept {
233  IndexBox<R> box;
234  box.lower = this->origin_;
235  std::array<std::ptrdiff_t, sRank> extents = AsArray(Extents());
236  std::transform(extents.begin(), extents.end(), box.lower.begin(),
237  box.upper.begin(),
238  [](std::ptrdiff_t extents, std::ptrdiff_t lower) {
239  FUB_ASSERT(extents >= 0);
240  return lower + extents;
241  });
242  return box;
243  }
244 
246  std::array<std::ptrdiff_t, sRank> offset;
247  std::transform(box.lower.begin(), box.lower.end(), this->origin_.begin(),
248  offset.begin(),
249  [](std::ptrdiff_t lower, std::ptrdiff_t origin) {
250  FUB_ASSERT(origin <= lower);
251  return lower - origin;
252  });
253  std::array<std::ptrdiff_t, sRank> extents;
254  std::transform(box.lower.begin(), box.lower.end(), box.upper.begin(),
255  extents.begin(),
256  [](std::ptrdiff_t lower, std::ptrdiff_t upper) {
257  FUB_ASSERT(lower <= upper);
258  return upper - lower;
259  });
260  std::array<std::pair<std::ptrdiff_t, std::ptrdiff_t>, sRank> slice_array;
261  std::transform(offset.begin(), offset.end(), extents.begin(),
262  slice_array.begin(),
263  [](std::ptrdiff_t offset, std::ptrdiff_t extents) {
264  return std::make_pair(offset, offset + extents);
265  });
266  return std::apply(
267  [&](const auto&... slices) {
269  subspan(MdSpan(), slices...), box.lower);
270  },
271  slice_array);
272  }
273 
274  template <typename... IndexType,
275  typename = std::enable_if_t<conjunction<
276  std::is_convertible<IndexType, std::ptrdiff_t>...>::value>>
277  auto& operator()(IndexType... indices) const {
278  std::array<std::ptrdiff_t, sRank> index{
279  static_cast<std::ptrdiff_t>(indices)...};
280  return this->operator()(index);
281  }
282 
283  template <typename IndexType,
284  typename = std::enable_if_t<
285  std::is_convertible_v<IndexType, std::ptrdiff_t>>>
286  auto& operator()(const std::array<IndexType, sRank>& indices) const {
287  std::array<IndexType, sRank> local_index;
288  std::transform(indices.begin(), indices.end(), Origin().begin(),
289  local_index.begin(),
290  [](IndexType i, IndexType o) { return i - o; });
291  return this->mdspan_(local_index);
292  }
293 };
294 
295 template <typename T, int Rank, typename Layout>
296 PatchDataView<T, Rank - 1, Layout>
297 SliceLast(const PatchDataView<T, Rank, Layout>& pdv, int component = 0) {
298  constexpr std::size_t sRank = static_cast<std::size_t>(Rank - 1);
299  std::array<std::ptrdiff_t, sRank + 1> index{};
300  index[sRank] = component;
301  std::array<std::ptrdiff_t, sRank> extents;
302  for (std::size_t r = 0; r < sRank; ++r) {
303  extents[r] = pdv.Extent(r);
304  }
305  std::array<std::ptrdiff_t, sRank> strides;
306  for (std::size_t r = 0; r < sRank; ++r) {
307  strides[r] = pdv.Stride(r);
308  }
309  std::array<std::ptrdiff_t, sRank> origin;
310  std::copy_n(pdv.Origin().begin(), Rank - 1, origin.begin());
311  if constexpr (std::is_same_v<Layout, layout_stride>) {
313  dynamic_extents<sRank>(extents), strides};
314  mdspan<T, sRank, Layout> mds(&pdv.MdSpan()(index), mapping);
315  return PatchDataView<T, Rank - 1, Layout>(mds, origin);
316  } else {
318  return PatchDataView<T, Rank - 1, Layout>(mds, origin);
319  }
320 }
321 
322 template <typename T, int Rank>
324 
325 } // namespace fub
326 
327 #endif
Definition: mdspan.hpp:573
An extents object defines a multidimensional index space which is the Cartesian product of integers e...
Definition: mdspan.hpp:208
Definition: mdspan.hpp:473
A span is a view over a contiguous sequence of objects, the storage of which is owned by some other o...
Definition: span.hpp:81
The fub namespace.
Definition: AnyBoundaryCondition.hpp:31
auto Shrink(const layout_left::mapping< Extent > &layout, Direction dir, std::ptrdiff_t n=1)
Definition: Equation.hpp:78
IndexBox< Rank > Grow(const IndexBox< Rank > &box, Direction dir, const std::array< std::ptrdiff_t, 2 > &shifts)
Definition: PatchDataView.hpp:106
std::array< std::ptrdiff_t, N > RightTo(const std::array< std::ptrdiff_t, N > &idx, Direction dir, std::ptrdiff_t shift=1)
Definition: PatchDataView.hpp:51
typename dynamic_extents_< make_index_sequence< Rank > >::type dynamic_extents
Definition: mdspan.hpp:725
constexpr std::array< std::ptrdiff_t, Extents::rank()> AsArray(Extents e) noexcept
Definition: PatchDataView.hpp:154
mdspan_subspan_t< ElementType, Extents, LayoutPolicy, AccessorPolicy, SliceSpecifiers... > subspan(const basic_mdspan< ElementType, Extents, LayoutPolicy, AccessorPolicy > &src, SliceSpecifiers... slices) noexcept
Definition: mdspan.hpp:968
Direction
This is a type safe type to denote a dimensional split direction.
Definition: Direction.hpp:30
std::array< std::ptrdiff_t, static_cast< std::size_t >(Rank)> Index
Definition: PatchDataView.hpp:34
bool operator==(const IndexBox< Rank > &b1, const IndexBox< Rank > &b2)
Definition: PatchDataView.hpp:63
bool Contains(const IndexBox< Rank > &b1, const IndexBox< Rank > &b2)
Definition: PatchDataView.hpp:73
dynamic_extents< static_cast< std::size_t >Rank)> Extents(const BasicView< State, Layout, Rank > &view)
Definition: State.hpp:480
std::array< double, 2 > Intersect(const std::array< double, 2 > &i1, const std::array< double, 2 > &i2)
Definition: CutCellData.hpp:29
bool operator!=(const IndexBox< Rank > &b1, const IndexBox< Rank > &b2)
Definition: PatchDataView.hpp:68
std::array< std::ptrdiff_t, N > Shift(const std::array< std::ptrdiff_t, N > &idx, Direction dir, std::ptrdiff_t shift)
Definition: PatchDataView.hpp:37
IndexBox< Rank > Project(const IndexBox< OtherRank > &box)
Definition: PatchDataView.hpp:143
IndexBox< Rank > Embed(const IndexBox< Rank - 1 > &box, const std::array< std::ptrdiff_t, 2 > &limits)
Definition: PatchDataView.hpp:130
PatchDataView< T, Rank - 1, Layout > SliceLast(const PatchDataView< T, Rank, Layout > &pdv, int component=0)
Definition: PatchDataView.hpp:297
std::ptrdiff_t index
Definition: type_traits.hpp:179
std::array< std::ptrdiff_t, N > LeftTo(const std::array< std::ptrdiff_t, N > &idx, Direction dir, std::ptrdiff_t shift=1)
Definition: PatchDataView.hpp:45
Definition: PatchDataView.hpp:56
Index< Rank > lower
Definition: PatchDataView.hpp:57
Index< Rank > upper
Definition: PatchDataView.hpp:59
std::array< std::ptrdiff_t, sRank > origin_
Definition: PatchDataView.hpp:197
PatchDataViewBase(const PatchDataViewBase &)=default
PatchDataViewBase(const PatchDataView< T, Rank, Layout > &other)
Definition: PatchDataView.hpp:189
PatchDataViewBase(const mdspan< const T, sRank, Layout > &data, const std::array< std::ptrdiff_t, sRank > &origin)
Definition: PatchDataView.hpp:192
mdspan< const T, sRank, Layout > mdspan_
Definition: PatchDataView.hpp:196
PatchDataViewBase & operator=(const PatchDataViewBase &)=default
Definition: PatchDataView.hpp:165
mdspan< T, sRank, Layout > mdspan_
Definition: PatchDataView.hpp:176
PatchDataViewBase(const mdspan< T, sRank, Layout > &data, const std::array< std::ptrdiff_t, sRank > &origin)
Definition: PatchDataView.hpp:172
PatchDataViewBase & operator=(const PatchDataViewBase &)=default
PatchDataViewBase(const PatchDataViewBase &)=default
static constexpr std::size_t sRank
Definition: PatchDataView.hpp:166
std::array< std::ptrdiff_t, sRank > origin_
Definition: PatchDataView.hpp:177
Definition: PatchDataView.hpp:201
auto & operator()(const std::array< IndexType, sRank > &indices) const
Definition: PatchDataView.hpp:286
std::ptrdiff_t Stride(std::size_t n) const
Definition: PatchDataView.hpp:228
static constexpr int rank() noexcept
Definition: PatchDataView.hpp:224
dynamic_extents< sRank > Extents() const noexcept
Definition: PatchDataView.hpp:214
auto & operator()(IndexType... indices) const
Definition: PatchDataView.hpp:277
static constexpr std::size_t sRank
Definition: PatchDataView.hpp:202
const mdspan< T, sRank, Layout > & MdSpan() const noexcept
Definition: PatchDataView.hpp:206
IndexBox< R > Box() const noexcept
Definition: PatchDataView.hpp:232
static constexpr int Rank() noexcept
Definition: PatchDataView.hpp:223
Layout::template mapping< dynamic_extents< sRank > > Mapping() const noexcept
Definition: PatchDataView.hpp:219
std::ptrdiff_t Extent(std::size_t n) const
Definition: PatchDataView.hpp:230
span< T > Span() const noexcept
Definition: PatchDataView.hpp:226
PatchDataView< T, R, layout_stride > Subview(const IndexBox< R > &box) const
Definition: PatchDataView.hpp:245
const std::array< std::ptrdiff_t, sRank > & Origin() const noexcept
Definition: PatchDataView.hpp:210
Definition: type_traits.hpp:123