Finite Volume Solver  prototype
A framework to build finite volume solvers for the AG Klein at the Freie Universität Berlin.
ForEach.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 /// \file This file defines several ForEachXXX functions to iterate through some
22 /// kind of range.
23 
24 /// \defgroup ForEach For Each Loops
25 /// \brief This group contains all functions that help to iterate over some
26 /// range.
27 
28 #ifndef FUB_FOR_EACH_HPP
29 #define FUB_FOR_EACH_HPP
30 
31 #include "fub/State.hpp"
32 #include "fub/core/mdspan.hpp"
33 
34 namespace fub {
35 
36 /// \ingroup ForEach
37 /// @{
38 ///
39 /// \brief Iterate through the multi-dimensional index space descibed by \p
40 /// mapping and invoke \p function for each such indices.
41 ///
42 /// \param[in] mapping Describes how a multi dimensional index is mapped into a
43 /// linear space.
44 ///
45 /// \param[in] function The callback object which is being invoked by this
46 /// function.
47 ///
48 /// \return Returns the callback function obect.
49 ///
50 /// The following example shows how to use this function.
51 ///
52 /// ~~~~~~~~~~~~~{.cpp}
53 /// // Invoke a function in two one-dimensional index space
54 /// mdspan<double, 2> array;
55 /// ForEachIndex(array.mapping(), [&](int i, int j) {
56 /// std::cout << fmt::format("array({}, {}) = {}\n", i, j, array(i, j));
57 /// });
58 ///
59 /// // Invoke a function in three one-dimensional index space
60 /// mdspan<double, 3> array;
61 /// ForEachIndex(array.mapping(), [](int i, int j, int k) {
62 /// std::cout << fmt::format("array({}, {}, {}) = \n", i, j, k, array(i, j,
63 /// k));
64 /// });
65 ///
66 /// // Invoke a function where dimension is generic
67 /// mdspan<double, Rank> array;
68 /// ForEachIndex(array.mapping(), [](auto... is) {
69 /// std::array<int, Rank> index{is...};
70 /// std::cout << fmt::format("array({}) = \n", index, array(index));
71 /// });
72 /// ~~~~~~~~~~~~~
73 template <typename Extents, typename Function>
75  Function function) {
76  static_assert(Extents::rank() == 1 || Extents::rank() == 2 ||
77  Extents::rank() == 3 || Extents::rank() == 4);
78  if constexpr (Extents::rank() == 1) {
79  for (int i = 0; i < mapping.extents().extent(0); ++i) {
80  function(i);
81  }
82  } else if constexpr (Extents::rank() == 2) {
83  for (int i = 0; i < mapping.extents().extent(1); ++i) {
84  for (int j = 0; j < mapping.extents().extent(0); ++j) {
85  function(j, i);
86  }
87  }
88  } else if constexpr (Extents::rank() == 3) {
89  for (int i = 0; i < mapping.extents().extent(2); ++i) {
90  for (int j = 0; j < mapping.extents().extent(1); ++j) {
91  for (int k = 0; k < mapping.extents().extent(0); ++k) {
92  function(k, j, i);
93  }
94  }
95  }
96  } else if constexpr (Extents::rank() == 4) {
97  for (int c = 0; c < mapping.extents().extent(3); ++c) {
98  for (int i = 0; i < mapping.extents().extent(2); ++i) {
99  for (int j = 0; j < mapping.extents().extent(1); ++j) {
100  for (int k = 0; k < mapping.extents().extent(0); ++k) {
101  function(k, j, i, c);
102  }
103  }
104  }
105  }
106  }
107  return function;
108 }
109 
110 template <typename Extents, typename Function>
112  Function function) {
113  static_assert(Extents::rank() == 1 || Extents::rank() == 2 ||
114  Extents::rank() == 3 || Extents::rank() == 4);
115  if constexpr (Extents::rank() == 1) {
116  for (int i = 0; i < mapping.extents().extent(0); ++i) {
117  function(i);
118  }
119  } else if constexpr (Extents::rank() == 2) {
120  FUB_ASSERT(mapping.stride(0) < mapping.stride(1));
121  for (int i = 0; i < mapping.extents().extent(1); ++i) {
122  for (int j = 0; j < mapping.extents().extent(0); ++j) {
123  function(j, i);
124  }
125  }
126  } else if constexpr (Extents::rank() == 3) {
127  FUB_ASSERT(mapping.stride(0) < mapping.stride(1));
128  FUB_ASSERT(mapping.stride(1) < mapping.stride(2));
129  for (int i = 0; i < mapping.extents().extent(2); ++i) {
130  for (int j = 0; j < mapping.extents().extent(1); ++j) {
131  for (int k = 0; k < mapping.extents().extent(0); ++k) {
132  function(k, j, i);
133  }
134  }
135  }
136  } else if constexpr (Extents::rank() == 4) {
137  for (int c = 0; c < mapping.extents().extent(3); ++c) {
138  for (int i = 0; i < mapping.extents().extent(2); ++i) {
139  for (int j = 0; j < mapping.extents().extent(1); ++j) {
140  for (int k = 0; k < mapping.extents().extent(0); ++k) {
141  function(k, j, i, c);
142  }
143  }
144  }
145  }
146  }
147  return function;
148 }
149 /// @}
150 
151 template <int Rank, typename Function>
152 Function ForEachIndex(const IndexBox<Rank>& box, Function function) {
153  static_assert(Rank == 1 || Rank == 2 || Rank == 3 || Rank == 4);
154  if constexpr (Rank == 1) {
155  for (std::ptrdiff_t i = box.lower[0]; i < box.upper[0]; ++i) {
156  function(i);
157  }
158  } else if constexpr (Rank == 2) {
159  for (std::ptrdiff_t i = box.lower[1]; i < box.upper[1]; ++i) {
160  for (std::ptrdiff_t j = box.lower[0]; j < box.upper[0]; ++j) {
161  function(j, i);
162  }
163  }
164  } else if constexpr (Rank == 3) {
165  for (std::ptrdiff_t i = box.lower[2]; i < box.upper[2]; ++i) {
166  for (std::ptrdiff_t j = box.lower[1]; j < box.upper[1]; ++j) {
167  for (std::ptrdiff_t k = box.lower[0]; k < box.upper[0]; ++k) {
168  function(k, j, i);
169  }
170  }
171  }
172  } else if constexpr (Rank == 4) {
173  for (std::ptrdiff_t c = box.lower[3]; c < box.upper[3]; ++c) {
174  for (std::ptrdiff_t i = box.lower[2]; i < box.upper[2]; ++i) {
175  for (std::ptrdiff_t j = box.lower[1]; j < box.upper[1]; ++j) {
176  for (std::ptrdiff_t k = box.lower[0]; k < box.upper[0]; ++k) {
177  function(k, j, i, c);
178  }
179  }
180  }
181  }
182  }
183  return function;
184 }
185 
186 } // namespace fub
187 
188 #endif
#define FUB_ASSERT(x)
Definition: assert.hpp:39
This mapping does row first indexing (as in Fortran).
Definition: mdspan.hpp:302
constexpr const Extents & extents() const noexcept
Definition: mdspan.hpp:325
Definition: mdspan.hpp:473
std::ptrdiff_t stride(size_t rank) const noexcept
Definition: mdspan.hpp:534
constexpr const Extents & extents() const noexcept
Definition: mdspan.hpp:496
Function ForEachIndex(const layout_left::mapping< Extents > &mapping, Function function)
Iterate through the multi-dimensional index space descibed by mapping and invoke function for each su...
Definition: ForEach.hpp:74
The fub namespace.
Definition: AnyBoundaryCondition.hpp:31
Definition: PatchDataView.hpp:56
Index< Rank > lower
Definition: PatchDataView.hpp:57
Index< Rank > upper
Definition: PatchDataView.hpp:59