KASKADE 7 development version
linalg/determinant.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* see http://www.zib.de/en/numerik/software/kaskade-7.html */
5/* */
6/* Copyright (C) 2015-2015 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13#ifndef DETERMINANT_HH
14#define DETERMINANT_HH
15
16namespace Kaskade
17{
21 namespace DeterminantDetail
22 {
23 template <int dim, class Scalar>
24 double determinantD1(Dune::FieldMatrix<Scalar,dim,dim> const& A, Dune::FieldMatrix<Scalar,dim,dim> const& dA)
25 {
26 if (dim==1)
27 return A[0][0];
28
29 if (dim==2)
30 return A[0][0]*dA[1][1] + dA[0][0]*A[1][1] - A[0][1]*dA[1][0] - dA[0][1]*A[1][0];
31
32 if (dim==3)
33 {
34 double ret = 0;
35
36 // This is the rule of Sarrus, coded here for easy derivation of the derivative code.
37 // for (int i=0; i<3; ++i)
38 // ret += A[0][i]*A[1][(i+1)%3]*A[2][(i+2)%3] - A[2][i]*A[1][(i+1)%3]*A[0][(i+2)%3];
39
40 for (int i=0; i<3; ++i)
41 ret += A[0][i]*A[1][(i+1)%3]*dA[2][(i+2)%3] + A[0][i]*dA[1][(i+1)%3]*A[2][(i+2)%3] + dA[0][i]*A[1][(i+1)%3]*A[2][(i+2)%3]
42 - A[2][i]*A[1][(i+1)%3]*dA[0][(i+2)%3] - A[2][i]*dA[1][(i+1)%3]*A[0][(i+2)%3] - dA[2][i]*A[1][(i+1)%3]*A[0][(i+2)%3];
43
44 return ret;
45 }
46 }
47
48 template <int dim, class Scalar>
50 {
51 if (dim==1)
52 return 0;
53
54 if (dim==2)
55 return dA2[0][0]*dA1[1][1] + dA1[0][0]*dA2[1][1] - dA2[0][1]*dA1[1][0] - dA1[0][1]*dA2[1][0];
56
57 if (dim==3)
58 {
59 double ret = 0;
60 for (int i=0; i<3; ++i)
61 ret += A[0][i]*dA2[1][(i+1)%3]*dA1[2][(i+2)%3] + A[0][i]*dA1[1][(i+1)%3]*dA2[2][(i+2)%3] + dA1[0][i]*A[1][(i+1)%3]*dA2[2][(i+2)%3]
62 + dA2[0][i]*A[1][(i+1)%3]*dA1[2][(i+2)%3] + dA2[0][i]*dA1[1][(i+1)%3]*A[2][(i+2)%3] + dA1[0][i]*dA2[1][(i+1)%3]*A[2][(i+2)%3]
63 - A[2][i]*dA2[1][(i+1)%3]*dA1[0][(i+2)%3] - A[2][i]*dA1[1][(i+1)%3]*dA2[0][(i+2)%3] - dA1[2][i]*A[1][(i+1)%3]*dA2[0][(i+2)%3]
64 - dA2[2][i]*A[1][(i+1)%3]*dA1[0][(i+2)%3] - dA2[2][i]*dA1[1][(i+1)%3]*A[0][(i+2)%3] - dA1[2][i]*dA2[1][(i+1)%3]*A[0][(i+2)%3];
65 // TODO: does it pay off to factorize out common terms?
66 return ret;
67 }
68 }
69
70 template <int dim, class Scalar>
71 double determinantD3(Dune::FieldMatrix<Scalar,dim,dim> const& A, Dune::FieldMatrix<Scalar,dim,dim> const& dA1,
73 {
74 if (dim<=2)
75 return 0;
76
77 if (dim==3)
78 {
79 double ret = 0;
80 for (int i=0; i<3; ++i)
81 ret += dA3[0][i]*dA2[1][(i+1)%3]*dA1[2][(i+2)%3] + dA3[0][i]*dA1[1][(i+1)%3]*dA2[2][(i+2)%3] + dA1[0][i]*dA3[1][(i+1)%3]*dA2[2][(i+2)%3]
82 + dA2[0][i]*dA3[1][(i+1)%3]*dA1[2][(i+2)%3] + dA2[0][i]*dA1[1][(i+1)%3]*dA3[2][(i+2)%3] + dA1[0][i]*dA2[1][(i+1)%3]*dA3[2][(i+2)%3]
83 - dA3[2][i]*dA2[1][(i+1)%3]*dA1[0][(i+2)%3] - dA3[2][i]*dA1[1][(i+1)%3]*dA2[0][(i+2)%3] - dA1[2][i]*dA3[1][(i+1)%3]*dA2[0][(i+2)%3]
84 - dA2[2][i]*dA3[1][(i+1)%3]*dA1[0][(i+2)%3] - dA2[2][i]*dA1[1][(i+1)%3]*dA3[0][(i+2)%3] - dA1[2][i]*dA2[1][(i+1)%3]*dA3[0][(i+2)%3];
85
86 return ret;
87 }
88 }
89 }
100 template <int dim, class Scalar=double, bool byValue=true>
102 {
103 static_assert(0<dim && dim<=3,"determinant implemented only for dimensions 1-3");
104
105 public:
107
108 explicit Determinant(Matrix const& A_) : A(A_) {}
109
110 Determinant(Determinant const&) = default;
112
113 double d0() const
114 {
115 return A.determinant();
116 }
117
118 double d1(Matrix const& dA) const
119 {
120 return DeterminantDetail::determinantD1(A,dA);
121 }
122
123 double d2(Matrix const& dA1, Matrix const& dA2) const
124 {
125 return DeterminantDetail::determinantD2(A,dA1,dA2);
126 }
127
128 double d3(Matrix const& dA1, Matrix const& dA2, Matrix const& dA3) const
129 {
130 return DeterminantDetail::determinantD3(A,dA1,dA2,dA3);
131 }
132
133 private:
134 std::conditional_t<byValue,Matrix,Matrix const&> A;
135 };
136
137}
138
139#endif // DETERMINANT_HH
A class for computing determinants and their derivatives.
Determinant(Determinant const &)=default
double d1(Matrix const &dA) const
double d3(Matrix const &dA1, Matrix const &dA2, Matrix const &dA3) const
Determinant & operator=(Determinant const &)=default
double d2(Matrix const &dA1, Matrix const &dA2) const
Determinant(Matrix const &A_)