Version info:
diff --git a/doc/html/Section_packages.html b/doc/html/Section_packages.html
index f882ee234b..fedd3cc1ae 100644
--- a/doc/html/Section_packages.html
+++ b/doc/html/Section_packages.html
@@ -493,7 +493,7 @@ name links to a sub-section below with more details.
python |
lib/python |
-
| REAX |
+
| REAX |
ReaxFF potential |
Aidan Thompson (Sandia) |
pair_style reax |
diff --git a/doc/html/compute_rdf.html b/doc/html/compute_rdf.html
index c8d486553f..ef1d1d8cfc 100644
--- a/doc/html/compute_rdf.html
+++ b/doc/html/compute_rdf.html
@@ -227,7 +227,7 @@ atoms of type jtypeN.
to a file is to use the fix ave/time command, for
example:
compute myRDF all rdf 50
-fix 1 all ave/time 100 1 100 c_myRDF file tmp.rdf mode vector
+fix 1 all ave/time 100 1 100 c_myRDF[*] file tmp.rdf mode vector
Output info:
diff --git a/doc/html/fix_lb_pc.html b/doc/html/fix_lb_pc.html
index 8a5281c6c3..4fe4f72ced 100644
--- a/doc/html/fix_lb_pc.html
+++ b/doc/html/fix_lb_pc.html
@@ -146,7 +146,7 @@
Description
Update the positions and velocities of the individual particles
described by group-ID, experiencing velocity-dependent hydrodynamic
-forces, using the integration algorithm described in Mackay et al.. This integration algorithm should only be used if a
+forces, using the integration algorithm described in Mackay et al.. This integration algorithm should only be used if a
user-specified value for the force-coupling constant used in fix lb/fluid has been set; do not use this integration
algorithm if the force coupling constant has been set by default.
diff --git a/doc/html/pair_thole.html b/doc/html/pair_thole.html
index b2742247f9..e3a5f8b9cb 100644
--- a/doc/html/pair_thole.html
+++ b/doc/html/pair_thole.html
@@ -189,8 +189,8 @@ short distances by a function
\frac{s_{ij} r_{ij} }{2} \right)
\exp \left( - s_{ij} r_{ij} \right) \end{equation}\]
This function results from an adaptation to point charges
-(Noskov) of the dipole screening scheme originally proposed
-by Thole. The scaling coefficient \(s_{ij}\) is determined
+(Noskov) of the dipole screening scheme originally proposed
+by Thole. The scaling coefficient \(s_{ij}\) is determined
by the polarizability of the atoms, \(\alpha_i\), and by a Thole
damping parameter \(a\). This Thole damping parameter usually takes
a value of 2.6, but in certain force fields the value can depend upon
diff --git a/doc/src/Manual.txt b/doc/src/Manual.txt
index adf6b5c47e..b7edc5ea99 100644
--- a/doc/src/Manual.txt
+++ b/doc/src/Manual.txt
@@ -1,7 +1,7 @@
LAMMPS Users Manual
-
+
@@ -21,7 +21,7 @@
LAMMPS Documentation :c,h3
-27 Aug 2016 version :c,h4
+7 Sep 2016 version :c,h4
Version info: :h4
diff --git a/src/KOKKOS/pair_eam_kokkos.cpp b/src/KOKKOS/pair_eam_kokkos.cpp
index 37a26145e0..d91da280ac 100755
--- a/src/KOKKOS/pair_eam_kokkos.cpp
+++ b/src/KOKKOS/pair_eam_kokkos.cpp
@@ -340,81 +340,64 @@ void PairEAMKokkos::array2spline()
rdr = 1.0/dr;
rdrho = 1.0/drho;
- tdual_ffloat4 k_frho_spline_a = tdual_ffloat4("pair:frho_a",nfrho,nrho+1);
- tdual_ffloat4 k_rhor_spline_a = tdual_ffloat4("pair:rhor_a",nrhor,nr+1);
- tdual_ffloat4 k_z2r_spline_a = tdual_ffloat4("pair:z2r_a",nz2r,nr+1);
- tdual_ffloat4 k_frho_spline_b = tdual_ffloat4("pair:frho_b",nfrho,nrho+1);
- tdual_ffloat4 k_rhor_spline_b = tdual_ffloat4("pair:rhor_b",nrhor,nr+1);
- tdual_ffloat4 k_z2r_spline_b = tdual_ffloat4("pair:z2r_b",nz2r,nr+1);
+ tdual_ffloat_2d_n7 k_frho_spline = tdual_ffloat_2d_n7("pair:frho",nfrho,nrho+1);
+ tdual_ffloat_2d_n7 k_rhor_spline = tdual_ffloat_2d_n7("pair:rhor",nrhor,nr+1);
+ tdual_ffloat_2d_n7 k_z2r_spline = tdual_ffloat_2d_n7("pair:z2r",nz2r,nr+1);
- t_host_ffloat4 h_frho_spline_a = k_frho_spline_a.h_view;
- t_host_ffloat4 h_rhor_spline_a = k_rhor_spline_a.h_view;
- t_host_ffloat4 h_z2r_spline_a = k_z2r_spline_a.h_view;
- t_host_ffloat4 h_frho_spline_b = k_frho_spline_b.h_view;
- t_host_ffloat4 h_rhor_spline_b = k_rhor_spline_b.h_view;
- t_host_ffloat4 h_z2r_spline_b = k_z2r_spline_b.h_view;
+ t_host_ffloat_2d_n7 h_frho_spline = k_frho_spline.h_view;
+ t_host_ffloat_2d_n7 h_rhor_spline = k_rhor_spline.h_view;
+ t_host_ffloat_2d_n7 h_z2r_spline = k_z2r_spline.h_view;
for (int i = 0; i < nfrho; i++)
- interpolate(nrho,drho,frho[i],h_frho_spline_a,h_frho_spline_b,i);
- k_frho_spline_a.template modify();
- k_frho_spline_a.template sync();
- k_frho_spline_b.template modify();
- k_frho_spline_b.template sync();
+ interpolate(nrho,drho,frho[i],h_frho_spline,i);
+ k_frho_spline.template modify();
+ k_frho_spline.template sync();
for (int i = 0; i < nrhor; i++)
- interpolate(nr,dr,rhor[i],h_rhor_spline_a,h_rhor_spline_b,i);
- k_rhor_spline_a.template modify();
- k_rhor_spline_a.template sync();
- k_rhor_spline_b.template modify();
- k_rhor_spline_b.template sync();
+ interpolate(nr,dr,rhor[i],h_rhor_spline,i);
+ k_rhor_spline.template modify();
+ k_rhor_spline.template sync();
for (int i = 0; i < nz2r; i++)
- interpolate(nr,dr,z2r[i],h_z2r_spline_a,h_z2r_spline_b,i);
- k_z2r_spline_a.template modify();
- k_z2r_spline_a.template sync();
- k_z2r_spline_b.template modify();
- k_z2r_spline_b.template sync();
-
- d_frho_spline_a = k_frho_spline_a.d_view;
- d_rhor_spline_a = k_rhor_spline_a.d_view;
- d_z2r_spline_a = k_z2r_spline_a.d_view;
- d_frho_spline_b = k_frho_spline_b.d_view;
- d_rhor_spline_b = k_rhor_spline_b.d_view;
- d_z2r_spline_b = k_z2r_spline_b.d_view;
-
+ interpolate(nr,dr,z2r[i],h_z2r_spline,i);
+ k_z2r_spline.template modify();
+ k_z2r_spline.template sync();
+ d_frho_spline = k_frho_spline.d_view;
+ d_rhor_spline = k_rhor_spline.d_view;
+ d_z2r_spline = k_z2r_spline.d_view;
}
/* ---------------------------------------------------------------------- */
template
-void PairEAMKokkos::interpolate(int n, double delta, double *f, t_host_ffloat4 h_spline_a, t_host_ffloat4 h_spline_b, int i)
+void PairEAMKokkos::interpolate(int n, double delta, double *f, t_host_ffloat_2d_n7 h_spline, int i)
{
- for (int m = 1; m <= n; m++) h_spline_b(i,m).w = f[m];
+ for (int m = 1; m <= n; m++) h_spline(i,m,6) = f[m];
- h_spline_b(i,1).z = h_spline_b(i,2).w - h_spline_b(i,1).w;
- h_spline_b(i,2).z = 0.5 * (h_spline_b(i,3).w-h_spline_b(i,1).w);
- h_spline_b(i,n-1).z = 0.5 * (h_spline_b(i,n).w-h_spline_b(i,n-2).w);
- h_spline_b(i,n).z = h_spline_b(i,n).w - h_spline_b(i,n-1).w;
+ h_spline(i,1,5) = h_spline(i,2,6) - h_spline(i,1,6);
+ h_spline(i,2,5) = 0.5 * (h_spline(i,3,6)-h_spline(i,1,6));
+ h_spline(i,n-1,5) = 0.5 * (h_spline(i,n,6)-h_spline(i,n-2,6));
+ h_spline(i,n,5) = h_spline(i,n,6) - h_spline(i,n-1,6);
for (int m = 3; m <= n-2; m++)
- h_spline_b(i,m).z = ((h_spline_b(i,m-2).w-h_spline_b(i,m+2).w) +
- 8.0*(h_spline_b(i,m+1).w-h_spline_b(i,m-1).w)) / 12.0;
+ h_spline(i,m,5) = ((h_spline(i,m-2,6)-h_spline(i,m+2,6)) +
+ 8.0*(h_spline(i,m+1,6)-h_spline(i,m-1,6))) / 12.0;
for (int m = 1; m <= n-1; m++) {
- h_spline_b(i,m).y = 3.0*(h_spline_b(i,m+1).w-h_spline_b(i,m).w) -
- 2.0*h_spline_b(i,m).z - h_spline_b(i,m+1).z;
- h_spline_b(i,m).x = h_spline_b(i,m).z + h_spline_b(i,m+1).z -
- 2.0*(h_spline_b(i,m+1).w-h_spline_b(i,m).w);
+ h_spline(i,m,4) = 3.0*(h_spline(i,m+1,6)-h_spline(i,m,6)) -
+ 2.0*h_spline(i,m,5) - h_spline(i,m+1,5);
+ h_spline(i,m,3) = h_spline(i,m,5) + h_spline(i,m+1,5) -
+ 2.0*(h_spline(i,m+1,6)-h_spline(i,m,6));
}
- h_spline_b(i,n).y = 0.0;
- h_spline_b(i,n).x = 0.0;
+ h_spline(i,n,4) = 0.0;
+ h_spline(i,n,3) = 0.0;
for (int m = 1; m <= n; m++) {
- h_spline_a(i,m).z = h_spline_b(i,m).z/delta;
- h_spline_a(i,m).y = 2.0*h_spline_b(i,m).y/delta;
- h_spline_a(i,m).x = 3.0*h_spline_b(i,m).x/delta;
+ h_spline(i,m,2) = h_spline(i,m,5)/delta;
+ h_spline(i,m,1) = 2.0*h_spline(i,m,4)/delta;
+ h_spline(i,m,0) = 3.0*h_spline(i,m,3)/delta;
}
}
@@ -558,13 +541,12 @@ void PairEAMKokkos::operator()(TagPairEAMKernelA::operator()(TagPairEAMKernelB, const int &
p -= m;
p = MIN(p,1.0);
const int d_type2frho_i = d_type2frho[itype];
- const F_FLOAT4 frho = d_frho_spline_a(d_type2frho_i,m);
- d_fp[i] = (frho.x*p + frho.y)*p + frho.z;
+ d_fp[i] = (d_frho_spline(d_type2frho_i,m,0)*p + d_frho_spline(d_type2frho_i,m,1))*p + d_frho_spline(d_type2frho_i,m,2);
if (EFLAG) {
- const F_FLOAT4 frho_b = d_frho_spline_b(d_type2frho_i,m);
- F_FLOAT phi = ((frho_b.x*p + frho_b.y)*p + frho_b.z)*p + frho_b.w;
+ F_FLOAT phi = ((d_frho_spline(d_type2frho_i,m,3)*p + d_frho_spline(d_type2frho_i,m,4))*p +
+ d_frho_spline(d_type2frho_i,m,5))*p + d_frho_spline(d_type2frho_i,m,6);
if (d_rho[i] > rhomax) phi += d_fp[i] * (d_rho[i]-rhomax);
if (eflag_global) ev.evdwl += phi;
if (eflag_atom) d_eatom[i] += phi;
@@ -651,8 +632,8 @@ void PairEAMKokkos::operator()(TagPairEAMKernelAB, const int
p -= m;
p = MIN(p,1.0);
const int d_type2rhor_ji = d_type2rhor(jtype,itype);
- const F_FLOAT4 rhor = d_rhor_spline_b(d_type2rhor_ji,m);
- rhotmp += ((rhor.x*p + rhor.y)*p + rhor.z)*p + rhor.w;
+ rhotmp += ((d_rhor_spline(d_type2rhor_ji,m,3)*p + d_rhor_spline(d_type2rhor_ji,m,4))*p +
+ d_rhor_spline(d_type2rhor_ji,m,5))*p + d_rhor_spline(d_type2rhor_ji,m,6);
}
}
@@ -669,11 +650,10 @@ void PairEAMKokkos::operator()(TagPairEAMKernelAB, const int
p -= m;
p = MIN(p,1.0);
const int d_type2frho_i = d_type2frho[itype];
- const F_FLOAT4 frho = d_frho_spline_a(d_type2frho_i,m);
- d_fp[i] = (frho.x*p + frho.y)*p + frho.z;
+ d_fp[i] = (d_frho_spline(d_type2frho_i,m,0)*p + d_frho_spline(d_type2frho_i,m,1))*p + d_frho_spline(d_type2frho_i,m,2);
if (EFLAG) {
- const F_FLOAT4 frho_b = d_frho_spline_b(d_type2frho_i,m);
- F_FLOAT phi = ((frho_b.x*p + frho_b.y)*p + frho_b.z)*p + frho_b.w;
+ F_FLOAT phi = ((d_frho_spline(d_type2frho_i,m,3)*p + d_frho_spline(d_type2frho_i,m,4))*p +
+ d_frho_spline(d_type2frho_i,m,5))*p + d_frho_spline(d_type2frho_i,m,6);
if (d_rho[i] > rhomax) phi += d_fp[i] * (d_rho[i]-rhomax);
if (eflag_global) ev.evdwl += phi;
if (eflag_atom) d_eatom[i] += phi;
@@ -742,18 +722,16 @@ void PairEAMKokkos::operator()(TagPairEAMKernelC;
#ifdef KOKKOS_HAVE_CUDA
template class PairEAMKokkos;
#endif
-}
-
+}
\ No newline at end of file
diff --git a/src/KOKKOS/pair_eam_kokkos.h b/src/KOKKOS/pair_eam_kokkos.h
index b3d33bb37f..89d1d61b6b 100755
--- a/src/KOKKOS/pair_eam_kokkos.h
+++ b/src/KOKKOS/pair_eam_kokkos.h
@@ -136,14 +136,14 @@ class PairEAMKokkos : public PairEAM {
DAT::t_int_2d_randomread d_type2rhor;
DAT::t_int_2d_randomread d_type2z2r;
- typedef Kokkos::DualView tdual_ffloat4;
- typedef typename tdual_ffloat4::t_dev_const_randomread t_ffloat4_randomread;
- typedef typename tdual_ffloat4::t_host t_host_ffloat4;
+ typedef Kokkos::DualView tdual_ffloat_2d_n7;
+ typedef typename tdual_ffloat_2d_n7::t_dev_const_randomread t_ffloat_2d_n7_randomread;
+ typedef typename tdual_ffloat_2d_n7::t_host t_host_ffloat_2d_n7;
- t_ffloat4_randomread d_frho_spline_a, d_frho_spline_b;
- t_ffloat4_randomread d_rhor_spline_a, d_rhor_spline_b;
- t_ffloat4_randomread d_z2r_spline_a, d_z2r_spline_b;
- void interpolate(int, double, double *, t_host_ffloat4, t_host_ffloat4, int);
+ t_ffloat_2d_n7_randomread d_frho_spline;
+ t_ffloat_2d_n7_randomread d_rhor_spline;
+ t_ffloat_2d_n7_randomread d_z2r_spline;
+ void interpolate(int, double, double *, t_host_ffloat_2d_n7, int);
virtual void file2array();
void array2spline();
diff --git a/src/compute_omega_chunk.cpp b/src/compute_omega_chunk.cpp
index ca4af7931f..f2a8394964 100644
--- a/src/compute_omega_chunk.cpp
+++ b/src/compute_omega_chunk.cpp
@@ -18,11 +18,14 @@
#include "modify.h"
#include "compute_chunk_atom.h"
#include "domain.h"
+#include "math_extra.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
+#define EPSILON 1.0e-6
+
/* ---------------------------------------------------------------------- */
ComputeOmegaChunk::ComputeOmegaChunk(LAMMPS *lmp, int narg, char **arg) :
@@ -192,49 +195,97 @@ void ComputeOmegaChunk::compute_array()
MPI_Allreduce(&angmom[0][0],&angmomall[0][0],3*nchunk,
MPI_DOUBLE,MPI_SUM,world);
- // compute omega for each chunk from L = Iw, inverting I to solve for w
+ // compute omega for each chunk
- double ione[3][3],inverse[3][3];
+ double determinant,invdeterminant;
+ double idiag[3],ex[3],ey[3],ez[3],cross[3];
+ double ione[3][3],inverse[3][3],evectors[3][3];
+ double *iall,*mall;
for (m = 0; m < nchunk; m++) {
- ione[0][0] = inertiaall[m][0];
- ione[1][1] = inertiaall[m][1];
- ione[2][2] = inertiaall[m][2];
- ione[0][1] = inertiaall[m][3];
- ione[1][2] = inertiaall[m][4];
- ione[0][2] = inertiaall[m][5];
- ione[1][0] = ione[0][1];
- ione[2][1] = ione[1][2];
- ione[2][0] = ione[0][2];
- inverse[0][0] = ione[1][1]*ione[2][2] - ione[1][2]*ione[2][1];
- inverse[0][1] = -(ione[0][1]*ione[2][2] - ione[0][2]*ione[2][1]);
- inverse[0][2] = ione[0][1]*ione[1][2] - ione[0][2]*ione[1][1];
+ // determinant = triple product of rows of inertia matrix
- inverse[1][0] = -(ione[1][0]*ione[2][2] - ione[1][2]*ione[2][0]);
- inverse[1][1] = ione[0][0]*ione[2][2] - ione[0][2]*ione[2][0];
- inverse[1][2] = -(ione[0][0]*ione[1][2] - ione[0][2]*ione[1][0]);
+ iall = &inertiaall[m][0];
+ determinant = iall[0] * (iall[1]*iall[2] - iall[4]*iall[4]) +
+ iall[3] * (iall[4]*iall[5] - iall[3]*iall[2]) +
+ iall[5] * (iall[3]*iall[4] - iall[1]*iall[5]);
- inverse[2][0] = ione[1][0]*ione[2][1] - ione[1][1]*ione[2][0];
- inverse[2][1] = -(ione[0][0]*ione[2][1] - ione[0][1]*ione[2][0]);
- inverse[2][2] = ione[0][0]*ione[1][1] - ione[0][1]*ione[1][0];
+ ione[0][0] = iall[0];
+ ione[1][1] = iall[1];
+ ione[2][2] = iall[2];
+ ione[0][1] = ione[1][0] = iall[3];
+ ione[1][2] = ione[2][1] = iall[4];
+ ione[0][2] = ione[2][0] = iall[5];
- double determinant = ione[0][0]*ione[1][1]*ione[2][2] +
- ione[0][1]*ione[1][2]*ione[2][0] + ione[0][2]*ione[1][0]*ione[2][1] -
- ione[0][0]*ione[1][2]*ione[2][1] - ione[0][1]*ione[1][0]*ione[2][2] -
- ione[2][0]*ione[1][1]*ione[0][2];
+ // non-singular I matrix
+ // use L = Iw, inverting I to solve for w
- if (determinant > 0.0)
+ if (determinant > EPSILON) {
+ inverse[0][0] = ione[1][1]*ione[2][2] - ione[1][2]*ione[2][1];
+ inverse[0][1] = -(ione[0][1]*ione[2][2] - ione[0][2]*ione[2][1]);
+ inverse[0][2] = ione[0][1]*ione[1][2] - ione[0][2]*ione[1][1];
+
+ inverse[1][0] = -(ione[1][0]*ione[2][2] - ione[1][2]*ione[2][0]);
+ inverse[1][1] = ione[0][0]*ione[2][2] - ione[0][2]*ione[2][0];
+ inverse[1][2] = -(ione[0][0]*ione[1][2] - ione[0][2]*ione[1][0]);
+
+ inverse[2][0] = ione[1][0]*ione[2][1] - ione[1][1]*ione[2][0];
+ inverse[2][1] = -(ione[0][0]*ione[2][1] - ione[0][1]*ione[2][0]);
+ inverse[2][2] = ione[0][0]*ione[1][1] - ione[0][1]*ione[1][0];
+
+ invdeterminant = 1.0/determinant;
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
- inverse[i][j] /= determinant;
+ inverse[i][j] *= invdeterminant;
+
+ mall = &angmomall[m][0];
+ omega[m][0] = inverse[0][0]*mall[0] + inverse[0][1]*mall[1] +
+ inverse[0][2]*mall[2];
+ omega[m][1] = inverse[1][0]*mall[0] + inverse[1][1]*mall[1] +
+ inverse[1][2]*mall[2];
+ omega[m][2] = inverse[2][0]*mall[0] + inverse[2][1]*mall[1] +
+ inverse[2][2]*mall[2];
- omega[m][0] = inverse[0][0]*angmom[m][0] + inverse[0][1]*angmom[m][1] +
- inverse[0][2]*angmom[m][2];
- omega[m][1] = inverse[1][0]*angmom[m][0] + inverse[1][1]*angmom[m][1] +
- inverse[1][2]*angmom[m][2];
- omega[m][2] = inverse[2][0]*angmom[m][0] + inverse[2][1]*angmom[m][1] +
- inverse[2][2]*angmom[i][2];
+ // handle each (nearly) singular I matrix
+ // due to 2-atom chunk or linear molecule
+ // use jacobi() and angmom_to_omega() to calculate valid omega
+
+ } else {
+ int ierror = MathExtra::jacobi(ione,idiag,evectors);
+ if (ierror) error->all(FLERR,
+ "Insufficient Jacobi rotations for omega/chunk");
+
+ ex[0] = evectors[0][0];
+ ex[1] = evectors[1][0];
+ ex[2] = evectors[2][0];
+ ey[0] = evectors[0][1];
+ ey[1] = evectors[1][1];
+ ey[2] = evectors[2][1];
+ ez[0] = evectors[0][2];
+ ez[1] = evectors[1][2];
+ ez[2] = evectors[2][2];
+
+ // enforce 3 evectors as a right-handed coordinate system
+ // flip 3rd vector if needed
+
+ MathExtra::cross3(ex,ey,cross);
+ if (MathExtra::dot3(cross,ez) < 0.0) MathExtra::negate3(ez);
+
+ // if any principal moment < scaled EPSILON, set to 0.0
+
+ double max;
+ max = MAX(idiag[0],idiag[1]);
+ max = MAX(max,idiag[2]);
+
+ if (idiag[0] < EPSILON*max) idiag[0] = 0.0;
+ if (idiag[1] < EPSILON*max) idiag[1] = 0.0;
+ if (idiag[2] < EPSILON*max) idiag[2] = 0.0;
+
+ // calculate omega using diagonalized inertia matrix
+
+ MathExtra::angmom_to_omega(&angmomall[m][0],ex,ey,ez,idiag,&omega[m][0]);
+ }
}
}
diff --git a/src/group.cpp b/src/group.cpp
index 5b572b2070..da0e94fc11 100644
--- a/src/group.cpp
+++ b/src/group.cpp
@@ -29,6 +29,7 @@
#include "input.h"
#include "variable.h"
#include "dump.h"
+#include "math_extra.h"
#include "memory.h"
#include "error.h"
@@ -37,6 +38,7 @@
using namespace LAMMPS_NS;
#define MAX_GROUP 32
+#define EPSILON 1.0e-6
enum{TYPE,MOLECULE,ID};
enum{LT,LE,GT,GE,EQ,NEQ,BETWEEN};
@@ -1662,42 +1664,47 @@ void Group::inertia(int igroup, double *cm, double itensor[3][3], int iregion)
}
/* ----------------------------------------------------------------------
- compute angular velocity omega from L = Iw, inverting I to solve for w
+ compute angular velocity omega from L and I
really not a group/region operation, but L,I were computed for a group/region
+ diagonalize I instead of inverting it, to allow for a singular matrix
------------------------------------------------------------------------- */
void Group::omega(double *angmom, double inertia[3][3], double *w)
{
- double inverse[3][3];
+ double idiag[3],ex[3],ey[3],ez[3],cross[3];
+ double evectors[3][3];
+
+ int ierror = MathExtra::jacobi(inertia,idiag,evectors);
+ if (ierror) error->all(FLERR,
+ "Insufficient Jacobi rotations for group::omega");
- inverse[0][0] = inertia[1][1]*inertia[2][2] - inertia[1][2]*inertia[2][1];
- inverse[0][1] = -(inertia[0][1]*inertia[2][2] - inertia[0][2]*inertia[2][1]);
- inverse[0][2] = inertia[0][1]*inertia[1][2] - inertia[0][2]*inertia[1][1];
-
- inverse[1][0] = -(inertia[1][0]*inertia[2][2] - inertia[1][2]*inertia[2][0]);
- inverse[1][1] = inertia[0][0]*inertia[2][2] - inertia[0][2]*inertia[2][0];
- inverse[1][2] = -(inertia[0][0]*inertia[1][2] - inertia[0][2]*inertia[1][0]);
-
- inverse[2][0] = inertia[1][0]*inertia[2][1] - inertia[1][1]*inertia[2][0];
- inverse[2][1] = -(inertia[0][0]*inertia[2][1] - inertia[0][1]*inertia[2][0]);
- inverse[2][2] = inertia[0][0]*inertia[1][1] - inertia[0][1]*inertia[1][0];
-
- double determinant = inertia[0][0]*inertia[1][1]*inertia[2][2] +
- inertia[0][1]*inertia[1][2]*inertia[2][0] +
- inertia[0][2]*inertia[1][0]*inertia[2][1] -
- inertia[0][0]*inertia[1][2]*inertia[2][1] -
- inertia[0][1]*inertia[1][0]*inertia[2][2] -
- inertia[2][0]*inertia[1][1]*inertia[0][2];
-
- if (determinant > 0.0)
- for (int i = 0; i < 3; i++)
- for (int j = 0; j < 3; j++)
- inverse[i][j] /= determinant;
-
- w[0] = inverse[0][0]*angmom[0] + inverse[0][1]*angmom[1] +
- inverse[0][2]*angmom[2];
- w[1] = inverse[1][0]*angmom[0] + inverse[1][1]*angmom[1] +
- inverse[1][2]*angmom[2];
- w[2] = inverse[2][0]*angmom[0] + inverse[2][1]*angmom[1] +
- inverse[2][2]*angmom[2];
+ ex[0] = evectors[0][0];
+ ex[1] = evectors[1][0];
+ ex[2] = evectors[2][0];
+ ey[0] = evectors[0][1];
+ ey[1] = evectors[1][1];
+ ey[2] = evectors[2][1];
+ ez[0] = evectors[0][2];
+ ez[1] = evectors[1][2];
+ ez[2] = evectors[2][2];
+
+ // enforce 3 evectors as a right-handed coordinate system
+ // flip 3rd vector if needed
+
+ MathExtra::cross3(ex,ey,cross);
+ if (MathExtra::dot3(cross,ez) < 0.0) MathExtra::negate3(ez);
+
+ // if any principal moment < scaled EPSILON, set to 0.0
+
+ double max;
+ max = MAX(idiag[0],idiag[1]);
+ max = MAX(max,idiag[2]);
+
+ if (idiag[0] < EPSILON*max) idiag[0] = 0.0;
+ if (idiag[1] < EPSILON*max) idiag[1] = 0.0;
+ if (idiag[2] < EPSILON*max) idiag[2] = 0.0;
+
+ // calculate omega using diagonalized inertia matrix
+
+ MathExtra::angmom_to_omega(angmom,ex,ey,ez,idiag,w);
}
diff --git a/src/version.h b/src/version.h
index 9725014aa4..006495e9f1 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1 +1 @@
-#define LAMMPS_VERSION "27 Aug 2016"
+#define LAMMPS_VERSION "7 Sep 2016"