Finite Volume Solver  prototype
A framework to build finite volume solvers for the AG Klein at the Freie Universität Berlin.
Eigen.hpp
Go to the documentation of this file.
1 // Copyright (c) 2018 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_CORE_EIGEN_HPP
22 #define FUB_CORE_EIGEN_HPP
23 
24 #include <Eigen/Eigen>
25 
26 #include "fub/Direction.hpp"
27 #include "fub/PatchDataView.hpp"
28 #include "fub/config.hpp"
29 
30 #include <type_traits>
31 
32 #include <boost/mp11/function.hpp>
33 
34 namespace fub {
35 
36 #ifdef FUB_DEFAULT_CHUNK_SIZE
37 constexpr const int kDefaultChunkSize = FUB_DEFAULT_CHUNK_SIZE;
38 #else
39 constexpr const int kDefaultChunkSize = 8;
40 #endif
41 
42 template <std::size_t N>
43 Eigen::Matrix<double, static_cast<int>(N), 1>
44 AsEigenVector(const std::array<double, N>& x) {
45  return Eigen::Matrix<double, static_cast<int>(N), 1>::Map(x.data());
46 }
47 
48 template <typename T, int N, int M = kDefaultChunkSize>
49 using Array = std::conditional_t<N == 1 || M == 1, Eigen::Array<T, N, M>,
50  Eigen::Array<T, N, M, Eigen::RowMajor>>;
51 // using Array = Eigen::Array<T, N, M, Eigen::ColMajor>;
52 
54 // using Scalar = Array1d;
58 
60 
61 inline void LoadN(Array<char, 1>& array, const char* pointer, int n) {
62  for (int i = 0; i < n; ++i) {
63  array[i] = pointer[i];
64  }
65 }
66 
67 inline void StoreN(char* pointer, const Array<char, 1>& array, int n) {
68  for (int i = 0; i < n; ++i) {
69  pointer[i] = array[i];
70  }
71 }
72 
73 template <int N, typename T, int Rank, typename Layout, typename... Indices>
74 std::enable_if_t<boost::mp11::mp_all<std::is_integral<Indices>...>::value,
75  Eigen::Array<std::remove_cv_t<T>, N, 1>>
77  std::ptrdiff_t i0, Indices... indices) {
78  FUB_ASSERT(0 < size && size < N);
79  Eigen::Array<std::remove_cv_t<T>, N, 1> array;
80  for (int i = 0; i < size; ++i) {
81  array[i] = pdv(i0 + i, indices...);
82  }
83  return array;
84 }
85 
86 template <int Rank>
87 Eigen::Matrix<double, Rank, 1> Shift(const Eigen::Matrix<double, Rank, 1>& v,
88  Direction dir, double shift) {
89  Eigen::Matrix<double, Rank, 1> shifted(v);
90  shifted[static_cast<int>(dir)] += shift;
91  return shifted;
92 }
93 
94 template <int Rank>
95 Eigen::Matrix<double, Rank, 1> UnitVector(Direction dir) noexcept {
96  Eigen::Matrix<double, Rank, 1> unit = Eigen::Matrix<double, Rank, 1>::Zero();
97  Eigen::Index dir_v = static_cast<Eigen::Index>(dir);
98  unit[dir_v] = 1.0;
99  return unit;
100 }
101 
102 inline Eigen::Matrix<double, 2, 2>
103 MakeRotation(const Eigen::Matrix<double, 2, 1>& a,
104  const Eigen::Matrix<double, 2, 1>& b) {
105  if (a == -b) {
106  return -Eigen::Matrix<double, 2, 2>::Identity();
107  }
108  const double s = a[0] * b[1] - a[1] * b[0];
109  const double c = a.dot(b);
110  Eigen::Matrix<double, 2, 2> rotation;
111  rotation << c, -s, s, c;
112  return rotation;
113 }
114 
115 inline Eigen::Matrix<double, 3, 3>
116 MakeRotation(const Eigen::Matrix<double, 3, 1>& a,
117  const Eigen::Matrix<double, 3, 1>& b) {
118  if (a == -b) {
119  return -Eigen::Matrix<double, 3, 3>::Identity();
120  }
121  const Eigen::Matrix<double, 3, 1> v = a.cross(b);
122  const double c = a.dot(b);
123  Eigen::Matrix<double, 3, 3> skew;
124  skew << 0, -v[2], +v[1], +v[2], 0, -v[0], -v[1], +v[0], 0;
125  Eigen::Matrix<double, 3, 3> I = Eigen::Matrix<double, 3, 3>::Identity();
126  Eigen::Matrix<double, 3, 3> rotation = I + skew + skew * skew / (1 + c);
127  return rotation;
128 }
129 
130 template <int N, typename T, int Rank, typename Layout, typename... Indices>
131 Eigen::Array<std::remove_cv_t<T>, N, 1>
133  nodeduce_t<const std::array<std::ptrdiff_t, std::size_t(Rank)>&> index) {
134  FUB_ASSERT(0 < size && size < N);
135  Eigen::Array<std::remove_cv_t<T>, N, 1> array{};
136  for (int i = 0; i < size; ++i) {
137  array[i] = pdv(Shift(index, Direction::X, i));
138  }
139  return array;
140 }
141 
142 template <int N, typename T, int Rank, typename Layout, typename... Indices>
143 Eigen::Array<std::remove_cv_t<T>, N, 1>
145  Indices... indices) {
146  if (pdv.MdSpan().stride(0) == 1) {
147  return Eigen::Map<const Eigen::Array<std::remove_cv_t<T>, N, 1>>(
148  &pdv(indices...), n);
149  } else {
150  using Stride = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
151  return Eigen::Map<const Eigen::Array<std::remove_cv_t<T>, N, 1>,
152  Eigen::Unaligned, Stride>(
153  &pdv(indices...), n, 1, Stride(1, pdv.MdSpan().stride(0)));
154  }
155 }
156 
157 template <typename T, int Rank, typename Layout, typename... Indices>
158 auto Load(const PatchDataView<T, Rank, Layout>& pdv, Indices... indices) {
159  return Load(int_c<kDefaultChunkSize>, pdv, indices...);
160 }
161 
162 template <typename T, typename A, int N, bool B, typename Layout>
163 void StoreN(const PatchDataView<T, 1, Layout>& pdv, int n,
164  const Eigen::Block<A, 1, N, B>& chunk, std::ptrdiff_t offset) {
165  for (int i = 0; i < n; ++i) {
166  pdv(offset + i) = chunk[i];
167  }
168 }
169 
170 template <typename T, int Rank, typename Layout, int N, int Options,
171  typename... Indices>
172 void Store(
173  const PatchDataView<T, Rank, Layout>& view,
174  const Eigen::Array<T, 1, N, Options>& chunk,
175  const nodeduce_t<
176  std::array<std::ptrdiff_t, static_cast<std::size_t>(Rank)>>& index) {
177  FUB_ASSERT(view.Extent(0) >= N);
178  if (view.MdSpan().stride(0) == 1) {
179  Eigen::Map<Eigen::Array<T, N, 1>> mapped(&view(index), N);
180  mapped = chunk;
181  } else {
182  using Stride = Eigen::Stride<1, Eigen::Dynamic>;
183  Eigen::Map<Eigen::Array<T, N, 1>, Eigen::Unaligned, Stride> mapped(
184  &view(index), N, Stride(1, view.stride(0)));
185  mapped = chunk;
186  }
187  return;
188 }
189 
190 template <typename T, typename Base, int Rank, typename Layout, int N,
191  bool Options, typename... Indices>
192 void Store(
193  const PatchDataView<T, Rank, Layout>& view,
194  const Eigen::Block<Base, 1, N, Options>& chunk,
195  const nodeduce_t<
196  std::array<std::ptrdiff_t, static_cast<std::size_t>(Rank)>>& index) {
197  FUB_ASSERT(view.Extent(0) >= N);
198  if (view.MdSpan().stride(0) == 1) {
199  Eigen::Map<Eigen::Array<T, N, 1>> mapped(&view(index), N);
200  mapped = chunk;
201  } else {
202  using Stride = Eigen::Stride<1, Eigen::Dynamic>;
203  Eigen::Map<Eigen::Array<T, N, 1>, Eigen::Unaligned, Stride> mapped(
204  &view(index), N, Stride(1, view.MdSpan().stride(0)));
205  mapped = chunk;
206  }
207  return;
208 }
209 
210 template <typename T, int Rank, typename L>
211 void Store(
213  const nodeduce_t<
214  std::array<std::ptrdiff_t, static_cast<std::size_t>(Rank)>>& index) {
215  view(index) = value;
216 }
217 
218 } // namespace fub
219 
220 #endif
#define FUB_ASSERT(x)
Definition: assert.hpp:39
The fub namespace.
Definition: AnyBoundaryCondition.hpp:31
Array< double, 3 > Array3d
Definition: Eigen.hpp:56
std::conditional_t< N==1||M==1, Eigen::Array< T, N, M >, Eigen::Array< T, N, M, Eigen::RowMajor > > Array
Definition: Eigen.hpp:50
Array< double, Eigen::Dynamic > ArrayXd
Definition: Eigen.hpp:57
Array< double, 1 > Array1d
Definition: Eigen.hpp:53
constexpr const int kDefaultChunkSize
Definition: Eigen.hpp:39
Array< double, 2 > Array2d
Definition: Eigen.hpp:55
void StoreN(nodeduce_t< ViewPointer< Conservative< Eq >>> pointer, const ConservativeArray< Eq > &state, int n)
Definition: StateArray.hpp:416
typename nodeduce< T >::type nodeduce_t
Definition: type_traits.hpp:47
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
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
Eigen::Matrix< double, static_cast< int >N), 1 > AsEigenVector(const std::array< double, N > &x)
Definition: Eigen.hpp:44
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
Eigen::Matrix< double, Rank, 1 > UnitVector(Direction dir) noexcept
Definition: Eigen.hpp:95
Eigen::Matrix< double, 2, 2 > MakeRotation(const Eigen::Matrix< double, 2, 1 > &a, const Eigen::Matrix< double, 2, 1 > &b)
Definition: Eigen.hpp:103
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
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
Array< bool, 1 > MaskArray
Definition: Eigen.hpp:59
std::integral_constant< int, I > int_constant
Definition: type_traits.hpp:183
std::ptrdiff_t index
Definition: type_traits.hpp:179
Definition: PatchDataView.hpp:201
const mdspan< T, sRank, Layout > & MdSpan() const noexcept
Definition: PatchDataView.hpp:206
std::ptrdiff_t Extent(std::size_t n) const
Definition: PatchDataView.hpp:230