FieldMatVec.hpp 8.98 KB
Newer Older
1
2
#pragma once

3
4
#include <algorithm>

5
6
7
#include <dune/common/fmatrix.hh>
#include <dune/common/fvector.hh>

8
#include <dune/amdis/common/Math.hpp>
9
10
#include <dune/amdis/common/Concepts.hpp>
#include <dune/amdis/common/ScalarTypes.hpp>
11
12
#include <dune/amdis/operations/Arithmetic.hpp>
#include <dune/amdis/operations/MaxMin.hpp>
13
14
15

namespace AMDiS
{
Praetorius, Simon's avatar
Praetorius, Simon committed
16
17
18
19
  using Dune::FieldVector;
  using Dune::FieldMatrix;

  // some arithmetic operations with FieldVector
20
21
22

  template <class T, int N, class S,
    REQUIRES(Concepts::Arithmetic<S>) >
Praetorius, Simon's avatar
Praetorius, Simon committed
23
  FieldVector<T,N> operator*(FieldVector<T,N> v, S factor)
24
25
26
27
28
29
  {
    return v *= factor;
  }

  template <class S, class T, int N,
    REQUIRES(Concepts::Arithmetic<S>) >
Praetorius, Simon's avatar
Praetorius, Simon committed
30
  FieldVector<T,N> operator*(S factor, FieldVector<T,N> v)
31
32
33
34
35
36
  {
    return v *= factor;
  }

  template <class T, int N, class S,
    REQUIRES(Concepts::Arithmetic<S>) >
Praetorius, Simon's avatar
Praetorius, Simon committed
37
  FieldVector<T,N> operator/(FieldVector<T,N> v, S factor)
38
39
40
41
  {
    return v /= factor;
  }

Praetorius, Simon's avatar
Praetorius, Simon committed
42
  // some arithmetic operations with FieldMatrix
43
44

  template <class T, int N, int M>
Praetorius, Simon's avatar
Praetorius, Simon committed
45
  FieldMatrix<T,N,M> operator+(FieldMatrix<T,N,M> A, FieldMatrix<T,N,M> const& B)
46
47
48
49
50
  {
    return A += B;
  }

  template <class T, int N, int M>
Praetorius, Simon's avatar
Praetorius, Simon committed
51
  FieldMatrix<T,N,M> operator-(FieldMatrix<T,N,M> A, FieldMatrix<T,N,M> const& B)
52
53
54
55
  {
    return A -= B;
  }

56
  template <class T, int N, int M>
Praetorius, Simon's avatar
Praetorius, Simon committed
57
  FieldVector<T,N> operator*(FieldMatrix<T,N,M> const& mat, FieldVector<T,M> const& vec)
58
59
60
61
  {
    return Dune::FMatrixHelp::mult(mat, vec);
  }

62
63
64
65
  // ----------------------------------------------------------------------------

  /// Cross-product a 2d-vector = orthogonal vector
  template <class T>
Praetorius, Simon's avatar
Praetorius, Simon committed
66
  FieldVector<T, 2> cross(FieldVector<T, 2> const& a)
67
68
69
70
71
72
  {
    return {{ a[1], -a[0] }};
  }

  /// Cross-product of two vectors (in 3d only)
  template <class T>
Praetorius, Simon's avatar
Praetorius, Simon committed
73
  FieldVector<T, 3> cross(FieldVector<T, 3> const& a, FieldVector<T, 3> const& b)
74
75
76
77
78
79
80
81
  {
    return {{ a[1]*b[2] - a[2]*b[1],
              a[2]*b[0] - a[0]*b[2],
              a[0]*b[1] - a[1]*b[0] }};
  }

  /// Dot product (vec1^T * vec2)
  template <class T, class S, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
82
  auto dot(FieldVector<T,N> const& vec1, FieldVector<S,N> const& vec2)
83
84
85
86
87
88
89
90
91
  {
    return vec1.dot(vec2);
  }

  // ----------------------------------------------------------------------------

  namespace Impl
  {
    template <class T, int N, class Operation>
Praetorius, Simon's avatar
Praetorius, Simon committed
92
    T accumulate(FieldVector<T, N> const& x, Operation op)
93
94
95
96
97
98
99
100
101
102
103
    {
      T result = 0;
      for (int i = 0; i < N; ++i)
        result = op(result, x[i]);
      return result;
    }

  } // end namespace Impl

  /// Sum of vector entires.
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
104
  T sum(FieldVector<T, N> const& x)
105
  {
106
    return Impl::accumulate(x, Operation::Plus{});
107
108
109
110
111
  }


  /// Dot-product with the vector itself
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
112
  auto unary_dot(FieldVector<T, N> const& x)
113
  {
114
    auto op = [](auto const& a, auto const& b) { return a + Math::sqr(std::abs(b)); };
115
116
117
118
119
    return Impl::accumulate(x, op);
  }

  /// Maximum over all vector entries
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
120
  auto max(FieldVector<T, N> const& x)
121
  {
122
    return Impl::accumulate(x, Operation::Max{});
123
124
125
126
  }

  /// Minimum over all vector entries
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
127
  auto min(FieldVector<T, N> const& x)
128
  {
129
    return Impl::accumulate(x, Operation::Min{});
130
131
132
133
  }

  /// Maximum of the absolute values of vector entries
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
134
  auto abs_max(FieldVector<T, N> const& x)
135
  {
136
    return Impl::accumulate(x, Operation::AbsMax{});
137
138
139
140
  }

  /// Minimum of the absolute values of vector entries
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
141
  auto abs_min(FieldVector<T, N> const& x)
142
  {
143
    return Impl::accumulate(x, Operation::AbsMin{});
144
145
146
147
148
149
150
151
  }

  // ----------------------------------------------------------------------------

  /** \ingroup vector_norms
   *  \brief The 1-norm of a vector = sum_i |x_i|
   **/
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
152
  auto one_norm(FieldVector<T, N> const& x)
153
154
155
156
157
158
159
160
161
  {
    auto op = [](auto const& a, auto const& b) { return a + std::abs(b); };
    return Impl::accumulate(x, op);
  }

  /** \ingroup vector_norms
   *  \brief The euklidean 2-norm of a vector = sqrt( sum_i |x_i|^2 )
   **/
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
162
  auto two_norm(FieldVector<T, N> const& x)
163
164
165
166
167
168
169
170
  {
    return std::sqrt(unary_dot(x));
  }

  /** \ingroup vector_norms
   *  \brief The p-norm of a vector = ( sum_i |x_i|^p )^(1/p)
   **/
  template <int p, class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
171
  auto p_norm(FieldVector<T, N> const& x)
172
173
174
175
176
177
178
179
180
  {
    auto op = [](auto const& a, auto const& b) { return a + Math::pow<p>(std::abs(b)); };
    return std::pow( Impl::accumulate(x, op), 1.0/p );
  }

  /** \ingroup vector_norms
   *  \brief The infty-norm of a vector = max_i |x_i| = alias for \ref abs_max
   **/
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
181
  auto infty_norm(FieldVector<T, N> const& x)
182
183
184
185
186
187
188
189
  {
    return abs_max(x);
  }

  // ----------------------------------------------------------------------------

  /// The euklidean distance between two vectors = |lhs-rhs|_2
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
190
  T distance(FieldVector<T, N> const& lhs, FieldVector<T, N> const& rhs)
191
192
193
  {
    T result = 0;
    for (int i = 0; i < N; ++i)
194
      result += Math::sqr(lhs[i] - rhs[i]);
195
196
197
198
199
200
201
    return std::sqrt(result);
  }

  // ----------------------------------------------------------------------------

  /// Outer product (vec1 * vec2^T)
  template <class T, class S, int N, int M, int K>
Praetorius, Simon's avatar
Praetorius, Simon committed
202
  auto outer(FieldMatrix<T,N,K> const& vec1, FieldMatrix<S,M,K> const& vec2)
203
  {
Praetorius, Simon's avatar
Praetorius, Simon committed
204
    using result_type = FieldMatrix<decltype( std::declval<T>() * std::declval<S>() ), N, M>;
205
206
207
208
209
210
211
212
213
214
    result_type mat;
    for (int i = 0; i < N; ++i)
      for (int j = 0; j < M; ++j)
        mat[i][j] = vec1[i].dot(vec2[j]);
    return mat;
  }

  // ----------------------------------------------------------------------------

  template <class T>
Praetorius, Simon's avatar
Praetorius, Simon committed
215
  T det(FieldMatrix<T, 0, 0> const& /*mat*/)
216
217
218
219
220
221
  {
    return 0;
  }

  /// Determinant of a 1x1 matrix
  template <class T>
Praetorius, Simon's avatar
Praetorius, Simon committed
222
  T det(FieldMatrix<T, 1, 1> const& mat)
223
224
225
226
227
228
  {
    return mat[0][0];
  }

  /// Determinant of a 2x2 matrix
  template <class T>
Praetorius, Simon's avatar
Praetorius, Simon committed
229
  T det(FieldMatrix<T, 2, 2> const& mat)
230
231
232
233
234
235
  {
    return mat[0][0]*mat[1][1] - mat[0][1]*mat[1][0];
  }

  /// Determinant of a 3x3 matrix
  template <class T>
Praetorius, Simon's avatar
Praetorius, Simon committed
236
  T det(FieldMatrix<T, 3, 3> const& mat)
237
238
239
240
241
242
243
  {
    return mat[0][0]*mat[1][1]*mat[2][2] + mat[0][1]*mat[1][2]*mat[2][0] + mat[0][2]*mat[1][0]*mat[2][1]
        - (mat[0][2]*mat[1][1]*mat[2][0] + mat[0][1]*mat[1][0]*mat[2][2] + mat[0][0]*mat[1][2]*mat[2][1]);
  }

  /// Determinant of a NxN matrix
  template <class T,  int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
244
  T det(FieldMatrix<T, N, N> const& mat)
245
246
247
248
249
250
  {
    return mat.determinant();
  }

  /// Return the inverse of the matrix `mat`
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
251
  auto inv(FieldMatrix<T, N, N> mat)
252
253
254
255
256
257
258
  {
    mat.invert();
    return mat;
  }

  /// Solve the linear system A*x = b
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
259
  void solve(FieldMatrix<T, N, N> const& A,  FieldVector<T, N>& x,  FieldVector<T, N> const& b)
260
261
262
263
264
265
266
  {
    A.solve(x, b);
  }


  /// Gramian determinant = sqrt( det( DT^T * DF ) )
  template <class T, int N, int M>
Praetorius, Simon's avatar
Praetorius, Simon committed
267
  T gramian(FieldMatrix<T,N,M> const& DF)
268
269
270
271
272
273
274
  {
    using std::sqrt;
    return sqrt( det(outer(DF, DF)) );
  }

  /// Gramian determinant, specialization for 1 column matrices
  template <class T, int M>
Praetorius, Simon's avatar
Praetorius, Simon committed
275
  T gramian(FieldMatrix<T, 1, M> const& DF)
276
277
278
279
280
  {
    using std::sqrt;
    return sqrt(dot(DF[0], DF[0]));
  }

281
  template <class T, int M, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
282
  FieldMatrix<T,N,M> trans(FieldMatrix<T, M, N> const& A)
283
  {
Praetorius, Simon's avatar
Praetorius, Simon committed
284
    FieldMatrix<T,N,M> At;
285
286
287
288
289
290
291
292
293
    for (int i = 0; i < M; ++i)
      for (int j = 0; j < N; ++j)
        At[j][i] = A[i][j];

    return At;
  }


  template <class T, int M, int N, int L>
Praetorius, Simon's avatar
Praetorius, Simon committed
294
  FieldMatrix<T,M,N> multiplies(FieldMatrix<T, M, L> const& A,  FieldMatrix<T, L, N> const& B)
295
296
297
298
299
300
301
  {
    return A.rightmultiplyany(B);
  }



  template <class T, int M, int N, int L>
Praetorius, Simon's avatar
Praetorius, Simon committed
302
  FieldMatrix<T,M,N> multiplies_AtB(FieldMatrix<T, L, M> const& A,  FieldMatrix<T, N, L> const& B)
303
  {
Praetorius, Simon's avatar
Praetorius, Simon committed
304
    FieldMatrix<T,M,N> C;
305
306
307
308
309
310
311
312
313
314
315
316

    for (int m = 0; m < M; ++m) {
      for (int n = 0; n < N; ++n) {
        C[m][n] = 0;
        for (int l = 0; l < L; ++l)
          C[m][n] += A[l][m] * B[n][l];
      }
    }
    return C;
  }

  template <class T, int M, int N, int L>
Praetorius, Simon's avatar
Praetorius, Simon committed
317
  FieldMatrix<T,M,N> multiplies_ABt(FieldMatrix<T, M, L> const& A,  FieldMatrix<T, N, L> const& B)
318
  {
Praetorius, Simon's avatar
Praetorius, Simon committed
319
    FieldMatrix<T,M,N> C;
320
321
322
323
324
325
326
327
328
329
330
331

    for (int m = 0; m < M; ++m) {
      for (int n = 0; n < N; ++n) {
        C[m][n] = 0;
        for (int l = 0; l < L; ++l)
          C[m][n] += A[m][l] * B[n][l];
      }
    }
    return C;
  }

  template <class T, int M, int N, int L>
Praetorius, Simon's avatar
Praetorius, Simon committed
332
  FieldMatrix<T,M,N>& multiplies_ABt(FieldMatrix<T, M, L> const& A,  FieldMatrix<T, N, L> const& B, FieldMatrix<T,M,N>& C)
333
334
335
336
337
338
339
340
341
342
343
  {
    for (int m = 0; m < M; ++m) {
      for (int n = 0; n < N; ++n) {
        C[m][n] = 0;
        for (int l = 0; l < L; ++l)
          C[m][n] += A[m][l] * B[n][l];
      }
    }
    return C;
  }

344
345
346
347
348
349
350
351
352
353
354
  template <class T, int M, int N>
  Dune::FieldMatrix<T,M,N>& multiplies_ABt(Dune::FieldMatrix<T, M, N> const& A,  Dune::DiagonalMatrix<T, N> const& B, Dune::FieldMatrix<T,M,N>& C)
  {
    for (int m = 0; m < M; ++m) {
      for (int n = 0; n < N; ++n) {
        C[m][n] = A[m][n] * B.diagonal(n);
      }
    }
    return C;
  }

355
} // end namespace AMDiS