ESyS-Particle  2.3.4
EigenvalueCalculator.h
Go to the documentation of this file.
1 // //
3 // Copyright (c) 2003-2017 by The University of Queensland //
4 // Centre for Geoscience Computing //
5 // http://earth.uq.edu.au/centre-geoscience-computing //
6 // //
7 // Primary Business: Brisbane, Queensland, Australia //
8 // Licensed under the Open Software License version 3.0 //
9 // http://www.apache.org/licenses/LICENSE-2.0 //
10 // //
12 
13 
14 #ifndef ESYS_LSMEIGENVALUECALCULATOR_H
15 #define ESYS_LSMEIGENVALUECALCULATOR_H
16 
17 #include "Foundation/Matrix3.h"
18 
19 #include <iostream>
20 #include <complex>
21 #include <vector>
22 #include <algorithm>
23 
24 namespace esys
25 {
26  namespace lsm
27  {
29  {
30  public:
31  typedef std::complex<double> Complex;
32  typedef std::vector<Complex> ComplexVector;
33 
34  static const double ONE_THIRD;
35  static const double SQRT_THREE;
36 
37  inline double cbrt(double a)
38  {
39  // cube root is antisymmetric
40  return (a < 0) ? -std::pow(-a, ONE_THIRD) : std::pow(a, ONE_THIRD);
41  }
42 
43  bool hasComplexEigenvalues(const Matrix3 &a) const
44  {
45  double b = -(a(0, 0) + a(1, 1) + a(2, 2));
46 
47  double a00a11 = a(0, 0) * a(1, 1);
48  double a11a22 = a(1, 1) * a(2, 2);
49  double a00a22 = a(0, 0) * a(2, 2);
50  double a10a01 = a(1, 0) * a(0, 1);
51  double a12a21 = a(1, 2) * a(2, 1);
52  double a20a02 = a(2, 0) * a(0, 2);
53  double c = a00a11 + a11a22 + a00a22 - a10a01 - a12a21 - a20a02;
54 
55  double a10a01a22 = a10a01 * a(2, 2);
56  double a12a21a00 = a12a21 * a(0, 0);
57  double a20a02a11 = a20a02 * a(1, 1);
58  double a00a11a22 = a00a11 * a(2, 2);
59  double a01a12a20 = a(0, 1) * a( 1, 2) * a( 2, 0);
60  double a02a10a21 = a(0, 2) * a( 1, 0) * a( 2, 1);
61  double d = a10a01a22 + a12a21a00 + a20a02a11
62  - a00a11a22 - a01a12a20 - a02a10a21;
63 
64  double bb = b * b;
65  double Q = (3.0 * c - bb) / 9.0;
66  double R = (9.0 * b * c - 27.0 * d - 2.0 * bb * b) / 54.0;
67 
68  return (Q * Q * Q > -(R * R));
69  }
70 
72  {
73  public:
74  bool operator()(const Complex &c1, const Complex &c2) const
75  {
76  return
77  (
78  (c1.real() < c2.real())
79  ||
80  (
81  (c1.real() == c2.real())
82  &&
83  (c1.imag() < c2.imag())
84  )
85  );
86  }
87  };
88 
90  {
91  public:
92  bool operator()(const Complex &c1, const Complex &c2) const
93  {
94  return
95  (
96  (fabs(c1.real()) < fabs(c2.real()))
97  ||
98  (
99  (fabs(c1.real()) == fabs(c2.real()))
100  &&
101  (fabs(c1.imag()) < fabs(c2.imag()))
102  )
103  );
104  }
105  };
106 
108  {
109  public:
110  bool operator()(const Complex &c1, const Complex &c2) const
111  {
112  return (std::norm(c1) < std::norm(c2));
113  }
114  };
115 
117  {
118  ComplexVector e(3, Complex(0.0, 0.0));
119  double b = -(a(0, 0) + a(1, 1) + a(2, 2));
120 
121  double a00a11 = a(0, 0) * a(1, 1);
122  double a11a22 = a(1, 1) * a(2, 2);
123  double a00a22 = a(0, 0) * a(2, 2);
124  double a10a01 = a(1, 0) * a(0, 1);
125  double a12a21 = a(1, 2) * a(2, 1);
126  double a20a02 = a(2, 0) * a(0, 2);
127  double c = a00a11 + a11a22 + a00a22 - a10a01 - a12a21 - a20a02;
128 
129  double a10a01a22 = a10a01 * a(2, 2);
130  double a12a21a00 = a12a21 * a(0, 0);
131  double a20a02a11 = a20a02 * a(1, 1);
132  double a00a11a22 = a00a11 * a(2, 2);
133  double a01a12a20 = a(0, 1) * a(1, 2) * a(2, 0);
134  double a02a10a21 = a(0, 2) * a(1, 0) * a(2, 1);
135  double d = a10a01a22 + a12a21a00 + a20a02a11
136  - a00a11a22 - a01a12a20 - a02a10a21;
137 
138  double bb = b * b;
139  double Q = (3.0 * c - bb) / 9.0;
140  double R = (9.0 * b * c - 27.0 * d - 2.0 * bb * b) / 54.0;
141  double D = Q * Q * Q + R * R;
142 
143  double nOTb = -ONE_THIRD * b;
144 
145  if (D > 0) {
146  // one real and two Complex conjugate
147  double sqrtD = sqrt(D);
148  double S = cbrt(R + sqrtD);
149  double T = cbrt(R - sqrtD);
150  double SpT = S + T;
151  e[0] = nOTb + SpT;
152 
153  double x = nOTb - 0.5 * SpT;
154  double y = 0.5 * SQRT_THREE * (S - T);
155  e[1] = Complex(x, y);
156  e[2] = Complex(x, -y);
157  }
158  else if (D < 0) {
159  // all real and unequal
160  double sqrtD = sqrt(-D);
161  Complex S = std::pow(Complex(R, sqrtD), ONE_THIRD); // T == S.conj()
162  e[0] = nOTb + 2.0 * S.real();
163 
164  double x = nOTb - S.real();
165  double y = SQRT_THREE * S.imag();
166  e[1] = x - y;
167  e[2] = x + y;
168  }
169  else {
170  // all real and at least two equal
171  double S = cbrt(R); // T == S
172  e[0] = nOTb + 2.0 * S;
173  e[1] = nOTb - S;
174  e[2] = e[1];
175  }
176  std::sort(e.begin(), e.end(), ComplexRealImagComparer());
177  return e;
178  }
179 
180  void printEigenvalues(const Matrix3 &a)
181  {
182  std::cout << "a: " << a(0, 0) << " " << a(0, 1) << " " << a(0, 2) << std::endl
183  << " " << a(1, 0) << " " << a(1, 1) << " " << a(1, 2) << std::endl
184  << " " << a(2, 0) << " " << a(2, 1) << " " << a(2, 2) << std::endl;
185 
186  if (hasComplexEigenvalues(a))
187  std::cout << "Complex eigenvalues" << std::endl;
188  else
189  std::cout << "Real eigenvalues" << std::endl;
190 
192  std::cout << "e0: " << e[0] << std::endl;
193  std::cout << "e1: " << e[1] << std::endl;
194  std::cout << "e2: " << e[2] << std::endl;
195  std::cout << std::endl;
196  }
197  };
198  }
199 }
200 
201 inline std::ostream &operator<<(std::ostream &oStream, const esys::lsm::EigenvalueCalculator::ComplexVector &vec)
202 {
203  esys::lsm::EigenvalueCalculator::ComplexVector::const_iterator it = vec.begin();
204  if (it != vec.end()) {
205  oStream << (*it);
206  it++;
207  }
208  for (; it != vec.end(); it++)
209  {
210  oStream << " " << (*it);
211  }
212  return oStream;
213 }
214 
215 #endif
esys::lsm::EigenvalueCalculator::hasComplexEigenvalues
bool hasComplexEigenvalues(const Matrix3 &a) const
Definition: EigenvalueCalculator.h:43
esys::lsm::EigenvalueCalculator::printEigenvalues
void printEigenvalues(const Matrix3 &a)
Definition: EigenvalueCalculator.h:180
esys::lsm::EigenvalueCalculator::getEigenvalues
ComplexVector getEigenvalues(const Matrix3 &a)
Definition: EigenvalueCalculator.h:116
esys::lsm::EigenvalueCalculator::ComplexRealImagComparer
Definition: EigenvalueCalculator.h:72
esys::lsm::EigenvalueCalculator
Definition: EigenvalueCalculator.h:29
Matrix3.h
esys::lsm::EigenvalueCalculator::ONE_THIRD
static const double ONE_THIRD
Definition: EigenvalueCalculator.h:34
esys::lsm::EigenvalueCalculator::ComplexAbsRealImagComparer::operator()
bool operator()(const Complex &c1, const Complex &c2) const
Definition: EigenvalueCalculator.h:92
esys::lsm::EigenvalueCalculator::SQRT_THREE
static const double SQRT_THREE
Definition: EigenvalueCalculator.h:35
esys
Definition: CheckPointable.cpp:17
esys::lsm::EigenvalueCalculator::ComplexRealImagComparer::operator()
bool operator()(const Complex &c1, const Complex &c2) const
Definition: EigenvalueCalculator.h:74
operator<<
std::ostream & operator<<(std::ostream &oStream, const esys::lsm::EigenvalueCalculator::ComplexVector &vec)
Definition: EigenvalueCalculator.h:201
esys::lsm::EigenvalueCalculator::ComplexNormComparer::operator()
bool operator()(const Complex &c1, const Complex &c2) const
Definition: EigenvalueCalculator.h:110
esys::lsm::EigenvalueCalculator::ComplexAbsRealImagComparer
Definition: EigenvalueCalculator.h:90
esys::lsm::EigenvalueCalculator::ComplexNormComparer
Definition: EigenvalueCalculator.h:108
Matrix3
3x3 Matrix
Definition: Matrix3.h:48
esys::lsm::EigenvalueCalculator::ComplexVector
std::vector< Complex > ComplexVector
Definition: EigenvalueCalculator.h:32
esys::lsm::EigenvalueCalculator::cbrt
double cbrt(double a)
Definition: EigenvalueCalculator.h:37
EigenvalueCalculator.h
esys::lsm::EigenvalueCalculator::Complex
std::complex< double > Complex
Definition: EigenvalueCalculator.h:31