Finite Volume Solver  prototype
A framework to build finite volume solvers for the AG Klein at the Freie Universität Berlin.
tagging_method/GradientDetector.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_TAGGING_GRADIENT_DETECTOR_HPP
22 #define FUB_TAGGING_GRADIENT_DETECTOR_HPP
23 
24 #include "fub/ForEach.hpp"
25 #include "fub/StateArray.hpp"
26 #include "fub/StateRow.hpp"
27 #include "fub/core/mdspan.hpp"
28 #include "fub/ext/Eigen.hpp"
29 
30 #include <utility>
31 
32 namespace fub {
33 
34 template <std::size_t DestRank, std::size_t SrcRank>
35 std::array<std::ptrdiff_t, DestRank>
36 EmbedInSpace(const std::array<std::ptrdiff_t, SrcRank>& index) {
37  if constexpr (DestRank == SrcRank) {
38  return index;
39  } else {
40  std::array<std::ptrdiff_t, DestRank> dest{};
41  std::copy_n(index.begin(), static_cast<std::ptrdiff_t>(SrcRank),
42  dest.begin());
43  return dest;
44  }
45 }
46 
47 template <typename Proj, typename State>
48 using Projection_t =
49  decltype(std::invoke(std::declval<Proj>(), std::declval<State>()));
50 
51 template <typename Proj, typename State>
53 
54 template <typename Equation, typename... Projections>
56 public:
58  const std::pair<Projections, double>&... conds)
59  : equation_{equation}, conditions_{conds...} {}
60 
61  Equation& GetEquation() noexcept { return equation_; }
62  const Equation& GetEquation() const noexcept { return equation_; }
63 
64  const std::tuple<std::pair<Projections, double>...>& GetConditions() const
65  noexcept {
66  return conditions_;
67  }
68 
69 protected:
71  std::tuple<std::pair<Projections, double>...> conditions_;
72 };
73 
74 template <typename Equation, typename... Projections>
76  : public GradientDetectorBase_<Equation, Projections...> {
77 public:
78  ScalarGradientDetector_(const Equation& equation,
79  const std::pair<Projections, double>&... conds);
80 
81  template <typename T, int TagRank>
82  void
84  const View<const Complete<Equation>>& states);
85 
86  template <int TagRank>
89  const View<const Complete<Equation>>& states,
91 
92 private:
93  using Base = GradientDetectorBase_<Equation, Projections...>;
97 };
98 
99 template <typename Equation, typename... Projections>
101  : public GradientDetectorBase_<Equation, Projections...> {
102 public:
103  static constexpr int Rank = Equation::Rank();
104 
105  ArrayGradientDetector_(const Equation& equation,
106  const std::pair<Projections, double>&... conds);
107 
108  void
110  const View<const Complete<Equation>>& states);
111 
112 private:
113  using Base = GradientDetectorBase_<Equation, Projections...>;
117 };
118 
119 template <bool IsArray, typename Eq, typename... Ps>
121  using type = ArrayGradientDetector_<Eq, Ps...>;
122 };
123 
124 template <typename Eq, typename... Ps>
125 struct GradientDetectorImpl_<false, Eq, Ps...> {
126  using type = ScalarGradientDetector_<Eq, Ps...>;
127 };
128 
129 /// \ingroup tagging
130 /// \brief This class tags cells with a relative error to their neighbors.
131 template <typename Eq, typename... Ps>
133  : public GradientDetectorImpl_<
134  (IsProjection<Ps&, const CompleteArray<Eq>&>::value && ...), Eq,
135  Ps...>::type {
136 public:
137  static constexpr bool is_array_based =
139  using Base = typename GradientDetectorImpl_<is_array_based, Eq, Ps...>::type;
140 
141  GradientDetector(const Eq& equation, const std::pair<Ps, double>&... projs)
142  : Base(equation, projs...) {}
143 };
144 
145 template <typename Eq, typename... Ps>
146 GradientDetector(const Eq&, const std::pair<Ps, double>&...)
147  ->GradientDetector<Eq, Ps...>;
148 
149 template <typename Equation, typename... Projections>
151  const Equation& equation, const std::pair<Projections, double>&... conds)
152  : Base(equation, conds...) {}
153 
154 template <typename Equation, typename... Projections>
155 template <typename T, int TagRank>
158  const View<const Complete<Equation>>& states) {
159  // GCC-7 complains that sTagRank is unused although we use this value at a
160  // constexpr context.
161  [[maybe_unused]] constexpr std::size_t sTagRank =
162  static_cast<std::size_t>(TagRank);
163  const auto tagbox = tags.Box();
164  for (std::size_t dir = 0; dir < Extents<0>(states).rank(); ++dir) {
165  ForEachIndex(
166  Shrink(Box<0>(states), Direction(dir), {1, 1}), [&](auto... is) {
167  using Index = std::array<std::ptrdiff_t, sizeof...(is)>;
168  const Index mid{is...};
169  if (Contains(tagbox, EmbedInSpace<sTagRank>(mid))) {
170  const Index left = Shift(mid, Direction(dir), -1);
171  const Index right = Shift(mid, Direction(dir), 1);
172  boost::mp11::tuple_for_each(Base::conditions_, [&](auto cond) {
173  auto&& [proj, tolerance] = cond;
174  Load(sL, states, left);
175  Load(sM, states, mid);
176  Load(sR, states, right);
177  auto&& xL = std::invoke(proj, sL);
178  auto&& xM = std::invoke(proj, sM);
179  auto&& xR = std::invoke(proj, sR);
180  if (xM != xR || xM != xL) {
181  const double left =
182  std::abs(xM - xL) / (std::abs(xM) + std::abs(xL));
183  const double right =
184  std::abs(xM - xR) / (std::abs(xM) + std::abs(xR));
185  tags(EmbedInSpace<sTagRank>(mid)) |=
186  static_cast<T>(left > tolerance || right > tolerance);
187  }
188  });
189  }
190  });
191  }
192 }
193 
194 template <typename Equation, typename... Projections>
195 template <int TagRank>
198  const View<const Complete<Equation>>& states,
200  const auto tagbox = tags.Box();
201  for (std::size_t dir = 0; dir < Extents<0>(states).rank(); ++dir) {
202  ForEachIndex(
203  Shrink(Box<0>(states), Direction(dir), {1, 1}), [&](auto... is) {
204  using Index = std::array<std::ptrdiff_t, sizeof...(is)>;
205  const Index mid{is...};
206  if (Contains(tagbox, mid)) {
207  const Index left = Shift(mid, Direction(dir), -1);
208  const Index right = Shift(mid, Direction(dir), 1);
209  if (volumes(left) > 0.0 && volumes(mid) > 0.0 &&
210  volumes(right) > 0.0) {
211  boost::mp11::tuple_for_each(Base::conditions_, [&](auto cond) {
212  auto&& [proj, tolerance] = cond;
213  Load(sL, states, left);
214  Load(sM, states, mid);
215  Load(sR, states, right);
216  auto&& xL = std::invoke(proj, sL);
217  auto&& xM = std::invoke(proj, sM);
218  auto&& xR = std::invoke(proj, sR);
219  if (xM != xR || xM != xL) {
220  const double left =
221  std::abs(xM - xL) / (std::abs(xM) + std::abs(xL));
222  const double right =
223  std::abs(xM - xR) / (std::abs(xM) + std::abs(xR));
224  tags(mid) |=
225  static_cast<char>(left > tolerance || right > tolerance);
226  }
227  });
228  }
229  }
230  });
231  }
232 }
233 
234 template <typename Equation, typename... Projections>
236  const Equation& equation, const std::pair<Projections, double>&... conds)
237  : Base(equation, conds...) {}
238 
239 template <typename Equation, typename... Projections>
242  const View<const Complete<Equation>>& states) {
243  Direction dir = Direction::X;
244  BasicView shifted = Subview(states, Grow(tags.Box(), dir, {1, 1}));
245  std::tuple views{tags, Shrink(shifted, dir, {0, 2}),
246  Shrink(shifted, dir, {1, 1}), Shrink(shifted, dir, {2, 0})};
247  FUB_ASSERT(Box<0>(std::get<2>(views)) == tags.Box());
248  ForEachRow(views, [&](span<char> tags_row,
249  const Row<const Complete<Equation>>& rL,
250  const Row<const Complete<Equation>>& rM,
251  const Row<const Complete<Equation>>& rR) {
252  char* tags_pointer = tags_row.begin();
257  int n = static_cast<int>(get<0>(pEnd) - get<0>(pR));
258  if (n >= kDefaultChunkSize) {
259  Load(sM_, pL);
260  Load(sR_, pM);
261  }
262  const Array<char, 1> ones = Array<char, 1>::Constant(char(1));
263  while (n >= kDefaultChunkSize) {
264  sL_ = sM_;
265  sM_ = sR_;
266  Load(sR_, pR);
267  Array<char, 1> tags_array = Array<char, 1>::Map(tags_pointer);
268  boost::mp11::tuple_for_each(Base::conditions_, [&](auto&& condition) {
269  auto&& [proj, tolerance] = condition;
270  const Array1d xL = std::invoke(proj, sL_);
271  const Array1d xM = std::invoke(proj, sM_);
272  const Array1d xR = std::invoke(proj, sR_);
273  const Array1d left = (xM - xL).abs() / (xM.abs() + xL.abs());
274  const Array1d right = (xM - xR).abs() / (xM.abs() + xR.abs());
275  tags_array = (left < tolerance).select(tags_array, ones);
276  tags_array = (right < tolerance).select(tags_array, ones);
277  });
278  Array<char, 1>::Map(tags_pointer) = tags_array;
280  tags_pointer += kDefaultChunkSize;
281  n = static_cast<int>(get<0>(pEnd) - get<0>(pR));
282  }
283  LoadN(sL_, pL, n);
284  LoadN(sM_, pM, n);
285  LoadN(sR_, pR, n);
286  Array<char, 1> tags_array = Array<char, 1>::Zero();
287  LoadN(tags_array, tags_pointer, n);
288  boost::mp11::tuple_for_each(Base::conditions_, [&](auto&& condition) {
289  auto&& [proj, tolerance] = condition;
290  const Array1d xL = std::invoke(proj, sL_);
291  const Array1d xM = std::invoke(proj, sM_);
292  const Array1d xR = std::invoke(proj, sR_);
293  const Array1d left = (xM - xL).abs() / (xM.abs() + xL.abs());
294  const Array1d right = (xM - xR).abs() / (xM.abs() + xR.abs());
295  tags_array = (left < tolerance).select(tags_array, ones);
296  tags_array = (right < tolerance).select(tags_array, ones);
297  });
298  StoreN(tags_pointer, tags_array, n);
299  });
300 }
301 
302 } // namespace fub
303 
304 #endif
#define FUB_ASSERT(x)
Definition: assert.hpp:39
Definition: tagging_method/GradientDetector.hpp:101
CompleteArray< Equation > sL_
Definition: tagging_method/GradientDetector.hpp:114
static constexpr int Rank
Definition: tagging_method/GradientDetector.hpp:103
CompleteArray< Equation > sM_
Definition: tagging_method/GradientDetector.hpp:115
ArrayGradientDetector_(const Equation &equation, const std::pair< Projections, double > &... conds)
Definition: tagging_method/GradientDetector.hpp:235
void TagCellsForRefinement(const PatchDataView< char, Rank, layout_stride > &tags, const View< const Complete< Equation >> &states)
Definition: tagging_method/GradientDetector.hpp:240
CompleteArray< Equation > sR_
Definition: tagging_method/GradientDetector.hpp:116
Definition: tagging_method/GradientDetector.hpp:55
Equation & GetEquation() noexcept
Definition: tagging_method/GradientDetector.hpp:61
GradientDetectorBase_(const Equation &equation, const std::pair< Projections, double > &... conds)
Definition: tagging_method/GradientDetector.hpp:57
Equation equation_
Definition: tagging_method/GradientDetector.hpp:70
std::tuple< std::pair< Projections, double >... > conditions_
Definition: tagging_method/GradientDetector.hpp:71
const std::tuple< std::pair< Projections, double >... > & GetConditions() const noexcept
Definition: tagging_method/GradientDetector.hpp:64
const Equation & GetEquation() const noexcept
Definition: tagging_method/GradientDetector.hpp:62
Definition: tagging_method/GradientDetector.hpp:76
void TagCellsForRefinement(const PatchDataView< T, TagRank, layout_stride > &tags, const View< const Complete< Equation >> &states)
Definition: tagging_method/GradientDetector.hpp:156
ScalarGradientDetector_(const Equation &equation, const std::pair< Projections, double > &... conds)
Definition: tagging_method/GradientDetector.hpp:150
Complete< Equation > sR
Definition: tagging_method/GradientDetector.hpp:96
Complete< Equation > sL
Definition: tagging_method/GradientDetector.hpp:94
Complete< Equation > sM
Definition: tagging_method/GradientDetector.hpp:95
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
constexpr iterator begin() const noexcept
Returns an iterator pointing to the first element of the span.
Definition: span.hpp:428
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
std::decay_t< decltype(std::declval< T >().GetEquation())> Equation
A template typedef to detect the member function.
Definition: Meta.hpp:59
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
std::conditional_t< N==1||M==1, Eigen::Array< T, N, M >, Eigen::Array< T, N, M, Eigen::RowMajor > > Array
Definition: Eigen.hpp:50
View< State > Subview(const BasicView< State, Layout, Rank > &state, const IndexBox< Rank > &box)
Definition: Equation.hpp:86
Array< double, 1 > Array1d
Definition: Eigen.hpp:53
constexpr const int kDefaultChunkSize
Definition: Eigen.hpp:39
GradientDetector(const Eq &, const std::pair< Ps, double > &...) -> GradientDetector< Eq, Ps... >
void StoreN(nodeduce_t< ViewPointer< Conservative< Eq >>> pointer, const ConservativeArray< Eq > &state, int n)
Definition: StateArray.hpp:416
IndexBox< Rank > Grow(const IndexBox< Rank > &box, Direction dir, const std::array< std::ptrdiff_t, 2 > &shifts)
Definition: PatchDataView.hpp:106
void ForEachRow(const Tuple &views, Function f)
Definition: StateRow.hpp:172
void Load(State &state, const BasicView< const State, Layout, Rank > &view, const std::array< std::ptrdiff_t, State::Equation::Rank()> &index)
Definition: State.hpp:640
ViewPointer< State > Begin(const BasicView< State, Layout, Rank > &view)
Definition: State.hpp:769
void LoadN(CompleteArray< Eq, N > &state, const BasicView< const Complete< Eq >, Layout, Rank > &view, int size, nodeduce_t< const std::array< std::ptrdiff_t, std::size_t(Rank)> & > pos)
Definition: StateArray.hpp:310
std::array< std::ptrdiff_t, DestRank > EmbedInSpace(const std::array< std::ptrdiff_t, SrcRank > &index)
Definition: tagging_method/GradientDetector.hpp:36
decltype(std::invoke(std::declval< Proj >(), std::declval< State >())) Projection_t
Definition: tagging_method/GradientDetector.hpp:49
Direction
This is a type safe type to denote a dimensional split direction.
Definition: Direction.hpp:30
void Advance(ViewPointer< State > &pointer, std::ptrdiff_t n) noexcept
Definition: State.hpp:825
std::array< std::ptrdiff_t, static_cast< std::size_t >(Rank)> Index
Definition: PatchDataView.hpp:34
bool Contains(const IndexBox< Rank > &b1, const IndexBox< Rank > &b2)
Definition: PatchDataView.hpp:73
ViewPointer< State > End(const BasicView< State, Layout, Rank > &view)
Definition: State.hpp:782
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
std::ptrdiff_t index
Definition: type_traits.hpp:179
Definition: State.hpp:403
Definition: tagging_method/GradientDetector.hpp:120
This class tags cells with a relative error to their neighbors.
Definition: tagging_method/GradientDetector.hpp:135
static constexpr bool is_array_based
Definition: tagging_method/GradientDetector.hpp:137
GradientDetector(const Eq &equation, const std::pair< Ps, double > &... projs)
Definition: tagging_method/GradientDetector.hpp:141
Definition: PatchDataView.hpp:201
IndexBox< R > Box() const noexcept
Definition: PatchDataView.hpp:232
Definition: StateRow.hpp:51
Definition: State.hpp:750
This is std::true_type if Op<Args...> is a valid SFINAE expression.
Definition: type_traits.hpp:92