compute Eigenvalues and -vectors in 1-3d without LAPACK
When dealing with small matrices calling LAPACK to calculate Eigenvalues and Eigenvectors can be quite slow. 1d- and 2d-specializations are quite straightforward, for the 3d-specialization I´m using the approach presented in https://www.geometrictools.com/Documentation/RobustEigenSymmetric3x3.pdf.
Merge request reports
Activity
added feature label
@christi The main work should be done here, however, there are still two design choices to be made: I implemented the new Eigenvector functions with the signature
eigenValuesVectors(const FieldMatrix<K, dim, dim>& matrix, FieldVector<K, dim>& eigenValues, FieldVector<FieldVector<K, dim>, dim>& eigenVectors)
while the existing Lapack-binding has the signature
eigenValuesVectorsLapack(const FieldMatrix<K, dim, dim>& matrix, FieldVector<K, dim>& eigenValues, FieldMatrix<K, dim, dim>& eigenVectors, const char& jobz)
First, I propose to adopt the
jobz
-tag (which controls whether to only calculate eigenvalues or eigenvalues and eigenvectors) and get rid of theeigenValues
-function. Second, I feel thatFieldVector<FieldVector<K, dim>, dim>
is the more natural type for a set of eigenvectors, so I´d like to change the return type in the Lapack-binding. Both of those changes would most likely lead to subsequent changes in dependend code. How do you feel about this?Second, I feel that
FieldVector<FieldVector<K, dim>, dim>
is the more natural type for a set of eigenvectors, so I´d like to change the return type in the Lapack-binding. Both of those changes would most likely lead to subsequent changes in dependend code. How do you feel about this?I'd stick to the current interface. It is not uncommon that you want to use the eigenvector basis to map an operator or a vector. In this case
FieldMatrix
is the right type. If you want to access individual eigenevectors, you can still do so in the current interface, asFieldMatrix::operator[]
returns aFieldVector
.added 1 commit
- c35c18f4 - resolve signature difference with lapack-binding
Just a small side note: Please don't use
FieldVector<FieldVector<...>>
at all. SinceFieldVector<...>
is intended to contain entries from a field we dropped all occurrences long ago. If this should represent a linear operator or tensor, useFieldMatrix<...>
, it it's just a statically sized collection of vectors then usestd::array<FieldVector<...>>
.added 2 commits
There are currently two issues with this MR:
-
if constexpr
only works for newer compilers, so you have to switch to the updated.gitlab-ci.yml
(easiest is to rebase on current master) - you removed the
eigenValues
functions. We still need them for backwards compatibility and can think about deprecating them...
-
mentioned in merge request !724 (closed)
added 23 commits
-
08fda1d6...cd4c780f - 15 commits from branch
master
- b3b21f87 - [test] test multiplicity of 3x3 EV calculation
- c7786333 - add 1d and 2d functionality
- 5a3526e1 - add 3d specialization
- a8f44b95 - change interface, minor bugfixes
- 91d8d961 - update tests
- ebb8e965 - resolve signature difference with lapack-binding
- 6dd1a09a - [temp] reenable tests for dim>3
- 9a4fb1f1 - restructure interface and update tests
Toggle commit list-
08fda1d6...cd4c780f - 15 commits from branch
added 2 commits
Thats probably the easiest solution. I was also thinking about keeping
eigenValues
and somehow makingComputationJob::EigenvaluesEigenvectors
the "default-tag" foreigenValuesVectors
- passing a tag calledEigenvaluesEigenvectors
to a functioneigenValuesVectors
(which is expected to compute exactly that) is also kind of counterintuitive...added 1 commit
- d4d36dc5 - simplify interface: hide ComputationTag internally
38 38 const long int* ldvl, double* vr, const long int* ldvr, double* work, 39 39 const long int* lwork, long int* info); 40 40 41 namespace Impl { 42 enum Jobs { OnlyEigenvalues, EigenvaluesEigenvectors }; 43 constexpr std::array<char,2> LapackTags = {'n', 'v'}; 362 } 363 } 324 364 } 365 //The preconditioning scaled the matrix, which scales the eigenvalues. Revert the scaling. 366 eigenValues *= maxAbsElement; 325 367 } 326 } 327 368 369 // forwarding to LAPACK with corresponding tag 370 template <Jobs Tag, int dim, typename K> 371 static void eigenValuesVectorsLapackImpl(const FieldMatrix<K, dim, dim>& matrix, 372 FieldVector<K, dim>& eigenValues, 373 FieldMatrix<K, dim, dim>& eigenVectors) 374 { 375 { 376 const char jobz = LapackTags[Tag]; mentioned in merge request !727 (closed)