FieldMatVec.hpp 10.7 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
    {
      T result = 0;
      for (int i = 0; i < N; ++i)
        result = op(result, x[i]);
      return result;
    }

100
101
102
103
104
105
106
107
108
    template <class T, int N, class Operation>
    T accumulate(FieldMatrix<T, 1, N> const& x, Operation op)
    {
      T result = 0;
      for (int i = 0; i < N; ++i)
        result = op(result, x[0][i]);
      return result;
    }

109
110
111
112
  } // end namespace Impl

  /// Sum of vector entires.
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
113
  T sum(FieldVector<T, N> const& x)
114
  {
115
    return Impl::accumulate(x, Operation::Plus{});
116
117
  }

118
119
120
121
122
123
  template <class T, int N>
  T sum(FieldMatrix<T, 1, N> const& x)
  {
    return Impl::accumulate(x, Operation::Plus{});
  }

124
125
126

  /// Dot-product with the vector itself
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
127
  auto unary_dot(FieldVector<T, N> const& x)
128
  {
129
    auto op = [](auto const& a, auto const& b) { return a + Math::sqr(std::abs(b)); };
130
131
132
    return Impl::accumulate(x, op);
  }

133
134
135
136
137
138
139
  template <class T, int N>
  auto unary_dot(FieldMatrix<T, 1, N> const& x)
  {
    auto op = [](auto const& a, auto const& b) { return a + Math::sqr(std::abs(b)); };
    return Impl::accumulate(x, op);
  }

140
141
  /// Maximum over all vector entries
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
142
  auto max(FieldVector<T, N> const& x)
143
  {
144
    return Impl::accumulate(x, Operation::Max{});
145
146
  }

147
148
149
150
151
152
  template <class T, int N>
  auto max(FieldMatrix<T, 1, N> const& x)
  {
    return Impl::accumulate(x, Operation::Max{});
  }

153
154
  /// Minimum over all vector entries
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
155
  auto min(FieldVector<T, N> const& x)
156
  {
157
    return Impl::accumulate(x, Operation::Min{});
158
159
  }

160
161
162
163
164
165
  template <class T, int N>
  auto min(FieldMatrix<T, 1, N> const& x)
  {
    return Impl::accumulate(x, Operation::Min{});
  }

166
167
  /// Maximum of the absolute values of vector entries
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
168
  auto abs_max(FieldVector<T, N> const& x)
169
  {
170
    return Impl::accumulate(x, Operation::AbsMax{});
171
172
  }

173
174
175
176
177
178
  template <class T, int N>
  auto abs_max(FieldMatrix<T, 1, N> const& x)
  {
    return Impl::accumulate(x, Operation::AbsMax{});
  }

179
180
  /// Minimum of the absolute values of vector entries
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
181
  auto abs_min(FieldVector<T, N> const& x)
182
  {
183
    return Impl::accumulate(x, Operation::AbsMin{});
184
185
  }

186
187
188
189
190
191
  template <class T, int N>
  auto abs_min(FieldMatrix<T, 1, N> const& x)
  {
    return Impl::accumulate(x, Operation::AbsMin{});
  }

192
193
194
195
196
197
  // ----------------------------------------------------------------------------

  /** \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
198
  auto one_norm(FieldVector<T, N> const& x)
199
200
201
202
203
  {
    auto op = [](auto const& a, auto const& b) { return a + std::abs(b); };
    return Impl::accumulate(x, op);
  }

204
205
206
207
208
209
210
  template <class T, int N>
  auto one_norm(FieldMatrix<T, 1, N> const& x)
  {
    auto op = [](auto const& a, auto const& b) { return a + std::abs(b); };
    return Impl::accumulate(x, op);
  }

211
212
213
214
  /** \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
215
  auto two_norm(FieldVector<T, N> const& x)
216
217
218
219
  {
    return std::sqrt(unary_dot(x));
  }

220
221
222
223
224
225
  template <class T, int N>
  auto two_norm(FieldMatrix<T, 1, N> const& x)
  {
    return std::sqrt(unary_dot(x));
  }

226
227
228
229
  /** \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
230
  auto p_norm(FieldVector<T, N> const& x)
231
232
233
234
235
  {
    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 );
  }

236
237
238
239
240
241
242
  template <int p, class T, int N>
  auto p_norm(FieldMatrix<T, 1, N> const& x)
  {
    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 );
  }

243
244
245
246
  /** \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
247
  auto infty_norm(FieldVector<T, N> const& x)
248
249
250
251
  {
    return abs_max(x);
  }

252
253
254
255
256
257
  template <class T, int N>
  auto infty_norm(FieldMatrix<T, 1, N> const& x)
  {
    return abs_max(x);
  }

258
259
260
261
  // ----------------------------------------------------------------------------

  /// The euklidean distance between two vectors = |lhs-rhs|_2
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
262
  T distance(FieldVector<T, N> const& lhs, FieldVector<T, N> const& rhs)
263
264
265
  {
    T result = 0;
    for (int i = 0; i < N; ++i)
266
      result += Math::sqr(lhs[i] - rhs[i]);
267
268
269
270
271
272
273
    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
274
  auto outer(FieldMatrix<T,N,K> const& vec1, FieldMatrix<S,M,K> const& vec2)
275
  {
Praetorius, Simon's avatar
Praetorius, Simon committed
276
    using result_type = FieldMatrix<decltype( std::declval<T>() * std::declval<S>() ), N, M>;
277
278
279
280
281
282
283
284
285
286
    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
287
  T det(FieldMatrix<T, 0, 0> const& /*mat*/)
288
289
290
291
292
293
  {
    return 0;
  }

  /// Determinant of a 1x1 matrix
  template <class T>
Praetorius, Simon's avatar
Praetorius, Simon committed
294
  T det(FieldMatrix<T, 1, 1> const& mat)
295
296
297
298
299
300
  {
    return mat[0][0];
  }

  /// Determinant of a 2x2 matrix
  template <class T>
Praetorius, Simon's avatar
Praetorius, Simon committed
301
  T det(FieldMatrix<T, 2, 2> const& mat)
302
303
304
305
306
307
  {
    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
308
  T det(FieldMatrix<T, 3, 3> const& mat)
309
310
311
312
313
314
315
  {
    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
316
  T det(FieldMatrix<T, N, N> const& mat)
317
318
319
320
321
322
  {
    return mat.determinant();
  }

  /// Return the inverse of the matrix `mat`
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
323
  auto inv(FieldMatrix<T, N, N> mat)
324
325
326
327
328
329
330
  {
    mat.invert();
    return mat;
  }

  /// Solve the linear system A*x = b
  template <class T, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
331
  void solve(FieldMatrix<T, N, N> const& A,  FieldVector<T, N>& x,  FieldVector<T, N> const& b)
332
333
334
335
336
337
338
  {
    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
339
  T gramian(FieldMatrix<T,N,M> const& DF)
340
341
342
343
344
345
346
  {
    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
347
  T gramian(FieldMatrix<T, 1, M> const& DF)
348
349
350
351
352
  {
    using std::sqrt;
    return sqrt(dot(DF[0], DF[0]));
  }

353
  template <class T, int M, int N>
Praetorius, Simon's avatar
Praetorius, Simon committed
354
  FieldMatrix<T,N,M> trans(FieldMatrix<T, M, N> const& A)
355
  {
Praetorius, Simon's avatar
Praetorius, Simon committed
356
    FieldMatrix<T,N,M> At;
357
358
359
360
361
362
363
364
365
    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
366
  FieldMatrix<T,M,N> multiplies(FieldMatrix<T, M, L> const& A,  FieldMatrix<T, L, N> const& B)
367
368
369
370
371
372
373
  {
    return A.rightmultiplyany(B);
  }



  template <class T, int M, int N, int L>
Praetorius, Simon's avatar
Praetorius, Simon committed
374
  FieldMatrix<T,M,N> multiplies_AtB(FieldMatrix<T, L, M> const& A,  FieldMatrix<T, N, L> const& B)
375
  {
Praetorius, Simon's avatar
Praetorius, Simon committed
376
    FieldMatrix<T,M,N> C;
377
378
379
380
381
382
383
384
385
386
387
388

    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
389
  FieldMatrix<T,M,N> multiplies_ABt(FieldMatrix<T, M, L> const& A,  FieldMatrix<T, N, L> const& B)
390
  {
Praetorius, Simon's avatar
Praetorius, Simon committed
391
    FieldMatrix<T,M,N> C;
392
393
394
395
396
397
398
399
400
401
402
403

    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
404
  FieldMatrix<T,M,N>& multiplies_ABt(FieldMatrix<T, M, L> const& A,  FieldMatrix<T, N, L> const& B, FieldMatrix<T,M,N>& C)
405
406
407
408
409
410
411
412
413
414
415
  {
    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;
  }

416
  template <class T, int M, int N>
417
  FieldMatrix<T,M,N>& multiplies_ABt(FieldMatrix<T, M, N> const& A,  Dune::DiagonalMatrix<T, N> const& B, FieldMatrix<T,M,N>& C)
418
419
420
421
422
423
424
425
426
  {
    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;
  }

427
} // end namespace AMDiS