Finite Volume Solver  prototype
A framework to build finite volume solvers for the AG Klein at the Freie Universität Berlin.
State.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_STATE_HPP
22 #define FUB_STATE_HPP
23 
24 #include "fub/PatchDataView.hpp"
25 #include "fub/core/tuple.hpp"
26 #include "fub/ext/Eigen.hpp"
27 
28 #include <boost/mp11/algorithm.hpp>
29 #include <boost/mp11/tuple.hpp>
30 
31 #include <numeric>
32 
33 namespace fub {
34 
35 template <typename T> struct StateTraits;
36 
37 namespace meta {
38 
39 template <typename Depths> struct Rank;
40 
41 }
42 
43 namespace detail {
44 template <std::size_t I, typename... Ts> constexpr auto ZipNested(Ts&&... ts) {
45  return std::make_tuple(std::get<I>(ts)...);
46 }
47 
48 template <std::size_t... Is, typename... Ts>
49 constexpr auto ZipHelper(std::index_sequence<Is...>, Ts&&... ts) {
50  return std::make_tuple(ZipNested<Is>(std::forward<Ts>(ts)...)...);
51 }
52 
53 template <std::size_t I, typename... Ts>
54 constexpr auto UnzipNested(const std::tuple<Ts...>& ts) {
55  return std::apply([](const auto& t) { return std::get<I>(t); }, ts);
56 }
57 
58 template <std::size_t... Is, typename... Ts>
59 constexpr auto UnzipHelper(std::index_sequence<Is...>,
60  const std::tuple<Ts...>& ts) {
61  return std::make_tuple(UnzipNested<Is>(ts)...);
62 }
63 } // namespace detail
64 
65 template <typename... Ts> constexpr auto Zip(Ts&&... ts) {
66  using First =
67  std::decay_t<boost::mp11::mp_front<boost::mp11::mp_list<Ts...>>>;
68  return detail::ZipHelper(
69  std::make_index_sequence<std::tuple_size<First>::value>(),
70  std::forward<Ts>(ts)...);
71 }
72 
73 template <typename... Ts>
74 constexpr auto Unzip(const std::tuple<Ts...>& zipped) {
75  using First =
76  std::decay_t<boost::mp11::mp_front<boost::mp11::mp_list<Ts...>>>;
77  return detail::UnzipHelper(
78  std::make_index_sequence<std::tuple_size<First>::value>(), zipped);
79 }
80 
81 template <std::size_t I, typename State>
82 constexpr decltype(auto) get(State&& x) {
83  using S = remove_cvref_t<State>;
84  constexpr auto& pointers_to_member = S::Traits::pointers_to_member;
85  return x.*std::get<I>(pointers_to_member);
86 }
87 
88 template <typename F, typename... Ts>
89 void ForEachVariable(F function, Ts&&... states) {
90  constexpr auto pointers =
91  Zip(StateTraits<remove_cvref_t<Ts>>::pointers_to_member...);
92  const auto xs = std::make_tuple(std::addressof(states)...);
93  boost::mp11::tuple_for_each(pointers, [&function, &xs](const auto& ps) {
94  boost::mp11::tuple_apply(
95  [&function](auto... ys) {
96  function((*std::get<0>(ys)).*std::get<1>(ys)...);
97  },
98  Zip(xs, ps));
99  });
100 }
101 
102 template <typename T>
104  : std::integral_constant<
105  std::size_t,
106  std::tuple_size_v<std::decay_t<decltype(T::Traits::names)>>> {};
107 
108 /// This type is used to tag scalar quantities
109 struct ScalarDepth : std::integral_constant<int, 1> {};
110 
111 /// This type is used to tag quantities with a depth known at compile time.
112 template <int Depth> struct VectorDepth : std::integral_constant<int, Depth> {};
113 
114 template <typename Depth> struct ToConcreteDepthImpl { using type = Depth; };
115 
116 template <> struct ToConcreteDepthImpl<VectorDepth<-1>> { using type = int; };
117 
118 template <typename Depth>
120 
121 template <typename Depths>
122 using ToConcreteDepths = boost::mp11::mp_transform<ToConcreteDepth, Depths>;
123 
124 namespace detail {
125 /// @{
126 /// This meta-function transforms a Depth into a value type used in a states or
127 /// state arrays.
128 template <typename T, int Width> struct DepthToStateValueTypeImpl;
129 
130 /// The value-type for a single-cell state for a scalar quantity.
131 template <> struct DepthToStateValueTypeImpl<ScalarDepth, 1> {
132  using type = double;
133 };
134 
135 /// The value-type for a single-cell state for a scalar quantity.
136 template <int Width> struct DepthToStateValueTypeImpl<ScalarDepth, Width> {
137  using type = Array<double, 1, Width>;
138 };
139 
140 /// The value-type for a single-cell state for a scalar quantity.
141 template <int Depth, int Width>
142 struct DepthToStateValueTypeImpl<VectorDepth<Depth>, Width> {
143  using type = Array<double, Depth, Width>;
144 };
145 
146 /// For usage with boost::mp11
147 template <typename T>
148 using DepthToStateValueType = typename DepthToStateValueTypeImpl<T, 1>::type;
149 /// @}
150 
151 template <typename T, typename Eq>
152 using DepthsT = typename StateTraits<T>::template Depths<Eq::Rank()>;
153 
154 template <typename T, typename Eq> struct DepthsImpl {
155  constexpr typename StateTraits<T>::template Depths<Eq::Rank()>
156  operator()(const Eq&) const noexcept {
157  return {};
158  }
159 };
160 } // namespace detail
161 
162 template <typename T> struct Type {
163  using type = T;
164 };
165 
166 inline constexpr struct DepthsFn {
167  template <typename Eq, typename State>
168  constexpr auto operator()(const Eq& eq,
169  [[maybe_unused]] Type<State> state) const
170  noexcept(
171  is_nothrow_tag_invocable<DepthsFn, const Eq&, Type<State>>::value ||
172  !is_tag_invocable<DepthsFn, const Eq&, Type<State>>::value) {
173  if constexpr (is_tag_invocable<DepthsFn, const Eq&, Type<State>>::value) {
174  return fub::meta::tag_invoke(*this, eq, std::move(state));
175  } else if constexpr (is_detected<detail::DepthsT, State, Eq>::value) {
176  detail::DepthsImpl<State, Eq> default_depths;
177  return default_depths(eq);
178  } else {
179  static_assert(
180  is_tag_invocable<DepthsFn, const Eq&, Type<State>>::value ||
182  }
183  }
185 
186 namespace meta {
187 template <typename T>
188 using Depths = decltype(
189  ::fub::Depths(std::declval<typename T::Equation const&>(), Type<T>{}));
190 }
191 
192 template <typename Depths>
194  boost::mp11::mp_transform<detail::DepthToStateValueType, Depths>;
195 
196 template <typename Depths> struct ScalarState : ScalarStateBase<Depths> {
199 
200  using Base::Base;
201 
202  template <typename Equation>
203  ScalarState(const Equation& eq) : Base{} {
204  auto depths = ::fub::Depths(eq, Type<ScalarState>{});
206  overloaded{
207  [&](double& id, ScalarDepth) { id = 0.0; },
208  [&](auto&& ids, auto depth) {
209  if constexpr (std::is_same_v<std::decay_t<decltype(depth)>,
210  int>) {
212  } else {
213  ids = Array<double, 1, decltype(depth)::value>::Zero();
214  }
215  },
216  },
217  *this, depths);
218  }
219 
220  ScalarState& operator+=(const Base& other) {
221  ForEachVariable([](auto&& that, auto&& other) { that += other; }, *this,
222  other);
223  return *this;
224  }
225 
226  ScalarState& operator-=(const Base& other) {
227  ForEachVariable([](auto&& that, auto&& other) { that -= other; }, *this,
228  other);
229  return *this;
230  }
231 
232  ScalarState& operator*=(double lambda) {
233  ForEachVariable([lambda](auto&& that) { that *= lambda; }, *this);
234  return *this;
235  }
236 };
237 
238 template <typename Depths>
239 struct StateTraits<ScalarState<Depths>> : StateTraits<ScalarStateBase<Depths>> {
240 };
241 
242 /// This type alias transforms state depths into a conservative state
243 /// associated with a specified equation.
244 template <typename Equation>
246  boost::mp11::mp_transform<detail::DepthToStateValueType,
247  typename Equation::ConservativeDepths>;
248 
249 /// This type has a constructor which takes an equation and might allocate any
250 /// dynamically sized member variable.
251 template <typename Eq> struct Conservative : ConservativeBase<Eq> {
252  using Equation = Eq;
253  using ValueType = double;
255 
256  Conservative() = default;
259  static_cast<ConservativeBase<Eq>&>(*this) = x;
260  return *this;
261  }
263  auto depths = ::fub::Depths(eq, Type<Conservative<Equation>>{});
265  overloaded{
266  [&](double& id, ScalarDepth) { id = 0.0; },
267  [&](auto&& ids, auto depth) {
268  if constexpr (std::is_same_v<std::decay_t<decltype(depth)>,
269  int>) {
270  ids = Array<double, 1, Eigen::Dynamic>::Zero(1, depth);
271  } else {
272  ids = Array<double, 1, decltype(depth)::value>::Zero();
273  }
274  },
275  },
276  *this, depths);
277  }
278 
280  ForEachVariable([](auto&& that, auto&& other) { that += other; }, *this,
281  other);
282  return *this;
283  }
284 };
285 
286 template <typename Eq>
287 struct StateTraits<Conservative<Eq>> : StateTraits<ConservativeBase<Eq>> {};
288 
289 template <typename Eq>
290 struct Primitive : ScalarState<typename Eq::PrimitiveDepths> {
292 
293  using Base::Base;
294 };
295 
296 template <typename Eq>
298  : StateTraits<ScalarStateBase<typename Eq::PrimitiveDepths>> {};
299 
300 template <typename Eq>
301 struct KineticState : ScalarState<typename Eq::KineticStateDepths> {
303 
304  using Base::Base;
305 };
306 
307 template <typename Eq>
309  : StateTraits<ScalarStateBase<typename Eq::KineticStateDepths>> {};
310 
311 template <typename Eq>
312 struct Characteristics : ScalarState<typename Eq::CharacteristicsDepths> {
314 
315  using Base::Base;
316 };
317 
318 template <typename Eq>
320  : StateTraits<ScalarStateBase<typename Eq::CharacteristicsDepths>> {};
321 
322 template <typename State> auto StateToTuple(const State& x) {
323  return boost::mp11::tuple_apply(
324  [&x](auto... pointer) { return std::make_tuple((x.*pointer)...); },
326 }
327 
328 template <typename Equation>
330  boost::mp11::mp_transform<detail::DepthToStateValueType,
331  typename Equation::CompleteDepths>;
332 
333 /// This type has a constructor which takes an equation and might allocate any
334 /// dynamically sized member variable.
335 template <typename Eq> struct Complete : CompleteBase<Eq> {
336  using Equation = Eq;
337  using ValueType = double;
339 
340  Complete() = default;
341  Complete(const CompleteBase<Eq>& x) : CompleteBase<Eq>{x} {}
343  static_cast<CompleteBase<Eq>&>(*this) = x;
344  }
345  Complete(const Equation& eq) : CompleteBase<Eq>{} {
346  auto depths = ::fub::Depths(eq, Type<Complete<Equation>>{});
348  overloaded{
349  [&](double& id, ScalarDepth) { id = 0.0; },
350  [&](auto&& ids, auto depth) {
351  if constexpr (std::is_same_v<std::decay_t<decltype(depth)>,
352  int>) {
353  ids = Array<double, 1, Eigen::Dynamic>::Zero(1, depth);
354  } else {
355  ids = Array<double, 1, decltype(depth)::value>::Zero();
356  }
357  },
358  },
359  *this, depths);
360  }
361 
362  Complete& operator+=(const Complete& other) {
363  ForEachVariable([](auto&& that, auto&& other) { that += other; }, *this,
364  other);
365  return *this;
366  }
367 };
368 
369 template <typename Eq>
370 struct StateTraits<Complete<Eq>> : StateTraits<CompleteBase<Eq>> {};
371 
372 ///// View type
373 namespace detail {
374 template <typename Depth, typename T, int Rank, typename Layout>
375 struct DepthToViewValueType {
377 };
378 
379 template <typename T, int Rank, typename Layout>
380 struct DepthToViewValueType<ScalarDepth, T, Rank, Layout> {
381  using type = PatchDataView<T, Rank, Layout>;
382 };
383 
384 template <typename State, typename Layout, int Rank> struct ViewBaseImpl {
385  template <typename Depth>
386  using fn = typename DepthToViewValueType<Depth, double, Rank, Layout>::type;
387  using type = boost::mp11::mp_transform<fn, meta::Depths<State>>;
388 };
389 
390 template <typename State, typename Layout, int Rank>
391 struct ViewBaseImpl<const State, Layout, Rank> {
392  template <typename Depth>
393  using fn =
394  typename DepthToViewValueType<Depth, const double, Rank, Layout>::type;
395  using type = boost::mp11::mp_transform<fn, meta::Depths<State>>;
396 };
397 } // namespace detail
398 
399 template <typename State, typename Layout, int Rank>
400 using ViewBase = typename detail::ViewBaseImpl<State, Layout, Rank>::type;
401 
402 template <typename S, typename L = layout_left, int R = S::Equation::Rank()>
403 struct BasicView : ViewBase<S, L, R> {
404  using State = S;
405  using Layout = L;
406  static constexpr int Rank = R;
407  using ValueType =
408  std::conditional_t<std::is_const<S>::value, const double, double>;
409  using Equation = typename State::Equation;
410  using Depths = typename Equation::ConservativeDepths;
412 
413  static constexpr int rank() noexcept { return Rank; }
414 
415  BasicView() = default;
416 
417  BasicView(const ViewBase<S, L, R>& base) : ViewBase<S, L, R>{base} {}
419  static_cast<ViewBase<S, L, R>&>(*this) = base;
420  }
421 };
422 
423 template <typename S, typename L, int R>
425 
426 template <typename S, typename L, int R>
427 struct StateTraits<BasicView<S, L, R>> : StateTraits<ViewBase<S, L, R>> {};
428 
429 template <typename State, typename Layout, int Rank>
433  ForEachVariable([](auto& w, const auto& v) { w = v; }, w, v);
434  return w;
435 }
436 
437 template <typename Eq>
439  return x;
440 }
441 
442 template <typename Eq> Conservative<Eq>& AsCons(Conservative<Eq>& x) {
443  return x;
444 }
445 
446 template <typename Eq>
448  return x;
449 }
450 
451 template <typename Eq> ConservativeBase<Eq>& AsCons(Complete<Eq>& x) {
452  return x;
453 }
454 
455 template <typename State, typename L, int R>
456 auto AsCons(const BasicView<State, L, R>& view) {
457  using T = std::remove_const_t<State>;
458  using Equation = typename T::Equation;
459  if constexpr (std::is_same<T, Conservative<Equation>>::value) {
460  return view;
461  } else {
462  using Cons = std::conditional_t<std::is_const<State>::value,
465  BasicView<Cons, L, R> cons(view);
466  return cons;
467  }
468 }
469 
470 template <typename State, int Rank = State::Equation::Rank()>
472 
473 template <typename T> struct IsView : std::false_type {};
474 
475 template <typename State, typename Layout, int Rank>
476 struct IsView<BasicView<State, Layout, Rank>> : std::true_type {};
477 
478 template <int N, typename State, typename Layout, int Rank>
481  static_assert(N >= 0, "N has to be greater than 0!");
482  return get<static_cast<std::size_t>(N)>(view).Extents();
483 }
484 
485 template <int N, typename State, typename Layout, int Rank>
487  static_assert(N >= 0, "N has to be greater than 0!");
488  return get<static_cast<std::size_t>(N)>(view).Box();
489 }
490 
491 template <int N, typename State, typename Layout, int Rank>
492 typename Layout::template mapping<
493  dynamic_extents<static_cast<std::size_t>(Rank)>>
495  static_assert(N >= 0, "N has to be greater than 0!");
496  return get<static_cast<std::size_t>(N)>(view).Mapping();
497 }
498 
499 namespace detail {
500 
501 template <typename State, typename Layout, int Rank, typename Eq>
502 struct DepthsImpl<BasicView<State, Layout, Rank>, Eq> {
503  constexpr auto operator()(const Eq& eq) const noexcept {
504  DepthsImpl<std::remove_const_t<State>, Eq> depths{};
505  return depths(eq);
506  }
507 };
508 
509 template <typename T> struct GetNumberOfComponentsImpl {
510  int_constant<1> operator()(double) const noexcept { return {}; }
511  int_constant<1> operator()(int) const noexcept { return {}; }
512 
513  template <std::size_t N>
514  int_constant<static_cast<int>(N)>
515  operator()(const std::array<int, N>&) const noexcept {
516  return {};
517  }
518 
519  template <int N, int M, int O, int MR, int MC>
520  int_constant<N>
521  operator()(const Eigen::Array<double, N, M, O, MR, MC>&) const noexcept {
522  return {};
523  }
524 
525  template <int M, int O, int MR, int MC>
526  int operator()(const Eigen::Array<double, Eigen::Dynamic, M, O, MR, MC>& x)
527  const noexcept {
528  return static_cast<int>(x.rows());
529  }
530 
531  int operator()(const std::vector<int>& x) const noexcept {
532  return static_cast<int>(x.size());
533  }
534 };
535 
536 template <typename S, typename Layout, int Rank>
537 struct GetNumberOfComponentsImpl<BasicView<S, Layout, Rank>> {
538  int_constant<1>
539  operator()(const PatchDataView<double, Rank, Layout>&) const noexcept {
540  return {};
541  }
542  int operator()(
543  const PatchDataView<double, Rank + 1, Layout>& pdv) const noexcept {
544  return static_cast<int>(pdv.Extent(Rank));
545  }
546 };
547 
548 template <typename T>
549 static constexpr GetNumberOfComponentsImpl<T> GetNumberOfComponents{};
550 
551 template <typename T> struct AtComponentImpl {
552  template <typename FP>
553  std::enable_if_t<std::is_floating_point<remove_cvref_t<FP>>::value, FP>
554  operator()(FP&& x, int) const noexcept {
555  return x;
556  }
557 
558  template <int N>
559  double& operator()(Eigen::Array<double, N, 1>& x, int n) const noexcept {
560  return x[n];
561  }
562 
563  template <int N>
564  const double& operator()(const Eigen::Array<double, N, 1>& x,
565  int n) const noexcept {
566  return x[n];
567  }
568 
569  template <int N, int M, int O, int MR, int MC>
570  auto operator()(Eigen::Array<double, N, M, O, MR, MC>& x,
571  int n) const noexcept {
572  return x.row(n);
573  }
574 
575  template <int N, int M, int O, int MR, int MC>
576  auto operator()(const Eigen::Array<double, N, M, O, MR, MC>& x,
577  int n) const noexcept {
578  return x.row(n);
579  }
580 };
581 
582 template <typename S, typename Layout, int Rank>
583 struct AtComponentImpl<BasicView<S, Layout, Rank>> {
584  using ValueType = typename BasicView<S, Layout, Rank>::ValueType;
585 
586  const PatchDataView<ValueType, Rank, Layout>&
587  operator()(const PatchDataView<ValueType, Rank, Layout>& x,
588  int) const noexcept {
589  return x;
590  }
591 
592  PatchDataView<ValueType, Rank, Layout>
593  operator()(const PatchDataView<ValueType, Rank + 1, Layout>& x,
594  int n) const noexcept {
595  constexpr std::size_t sRank = Rank;
596  std::array<std::ptrdiff_t, sRank + 1> index{};
597  index[sRank] = n;
598  std::array<std::ptrdiff_t, sRank> extents;
599  for (std::size_t r = 0; r < sRank; ++r) {
600  extents[r] = x.Extent(r);
601  }
602  std::array<std::ptrdiff_t, sRank> strides;
603  for (std::size_t r = 0; r < sRank; ++r) {
604  strides[r] = x.Stride(r);
605  }
606  std::array<std::ptrdiff_t, sRank> origin;
607  std::copy_n(x.Origin().begin(), Rank, origin.begin());
608  if constexpr (std::is_same_v<Layout, layout_stride>) {
609  layout_stride::mapping<dynamic_extents<sRank>> mapping{
610  dynamic_extents<sRank>(extents), strides};
611  mdspan<ValueType, sRank, Layout> mds(&x.MdSpan()(index), mapping);
612  return PatchDataView<ValueType, Rank, Layout>(mds, origin);
613  } else {
614  mdspan<ValueType, sRank, Layout> mds(&x.MdSpan()(index), extents);
615  return PatchDataView<ValueType, Rank, Layout>(mds, origin);
616  }
617  }
618 };
619 
620 template <typename State> constexpr static AtComponentImpl<State> AtComponent{};
621 } // namespace detail
622 
623 template <typename F, typename... Ts>
624 void ForEachComponent(F function, Ts&&... states) {
626  [&](auto&&... variables) {
627  const auto vs = std::make_tuple(std::addressof(variables)...);
628  using T =
629  remove_cvref_t<boost::mp11::mp_first<boost::mp11::mp_list<Ts...>>>;
630  const int n_components =
631  detail::GetNumberOfComponents<T>(*std::get<0>(vs));
632  for (int i = 0; i < n_components; ++i) {
633  function(detail::AtComponent<remove_cvref_t<Ts>>(variables, i)...);
634  }
635  },
636  std::forward<Ts>(states)...);
637 }
638 
639 template <typename State, typename Layout, int Rank>
640 void Load(State& state, const BasicView<const State, Layout, Rank>& view,
641  const std::array<std::ptrdiff_t, State::Equation::Rank()>& index) {
643  [&](double& component,
645  FUB_ASSERT(Contains(pdv.Box(), index));
646  component = pdv(index);
647  },
648  state, view);
649 }
650 
651 template <typename State, typename Layout, int Rank>
652 void Load(State& state, const BasicView<State, Layout, Rank>& view,
653  const std::array<std::ptrdiff_t, State::Equation::Rank()>& index) {
655  [&](double& component, const auto& pdv) {
656  FUB_ASSERT(Contains(pdv.Box(), index));
657  component = pdv(index);
658  },
659  state, view);
660 }
661 
662 template <typename Eq, typename Layout>
663 void Store(const BasicView<Conservative<Eq>, Layout, Eq::Rank()>& view,
664  const Conservative<Eq>& state,
665  const std::array<std::ptrdiff_t, Eq::Rank()>& index) {
667  [&](auto data, auto block) {
668  FUB_ASSERT(Contains(data.Box(), index));
669  Store(data, block, index);
670  },
671  view, state);
672 }
673 
674 template <typename Eq, typename Layout>
675 void Store(const BasicView<Complete<Eq>, Layout, Eq::Rank()>& view,
676  const Complete<Eq>& state,
677  const std::array<std::ptrdiff_t, Eq::Rank()>& index) {
679  [&](auto data, auto block) {
680  FUB_ASSERT(Contains(data.Box(), index));
681  Store(data, block, index);
682  },
683  view, state);
684 }
685 
686 template <Direction dir, typename T, typename L, int Rank,
687  typename SliceSpecifier>
688 auto Slice(const BasicView<T, L, Rank>& view, SliceSpecifier slice) {
689  View<T, Rank> sliced_view;
690  ForEachVariable([&](auto& s, auto v) { s = Slice<dir>(v, slice); },
691  sliced_view, view);
692  return sliced_view;
693 }
694 
695 template <typename State, int Rank, typename Layout>
697  Direction dir, std::array<std::ptrdiff_t, 2> offsets) {
698  IndexBox<Rank> box = Box<0>(view);
699  IndexBox<Rank> shrinked_box = Shrink(box, dir, offsets);
700  View<State, Rank> shrinked_view;
701  using T = std::conditional_t<std::is_const_v<State>, const double, double>;
703  overloaded{
704  [&shrinked_box](PatchDataView<T, Rank, layout_stride>& dest,
706  dest = src.Subview(shrinked_box);
707  },
708  [&shrinked_box](PatchDataView<T, Rank + 1, layout_stride>& dest,
710  IndexBox<Rank + 1> src_box = src.Box();
711  IndexBox<Rank + 1> embed_shrinked_box = Embed<Rank + 1>(
712  shrinked_box, {src_box.lower[Rank], src_box.upper[Rank]});
713  dest = src.Subview(embed_shrinked_box);
714  }},
715  shrinked_view, view);
716  return shrinked_view;
717 }
718 
719 template <typename Equation> bool AnyNaN(const Complete<Equation>& state) {
720  bool any_nan = false;
721  ForEachComponent([&any_nan](double x) { any_nan |= std::isnan(x); }, state);
722  return any_nan;
723 }
724 
725 namespace detail {
726 template <typename T, typename Depth> struct DepthToPointerType {
727  using type = std::pair<T*, std::ptrdiff_t>;
728 };
729 
730 template <typename T> struct DepthToPointerType<T, ScalarDepth> {
731  using type = T*;
732 };
733 
734 template <typename State> struct ViewPointerBaseImpl {
735  template <typename Depth>
736  using fn = typename DepthToPointerType<double, Depth>::type;
737  using type = boost::mp11::mp_transform<fn, meta::Depths<State>>;
738 };
739 
740 template <typename State> struct ViewPointerBaseImpl<const State> {
741  template <typename Depth>
742  using fn = typename DepthToPointerType<const double, Depth>::type;
743  using type = boost::mp11::mp_transform<fn, meta::Depths<State>>;
744 };
745 } // namespace detail
746 
747 template <typename State>
748 using ViewPointerBase = typename detail::ViewPointerBaseImpl<State>::type;
749 
750 template <typename State> struct ViewPointer : ViewPointerBase<State> {
752 };
753 
754 template <typename State>
755 struct StateTraits<ViewPointer<State>> : StateTraits<ViewPointerBase<State>> {};
756 
757 template <typename State>
759 
760 template <typename State>
762 {
764  ForEachVariable([](auto& cptr, auto ptr) { cptr = ptr; }, cp, p);
765  return cp;
766 }
767 
768 template <typename State, typename Layout, int Rank>
770  ViewPointer<State> pointer;
772  overloaded{[&](double*& p, auto pdv) { p = pdv.Span().begin(); },
773  [&](const double*& p, auto pdv) { p = pdv.Span().begin(); },
774  [&](auto& p, auto pdv) {
775  p = std::pair{pdv.Span().begin(), pdv.Stride(Rank)};
776  }},
777  pointer, view);
778  return pointer;
779 }
780 
781 template <typename State, typename Layout, int Rank>
783  ViewPointer<State> pointer;
785  overloaded{[&](double*& p, auto pdv) { p = pdv.Span().end(); },
786  [&](const double*& p, auto pdv) { p = pdv.Span().end(); },
787  [&](auto& p, auto pdv) {
788  p = std::pair{pdv.Span().end(), pdv.Stride(Rank)};
789  }},
790  pointer, view);
791  return pointer;
792 }
793 
794 template <typename Eq>
795 void Load(Complete<Eq>& state,
796  nodeduce_t<ViewPointer<const Complete<Eq>>> pointer) {
798  overloaded{[](double& x, const double* p) { x = *p; },
799  [](auto& xs, std::pair<const double*, std::ptrdiff_t> ps) {
800  const double* p = ps.first;
801  for (std::size_t i = 0; i < xs.size(); ++i) {
802  xs[i] = *p;
803  p += ps.second;
804  }
805  }},
806  state, pointer);
807 }
808 
809 template <typename Eq>
810 void Load(Conservative<Eq>& state,
811  nodeduce_t<ViewPointer<const Conservative<Eq>>> pointer) {
813  overloaded{[](double& x, const double* p) { x = *p; },
814  [](auto& xs, std::pair<const double*, std::ptrdiff_t> ps) {
815  const double* p = ps.first;
816  for (std::size_t i = 0; i < xs.size(); ++i) {
817  xs[i] = *p;
818  p += ps.second;
819  }
820  }},
821  state, pointer);
822 }
823 
824 template <typename State>
825 void Advance(ViewPointer<State>& pointer, std::ptrdiff_t n) noexcept {
826  ForEachVariable(overloaded{[n](double*& ptr) { ptr += n; },
827  [n](const double*& ptr) { ptr += n; },
828  [n](auto& ptr) { ptr.first += n; }},
829  pointer);
830 }
831 
832 namespace detail {
833 template <typename T> struct DepthToIndexMappingTypeImpl;
834 
835 /// The value-type for a single-cell state for a scalar quantity.
836 template <> struct DepthToIndexMappingTypeImpl<ScalarDepth> {
837  using type = int;
838 };
839 
840 /// The value-type for a single-cell state for a scalar quantity.
841 template <int Depth> struct DepthToIndexMappingTypeImpl<VectorDepth<Depth>> {
842  using type = std::array<int, static_cast<std::size_t>(Depth)>;
843 };
844 
845 /// The value-type for a single-cell state for a scalar quantity.
846 template <> struct DepthToIndexMappingTypeImpl<VectorDepth<dynamic_extent>> {
847  using type = std::vector<int>;
848 };
849 
850 template <typename T>
851 using DepthToIndexMappingType = typename DepthToIndexMappingTypeImpl<T>::type;
852 } // namespace detail
853 
854 template <typename Equation>
856  boost::mp11::mp_transform<detail::DepthToIndexMappingType,
857  typename Equation::CompleteDepths>;
858 
859 template <typename Equation> struct IndexMapping : IndexMappingBase<Equation> {
860  IndexMapping() = default;
861  IndexMapping(const Equation& equation) {
862  auto depths = Depths(equation, Type<Complete<Equation>>{});
863  int counter = 0;
865  overloaded{
866  [&](int& id, ScalarDepth) { id = counter++; },
867  [&](auto&& ids, auto depth) {
868  if constexpr (std::is_same_v<std::decay_t<decltype(depth)>,
869  int>) {
870  ids.resize(depth);
871  }
872  std::iota(ids.begin(), ids.end(), counter);
873  counter += depth;
874  },
875  },
876  *this, depths);
877  }
878 };
879 
880 template <typename Eq>
881 struct StateTraits<IndexMapping<Eq>> : StateTraits<IndexMappingBase<Eq>> {};
882 
883 template <typename Equation>
885  int comp = 0;
887  [&comp, &buffer](auto&& var) {
888  var = buffer[comp];
889  comp += 1;
890  },
891  state);
892 }
893 
894 template <typename Equation>
896  int comp = 0;
898  [&comp, &buffer](auto&& var) {
899  var = buffer[comp];
900  comp += 1;
901  },
902  state);
903 }
904 
905 template <typename Equation>
907  int comp = 0;
909  [&comp, buffer](auto&& var) {
910  buffer[comp] = var;
911  comp += 1;
912  },
913  state);
914 }
915 
916 } // namespace fub
917 
918 #endif
#define FUB_ASSERT(x)
Definition: assert.hpp:39
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 tag_invoke_fn::tag_invoke_fn tag_invoke
Definition: type_traits.hpp:317
std::decay_t< decltype(std::declval< T >().GetEquation())> Equation
A template typedef to detect the member function.
Definition: Meta.hpp:59
decltype(::fub::Depths(std::declval< typename T::Equation const & >(), Type< T >{})) Depths
Definition: State.hpp:189
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
void CopyToBuffer(span< double > buffer, const Conservative< Equation > &state)
Definition: State.hpp:906
std::conditional_t< N==1||M==1, Eigen::Array< T, N, M >, Eigen::Array< T, N, M, Eigen::RowMajor > > Array
Definition: Eigen.hpp:50
typename remove_cvref< T >::type remove_cvref_t
Definition: type_traits.hpp:226
boost::mp11::mp_transform< detail::DepthToStateValueType, Depths > ScalarStateBase
Definition: State.hpp:194
void ForEachVariable(F function, Ts &&... states)
Definition: State.hpp:89
bool AnyNaN(const Complete< Equation > &state)
Definition: State.hpp:719
typename dynamic_extents_< make_index_sequence< Rank > >::type dynamic_extents
Definition: mdspan.hpp:725
make_integer_sequence< std::size_t, N > make_index_sequence
Definition: type_traits.hpp:173
typename nodeduce< T >::type nodeduce_t
Definition: type_traits.hpp:47
constexpr struct fub::DepthsFn Depths
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
constexpr auto Unzip(const std::tuple< Ts... > &zipped)
Definition: State.hpp:74
Layout::template mapping< dynamic_extents< static_cast< std::size_t >Rank)> > Mapping(const BasicView< State, Layout, Rank > &view)
Definition: State.hpp:494
void CopyFromBuffer(Complete< Equation > &state, span< const double > buffer)
Definition: State.hpp:884
typename detail::ViewPointerBaseImpl< State >::type ViewPointerBase
Definition: State.hpp:748
boost::mp11::mp_transform< detail::DepthToStateValueType, typename Equation::CompleteDepths > CompleteBase
Definition: State.hpp:331
Direction
This is a type safe type to denote a dimensional split direction.
Definition: Direction.hpp:30
ViewPointer(const ViewPointer< State > &) -> ViewPointer< State >
void Advance(ViewPointer< State > &pointer, std::ptrdiff_t n) noexcept
Definition: State.hpp:825
typename ToConcreteDepthImpl< Depth >::type ToConcreteDepth
Definition: State.hpp:119
constexpr auto Zip(Ts &&... ts)
Definition: State.hpp:65
const Conservative< Eq > & AsCons(const Conservative< Eq > &x)
Definition: State.hpp:438
typename detail::ViewBaseImpl< State, Layout, Rank >::type ViewBase
Definition: State.hpp:400
BasicView(const BasicView< S, L, R > &) -> BasicView< S, L, R >
static constexpr std::ptrdiff_t dynamic_extent
This is a magic value to denote runtime-known extents.
Definition: dynamic_extent.hpp:28
boost::mp11::mp_transform< ToConcreteDepth, Depths > ToConcreteDepths
Definition: State.hpp:122
bool Contains(const IndexBox< Rank > &b1, const IndexBox< Rank > &b2)
Definition: PatchDataView.hpp:73
constexpr decltype(auto) get(State &&x)
Definition: State.hpp:82
void Store(const BasicView< Conservative< Eq >, Layout, Eq::Rank()> &view, const Conservative< Eq > &state, const std::array< std::ptrdiff_t, Eq::Rank()> &index)
Definition: State.hpp:663
ViewPointer< State > End(const BasicView< State, Layout, Rank > &view)
Definition: State.hpp:782
dynamic_extents< static_cast< std::size_t >Rank)> Extents(const BasicView< State, Layout, Rank > &view)
Definition: State.hpp:480
boost::mp11::mp_transform< detail::DepthToIndexMappingType, typename Equation::CompleteDepths > IndexMappingBase
Definition: State.hpp:857
void ForEachComponent(F function, Ts &&... states)
Definition: State.hpp:624
auto StateToTuple(const State &x)
Definition: State.hpp:322
auto Slice(const BasicView< T, L, Rank > &view, SliceSpecifier slice)
Definition: State.hpp:688
IndexBox< Rank > Box(const BasicView< State, Layout, Rank > &view)
Definition: State.hpp:486
overloaded(Ts...) -> overloaded< Ts... >
boost::mp11::mp_transform< detail::DepthToStateValueType, typename Equation::ConservativeDepths > ConservativeBase
This type alias transforms state depths into a conservative state associated with a specified equatio...
Definition: State.hpp:247
std::ptrdiff_t index
Definition: type_traits.hpp:179
BasicView< const State, Layout, Rank > AsConst(const BasicView< State, Layout, Rank > &v)
Definition: State.hpp:431
Definition: State.hpp:403
typename State::Equation Equation
Definition: State.hpp:409
typename Equation::ConservativeDepths Depths
Definition: State.hpp:410
S State
Definition: State.hpp:404
BasicView()=default
static constexpr int Rank
Definition: State.hpp:406
BasicView & operator=(const ViewBase< S, L, R > &base)
Definition: State.hpp:418
static constexpr int rank() noexcept
Definition: State.hpp:413
L Layout
Definition: State.hpp:405
BasicView(const ViewBase< S, L, R > &base)
Definition: State.hpp:417
std::conditional_t< std::is_const< S >::value, const double, double > ValueType
Definition: State.hpp:408
Definition: State.hpp:312
This type has a constructor which takes an equation and might allocate any dynamically sized member v...
Definition: State.hpp:335
Eq Equation
Definition: State.hpp:336
Complete(const Equation &eq)
Definition: State.hpp:345
Complete(const CompleteBase< Eq > &x)
Definition: State.hpp:341
Complete & operator+=(const Complete &other)
Definition: State.hpp:362
Complete & operator=(const CompleteBase< Eq > &x)
Definition: State.hpp:342
double ValueType
Definition: State.hpp:337
Complete()=default
This type has a constructor which takes an equation and might allocate any dynamically sized member v...
Definition: State.hpp:251
Conservative()=default
Eq Equation
Definition: State.hpp:252
Conservative & operator+=(const Conservative &other)
Definition: State.hpp:279
Conservative(const Equation &eq)
Definition: State.hpp:262
Conservative(const ConservativeBase< Eq > &x)
Definition: State.hpp:257
double ValueType
Definition: State.hpp:253
Conservative & operator=(const ConservativeBase< Eq > &x)
Definition: State.hpp:258
Definition: State.hpp:166
constexpr auto operator()(const Eq &eq, [[maybe_unused]] Type< State > state) const noexcept(is_nothrow_tag_invocable< DepthsFn, const Eq &, Type< State >>::value||!is_tag_invocable< DepthsFn, const Eq &, Type< State >>::value)
Definition: State.hpp:168
Definition: PatchDataView.hpp:56
Index< Rank > lower
Definition: PatchDataView.hpp:57
Index< Rank > upper
Definition: PatchDataView.hpp:59
Definition: State.hpp:859
IndexMapping(const Equation &equation)
Definition: State.hpp:861
IndexMapping()=default
Definition: State.hpp:473
Definition: State.hpp:301
Definition: State.hpp:106
Definition: PatchDataView.hpp:201
IndexBox< R > Box() const noexcept
Definition: PatchDataView.hpp:232
PatchDataView< T, R, layout_stride > Subview(const IndexBox< R > &box) const
Definition: PatchDataView.hpp:245
Definition: State.hpp:290
This type is used to tag scalar quantities.
Definition: State.hpp:109
Definition: State.hpp:196
ScalarState & operator+=(const Base &other)
Definition: State.hpp:220
ScalarState & operator*=(double lambda)
Definition: State.hpp:232
ScalarState(const Equation &eq)
Definition: State.hpp:203
ScalarStateBase< Depths > Base
Definition: State.hpp:198
ScalarState & operator-=(const Base &other)
Definition: State.hpp:226
Definition: State.hpp:35
Definition: State.hpp:114
Depth type
Definition: State.hpp:114
Definition: State.hpp:162
T type
Definition: State.hpp:163
This type is used to tag quantities with a depth known at compile time.
Definition: State.hpp:112
Definition: State.hpp:750
This is std::true_type if Op<Args...> is a valid SFINAE expression.
Definition: type_traits.hpp:92
Definition: type_traits.hpp:339
Definition: type_traits.hpp:323
Definition: State.hpp:39
Definition: type_traits.hpp:291