DNDSR 0.1.0.dev1+gcd065ad
Distributed Numeric Data Structure for CFV
Loading...
Searching...
No Matches
HardEigen.cpp
Go to the documentation of this file.
1/// @file HardEigen.cpp
2/// @brief Implementations of the numerically-careful Eigen primitives
3/// declared in @ref HardEigen.hpp (pseudoinverses, symmetric eigen decompositions,
4/// condition-number helpers).
5
6#include "HardEigen.hpp"
7#include <iostream>
8
10{
11 /// @todo test these eigen solvers !!
12 // #define EIGEN_USE_LAPACKE
13 real EigenLeastSquareInverse(const Eigen::MatrixXd &A, Eigen::MatrixXd &AI, real svdTol)
14 {
15 // static const double sVmin = 1e-12;
16 // auto SVDResult = A.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV);
17 auto SVDResult = A.jacobiSvd<Eigen::ComputeThinU | Eigen::ComputeThinV>();
18 if (svdTol > 0)
19 SVDResult.setThreshold(svdTol);
20 AI = SVDResult.solve(Eigen::MatrixXd::Identity(A.rows(), A.rows()));
21 Eigen::VectorXd svs = SVDResult.singularValues().array().abs();
22 return svs.maxCoeff() / (svs.minCoeff() + verySmallReal);
23 }
24
25 real EigenLeastSquareInverse_Filtered(const Eigen::MatrixXd &A, Eigen::MatrixXd &AI, real svdTol, int mode)
26 {
27 double sVmin = svdTol == 0 ? Eigen::NumTraits<real>::epsilon() : svdTol;
28 double sVminInv = 1. / (sVmin + verySmallReal);
29 auto SVDResult = A.jacobiSvd<Eigen::ComputeThinU | Eigen::ComputeThinV>();
30 // auto SVDResult = A.jacobiSvd(Eigen::ComputeFullU | Eigen::ComputeFullV);
31
32 // AI = SVDResult.solve(Eigen::MatrixXd::Identity(A.rows(), A.rows()));
33 auto sVs = SVDResult.singularValues();
34 if (mode == 0)
35 {
36 real sVsMax = SVDResult.singularValues().array().abs().maxCoeff();
37 for (auto &i : sVs)
38 if (std::fabs(i) > sVmin * sVsMax) //! note this filtering!
39 i = 1. / i;
40 else
41 i = 0.;
42 }
43 else if (mode == 1)
44 {
45 real sVsMin = SVDResult.singularValues().array().abs().minCoeff();
46 for (auto &i : sVs)
47 if (std::fabs(i) < sVsMin * sVminInv) //! note this filtering!
48 i = 1. / i;
49 else
50 i = 0.;
51 }
52 AI = SVDResult.matrixV() * sVs.asDiagonal() * SVDResult.matrixU().transpose();
53 Eigen::VectorXd svs = SVDResult.singularValues().array().abs();
54 DNDS_assert_info(AI.allFinite() && !AI.hasNaN(), [&]() -> std::string
55 {
56 log() << sVmin << " " << sVminInv << std::endl;
57 log() << sVs.transpose() << std::endl;
58 log() << svs.transpose() << std::endl;
59 log() << "A \n"
60 << std::scientific << std::setprecision(16) << A << std::endl;
61 log() << "AI \n"
62 << std::scientific << std::setprecision(16) << AI << std::endl;
63 log() << "V \n"
64 << std::scientific << std::setprecision(16) << SVDResult.matrixV() << std::endl;
65 log() << "U \n"
66 << std::scientific << std::setprecision(16) << SVDResult.matrixU() << std::endl;
67 return "EigenLeastSquareInverse_Filtered Error info"; }());
68 return svs.maxCoeff() / (svs.minCoeff() + verySmallReal);
69 // std::cout << AI * A << std::endl;
70 }
71
72 Eigen::Matrix3d Eigen3x3RealSymEigenDecomposition(const Eigen::Matrix3d &A)
73 {
74 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> solver;
75 solver.computeDirect(A);
76 // if (!(solver.eigenvalues()(1) <= solver.eigenvalues()(2)))
77 // {
78 // std::cout << solver.eigenvalues() << std::endl;
79 // std::exit(-1);
80 // }
81 Eigen::Matrix3d ret = (solver.eigenvectors() * solver.eigenvalues().array().abs().sqrt().matrix().asDiagonal())(EigenAll, {2, 1, 0});
82 // ret(EigenAll, 0) *= signP(ret(0, 0));
83 // ret(EigenAll, 1) *= signP(ret(1, 1));
84 // ret(EigenAll, 2) *= ret.determinant();
85 return ret;
86 }
87
88 Eigen::Matrix2d Eigen2x2RealSymEigenDecomposition(const Eigen::Matrix2d &A)
89 {
90 Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> solver;
91 solver.computeDirect(A);
92 // if (!(solver.eigenvalues()(1) <= solver.eigenvalues()(2)))
93 // {
94 // std::cout << solver.eigenvalues() << std::endl;
95 // std::exit(-1);
96 // }
97 Eigen::Matrix2d ret = (solver.eigenvectors() * solver.eigenvalues().array().abs().sqrt().matrix().asDiagonal())(EigenAll, {1, 0});
98 // ret(EigenAll, 0) *= signP(ret(0, 0));
99 // ret(EigenAll, 1) *= signP(ret(1, 1));
100 // ret(EigenAll, 2) *= ret.determinant();
101 return ret;
102 }
103
105 {
106 Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> solver;
107 solver.computeDirect(A);
108 Eigen::Vector2d ev = solver.eigenvalues().array().abs();
109 return ev.maxCoeff() / (ev.minCoeff() + verySmallReal);
110 }
111
113 {
114 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> solver;
115 solver.computeDirect(A);
116 Eigen::Vector3d ev = solver.eigenvalues().array().abs();
117 return ev.maxCoeff() / (ev.minCoeff() + verySmallReal);
118 }
119
121 {
122 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> solver;
123 solver.computeDirect(A);
124 Eigen::Vector3d ev = solver.eigenvalues().array().abs();
125 std::sort(ev.begin(), ev.end());
126 return ev(2) / (ev(1) + verySmallReal);
127 }
128
129 Eigen::Matrix3d Eigen3x3RealSymEigenDecompositionNormalized(const Eigen::Matrix3d &A)
130 {
131 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> solver;
132 solver.computeDirect(A);
133 // if (!(solver.eigenvalues()(1) <= solver.eigenvalues()(2)))
134 // {
135 // std::cout << solver.eigenvalues() << std::endl;
136 // std::exit(-1);
137 // }
138 Eigen::Matrix3d ret = (solver.eigenvectors())(EigenAll, {2, 1, 0});
139 // ret(EigenAll, 0) *= signP(ret(0, 0));
140 // ret(EigenAll, 1) *= signP(ret(1, 1));
141 // ret(EigenAll, 2) *= ret.determinant();
142 return ret;
143 }
144
145 Eigen::Matrix2d Eigen2x2RealSymEigenDecompositionNormalized(const Eigen::Matrix2d &A)
146 {
147 Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> solver;
148 solver.computeDirect(A);
149 // if (!(solver.eigenvalues()(0) <= solver.eigenvalues()(1)))
150 // {
151 // std::cout << solver.eigenvalues() << std::endl;
152 // std::exit(-1);
153 // }
154 Eigen::Matrix2d ret = (solver.eigenvectors())(EigenAll, {1, 0});
155 // ret(EigenAll, 0) *= signP(ret(0, 0));
156 // ret(EigenAll, 1) *= ret.determinant();
157 return ret;
158 }
159
160 Eigen::Index EigenLeastSquareSolve(const Eigen::MatrixXd &A, const Eigen::MatrixXd &B, Eigen::MatrixXd &AIB)
161 {
162 auto SVDResult = A.jacobiSvd<Eigen::ComputeThinU | Eigen::ComputeThinV>();
163 AIB = SVDResult.solve(B);
164 return SVDResult.rank();
165 }
166
167}
#define DNDS_assert_info(expr, info)
Debug-only assertion with an extra std::string info message.
Definition Errors.hpp:113
Robust linear-algebra primitives for small / moderately-sized Eigen matrices that are more numericall...
Eigen::Index EigenLeastSquareSolve(const Eigen::MatrixXd &A, const Eigen::MatrixXd &B, Eigen::MatrixXd &AIB)
Least-squares solve A * AIB ~= B via a rank-revealing QR-style decomposition; returns the computed ra...
real EigenLeastSquareInverse_Filtered(const Eigen::MatrixXd &A, Eigen::MatrixXd &AI, real svdTol, int mode)
Pseudoinverse with a choice of singular-value filter.
Definition HardEigen.cpp:25
real Eigen3x3RealSymEigenDecompositionGetCond01(const Eigen::Matrix3d &A)
Like Eigen3x3RealSymEigenDecompositionGetCond but returns lambda0 / lambda1 only (ignores the smalles...
Eigen::Matrix3d Eigen3x3RealSymEigenDecompositionNormalized(const Eigen::Matrix3d &A)
Eigen-decomposition with eigenvector columns normalised to unit length.
Eigen::Matrix2d Eigen2x2RealSymEigenDecompositionNormalized(const Eigen::Matrix2d &A)
2x2 analogue of Eigen3x3RealSymEigenDecompositionNormalized.
Eigen::Matrix3d Eigen3x3RealSymEigenDecomposition(const Eigen::Matrix3d &A)
Analytic eigen-decomposition of a 3x3 real symmetric matrix. Returns the eigenvector matrix (columns ...
Definition HardEigen.cpp:72
Eigen::Matrix2d Eigen2x2RealSymEigenDecomposition(const Eigen::Matrix2d &A)
Analytic 2x2 analogue of Eigen3x3RealSymEigenDecomposition.
Definition HardEigen.cpp:88
real Eigen3x3RealSymEigenDecompositionGetCond(const Eigen::Matrix3d &A)
Condition number of a 3x3 SPD matrix from its eigenvalues.
real EigenLeastSquareInverse(const Eigen::MatrixXd &A, Eigen::MatrixXd &AI, real svdTol)
Moore-Penrose pseudoinverse via SVD, dropping singular values below svdTol (relative to the largest)....
Definition HardEigen.cpp:13
real Eigen2x2RealSymEigenDecompositionGetCond(const Eigen::Matrix2d &A)
2x2 analogue of Eigen3x3RealSymEigenDecompositionGetCond.
DNDS_CONSTANT const real verySmallReal
Catch-all lower bound ("effectively zero").
Definition Defines.hpp:194
double real
Canonical floating-point scalar used throughout DNDSR (double precision).
Definition Defines.hpp:105