updated all code in LAMMPS to use the open-source "math_eigen.h" instead of "math_extra.h". Code in "lib" now uses its own abbreviated local version of the "math_eigen.h" file (which is named "jacobi_pd.h"), since it is not clear how code from "lib/" can access the code in "src/"

This commit is contained in:
Andrew Jewett
2020-09-05 01:39:27 -07:00
parent 7f6fc8a003
commit 57f82abae3
20 changed files with 1299 additions and 768 deletions

140
src/math_eigen.cpp Normal file
View File

@ -0,0 +1,140 @@
#include "math_eigen.h"
#include<array>
using std::vector;
using std::array;
using namespace MathEigen;
// --- Instantiate template class instances ---
// --- to reduce bloat in the compiled binary ---
// When using one of these versions of Jacobi, you can reduce code bloat by
// using an "extern template class" declaration in your cpp file. For example:
//
// #include"math_eigen.h"
// extern template class MathEigen::Jacobi<double, double*, double**, double const*const*>;
//
// ...This should (hopefully) use the version of Jacobi defined in this file
// instead of compiling a new version.
// template instantiations of Jacobi for pointer->pointer arrays
template class MathEigen::Jacobi<double, double*, double**, double const*const*>;
// template instantiations of Jacbi for fixed-size (3x3) arrays
template class MathEigen::Jacobi<double, double*, double (*)[3], double const (*)[3]>;
// template instantiations of Jacobi for vector-of-vectors:
template class MathEigen::Jacobi<double,
vector<double>&,
vector<vector<double> >&,
const vector<vector<double> >& >;
// template instantiations of Jacobi for array-of-arrays:
template class MathEigen::Jacobi<double,
array<double, 3>&,
array<array<double, 3>, 3 >&,
const array<array<double, 3>, 3 >& >;
// template instantiations of LambdaLanczos
template class MathEigen::LambdaLanczos<double>;
// template instantiations of PEidenDense for pointer->pointer arrays
template class MathEigen::PEigenDense<double, double*, double const*const*>;
// template instantiations of PEidenDense for vector<vector<>>
template class MathEigen::PEigenDense<double,
vector<double>&,
const vector<vector<double> >&>;
// ----------------- now create instances for floats ----------------
template class MathEigen::Jacobi<float, float*, float**, float const*const*>;
template class MathEigen::Jacobi<float, float*, float (*)[3], float const (*)[3]>;
template class MathEigen::Jacobi<float,
vector<float>&,
vector<vector<float> >&,
const vector<vector<float> >& >;
template class MathEigen::Jacobi<float,
array<float, 3>&,
array<array<float, 3>, 3 >&,
const array<array<float, 3>, 3 >& >;
template class MathEigen::LambdaLanczos<float>;
template class MathEigen::PEigenDense<float, float*, float const*const*>;
template class MathEigen::PEigenDense<float,
vector<float>&,
const vector<vector<float> >&>;
// If you plan to use other numeric types, add them below...
// Special case: 3x3 matrices
int MathEigen::
jacobi3(double const mat[3][3], // the 3x3 matrix you wish to diagonalize
double *eval, // store the eigenvalues here
double evec[3][3], // store the eigenvectors here...
bool evec_as_columns, // ...as rows or columns?
Jacobi<double,double*,double(*)[3],double const(*)[3]>::SortCriteria
sort_criteria)
{
// Create "ecalc3", an instance of the MathEigen::Jacobi class to calculate
// the eigenvalues oand eigenvectors of matrix "mat". It requires memory
// to be allocated to store a copy of the matrix. To avoid allocating
// this memory on the heap, we create a fixed size 3x3 array on the stack
// (and convert it to type double**).
double mat_cpy[3][3] = { {mat[0][0], mat[0][1], mat[0][2]},
{mat[1][0], mat[1][1], mat[1][2]},
{mat[2][0], mat[2][1], mat[2][2]} };
double *M[3] = { &(mat_cpy[0][0]), &(mat_cpy[1][0]), &(mat_cpy[2][0]) };
// variable "ecalc3" does all the work:
Jacobi<double,double*,double(*)[3],double const(*)[3]> ecalc3(3,M);
int ierror = ecalc3.Diagonalize(mat, eval, evec, sort_criteria);
// This will store the eigenvectors in the rows of "evec".
// Do we want to return the eigenvectors in columns instead of rows?
if (evec_as_columns)
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
std::swap(evec[i][j], evec[j][i]);
return ierror;
}
int MathEigen::
jacobi3(double const **mat, // the 3x3 matrix you wish to diagonalize
double *eval, // store the eigenvalues here
double **evec, // store the eigenvectors here...
bool evec_as_columns, // ...as rows or columns?
Jacobi<double,double*,double**,double const*const*>::SortCriteria
sort_criteria)
{
// Create "ecalc3", an instance of the MathEigen::Jacobi class to calculate
// the eigenvalues oand eigenvectors of matrix "mat". It requires memory
// to be allocated to store a copy of the matrix. To avoid allocating
// this memory on the heap, we create a fixed size 3x3 array on the stack
// (and convert it to type double**).
double mat_cpy[3][3] = { {mat[0][0], mat[0][1], mat[0][2]},
{mat[1][0], mat[1][1], mat[1][2]},
{mat[2][0], mat[2][1], mat[2][2]} };
double *M[3] = { &(mat_cpy[0][0]), &(mat_cpy[1][0]), &(mat_cpy[2][0]) };
// variable "ecalc3" does all the work:
Jacobi<double,double*,double**,double const*const*> ecalc3(3,M);
int ierror = ecalc3.Diagonalize(mat, eval, evec, sort_criteria);
// This will store the eigenvectors in the rows of "evec".
// Do we want to return the eigenvectors in columns instead of rows?
if (evec_as_columns)
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
std::swap(evec[i][j], evec[j][i]);
return ierror;
}