From 7f6fc8a003d2031de30d03835a5432e71d00f661 Mon Sep 17 00:00:00 2001 From: Andrew Jewett Date: Fri, 4 Sep 2020 04:10:47 -0700 Subject: [PATCH 01/28] updated math_eigen.h and moved it into the main "src" directory --- src/{USER-REACTION => }/math_eigen.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{USER-REACTION => }/math_eigen.h (100%) diff --git a/src/USER-REACTION/math_eigen.h b/src/math_eigen.h similarity index 100% rename from src/USER-REACTION/math_eigen.h rename to src/math_eigen.h From 57f82abae3d3504d3136ba19fc48a1ae4636e22a Mon Sep 17 00:00:00 2001 From: Andrew Jewett Date: Sat, 5 Sep 2020 01:39:27 -0700 Subject: [PATCH 02/28] 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/" --- lib/colvars/colvartypes.cpp | 197 +--- lib/colvars/colvartypes.h | 14 +- lib/jacobi_pd.h | 623 ++++++++++++ src/BODY/body_nparticle.cpp | 3 +- src/BODY/body_rounded_polygon.cpp | 3 +- src/BODY/body_rounded_polyhedron.cpp | 3 +- src/POEMS/fix_poems.cpp | 86 +- src/POEMS/fix_poems.h | 2 - src/RIGID/fix_rigid.cpp | 3 +- src/RIGID/fix_rigid_small.cpp | 3 +- src/USER-MISC/compute_gyration_shape.cpp | 3 +- .../compute_gyration_shape_chunk.cpp | 3 +- src/atom_vec_tri.cpp | 3 +- src/compute_omega_chunk.cpp | 5 +- src/group.cpp | 5 +- src/math_eigen.cpp | 140 +++ src/math_eigen.h | 883 ++++++++++-------- src/math_extra.cpp | 84 -- src/math_extra.h | 1 - src/molecule.cpp | 3 +- 20 files changed, 1299 insertions(+), 768 deletions(-) create mode 100644 lib/jacobi_pd.h create mode 100644 src/math_eigen.cpp diff --git a/lib/colvars/colvartypes.cpp b/lib/colvars/colvartypes.cpp index da00183323..460eec06ac 100644 --- a/lib/colvars/colvartypes.cpp +++ b/lib/colvars/colvartypes.cpp @@ -10,6 +10,7 @@ #include #include +#include "jacobi_pd.h" #include "colvarmodule.h" #include "colvartypes.h" #include "colvarparse.h" @@ -19,20 +20,6 @@ bool colvarmodule::rotation::monitor_crossings = false; cvm::real colvarmodule::rotation::crossing_threshold = 1.0E-02; -namespace { - -/// Numerical recipes diagonalization -static int jacobi(cvm::real **a, cvm::real *d, cvm::real **v, int *nrot); - -/// Eigenvector sort -static int eigsrt(cvm::real *d, cvm::real **v); - -/// Transpose the matrix -static int transpose(cvm::real **v); - -} - - std::string cvm::rvector::to_simple_string() const { std::ostringstream os; @@ -291,43 +278,6 @@ void colvarmodule::rotation::compute_overlap_matrix() } -void colvarmodule::rotation::diagonalize_matrix( - cvm::matrix2d &m, - cvm::vector1d &eigval, - cvm::matrix2d &eigvec) -{ - eigval.resize(4); - eigval.reset(); - eigvec.resize(4, 4); - eigvec.reset(); - - // diagonalize - int jac_nrot = 0; - if (jacobi(m.c_array(), eigval.c_array(), eigvec.c_array(), &jac_nrot) != - COLVARS_OK) { - cvm::error("Too many iterations in routine jacobi.\n" - "This is usually the result of an ill-defined set of atoms for " - "rotational alignment (RMSD, rotateReference, etc).\n"); - } - eigsrt(eigval.c_array(), eigvec.c_array()); - // jacobi saves eigenvectors by columns - transpose(eigvec.c_array()); - - // normalize eigenvectors - for (size_t ie = 0; ie < 4; ie++) { - cvm::real norm2 = 0.0; - size_t i; - for (i = 0; i < 4; i++) { - norm2 += eigvec[ie][i] * eigvec[ie][i]; - } - cvm::real const norm = cvm::sqrt(norm2); - for (i = 0; i < 4; i++) { - eigvec[ie][i] /= norm; - } - } -} - - // Calculate the rotation, plus its derivatives void colvarmodule::rotation::calc_optimal_rotation( @@ -349,7 +299,13 @@ void colvarmodule::rotation::calc_optimal_rotation( cvm::log("S = "+cvm::to_str(S_backup, cvm::cv_width, cvm::cv_prec)+"\n"); } - diagonalize_matrix(S, S_eigval, S_eigvec); + int ierror = ecalc.Diagonalize(S, S_eigval, S_eigvec); + if (ierror) { + cvm::error("Too many iterations in routine jacobi.\n" + "This is usually the result of an ill-defined set of atoms for " + "rotational alignment (RMSD, rotateReference, etc).\n"); + } + // eigenvalues and eigenvectors cvm::real const L0 = S_eigval[0]; cvm::real const L1 = S_eigval[1]; @@ -521,7 +477,7 @@ void colvarmodule::rotation::calc_optimal_rotation( // cvm::log("S_new = "+cvm::to_str(cvm::to_str (S_new), cvm::cv_width, cvm::cv_prec)+"\n"); - diagonalize_matrix(S_new, S_new_eigval, S_new_eigvec); + ecalc.Diagonalize(S_new, S_new_eigval, S_new_eigvec); cvm::real const &L0_new = S_new_eigval[0]; cvm::quaternion const Q0_new(S_new_eigvec[0]); @@ -544,138 +500,3 @@ void colvarmodule::rotation::calc_optimal_rotation( -// Numerical Recipes routine for diagonalization - -#define ROTATE(a,i,j,k,l) g=a[i][j]; \ - h=a[k][l]; \ - a[i][j]=g-s*(h+g*tau); \ - a[k][l]=h+s*(g-h*tau); - -#define n 4 - - -namespace { - -int jacobi(cvm::real **a, cvm::real *d, cvm::real **v, int *nrot) -{ - int j,iq,ip,i; - cvm::real tresh,theta,tau,t,sm,s,h,g,c; - - cvm::vector1d b(n); - cvm::vector1d z(n); - - for (ip=0;ip 4 && (cvm::real)(cvm::fabs(d[ip])+g) == (cvm::real)cvm::fabs(d[ip]) - && (cvm::real)(cvm::fabs(d[iq])+g) == (cvm::real)cvm::fabs(d[iq])) - a[ip][iq]=0.0; - else if (cvm::fabs(a[ip][iq]) > tresh) { - h=d[iq]-d[ip]; - if ((cvm::real)(cvm::fabs(h)+g) == (cvm::real)cvm::fabs(h)) - t=(a[ip][iq])/h; - else { - theta=0.5*h/(a[ip][iq]); - t=1.0/(cvm::fabs(theta)+cvm::sqrt(1.0+theta*theta)); - if (theta < 0.0) t = -t; - } - c=1.0/cvm::sqrt(1+t*t); - s=t*c; - tau=s/(1.0+c); - h=t*a[ip][iq]; - z[ip] -= h; - z[iq] += h; - d[ip] -= h; - d[iq] += h; - a[ip][iq]=0.0; - for (j=0;j<=ip-1;j++) { - ROTATE(a,j,ip,j,iq) - } - for (j=ip+1;j<=iq-1;j++) { - ROTATE(a,ip,j,j,iq) - } - for (j=iq+1;j= p) p=d[k=j]; - if (k != i) { - d[k]=d[i]; - d[i]=p; - for (j=0;j +#include "jacobi_pd.h" #include "colvarmodule.h" #ifndef PI @@ -1390,19 +1391,20 @@ public: /// Default constructor inline rotation() - : b_debug_gradients(false) + : b_debug_gradients(false), ecalc(4) {} /// Constructor after a quaternion inline rotation(cvm::quaternion const &qi) : q(qi), - b_debug_gradients(false) + b_debug_gradients(false), + ecalc(4) { } /// Constructor after an axis of rotation and an angle (in radians) inline rotation(cvm::real angle, cvm::rvector const &axis) - : b_debug_gradients(false) + : b_debug_gradients(false), ecalc(4) { cvm::rvector const axis_n = axis.unit(); cvm::real const sina = cvm::sin(angle/2.0); @@ -1538,9 +1540,9 @@ protected: void compute_overlap_matrix(); /// Diagonalize a given matrix m (used by calc_optimal_rotation()) - static void diagonalize_matrix(cvm::matrix2d &m, - cvm::vector1d &eigval, - cvm::matrix2d &eigvec); + MathEigen::Jacobi &, + cvm::matrix2d &> ecalc; }; diff --git a/lib/jacobi_pd.h b/lib/jacobi_pd.h new file mode 100644 index 0000000000..ca68e6ba3a --- /dev/null +++ b/lib/jacobi_pd.h @@ -0,0 +1,623 @@ +/// @file jacobi_pd.h +/// @brief Calculate the eigenvalues and eigevectors of a symmetric matrix +/// using the Jacobi eigenvalue algorithm. +/// @author Andrew Jewett +/// @note Benchmarks and tests: https://github.com/jewettaij/jacobi_pd +/// @note A version of this code is included with LAMMPS ("math_eigen.h"). +/// @license CC0-1.0 (public domain) + +#ifndef _MATH_EIGEN_H +#define _MATH_EIGEN_H + +#include +#include +//#include + + +namespace MathEigen { + +/// @brief Allocate a 2-dimensional array. (Uses row-major order.) +/// @note (Matrix allocation functions can also be found in colvartypes.h) +template +void Alloc2D(size_t nrows, //!< size of the array (number of rows) + size_t ncols, //!< size of the array (number of columns) + Entry ***paaX //!< pointer to a 2D C-style array + ); + +/// @brief Deallocate arrays that were created using Alloc2D(). +/// @note (Matrix allocation functions can also be found in colvartypes.h) +template +void Dealloc2D(Entry ***paaX //!< pointer to a 2D C-style array + ); + + +// ---- Eigendecomposition of small dense symmetric matrices ---- + +/// @class Jacobi +/// @brief Calculate the eigenvalues and eigevectors of a symmetric matrix +/// using the Jacobi eigenvalue algorithm. Code for the Jacobi class +/// (along with tests and benchmarks) is available free of copyright at +/// https://github.com/jewettaij/jacobi_pd +/// @note The "Vector" and "Matrix" type arguments can be any +/// C or C++ object that support indexing, including pointers or vectors. +/// @details +/// Usage example: +/// @code +/// +/// int n = 5; // Matrix size +/// double **M; // A symmetric n x n matrix you want to diagonalize +/// double *evals; // Store the eigenvalues here. +/// double **evects; // Store the eigenvectors here. +/// // Allocate space for M, evals, and evects, and load contents of M (omitted) +/// +/// // Now create an instance of Jacobi ("eigen_calc"). This will allocate space +/// // for storing intermediate calculations. Once created, it can be reused +/// // multiple times without paying the cost of allocating memory on the heap. +/// +/// Jacobi eigen_calc(n); +/// +/// // Note: +/// // If the matrix you plan to diagonalize (M) is read-only, use this instead: +/// // Jacobi eigen_calc(n); +/// // If you prefer using vectors over C-style pointers, this works also: +/// // Jacobi&, vector>&> eigen_calc(n); +/// +/// // Now, calculate the eigenvalues and eigenvectors of M +/// +/// eigen_calc.Diagonalize(M, evals, evects); +/// +/// @endcode + +template +class Jacobi +{ + int n; //!< the size of the matrix + Scalar **M; //!< local copy of the matrix being analyzed + // Precomputed cosine, sine, and tangent of the most recent rotation angle: + Scalar c; //!< = cos(θ) + Scalar s; //!< = sin(θ) + Scalar t; //!< = tan(θ), (note |t|<=1) + int *max_idx_row; //!< for row i, the index j of the maximum element where j>i + +public: + + /// @brief Specify the size of the matrices you want to diagonalize later. + /// @param n the size (ie. number of rows) of the square matrix + void SetSize(int n); + + Jacobi(int n = 0) { + Init(); + SetSize(n); + } + + ~Jacobi() { + Dealloc(); + } + + // @typedef choose the criteria for sorting eigenvalues and eigenvectors + typedef enum eSortCriteria { + DO_NOT_SORT, + SORT_DECREASING_EVALS, + SORT_INCREASING_EVALS, + SORT_DECREASING_ABS_EVALS, + SORT_INCREASING_ABS_EVALS + } SortCriteria; + + /// @brief Calculate the eigenvalues and eigevectors of a symmetric matrix + /// using the Jacobi eigenvalue algorithm. + /// @returns 0 if the algorithm converged, + /// 1 if the algorithm failed to converge. (IE, if the number of + /// pivot iterations exceeded max_num_sweeps * iters_per_sweep, + /// where iters_per_sweep = (n*(n-1)/2)) + /// @note To reduce the computation time further, set calc_evecs=false. + int + Diagonalize(ConstMatrix mat, //!< the matrix you wish to diagonalize (size n) + Vector eval, //!< store the eigenvalues here + Matrix evec, //!< store the eigenvectors here (in rows) + SortCriteria sort_criteria=SORT_DECREASING_EVALS,//!c, this->s, and + /// this->t (which store cos(θ), sin(θ), and tan(θ), respectively). + void CalcRot(Scalar const *const *M, //!< matrix + int i, //!< row index + int j); //!< column index + + /// @brief Apply the (previously calculated) rotation matrix to matrix M + /// by multiplying it on both sides (a "similarity transform"). + /// (To save time, only the elements in the upper-right-triangular + /// region of the matrix are updated. It is assumed that i < j.) + void ApplyRot(Scalar **M, //!< matrix + int i, //!< row index + int j); //!< column index + + /// @brief Multiply matrix E on the left by the (previously calculated) + /// rotation matrix. + void ApplyRotLeft(Matrix E, //!< matrix + int i, //!< row index + int j); //!< column index + + ///@brief Find the off-diagonal index in row i whose absolute value is largest + int MaxEntryRow(Scalar const *const *M, int i) const; + + /// @brief Find the indices (i_max, j_max) marking the location of the + /// entry in the matrix with the largest absolute value. This + /// uses the max_idx_row[] array to find the answer in O(n) time. + /// @returns This function does not return a avalue. However after it is + /// invoked, the location of the largest matrix element will be + /// stored in the i_max and j_max arguments. + void MaxEntry(Scalar const *const *M, int& i_max, int& j_max) const; + + // @brief Sort the rows in M according to the numbers in v (also sorted) + void SortRows(Vector v, //!< vector containing the keys used for sorting + Matrix M, //!< matrix whose rows will be sorted according to v + int n, //!< size of the vector and matrix + SortCriteria s=SORT_DECREASING_EVALS //!< sort decreasing order? + ) const; + + // memory management: + void Alloc(int n); + void Init(); + void Dealloc(); + +public: + // memory management: copy and move constructor, swap, and assignment operator + Jacobi(const Jacobi& source); + Jacobi(Jacobi&& other); + void swap(Jacobi &other); + Jacobi& operator = (Jacobi source); + +}; // class Jacobi + + + + + +// -------------- IMPLEMENTATION -------------- + +// Utilities for memory allocation + +template +void Alloc2D(size_t nrows, // size of the array (number of rows) + size_t ncols, // size of the array (number of columns) + Entry ***paaX) // pointer to a 2D C-style array +{ + //assert(paaX); + *paaX = new Entry* [nrows]; //conventional 2D C array (pointer-to-pointer) + (*paaX)[0] = new Entry [nrows * ncols]; // 1D C array (contiguous memory) + for(size_t iy=0; iy +void Dealloc2D(Entry ***paaX) // pointer to a 2D C-style array +{ + if (paaX && *paaX) { + delete [] (*paaX)[0]; + delete [] (*paaX); + *paaX = nullptr; + } +} + + + +template +int Jacobi:: +Diagonalize(ConstMatrix mat, // the matrix you wish to diagonalize (size n) + Vector eval, // store the eigenvalues here + Matrix evec, // store the eigenvectors here (in rows) + SortCriteria sort_criteria, // sort results? + bool calc_evec, // calculate the eigenvectors? + int max_num_sweeps) // limit the number of iterations ("sweeps") +{ + // -- Initialization -- + for (int i = 0; i < n; i++) + for (int j = i; j < n; j++) //copy mat[][] into M[][] + M[i][j] = mat[i][j]; //(M[][] is a local copy we can modify) + + if (calc_evec) + for (int i = 0; i < n; i++) + for (int j = 0; j < n; j++) + evec[i][j] = (i==j) ? 1.0 : 0.0; //Set evec equal to the identity matrix + + for (int i = 0; i < n-1; i++) //Initialize the "max_idx_row[]" array + max_idx_row[i] = MaxEntryRow(M, i); //(which is needed by MaxEntry()) + + // -- Iteration -- + int n_iters; + int max_num_iters = max_num_sweeps*n*(n-1)/2; //"sweep" = n*(n-1)/2 iters + for (n_iters=0; n_iters < max_num_iters; n_iters++) { + int i,j; + MaxEntry(M, i, j); // Find the maximum entry in the matrix. Store in i,j + + // If M[i][j] is small compared to M[i][i] and M[j][j], set it to 0. + if ((M[i][i] + M[i][j] == M[i][i]) && (M[j][j] + M[i][j] == M[j][j])) { + M[i][j] = 0.0; + max_idx_row[i] = MaxEntryRow(M,i); //must also update max_idx_row[i] + } + + if (M[i][j] == 0.0) + break; + + // Otherwise, apply a rotation to make M[i][j] = 0 + CalcRot(M, i, j); // Calculate the parameters of the rotation matrix. + ApplyRot(M, i, j); // Apply this rotation to the M matrix. + if (calc_evec) // Optional: If the caller wants the eigenvectors, then + ApplyRotLeft(evec,i,j); // apply the rotation to the eigenvector matrix + + } //for (int n_iters=0; n_iters < max_num_iters; n_iters++) + + // -- Post-processing -- + for (int i = 0; i < n; i++) + eval[i] = M[i][i]; + + // Optional: Sort results by eigenvalue. + SortRows(eval, evec, n, sort_criteria); + + return (n_iters == max_num_iters); +} + + +/// @brief Calculate the components of a rotation matrix which performs a +/// rotation in the i,j plane by an angle (θ) that (when multiplied on +/// both sides) will zero the ij'th element of M, so that afterwards +/// M[i][j] = 0. The results will be stored in c, s, and t +/// (which store cos(θ), sin(θ), and tan(θ), respectively). + +template +void Jacobi:: +CalcRot(Scalar const *const *M, // matrix + int i, // row index + int j) // column index +{ + t = 1.0; // = tan(θ) + Scalar M_jj_ii = (M[j][j] - M[i][i]); + if (M_jj_ii != 0.0) { + // kappa = (M[j][j] - M[i][i]) / (2*M[i][j]) + Scalar kappa = M_jj_ii; + t = 0.0; + Scalar M_ij = M[i][j]; + if (M_ij != 0.0) { + kappa /= (2.0*M_ij); + // t satisfies: t^2 + 2*t*kappa - 1 = 0 + // (choose the root which has the smaller absolute value) + t = 1.0 / (std::sqrt(1 + kappa*kappa) + std::abs(kappa)); + if (kappa < 0.0) + t = -t; + } + } + //assert(std::abs(t) <= 1.0); + c = 1.0 / std::sqrt(1 + t*t); + s = c*t; +} + +/// brief Perform a similarity transformation by multiplying matrix M on both +/// sides by a rotation matrix (and its transpose) to eliminate M[i][j]. +/// details This rotation matrix performs a rotation in the i,j plane by +/// angle θ. This function assumes that c=cos(θ). s=som(θ), t=tan(θ) +/// have been calculated in advance (using the CalcRot() function). +/// It also assumes that iv) are not computed. +/// verbatim +/// M' = R^T * M * R +/// where R the rotation in the i,j plane and ^T denotes the transpose. +/// i j +/// _ _ +/// | 1 | +/// | . | +/// | . | +/// | 1 | +/// | c ... s | +/// | . . . | +/// R = | . 1 . | +/// | . . . | +/// | -s ... c | +/// | 1 | +/// | . | +/// | . | +/// |_ 1 _| +/// endverbatim +/// +/// Let M' denote the matrix M after multiplication by R^T and R. +/// The components of M' are: +/// +/// verbatim +/// M'_uv = Σ_w Σ_z R_wu * M_wz * R_zv +/// endverbatim +/// +/// Note that a the rotation at location i,j will modify all of the matrix +/// elements containing at least one index which is either i or j +/// such as: M[w][i], M[i][w], M[w][j], M[j][w]. +/// Check and see whether these modified matrix elements exceed the +/// corresponding values in max_idx_row[] array for that row. +/// If so, then update max_idx_row for that row. +/// This is somewhat complicated by the fact that we must only consider +/// matrix elements in the upper-right triangle strictly above the diagonal. +/// (ie. matrix elements whose second index is > the first index). +/// The modified elements we must consider are marked with an "X" below: +/// +/// @verbatim +/// i j +/// _ _ +/// | . X X | +/// | . X X | +/// | . X X | +/// | . X X | +/// | X X X X X 0 X X X X | i +/// | . X | +/// | . X | +/// M = | . X | +/// | . X | +/// | X X X X X | j +/// | . | +/// | . | +/// | . | +/// |_ . _| +/// @endverbatim + +template +void Jacobi:: +ApplyRot(Scalar **M, // matrix + int i, // row index + int j) // column index +{ + // Recall that: + // c = cos(θ) + // s = sin(θ) + // t = tan(θ) (which should be <= 1.0) + + // Compute the diagonal elements of M which have changed: + M[i][i] -= t * M[i][j]; + M[j][j] += t * M[i][j]; + // Note: This is algebraically equivalent to: + // M[i][i] = c*c*M[i][i] + s*s*M[j][j] - 2*s*c*M[i][j] + // M[j][j] = s*s*M[i][i] + c*c*M[j][j] + 2*s*c*M[i][j] + + //Update the off-diagonal elements of M which will change (above the diagonal) + + //assert(i < j); + + M[i][j] = 0.0; + + //compute M[w][i] and M[i][w] for all w!=i,considering above-diagonal elements + for (int w=0; w < i; w++) { // 0 <= w < i < j < n + M[i][w] = M[w][i]; //backup the previous value. store below diagonal (i>w) + M[w][i] = c*M[w][i] - s*M[w][j]; //M[w][i], M[w][j] from previous iteration + if (i == max_idx_row[w]) max_idx_row[w] = MaxEntryRow(M, w); + else if (std::abs(M[w][i])>std::abs(M[w][max_idx_row[w]])) max_idx_row[w]=i; + //assert(max_idx_row[w] == MaxEntryRow(M, w)); + } + for (int w=i+1; w < j; w++) { // 0 <= i < w < j < n + M[w][i] = M[i][w]; //backup the previous value. store below diagonal (w>i) + M[i][w] = c*M[i][w] - s*M[w][j]; //M[i][w], M[w][j] from previous iteration + } + for (int w=j+1; w < n; w++) { // 0 <= i < j+1 <= w < n + M[w][i] = M[i][w]; //backup the previous value. store below diagonal (w>i) + M[i][w] = c*M[i][w] - s*M[j][w]; //M[i][w], M[j][w] from previous iteration + } + + // now that we're done modifying row i, we can update max_idx_row[i] + max_idx_row[i] = MaxEntryRow(M, i); + + //compute M[w][j] and M[j][w] for all w!=j,considering above-diagonal elements + for (int w=0; w < i; w++) { // 0 <= w < i < j < n + M[w][j] = s*M[i][w] + c*M[w][j]; //M[i][w], M[w][j] from previous iteration + if (j == max_idx_row[w]) max_idx_row[w] = MaxEntryRow(M, w); + else if (std::abs(M[w][j])>std::abs(M[w][max_idx_row[w]])) max_idx_row[w]=j; + //assert(max_idx_row[w] == MaxEntryRow(M, w)); + } + for (int w=i+1; w < j; w++) { // 0 <= i+1 <= w < j < n + M[w][j] = s*M[w][i] + c*M[w][j]; //M[w][i], M[w][j] from previous iteration + if (j == max_idx_row[w]) max_idx_row[w] = MaxEntryRow(M, w); + else if (std::abs(M[w][j])>std::abs(M[w][max_idx_row[w]])) max_idx_row[w]=j; + //assert(max_idx_row[w] == MaxEntryRow(M, w)); + } + for (int w=j+1; w < n; w++) { // 0 <= i < j < w < n + M[j][w] = s*M[w][i] + c*M[j][w]; //M[w][i], M[j][w] from previous iteration + } + // now that we're done modifying row j, we can update max_idx_row[j] + max_idx_row[j] = MaxEntryRow(M, j); + +} //Jacobi::ApplyRot() + + + + +///@brief Multiply matrix M on the LEFT side by a transposed rotation matrix R^T +/// This matrix performs a rotation in the i,j plane by angle θ (where +/// the arguments "s" and "c" refer to cos(θ) and sin(θ), respectively). +/// @verbatim +/// E'_uv = Σ_w R_wu * E_wv +/// @endverbatim + +template +void Jacobi:: +ApplyRotLeft(Matrix E, // matrix + int i, // row index + int j) // column index +{ + // Recall that c = cos(θ) and s = sin(θ) + for (int v = 0; v < n; v++) { + Scalar Eiv = E[i][v]; //backup E[i][v] + E[i][v] = c*E[i][v] - s*E[j][v]; + E[j][v] = s*Eiv + c*E[j][v]; + } +} + + + +template +int Jacobi:: +MaxEntryRow(Scalar const *const *M, int i) const { + int j_max = i+1; + for(int j = i+2; j < n; j++) + if (std::abs(M[i][j]) > std::abs(M[i][j_max])) + j_max = j; + return j_max; +} + + + +template +void Jacobi:: +MaxEntry(Scalar const *const *M, int& i_max, int& j_max) const { + // find the maximum entry in the matrix M in O(n) time + i_max = 0; + j_max = max_idx_row[i_max]; + Scalar max_entry = std::abs(M[i_max][j_max]); + int nm1 = n-1; + for (int i=1; i < nm1; i++) { + int j = max_idx_row[i]; + if (std::abs(M[i][j]) > max_entry) { + max_entry = std::abs(M[i][j]); + i_max = i; + j_max = j; + } + } + //#ifndef NDEBUG + //// make sure that the maximum element really is stored at i_max, j_max + //// (comment out the next loop before using. it slows down the code) + //for (int i = 0; i < nm1; i++) + // for (int j = i+1; j < n; j++) + // assert(std::abs(M[i][j]) <= max_entry); + //#endif +} + + + +//Sort the rows of a matrix "evec" by the numbers contained in "eval" +template +void Jacobi:: +SortRows(Vector eval, Matrix evec, int n, SortCriteria sort_criteria) const +{ + for (int i = 0; i < n-1; i++) { + int i_max = i; + for (int j = i+1; j < n; j++) { + // find the "maximum" element in the array starting at position i+1 + switch (sort_criteria) { + case SORT_DECREASING_EVALS: + if (eval[j] > eval[i_max]) + i_max = j; + break; + case SORT_INCREASING_EVALS: + if (eval[j] < eval[i_max]) + i_max = j; + break; + case SORT_DECREASING_ABS_EVALS: + if (std::abs(eval[j]) > std::abs(eval[i_max])) + i_max = j; + break; + case SORT_INCREASING_ABS_EVALS: + if (std::abs(eval[j]) < std::abs(eval[i_max])) + i_max = j; + break; + default: + break; + } + } + std::swap(eval[i], eval[i_max]); // sort "eval" + for (int k = 0; k < n; k++) + std::swap(evec[i][k], evec[i_max][k]); // sort "evec" + } +} + + + +template +void Jacobi:: +Init() { + n = 0; + M = nullptr; + max_idx_row = nullptr; +} + +template +void Jacobi:: +SetSize(int n) { + Dealloc(); + Alloc(n); +} + +// memory management: + +template +void Jacobi:: +Alloc(int n) { + this->n = n; + if (n > 0) { + max_idx_row = new int[n]; + Alloc2D(n, n, &M); + } +} + +template +void Jacobi:: +Dealloc() { + if (max_idx_row) + delete [] max_idx_row; + Dealloc2D(&M); + Init(); +} + +// memory management: copy and move constructor, swap, and assignment operator: + +template +Jacobi:: +Jacobi(const Jacobi& source) +{ + Init(); + SetSize(source.n); + //assert(n == source.n); + + // The following lines aren't really necessary, because the contents + // of source.M and source.max_idx_row are not needed (since they are + // overwritten every time Jacobi::Diagonalize() is invoked). + std::copy(source.max_idx_row, + source.max_idx_row + n, + max_idx_row); + for (int i = 0; i < n; i++) + std::copy(source.M[i], + source.M[i] + n, + M[i]); +} + +template +void Jacobi:: +swap(Jacobi &other) { + std::swap(n, other.n); + std::swap(max_idx_row, other.max_idx_row); + std::swap(M, other.M); +} + +// Move constructor (C++11) +template +Jacobi:: +Jacobi(Jacobi&& other) { + Init(); + this->swap(other); +} + +// Using the "copy-swap" idiom for the assignment operator +template +Jacobi& +Jacobi:: +operator = (Jacobi source) { + this->swap(source); + return *this; +} + +} // namespace MathEigen + + +#endif //#ifndef _MATH_EIGEN_H + diff --git a/src/BODY/body_nparticle.cpp b/src/BODY/body_nparticle.cpp index a99c025e1f..52ae2a2eb8 100644 --- a/src/BODY/body_nparticle.cpp +++ b/src/BODY/body_nparticle.cpp @@ -16,6 +16,7 @@ #include #include "my_pool_chunk.h" #include "math_extra.h" +#include "math_eigen.h" #include "atom_vec_body.h" #include "atom.h" #include "force.h" @@ -137,7 +138,7 @@ void BodyNparticle::data_body(int ibonus, int ninteger, int ndouble, double *inertia = bonus->inertia; double evectors[3][3]; - int ierror = MathExtra::jacobi(tensor,inertia,evectors); + int ierror = MathEigen::jacobi3(tensor,inertia,evectors); if (ierror) error->one(FLERR, "Insufficient Jacobi rotations for body nparticle"); diff --git a/src/BODY/body_rounded_polygon.cpp b/src/BODY/body_rounded_polygon.cpp index 349ad957c2..375ec7c5d7 100644 --- a/src/BODY/body_rounded_polygon.cpp +++ b/src/BODY/body_rounded_polygon.cpp @@ -24,6 +24,7 @@ #include "force.h" #include "domain.h" #include "math_extra.h" +#include "math_eigen.h" #include "memory.h" #include "error.h" #include "fmt/format.h" @@ -198,7 +199,7 @@ void BodyRoundedPolygon::data_body(int ibonus, int ninteger, int ndouble, double *inertia = bonus->inertia; double evectors[3][3]; - int ierror = MathExtra::jacobi(tensor,inertia,evectors); + int ierror = MathEigen::jacobi3(tensor,inertia,evectors); if (ierror) error->one(FLERR, "Insufficient Jacobi rotations for body nparticle"); diff --git a/src/BODY/body_rounded_polyhedron.cpp b/src/BODY/body_rounded_polyhedron.cpp index cb84517b6f..73a6148b3e 100644 --- a/src/BODY/body_rounded_polyhedron.cpp +++ b/src/BODY/body_rounded_polyhedron.cpp @@ -24,6 +24,7 @@ #include "atom.h" #include "force.h" #include "math_extra.h" +#include "math_eigen.h" #include "memory.h" #include "error.h" #include "fmt/format.h" @@ -243,7 +244,7 @@ void BodyRoundedPolyhedron::data_body(int ibonus, int ninteger, int ndouble, double *inertia = bonus->inertia; double evectors[3][3]; - int ierror = MathExtra::jacobi(tensor,inertia,evectors); + int ierror = MathEigen::jacobi3(tensor,inertia,evectors); if (ierror) error->one(FLERR, "Insufficient Jacobi rotations for body nparticle"); diff --git a/src/POEMS/fix_poems.cpp b/src/POEMS/fix_poems.cpp index b0b1287717..aeca600a51 100644 --- a/src/POEMS/fix_poems.cpp +++ b/src/POEMS/fix_poems.cpp @@ -36,6 +36,7 @@ #include "error.h" #include "utils.h" #include "fmt/format.h" +#include "math_eigen.h" using namespace LAMMPS_NS; using namespace FixConst; @@ -44,7 +45,6 @@ using namespace FixConst; #define DELTA 128 #define TOLERANCE 1.0e-6 #define EPSILON 1.0e-7 -#define MAXJACOBI 50 static const char cite_fix_poems[] = "fix poems command:\n\n" @@ -492,7 +492,7 @@ void FixPOEMS::init() tensor[1][2] = tensor[2][1] = all[ibody][4]; tensor[0][2] = tensor[2][0] = all[ibody][5]; - ierror = jacobi(tensor,inertia[ibody],evectors); + ierror = MathEigen::jacobi3(tensor,inertia[ibody],evectors); if (ierror) error->all(FLERR,"Insufficient Jacobi rotations for POEMS body"); ex_space[ibody][0] = evectors[0][0]; @@ -1283,88 +1283,6 @@ int FixPOEMS::loopcheck(int nvert, int nedge, tagint **elist) return 0; } -/* ---------------------------------------------------------------------- - compute evalues and evectors of 3x3 real symmetric matrix - based on Jacobi rotations - adapted from Numerical Recipes jacobi() function -------------------------------------------------------------------------- */ - -int FixPOEMS::jacobi(double **matrix, double *evalues, double **evectors) -{ - int i,j,k; - double tresh,theta,tau,t,sm,s,h,g,c,b[3],z[3]; - - for (i = 0; i < 3; i++) { - for (j = 0; j < 3; j++) evectors[i][j] = 0.0; - evectors[i][i] = 1.0; - } - for (i = 0; i < 3; i++) { - b[i] = evalues[i] = matrix[i][i]; - z[i] = 0.0; - } - - for (int iter = 1; iter <= MAXJACOBI; iter++) { - sm = 0.0; - for (i = 0; i < 2; i++) - for (j = i+1; j < 3; j++) - sm += fabs(matrix[i][j]); - if (sm == 0.0) return 0; - - if (iter < 4) tresh = 0.2*sm/(3*3); - else tresh = 0.0; - - for (i = 0; i < 2; i++) { - for (j = i+1; j < 3; j++) { - g = 100.0*fabs(matrix[i][j]); - if (iter > 4 && fabs(evalues[i])+g == fabs(evalues[i]) - && fabs(evalues[j])+g == fabs(evalues[j])) - matrix[i][j] = 0.0; - else if (fabs(matrix[i][j]) > tresh) { - h = evalues[j]-evalues[i]; - if (fabs(h)+g == fabs(h)) t = (matrix[i][j])/h; - else { - theta = 0.5*h/(matrix[i][j]); - t = 1.0/(fabs(theta)+sqrt(1.0+theta*theta)); - if (theta < 0.0) t = -t; - } - c = 1.0/sqrt(1.0+t*t); - s = t*c; - tau = s/(1.0+c); - h = t*matrix[i][j]; - z[i] -= h; - z[j] += h; - evalues[i] -= h; - evalues[j] += h; - matrix[i][j] = 0.0; - for (k = 0; k < i; k++) rotate(matrix,k,i,k,j,s,tau); - for (k = i+1; k < j; k++) rotate(matrix,i,k,k,j,s,tau); - for (k = j+1; k < 3; k++) rotate(matrix,i,k,j,k,s,tau); - for (k = 0; k < 3; k++) rotate(evectors,k,i,k,j,s,tau); - } - } - } - - for (i = 0; i < 3; i++) { - evalues[i] = b[i] += z[i]; - z[i] = 0.0; - } - } - return 1; -} - -/* ---------------------------------------------------------------------- - perform a single Jacobi rotation -------------------------------------------------------------------------- */ - -void FixPOEMS::rotate(double **matrix, int i, int j, int k, int l, - double s, double tau) -{ - double g = matrix[i][j]; - double h = matrix[k][l]; - matrix[i][j] = g-s*(h+g*tau); - matrix[k][l] = h+s*(g-h*tau); -} - /* ---------------------------------------------------------------------- compute omega from angular momentum w = omega = angular velocity in space frame diff --git a/src/POEMS/fix_poems.h b/src/POEMS/fix_poems.h index 6892c51d7e..7c81889639 100644 --- a/src/POEMS/fix_poems.h +++ b/src/POEMS/fix_poems.h @@ -106,8 +106,6 @@ class FixPOEMS : public Fix { void jointbuild(); void sortlist(int, tagint **); int loopcheck(int, int, tagint **); - int jacobi(double **, double *, double **); - void rotate(double **, int, int, int, int, double, double); void omega_from_mq(double *, double *, double *, double *, double *, double *); void set_v(); diff --git a/src/RIGID/fix_rigid.cpp b/src/RIGID/fix_rigid.cpp index 761b957292..293d86f7a9 100644 --- a/src/RIGID/fix_rigid.cpp +++ b/src/RIGID/fix_rigid.cpp @@ -17,6 +17,7 @@ #include #include #include "math_extra.h" +#include "math_eigen.h" #include "atom.h" #include "atom_vec_ellipsoid.h" #include "atom_vec_line.h" @@ -1948,7 +1949,7 @@ void FixRigid::setup_bodies_static() tensor[0][2] = tensor[2][0] = all[ibody][4]; tensor[0][1] = tensor[1][0] = all[ibody][5]; - ierror = MathExtra::jacobi(tensor,inertia[ibody],evectors); + ierror = MathEigen::jacobi3(tensor,inertia[ibody],evectors); if (ierror) error->all(FLERR, "Insufficient Jacobi rotations for rigid body"); diff --git a/src/RIGID/fix_rigid_small.cpp b/src/RIGID/fix_rigid_small.cpp index 01dd9e889e..3af63dc5ec 100644 --- a/src/RIGID/fix_rigid_small.cpp +++ b/src/RIGID/fix_rigid_small.cpp @@ -18,6 +18,7 @@ #include #include #include "math_extra.h" +#include "math_eigen.h" #include "atom.h" #include "atom_vec_ellipsoid.h" #include "atom_vec_line.h" @@ -2085,7 +2086,7 @@ void FixRigidSmall::setup_bodies_static() tensor[0][1] = tensor[1][0] = itensor[ibody][5]; inertia = body[ibody].inertia; - ierror = MathExtra::jacobi(tensor,inertia,evectors); + ierror = MathEigen::jacobi3(tensor,inertia,evectors); if (ierror) error->all(FLERR, "Insufficient Jacobi rotations for rigid body"); diff --git a/src/USER-MISC/compute_gyration_shape.cpp b/src/USER-MISC/compute_gyration_shape.cpp index aef5ef91a3..7b5d77ea04 100644 --- a/src/USER-MISC/compute_gyration_shape.cpp +++ b/src/USER-MISC/compute_gyration_shape.cpp @@ -21,6 +21,7 @@ #include #include "error.h" #include "math_extra.h" +#include "math_eigen.h" #include "math_special.h" #include "modify.h" #include "update.h" @@ -95,7 +96,7 @@ void ComputeGyrationShape::compute_vector() ione[1][2] = ione[2][1] = gyration_tensor[4]; ione[0][2] = ione[2][0] = gyration_tensor[5]; - int ierror = MathExtra::jacobi(ione,evalues,evectors); + int ierror = MathEigen::jacobi3(ione,evalues,evectors); if (ierror) error->all(FLERR, "Insufficient Jacobi rotations " "for gyration/shape"); diff --git a/src/USER-MISC/compute_gyration_shape_chunk.cpp b/src/USER-MISC/compute_gyration_shape_chunk.cpp index 116d851024..e0fc5c1342 100644 --- a/src/USER-MISC/compute_gyration_shape_chunk.cpp +++ b/src/USER-MISC/compute_gyration_shape_chunk.cpp @@ -21,6 +21,7 @@ #include #include "error.h" #include "math_extra.h" +#include "math_eigen.h" #include "math_special.h" #include "modify.h" #include "memory.h" @@ -125,7 +126,7 @@ void ComputeGyrationShapeChunk::compute_array() ione[0][2] = ione[2][0] = gyration_tensor[ichunk][4]; ione[1][2] = ione[2][1] = gyration_tensor[ichunk][5]; - int ierror = MathExtra::jacobi(ione,evalues,evectors); + int ierror = MathEigen::jacobi3(ione,evalues,evectors); if (ierror) error->all(FLERR, "Insufficient Jacobi rotations " "for gyration/shape"); diff --git a/src/atom_vec_tri.cpp b/src/atom_vec_tri.cpp index d5b48b9540..a3409ef584 100644 --- a/src/atom_vec_tri.cpp +++ b/src/atom_vec_tri.cpp @@ -15,6 +15,7 @@ #include #include #include "math_extra.h" +#include "math_eigen.h" #include "atom.h" #include "domain.h" #include "modify.h" @@ -555,7 +556,7 @@ void AtomVecTri::data_atom_bonus(int m, char **values) tensor[0][2] = tensor[2][0] = inertia[4]; tensor[0][1] = tensor[1][0] = inertia[5]; - int ierror = MathExtra::jacobi(tensor,bonus[nlocal_bonus].inertia,evectors); + int ierror = MathEigen::jacobi3(tensor,bonus[nlocal_bonus].inertia,evectors); if (ierror) error->one(FLERR,"Insufficient Jacobi rotations for triangle"); double ex_space[3],ey_space[3],ez_space[3]; diff --git a/src/compute_omega_chunk.cpp b/src/compute_omega_chunk.cpp index 327c64493f..5c51d036ac 100644 --- a/src/compute_omega_chunk.cpp +++ b/src/compute_omega_chunk.cpp @@ -20,6 +20,7 @@ #include "compute_chunk_atom.h" #include "domain.h" #include "math_extra.h" +#include "math_eigen.h" #include "memory.h" #include "error.h" @@ -250,10 +251,10 @@ void ComputeOmegaChunk::compute_array() // handle each (nearly) singular I matrix // due to 2-atom chunk or linear molecule - // use jacobi() and angmom_to_omega() to calculate valid omega + // use jacobi3() and angmom_to_omega() to calculate valid omega } else { - int ierror = MathExtra::jacobi(ione,idiag,evectors); + int ierror = MathEigen::jacobi3(ione,idiag,evectors); if (ierror) error->all(FLERR, "Insufficient Jacobi rotations for omega/chunk"); diff --git a/src/group.cpp b/src/group.cpp index 2377f028bd..c007ba813e 100644 --- a/src/group.cpp +++ b/src/group.cpp @@ -30,6 +30,7 @@ #include "variable.h" #include "dump.h" #include "math_extra.h" +#include "math_eigen.h" #include "memory.h" #include "error.h" #include "utils.h" @@ -1729,11 +1730,11 @@ void Group::omega(double *angmom, double inertia[3][3], double *w) // handle (nearly) singular I matrix // typically due to 2-atom group or linear molecule - // use jacobi() and angmom_to_omega() to calculate valid omega + // use jacobi3() and angmom_to_omega() to calculate valid omega // less exact answer than matrix inversion, due to iterative Jacobi method } else { - int ierror = MathExtra::jacobi(inertia,idiag,evectors); + int ierror = MathEigen::jacobi3(inertia, idiag, evectors); if (ierror) error->all(FLERR, "Insufficient Jacobi rotations for group::omega"); diff --git a/src/math_eigen.cpp b/src/math_eigen.cpp new file mode 100644 index 0000000000..b86b626309 --- /dev/null +++ b/src/math_eigen.cpp @@ -0,0 +1,140 @@ +#include "math_eigen.h" +#include + +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; +// +// ...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; + +// template instantiations of Jacbi for fixed-size (3x3) arrays +template class MathEigen::Jacobi; + +// template instantiations of Jacobi for vector-of-vectors: +template class MathEigen::Jacobi&, + vector >&, + const vector >& >; + +// template instantiations of Jacobi for array-of-arrays: +template class MathEigen::Jacobi&, + array, 3 >&, + const array, 3 >& >; +// template instantiations of LambdaLanczos +template class MathEigen::LambdaLanczos; + +// template instantiations of PEidenDense for pointer->pointer arrays +template class MathEigen::PEigenDense; + +// template instantiations of PEidenDense for vector> +template class MathEigen::PEigenDense&, + const vector >&>; + +// ----------------- now create instances for floats ---------------- + +template class MathEigen::Jacobi; +template class MathEigen::Jacobi; +template class MathEigen::Jacobi&, + vector >&, + const vector >& >; +template class MathEigen::Jacobi&, + array, 3 >&, + const array, 3 >& >; +template class MathEigen::LambdaLanczos; +template class MathEigen::PEigenDense; +template class MathEigen::PEigenDense&, + const vector >&>; + +// 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::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 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::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 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; +} + diff --git a/src/math_eigen.h b/src/math_eigen.h index f8d2be4e21..3a697584d7 100644 --- a/src/math_eigen.h +++ b/src/math_eigen.h @@ -16,8 +16,8 @@ Andrew Jewett (Scripps Research, Jacobi algorithm) ------------------------------------------------------------------------- */ -#ifndef _MATH_EIGEN_H -#define _MATH_EIGEN_H +#ifndef LMP_MATH_EIGEN_H +#define LMP_MATH_EIGEN_H /// @file This file contains a library of functions and classes which can /// efficiently perform eigendecomposition for an extremely broad @@ -40,7 +40,7 @@ /// https://github.com/jewettaij/jacobi_pd (CC0-1.0 license) /// https://github.com/mrcdr/lambda-lanczos (MIT license) -#include +//#include #include #include #include @@ -51,408 +51,475 @@ namespace MathEigen { -// --- Memory allocation for matrices --- + // --- Memory allocation for matrices --- -/// @brief Allocate an arbitrary 2-dimensional array. (Uses row-major order.) -/// @note This function was intended for relatively small matrices (eg 4x4). -/// For large arrays, please use the 2d create() function from "memory.h" -template -void Alloc2D(size_t nrows, //!< size of the array (number of rows) - size_t ncols, //!< size of the array (number of columns) - Entry ***paaX); //!< pointer to a 2D C-style array + /// @brief Allocate an arbitrary 2-dimensional array. (Uses row-major order.) + /// @note This function was intended for relatively small matrices (eg 4x4). + /// For large arrays, please use the 2d create() function from "memory.h" + template + void Alloc2D(size_t nrows, //!< size of the array (number of rows) + size_t ncols, //!< size of the array (number of columns) + Entry ***paaX); //!< pointer to a 2D C-style array -/// @brief Deallocate arrays that were created using Alloc2D(). -template -void Dealloc2D(Entry ***paaX); //!< pointer to 2D multidimensional array + /// @brief Deallocate arrays that were created using Alloc2D(). + template + void Dealloc2D(Entry ***paaX); //!< pointer to 2D multidimensional array -// --- Complex numbers --- + // --- Complex numbers --- -/// @brief "realTypeMap" struct is used to the define "real_t" type mapper -/// which returns the C++ type corresponding to the real component of T. -/// @details Consider a function ("l2_norm()") that calculates the -/// (Euclidian) length of a vector of numbers (either real or complex): -/// @code -/// template real_t l2_norm(const std::vector& vec); -/// @endcode -/// The l2_norm is always real by definition. -/// (See https://en.wikipedia.org/wiki/Norm_(mathematics)#Euclidean_norm) -/// The return type of this function ("real_t") indicates that -/// it returns a real number, even if the entries (of type T) -/// are complex numbers. In other words, by default, real_t returns T. -/// However real_t> returns T (not std::complex). -/// We define "real_t" below using C++ template specializations: + /// @brief "realTypeMap" struct is used to the define "real_t" type mapper + /// which returns the C++ type corresponding to the real component of T. + /// @details Consider a function ("l2_norm()") that calculates the + /// (Euclidian) length of a vector of numbers (either real or complex): + /// @code + /// template real_t l2_norm(const std::vector& vec); + /// @endcode + /// The l2_norm is always real by definition. + /// (See https://en.wikipedia.org/wiki/Norm_(mathematics)#Euclidean_norm) + /// The return type of this function ("real_t") indicates that + /// it returns a real number, even if the entries (of type T) + /// are complex numbers. In other words, by default, real_t returns T. + /// However real_t> returns T (not std::complex). + /// We define "real_t" below using C++ template specializations: -template -struct realTypeMap { - typedef T type; -}; -template -struct realTypeMap> { - typedef T type; -}; -template -using real_t = typename realTypeMap::type; + template + struct realTypeMap { + typedef T type; + }; + template + struct realTypeMap> { + typedef T type; + }; + template + using real_t = typename realTypeMap::type; -// --- Operations on vectors (of real and complex numbers) --- + // --- Operations on vectors (of real and complex numbers) --- -/// @brief Calculate the inner product of two vectors. -/// (For vectors of complex numbers, std::conj() is used.) -template -T inner_prod(const std::vector& v1, const std::vector& v2); + /// @brief Calculate the inner product of two vectors. + /// (For vectors of complex numbers, std::conj() is used.) + template + T inner_prod(const std::vector& v1, const std::vector& v2); -/// @brief Compute the sum of the absolute values of the entries in v -/// @returns a real number (of type real_t). -template -real_t l1_norm(const std::vector& v); + /// @brief Compute the sum of the absolute values of the entries in v + /// @returns a real number (of type real_t). + template + real_t l1_norm(const std::vector& v); -/// @brief Calculate the l2_norm (Euclidian length) of vector v. -/// @returns a real number (of type real_t). -template -real_t l2_norm(const std::vector& v); + /// @brief Calculate the l2_norm (Euclidian length) of vector v. + /// @returns a real number (of type real_t). + template + real_t l2_norm(const std::vector& v); -/// @brief Multiply a vector (v) by a scalar (c). -template -void scalar_mul(T1 c, std::vector& v); + /// @brief Multiply a vector (v) by a scalar (c). + template + void scalar_mul(T1 c, std::vector& v); -/// @brief Divide vector "v" in-place by it's length (l2_norm(v)). -template -void normalize(std::vector& v); + /// @brief Divide vector "v" in-place by it's length (l2_norm(v)). + template + void normalize(std::vector& v); + // ---- Eigendecomposition of small dense symmetric matrices ---- -// ---- Eigendecomposition of small dense symmetric matrices ---- - -/// @class Jacobi -/// @brief Calculate the eigenvalues and eigevectors of a symmetric matrix -/// using the Jacobi eigenvalue algorithm. Code for the Jacobi class -/// (along with tests and benchmarks) is available free of copyright at -/// https://github.com/jewettaij/jacobi_pd -/// @note The "Vector" and "Matrix" type arguments can be any -/// C or C++ object that support indexing, including pointers or vectors. -/// @details -/// -- Example: -- -/// -/// int n = 5; // Matrix size -/// double **M; // A symmetric n x n matrix you want to diagonalize -/// double *evals; // Store the eigenvalues here. -/// double **evects; // Store the eigenvectors here. -/// // Allocate space for M, evals, and evects, and load contents of M (omitted) -/// -/// // Now create an instance of Jacobi ("eigen_calc"). This will allocate space -/// // for storing intermediate calculations. Once created, it can be reused -/// // multiple times without paying the cost of allocating memory on the heap. -/// -/// Jacobi eigen_calc(n); -/// -/// // Note: -/// // If the matrix you plan to diagonalize (M) is read-only, use this instead: -/// // Jacobi eigen_calc(n); -/// // If you prefer using vectors over C-style pointers, this works also: -/// // Jacobi&, vector>&> eigen_calc(n); -/// -/// // Now, calculate the eigenvalues and eigenvectors of M -/// -/// eigen_calc.Diagonalize(M, evals, evects); -/// -/// --- end of example --- - -template - -class Jacobi -{ - int n; //!< the size of the matrices you want to diagonalize - Scalar **M; //!< local copy of the current matrix being analyzed - // Precomputed cosine, sine, and tangent of the most recent rotation angle: - Scalar c; //!< = cos(θ) - Scalar s; //!< = sin(θ) - Scalar t; //!< = tan(θ), (note |t|<=1) - int *max_idx_row; //!< = keep track of the the maximum element in row i (>i) - -public: - - /// @brief Specify the size of the matrices you want to diagonalize later. - /// @param n the size (ie. number of rows) of the (square) matrix. - void SetSize(int n); - - Jacobi(int n = 0) { Init(); SetSize(n); } - - ~Jacobi() { Dealloc(); } - - // @typedef choose the criteria for sorting eigenvalues and eigenvectors - typedef enum eSortCriteria { - DO_NOT_SORT, - SORT_DECREASING_EVALS, - SORT_INCREASING_EVALS, - SORT_DECREASING_ABS_EVALS, - SORT_INCREASING_ABS_EVALS - } SortCriteria; - + /// @class Jacobi /// @brief Calculate the eigenvalues and eigevectors of a symmetric matrix - /// using the Jacobi eigenvalue algorithm. - /// @returns The number_of_sweeps (= number_of_iterations / (n*(n-1)/2)). - /// If this equals max_num_sweeps, the algorithm failed to converge. - /// @note To reduce the computation time further, set calc_evecs=false. - int - Diagonalize(ConstMatrix mat, //!< the matrix you wish to diagonalize (size n) - Vector eval, //!< store the eigenvalues here - Matrix evec, //!< store the eigenvectors here (in rows) - SortCriteria sort_criteria=SORT_DECREASING_EVALS,//! eigen_calc(n); + /// + /// // Note: + /// // If the matrix you plan to diagonalize (M) is read-only, use this instead: + /// // Jacobi eigen_calc(n); + /// // If you prefer using vectors over C-style pointers, this works also: + /// // Jacobi&, vector>&> eigen_calc(n); + /// + /// // Now, calculate the eigenvalues and eigenvectors of M + /// + /// eigen_calc.Diagonalize(M, evals, evects); + /// + /// @endcode -private: - // (Descriptions of private functions can be found in their implementation.) - void CalcRot(Scalar const *const *M, int i, int j); - void ApplyRot(Scalar **M, int i, int j); - void ApplyRotLeft(Matrix E, int i, int j); - int MaxEntryRow(Scalar const *const *M, int i) const; - void MaxEntry(Scalar const *const *M, int& i_max, int& j_max) const; - void SortRows(Vector v, Matrix M, int n, SortCriteria s=SORT_DECREASING_EVALS) const; - void Init(); - void Alloc(int n); - void Dealloc(); -public: - // C++ boilerplate: copy and move constructor, swap, and assignment operator - Jacobi(const Jacobi& source); - Jacobi(Jacobi&& other); - void swap(Jacobi &other); - Jacobi& operator = (Jacobi source); + template -}; // class Jacobi + class Jacobi + { + int n; //!< the size of the matrices you want to diagonalize + Scalar **M; //!< local copy of the current matrix being analyzed + // Precomputed cosine, sine, and tangent of the most recent rotation angle: + Scalar c; //!< = cos(θ) + Scalar s; //!< = sin(θ) + Scalar t; //!< = tan(θ), (note |t|<=1) + int *max_idx_row; //!< = keep track of the the maximum element in row i (>i) + + public: + /// @brief Specify the size of the matrices you want to diagonalize later. + /// @param n the size (ie. number of rows) of the (square) matrix. + /// @param workspace optional array for storing intermediate calculations + /// (The vast majority of users can ignore this argument.) + Jacobi(int n = 0, Scalar **workspace=nullptr); + + ~Jacobi(); + + /// @brief Change the size of the matrices you want to diagonalize. + /// @param n the size (ie. number of rows) of the (square) matrix. + void SetSize(int n); + + // @typedef choose the criteria for sorting eigenvalues and eigenvectors + typedef enum eSortCriteria { + DO_NOT_SORT, + SORT_DECREASING_EVALS, + SORT_INCREASING_EVALS, + SORT_DECREASING_ABS_EVALS, + SORT_INCREASING_ABS_EVALS + } SortCriteria; + + /// @brief Calculate the eigenvalues and eigevectors of a symmetric matrix + /// using the Jacobi eigenvalue algorithm. + /// @returns 0 if the algorithm converged, + /// 1 if the algorithm failed to converge. (IE, if the number of + /// pivot iterations exceeded max_num_sweeps * iters_per_sweep, + /// where iters_per_sweep = (n*(n-1)/2)) + /// @note To reduce the computation time further, set calc_evecs=false. + int + Diagonalize(ConstMatrix mat, //!< the matrix you wish to diagonalize (size n) + Vector eval, //!< store the eigenvalues here + Matrix evec, //!< store the eigenvectors here (in rows) + SortCriteria sort_criteria=SORT_DECREASING_EVALS,//!& source); + Jacobi(Jacobi&& other); + void swap(Jacobi &other); + Jacobi& operator = (Jacobi source); + + }; // class Jacobi + + + /// @brief + /// A specialized function which finds the eigenvalues and eigenvectors + /// of a 3x3 matrix (in double ** format). + /// @param mat the 3x3 matrix you wish to diagonalize + /// @param eval store the eigenvalues here + /// @param evec store the eigenvectors here... + /// @param evec_as_columns ...in the columns or in rows? + /// @param sort_criteria sort the resulting eigenvalues? + /// @note + /// When invoked using default arguments, this function is a stand-in for + /// the the version of "jacobi()" that was defined in "POEMS/fix_poems.cpp". + int jacobi3(double const **mat, + double *eval, + double **evec, + // optional arguments: + bool evec_as_columns = true, + Jacobi:: + SortCriteria sort_criteria = + Jacobi:: + SORT_DECREASING_EVALS + ); + + + /// @brief + /// This version of jacobi3() finds the eigenvalues and eigenvectors + /// of a 3x3 matrix (which is in double (*)[3] format, instead of double **) + /// @param mat the 3x3 matrix you wish to diagonalize + /// @param eval store the eigenvalues here + /// @param evec store the eigenvectors here... + /// @param evec_as_columns ...in the columns or in rows? + /// @param sort_criteria sort the resulting eigenvalues? + /// @note + /// When invoked using default arguments, this function is a stand-in for + /// the previous version of "jacobi()" that was declared in "math_extra.h". + int 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=true, //!< ...as columns or as rows? + // optional arguments: + Jacobi:: + SortCriteria sort_criteria= + Jacobi:: + SORT_DECREASING_EVALS //! + struct VectorRandomInitializer { + public: + static void init(std::vector&); + }; -// @brief Create random vectors used at the beginning of the Lanczos algorithm. -// @note "Partially specialization of function" is not allowed, so -// it is mimicked by wrapping the "init" function with a class template. -template -struct VectorRandomInitializer { -public: - static void init(std::vector&); -}; + template + struct VectorRandomInitializer> { + public: + static void init(std::vector>&); + }; -template -struct VectorRandomInitializer> { -public: - static void init(std::vector>&); -}; - -/// @brief Return the number of significant decimal digits of type T. -template -inline constexpr int sig_decimal_digit() { - return (int)(std::numeric_limits::digits * - std::log10(std::numeric_limits::radix)); -} - -/// @brief Return 10^-n where n=number of significant decimal digits of type T. -template -inline constexpr T minimum_effective_decimal() { - return std::pow(10, -sig_decimal_digit()); -} - - -/// @brief The LambdaLanczos class provides a general way to calculate -/// the smallest or largest eigenvalue and the corresponding eigenvector -/// of a symmetric (Hermitian) matrix using the Lanczos algorithm. -/// The characteristic feature of LambdaLanczos is that the matrix-vector -/// multiplication routine used in the Lanczos algorithm is adaptable. -/// @details -/// @code -/// -/// //Example: -/// const int n = 3; -/// double M[n][n] = { {-1.0, -1.0, 1.0}, -/// {-1.0, 1.0, 1.0}, -/// { 1.0, 1.0, 1.0} }; -/// // (Its eigenvalues are {-2, 1, 2}) -/// -/// // Specify the matrix-vector multiplication function -/// auto mv_mul = [&](const vector& in, vector& out) { -/// for(int i = 0;i < n;i++) { -/// for(int j = 0;j < n;j++) { -/// out[i] += M[i][j]*in[j]; -/// } -/// } -/// }; -/// -/// LambdaLanczos engine(mv_mul, n, true); -/// // ("true" means to calculate the largest eigenvalue.) -/// engine.eigenvalue_offset = 3.0 # = max_i{Σ_j|Mij|} (see below) -/// double eigenvalue; -/// vector eigenvector(n); -/// int itern = engine.run(eigenvalue, eigenvector); -/// -/// cout << "Iteration count: " << itern << endl; -/// cout << "Eigen value: " << setprecision(16) << eigenvalue << endl; -/// cout << "Eigen vector:"; -/// for(int i = 0; i < n; i++) { -/// cout << eigenvector[i] << " "; -/// } -/// cout << endl; -/// -/// @endcode -/// This feature allows you to use a matrix whose elements are partially given, -/// e.g. a sparse matrix whose non-zero elements are stored as a list of -/// {row-index, column-index, value} tuples. You can also easily combine -/// LambdaLanczos with existing matrix libraries (e.g. Eigen) -/// -/// @note -/// If the matrices you want to analyze are ordinary square matrices, (as in -/// the example) it might be easier to use "PEigenDense" instead. (It is a -/// wrapper which takes care of all of the LambdaLanczos details for you.) -/// -/// @note -/// IMPORTANT: -/// The Lanczos algorithm finds the largest magnitude eigenvalue, so you -/// MUST ensure that the eigenvalue you are seeking has the largest magnitude -/// (regardless of whether it is the maximum or minimum eigenvalue). -/// To insure that this is so, you can add or subtract a number to all -/// of the eigenvalues of the matrix by specifying the "eigenvalue_offset". -/// This number should exceed the largest magnitude eigenvalue of the matrix. -/// According to the Gershgorin theorem, you can estimate this number using -/// r = max_i{Σ_j|Mij|} = max_j{Σ_i|Mij|} -/// (where Mij are the elements of the matrix and Σ_j denotes the sum over j). -/// If find_maximum == true (if you are seeking the maximum eigenvalue), then -/// eigenvalue_offset = +r -/// If find_maximum == false, then -/// eigenvalue_offset = -r -/// The eigenvalue_offset MUST be specified by the user. LambdaLanczos does -/// not have an efficient and general way to access the elements of the matrix. -/// -/// (You can omit this step if you are seeking the maximum eigenvalue, -/// and the matrix is positive definite, or if you are seeking the minimum -/// eigenvalue and the matrix is negative definite.) -/// -/// @note -/// LambdaLanczos is available under the MIT license and downloadable at: -/// https://github.com/mrcdr/lambda-lanczos - -template -class LambdaLanczos { -public: - LambdaLanczos(); - LambdaLanczos(std::function&, std::vector&)> mv_mul, int matrix_size, bool find_maximum); - LambdaLanczos(std::function&, std::vector&)> mv_mul, int matrix_size) : LambdaLanczos(mv_mul, matrix_size, true) {} - - /// @brief Calculate the principal (largest or smallest) eigenvalue - /// of the matrix (and its corresponding eigenvector). - int run(real_t&, std::vector&) const; - - // --- public data members --- - - /// @brief Specify the size of the matrix you will analyze. - /// (This equals the size of the eigenvector which will be returned.) - int matrix_size; - - /// @brief Specify the function used for matrix*vector multiplication - /// used by the Lanczos algorithm. For an ordinary dense matrix, - /// this function is the ordinary matrix*vector product. (See the - /// example above. For a sparse matrix, it will be something else.) - std::function&, std::vector&)> mv_mul; - - /// @brief Are we searching for the maximum or minimum eigenvalue? - /// @note (Usually, you must also specify eigenvalue_offset.) - bool find_maximum = false; - - /// @brief Shift all the eigenvalues by "eigenvalue_offset" during the Lanczos - /// iteration (ie. during LambdaLanczos::run()). The goal is to insure - /// that the correct eigenvalue is selected (the one with the maximum - /// magnitude). - /// @note The eigevalue returned by LambdaLanczos::run() is not effected - /// because after the iteration is finished, it will subtract this - /// number from the eigenvalue before it is returned to the caller. - /// @note Unless your matrix is positive definite or negative definite, - /// you MUST specify eigenvalue_offset. See comment above for details. - real_t eigenvalue_offset = 0.0; - - /// @brief This function sets "eigenvalue_offset" automatically. - /// @note Using this function is not recommended because it is very slow. - /// For efficiency, set the "eigenvalue_offset" yourself. - void ChooseOffset(); - - // The remaining data members usually can be left alone: - int max_iteration; - real_t eps = minimum_effective_decimal>() * 1e3; - real_t tridiag_eps_ratio = 1e-1; - int initial_vector_size = 200; - std::function&)> init_vector = - VectorRandomInitializer::init; - - // (for those who prefer "Set" functions...) - int SetSize(int matrix_size); - void SetMul(std::function&, - std::vector&)> mv_mul); - void SetInitVec(std::function&)> init_vector); - void SetFindMax(bool find_maximum); - void SetEvalOffset(T eigenvalue_offset); - void SetEpsilon(T eps); - void SetTriEpsRatio(T tridiag_eps_ratio); - -private: - static void schmidt_orth(std::vector&, const std::vector>&); - real_t find_minimum_eigenvalue(const std::vector>&, - const std::vector>&) const; - real_t find_maximum_eigenvalue(const std::vector>&, - const std::vector>&) const; - static real_t tridiagonal_eigen_limit(const std::vector>&, - const std::vector>&); - static int num_of_eigs_smaller_than(real_t, - const std::vector>&, - const std::vector>&); - real_t UpperBoundEvals() const; -}; - - - -/// @brief -/// PEigenDense is a class containing only one useful member function: -/// PrincipalEigen(). This function calculates the principal (largest -/// or smallest) eigenvalue and corresponding eigenvector of a square -/// n x n matrix. This can be faster than diagionalizing the entire matrix. -/// (For example by using the Lanczos algorithm or something similar.) -/// @note -/// This code is a wrapper. Internally, it uses the "LambdaLanczos" class. -/// @note -/// For matrices larger than 13x13, PEigenDense::PrincipleEigen() -/// is usually faster than Jacobi::Diagonalize().) - -template -class PEigenDense -{ - size_t n; // the size of the matrix - std::vector evec; // preallocated vector - -public: - void SetSize(int matrix_size) { - n = matrix_size; - evec.resize(n); + /// @brief Return the number of significant decimal digits of type T. + template + inline constexpr int sig_decimal_digit() { + return (int)(std::numeric_limits::digits * + std::log10(std::numeric_limits::radix)); } - PEigenDense(int matrix_size=0):evec(matrix_size) { - SetSize(matrix_size); + /// @brief Return 10^-n where n=number of significant decimal digits of type T. + template + inline constexpr T minimum_effective_decimal() { + return std::pow(10, -sig_decimal_digit()); } - /// @brief Calculate the principal eigenvalue and eigenvector of a matrix. - /// @return Return the principal eigenvalue of the matrix. - /// If you want the eigenvector, pass a non-null "evector" argument. - Scalar - PrincipalEigen(ConstMatrix matrix, //!< the input patrix - Vector evector, //!< the eigenvector is stored here - bool find_max=false); //!< want the max or min eigenvalue? -}; // class PEigenDense + /// @class LambdaLanczos + /// @brief The LambdaLanczos class provides a general way to calculate + /// the smallest or largest eigenvalue and the corresponding eigenvector + /// of a symmetric (Hermitian) matrix using the Lanczos algorithm. + /// The characteristic feature of LambdaLanczos is that the matrix-vector + /// multiplication routine used in the Lanczos algorithm is adaptable. + /// @details + /// @code + /// + /// //Example: + /// const int n = 3; + /// double M[n][n] = { {-1.0, -1.0, 1.0}, + /// {-1.0, 1.0, 1.0}, + /// { 1.0, 1.0, 1.0} }; + /// // (Its eigenvalues are {-2, 1, 2}) + /// + /// // Specify the matrix-vector multiplication function + /// auto mv_mul = [&](const vector& in, vector& out) { + /// for(int i = 0;i < n;i++) { + /// for(int j = 0;j < n;j++) { + /// out[i] += M[i][j]*in[j]; + /// } + /// } + /// }; + /// + /// LambdaLanczos engine(mv_mul, n, true); + /// // ("true" means to calculate the largest eigenvalue.) + /// engine.eigenvalue_offset = 3.0; // = max_i{Σ_j|Mij|} (see below) + /// + /// double eigenvalue; //(must never be a complex number even if M is complex) + /// vector eigenvector(n); + /// + /// int itern = engine.run(eigenvalue, eigenvector); + /// + /// cout << "Iteration count: " << itern << endl; + /// cout << "Eigen value: " << setprecision(16) << eigenvalue << endl; + /// cout << "Eigen vector:"; + /// for(int i = 0; i < n; i++) { + /// cout << eigenvector[i] << " "; + /// } + /// cout << endl; + /// + /// @endcode + /// This feature allows you to use a matrix whose elements are partially given, + /// e.g. a sparse matrix whose non-zero elements are stored as a list of + /// {row-index, column-index, value} tuples. You can also easily combine + /// LambdaLanczos with existing matrix libraries (e.g. Eigen) + /// + /// @note + /// If the matrices you want to analyze are ordinary square matrices, (as in + /// the example) it might be easier to use "PEigenDense" instead. (It is a + /// wrapper which takes care of all of the LambdaLanczos details for you.) + /// + /// @note + /// IMPORTANT: + /// The Lanczos algorithm finds the largest magnitude eigenvalue, so you + /// MUST ensure that the eigenvalue you are seeking has the largest magnitude + /// (regardless of whether it is the maximum or minimum eigenvalue). + /// To insure that this is so, you can add or subtract a number to all + /// of the eigenvalues of the matrix by specifying the "eigenvalue_offset". + /// This number should exceed the largest magnitude eigenvalue of the matrix. + /// According to the Gershgorin theorem, you can estimate this number using + /// r = max_i{Σ_j|Mij|} = max_j{Σ_i|Mij|} + /// (where Mij are the elements of the matrix and Σ_j denotes the sum over j). + /// If find_maximum == true (if you are seeking the maximum eigenvalue), then + /// eigenvalue_offset = +r + /// If find_maximum == false, then + /// eigenvalue_offset = -r + /// The eigenvalue_offset MUST be specified by the user. LambdaLanczos does + /// not have an efficient and general way to access the elements of the matrix. + /// + /// (You can omit this step if you are seeking the maximum eigenvalue, + /// and the matrix is positive definite, or if you are seeking the minimum + /// eigenvalue and the matrix is negative definite.) + /// + /// @note + /// LambdaLanczos is available under the MIT license and downloadable at: + /// https://github.com/mrcdr/lambda-lanczos + + template + class LambdaLanczos { + public: + LambdaLanczos(); + LambdaLanczos(std::function&, std::vector&)> mv_mul, int matrix_size, bool find_maximum); + LambdaLanczos(std::function&, std::vector&)> mv_mul, int matrix_size) : LambdaLanczos(mv_mul, matrix_size, true) {} + + /// @brief Calculate the principal (largest or smallest) eigenvalue + /// of the matrix (and its corresponding eigenvector). + int run(real_t&, std::vector&) const; + + // --- public data members --- + + /// @brief Specify the size of the matrix you will analyze. + /// (This equals the size of the eigenvector which will be returned.) + int matrix_size; + + /// @brief Specify the function used for matrix*vector multiplication + /// used by the Lanczos algorithm. For an ordinary dense matrix, + /// this function is the ordinary matrix*vector product. (See the + /// example above. For a sparse matrix, it will be something else.) + std::function&, std::vector&)> mv_mul; + + /// @brief Are we searching for the maximum or minimum eigenvalue? + /// @note (Usually, you must also specify eigenvalue_offset.) + bool find_maximum = false; + + /// @brief Shift all the eigenvalues by "eigenvalue_offset" during the Lanczos + /// iteration (ie. during LambdaLanczos::run()). The goal is to insure + /// that the correct eigenvalue is selected (the one with the maximum + /// magnitude). + /// @note The eigevalue returned by LambdaLanczos::run() is not effected + /// because after the iteration is finished, it will subtract this + /// number from the eigenvalue before it is returned to the caller. + /// @note Unless your matrix is positive definite or negative definite, + /// you MUST specify eigenvalue_offset. See comment above for details. + real_t eigenvalue_offset = 0.0; + + /// @brief This function sets "eigenvalue_offset" automatically. + /// @note Using this function is not recommended because it is very slow. + /// For efficiency, set the "eigenvalue_offset" yourself. + void ChooseOffset(); + + // The remaining data members usually can be left alone: + int max_iteration; + real_t eps = minimum_effective_decimal>() * 1e3; + real_t tridiag_eps_ratio = 1e-1; + int initial_vector_size = 200; + std::function&)> init_vector = + VectorRandomInitializer::init; + + // (for those who prefer "Set" functions...) + int SetSize(int matrix_size); + void SetMul(std::function&, + std::vector&)> mv_mul); + void SetInitVec(std::function&)> init_vector); + void SetFindMax(bool find_maximum); + void SetEvalOffset(T eigenvalue_offset); + void SetEpsilon(T eps); + void SetTriEpsRatio(T tridiag_eps_ratio); + + private: + static void schmidt_orth(std::vector&, const std::vector>&); + real_t find_minimum_eigenvalue(const std::vector>&, + const std::vector>&) const; + real_t find_maximum_eigenvalue(const std::vector>&, + const std::vector>&) const; + static real_t tridiagonal_eigen_limit(const std::vector>&, + const std::vector>&); + static int num_of_eigs_smaller_than(real_t, + const std::vector>&, + const std::vector>&); + real_t UpperBoundEvals() const; + }; + + + + /// @class PEigenDense + /// @brief + /// PEigenDense is a class containing only one useful member function: + /// PrincipalEigen(). This function calculates the principal (largest + /// or smallest) eigenvalue and corresponding eigenvector of a square + /// n x n matrix. This can be faster than diagionalizing the entire matrix. + /// (For example by using the Lanczos algorithm or something similar.) + /// @note + /// This code is a wrapper. Internally, it uses the "LambdaLanczos" class. + /// @note + /// For dense matrices smaller than 13x13, Jacobi::Diagonalize(), + /// is usually faster than PEigenDense::PrincipleEigen(). + /// @details + /// Usage example: + /// @code + /// + /// const int n = 100; + /// + /// PEigenDense pe(n); + /// + /// double **M; // A symmetric n x n matrix you want to diagonalize + /// double evect[n]; // Store the principal eigenvector here. + /// + /// // Now, allocate space for M and load it's contents. (omitted) + /// + /// double eval = pe.PrincipalEigen(M, evect, true); //Returns the max eval + /// + /// @endcode + + template + class PEigenDense + { + size_t n; // the size of the matrix + std::vector evec; // preallocated vector + + public: + PEigenDense(int matrix_size=0); + + /// @brief Calculate the principal eigenvalue and eigenvector of a matrix. + /// @return Return the principal eigenvalue of the matrix. + /// If you want the eigenvector, pass a non-null "evector" argument. + Scalar + PrincipalEigen(ConstMatrix matrix, //!< the input patrix + Vector evector, //!< the eigenvector is stored here + bool find_max=false); //!< want the max or min eigenvalue? + + void SetSize(int matrix_size); //change matrix size after instantiation + + }; // class PEigenDense @@ -460,16 +527,13 @@ public: // ----------- IMPLEMENTATION ----------- // -------------------------------------- - - - // --- Implementation: Memory allocation for matrices --- template void Alloc2D(size_t nrows, // size of the array (number of rows) size_t ncols, // size of the array (number of columns) Entry ***paaX) // pointer to a 2D C-style array { - assert(paaX); + //assert(paaX); *paaX = new Entry* [nrows]; //conventional 2D C array (pointer-to-pointer) (*paaX)[0] = new Entry [nrows * ncols]; // 1D C array (contiguous memor) for(size_t iy=0; iy l1_norm(const std::vector& vec) { // --- Implementation: Eigendecomposition of small dense matrices --- +template +Jacobi:: +Jacobi(int n, Scalar **workspace) { + Init(); + if (workspace) { + is_M_preallocated = true; + M = workspace; + this->n = n; + } + else { + is_M_preallocated = false; + SetSize(n); + } +} + +template +Jacobi:: +~Jacobi() { + if (! is_M_preallocated) + Dealloc(); +} + template int Jacobi:: Diagonalize(ConstMatrix mat, // the matrix you wish to diagonalize (size n) @@ -602,7 +688,7 @@ Diagonalize(ConstMatrix mat, // the matrix you wish to diagonalize (size n) // Optional: Sort results by eigenvalue. SortRows(eval, evec, n, sort_criteria); - return n_iters / (n*(n-1)/2); //returns the number of "sweeps" (converged?) + return (n_iters == max_num_iters); } @@ -634,7 +720,7 @@ CalcRot(Scalar const *const *M, //!< matrix t = -t; } } - assert(std::abs(t) <= 1.0); + //assert(std::abs(t) <= 1.0); c = 1.0 / std::sqrt(1 + t*t); s = c*t; } @@ -699,7 +785,7 @@ ApplyRot(Scalar **M, // matrix M[j][j] += t * M[i][j]; //Update the off-diagonal elements of M which will change (above the diagonal) - assert(i < j); + //assert(i < j); M[i][j] = 0.0; //compute M[w][i] and M[i][w] for all w!=i,considering above-diagonal elements @@ -887,7 +973,7 @@ Jacobi(const Jacobi& source) { Init(); SetSize(source.n); - assert(n == source.n); + //assert(n == source.n); // The following lines aren't really necessary, because the contents // of source.M and source.max_idx_row are not needed (since they are // overwritten every time Jacobi::Diagonalize() is invoked). @@ -912,8 +998,8 @@ swap(Jacobi &other) { template Jacobi:: Jacobi(Jacobi&& other) { - Init(); - swap(*this, other); + Init(); + this->swap(other); } // Using the "copy-swap" idiom for the assignment operator @@ -955,8 +1041,8 @@ template inline int LambdaLanczos:: run(real_t& eigvalue, std::vector& eigvec) const { - assert(matrix_size > 0); - assert(0 < this->tridiag_eps_ratio && this->tridiag_eps_ratio < 1); + //assert(matrix_size > 0); + //assert(0 < this->tridiag_eps_ratio && this->tridiag_eps_ratio < 1); std::vector> u; // Lanczos vectors std::vector> alpha; // Diagonal elements of an approximated tridiagonal matrix @@ -1321,13 +1407,26 @@ init(std::vector>& v) // --- Implementation of PEigenDense +template +void PEigenDense:: +SetSize(int matrix_size) { + n = matrix_size; + evec.resize(n); +} + +template +PEigenDense:: +PEigenDense(int matrix_size):evec(matrix_size) { + SetSize(matrix_size); +} + template Scalar PEigenDense:: PrincipalEigen(ConstMatrix matrix, Vector eigenvector, bool find_max) { - assert(n > 0); + //assert(n > 0); auto matmul = [&](const std::vector& in, std::vector& out) { for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { @@ -1373,8 +1472,12 @@ PrincipalEigen(ConstMatrix matrix, return eval; } - } //namespace MathEigen -#endif //#ifndef _MATH_EIGEN_H + + + + + +#endif //#ifndef LMP_MATH_EIGEN_H diff --git a/src/math_extra.cpp b/src/math_extra.cpp index b04414a300..a7a8a98a90 100644 --- a/src/math_extra.cpp +++ b/src/math_extra.cpp @@ -19,8 +19,6 @@ #include #include -#define MAXJACOBI 50 - namespace MathExtra { /* ---------------------------------------------------------------------- @@ -92,88 +90,6 @@ int mldivide3(const double m[3][3], const double *v, double *ans) return 0; } -/* ---------------------------------------------------------------------- - compute evalues and evectors of 3x3 real symmetric matrix - based on Jacobi rotations - adapted from Numerical Recipes jacobi() function -------------------------------------------------------------------------- */ - -int jacobi(double matrix[3][3], double *evalues, double evectors[3][3]) -{ - int i,j,k; - double tresh,theta,tau,t,sm,s,h,g,c,b[3],z[3]; - - for (i = 0; i < 3; i++) { - for (j = 0; j < 3; j++) evectors[i][j] = 0.0; - evectors[i][i] = 1.0; - } - for (i = 0; i < 3; i++) { - b[i] = evalues[i] = matrix[i][i]; - z[i] = 0.0; - } - - for (int iter = 1; iter <= MAXJACOBI; iter++) { - sm = 0.0; - for (i = 0; i < 2; i++) - for (j = i+1; j < 3; j++) - sm += fabs(matrix[i][j]); - if (sm == 0.0) return 0; - - if (iter < 4) tresh = 0.2*sm/(3*3); - else tresh = 0.0; - - for (i = 0; i < 2; i++) { - for (j = i+1; j < 3; j++) { - g = 100.0*fabs(matrix[i][j]); - if (iter > 4 && fabs(evalues[i])+g == fabs(evalues[i]) - && fabs(evalues[j])+g == fabs(evalues[j])) - matrix[i][j] = 0.0; - else if (fabs(matrix[i][j]) > tresh) { - h = evalues[j]-evalues[i]; - if (fabs(h)+g == fabs(h)) t = (matrix[i][j])/h; - else { - theta = 0.5*h/(matrix[i][j]); - t = 1.0/(fabs(theta)+sqrt(1.0+theta*theta)); - if (theta < 0.0) t = -t; - } - c = 1.0/sqrt(1.0+t*t); - s = t*c; - tau = s/(1.0+c); - h = t*matrix[i][j]; - z[i] -= h; - z[j] += h; - evalues[i] -= h; - evalues[j] += h; - matrix[i][j] = 0.0; - for (k = 0; k < i; k++) rotate(matrix,k,i,k,j,s,tau); - for (k = i+1; k < j; k++) rotate(matrix,i,k,k,j,s,tau); - for (k = j+1; k < 3; k++) rotate(matrix,i,k,j,k,s,tau); - for (k = 0; k < 3; k++) rotate(evectors,k,i,k,j,s,tau); - } - } - } - - for (i = 0; i < 3; i++) { - evalues[i] = b[i] += z[i]; - z[i] = 0.0; - } - } - return 1; -} - -/* ---------------------------------------------------------------------- - perform a single Jacobi rotation -------------------------------------------------------------------------- */ - -void rotate(double matrix[3][3], int i, int j, int k, int l, - double s, double tau) -{ - double g = matrix[i][j]; - double h = matrix[k][l]; - matrix[i][j] = g-s*(h+g*tau); - matrix[k][l] = h+s*(g-h*tau); -} - /* ---------------------------------------------------------------------- Richardson iteration to update quaternion from angular momentum return new normalized quaternion q diff --git a/src/math_extra.h b/src/math_extra.h index a818bae4f4..6c58bc93c2 100644 --- a/src/math_extra.h +++ b/src/math_extra.h @@ -85,7 +85,6 @@ namespace MathExtra { void write3(const double mat[3][3]); int mldivide3(const double mat[3][3], const double *vec, double *ans); - int jacobi(double matrix[3][3], double *evalues, double evectors[3][3]); void rotate(double matrix[3][3], int i, int j, int k, int l, double s, double tau); void richardson(double *q, double *m, double *w, double *moments, double dtq); diff --git a/src/molecule.cpp b/src/molecule.cpp index 18f5c38992..9042bf0521 100644 --- a/src/molecule.cpp +++ b/src/molecule.cpp @@ -23,6 +23,7 @@ #include "comm.h" #include "domain.h" #include "math_extra.h" +#include "math_eigen.h" #include "memory.h" #include "error.h" #include "utils.h" @@ -350,7 +351,7 @@ void Molecule::compute_inertia() tensor[0][2] = tensor[2][0] = itensor[4]; tensor[0][1] = tensor[1][0] = itensor[5]; - if (MathExtra::jacobi(tensor,inertia,evectors)) + if (MathEigen::jacobi3(tensor,inertia,evectors)) error->all(FLERR,"Insufficient Jacobi rotations for rigid molecule"); ex[0] = evectors[0][0]; From 58fa72ddc560fd81cf87d30303a21bdbf785443b Mon Sep 17 00:00:00 2001 From: Andrew Jewett Date: Sat, 5 Sep 2020 10:19:19 -0700 Subject: [PATCH 03/28] replaced all numerical recipes jacobi() code with code from "math_eigen.h". moved "math_eigen.h" into the main "src" directory. --- lib/colvars/colvartypes.cpp | 197 ++++++++++++++++++++++++++++++++++-- lib/colvars/colvartypes.h | 14 ++- 2 files changed, 194 insertions(+), 17 deletions(-) diff --git a/lib/colvars/colvartypes.cpp b/lib/colvars/colvartypes.cpp index 460eec06ac..da00183323 100644 --- a/lib/colvars/colvartypes.cpp +++ b/lib/colvars/colvartypes.cpp @@ -10,7 +10,6 @@ #include #include -#include "jacobi_pd.h" #include "colvarmodule.h" #include "colvartypes.h" #include "colvarparse.h" @@ -20,6 +19,20 @@ bool colvarmodule::rotation::monitor_crossings = false; cvm::real colvarmodule::rotation::crossing_threshold = 1.0E-02; +namespace { + +/// Numerical recipes diagonalization +static int jacobi(cvm::real **a, cvm::real *d, cvm::real **v, int *nrot); + +/// Eigenvector sort +static int eigsrt(cvm::real *d, cvm::real **v); + +/// Transpose the matrix +static int transpose(cvm::real **v); + +} + + std::string cvm::rvector::to_simple_string() const { std::ostringstream os; @@ -278,6 +291,43 @@ void colvarmodule::rotation::compute_overlap_matrix() } +void colvarmodule::rotation::diagonalize_matrix( + cvm::matrix2d &m, + cvm::vector1d &eigval, + cvm::matrix2d &eigvec) +{ + eigval.resize(4); + eigval.reset(); + eigvec.resize(4, 4); + eigvec.reset(); + + // diagonalize + int jac_nrot = 0; + if (jacobi(m.c_array(), eigval.c_array(), eigvec.c_array(), &jac_nrot) != + COLVARS_OK) { + cvm::error("Too many iterations in routine jacobi.\n" + "This is usually the result of an ill-defined set of atoms for " + "rotational alignment (RMSD, rotateReference, etc).\n"); + } + eigsrt(eigval.c_array(), eigvec.c_array()); + // jacobi saves eigenvectors by columns + transpose(eigvec.c_array()); + + // normalize eigenvectors + for (size_t ie = 0; ie < 4; ie++) { + cvm::real norm2 = 0.0; + size_t i; + for (i = 0; i < 4; i++) { + norm2 += eigvec[ie][i] * eigvec[ie][i]; + } + cvm::real const norm = cvm::sqrt(norm2); + for (i = 0; i < 4; i++) { + eigvec[ie][i] /= norm; + } + } +} + + // Calculate the rotation, plus its derivatives void colvarmodule::rotation::calc_optimal_rotation( @@ -299,13 +349,7 @@ void colvarmodule::rotation::calc_optimal_rotation( cvm::log("S = "+cvm::to_str(S_backup, cvm::cv_width, cvm::cv_prec)+"\n"); } - int ierror = ecalc.Diagonalize(S, S_eigval, S_eigvec); - if (ierror) { - cvm::error("Too many iterations in routine jacobi.\n" - "This is usually the result of an ill-defined set of atoms for " - "rotational alignment (RMSD, rotateReference, etc).\n"); - } - + diagonalize_matrix(S, S_eigval, S_eigvec); // eigenvalues and eigenvectors cvm::real const L0 = S_eigval[0]; cvm::real const L1 = S_eigval[1]; @@ -477,7 +521,7 @@ void colvarmodule::rotation::calc_optimal_rotation( // cvm::log("S_new = "+cvm::to_str(cvm::to_str (S_new), cvm::cv_width, cvm::cv_prec)+"\n"); - ecalc.Diagonalize(S_new, S_new_eigval, S_new_eigvec); + diagonalize_matrix(S_new, S_new_eigval, S_new_eigvec); cvm::real const &L0_new = S_new_eigval[0]; cvm::quaternion const Q0_new(S_new_eigvec[0]); @@ -500,3 +544,138 @@ void colvarmodule::rotation::calc_optimal_rotation( +// Numerical Recipes routine for diagonalization + +#define ROTATE(a,i,j,k,l) g=a[i][j]; \ + h=a[k][l]; \ + a[i][j]=g-s*(h+g*tau); \ + a[k][l]=h+s*(g-h*tau); + +#define n 4 + + +namespace { + +int jacobi(cvm::real **a, cvm::real *d, cvm::real **v, int *nrot) +{ + int j,iq,ip,i; + cvm::real tresh,theta,tau,t,sm,s,h,g,c; + + cvm::vector1d b(n); + cvm::vector1d z(n); + + for (ip=0;ip 4 && (cvm::real)(cvm::fabs(d[ip])+g) == (cvm::real)cvm::fabs(d[ip]) + && (cvm::real)(cvm::fabs(d[iq])+g) == (cvm::real)cvm::fabs(d[iq])) + a[ip][iq]=0.0; + else if (cvm::fabs(a[ip][iq]) > tresh) { + h=d[iq]-d[ip]; + if ((cvm::real)(cvm::fabs(h)+g) == (cvm::real)cvm::fabs(h)) + t=(a[ip][iq])/h; + else { + theta=0.5*h/(a[ip][iq]); + t=1.0/(cvm::fabs(theta)+cvm::sqrt(1.0+theta*theta)); + if (theta < 0.0) t = -t; + } + c=1.0/cvm::sqrt(1+t*t); + s=t*c; + tau=s/(1.0+c); + h=t*a[ip][iq]; + z[ip] -= h; + z[iq] += h; + d[ip] -= h; + d[iq] += h; + a[ip][iq]=0.0; + for (j=0;j<=ip-1;j++) { + ROTATE(a,j,ip,j,iq) + } + for (j=ip+1;j<=iq-1;j++) { + ROTATE(a,ip,j,j,iq) + } + for (j=iq+1;j= p) p=d[k=j]; + if (k != i) { + d[k]=d[i]; + d[i]=p; + for (j=0;j -#include "jacobi_pd.h" #include "colvarmodule.h" #ifndef PI @@ -1391,20 +1390,19 @@ public: /// Default constructor inline rotation() - : b_debug_gradients(false), ecalc(4) + : b_debug_gradients(false) {} /// Constructor after a quaternion inline rotation(cvm::quaternion const &qi) : q(qi), - b_debug_gradients(false), - ecalc(4) + b_debug_gradients(false) { } /// Constructor after an axis of rotation and an angle (in radians) inline rotation(cvm::real angle, cvm::rvector const &axis) - : b_debug_gradients(false), ecalc(4) + : b_debug_gradients(false) { cvm::rvector const axis_n = axis.unit(); cvm::real const sina = cvm::sin(angle/2.0); @@ -1540,9 +1538,9 @@ protected: void compute_overlap_matrix(); /// Diagonalize a given matrix m (used by calc_optimal_rotation()) - MathEigen::Jacobi &, - cvm::matrix2d &> ecalc; + static void diagonalize_matrix(cvm::matrix2d &m, + cvm::vector1d &eigval, + cvm::matrix2d &eigvec); }; From 4b66414bdf20ffa6f369665c5d3b7fdd973daa7d Mon Sep 17 00:00:00 2001 From: Andrew Jewett Date: Sat, 5 Sep 2020 10:38:14 -0700 Subject: [PATCH 04/28] fixed a type error in math_eigen.h --- src/math_eigen.cpp | 8 ++++---- src/math_eigen.h | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/math_eigen.cpp b/src/math_eigen.cpp index b86b626309..18ca97200b 100644 --- a/src/math_eigen.cpp +++ b/src/math_eigen.cpp @@ -107,10 +107,10 @@ jacobi3(double const mat[3][3], // the 3x3 matrix you wish to diagonalize 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? +jacobi3(double const* 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::SortCriteria sort_criteria) { diff --git a/src/math_eigen.h b/src/math_eigen.h index 3a697584d7..17d234f0b9 100644 --- a/src/math_eigen.h +++ b/src/math_eigen.h @@ -242,7 +242,7 @@ namespace MathEigen { /// @note /// When invoked using default arguments, this function is a stand-in for /// the the version of "jacobi()" that was defined in "POEMS/fix_poems.cpp". - int jacobi3(double const **mat, + int jacobi3(double const* const* mat, double *eval, double **evec, // optional arguments: @@ -599,7 +599,6 @@ inline void normalize(std::vector& vec) { scalar_mul(1.0/l2_norm(vec), vec); } - template inline real_t l1_norm(const std::vector& vec) { real_t norm = real_t(); // Zero initialization @@ -628,6 +627,7 @@ Jacobi(int n, Scalar **workspace) { } } + template Jacobi:: ~Jacobi() { @@ -635,6 +635,7 @@ Jacobi:: Dealloc(); } + template int Jacobi:: Diagonalize(ConstMatrix mat, // the matrix you wish to diagonalize (size n) From 7cb774e6bc0afc74ad3d932d187c08a6d55e819f Mon Sep 17 00:00:00 2001 From: Andrew Jewett Date: Sat, 5 Sep 2020 16:37:15 -0700 Subject: [PATCH 05/28] some corrections before rewriting the doxygen comments to comply with LAMMPS doxygen style. --- doc/doxygen/Doxyfile.in | 1 + src/math_eigen.h | 54 +++++++++++++++++++++++------------------ 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/doc/doxygen/Doxyfile.in b/doc/doxygen/Doxyfile.in index 9acd994a68..ee34b77355 100644 --- a/doc/doxygen/Doxyfile.in +++ b/doc/doxygen/Doxyfile.in @@ -424,6 +424,7 @@ INPUT = @LAMMPS_SOURCE_DIR@/utils.cpp \ @LAMMPS_SOURCE_DIR@/input.h \ @LAMMPS_SOURCE_DIR@/tokenizer.cpp \ @LAMMPS_SOURCE_DIR@/tokenizer.h \ + @LAMMPS_SOURCE_DIR@/math_eigen.h \ @LAMMPS_SOURCE_DIR@/text_file_reader.cpp \ @LAMMPS_SOURCE_DIR@/text_file_reader.h \ @LAMMPS_SOURCE_DIR@/potential_file_reader.cpp \ diff --git a/src/math_eigen.h b/src/math_eigen.h index 17d234f0b9..f7ceb1126d 100644 --- a/src/math_eigen.h +++ b/src/math_eigen.h @@ -66,21 +66,30 @@ namespace MathEigen { void Dealloc2D(Entry ***paaX); //!< pointer to 2D multidimensional array // --- Complex numbers --- - - /// @brief "realTypeMap" struct is used to the define "real_t" type mapper - /// which returns the C++ type corresponding to the real component of T. - /// @details Consider a function ("l2_norm()") that calculates the - /// (Euclidian) length of a vector of numbers (either real or complex): + /// @brief + /// The "realTypeMap" struct is used to the define "real_t" type mapper. + /// The "real_t" type mapper is used by the "LambdaLanczos" and "PEigenDense" + /// classes, so it is documented here to help users understand those classes. + /// "real_t" returns the C++ type corresponding to the real component of T. + /// @details + /// For example, suppose you have a matrix of type std::complex **. + /// The eigenvalues calculated by "LambdaLanczos" and "PEigenDense" should be + /// of type "double" (which is the same as "real_T>"), + /// (This is because the algorithm assumes the matrix is Hermetian, and the + /// eigenvalues of a Hermetian matrix are always real. + /// So if you attempt to pass a reference to a complex number as the first + /// argument to LambdaLanczos::run(), the compiler will complain.) + /// For a simpler example, consider a function ("l2_norm()") that calculates + /// the (Euclidian) length of a vector of numbers (either real or complex): /// @code /// template real_t l2_norm(const std::vector& vec); /// @endcode - /// The l2_norm is always real by definition. + /// Since it is a "length", the l2_norm is always real by definition. /// (See https://en.wikipedia.org/wiki/Norm_(mathematics)#Euclidean_norm) - /// The return type of this function ("real_t") indicates that - /// it returns a real number, even if the entries (of type T) - /// are complex numbers. In other words, by default, real_t returns T. - /// However real_t> returns T (not std::complex). - /// We define "real_t" below using C++ template specializations: + /// The return type of this function ("real_t") indicates that it returns + /// a real number, even if the entries (of type T) are complex numbers. + /// (Implementation details: "real_t" is defined using C++ template + /// specializations.) template struct realTypeMap { @@ -265,15 +274,15 @@ namespace MathEigen { /// @note /// When invoked using default arguments, this function is a stand-in for /// the previous version of "jacobi()" that was declared in "math_extra.h". - int 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=true, //!< ...as columns or as rows? + int jacobi3(double const mat[3][3], + double *eval, + double evec[3][3], // optional arguments: + bool evec_as_columns=true, Jacobi:: SortCriteria sort_criteria= Jacobi:: - SORT_DECREASING_EVALS //! eigenvalue_offset = 0.0; /// @brief This function sets "eigenvalue_offset" automatically. @@ -445,7 +453,7 @@ namespace MathEigen { std::function&)> init_vector = VectorRandomInitializer::init; - // (for those who prefer "Set" functions...) + // (for those who prefer using "Set" functions...) int SetSize(int matrix_size); void SetMul(std::function&, std::vector&)> mv_mul); @@ -512,7 +520,7 @@ namespace MathEigen { /// @brief Calculate the principal eigenvalue and eigenvector of a matrix. /// @return Return the principal eigenvalue of the matrix. /// If you want the eigenvector, pass a non-null "evector" argument. - Scalar + real_t PrincipalEigen(ConstMatrix matrix, //!< the input patrix Vector evector, //!< the eigenvector is stored here bool find_max=false); //!< want the max or min eigenvalue? @@ -1422,7 +1430,7 @@ PEigenDense(int matrix_size):evec(matrix_size) { } template -Scalar PEigenDense:: +real_t PEigenDense:: PrincipalEigen(ConstMatrix matrix, Vector eigenvector, bool find_max) From 4ad6d99ca00d2343a05b69987d623e5c69b0092a Mon Sep 17 00:00:00 2001 From: Andrew Jewett Date: Sat, 5 Sep 2020 20:08:45 -0700 Subject: [PATCH 06/28] updated documentation files: "pg_developer.rst", "math_eigen.h", and "false_positives.txt" --- doc/src/pg_developer.rst | 193 +++++++++++++++ doc/utils/sphinx-config/false_positives.txt | 45 ++++ src/math_eigen.h | 247 ++++++-------------- 3 files changed, 304 insertions(+), 181 deletions(-) diff --git a/doc/src/pg_developer.rst b/doc/src/pg_developer.rst index b6fb10e37b..ab9b2295ac 100644 --- a/doc/src/pg_developer.rst +++ b/doc/src/pg_developer.rst @@ -1086,3 +1086,196 @@ A file that would be parsed by the reader code fragment looks like this: :project: progguide :members: +Eigensolver classes +=============================================================== + +The "math_eigen.h" file contains the definition of 3 template classes +used for calculating eigenvalues and eigenvectors of matrices: +"Jacobi", "PeigenDense", and "LambdaLanczos". + +"Jacobi" calculates all of the eigenvalues and eigenvectors +of a dense, symmetric, real matrix. + +The "PEigenDense" class only calculates the principal eigenvalue +(ie. the largest or smallest eigenvalue), and its corresponding eigenvector. +However it is much more efficient than "Jacobi" when applied to large matrices +(larger than 13x13). PEigenDense also can understand complex-valued +Hermitian matrices. + +The "LambdaLanczos" class is a generalization of "PEigenDense" which can be +applied to arbitrary sparse matrices. + +Together, these matrix eigensolvers cover a fairly wide range of use cases. + +Note: The code described here does not take advantage of parallelization. +(It is assumed that the matrices are small enough +that they can be diagonalized using individual CPU cores.) + +.. code-block:: C++ + :caption: Jacobi usage example + + #include "math_eigen.h" + using namespace MathEigen; + + int n = 5; // Matrix size + double **M; // A symmetric n x n matrix you want to diagonalize + double *evals; // Store the eigenvalues here. + double **evects; // Store the eigenvectors here. + // Allocate space for M, evals, and evects, and load contents of M (omitted) + + // Now create an instance of Jacobi ("eigen_calc"). This will allocate space + // for storing intermediate calculations. Once created, it can be reused + // multiple times without paying the cost of allocating memory on the heap. + + Jacobi eigen_calc(n); + + // Note: + // If the matrix you plan to diagonalize (M) is read-only, use this instead: + // Jacobi eigen_calc(n); + + // Now, calculate the eigenvalues and eigenvectors of M + eigen_calc.Diagonalize(M, evals, evects); + +The Jacobi class is not limited to double** matrices. It works on any C or C++ +object that supports indexing using [i][j] bracket notation. +For example, if you prefer using std::vectors, then define a +Jacobi instance this way instead: + +.. code-block:: C++ + :caption: Jacobi std::vector example + + Jacobi&, vector>&, const vector>&> eigen_calc(n); + + +The PEigenDense class is useful for diagonalizing larger matrices +which can be real (symmetric) or complex-valued (Hermitian): + +.. code-block:: C++ + :caption: PEigenDense usage example + + #include "math_eigen.h" + using namespace MathEigen; + + const int n = 100; + + PEigenDense pe(n); + + double **M; // A symmetric n x n matrix you want to diagonalize + double evect[n]; // Store the principal eigenvector here. + + // Now, allocate space for M and load it's contents. (omitted) + + double eval = pe.PrincipalEigen(M, evect, true); + + // This calculates only the maximum eigenvalue and its eigenvector + + +The "LambdaLanczos" class generalizes "PEigenDense" by allowing the user +to diagonalize arbitrary sparse matrices. The "LambdaLanczos" class +does not need to know how the matrices are implemented or stored in memory. +Instead, users supply a function as an argument to the "LambdaLanczos" +constructor (a lambda expression) that multiplies vectors by matrices. The +specific implementation details are never revealed to the LambdaLanczos class. +This allows users to choose arbitrary data structures to represent +(sparse or dense) matrices. + +Note: If the matrix is not positive or negative definite, +then user must specify an "eigenvalue_offset" parameter. (See below.) + +Note: Both "LambdaLanczos" and "PEigenDense" use the Lanczos algorithm. + +.. code-block:: C++ + :caption: LambdaLanczos usage example + + #include "math_eigen.h" + using namespace MathEigen; + + const int n = 3; + double M[n][n] = { {-1.0, -1.0, 1.0}, + {-1.0, 1.0, 1.0}, + { 1.0, 1.0, 1.0} }; + // (Its eigenvalues are {-2, 1, 2}) + + // Specify the matrix-vector multiplication function + auto mv_mul = [&](const vector& in, vector& out) { + for(int i = 0;i < n;i++) { + for(int j = 0;j < n;j++) { + out[i] += M[i][j]*in[j]; + } + } + }; + + LambdaLanczos engine(mv_mul, n, true); + //(Setting 3rd arg (find_maximum) to true calculates the largest eigenvalue.) + + engine.eigenvalue_offset = 3.0; // = max_i{Σ_j|Mij|} (see below) + + double eigenvalue; //(must never be a complex number, even if M is complex) + vector eigenvector(n); + + int itern = engine.run(eigenvalue, eigenvector); + + cout << "Iteration count: " << itern << endl; + cout << "Eigenvalue: " << eigenvalue << endl; + cout << "Eigenvector:"; + for(int i = 0; i < n; i++) { + cout << eigenvector[i] << " "; + } + cout << endl; + +In this example, an small dense square matrix was used for simplicity. +One could however, implement a large sparse matrix whose elements are +stored as a list of {row-index, column-index, value} tuples, +and modify the "mv_mult" function accordingly. + + +IMPORTANT: +The Lanczos algorithm finds the largest magnitude eigenvalue, so you +MUST ensure that the eigenvalue you are seeking has the largest magnitude +(regardless of whether it is the maximum or minimum eigenvalue). +To insure that this is so, you can add or subtract a number to all +of the eigenvalues of the matrix by specifying the "eigenvalue_offset". +This number should exceed the largest magnitude eigenvalue of the matrix. +According to the Gershgorin theorem, you can estimate this number using + +r = max_i{Σ_j|Mij|} +or +r = max_j{Σ_i|Mij|} + +(where Mij are the elements of the matrix and Σ_j denotes the sum over j). + +If you are seeking the maximum eigenvalue, then use: + + eigenvalue_offset = +r + +If you are seeking the minimum eigenvalue, use: + + eigenvalue_offset = -r + +You can omit this step if you are seeking the maximum eigenvalue, +and the matrix is positive definite, or if you are seeking the minimum +eigenvalue and the matrix is negative definite.) +Otherwise, for dense (or mostly-dense) matrices, you can use the +"ChooseOffset()" member function to pick the eigenvalue_offset automatically. +Otherwise, the eigenvalue_offset MUST be specified by the user explicitly. +(LambdaLanczos is ignorant of the way the matrix is implemented internally, +so it does not have an efficient and general way to access the +elements of a sparse matrix.) + +---------- + +.. doxygenclass:: MathEigen::Jacobi + :project: progguide + :members: + +.. doxygenclass:: MathEigen::PEigenDense + :project: progguide + :members: + +.. doxygenclass:: MathEigen::LambdaLanczos + :project: progguide + :members: + +.. doxygenstruct:: MathEigen::realTypeMap + :project: progguide + :members: diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index 6a4ffa465f..ff10797b8d 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -325,6 +325,7 @@ Buyl Bybee bz cadetblue +calc calibre caltech Caltech @@ -639,7 +640,10 @@ dhex dia diag diagonalization +diagonalize diagonalized +diagonalizers +diagonalizing Diallo diel differentiable @@ -779,7 +783,13 @@ ehex eHEX Ei Eigen +eigen +Eigendecomposition Eigensolve +eigenvalue +eigenvalues +eigenvector +eigenvectors eij Eij Eijnden @@ -893,6 +903,11 @@ eV evalue Evanseck evdwl +evector +evec +evecs +eval +evals Everaers Evgeny evirials @@ -1068,6 +1083,7 @@ Germann Germano gerolf Gerolf +Gershgorin gettimeofday gewald Gezelter @@ -1183,6 +1199,7 @@ Henkelman Henkes henrich Henrich +Hermitian Herrmann Hertizian hertzian @@ -1255,6 +1272,7 @@ icosahedral idealgas IDR idx +ie ielement ieni ifdefs @@ -1345,6 +1363,8 @@ isothermal isotropically isovolume Isralewitz +iter +iters iteratively Ith Itsets @@ -1536,6 +1556,7 @@ LAMMPS lammpsplot Lampis Lamoureux +Lanczos Lande Landron langevin @@ -1841,6 +1862,7 @@ Microscale midnightblue mie Mie +Mij Mikami Militzer Minary @@ -1939,6 +1961,7 @@ Muccioli mui Mukherjee Mulders +mult multi multibody Multibody @@ -3455,3 +3478,25 @@ zz Zm PowerShell filesystems +ε +σ +Σ +π +δ +Δ +θ +Θ +φ +Φ +Ψ +ψ +ρ +β +ω +Ω +κ +τ +λ +γ +μ +ν diff --git a/src/math_eigen.h b/src/math_eigen.h index f7ceb1126d..9492ec001a 100644 --- a/src/math_eigen.h +++ b/src/math_eigen.h @@ -19,26 +19,26 @@ #ifndef LMP_MATH_EIGEN_H #define LMP_MATH_EIGEN_H -/// @file This file contains a library of functions and classes which can -/// efficiently perform eigendecomposition for an extremely broad -/// range of matrix types: both real and complex, dense and sparse. -/// Matrices need not be of type "double **", for example. -/// In principle, almost any type of C++ container can be used. -/// Some general C++11 compatible functions for allocating matrices and -/// calculating norms of real and complex vectors are also provided. -/// @note -/// The "Jacobi" and "PEigenDense" classes are used for calculating -/// eigenvalues and eigenvectors of conventional dense square matrices. -/// @note -/// The "LambdaLanczos" class can calculate eigenalues and eigenvectors -/// of more general types of matrices, especially large, sparse matrices. -/// It uses C++ lambda expressions to simplify and generalize the way -/// matrices can be represented. This allows it to be applied to -/// nearly any kind of sparse (or dense) matrix representation. -/// @note -/// The source code for Jacobi and LambdaLanczos is also available at: -/// https://github.com/jewettaij/jacobi_pd (CC0-1.0 license) -/// https://github.com/mrcdr/lambda-lanczos (MIT license) +// This file contains a library of functions and classes which can +// efficiently perform eigendecomposition for an extremely broad +// range of matrix types: both real and complex, dense and sparse. +// Matrices need not be of type "double **", for example. +// In principle, almost any type of C++ container can be used. +// Some general C++11 compatible functions for allocating matrices and +// calculating norms of real and complex vectors are also provided. +// note +// The "Jacobi" and "PEigenDense" classes are used for calculating +// eigenvalues and eigenvectors of conventional dense square matrices. +// note +// The "LambdaLanczos" class can calculate eigenalues and eigenvectors +// of more general types of matrices, especially large, sparse matrices. +// It uses C++ lambda expressions to simplify and generalize the way +// matrices can be represented. This allows it to be applied to +// nearly any kind of sparse (or dense) matrix representation. +// note +// The source code for Jacobi and LambdaLanczos is also available at: +// https://github.com/jewettaij/jacobi_pd (CC0-1.0 license) +// https://github.com/mrcdr/lambda-lanczos (MIT license) //#include #include @@ -53,43 +53,37 @@ namespace MathEigen { // --- Memory allocation for matrices --- - /// @brief Allocate an arbitrary 2-dimensional array. (Uses row-major order.) - /// @note This function was intended for relatively small matrices (eg 4x4). - /// For large arrays, please use the 2d create() function from "memory.h" + // Allocate an arbitrary 2-dimensional array. (Uses row-major order.) + // note This function was intended for relatively small matrices (eg 4x4). + // For large arrays, please use the 2d create() function from "memory.h" template - void Alloc2D(size_t nrows, //!< size of the array (number of rows) - size_t ncols, //!< size of the array (number of columns) - Entry ***paaX); //!< pointer to a 2D C-style array + void Alloc2D(size_t nrows, // size of the array (number of rows) + size_t ncols, // size of the array (number of columns) + Entry ***paaX); // pointer to a 2D C-style array - /// @brief Deallocate arrays that were created using Alloc2D(). + // Deallocate arrays that were created using Alloc2D(). template - void Dealloc2D(Entry ***paaX); //!< pointer to 2D multidimensional array + void Dealloc2D(Entry ***paaX); // pointer to 2D multidimensional array // --- Complex numbers --- + /// @brief - /// The "realTypeMap" struct is used to the define "real_t" type mapper. + /// "realTypeMap" struct is used to the define "real_t" type mapper. /// The "real_t" type mapper is used by the "LambdaLanczos" and "PEigenDense" /// classes, so it is documented here to help users understand those classes. /// "real_t" returns the C++ type corresponding to the real component of T. + /// /// @details - /// For example, suppose you have a matrix of type std::complex **. + /// For example, suppose you have a matrix of type std::complex**. /// The eigenvalues calculated by "LambdaLanczos" and "PEigenDense" should be /// of type "double" (which is the same as "real_T>"), - /// (This is because the algorithm assumes the matrix is Hermetian, and the - /// eigenvalues of a Hermetian matrix are always real. - /// So if you attempt to pass a reference to a complex number as the first - /// argument to LambdaLanczos::run(), the compiler will complain.) - /// For a simpler example, consider a function ("l2_norm()") that calculates - /// the (Euclidian) length of a vector of numbers (either real or complex): - /// @code - /// template real_t l2_norm(const std::vector& vec); - /// @endcode - /// Since it is a "length", the l2_norm is always real by definition. - /// (See https://en.wikipedia.org/wiki/Norm_(mathematics)#Euclidean_norm) - /// The return type of this function ("real_t") indicates that it returns - /// a real number, even if the entries (of type T) are complex numbers. - /// (Implementation details: "real_t" is defined using C++ template - /// specializations.) + /// not "std::complex". (This is because the algorithm assumes the + /// matrix is Hermitian, and the eigenvalues of a Hermitian matrix are always + /// real. So if you attempt to pass a reference to a complex number as the + /// first argument to LambdaLanczos::run(), the compiler will complain.) + /// + /// Implementation details: "real_t" is defined using C++ template + /// specializations. template struct realTypeMap { @@ -105,65 +99,38 @@ namespace MathEigen { // --- Operations on vectors (of real and complex numbers) --- - /// @brief Calculate the inner product of two vectors. - /// (For vectors of complex numbers, std::conj() is used.) + // Calculate the inner product of two vectors. + // (For vectors of complex numbers, std::conj() is used.) template T inner_prod(const std::vector& v1, const std::vector& v2); - /// @brief Compute the sum of the absolute values of the entries in v - /// @returns a real number (of type real_t). + // Compute the sum of the absolute values of the entries in v + // returns a real number (of type real_t). template real_t l1_norm(const std::vector& v); - /// @brief Calculate the l2_norm (Euclidian length) of vector v. - /// @returns a real number (of type real_t). + // Calculate the l2_norm (Euclidian length) of vector v. + // returns a real number (of type real_t). template real_t l2_norm(const std::vector& v); - /// @brief Multiply a vector (v) by a scalar (c). + /// Multiply a vector (v) by a scalar (c). template void scalar_mul(T1 c, std::vector& v); - /// @brief Divide vector "v" in-place by it's length (l2_norm(v)). + /// Divide vector "v" in-place by it's length (l2_norm(v)). template void normalize(std::vector& v); // ---- Eigendecomposition of small dense symmetric matrices ---- /// @class Jacobi - /// @brief Calculate the eigenvalues and eigevectors of a symmetric matrix - /// using the Jacobi eigenvalue algorithm. Code for the Jacobi class - /// (along with tests and benchmarks) is available free of copyright at + /// @brief Calculate the eigenvalues and eigenvectors of a symmetric matrix + /// using the Jacobi eigenvalue algorithm. This code (along with tests + /// and benchmarks) is available free of license restrictions at: /// https://github.com/jewettaij/jacobi_pd - /// @note The "Vector" and "Matrix" type arguments can be any - /// C or C++ object that support indexing, including pointers or vectors. - /// @details - /// Usage example: - /// @code - /// - /// int n = 5; // Matrix size - /// double **M; // A symmetric n x n matrix you want to diagonalize - /// double *evals; // Store the eigenvalues here. - /// double **evects; // Store the eigenvectors here. - /// // Allocate space for M, evals, and evects, and load contents of M (omitted) - /// - /// // Now create an instance of Jacobi ("eigen_calc"). This will allocate space - /// // for storing intermediate calculations. Once created, it can be reused - /// // multiple times without paying the cost of allocating memory on the heap. - /// - /// Jacobi eigen_calc(n); - /// - /// // Note: - /// // If the matrix you plan to diagonalize (M) is read-only, use this instead: - /// // Jacobi eigen_calc(n); - /// // If you prefer using vectors over C-style pointers, this works also: - /// // Jacobi&, vector>&> eigen_calc(n); - /// - /// // Now, calculate the eigenvalues and eigenvectors of M - /// - /// eigen_calc.Diagonalize(M, evals, evects); - /// - /// @endcode + /// @note The "Vector", "Matrix", and "ConstMatrix" type arguments can be any + /// C or C++ object that supports indexing, including pointers or vectors. template struct VectorRandomInitializer { @@ -310,14 +272,14 @@ namespace MathEigen { static void init(std::vector>&); }; - /// @brief Return the number of significant decimal digits of type T. + // Return the number of significant decimal digits of type T. template inline constexpr int sig_decimal_digit() { return (int)(std::numeric_limits::digits * std::log10(std::numeric_limits::radix)); } - /// @brief Return 10^-n where n=number of significant decimal digits of type T. + // Return 10^-n where n=number of significant decimal digits of type T. template inline constexpr T minimum_effective_decimal() { return std::pow(10, -sig_decimal_digit()); @@ -327,50 +289,11 @@ namespace MathEigen { /// @class LambdaLanczos /// @brief The LambdaLanczos class provides a general way to calculate /// the smallest or largest eigenvalue and the corresponding eigenvector - /// of a symmetric (Hermitian) matrix using the Lanczos algorithm. + /// of a Hermitian matrix using the Lanczos algorithm. /// The characteristic feature of LambdaLanczos is that the matrix-vector /// multiplication routine used in the Lanczos algorithm is adaptable. - /// @details - /// @code - /// - /// //Example: - /// const int n = 3; - /// double M[n][n] = { {-1.0, -1.0, 1.0}, - /// {-1.0, 1.0, 1.0}, - /// { 1.0, 1.0, 1.0} }; - /// // (Its eigenvalues are {-2, 1, 2}) - /// - /// // Specify the matrix-vector multiplication function - /// auto mv_mul = [&](const vector& in, vector& out) { - /// for(int i = 0;i < n;i++) { - /// for(int j = 0;j < n;j++) { - /// out[i] += M[i][j]*in[j]; - /// } - /// } - /// }; - /// - /// LambdaLanczos engine(mv_mul, n, true); - /// // ("true" means to calculate the largest eigenvalue.) - /// engine.eigenvalue_offset = 3.0; // = max_i{Σ_j|Mij|} (see below) - /// - /// double eigenvalue; //(must never be a complex number even if M is complex) - /// vector eigenvector(n); - /// - /// int itern = engine.run(eigenvalue, eigenvector); - /// - /// cout << "Iteration count: " << itern << endl; - /// cout << "Eigen value: " << setprecision(16) << eigenvalue << endl; - /// cout << "Eigen vector:"; - /// for(int i = 0; i < n; i++) { - /// cout << eigenvector[i] << " "; - /// } - /// cout << endl; - /// - /// @endcode - /// This feature allows you to use a matrix whose elements are partially given, - /// e.g. a sparse matrix whose non-zero elements are stored as a list of - /// {row-index, column-index, value} tuples. You can also easily combine - /// LambdaLanczos with existing matrix libraries (e.g. Eigen) + /// This code (along with automatic unit tests) is also distributed + /// under the MIT license at https://github.com/mrcdr/lambda-lanczos /// /// @note /// If the matrices you want to analyze are ordinary square matrices, (as in @@ -379,29 +302,8 @@ namespace MathEigen { /// /// @note /// IMPORTANT: - /// The Lanczos algorithm finds the largest magnitude eigenvalue, so you - /// MUST ensure that the eigenvalue you are seeking has the largest magnitude - /// (regardless of whether it is the maximum or minimum eigenvalue). - /// To insure that this is so, you can add or subtract a number to all - /// of the eigenvalues of the matrix by specifying the "eigenvalue_offset". - /// This number should exceed the largest magnitude eigenvalue of the matrix. - /// According to the Gershgorin theorem, you can estimate this number using - /// r = max_i{Σ_j|Mij|} = max_j{Σ_i|Mij|} - /// (where Mij are the elements of the matrix and Σ_j denotes the sum over j). - /// If find_maximum == true (if you are seeking the maximum eigenvalue), then - /// eigenvalue_offset = +r - /// If find_maximum == false, then - /// eigenvalue_offset = -r - /// The eigenvalue_offset MUST be specified by the user. LambdaLanczos does - /// not have an efficient and general way to access the elements of the matrix. - /// - /// (You can omit this step if you are seeking the maximum eigenvalue, - /// and the matrix is positive definite, or if you are seeking the minimum - /// eigenvalue and the matrix is negative definite.) - /// - /// @note - /// LambdaLanczos is available under the MIT license and downloadable at: - /// https://github.com/mrcdr/lambda-lanczos + /// Unless the matrix you are solving is positive or negative definite, you + /// MUST set the "eigenvalue_offset" parameter. See the "pg_developer" docs. template class LambdaLanczos { @@ -484,29 +386,12 @@ namespace MathEigen { /// PEigenDense is a class containing only one useful member function: /// PrincipalEigen(). This function calculates the principal (largest /// or smallest) eigenvalue and corresponding eigenvector of a square - /// n x n matrix. This can be faster than diagionalizing the entire matrix. - /// (For example by using the Lanczos algorithm or something similar.) + /// n x n matrix. This can be faster than diagonalizing the entire matrix. /// @note /// This code is a wrapper. Internally, it uses the "LambdaLanczos" class. /// @note /// For dense matrices smaller than 13x13, Jacobi::Diagonalize(), /// is usually faster than PEigenDense::PrincipleEigen(). - /// @details - /// Usage example: - /// @code - /// - /// const int n = 100; - /// - /// PEigenDense pe(n); - /// - /// double **M; // A symmetric n x n matrix you want to diagonalize - /// double evect[n]; // Store the principal eigenvector here. - /// - /// // Now, allocate space for M and load it's contents. (omitted) - /// - /// double eval = pe.PrincipalEigen(M, evect, true); //Returns the max eval - /// - /// @endcode template class PEigenDense @@ -521,7 +406,7 @@ namespace MathEigen { /// @return Return the principal eigenvalue of the matrix. /// If you want the eigenvector, pass a non-null "evector" argument. real_t - PrincipalEigen(ConstMatrix matrix, //!< the input patrix + PrincipalEigen(ConstMatrix matrix, //!< the input matrix Vector evector, //!< the eigenvector is stored here bool find_max=false); //!< want the max or min eigenvalue? @@ -1028,7 +913,7 @@ template inline LambdaLanczos::LambdaLanczos() { this->matrix_size = 0; this->max_iteration = 0; - this->find_maximum = 0; + this->find_maximum = false; } From c16321e9d3f8361bcc53cda9aa36939671d7eb35 Mon Sep 17 00:00:00 2001 From: Andrew Jewett Date: Sat, 5 Sep 2020 21:44:32 -0700 Subject: [PATCH 07/28] purged greek characters from "pd_developer.rst" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I replaced the 'Σ' character that was causing problems with PDF generation with the word "sum". Hopefully PDF documentation generation works now. --- doc/src/pg_developer.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/src/pg_developer.rst b/doc/src/pg_developer.rst index ab9b2295ac..8d15aa0e6f 100644 --- a/doc/src/pg_developer.rst +++ b/doc/src/pg_developer.rst @@ -1208,7 +1208,7 @@ Note: Both "LambdaLanczos" and "PEigenDense" use the Lanczos algorithm. LambdaLanczos engine(mv_mul, n, true); //(Setting 3rd arg (find_maximum) to true calculates the largest eigenvalue.) - engine.eigenvalue_offset = 3.0; // = max_i{Σ_j|Mij|} (see below) + engine.eigenvalue_offset = 3.0; // = max_i{sum_j|Mij|} (see below) double eigenvalue; //(must never be a complex number, even if M is complex) vector eigenvector(n); @@ -1238,11 +1238,11 @@ of the eigenvalues of the matrix by specifying the "eigenvalue_offset". This number should exceed the largest magnitude eigenvalue of the matrix. According to the Gershgorin theorem, you can estimate this number using -r = max_i{Σ_j|Mij|} +r = max_i{sum_j|Mij|} or -r = max_j{Σ_i|Mij|} +r = max_j{sum_i|Mij|} -(where Mij are the elements of the matrix and Σ_j denotes the sum over j). +(where Mij are the elements of the matrix and sum_j denotes the sum over j). If you are seeking the maximum eigenvalue, then use: From 2ee200935677bef6be3eebcb0d840e33018c13cd Mon Sep 17 00:00:00 2001 From: Andrew Jewett Date: Sun, 6 Sep 2020 02:30:20 -0700 Subject: [PATCH 08/28] removed assert() statements from "superpose3d.h" --- src/USER-REACTION/superpose3d.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/USER-REACTION/superpose3d.h b/src/USER-REACTION/superpose3d.h index e61e8e0c93..63c5bf5de8 100644 --- a/src/USER-REACTION/superpose3d.h +++ b/src/USER-REACTION/superpose3d.h @@ -144,11 +144,6 @@ Superpose(ConstArrayOfCoords aaXf, // coords for the "frozen" object ConstArrayOfCoords aaXm, // coords for the "mobile" object bool allow_rescale) // rescale mobile object? (c!=1?) { - assert(aaXf && aaXm); - assert(aaXf_shifted && aaXm_shifted); - assert(aWeights); - assert(R && T); - // Find the center of mass of each object: Scalar aCenter_f[3] = {0.0, 0.0, 0.0}; Scalar aCenter_m[3] = {0.0, 0.0, 0.0}; @@ -161,7 +156,9 @@ Superpose(ConstArrayOfCoords aaXf, // coords for the "frozen" object } sum_weights += weight; } - assert(sum_weights != 0.0); + + //assert(sum_weights != 0.0); + for (int d=0; d < 3; d++) { aCenter_f[d] /= sum_weights; aCenter_m[d] /= sum_weights; @@ -425,7 +422,9 @@ Superpose3D(const Superpose3D& source) { Init(); Alloc(source.N); - assert(N == source.N); + + //assert(N == source.N); + for (int i = 0; i < N; i++) { std::copy(source.aaXf_shifted[i], source.aaXf_shifted[i] + 3, From b29522273a5a0add3fac4af6411d645cd567a7a3 Mon Sep 17 00:00:00 2001 From: Andrew Jewett Date: Sun, 6 Sep 2020 09:40:28 -0700 Subject: [PATCH 09/28] changed the "trim_and_count_words()" function declaration in "utils.h" to make sphinx happy. Fixed some new spelling mistakes. --- doc/src/pg_developer.rst | 4 ++-- doc/utils/sphinx-config/false_positives.txt | 15 ++++++++++++--- src/math_eigen.cpp | 1 - src/math_eigen.h | 2 +- src/utils.h | 9 ++++++++- 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/doc/src/pg_developer.rst b/doc/src/pg_developer.rst index 8d15aa0e6f..05b254ee52 100644 --- a/doc/src/pg_developer.rst +++ b/doc/src/pg_developer.rst @@ -827,7 +827,7 @@ and parsing files or arguments. .. doxygenfunction:: count_words(const std::string &text, const std::string &separators) :project: progguide -.. doxygenfunction:: trim_and_count_words +.. doxygenfunction:: trim_and_count_words(const std::string &text, const std::string &separators) :project: progguide .. doxygenfunction:: split_words @@ -1091,7 +1091,7 @@ Eigensolver classes The "math_eigen.h" file contains the definition of 3 template classes used for calculating eigenvalues and eigenvectors of matrices: -"Jacobi", "PeigenDense", and "LambdaLanczos". +"Jacobi", "PEigenDense", and "LambdaLanczos". "Jacobi" calculates all of the eigenvalues and eigenvectors of a dense, symmetric, real matrix. diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index ff10797b8d..5dd4ea3b1b 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -398,6 +398,7 @@ ChiralIDs chiralIDs chirality Cho +ChooseOffset chris Christoph Chu @@ -470,6 +471,7 @@ config configfile configurational conformational +ConstMatrix Contrib cooperativity coord @@ -782,10 +784,11 @@ Eggebrecht ehex eHEX Ei -Eigen eigen -Eigendecomposition -Eigensolve +eigensolve +eigensolver +eigensolvers +eigendecomposition eigenvalue eigenvalues eigenvector @@ -1550,6 +1553,7 @@ Ladd lagrangian lambdai lamda +LambdaLanczos lammps Lammps LAMMPS @@ -2346,6 +2350,7 @@ peachpuff Pearlman Pedersen peID +PEigenDense Peng peptide peratom @@ -2574,6 +2579,8 @@ rdf RDideal rdx reacter +realTypeMap +real_t README realtime reamin @@ -3146,6 +3153,8 @@ tu Tuckerman tue tunable +tuple +tuples Turkand Tutein tweakable diff --git a/src/math_eigen.cpp b/src/math_eigen.cpp index 18ca97200b..9255338e09 100644 --- a/src/math_eigen.cpp +++ b/src/math_eigen.cpp @@ -137,4 +137,3 @@ jacobi3(double const* const* mat, // the 3x3 matrix you wish to diagonalize return ierror; } - diff --git a/src/math_eigen.h b/src/math_eigen.h index 9492ec001a..a0bd292263 100644 --- a/src/math_eigen.h +++ b/src/math_eigen.h @@ -892,7 +892,7 @@ swap(Jacobi &other) { template Jacobi:: Jacobi(Jacobi&& other) { - Init(); + Init(); this->swap(other); } diff --git a/src/utils.h b/src/utils.h index a06be39e28..7ab3e7876e 100644 --- a/src/utils.h +++ b/src/utils.h @@ -236,7 +236,14 @@ namespace LAMMPS_NS { * \param separators string containing characters that will be treated as whitespace * \return number of words found */ - size_t trim_and_count_words(const std::string &text, const std::string &separators = " \t\r\n\f"); + size_t trim_and_count_words(const std::string &text, const std::string &separators); + + /** This version sets the separators argument to " \t\r\n\f" by default + */ + size_t trim_and_count_words(const std::string &text) { + std::string separators = " \t\r\n\f"; + return trim_and_count_words(text, separators); + } /** Take text and split into non-whitespace words. * From d97e8d8cbf2179aab858b50c2599bc2e376bad38 Mon Sep 17 00:00:00 2001 From: Andrew Jewett Date: Sun, 6 Sep 2020 10:12:07 -0700 Subject: [PATCH 10/28] fixed linker problems in "utils.h" and "utils.cpp" --- src/utils.cpp | 5 +++++ src/utils.h | 5 +---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/utils.cpp b/src/utils.cpp index 45bd629c19..7bf56e1ada 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -625,6 +625,11 @@ size_t utils::trim_and_count_words(const std::string &text, const std::string &s return utils::count_words(utils::trim_comment(text), separators); } +size_t utils::trim_and_count_words(const std::string &text) { + std::string separators = " \t\r\n\f"; + return trim_and_count_words(text, separators); +} + /* ---------------------------------------------------------------------- Convert string into words on whitespace while handling single and double quotes. diff --git a/src/utils.h b/src/utils.h index 7ab3e7876e..fa47059bf2 100644 --- a/src/utils.h +++ b/src/utils.h @@ -240,10 +240,7 @@ namespace LAMMPS_NS { /** This version sets the separators argument to " \t\r\n\f" by default */ - size_t trim_and_count_words(const std::string &text) { - std::string separators = " \t\r\n\f"; - return trim_and_count_words(text, separators); - } + size_t trim_and_count_words(const std::string &text); /** Take text and split into non-whitespace words. * From fabf762fa8a14c1ea32ee45996fe609cd32bc5f3 Mon Sep 17 00:00:00 2001 From: Andrew Jewett Date: Sun, 6 Sep 2020 11:09:36 -0700 Subject: [PATCH 11/28] reverting to previous version of util.h and util.cpp --- src/utils.cpp | 5 ----- src/utils.h | 6 +----- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/utils.cpp b/src/utils.cpp index 07560e9a20..af800f48b0 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -625,11 +625,6 @@ size_t utils::trim_and_count_words(const std::string &text, const std::string &s return utils::count_words(utils::trim_comment(text), separators); } -size_t utils::trim_and_count_words(const std::string &text) { - std::string separators = " \t\r\n\f"; - return trim_and_count_words(text, separators); -} - /* ---------------------------------------------------------------------- Convert string into words on whitespace while handling single and double quotes. diff --git a/src/utils.h b/src/utils.h index cc4dd28824..026f46955f 100644 --- a/src/utils.h +++ b/src/utils.h @@ -236,11 +236,7 @@ namespace LAMMPS_NS { * \param separators string containing characters that will be treated as whitespace * \return number of words found */ - size_t trim_and_count_words(const std::string &text, const std::string &separators); - - /** This version sets the separators argument to " \t\r\n\f" by default - */ - size_t trim_and_count_words(const std::string &text); + size_t trim_and_count_words(const std::string &text, const std::string &separators = " \t\r\n\f"); /** Take text and split into non-whitespace words. * From a57a1404f3db3640a78ef217be431f3744c19aa6 Mon Sep 17 00:00:00 2001 From: Andrew Jewett Date: Sun, 6 Sep 2020 20:05:47 -0700 Subject: [PATCH 12/28] bug fix fix unit tests, improve doc readability, and to prevent accidentally allocating memory on the heap. (Note: All of these changes are related to "jacobi3()". That function instantiates Jacobi without allocating memory on the heap, and this created some headaches. The original code at https://github/jewettaij/jacobi_pd does not have this feature, and the unit tests there do not test for these kinds of errors. Hopefully this commit fixes everything.) --- doc/src/pg_developer.rst | 3 -- src/math_eigen.cpp | 16 ++++++---- src/math_eigen.h | 69 +++++++++++++++++++++++++++++++--------- 3 files changed, 64 insertions(+), 24 deletions(-) diff --git a/doc/src/pg_developer.rst b/doc/src/pg_developer.rst index d67b69a80c..4f58eeec6b 100644 --- a/doc/src/pg_developer.rst +++ b/doc/src/pg_developer.rst @@ -1286,6 +1286,3 @@ elements of a sparse matrix.) :project: progguide :members: -.. doxygenstruct:: MathEigen::realTypeMap - :project: progguide - :members: diff --git a/src/math_eigen.cpp b/src/math_eigen.cpp index 9255338e09..9e98a161b6 100644 --- a/src/math_eigen.cpp +++ b/src/math_eigen.cpp @@ -90,16 +90,18 @@ jacobi3(double const mat[3][3], // the 3x3 matrix you wish to diagonalize {mat[2][0], mat[2][1], mat[2][2]} }; double *M[3] = { &(mat_cpy[0][0]), &(mat_cpy[1][0]), &(mat_cpy[2][0]) }; + int midx[3]; // (another array which is preallocated to avoid using the heap) + // variable "ecalc3" does all the work: - Jacobi ecalc3(3,M); + Jacobi ecalc3(3, M, midx); 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]); + for (int j=i+1; j<3; j++) + std::swap(evec[i][j], evec[j][i]); // transpose the evec matrix return ierror; } @@ -124,16 +126,18 @@ jacobi3(double const* const* mat, // the 3x3 matrix you wish to diagonalize {mat[2][0], mat[2][1], mat[2][2]} }; double *M[3] = { &(mat_cpy[0][0]), &(mat_cpy[1][0]), &(mat_cpy[2][0]) }; + int midx[3]; // (another array which is preallocated to avoid using the heap) + // variable "ecalc3" does all the work: - Jacobi ecalc3(3,M); + Jacobi ecalc3(3, M, midx); 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]); + for (int j=i+1; j<3; j++) + std::swap(evec[i][j], evec[j][i]); // transpose the evec matrix return ierror; } diff --git a/src/math_eigen.h b/src/math_eigen.h index a0bd292263..8bb61111f3 100644 --- a/src/math_eigen.h +++ b/src/math_eigen.h @@ -150,9 +150,7 @@ namespace MathEigen { public: /// @brief Specify the size of the matrices you want to diagonalize later. /// @param n the size (ie. number of rows) of the (square) matrix. - /// @param workspace optional array for storing intermediate calculations - /// (The vast majority of users can ignore this argument.) - Jacobi(int n = 0, Scalar **workspace=nullptr); + Jacobi(int n); ~Jacobi(); @@ -185,9 +183,25 @@ namespace MathEigen { int max_num_sweeps=50 //!< limit the number of iterations ); + // An alternative constructor is provided, if, for some reason, + // you want to avoid allocating memory on the heap during + // initialization. In that case, you can allocate space for the "M" + // and "max_idx_row" arrays on the stack in advance, and pass them + // to the constructor. (The vast majority of users probably + // do not need this feature. Unless you do, I encourage you + // to use the regular constructor instead.) + // n the size (ie. number of rows) of the (square) matrix. + // M optional preallocated n x n array + // max_idx_row optional preallocated array of size n + // note If either the "M" or "max_idx_row" arguments are specified, + // they both must be specified. + Jacobi(int n, Scalar **M, int *max_idx_row); + private: - bool is_M_preallocated; + bool is_preallocated; + // (Descriptions of private functions can be found in their implementation.) + void _Jacobi(int n, Scalar **M, int *max_idx_row); void CalcRot(Scalar const *const *M, int i, int j); void ApplyRot(Scalar **M, int i, int j); void ApplyRotLeft(Matrix E, int i, int j); @@ -240,9 +254,9 @@ namespace MathEigen { double *eval, double evec[3][3], // optional arguments: - bool evec_as_columns=true, + bool evec_as_columns = true, Jacobi:: - SortCriteria sort_criteria= + SortCriteria sort_criteria = Jacobi:: SORT_DECREASING_EVALS ); @@ -505,18 +519,40 @@ inline real_t l1_norm(const std::vector& vec) { // --- Implementation: Eigendecomposition of small dense matrices --- + template Jacobi:: -Jacobi(int n, Scalar **workspace) { +Jacobi(int n) { + _Jacobi(n, nullptr, nullptr); +} + + +template +Jacobi:: +Jacobi(int n, Scalar **M, int *max_idx_row) { + _Jacobi(n, M, max_idx_row); +} + + +// _Jacobi() is a function which is invoked by the two constructors and it +// does all of the work. (Splitting the constructor into multiple functions +// was technically unnecessary, but it makes documenting the code easier.) + +template +void +Jacobi:: +_Jacobi(int n, Scalar **M, int *max_idx_row) { Init(); - if (workspace) { - is_M_preallocated = true; - M = workspace; + if (M) { // if caller supplies their own "M" array, don't allocate M + is_preallocated = true; this->n = n; + this->M = M; + this->max_idx_row = max_idx_row; + //assert(this->max_idx_row); } else { - is_M_preallocated = false; - SetSize(n); + is_preallocated = false; + SetSize(n); // allocate the "M" and "max_int_row" arrays } } @@ -524,7 +560,7 @@ Jacobi(int n, Scalar **workspace) { template Jacobi:: ~Jacobi() { - if (! is_M_preallocated) + if (! is_preallocated) Dealloc(); } @@ -829,6 +865,7 @@ Init() { n = 0; M = nullptr; max_idx_row = nullptr; + is_preallocated = false; } template @@ -843,6 +880,7 @@ SetSize(int n) { template void Jacobi:: Alloc(int n) { + //assert(! is_preallocated); this->n = n; if (n > 0) { max_idx_row = new int[n]; @@ -853,8 +891,7 @@ Alloc(int n) { template void Jacobi:: Dealloc() { - if (max_idx_row) - delete [] max_idx_row; + //assert(! is_preallocated); Dealloc2D(&M); Init(); } @@ -867,6 +904,7 @@ Jacobi(const Jacobi& source) { Init(); SetSize(source.n); + //assert(n == source.n); // The following lines aren't really necessary, because the contents // of source.M and source.max_idx_row are not needed (since they are @@ -884,6 +922,7 @@ template void Jacobi:: swap(Jacobi &other) { std::swap(n, other.n); + std::swap(is_preallocated, other.is_preallocated); std::swap(max_idx_row, other.max_idx_row); std::swap(M, other.M); } From f329d56495ae458732d409aa4454f30ebe56d17a Mon Sep 17 00:00:00 2001 From: Andrew Jewett Date: Sun, 6 Sep 2020 20:12:38 -0700 Subject: [PATCH 13/28] updated pg_developer.rst --- doc/src/pg_developer.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/pg_developer.rst b/doc/src/pg_developer.rst index 4f58eeec6b..6b818676aa 100644 --- a/doc/src/pg_developer.rst +++ b/doc/src/pg_developer.rst @@ -834,7 +834,7 @@ and parsing files or arguments. .. doxygenfunction:: count_words(const std::string &text, const std::string &separators) :project: progguide -.. doxygenfunction:: trim_and_count_words(const std::string &text, const std::string &separators) +.. doxygenfunction:: trim_and_count_words :project: progguide .. doxygenfunction:: split_words From 6ade5dd74095430f0730a8dc9d73ff1fb7e49ad0 Mon Sep 17 00:00:00 2001 From: Andrew Jewett Date: Tue, 8 Sep 2020 17:05:08 -0700 Subject: [PATCH 14/28] changed the default sorting options in "jacobi3()" to be more similar to the original "jacobi()" function from "math_extra.h". This should not have any effect on LAMMPS behavior --- src/math_eigen.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/math_eigen.h b/src/math_eigen.h index 8bb61111f3..21ec5904f8 100644 --- a/src/math_eigen.h +++ b/src/math_eigen.h @@ -240,7 +240,7 @@ namespace MathEigen { Jacobi:: SortCriteria sort_criteria = Jacobi:: - SORT_DECREASING_EVALS + DO_NOT_SORT ); @@ -258,7 +258,7 @@ namespace MathEigen { Jacobi:: SortCriteria sort_criteria = Jacobi:: - SORT_DECREASING_EVALS + DO_NOT_SORT ); From 56b1300fd350e3e38df9f4432088442fea549486 Mon Sep 17 00:00:00 2001 From: Andrew Jewett Date: Tue, 8 Sep 2020 21:58:54 -0700 Subject: [PATCH 15/28] reverted the default behavior of "jacobi3()". By default it now sorts the eigenvalues again. --- src/math_eigen.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/math_eigen.h b/src/math_eigen.h index 21ec5904f8..8bb61111f3 100644 --- a/src/math_eigen.h +++ b/src/math_eigen.h @@ -240,7 +240,7 @@ namespace MathEigen { Jacobi:: SortCriteria sort_criteria = Jacobi:: - DO_NOT_SORT + SORT_DECREASING_EVALS ); @@ -258,7 +258,7 @@ namespace MathEigen { Jacobi:: SortCriteria sort_criteria = Jacobi:: - DO_NOT_SORT + SORT_DECREASING_EVALS ); From 2ab0878c9e68016cbb5085a15bef938a5a70557b Mon Sep 17 00:00:00 2001 From: Andrew Jewett Date: Wed, 9 Sep 2020 14:43:28 -0700 Subject: [PATCH 16/28] remreduced compile time by removing unnecessary instantiations from math_eigen.cpp --- src/math_eigen.cpp | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/math_eigen.cpp b/src/math_eigen.cpp index 9e98a161b6..2caa6414d1 100644 --- a/src/math_eigen.cpp +++ b/src/math_eigen.cpp @@ -48,25 +48,7 @@ template class MathEigen::PEigenDense&, const vector >&>; -// ----------------- now create instances for floats ---------------- - -template class MathEigen::Jacobi; -template class MathEigen::Jacobi; -template class MathEigen::Jacobi&, - vector >&, - const vector >& >; -template class MathEigen::Jacobi&, - array, 3 >&, - const array, 3 >& >; -template class MathEigen::LambdaLanczos; -template class MathEigen::PEigenDense; -template class MathEigen::PEigenDense&, - const vector >&>; - -// If you plan to use other numeric types, add them below... +// If you plan to use other numeric types (eg floats), add them to this list. From ed14793c69605fa33e926d2566ef4dd1194e82f0 Mon Sep 17 00:00:00 2001 From: Andrew Jewett Date: Wed, 9 Sep 2020 14:59:00 -0700 Subject: [PATCH 17/28] moved eigensolver documentation into pg_dev_utils.rst --- doc/src/pg_dev_utils.rst | 190 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) diff --git a/doc/src/pg_dev_utils.rst b/doc/src/pg_dev_utils.rst index e34f8c806e..36c2a82121 100644 --- a/doc/src/pg_dev_utils.rst +++ b/doc/src/pg_dev_utils.rst @@ -415,3 +415,193 @@ its size is registered later with :cpp:func:`vgot() .. doxygenclass:: LAMMPS_NS::MyPoolChunk :project: progguide :members: + +Eigensolver classes +=============================================================== + +The "math_eigen.h" file contains the definition of 3 template classes +used for calculating eigenvalues and eigenvectors of matrices: +"Jacobi", "PEigenDense", and "LambdaLanczos". + +"Jacobi" calculates all of the eigenvalues and eigenvectors +of a dense, symmetric, real matrix. + +The "PEigenDense" class only calculates the principal eigenvalue +(ie. the largest or smallest eigenvalue), and its corresponding eigenvector. +However it is much more efficient than "Jacobi" when applied to large matrices +(larger than 13x13). PEigenDense also can understand complex-valued +Hermitian matrices. + +The "LambdaLanczos" class is a generalization of "PEigenDense" which can be +applied to arbitrary sparse matrices. + +Together, these matrix eigensolvers cover a fairly wide range of use cases. + +Note: The code described here does not take advantage of parallelization. +(It is assumed that the matrices are small enough +that they can be diagonalized using individual CPU cores.) + +.. code-block:: C++ + :caption: Jacobi usage example + + #include "math_eigen.h" + using namespace MathEigen; + + int n = 5; // Matrix size + double **M; // A symmetric n x n matrix you want to diagonalize + double *evals; // Store the eigenvalues here. + double **evects; // Store the eigenvectors here. + // Allocate space for M, evals, and evects, and load contents of M (omitted) + + // Now create an instance of Jacobi ("eigen_calc"). This will allocate space + // for storing intermediate calculations. Once created, it can be reused + // multiple times without paying the cost of allocating memory on the heap. + + Jacobi eigen_calc(n); + + // Note: + // If the matrix you plan to diagonalize (M) is read-only, use this instead: + // Jacobi eigen_calc(n); + + // Now, calculate the eigenvalues and eigenvectors of M + eigen_calc.Diagonalize(M, evals, evects); + +The Jacobi class is not limited to double** matrices. It works on any C or C++ +object that supports indexing using [i][j] bracket notation. +For example, if you prefer using std::vectors, then define a +Jacobi instance this way instead: + +.. code-block:: C++ + :caption: Jacobi std::vector example + + Jacobi&, vector>&, const vector>&> eigen_calc(n); + + +The PEigenDense class is useful for diagonalizing larger matrices +which can be real (symmetric) or complex-valued (Hermitian): + +.. code-block:: C++ + :caption: PEigenDense usage example + + #include "math_eigen.h" + using namespace MathEigen; + + const int n = 100; + + PEigenDense pe(n); + + double **M; // A symmetric n x n matrix you want to diagonalize + double evect[n]; // Store the principal eigenvector here. + + // Now, allocate space for M and load it's contents. (omitted) + + double eval = pe.PrincipalEigen(M, evect, true); + + // This calculates only the maximum eigenvalue and its eigenvector + + +The "LambdaLanczos" class generalizes "PEigenDense" by allowing the user +to diagonalize arbitrary sparse matrices. The "LambdaLanczos" class +does not need to know how the matrices are implemented or stored in memory. +Instead, users supply a function as an argument to the "LambdaLanczos" +constructor (a lambda expression) that multiplies vectors by matrices. The +specific implementation details are never revealed to the LambdaLanczos class. +This allows users to choose arbitrary data structures to represent +(sparse or dense) matrices. + +Note: If the matrix is not positive or negative definite, +then user must specify an "eigenvalue_offset" parameter. (See below.) + +Note: Both "LambdaLanczos" and "PEigenDense" use the Lanczos algorithm. + +.. code-block:: C++ + :caption: LambdaLanczos usage example + + #include "math_eigen.h" + using namespace MathEigen; + + const int n = 3; + double M[n][n] = { {-1.0, -1.0, 1.0}, + {-1.0, 1.0, 1.0}, + { 1.0, 1.0, 1.0} }; + // (Its eigenvalues are {-2, 1, 2}) + + // Specify the matrix-vector multiplication function + auto mv_mul = [&](const vector& in, vector& out) { + for(int i = 0;i < n;i++) { + for(int j = 0;j < n;j++) { + out[i] += M[i][j]*in[j]; + } + } + }; + + LambdaLanczos engine(mv_mul, n, true); + //(Setting 3rd arg (find_maximum) to true calculates the largest eigenvalue.) + + engine.eigenvalue_offset = 3.0; // = max_i{sum_j|Mij|} (see below) + + double eigenvalue; //(must never be a complex number, even if M is complex) + vector eigenvector(n); + + int itern = engine.run(eigenvalue, eigenvector); + + cout << "Iteration count: " << itern << endl; + cout << "Eigenvalue: " << eigenvalue << endl; + cout << "Eigenvector:"; + for(int i = 0; i < n; i++) { + cout << eigenvector[i] << " "; + } + cout << endl; + +In this example, an small dense square matrix was used for simplicity. +One could however, implement a large sparse matrix whose elements are +stored as a list of {row-index, column-index, value} tuples, +and modify the "mv_mult" function accordingly. + + +IMPORTANT: +The Lanczos algorithm finds the largest magnitude eigenvalue, so you +MUST ensure that the eigenvalue you are seeking has the largest magnitude +(regardless of whether it is the maximum or minimum eigenvalue). +To insure that this is so, you can add or subtract a number to all +of the eigenvalues of the matrix by specifying the "eigenvalue_offset". +This number should exceed the largest magnitude eigenvalue of the matrix. +According to the Gershgorin theorem, you can estimate this number using + +r = max_i{sum_j|Mij|} +or +r = max_j{sum_i|Mij|} + +(where Mij are the elements of the matrix and sum_j denotes the sum over j). + +If you are seeking the maximum eigenvalue, then use: + + eigenvalue_offset = +r + +If you are seeking the minimum eigenvalue, use: + + eigenvalue_offset = -r + +You can omit this step if you are seeking the maximum eigenvalue, +and the matrix is positive definite, or if you are seeking the minimum +eigenvalue and the matrix is negative definite.) +Otherwise, for dense (or mostly-dense) matrices, you can use the +"ChooseOffset()" member function to pick the eigenvalue_offset automatically. +Otherwise, the eigenvalue_offset MUST be specified by the user explicitly. +(LambdaLanczos is ignorant of the way the matrix is implemented internally, +so it does not have an efficient and general way to access the +elements of a sparse matrix.) + +---------- + +.. doxygenclass:: MathEigen::Jacobi + :project: progguide + :members: + +.. doxygenclass:: MathEigen::PEigenDense + :project: progguide + :members: + +.. doxygenclass:: MathEigen::LambdaLanczos + :project: progguide + :members: From 48ad8608893aeb0531e384262754cec71973daf2 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 15 Sep 2020 22:47:10 -0400 Subject: [PATCH 18/28] only do Zstd tests if it is enabled/found. --- unittest/formats/CMakeLists.txt | 56 +++++++++++++++++---------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/unittest/formats/CMakeLists.txt b/unittest/formats/CMakeLists.txt index 0a3e7bce56..e8bfa64ef3 100644 --- a/unittest/formats/CMakeLists.txt +++ b/unittest/formats/CMakeLists.txt @@ -62,38 +62,40 @@ if (PKG_COMPRESS) set_tests_properties(DumpLocalGZ PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") set_tests_properties(DumpLocalGZ PROPERTIES ENVIRONMENT "GZIP_BINARY=${GZIP_BINARY}") - find_program(ZSTD_BINARY NAMES zstd) + if(Zstd_FOUND) + find_program(ZSTD_BINARY NAMES zstd) - if (ZSTD_BINARY) - add_executable(test_dump_atom_zstd test_dump_atom_zstd.cpp) - target_link_libraries(test_dump_atom_zstd PRIVATE lammps GTest::GMock GTest::GTest) - add_test(NAME DumpAtomZstd COMMAND test_dump_atom_zstd WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - set_tests_properties(DumpAtomZstd PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") - set_tests_properties(DumpAtomZstd PROPERTIES ENVIRONMENT "ZSTD_BINARY=${ZSTD_BINARY}") + if (ZSTD_BINARY) + add_executable(test_dump_atom_zstd test_dump_atom_zstd.cpp) + target_link_libraries(test_dump_atom_zstd PRIVATE lammps GTest::GMock GTest::GTest) + add_test(NAME DumpAtomZstd COMMAND test_dump_atom_zstd WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + set_tests_properties(DumpAtomZstd PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") + set_tests_properties(DumpAtomZstd PROPERTIES ENVIRONMENT "ZSTD_BINARY=${ZSTD_BINARY}") - add_executable(test_dump_custom_zstd test_dump_custom_zstd.cpp) - target_link_libraries(test_dump_custom_zstd PRIVATE lammps GTest::GMock GTest::GTest) - add_test(NAME DumpCustomZstd COMMAND test_dump_custom_zstd WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - set_tests_properties(DumpCustomZstd PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") - set_tests_properties(DumpCustomZstd PROPERTIES ENVIRONMENT "ZSTD_BINARY=${ZSTD_BINARY}") + add_executable(test_dump_custom_zstd test_dump_custom_zstd.cpp) + target_link_libraries(test_dump_custom_zstd PRIVATE lammps GTest::GMock GTest::GTest) + add_test(NAME DumpCustomZstd COMMAND test_dump_custom_zstd WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + set_tests_properties(DumpCustomZstd PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") + set_tests_properties(DumpCustomZstd PROPERTIES ENVIRONMENT "ZSTD_BINARY=${ZSTD_BINARY}") - add_executable(test_dump_cfg_zstd test_dump_cfg_zstd.cpp) - target_link_libraries(test_dump_cfg_zstd PRIVATE lammps GTest::GMock GTest::GTest) - add_test(NAME DumpCfgZstd COMMAND test_dump_cfg_zstd WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - set_tests_properties(DumpCfgZstd PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") - set_tests_properties(DumpCfgZstd PROPERTIES ENVIRONMENT "ZSTD_BINARY=${ZSTD_BINARY}") + add_executable(test_dump_cfg_zstd test_dump_cfg_zstd.cpp) + target_link_libraries(test_dump_cfg_zstd PRIVATE lammps GTest::GMock GTest::GTest) + add_test(NAME DumpCfgZstd COMMAND test_dump_cfg_zstd WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + set_tests_properties(DumpCfgZstd PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") + set_tests_properties(DumpCfgZstd PROPERTIES ENVIRONMENT "ZSTD_BINARY=${ZSTD_BINARY}") - add_executable(test_dump_xyz_zstd test_dump_xyz_zstd.cpp) - target_link_libraries(test_dump_xyz_zstd PRIVATE lammps GTest::GMock GTest::GTest) - add_test(NAME DumpXYZZstd COMMAND test_dump_xyz_zstd WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - set_tests_properties(DumpXYZZstd PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") - set_tests_properties(DumpXYZZstd PROPERTIES ENVIRONMENT "ZSTD_BINARY=${ZSTD_BINARY}") + add_executable(test_dump_xyz_zstd test_dump_xyz_zstd.cpp) + target_link_libraries(test_dump_xyz_zstd PRIVATE lammps GTest::GMock GTest::GTest) + add_test(NAME DumpXYZZstd COMMAND test_dump_xyz_zstd WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + set_tests_properties(DumpXYZZstd PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") + set_tests_properties(DumpXYZZstd PROPERTIES ENVIRONMENT "ZSTD_BINARY=${ZSTD_BINARY}") - add_executable(test_dump_local_zstd test_dump_local_zstd.cpp) - target_link_libraries(test_dump_local_zstd PRIVATE lammps GTest::GMock GTest::GTest) - add_test(NAME DumpLocalZstd COMMAND test_dump_local_zstd WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - set_tests_properties(DumpLocalZstd PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") - set_tests_properties(DumpLocalZstd PROPERTIES ENVIRONMENT "ZSTD_BINARY=${ZSTD_BINARY}") + add_executable(test_dump_local_zstd test_dump_local_zstd.cpp) + target_link_libraries(test_dump_local_zstd PRIVATE lammps GTest::GMock GTest::GTest) + add_test(NAME DumpLocalZstd COMMAND test_dump_local_zstd WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + set_tests_properties(DumpLocalZstd PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") + set_tests_properties(DumpLocalZstd PROPERTIES ENVIRONMENT "ZSTD_BINARY=${ZSTD_BINARY}") + endif() endif() endif() From 981d60f1bd375f29fe323ab9b8913cc25ed3d1ed Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 15 Sep 2020 22:47:52 -0400 Subject: [PATCH 19/28] update rigid tests for new eigensolver --- .../tests/fix-timestep-rigid_group.yaml | 108 ++++++++-------- .../tests/fix-timestep-rigid_molecule.yaml | 34 ++--- .../fix-timestep-rigid_molecule_tri.yaml | 30 ++--- .../tests/fix-timestep-rigid_nph.yaml | 82 ++++++------- .../tests/fix-timestep-rigid_nph_small.yaml | 82 ++++++------- .../tests/fix-timestep-rigid_npt.yaml | 116 +++++++++--------- .../tests/fix-timestep-rigid_npt_small.yaml | 82 ++++++------- .../tests/fix-timestep-rigid_nve_group.yaml | 108 ++++++++-------- .../fix-timestep-rigid_nve_molecule.yaml | 42 +++---- .../tests/fix-timestep-rigid_nve_single.yaml | 74 +++++------ .../tests/fix-timestep-rigid_nve_small.yaml | 42 +++---- .../tests/fix-timestep-rigid_nvt.yaml | 74 +++++------ .../tests/fix-timestep-rigid_nvt_small.yaml | 42 +++---- .../tests/fix-timestep-rigid_single.yaml | 74 +++++------ .../tests/fix-timestep-rigid_small.yaml | 34 ++--- 15 files changed, 512 insertions(+), 512 deletions(-) diff --git a/unittest/force-styles/tests/fix-timestep-rigid_group.yaml b/unittest/force-styles/tests/fix-timestep-rigid_group.yaml index a911989c25..7fb76380c8 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_group.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_group.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:41 202 +date_generated: Tue Sep 15 22:36:53 202 epsilon: 2.5e-13 prerequisites: ! | atom full @@ -13,65 +13,65 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -1.4245356937318927e+03 -1.4496493315649675e+03 -3.6144360984224963e+03 8.4840626828643849e+02 2.0318336761611764e+02 -6.0622397707969685e+02 + -1.4245356937318884e+03 -1.4496493315649705e+03 -3.6144360984225009e+03 8.4840626828644258e+02 2.0318336761611707e+02 -6.0622397707970117e+02 global_scalar: 15.7115214231781 run_pos: ! |2 - 1 -2.7899546863891622e-01 2.4731857340328216e+00 -1.7290667740241872e-01 - 2 3.0296221610264007e-01 2.9517129916957545e+00 -8.5798904387772823e-01 - 3 -6.9368802364134852e-01 1.2445115421754183e+00 -6.2281111198650230e-01 - 4 -1.5764879647103172e+00 1.4919714415841274e+00 -1.2492069414674600e+00 - 5 -8.9434512967430013e-01 9.3651699743510730e-01 4.0191726558261431e-01 - 6 2.9454439634451690e-01 2.2724545792544065e-01 -1.2845195053960263e+00 - 7 3.4049112903270062e-01 -9.4655678322440595e-03 -2.4634480020857059e+00 - 8 1.1644354555804877e+00 -4.8367776650961369e-01 -6.7663643940735896e-01 - 9 1.3781717822696469e+00 -2.5332509530010827e-01 2.6864954436590061e-01 - 10 2.0186368606041905e+00 -1.4285861423625792e+00 -9.6712491252780297e-01 - 11 1.7929137227577470e+00 -1.9875455388407410e+00 -1.8836565352266557e+00 - 12 3.0032775230399604e+00 -4.8983022415173838e-01 -1.6190248017343647e+00 - 13 4.0448964162125947e+00 -9.0213155122390720e-01 -1.6385398399479572e+00 - 14 2.6035151245015831e+00 -4.0874995493218902e-01 -2.6555999074786611e+00 - 15 2.9761196776172314e+00 5.6287237454108840e-01 -1.2442626196083382e+00 - 16 2.6517373021566191e+00 -2.3957035508393720e+00 3.3389262100689376e-02 - 17 2.2311114924744988e+00 -2.1018393228798540e+00 1.1496088522377521e+00 - 18 2.1390642573201788e+00 3.0164773560693772e+00 -3.5143984803853874e+00 - 19 1.5353246655146275e+00 2.6305911186316124e+00 -4.2455871034737074e+00 - 20 2.7649421538938386e+00 3.6818603528430827e+00 -3.9364115785985558e+00 - 21 4.9043112657298868e+00 -4.0774268210397873e+00 -3.6200836396129810e+00 - 22 4.3665322424283302e+00 -4.2075138112953594e+00 -4.4636587264885854e+00 - 23 5.7355405581985170e+00 -3.5789558641908905e+00 -3.8805763324089964e+00 - 24 2.0692780332810123e+00 3.1504920436416004e+00 3.1571131300668775e+00 - 25 1.3007297593169085e+00 3.2745259354179486e+00 2.5110163874103657e+00 - 26 2.5819416446099748e+00 4.0104903120756585e+00 3.2150249624526013e+00 + 1 -2.7899546863891489e-01 2.4731857340328216e+00 -1.7290667740242327e-01 + 2 3.0296221610264151e-01 2.9517129916957532e+00 -8.5798904387773267e-01 + 3 -6.9368802364134807e-01 1.2445115421754180e+00 -6.2281111198650496e-01 + 4 -1.5764879647103154e+00 1.4919714415841261e+00 -1.2492069414674631e+00 + 5 -8.9434512967430058e-01 9.3651699743510919e-01 4.0191726558261187e-01 + 6 2.9454439634451712e-01 2.2724545792543988e-01 -1.2845195053960272e+00 + 7 3.4049112903270107e-01 -9.4655678322462800e-03 -2.4634480020857055e+00 + 8 1.1644354555804874e+00 -4.8367776650961330e-01 -6.7663643940735863e-01 + 9 1.3781717822696467e+00 -2.5332509530010694e-01 2.6864954436590061e-01 + 10 2.0186368606041896e+00 -1.4285861423625787e+00 -9.6712491252780097e-01 + 11 1.7929137227577463e+00 -1.9875455388407417e+00 -1.8836565352266530e+00 + 12 3.0032775230399609e+00 -4.8983022415173938e-01 -1.6190248017343634e+00 + 13 4.0448964162125947e+00 -9.0213155122390887e-01 -1.6385398399479545e+00 + 14 2.6035151245015831e+00 -4.0874995493219152e-01 -2.6555999074786603e+00 + 15 2.9761196776172318e+00 5.6287237454108718e-01 -1.2442626196083382e+00 + 16 2.6517373021566177e+00 -2.3957035508393694e+00 3.3389262100692485e-02 + 17 2.2311114924744970e+00 -2.1018393228798504e+00 1.1496088522377548e+00 + 18 2.1390642573201784e+00 3.0164773560693781e+00 -3.5143984803853878e+00 + 19 1.5353246655146278e+00 2.6305911186316133e+00 -4.2455871034737074e+00 + 20 2.7649421538938390e+00 3.6818603528430849e+00 -3.9364115785985550e+00 + 21 4.9043112657298877e+00 -4.0774268210397882e+00 -3.6200836396129836e+00 + 22 4.3665322424283310e+00 -4.2075138112953594e+00 -4.4636587264885881e+00 + 23 5.7355405581985188e+00 -3.5789558641908918e+00 -3.8805763324089981e+00 + 24 2.0692780332810115e+00 3.1504920436416004e+00 3.1571131300668789e+00 + 25 1.3007297593169076e+00 3.2745259354179481e+00 2.5110163874103675e+00 + 26 2.5819416446099739e+00 4.0104903120756576e+00 3.2150249624526035e+00 27 -1.9613581876744359e+00 -4.3556300596085160e+00 2.1101467673534788e+00 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 run_vel: ! |2 - 1 4.7093289825842518e-04 2.6351122778447999e-04 -4.4905093064114991e-04 - 2 4.9594625316470484e-04 9.4561370489631939e-05 -5.4581359894047949e-04 - 3 3.3306085115756087e-04 2.3224943880673381e-04 -2.3659455671746045e-04 - 4 3.3692327392261114e-04 2.1926810694051279e-04 -2.4716631558862527e-04 - 5 3.3642542694186013e-04 4.1797578013265895e-04 -1.8011341766657651e-04 - 6 2.0926869754934733e-04 2.6449308951578761e-05 -1.0508938983871863e-04 - 7 1.4629043007907862e-04 -1.6873376665350138e-04 -6.8354048774351599e-05 - 8 1.5844101624224864e-04 3.7728761274000492e-05 -1.9162715667091517e-05 - 9 2.1299362072601976e-04 1.6917140529157604e-04 -6.3528165037846039e-05 - 10 5.4261629412254251e-05 -9.4655528376811197e-05 1.0511362869146629e-04 - 11 -3.2194160796503320e-05 -2.2025095264758748e-04 2.0300202946212385e-04 - 12 1.2640586304750342e-04 -2.9851080445665075e-04 -7.9476371818247547e-05 - 13 8.4523575162142323e-05 -4.0583135407330540e-04 -4.7551111331702706e-05 - 14 9.9954050381270240e-05 -4.2610816481298321e-04 -7.9255633594381333e-05 - 15 2.4417481119789840e-04 -2.3521002264677917e-04 -2.4875318161049140e-04 - 16 -9.0958138549664179e-06 3.7774817121227626e-06 2.4035199548835075e-04 - 17 5.7507224523612718e-05 2.2629217444843883e-04 2.0686920072684827e-04 - 18 2.9220264989359676e-04 -6.2478376436796309e-04 8.4222594596602344e-04 - 19 2.0572616567799036e-04 -5.0334424271726705e-04 8.4953929443210658e-04 - 20 4.1224811789512805e-04 -7.4115205416011576e-04 8.3678612337507888e-04 - 21 -1.0671858777656380e-03 -1.1531171045499509e-03 7.3720674900162192e-04 - 22 -1.1066511338291703e-03 -1.0433933757600456e-03 7.4544544325708616e-04 - 23 -9.7629260480941438e-04 -1.3100872491594094e-03 7.2687284219704804e-04 - 24 4.3308126651259334e-04 -6.6527658087322747e-04 8.4451298670663595e-04 - 25 4.4565811905442911e-04 -5.1298436273584274e-04 8.5878867884521559e-04 - 26 5.9865972692022798e-04 -7.6385263287080316e-04 8.4259943226842134e-04 + 1 4.7093289825842486e-04 2.6351122778447826e-04 -4.4905093064114855e-04 + 2 4.9594625316470495e-04 9.4561370489630651e-05 -5.4581359894047721e-04 + 3 3.3306085115756092e-04 2.3224943880673270e-04 -2.3659455671746018e-04 + 4 3.3692327392261152e-04 2.1926810694051195e-04 -2.4716631558862522e-04 + 5 3.3642542694185980e-04 4.1797578013265732e-04 -1.8011341766657692e-04 + 6 2.0926869754934785e-04 2.6449308951578490e-05 -1.0508938983871839e-04 + 7 1.4629043007907975e-04 -1.6873376665350062e-04 -6.8354048774351260e-05 + 8 1.5844101624224894e-04 3.7728761274000044e-05 -1.9162715667091402e-05 + 9 2.1299362072601955e-04 1.6917140529157490e-04 -6.3528165037845781e-05 + 10 5.4261629412254793e-05 -9.4655528376811116e-05 1.0511362869146627e-04 + 11 -3.2194160796502263e-05 -2.2025095264758662e-04 2.0300202946212347e-04 + 12 1.2640586304750418e-04 -2.9851080445665042e-04 -7.9476371818246096e-05 + 13 8.4523575162143095e-05 -4.0583135407330485e-04 -4.7551111331700809e-05 + 14 9.9954050381271487e-05 -4.2610816481298213e-04 -7.9255633594379828e-05 + 15 2.4417481119789889e-04 -2.3521002264677933e-04 -2.4875318161048917e-04 + 16 -9.0958138549662281e-06 3.7774817121223831e-06 2.4035199548835009e-04 + 17 5.7507224523612284e-05 2.2629217444843761e-04 2.0686920072684746e-04 + 18 2.9220264989359801e-04 -6.2478376436796276e-04 8.4222594596602355e-04 + 19 2.0572616567799155e-04 -5.0334424271726661e-04 8.4953929443210658e-04 + 20 4.1224811789512974e-04 -7.4115205416011565e-04 8.3678612337507910e-04 + 21 -1.0671858777656390e-03 -1.1531171045499513e-03 7.3720674900162170e-04 + 22 -1.1066511338291712e-03 -1.0433933757600460e-03 7.4544544325708584e-04 + 23 -9.7629260480941536e-04 -1.3100872491594103e-03 7.2687284219704793e-04 + 24 4.3308126651259350e-04 -6.6527658087322768e-04 8.4451298670663606e-04 + 25 4.4565811905442927e-04 -5.1298436273584263e-04 8.5878867884521559e-04 + 26 5.9865972692022809e-04 -7.6385263287080348e-04 8.4259943226842155e-04 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_molecule.yaml b/unittest/force-styles/tests/fix-timestep-rigid_molecule.yaml index 0ecc6afe1b..631e538f6e 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_molecule.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_molecule.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:41 202 +date_generated: Tue Sep 15 22:36:54 202 epsilon: 2.5e-13 prerequisites: ! | atom full @@ -13,7 +13,7 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -4.9200116134790363e+01 -2.6907707565987732e+01 -6.0080860422282560e+00 -2.5620423972101747e+01 -1.3450224059984075e+01 -1.4947288487004844e+00 + -4.9200116134789894e+01 -2.6907707565987600e+01 -6.0080860422279923e+00 -2.5620423972101459e+01 -1.3450224059984031e+01 -1.4947288487004347e+00 global_scalar: 18.3405601674144 run_pos: ! |2 1 -2.7993683669226832e-01 2.4726588069312840e+00 -1.7200860244148433e-01 @@ -33,15 +33,15 @@ run_pos: ! |2 15 2.9756315249791303e+00 5.6334269722969288e-01 -1.2437650754599008e+00 16 2.6517554244980306e+00 -2.3957110424978438e+00 3.2908335999178327e-02 17 2.2309964792710639e+00 -2.1022918943319384e+00 1.1491948328949437e+00 - 18 2.1392027588271301e+00 3.0171068018412783e+00 -3.5144628518856349e+00 - 19 1.5366124997074573e+00 2.6286809834111744e+00 -4.2452547844370221e+00 - 20 2.7628161763455852e+00 3.6842251687634779e+00 -3.9370881219352558e+00 - 21 4.9036621347791245e+00 -4.0757648442838548e+00 -3.6192617654515908e+00 + 18 2.1392027588271301e+00 3.0171068018412779e+00 -3.5144628518856349e+00 + 19 1.5366124997074571e+00 2.6286809834111748e+00 -4.2452547844370221e+00 + 20 2.7628161763455852e+00 3.6842251687634775e+00 -3.9370881219352554e+00 + 21 4.9036621347791245e+00 -4.0757648442838548e+00 -3.6192617654515904e+00 22 4.3655322291888483e+00 -4.2084949965552561e+00 -4.4622011117402334e+00 23 5.7380414793463101e+00 -3.5841969195032672e+00 -3.8827839830470219e+00 24 2.0701314765323930e+00 3.1499370533342330e+00 3.1565324852522938e+00 - 25 1.3030170721374783e+00 3.2711173927682244e+00 2.5081940917429759e+00 - 26 2.5776230782480041e+00 4.0127347068243884e+00 3.2182355138709284e+00 + 25 1.3030170721374779e+00 3.2711173927682249e+00 2.5081940917429768e+00 + 26 2.5776230782480045e+00 4.0127347068243875e+00 3.2182355138709275e+00 27 -1.9613581876744359e+00 -4.3556300596085160e+00 2.1101467673534788e+00 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 @@ -63,15 +63,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 3.6149625095704870e-04 -3.1032459262908302e-04 8.1043030117346052e-04 - 19 8.5103884665345441e-04 -1.4572280596788099e-03 1.0163621287634116e-03 - 20 -6.5204659278590758e-04 4.3989037444289831e-04 4.9909839028507966e-04 - 21 -1.3888125881903919e-03 -3.1978049143082570e-04 1.1455681499836646e-03 - 22 -1.6084223477729497e-03 -1.5355394240821158e-03 1.4772010826232373e-03 - 23 2.6392672378804886e-04 -3.9375414431174760e-03 -3.6991583139728127e-04 - 24 8.6062827067890290e-04 -9.4179873474469259e-04 5.5396395550012367e-04 - 25 1.5933645477487557e-03 -2.2139156625681682e-03 -5.5078029695647412e-04 - 26 -1.5679561743998888e-03 3.5146224354725948e-04 2.4446924193334482e-03 + 18 3.6149625095704908e-04 -3.1032459262908286e-04 8.1043030117346042e-04 + 19 8.5103884665345452e-04 -1.4572280596788108e-03 1.0163621287634116e-03 + 20 -6.5204659278590683e-04 4.3989037444289853e-04 4.9909839028507890e-04 + 21 -1.3888125881903923e-03 -3.1978049143082407e-04 1.1455681499836646e-03 + 22 -1.6084223477729508e-03 -1.5355394240821113e-03 1.4772010826232373e-03 + 23 2.6392672378805081e-04 -3.9375414431174812e-03 -3.6991583139728051e-04 + 24 8.6062827067890236e-04 -9.4179873474469237e-04 5.5396395550012442e-04 + 25 1.5933645477487542e-03 -2.2139156625681699e-03 -5.5078029695647488e-04 + 26 -1.5679561743998840e-03 3.5146224354726122e-04 2.4446924193334474e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_molecule_tri.yaml b/unittest/force-styles/tests/fix-timestep-rigid_molecule_tri.yaml index d1d1e9492d..f23297ece8 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_molecule_tri.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_molecule_tri.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:41 202 +date_generated: Tue Sep 15 22:36:54 202 epsilon: 5e-12 prerequisites: ! | atom full @@ -14,7 +14,7 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -4.9200116134791799e+01 -2.6907707565986644e+01 -6.0080860422294684e+00 -2.5620423972101577e+01 -1.3450224059984462e+01 -1.4947288487000847e+00 + -4.9200116134789241e+01 -2.6907707565985238e+01 -6.0080860422273377e+00 -2.5620423972099417e+01 -1.3450224059984127e+01 -1.4947288486998911e+00 global_scalar: 18.3405601674143 run_pos: ! |2 1 -2.7993683669226854e-01 2.4726588069312836e+00 -1.7200860244148508e-01 @@ -35,14 +35,14 @@ run_pos: ! |2 16 2.6517554244980301e+00 -2.3957110424978438e+00 3.2908335999177751e-02 17 2.2309964792710639e+00 -2.1022918943319384e+00 1.1491948328949437e+00 18 2.1392027588271310e+00 3.0171068018412779e+00 -3.5144628518856349e+00 - 19 1.5366124997074584e+00 2.6286809834111740e+00 -4.2452547844370230e+00 + 19 1.5366124997074566e+00 2.6286809834111740e+00 -4.2452547844370239e+00 20 2.7628161763455852e+00 3.6842251687634775e+00 -3.9370881219352558e+00 - 21 4.9036621347791245e+00 -4.0757648442838557e+00 -3.6192617654515917e+00 + 21 4.9036621347791245e+00 -4.0757648442838557e+00 -3.6192617654515900e+00 22 4.3655322291888483e+00 -4.2084949965552569e+00 -4.4622011117402334e+00 - 23 5.7380414793463084e+00 -3.5841969195032686e+00 -3.8827839830470223e+00 + 23 5.7380414793463101e+00 -3.5841969195032686e+00 -3.8827839830470232e+00 24 2.0701314765323913e+00 3.1499370533342308e+00 3.1565324852522920e+00 25 1.3030170721374779e+00 3.2711173927682236e+00 2.5081940917429755e+00 - 26 2.5776230782480036e+00 4.0127347068243875e+00 3.2182355138709280e+00 + 26 2.5776230782480054e+00 4.0127347068243875e+00 3.2182355138709262e+00 27 -1.9613581876744357e+00 -4.3556300596085160e+00 2.1101467673534788e+00 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678509e+00 29 -1.3108232656499084e+00 -3.5992986322410765e+00 2.2680459788743512e+00 @@ -64,15 +64,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 3.6149625095704496e-04 -3.1032459262907451e-04 8.1043030117346150e-04 - 19 8.5103884665346059e-04 -1.4572280596788069e-03 1.0163621287634041e-03 - 20 -6.5204659278589056e-04 4.3989037444288725e-04 4.9909839028508367e-04 - 21 -1.3888125881903861e-03 -3.1978049143082461e-04 1.1455681499836603e-03 - 22 -1.6084223477729506e-03 -1.5355394240821054e-03 1.4772010826232355e-03 - 23 2.6392672378804235e-04 -3.9375414431174561e-03 -3.6991583139728127e-04 - 24 8.6062827067889531e-04 -9.4179873474469281e-04 5.5396395550012681e-04 - 25 1.5933645477487551e-03 -2.2139156625681582e-03 -5.5078029695647629e-04 - 26 -1.5679561743998853e-03 3.5146224354725482e-04 2.4446924193334521e-03 + 18 3.6149625095704480e-04 -3.1032459262907435e-04 8.1043030117346128e-04 + 19 8.5103884665346124e-04 -1.4572280596788089e-03 1.0163621287634045e-03 + 20 -6.5204659278589121e-04 4.3989037444288817e-04 4.9909839028508280e-04 + 21 -1.3888125881903863e-03 -3.1978049143082245e-04 1.1455681499836596e-03 + 22 -1.6084223477729515e-03 -1.5355394240820991e-03 1.4772010826232349e-03 + 23 2.6392672378804170e-04 -3.9375414431174621e-03 -3.6991583139727824e-04 + 24 8.6062827067889477e-04 -9.4179873474469237e-04 5.5396395550012714e-04 + 25 1.5933645477487534e-03 -2.2139156625681600e-03 -5.5078029695647803e-04 + 26 -1.5679561743998831e-03 3.5146224354725699e-04 2.4446924193334539e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nph.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nph.yaml index 84b1d84927..64585af6bb 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nph.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nph.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:41 202 +date_generated: Tue Sep 15 22:36:55 202 epsilon: 2.5e-13 prerequisites: ! | atom full @@ -13,38 +13,38 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |2- - 4.3578059170174832e+01 1.7275105168494740e+01 6.7372361278298868e+01 5.1985075051780690e+01 -2.0990677390560389e+01 -7.5321398094463152e+00 -global_scalar: 29.0236364415722 + 4.3578059172167876e+01 1.7275105166465064e+01 6.7372361276630770e+01 5.1985075049901859e+01 -2.0990677389800858e+01 -7.5321398101845993e+00 +global_scalar: 29.023636440848 run_pos: ! |2 - 1 -6.3472039825537774e-01 3.0113983126285238e+00 -8.8148450172184312e-02 - 2 6.4798884173359994e-02 3.5870486860061543e+00 -9.1146271255437306e-01 - 3 -1.1328967478842920e+00 1.5344674077764360e+00 -6.2949567786978733e-01 - 4 -2.1941320441844692e+00 1.8319737599532431e+00 -1.3824693495475060e+00 - 5 -1.3741175247363460e+00 1.1637763350571220e+00 6.0220861483097998e-01 - 6 5.5368589242019262e-02 3.1209253712249385e-01 -1.4252606627468101e+00 - 7 1.1075313780256746e-01 2.8008314824816694e-02 -2.8425552056440306e+00 - 8 1.1011987966103707e+00 -5.4254536577072088e-01 -6.9472264392662098e-01 - 9 1.3580030945400914e+00 -2.6595138115347083e-01 4.4172536708307497e-01 - 10 2.1282964643832063e+00 -1.6781145595678426e+00 -1.0442216631471748e+00 - 11 1.8571593172391960e+00 -2.3497452731073585e+00 -2.1462323657666937e+00 - 12 3.3117732698471869e+00 -5.4913311816194721e-01 -1.8274356036323782e+00 - 13 4.5640183918456163e+00 -1.0445083545908478e+00 -1.8509716390299458e+00 - 14 2.8312769330519441e+00 -4.5135848464346751e-01 -3.0735173792334480e+00 - 15 3.2788434490966072e+00 7.1618295543704136e-01 -1.3765217601453035e+00 - 16 2.8895075000233614e+00 -2.8409365554013073e+00 1.5818504152562340e-01 - 17 2.3837073405560201e+00 -2.4882133308171541e+00 1.5000885103551340e+00 - 18 2.2738793194347995e+00 3.6743407122546436e+00 -4.1408965121169743e+00 - 19 1.6572750518209620e+00 3.2770314238218798e+00 -4.8886441786647481e+00 - 20 2.9120476452842148e+00 4.3568412675017782e+00 -4.5732834167711358e+00 - 21 5.6058485050574518e+00 -4.8495065176199610e+00 -4.2655497599977545e+00 - 22 5.0552709233227606e+00 -4.9851876751499695e+00 -5.1280564953937073e+00 - 23 6.4593933586526457e+00 -4.3461765106386885e+00 -4.5350231455787116e+00 - 24 2.1823354618683499e+00 3.8552931130562804e+00 3.8953804330779338e+00 - 25 1.3973696115700314e+00 3.9794119229081808e+00 3.2321313265763383e+00 - 26 2.7018361229436447e+00 4.7379517630363708e+00 3.9583193477160581e+00 - 27 -2.6559803075362280e+00 -5.1969823689083769e+00 2.6552621488558881e+00 - 28 -3.5927802460212037e+00 -4.7943885088606857e+00 2.0214142204097989e+00 - 29 -1.8739632618342412e+00 -4.2877858778717988e+00 2.8450749793922530e+00 + 1 -6.3472039825517168e-01 3.0113983126282058e+00 -8.8148450172235826e-02 + 2 6.4798884173500326e-02 3.5870486860057795e+00 -9.1146271255434463e-01 + 3 -1.1328967478840362e+00 1.5344674077762583e+00 -6.2949567786977667e-01 + 4 -2.1941320441841130e+00 1.8319737599530370e+00 -1.3824693495474225e+00 + 5 -1.3741175247360697e+00 1.1637763350569887e+00 6.0220861483086097e-01 + 6 5.5368589242158706e-02 3.1209253712244411e-01 -1.4252606627467266e+00 + 7 1.1075313780270069e-01 2.8008314824797154e-02 -2.8425552056438050e+00 + 8 1.1011987966104080e+00 -5.4254536577068713e-01 -6.9472264392660854e-01 + 9 1.3580030945401020e+00 -2.6595138115345840e-01 4.4172536708297194e-01 + 10 2.1282964643831388e+00 -1.6781145595676907e+00 -1.0442216631471304e+00 + 11 1.8571593172391605e+00 -2.3497452731071471e+00 -2.1462323657665392e+00 + 12 3.3117732698469986e+00 -5.4913311816190635e-01 -1.8274356036322548e+00 + 13 4.5640183918453143e+00 -1.0445083545907554e+00 -1.8509716390298214e+00 + 14 2.8312769330518019e+00 -4.5135848464344086e-01 -3.0735173792331993e+00 + 15 3.2788434490964296e+00 7.1618295543695254e-01 -1.3765217601452289e+00 + 16 2.8895075000232158e+00 -2.8409365554010479e+00 1.5818504152554702e-01 + 17 2.3837073405559277e+00 -2.4882133308169232e+00 1.5000885103549333e+00 + 18 2.2738793194357232e+00 3.6743407122553755e+00 -4.1408965121163197e+00 + 19 1.6572750518209336e+00 3.2770314238152451e+00 -4.8886441786593569e+00 + 20 2.9120476452800226e+00 4.3568412675031851e+00 -4.5732834167769187e+00 + 21 5.6058485050774536e+00 -4.8495065176300871e+00 -4.2655497599953458e+00 + 22 5.0552709232982114e+00 -4.9851876752032496e+00 -5.1280564953560424e+00 + 23 6.4593933585948218e+00 -4.3461765105422652e+00 -4.5350231456236889e+00 + 24 2.1823354619125279e+00 3.8552931130470363e+00 3.8953804330431208e+00 + 25 1.3973696115403698e+00 3.9794119228484153e+00 3.2321313266194949e+00 + 26 2.7018361227965517e+00 4.7379517631305443e+00 3.9583193478092706e+00 + 27 -2.6559803075358257e+00 -5.1969823689078796e+00 2.6552621488555683e+00 + 28 -3.5927802460207046e+00 -4.7943885088602283e+00 2.0214142204095413e+00 + 29 -1.8739632618339108e+00 -4.2877858778713946e+00 2.8450749793919066e+00 run_vel: ! |2 1 7.7867804888392077e-04 5.8970331623292821e-04 -2.2179517633030531e-04 2 2.7129529964126462e-03 4.6286427111164284e-03 3.5805549693846352e-03 @@ -63,15 +63,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 3.0094600491857170e-04 -2.4312792028099414e-04 6.5542049134060274e-04 - 19 7.4731683461619846e-04 -1.2894119671259621e-03 8.4327024053358754e-04 - 20 -6.2333686370008492e-04 4.4115361642793068e-04 3.7135656431973134e-04 - 21 -1.1457423792961207e-03 -1.7337748147951398e-04 9.4510018428184666e-04 - 22 -1.3457150580799371e-03 -1.2816797359999673e-03 1.2470992249788205e-03 - 23 3.6277645396700405e-04 -3.4719859050652826e-03 -4.3796817842582582e-04 - 24 7.2410992459670976e-04 -7.6012809759400297e-04 4.3327155120506525e-04 - 25 1.3921349891892296e-03 -1.9207002802470775e-03 -5.7453335098664004e-04 - 26 -1.4901465945625163e-03 4.2012923513626613e-04 2.1578545406129362e-03 + 18 3.0094600491564739e-04 -2.4312792027781274e-04 6.5542049134062323e-04 + 19 7.4731683462770054e-04 -1.2894119671278408e-03 8.4327024053533386e-04 + 20 -6.2333686369976584e-04 4.4115361641690066e-04 3.7135656431834237e-04 + 21 -1.1457423793218525e-03 -1.7337748161437973e-04 9.4510018429417686e-04 + 22 -1.3457150581639319e-03 -1.2816797357047460e-03 1.2470992250388101e-03 + 23 3.6277645415306540e-04 -3.4719859048227848e-03 -4.3796817853449140e-04 + 24 7.2410992462873655e-04 -7.6012809744767037e-04 4.3327155128124932e-04 + 25 1.3921349892629666e-03 -1.9207002802664867e-03 -5.7453335109528100e-04 + 26 -1.4901465947638008e-03 4.2012923457099966e-04 2.1578545404178414e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml index 7844d7fcb7..2aa29b2d39 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:41 202 +date_generated: Tue Sep 15 22:36:55 202 epsilon: 2.5e-13 prerequisites: ! | atom full @@ -13,38 +13,38 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |2- - 2.7340318969496678e+01 4.7963870140135469e+00 6.8884396850629400e+01 2.9853310008504316e+01 -1.0857139901179401e+01 -5.1889756547613537e+00 -global_scalar: 9.77678786322453 + 2.7340318973870428e+01 4.7963870091858531e+00 6.8884396847592484e+01 2.9853310007358978e+01 -1.0857139901347637e+01 -5.1889756561453346e+00 +global_scalar: 9.77678786310451 run_pos: ! |2 - 1 -5.1121862036607624e-01 2.8134872171085981e+00 -4.8993015395440764e-02 - 2 1.4735952488044823e-01 3.3535825972284670e+00 -9.3694001270740124e-01 - 3 -9.8023793775382462e-01 1.4277788160413873e+00 -6.3283768722999412e-01 - 4 -1.9793617512974810e+00 1.7069097152783730e+00 -1.4449221382956789e+00 - 5 -1.2073406578712493e+00 1.0799834439083895e+00 6.9555923026710076e-01 - 6 1.3848116183740711e-01 2.8090381873862391e-01 -1.4910727029129127e+00 - 7 1.9062418946015125e-01 1.4366032742495705e-02 -3.0196292835202954e+00 - 8 1.1231015082845470e+00 -5.2094745136408704e-01 -7.0318517336044728e-01 - 9 1.3648756844511940e+00 -2.6143726919536014e-01 5.2247754752749742e-01 - 10 2.0900856844466613e+00 -1.5863783165915786e+00 -1.0801209545801669e+00 - 11 1.8348175253566694e+00 -2.2165258198423707e+00 -2.2686429310674399e+00 - 12 3.2042965133156294e+00 -5.2712831182456732e-01 -1.9248196297791935e+00 - 13 4.3832508188729644e+00 -9.9190674157035730e-01 -1.9502033172904838e+00 - 14 2.7519224412447869e+00 -4.3539271970396598e-01 -3.2687227073824996e+00 - 15 3.1732939937025613e+00 6.6003562890635337e-01 -1.4385076445935461e+00 - 16 2.8067449168448011e+00 -2.6773787170020160e+00 2.1667842294155371e-01 - 17 2.3305479923928605e+00 -2.3464414104888620e+00 1.6639254952588054e+00 - 18 2.2269920241221968e+00 3.4328783208250648e+00 -4.4342132514643442e+00 - 19 1.6145347679280437e+00 3.0386658278250263e+00 -5.1868156516302486e+00 - 20 2.8608613711069921e+00 4.1100452338277211e+00 -4.8694049549850762e+00 - 21 5.3613621396753839e+00 -4.5653056926381028e+00 -4.5681019697332310e+00 - 22 4.8144754755163870e+00 -4.6999404673940806e+00 -5.4362066556515076e+00 - 23 6.2091840279374200e+00 -4.0659479263393665e+00 -4.8393130641406774e+00 - 24 2.1433208912156090e+00 3.5960988832244993e+00 4.2399236066761858e+00 - 25 1.3636453973791856e+00 3.7192408266937900e+00 3.5723762826039014e+00 - 26 2.6593036731430075e+00 4.4718649489299125e+00 4.3032623332451116e+00 - 27 -2.4141791756399114e+00 -4.8879035738861889e+00 2.9097838637423070e+00 - 28 -3.2961505257539727e+00 -4.5101758871992912e+00 2.2261768979311878e+00 - 29 -1.6779316575994772e+00 -4.0348635219032660e+00 3.1144975929061580e+00 + 1 -5.1121862036604515e-01 2.8134872171079977e+00 -4.8993015395518924e-02 + 2 1.4735952488047133e-01 3.3535825972277546e+00 -9.3694001270735150e-01 + 3 -9.8023793775378820e-01 1.4277788160410712e+00 -6.3283768722999234e-01 + 4 -1.9793617512974304e+00 1.7069097152779946e+00 -1.4449221382955635e+00 + 5 -1.2073406578712120e+00 1.0799834439081337e+00 6.9555923026692668e-01 + 6 1.3848116183742931e-01 2.8090381873852976e-01 -1.4910727029127884e+00 + 7 1.9062418946016990e-01 1.4366032742456625e-02 -3.0196292835199614e+00 + 8 1.1231015082845541e+00 -5.2094745136401599e-01 -7.0318517336042774e-01 + 9 1.3648756844511976e+00 -2.6143726919534771e-01 5.2247754752734465e-01 + 10 2.0900856844466578e+00 -1.5863783165912952e+00 -1.0801209545800976e+00 + 11 1.8348175253566659e+00 -2.2165258198419622e+00 -2.2686429310672072e+00 + 12 3.2042965133156098e+00 -5.2712831182449804e-01 -1.9248196297790088e+00 + 13 4.3832508188729271e+00 -9.9190674157019298e-01 -1.9502033172902991e+00 + 14 2.7519224412447691e+00 -4.3539271970391624e-01 -3.2687227073821310e+00 + 15 3.1732939937025400e+00 6.6003562890618639e-01 -1.4385076445934288e+00 + 16 2.8067449168447887e+00 -2.6773787170015133e+00 2.1667842294144180e-01 + 17 2.3305479923928516e+00 -2.3464414104884277e+00 1.6639254952584981e+00 + 18 2.2269920241232128e+00 3.4328783208254681e+00 -4.4342132514635013e+00 + 19 1.6145347679280793e+00 3.0386658278179439e+00 -5.1868156516245785e+00 + 20 2.8608613711028656e+00 4.1100452338287408e+00 -4.8694049549907970e+00 + 21 5.3613621396958795e+00 -4.5653056926475841e+00 -4.5681019697305372e+00 + 22 4.8144754754921184e+00 -4.6999404674483083e+00 -5.4362066556130868e+00 + 23 6.2091840278795729e+00 -4.0659479262420684e+00 -4.8393130641864568e+00 + 24 2.1433208912603074e+00 3.5960988832146015e+00 4.2399236066404100e+00 + 25 1.3636453973491918e+00 3.7192408266342980e+00 3.5723762826473990e+00 + 26 2.6593036729945752e+00 4.4718649490241678e+00 4.3032623333405660e+00 + 27 -2.4141791756398536e+00 -4.8879035738852403e+00 2.9097838637418292e+00 + 28 -3.2961505257539048e+00 -4.5101758871984199e+00 2.2261768979308005e+00 + 29 -1.6779316575994301e+00 -4.0348635219024889e+00 3.1144975929056571e+00 run_vel: ! |2 1 7.7867804888392077e-04 5.8970331623292821e-04 -2.2179517633030531e-04 2 2.7129529964126462e-03 4.6286427111164284e-03 3.5805549693846352e-03 @@ -63,15 +63,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 3.1638284997374886e-04 -2.6313163919391785e-04 6.1054395248654240e-04 - 19 7.6494647251130164e-04 -1.3190724749194743e-03 7.9947132612800302e-04 - 20 -6.1620104632544958e-04 4.2577138775425278e-04 3.2526261653689488e-04 - 21 -1.2063428871264968e-03 -2.2879409865288636e-04 8.9132836537584854e-04 - 22 -1.4151473871025083e-03 -1.3502255396192354e-03 1.1972773108803675e-03 - 23 3.1280366090588076e-04 -3.5563936895860802e-03 -4.9548546521909192e-04 - 24 7.5594375538132891e-04 -8.1321044009404451e-04 3.9340911288127442e-04 - 25 1.4373446730971094e-03 -1.9778020567293888e-03 -6.1842201907464972e-04 - 26 -1.4806168648241629e-03 3.7766934332214119e-04 2.1280924227254782e-03 + 18 3.1638284997073288e-04 -2.6313163919070400e-04 6.1054395248656961e-04 + 19 7.6494647252307629e-04 -1.3190724749214317e-03 7.9947132612985744e-04 + 20 -6.1620104632513885e-04 4.2577138774295257e-04 3.2526261653548683e-04 + 21 -1.2063428871524097e-03 -2.2879409878999576e-04 8.9132836538734455e-04 + 22 -1.4151473871894464e-03 -1.3502255393198256e-03 1.1972773109437851e-03 + 23 3.1280366109607172e-04 -3.5563936893394407e-03 -4.9548546532774947e-04 + 24 7.5594375541558048e-04 -8.1321043994394464e-04 3.9340911295780760e-04 + 25 1.4373446731689036e-03 -1.9778020567486213e-03 -6.1842201918304457e-04 + 26 -1.4806168650325995e-03 3.7766934274110835e-04 2.1280924225288347e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_npt.yaml b/unittest/force-styles/tests/fix-timestep-rigid_npt.yaml index 8409597e0b..2733d8a704 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_npt.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_npt.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:41 202 +date_generated: Tue Sep 15 22:36:56 202 epsilon: 2.5e-13 prerequisites: ! | atom full @@ -12,65 +12,65 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -1.6326314448657713e+03 -1.4727331978534244e+03 -3.8557370515929333e+03 5.5052891601613476e+02 4.7346742977275369e+02 -6.2035591882215908e+02 -global_scalar: 106.866830724743 + -1.6326314448663304e+03 -1.4727331978532306e+03 -3.8557370515932275e+03 5.5052891601644728e+02 4.7346742977310510e+02 -6.2035591882122242e+02 +global_scalar: 106.866830724741 run_pos: ! |2 - 1 -2.6314711410821801e-01 2.4664715027249615e+00 -1.7093568570971751e-01 - 2 3.1632911016085430e-01 2.9434731493855670e+00 -8.5432214735894441e-01 - 3 -6.7623447816539795e-01 1.2410822625702851e+00 -6.1935152269952987e-01 - 4 -1.5552134736900181e+00 1.4878541801000127e+00 -1.2440909745472499e+00 - 5 -8.7601967096356681e-01 9.3417436540695586e-01 4.0272031680403497e-01 - 6 3.0755837780652939e-01 2.2629147986257614e-01 -1.2791162680675363e+00 - 7 3.5322094628055822e-01 -1.0043890952604606e-02 -2.4548503163676925e+00 - 8 1.1736205127906949e+00 -4.8269091330534497e-01 -6.7273784266497216e-01 - 9 1.3865071239751776e+00 -2.5278331076587346e-01 2.6996653369767554e-01 - 10 2.0239883243188919e+00 -1.4252201368166180e+00 -9.6228264545848585e-01 - 11 1.7991233925762300e+00 -1.9828365722523360e+00 -1.8762366544349351e+00 - 12 3.0044710092991540e+00 -4.8928363303993549e-01 -1.6126944183950824e+00 - 13 4.0415308387389697e+00 -9.0061411582067930e-01 -1.6321139880361839e+00 - 14 2.6064005411337394e+00 -4.0859653026992238e-01 -2.6465043951812257e+00 - 15 2.9775904824776660e+00 5.6065407887794816e-01 -1.2391617757507083e+00 - 16 2.6542663248050005e+00 -2.3895844048758690e+00 3.5746598094905657e-02 - 17 2.2355490747039930e+00 -2.0962135127176689e+00 1.1489434027787402e+00 - 18 2.0921160979688356e+00 2.9872159674132197e+00 -3.4902339097021988e+00 - 19 1.4908686219050935e+00 2.6025398330890352e+00 -4.2194623779111327e+00 - 20 2.7154518806596677e+00 3.6506388357590405e+00 -3.9111287168646642e+00 - 21 4.8435638296059782e+00 -4.0881941921713345e+00 -3.5957796498843582e+00 - 22 4.3080557005390165e+00 -4.2177797604315348e+00 -4.4370935526129456e+00 - 23 5.6713237924952811e+00 -3.5912865024270464e+00 -3.8555915013200188e+00 - 24 2.0228224543362074e+00 3.1208125399078126e+00 3.1634860992081633e+00 - 25 1.2576132296064850e+00 3.2447174749282715e+00 2.5191319958263714e+00 - 26 2.5334951322496941e+00 3.9783477827943221e+00 3.2212409164234250e+00 - 27 -1.8488304998563310e+00 -4.2601261704683537e+00 2.0568476369354167e+00 - 28 -2.6026086128772414e+00 -3.9329047688996477e+00 1.5399898445636326e+00 - 29 -1.2195954744860948e+00 -3.5211468177700955e+00 2.2116264666073553e+00 + 1 -2.6314711410922875e-01 2.4664715027241684e+00 -1.7093568570875561e-01 + 2 3.1632911015968190e-01 2.9434731493852482e+00 -8.5432214735778889e-01 + 3 -6.7623447816593885e-01 1.2410822625695044e+00 -6.1935152269903870e-01 + 4 -1.5552134736906362e+00 1.4878541800991378e+00 -1.2440909745466859e+00 + 5 -8.7601967096402067e-01 9.3417436540572218e-01 4.0272031680440712e-01 + 6 3.0755837780638462e-01 2.2629147986241449e-01 -1.2791162680673960e+00 + 7 3.5322094628053069e-01 -1.0043890952307954e-02 -2.4548503163676365e+00 + 8 1.1736205127907979e+00 -4.8269091330540537e-01 -6.7273784266507608e-01 + 9 1.3865071239751696e+00 -2.5278331076620741e-01 2.6996653369766221e-01 + 10 2.0239883243193546e+00 -1.4252201368162511e+00 -9.6228264545891751e-01 + 11 1.7991233925769246e+00 -1.9828365722517098e+00 -1.8762366544355809e+00 + 12 3.0044710092992837e+00 -4.8928363303895761e-01 -1.6126944183951402e+00 + 13 4.0415308387392486e+00 -9.0061411581930262e-01 -1.6321139880363669e+00 + 14 2.6064005411338655e+00 -4.0859653026870735e-01 -2.6465043951812621e+00 + 15 2.9775904824773907e+00 5.6065407887877150e-01 -1.2391617757503752e+00 + 16 2.6542663248057963e+00 -2.3895844048756363e+00 3.5746598094128501e-02 + 17 2.2355490747046538e+00 -2.0962135127180099e+00 1.1489434027780590e+00 + 18 2.0921160979727347e+00 2.9872159674143273e+00 -3.4902339097026891e+00 + 19 1.4908686219092431e+00 2.6025398330908249e+00 -4.2194623779121834e+00 + 20 2.7154518806645740e+00 3.6506388357595867e+00 -3.9111287168645399e+00 + 21 4.8435638296030810e+00 -4.0881941921728835e+00 -3.5957796498833634e+00 + 22 4.3080557005367073e+00 -4.2177797604324549e+00 -4.4370935526124242e+00 + 23 5.6713237924930837e+00 -3.5912865024293716e+00 -3.8555915013182531e+00 + 24 2.0228224543345528e+00 3.1208125399081723e+00 3.1634860992076259e+00 + 25 1.2576132296055036e+00 3.2447174749294536e+00 2.5191319958251963e+00 + 26 2.5334951322488237e+00 3.9783477827941720e+00 3.2212409164234312e+00 + 27 -1.8488304998563332e+00 -4.2601261704683342e+00 2.0568476369354265e+00 + 28 -2.6026086128772454e+00 -3.9329047688996304e+00 1.5399898445636406e+00 + 29 -1.2195954744860957e+00 -3.5211468177700818e+00 2.2116264666073615e+00 run_vel: ! |2 - 1 1.2393084479632990e-03 7.0215195817088653e-04 -1.1910956210641626e-03 - 2 1.3060936199990425e-03 2.5041119719272501e-04 -1.4496302699049824e-03 - 3 8.7069732478185780e-04 6.1866591813723552e-04 -6.2317312592577423e-04 - 4 8.8100215742054977e-04 5.8380213791498826e-04 -6.5145037264871986e-04 - 5 8.7979303398027825e-04 1.1152950208759250e-03 -4.7231382224803808e-04 - 6 5.3965146863318037e-04 6.8643008418777597e-05 -2.7149223435852534e-04 - 7 3.7117679682175872e-04 -4.5322194777188925e-04 -1.7317402888836805e-04 - 8 4.0378854177636902e-04 9.9015358993729126e-05 -4.1783685861320472e-05 - 9 5.4970639315548295e-04 4.5048022318715903e-04 -1.6045108899934789e-04 - 10 1.2521448037932167e-04 -2.5472783650505810e-04 2.9052485920883609e-04 - 11 -1.0599027352509822e-04 -5.9051612835328310e-04 5.5226010155811516e-04 - 12 3.1798607399596227e-04 -7.9980833669007897e-04 -2.0274707260252713e-04 - 13 2.0597404142647623e-04 -1.0865778699534437e-03 -1.1731137935602721e-04 - 14 2.4719215573317237e-04 -1.1410575874167027e-03 -2.0209037936245712e-04 - 15 6.3286464043707177e-04 -6.3068988069316188e-04 -6.5527927471316393e-04 - 16 -4.4100406049097274e-05 8.6869240447760984e-06 6.5198761255915241e-04 - 17 1.3407421346951786e-04 6.0357565278281160e-04 5.6233596575944243e-04 - 18 7.9277804690583290e-04 -1.5618239874403777e-03 2.1367192719678641e-03 - 19 5.6167660797931120e-04 -1.2371794194899347e-03 2.1562222137423708e-03 - 20 1.1137406410129261e-03 -1.8729421751404616e-03 2.1222207985342511e-03 - 21 -2.8426953558134279e-03 -2.9730185469798933e-03 1.8564402246260027e-03 - 22 -2.9480844379788478e-03 -2.6797216173783146e-03 1.8784164631756271e-03 - 23 -2.5997293519666649e-03 -3.3926375081648440e-03 1.8288830284145640e-03 - 24 1.1689404599038080e-03 -1.6701257754522614e-03 2.1428138286392188e-03 - 25 1.2027302640324651e-03 -1.2630861421198962e-03 2.1808987508666854e-03 - 26 1.6116362268904522e-03 -1.9337182438142464e-03 2.1377249582866698e-03 + 1 1.2393084479630032e-03 7.0215195817154908e-04 -1.1910956210640377e-03 + 2 1.3060936199988530e-03 2.5041119719347138e-04 -1.4496302699051106e-03 + 3 8.7069732478159932e-04 6.1866591813748793e-04 -6.2317312592554438e-04 + 4 8.8100215742025042e-04 5.8380213791515870e-04 -6.5145037264846355e-04 + 5 8.7979303397991721e-04 1.1152950208762108e-03 -4.7231382224758082e-04 + 6 5.3965146863311749e-04 6.8643008418756997e-05 -2.7149223435848598e-04 + 7 3.7117679682181569e-04 -4.5322194777211666e-04 -1.7317402888850959e-04 + 8 4.0378854177636355e-04 9.9015358993666161e-05 -4.1783685861269487e-05 + 9 5.4970639315540587e-04 4.5048022318729201e-04 -1.6045108899919846e-04 + 10 1.2521448037946088e-04 -2.5472783650533852e-04 2.9052485920877543e-04 + 11 -1.0599027352488030e-04 -5.9051612835384288e-04 5.5226010155799091e-04 + 12 3.1798607399623077e-04 -7.9980833669012060e-04 -2.0274707260294395e-04 + 13 2.0597404142686724e-04 -1.0865778699535142e-03 -1.1731137935659032e-04 + 14 2.4719215573349167e-04 -1.1410575874168849e-03 -2.0209037936298269e-04 + 15 6.3286464043726856e-04 -6.3068988069288280e-04 -6.5527927471360488e-04 + 16 -4.4100406048952316e-05 8.6869240444182845e-06 6.5198761255923058e-04 + 17 1.3407421346950843e-04 6.0357565278263792e-04 5.6233596575975002e-04 + 18 7.9277804690569055e-04 -1.5618239874425177e-03 2.1367192719678593e-03 + 19 5.6167660797942721e-04 -1.2371794194922850e-03 2.1562222137424718e-03 + 20 1.1137406410123482e-03 -1.8729421751430327e-03 2.1222207985340819e-03 + 21 -2.8426953558137735e-03 -2.9730185469781377e-03 1.8564402246257746e-03 + 22 -2.9480844379790160e-03 -2.6797216173769355e-03 1.8784164631754769e-03 + 23 -2.5997293519674954e-03 -3.3926375081633348e-03 1.8288830284141457e-03 + 24 1.1689404599043950e-03 -1.6701257754515664e-03 2.1428138286394673e-03 + 25 1.2027302640333160e-03 -1.2630861421196525e-03 2.1808987508670514e-03 + 26 1.6116362268906777e-03 -1.9337182438138849e-03 2.1377249582867847e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_npt_small.yaml b/unittest/force-styles/tests/fix-timestep-rigid_npt_small.yaml index 466f5ac5fb..57d18854e0 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_npt_small.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_npt_small.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:41 202 +date_generated: Tue Sep 15 22:36:56 202 epsilon: 2.5e-13 prerequisites: ! | atom full @@ -12,38 +12,38 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -8.7531774792845880e+01 5.5811525713967427e+00 -5.5468297751741936e+01 -1.5316306340330462e+02 1.4641268099032845e+02 1.7263710124990443e+01 -global_scalar: 77.7898343033466 + -8.7531774769722233e+01 5.5811525017967618e+00 -5.5468297744356789e+01 -1.5316306343483367e+02 1.4641268097314369e+02 1.7263710089631282e+01 +global_scalar: 77.7898343029329 run_pos: ! |2 - 1 -4.6333219629017464e-01 2.7511450055072171e+00 -1.2865946102804671e-01 - 2 1.7937148390197599e-01 3.2800405238541188e+00 -8.8510337855740406e-01 - 3 -9.2104620265683845e-01 1.3941717929286863e+00 -6.2603796687146485e-01 - 4 -1.8960869879713140e+00 1.6675144043870791e+00 -1.3178544214441361e+00 - 5 -1.1426748052070774e+00 1.0535885915280208e+00 5.0562616550060646e-01 - 6 1.7070712623534234e-01 2.7107933832759024e-01 -1.3571701846607818e+00 - 7 2.2159329060533217e-01 1.0068698962056644e-02 -2.6593507556861287e+00 - 8 1.1315940381700900e+00 -5.1414408469810713e-01 -6.8596713849764512e-01 - 9 1.3675404538221958e+00 -2.6001531899017039e-01 3.5817751536668574e-01 - 10 2.0752698846777538e+00 -1.5574812996955973e+00 -1.0070795245589732e+00 - 11 1.8261547470632262e+00 -2.1745615463232557e+00 -2.0195839000289277e+00 - 12 3.1626236108721919e+00 -5.2019677375527529e-01 -1.7266801053748662e+00 - 13 4.3131602274136434e+00 -9.7533717592330937e-01 -1.7483045222381550e+00 - 14 2.7211536303665351e+00 -4.3036348628164767e-01 -2.8715539682061753e+00 - 15 3.1323683805789226e+00 6.4234915962461692e-01 -1.3123899007467301e+00 - 16 2.7746546569033050e+00 -2.6258578189757298e+00 9.7666596945760631e-02 - 17 2.3099360535750968e+00 -2.3017831004885014e+00 1.3305794265748698e+00 - 18 2.2091748314050417e+00 3.3564440703049438e+00 -3.8370878209013126e+00 - 19 1.5986312961637505e+00 2.9614993054696921e+00 -4.5778944294659887e+00 - 20 2.8405364052349338e+00 4.0335971973396720e+00 -4.2659151034058365e+00 - 21 5.2651527409770740e+00 -4.4761614286051783e+00 -3.9518304737729775e+00 - 22 4.7192922285199597e+00 -4.6119045763260864e+00 -4.8062296932313151e+00 - 23 6.1127575785040520e+00 -3.9811721112979788e+00 -4.2204729622207884e+00 - 24 2.1290800759969954e+00 3.5132841007979358e+00 3.5392070210911051e+00 - 25 1.3519459805791634e+00 3.6349473856919570e+00 2.8807586651537935e+00 - 26 2.6413474240254864e+00 4.3893648731783070e+00 3.6035699963144729e+00 - 27 -2.3204235087830414e+00 -4.7905434153253355e+00 2.3919287951693260e+00 - 28 -3.1811356909799748e+00 -4.4206486004504146e+00 1.8095625809313809e+00 - 29 -1.6019226098505461e+00 -3.9551927030788505e+00 2.5663248522870763e+00 + 1 -4.6333219629007161e-01 2.7511450055070625e+00 -1.2865946102806269e-01 + 2 1.7937148390204793e-01 3.2800405238539234e+00 -8.8510337855738808e-01 + 3 -9.2104620265671233e-01 1.3941717929286011e+00 -6.2603796687145774e-01 + 4 -1.8960869879711328e+00 1.6675144043869761e+00 -1.3178544214440926e+00 + 5 -1.1426748052069362e+00 1.0535885915279550e+00 5.0562616550054784e-01 + 6 1.7070712623541162e-01 2.7107933832755826e-01 -1.3571701846607374e+00 + 7 2.2159329060539701e-01 1.0068698962042433e-02 -2.6593507556860114e+00 + 8 1.1315940381701060e+00 -5.1414408469809381e-01 -6.8596713849763802e-01 + 9 1.3675404538221994e+00 -2.6001531899016506e-01 3.5817751536664133e-01 + 10 2.0752698846777218e+00 -1.5574812996955254e+00 -1.0070795245589492e+00 + 11 1.8261547470632067e+00 -2.1745615463231482e+00 -2.0195839000288469e+00 + 12 3.1626236108721066e+00 -5.2019677375525752e-01 -1.7266801053747978e+00 + 13 4.3131602274134853e+00 -9.7533717592326674e-01 -1.7483045222380902e+00 + 14 2.7211536303664605e+00 -4.3036348628163701e-01 -2.8715539682060491e+00 + 15 3.1323683805788374e+00 6.4234915962457073e-01 -1.3123899007466848e+00 + 16 2.7746546569032322e+00 -2.6258578189755974e+00 9.7666596945726880e-02 + 17 2.3099360535750506e+00 -2.3017831004883886e+00 1.3305794265747686e+00 + 18 2.2091748314094701e+00 3.3564440703097080e+00 -3.8370878208998480e+00 + 19 1.5986312961639815e+00 2.9614993054417287e+00 -4.5778944294436021e+00 + 20 2.8405364052167421e+00 4.0335971973474170e+00 -4.2659151034329339e+00 + 21 5.2651527410670678e+00 -4.4761614286515128e+00 -3.9518304737634447e+00 + 22 4.7192922284117014e+00 -4.6119045765637390e+00 -4.8062296930647124e+00 + 23 6.1127575782518644e+00 -3.9811721108739997e+00 -4.2204729624242692e+00 + 24 2.1290800761933255e+00 3.5132841007593623e+00 3.5392070209389175e+00 + 25 1.3519459804490630e+00 3.6349473854278020e+00 2.8807586653452137e+00 + 26 2.6413474233716503e+00 4.3893648735951771e+00 3.6035699967293215e+00 + 27 -2.3204235087828389e+00 -4.7905434153250859e+00 2.3919287951691697e+00 + 28 -3.1811356909797261e+00 -4.4206486004501846e+00 1.8095625809312565e+00 + 29 -1.6019226098503827e+00 -3.9551927030786480e+00 2.5663248522869146e+00 run_vel: ! |2 1 7.7867804888392077e-04 5.8970331623292821e-04 -2.2179517633030531e-04 2 2.7129529964126462e-03 4.6286427111164284e-03 3.5805549693846352e-03 @@ -62,15 +62,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 7.2384391134040955e-04 -6.0015829216475349e-04 1.5957533238985767e-03 - 19 1.7583138221050250e-03 -3.0158245947715639e-03 2.0310435057846504e-03 - 20 -1.4153552731881595e-03 9.7835305937683196e-04 9.3881222519315256e-04 - 21 -2.7591188769548157e-03 -5.1180650667742274e-04 2.2758295070616427e-03 - 22 -3.2319732392443201e-03 -3.0809796458321497e-03 2.9861065761939520e-03 - 23 6.9767442924221611e-04 -8.1543313165593767e-03 -8.9929522622873284e-04 - 24 1.7345816996370428e-03 -1.8508160077952193e-03 1.0723416139295039e-03 - 25 3.2855417747190488e-03 -4.5284294759700113e-03 -1.2529298996019375e-03 - 26 -3.4004728773874863e-03 8.5952141315486798e-04 5.0505027866838918e-03 + 18 7.2384391131466962e-04 -6.0015829212802744e-04 1.5957533238990557e-03 + 19 1.7583138222551382e-03 -3.0158245948490800e-03 2.0310435058142466e-03 + 20 -1.4153552732353322e-03 9.7835305930749246e-04 9.3881222516217452e-04 + 21 -2.7591188772323472e-03 -5.1180650802276303e-04 2.2758295071994400e-03 + 22 -3.2319732401280494e-03 -3.0809796427949646e-03 2.9861065768383484e-03 + 23 6.9767443123301817e-04 -8.1543313142268207e-03 -8.9929522742256325e-04 + 24 1.7345816999787503e-03 -1.8508160062822960e-03 1.0723416147087285e-03 + 25 3.2855417755407170e-03 -4.5284294762327620e-03 -1.2529299007822620e-03 + 26 -3.4004728795728927e-03 8.5952140737749570e-04 5.0505027847540657e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nve_group.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nve_group.yaml index b11626104d..71d222c599 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nve_group.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nve_group.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:42 202 +date_generated: Tue Sep 15 22:36:57 202 epsilon: 2.5e-13 prerequisites: ! | atom full @@ -13,65 +13,65 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -1.4245356938010630e+03 -1.4496493316651863e+03 -3.6144360982531375e+03 8.4840626794791422e+02 2.0318336802435149e+02 -6.0622397695991776e+02 + -1.4245356938011612e+03 -1.4496493316650422e+03 -3.6144360982532016e+03 8.4840626794792297e+02 2.0318336802442892e+02 -6.0622397695978816e+02 global_scalar: 15.7115214231781 run_pos: ! |2 - 1 -2.7899546863889757e-01 2.4731857340328407e+00 -1.7290667740246246e-01 - 2 3.0296221610270047e-01 2.9517129916957696e+00 -8.5798904387773733e-01 - 3 -6.9368802364133009e-01 1.2445115421754502e+00 -6.2281111198657968e-01 - 4 -1.5764879647102630e+00 1.4919714415841832e+00 -1.2492069414675773e+00 - 5 -8.9434512967433699e-01 9.3651699743513128e-01 4.0191726558252272e-01 - 6 2.9454439634454876e-01 2.2724545792546230e-01 -1.2845195053960661e+00 - 7 3.4049112903278611e-01 -9.4655678322095593e-03 -2.4634480020857445e+00 - 8 1.1644354555804766e+00 -4.8367776650961408e-01 -6.7663643940736429e-01 - 9 1.3781717822695931e+00 -2.5332509530012332e-01 2.6864954436590760e-01 - 10 2.0186368606041754e+00 -1.4285861423625910e+00 -9.6712491252777666e-01 - 11 1.7929137227577672e+00 -1.9875455388407388e+00 -1.8836565352266459e+00 - 12 3.0032775230399946e+00 -4.8983022415176181e-01 -1.6190248017342788e+00 - 13 4.0448964162126213e+00 -9.0213155122394928e-01 -1.6385398399478248e+00 - 14 2.6035151245016692e+00 -4.0874995493219357e-01 -2.6555999074785932e+00 - 15 2.9761196776172660e+00 5.6287237454106087e-01 -1.2442626196082420e+00 - 16 2.6517373021565369e+00 -2.3957035508394062e+00 3.3389262100735007e-02 - 17 2.2311114924743678e+00 -2.1018393228798926e+00 1.1496088522377799e+00 - 18 2.1390642573193248e+00 3.0164773560690969e+00 -3.5143984803853079e+00 - 19 1.5353246655137389e+00 2.6305911186311701e+00 -4.2455871034735111e+00 - 20 2.7649421538927594e+00 3.6818603528429303e+00 -3.9364115785986051e+00 - 21 4.9043112657306356e+00 -4.0774268210394267e+00 -3.6200836396131266e+00 - 22 4.3665322424289670e+00 -4.2075138112951516e+00 -4.4636587264886334e+00 - 23 5.7355405581991068e+00 -3.5789558641903501e+00 -3.8805763324092997e+00 - 24 2.0692780332812601e+00 3.1504920436415342e+00 3.1571131300669530e+00 - 25 1.3007297593170202e+00 3.2745259354176830e+00 2.5110163874105687e+00 - 26 2.5819416446100352e+00 4.0104903120757118e+00 3.2150249624525613e+00 + 1 -2.7899546863905123e-01 2.4731857340327181e+00 -1.7290667740231969e-01 + 2 3.0296221610252227e-01 2.9517129916957194e+00 -8.5798904387756503e-01 + 3 -6.9368802364141247e-01 1.2445115421753310e+00 -6.2281111198650718e-01 + 4 -1.5764879647103560e+00 1.4919714415840475e+00 -1.2492069414674947e+00 + 5 -8.9434512967440649e-01 9.3651699743494377e-01 4.0191726558257690e-01 + 6 2.9454439634452678e-01 2.2724545792543693e-01 -1.2845195053960459e+00 + 7 3.4049112903278234e-01 -9.4655678321664549e-03 -2.4634480020857370e+00 + 8 1.1644354555804921e+00 -4.8367776650962330e-01 -6.7663643940738027e-01 + 9 1.3781717822695918e+00 -2.5332509530017322e-01 2.6864954436590494e-01 + 10 2.0186368606042460e+00 -1.4285861423625348e+00 -9.6712491252784183e-01 + 11 1.7929137227578726e+00 -1.9875455388406436e+00 -1.8836565352267429e+00 + 12 3.0032775230400142e+00 -4.8983022415161337e-01 -1.6190248017342870e+00 + 13 4.0448964162126639e+00 -9.0213155122374034e-01 -1.6385398399478515e+00 + 14 2.6035151245016883e+00 -4.0874995493201027e-01 -2.6555999074785985e+00 + 15 2.9761196776172243e+00 5.6287237454118566e-01 -1.2442626196081918e+00 + 16 2.6517373021566577e+00 -2.3957035508393689e+00 3.3389262100618433e-02 + 17 2.2311114924744668e+00 -2.1018393228799419e+00 1.1496088522376777e+00 + 18 2.1390642573199212e+00 3.0164773560692755e+00 -3.5143984803853900e+00 + 19 1.5353246655143720e+00 2.6305911186314508e+00 -4.2455871034736816e+00 + 20 2.7649421538935122e+00 3.6818603528430254e+00 -3.9364115785985936e+00 + 21 4.9043112657301942e+00 -4.0774268210396798e+00 -3.6200836396129796e+00 + 22 4.3665322424286144e+00 -4.2075138112953070e+00 -4.4636587264885614e+00 + 23 5.7355405581987764e+00 -3.5789558641907195e+00 -3.8805763324090350e+00 + 24 2.0692780332810026e+00 3.1504920436416008e+00 3.1571131300668833e+00 + 25 1.3007297593168636e+00 3.2745259354178766e+00 2.5110163874103986e+00 + 26 2.5819416446099002e+00 4.0104903120757012e+00 3.2150249624525742e+00 27 -1.9613581876744359e+00 -4.3556300596085160e+00 2.1101467673534788e+00 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 run_vel: ! |2 - 1 4.7093289825842822e-04 2.6351122778447077e-04 -4.4905093064114498e-04 - 2 4.9594625316470929e-04 9.4561370489625745e-05 -5.4581359894047363e-04 - 3 3.3306085115756277e-04 2.3224943880672107e-04 -2.3659455671746167e-04 - 4 3.3692327392261439e-04 2.1926810694049314e-04 -2.4716631558863080e-04 - 5 3.3642542694186029e-04 4.1797578013264637e-04 -1.8011341766657562e-04 - 6 2.0926869754934836e-04 2.6449308951571896e-05 -1.0508938983872182e-04 - 7 1.4629043007908084e-04 -1.6873376665350970e-04 -6.8354048774359419e-05 - 8 1.5844101624224778e-04 3.7728761274000532e-05 -1.9162715667091917e-05 - 9 2.1299362072601795e-04 1.6917140529157899e-04 -6.3528165037841878e-05 - 10 5.4261629412252272e-05 -9.4655528376805682e-05 1.0511362869146485e-04 - 11 -3.2194160796505001e-05 -2.2025095264758494e-04 2.0300202946211710e-04 - 12 1.2640586304750337e-04 -2.9851080445663953e-04 -7.9476371818245541e-05 - 13 8.4523575162141496e-05 -4.0583135407328702e-04 -4.7551111331698668e-05 - 14 9.9954050381271663e-05 -4.2610816481297622e-04 -7.9255633594383908e-05 - 15 2.4417481119789943e-04 -2.3521002264676751e-04 -2.4875318161048533e-04 - 16 -9.0958138549712697e-06 3.7774817121341365e-06 2.4035199548835218e-04 - 17 5.7507224523607053e-05 2.2629217444844902e-04 2.0686920072685291e-04 - 18 2.9220264989358690e-04 -6.2478376436779113e-04 8.4222594596602713e-04 - 19 2.0572616567795615e-04 -5.0334424271708381e-04 8.4953929443210246e-04 - 20 4.1224811789515093e-04 -7.4115205415990477e-04 8.3678612337509482e-04 - 21 -1.0671858777655896e-03 -1.1531171045501079e-03 7.3720674900162972e-04 - 22 -1.1066511338291411e-03 -1.0433933757601768e-03 7.4544544325708855e-04 - 23 -9.7629260480932688e-04 -1.3100872491595415e-03 7.2687284219706961e-04 - 24 4.3308126651255062e-04 -6.6527658087326986e-04 8.4451298670662164e-04 - 25 4.4565811905435875e-04 -5.1298436273585293e-04 8.5878867884519347e-04 - 26 5.9865972692021269e-04 -7.6385263287081313e-04 8.4259943226841743e-04 + 1 4.7093289825841293e-04 2.6351122778450878e-04 -4.4905093064113820e-04 + 2 4.9594625316469953e-04 9.4561370489667690e-05 -5.4581359894048231e-04 + 3 3.3306085115754900e-04 2.3224943880673573e-04 -2.3659455671744771e-04 + 4 3.3692327392259743e-04 2.1926810694050262e-04 -2.4716631558861427e-04 + 5 3.3642542694184180e-04 4.1797578013266394e-04 -1.8011341766654835e-04 + 6 2.0926869754934465e-04 2.6449308951570318e-05 -1.0508938983871884e-04 + 7 1.4629043007908249e-04 -1.6873376665352393e-04 -6.8354048774366371e-05 + 8 1.5844101624224789e-04 3.7728761273996988e-05 -1.9162715667088746e-05 + 9 2.1299362072601516e-04 1.6917140529158729e-04 -6.3528165037833679e-05 + 10 5.4261629412260051e-05 -9.4655528376821931e-05 1.0511362869146147e-04 + 11 -3.2194160796493915e-05 -2.2025095264761762e-04 2.0300202946211090e-04 + 12 1.2640586304751801e-04 -2.9851080445664316e-04 -7.9476371818270898e-05 + 13 8.4523575162162963e-05 -4.0583135407329249e-04 -4.7551111331733104e-05 + 14 9.9954050381287994e-05 -4.2610816481298853e-04 -7.9255633594414862e-05 + 15 2.4417481119791065e-04 -2.3521002264675271e-04 -2.4875318161051281e-04 + 16 -9.0958138549621353e-06 3.7774817121143600e-06 2.4035199548835649e-04 + 17 5.7507224523608761e-05 2.2629217444844084e-04 2.0686920072687044e-04 + 18 2.9220264989358500e-04 -6.2478376436791039e-04 8.4222594596602756e-04 + 19 2.0572616567796797e-04 -5.0334424271721316e-04 8.4953929443210886e-04 + 20 4.1224811789512605e-04 -7.4115205416005038e-04 8.3678612337508614e-04 + 21 -1.0671858777656232e-03 -1.1531171045500114e-03 7.3720674900161617e-04 + 22 -1.1066511338291647e-03 -1.0433933757601002e-03 7.4544544325707944e-04 + 23 -9.7629260480938673e-04 -1.3100872491594617e-03 7.2687284219704544e-04 + 24 4.3308126651259079e-04 -6.6527658087322801e-04 8.4451298670663660e-04 + 25 4.4565811905441442e-04 -5.1298436273583461e-04 8.5878867884521515e-04 + 26 5.9865972692023438e-04 -7.6385263287079188e-04 8.4259943226842502e-04 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nve_molecule.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nve_molecule.yaml index 733ae4bed0..fdf2dd5c59 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nve_molecule.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nve_molecule.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:42 202 +date_generated: Tue Sep 15 22:36:57 202 epsilon: 2.5e-13 prerequisites: ! | atom full @@ -13,8 +13,8 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -4.9200114783104425e+01 -2.6907707681632978e+01 -6.0080872466970643e+00 -2.5620425754068116e+01 -1.3450222537284642e+01 -1.4947348675137455e+00 -global_scalar: 18.3405601681427 + -4.9200114774917928e+01 -2.6907707694141234e+01 -6.0080872444876876e+00 -2.5620425756344922e+01 -1.3450222538011758e+01 -1.4947348732783965e+00 +global_scalar: 18.3405601673644 run_pos: ! |2 1 -2.7993683669226832e-01 2.4726588069312840e+00 -1.7200860244148433e-01 2 3.0197083955402204e-01 2.9515239068888608e+00 -8.5689735572907566e-01 @@ -33,15 +33,15 @@ run_pos: ! |2 15 2.9756315249791303e+00 5.6334269722969288e-01 -1.2437650754599008e+00 16 2.6517554244980306e+00 -2.3957110424978438e+00 3.2908335999178327e-02 17 2.2309964792710639e+00 -2.1022918943319384e+00 1.1491948328949437e+00 - 18 2.1392027588259426e+00 3.0171068018410385e+00 -3.5144628518857144e+00 - 19 1.5366124996933792e+00 2.6286809834308120e+00 -4.2452547844370390e+00 - 20 2.7628161763644057e+00 3.6842251687447973e+00 -3.9370881219349219e+00 - 21 4.9036621348239384e+00 -4.0757648444484591e+00 -3.6192617654929755e+00 - 22 4.3655322292403929e+00 -4.2084949963658875e+00 -4.4622011118416509e+00 - 23 5.7380414791158731e+00 -3.5841969190355476e+00 -3.8827839827804009e+00 - 24 2.0701314764430689e+00 3.1499370533656190e+00 3.1565324853444698e+00 - 25 1.3030170721374641e+00 3.2711173928413317e+00 2.5081940917372791e+00 - 26 2.5776230786045939e+00 4.0127347066259897e+00 3.2182355135086644e+00 + 18 2.1392027588270928e+00 3.0171068018423082e+00 -3.5144628518853867e+00 + 19 1.5366124996934336e+00 2.6286809834236959e+00 -4.2452547844313493e+00 + 20 2.7628161763597592e+00 3.6842251687468450e+00 -3.9370881219419189e+00 + 21 4.9036621348471368e+00 -4.0757648444604762e+00 -3.6192617654906609e+00 + 22 4.3655322292129357e+00 -4.2084949964269480e+00 -4.4622011117992786e+00 + 23 5.7380414790507261e+00 -3.5841969189265162e+00 -3.8827839828320116e+00 + 24 2.0701314764933532e+00 3.1499370533556008e+00 3.1565324853054118e+00 + 25 1.3030170721038390e+00 3.2711173927738786e+00 2.5081940917867680e+00 + 26 2.5776230784374867e+00 4.0127347067334345e+00 3.2182355136150917e+00 27 -1.9613581876744359e+00 -4.3556300596085160e+00 2.1101467673534788e+00 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 @@ -63,15 +63,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 3.6149625095274778e-04 -3.1032459262586538e-04 8.1043030117478813e-04 - 19 8.5103884663454885e-04 -1.4572280597095664e-03 1.0163621287550262e-03 - 20 -6.5204659274983282e-04 4.3989037446081253e-04 4.9909839028816031e-04 - 21 -1.3888125887768562e-03 -3.1978049174111308e-04 1.1455681505473695e-03 - 22 -1.6084223472408303e-03 -1.5355394238968283e-03 1.4772010818589064e-03 - 23 2.6392672559722471e-04 -3.9375414420642855e-03 -3.6991583288341215e-04 - 24 8.6062827042478272e-04 -9.4179873506334698e-04 5.5396395546095079e-04 - 25 1.5933645477524169e-03 -2.2139156628045906e-03 -5.5078029709943800e-04 - 26 -1.5679561733890394e-03 3.5146224505577979e-04 2.4446924196328459e-03 + 18 3.6149625094898083e-04 -3.1032459262177046e-04 8.1043030117471950e-04 + 19 8.5103884664914189e-04 -1.4572280597118458e-03 1.0163621287571445e-03 + 20 -6.5204659274939046e-04 4.3989037444674766e-04 4.9909839028631543e-04 + 21 -1.3888125888095134e-03 -3.1978049191290828e-04 1.1455681505629727e-03 + 22 -1.6084223473476298e-03 -1.5355394235202365e-03 1.4772010819351848e-03 + 23 2.6392672583440695e-04 -3.9375414417551127e-03 -3.6991583302200246e-04 + 24 8.6062827046548757e-04 -9.4179873487668705e-04 5.5396395555797225e-04 + 25 1.5933645478462869e-03 -2.2139156628290971e-03 -5.5078029723781006e-04 + 26 -1.5679561736454228e-03 3.5146224433513598e-04 2.4446924193838983e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nve_single.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nve_single.yaml index 19416939d5..d4780f234f 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nve_single.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nve_single.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:42 202 +date_generated: Tue Sep 15 22:36:58 202 epsilon: 2.5e-13 prerequisites: ! | atom full @@ -13,26 +13,26 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -1.3754817467882001e+03 -1.4228425246443051e+03 -3.6087196200592211e+03 8.7407043142561224e+02 2.1665316510417915e+02 -6.0480791467760923e+02 -global_scalar: 4.53142303857025 + -1.3754817467882772e+03 -1.4228425246441275e+03 -3.6087196200592480e+03 8.7407043142559348e+02 2.1665316510426322e+02 -6.0480791467747576e+02 +global_scalar: 4.53142303857033 run_pos: ! |2 - 1 -2.7899546859691271e-01 2.4731857340428940e+00 -1.7290667720880570e-01 - 2 3.0296221616799635e-01 2.9517129917211671e+00 -8.5798904365355999e-01 - 3 -6.9368802362164272e-01 1.2445115422150048e+00 -6.2281111185293192e-01 - 4 -1.5764879646738923e+00 1.4919714416722523e+00 -1.2492069413382727e+00 - 5 -8.9434512967957924e-01 9.3651699743540839e-01 4.0191726569948305e-01 - 6 2.9454439635069130e-01 2.2724545796945167e-01 -1.2845195052894625e+00 - 7 3.4049112905320356e-01 -9.4655677385257209e-03 -2.4634480019885614e+00 - 8 1.1644354555589551e+00 -4.8367776651302752e-01 -6.7663643931661333e-01 - 9 1.3781717822376145e+00 -2.5332509534949033e-01 2.6864954447022071e-01 - 10 2.0186368605645622e+00 -1.4285861423743027e+00 -9.6712491246322974e-01 - 11 1.7929137227201126e+00 -1.9875455388074434e+00 -1.8836565351900285e+00 - 12 3.0032775230343445e+00 -4.8983022415937488e-01 -1.6190248016125284e+00 - 13 4.0448964161972523e+00 -9.0213155125610900e-01 -1.6385398398261353e+00 - 14 2.6035151245156194e+00 -4.0874995488538468e-01 -2.6555999073601440e+00 - 15 2.9761196776309022e+00 5.6287237451795524e-01 -1.2442626194415798e+00 - 16 2.6517373020763406e+00 -2.3957035509096727e+00 3.3389262134360442e-02 - 17 2.2311114923823547e+00 -2.1018393229880195e+00 1.1496088522769190e+00 + 1 -2.7899546859706881e-01 2.4731857340427750e+00 -1.7290667720866193e-01 + 2 3.0296221616781649e-01 2.9517129917211218e+00 -8.5798904365338713e-01 + 3 -6.9368802362172777e-01 1.2445115422148878e+00 -6.2281111185285920e-01 + 4 -1.5764879646739900e+00 1.4919714416721197e+00 -1.2492069413381908e+00 + 5 -8.9434512967965252e-01 9.3651699743522254e-01 4.0191726569953845e-01 + 6 2.9454439635066831e-01 2.2724545796942719e-01 -1.2845195052894431e+00 + 7 3.4049112905319934e-01 -9.4655677384814507e-03 -2.4634480019885556e+00 + 8 1.1644354555589707e+00 -4.8367776651303718e-01 -6.7663643931662931e-01 + 9 1.3781717822376129e+00 -2.5332509534954067e-01 2.6864954447021949e-01 + 10 2.0186368605646337e+00 -1.4285861423742481e+00 -9.6712491246329535e-01 + 11 1.7929137227202196e+00 -1.9875455388073511e+00 -1.8836565351901273e+00 + 12 3.0032775230343667e+00 -4.8983022415922672e-01 -1.6190248016125368e+00 + 13 4.0448964161972993e+00 -9.0213155125590028e-01 -1.6385398398261621e+00 + 14 2.6035151245156412e+00 -4.0874995488520105e-01 -2.6555999073601511e+00 + 15 2.9761196776308623e+00 5.6287237451808192e-01 -1.2442626194415292e+00 + 16 2.6517373020764632e+00 -2.3957035509096389e+00 3.3389262134244646e-02 + 17 2.2311114923824555e+00 -2.1018393229880719e+00 1.1496088522768189e+00 18 2.1384791188033843e+00 3.0177261773770208e+00 -3.5160827596876225e+00 19 1.5349125211132961e+00 2.6315969880333707e+00 -4.2472859440220647e+00 20 2.7641167828863153e+00 3.6833419064000221e+00 -3.9380850623312638e+00 @@ -46,23 +46,23 @@ run_pos: ! |2 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 run_vel: ! |2 - 1 4.7093296226166030e-04 2.6351124312056276e-04 -4.4905063547614088e-04 - 2 4.9594635271877621e-04 9.4561409237131533e-05 -5.4581325723052814e-04 - 3 3.3306088119083302e-04 2.3224949911014063e-04 -2.3659435306900835e-04 - 4 3.3692332940286982e-04 2.1926824120527540e-04 -2.4716611858556823e-04 - 5 3.3642541894624174e-04 4.1797578053942325e-04 -1.8011323945928826e-04 - 6 2.0926870695908416e-04 2.6449376032433866e-05 -1.0508922741401649e-04 - 7 1.4629046128363069e-04 -1.6873362379724041e-04 -6.8353900724078427e-05 - 8 1.5844098346817965e-04 3.7728756087618508e-05 -1.9162577392849601e-05 - 9 2.1299357198252983e-04 1.6917133003967010e-04 -6.3528006071196204e-05 - 10 5.4261569071245287e-05 -9.4655546204693502e-05 1.0511372702289562e-04 - 11 -3.2194218121523810e-05 -2.2025090185602106e-04 2.0300208519292106e-04 - 12 1.2640585449263605e-04 -2.9851081600945606e-04 -7.9476186245574772e-05 - 13 8.4523551795102371e-05 -4.0583140303606291e-04 -4.7550925831929232e-05 - 14 9.9954071734164831e-05 -4.2610809338913152e-04 -7.9255453072665335e-05 - 15 2.4417483202630110e-04 -2.3521005781667857e-04 -2.4875292755151528e-04 - 16 -9.0959360838858137e-06 3.7773746063309333e-06 2.4035204669042528e-04 - 17 5.7507084250805080e-05 2.2629200960630369e-04 2.0686926033794975e-04 + 1 4.7093296226164512e-04 2.6351124312060207e-04 -4.4905063547613525e-04 + 2 4.9594635271876732e-04 9.4561409237174874e-05 -5.4581325723053746e-04 + 3 3.3306088119081914e-04 2.3224949911015690e-04 -2.3659435306899615e-04 + 4 3.3692332940285356e-04 2.1926824120528714e-04 -2.4716611858555419e-04 + 5 3.3642541894622217e-04 4.1797578053944228e-04 -1.8011323945926297e-04 + 6 2.0926870695908053e-04 2.6449376032433595e-05 -1.0508922741401471e-04 + 7 1.4629046128363337e-04 -1.6873362379725315e-04 -6.8353900724086707e-05 + 8 1.5844098346817900e-04 3.7728756087615784e-05 -1.9162577392846985e-05 + 9 2.1299357198252555e-04 1.6917133003967901e-04 -6.3528006071188276e-05 + 10 5.4261569071252172e-05 -9.4655546204709209e-05 1.0511372702289220e-04 + 11 -3.2194218121513158e-05 -2.2025090185605299e-04 2.0300208519291455e-04 + 12 1.2640585449265077e-04 -2.9851081600945932e-04 -7.9476186245599193e-05 + 13 8.4523551795123811e-05 -4.0583140303606844e-04 -4.7550925831962043e-05 + 14 9.9954071734182138e-05 -4.2610809338914323e-04 -7.9255453072695788e-05 + 15 2.4417483202631259e-04 -2.3521005781666340e-04 -2.4875292755154174e-04 + 16 -9.0959360838789561e-06 3.7773746063112143e-06 2.4035204669043016e-04 + 17 5.7507084250803752e-05 2.2629200960629542e-04 2.0686926033796743e-04 18 -6.0936815808025862e-04 -9.3774557532468582e-04 -3.3558072507805731e-04 19 -6.9919768291957119e-04 -3.6060777270430031e-03 4.2833405289822791e-03 20 4.7777805013736515e-03 5.1003745845520452e-03 1.8002873923729241e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nve_small.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nve_small.yaml index 799e039bae..c6ecc22a44 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nve_small.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nve_small.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:42 202 +date_generated: Tue Sep 15 22:36:58 202 epsilon: 2.5e-13 prerequisites: ! | atom full @@ -13,8 +13,8 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -4.9200114783104425e+01 -2.6907707681632978e+01 -6.0080872466970643e+00 -2.5620425754068116e+01 -1.3450222537284642e+01 -1.4947348675137455e+00 -global_scalar: 0.500731871980239 + -4.9200114774917928e+01 -2.6907707694141234e+01 -6.0080872444876876e+00 -2.5620425756344922e+01 -1.3450222538011758e+01 -1.4947348732783965e+00 +global_scalar: 0.50073187196632 run_pos: ! |2 1 -2.7993683669226832e-01 2.4726588069312840e+00 -1.7200860244148433e-01 2 3.0197083955402204e-01 2.9515239068888608e+00 -8.5689735572907566e-01 @@ -33,15 +33,15 @@ run_pos: ! |2 15 2.9756315249791303e+00 5.6334269722969288e-01 -1.2437650754599008e+00 16 2.6517554244980306e+00 -2.3957110424978438e+00 3.2908335999178327e-02 17 2.2309964792710639e+00 -2.1022918943319384e+00 1.1491948328949437e+00 - 18 2.1392027588259426e+00 3.0171068018410385e+00 -3.5144628518857144e+00 - 19 1.5366124996933792e+00 2.6286809834308120e+00 -4.2452547844370390e+00 - 20 2.7628161763644057e+00 3.6842251687447973e+00 -3.9370881219349219e+00 - 21 4.9036621348239384e+00 -4.0757648444484591e+00 -3.6192617654929755e+00 - 22 4.3655322292403929e+00 -4.2084949963658875e+00 -4.4622011118416509e+00 - 23 5.7380414791158731e+00 -3.5841969190355476e+00 -3.8827839827804009e+00 - 24 2.0701314764430689e+00 3.1499370533656190e+00 3.1565324853444698e+00 - 25 1.3030170721374641e+00 3.2711173928413317e+00 2.5081940917372791e+00 - 26 2.5776230786045939e+00 4.0127347066259897e+00 3.2182355135086644e+00 + 18 2.1392027588270928e+00 3.0171068018423082e+00 -3.5144628518853867e+00 + 19 1.5366124996934336e+00 2.6286809834236959e+00 -4.2452547844313493e+00 + 20 2.7628161763597592e+00 3.6842251687468450e+00 -3.9370881219419189e+00 + 21 4.9036621348471368e+00 -4.0757648444604762e+00 -3.6192617654906609e+00 + 22 4.3655322292129357e+00 -4.2084949964269480e+00 -4.4622011117992786e+00 + 23 5.7380414790507261e+00 -3.5841969189265162e+00 -3.8827839828320116e+00 + 24 2.0701314764933532e+00 3.1499370533556008e+00 3.1565324853054118e+00 + 25 1.3030170721038390e+00 3.2711173927738786e+00 2.5081940917867680e+00 + 26 2.5776230784374867e+00 4.0127347067334345e+00 3.2182355136150917e+00 27 -1.9613581876744359e+00 -4.3556300596085160e+00 2.1101467673534788e+00 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 @@ -63,15 +63,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 3.6149625095274778e-04 -3.1032459262586538e-04 8.1043030117478813e-04 - 19 8.5103884663454885e-04 -1.4572280597095664e-03 1.0163621287550262e-03 - 20 -6.5204659274983282e-04 4.3989037446081253e-04 4.9909839028816031e-04 - 21 -1.3888125887768562e-03 -3.1978049174111308e-04 1.1455681505473695e-03 - 22 -1.6084223472408303e-03 -1.5355394238968283e-03 1.4772010818589064e-03 - 23 2.6392672559722471e-04 -3.9375414420642855e-03 -3.6991583288341215e-04 - 24 8.6062827042478272e-04 -9.4179873506334698e-04 5.5396395546095079e-04 - 25 1.5933645477524169e-03 -2.2139156628045906e-03 -5.5078029709943800e-04 - 26 -1.5679561733890394e-03 3.5146224505577979e-04 2.4446924196328459e-03 + 18 3.6149625094898083e-04 -3.1032459262177046e-04 8.1043030117471950e-04 + 19 8.5103884664914189e-04 -1.4572280597118458e-03 1.0163621287571445e-03 + 20 -6.5204659274939046e-04 4.3989037444674766e-04 4.9909839028631543e-04 + 21 -1.3888125888095134e-03 -3.1978049191290828e-04 1.1455681505629727e-03 + 22 -1.6084223473476298e-03 -1.5355394235202365e-03 1.4772010819351848e-03 + 23 2.6392672583440695e-04 -3.9375414417551127e-03 -3.6991583302200246e-04 + 24 8.6062827046548757e-04 -9.4179873487668705e-04 5.5396395555797225e-04 + 25 1.5933645478462869e-03 -2.2139156628290971e-03 -5.5078029723781006e-04 + 26 -1.5679561736454228e-03 3.5146224433513598e-04 2.4446924193838983e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nvt.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nvt.yaml index d2950b829d..8a3a1d9c31 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nvt.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nvt.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:42 202 +date_generated: Tue Sep 15 22:36:59 202 epsilon: 5e-13 prerequisites: ! | atom full @@ -12,26 +12,26 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -1.3123962047751329e+03 -1.3675423591737690e+03 -3.5468492999580276e+03 7.8271738572462300e+02 2.6480486115425720e+02 -7.6950536863901277e+02 -global_scalar: 68.0865964742217 + -1.3123962047757550e+03 -1.3675423591710455e+03 -3.5468492999583855e+03 7.8271738572396384e+02 2.6480486115495091e+02 -7.6950536863736306e+02 +global_scalar: 68.0865964742317 run_pos: ! |2 - 1 -2.7802951913770868e-01 2.4737132264328308e+00 -1.7381271738810056e-01 - 2 3.0397800832728550e-01 2.9519031941438283e+00 -8.5908822750516822e-01 - 3 -6.9299720296286593e-01 1.2449766685883559e+00 -6.2329294828441417e-01 - 4 -1.5757894675962001e+00 1.4924105480993224e+00 -1.2497098747252475e+00 - 5 -8.9364750934319548e-01 9.3735293261268249e-01 4.0154813851909255e-01 - 6 2.9498813449207129e-01 2.2729986883011363e-01 -1.2847387164263608e+00 - 7 3.4080910885033866e-01 -9.8008218366116284e-03 -2.4635938021180581e+00 - 8 1.1647778042703230e+00 -4.8360070140693001e-01 -6.7668409924195017e-01 - 9 1.3786230528159205e+00 -2.5298559880078242e-01 2.6851325883864419e-01 - 10 2.0187712935455902e+00 -1.4287732348430000e+00 -9.6692440387054135e-01 - 11 1.7928755785816499e+00 -1.9879833661326805e+00 -1.8832605388676149e+00 - 12 3.0035558347416837e+00 -4.9042429038483137e-01 -1.6191927838344911e+00 - 13 4.0450911337524778e+00 -9.0293975523458492e-01 -1.6386440514131717e+00 - 14 2.6037405819191823e+00 -4.0959881564364919e-01 -2.6557674031620193e+00 - 15 2.9766330093341349e+00 5.6240461100592032e-01 -1.2447686007440930e+00 - 16 2.6517453810130034e+00 -2.3956939898031364e+00 3.3859750044474057e-02 - 17 2.2312525656134730e+00 -2.1013855689257279e+00 1.1500124166849996e+00 + 1 -2.7802951913990959e-01 2.4737132264311215e+00 -1.7381271738602289e-01 + 2 3.0397800832473609e-01 2.9519031941431444e+00 -8.5908822750267100e-01 + 3 -6.9299720296404743e-01 1.2449766685866726e+00 -6.2329294828335358e-01 + 4 -1.5757894675975461e+00 1.4924105480974301e+00 -1.2497098747240374e+00 + 5 -8.9364750934418624e-01 9.3735293261000852e-01 4.0154813851989335e-01 + 6 2.9498813449175199e-01 2.2729986882976547e-01 -1.2847387164260673e+00 + 7 3.4080910885027837e-01 -9.8008218359699473e-03 -2.4635938021179546e+00 + 8 1.1647778042705452e+00 -4.8360070140706557e-01 -6.7668409924218165e-01 + 9 1.3786230528159027e+00 -2.5298559880150862e-01 2.6851325883861188e-01 + 10 2.0187712935465942e+00 -1.4287732348422091e+00 -9.6692440387148870e-01 + 11 1.7928755785831587e+00 -1.9879833661313322e+00 -1.8832605388690278e+00 + 12 3.0035558347419657e+00 -4.9042429038271507e-01 -1.6191927838346238e+00 + 13 4.0450911337530959e+00 -9.0293975523160919e-01 -1.6386440514135796e+00 + 14 2.6037405819194577e+00 -4.0959881564101863e-01 -2.6557674031621108e+00 + 15 2.9766330093335447e+00 5.6240461100771322e-01 -1.2447686007433758e+00 + 16 2.6517453810147344e+00 -2.3956939898026426e+00 3.3859750042781744e-02 + 17 2.2312525656149020e+00 -2.1013855689264771e+00 1.1500124166835219e+00 18 2.1384791188033843e+00 3.0177261773770208e+00 -3.5160827596876225e+00 19 1.5349125211132961e+00 2.6315969880333707e+00 -4.2472859440220647e+00 20 2.7641167828863153e+00 3.6833419064000221e+00 -3.9380850623312638e+00 @@ -45,23 +45,23 @@ run_pos: ! |2 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 run_vel: ! |2 - 1 1.8443993556510503e-03 1.0121779579994334e-03 -1.7361326034903994e-03 - 2 1.9401022924564379e-03 3.6428754787360968e-04 -2.1069540627800783e-03 - 3 1.3158623602991188e-03 8.9265747656383358e-04 -9.2144725682236322e-04 - 4 1.3306255280105470e-03 8.4281508655937773e-04 -9.6194026572644226e-04 - 5 1.3289682243421974e-03 1.6048237018825233e-03 -7.0511232123213988e-04 - 6 8.4113718611853719e-04 1.0389683283150482e-04 -4.1697370456886506e-04 - 7 5.9950574545609200e-04 -6.4437674895145240e-04 -2.7586696717539212e-04 - 8 6.4634547270653927e-04 1.4734228826541389e-04 -8.7540766366893413e-05 - 9 8.5561404484529586e-04 6.5123532540296175e-04 -2.5782947158571319e-04 - 10 2.4688038968437656e-04 -3.5995975343979376e-04 3.8912416843293868e-04 - 11 -8.4672359473885383e-05 -8.4134349031467540e-04 7.6463157764253384e-04 - 12 5.2321633256236573e-04 -1.1418047427479729e-03 -3.1842516233433678e-04 - 13 3.6258187754787622e-04 -1.5531581259492578e-03 -1.9590476903839454e-04 - 14 4.2166181631225470e-04 -1.6310415916625015e-03 -3.1740232809197801e-04 - 15 9.7471807923322747e-04 -8.9939841791080669e-04 -9.6757308853273301e-04 - 16 4.1534888644708355e-06 1.7705740203958010e-05 9.0753010117789151e-04 - 17 2.5969943716028801e-04 8.7075266710323401e-04 7.7887058799549764e-04 + 1 1.8443993556501194e-03 1.0121779580014880e-03 -1.7361326034900004e-03 + 2 1.9401022924558353e-03 3.6428754787592717e-04 -2.1069540627804630e-03 + 3 1.3158623602983117e-03 8.9265747656461518e-04 -9.2144725682164765e-04 + 4 1.3306255280096098e-03 8.4281508655990065e-04 -9.6194026572564277e-04 + 5 1.3289682243410694e-03 1.6048237018834058e-03 -7.0511232123071578e-04 + 6 8.4113718611833759e-04 1.0389683283144291e-04 -4.1697370456874000e-04 + 7 5.9950574545626460e-04 -6.4437674895215539e-04 -2.7586696717582770e-04 + 8 6.4634547270651889e-04 1.4734228826522393e-04 -8.7540766366731677e-05 + 9 8.5561404484505246e-04 6.5123532540337949e-04 -2.5782947158524541e-04 + 10 2.4688038968480883e-04 -3.5995975344065598e-04 3.8912416843275036e-04 + 11 -8.4672359473207540e-05 -8.4134349031640384e-04 7.6463157764214765e-04 + 12 5.2321633256319677e-04 -1.1418047427480885e-03 -3.1842516233562650e-04 + 13 3.6258187754908706e-04 -1.5531581259494627e-03 -1.9590476904013686e-04 + 14 4.2166181631324295e-04 -1.6310415916630534e-03 -3.1740232809360442e-04 + 15 9.7471807923383419e-04 -8.9939841790992849e-04 -9.6757308853409715e-04 + 16 4.1534888649229478e-06 1.7705740202855492e-05 9.0753010117813307e-04 + 17 2.5969943716026037e-04 8.7075266710270329e-04 7.7887058799645153e-04 18 -6.0936815808025862e-04 -9.3774557532468582e-04 -3.3558072507805731e-04 19 -6.9919768291957119e-04 -3.6060777270430031e-03 4.2833405289822791e-03 20 4.7777805013736515e-03 5.1003745845520452e-03 1.8002873923729241e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nvt_small.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nvt_small.yaml index 5a500df244..814353d1b2 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nvt_small.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nvt_small.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:42 202 +date_generated: Tue Sep 15 22:36:59 202 epsilon: 2.5e-13 prerequisites: ! | atom full @@ -12,8 +12,8 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -1.4827261120559041e+02 -1.8411194247813761e+01 -1.0752762861073667e+02 -2.1814511473385389e+02 1.7027764309482512e+02 2.1058942295369583e+01 -global_scalar: 0.953260955609303 + -1.4827261116680450e+02 -1.8411194349753366e+01 -1.0752762859308652e+02 -2.1814511477016262e+02 1.7027764307147635e+02 2.1058942244057143e+01 +global_scalar: 0.953260955473961 run_pos: ! |2 1 -2.7993683669226832e-01 2.4726588069312840e+00 -1.7200860244148433e-01 2 3.0197083955402204e-01 2.9515239068888608e+00 -8.5689735572907566e-01 @@ -32,15 +32,15 @@ run_pos: ! |2 15 2.9756315249791303e+00 5.6334269722969288e-01 -1.2437650754599008e+00 16 2.6517554244980306e+00 -2.3957110424978438e+00 3.2908335999178327e-02 17 2.2309964792710639e+00 -2.1022918943319384e+00 1.1491948328949437e+00 - 18 2.1395635672932589e+00 3.0168023048438113e+00 -3.5136606977881328e+00 - 19 1.5374727853250358e+00 2.6272080573122807e+00 -4.2442423140709664e+00 - 20 2.7621434608188427e+00 3.6846842324656390e+00 -3.9366036440732435e+00 - 21 4.9022821624140818e+00 -4.0760572703872384e+00 -3.6181235131011493e+00 - 22 4.3639257460005378e+00 -4.2100277322528781e+00 -4.4607219431898768e+00 - 23 5.7383384136101201e+00 -3.5881799321988401e+00 -3.8831848686362500e+00 - 24 2.0709922900187094e+00 3.1490053461587988e+00 3.1570777021928111e+00 - 25 1.3046262535950155e+00 3.2688902578411003e+00 2.5076144139609760e+00 - 26 2.5760050692221945e+00 4.0131166908052700e+00 3.2207051908682689e+00 + 18 2.1395635672981443e+00 3.0168023048492310e+00 -3.5136606977867388e+00 + 19 1.5374727853253387e+00 2.6272080572819609e+00 -4.2442423140467360e+00 + 20 2.7621434607990372e+00 3.6846842324743214e+00 -3.9366036441030396e+00 + 21 4.9022821625125470e+00 -4.0760572704380627e+00 -3.6181235130909242e+00 + 22 4.3639257458824501e+00 -4.2100277325126187e+00 -4.4607219430080747e+00 + 23 5.7383384133351401e+00 -3.5881799317362106e+00 -3.8831848688588710e+00 + 24 2.0709922902331592e+00 3.1490053461169678e+00 3.1570777020268803e+00 + 25 1.3046262534530633e+00 3.2688902575528282e+00 2.5076144141701078e+00 + 26 2.5760050685080813e+00 4.0131166912605272e+00 3.2207051913215210e+00 27 -1.9613581876744359e+00 -4.3556300596085160e+00 2.1101467673534788e+00 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 @@ -62,15 +62,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 7.8522439442960720e-04 -6.6826115066907776e-04 1.7528441282148588e-03 - 19 1.8628941717468176e-03 -3.1840047050999288e-03 2.2062694139862180e-03 - 20 -1.4430972530733339e-03 9.7564145849438695e-04 1.0686492192934641e-03 - 21 -3.0047717243369713e-03 -6.6139343733813178e-04 2.4784169375747654e-03 - 22 -3.4980341561451885e-03 -3.3380963360956396e-03 3.2191613971836179e-03 - 23 5.9333930339444674e-04 -8.6231086246656499e-03 -8.2692040217646409e-04 - 24 1.8727912307154753e-03 -2.0349136837723969e-03 1.1951471744036815e-03 - 25 3.4887365949246578e-03 -4.8232966886339428e-03 -1.2263764476660806e-03 - 26 -3.4770257985509852e-03 7.8662050889240958e-04 5.3381090683576344e-03 + 18 7.8522439440007548e-04 -6.6826115062653757e-04 1.7528441282153480e-03 + 19 1.8628941719211860e-03 -3.1840047051916367e-03 2.2062694140207390e-03 + 20 -1.4430972531298200e-03 9.7564145841628493e-04 1.0686492192569896e-03 + 21 -3.0047717246574372e-03 -6.6139343888744952e-04 2.4784169377340712e-03 + 22 -3.4980341571643780e-03 -3.3380963325930985e-03 3.2191613979274045e-03 + 23 5.9333930569297963e-04 -8.6231086219834985e-03 -8.2692040355627789e-04 + 24 1.8727912311097637e-03 -2.0349136820274911e-03 1.1951471753018509e-03 + 25 3.4887365958745937e-03 -4.8232966889391275e-03 -1.2263764490291341e-03 + 26 -3.4770258010749858e-03 7.8662050223200905e-04 5.3381090661352281e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_single.yaml b/unittest/force-styles/tests/fix-timestep-rigid_single.yaml index 630cc3424d..6be1fafd47 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_single.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_single.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:42 202 +date_generated: Tue Sep 15 22:37:00 202 epsilon: 2.5e-13 prerequisites: ! | atom full @@ -13,26 +13,26 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -1.3754817466835852e+03 -1.4228425246165939e+03 -3.6087196201913630e+03 8.7407043149698166e+02 2.1665316519768876e+02 -6.0480791462031175e+02 -global_scalar: 4.53142303857031 + -1.3754817466835989e+03 -1.4228425246166139e+03 -3.6087196201914344e+03 8.7407043149698939e+02 2.1665316519769868e+02 -6.0480791462033017e+02 +global_scalar: 4.53142303857029 run_pos: ! |2 - 1 -2.7899546859693181e-01 2.4731857340428789e+00 -1.7290667720876129e-01 - 2 3.0296221616793595e-01 2.9517129917211555e+00 -8.5798904365355089e-01 - 3 -6.9368802362166315e-01 1.2445115422149753e+00 -6.2281111185285432e-01 - 4 -1.5764879646739509e+00 1.4919714416722003e+00 -1.2492069413381559e+00 - 5 -8.9434512967954460e-01 9.3651699743538708e-01 4.0191726569957620e-01 - 6 2.9454439635065854e-01 2.2724545796943085e-01 -1.2845195052894232e+00 - 7 3.4049112905311674e-01 -9.4655677385591108e-03 -2.4634480019885245e+00 - 8 1.1644354555589662e+00 -4.8367776651302741e-01 -6.7663643931660777e-01 - 9 1.3781717822376685e+00 -2.5332509534947545e-01 2.6864954447021527e-01 - 10 2.0186368605645773e+00 -1.4285861423742925e+00 -9.6712491246325638e-01 - 11 1.7929137227200924e+00 -1.9875455388074488e+00 -1.8836565351900403e+00 - 12 3.0032775230343129e+00 -4.8983022415935262e-01 -1.6190248016126150e+00 - 13 4.0448964161972292e+00 -9.0213155125606903e-01 -1.6385398398262687e+00 - 14 2.6035151245155346e+00 -4.0874995488538102e-01 -2.6555999073602141e+00 - 15 2.9761196776308703e+00 5.6287237451798355e-01 -1.2442626194416762e+00 - 16 2.6517373020764223e+00 -2.3957035509096416e+00 3.3389262134315478e-02 - 17 2.2311114923824862e+00 -2.1018393229879826e+00 1.1496088522768946e+00 + 1 -2.7899546859693136e-01 2.4731857340428784e+00 -1.7290667720876285e-01 + 2 3.0296221616793728e-01 2.9517129917211546e+00 -8.5798904365355155e-01 + 3 -6.9368802362166204e-01 1.2445115422149751e+00 -6.2281111185285498e-01 + 4 -1.5764879646739487e+00 1.4919714416722010e+00 -1.2492069413381564e+00 + 5 -8.9434512967954416e-01 9.3651699743538730e-01 4.0191726569957442e-01 + 6 2.9454439635065910e-01 2.2724545796943096e-01 -1.2845195052894232e+00 + 7 3.4049112905311751e-01 -9.4655677385591108e-03 -2.4634480019885228e+00 + 8 1.1644354555589662e+00 -4.8367776651302724e-01 -6.7663643931660777e-01 + 9 1.3781717822376680e+00 -2.5332509534947545e-01 2.6864954447021416e-01 + 10 2.0186368605645764e+00 -1.4285861423742918e+00 -9.6712491246325605e-01 + 11 1.7929137227200918e+00 -1.9875455388074483e+00 -1.8836565351900385e+00 + 12 3.0032775230343125e+00 -4.8983022415935312e-01 -1.6190248016126132e+00 + 13 4.0448964161972283e+00 -9.0213155125606947e-01 -1.6385398398262669e+00 + 14 2.6035151245155355e+00 -4.0874995488538129e-01 -2.6555999073602123e+00 + 15 2.9761196776308694e+00 5.6287237451798222e-01 -1.2442626194416753e+00 + 16 2.6517373020764219e+00 -2.3957035509096407e+00 3.3389262134315700e-02 + 17 2.2311114923824857e+00 -2.1018393229879817e+00 1.1496088522768926e+00 18 2.1384791188033843e+00 3.0177261773770208e+00 -3.5160827596876225e+00 19 1.5349125211132961e+00 2.6315969880333707e+00 -4.2472859440220647e+00 20 2.7641167828863153e+00 3.6833419064000221e+00 -3.9380850623312638e+00 @@ -46,23 +46,23 @@ run_pos: ! |2 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 run_vel: ! |2 - 1 4.7093296226165759e-04 2.6351124312057328e-04 -4.4905063547614815e-04 - 2 4.9594635271877263e-04 9.4561409237138648e-05 -5.4581325723053584e-04 - 3 3.3306088119083106e-04 2.3224949911015489e-04 -2.3659435306900921e-04 - 4 3.3692332940286711e-04 2.1926824120529708e-04 -2.4716611858556546e-04 - 5 3.3642541894624088e-04 4.1797578053943778e-04 -1.8011323945929135e-04 - 6 2.0926870695908297e-04 2.6449376032441632e-05 -1.0508922741401441e-04 - 7 1.4629046128362895e-04 -1.6873362379723160e-04 -6.8353900724071678e-05 - 8 1.5844098346817962e-04 3.7728756087619151e-05 -1.9162577392849499e-05 - 9 2.1299357198253027e-04 1.6917133003966806e-04 -6.3528006071200595e-05 - 10 5.4261569071246100e-05 -9.4655546204698788e-05 1.0511372702289762e-04 - 11 -3.2194218121523160e-05 -2.2025090185602363e-04 2.0300208519292848e-04 - 12 1.2640585449263567e-04 -2.9851081600946788e-04 -7.9476186245575856e-05 - 13 8.4523551795102534e-05 -4.0583140303608248e-04 -4.7550925831931509e-05 - 14 9.9954071734163638e-05 -4.2610809338913916e-04 -7.9255453072662124e-05 - 15 2.4417483202630001e-04 -2.3521005781669064e-04 -2.4875292755152092e-04 - 16 -9.0959360838833471e-06 3.7773746063198897e-06 2.4035204669042528e-04 - 17 5.7507084250808007e-05 2.2629200960629450e-04 2.0686926033794596e-04 + 1 4.7093296226165726e-04 2.6351124312057247e-04 -4.4905063547614652e-04 + 2 4.9594635271877252e-04 9.4561409237138173e-05 -5.4581325723053399e-04 + 3 3.3306088119083085e-04 2.3224949911015443e-04 -2.3659435306900835e-04 + 4 3.3692332940286711e-04 2.1926824120529689e-04 -2.4716611858556487e-04 + 5 3.3642541894624033e-04 4.1797578053943675e-04 -1.8011323945929070e-04 + 6 2.0926870695908275e-04 2.6449376032441517e-05 -1.0508922741401380e-04 + 7 1.4629046128362901e-04 -1.6873362379723092e-04 -6.8353900724071163e-05 + 8 1.5844098346817922e-04 3.7728756087618725e-05 -1.9162577392849018e-05 + 9 2.1299357198252964e-04 1.6917133003966706e-04 -6.3528006071199931e-05 + 10 5.4261569071245721e-05 -9.4655546204699004e-05 1.0511372702289778e-04 + 11 -3.2194218121523377e-05 -2.2025090185602322e-04 2.0300208519292837e-04 + 12 1.2640585449263546e-04 -2.9851081600946783e-04 -7.9476186245574907e-05 + 13 8.4523551795102276e-05 -4.0583140303608237e-04 -4.7550925831930506e-05 + 14 9.9954071734163652e-05 -4.2610809338913862e-04 -7.9255453072661283e-05 + 15 2.4417483202629974e-04 -2.3521005781669077e-04 -2.4875292755151935e-04 + 16 -9.0959360838839976e-06 3.7773746063190714e-06 2.4035204669042517e-04 + 17 5.7507084250807059e-05 2.2629200960629290e-04 2.0686926033794590e-04 18 -6.0936815808025862e-04 -9.3774557532468582e-04 -3.3558072507805731e-04 19 -6.9919768291957119e-04 -3.6060777270430031e-03 4.2833405289822791e-03 20 4.7777805013736515e-03 5.1003745845520452e-03 1.8002873923729241e-03 diff --git a/unittest/force-styles/tests/fix-timestep-rigid_small.yaml b/unittest/force-styles/tests/fix-timestep-rigid_small.yaml index d729cd77bc..bb44e6fe0f 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_small.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_small.yaml @@ -1,6 +1,6 @@ --- lammps_version: 24 Aug 2020 -date_generated: Tue Sep 15 09:44:42 202 +date_generated: Tue Sep 15 22:37:00 202 epsilon: 2.5e-13 prerequisites: ! | atom full @@ -13,7 +13,7 @@ post_commands: ! | input_file: in.fourmol natoms: 29 run_stress: ! |- - -4.9200116134790363e+01 -2.6907707565987732e+01 -6.0080860422282560e+00 -2.5620423972101747e+01 -1.3450224059984075e+01 -1.4947288487004844e+00 + -4.9200116134789894e+01 -2.6907707565987600e+01 -6.0080860422279923e+00 -2.5620423972101459e+01 -1.3450224059984031e+01 -1.4947288487004347e+00 global_scalar: 18.3405601674144 run_pos: ! |2 1 -2.7993683669226832e-01 2.4726588069312840e+00 -1.7200860244148433e-01 @@ -33,15 +33,15 @@ run_pos: ! |2 15 2.9756315249791303e+00 5.6334269722969288e-01 -1.2437650754599008e+00 16 2.6517554244980306e+00 -2.3957110424978438e+00 3.2908335999178327e-02 17 2.2309964792710639e+00 -2.1022918943319384e+00 1.1491948328949437e+00 - 18 2.1392027588271301e+00 3.0171068018412783e+00 -3.5144628518856349e+00 - 19 1.5366124997074573e+00 2.6286809834111744e+00 -4.2452547844370221e+00 - 20 2.7628161763455852e+00 3.6842251687634779e+00 -3.9370881219352558e+00 - 21 4.9036621347791245e+00 -4.0757648442838548e+00 -3.6192617654515908e+00 + 18 2.1392027588271301e+00 3.0171068018412779e+00 -3.5144628518856349e+00 + 19 1.5366124997074571e+00 2.6286809834111748e+00 -4.2452547844370221e+00 + 20 2.7628161763455852e+00 3.6842251687634775e+00 -3.9370881219352554e+00 + 21 4.9036621347791245e+00 -4.0757648442838548e+00 -3.6192617654515904e+00 22 4.3655322291888483e+00 -4.2084949965552561e+00 -4.4622011117402334e+00 23 5.7380414793463101e+00 -3.5841969195032672e+00 -3.8827839830470219e+00 24 2.0701314765323930e+00 3.1499370533342330e+00 3.1565324852522938e+00 - 25 1.3030170721374783e+00 3.2711173927682244e+00 2.5081940917429759e+00 - 26 2.5776230782480041e+00 4.0127347068243884e+00 3.2182355138709284e+00 + 25 1.3030170721374779e+00 3.2711173927682249e+00 2.5081940917429768e+00 + 26 2.5776230782480045e+00 4.0127347068243875e+00 3.2182355138709275e+00 27 -1.9613581876744359e+00 -4.3556300596085160e+00 2.1101467673534788e+00 28 -2.7406520384725965e+00 -4.0207251278130975e+00 1.5828689861678511e+00 29 -1.3108232656499081e+00 -3.5992986322410760e+00 2.2680459788743503e+00 @@ -63,15 +63,15 @@ run_vel: ! |2 15 -4.3301707382721859e-03 -3.1802661664634938e-03 3.2037919043360571e-03 16 -9.6715751018414326e-05 -5.0016572678960377e-04 1.4945658875149626e-03 17 6.5692180538157174e-04 3.6635779995305095e-04 8.3495414466050911e-04 - 18 3.6149625095704870e-04 -3.1032459262908302e-04 8.1043030117346052e-04 - 19 8.5103884665345441e-04 -1.4572280596788099e-03 1.0163621287634116e-03 - 20 -6.5204659278590758e-04 4.3989037444289831e-04 4.9909839028507966e-04 - 21 -1.3888125881903919e-03 -3.1978049143082570e-04 1.1455681499836646e-03 - 22 -1.6084223477729497e-03 -1.5355394240821158e-03 1.4772010826232373e-03 - 23 2.6392672378804886e-04 -3.9375414431174760e-03 -3.6991583139728127e-04 - 24 8.6062827067890290e-04 -9.4179873474469259e-04 5.5396395550012367e-04 - 25 1.5933645477487557e-03 -2.2139156625681682e-03 -5.5078029695647412e-04 - 26 -1.5679561743998888e-03 3.5146224354725948e-04 2.4446924193334482e-03 + 18 3.6149625095704908e-04 -3.1032459262908286e-04 8.1043030117346042e-04 + 19 8.5103884665345452e-04 -1.4572280596788108e-03 1.0163621287634116e-03 + 20 -6.5204659278590683e-04 4.3989037444289853e-04 4.9909839028507890e-04 + 21 -1.3888125881903923e-03 -3.1978049143082407e-04 1.1455681499836646e-03 + 22 -1.6084223477729508e-03 -1.5355394240821113e-03 1.4772010826232373e-03 + 23 2.6392672378805081e-04 -3.9375414431174812e-03 -3.6991583139728051e-04 + 24 8.6062827067890236e-04 -9.4179873474469237e-04 5.5396395550012442e-04 + 25 1.5933645477487542e-03 -2.2139156625681699e-03 -5.5078029695647488e-04 + 26 -1.5679561743998840e-03 3.5146224354726122e-04 2.4446924193334474e-03 27 -2.6510179146429716e-04 3.6306203629019116e-04 -5.6235585400647747e-04 28 -2.3068708109787484e-04 -8.5663070212203200e-04 2.1302563179109169e-03 29 -2.5054744388303732e-03 -1.6773997805290820e-04 2.8436699761004796e-03 From f7a939dec214b17f3075ddef09d7d158a6e480ec Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 16 Sep 2020 10:25:03 -0400 Subject: [PATCH 20/28] update atom_style tester for new jacobi implementation --- unittest/formats/test_atom_styles.cpp | 2156 +++++++++++++------------ 1 file changed, 1079 insertions(+), 1077 deletions(-) diff --git a/unittest/formats/test_atom_styles.cpp b/unittest/formats/test_atom_styles.cpp index 12171ae1d3..44d2c316e4 100644 --- a/unittest/formats/test_atom_styles.cpp +++ b/unittest/formats/test_atom_styles.cpp @@ -28,8 +28,8 @@ #include #include #include -#include #include +#include #if !defined(_FORTIFY_SOURCE) || (_FORTIFY_SOURCE == 0) #if defined(__INTEL_COMPILER) @@ -54,6 +54,8 @@ using LAMMPS_NS::utils::split_words; // whether to print verbose output (i.e. not capturing LAMMPS screen output). bool verbose = false; +const double EPSILON=1.0e-14; + namespace LAMMPS_NS { using ::testing::Eq; @@ -351,33 +353,33 @@ TEST_F(AtomStyleTest, atomic) auto x = lmp->atom->x; auto v = lmp->atom->v; auto tag = lmp->atom->tag; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); - ASSERT_NEAR(lmp->atom->mass[1], 4.0, 1.0e-14); - ASSERT_NEAR(lmp->atom->mass[2], 2.4, 1.0e-14); + EXPECT_NEAR(lmp->atom->mass[1], 4.0, EPSILON); + EXPECT_NEAR(lmp->atom->mass[2], 2.4, EPSILON); ASSERT_EQ(lmp->atom->mass_setflag[1], 1); ASSERT_EQ(lmp->atom->mass_setflag[2], 1); ASSERT_EQ(lmp->atom->map_style, Atom::MAP_ARRAY); @@ -406,21 +408,21 @@ TEST_F(AtomStyleTest, atomic) x = lmp->atom->x; v = lmp->atom->v; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); - ASSERT_NEAR(lmp->atom->mass[1], 4.0, 1.0e-14); - ASSERT_NEAR(lmp->atom->mass[2], 2.4, 1.0e-14); + EXPECT_NEAR(lmp->atom->mass[1], 4.0, EPSILON); + EXPECT_NEAR(lmp->atom->mass[2], 2.4, EPSILON); ASSERT_EQ(lmp->atom->mass_setflag[1], 1); ASSERT_EQ(lmp->atom->mass_setflag[2], 1); ASSERT_EQ(lmp->atom->map_style, Atom::MAP_ARRAY); @@ -439,54 +441,54 @@ TEST_F(AtomStyleTest, atomic) ASSERT_EQ(lmp->atom->map_tag_max, 16); x = lmp->atom->x; tag = lmp->atom->tag; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 6.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(7)][0], 6.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(7)][1], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(7)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(8)][0], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(8)][1], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(8)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(9)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(9)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(9)][2], 8.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(10)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(10)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(10)][2], 7.9, 1.0e-14); - ASSERT_NEAR(x[GETIDX(11)][0], 6.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(11)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(11)][2], 8.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(12)][0], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(12)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(12)][2], 7.9, 1.0e-14); - ASSERT_NEAR(x[GETIDX(13)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(13)][1], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(13)][2], 8.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(14)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(14)][1], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(14)][2], 7.9, 1.0e-14); - ASSERT_NEAR(x[GETIDX(15)][0], 6.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(15)][1], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(15)][2], 8.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(16)][0], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(16)][1], 10.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(16)][2], 7.9, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 6.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(7)][0], 6.0, EPSILON); + EXPECT_NEAR(x[GETIDX(7)][1], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(7)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(8)][0], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(8)][1], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(8)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(9)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(9)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(9)][2], 8.1, EPSILON); + EXPECT_NEAR(x[GETIDX(10)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(10)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(10)][2], 7.9, EPSILON); + EXPECT_NEAR(x[GETIDX(11)][0], 6.0, EPSILON); + EXPECT_NEAR(x[GETIDX(11)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(11)][2], 8.1, EPSILON); + EXPECT_NEAR(x[GETIDX(12)][0], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(12)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(12)][2], 7.9, EPSILON); + EXPECT_NEAR(x[GETIDX(13)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(13)][1], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(13)][2], 8.1, EPSILON); + EXPECT_NEAR(x[GETIDX(14)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(14)][1], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(14)][2], 7.9, EPSILON); + EXPECT_NEAR(x[GETIDX(15)][0], 6.0, EPSILON); + EXPECT_NEAR(x[GETIDX(15)][1], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(15)][2], 8.1, EPSILON); + EXPECT_NEAR(x[GETIDX(16)][0], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(16)][1], 10.0, EPSILON); + EXPECT_NEAR(x[GETIDX(16)][2], 7.9, EPSILON); } TEST_F(AtomStyleTest, charge) @@ -737,37 +739,37 @@ TEST_F(AtomStyleTest, charge) auto x = lmp->atom->x; auto v = lmp->atom->v; auto q = lmp->atom->q; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(1)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(2)], 0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(3)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(4)], 1.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(q[GETIDX(1)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(2)], 0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(3)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(4)], 1.0, EPSILON); - ASSERT_NEAR(lmp->atom->mass[1], 4.0, 1.0e-14); - ASSERT_NEAR(lmp->atom->mass[2], 2.4, 1.0e-14); + EXPECT_NEAR(lmp->atom->mass[1], 4.0, EPSILON); + EXPECT_NEAR(lmp->atom->mass[2], 2.4, EPSILON); ASSERT_EQ(lmp->atom->mass_setflag[1], 1); ASSERT_EQ(lmp->atom->mass_setflag[2], 1); @@ -777,7 +779,7 @@ TEST_F(AtomStyleTest, charge) lmp->input->one("delete_atoms group two compress no"); lmp->input->one("write_restart test_atom_styles.restart"); lmp->input->one("clear"); - EXPECT_THAT(std::string(lmp->atom->atom_style), Eq("atomic")); + ASSERT_THAT(std::string(lmp->atom->atom_style), Eq("atomic")); lmp->input->one("read_restart test_atom_styles.restart"); if (!verbose) ::testing::internal::GetCapturedStdout(); ASSERT_THAT(std::string(lmp->atom->atom_style), Eq("charge")); @@ -795,23 +797,23 @@ TEST_F(AtomStyleTest, charge) x = lmp->atom->x; v = lmp->atom->v; q = lmp->atom->q; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(1)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(3)], -1.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(q[GETIDX(1)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(3)], -1.0, EPSILON); - ASSERT_NEAR(lmp->atom->mass[1], 4.0, 1.0e-14); - ASSERT_NEAR(lmp->atom->mass[2], 2.4, 1.0e-14); + EXPECT_NEAR(lmp->atom->mass[1], 4.0, EPSILON); + EXPECT_NEAR(lmp->atom->mass[2], 2.4, EPSILON); ASSERT_EQ(lmp->atom->mass_setflag[1], 1); ASSERT_EQ(lmp->atom->mass_setflag[2], 1); @@ -822,22 +824,22 @@ TEST_F(AtomStyleTest, charge) if (!verbose) ::testing::internal::GetCapturedStdout(); ASSERT_EQ(lmp->atom->map_tag_max, 16); q = lmp->atom->q; - ASSERT_NEAR(q[GETIDX(1)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(2)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(3)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(4)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(5)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(6)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(7)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(8)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(9)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(10)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(11)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(12)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(13)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(14)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(15)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(16)], -1.0, 1.0e-14); + EXPECT_NEAR(q[GETIDX(1)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(2)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(3)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(4)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(5)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(6)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(7)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(8)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(9)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(10)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(11)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(12)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(13)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(14)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(15)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(16)], -1.0, EPSILON); } TEST_F(AtomStyleTest, sphere) @@ -1094,46 +1096,46 @@ TEST_F(AtomStyleTest, sphere) auto v = lmp->atom->v; auto rmass = lmp->atom->rmass; auto omega = lmp->atom->omega; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(1)], 4.0, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4.0, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 2.4, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(1)][0], -0.5, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(1)][1], 0.1, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(2)][0], 0.5, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(2)][1], -0.1, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(3)][0], -1.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(4)][1], 1.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(4)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(rmass[GETIDX(1)], 4.0, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4.0, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 2.4, EPSILON); + EXPECT_NEAR(omega[GETIDX(1)][0], -0.5, EPSILON); + EXPECT_NEAR(omega[GETIDX(1)][1], 0.1, EPSILON); + EXPECT_NEAR(omega[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(omega[GETIDX(2)][0], 0.5, EPSILON); + EXPECT_NEAR(omega[GETIDX(2)][1], -0.1, EPSILON); + EXPECT_NEAR(omega[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(omega[GETIDX(3)][0], -1.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(4)][1], 1.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(4)][2], 0.0, EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("pair_coeff * *"); @@ -1141,7 +1143,7 @@ TEST_F(AtomStyleTest, sphere) lmp->input->one("delete_atoms group two compress no"); lmp->input->one("write_restart test_atom_styles.restart"); lmp->input->one("clear"); - EXPECT_THAT(std::string(lmp->atom->atom_style), Eq("atomic")); + ASSERT_THAT(std::string(lmp->atom->atom_style), Eq("atomic")); lmp->input->one("read_restart test_atom_styles.restart"); lmp->input->one("replicate 1 1 2"); lmp->input->one("reset_atom_ids"); @@ -1160,22 +1162,22 @@ TEST_F(AtomStyleTest, sphere) rmass = lmp->atom->rmass; omega = lmp->atom->omega; - ASSERT_NEAR(rmass[GETIDX(1)], 4.0, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 4.0, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 2.4, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(1)][0], -0.5, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(1)][1], 0.1, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(2)][0], -1.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(3)][0], -0.5, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(3)][1], 0.1, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(3)][2], 0.1, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(4)][0], -1.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(omega[GETIDX(4)][2], 0.0, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4.0, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 4.0, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 2.4, EPSILON); + EXPECT_NEAR(omega[GETIDX(1)][0], -0.5, EPSILON); + EXPECT_NEAR(omega[GETIDX(1)][1], 0.1, EPSILON); + EXPECT_NEAR(omega[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(omega[GETIDX(2)][0], -1.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(3)][0], -0.5, EPSILON); + EXPECT_NEAR(omega[GETIDX(3)][1], 0.1, EPSILON); + EXPECT_NEAR(omega[GETIDX(3)][2], 0.1, EPSILON); + EXPECT_NEAR(omega[GETIDX(4)][0], -1.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(omega[GETIDX(4)][2], 0.0, EPSILON); } TEST_F(AtomStyleTest, ellipsoid) @@ -1454,42 +1456,42 @@ TEST_F(AtomStyleTest, ellipsoid) auto rmass = lmp->atom->rmass; auto avec = (AtomVecEllipsoid *)lmp->atom->avec; auto bonus = avec->bonus; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], -2.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], 2.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], -2.1, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], 2.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][2], 0.0, EPSILON); ASSERT_EQ(type[GETIDX(1)], 1); ASSERT_EQ(type[GETIDX(2)], 1); ASSERT_EQ(type[GETIDX(3)], 2); @@ -1502,41 +1504,41 @@ TEST_F(AtomStyleTest, ellipsoid) ASSERT_EQ(ellipsoid[GETIDX(4)], 3); ASSERT_EQ(ellipsoid[GETIDX(5)], -1); ASSERT_EQ(ellipsoid[GETIDX(6)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], sqrt(5.0 / 30.0), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], sqrt(5.0 / 30.0), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], sqrt(5.0 / 30.0), 1.0e-14); + EXPECT_NEAR(bonus[0].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[2].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[3].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[3].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[3].quat[1], sqrt(5.0 / 30.0), EPSILON); + EXPECT_NEAR(bonus[3].quat[2], sqrt(5.0 / 30.0), EPSILON); + EXPECT_NEAR(bonus[3].quat[3], sqrt(5.0 / 30.0), EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("group two id 2:4:2"); @@ -1581,43 +1583,43 @@ TEST_F(AtomStyleTest, ellipsoid) ASSERT_EQ(ellipsoid[GETIDX(9)], 3); ASSERT_EQ(ellipsoid[GETIDX(11)], -1); ASSERT_EQ(ellipsoid[GETIDX(12)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(7)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(9)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(11)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(12)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(7)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(9)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(11)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(12)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], 0.25056280708573159, 1.0e-14); + EXPECT_NEAR(bonus[0].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[1].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[2].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[3].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[3].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[3].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[3], 0.25056280708573159, EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("reset_atom_ids"); @@ -1646,43 +1648,43 @@ TEST_F(AtomStyleTest, ellipsoid) ASSERT_EQ(ellipsoid[GETIDX(6)], -1); ASSERT_EQ(ellipsoid[GETIDX(7)], 3); ASSERT_EQ(ellipsoid[GETIDX(8)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(7)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(8)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(7)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(8)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], 0.25056280708573159, 1.0e-14); + EXPECT_NEAR(bonus[0].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[1].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[2].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[3].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[3].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[3].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[3], 0.25056280708573159, EPSILON); } TEST_F(AtomStyleTest, line) @@ -1950,42 +1952,42 @@ TEST_F(AtomStyleTest, line) auto rmass = lmp->atom->rmass; auto avec = (AtomVecLine *)lmp->atom->avec; auto bonus = avec->bonus; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], 3.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], -3.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], 3.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], -3.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][2], 0.0, EPSILON); ASSERT_EQ(type[GETIDX(1)], 1); ASSERT_EQ(type[GETIDX(2)], 1); ASSERT_EQ(type[GETIDX(3)], 2); @@ -1998,21 +2000,21 @@ TEST_F(AtomStyleTest, line) ASSERT_EQ(line[GETIDX(4)], 3); ASSERT_EQ(line[GETIDX(5)], -1); ASSERT_EQ(line[GETIDX(6)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].length, 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].theta, 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].length, 2.0, 1.0e-14); - ASSERT_NEAR(bonus[1].theta, MathConst::MY_PI * 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].length, 3.0, 1.0e-14); - ASSERT_NEAR(bonus[2].theta, MathConst::MY_PI / 6.0, 1.0e-14); - ASSERT_NEAR(bonus[3].length, 3.0, 1.0e-14); - ASSERT_NEAR(bonus[3].theta, MathConst::MY_PI / 3.0, 1.0e-14); + EXPECT_NEAR(bonus[0].length, 2.0, EPSILON); + EXPECT_NEAR(bonus[0].theta, 0.0, EPSILON); + EXPECT_NEAR(bonus[1].length, 2.0, EPSILON); + EXPECT_NEAR(bonus[1].theta, MathConst::MY_PI * 0.5, EPSILON); + EXPECT_NEAR(bonus[2].length, 3.0, EPSILON); + EXPECT_NEAR(bonus[2].theta, MathConst::MY_PI / 6.0, EPSILON); + EXPECT_NEAR(bonus[3].length, 3.0, EPSILON); + EXPECT_NEAR(bonus[3].theta, MathConst::MY_PI / 3.0, EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("pair_coeff * *"); @@ -2059,23 +2061,23 @@ TEST_F(AtomStyleTest, line) ASSERT_EQ(line[GETIDX(9)], 3); ASSERT_EQ(line[GETIDX(11)], -1); ASSERT_EQ(line[GETIDX(12)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(7)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(9)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(11)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(12)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(7)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(9)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(11)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(12)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].length, 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].theta, 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].length, 3.0, 1.0e-14); - ASSERT_NEAR(bonus[1].theta, MathConst::MY_PI / 6.0, 1.0e-14); - ASSERT_NEAR(bonus[2].length, 2.0, 1.0e-14); - ASSERT_NEAR(bonus[2].theta, 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].length, 3.0, 1.0e-14); - ASSERT_NEAR(bonus[3].theta, MathConst::MY_PI / 6.0, 1.0e-14); + EXPECT_NEAR(bonus[0].length, 2.0, EPSILON); + EXPECT_NEAR(bonus[0].theta, 0.0, EPSILON); + EXPECT_NEAR(bonus[1].length, 3.0, EPSILON); + EXPECT_NEAR(bonus[1].theta, MathConst::MY_PI / 6.0, EPSILON); + EXPECT_NEAR(bonus[2].length, 2.0, EPSILON); + EXPECT_NEAR(bonus[2].theta, 0.0, EPSILON); + EXPECT_NEAR(bonus[3].length, 3.0, EPSILON); + EXPECT_NEAR(bonus[3].theta, MathConst::MY_PI / 6.0, EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("reset_atom_ids"); @@ -2104,23 +2106,23 @@ TEST_F(AtomStyleTest, line) ASSERT_EQ(line[GETIDX(6)], -1); ASSERT_EQ(line[GETIDX(7)], 3); ASSERT_EQ(line[GETIDX(8)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(7)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(8)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(7)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(8)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].length, 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].theta, 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].length, 3.0, 1.0e-14); - ASSERT_NEAR(bonus[1].theta, MathConst::MY_PI / 6.0, 1.0e-14); - ASSERT_NEAR(bonus[2].length, 2.0, 1.0e-14); - ASSERT_NEAR(bonus[2].theta, 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].length, 3.0, 1.0e-14); - ASSERT_NEAR(bonus[3].theta, MathConst::MY_PI / 6.0, 1.0e-14); + EXPECT_NEAR(bonus[0].length, 2.0, EPSILON); + EXPECT_NEAR(bonus[0].theta, 0.0, EPSILON); + EXPECT_NEAR(bonus[1].length, 3.0, EPSILON); + EXPECT_NEAR(bonus[1].theta, MathConst::MY_PI / 6.0, EPSILON); + EXPECT_NEAR(bonus[2].length, 2.0, EPSILON); + EXPECT_NEAR(bonus[2].theta, 0.0, EPSILON); + EXPECT_NEAR(bonus[3].length, 3.0, EPSILON); + EXPECT_NEAR(bonus[3].theta, MathConst::MY_PI / 6.0, EPSILON); } TEST_F(AtomStyleTest, tri) @@ -2400,42 +2402,42 @@ TEST_F(AtomStyleTest, tri) auto radius = lmp->atom->radius; auto avec = (AtomVecTri *)lmp->atom->avec; auto bonus = avec->bonus; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], -2.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], 2.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], -2.1, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], 2.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][2], 0.0, EPSILON); ASSERT_EQ(type[GETIDX(1)], 1); ASSERT_EQ(type[GETIDX(2)], 1); ASSERT_EQ(type[GETIDX(3)], 2); @@ -2448,83 +2450,83 @@ TEST_F(AtomStyleTest, tri) ASSERT_EQ(tri[GETIDX(4)], 3); ASSERT_EQ(tri[GETIDX(5)], -1); ASSERT_EQ(tri[GETIDX(6)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(1)], 0.5773502691896258, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(2)], 0.5773502691896258, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(3)], 0.8660254037844390, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(4)], 0.8660254037844390, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(5)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(6)], 0.5, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(radius[GETIDX(1)], 0.5773502691896258, EPSILON); + EXPECT_NEAR(radius[GETIDX(2)], 0.5773502691896258, EPSILON); + EXPECT_NEAR(radius[GETIDX(3)], 0.8660254037844390, EPSILON); + EXPECT_NEAR(radius[GETIDX(4)], 0.8660254037844390, EPSILON); + EXPECT_NEAR(radius[GETIDX(5)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(6)], 0.5, EPSILON); - ASSERT_NEAR(bonus[0].inertia[0], 0.072258416330334363, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[1], 13.94589575227541, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[2], 14.017974903242481, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[0], 13.982119044342252, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[1], 0.10811427523057447, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[2], 13.945895752275419, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[0], 0.23541253382609079, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[1], 18.948744087979005, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[2], 19.15175691481879, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[0], 19.018309360029388, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[1], 0.36886008861549813, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[2], 18.948744087979012, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 0.92373678792937974, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0067268233964605153, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.016239988275423625, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], -0.38262430562330857, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], 0.92420701665838023, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.023090752704586423, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], 0.0095209086022933816, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], -0.38107421822833848, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 0.90191325590647364, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.20096813128512517, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.10027584751231088, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.36892959143125964, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], 0.8851587738551242, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], 0.093233030525564045, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], -0.26735735980719261, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], 0.36921753647848277, 1.0e-14); - ASSERT_NEAR(bonus[0].c1[0], -0.14933690186163631, 1.0e-14); - ASSERT_NEAR(bonus[0].c1[1], -0.55767753582520529, 1.0e-14); - ASSERT_NEAR(bonus[0].c1[2], -0.0052525338293288905, 1.0e-14); - ASSERT_NEAR(bonus[1].c1[0], 0.18561232929671426, 1.0e-14); - ASSERT_NEAR(bonus[1].c1[1], -0.18681344121910506, 1.0e-14); - ASSERT_NEAR(bonus[1].c1[2], 0.51379191773154387, 1.0e-14); - ASSERT_NEAR(bonus[2].c1[0], -0.78775285695558617, 1.0e-14); - ASSERT_NEAR(bonus[2].c1[1], -0.28372571379613187, 1.0e-14); - ASSERT_NEAR(bonus[2].c1[2], -0.22123552085772166, 1.0e-14); - ASSERT_NEAR(bonus[3].c1[0], -0.69845793336676587, 1.0e-14); - ASSERT_NEAR(bonus[3].c1[1], -0.47901475403318056, 1.0e-14); - ASSERT_NEAR(bonus[3].c1[2], 0.18083523090249506, 1.0e-14); - ASSERT_NEAR(bonus[0].c2[0], 0.55733290519255385, 1.0e-14); - ASSERT_NEAR(bonus[0].c2[1], 0.14942924536134222, 1.0e-14); - ASSERT_NEAR(bonus[0].c2[2], 0.019602723119529659, 1.0e-14); - ASSERT_NEAR(bonus[1].c2[0], 0.2208094914375279, 1.0e-14); - ASSERT_NEAR(bonus[1].c2[1], -0.22223836695322471, 1.0e-14); - ASSERT_NEAR(bonus[1].c2[2], -0.48496042114630089, 1.0e-14); - ASSERT_NEAR(bonus[2].c2[0], 0.6304379562181005, 1.0e-14); - ASSERT_NEAR(bonus[2].c2[1], -0.56674478453558153, 1.0e-14); - ASSERT_NEAR(bonus[2].c2[2], 0.17705460333259249, 1.0e-14); - ASSERT_NEAR(bonus[3].c2[0], 0.22007613459534958, 1.0e-14); - ASSERT_NEAR(bonus[3].c2[1], 0.15093208974463554, 1.0e-14); - ASSERT_NEAR(bonus[3].c2[2], -0.8238847002262436, 1.0e-14); - ASSERT_NEAR(bonus[0].c3[0], -0.40799600333091751, 1.0e-14); - ASSERT_NEAR(bonus[0].c3[1], 0.40824829046386302, 1.0e-14); - ASSERT_NEAR(bonus[0].c3[2], -0.014350189290200811, 1.0e-14); - ASSERT_NEAR(bonus[1].c3[0], -0.40642182073424188, 1.0e-14); - ASSERT_NEAR(bonus[1].c3[1], 0.40905180817232945, 1.0e-14); - ASSERT_NEAR(bonus[1].c3[2], -0.028831496585242929, 1.0e-14); - ASSERT_NEAR(bonus[2].c3[0], 0.15731490073748589, 1.0e-14); - ASSERT_NEAR(bonus[2].c3[1], 0.85047049833171351, 1.0e-14); - ASSERT_NEAR(bonus[2].c3[2], 0.044180917525129149, 1.0e-14); - ASSERT_NEAR(bonus[3].c3[0], 0.47838179877141634, 1.0e-14); - ASSERT_NEAR(bonus[3].c3[1], 0.32808266428854471, 1.0e-14); - ASSERT_NEAR(bonus[3].c3[2], 0.64304946932374851, 1.0e-14); + EXPECT_NEAR(bonus[0].inertia[0], 14.017974903242481, EPSILON); + EXPECT_NEAR(bonus[0].inertia[1], 13.94589575227541, EPSILON); + EXPECT_NEAR(bonus[0].inertia[2], 0.072258416330334363, EPSILON); + EXPECT_NEAR(bonus[1].inertia[0], 13.982119044342252, EPSILON); + EXPECT_NEAR(bonus[1].inertia[1], 13.945895752275419, EPSILON); + EXPECT_NEAR(bonus[1].inertia[2], 0.10811427523057447, EPSILON); + EXPECT_NEAR(bonus[2].inertia[0], 19.15175691481879, EPSILON); + EXPECT_NEAR(bonus[2].inertia[1], 18.948744087979005, EPSILON); + EXPECT_NEAR(bonus[2].inertia[2], 0.23541253382609079, EPSILON); + EXPECT_NEAR(bonus[3].inertia[0], 19.018309360029388, EPSILON); + EXPECT_NEAR(bonus[3].inertia[1], 18.948744087979012, EPSILON); + EXPECT_NEAR(bonus[3].inertia[2], 0.36886008861549813, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 0.66466395261228639, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], -0.26579965871355399, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], -0.64169714094040209, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], -0.27531282359251713, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], 0.63718542087921404, EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.66984067651944412, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], -0.26272786480888066, EPSILON); + EXPECT_NEAR(bonus[1].quat[3], -0.27619246288035992, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 0.70865471105868871, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.40297854431552654, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], -0.56684324752832238, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.11876668744732566, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], 0.55997606330452898, EPSILON); + EXPECT_NEAR(bonus[3].quat[1], 0.69182747953492685, EPSILON); + EXPECT_NEAR(bonus[3].quat[2], 0.072026021657128514, EPSILON); + EXPECT_NEAR(bonus[3].quat[3], 0.45012642589672475, EPSILON); + EXPECT_NEAR(bonus[0].c1[0], -0.0052525338293288905, EPSILON); + EXPECT_NEAR(bonus[0].c1[1], -0.55767753582520529, EPSILON); + EXPECT_NEAR(bonus[0].c1[2], 0.14933690186163631, EPSILON); + EXPECT_NEAR(bonus[1].c1[0], 0.18561232929671426, EPSILON); + EXPECT_NEAR(bonus[1].c1[1], 0.51379191773154387, EPSILON); + EXPECT_NEAR(bonus[1].c1[2], 0.18681344121910506, EPSILON); + EXPECT_NEAR(bonus[2].c1[0], -0.22123552085772166, EPSILON); + EXPECT_NEAR(bonus[2].c1[1], -0.28372571379613187, EPSILON); + EXPECT_NEAR(bonus[2].c1[2], 0.78775285695558617, EPSILON); + EXPECT_NEAR(bonus[3].c1[0], -0.69845793336676587, EPSILON); + EXPECT_NEAR(bonus[3].c1[1], 0.18083523090249506, EPSILON); + EXPECT_NEAR(bonus[3].c1[2], 0.47901475403318056, EPSILON); + EXPECT_NEAR(bonus[0].c2[0], 0.019602723119529659, EPSILON); + EXPECT_NEAR(bonus[0].c2[1], 0.14942924536134222, EPSILON); + EXPECT_NEAR(bonus[0].c2[2], -0.55733290519255385, EPSILON); + EXPECT_NEAR(bonus[1].c2[0], 0.2208094914375279, EPSILON); + EXPECT_NEAR(bonus[1].c2[1], -0.4849604211463005, EPSILON); + EXPECT_NEAR(bonus[1].c2[2], 0.22223836695322477, EPSILON); + EXPECT_NEAR(bonus[2].c2[0], 0.17705460333259249, EPSILON); + EXPECT_NEAR(bonus[2].c2[1], -0.56674478453558153, EPSILON); + EXPECT_NEAR(bonus[2].c2[2], -0.6304379562181005, EPSILON); + EXPECT_NEAR(bonus[3].c2[0], 0.22007613459534958, EPSILON); + EXPECT_NEAR(bonus[3].c2[1], -0.82388470022624394, EPSILON); + EXPECT_NEAR(bonus[3].c2[2], -0.15093208974463557, EPSILON); + EXPECT_NEAR(bonus[0].c3[0], -0.014350189290200811, EPSILON); + EXPECT_NEAR(bonus[0].c3[1], 0.40824829046386302, EPSILON); + EXPECT_NEAR(bonus[0].c3[2], 0.40799600333091751, EPSILON); + EXPECT_NEAR(bonus[1].c3[0], -0.40642182073424188, EPSILON); + EXPECT_NEAR(bonus[1].c3[1], -0.028831496585242929, EPSILON); + EXPECT_NEAR(bonus[1].c3[2], -0.40905180817232945, EPSILON); + EXPECT_NEAR(bonus[2].c3[0], 0.044180917525129149, EPSILON); + EXPECT_NEAR(bonus[2].c3[1], 0.85047049833171351, EPSILON); + EXPECT_NEAR(bonus[2].c3[2], -0.15731490073748589, EPSILON); + EXPECT_NEAR(bonus[3].c3[0], 0.47838179877141634, EPSILON); + EXPECT_NEAR(bonus[3].c3[1], 0.64304946932374796, EPSILON); + EXPECT_NEAR(bonus[3].c3[2], -0.32808266428854477, EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("group two id 2:4:2"); @@ -2570,87 +2572,87 @@ TEST_F(AtomStyleTest, tri) ASSERT_EQ(tri[GETIDX(9)], 3); ASSERT_EQ(tri[GETIDX(11)], -1); ASSERT_EQ(tri[GETIDX(12)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(7)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(9)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(11)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(12)], 4.4, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(1)], 0.5773502691896258, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(3)], 0.8660254037844390, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(5)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(6)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(7)], 0.5773502691896258, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(9)], 0.8660254037844390, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(11)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(12)], 0.5, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(7)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(9)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(11)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(12)], 4.4, EPSILON); + EXPECT_NEAR(radius[GETIDX(1)], 0.5773502691896258, EPSILON); + EXPECT_NEAR(radius[GETIDX(3)], 0.8660254037844390, EPSILON); + EXPECT_NEAR(radius[GETIDX(5)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(6)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(7)], 0.5773502691896258, EPSILON); + EXPECT_NEAR(radius[GETIDX(9)], 0.8660254037844390, EPSILON); + EXPECT_NEAR(radius[GETIDX(11)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(12)], 0.5, EPSILON); - ASSERT_NEAR(bonus[0].inertia[0], 0.072258416330334363, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[1], 13.94589575227541, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[2], 14.017974903242481, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[0], 0.23541253382609079, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[1], 18.948744087979005, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[2], 19.15175691481879, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[0], 0.072258416330334363, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[1], 13.94589575227541, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[2], 14.017974903242481, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[0], 0.23541253382609079, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[1], 18.948744087979005, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[2], 19.15175691481879, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 0.92373678792937974, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0067268233964605153, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.016239988275423625, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], -0.38262430562330857, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], 0.90191325590647364, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.20096813128512517, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], 0.10027584751231088, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.36892959143125964, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 0.92373678792937974, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.0067268233964605153, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.016239988275423625, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], -0.38262430562330857, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], 0.90191325590647364, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], 0.20096813128512517, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], 0.10027584751231088, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], 0.36892959143125964, 1.0e-14); - ASSERT_NEAR(bonus[0].c1[0], -0.14933690186163631, 1.0e-14); - ASSERT_NEAR(bonus[0].c1[1], -0.55767753582520529, 1.0e-14); - ASSERT_NEAR(bonus[0].c1[2], -0.0052525338293288905, 1.0e-14); - ASSERT_NEAR(bonus[1].c1[0], -0.78775285695558617, 1.0e-14); - ASSERT_NEAR(bonus[1].c1[1], -0.28372571379613187, 1.0e-14); - ASSERT_NEAR(bonus[1].c1[2], -0.22123552085772166, 1.0e-14); - ASSERT_NEAR(bonus[2].c1[0], -0.14933690186163631, 1.0e-14); - ASSERT_NEAR(bonus[2].c1[1], -0.55767753582520529, 1.0e-14); - ASSERT_NEAR(bonus[2].c1[2], -0.0052525338293288905, 1.0e-14); - ASSERT_NEAR(bonus[3].c1[0], -0.78775285695558617, 1.0e-14); - ASSERT_NEAR(bonus[3].c1[1], -0.28372571379613187, 1.0e-14); - ASSERT_NEAR(bonus[3].c1[2], -0.22123552085772166, 1.0e-14); - ASSERT_NEAR(bonus[0].c2[0], 0.55733290519255385, 1.0e-14); - ASSERT_NEAR(bonus[0].c2[1], 0.14942924536134222, 1.0e-14); - ASSERT_NEAR(bonus[0].c2[2], 0.019602723119529659, 1.0e-14); - ASSERT_NEAR(bonus[1].c2[0], 0.6304379562181005, 1.0e-14); - ASSERT_NEAR(bonus[1].c2[1], -0.56674478453558153, 1.0e-14); - ASSERT_NEAR(bonus[1].c2[2], 0.17705460333259249, 1.0e-14); - ASSERT_NEAR(bonus[2].c2[0], 0.55733290519255385, 1.0e-14); - ASSERT_NEAR(bonus[2].c2[1], 0.14942924536134222, 1.0e-14); - ASSERT_NEAR(bonus[2].c2[2], 0.019602723119529659, 1.0e-14); - ASSERT_NEAR(bonus[3].c2[0], 0.6304379562181005, 1.0e-14); - ASSERT_NEAR(bonus[3].c2[1], -0.56674478453558153, 1.0e-14); - ASSERT_NEAR(bonus[3].c2[2], 0.17705460333259249, 1.0e-14); - ASSERT_NEAR(bonus[0].c3[0], -0.40799600333091751, 1.0e-14); - ASSERT_NEAR(bonus[0].c3[1], 0.40824829046386302, 1.0e-14); - ASSERT_NEAR(bonus[0].c3[2], -0.014350189290200811, 1.0e-14); - ASSERT_NEAR(bonus[1].c3[0], 0.15731490073748589, 1.0e-14); - ASSERT_NEAR(bonus[1].c3[1], 0.85047049833171351, 1.0e-14); - ASSERT_NEAR(bonus[1].c3[2], 0.044180917525129149, 1.0e-14); - ASSERT_NEAR(bonus[2].c3[0], -0.40799600333091751, 1.0e-14); - ASSERT_NEAR(bonus[2].c3[1], 0.40824829046386302, 1.0e-14); - ASSERT_NEAR(bonus[2].c3[2], -0.014350189290200811, 1.0e-14); - ASSERT_NEAR(bonus[3].c3[0], 0.15731490073748589, 1.0e-14); - ASSERT_NEAR(bonus[3].c3[1], 0.85047049833171351, 1.0e-14); - ASSERT_NEAR(bonus[3].c3[2], 0.044180917525129149, 1.0e-14); + EXPECT_NEAR(bonus[0].inertia[0], 14.017974903242481, EPSILON); + EXPECT_NEAR(bonus[0].inertia[1], 13.94589575227541, EPSILON); + EXPECT_NEAR(bonus[0].inertia[2], 0.072258416330334363, EPSILON); + EXPECT_NEAR(bonus[1].inertia[0], 19.15175691481879, EPSILON); + EXPECT_NEAR(bonus[1].inertia[1], 18.948744087979005, EPSILON); + EXPECT_NEAR(bonus[1].inertia[2], 0.23541253382609079, EPSILON); + EXPECT_NEAR(bonus[2].inertia[0], 14.017974903242481, EPSILON); + EXPECT_NEAR(bonus[2].inertia[1], 13.94589575227541, EPSILON); + EXPECT_NEAR(bonus[2].inertia[2], 0.072258416330334363, EPSILON); + EXPECT_NEAR(bonus[3].inertia[0], 19.15175691481879, EPSILON); + EXPECT_NEAR(bonus[3].inertia[1], 18.948744087979005, EPSILON); + EXPECT_NEAR(bonus[3].inertia[2], 0.23541253382609079, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 0.66466395261228639, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], -0.26579965871355399, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], -0.64169714094040209, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], -0.27531282359251713, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], 0.70865471105868871, EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.40297854431552654, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], -0.56684324752832238, EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.11876668744732566, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 0.66466395261228639, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], -0.26579965871355399, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], -0.64169714094040209, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], -0.27531282359251713, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], 0.70865471105868871, EPSILON); + EXPECT_NEAR(bonus[3].quat[1], 0.40297854431552654, EPSILON); + EXPECT_NEAR(bonus[3].quat[2], -0.56684324752832238, EPSILON); + EXPECT_NEAR(bonus[3].quat[3], 0.11876668744732566, EPSILON); + EXPECT_NEAR(bonus[0].c1[0], -0.0052525338293288879, EPSILON); + EXPECT_NEAR(bonus[0].c1[1], -0.55767753582520529, EPSILON); + EXPECT_NEAR(bonus[0].c1[2], 0.14933690186163626, EPSILON); + EXPECT_NEAR(bonus[1].c1[0], -0.22123552085772158, EPSILON); + EXPECT_NEAR(bonus[1].c1[1], -0.28372571379613187, EPSILON); + EXPECT_NEAR(bonus[1].c1[2], 0.78775285695558628, EPSILON); + EXPECT_NEAR(bonus[2].c1[0], -0.0052525338293288905, EPSILON); + EXPECT_NEAR(bonus[2].c1[1], -0.55767753582520529, EPSILON); + EXPECT_NEAR(bonus[2].c1[2], 0.14933690186163631, EPSILON); + EXPECT_NEAR(bonus[3].c1[0], -0.22123552085772166, EPSILON); + EXPECT_NEAR(bonus[3].c1[1], -0.28372571379613187, EPSILON); + EXPECT_NEAR(bonus[3].c1[2], 0.78775285695558617, EPSILON); + EXPECT_NEAR(bonus[0].c2[0], 0.019602723119529659, EPSILON); + EXPECT_NEAR(bonus[0].c2[1], 0.14942924536134222, EPSILON); + EXPECT_NEAR(bonus[0].c2[2], -0.55733290519255385, EPSILON); + EXPECT_NEAR(bonus[1].c2[0], 0.17705460333259249, EPSILON); + EXPECT_NEAR(bonus[1].c2[1], -0.56674478453558153, EPSILON); + EXPECT_NEAR(bonus[1].c2[2], -0.6304379562181005, EPSILON); + EXPECT_NEAR(bonus[2].c2[0], 0.019602723119529659, EPSILON); + EXPECT_NEAR(bonus[2].c2[1], 0.14942924536134222, EPSILON); + EXPECT_NEAR(bonus[2].c2[2], -0.55733290519255385, EPSILON); + EXPECT_NEAR(bonus[3].c2[0], 0.17705460333259249, EPSILON); + EXPECT_NEAR(bonus[3].c2[1], -0.56674478453558153, EPSILON); + EXPECT_NEAR(bonus[3].c2[2], -0.6304379562181005, EPSILON); + EXPECT_NEAR(bonus[0].c3[0], -0.014350189290200811, EPSILON); + EXPECT_NEAR(bonus[0].c3[1], 0.40824829046386302, EPSILON); + EXPECT_NEAR(bonus[0].c3[2], 0.40799600333091751, EPSILON); + EXPECT_NEAR(bonus[1].c3[0], 0.044180917525129149, EPSILON); + EXPECT_NEAR(bonus[1].c3[1], 0.85047049833171351, EPSILON); + EXPECT_NEAR(bonus[1].c3[2], -0.15731490073748589, EPSILON); + EXPECT_NEAR(bonus[2].c3[0], -0.014350189290200811, EPSILON); + EXPECT_NEAR(bonus[2].c3[1], 0.40824829046386302, EPSILON); + EXPECT_NEAR(bonus[2].c3[2], 0.40799600333091751, EPSILON); + EXPECT_NEAR(bonus[3].c3[0], 0.044180917525129149, EPSILON); + EXPECT_NEAR(bonus[3].c3[1], 0.85047049833171351, EPSILON); + EXPECT_NEAR(bonus[3].c3[2], -0.15731490073748589, EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("reset_atom_ids"); @@ -2679,18 +2681,18 @@ TEST_F(AtomStyleTest, tri) ASSERT_EQ(tri[GETIDX(6)], -1); ASSERT_EQ(tri[GETIDX(7)], 3); ASSERT_EQ(tri[GETIDX(8)], -1); - ASSERT_NEAR(bonus[0].inertia[0], 0.072258416330334363, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[1], 13.94589575227541, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[2], 14.017974903242481, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[0], 0.23541253382609079, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[1], 18.948744087979005, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[2], 19.15175691481879, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[0], 0.072258416330334363, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[1], 13.94589575227541, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[2], 14.017974903242481, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[0], 0.23541253382609079, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[1], 18.948744087979005, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[2], 19.15175691481879, 1.0e-14); + EXPECT_NEAR(bonus[0].inertia[0], 14.017974903242481, EPSILON); + EXPECT_NEAR(bonus[0].inertia[1], 13.94589575227541, EPSILON); + EXPECT_NEAR(bonus[0].inertia[2], 0.072258416330334363, EPSILON); + EXPECT_NEAR(bonus[1].inertia[0], 19.15175691481879, EPSILON); + EXPECT_NEAR(bonus[1].inertia[1], 18.948744087979005, EPSILON); + EXPECT_NEAR(bonus[1].inertia[2], 0.23541253382609079, EPSILON); + EXPECT_NEAR(bonus[2].inertia[0], 14.017974903242481, EPSILON); + EXPECT_NEAR(bonus[2].inertia[1], 13.94589575227541, EPSILON); + EXPECT_NEAR(bonus[2].inertia[2], 0.072258416330334363, EPSILON); + EXPECT_NEAR(bonus[3].inertia[0], 19.15175691481879, EPSILON); + EXPECT_NEAR(bonus[3].inertia[1], 18.948744087979005, EPSILON); + EXPECT_NEAR(bonus[3].inertia[2], 0.23541253382609079, EPSILON); } TEST_F(AtomStyleTest, body_nparticle) @@ -2981,60 +2983,60 @@ TEST_F(AtomStyleTest, body_nparticle) auto radius = lmp->atom->radius; auto angmom = lmp->atom->angmom; auto bonus = avec->bonus; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], -2.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], 2.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], -2.1, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], 2.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][2], 0.0, EPSILON); ASSERT_EQ(type[GETIDX(1)], 1); ASSERT_EQ(type[GETIDX(2)], 1); ASSERT_EQ(type[GETIDX(3)], 2); ASSERT_EQ(type[GETIDX(4)], 2); ASSERT_EQ(type[GETIDX(5)], 3); ASSERT_EQ(type[GETIDX(6)], 3); - ASSERT_NEAR(angmom[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(4)][2], 0.0, 1.0e-14); + EXPECT_NEAR(angmom[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(4)][2], 0.0, EPSILON); ASSERT_EQ(body[GETIDX(1)], 0); ASSERT_EQ(body[GETIDX(2)], 1); @@ -3042,47 +3044,47 @@ TEST_F(AtomStyleTest, body_nparticle) ASSERT_EQ(body[GETIDX(4)], 3); ASSERT_EQ(body[GETIDX(5)], -1); ASSERT_EQ(body[GETIDX(6)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(1)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(2)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(3)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(4)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(5)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(6)], 0.5, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(radius[GETIDX(1)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(2)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(3)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(4)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(5)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(6)], 0.5, EPSILON); - ASSERT_NEAR(bonus[0].inertia[0], 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[1], 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[1], 4.0, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[2], 4.5, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[0], 1.67188, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[1], 1.7746273249544022, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[2], 0.49099767504559777, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[0], 12.0, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[2], 12.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], sqrt(5.0 / 30.0), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], sqrt(5.0 / 30.0), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], sqrt(5.0 / 30.0), 1.0e-14); + EXPECT_NEAR(bonus[0].inertia[0], 2.0, EPSILON); + EXPECT_NEAR(bonus[0].inertia[1], 2.0, EPSILON); + EXPECT_NEAR(bonus[0].inertia[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].inertia[0], 4.5, EPSILON); + EXPECT_NEAR(bonus[1].inertia[1], 4.0, EPSILON); + EXPECT_NEAR(bonus[1].inertia[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].inertia[0], 1.7746273249544022, EPSILON); + EXPECT_NEAR(bonus[2].inertia[1], 1.67188, EPSILON); + EXPECT_NEAR(bonus[2].inertia[2], 0.49099767504559777, EPSILON); + EXPECT_NEAR(bonus[3].inertia[0], 12.0, EPSILON); + EXPECT_NEAR(bonus[3].inertia[1], 12.0, EPSILON); + EXPECT_NEAR(bonus[3].inertia[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[3].quat[1], sqrt(5.0 / 30.0), EPSILON); + EXPECT_NEAR(bonus[3].quat[2], sqrt(5.0 / 30.0), EPSILON); + EXPECT_NEAR(bonus[3].quat[3], sqrt(5.0 / 30.0), EPSILON); ASSERT_EQ(bonus[0].ilocal, 0); ASSERT_EQ(bonus[1].ilocal, 1); ASSERT_EQ(bonus[2].ilocal, 2); @@ -3153,60 +3155,60 @@ TEST_F(AtomStyleTest, body_nparticle) angmom = lmp->atom->angmom; avec = (AtomVecBody *)lmp->atom->avec; bonus = avec->bonus; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], -2.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], 2.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], -2.1, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], 2.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][2], 0.0, EPSILON); ASSERT_EQ(type[GETIDX(1)], 1); ASSERT_EQ(type[GETIDX(2)], 1); ASSERT_EQ(type[GETIDX(3)], 2); ASSERT_EQ(type[GETIDX(4)], 2); ASSERT_EQ(type[GETIDX(5)], 3); ASSERT_EQ(type[GETIDX(6)], 3); - ASSERT_NEAR(angmom[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(angmom[GETIDX(4)][2], 0.0, 1.0e-14); + EXPECT_NEAR(angmom[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(angmom[GETIDX(4)][2], 0.0, EPSILON); ASSERT_EQ(body[GETIDX(1)], 0); ASSERT_EQ(body[GETIDX(2)], 1); @@ -3214,47 +3216,47 @@ TEST_F(AtomStyleTest, body_nparticle) ASSERT_EQ(body[GETIDX(4)], 3); ASSERT_EQ(body[GETIDX(5)], -1); ASSERT_EQ(body[GETIDX(6)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(1)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(2)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(3)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(4)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(5)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(6)], 0.5, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(radius[GETIDX(1)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(2)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(3)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(4)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(5)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(6)], 0.5, EPSILON); - ASSERT_NEAR(bonus[0].inertia[0], 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[1], 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[0], 4.5, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[1], 4.0, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[0], 1.67188, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[1], 1.7746273249544022, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[2], 0.49099767504559777, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[0], 12.0, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[1], 12.0, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.25056280708573148, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], 0.94328772332207422, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], -0.19726148412050853, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], -0.075803071317030998, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], 0.25602748346874377, 1.0e-14); + EXPECT_NEAR(bonus[0].inertia[0], 2.0, EPSILON); + EXPECT_NEAR(bonus[0].inertia[1], 2.0, EPSILON); + EXPECT_NEAR(bonus[0].inertia[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].inertia[0], 4.5, EPSILON); + EXPECT_NEAR(bonus[1].inertia[1], 4.0, EPSILON); + EXPECT_NEAR(bonus[1].inertia[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].inertia[0], 1.7746273249544022, EPSILON); + EXPECT_NEAR(bonus[2].inertia[1], 1.67188, EPSILON); + EXPECT_NEAR(bonus[2].inertia[2], 0.49099767504559777, EPSILON); + EXPECT_NEAR(bonus[3].inertia[0], 12.0, EPSILON); + EXPECT_NEAR(bonus[3].inertia[1], 12.0, EPSILON); + EXPECT_NEAR(bonus[3].inertia[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], -sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.25056280708573148, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], 0.62499650256800654, EPSILON); + EXPECT_NEAR(bonus[3].quat[1], 0.47323774316465234, EPSILON); + EXPECT_NEAR(bonus[3].quat[2], 0.33072552332373728, EPSILON); + EXPECT_NEAR(bonus[3].quat[3], 0.52540083597613996, EPSILON); ASSERT_EQ(bonus[0].ilocal, 0); ASSERT_EQ(bonus[1].ilocal, 1); ASSERT_EQ(bonus[2].ilocal, 2); @@ -3326,50 +3328,50 @@ TEST_F(AtomStyleTest, body_nparticle) ASSERT_EQ(body[GETIDX(9)], 3); ASSERT_EQ(body[GETIDX(11)], -1); ASSERT_EQ(body[GETIDX(12)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(7)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(9)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(11)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(12)], 4.4, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(1)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(3)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(5)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(6)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(7)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(9)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(11)], 0.5, 1.0e-14); - ASSERT_NEAR(radius[GETIDX(12)], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[0], 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[1], 2.0, 1.0e-14); - ASSERT_NEAR(bonus[0].inertia[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[0], 1.67188, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[1], 1.7746273249544022, 1.0e-14); - ASSERT_NEAR(bonus[1].inertia[2], 0.49099767504559777, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[0], 2.0, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[1], 2.0, 1.0e-14); - ASSERT_NEAR(bonus[2].inertia[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[0], 1.67188, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[1], 1.7746273249544022, 1.0e-14); - ASSERT_NEAR(bonus[3].inertia[2], 0.49099767504559777, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.25056280708573148, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], 0.25056280708573148, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(7)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(9)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(11)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(12)], 4.4, EPSILON); + EXPECT_NEAR(radius[GETIDX(1)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(3)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(5)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(6)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(7)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(9)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(11)], 0.5, EPSILON); + EXPECT_NEAR(radius[GETIDX(12)], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].inertia[0], 2.0, EPSILON); + EXPECT_NEAR(bonus[0].inertia[1], 2.0, EPSILON); + EXPECT_NEAR(bonus[0].inertia[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].inertia[0], 1.7746273249544022, EPSILON); + EXPECT_NEAR(bonus[1].inertia[1], 1.67188, EPSILON); + EXPECT_NEAR(bonus[1].inertia[2], 0.49099767504559777, EPSILON); + EXPECT_NEAR(bonus[2].inertia[0], 2.0, EPSILON); + EXPECT_NEAR(bonus[2].inertia[1], 2.0, EPSILON); + EXPECT_NEAR(bonus[2].inertia[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].inertia[0], 1.7746273249544022, EPSILON); + EXPECT_NEAR(bonus[3].inertia[1], 1.67188, EPSILON); + EXPECT_NEAR(bonus[3].inertia[2], 0.49099767504559777, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.25056280708573148, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[3].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[3].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[3], 0.25056280708573148, EPSILON); ASSERT_EQ(bonus[0].ilocal, 0); ASSERT_EQ(bonus[1].ilocal, 2); ASSERT_EQ(bonus[2].ilocal, 4); @@ -3775,42 +3777,42 @@ TEST_F(AtomStyleTest, bond) bond_type = lmp->atom->bond_type; bond_atom = lmp->atom->bond_atom; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], -2.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], 2.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], -2.1, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], 2.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][2], 0.0, EPSILON); ASSERT_EQ(type[GETIDX(1)], 1); ASSERT_EQ(type[GETIDX(2)], 1); ASSERT_EQ(type[GETIDX(3)], 2); @@ -4337,42 +4339,42 @@ TEST_F(AtomStyleTest, angle) num_angle = lmp->atom->num_angle; angle_type = lmp->atom->angle_type; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], -2.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], 2.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], -2.1, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], 2.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][2], 0.0, EPSILON); ASSERT_EQ(type[GETIDX(1)], 1); ASSERT_EQ(type[GETIDX(2)], 1); ASSERT_EQ(type[GETIDX(3)], 2); @@ -4788,95 +4790,95 @@ TEST_F(AtomStyleTest, full_ellipsoid) auto avec = (AtomVecEllipsoid *)hybrid->styles[1]; auto bonus = avec->bonus; - ASSERT_NEAR(x[GETIDX(1)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(1)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][0], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(2)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(3)][2], -0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(4)][2], 0.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][1], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(5)][2], -2.1, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][0], 2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][1], -2.0, 1.0e-14); - ASSERT_NEAR(x[GETIDX(6)][2], 2.1, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(1)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(2)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(3)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(4)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(5)][2], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][0], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][1], 0.0, 1.0e-14); - ASSERT_NEAR(v[GETIDX(6)][2], 0.0, 1.0e-14); + EXPECT_NEAR(x[GETIDX(1)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(1)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][0], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(2)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(3)][2], -0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(4)][2], 0.1, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][1], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(5)][2], -2.1, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][0], 2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][1], -2.0, EPSILON); + EXPECT_NEAR(x[GETIDX(6)][2], 2.1, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(1)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(2)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(3)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(4)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(5)][2], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][0], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][1], 0.0, EPSILON); + EXPECT_NEAR(v[GETIDX(6)][2], 0.0, EPSILON); ASSERT_EQ(type[GETIDX(1)], 1); ASSERT_EQ(type[GETIDX(2)], 1); ASSERT_EQ(type[GETIDX(3)], 2); ASSERT_EQ(type[GETIDX(4)], 2); ASSERT_EQ(type[GETIDX(5)], 3); ASSERT_EQ(type[GETIDX(6)], 3); - ASSERT_NEAR(q[GETIDX(1)], -0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(2)], 0.5, 1.0e-14); - ASSERT_NEAR(q[GETIDX(3)], -1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(4)], 1.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(5)], 2.0, 1.0e-14); - ASSERT_NEAR(q[GETIDX(6)], -2.0, 1.0e-14); + EXPECT_NEAR(q[GETIDX(1)], -0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(2)], 0.5, EPSILON); + EXPECT_NEAR(q[GETIDX(3)], -1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(4)], 1.0, EPSILON); + EXPECT_NEAR(q[GETIDX(5)], 2.0, EPSILON); + EXPECT_NEAR(q[GETIDX(6)], -2.0, EPSILON); ASSERT_EQ(ellipsoid[GETIDX(1)], 0); ASSERT_EQ(ellipsoid[GETIDX(2)], 1); ASSERT_EQ(ellipsoid[GETIDX(3)], 2); ASSERT_EQ(ellipsoid[GETIDX(4)], 3); ASSERT_EQ(ellipsoid[GETIDX(5)], -1); ASSERT_EQ(ellipsoid[GETIDX(6)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], sqrt(0.5), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], sqrt(5.0 / 30.0), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], sqrt(5.0 / 30.0), 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], sqrt(5.0 / 30.0), 1.0e-14); + EXPECT_NEAR(bonus[0].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[2].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[3].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[3].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], sqrt(0.5), EPSILON); + EXPECT_NEAR(bonus[3].quat[1], sqrt(5.0 / 30.0), EPSILON); + EXPECT_NEAR(bonus[3].quat[2], sqrt(5.0 / 30.0), EPSILON); + EXPECT_NEAR(bonus[3].quat[3], sqrt(5.0 / 30.0), EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("pair_coeff * *"); @@ -4927,43 +4929,43 @@ TEST_F(AtomStyleTest, full_ellipsoid) ASSERT_EQ(ellipsoid[GETIDX(9)], 3); ASSERT_EQ(ellipsoid[GETIDX(11)], -1); ASSERT_EQ(ellipsoid[GETIDX(12)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(7)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(9)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(11)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(12)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(7)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(9)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(11)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(12)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], 0.25056280708573159, 1.0e-14); + EXPECT_NEAR(bonus[0].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[1].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[2].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[3].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[3].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[3].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[3], 0.25056280708573159, EPSILON); if (!verbose) ::testing::internal::CaptureStdout(); lmp->input->one("reset_atom_ids"); @@ -4993,43 +4995,43 @@ TEST_F(AtomStyleTest, full_ellipsoid) ASSERT_EQ(ellipsoid[GETIDX(6)], -1); ASSERT_EQ(ellipsoid[GETIDX(7)], 3); ASSERT_EQ(ellipsoid[GETIDX(8)], -1); - ASSERT_NEAR(rmass[GETIDX(1)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(2)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(3)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(4)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(5)], 4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(6)], 4.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(7)], 2.4, 1.0e-14); - ASSERT_NEAR(rmass[GETIDX(8)], 4.4, 1.0e-14); + EXPECT_NEAR(rmass[GETIDX(1)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(2)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(3)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(4)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(5)], 4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(6)], 4.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(7)], 2.4, EPSILON); + EXPECT_NEAR(rmass[GETIDX(8)], 4.4, EPSILON); - ASSERT_NEAR(bonus[0].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[0].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[1].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[0], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[1], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[2].shape[2], 0.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[0], 1.5, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[1], 0.4, 1.0e-14); - ASSERT_NEAR(bonus[3].shape[2], 0.55, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[0].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[1].quat[3], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[0], 1.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[1], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[2].quat[3], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[0], 0.9351131265310294, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[1], 0.25056280708573159, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[2], 0.0, 1.0e-14); - ASSERT_NEAR(bonus[3].quat[3], 0.25056280708573159, 1.0e-14); + EXPECT_NEAR(bonus[0].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[0].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[1].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[1].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[2].shape[0], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[1], 0.5, EPSILON); + EXPECT_NEAR(bonus[2].shape[2], 0.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[0], 1.5, EPSILON); + EXPECT_NEAR(bonus[3].shape[1], 0.4, EPSILON); + EXPECT_NEAR(bonus[3].shape[2], 0.55, EPSILON); + EXPECT_NEAR(bonus[0].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[0].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[1].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[1].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[1].quat[3], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[2].quat[0], 1.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[1], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[2].quat[3], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[0], 0.9351131265310294, EPSILON); + EXPECT_NEAR(bonus[3].quat[1], 0.25056280708573159, EPSILON); + EXPECT_NEAR(bonus[3].quat[2], 0.0, EPSILON); + EXPECT_NEAR(bonus[3].quat[3], 0.25056280708573159, EPSILON); } } // namespace LAMMPS_NS From 10991ee638c587105f94c7acf0354144e7383e32 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 16 Sep 2020 14:06:58 -0400 Subject: [PATCH 21/28] separate the MathEigen implementation into its own header file --- lib/jacobi_pd.h | 623 ------------------------ src/USER-REACTION/superpose3d.h | 8 +- src/math_eigen.cpp | 123 ++--- src/{math_eigen.h => math_eigen_impl.h} | 50 +- 4 files changed, 37 insertions(+), 767 deletions(-) delete mode 100644 lib/jacobi_pd.h rename src/{math_eigen.h => math_eigen_impl.h} (96%) diff --git a/lib/jacobi_pd.h b/lib/jacobi_pd.h deleted file mode 100644 index ca68e6ba3a..0000000000 --- a/lib/jacobi_pd.h +++ /dev/null @@ -1,623 +0,0 @@ -/// @file jacobi_pd.h -/// @brief Calculate the eigenvalues and eigevectors of a symmetric matrix -/// using the Jacobi eigenvalue algorithm. -/// @author Andrew Jewett -/// @note Benchmarks and tests: https://github.com/jewettaij/jacobi_pd -/// @note A version of this code is included with LAMMPS ("math_eigen.h"). -/// @license CC0-1.0 (public domain) - -#ifndef _MATH_EIGEN_H -#define _MATH_EIGEN_H - -#include -#include -//#include - - -namespace MathEigen { - -/// @brief Allocate a 2-dimensional array. (Uses row-major order.) -/// @note (Matrix allocation functions can also be found in colvartypes.h) -template -void Alloc2D(size_t nrows, //!< size of the array (number of rows) - size_t ncols, //!< size of the array (number of columns) - Entry ***paaX //!< pointer to a 2D C-style array - ); - -/// @brief Deallocate arrays that were created using Alloc2D(). -/// @note (Matrix allocation functions can also be found in colvartypes.h) -template -void Dealloc2D(Entry ***paaX //!< pointer to a 2D C-style array - ); - - -// ---- Eigendecomposition of small dense symmetric matrices ---- - -/// @class Jacobi -/// @brief Calculate the eigenvalues and eigevectors of a symmetric matrix -/// using the Jacobi eigenvalue algorithm. Code for the Jacobi class -/// (along with tests and benchmarks) is available free of copyright at -/// https://github.com/jewettaij/jacobi_pd -/// @note The "Vector" and "Matrix" type arguments can be any -/// C or C++ object that support indexing, including pointers or vectors. -/// @details -/// Usage example: -/// @code -/// -/// int n = 5; // Matrix size -/// double **M; // A symmetric n x n matrix you want to diagonalize -/// double *evals; // Store the eigenvalues here. -/// double **evects; // Store the eigenvectors here. -/// // Allocate space for M, evals, and evects, and load contents of M (omitted) -/// -/// // Now create an instance of Jacobi ("eigen_calc"). This will allocate space -/// // for storing intermediate calculations. Once created, it can be reused -/// // multiple times without paying the cost of allocating memory on the heap. -/// -/// Jacobi eigen_calc(n); -/// -/// // Note: -/// // If the matrix you plan to diagonalize (M) is read-only, use this instead: -/// // Jacobi eigen_calc(n); -/// // If you prefer using vectors over C-style pointers, this works also: -/// // Jacobi&, vector>&> eigen_calc(n); -/// -/// // Now, calculate the eigenvalues and eigenvectors of M -/// -/// eigen_calc.Diagonalize(M, evals, evects); -/// -/// @endcode - -template -class Jacobi -{ - int n; //!< the size of the matrix - Scalar **M; //!< local copy of the matrix being analyzed - // Precomputed cosine, sine, and tangent of the most recent rotation angle: - Scalar c; //!< = cos(θ) - Scalar s; //!< = sin(θ) - Scalar t; //!< = tan(θ), (note |t|<=1) - int *max_idx_row; //!< for row i, the index j of the maximum element where j>i - -public: - - /// @brief Specify the size of the matrices you want to diagonalize later. - /// @param n the size (ie. number of rows) of the square matrix - void SetSize(int n); - - Jacobi(int n = 0) { - Init(); - SetSize(n); - } - - ~Jacobi() { - Dealloc(); - } - - // @typedef choose the criteria for sorting eigenvalues and eigenvectors - typedef enum eSortCriteria { - DO_NOT_SORT, - SORT_DECREASING_EVALS, - SORT_INCREASING_EVALS, - SORT_DECREASING_ABS_EVALS, - SORT_INCREASING_ABS_EVALS - } SortCriteria; - - /// @brief Calculate the eigenvalues and eigevectors of a symmetric matrix - /// using the Jacobi eigenvalue algorithm. - /// @returns 0 if the algorithm converged, - /// 1 if the algorithm failed to converge. (IE, if the number of - /// pivot iterations exceeded max_num_sweeps * iters_per_sweep, - /// where iters_per_sweep = (n*(n-1)/2)) - /// @note To reduce the computation time further, set calc_evecs=false. - int - Diagonalize(ConstMatrix mat, //!< the matrix you wish to diagonalize (size n) - Vector eval, //!< store the eigenvalues here - Matrix evec, //!< store the eigenvectors here (in rows) - SortCriteria sort_criteria=SORT_DECREASING_EVALS,//!c, this->s, and - /// this->t (which store cos(θ), sin(θ), and tan(θ), respectively). - void CalcRot(Scalar const *const *M, //!< matrix - int i, //!< row index - int j); //!< column index - - /// @brief Apply the (previously calculated) rotation matrix to matrix M - /// by multiplying it on both sides (a "similarity transform"). - /// (To save time, only the elements in the upper-right-triangular - /// region of the matrix are updated. It is assumed that i < j.) - void ApplyRot(Scalar **M, //!< matrix - int i, //!< row index - int j); //!< column index - - /// @brief Multiply matrix E on the left by the (previously calculated) - /// rotation matrix. - void ApplyRotLeft(Matrix E, //!< matrix - int i, //!< row index - int j); //!< column index - - ///@brief Find the off-diagonal index in row i whose absolute value is largest - int MaxEntryRow(Scalar const *const *M, int i) const; - - /// @brief Find the indices (i_max, j_max) marking the location of the - /// entry in the matrix with the largest absolute value. This - /// uses the max_idx_row[] array to find the answer in O(n) time. - /// @returns This function does not return a avalue. However after it is - /// invoked, the location of the largest matrix element will be - /// stored in the i_max and j_max arguments. - void MaxEntry(Scalar const *const *M, int& i_max, int& j_max) const; - - // @brief Sort the rows in M according to the numbers in v (also sorted) - void SortRows(Vector v, //!< vector containing the keys used for sorting - Matrix M, //!< matrix whose rows will be sorted according to v - int n, //!< size of the vector and matrix - SortCriteria s=SORT_DECREASING_EVALS //!< sort decreasing order? - ) const; - - // memory management: - void Alloc(int n); - void Init(); - void Dealloc(); - -public: - // memory management: copy and move constructor, swap, and assignment operator - Jacobi(const Jacobi& source); - Jacobi(Jacobi&& other); - void swap(Jacobi &other); - Jacobi& operator = (Jacobi source); - -}; // class Jacobi - - - - - -// -------------- IMPLEMENTATION -------------- - -// Utilities for memory allocation - -template -void Alloc2D(size_t nrows, // size of the array (number of rows) - size_t ncols, // size of the array (number of columns) - Entry ***paaX) // pointer to a 2D C-style array -{ - //assert(paaX); - *paaX = new Entry* [nrows]; //conventional 2D C array (pointer-to-pointer) - (*paaX)[0] = new Entry [nrows * ncols]; // 1D C array (contiguous memory) - for(size_t iy=0; iy -void Dealloc2D(Entry ***paaX) // pointer to a 2D C-style array -{ - if (paaX && *paaX) { - delete [] (*paaX)[0]; - delete [] (*paaX); - *paaX = nullptr; - } -} - - - -template -int Jacobi:: -Diagonalize(ConstMatrix mat, // the matrix you wish to diagonalize (size n) - Vector eval, // store the eigenvalues here - Matrix evec, // store the eigenvectors here (in rows) - SortCriteria sort_criteria, // sort results? - bool calc_evec, // calculate the eigenvectors? - int max_num_sweeps) // limit the number of iterations ("sweeps") -{ - // -- Initialization -- - for (int i = 0; i < n; i++) - for (int j = i; j < n; j++) //copy mat[][] into M[][] - M[i][j] = mat[i][j]; //(M[][] is a local copy we can modify) - - if (calc_evec) - for (int i = 0; i < n; i++) - for (int j = 0; j < n; j++) - evec[i][j] = (i==j) ? 1.0 : 0.0; //Set evec equal to the identity matrix - - for (int i = 0; i < n-1; i++) //Initialize the "max_idx_row[]" array - max_idx_row[i] = MaxEntryRow(M, i); //(which is needed by MaxEntry()) - - // -- Iteration -- - int n_iters; - int max_num_iters = max_num_sweeps*n*(n-1)/2; //"sweep" = n*(n-1)/2 iters - for (n_iters=0; n_iters < max_num_iters; n_iters++) { - int i,j; - MaxEntry(M, i, j); // Find the maximum entry in the matrix. Store in i,j - - // If M[i][j] is small compared to M[i][i] and M[j][j], set it to 0. - if ((M[i][i] + M[i][j] == M[i][i]) && (M[j][j] + M[i][j] == M[j][j])) { - M[i][j] = 0.0; - max_idx_row[i] = MaxEntryRow(M,i); //must also update max_idx_row[i] - } - - if (M[i][j] == 0.0) - break; - - // Otherwise, apply a rotation to make M[i][j] = 0 - CalcRot(M, i, j); // Calculate the parameters of the rotation matrix. - ApplyRot(M, i, j); // Apply this rotation to the M matrix. - if (calc_evec) // Optional: If the caller wants the eigenvectors, then - ApplyRotLeft(evec,i,j); // apply the rotation to the eigenvector matrix - - } //for (int n_iters=0; n_iters < max_num_iters; n_iters++) - - // -- Post-processing -- - for (int i = 0; i < n; i++) - eval[i] = M[i][i]; - - // Optional: Sort results by eigenvalue. - SortRows(eval, evec, n, sort_criteria); - - return (n_iters == max_num_iters); -} - - -/// @brief Calculate the components of a rotation matrix which performs a -/// rotation in the i,j plane by an angle (θ) that (when multiplied on -/// both sides) will zero the ij'th element of M, so that afterwards -/// M[i][j] = 0. The results will be stored in c, s, and t -/// (which store cos(θ), sin(θ), and tan(θ), respectively). - -template -void Jacobi:: -CalcRot(Scalar const *const *M, // matrix - int i, // row index - int j) // column index -{ - t = 1.0; // = tan(θ) - Scalar M_jj_ii = (M[j][j] - M[i][i]); - if (M_jj_ii != 0.0) { - // kappa = (M[j][j] - M[i][i]) / (2*M[i][j]) - Scalar kappa = M_jj_ii; - t = 0.0; - Scalar M_ij = M[i][j]; - if (M_ij != 0.0) { - kappa /= (2.0*M_ij); - // t satisfies: t^2 + 2*t*kappa - 1 = 0 - // (choose the root which has the smaller absolute value) - t = 1.0 / (std::sqrt(1 + kappa*kappa) + std::abs(kappa)); - if (kappa < 0.0) - t = -t; - } - } - //assert(std::abs(t) <= 1.0); - c = 1.0 / std::sqrt(1 + t*t); - s = c*t; -} - -/// brief Perform a similarity transformation by multiplying matrix M on both -/// sides by a rotation matrix (and its transpose) to eliminate M[i][j]. -/// details This rotation matrix performs a rotation in the i,j plane by -/// angle θ. This function assumes that c=cos(θ). s=som(θ), t=tan(θ) -/// have been calculated in advance (using the CalcRot() function). -/// It also assumes that iv) are not computed. -/// verbatim -/// M' = R^T * M * R -/// where R the rotation in the i,j plane and ^T denotes the transpose. -/// i j -/// _ _ -/// | 1 | -/// | . | -/// | . | -/// | 1 | -/// | c ... s | -/// | . . . | -/// R = | . 1 . | -/// | . . . | -/// | -s ... c | -/// | 1 | -/// | . | -/// | . | -/// |_ 1 _| -/// endverbatim -/// -/// Let M' denote the matrix M after multiplication by R^T and R. -/// The components of M' are: -/// -/// verbatim -/// M'_uv = Σ_w Σ_z R_wu * M_wz * R_zv -/// endverbatim -/// -/// Note that a the rotation at location i,j will modify all of the matrix -/// elements containing at least one index which is either i or j -/// such as: M[w][i], M[i][w], M[w][j], M[j][w]. -/// Check and see whether these modified matrix elements exceed the -/// corresponding values in max_idx_row[] array for that row. -/// If so, then update max_idx_row for that row. -/// This is somewhat complicated by the fact that we must only consider -/// matrix elements in the upper-right triangle strictly above the diagonal. -/// (ie. matrix elements whose second index is > the first index). -/// The modified elements we must consider are marked with an "X" below: -/// -/// @verbatim -/// i j -/// _ _ -/// | . X X | -/// | . X X | -/// | . X X | -/// | . X X | -/// | X X X X X 0 X X X X | i -/// | . X | -/// | . X | -/// M = | . X | -/// | . X | -/// | X X X X X | j -/// | . | -/// | . | -/// | . | -/// |_ . _| -/// @endverbatim - -template -void Jacobi:: -ApplyRot(Scalar **M, // matrix - int i, // row index - int j) // column index -{ - // Recall that: - // c = cos(θ) - // s = sin(θ) - // t = tan(θ) (which should be <= 1.0) - - // Compute the diagonal elements of M which have changed: - M[i][i] -= t * M[i][j]; - M[j][j] += t * M[i][j]; - // Note: This is algebraically equivalent to: - // M[i][i] = c*c*M[i][i] + s*s*M[j][j] - 2*s*c*M[i][j] - // M[j][j] = s*s*M[i][i] + c*c*M[j][j] + 2*s*c*M[i][j] - - //Update the off-diagonal elements of M which will change (above the diagonal) - - //assert(i < j); - - M[i][j] = 0.0; - - //compute M[w][i] and M[i][w] for all w!=i,considering above-diagonal elements - for (int w=0; w < i; w++) { // 0 <= w < i < j < n - M[i][w] = M[w][i]; //backup the previous value. store below diagonal (i>w) - M[w][i] = c*M[w][i] - s*M[w][j]; //M[w][i], M[w][j] from previous iteration - if (i == max_idx_row[w]) max_idx_row[w] = MaxEntryRow(M, w); - else if (std::abs(M[w][i])>std::abs(M[w][max_idx_row[w]])) max_idx_row[w]=i; - //assert(max_idx_row[w] == MaxEntryRow(M, w)); - } - for (int w=i+1; w < j; w++) { // 0 <= i < w < j < n - M[w][i] = M[i][w]; //backup the previous value. store below diagonal (w>i) - M[i][w] = c*M[i][w] - s*M[w][j]; //M[i][w], M[w][j] from previous iteration - } - for (int w=j+1; w < n; w++) { // 0 <= i < j+1 <= w < n - M[w][i] = M[i][w]; //backup the previous value. store below diagonal (w>i) - M[i][w] = c*M[i][w] - s*M[j][w]; //M[i][w], M[j][w] from previous iteration - } - - // now that we're done modifying row i, we can update max_idx_row[i] - max_idx_row[i] = MaxEntryRow(M, i); - - //compute M[w][j] and M[j][w] for all w!=j,considering above-diagonal elements - for (int w=0; w < i; w++) { // 0 <= w < i < j < n - M[w][j] = s*M[i][w] + c*M[w][j]; //M[i][w], M[w][j] from previous iteration - if (j == max_idx_row[w]) max_idx_row[w] = MaxEntryRow(M, w); - else if (std::abs(M[w][j])>std::abs(M[w][max_idx_row[w]])) max_idx_row[w]=j; - //assert(max_idx_row[w] == MaxEntryRow(M, w)); - } - for (int w=i+1; w < j; w++) { // 0 <= i+1 <= w < j < n - M[w][j] = s*M[w][i] + c*M[w][j]; //M[w][i], M[w][j] from previous iteration - if (j == max_idx_row[w]) max_idx_row[w] = MaxEntryRow(M, w); - else if (std::abs(M[w][j])>std::abs(M[w][max_idx_row[w]])) max_idx_row[w]=j; - //assert(max_idx_row[w] == MaxEntryRow(M, w)); - } - for (int w=j+1; w < n; w++) { // 0 <= i < j < w < n - M[j][w] = s*M[w][i] + c*M[j][w]; //M[w][i], M[j][w] from previous iteration - } - // now that we're done modifying row j, we can update max_idx_row[j] - max_idx_row[j] = MaxEntryRow(M, j); - -} //Jacobi::ApplyRot() - - - - -///@brief Multiply matrix M on the LEFT side by a transposed rotation matrix R^T -/// This matrix performs a rotation in the i,j plane by angle θ (where -/// the arguments "s" and "c" refer to cos(θ) and sin(θ), respectively). -/// @verbatim -/// E'_uv = Σ_w R_wu * E_wv -/// @endverbatim - -template -void Jacobi:: -ApplyRotLeft(Matrix E, // matrix - int i, // row index - int j) // column index -{ - // Recall that c = cos(θ) and s = sin(θ) - for (int v = 0; v < n; v++) { - Scalar Eiv = E[i][v]; //backup E[i][v] - E[i][v] = c*E[i][v] - s*E[j][v]; - E[j][v] = s*Eiv + c*E[j][v]; - } -} - - - -template -int Jacobi:: -MaxEntryRow(Scalar const *const *M, int i) const { - int j_max = i+1; - for(int j = i+2; j < n; j++) - if (std::abs(M[i][j]) > std::abs(M[i][j_max])) - j_max = j; - return j_max; -} - - - -template -void Jacobi:: -MaxEntry(Scalar const *const *M, int& i_max, int& j_max) const { - // find the maximum entry in the matrix M in O(n) time - i_max = 0; - j_max = max_idx_row[i_max]; - Scalar max_entry = std::abs(M[i_max][j_max]); - int nm1 = n-1; - for (int i=1; i < nm1; i++) { - int j = max_idx_row[i]; - if (std::abs(M[i][j]) > max_entry) { - max_entry = std::abs(M[i][j]); - i_max = i; - j_max = j; - } - } - //#ifndef NDEBUG - //// make sure that the maximum element really is stored at i_max, j_max - //// (comment out the next loop before using. it slows down the code) - //for (int i = 0; i < nm1; i++) - // for (int j = i+1; j < n; j++) - // assert(std::abs(M[i][j]) <= max_entry); - //#endif -} - - - -//Sort the rows of a matrix "evec" by the numbers contained in "eval" -template -void Jacobi:: -SortRows(Vector eval, Matrix evec, int n, SortCriteria sort_criteria) const -{ - for (int i = 0; i < n-1; i++) { - int i_max = i; - for (int j = i+1; j < n; j++) { - // find the "maximum" element in the array starting at position i+1 - switch (sort_criteria) { - case SORT_DECREASING_EVALS: - if (eval[j] > eval[i_max]) - i_max = j; - break; - case SORT_INCREASING_EVALS: - if (eval[j] < eval[i_max]) - i_max = j; - break; - case SORT_DECREASING_ABS_EVALS: - if (std::abs(eval[j]) > std::abs(eval[i_max])) - i_max = j; - break; - case SORT_INCREASING_ABS_EVALS: - if (std::abs(eval[j]) < std::abs(eval[i_max])) - i_max = j; - break; - default: - break; - } - } - std::swap(eval[i], eval[i_max]); // sort "eval" - for (int k = 0; k < n; k++) - std::swap(evec[i][k], evec[i_max][k]); // sort "evec" - } -} - - - -template -void Jacobi:: -Init() { - n = 0; - M = nullptr; - max_idx_row = nullptr; -} - -template -void Jacobi:: -SetSize(int n) { - Dealloc(); - Alloc(n); -} - -// memory management: - -template -void Jacobi:: -Alloc(int n) { - this->n = n; - if (n > 0) { - max_idx_row = new int[n]; - Alloc2D(n, n, &M); - } -} - -template -void Jacobi:: -Dealloc() { - if (max_idx_row) - delete [] max_idx_row; - Dealloc2D(&M); - Init(); -} - -// memory management: copy and move constructor, swap, and assignment operator: - -template -Jacobi:: -Jacobi(const Jacobi& source) -{ - Init(); - SetSize(source.n); - //assert(n == source.n); - - // The following lines aren't really necessary, because the contents - // of source.M and source.max_idx_row are not needed (since they are - // overwritten every time Jacobi::Diagonalize() is invoked). - std::copy(source.max_idx_row, - source.max_idx_row + n, - max_idx_row); - for (int i = 0; i < n; i++) - std::copy(source.M[i], - source.M[i] + n, - M[i]); -} - -template -void Jacobi:: -swap(Jacobi &other) { - std::swap(n, other.n); - std::swap(max_idx_row, other.max_idx_row); - std::swap(M, other.M); -} - -// Move constructor (C++11) -template -Jacobi:: -Jacobi(Jacobi&& other) { - Init(); - this->swap(other); -} - -// Using the "copy-swap" idiom for the assignment operator -template -Jacobi& -Jacobi:: -operator = (Jacobi source) { - this->swap(source); - return *this; -} - -} // namespace MathEigen - - -#endif //#ifndef _MATH_EIGEN_H - diff --git a/src/USER-REACTION/superpose3d.h b/src/USER-REACTION/superpose3d.h index 63c5bf5de8..b0b290ddad 100644 --- a/src/USER-REACTION/superpose3d.h +++ b/src/USER-REACTION/superpose3d.h @@ -22,10 +22,10 @@ /// @author Andrew Jewett /// @license MIT -#ifndef _SUPERPOSE3D_H -#define _SUPERPOSE3D_H +#ifndef LMP_SUPERPOSE3D_H +#define LMP_SUPERPOSE3D_H -#include "math_eigen.h" //functions to calculate eigenvalues and eigenvectors +#include "math_eigen_impl.h" //functions to calculate eigenvalues and eigenvectors // ----------------------------------------------------------- // ------------------------ INTERFACE ------------------------ @@ -462,4 +462,4 @@ operator = (Superpose3D source) { } -#endif //#ifndef _SUPERPOSE3D_H +#endif //#ifndef LMP_SUPERPOSE3D_H diff --git a/src/math_eigen.cpp b/src/math_eigen.cpp index 2caa6414d1..e2a811bdab 100644 --- a/src/math_eigen.cpp +++ b/src/math_eigen.cpp @@ -1,125 +1,62 @@ + #include "math_eigen.h" +#include "math_eigen_impl.h" + #include 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; -// -// ...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; - -// template instantiations of Jacbi for fixed-size (3x3) arrays -template class MathEigen::Jacobi; - -// template instantiations of Jacobi for vector-of-vectors: -template class MathEigen::Jacobi&, - vector >&, - const vector >& >; - -// template instantiations of Jacobi for array-of-arrays: -template class MathEigen::Jacobi&, - array, 3 >&, - const array, 3 >& >; -// template instantiations of LambdaLanczos -template class MathEigen::LambdaLanczos; - -// template instantiations of PEidenDense for pointer->pointer arrays -template class MathEigen::PEigenDense; - -// template instantiations of PEidenDense for vector> -template class MathEigen::PEigenDense&, - const vector >&>; - -// If you plan to use other numeric types (eg floats), add them to this list. - - - // 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::SortCriteria - sort_criteria) +typedef Jacobi Jacobi_v1; +typedef Jacobi Jacobi_v2; + +int MathEigen::jacobi3(double const mat[3][3], double *eval, double evec[3][3]) { - // 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**). + // make copy of const matrix + 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]) }; + int midx[3]; - int midx[3]; // (another array which is preallocated to avoid using the heap) + // create instance of generic Jacobi class and get eigenvalues and -vectors - // variable "ecalc3" does all the work: - Jacobi ecalc3(3, M, midx); - int ierror = ecalc3.Diagonalize(mat, eval, evec, sort_criteria); + Jacobi_v1 ecalc3(3, M, midx); + int ierror = ecalc3.Diagonalize(mat, eval, evec, Jacobi_v1::SORT_DECREASING_EVALS); - // 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=i+1; j<3; j++) - std::swap(evec[i][j], evec[j][i]); // transpose the evec matrix + // transpose the evec matrix + + for (int i=0; i<3; i++) + for (int j=i+1; j<3; j++) + std::swap(evec[i][j], evec[j][i]); return ierror; } - - -int MathEigen:: -jacobi3(double const* 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::SortCriteria - sort_criteria) +int MathEigen::jacobi3(double const* const* mat, double *eval, double **evec) { - // 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**). + // make copy of const matrix + 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]) }; + int midx[3]; - int midx[3]; // (another array which is preallocated to avoid using the heap) + // create instance of generic Jacobi class and get eigenvalues and -vectors - // variable "ecalc3" does all the work: - Jacobi ecalc3(3, M, midx); - int ierror = ecalc3.Diagonalize(mat, eval, evec, sort_criteria); + Jacobi_v2 ecalc3(3, M, midx); + int ierror = ecalc3.Diagonalize(mat, eval, evec, Jacobi_v2::SORT_DECREASING_EVALS); - // 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=i+1; j<3; j++) - std::swap(evec[i][j], evec[j][i]); // transpose the evec matrix + // transpose the evec matrix + + for (int i=0; i<3; i++) + for (int j=i+1; j<3; j++) + std::swap(evec[i][j], evec[j][i]); return ierror; } diff --git a/src/math_eigen.h b/src/math_eigen_impl.h similarity index 96% rename from src/math_eigen.h rename to src/math_eigen_impl.h index 8bb61111f3..5f7dc0a255 100644 --- a/src/math_eigen.h +++ b/src/math_eigen_impl.h @@ -16,8 +16,8 @@ Andrew Jewett (Scripps Research, Jacobi algorithm) ------------------------------------------------------------------------- */ -#ifndef LMP_MATH_EIGEN_H -#define LMP_MATH_EIGEN_H +#ifndef LMP_MATH_EIGEN_IMPL_H +#define LMP_MATH_EIGEN_IMPL_H // This file contains a library of functions and classes which can // efficiently perform eigendecomposition for an extremely broad @@ -220,50 +220,6 @@ namespace MathEigen { }; // class Jacobi - - /// @brief - /// A specialized function which finds the eigenvalues and eigenvectors - /// of a 3x3 matrix (in double ** format). - /// @param mat the 3x3 matrix you wish to diagonalize - /// @param eval store the eigenvalues here - /// @param evec store the eigenvectors here... - /// @param evec_as_columns ...in the columns or in rows? - /// @param sort_criteria sort the resulting eigenvalues? - /// @note - /// When invoked using default arguments, this function is a stand-in for - /// the the version of "jacobi()" that was defined in "POEMS/fix_poems.cpp". - int jacobi3(double const* const* mat, - double *eval, - double **evec, - // optional arguments: - bool evec_as_columns = true, - Jacobi:: - SortCriteria sort_criteria = - Jacobi:: - SORT_DECREASING_EVALS - ); - - - /// @brief - /// This version of jacobi3() finds the eigenvalues and eigenvectors - /// of a 3x3 matrix (which is in double (*)[3] format, instead of double **) - /// @note - /// When invoked using default arguments, this function is a stand-in for - /// the previous version of "jacobi()" that was declared in "math_extra.h". - int jacobi3(double const mat[3][3], - double *eval, - double evec[3][3], - // optional arguments: - bool evec_as_columns = true, - Jacobi:: - SortCriteria sort_criteria = - Jacobi:: - SORT_DECREASING_EVALS - ); - - - - // ---- Eigendecomposition of large sparse (or dense) matrices ---- // The "LambdaLanczos" is a class useful for calculating eigenvalues @@ -1413,4 +1369,4 @@ PrincipalEigen(ConstMatrix matrix, -#endif //#ifndef LMP_MATH_EIGEN_H +#endif //#ifndef LMP_MATH_EIGEN_IMPL_H From fd9e39bf1ac603023548186d13abff93069a6507 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 16 Sep 2020 14:07:06 -0400 Subject: [PATCH 22/28] update docs --- doc/src/pg_dev_utils.rst | 207 ++++++--------------------------------- 1 file changed, 28 insertions(+), 179 deletions(-) diff --git a/doc/src/pg_dev_utils.rst b/doc/src/pg_dev_utils.rst index 36c2a82121..5a1668f20d 100644 --- a/doc/src/pg_dev_utils.rst +++ b/doc/src/pg_dev_utils.rst @@ -10,7 +10,7 @@ strings into specific types of numbers with checking for validity. This reduces redundant implementations and encourages consistent behavior. I/O with status check -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^ These are wrappers around the corresponding C library calls like ``fgets()`` or ``fread()``. They will check if there were errors @@ -26,6 +26,8 @@ indicating the name of the problematic file, if possible. .. doxygenfunction:: sfread :project: progguide +---------- + String to number conversions with validity check ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -281,6 +283,8 @@ This code example should produce the following output: :project: progguide :members: what +---------- + File reader classes ==================== @@ -333,6 +337,8 @@ convert numbers, so that LAMMPS will be aborted. A file that would be parsed by the reader code fragment looks like this: +.. parsed-literal:: + # DATE: 2015-02-19 UNITS: metal CONTRIBUTOR: Ray Shan CITATION: Streitz and Mintmire, Phys Rev B, 50, 11996-12003 (1994) # # X (eV) J (eV) gamma (1/\AA) zeta (1/\AA) Z (e) @@ -351,7 +357,6 @@ A file that would be parsed by the reader code fragment looks like this: :project: progguide :members: - ---------- Memory pool classes @@ -416,192 +421,36 @@ its size is registered later with :cpp:func:`vgot() :project: progguide :members: -Eigensolver classes -=============================================================== +---------- -The "math_eigen.h" file contains the definition of 3 template classes -used for calculating eigenvalues and eigenvectors of matrices: -"Jacobi", "PEigenDense", and "LambdaLanczos". +Eigensolver functions +===================== -"Jacobi" calculates all of the eigenvalues and eigenvectors -of a dense, symmetric, real matrix. +The ``MathEigen`` sub-namespace of the ``LAMMPS_NS`` namespace contains +functions and classes for eigensolvers. Currently only the +:cpp:func:`jacobi3 function ` +is used in various places in LAMMPS. That function is built on top +of a group of more generic eigensolvers that are maintained in the +``math_eigen_impl.h`` header file. This header contains the implementation +of three template classes: -The "PEigenDense" class only calculates the principal eigenvalue -(ie. the largest or smallest eigenvalue), and its corresponding eigenvector. -However it is much more efficient than "Jacobi" when applied to large matrices -(larger than 13x13). PEigenDense also can understand complex-valued -Hermitian matrices. +#. "Jacobi" calculates all of the eigenvalues and eigenvectors + of a dense, symmetric, real matrix. -The "LambdaLanczos" class is a generalization of "PEigenDense" which can be -applied to arbitrary sparse matrices. +#. The "PEigenDense" class only calculates the principal eigenvalue + (ie. the largest or smallest eigenvalue), and its corresponding + eigenvector. However it is much more efficient than "Jacobi" when + applied to large matrices (larger than 13x13). PEigenDense also can + understand complex-valued Hermitian matrices. -Together, these matrix eigensolvers cover a fairly wide range of use cases. - -Note: The code described here does not take advantage of parallelization. -(It is assumed that the matrices are small enough -that they can be diagonalized using individual CPU cores.) - -.. code-block:: C++ - :caption: Jacobi usage example - - #include "math_eigen.h" - using namespace MathEigen; - - int n = 5; // Matrix size - double **M; // A symmetric n x n matrix you want to diagonalize - double *evals; // Store the eigenvalues here. - double **evects; // Store the eigenvectors here. - // Allocate space for M, evals, and evects, and load contents of M (omitted) - - // Now create an instance of Jacobi ("eigen_calc"). This will allocate space - // for storing intermediate calculations. Once created, it can be reused - // multiple times without paying the cost of allocating memory on the heap. - - Jacobi eigen_calc(n); - - // Note: - // If the matrix you plan to diagonalize (M) is read-only, use this instead: - // Jacobi eigen_calc(n); - - // Now, calculate the eigenvalues and eigenvectors of M - eigen_calc.Diagonalize(M, evals, evects); - -The Jacobi class is not limited to double** matrices. It works on any C or C++ -object that supports indexing using [i][j] bracket notation. -For example, if you prefer using std::vectors, then define a -Jacobi instance this way instead: - -.. code-block:: C++ - :caption: Jacobi std::vector example - - Jacobi&, vector>&, const vector>&> eigen_calc(n); - - -The PEigenDense class is useful for diagonalizing larger matrices -which can be real (symmetric) or complex-valued (Hermitian): - -.. code-block:: C++ - :caption: PEigenDense usage example - - #include "math_eigen.h" - using namespace MathEigen; - - const int n = 100; - - PEigenDense pe(n); - - double **M; // A symmetric n x n matrix you want to diagonalize - double evect[n]; // Store the principal eigenvector here. - - // Now, allocate space for M and load it's contents. (omitted) - - double eval = pe.PrincipalEigen(M, evect, true); - - // This calculates only the maximum eigenvalue and its eigenvector - - -The "LambdaLanczos" class generalizes "PEigenDense" by allowing the user -to diagonalize arbitrary sparse matrices. The "LambdaLanczos" class -does not need to know how the matrices are implemented or stored in memory. -Instead, users supply a function as an argument to the "LambdaLanczos" -constructor (a lambda expression) that multiplies vectors by matrices. The -specific implementation details are never revealed to the LambdaLanczos class. -This allows users to choose arbitrary data structures to represent -(sparse or dense) matrices. - -Note: If the matrix is not positive or negative definite, -then user must specify an "eigenvalue_offset" parameter. (See below.) - -Note: Both "LambdaLanczos" and "PEigenDense" use the Lanczos algorithm. - -.. code-block:: C++ - :caption: LambdaLanczos usage example - - #include "math_eigen.h" - using namespace MathEigen; - - const int n = 3; - double M[n][n] = { {-1.0, -1.0, 1.0}, - {-1.0, 1.0, 1.0}, - { 1.0, 1.0, 1.0} }; - // (Its eigenvalues are {-2, 1, 2}) - - // Specify the matrix-vector multiplication function - auto mv_mul = [&](const vector& in, vector& out) { - for(int i = 0;i < n;i++) { - for(int j = 0;j < n;j++) { - out[i] += M[i][j]*in[j]; - } - } - }; - - LambdaLanczos engine(mv_mul, n, true); - //(Setting 3rd arg (find_maximum) to true calculates the largest eigenvalue.) - - engine.eigenvalue_offset = 3.0; // = max_i{sum_j|Mij|} (see below) - - double eigenvalue; //(must never be a complex number, even if M is complex) - vector eigenvector(n); - - int itern = engine.run(eigenvalue, eigenvector); - - cout << "Iteration count: " << itern << endl; - cout << "Eigenvalue: " << eigenvalue << endl; - cout << "Eigenvector:"; - for(int i = 0; i < n; i++) { - cout << eigenvector[i] << " "; - } - cout << endl; - -In this example, an small dense square matrix was used for simplicity. -One could however, implement a large sparse matrix whose elements are -stored as a list of {row-index, column-index, value} tuples, -and modify the "mv_mult" function accordingly. - - -IMPORTANT: -The Lanczos algorithm finds the largest magnitude eigenvalue, so you -MUST ensure that the eigenvalue you are seeking has the largest magnitude -(regardless of whether it is the maximum or minimum eigenvalue). -To insure that this is so, you can add or subtract a number to all -of the eigenvalues of the matrix by specifying the "eigenvalue_offset". -This number should exceed the largest magnitude eigenvalue of the matrix. -According to the Gershgorin theorem, you can estimate this number using - -r = max_i{sum_j|Mij|} -or -r = max_j{sum_i|Mij|} - -(where Mij are the elements of the matrix and sum_j denotes the sum over j). - -If you are seeking the maximum eigenvalue, then use: - - eigenvalue_offset = +r - -If you are seeking the minimum eigenvalue, use: - - eigenvalue_offset = -r - -You can omit this step if you are seeking the maximum eigenvalue, -and the matrix is positive definite, or if you are seeking the minimum -eigenvalue and the matrix is negative definite.) -Otherwise, for dense (or mostly-dense) matrices, you can use the -"ChooseOffset()" member function to pick the eigenvalue_offset automatically. -Otherwise, the eigenvalue_offset MUST be specified by the user explicitly. -(LambdaLanczos is ignorant of the way the matrix is implemented internally, -so it does not have an efficient and general way to access the -elements of a sparse matrix.) +#. The "LambdaLanczos" class is a generalization of "PEigenDense" which can be + applied to arbitrary sparse matrices. ---------- -.. doxygenclass:: MathEigen::Jacobi +.. doxygenfunction:: MathEigen::jacobi3(double const *const *mat, double *eval, double **evec) :project: progguide - :members: -.. doxygenclass:: MathEigen::PEigenDense +.. doxygenfunction:: MathEigen::jacobi3(double const mat[3][3], double *eval, double evec[3][3]) :project: progguide - :members: -.. doxygenclass:: MathEigen::LambdaLanczos - :project: progguide - :members: From 0931cdd1097ee388a48e32d5ac6b8da02a0136fb Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 16 Sep 2020 14:07:28 -0400 Subject: [PATCH 23/28] relax epsilon for rigid body integrators --- unittest/force-styles/tests/fix-timestep-rigid_group.yaml | 2 +- unittest/force-styles/tests/fix-timestep-rigid_molecule.yaml | 2 +- unittest/force-styles/tests/fix-timestep-rigid_nph.yaml | 2 +- unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml | 2 +- unittest/force-styles/tests/fix-timestep-rigid_npt.yaml | 2 +- unittest/force-styles/tests/fix-timestep-rigid_npt_small.yaml | 2 +- unittest/force-styles/tests/fix-timestep-rigid_nve_group.yaml | 2 +- .../force-styles/tests/fix-timestep-rigid_nve_molecule.yaml | 2 +- unittest/force-styles/tests/fix-timestep-rigid_nve_single.yaml | 2 +- unittest/force-styles/tests/fix-timestep-rigid_nve_small.yaml | 2 +- unittest/force-styles/tests/fix-timestep-rigid_nvt_small.yaml | 2 +- unittest/force-styles/tests/fix-timestep-rigid_single.yaml | 2 +- unittest/force-styles/tests/fix-timestep-rigid_small.yaml | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/unittest/force-styles/tests/fix-timestep-rigid_group.yaml b/unittest/force-styles/tests/fix-timestep-rigid_group.yaml index 7fb76380c8..00201c36b5 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_group.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_group.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 22:36:53 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid diff --git a/unittest/force-styles/tests/fix-timestep-rigid_molecule.yaml b/unittest/force-styles/tests/fix-timestep-rigid_molecule.yaml index 631e538f6e..418614b035 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_molecule.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_molecule.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 22:36:54 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nph.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nph.yaml index 64585af6bb..4e5c3cf1bc 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nph.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nph.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 22:36:55 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/nph diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml index 2aa29b2d39..5019d8fbe5 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 22:36:55 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/nph/small diff --git a/unittest/force-styles/tests/fix-timestep-rigid_npt.yaml b/unittest/force-styles/tests/fix-timestep-rigid_npt.yaml index 2733d8a704..f85f2119b5 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_npt.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_npt.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 22:36:56 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/npt diff --git a/unittest/force-styles/tests/fix-timestep-rigid_npt_small.yaml b/unittest/force-styles/tests/fix-timestep-rigid_npt_small.yaml index 57d18854e0..4b5a717e25 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_npt_small.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_npt_small.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 22:36:56 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/npt/small diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nve_group.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nve_group.yaml index 71d222c599..ee40036bf9 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nve_group.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nve_group.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 22:36:57 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/nve diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nve_molecule.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nve_molecule.yaml index fdf2dd5c59..d422c3d56e 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nve_molecule.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nve_molecule.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 22:36:57 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/nve diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nve_single.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nve_single.yaml index d4780f234f..d72a0ff3b7 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nve_single.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nve_single.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 22:36:58 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/nve diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nve_small.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nve_small.yaml index c6ecc22a44..74121559aa 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nve_small.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nve_small.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 22:36:58 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/nve/small diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nvt_small.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nvt_small.yaml index 814353d1b2..654b85416a 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nvt_small.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nvt_small.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 22:36:59 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/nvt/small diff --git a/unittest/force-styles/tests/fix-timestep-rigid_single.yaml b/unittest/force-styles/tests/fix-timestep-rigid_single.yaml index 6be1fafd47..e419416c7e 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_single.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_single.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 22:37:00 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid diff --git a/unittest/force-styles/tests/fix-timestep-rigid_small.yaml b/unittest/force-styles/tests/fix-timestep-rigid_small.yaml index bb44e6fe0f..2c5fa3a2c0 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_small.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_small.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 22:37:00 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full fix rigid/small From bd542efa52002e7564ac46b249f679e020dbf617 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 16 Sep 2020 14:12:14 -0400 Subject: [PATCH 24/28] include math_eigen.h, remove it from .gitignore --- doc/src/pg_dev_utils.rst | 10 +++++----- src/.gitignore | 1 - src/math_eigen.h | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 src/math_eigen.h diff --git a/doc/src/pg_dev_utils.rst b/doc/src/pg_dev_utils.rst index 5a1668f20d..ce5ecf2e7a 100644 --- a/doc/src/pg_dev_utils.rst +++ b/doc/src/pg_dev_utils.rst @@ -428,11 +428,11 @@ Eigensolver functions The ``MathEigen`` sub-namespace of the ``LAMMPS_NS`` namespace contains functions and classes for eigensolvers. Currently only the -:cpp:func:`jacobi3 function ` -is used in various places in LAMMPS. That function is built on top -of a group of more generic eigensolvers that are maintained in the -``math_eigen_impl.h`` header file. This header contains the implementation -of three template classes: +:cpp:func:`jacobi3 function ` is used in various +places in LAMMPS. That function is built on top of a group of more +generic eigensolvers that are maintained in the ``math_eigen_impl.h`` +header file. This header contains the implementation of three template +classes: #. "Jacobi" calculates all of the eigenvalues and eigenvectors of a dense, symmetric, real matrix. diff --git a/src/.gitignore b/src/.gitignore index 54b5edd8e3..ebeb7076da 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -33,7 +33,6 @@ /pair_kim.h /superpose3d.h -/math_eigen.h /kokkos.cpp /kokkos.h diff --git a/src/math_eigen.h b/src/math_eigen.h new file mode 100644 index 0000000000..b30dbc7f89 --- /dev/null +++ b/src/math_eigen.h @@ -0,0 +1,40 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. (Some of the code in this file is also + available using a more premissive license. See below for details.) + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- + Contributing authors: Yuya Kurebayashi (Tohoku University, Lanczos algorithm) + Andrew Jewett (Scripps Research, Jacobi algorithm) +------------------------------------------------------------------------- */ + +#ifndef LMP_MATH_EIGEN_H +#define LMP_MATH_EIGEN_H + +namespace MathEigen { + +/** A specialized function which finds the eigenvalues and eigenvectors + * of a 3x3 matrix (in double ** format). + * + * \param mat the 3x3 matrix you wish to diagonalize + * \param eval store the eigenvalues here + * \param evec store the eigenvectors here... + * \return 0 if eigenvalue calculation converged, 1 if it failed */ + +int jacobi3(double const* const* mat, double *eval, double **evec); + +/** \overload */ + +int jacobi3(double const mat[3][3], double *eval, double evec[3][3]); + +} + +#endif //#ifndef LMP_MATH_EIGEN_H From 942ed3afeb7c54ea8df55867c2e8ac2bd09fa461 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 16 Sep 2020 17:35:58 -0400 Subject: [PATCH 25/28] update copyright headers to match LAMMPS' conventions --- src/math_eigen.cpp | 16 ++++++++++++++++ src/math_eigen.h | 8 ++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/math_eigen.cpp b/src/math_eigen.cpp index e2a811bdab..0c4895f0ed 100644 --- a/src/math_eigen.cpp +++ b/src/math_eigen.cpp @@ -1,3 +1,19 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing author: Andrew Jewett (Scripps Research) +------------------------------------------------------------------------- */ #include "math_eigen.h" #include "math_eigen_impl.h" diff --git a/src/math_eigen.h b/src/math_eigen.h index b30dbc7f89..7abf7eb539 100644 --- a/src/math_eigen.h +++ b/src/math_eigen.h @@ -6,15 +6,11 @@ Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under - the GNU General Public License. (Some of the code in this file is also - available using a more premissive license. See below for details.) + the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ -/* ---------------------------------------------------------------------- - Contributing authors: Yuya Kurebayashi (Tohoku University, Lanczos algorithm) - Andrew Jewett (Scripps Research, Jacobi algorithm) -------------------------------------------------------------------------- */ + #ifndef LMP_MATH_EIGEN_H #define LMP_MATH_EIGEN_H From 96f4178d927e80d573e84952dd46c47d4b90d7a0 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 16 Sep 2020 17:46:24 -0400 Subject: [PATCH 26/28] add URLs to upstream projects for eigensolvers --- doc/src/pg_dev_utils.rst | 6 ++++++ doc/utils/sphinx-config/false_positives.txt | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/doc/src/pg_dev_utils.rst b/doc/src/pg_dev_utils.rst index ce5ecf2e7a..55217f17e0 100644 --- a/doc/src/pg_dev_utils.rst +++ b/doc/src/pg_dev_utils.rst @@ -446,6 +446,12 @@ classes: #. The "LambdaLanczos" class is a generalization of "PEigenDense" which can be applied to arbitrary sparse matrices. +The "math_eigen_impl.h" code is an amalgamation of `jacobi_pd +`_ by Andrew Jewett at Scripps +Research (under CC0-1.0 license) and `Lambda Lanczos +`_ by Yuya Kurebayashi at +Tohoku University (under MIT license) + ---------- .. doxygenfunction:: MathEigen::jacobi3(double const *const *mat, double *eval, double **evec) diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index e3f9bf7a43..17e4ed4fd9 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -1300,6 +1300,7 @@ Imageint Imagemagick imd Impey +impl impropers Impropers includelink @@ -1547,6 +1548,7 @@ Kub Kubo Kumagai Kumar +Kurebayashi Kuronen Kusters Kutta @@ -2771,6 +2773,7 @@ Schuring Schwen screenshot screenshots +Scripps Scripta sdk sdpd @@ -3099,6 +3102,7 @@ Tmin tmp tN Tobias +Tohoku tokenizer tokyo tol @@ -3457,6 +3461,7 @@ Yuh yukawa Yukawa Yusof +Yuya yx yy yz @@ -3500,4 +3505,4 @@ filesystems Zstandard Zstd zstd -checksum \ No newline at end of file +checksum From a8a9fb6eb8b3790b84ad4e798fa838958ffe32e5 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 16 Sep 2020 18:17:23 -0400 Subject: [PATCH 27/28] adapt unit test for Jacobi class --- unittest/utils/CMakeLists.txt | 4 + unittest/utils/test_math_eigen_impl.cpp | 766 ++++++++++++++++++++++++ 2 files changed, 770 insertions(+) create mode 100644 unittest/utils/test_math_eigen_impl.cpp diff --git a/unittest/utils/CMakeLists.txt b/unittest/utils/CMakeLists.txt index 5b5b931210..1a10613403 100644 --- a/unittest/utils/CMakeLists.txt +++ b/unittest/utils/CMakeLists.txt @@ -14,3 +14,7 @@ set_tests_properties(Utils PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_PO add_executable(test_fmtlib test_fmtlib.cpp) target_link_libraries(test_fmtlib PRIVATE lammps GTest::GMockMain GTest::GMock GTest::GTest) add_test(FmtLib test_fmtlib) + +add_executable(test_math_eigen_impl test_math_eigen_impl.cpp) +target_include_directories(test_math_eigen_impl PRIVATE ${LAMMPS_SOURCE_DIR}) +add_test(MathEigen test_math_eigen_impl 10 5) diff --git a/unittest/utils/test_math_eigen_impl.cpp b/unittest/utils/test_math_eigen_impl.cpp new file mode 100644 index 0000000000..a39a71417d --- /dev/null +++ b/unittest/utils/test_math_eigen_impl.cpp @@ -0,0 +1,766 @@ +// THIS FILE USED TO BE EASY TO READ until I added "#if defined" statements. +// (They were added to test for many different kinds of array formats.) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "math_eigen_impl.h" + +using std::cout; +using std::cerr; +using std::endl; +using std::setprecision; +using std::vector; +using std::array; +using namespace MathEigen; + + +// This code works with various types of C++ matrices (for example, +// double **, vector> array,5>). +// I use "#if defined" statements to test different matrix types. +// For some of these (eg. array,5>), the size of the matrix +// must be known at compile time. I specify that size now. +#if defined USE_ARRAY_OF_ARRAYS +const int NF=5; //(the array size must be known at compile time) +#elif defined USE_C_FIXED_SIZE_ARRAYS +const int NF=5; //(the array size must be known at compile time) +#endif + + +// @brief Are two numbers "similar"? +template +inline static bool Similar(Scalar a, Scalar b, + Scalar eps=1.0e-06, + Scalar ratio=1.0e-06, + Scalar ratio_denom=1.0) +{ + return ((std::abs(a-b)<=std::abs(eps)) + || + (std::abs(ratio_denom)*std::abs(a-b) + <= + std::abs(ratio)*0.5*(std::abs(a)+std::abs(b)))); +} + +/// @brief Are two vectors (containing n numbers) similar? +template +inline static bool SimilarVec(Vector a, Vector b, int n, + Scalar eps=1.0e-06, + Scalar ratio=1.0e-06, + Scalar ratio_denom=1.0) +{ + for (int i = 0; i < n; i++) + if (not Similar(a[i], b[i], eps, ratio, ratio_denom)) + return false; + return true; +} + +/// @brief Are two vectors (or their reflections) similar? +template +inline static bool SimilarVecUnsigned(Vector a, Vector b, int n, + Scalar eps=1.0e-06, + Scalar ratio=1.0e-06, + Scalar ratio_denom=1.0) +{ + if (SimilarVec(a, b, n, eps)) + return true; + else { + for (int i = 0; i < n; i++) + if (not Similar(a[i], -b[i], eps, ratio, ratio_denom)) + return false; + return true; + } +} + + +/// @brief Multiply two matrices A and B, store the result in C. (C = AB). + +template +void mmult(ConstMatrix A, // +void +SortRows(Vector eval, + Matrix evec, + int n, + bool sort_decreasing=true, + bool sort_abs=false) +{ + for (int i = 0; i < n-1; i++) { + int i_max = i; + for (int j = i+1; j < n; j++) { + if (sort_decreasing) { + if (sort_abs) { //sort by absolute value? + if (std::abs(eval[j]) > std::abs(eval[i_max])) + i_max = j; + } + else if (eval[j] > eval[i_max]) + i_max = j; + } + else { + if (sort_abs) { //sort by absolute value? + if (std::abs(eval[j]) < std::abs(eval[i_max])) + i_max = j; + } + else if (eval[j] < eval[i_max]) + i_max = j; + } + } + std::swap(eval[i], eval[i_max]); // sort "eval" + for (int k = 0; k < n; k++) + std::swap(evec[i][k], evec[i_max][k]); // sort "evec" + } +} + + + +/// @brief Generate a random orthonormal n x n matrix + +template +void GenRandOrth(Matrix R, + int n, + std::default_random_engine &rand_generator) +{ + std::normal_distribution gaussian_distribution(0,1); + std::vector v(n); + + for (int i = 0; i < n; i++) { + // Generate a vector, "v", in a random direction subject to the constraint + // that it is orthogonal to the first i-1 rows-vectors of the R matrix. + Scalar rsq = 0.0; + while (rsq == 0.0) { + // Generate a vector in a random direction + // (This works because we are using a normal (Gaussian) distribution) + for (int j = 0; j < n; j++) + v[j] = gaussian_distribution(rand_generator); + + //Now subtract from v, the projection of v onto the first i-1 rows of R. + //This will produce a vector which is orthogonal to these i-1 row-vectors. + //(They are already normalized and orthogonal to each other.) + for (int k = 0; k < i; k++) { + Scalar v_dot_Rk = 0.0; + for (int j = 0; j < n; j++) + v_dot_Rk += v[j] * R[k][j]; + for (int j = 0; j < n; j++) + v[j] -= v_dot_Rk * R[k][j]; + } + // check if it is linearly independent of the other vectors and non-zero + rsq = 0.0; + for (int j = 0; j < n; j++) + rsq += v[j]*v[j]; + } + // Now normalize the vector + Scalar r_inv = 1.0 / std::sqrt(rsq); + for (int j = 0; j < n; j++) + v[j] *= r_inv; + // Now copy this vector to the i'th row of R + for (int j = 0; j < n; j++) + R[i][j] = v[j]; + } //for (int i = 0; i < n; i++) +} //void GenRandOrth() + + + +/// @brief Generate a random symmetric n x n matrix, M. +/// This function generates random numbers for the eigenvalues ("evals_known") +/// as well as the eigenvectors ("evecs_known"), and uses them to generate M. +/// The "eval_magnitude_range" argument specifies the the base-10 logarithm +/// of the range of eigenvalues desired. The "n_degeneracy" argument specifies +/// the number of repeated eigenvalues desired (if any). +/// @returns This function does not return a value. However after it is +/// invoked, the M matrix will be filled with random numbers. +/// Additionally, the "evals" and "evecs" arguments will contain +/// the eigenvalues and eigenvectors (one eigenvector per row) +/// of the matrix. Later, they can be compared with the eigenvalues +/// and eigenvectors calculated by Jacobi::Diagonalize() + +template +void GenRandSymm(Matrix M, // random_real01; + std::normal_distribution gaussian_distribution(0, max_eval_size); + bool use_log_uniform_distribution = false; + if (min_eval_size > 0.0) + use_log_uniform_distribution = true; + #if defined USE_VECTOR_OF_VECTORS + vector > D(n, vector(n)); + vector > tmp(n, vector(n)); + #elif defined USE_ARRAY_OF_ARRAYS + array, NF> D; + array, NF> tmp; + #elif defined USE_C_FIXED_SIZE_ARRAYS + Scalar D[NF][NF], tmp[NF][NF]; + #else + #define USE_C_POINTER_TO_POINTERS + Scalar **D, **tmp; + Alloc2D(n, n, &D); + Alloc2D(n, n, &tmp); + #endif + + // Randomly generate the eigenvalues + for (int i = 0; i < n; i++) { + if (use_log_uniform_distribution) { + // Use a "log-uniform distribution" (a.k.a. "reciprocal distribution") + // (This is a way to specify numbers with a precise range of magnitudes.) + assert((min_eval_size > 0.0) && (max_eval_size > 0.0)); + Scalar log_min = std::log(std::abs(min_eval_size)); + Scalar log_max = std::log(std::abs(max_eval_size)); + Scalar log_eval = (log_min + random_real01(rand_generator)*(log_max-log_min)); + evals[i] = std::exp(log_eval); + // also consider both positive and negative eigenvalues: + if (random_real01(rand_generator) < 0.5) + evals[i] = -evals[i]; + } + else { + evals[i] = gaussian_distribution(rand_generator); + } + } + + // Does the user want us to force some of the eigenvalues to be the same? + if (n_degeneracy > 1) { + int *permutation = new int[n]; //a random permutation from 0...n-1 + for (int i = 0; i < n; i++) + permutation[i] = i; + std::shuffle(permutation, permutation+n, rand_generator); + for (int i = 1; i < n_degeneracy; i++) //set the first n_degeneracy to same + evals[permutation[i]] = evals[permutation[0]]; + delete [] permutation; + } + + // D is a diagonal matrix whose diagonal elements are the eigenvalues + for (int i = 0; i < n; i++) + for (int j = 0; j < n; j++) + D[i][j] = ((i == j) ? evals[i] : 0.0); + + // Now randomly generate the (transpose of) the "evecs" matrix + GenRandOrth(evecs, n, rand_generator); //(will transpose it later) + + // Construct the test matrix, M, where M = Rt * D * R + + // Original code: + //mmult(evecs, D, tmp, n); // <--> tmp = Rt * D + // Unfortunately, C++ guesses the types incorrectly. Must manually specify: + // #ifdefs making the code ugly again: + #if defined USE_VECTOR_OF_VECTORS + mmult >&, const vector >&> + #elif defined USE_ARRAY_OF_ARRAYS + mmult,NF>&, const array,NF>&> + #elif defined USE_C_FIXED_SIZE_ARRAYS + mmult + #else + mmult + #endif + (evecs, D, tmp, n); + + for (int i = 0; i < n-1; i++) + for (int j = i+1; j < n; j++) + std::swap(evecs[i][j], evecs[j][i]); //transpose "evecs" + + // Original code: + //mmult(tmp, evecs, M, n); + // Unfortunately, C++ guesses the types incorrectly. Must manually specify: + // #ifdefs making the code ugly again: + #if defined USE_VECTOR_OF_VECTORS + mmult >&, const vector >&> + #elif defined USE_ARRAY_OF_ARRAYS + mmult,NF>&, const array,NF>&> + #elif defined USE_C_FIXED_SIZE_ARRAYS + mmult + #else + mmult + #endif + (tmp, evecs, M, n); + //at this point M = Rt*D*R (where "R"="evecs") + + #if defined USE_C_POINTER_TO_POINTERS + Dealloc2D(&D); + Dealloc2D(&tmp); + #endif +} // GenRandSymm() + + + +template +void TestJacobi(int n, //&, + vector >&, + const vector >& > ecalc(n); + + // allocate the matrix, eigenvalues, eigenvectors + vector > M(n, vector(n)); + vector > evecs(n, vector(n)); + vector > evecs_known(n, vector(n)); + vector evals(n); + vector evals_known(n); + vector test_evec(n); + + #elif defined USE_ARRAY_OF_ARRAYS + + n = NF; + cout << "Testing std::array (fixed size).\n" + "(Ignoring first argument, and setting matrix size to " << n << ")" << endl; + + Jacobi&, + array, NF>&, + const array, NF>&> ecalc(n); + + // allocate the matrix, eigenvalues, eigenvectors + array, NF> M; + array, NF> evecs; + array, NF> evecs_known; + array evals; + array evals_known; + array test_evec; + + #elif defined USE_C_FIXED_SIZE_ARRAYS + + n = NF; + cout << "Testing C fixed size arrays.\n" + "(Ignoring first argument, and setting matrix size to " << n << ")" << endl; + Jacobi ecalc(n); + + // allocate the matrix, eigenvalues, eigenvectors + Scalar M[NF][NF]; + Scalar evecs[NF][NF]; + Scalar evecs_known[NF][NF]; + Scalar evals[NF]; + Scalar evals_known[NF]; + Scalar test_evec[NF]; + + #else + + #define USE_C_POINTER_TO_POINTERS + + // Note: Normally, you would just use this to instantiate Jacobi: + // Jacobi ecalc(n); + // ------------------------- + // ..but since Jacobi manages its own memory using new and delete, I also want + // to test that the copy constructors, copy operators, and destructors work. + // The following lines do this: + Jacobi ecalc_test_mem1(n); + Jacobi ecalc_test_mem2(2); + // test the = operator + ecalc_test_mem2 = ecalc_test_mem1; + // test the copy constructor + Jacobi ecalc(ecalc_test_mem2); + // allocate the matrix, eigenvalues, eigenvectors + Scalar **M, **evecs, **evecs_known; + Alloc2D(n, n, &M); + Alloc2D(n, n, &evecs); + Alloc2D(n, n, &evecs_known); + Scalar *evals = new Scalar[n]; + Scalar *evals_known = new Scalar[n]; + Scalar *test_evec = new Scalar[n]; + + #endif + + + // -------------------------------------------------------------------- + // Now, generate random matrices and test Jacobi::Diagonalize() on them. + // -------------------------------------------------------------------- + + for(int imat = 0; imat < n_matrices; imat++) { + + // Create a randomly generated symmetric matrix. + //This function generates random numbers for the eigenvalues ("evals_known") + //as well as the eigenvectors ("evecs_known"), and uses them to generate M. + + #if defined USE_VECTOR_OF_VECTORS + GenRandSymm&, vector >&> + #elif defined USE_ARRAY_OF_ARRAYS + GenRandSymm&, array,NF>&> + #elif defined USE_C_FIXED_SIZE_ARRAYS + GenRandSymm + #else + GenRandSymm + #endif + (M, + n, + evals_known, + evecs_known, + rand_generator, + min_eval_size, + max_eval_size, + n_degeneracy); + + // Sort the matrix evals and eigenvector rows: + // Original code: + //SortRows(evals_known, evecs_known, n); + // Unfortunately, C++ guesses the types incorrectly. Must use #ifdefs again: + #if defined USE_VECTOR_OF_VECTORS + SortRows&, vector >&> + #elif defined USE_ARRAY_OF_ARRAYS + SortRows&, array,NF>&> + #elif defined USE_C_FIXED_SIZE_ARRAYS + SortRows + #else + SortRows + #endif + (evals_known, evecs_known, n); + + + if (n_matrices == 1) { + cout << "Eigenvalues (after sorting):\n"; + for (int i = 0; i < n; i++) + cout << evals_known[i] << " "; + cout << "\n"; + cout << "Eigenvectors (rows) which are known in advance:\n"; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) + cout << evecs_known[i][j] << " "; + cout << "\n"; + } + cout << " (The eigenvectors calculated by Jacobi::Diagonalize() should match these.)\n"; + } + + for (int i_test = 0; i_test < n_tests_per_matrix; i_test++) { + + if (test_code_coverage) { + + // test SORT_INCREASING_ABS_EVALS: + #if defined USE_VECTOR_OF_VECTORS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi&, + vector >&, + const vector >& >::SORT_INCREASING_ABS_EVALS); + #elif defined USE_ARRAY_OF_ARRAYS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi&, + array,NF>&, + const array,NF>&>::SORT_INCREASING_ABS_EVALS); + #elif defined USE_C_FIXED_SIZE_ARRAYS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi::SORT_INCREASING_ABS_EVALS); + #else + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi::SORT_INCREASING_ABS_EVALS); + #endif + + for (int i = 1; i < n; i++) + assert(std::abs(evals[i-1])<=std::abs(evals[i])); + + // test SORT_DECREASING_ABS_EVALS: + #if defined USE_VECTOR_OF_VECTORS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi&, + vector >&, + const vector >& >::SORT_DECREASING_ABS_EVALS); + #elif defined USE_ARRAY_OF_ARRAYS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi&, + array,NF>&, + const array,NF>&>::SORT_DECREASING_ABS_EVALS); + #elif defined USE_C_FIXED_SIZE_ARRAYS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi::SORT_DECREASING_ABS_EVALS); + #else + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi::SORT_DECREASING_ABS_EVALS); + #endif + + for (int i = 1; i < n; i++) + assert(std::abs(evals[i-1])>=std::abs(evals[i])); + + // test SORT_INCREASING_EVALS: + #if defined USE_VECTOR_OF_VECTORS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi&, + vector >&, + const vector >& >::SORT_INCREASING_EVALS); + #elif defined USE_ARRAY_OF_ARRAYS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi&, + array,NF>&, + const array,NF>&>::SORT_INCREASING_EVALS); + #elif defined USE_C_FIXED_SIZE_ARRAYS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi::SORT_INCREASING_EVALS); + #else + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi::SORT_INCREASING_EVALS); + #endif + for (int i = 1; i < n; i++) + assert(evals[i-1] <= evals[i]); + + // test DO_NOT_SORT + #if defined USE_VECTOR_OF_VECTORS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi&, + vector >&, + const vector >& >::DO_NOT_SORT); + #elif defined USE_ARRAY_OF_ARRAYS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi&, + array,NF>&, + const array,NF>&>::DO_NOT_SORT); + #elif defined USE_C_FIXED_SIZE_ARRAYS + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi::DO_NOT_SORT); + #else + ecalc.Diagonalize(M, + evals, + evecs, + Jacobi::DO_NOT_SORT); + #endif + + } //if (test_code_coverage) + + + // Now (finally) calculate the eigenvalues and eigenvectors + int n_sweeps = ecalc.Diagonalize(M, evals, evecs); + + if ((n_matrices == 1) && (i_test == 0)) { + cout <<"Jacobi::Diagonalize() ran for "< Σ_b M[a][b]*evecs[i][b] = evals[i]*evecs[i][b] (for all a) + for (int i = 0; i < n; i++) { + for (int a = 0; a < n; a++) { + test_evec[a] = 0.0; + for (int b = 0; b < n; b++) + test_evec[a] += M[a][b] * evecs[i][b]; + assert(Similar(test_evec[a], + evals[i] * evecs[i][a], + eps, // tolerance (absolute difference) + eps*max_eval_size, // tolerance ratio (numerator) + evals_known[i] // tolerance ration (denominator) + )); + } + } + + } //for (int i_test = 0; i_test < n_tests_per_matrix; i++) + + } //for(int imat = 0; imat < n_matrices; imat++) { + + #if defined USE_C_POINTER_TO_POINTERS + Dealloc2D(&M); + Dealloc2D(&evecs); + Dealloc2D(&evecs_known); + delete [] evals; + delete [] evals_known; + delete [] test_evec; + #endif + +} //TestJacobi() + + +int main(int argc, char **argv) { + int n_size = 2; + int n_matr = 1; + double emin = 0.0; + double emax = 1.0; + int n_tests = 1; + int n_degeneracy = 1; + unsigned seed = 0; + + if (argc <= 1) { + cerr << + "Error: This program requires at least 1 argument.\n" + "\n" + "Description: Run Jacobi::Diagonalize() on randomly generated matrices.\n" + "\n" + "Arguments: n_size [n_matr emin emax n_degeneracy n_tests seed eps]\n" + " n_size = the size of the matrices\n" + " (NOTE: The remaining arguments are optional.)\n" + " n_matr = the number of randomly generated matrices to test\n" + " emin = the smallest possible eigenvalue magnitude (eg. 1e-05)\n" + " emax = the largest possible eigenvalue magnitude (>0 eg. 1e+05)\n" + " (NOTE: If emin=0, a normal distribution is used centered at 0.\n" + " Otherwise a log-uniform distribution is used from emin to emax.)\n" + " n_degeneracy = the number of repeated eigenvalues (1 disables, default)\n" + " n_tests = the number of times the eigenvalues and eigenvectors\n" + " are calculated for EACH matrix. By default this is 1.\n" + " (Increase this to at least 20 if you plan to use this\n" + " program for benchmarking (speed testing), because the time\n" + " needed for generating a random matrix is not negligible.)\n" + " (IF THIS NUMBER IS 0, it will test CODE-COVERAGE instead.)\n" + " seed = the seed used by the random number \"rand_generator\".\n" + " (If this number is 0, which is the default, the system\n" + " clock is used to choose a random seed.)\n" + " eps = the tolerance. The difference between eigenvalues and their\n" + " true value, cannot exceed this (multiplied by the eigenvalue\n" + " of maximum magnitude). Similarly, the difference between\n" + " the eigenvectors after multiplication by the matrix and by\n" + " and after multiplication by the eigenvalue, cannot exceed\n" + " eps*maximum_eigenvalue/eigenvalue. The default value is\n" + " 1.0e-06 (which works well for double precision numbers).\n" + << endl; + return 1; + } + + n_size = std::stoi(argv[1]); + if (argc > 2) + n_matr = std::stoi(argv[2]); + if (argc > 3) + emin = std::stof(argv[3]); + if (argc > 4) + emax = std::stof(argv[4]); + if (argc > 5) + n_degeneracy = std::stoi(argv[5]); + if (argc > 6) + n_tests = std::stoi(argv[6]); + if (argc > 7) + seed = std::stoi(argv[7]); + double eps = 1.0e-06; + if (argc > 8) + eps = std::stof(argv[8]); + + TestJacobi(n_size, n_matr, emin, emax, n_tests, n_degeneracy, seed, eps); + + cout << "test passed\n" << endl; + return EXIT_SUCCESS; +} From b176cdf28ce59955d1ceb7b65eb0c9a7ed33df12 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 16 Sep 2020 18:18:53 -0400 Subject: [PATCH 28/28] remove trailing whitespace --- unittest/utils/test_math_eigen_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unittest/utils/test_math_eigen_impl.cpp b/unittest/utils/test_math_eigen_impl.cpp index a39a71417d..3ff60c2eb6 100644 --- a/unittest/utils/test_math_eigen_impl.cpp +++ b/unittest/utils/test_math_eigen_impl.cpp @@ -354,7 +354,7 @@ void TestJacobi(int n, //