Commit 047934e2 authored by Rafal P. Wiewiora's avatar Rafal P. Wiewiora
Browse files

Merge remote-tracking branch 'upstream/master'

parents ce3a5dc0 d12c9bd1
......@@ -39,13 +39,6 @@ using namespace OpenMM;
--------------------------------------------------------------------------------------- */
ReferenceLJCoulomb14::ReferenceLJCoulomb14() {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceLJCoulomb14::ReferenceLJCoulomb14";
// ---------------------------------------------------------------------------------------
}
/**---------------------------------------------------------------------------------------
......@@ -55,13 +48,6 @@ ReferenceLJCoulomb14::ReferenceLJCoulomb14() {
--------------------------------------------------------------------------------------- */
ReferenceLJCoulomb14::~ReferenceLJCoulomb14() {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceLJCoulomb14::~ReferenceLJCoulomb14";
// ---------------------------------------------------------------------------------------
}
/**---------------------------------------------------------------------------------------
......@@ -79,33 +65,10 @@ ReferenceLJCoulomb14::~ReferenceLJCoulomb14() {
--------------------------------------------------------------------------------------- */
void ReferenceLJCoulomb14::calculateBondIxn(int* atomIndices, vector<RealVec>& atomCoordinates,
RealOpenMM* parameters, vector<RealVec>& forces,
RealOpenMM* totalEnergy, double* energyParamDerivs) {
static const std::string methodName = "\nReferenceLJCoulomb14::calculateBondIxn";
// constants -- reduce Visual Studio warnings regarding conversions between float & double
static const RealOpenMM zero = 0.0;
static const RealOpenMM one = 1.0;
static const RealOpenMM two = 2.0;
static const RealOpenMM three = 3.0;
static const RealOpenMM six = 6.0;
static const RealOpenMM twelve = 12.0;
static const RealOpenMM oneM = -1.0;
static const int threeI = 3;
// number of parameters
static const int numberOfParameters = 3;
static const int LastAtomIndex = 2;
RealOpenMM deltaR[2][ReferenceForce::LastDeltaRIndex];
// ---------------------------------------------------------------------------------------
void ReferenceLJCoulomb14::calculateBondIxn(int* atomIndices, vector<Vec3>& atomCoordinates,
double* parameters, vector<Vec3>& forces,
double* totalEnergy, double* energyParamDerivs) {
double deltaR[2][ReferenceForce::LastDeltaRIndex];
// get deltaR, R2, and R between 2 atoms
......@@ -113,20 +76,19 @@ void ReferenceLJCoulomb14::calculateBondIxn(int* atomIndices, vector<RealVec>& a
int atomBIndex = atomIndices[1];
ReferenceForce::getDeltaR(atomCoordinates[atomBIndex], atomCoordinates[atomAIndex], deltaR[0]);
RealOpenMM r2 = deltaR[0][ReferenceForce::R2Index];
RealOpenMM inverseR = one/(deltaR[0][ReferenceForce::RIndex]);
RealOpenMM sig2 = inverseR*parameters[0];
sig2 *= sig2;
RealOpenMM sig6 = sig2*sig2*sig2;
double inverseR = 1.0/(deltaR[0][ReferenceForce::RIndex]);
double sig2 = inverseR*parameters[0];
sig2 *= sig2;
double sig6 = sig2*sig2*sig2;
RealOpenMM dEdR = parameters[1]*(twelve*sig6 - six)*sig6;
dEdR += (RealOpenMM) (ONE_4PI_EPS0*parameters[2]*inverseR);
dEdR *= inverseR*inverseR;
double dEdR = parameters[1]*(12.0*sig6 - 6.0)*sig6;
dEdR += ONE_4PI_EPS0*parameters[2]*inverseR;
dEdR *= inverseR*inverseR;
// accumulate forces
for (int ii = 0; ii < 3; ii++) {
RealOpenMM force = dEdR*deltaR[0][ii];
double force = dEdR*deltaR[0][ii];
forces[atomAIndex][ii] += force;
forces[atomBIndex][ii] -= force;
}
......@@ -134,5 +96,5 @@ void ReferenceLJCoulomb14::calculateBondIxn(int* atomIndices, vector<RealVec>& a
// accumulate energies
if (totalEnergy != NULL)
*totalEnergy += parameters[1]*(sig6 - one)*sig6 + (ONE_4PI_EPS0*parameters[2]*inverseR);
*totalEnergy += parameters[1]*(sig6 - 1.0)*sig6 + (ONE_4PI_EPS0*parameters[2]*inverseR);
}
......@@ -26,6 +26,7 @@
#include <sstream>
#include <complex>
#include <algorithm>
#include <iostream>
#include "SimTKOpenMMUtilities.h"
#include "ReferenceLJCoulombIxn.h"
......@@ -47,14 +48,7 @@ using namespace OpenMM;
--------------------------------------------------------------------------------------- */
ReferenceLJCoulombIxn::ReferenceLJCoulombIxn() : cutoff(false), useSwitch(false), periodic(false), ewald(false), pme(false) {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceLJCoulombIxn::ReferenceLJCoulombIxn";
// ---------------------------------------------------------------------------------------
ReferenceLJCoulombIxn::ReferenceLJCoulombIxn() : cutoff(false), useSwitch(false), periodic(false), ewald(false), pme(false), ljpme(false) {
}
/**---------------------------------------------------------------------------------------
......@@ -64,16 +58,9 @@ ReferenceLJCoulombIxn::ReferenceLJCoulombIxn() : cutoff(false), useSwitch(false)
--------------------------------------------------------------------------------------- */
ReferenceLJCoulombIxn::~ReferenceLJCoulombIxn() {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceLJCoulombIxn::~ReferenceLJCoulombIxn";
// ---------------------------------------------------------------------------------------
}
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
Set the force to use a cutoff.
......@@ -83,14 +70,14 @@ ReferenceLJCoulombIxn::~ReferenceLJCoulombIxn() {
--------------------------------------------------------------------------------------- */
void ReferenceLJCoulombIxn::setUseCutoff(RealOpenMM distance, const OpenMM::NeighborList& neighbors, RealOpenMM solventDielectric) {
void ReferenceLJCoulombIxn::setUseCutoff(double distance, const OpenMM::NeighborList& neighbors, double solventDielectric) {
cutoff = true;
cutoffDistance = distance;
neighborList = &neighbors;
krf = pow(cutoffDistance, -3.0)*(solventDielectric-1.0)/(2.0*solventDielectric+1.0);
crf = (1.0/cutoffDistance)*(3.0*solventDielectric)/(2.0*solventDielectric+1.0);
}
}
/**---------------------------------------------------------------------------------------
......@@ -100,12 +87,12 @@ ReferenceLJCoulombIxn::~ReferenceLJCoulombIxn() {
--------------------------------------------------------------------------------------- */
void ReferenceLJCoulombIxn::setUseSwitchingFunction(RealOpenMM distance) {
void ReferenceLJCoulombIxn::setUseSwitchingFunction(double distance) {
useSwitch = true;
switchingDistance = distance;
}
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
Set the force to use periodic boundary conditions. This requires that a cutoff has
also been set, and the smallest side of the periodic box is at least twice the cutoff
......@@ -115,7 +102,7 @@ void ReferenceLJCoulombIxn::setUseSwitchingFunction(RealOpenMM distance) {
--------------------------------------------------------------------------------------- */
void ReferenceLJCoulombIxn::setPeriodic(OpenMM::RealVec* vectors) {
void ReferenceLJCoulombIxn::setPeriodic(OpenMM::Vec3* vectors) {
assert(cutoff);
assert(vectors[0][0] >= 2.0*cutoffDistance);
......@@ -125,9 +112,9 @@ void ReferenceLJCoulombIxn::setUseSwitchingFunction(RealOpenMM distance) {
periodicBoxVectors[0] = vectors[0];
periodicBoxVectors[1] = vectors[1];
periodicBoxVectors[2] = vectors[2];
}
}
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
Set the force to use Ewald summation.
......@@ -138,15 +125,15 @@ void ReferenceLJCoulombIxn::setUseSwitchingFunction(RealOpenMM distance) {
--------------------------------------------------------------------------------------- */
void ReferenceLJCoulombIxn::setUseEwald(RealOpenMM alpha, int kmaxx, int kmaxy, int kmaxz) {
alphaEwald = alpha;
numRx = kmaxx;
numRy = kmaxy;
numRz = kmaxz;
ewald = true;
}
void ReferenceLJCoulombIxn::setUseEwald(double alpha, int kmaxx, int kmaxy, int kmaxz) {
alphaEwald = alpha;
numRx = kmaxx;
numRy = kmaxy;
numRz = kmaxz;
ewald = true;
}
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
Set the force to use Particle-Mesh Ewald (PME) summation.
......@@ -155,13 +142,30 @@ void ReferenceLJCoulombIxn::setUseSwitchingFunction(RealOpenMM distance) {
--------------------------------------------------------------------------------------- */
void ReferenceLJCoulombIxn::setUsePME(RealOpenMM alpha, int meshSize[3]) {
alphaEwald = alpha;
meshDim[0] = meshSize[0];
meshDim[1] = meshSize[1];
meshDim[2] = meshSize[2];
pme = true;
}
void ReferenceLJCoulombIxn::setUsePME(double alpha, int meshSize[3]) {
alphaEwald = alpha;
meshDim[0] = meshSize[0];
meshDim[1] = meshSize[1];
meshDim[2] = meshSize[2];
pme = true;
}
/**---------------------------------------------------------------------------------------
Set the force to use Particle-Mesh Ewald (PME) summation for dispersion terms.
@param alpha the dispersion Ewald separation parameter
@param gridSize the dimensions of the dispersion mesh
--------------------------------------------------------------------------------------- */
void ReferenceLJCoulombIxn::setUseLJPME(double alpha, int meshSize[3]) {
alphaDispersionEwald = alpha;
dispersionMeshDim[0] = meshSize[0];
dispersionMeshDim[1] = meshSize[1];
dispersionMeshDim[2] = meshSize[2];
ljpme = true;
}
/**---------------------------------------------------------------------------------------
......@@ -181,36 +185,44 @@ void ReferenceLJCoulombIxn::setUseSwitchingFunction(RealOpenMM distance) {
--------------------------------------------------------------------------------------- */
void ReferenceLJCoulombIxn::calculateEwaldIxn(int numberOfAtoms, vector<RealVec>& atomCoordinates,
RealOpenMM** atomParameters, vector<set<int> >& exclusions,
RealOpenMM* fixedParameters, vector<RealVec>& forces,
RealOpenMM* energyByAtom, RealOpenMM* totalEnergy, bool includeDirect, bool includeReciprocal) const {
typedef std::complex<RealOpenMM> d_complex;
void ReferenceLJCoulombIxn::calculateEwaldIxn(int numberOfAtoms, vector<Vec3>& atomCoordinates,
double** atomParameters, vector<set<int> >& exclusions,
double* fixedParameters, vector<Vec3>& forces,
double* energyByAtom, double* totalEnergy, bool includeDirect, bool includeReciprocal) const {
typedef std::complex<double> d_complex;
static const RealOpenMM epsilon = 1.0;
static const RealOpenMM one = 1.0;
static const RealOpenMM six = 6.0;
static const RealOpenMM twelve = 12.0;
static const double epsilon = 1.0;
int kmax = (ewald ? std::max(numRx, std::max(numRy,numRz)) : 0);
RealOpenMM factorEwald = -1 / (4*alphaEwald*alphaEwald);
RealOpenMM SQRT_PI = sqrt(PI_M);
RealOpenMM TWO_PI = 2.0 * PI_M;
RealOpenMM recipCoeff = (RealOpenMM)(ONE_4PI_EPS0*4*PI_M/(periodicBoxVectors[0][0] * periodicBoxVectors[1][1] * periodicBoxVectors[2][2]) /epsilon);
RealOpenMM totalSelfEwaldEnergy = 0.0;
RealOpenMM realSpaceEwaldEnergy = 0.0;
RealOpenMM recipEnergy = 0.0;
RealOpenMM totalRecipEnergy = 0.0;
RealOpenMM vdwEnergy = 0.0;
// **************************************************************************************
// SELF ENERGY
// **************************************************************************************
double factorEwald = -1 / (4*alphaEwald*alphaEwald);
double SQRT_PI = sqrt(PI_M);
double TWO_PI = 2.0 * PI_M;
double recipCoeff = ONE_4PI_EPS0*4*PI_M/(periodicBoxVectors[0][0] * periodicBoxVectors[1][1] * periodicBoxVectors[2][2]) /epsilon;
double totalSelfEwaldEnergy = 0.0;
double realSpaceEwaldEnergy = 0.0;
double recipEnergy = 0.0;
double recipDispersionEnergy = 0.0;
double totalRecipEnergy = 0.0;
double vdwEnergy = 0.0;
// A couple of sanity checks for
if(ljpme && useSwitch)
throw OpenMMException("Switching cannot be used with LJPME");
if(ljpme && !pme)
throw OpenMMException("LJPME has been set, without PME being set");
// **************************************************************************************
// SELF ENERGY
// **************************************************************************************
if (includeReciprocal) {
for (int atomID = 0; atomID < numberOfAtoms; atomID++) {
RealOpenMM selfEwaldEnergy = (RealOpenMM) (ONE_4PI_EPS0*atomParameters[atomID][QIndex]*atomParameters[atomID][QIndex] * alphaEwald/SQRT_PI);
double selfEwaldEnergy = ONE_4PI_EPS0*atomParameters[atomID][QIndex]*atomParameters[atomID][QIndex] * alphaEwald/SQRT_PI;
if(ljpme) {
// Dispersion self term
selfEwaldEnergy -= pow(alphaDispersionEwald, 6.0) * 64.0*pow(atomParameters[atomID][SigIndex], 6.0) * pow(atomParameters[atomID][EpsIndex], 2.0) / 12.0;
}
totalSelfEwaldEnergy -= selfEwaldEnergy;
if (energyByAtom) {
energyByAtom[atomID] -= selfEwaldEnergy;
......@@ -222,194 +234,249 @@ void ReferenceLJCoulombIxn::calculateEwaldIxn(int numberOfAtoms, vector<RealVec>
*totalEnergy += totalSelfEwaldEnergy;
}
// **************************************************************************************
// RECIPROCAL SPACE EWALD ENERGY AND FORCES
// **************************************************************************************
// **************************************************************************************
// RECIPROCAL SPACE EWALD ENERGY AND FORCES
// **************************************************************************************
// PME
if (pme && includeReciprocal) {
pme_t pmedata; /* abstract handle for PME data */
if (pme && includeReciprocal) {
pme_t pmedata; /* abstract handle for PME data */
pme_init(&pmedata,alphaEwald,numberOfAtoms,meshDim,5,1);
pme_init(&pmedata,alphaEwald,numberOfAtoms,meshDim,5,1);
vector<RealOpenMM> charges(numberOfAtoms);
for (int i = 0; i < numberOfAtoms; i++)
charges[i] = atomParameters[i][QIndex];
pme_exec(pmedata,atomCoordinates,forces,charges,periodicBoxVectors,&recipEnergy);
vector<double> charges(numberOfAtoms);
for (int i = 0; i < numberOfAtoms; i++)
charges[i] = atomParameters[i][QIndex];
pme_exec(pmedata,atomCoordinates,forces,charges,periodicBoxVectors,&recipEnergy);
if (totalEnergy)
*totalEnergy += recipEnergy;
if (totalEnergy)
*totalEnergy += recipEnergy;
if (energyByAtom)
for (int n = 0; n < numberOfAtoms; n++)
energyByAtom[n] += recipEnergy;
if (energyByAtom)
for (int n = 0; n < numberOfAtoms; n++)
energyByAtom[n] += recipEnergy;
pme_destroy(pmedata);
}
if (ljpme) {
// Dispersion reciprocal space terms
pme_init(&pmedata,alphaDispersionEwald,numberOfAtoms,dispersionMeshDim,5,1);
std::vector<Vec3> dpmeforces;
for (int i = 0; i < numberOfAtoms; i++){
charges[i] = 8.0*pow(atomParameters[i][SigIndex], 3.0) * atomParameters[i][EpsIndex];
dpmeforces.push_back(Vec3());
}
pme_exec_dpme(pmedata,atomCoordinates,dpmeforces,charges,periodicBoxVectors,&recipDispersionEnergy);
for (int i = 0; i < numberOfAtoms; i++){
forces[i][0] -= 2.0*dpmeforces[i][0];
forces[i][1] -= 2.0*dpmeforces[i][1];
forces[i][2] -= 2.0*dpmeforces[i][2];
}
if (totalEnergy)
*totalEnergy += recipDispersionEnergy;
if (energyByAtom)
for (int n = 0; n < numberOfAtoms; n++)
energyByAtom[n] += recipDispersionEnergy;
pme_destroy(pmedata);
}
}
// Ewald method
else if (ewald && includeReciprocal) {
else if (ewald && includeReciprocal) {
// setup reciprocal box
// setup reciprocal box
RealOpenMM recipBoxSize[3] = { TWO_PI / periodicBoxVectors[0][0], TWO_PI / periodicBoxVectors[1][1], TWO_PI / periodicBoxVectors[2][2]};
double recipBoxSize[3] = { TWO_PI / periodicBoxVectors[0][0], TWO_PI / periodicBoxVectors[1][1], TWO_PI / periodicBoxVectors[2][2]};
// setup K-vectors
// setup K-vectors
#define EIR(x, y, z) eir[(x)*numberOfAtoms*3+(y)*3+z]
vector<d_complex> eir(kmax*numberOfAtoms*3);
vector<d_complex> tab_xy(numberOfAtoms);
vector<d_complex> tab_qxyz(numberOfAtoms);
#define EIR(x, y, z) eir[(x)*numberOfAtoms*3+(y)*3+z]
vector<d_complex> eir(kmax*numberOfAtoms*3);
vector<d_complex> tab_xy(numberOfAtoms);
vector<d_complex> tab_qxyz(numberOfAtoms);
if (kmax < 1)
throw OpenMMException("kmax for Ewald summation < 1");
if (kmax < 1)
throw OpenMMException("kmax for Ewald summation < 1");
for (int i = 0; (i < numberOfAtoms); i++) {
for (int m = 0; (m < 3); m++)
EIR(0, i, m) = d_complex(1,0);
for (int i = 0; (i < numberOfAtoms); i++) {
for (int m = 0; (m < 3); m++)
EIR(0, i, m) = d_complex(1,0);
for (int m=0; (m<3); m++)
EIR(1, i, m) = d_complex(cos(atomCoordinates[i][m]*recipBoxSize[m]),
sin(atomCoordinates[i][m]*recipBoxSize[m]));
for (int m=0; (m<3); m++)
EIR(1, i, m) = d_complex(cos(atomCoordinates[i][m]*recipBoxSize[m]),
sin(atomCoordinates[i][m]*recipBoxSize[m]));
for (int j=2; (j<kmax); j++)
for (int m=0; (m<3); m++)
EIR(j, i, m) = EIR(j-1, i, m) * EIR(1, i, m);
}
for (int j=2; (j<kmax); j++)
for (int m=0; (m<3); m++)
EIR(j, i, m) = EIR(j-1, i, m) * EIR(1, i, m);
}
// calculate reciprocal space energy and forces
// calculate reciprocal space energy and forces
int lowry = 0;
int lowrz = 1;
int lowry = 0;
int lowrz = 1;
for (int rx = 0; rx < numRx; rx++) {
for (int rx = 0; rx < numRx; rx++) {
RealOpenMM kx = rx * recipBoxSize[0];
double kx = rx * recipBoxSize[0];
for (int ry = lowry; ry < numRy; ry++) {
for (int ry = lowry; ry < numRy; ry++) {
RealOpenMM ky = ry * recipBoxSize[1];
double ky = ry * recipBoxSize[1];
if (ry >= 0) {
for (int n = 0; n < numberOfAtoms; n++)
tab_xy[n] = EIR(rx, n, 0) * EIR(ry, n, 1);
}
if (ry >= 0) {
for (int n = 0; n < numberOfAtoms; n++)
tab_xy[n] = EIR(rx, n, 0) * EIR(ry, n, 1);
}
else {
for (int n = 0; n < numberOfAtoms; n++)
tab_xy[n]= EIR(rx, n, 0) * conj (EIR(-ry, n, 1));
}
else {
for (int n = 0; n < numberOfAtoms; n++)
tab_xy[n]= EIR(rx, n, 0) * conj (EIR(-ry, n, 1));
}
for (int rz = lowrz; rz < numRz; rz++) {
for (int rz = lowrz; rz < numRz; rz++) {
if (rz >= 0) {
for (int n = 0; n < numberOfAtoms; n++)
tab_qxyz[n] = atomParameters[n][QIndex] * (tab_xy[n] * EIR(rz, n, 2));
}
if (rz >= 0) {
for (int n = 0; n < numberOfAtoms; n++)
tab_qxyz[n] = atomParameters[n][QIndex] * (tab_xy[n] * EIR(rz, n, 2));
}
else {
for (int n = 0; n < numberOfAtoms; n++)
tab_qxyz[n] = atomParameters[n][QIndex] * (tab_xy[n] * conj(EIR(-rz, n, 2)));
}
else {
for (int n = 0; n < numberOfAtoms; n++)
tab_qxyz[n] = atomParameters[n][QIndex] * (tab_xy[n] * conj(EIR(-rz, n, 2)));
}
RealOpenMM cs = 0.0f;
RealOpenMM ss = 0.0f;
double cs = 0.0f;
double ss = 0.0f;
for (int n = 0; n < numberOfAtoms; n++) {
cs += tab_qxyz[n].real();
ss += tab_qxyz[n].imag();
}
for (int n = 0; n < numberOfAtoms; n++) {
cs += tab_qxyz[n].real();
ss += tab_qxyz[n].imag();
}
RealOpenMM kz = rz * recipBoxSize[2];
RealOpenMM k2 = kx * kx + ky * ky + kz * kz;
RealOpenMM ak = exp(k2*factorEwald) / k2;
double kz = rz * recipBoxSize[2];
double k2 = kx * kx + ky * ky + kz * kz;
double ak = exp(k2*factorEwald) / k2;
for (int n = 0; n < numberOfAtoms; n++) {
RealOpenMM force = ak * (cs * tab_qxyz[n].imag() - ss * tab_qxyz[n].real());
forces[n][0] += 2 * recipCoeff * force * kx ;
forces[n][1] += 2 * recipCoeff * force * ky ;
forces[n][2] += 2 * recipCoeff * force * kz ;
}
for (int n = 0; n < numberOfAtoms; n++) {
double force = ak * (cs * tab_qxyz[n].imag() - ss * tab_qxyz[n].real());
forces[n][0] += 2 * recipCoeff * force * kx ;
forces[n][1] += 2 * recipCoeff * force * ky ;
forces[n][2] += 2 * recipCoeff * force * kz ;
}
recipEnergy = recipCoeff * ak * (cs * cs + ss * ss);
totalRecipEnergy += recipEnergy;
recipEnergy = recipCoeff * ak * (cs * cs + ss * ss);
totalRecipEnergy += recipEnergy;
if (totalEnergy)
*totalEnergy += recipEnergy;
if (totalEnergy)
*totalEnergy += recipEnergy;
if (energyByAtom)
for (int n = 0; n < numberOfAtoms; n++)
energyByAtom[n] += recipEnergy;
if (energyByAtom)
for (int n = 0; n < numberOfAtoms; n++)
energyByAtom[n] += recipEnergy;
lowrz = 1 - numRz;
lowrz = 1 - numRz;
}
lowry = 1 - numRy;
}
}
lowry = 1 - numRy;
}
}
}
// **************************************************************************************
// SHORT-RANGE ENERGY AND FORCES
// **************************************************************************************
// **************************************************************************************
// SHORT-RANGE ENERGY AND FORCES
// **************************************************************************************
if (!includeDirect)
return;
RealOpenMM totalVdwEnergy = 0.0f;
RealOpenMM totalRealSpaceEwaldEnergy = 0.0f;
double totalVdwEnergy = 0.0f;
double totalRealSpaceEwaldEnergy = 0.0f;
for (int i = 0; i < (int) neighborList->size(); i++) {
OpenMM::AtomPair pair = (*neighborList)[i];
int ii = pair.first;
int jj = pair.second;
RealOpenMM deltaR[2][ReferenceForce::LastDeltaRIndex];
ReferenceForce::getDeltaRPeriodic(atomCoordinates[jj], atomCoordinates[ii], periodicBoxVectors, deltaR[0]);
RealOpenMM r = deltaR[0][ReferenceForce::RIndex];
RealOpenMM inverseR = one/(deltaR[0][ReferenceForce::RIndex]);
RealOpenMM switchValue = 1, switchDeriv = 0;
if (useSwitch && r > switchingDistance) {
RealOpenMM t = (r-switchingDistance)/(cutoffDistance-switchingDistance);
switchValue = 1+t*t*t*(-10+t*(15-t*6));
switchDeriv = t*t*(-30+t*(60-t*30))/(cutoffDistance-switchingDistance);
}
RealOpenMM alphaR = alphaEwald * r;
RealOpenMM dEdR = (RealOpenMM) (ONE_4PI_EPS0 * atomParameters[ii][QIndex] * atomParameters[jj][QIndex] * inverseR * inverseR * inverseR);
dEdR = (RealOpenMM) (dEdR * (erfc(alphaR) + 2 * alphaR * exp (- alphaR * alphaR) / SQRT_PI));
RealOpenMM sig = atomParameters[ii][SigIndex] + atomParameters[jj][SigIndex];
RealOpenMM sig2 = inverseR*sig;
sig2 *= sig2;
RealOpenMM sig6 = sig2*sig2*sig2;
RealOpenMM eps = atomParameters[ii][EpsIndex]*atomParameters[jj][EpsIndex];
dEdR += switchValue*eps*(twelve*sig6 - six)*sig6*inverseR*inverseR;
vdwEnergy = eps*(sig6-one)*sig6;
if (useSwitch) {
dEdR -= vdwEnergy*switchDeriv*inverseR;
vdwEnergy *= switchValue;
}
// accumulate forces
for (int kk = 0; kk < 3; kk++) {
RealOpenMM force = dEdR*deltaR[0][kk];
forces[ii][kk] += force;
forces[jj][kk] -= force;
}
// accumulate energies
realSpaceEwaldEnergy = (RealOpenMM) (ONE_4PI_EPS0*atomParameters[ii][QIndex]*atomParameters[jj][QIndex]*inverseR*erfc(alphaR));
totalVdwEnergy += vdwEnergy;
totalRealSpaceEwaldEnergy += realSpaceEwaldEnergy;
OpenMM::AtomPair pair = (*neighborList)[i];
int ii = pair.first;
int jj = pair.second;
double deltaR[2][ReferenceForce::LastDeltaRIndex];
ReferenceForce::getDeltaRPeriodic(atomCoordinates[jj], atomCoordinates[ii], periodicBoxVectors, deltaR[0]);
double r = deltaR[0][ReferenceForce::RIndex];
double inverseR = 1.0/(deltaR[0][ReferenceForce::RIndex]);
double switchValue = 1, switchDeriv = 0;
if (useSwitch && r > switchingDistance) {
double t = (r-switchingDistance)/(cutoffDistance-switchingDistance);
switchValue = 1+t*t*t*(-10+t*(15-t*6));
switchDeriv = t*t*(-30+t*(60-t*30))/(cutoffDistance-switchingDistance);
}
double alphaR = alphaEwald * r;
double dEdR = ONE_4PI_EPS0 * atomParameters[ii][QIndex] * atomParameters[jj][QIndex] * inverseR * inverseR * inverseR;
dEdR = dEdR * (erfc(alphaR) + 2 * alphaR * exp (- alphaR * alphaR) / SQRT_PI);
double sig = atomParameters[ii][SigIndex] + atomParameters[jj][SigIndex];
double sig2 = inverseR*sig;
sig2 *= sig2;
double sig6 = sig2*sig2*sig2;
double eps = atomParameters[ii][EpsIndex]*atomParameters[jj][EpsIndex];
dEdR += switchValue*eps*(12.0*sig6 - 6.0)*sig6*inverseR*inverseR;
vdwEnergy = eps*(sig6-1.0)*sig6;
if (ljpme) {
double dalphaR = alphaDispersionEwald * r;
double dar2 = dalphaR*dalphaR;
double dar4 = dar2*dar2;
double dar6 = dar4*dar2;
double inverseR2 = inverseR*inverseR;
double c6i = 8.0*pow(atomParameters[ii][SigIndex], 3.0) * atomParameters[ii][EpsIndex];
double c6j = 8.0*pow(atomParameters[jj][SigIndex], 3.0) * atomParameters[jj][EpsIndex];
// For the energies and forces, we first add the regular Lorentz−Berthelot terms. The C12 term is treated as usual
// but we then subtract out (remembering that the C6 term is negative) the multiplicative C6 term that has been
// computed in real space. Finally, we add a potential shift term to account for the difference between the LB
// and multiplicative functional forms at the cutoff.
double emult = c6i*c6j*inverseR2*inverseR2*inverseR2*(1.0 - EXP(-dar2) * (1.0 + dar2 + 0.5*dar4));
dEdR += 6.0*c6i*c6j*inverseR2*inverseR2*inverseR2*inverseR2*(1.0 - EXP(-dar2) * (1.0 + dar2 + 0.5*dar4 + dar6/6.0));
double inverseCut2 = 1.0/(cutoffDistance*cutoffDistance);
double inverseCut6 = inverseCut2*inverseCut2*inverseCut2;
sig2 = atomParameters[ii][SigIndex] + atomParameters[jj][SigIndex];
sig2 *= sig2;
sig6 = sig2*sig2*sig2;
// The additive part of the potential shift
double potentialshift = eps*(1.0-sig6*inverseCut6)*sig6*inverseCut6;
dalphaR = alphaDispersionEwald * cutoffDistance;
dar2 = dalphaR*dalphaR;
dar4 = dar2*dar2;
// The multiplicative part of the potential shift
potentialshift -= c6i*c6j*inverseCut6*(1.0 - EXP(-dar2) * (1.0 + dar2 + 0.5*dar4));
vdwEnergy += emult + potentialshift;
}
if (useSwitch) {
dEdR -= vdwEnergy*switchDeriv*inverseR;
vdwEnergy *= switchValue;
}
// accumulate forces
for (int kk = 0; kk < 3; kk++) {
double force = dEdR*deltaR[0][kk];
forces[ii][kk] += force;
forces[jj][kk] -= force;
}
// accumulate energies
realSpaceEwaldEnergy = ONE_4PI_EPS0*atomParameters[ii][QIndex]*atomParameters[jj][QIndex]*inverseR*erfc(alphaR);
totalVdwEnergy += vdwEnergy;
totalRealSpaceEwaldEnergy += realSpaceEwaldEnergy;
if (energyByAtom) {
energyByAtom[ii] += realSpaceEwaldEnergy + vdwEnergy;
energyByAtom[jj] += realSpaceEwaldEnergy + vdwEnergy;
energyByAtom[ii] += realSpaceEwaldEnergy + vdwEnergy;
energyByAtom[jj] += realSpaceEwaldEnergy + vdwEnergy;
}
}
......@@ -419,44 +486,62 @@ void ReferenceLJCoulombIxn::calculateEwaldIxn(int numberOfAtoms, vector<RealVec>
// Now subtract off the exclusions, since they were implicitly included in the reciprocal space sum.
RealOpenMM totalExclusionEnergy = 0.0f;
double totalExclusionEnergy = 0.0f;
const double TWO_OVER_SQRT_PI = 2/sqrt(PI_M);
for (int i = 0; i < numberOfAtoms; i++)
for (set<int>::const_iterator iter = exclusions[i].begin(); iter != exclusions[i].end(); ++iter) {
if (*iter > i) {
int ii = i;
int jj = *iter;
RealOpenMM deltaR[2][ReferenceForce::LastDeltaRIndex];
ReferenceForce::getDeltaR(atomCoordinates[jj], atomCoordinates[ii], deltaR[0]);
RealOpenMM r = deltaR[0][ReferenceForce::RIndex];
RealOpenMM inverseR = one/(deltaR[0][ReferenceForce::RIndex]);
RealOpenMM alphaR = alphaEwald * r;
if (erf(alphaR) > 1e-6) {
RealOpenMM dEdR = (RealOpenMM) (ONE_4PI_EPS0 * atomParameters[ii][QIndex] * atomParameters[jj][QIndex] * inverseR * inverseR * inverseR);
dEdR = (RealOpenMM) (dEdR * (erf(alphaR) - 2 * alphaR * exp (- alphaR * alphaR) / SQRT_PI));
// accumulate forces
for (int kk = 0; kk < 3; kk++) {
RealOpenMM force = dEdR*deltaR[0][kk];
forces[ii][kk] -= force;
forces[jj][kk] += force;
}
// accumulate energies
realSpaceEwaldEnergy = (RealOpenMM) (ONE_4PI_EPS0*atomParameters[ii][QIndex]*atomParameters[jj][QIndex]*inverseR*erf(alphaR));
}
else {
realSpaceEwaldEnergy = (RealOpenMM) (alphaEwald*TWO_OVER_SQRT_PI*ONE_4PI_EPS0*atomParameters[ii][QIndex]*atomParameters[jj][QIndex]);
}
totalExclusionEnergy += realSpaceEwaldEnergy;
if (energyByAtom) {
energyByAtom[ii] -= realSpaceEwaldEnergy;
energyByAtom[jj] -= realSpaceEwaldEnergy;
}
int ii = i;
int jj = *iter;
double deltaR[2][ReferenceForce::LastDeltaRIndex];
ReferenceForce::getDeltaR(atomCoordinates[jj], atomCoordinates[ii], deltaR[0]);
double r = deltaR[0][ReferenceForce::RIndex];
double inverseR = 1.0/(deltaR[0][ReferenceForce::RIndex]);
double alphaR = alphaEwald * r;
if (erf(alphaR) > 1e-6) {
double dEdR = ONE_4PI_EPS0 * atomParameters[ii][QIndex] * atomParameters[jj][QIndex] * inverseR * inverseR * inverseR;
dEdR = dEdR * (erf(alphaR) - 2 * alphaR * exp (- alphaR * alphaR) / SQRT_PI);
// accumulate forces
for (int kk = 0; kk < 3; kk++) {
double force = dEdR*deltaR[0][kk];
forces[ii][kk] -= force;
forces[jj][kk] += force;
}
// accumulate energies
realSpaceEwaldEnergy = ONE_4PI_EPS0*atomParameters[ii][QIndex]*atomParameters[jj][QIndex]*inverseR*erf(alphaR);
}
else {
realSpaceEwaldEnergy = alphaEwald*TWO_OVER_SQRT_PI*ONE_4PI_EPS0*atomParameters[ii][QIndex]*atomParameters[jj][QIndex];
}
if(ljpme){
// Dispersion terms. Here we just back out the reciprocal space terms, and don't add any extra real space terms.
double dalphaR = alphaDispersionEwald * r;
double inverseR2 = inverseR*inverseR;
double dar2 = dalphaR*dalphaR;
double dar4 = dar2*dar2;
double dar6 = dar4*dar2;
double c6i = 8.0*pow(atomParameters[ii][SigIndex], 3.0) * atomParameters[ii][EpsIndex];
double c6j = 8.0*pow(atomParameters[jj][SigIndex], 3.0) * atomParameters[jj][EpsIndex];
realSpaceEwaldEnergy -= c6i*c6j*inverseR2*inverseR2*inverseR2*(1.0 - EXP(-dar2) * (1.0 + dar2 + 0.5*dar4));
double dEdR = -6.0*c6i*c6j*inverseR2*inverseR2*inverseR2*inverseR2*(1.0 - EXP(-dar2) * (1.0 + dar2 + 0.5*dar4 + dar6/6.0));
for (int kk = 0; kk < 3; kk++) {
double force = dEdR*deltaR[0][kk];
forces[ii][kk] -= force;
forces[jj][kk] += force;
}
}
totalExclusionEnergy += realSpaceEwaldEnergy;
if (energyByAtom) {
energyByAtom[ii] -= realSpaceEwaldEnergy;
energyByAtom[jj] -= realSpaceEwaldEnergy;
}
}
}
......@@ -483,36 +568,36 @@ void ReferenceLJCoulombIxn::calculateEwaldIxn(int numberOfAtoms, vector<RealVec>
--------------------------------------------------------------------------------------- */
void ReferenceLJCoulombIxn::calculatePairIxn(int numberOfAtoms, vector<RealVec>& atomCoordinates,
RealOpenMM** atomParameters, vector<set<int> >& exclusions,
RealOpenMM* fixedParameters, vector<RealVec>& forces,
RealOpenMM* energyByAtom, RealOpenMM* totalEnergy, bool includeDirect, bool includeReciprocal) const {
if (ewald || pme) {
calculateEwaldIxn(numberOfAtoms, atomCoordinates, atomParameters, exclusions, fixedParameters, forces, energyByAtom,
totalEnergy, includeDirect, includeReciprocal);
return;
}
if (!includeDirect)
return;
if (cutoff) {
for (int i = 0; i < (int) neighborList->size(); i++) {
OpenMM::AtomPair pair = (*neighborList)[i];
calculateOneIxn(pair.first, pair.second, atomCoordinates, atomParameters, forces, energyByAtom, totalEnergy);
}
}
else {
for (int ii = 0; ii < numberOfAtoms; ii++) {
// loop over atom pairs
for (int jj = ii+1; jj < numberOfAtoms; jj++)
if (exclusions[jj].find(ii) == exclusions[jj].end())
calculateOneIxn(ii, jj, atomCoordinates, atomParameters, forces, energyByAtom, totalEnergy);
}
}
void ReferenceLJCoulombIxn::calculatePairIxn(int numberOfAtoms, vector<Vec3>& atomCoordinates,
double** atomParameters, vector<set<int> >& exclusions,
double* fixedParameters, vector<Vec3>& forces,
double* energyByAtom, double* totalEnergy, bool includeDirect, bool includeReciprocal) const {
if (ewald || pme || ljpme) {
calculateEwaldIxn(numberOfAtoms, atomCoordinates, atomParameters, exclusions, fixedParameters, forces, energyByAtom,
totalEnergy, includeDirect, includeReciprocal);
return;
}
if (!includeDirect)
return;
if (cutoff) {
for (int i = 0; i < (int) neighborList->size(); i++) {
OpenMM::AtomPair pair = (*neighborList)[i];
calculateOneIxn(pair.first, pair.second, atomCoordinates, atomParameters, forces, energyByAtom, totalEnergy);
}
}
else {
for (int ii = 0; ii < numberOfAtoms; ii++) {
// loop over atom pairs
for (int jj = ii+1; jj < numberOfAtoms; jj++)
if (exclusions[jj].find(ii) == exclusions[jj].end())
calculateOneIxn(ii, jj, atomCoordinates, atomParameters, forces, energyByAtom, totalEnergy);
}
}
}
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
Calculate LJ Coulomb pair ixn between two atoms
......@@ -526,31 +611,10 @@ void ReferenceLJCoulombIxn::calculatePairIxn(int numberOfAtoms, vector<RealVec>&
--------------------------------------------------------------------------------------- */
void ReferenceLJCoulombIxn::calculateOneIxn(int ii, int jj, vector<RealVec>& atomCoordinates,
RealOpenMM** atomParameters, vector<RealVec>& forces,
RealOpenMM* energyByAtom, RealOpenMM* totalEnergy) const {
// ---------------------------------------------------------------------------------------
static const std::string methodName = "\nReferenceLJCoulombIxn::calculateOneIxn";
// ---------------------------------------------------------------------------------------
// constants -- reduce Visual Studio warnings regarding conversions between float & double
static const RealOpenMM zero = 0.0;
static const RealOpenMM one = 1.0;
static const RealOpenMM two = 2.0;
static const RealOpenMM three = 3.0;
static const RealOpenMM six = 6.0;
static const RealOpenMM twelve = 12.0;
static const RealOpenMM oneM = -1.0;
static const int threeI = 3;
static const int LastAtomIndex = 2;
RealOpenMM deltaR[2][ReferenceForce::LastDeltaRIndex];
void ReferenceLJCoulombIxn::calculateOneIxn(int ii, int jj, vector<Vec3>& atomCoordinates,
double** atomParameters, vector<Vec3>& forces,
double* energyByAtom, double* totalEnergy) const {
double deltaR[2][ReferenceForce::LastDeltaRIndex];
// get deltaR, R2, and R between 2 atoms
......@@ -559,54 +623,54 @@ void ReferenceLJCoulombIxn::calculateOneIxn(int ii, int jj, vector<RealVec>& ato
else
ReferenceForce::getDeltaR(atomCoordinates[jj], atomCoordinates[ii], deltaR[0]);
RealOpenMM r2 = deltaR[0][ReferenceForce::R2Index];
RealOpenMM inverseR = one/(deltaR[0][ReferenceForce::RIndex]);
RealOpenMM switchValue = 1, switchDeriv = 0;
double r2 = deltaR[0][ReferenceForce::R2Index];
double inverseR = 1.0/(deltaR[0][ReferenceForce::RIndex]);
double switchValue = 1, switchDeriv = 0;
if (useSwitch) {
RealOpenMM r = deltaR[0][ReferenceForce::RIndex];
double r = deltaR[0][ReferenceForce::RIndex];
if (r > switchingDistance) {
RealOpenMM t = (r-switchingDistance)/(cutoffDistance-switchingDistance);
double t = (r-switchingDistance)/(cutoffDistance-switchingDistance);
switchValue = 1+t*t*t*(-10+t*(15-t*6));
switchDeriv = t*t*(-30+t*(60-t*30))/(cutoffDistance-switchingDistance);
}
}
RealOpenMM sig = atomParameters[ii][SigIndex] + atomParameters[jj][SigIndex];
RealOpenMM sig2 = inverseR*sig;
sig2 *= sig2;
RealOpenMM sig6 = sig2*sig2*sig2;
double sig = atomParameters[ii][SigIndex] + atomParameters[jj][SigIndex];
double sig2 = inverseR*sig;
sig2 *= sig2;
double sig6 = sig2*sig2*sig2;
RealOpenMM eps = atomParameters[ii][EpsIndex]*atomParameters[jj][EpsIndex];
RealOpenMM dEdR = switchValue*eps*(twelve*sig6 - six)*sig6;
double eps = atomParameters[ii][EpsIndex]*atomParameters[jj][EpsIndex];
double dEdR = switchValue*eps*(12.0*sig6 - 6.0)*sig6;
if (cutoff)
dEdR += (RealOpenMM) (ONE_4PI_EPS0*atomParameters[ii][QIndex]*atomParameters[jj][QIndex]*(inverseR-2.0f*krf*r2));
dEdR += ONE_4PI_EPS0*atomParameters[ii][QIndex]*atomParameters[jj][QIndex]*(inverseR-2.0f*krf*r2);
else
dEdR += (RealOpenMM) (ONE_4PI_EPS0*atomParameters[ii][QIndex]*atomParameters[jj][QIndex]*inverseR);
dEdR += ONE_4PI_EPS0*atomParameters[ii][QIndex]*atomParameters[jj][QIndex]*inverseR;
dEdR *= inverseR*inverseR;
RealOpenMM energy = eps*(sig6-one)*sig6;
double energy = eps*(sig6-1.0)*sig6;
if (useSwitch) {
dEdR -= energy*switchDeriv*inverseR;
energy *= switchValue;
}
if (cutoff)
energy += (RealOpenMM) (ONE_4PI_EPS0*atomParameters[ii][QIndex]*atomParameters[jj][QIndex]*(inverseR+krf*r2-crf));
energy += ONE_4PI_EPS0*atomParameters[ii][QIndex]*atomParameters[jj][QIndex]*(inverseR+krf*r2-crf);
else
energy += (RealOpenMM) (ONE_4PI_EPS0*atomParameters[ii][QIndex]*atomParameters[jj][QIndex]*inverseR);
energy += ONE_4PI_EPS0*atomParameters[ii][QIndex]*atomParameters[jj][QIndex]*inverseR;
// accumulate forces
for (int kk = 0; kk < 3; kk++) {
RealOpenMM force = dEdR*deltaR[0][kk];
forces[ii][kk] += force;
forces[jj][kk] -= force;
double force = dEdR*deltaR[0][kk];
forces[ii][kk] += force;
forces[jj][kk] -= force;
}
// accumulate energies
if (totalEnergy)
*totalEnergy += energy;
*totalEnergy += energy;
if (energyByAtom) {
energyByAtom[ii] += energy;
energyByAtom[jj] += energy;
energyByAtom[ii] += energy;
energyByAtom[jj] += energy;
}
}
}
......@@ -44,13 +44,7 @@ using namespace OpenMM;
ReferenceLincsAlgorithm::ReferenceLincsAlgorithm(int numberOfConstraints,
int** atomIndices,
RealOpenMM* distance) {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceLincsAlgorithm::ReferenceLincsAlgorithm";
// ---------------------------------------------------------------------------------------
double* distance) {
_numberOfConstraints = numberOfConstraints;
_atomIndices = atomIndices;
......@@ -69,13 +63,6 @@ ReferenceLincsAlgorithm::ReferenceLincsAlgorithm(int numberOfConstraints,
--------------------------------------------------------------------------------------- */
int ReferenceLincsAlgorithm::getNumberOfConstraints() const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceLincsAlgorithm::getNumberOfConstraints";
// ---------------------------------------------------------------------------------------
return _numberOfConstraints;
}
......@@ -88,13 +75,6 @@ int ReferenceLincsAlgorithm::getNumberOfConstraints() const {
--------------------------------------------------------------------------------------- */
int ReferenceLincsAlgorithm::getNumTerms() const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceLincsAlgorithm::getNumTerms";
// ---------------------------------------------------------------------------------------
return _numTerms;
}
......@@ -105,13 +85,6 @@ int ReferenceLincsAlgorithm::getNumTerms() const {
--------------------------------------------------------------------------------------- */
void ReferenceLincsAlgorithm::setNumTerms(int terms) {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceLincsAlgorithm::setNumTerms";
// ---------------------------------------------------------------------------------------
_numTerms = terms;
}
......@@ -125,8 +98,7 @@ void ReferenceLincsAlgorithm::setNumTerms(int terms) {
--------------------------------------------------------------------------------------- */
void ReferenceLincsAlgorithm::initialize(int numberOfAtoms, vector<RealOpenMM>& inverseMasses) {
static const RealOpenMM one = 1.0;
void ReferenceLincsAlgorithm::initialize(int numberOfAtoms, vector<double>& inverseMasses) {
_hasInitialized = true;
vector<vector<int> > atomConstraints(numberOfAtoms);
for (int constraint = 0; constraint < _numberOfConstraints; constraint++) {
......@@ -145,7 +117,7 @@ void ReferenceLincsAlgorithm::initialize(int numberOfAtoms, vector<RealOpenMM>&
}
_sMatrix.resize(_numberOfConstraints);
for (int constraint = 0; constraint < _numberOfConstraints; constraint++)
_sMatrix[constraint] = one/SQRT(inverseMasses[_atomIndices[constraint][0]]+inverseMasses[_atomIndices[constraint][1]]);
_sMatrix[constraint] = 1.0/sqrt(inverseMasses[_atomIndices[constraint][0]]+inverseMasses[_atomIndices[constraint][1]]);
_couplingMatrix.resize(_numberOfConstraints);
for (int constraint = 0; constraint < _numberOfConstraints; constraint++)
_couplingMatrix[constraint].resize(_linkedConstraints[constraint].size());
......@@ -162,12 +134,11 @@ void ReferenceLincsAlgorithm::initialize(int numberOfAtoms, vector<RealOpenMM>&
--------------------------------------------------------------------------------------- */
void ReferenceLincsAlgorithm::solveMatrix() {
static const RealOpenMM zero = 0.0;
for (int iteration = 0; iteration < _numTerms; iteration++) {
vector<RealOpenMM>& rhs1 = (iteration%2 == 0 ? _rhs1 : _rhs2);
vector<RealOpenMM>& rhs2 = (iteration%2 == 0 ? _rhs2 : _rhs1);
vector<double>& rhs1 = (iteration%2 == 0 ? _rhs1 : _rhs2);
vector<double>& rhs2 = (iteration%2 == 0 ? _rhs2 : _rhs1);
for (int c1 = 0; c1 < _numberOfConstraints; c1++) {
rhs2[c1] = zero;
rhs2[c1] = 0.0;
for (int j = 0; j < (int)_linkedConstraints[c1].size(); j++) {
int c2 = _linkedConstraints[c1][j];
rhs2[c1] += _couplingMatrix[c1][j]*rhs1[c2];
......@@ -187,19 +158,19 @@ void ReferenceLincsAlgorithm::solveMatrix() {
--------------------------------------------------------------------------------------- */
void ReferenceLincsAlgorithm::updateAtomPositions(int numberOfAtoms, vector<RealVec>& atomCoordinates, vector<RealOpenMM>& inverseMasses) {
void ReferenceLincsAlgorithm::updateAtomPositions(int numberOfAtoms, vector<Vec3>& atomCoordinates, vector<double>& inverseMasses) {
for (int i = 0; i < _numberOfConstraints; i++) {
RealVec delta(_sMatrix[i]*_solution[i]*_constraintDir[i][0],
Vec3 delta(_sMatrix[i]*_solution[i]*_constraintDir[i][0],
_sMatrix[i]*_solution[i]*_constraintDir[i][1],
_sMatrix[i]*_solution[i]*_constraintDir[i][2]);
int atom1 = _atomIndices[i][0];
int atom2 = _atomIndices[i][1];
atomCoordinates[atom1][0] -= (RealOpenMM)(inverseMasses[atom1]*delta[0]);
atomCoordinates[atom1][1] -= (RealOpenMM)(inverseMasses[atom1]*delta[1]);
atomCoordinates[atom1][2] -= (RealOpenMM)(inverseMasses[atom1]*delta[2]);
atomCoordinates[atom2][0] += (RealOpenMM)(inverseMasses[atom2]*delta[0]);
atomCoordinates[atom2][1] += (RealOpenMM)(inverseMasses[atom2]*delta[1]);
atomCoordinates[atom2][2] += (RealOpenMM)(inverseMasses[atom2]*delta[2]);
atomCoordinates[atom1][0] -= inverseMasses[atom1]*delta[0];
atomCoordinates[atom1][1] -= inverseMasses[atom1]*delta[1];
atomCoordinates[atom1][2] -= inverseMasses[atom1]*delta[2];
atomCoordinates[atom2][0] += inverseMasses[atom2]*delta[0];
atomCoordinates[atom2][1] += inverseMasses[atom2]*delta[1];
atomCoordinates[atom2][2] += inverseMasses[atom2]*delta[2];
}
}
......@@ -214,19 +185,9 @@ void ReferenceLincsAlgorithm::updateAtomPositions(int numberOfAtoms, vector<Real
--------------------------------------------------------------------------------------- */
void ReferenceLincsAlgorithm::apply(int numberOfAtoms, vector<RealVec>& atomCoordinates,
vector<RealVec>& atomCoordinatesP,
vector<RealOpenMM>& inverseMasses) {
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nReferenceLincsAlgorithm::apply";
static const RealOpenMM zero = 0.0;
static const RealOpenMM one = 1.0;
static const RealOpenMM two = 2.0;
// ---------------------------------------------------------------------------------------
void ReferenceLincsAlgorithm::apply(int numberOfAtoms, vector<Vec3>& atomCoordinates,
vector<Vec3>& atomCoordinatesP,
vector<double>& inverseMasses) {
if (_numberOfConstraints == 0)
return;
......@@ -239,27 +200,27 @@ void ReferenceLincsAlgorithm::apply(int numberOfAtoms, vector<RealVec>& atomCoor
for (int i = 0; i < _numberOfConstraints; i++) {
int atom1 = _atomIndices[i][0];
int atom2 = _atomIndices[i][1];
_constraintDir[i] = RealVec(atomCoordinatesP[atom1][0]-atomCoordinatesP[atom2][0],
_constraintDir[i] = Vec3(atomCoordinatesP[atom1][0]-atomCoordinatesP[atom2][0],
atomCoordinatesP[atom1][1]-atomCoordinatesP[atom2][1],
atomCoordinatesP[atom1][2]-atomCoordinatesP[atom2][2]);
RealOpenMM invLength = (RealOpenMM)(1/SQRT((RealOpenMM)_constraintDir[i].dot(_constraintDir[i])));
double invLength = 1/sqrt(_constraintDir[i].dot(_constraintDir[i]));
_constraintDir[i][0] *= invLength;
_constraintDir[i][1] *= invLength;
_constraintDir[i][2] *= invLength;
_rhs1[i] = _solution[i] = _sMatrix[i]*(one/invLength-_distance[i]);
_rhs1[i] = _solution[i] = _sMatrix[i]*(1.0/invLength-_distance[i]);
}
// Build the coupling matrix.
for (int c1 = 0; c1 < (int)_couplingMatrix.size(); c1++) {
RealVec& dir1 = _constraintDir[c1];
Vec3& dir1 = _constraintDir[c1];
for (int j = 0; j < (int)_couplingMatrix[c1].size(); j++) {
int c2 = _linkedConstraints[c1][j];
RealVec& dir2 = _constraintDir[c2];
Vec3& dir2 = _constraintDir[c2];
if (_atomIndices[c1][0] == _atomIndices[c2][0] || _atomIndices[c1][1] == _atomIndices[c2][1])
_couplingMatrix[c1][j] = (RealOpenMM)(-inverseMasses[_atomIndices[c1][0]]*_sMatrix[c1]*dir1.dot(dir2)*_sMatrix[c2]);
_couplingMatrix[c1][j] = -inverseMasses[_atomIndices[c1][0]]*_sMatrix[c1]*dir1.dot(dir2)*_sMatrix[c2];
else
_couplingMatrix[c1][j] = (RealOpenMM)(inverseMasses[_atomIndices[c1][1]]*_sMatrix[c1]*dir1.dot(dir2)*_sMatrix[c2]);
_couplingMatrix[c1][j] = inverseMasses[_atomIndices[c1][1]]*_sMatrix[c1]*dir1.dot(dir2)*_sMatrix[c2];
}
}
......@@ -273,13 +234,13 @@ void ReferenceLincsAlgorithm::apply(int numberOfAtoms, vector<RealVec>& atomCoor
for (int i = 0; i < _numberOfConstraints; i++) {
int atom1 = _atomIndices[i][0];
int atom2 = _atomIndices[i][1];
RealVec delta(atomCoordinatesP[atom1][0]-atomCoordinatesP[atom2][0],
Vec3 delta(atomCoordinatesP[atom1][0]-atomCoordinatesP[atom2][0],
atomCoordinatesP[atom1][1]-atomCoordinatesP[atom2][1],
atomCoordinatesP[atom1][2]-atomCoordinatesP[atom2][2]);
RealOpenMM p2 = (RealOpenMM)(two*_distance[i]*_distance[i]-delta.dot(delta));
if (p2 < zero)
p2 = zero;
_rhs1[i] = _solution[i] = _sMatrix[i]*(_distance[i]-SQRT(p2));
double p2 = 2.0*_distance[i]*_distance[i]-delta.dot(delta);
if (p2 < 0.0)
p2 = 0.0;
_rhs1[i] = _solution[i] = _sMatrix[i]*(_distance[i]-sqrt(p2));
}
solveMatrix();
updateAtomPositions(numberOfAtoms, atomCoordinatesP, inverseMasses);
......@@ -296,7 +257,7 @@ void ReferenceLincsAlgorithm::apply(int numberOfAtoms, vector<RealVec>& atomCoor
--------------------------------------------------------------------------------------- */
void ReferenceLincsAlgorithm::applyToVelocities(int numberOfAtoms, std::vector<OpenMM::RealVec>& atomCoordinates,
std::vector<OpenMM::RealVec>& velocities, std::vector<RealOpenMM>& inverseMasses) {
void ReferenceLincsAlgorithm::applyToVelocities(int numberOfAtoms, std::vector<OpenMM::Vec3>& atomCoordinates,
std::vector<OpenMM::Vec3>& velocities, std::vector<double>& inverseMasses) {
throw OpenMM::OpenMMException("applyToVelocities is not implemented");
}
......@@ -64,7 +64,7 @@ ReferenceMonteCarloBarostat::~ReferenceMonteCarloBarostat() {
--------------------------------------------------------------------------------------- */
void ReferenceMonteCarloBarostat::applyBarostat(vector<RealVec>& atomPositions, const RealVec* boxVectors, RealOpenMM scaleX, RealOpenMM scaleY, RealOpenMM scaleZ) {
void ReferenceMonteCarloBarostat::applyBarostat(vector<Vec3>& atomPositions, const Vec3* boxVectors, double scaleX, double scaleY, double scaleZ) {
int numAtoms = savedAtomPositions[0].size();
for (int i = 0; i < numAtoms; i++)
for (int j = 0; j < 3; j++)
......@@ -75,16 +75,16 @@ void ReferenceMonteCarloBarostat::applyBarostat(vector<RealVec>& atomPositions,
for (int i = 0; i < (int) molecules.size(); i++) {
// Find the molecule center.
RealVec pos(0, 0, 0);
Vec3 pos(0, 0, 0);
for (int j = 0; j < (int) molecules[i].size(); j++) {
RealVec& atomPos = atomPositions[molecules[i][j]];
Vec3& atomPos = atomPositions[molecules[i][j]];
pos += atomPos;
}
pos /= molecules[i].size();
// Move it into the first periodic box.
RealVec newPos = pos;
Vec3 newPos = pos;
newPos -= boxVectors[2]*floor(newPos[2]/boxVectors[2][2]);
newPos -= boxVectors[1]*floor(newPos[1]/boxVectors[1][1]);
newPos -= boxVectors[0]*floor(newPos[0]/boxVectors[0][0]);
......@@ -94,9 +94,9 @@ void ReferenceMonteCarloBarostat::applyBarostat(vector<RealVec>& atomPositions,
newPos[0] *= scaleX;
newPos[1] *= scaleY;
newPos[2] *= scaleZ;
RealVec offset = newPos-pos;
Vec3 offset = newPos-pos;
for (int j = 0; j < (int) molecules[i].size(); j++) {
RealVec& atomPos = atomPositions[molecules[i][j]];
Vec3& atomPos = atomPositions[molecules[i][j]];
atomPos += offset;
}
}
......@@ -110,7 +110,7 @@ void ReferenceMonteCarloBarostat::applyBarostat(vector<RealVec>& atomPositions,
--------------------------------------------------------------------------------------- */
void ReferenceMonteCarloBarostat::restorePositions(vector<RealVec>& atomPositions) {
void ReferenceMonteCarloBarostat::restorePositions(vector<Vec3>& atomPositions) {
int numAtoms = savedAtomPositions[0].size();
for (int i = 0; i < numAtoms; i++)
for (int j = 0; j < 3; j++)
......
......@@ -13,8 +13,8 @@ namespace OpenMM {
typedef std::vector<AtomIndex> AtomList;
// squared distance between two points
static double compPairDistanceSquared(const RealVec& pos1, const RealVec& pos2, const RealVec* periodicBoxVectors, bool usePeriodic) {
RealVec diff = pos2-pos1;
static double compPairDistanceSquared(const Vec3& pos1, const Vec3& pos2, const Vec3* periodicBoxVectors, bool usePeriodic) {
Vec3 diff = pos2-pos1;
if (usePeriodic) {
diff -= periodicBoxVectors[2]*floor(diff[2]/periodicBoxVectors[2][2]+0.5);
diff -= periodicBoxVectors[1]*floor(diff[1]/periodicBoxVectors[1][1]+0.5);
......@@ -30,7 +30,7 @@ void OPENMM_EXPORT computeNeighborListNaive(
int nAtoms,
const AtomLocationList& atomLocations,
const vector<set<int> >& exclusions,
const RealVec* periodicBoxVectors,
const Vec3* periodicBoxVectors,
bool usePeriodic,
double maxDistance,
double minDistance,
......@@ -78,13 +78,13 @@ public:
};
typedef std::pair<const RealVec*, AtomIndex> VoxelItem;
typedef std::pair<const Vec3*, AtomIndex> VoxelItem;
typedef std::vector< VoxelItem > Voxel;
class VoxelHash
{
public:
VoxelHash(double vsx, double vsy, double vsz, const RealVec* periodicBoxVectors, bool usePeriodic) :
VoxelHash(double vsx, double vsy, double vsz, const Vec3* periodicBoxVectors, bool usePeriodic) :
voxelSizeX(vsx), voxelSizeY(vsy), voxelSizeZ(vsz), periodicBoxVectors(periodicBoxVectors), usePeriodic(usePeriodic) {
if (usePeriodic) {
nx = (int) floor(periodicBoxVectors[0][0]/voxelSizeX+0.5);
......@@ -96,7 +96,7 @@ public:
}
}
void insert(const AtomIndex& item, const RealVec& location)
void insert(const AtomIndex& item, const Vec3& location)
{
VoxelIndex voxelIndex = getVoxelIndex(location);
if (voxelMap.find(voxelIndex) == voxelMap.end())
......@@ -106,8 +106,8 @@ public:
}
VoxelIndex getVoxelIndex(const RealVec& location) const {
RealVec r = location;
VoxelIndex getVoxelIndex(const Vec3& location) const {
Vec3 r = location;
if (usePeriodic) {
r -= periodicBoxVectors[2]*floor(r[2]/periodicBoxVectors[2][2]);
r -= periodicBoxVectors[1]*floor(r[1]/periodicBoxVectors[1][1]);
......@@ -138,7 +138,7 @@ public:
assert(voxelSizeZ > 0);
const AtomIndex atomI = referencePoint.second;
const RealVec& locationI = *referencePoint.first;
const Vec3& locationI = *referencePoint.first;
double maxDistanceSquared = maxDistance * maxDistance;
double minDistanceSquared = minDistance * minDistance;
......@@ -187,7 +187,7 @@ public:
for (Voxel::const_iterator itemIter = voxel.begin(); itemIter != voxel.end(); ++itemIter)
{
const AtomIndex atomJ = itemIter->second;
const RealVec& locationJ = *itemIter->first;
const Vec3& locationJ = *itemIter->first;
// Ignore self hits
if (atomI == atomJ) continue;
......@@ -211,7 +211,7 @@ public:
private:
double voxelSizeX, voxelSizeY, voxelSizeZ;
int nx, ny, nz;
const RealVec* periodicBoxVectors;
const Vec3* periodicBoxVectors;
const bool usePeriodic;
std::map<VoxelIndex, Voxel> voxelMap;
};
......@@ -223,7 +223,7 @@ void OPENMM_EXPORT computeNeighborListVoxelHash(
int nAtoms,
const AtomLocationList& atomLocations,
const vector<set<int> >& exclusions,
const RealVec* periodicBoxVectors,
const Vec3* periodicBoxVectors,
bool usePeriodic,
double maxDistance,
double minDistance,
......@@ -244,7 +244,7 @@ void OPENMM_EXPORT computeNeighborListVoxelHash(
for (AtomIndex atomJ = 0; atomJ < (AtomIndex) nAtoms; ++atomJ) // use "j", because j > i for pairs
{
// 1) Find other atoms that are close to this one
const RealVec& location = atomLocations[atomJ];
const Vec3& location = atomLocations[atomJ];
voxelHash.getNeighbors(
neighborList,
VoxelItem(&location, atomJ),
......
......@@ -111,7 +111,7 @@ void ReferenceObc::setIncludeAceApproximation(int includeAceApproximation) {
--------------------------------------------------------------------------------------- */
vector<RealOpenMM>& ReferenceObc::getObcChain() {
vector<double>& ReferenceObc::getObcChain() {
return _obcChain;
}
......@@ -127,30 +127,19 @@ vector<RealOpenMM>& ReferenceObc::getObcChain() {
--------------------------------------------------------------------------------------- */
void ReferenceObc::computeBornRadii(const vector<RealVec>& atomCoordinates, vector<RealOpenMM>& bornRadii) {
void ReferenceObc::computeBornRadii(const vector<Vec3>& atomCoordinates, vector<double>& bornRadii) {
// ---------------------------------------------------------------------------------------
static const RealOpenMM zero = static_cast<RealOpenMM>(0.0);
static const RealOpenMM one = static_cast<RealOpenMM>(1.0);
static const RealOpenMM two = static_cast<RealOpenMM>(2.0);
static const RealOpenMM three = static_cast<RealOpenMM>(3.0);
static const RealOpenMM half = static_cast<RealOpenMM>(0.5);
static const RealOpenMM fourth = static_cast<RealOpenMM>(0.25);
// ---------------------------------------------------------------------------------------
ObcParameters* obcParameters = getObcParameters();
ObcParameters* obcParameters = getObcParameters();
int numberOfAtoms = obcParameters->getNumberOfAtoms();
const vector<double>& atomicRadii = obcParameters->getAtomicRadii();
const vector<double>& scaledRadiusFactor = obcParameters->getScaledRadiusFactors();
vector<double>& obcChain = getObcChain();
int numberOfAtoms = obcParameters->getNumberOfAtoms();
const vector<RealOpenMM>& atomicRadii = obcParameters->getAtomicRadii();
const vector<RealOpenMM>& scaledRadiusFactor = obcParameters->getScaledRadiusFactors();
vector<RealOpenMM>& obcChain = getObcChain();
RealOpenMM dielectricOffset = obcParameters->getDielectricOffset();
RealOpenMM alphaObc = obcParameters->getAlphaObc();
RealOpenMM betaObc = obcParameters->getBetaObc();
RealOpenMM gammaObc = obcParameters->getGammaObc();
double dielectricOffset = obcParameters->getDielectricOffset();
double alphaObc = obcParameters->getAlphaObc();
double betaObc = obcParameters->getBetaObc();
double gammaObc = obcParameters->getGammaObc();
// ---------------------------------------------------------------------------------------
......@@ -158,11 +147,11 @@ void ReferenceObc::computeBornRadii(const vector<RealVec>& atomCoordinates, vect
for (int atomI = 0; atomI < numberOfAtoms; atomI++) {
RealOpenMM radiusI = atomicRadii[atomI];
RealOpenMM offsetRadiusI = radiusI - dielectricOffset;
double radiusI = atomicRadii[atomI];
double offsetRadiusI = radiusI - dielectricOffset;
RealOpenMM radiusIInverse = one/offsetRadiusI;
RealOpenMM sum = zero;
double radiusIInverse = 1.0/offsetRadiusI;
double sum = 0.0;
// HCT code
......@@ -170,38 +159,38 @@ void ReferenceObc::computeBornRadii(const vector<RealVec>& atomCoordinates, vect
if (atomJ != atomI) {
RealOpenMM deltaR[ReferenceForce::LastDeltaRIndex];
double deltaR[ReferenceForce::LastDeltaRIndex];
if (_obcParameters->getPeriodic())
ReferenceForce::getDeltaRPeriodic(atomCoordinates[atomI], atomCoordinates[atomJ], _obcParameters->getPeriodicBox(), deltaR);
else
ReferenceForce::getDeltaR(atomCoordinates[atomI], atomCoordinates[atomJ], deltaR);
RealOpenMM r = deltaR[ReferenceForce::RIndex];
double r = deltaR[ReferenceForce::RIndex];
if (_obcParameters->getUseCutoff() && r > _obcParameters->getCutoffDistance())
continue;
RealOpenMM offsetRadiusJ = atomicRadii[atomJ] - dielectricOffset;
RealOpenMM scaledRadiusJ = offsetRadiusJ*scaledRadiusFactor[atomJ];
RealOpenMM rScaledRadiusJ = r + scaledRadiusJ;
double offsetRadiusJ = atomicRadii[atomJ] - dielectricOffset;
double scaledRadiusJ = offsetRadiusJ*scaledRadiusFactor[atomJ];
double rScaledRadiusJ = r + scaledRadiusJ;
if (offsetRadiusI < rScaledRadiusJ) {
RealOpenMM rInverse = one/r;
RealOpenMM l_ij = offsetRadiusI > FABS(r - scaledRadiusJ) ? offsetRadiusI : FABS(r - scaledRadiusJ);
l_ij = one/l_ij;
double rInverse = 1.0/r;
double l_ij = offsetRadiusI > fabs(r - scaledRadiusJ) ? offsetRadiusI : fabs(r - scaledRadiusJ);
l_ij = 1.0/l_ij;
RealOpenMM u_ij = one/rScaledRadiusJ;
double u_ij = 1.0/rScaledRadiusJ;
RealOpenMM l_ij2 = l_ij*l_ij;
RealOpenMM u_ij2 = u_ij*u_ij;
double l_ij2 = l_ij*l_ij;
double u_ij2 = u_ij*u_ij;
RealOpenMM ratio = LN((u_ij/l_ij));
RealOpenMM term = l_ij - u_ij + fourth*r*(u_ij2 - l_ij2) + (half*rInverse*ratio) + (fourth*scaledRadiusJ*scaledRadiusJ*rInverse)*(l_ij2 - u_ij2);
double ratio = log((u_ij/l_ij));
double term = l_ij - u_ij + 0.25*r*(u_ij2 - l_ij2) + (0.5*rInverse*ratio) + (0.25*scaledRadiusJ*scaledRadiusJ*rInverse)*(l_ij2 - u_ij2);
// this case (atom i completely inside atom j) is not considered in the original paper
// Jay Ponder and the authors of Tinker recognized this and
// worked out the details
if (offsetRadiusI < (scaledRadiusJ - r)) {
term += two*(radiusIInverse - l_ij);
term += 2.0*(radiusIInverse - l_ij);
}
sum += term;
......@@ -211,15 +200,15 @@ void ReferenceObc::computeBornRadii(const vector<RealVec>& atomCoordinates, vect
// OBC-specific code (Eqs. 6-8 in paper)
sum *= half*offsetRadiusI;
RealOpenMM sum2 = sum*sum;
RealOpenMM sum3 = sum*sum2;
RealOpenMM tanhSum = TANH(alphaObc*sum - betaObc*sum2 + gammaObc*sum3);
sum *= 0.5*offsetRadiusI;
double sum2 = sum*sum;
double sum3 = sum*sum2;
double tanhSum = tanh(alphaObc*sum - betaObc*sum2 + gammaObc*sum3);
bornRadii[atomI] = one/(one/offsetRadiusI - tanhSum/radiusI);
bornRadii[atomI] = 1.0/(1.0/offsetRadiusI - tanhSum/radiusI);
obcChain[atomI] = offsetRadiusI*(alphaObc - two*betaObc*sum + three*gammaObc*sum2);
obcChain[atomI] = (one - tanhSum*tanhSum)*obcChain[atomI]/radiusI;
obcChain[atomI] = offsetRadiusI*(alphaObc - 2.0*betaObc*sum + 3.0*gammaObc*sum2);
obcChain[atomI] = (1.0 - tanhSum*tanhSum)*obcChain[atomI]/radiusI;
}
}
......@@ -236,24 +225,16 @@ void ReferenceObc::computeBornRadii(const vector<RealVec>& atomCoordinates, vect
--------------------------------------------------------------------------------------- */
void ReferenceObc::computeAceNonPolarForce(const ObcParameters* obcParameters,
const vector<RealOpenMM>& bornRadii,
RealOpenMM* energy,
vector<RealOpenMM>& forces) const {
// ---------------------------------------------------------------------------------------
static const RealOpenMM zero = static_cast<RealOpenMM>(0.0);
static const RealOpenMM minusSix = -6.0;
static const RealOpenMM six = static_cast<RealOpenMM>(6.0);
// ---------------------------------------------------------------------------------------
const vector<double>& bornRadii,
double* energy,
vector<double>& forces) const {
// compute the nonpolar solvation via ACE approximation
const RealOpenMM probeRadius = obcParameters->getProbeRadius();
const RealOpenMM surfaceAreaFactor = obcParameters->getPi4Asolv();
const double probeRadius = obcParameters->getProbeRadius();
const double surfaceAreaFactor = obcParameters->getPi4Asolv();
const vector<RealOpenMM>& atomicRadii = obcParameters->getAtomicRadii();
const vector<double>& atomicRadii = obcParameters->getAtomicRadii();
int numberOfAtoms = obcParameters->getNumberOfAtoms();
// the original ACE equation is based on Eq.2 of
......@@ -271,12 +252,12 @@ void ReferenceObc::computeAceNonPolarForce(const ObcParameters* obcParameters,
// no paper to cite.
for (int atomI = 0; atomI < numberOfAtoms; atomI++) {
if (bornRadii[atomI] > zero) {
RealOpenMM r = atomicRadii[atomI] + probeRadius;
RealOpenMM ratio6 = POW(atomicRadii[atomI]/bornRadii[atomI], six);
RealOpenMM saTerm = surfaceAreaFactor*r*r*ratio6;
if (bornRadii[atomI] > 0.0) {
double r = atomicRadii[atomI] + probeRadius;
double ratio6 = pow(atomicRadii[atomI]/bornRadii[atomI], 6.0);
double saTerm = surfaceAreaFactor*r*r*ratio6;
*energy += saTerm;
forces[atomI] += minusSix*saTerm/bornRadii[atomI];
forces[atomI] -= 6.0*saTerm/bornRadii[atomI];
}
}
}
......@@ -293,44 +274,33 @@ void ReferenceObc::computeAceNonPolarForce(const ObcParameters* obcParameters,
--------------------------------------------------------------------------------------- */
RealOpenMM ReferenceObc::computeBornEnergyForces(const vector<RealVec>& atomCoordinates,
const vector<RealOpenMM>& partialCharges, vector<RealVec>& inputForces) {
// ---------------------------------------------------------------------------------------
static const RealOpenMM zero = static_cast<RealOpenMM>(0.0);
static const RealOpenMM one = static_cast<RealOpenMM>(1.0);
static const RealOpenMM two = static_cast<RealOpenMM>(2.0);
static const RealOpenMM three = static_cast<RealOpenMM>(3.0);
static const RealOpenMM four = static_cast<RealOpenMM>(4.0);
static const RealOpenMM half = static_cast<RealOpenMM>(0.5);
static const RealOpenMM fourth = static_cast<RealOpenMM>(0.25);
static const RealOpenMM eighth = static_cast<RealOpenMM>(0.125);
double ReferenceObc::computeBornEnergyForces(const vector<Vec3>& atomCoordinates,
const vector<double>& partialCharges, vector<Vec3>& inputForces) {
// constants
const int numberOfAtoms = _obcParameters->getNumberOfAtoms();
const RealOpenMM dielectricOffset = _obcParameters->getDielectricOffset();
const RealOpenMM cutoffDistance = _obcParameters->getCutoffDistance();
const RealOpenMM soluteDielectric = _obcParameters->getSoluteDielectric();
const RealOpenMM solventDielectric = _obcParameters->getSolventDielectric();
RealOpenMM preFactor;
if (soluteDielectric != zero && solventDielectric != zero)
preFactor = two*_obcParameters->getElectricConstant()*((one/soluteDielectric) - (one/solventDielectric));
const double dielectricOffset = _obcParameters->getDielectricOffset();
const double cutoffDistance = _obcParameters->getCutoffDistance();
const double soluteDielectric = _obcParameters->getSoluteDielectric();
const double solventDielectric = _obcParameters->getSolventDielectric();
double preFactor;
if (soluteDielectric != 0.0 && solventDielectric != 0.0)
preFactor = 2.0*_obcParameters->getElectricConstant()*((1.0/soluteDielectric) - (1.0/solventDielectric));
else
preFactor = zero;
preFactor = 0.0;
// ---------------------------------------------------------------------------------------
// compute Born radii
vector<RealOpenMM> bornRadii(numberOfAtoms);
vector<double> bornRadii(numberOfAtoms);
computeBornRadii(atomCoordinates, bornRadii);
// set energy/forces to zero
RealOpenMM obcEnergy = zero;
vector<RealOpenMM> bornForces(numberOfAtoms, 0.0);
double obcEnergy = 0.0;
vector<double> bornForces(numberOfAtoms, 0.0);
// ---------------------------------------------------------------------------------------
......@@ -346,10 +316,10 @@ RealOpenMM ReferenceObc::computeBornEnergyForces(const vector<RealVec>& atomCoor
for (int atomI = 0; atomI < numberOfAtoms; atomI++) {
RealOpenMM partialChargeI = preFactor*partialCharges[atomI];
double partialChargeI = preFactor*partialCharges[atomI];
for (int atomJ = atomI; atomJ < numberOfAtoms; atomJ++) {
RealOpenMM deltaR[ReferenceForce::LastDeltaRIndex];
double deltaR[ReferenceForce::LastDeltaRIndex];
if (_obcParameters->getPeriodic())
ReferenceForce::getDeltaRPeriodic(atomCoordinates[atomI], atomCoordinates[atomJ], _obcParameters->getPeriodicBox(), deltaR);
else
......@@ -357,24 +327,24 @@ RealOpenMM ReferenceObc::computeBornEnergyForces(const vector<RealVec>& atomCoor
if (_obcParameters->getUseCutoff() && deltaR[ReferenceForce::RIndex] > cutoffDistance)
continue;
RealOpenMM r2 = deltaR[ReferenceForce::R2Index];
RealOpenMM deltaX = deltaR[ReferenceForce::XIndex];
RealOpenMM deltaY = deltaR[ReferenceForce::YIndex];
RealOpenMM deltaZ = deltaR[ReferenceForce::ZIndex];
double r2 = deltaR[ReferenceForce::R2Index];
double deltaX = deltaR[ReferenceForce::XIndex];
double deltaY = deltaR[ReferenceForce::YIndex];
double deltaZ = deltaR[ReferenceForce::ZIndex];
RealOpenMM alpha2_ij = bornRadii[atomI]*bornRadii[atomJ];
RealOpenMM D_ij = r2/(four*alpha2_ij);
double alpha2_ij = bornRadii[atomI]*bornRadii[atomJ];
double D_ij = r2/(4.0*alpha2_ij);
RealOpenMM expTerm = EXP(-D_ij);
RealOpenMM denominator2 = r2 + alpha2_ij*expTerm;
RealOpenMM denominator = SQRT(denominator2);
double expTerm = exp(-D_ij);
double denominator2 = r2 + alpha2_ij*expTerm;
double denominator = sqrt(denominator2);
RealOpenMM Gpol = (partialChargeI*partialCharges[atomJ])/denominator;
RealOpenMM dGpol_dr = -Gpol*(one - fourth*expTerm)/denominator2;
double Gpol = (partialChargeI*partialCharges[atomJ])/denominator;
double dGpol_dr = -Gpol*(1.0 - 0.25*expTerm)/denominator2;
RealOpenMM dGpol_dalpha2_ij = -half*Gpol*expTerm*(one + D_ij)/denominator2;
double dGpol_dalpha2_ij = -0.5*Gpol*expTerm*(1.0 + D_ij)/denominator2;
RealOpenMM energy = Gpol;
double energy = Gpol;
if (atomI != atomJ) {
......@@ -396,7 +366,7 @@ RealOpenMM ReferenceObc::computeBornEnergyForces(const vector<RealVec>& atomCoor
inputForces[atomJ][2] -= deltaZ;
} else {
energy *= half;
energy *= 0.5;
}
obcEnergy += energy;
......@@ -409,13 +379,13 @@ RealOpenMM ReferenceObc::computeBornEnergyForces(const vector<RealVec>& atomCoor
// second main loop
const vector<RealOpenMM>& obcChain = getObcChain();
const vector<RealOpenMM>& atomicRadii = _obcParameters->getAtomicRadii();
const vector<double>& obcChain = getObcChain();
const vector<double>& atomicRadii = _obcParameters->getAtomicRadii();
const RealOpenMM alphaObc = _obcParameters->getAlphaObc();
const RealOpenMM betaObc = _obcParameters->getBetaObc();
const RealOpenMM gammaObc = _obcParameters->getGammaObc();
const vector<RealOpenMM>& scaledRadiusFactor = _obcParameters->getScaledRadiusFactors();
const double alphaObc = _obcParameters->getAlphaObc();
const double betaObc = _obcParameters->getBetaObc();
const double gammaObc = _obcParameters->getGammaObc();
const vector<double>& scaledRadiusFactor = _obcParameters->getScaledRadiusFactors();
// compute factor that depends only on the outer loop index
......@@ -427,14 +397,14 @@ RealOpenMM ReferenceObc::computeBornEnergyForces(const vector<RealVec>& atomCoor
// radius w/ dielectric offset applied
RealOpenMM radiusI = atomicRadii[atomI];
RealOpenMM offsetRadiusI = radiusI - dielectricOffset;
double radiusI = atomicRadii[atomI];
double offsetRadiusI = radiusI - dielectricOffset;
for (int atomJ = 0; atomJ < numberOfAtoms; atomJ++) {
if (atomJ != atomI) {
RealOpenMM deltaR[ReferenceForce::LastDeltaRIndex];
double deltaR[ReferenceForce::LastDeltaRIndex];
if (_obcParameters->getPeriodic())
ReferenceForce::getDeltaRPeriodic(atomCoordinates[atomI], atomCoordinates[atomJ], _obcParameters->getPeriodicBox(), deltaR);
else
......@@ -442,39 +412,39 @@ RealOpenMM ReferenceObc::computeBornEnergyForces(const vector<RealVec>& atomCoor
if (_obcParameters->getUseCutoff() && deltaR[ReferenceForce::RIndex] > cutoffDistance)
continue;
RealOpenMM deltaX = deltaR[ReferenceForce::XIndex];
RealOpenMM deltaY = deltaR[ReferenceForce::YIndex];
RealOpenMM deltaZ = deltaR[ReferenceForce::ZIndex];
RealOpenMM r = deltaR[ReferenceForce::RIndex];
double deltaX = deltaR[ReferenceForce::XIndex];
double deltaY = deltaR[ReferenceForce::YIndex];
double deltaZ = deltaR[ReferenceForce::ZIndex];
double r = deltaR[ReferenceForce::RIndex];
// radius w/ dielectric offset applied
RealOpenMM offsetRadiusJ = atomicRadii[atomJ] - dielectricOffset;
double offsetRadiusJ = atomicRadii[atomJ] - dielectricOffset;
RealOpenMM scaledRadiusJ = offsetRadiusJ*scaledRadiusFactor[atomJ];
RealOpenMM scaledRadiusJ2 = scaledRadiusJ*scaledRadiusJ;
RealOpenMM rScaledRadiusJ = r + scaledRadiusJ;
double scaledRadiusJ = offsetRadiusJ*scaledRadiusFactor[atomJ];
double scaledRadiusJ2 = scaledRadiusJ*scaledRadiusJ;
double rScaledRadiusJ = r + scaledRadiusJ;
// dL/dr & dU/dr are zero (this can be shown analytically)
// removed from calculation
if (offsetRadiusI < rScaledRadiusJ) {
RealOpenMM l_ij = offsetRadiusI > FABS(r - scaledRadiusJ) ? offsetRadiusI : FABS(r - scaledRadiusJ);
l_ij = one/l_ij;
double l_ij = offsetRadiusI > fabs(r - scaledRadiusJ) ? offsetRadiusI : fabs(r - scaledRadiusJ);
l_ij = 1.0/l_ij;
RealOpenMM u_ij = one/rScaledRadiusJ;
double u_ij = 1.0/rScaledRadiusJ;
RealOpenMM l_ij2 = l_ij*l_ij;
double l_ij2 = l_ij*l_ij;
RealOpenMM u_ij2 = u_ij*u_ij;
double u_ij2 = u_ij*u_ij;
RealOpenMM rInverse = one/r;
RealOpenMM r2Inverse = rInverse*rInverse;
double rInverse = 1.0/r;
double r2Inverse = rInverse*rInverse;
RealOpenMM t3 = eighth*(one + scaledRadiusJ2*r2Inverse)*(l_ij2 - u_ij2) + fourth*LN(u_ij/l_ij)*r2Inverse;
double t3 = 0.125*(1.0 + scaledRadiusJ2*r2Inverse)*(l_ij2 - u_ij2) + 0.25*log(u_ij/l_ij)*r2Inverse;
RealOpenMM de = bornForces[atomI]*t3*rInverse;
double de = bornForces[atomI]*t3*rInverse;
deltaX *= de;
deltaY *= de;
......
......@@ -35,6 +35,7 @@
#include "ReferencePME.h"
#include "fftpack.h"
#include "SimTKOpenMMRealType.h"
using std::vector;
......@@ -45,7 +46,7 @@ namespace OpenMM {
struct pme
{
int natoms;
RealOpenMM ewaldcoeff;
double ewaldcoeff;
t_complex * grid; /* Memory for the grid we spread charges on.
* Element (i,j,k) is accessed as:
......@@ -57,9 +58,9 @@ struct pme
int order; /* PME interpolation order. Almost always 4 */
/* Data for bspline interpolation, see the Essman PME paper */
RealOpenMM * bsplines_moduli[3]; /* 3 pointers, to x/y/z bspline moduli, each of length ngrid[x/y/z] */
RealOpenMM * bsplines_theta[3]; /* each of x/y/z has length order*natoms */
RealOpenMM * bsplines_dtheta[3]; /* each of x/y/z has length order*natoms */
double * bsplines_moduli[3]; /* 3 pointers, to x/y/z bspline moduli, each of length ngrid[x/y/z] */
double * bsplines_theta[3]; /* each of x/y/z has length order*natoms */
double * bsplines_dtheta[3]; /* each of x/y/z has length order*natoms */
ivec * particleindex; /* Array of length natoms. Each element is
* an ivec (3 ints) that specify the grid
......@@ -85,7 +86,7 @@ struct pme
* the central cell, i.e., in this case we would assume all coordinates fall in -10 nm < x,y,z < 20 nm.
*/
RealOpenMM epsilon_r; /* Dielectric coefficient to use, typically 1.0 */
double epsilon_r; /* Dielectric coefficient to use, typically 1.0 */
};
......@@ -101,25 +102,25 @@ pme_calculate_bsplines_moduli(pme_t pme)
int i,j,k,l,d;
int order;
int ndata;
RealOpenMM * data;
RealOpenMM * ddata;
RealOpenMM * bsplines_data;
RealOpenMM div;
RealOpenMM sc,ss,arg;
double * data;
double * ddata;
double * bsplines_data;
double div;
double sc,ss,arg;
nmax = 0;
for (d=0;d<3;d++)
{
nmax = (pme->ngrid[d] > nmax) ? pme->ngrid[d] : nmax;
pme->bsplines_moduli[d] = (RealOpenMM *) malloc(sizeof(RealOpenMM)*pme->ngrid[d]);
pme->bsplines_moduli[d] = (double *) malloc(sizeof(double)*pme->ngrid[d]);
}
order = pme->order;
/* temp storage in this routine */
data = (RealOpenMM *) malloc(sizeof(RealOpenMM)*order);
ddata = (RealOpenMM *) malloc(sizeof(RealOpenMM)*order);
bsplines_data = (RealOpenMM *) malloc(sizeof(RealOpenMM)*nmax);
data = (double *) malloc(sizeof(double)*order);
ddata = (double *) malloc(sizeof(double)*order);
bsplines_data = (double *) malloc(sizeof(double)*nmax);
data[order-1]=0;
data[1]=0;
......@@ -127,7 +128,7 @@ pme_calculate_bsplines_moduli(pme_t pme)
for (k=3;k<order;k++)
{
div=(RealOpenMM) (1.0/(k-1.0));
div=1.0/(k-1.0);
data[k-1]=0;
for (l=1;l<(k-1);l++)
{
......@@ -143,7 +144,7 @@ pme_calculate_bsplines_moduli(pme_t pme)
ddata[k]=data[k-1]-data[k];
}
div=(RealOpenMM) (1.0/(order-1));
div=1.0/(order-1);
data[order-1]=0;
for (l=1;l<(order-1);l++)
......@@ -170,7 +171,7 @@ pme_calculate_bsplines_moduli(pme_t pme)
sc=ss=0;
for (j=0;j<ndata;j++)
{
arg=(RealOpenMM) ((2.0*M_PI*i*j)/ndata);
arg=(2.0*M_PI*i*j)/ndata;
sc+=bsplines_data[j]*cos(arg);
ss+=bsplines_data[j]*sin(arg);
}
......@@ -192,25 +193,25 @@ pme_calculate_bsplines_moduli(pme_t pme)
}
static void invert_box_vectors(const RealVec boxVectors[3], RealVec recipBoxVectors[3])
static void invert_box_vectors(const Vec3 boxVectors[3], Vec3 recipBoxVectors[3])
{
RealOpenMM determinant = boxVectors[0][0]*boxVectors[1][1]*boxVectors[2][2];
double determinant = boxVectors[0][0]*boxVectors[1][1]*boxVectors[2][2];
assert(determinant > 0);
RealOpenMM scale = 1.0/determinant;
recipBoxVectors[0] = RealVec(boxVectors[1][1]*boxVectors[2][2], 0, 0)*scale;
recipBoxVectors[1] = RealVec(-boxVectors[1][0]*boxVectors[2][2], boxVectors[0][0]*boxVectors[2][2], 0)*scale;
recipBoxVectors[2] = RealVec(boxVectors[1][0]*boxVectors[2][1]-boxVectors[1][1]*boxVectors[2][0], -boxVectors[0][0]*boxVectors[2][1], boxVectors[0][0]*boxVectors[1][1])*scale;
double scale = 1.0/determinant;
recipBoxVectors[0] = Vec3(boxVectors[1][1]*boxVectors[2][2], 0, 0)*scale;
recipBoxVectors[1] = Vec3(-boxVectors[1][0]*boxVectors[2][2], boxVectors[0][0]*boxVectors[2][2], 0)*scale;
recipBoxVectors[2] = Vec3(boxVectors[1][0]*boxVectors[2][1]-boxVectors[1][1]*boxVectors[2][0], -boxVectors[0][0]*boxVectors[2][1], boxVectors[0][0]*boxVectors[1][1])*scale;
}
static void
pme_update_grid_index_and_fraction(pme_t pme,
const vector<RealVec>& atomCoordinates,
const RealVec periodicBoxVectors[3],
const RealVec recipBoxVectors[3])
const vector<Vec3>& atomCoordinates,
const Vec3 periodicBoxVectors[3],
const Vec3 recipBoxVectors[3])
{
int i;
int d;
RealOpenMM t;
double t;
int ti;
for (i=0;i<pme->natoms;i++)
......@@ -251,7 +252,7 @@ pme_update_grid_index_and_fraction(pme_t pme,
* numerical problems, so this shouldnt cause any problems.
* (And, by adding 100.0 box lengths, we would lose a bit of numerical accuracy here!)
*/
RealVec coord = atomCoordinates[i];
Vec3 coord = atomCoordinates[i];
for (d=0;d<3;d++)
{
t = coord[0]*recipBoxVectors[0][d]+coord[1]*recipBoxVectors[1][d]+coord[2]*recipBoxVectors[2][d];
......@@ -275,9 +276,9 @@ pme_update_bsplines(pme_t pme)
{
int i,j,k,l;
int order;
RealOpenMM dr,div;
RealOpenMM * data;
RealOpenMM * ddata;
double dr,div;
double * data;
double * ddata;
order = pme->order;
......@@ -296,7 +297,7 @@ pme_update_bsplines(pme_t pme)
for (k=3; k<order; k++)
{
div = (RealOpenMM) (1.0/(k-1.0));
div = 1.0/(k-1.0);
data[k-1] = div*dr*data[k-2];
for (l=1; l<(k-1); l++)
{
......@@ -313,7 +314,7 @@ pme_update_bsplines(pme_t pme)
ddata[k] = data[k-1]-data[k];
}
div = (RealOpenMM) (1.0/(order-1));
div = 1.0/(order-1);
data[order-1] = div*dr*data[order-2];
for (l=1; l<(order-1); l++)
......@@ -327,7 +328,7 @@ pme_update_bsplines(pme_t pme)
static void
pme_grid_spread_charge(pme_t pme, const vector<RealOpenMM>& charges)
pme_grid_spread_charge(pme_t pme, const vector<double>& charges)
{
int order;
int i;
......@@ -335,10 +336,10 @@ pme_grid_spread_charge(pme_t pme, const vector<RealOpenMM>& charges)
int x0index,y0index,z0index;
int xindex,yindex,zindex;
int index;
RealOpenMM q;
RealOpenMM * thetax;
RealOpenMM * thetay;
RealOpenMM * thetaz;
double q;
double * thetax;
double * thetay;
double * thetaz;
order = pme->order;
......@@ -407,24 +408,24 @@ pme_grid_spread_charge(pme_t pme, const vector<RealOpenMM>& charges)
static void
pme_reciprocal_convolution(pme_t pme,
const RealVec periodicBoxVectors[3],
const RealVec recipBoxVectors[3],
RealOpenMM * energy)
const Vec3 periodicBoxVectors[3],
const Vec3 recipBoxVectors[3],
double * energy)
{
int kx,ky,kz;
int nx,ny,nz;
RealOpenMM mx,my,mz;
RealOpenMM mhx,mhy,mhz,m2;
RealOpenMM one_4pi_eps;
RealOpenMM virxx,virxy,virxz,viryy,viryz,virzz;
RealOpenMM bx,by,bz;
RealOpenMM d1,d2;
RealOpenMM eterm,vfactor,struct2,ets2;
RealOpenMM esum;
RealOpenMM factor;
RealOpenMM denom;
RealOpenMM boxfactor;
RealOpenMM maxkx,maxky,maxkz;
double mx,my,mz;
double mhx,mhy,mhz,m2;
double one_4pi_eps;
double virxx,virxy,virxz,viryy,viryz,virzz;
double bx,by,bz;
double d1,d2;
double eterm,vfactor,struct2,ets2;
double esum;
double factor;
double denom;
double boxfactor;
double maxkx,maxky,maxkz;
t_complex *ptr;
......@@ -432,9 +433,9 @@ pme_reciprocal_convolution(pme_t pme,
ny = pme->ngrid[1];
nz = pme->ngrid[2];
one_4pi_eps = (RealOpenMM) (ONE_4PI_EPS0/pme->epsilon_r);
factor = (RealOpenMM) (M_PI*M_PI/(pme->ewaldcoeff*pme->ewaldcoeff));
boxfactor = (RealOpenMM) (M_PI*periodicBoxVectors[0][0]*periodicBoxVectors[1][1]*periodicBoxVectors[2][2]);
one_4pi_eps = ONE_4PI_EPS0/pme->epsilon_r;
factor = M_PI*M_PI/(pme->ewaldcoeff*pme->ewaldcoeff);
boxfactor = M_PI*periodicBoxVectors[0][0]*periodicBoxVectors[1][1]*periodicBoxVectors[2][2];
esum = 0;
virxx = 0;
......@@ -444,21 +445,21 @@ pme_reciprocal_convolution(pme_t pme,
viryz = 0;
virzz = 0;
maxkx = (RealOpenMM) ((nx+1)/2);
maxky = (RealOpenMM) ((ny+1)/2);
maxkz = (RealOpenMM) ((nz+1)/2);
maxkx = (nx+1)/2;
maxky = (ny+1)/2;
maxkz = (nz+1)/2;
for (kx=0;kx<nx;kx++)
{
/* Calculate frequency. Grid indices in the upper half correspond to negative frequencies! */
mx = (RealOpenMM) ((kx<maxkx) ? kx : (kx-nx));
mx = (kx<maxkx) ? kx : (kx-nx);
mhx = mx*recipBoxVectors[0][0];
bx = boxfactor*pme->bsplines_moduli[0][kx];
for (ky=0;ky<ny;ky++)
{
/* Calculate frequency. Grid indices in the upper half correspond to negative frequencies! */
my = (RealOpenMM) ((ky<maxky) ? ky : (ky-ny));
my = (ky<maxky) ? ky : (ky-ny);
mhy = mx*recipBoxVectors[1][0]+my*recipBoxVectors[1][1];
by = pme->bsplines_moduli[1][ky];
......@@ -478,7 +479,7 @@ pme_reciprocal_convolution(pme_t pme,
}
/* Calculate frequency. Grid indices in the upper half correspond to negative frequencies! */
mz = (RealOpenMM) ((kz<maxkz) ? kz : (kz-nz));
mz = (kz<maxkz) ? kz : (kz-nz);
mhz = mx*recipBoxVectors[2][0]+my*recipBoxVectors[2][1]+mz*recipBoxVectors[2][2];
/* Pointer to the grid cell in question */
......@@ -509,15 +510,115 @@ pme_reciprocal_convolution(pme_t pme,
}
/* The factor 0.5 is nothing special, but it is better to have it here than inside the loop :-) */
*energy = (RealOpenMM) (0.5*esum);
*energy = 0.5*esum;
}
static void
dpme_reciprocal_convolution(pme_t pme,
const Vec3 periodicBoxVectors[3],
const Vec3 recipBoxVectors[3],
double* energy)
{
int kx,ky,kz;
int nx,ny,nz;
double mx,my,mz;
double mhx,mhy,mhz,m2;
double bx,by,bz;
double d1,d2;
double eterm,struct2,ets2;
double esum;
double denom;
double boxfactor;
double maxkx,maxky,maxkz;
t_complex *ptr;
nx = pme->ngrid[0];
ny = pme->ngrid[1];
nz = pme->ngrid[2];
boxfactor = M_PI*sqrt(M_PI) / (6.0*periodicBoxVectors[0][0]*periodicBoxVectors[1][1]*periodicBoxVectors[2][2]);
esum = 0;
maxkx = (nx+1)/2;
maxky = (ny+1)/2;
maxkz = (nz+1)/2;
double bfac = M_PI / pme->ewaldcoeff;
double fac1 = 2.0*M_PI*M_PI*M_PI*sqrt(M_PI);
double fac2 = pme->ewaldcoeff*pme->ewaldcoeff*pme->ewaldcoeff;
double fac3 = -2.0*pme->ewaldcoeff*M_PI*M_PI;
double b, m, m3, expfac, expterm, erfcterm;
for (kx=0;kx<nx;kx++)
{
/* Calculate frequency. Grid indices in the upper half correspond to negative frequencies! */
mx = ((kx<maxkx) ? kx : (kx-nx));
mhx = mx*recipBoxVectors[0][0];
bx = pme->bsplines_moduli[0][kx];
for (ky=0;ky<ny;ky++)
{
/* Calculate frequency. Grid indices in the upper half correspond to negative frequencies! */
my = ((ky<maxky) ? ky : (ky-ny));
mhy = mx*recipBoxVectors[1][0]+my*recipBoxVectors[1][1];
by = pme->bsplines_moduli[1][ky];
for (kz=0;kz<nz;kz++)
{
/*
* Unlike the Coulombic case, there's an m=0 term so all terms are considered here.
*/
/* Calculate frequency. Grid indices in the upper half correspond to negative frequencies! */
mz = ((kz<maxkz) ? kz : (kz-nz));
mhz = mx*recipBoxVectors[2][0]+my*recipBoxVectors[2][1]+mz*recipBoxVectors[2][2];
/* Pointer to the grid cell in question */
ptr = pme->grid + kx*ny*nz + ky*nz + kz;
/* Get grid data for this frequency */
d1 = ptr->re;
d2 = ptr->im;
/* Calculate the convolution - see the Essman/Darden paper for the equation! */
m2 = mhx*mhx+mhy*mhy+mhz*mhz;
bz = pme->bsplines_moduli[2][kz];
denom = boxfactor / (bx*by*bz);
m = sqrt(m2);
m3 = m*m2;
b = bfac*m;
expfac = -b*b;
erfcterm = erfc(b);
expterm = exp(expfac);
eterm = (fac1*erfcterm*m3 + expterm*(fac2 + fac3*m2)) * denom;
/* write back convolution data to grid */
ptr->re = d1*eterm;
ptr->im = d2*eterm;
struct2 = (d1*d1+d2*d2);
/* Long-range PME contribution to the energy for this frequency */
ets2 = eterm*struct2;
esum += ets2;
}
}
}
// Remember the C6 energy is attractive, hence the negative sign.
*energy = -esum;
}
static void
pme_grid_interpolate_force(pme_t pme,
const RealVec recipBoxVectors[3],
const vector<RealOpenMM>& charges,
vector<RealVec>& forces)
const Vec3 recipBoxVectors[3],
const vector<double>& charges,
vector<Vec3>& forces)
{
int i;
int ix,iy,iz;
......@@ -525,17 +626,17 @@ pme_grid_interpolate_force(pme_t pme,
int xindex,yindex,zindex;
int index;
int order;
RealOpenMM q;
RealOpenMM * thetax;
RealOpenMM * thetay;
RealOpenMM * thetaz;
RealOpenMM * dthetax;
RealOpenMM * dthetay;
RealOpenMM * dthetaz;
RealOpenMM tx,ty,tz;
RealOpenMM dtx,dty,dtz;
RealOpenMM fx,fy,fz;
RealOpenMM gridvalue;
double q;
double * thetax;
double * thetay;
double * thetaz;
double * dthetax;
double * dthetay;
double * dthetaz;
double tx,ty,tz;
double dtx,dty,dtz;
double fx,fy,fz;
double gridvalue;
int nx,ny,nz;
nx = pme->ngrid[0];
......@@ -617,11 +718,11 @@ pme_grid_interpolate_force(pme_t pme,
int
pme_init(pme_t * ppme,
RealOpenMM ewaldcoeff,
double ewaldcoeff,
int natoms,
const int ngrid[3],
const int ngrid[3],
int pme_order,
RealOpenMM epsilon_r)
double epsilon_r)
{
pme_t pme;
int d;
......@@ -636,8 +737,8 @@ pme_init(pme_t * ppme,
for (d=0;d<3;d++)
{
pme->ngrid[d] = ngrid[d];
pme->bsplines_theta[d] = (RealOpenMM *)malloc(sizeof(RealOpenMM)*pme_order*natoms);
pme->bsplines_dtheta[d] = (RealOpenMM *)malloc(sizeof(RealOpenMM)*pme_order*natoms);
pme->bsplines_theta[d] = (double *)malloc(sizeof(double)*pme_order*natoms);
pme->bsplines_dtheta[d] = (double *)malloc(sizeof(double)*pme_order*natoms);
}
pme->particlefraction = (rvec *)malloc(sizeof(rvec)*natoms);
......@@ -661,15 +762,15 @@ pme_init(pme_t * ppme,
int pme_exec(pme_t pme,
const vector<RealVec>& atomCoordinates,
vector<RealVec>& forces,
const vector<RealOpenMM>& charges,
const RealVec periodicBoxVectors[3],
RealOpenMM* energy)
const vector<Vec3>& atomCoordinates,
vector<Vec3>& forces,
const vector<double>& charges,
const Vec3 periodicBoxVectors[3],
double* energy)
{
/* Routine is called with coordinates in x, a box, and charges in q */
RealVec recipBoxVectors[3];
Vec3 recipBoxVectors[3];
invert_box_vectors(periodicBoxVectors, recipBoxVectors);
/* Before we can do the actual interpolation, we need to recalculate and update
......@@ -704,6 +805,49 @@ int pme_exec(pme_t pme,
}
int pme_exec_dpme(pme_t pme,
const vector<Vec3>& atomCoordinates,
vector<Vec3>& forces,
const vector<double>& c6s,
const Vec3 periodicBoxVectors[3],
double* energy)
{
/* Routine is called with coordinates in x, a box, and charges in q */
Vec3 recipBoxVectors[3];
invert_box_vectors(periodicBoxVectors, recipBoxVectors);
/* Before we can do the actual interpolation, we need to recalculate and update
* the indices for each particle in the charge grid (initialized in pme_init()),
* and what its fractional offset in this grid cell is.
*/
/* Update charge grid indices and fractional offsets for each atom.
* The indices/fractions are stored internally in the pme datatype
*/
pme_update_grid_index_and_fraction(pme,atomCoordinates,periodicBoxVectors,recipBoxVectors);
/* Calculate bsplines (and their differentials) from current fractional coordinates, store in pme structure */
pme_update_bsplines(pme);
/* Spread the charges on grid (using newly calculated bsplines in the pme structure) */
pme_grid_spread_charge(pme, c6s);
/* do 3d-fft */
fftpack_exec_3d(pme->fftplan,FFTPACK_FORWARD,pme->grid,pme->grid);
/* solve in k-space */
dpme_reciprocal_convolution(pme,periodicBoxVectors,recipBoxVectors,energy);
/* do 3d-invfft */
fftpack_exec_3d(pme->fftplan,FFTPACK_BACKWARD,pme->grid,pme->grid);
/* Get the particle forces from the grid and bsplines in the pme structure */
pme_grid_interpolate_force(pme,recipBoxVectors,c6s,forces);
return 0;
}
int
pme_destroy(pme_t pme)
......
......@@ -38,13 +38,6 @@ using namespace OpenMM;
--------------------------------------------------------------------------------------- */
ReferencePairIxn::ReferencePairIxn() {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferencePairIxn::ReferencePairIxn";
// ---------------------------------------------------------------------------------------
}
/**---------------------------------------------------------------------------------------
......@@ -54,11 +47,4 @@ ReferencePairIxn::ReferencePairIxn() {
--------------------------------------------------------------------------------------- */
ReferencePairIxn::~ReferencePairIxn() {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferencePairIxn::~ReferencePairIxn";
// ---------------------------------------------------------------------------------------
}
......@@ -50,7 +50,7 @@ ReferenceProperDihedralBond::ReferenceProperDihedralBond() : usePeriodic(false)
ReferenceProperDihedralBond::~ReferenceProperDihedralBond() {
}
void ReferenceProperDihedralBond::setPeriodic(OpenMM::RealVec* vectors) {
void ReferenceProperDihedralBond::setPeriodic(OpenMM::Vec3* vectors) {
usePeriodic = true;
boxVectors[0] = vectors[0];
boxVectors[1] = vectors[1];
......@@ -72,28 +72,13 @@ void ReferenceProperDihedralBond::setPeriodic(OpenMM::RealVec* vectors) {
--------------------------------------------------------------------------------------- */
void ReferenceProperDihedralBond::calculateBondIxn(int* atomIndices,
vector<RealVec>& atomCoordinates,
RealOpenMM* parameters,
vector<RealVec>& forces,
RealOpenMM* totalEnergy, double* energyParamDerivs) {
vector<Vec3>& atomCoordinates,
double* parameters,
vector<Vec3>& forces,
double* totalEnergy, double* energyParamDerivs) {
double deltaR[3][ReferenceForce::LastDeltaRIndex];
static const std::string methodName = "\nReferenceProperDihedralBond::calculateBondIxn";
// constants -- reduce Visual Studio warnings regarding conversions between float & double
static const RealOpenMM zero = 0.0;
static const RealOpenMM one = 1.0;
static const RealOpenMM two = 2.0;
static const RealOpenMM three = 3.0;
static const RealOpenMM oneM = -1.0;
static const int threeI = 3;
static const int LastAtomIndex = 4;
RealOpenMM deltaR[3][ReferenceForce::LastDeltaRIndex];
RealOpenMM crossProductMemory[6];
double crossProductMemory[6];
// ---------------------------------------------------------------------------------------
......@@ -114,55 +99,55 @@ void ReferenceProperDihedralBond::calculateBondIxn(int* atomIndices,
ReferenceForce::getDeltaR(atomCoordinates[atomDIndex], atomCoordinates[atomCIndex], deltaR[2]);
}
RealOpenMM dotDihedral;
RealOpenMM signOfAngle;
int hasREntry = 1;
double dotDihedral;
double signOfAngle;
int hasREntry = 1;
// Visual Studio complains if crossProduct declared as 'crossProduct[2][3]'
RealOpenMM* crossProduct[2];
double* crossProduct[2];
crossProduct[0] = crossProductMemory;
crossProduct[1] = crossProductMemory + 3;
// get dihedral angle
RealOpenMM dihedralAngle = getDihedralAngleBetweenThreeVectors(deltaR[0], deltaR[1], deltaR[2],
double dihedralAngle = getDihedralAngleBetweenThreeVectors(deltaR[0], deltaR[1], deltaR[2],
crossProduct, &dotDihedral, deltaR[0],
&signOfAngle, hasREntry);
// evaluate delta angle, dE/d(angle)
RealOpenMM deltaAngle = parameters[2]*dihedralAngle - parameters[1];
RealOpenMM sinDeltaAngle = SIN(deltaAngle);
RealOpenMM dEdAngle = -parameters[0]*parameters[2]*sinDeltaAngle;
RealOpenMM energy = parameters[0]*(one + COS(deltaAngle));
double deltaAngle = parameters[2]*dihedralAngle - parameters[1];
double sinDeltaAngle = SIN(deltaAngle);
double dEdAngle = -parameters[0]*parameters[2]*sinDeltaAngle;
double energy = parameters[0]*(1.0 + cos(deltaAngle));
// compute force
RealOpenMM internalF[4][3];
RealOpenMM forceFactors[4];
RealOpenMM normCross1 = DOT3(crossProduct[0], crossProduct[0]);
RealOpenMM normBC = deltaR[1][ReferenceForce::RIndex];
forceFactors[0] = (-dEdAngle*normBC)/normCross1;
double internalF[4][3];
double forceFactors[4];
double normCross1 = DOT3(crossProduct[0], crossProduct[0]);
double normBC = deltaR[1][ReferenceForce::RIndex];
forceFactors[0] = (-dEdAngle*normBC)/normCross1;
RealOpenMM normCross2 = DOT3(crossProduct[1], crossProduct[1]);
forceFactors[3] = (dEdAngle*normBC)/normCross2;
forceFactors[1] = DOT3(deltaR[0], deltaR[1]);
forceFactors[1] /= deltaR[1][ReferenceForce::R2Index];
double normCross2 = DOT3(crossProduct[1], crossProduct[1]);
forceFactors[3] = (dEdAngle*normBC)/normCross2;
forceFactors[1] = DOT3(deltaR[0], deltaR[1]);
forceFactors[1] /= deltaR[1][ReferenceForce::R2Index];
forceFactors[2] = DOT3(deltaR[2], deltaR[1]);
forceFactors[2] /= deltaR[1][ReferenceForce::R2Index];
forceFactors[2] = DOT3(deltaR[2], deltaR[1]);
forceFactors[2] /= deltaR[1][ReferenceForce::R2Index];
for (int ii = 0; ii < 3; ii++) {
internalF[0][ii] = forceFactors[0]*crossProduct[0][ii];
internalF[3][ii] = forceFactors[3]*crossProduct[1][ii];
internalF[0][ii] = forceFactors[0]*crossProduct[0][ii];
internalF[3][ii] = forceFactors[3]*crossProduct[1][ii];
RealOpenMM s = forceFactors[1]*internalF[0][ii] - forceFactors[2]*internalF[3][ii];
double s = forceFactors[1]*internalF[0][ii] - forceFactors[2]*internalF[3][ii];
internalF[1][ii] = internalF[0][ii] - s;
internalF[2][ii] = internalF[3][ii] + s;
internalF[1][ii] = internalF[0][ii] - s;
internalF[2][ii] = internalF[3][ii] + s;
}
// accumulate forces
......
......@@ -50,7 +50,7 @@ ReferenceRbDihedralBond::ReferenceRbDihedralBond() : usePeriodic(false) {
ReferenceRbDihedralBond::~ReferenceRbDihedralBond() {
}
void ReferenceRbDihedralBond::setPeriodic(OpenMM::RealVec* vectors) {
void ReferenceRbDihedralBond::setPeriodic(OpenMM::Vec3* vectors) {
usePeriodic = true;
boxVectors[0] = vectors[0];
boxVectors[1] = vectors[1];
......@@ -70,32 +70,17 @@ void ReferenceRbDihedralBond::setPeriodic(OpenMM::RealVec* vectors) {
--------------------------------------------------------------------------------------- */
void ReferenceRbDihedralBond::calculateBondIxn(int* atomIndices,
vector<RealVec>& atomCoordinates,
RealOpenMM* parameters,
vector<RealVec>& forces,
RealOpenMM* totalEnergy, double* energyParamDerivs) {
static const std::string methodName = "\nReferenceRbDihedralBond::calculateBondIxn";
// constants -- reduce Visual Studio warnings regarding conversions between float & double
static const RealOpenMM zero = 0.0;
static const RealOpenMM one = 1.0;
static const RealOpenMM two = 2.0;
static const RealOpenMM three = 3.0;
static const RealOpenMM oneM = -1.0;
static const int threeI = 3;
vector<Vec3>& atomCoordinates,
double* parameters,
vector<Vec3>& forces,
double* totalEnergy, double* energyParamDerivs) {
// number of parameters
static const int numberOfParameters = 6;
static const int LastAtomIndex = 4;
RealOpenMM deltaR[3][ReferenceForce::LastDeltaRIndex];
double deltaR[3][ReferenceForce::LastDeltaRIndex];
RealOpenMM crossProductMemory[6];
double crossProductMemory[6];
// ---------------------------------------------------------------------------------------
......@@ -116,65 +101,65 @@ void ReferenceRbDihedralBond::calculateBondIxn(int* atomIndices,
ReferenceForce::getDeltaR(atomCoordinates[atomDIndex], atomCoordinates[atomCIndex], deltaR[2]);
}
RealOpenMM cosPhi;
RealOpenMM signOfAngle;
int hasREntry = 1;
double cosPhi;
double signOfAngle;
int hasREntry = 1;
// Visual Studio complains if crossProduct declared as 'crossProduct[2][3]'
RealOpenMM* crossProduct[2];
double* crossProduct[2];
crossProduct[0] = crossProductMemory;
crossProduct[1] = crossProductMemory + 3;
RealOpenMM dihederalAngle = getDihedralAngleBetweenThreeVectors(deltaR[0], deltaR[1], deltaR[2],
crossProduct, &cosPhi, deltaR[0],
&signOfAngle, hasREntry);
double dihederalAngle = getDihedralAngleBetweenThreeVectors(deltaR[0], deltaR[1], deltaR[2],
crossProduct, &cosPhi, deltaR[0],
&signOfAngle, hasREntry);
// Gromacs: use polymer convention
if (dihederalAngle < zero) {
if (dihederalAngle < 0.0) {
dihederalAngle += PI_M;
} else {
dihederalAngle -= PI_M;
}
cosPhi *= -one;
cosPhi *= -1.0;
// Ryckaert-Bellemans:
// V = sum over i: { C_i*cos(psi)**i }, where psi = phi - PI,
// C_i is ith RB coefficient
RealOpenMM dEdAngle = zero;
RealOpenMM energy = parameters[0];
RealOpenMM cosFactor = one;
double dEdAngle = 0.0;
double energy = parameters[0];
double cosFactor = 1.0;
for (int ii = 1; ii < numberOfParameters; ii++) {
dEdAngle -= ((RealOpenMM) ii)*parameters[ii]*cosFactor;
dEdAngle -= ii*parameters[ii]*cosFactor;
cosFactor *= cosPhi;
energy += cosFactor*parameters[ii];
}
dEdAngle *= SIN(dihederalAngle);
RealOpenMM internalF[4][3];
RealOpenMM forceFactors[4];
RealOpenMM normCross1 = DOT3(crossProduct[0], crossProduct[0]);
RealOpenMM normBC = deltaR[1][ReferenceForce::RIndex];
forceFactors[0] = (-dEdAngle*normBC)/normCross1;
double internalF[4][3];
double forceFactors[4];
double normCross1 = DOT3(crossProduct[0], crossProduct[0]);
double normBC = deltaR[1][ReferenceForce::RIndex];
forceFactors[0] = (-dEdAngle*normBC)/normCross1;
double normCross2 = DOT3(crossProduct[1], crossProduct[1]);
forceFactors[3] = (dEdAngle*normBC)/normCross2;
RealOpenMM normCross2 = DOT3(crossProduct[1], crossProduct[1]);
forceFactors[3] = (dEdAngle*normBC)/normCross2;
forceFactors[1] = DOT3(deltaR[0], deltaR[1]);
forceFactors[1] /= deltaR[1][ReferenceForce::R2Index];
forceFactors[1] = DOT3(deltaR[0], deltaR[1]);
forceFactors[1] /= deltaR[1][ReferenceForce::R2Index];
forceFactors[2] = DOT3(deltaR[2], deltaR[1]);
forceFactors[2] /= deltaR[1][ReferenceForce::R2Index];
forceFactors[2] = DOT3(deltaR[2], deltaR[1]);
forceFactors[2] /= deltaR[1][ReferenceForce::R2Index];
for (int ii = 0; ii < 3; ii++) {
internalF[0][ii] = forceFactors[0]*crossProduct[0][ii];
internalF[3][ii] = forceFactors[3]*crossProduct[1][ii];
RealOpenMM s = forceFactors[1]*internalF[0][ii] - forceFactors[2]*internalF[3][ii];
double s = forceFactors[1]*internalF[0][ii] - forceFactors[2]*internalF[3][ii];
internalF[1][ii] = internalF[0][ii] - s;
internalF[2][ii] = internalF[3][ii] + s;
......
......@@ -35,7 +35,7 @@ using namespace OpenMM;
using namespace std;
ReferenceSETTLEAlgorithm::ReferenceSETTLEAlgorithm(const vector<int>& atom1, const vector<int>& atom2, const vector<int>& atom3,
const vector<RealOpenMM>& distance1, const vector<RealOpenMM>& distance2, vector<RealOpenMM>& masses) :
const vector<double>& distance1, const vector<double>& distance2, vector<double>& masses) :
atom1(atom1), atom2(atom2), atom3(atom3), distance1(distance1), distance2(distance2), masses(masses) {
}
......@@ -43,7 +43,7 @@ int ReferenceSETTLEAlgorithm::getNumClusters() const {
return atom1.size();
}
void ReferenceSETTLEAlgorithm::getClusterParameters(int index, int& atom1, int& atom2, int& atom3, RealOpenMM& distance1, RealOpenMM& distance2) const {
void ReferenceSETTLEAlgorithm::getClusterParameters(int index, int& atom1, int& atom2, int& atom3, double& distance1, double& distance2) const {
atom1 = this->atom1[index];
atom2 = this->atom2[index];
atom3 = this->atom3[index];
......@@ -51,130 +51,130 @@ void ReferenceSETTLEAlgorithm::getClusterParameters(int index, int& atom1, int&
distance2 = this->distance2[index];
}
void ReferenceSETTLEAlgorithm::apply(vector<OpenMM::RealVec>& atomCoordinates, vector<OpenMM::RealVec>& atomCoordinatesP, vector<RealOpenMM>& inverseMasses, RealOpenMM tolerance) {
void ReferenceSETTLEAlgorithm::apply(vector<OpenMM::Vec3>& atomCoordinates, vector<OpenMM::Vec3>& atomCoordinatesP, vector<double>& inverseMasses, double tolerance) {
for (int index = 0; index < (int) atom1.size(); ++index) {
RealVec apos0 = atomCoordinates[atom1[index]];
RealVec xp0 = atomCoordinatesP[atom1[index]]-apos0;
RealVec apos1 = atomCoordinates[atom2[index]];
RealVec xp1 = atomCoordinatesP[atom2[index]]-apos1;
RealVec apos2 = atomCoordinates[atom3[index]];
RealVec xp2 = atomCoordinatesP[atom3[index]]-apos2;
RealOpenMM m0 = masses[atom1[index]];
RealOpenMM m1 = masses[atom2[index]];
RealOpenMM m2 = masses[atom3[index]];
Vec3 apos0 = atomCoordinates[atom1[index]];
Vec3 xp0 = atomCoordinatesP[atom1[index]]-apos0;
Vec3 apos1 = atomCoordinates[atom2[index]];
Vec3 xp1 = atomCoordinatesP[atom2[index]]-apos1;
Vec3 apos2 = atomCoordinates[atom3[index]];
Vec3 xp2 = atomCoordinatesP[atom3[index]]-apos2;
double m0 = masses[atom1[index]];
double m1 = masses[atom2[index]];
double m2 = masses[atom3[index]];
// Apply the SETTLE algorithm.
RealOpenMM xb0 = apos1[0]-apos0[0];
RealOpenMM yb0 = apos1[1]-apos0[1];
RealOpenMM zb0 = apos1[2]-apos0[2];
RealOpenMM xc0 = apos2[0]-apos0[0];
RealOpenMM yc0 = apos2[1]-apos0[1];
RealOpenMM zc0 = apos2[2]-apos0[2];
RealOpenMM invTotalMass = 1/(m0+m1+m2);
RealOpenMM xcom = (xp0[0]*m0 + (xb0+xp1[0])*m1 + (xc0+xp2[0])*m2) * invTotalMass;
RealOpenMM ycom = (xp0[1]*m0 + (yb0+xp1[1])*m1 + (yc0+xp2[1])*m2) * invTotalMass;
RealOpenMM zcom = (xp0[2]*m0 + (zb0+xp1[2])*m1 + (zc0+xp2[2])*m2) * invTotalMass;
RealOpenMM xa1 = xp0[0] - xcom;
RealOpenMM ya1 = xp0[1] - ycom;
RealOpenMM za1 = xp0[2] - zcom;
RealOpenMM xb1 = xb0 + xp1[0] - xcom;
RealOpenMM yb1 = yb0 + xp1[1] - ycom;
RealOpenMM zb1 = zb0 + xp1[2] - zcom;
RealOpenMM xc1 = xc0 + xp2[0] - xcom;
RealOpenMM yc1 = yc0 + xp2[1] - ycom;
RealOpenMM zc1 = zc0 + xp2[2] - zcom;
RealOpenMM xaksZd = yb0*zc0 - zb0*yc0;
RealOpenMM yaksZd = zb0*xc0 - xb0*zc0;
RealOpenMM zaksZd = xb0*yc0 - yb0*xc0;
RealOpenMM xaksXd = ya1*zaksZd - za1*yaksZd;
RealOpenMM yaksXd = za1*xaksZd - xa1*zaksZd;
RealOpenMM zaksXd = xa1*yaksZd - ya1*xaksZd;
RealOpenMM xaksYd = yaksZd*zaksXd - zaksZd*yaksXd;
RealOpenMM yaksYd = zaksZd*xaksXd - xaksZd*zaksXd;
RealOpenMM zaksYd = xaksZd*yaksXd - yaksZd*xaksXd;
RealOpenMM axlng = sqrt(xaksXd*xaksXd + yaksXd*yaksXd + zaksXd*zaksXd);
RealOpenMM aylng = sqrt(xaksYd*xaksYd + yaksYd*yaksYd + zaksYd*zaksYd);
RealOpenMM azlng = sqrt(xaksZd*xaksZd + yaksZd*yaksZd + zaksZd*zaksZd);
RealOpenMM trns11 = xaksXd / axlng;
RealOpenMM trns21 = yaksXd / axlng;
RealOpenMM trns31 = zaksXd / axlng;
RealOpenMM trns12 = xaksYd / aylng;
RealOpenMM trns22 = yaksYd / aylng;
RealOpenMM trns32 = zaksYd / aylng;
RealOpenMM trns13 = xaksZd / azlng;
RealOpenMM trns23 = yaksZd / azlng;
RealOpenMM trns33 = zaksZd / azlng;
RealOpenMM xb0d = trns11*xb0 + trns21*yb0 + trns31*zb0;
RealOpenMM yb0d = trns12*xb0 + trns22*yb0 + trns32*zb0;
RealOpenMM xc0d = trns11*xc0 + trns21*yc0 + trns31*zc0;
RealOpenMM yc0d = trns12*xc0 + trns22*yc0 + trns32*zc0;
RealOpenMM za1d = trns13*xa1 + trns23*ya1 + trns33*za1;
RealOpenMM xb1d = trns11*xb1 + trns21*yb1 + trns31*zb1;
RealOpenMM yb1d = trns12*xb1 + trns22*yb1 + trns32*zb1;
RealOpenMM zb1d = trns13*xb1 + trns23*yb1 + trns33*zb1;
RealOpenMM xc1d = trns11*xc1 + trns21*yc1 + trns31*zc1;
RealOpenMM yc1d = trns12*xc1 + trns22*yc1 + trns32*zc1;
RealOpenMM zc1d = trns13*xc1 + trns23*yc1 + trns33*zc1;
double xb0 = apos1[0]-apos0[0];
double yb0 = apos1[1]-apos0[1];
double zb0 = apos1[2]-apos0[2];
double xc0 = apos2[0]-apos0[0];
double yc0 = apos2[1]-apos0[1];
double zc0 = apos2[2]-apos0[2];
double invTotalMass = 1/(m0+m1+m2);
double xcom = (xp0[0]*m0 + (xb0+xp1[0])*m1 + (xc0+xp2[0])*m2) * invTotalMass;
double ycom = (xp0[1]*m0 + (yb0+xp1[1])*m1 + (yc0+xp2[1])*m2) * invTotalMass;
double zcom = (xp0[2]*m0 + (zb0+xp1[2])*m1 + (zc0+xp2[2])*m2) * invTotalMass;
double xa1 = xp0[0] - xcom;
double ya1 = xp0[1] - ycom;
double za1 = xp0[2] - zcom;
double xb1 = xb0 + xp1[0] - xcom;
double yb1 = yb0 + xp1[1] - ycom;
double zb1 = zb0 + xp1[2] - zcom;
double xc1 = xc0 + xp2[0] - xcom;
double yc1 = yc0 + xp2[1] - ycom;
double zc1 = zc0 + xp2[2] - zcom;
double xaksZd = yb0*zc0 - zb0*yc0;
double yaksZd = zb0*xc0 - xb0*zc0;
double zaksZd = xb0*yc0 - yb0*xc0;
double xaksXd = ya1*zaksZd - za1*yaksZd;
double yaksXd = za1*xaksZd - xa1*zaksZd;
double zaksXd = xa1*yaksZd - ya1*xaksZd;
double xaksYd = yaksZd*zaksXd - zaksZd*yaksXd;
double yaksYd = zaksZd*xaksXd - xaksZd*zaksXd;
double zaksYd = xaksZd*yaksXd - yaksZd*xaksXd;
double axlng = sqrt(xaksXd*xaksXd + yaksXd*yaksXd + zaksXd*zaksXd);
double aylng = sqrt(xaksYd*xaksYd + yaksYd*yaksYd + zaksYd*zaksYd);
double azlng = sqrt(xaksZd*xaksZd + yaksZd*yaksZd + zaksZd*zaksZd);
double trns11 = xaksXd / axlng;
double trns21 = yaksXd / axlng;
double trns31 = zaksXd / axlng;
double trns12 = xaksYd / aylng;
double trns22 = yaksYd / aylng;
double trns32 = zaksYd / aylng;
double trns13 = xaksZd / azlng;
double trns23 = yaksZd / azlng;
double trns33 = zaksZd / azlng;
double xb0d = trns11*xb0 + trns21*yb0 + trns31*zb0;
double yb0d = trns12*xb0 + trns22*yb0 + trns32*zb0;
double xc0d = trns11*xc0 + trns21*yc0 + trns31*zc0;
double yc0d = trns12*xc0 + trns22*yc0 + trns32*zc0;
double za1d = trns13*xa1 + trns23*ya1 + trns33*za1;
double xb1d = trns11*xb1 + trns21*yb1 + trns31*zb1;
double yb1d = trns12*xb1 + trns22*yb1 + trns32*zb1;
double zb1d = trns13*xb1 + trns23*yb1 + trns33*zb1;
double xc1d = trns11*xc1 + trns21*yc1 + trns31*zc1;
double yc1d = trns12*xc1 + trns22*yc1 + trns32*zc1;
double zc1d = trns13*xc1 + trns23*yc1 + trns33*zc1;
// --- Step2 A2' ---
RealOpenMM rc = 0.5*distance2[index];
RealOpenMM rb = sqrt(distance1[index]*distance1[index]-rc*rc);
RealOpenMM ra = rb*(m1+m2)*invTotalMass;
double rc = 0.5*distance2[index];
double rb = sqrt(distance1[index]*distance1[index]-rc*rc);
double ra = rb*(m1+m2)*invTotalMass;
rb -= ra;
RealOpenMM sinphi = za1d / ra;
RealOpenMM cosphi = sqrt(1 - sinphi*sinphi);
RealOpenMM sinpsi = (zb1d - zc1d) / (2*rc*cosphi);
RealOpenMM cospsi = sqrt(1 - sinpsi*sinpsi);
RealOpenMM ya2d = ra*cosphi;
RealOpenMM xb2d = - rc*cospsi;
RealOpenMM yb2d = - rb*cosphi - rc*sinpsi*sinphi;
RealOpenMM yc2d = - rb*cosphi + rc*sinpsi*sinphi;
RealOpenMM xb2d2 = xb2d*xb2d;
RealOpenMM hh2 = 4.0f*xb2d2 + (yb2d-yc2d)*(yb2d-yc2d) + (zb1d-zc1d)*(zb1d-zc1d);
RealOpenMM deltx = 2.0f*xb2d + sqrt(4.0f*xb2d2 - hh2 + distance2[index]*distance2[index]);
double sinphi = za1d / ra;
double cosphi = sqrt(1 - sinphi*sinphi);
double sinpsi = (zb1d - zc1d) / (2*rc*cosphi);
double cospsi = sqrt(1 - sinpsi*sinpsi);
double ya2d = ra*cosphi;
double xb2d = - rc*cospsi;
double yb2d = - rb*cosphi - rc*sinpsi*sinphi;
double yc2d = - rb*cosphi + rc*sinpsi*sinphi;
double xb2d2 = xb2d*xb2d;
double hh2 = 4.0f*xb2d2 + (yb2d-yc2d)*(yb2d-yc2d) + (zb1d-zc1d)*(zb1d-zc1d);
double deltx = 2.0f*xb2d + sqrt(4.0f*xb2d2 - hh2 + distance2[index]*distance2[index]);
xb2d -= deltx*0.5;
// --- Step3 al,be,ga ---
RealOpenMM alpha = (xb2d*(xb0d-xc0d) + yb0d*yb2d + yc0d*yc2d);
RealOpenMM beta = (xb2d*(yc0d-yb0d) + xb0d*yb2d + xc0d*yc2d);
RealOpenMM gamma = xb0d*yb1d - xb1d*yb0d + xc0d*yc1d - xc1d*yc0d;
double alpha = (xb2d*(xb0d-xc0d) + yb0d*yb2d + yc0d*yc2d);
double beta = (xb2d*(yc0d-yb0d) + xb0d*yb2d + xc0d*yc2d);
double gamma = xb0d*yb1d - xb1d*yb0d + xc0d*yc1d - xc1d*yc0d;
RealOpenMM al2be2 = alpha*alpha + beta*beta;
RealOpenMM sintheta = (alpha*gamma - beta*sqrt(al2be2 - gamma*gamma)) / al2be2;
double al2be2 = alpha*alpha + beta*beta;
double sintheta = (alpha*gamma - beta*sqrt(al2be2 - gamma*gamma)) / al2be2;
// --- Step4 A3' ---
RealOpenMM costheta = sqrt(1 - sintheta*sintheta);
RealOpenMM xa3d = - ya2d*sintheta;
RealOpenMM ya3d = ya2d*costheta;
RealOpenMM za3d = za1d;
RealOpenMM xb3d = xb2d*costheta - yb2d*sintheta;
RealOpenMM yb3d = xb2d*sintheta + yb2d*costheta;
RealOpenMM zb3d = zb1d;
RealOpenMM xc3d = - xb2d*costheta - yc2d*sintheta;
RealOpenMM yc3d = - xb2d*sintheta + yc2d*costheta;
RealOpenMM zc3d = zc1d;
double costheta = sqrt(1 - sintheta*sintheta);
double xa3d = - ya2d*sintheta;
double ya3d = ya2d*costheta;
double za3d = za1d;
double xb3d = xb2d*costheta - yb2d*sintheta;
double yb3d = xb2d*sintheta + yb2d*costheta;
double zb3d = zb1d;
double xc3d = - xb2d*costheta - yc2d*sintheta;
double yc3d = - xb2d*sintheta + yc2d*costheta;
double zc3d = zc1d;
// --- Step5 A3 ---
RealOpenMM xa3 = trns11*xa3d + trns12*ya3d + trns13*za3d;
RealOpenMM ya3 = trns21*xa3d + trns22*ya3d + trns23*za3d;
RealOpenMM za3 = trns31*xa3d + trns32*ya3d + trns33*za3d;
RealOpenMM xb3 = trns11*xb3d + trns12*yb3d + trns13*zb3d;
RealOpenMM yb3 = trns21*xb3d + trns22*yb3d + trns23*zb3d;
RealOpenMM zb3 = trns31*xb3d + trns32*yb3d + trns33*zb3d;
RealOpenMM xc3 = trns11*xc3d + trns12*yc3d + trns13*zc3d;
RealOpenMM yc3 = trns21*xc3d + trns22*yc3d + trns23*zc3d;
RealOpenMM zc3 = trns31*xc3d + trns32*yc3d + trns33*zc3d;
double xa3 = trns11*xa3d + trns12*ya3d + trns13*za3d;
double ya3 = trns21*xa3d + trns22*ya3d + trns23*za3d;
double za3 = trns31*xa3d + trns32*ya3d + trns33*za3d;
double xb3 = trns11*xb3d + trns12*yb3d + trns13*zb3d;
double yb3 = trns21*xb3d + trns22*yb3d + trns23*zb3d;
double zb3 = trns31*xb3d + trns32*yb3d + trns33*zb3d;
double xc3 = trns11*xc3d + trns12*yc3d + trns13*zc3d;
double yc3 = trns21*xc3d + trns22*yc3d + trns23*zc3d;
double zc3 = trns31*xc3d + trns32*yc3d + trns33*zc3d;
xp0[0] = xcom + xa3;
xp0[1] = ycom + ya3;
......@@ -194,46 +194,46 @@ void ReferenceSETTLEAlgorithm::apply(vector<OpenMM::RealVec>& atomCoordinates, v
}
}
void ReferenceSETTLEAlgorithm::applyToVelocities(vector<OpenMM::RealVec>& atomCoordinates, vector<OpenMM::RealVec>& velocities, vector<RealOpenMM>& inverseMasses, RealOpenMM tolerance) {
void ReferenceSETTLEAlgorithm::applyToVelocities(vector<OpenMM::Vec3>& atomCoordinates, vector<OpenMM::Vec3>& velocities, vector<double>& inverseMasses, double tolerance) {
for (int index = 0; index < (int) atom1.size(); ++index) {
RealVec apos0 = atomCoordinates[atom1[index]];
RealVec apos1 = atomCoordinates[atom2[index]];
RealVec apos2 = atomCoordinates[atom3[index]];
RealVec v0 = velocities[atom1[index]];
RealVec v1 = velocities[atom2[index]];
RealVec v2 = velocities[atom3[index]];
Vec3 apos0 = atomCoordinates[atom1[index]];
Vec3 apos1 = atomCoordinates[atom2[index]];
Vec3 apos2 = atomCoordinates[atom3[index]];
Vec3 v0 = velocities[atom1[index]];
Vec3 v1 = velocities[atom2[index]];
Vec3 v2 = velocities[atom3[index]];
// Compute intermediate quantities: the atom masses, the bond directions, the relative velocities,
// and the angle cosines and sines.
RealOpenMM mA = masses[atom1[index]];
RealOpenMM mB = masses[atom2[index]];
RealOpenMM mC = masses[atom3[index]];
RealVec eAB = apos1-apos0;
RealVec eBC = apos2-apos1;
RealVec eCA = apos0-apos2;
double mA = masses[atom1[index]];
double mB = masses[atom2[index]];
double mC = masses[atom3[index]];
Vec3 eAB = apos1-apos0;
Vec3 eBC = apos2-apos1;
Vec3 eCA = apos0-apos2;
eAB /= sqrt(eAB[0]*eAB[0] + eAB[1]*eAB[1] + eAB[2]*eAB[2]);
eBC /= sqrt(eBC[0]*eBC[0] + eBC[1]*eBC[1] + eBC[2]*eBC[2]);
eCA /= sqrt(eCA[0]*eCA[0] + eCA[1]*eCA[1] + eCA[2]*eCA[2]);
RealOpenMM vAB = (v1[0]-v0[0])*eAB[0] + (v1[1]-v0[1])*eAB[1] + (v1[2]-v0[2])*eAB[2];
RealOpenMM vBC = (v2[0]-v1[0])*eBC[0] + (v2[1]-v1[1])*eBC[1] + (v2[2]-v1[2])*eBC[2];
RealOpenMM vCA = (v0[0]-v2[0])*eCA[0] + (v0[1]-v2[1])*eCA[1] + (v0[2]-v2[2])*eCA[2];
RealOpenMM cA = -(eAB[0]*eCA[0] + eAB[1]*eCA[1] + eAB[2]*eCA[2]);
RealOpenMM cB = -(eAB[0]*eBC[0] + eAB[1]*eBC[1] + eAB[2]*eBC[2]);
RealOpenMM cC = -(eBC[0]*eCA[0] + eBC[1]*eCA[1] + eBC[2]*eCA[2]);
RealOpenMM s2A = 1-cA*cA;
RealOpenMM s2B = 1-cB*cB;
RealOpenMM s2C = 1-cC*cC;
double vAB = (v1[0]-v0[0])*eAB[0] + (v1[1]-v0[1])*eAB[1] + (v1[2]-v0[2])*eAB[2];
double vBC = (v2[0]-v1[0])*eBC[0] + (v2[1]-v1[1])*eBC[1] + (v2[2]-v1[2])*eBC[2];
double vCA = (v0[0]-v2[0])*eCA[0] + (v0[1]-v2[1])*eCA[1] + (v0[2]-v2[2])*eCA[2];
double cA = -(eAB[0]*eCA[0] + eAB[1]*eCA[1] + eAB[2]*eCA[2]);
double cB = -(eAB[0]*eBC[0] + eAB[1]*eBC[1] + eAB[2]*eBC[2]);
double cC = -(eBC[0]*eCA[0] + eBC[1]*eCA[1] + eBC[2]*eCA[2]);
double s2A = 1-cA*cA;
double s2B = 1-cB*cB;
double s2C = 1-cC*cC;
// Solve the equations. These are different from those in the SETTLE paper (JCC 13(8), pp. 952-962, 1992), because
// in going from equations B1 to B2, they make the assumption that mB=mC (but don't bother to mention they're
// making that assumption). We allow all three atoms to have different masses.
RealOpenMM mABCinv = 1/(mA*mB*mC);
RealOpenMM denom = (((s2A*mB+s2B*mA)*mC+(s2A*mB*mB+2*(cA*cB*cC+1)*mA*mB+s2B*mA*mA))*mC+s2C*mA*mB*(mA+mB))*mABCinv;
RealOpenMM tab = ((cB*cC*mA-cA*mB-cA*mC)*vCA + (cA*cC*mB-cB*mC-cB*mA)*vBC + (s2C*mA*mA*mB*mB*mABCinv+(mA+mB+mC))*vAB)/denom;
RealOpenMM tbc = ((cA*cB*mC-cC*mB-cC*mA)*vCA + (s2A*mB*mB*mC*mC*mABCinv+(mA+mB+mC))*vBC + (cA*cC*mB-cB*mA-cB*mC)*vAB)/denom;
RealOpenMM tca = ((s2B*mA*mA*mC*mC*mABCinv+(mA+mB+mC))*vCA + (cA*cB*mC-cC*mB-cC*mA)*vBC + (cB*cC*mA-cA*mB-cA*mC)*vAB)/denom;
double mABCinv = 1/(mA*mB*mC);
double denom = (((s2A*mB+s2B*mA)*mC+(s2A*mB*mB+2*(cA*cB*cC+1)*mA*mB+s2B*mA*mA))*mC+s2C*mA*mB*(mA+mB))*mABCinv;
double tab = ((cB*cC*mA-cA*mB-cA*mC)*vCA + (cA*cC*mB-cB*mC-cB*mA)*vBC + (s2C*mA*mA*mB*mB*mABCinv+(mA+mB+mC))*vAB)/denom;
double tbc = ((cA*cB*mC-cC*mB-cC*mA)*vCA + (s2A*mB*mB*mC*mC*mABCinv+(mA+mB+mC))*vBC + (cA*cC*mB-cB*mA-cB*mC)*vAB)/denom;
double tca = ((s2B*mA*mA*mC*mC*mABCinv+(mA+mB+mC))*vCA + (cA*cB*mC-cC*mB-cC*mA)*vBC + (cB*cC*mA-cA*mB-cA*mC)*vAB)/denom;
v0 += (eAB*tab - eCA*tca)*inverseMasses[atom1[index]];
v1 += (eBC*tbc - eAB*tab)*inverseMasses[atom2[index]];
v2 += (eCA*tca - eBC*tbc)*inverseMasses[atom3[index]];
......
/* Portions copyright (c) 2006-2013 Stanford University and Simbios.
/* Portions copyright (c) 2006-2016 Stanford University and Simbios.
* Contributors: Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
......@@ -41,20 +41,15 @@ using namespace OpenMM;
@param numberOfAtoms number of atoms
@param deltaT delta t for dynamics
@param tau viscosity(?)
@param friction friction coefficient
@param temperature temperature
--------------------------------------------------------------------------------------- */
ReferenceStochasticDynamics::ReferenceStochasticDynamics(int numberOfAtoms,
RealOpenMM deltaT, RealOpenMM tau,
RealOpenMM temperature) :
ReferenceDynamics(numberOfAtoms, deltaT, temperature), _tau(tau) {
if (tau <= 0) {
std::stringstream message;
message << "illegal tau value: " << tau;
throw OpenMMException(message.str());
}
double deltaT, double friction,
double temperature) :
ReferenceDynamics(numberOfAtoms, deltaT, temperature), friction(friction) {
xPrime.resize(numberOfAtoms);
inverseMasses.resize(numberOfAtoms);
}
......@@ -66,32 +61,16 @@ ReferenceStochasticDynamics::ReferenceStochasticDynamics(int numberOfAtoms,
--------------------------------------------------------------------------------------- */
ReferenceStochasticDynamics::~ReferenceStochasticDynamics() {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceStochasticDynamics::~ReferenceStochasticDynamics";
// ---------------------------------------------------------------------------------------
}
/**---------------------------------------------------------------------------------------
Get tau
@return tau
Get friction coefficient
--------------------------------------------------------------------------------------- */
RealOpenMM ReferenceStochasticDynamics::getTau() const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceStochasticDynamics::getTau";
// ---------------------------------------------------------------------------------------
return _tau;
double ReferenceStochasticDynamics::getFriction() const {
return friction;
}
/**---------------------------------------------------------------------------------------
......@@ -107,28 +86,22 @@ RealOpenMM ReferenceStochasticDynamics::getTau() const {
--------------------------------------------------------------------------------------- */
void ReferenceStochasticDynamics::updatePart1(int numberOfAtoms, vector<RealVec>& atomCoordinates,
vector<RealVec>& velocities,
vector<RealVec>& forces, vector<RealOpenMM>& inverseMasses,
vector<RealVec>& xPrime) {
// ---------------------------------------------------------------------------------------
//static const char* methodName = "\nReferenceStochasticDynamics::updatePart1";
// ---------------------------------------------------------------------------------------
void ReferenceStochasticDynamics::updatePart1(int numberOfAtoms, vector<Vec3>& atomCoordinates,
vector<Vec3>& velocities,
vector<Vec3>& forces, vector<double>& inverseMasses,
vector<Vec3>& xPrime) {
// perform first update
RealOpenMM tau = getTau();
const RealOpenMM vscale = EXP(-getDeltaT()/tau);
const RealOpenMM fscale = (1-vscale)*tau;
const RealOpenMM kT = BOLTZ*getTemperature();
const RealOpenMM noisescale = SQRT(2*kT/tau)*SQRT(0.5*(1-vscale*vscale)*tau);
double dt = getDeltaT();
double friction = getFriction();
const double vscale = exp(-dt*friction);
const double fscale = (friction == 0 ? dt : (1-vscale)/friction);
const double kT = BOLTZ*getTemperature();
const double noisescale = sqrt(kT*(1-vscale*vscale));
for (int ii = 0; ii < numberOfAtoms; ii++) {
if (inverseMasses[ii] != 0.0) {
RealOpenMM sqrtInvMass = SQRT(inverseMasses[ii]);
double sqrtInvMass = sqrt(inverseMasses[ii]);
for (int jj = 0; jj < 3; jj++) {
velocities[ii][jj] = vscale*velocities[ii][jj] + fscale*inverseMasses[ii]*forces[ii][jj] + noisescale*sqrtInvMass*SimTKOpenMMUtilities::getNormallyDistributedRandomNumber();
}
......@@ -148,17 +121,10 @@ void ReferenceStochasticDynamics::updatePart1(int numberOfAtoms, vector<RealVec>
--------------------------------------------------------------------------------------- */
void ReferenceStochasticDynamics::updatePart2(int numberOfAtoms, vector<RealVec>& atomCoordinates,
vector<RealVec>& velocities,
vector<RealVec>& forces, vector<RealOpenMM>& inverseMasses,
vector<RealVec>& xPrime) {
// ---------------------------------------------------------------------------------------
//static const char* methodName = "\nReferenceStochasticDynamics::updatePart2";
// ---------------------------------------------------------------------------------------
void ReferenceStochasticDynamics::updatePart2(int numberOfAtoms, vector<Vec3>& atomCoordinates,
vector<Vec3>& velocities,
vector<Vec3>& forces, vector<double>& inverseMasses,
vector<Vec3>& xPrime) {
// perform second update
for (int ii = 0; ii < numberOfAtoms; ii++) {
......@@ -167,10 +133,10 @@ void ReferenceStochasticDynamics::updatePart2(int numberOfAtoms, vector<RealVec>
}
}
void ReferenceStochasticDynamics::updatePart3(int numberOfAtoms, vector<RealVec>& atomCoordinates,
vector<RealVec>& velocities, vector<RealOpenMM>& inverseMasses,
vector<RealVec>& xPrime) {
RealOpenMM invStepSize = 1.0/getDeltaT();
void ReferenceStochasticDynamics::updatePart3(int numberOfAtoms, vector<Vec3>& atomCoordinates,
vector<Vec3>& velocities, vector<double>& inverseMasses,
vector<Vec3>& xPrime) {
double invStepSize = 1.0/getDeltaT();
for (int i = 0; i < numberOfAtoms; ++i)
if (inverseMasses[i] != 0) {
velocities[i] = (xPrime[i]-atomCoordinates[i])*invStepSize;
......@@ -191,18 +157,8 @@ void ReferenceStochasticDynamics::updatePart3(int numberOfAtoms, vector<RealVec>
--------------------------------------------------------------------------------------- */
void ReferenceStochasticDynamics::update(const OpenMM::System& system, vector<RealVec>& atomCoordinates,
vector<RealVec>& velocities, vector<RealVec>& forces, vector<RealOpenMM>& masses, RealOpenMM tolerance) {
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nReferenceStochasticDynamics::update";
static const RealOpenMM zero = 0.0;
static const RealOpenMM one = 1.0;
// ---------------------------------------------------------------------------------------
void ReferenceStochasticDynamics::update(const OpenMM::System& system, vector<Vec3>& atomCoordinates,
vector<Vec3>& velocities, vector<Vec3>& forces, vector<double>& masses, double tolerance) {
// first-time-through initialization
int numberOfAtoms = system.getNumParticles();
......@@ -210,10 +166,10 @@ void ReferenceStochasticDynamics::update(const OpenMM::System& system, vector<Re
// invert masses
for (int ii = 0; ii < numberOfAtoms; ii++) {
if (masses[ii] == zero)
inverseMasses[ii] = zero;
if (masses[ii] == 0.0)
inverseMasses[ii] = 0.0;
else
inverseMasses[ii] = one/masses[ii];
inverseMasses[ii] = 1.0/masses[ii];
}
}
......
/* Portions copyright (c) 2006-2013 Stanford University and Simbios.
/* Portions copyright (c) 2006-2016 Stanford University and Simbios.
* Contributors: Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
......@@ -42,21 +42,16 @@ using namespace OpenMM;
@param numberOfAtoms number of atoms
@param deltaT delta t for dynamics
@param tau viscosity(?)
@param friction friction coefficient
@param temperature temperature
@param accuracy required accuracy
--------------------------------------------------------------------------------------- */
ReferenceVariableStochasticDynamics::ReferenceVariableStochasticDynamics(int numberOfAtoms,
RealOpenMM tau, RealOpenMM temperature,
RealOpenMM accuracy) :
ReferenceDynamics(numberOfAtoms, 0.0f, temperature), _tau(tau), _accuracy(accuracy) {
if (tau <= 0) {
std::stringstream message;
message << "illegal tau value: " << tau;
throw OpenMMException(message.str());
}
double friction, double temperature,
double accuracy) :
ReferenceDynamics(numberOfAtoms, 0.0f, temperature), friction(friction), _accuracy(accuracy) {
xPrime.resize(numberOfAtoms);
inverseMasses.resize(numberOfAtoms);
}
......@@ -68,13 +63,6 @@ ReferenceVariableStochasticDynamics::ReferenceVariableStochasticDynamics(int num
--------------------------------------------------------------------------------------- */
ReferenceVariableStochasticDynamics::~ReferenceVariableStochasticDynamics() {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceVariableStochasticDynamics::~ReferenceVariableStochasticDynamics";
// ---------------------------------------------------------------------------------------
}
/**---------------------------------------------------------------------------------------
......@@ -85,7 +73,7 @@ ReferenceVariableStochasticDynamics::~ReferenceVariableStochasticDynamics() {
--------------------------------------------------------------------------------------- */
RealOpenMM ReferenceVariableStochasticDynamics::getAccuracy() const {
double ReferenceVariableStochasticDynamics::getAccuracy() const {
return _accuracy;
}
......@@ -95,27 +83,18 @@ RealOpenMM ReferenceVariableStochasticDynamics::getAccuracy() const {
--------------------------------------------------------------------------------------- */
void ReferenceVariableStochasticDynamics::setAccuracy(RealOpenMM accuracy) {
void ReferenceVariableStochasticDynamics::setAccuracy(double accuracy) {
_accuracy = accuracy;
}
/**---------------------------------------------------------------------------------------
Get tau
@return tau
Get friction coefficient
--------------------------------------------------------------------------------------- */
RealOpenMM ReferenceVariableStochasticDynamics::getTau() const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceVariableStochasticDynamics::getTau";
// ---------------------------------------------------------------------------------------
return _tau;
double ReferenceVariableStochasticDynamics::getFriction() const {
return friction;
}
/**---------------------------------------------------------------------------------------
......@@ -133,18 +112,10 @@ RealOpenMM ReferenceVariableStochasticDynamics::getTau() const {
--------------------------------------------------------------------------------------- */
void ReferenceVariableStochasticDynamics::updatePart1(int numberOfAtoms, vector<RealVec>& atomCoordinates,
vector<RealVec>& velocities,
vector<RealVec>& forces, vector<RealOpenMM>& masses, vector<RealOpenMM>& inverseMasses,
vector<RealVec>& xPrime, RealOpenMM maxStepSize) {
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nReferenceVariableStochasticDynamics::updatePart1";
// ---------------------------------------------------------------------------------------
void ReferenceVariableStochasticDynamics::updatePart1(int numberOfAtoms, vector<Vec3>& atomCoordinates,
vector<Vec3>& velocities,
vector<Vec3>& forces, vector<double>& masses, vector<double>& inverseMasses,
vector<Vec3>& xPrime, double maxStepSize) {
// first-time-through initialization
if (getTimeStep() == 0) {
......@@ -159,15 +130,15 @@ void ReferenceVariableStochasticDynamics::updatePart1(int numberOfAtoms, vector<
}
// Select the step size to use
RealOpenMM error = 0;
double error = 0;
for (int i = 0; i < numberOfAtoms; ++i) {
for (int j = 0; j < 3; ++j) {
RealOpenMM xerror = inverseMasses[i]*forces[i][j];
double xerror = inverseMasses[i]*forces[i][j];
error += xerror*xerror;
}
}
error = SQRT(error/(numberOfAtoms*3));
RealOpenMM newStepSize = SQRT(getAccuracy()/error);
error = sqrt(error/(numberOfAtoms*3));
double newStepSize = sqrt(getAccuracy()/error);
if (getDeltaT() > 0.0f)
newStepSize = std::min(newStepSize, getDeltaT()*2.0f); // For safety, limit how quickly dt can increase.
if (newStepSize > getDeltaT() && newStepSize < 1.2f*getDeltaT())
......@@ -178,15 +149,16 @@ void ReferenceVariableStochasticDynamics::updatePart1(int numberOfAtoms, vector<
// perform first update
RealOpenMM tau = getTau();
const RealOpenMM vscale = EXP(-getDeltaT()/tau);
const RealOpenMM fscale = (1-vscale)*tau;
const RealOpenMM kT = BOLTZ*getTemperature();
const RealOpenMM noisescale = SQRT(2*kT/tau)*SQRT(0.5*(1-vscale*vscale)*tau);
double dt = getDeltaT();
double friction = getFriction();
const double vscale = exp(-dt*friction);
const double fscale = (friction == 0 ? dt : (1-vscale)/friction);
const double kT = BOLTZ*getTemperature();
const double noisescale = sqrt(kT*(1-vscale*vscale));
for (int ii = 0; ii < numberOfAtoms; ii++) {
if (masses[ii] != 0) {
RealOpenMM sqrtInvMass = SQRT(inverseMasses[ii]);
double sqrtInvMass = sqrt(inverseMasses[ii]);
for (int jj = 0; jj < 3; jj++) {
velocities[ii][jj] = vscale*velocities[ii][jj] + fscale*inverseMasses[ii]*forces[ii][jj] + noisescale*sqrtInvMass*SimTKOpenMMUtilities::getNormallyDistributedRandomNumber();
}
......@@ -207,17 +179,10 @@ void ReferenceVariableStochasticDynamics::updatePart1(int numberOfAtoms, vector<
--------------------------------------------------------------------------------------- */
void ReferenceVariableStochasticDynamics::updatePart2(int numberOfAtoms, vector<RealVec>& atomCoordinates,
vector<RealVec>& velocities,
vector<RealVec>& forces, vector<RealOpenMM>& inverseMasses,
vector<RealVec>& xPrime) {
// ---------------------------------------------------------------------------------------
//static const char* methodName = "\nReferenceVariableStochasticDynamics::updatePart2";
// ---------------------------------------------------------------------------------------
void ReferenceVariableStochasticDynamics::updatePart2(int numberOfAtoms, vector<Vec3>& atomCoordinates,
vector<Vec3>& velocities,
vector<Vec3>& forces, vector<double>& inverseMasses,
vector<Vec3>& xPrime) {
// perform second update
for (int ii = 0; ii < numberOfAtoms; ii++) {
......@@ -241,15 +206,9 @@ void ReferenceVariableStochasticDynamics::updatePart2(int numberOfAtoms, vector<
--------------------------------------------------------------------------------------- */
void ReferenceVariableStochasticDynamics::update(const OpenMM::System& system, vector<RealVec>& atomCoordinates,
vector<RealVec>& velocities,
vector<RealVec>& forces, vector<RealOpenMM>& masses, RealOpenMM maxStepSize, RealOpenMM tolerance) {
// ---------------------------------------------------------------------------------------
//static const char* methodName = "\nReferenceVariableStochasticDynamics::update";
// ---------------------------------------------------------------------------------------
void ReferenceVariableStochasticDynamics::update(const OpenMM::System& system, vector<Vec3>& atomCoordinates,
vector<Vec3>& velocities,
vector<Vec3>& forces, vector<double>& masses, double maxStepSize, double tolerance) {
// 1st update
......@@ -266,11 +225,11 @@ void ReferenceVariableStochasticDynamics::update(const OpenMM::System& system, v
// copy xPrime -> atomCoordinates
double invStepSize = 1.0/getDeltaT();
for (int ii = 0; ii < numberOfAtoms; ii++) {
if (masses[ii] != 0.0) {
atomCoordinates[ii][0] = xPrime[ii][0];
atomCoordinates[ii][1] = xPrime[ii][1];
atomCoordinates[ii][2] = xPrime[ii][2];
velocities[ii] = (xPrime[ii]-atomCoordinates[ii])*invStepSize;
atomCoordinates[ii] = xPrime[ii];
}
}
......
......@@ -43,7 +43,7 @@ using namespace OpenMM;
--------------------------------------------------------------------------------------- */
ReferenceVariableVerletDynamics::ReferenceVariableVerletDynamics(int numberOfAtoms, RealOpenMM accuracy) :
ReferenceVariableVerletDynamics::ReferenceVariableVerletDynamics(int numberOfAtoms, double accuracy) :
ReferenceDynamics(numberOfAtoms, 0.0f, 0.0f), _accuracy(accuracy) {
xPrime.resize(numberOfAtoms);
inverseMasses.resize(numberOfAtoms);
......@@ -56,13 +56,6 @@ ReferenceVariableVerletDynamics::ReferenceVariableVerletDynamics(int numberOfAto
--------------------------------------------------------------------------------------- */
ReferenceVariableVerletDynamics::~ReferenceVariableVerletDynamics() {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceVariableVerletDynamics::~ReferenceVariableVerletDynamics";
// ---------------------------------------------------------------------------------------
}
/**---------------------------------------------------------------------------------------
......@@ -73,7 +66,7 @@ ReferenceVariableVerletDynamics::~ReferenceVariableVerletDynamics() {
--------------------------------------------------------------------------------------- */
RealOpenMM ReferenceVariableVerletDynamics::getAccuracy() const {
double ReferenceVariableVerletDynamics::getAccuracy() const {
return _accuracy;
}
......@@ -83,7 +76,7 @@ RealOpenMM ReferenceVariableVerletDynamics::getAccuracy() const {
--------------------------------------------------------------------------------------- */
void ReferenceVariableVerletDynamics::setAccuracy(RealOpenMM accuracy) {
void ReferenceVariableVerletDynamics::setAccuracy(double accuracy) {
_accuracy = accuracy;
}
......@@ -101,19 +94,9 @@ void ReferenceVariableVerletDynamics::setAccuracy(RealOpenMM accuracy) {
--------------------------------------------------------------------------------------- */
void ReferenceVariableVerletDynamics::update(const OpenMM::System& system, vector<RealVec>& atomCoordinates,
vector<RealVec>& velocities,
vector<RealVec>& forces, vector<RealOpenMM>& masses, RealOpenMM maxStepSize, RealOpenMM tolerance) {
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nReferenceVariableVerletDynamics::update";
static const RealOpenMM zero = 0.0;
static const RealOpenMM one = 1.0;
// ---------------------------------------------------------------------------------------
void ReferenceVariableVerletDynamics::update(const OpenMM::System& system, vector<Vec3>& atomCoordinates,
vector<Vec3>& velocities,
vector<Vec3>& forces, vector<double>& masses, double maxStepSize, double tolerance) {
// first-time-through initialization
int numberOfAtoms = system.getNumParticles();
......@@ -121,34 +104,34 @@ void ReferenceVariableVerletDynamics::update(const OpenMM::System& system, vecto
// invert masses
for (int ii = 0; ii < numberOfAtoms; ii++) {
if (masses[ii] == zero)
inverseMasses[ii] = zero;
if (masses[ii] == 0.0)
inverseMasses[ii] = 0.0;
else
inverseMasses[ii] = one/masses[ii];
inverseMasses[ii] = 1.0/masses[ii];
}
}
RealOpenMM error = zero;
double error = 0.0;
for (int i = 0; i < numberOfAtoms; ++i) {
for (int j = 0; j < 3; ++j) {
RealOpenMM xerror = inverseMasses[i]*forces[i][j];
double xerror = inverseMasses[i]*forces[i][j];
error += xerror*xerror;
}
}
error = SQRT(error/(numberOfAtoms*3));
RealOpenMM newStepSize = SQRT(getAccuracy()/error);
error = sqrt(error/(numberOfAtoms*3));
double newStepSize = sqrt(getAccuracy()/error);
if (getDeltaT() > 0.0f)
newStepSize = std::min(newStepSize, getDeltaT()*2.0f); // For safety, limit how quickly dt can increase.
if (newStepSize > getDeltaT() && newStepSize < 1.2f*getDeltaT())
newStepSize = getDeltaT(); // Keeping dt constant between steps improves the behavior of the integrator.
if (newStepSize > maxStepSize)
newStepSize = maxStepSize;
RealOpenMM vstep = 0.5f*(newStepSize+getDeltaT()); // The time interval by which to advance the velocities
double vstep = 0.5f*(newStepSize+getDeltaT()); // The time interval by which to advance the velocities
setDeltaT(newStepSize);
for (int i = 0; i < numberOfAtoms; ++i) {
if (masses[i] != zero)
if (masses[i] != 0.0)
for (int j = 0; j < 3; ++j) {
RealOpenMM vPrime = velocities[i][j] + inverseMasses[i]*forces[i][j]*vstep;
double vPrime = velocities[i][j] + inverseMasses[i]*forces[i][j]*vstep;
xPrime[i][j] = atomCoordinates[i][j] + vPrime*getDeltaT();
}
}
......@@ -158,9 +141,9 @@ void ReferenceVariableVerletDynamics::update(const OpenMM::System& system, vecto
// Update the positions and velocities.
RealOpenMM velocityScale = one/getDeltaT();
double velocityScale = 1.0/getDeltaT();
for (int i = 0; i < numberOfAtoms; ++i) {
if (masses[i] != zero)
if (masses[i] != 0.0)
for (int j = 0; j < 3; ++j) {
velocities[i][j] = velocityScale*(xPrime[i][j] - atomCoordinates[i][j]);
atomCoordinates[i][j] = xPrime[i][j];
......
......@@ -45,18 +45,8 @@ using namespace OpenMM;
--------------------------------------------------------------------------------------- */
ReferenceVerletDynamics::ReferenceVerletDynamics(int numberOfAtoms, RealOpenMM deltaT) :
ReferenceVerletDynamics::ReferenceVerletDynamics(int numberOfAtoms, double deltaT) :
ReferenceDynamics(numberOfAtoms, deltaT, 0.0) {
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nReferenceVerletDynamics::ReferenceVerletDynamics";
static const RealOpenMM zero = 0.0;
static const RealOpenMM one = 1.0;
// ---------------------------------------------------------------------------------------
xPrime.resize(numberOfAtoms);
inverseMasses.resize(numberOfAtoms);
}
......@@ -68,13 +58,6 @@ ReferenceVerletDynamics::ReferenceVerletDynamics(int numberOfAtoms, RealOpenMM d
--------------------------------------------------------------------------------------- */
ReferenceVerletDynamics::~ReferenceVerletDynamics() {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceVerletDynamics::~ReferenceVerletDynamics";
// ---------------------------------------------------------------------------------------
}
/**---------------------------------------------------------------------------------------
......@@ -90,19 +73,9 @@ ReferenceVerletDynamics::~ReferenceVerletDynamics() {
--------------------------------------------------------------------------------------- */
void ReferenceVerletDynamics::update(const OpenMM::System& system, vector<RealVec>& atomCoordinates,
vector<RealVec>& velocities,
vector<RealVec>& forces, vector<RealOpenMM>& masses, RealOpenMM tolerance) {
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nReferenceVerletDynamics::update";
static const RealOpenMM zero = 0.0;
static const RealOpenMM one = 1.0;
// ---------------------------------------------------------------------------------------
void ReferenceVerletDynamics::update(const OpenMM::System& system, vector<Vec3>& atomCoordinates,
vector<Vec3>& velocities,
vector<Vec3>& forces, vector<double>& masses, double tolerance) {
// first-time-through initialization
int numberOfAtoms = system.getNumParticles();
......@@ -110,17 +83,17 @@ void ReferenceVerletDynamics::update(const OpenMM::System& system, vector<RealVe
// invert masses
for (int ii = 0; ii < numberOfAtoms; ii++) {
if (masses[ii] == zero)
inverseMasses[ii] = zero;
if (masses[ii] == 0.0)
inverseMasses[ii] = 0.0;
else
inverseMasses[ii] = one/masses[ii];
inverseMasses[ii] = 1.0/masses[ii];
}
}
// Perform the integration.
for (int i = 0; i < numberOfAtoms; ++i) {
if (masses[i] != zero)
if (masses[i] != 0.0)
for (int j = 0; j < 3; ++j) {
velocities[i][j] += inverseMasses[i]*forces[i][j]*getDeltaT();
xPrime[i][j] = atomCoordinates[i][j] + velocities[i][j]*getDeltaT();
......@@ -132,9 +105,9 @@ void ReferenceVerletDynamics::update(const OpenMM::System& system, vector<RealVe
// Update the positions and velocities.
RealOpenMM velocityScale = static_cast<RealOpenMM>(1.0/getDeltaT());
double velocityScale = static_cast<double>(1.0/getDeltaT());
for (int i = 0; i < numberOfAtoms; ++i) {
if (masses[i] != zero)
if (masses[i] != 0.0)
for (int j = 0; j < 3; ++j) {
velocities[i][j] = velocityScale*(xPrime[i][j] - atomCoordinates[i][j]);
atomCoordinates[i][j] = xPrime[i][j];
......
......@@ -31,11 +31,12 @@
#include "ReferenceVirtualSites.h"
#include "openmm/VirtualSite.h"
#include <cmath>
using namespace OpenMM;
using namespace std;
void ReferenceVirtualSites::computePositions(const OpenMM::System& system, vector<OpenMM::RealVec>& atomCoordinates) {
void ReferenceVirtualSites::computePositions(const OpenMM::System& system, vector<OpenMM::Vec3>& atomCoordinates) {
for (int i = 0; i < system.getNumParticles(); i++)
if (system.isVirtualSite(i)) {
if (dynamic_cast<const TwoParticleAverageSite*>(&system.getVirtualSite(i)) != NULL) {
......@@ -43,7 +44,7 @@ void ReferenceVirtualSites::computePositions(const OpenMM::System& system, vecto
const TwoParticleAverageSite& site = dynamic_cast<const TwoParticleAverageSite&>(system.getVirtualSite(i));
int p1 = site.getParticle(0), p2 = site.getParticle(1);
RealOpenMM w1 = site.getWeight(0), w2 = site.getWeight(1);
double w1 = site.getWeight(0), w2 = site.getWeight(1);
atomCoordinates[i] = atomCoordinates[p1]*w1 + atomCoordinates[p2]*w2;
}
else if (dynamic_cast<const ThreeParticleAverageSite*>(&system.getVirtualSite(i)) != NULL) {
......@@ -51,7 +52,7 @@ void ReferenceVirtualSites::computePositions(const OpenMM::System& system, vecto
const ThreeParticleAverageSite& site = dynamic_cast<const ThreeParticleAverageSite&>(system.getVirtualSite(i));
int p1 = site.getParticle(0), p2 = site.getParticle(1), p3 = site.getParticle(2);
RealOpenMM w1 = site.getWeight(0), w2 = site.getWeight(1), w3 = site.getWeight(2);
double w1 = site.getWeight(0), w2 = site.getWeight(1), w3 = site.getWeight(2);
atomCoordinates[i] = atomCoordinates[p1]*w1 + atomCoordinates[p2]*w2 + atomCoordinates[p3]*w3;
}
else if (dynamic_cast<const OutOfPlaneSite*>(&system.getVirtualSite(i)) != NULL) {
......@@ -59,10 +60,10 @@ void ReferenceVirtualSites::computePositions(const OpenMM::System& system, vecto
const OutOfPlaneSite& site = dynamic_cast<const OutOfPlaneSite&>(system.getVirtualSite(i));
int p1 = site.getParticle(0), p2 = site.getParticle(1), p3 = site.getParticle(2);
RealOpenMM w12 = site.getWeight12(), w13 = site.getWeight13(), wcross = site.getWeightCross();
RealVec v12 = atomCoordinates[p2]-atomCoordinates[p1];
RealVec v13 = atomCoordinates[p3]-atomCoordinates[p1];
RealVec cross = v12.cross(v13);
double w12 = site.getWeight12(), w13 = site.getWeight13(), wcross = site.getWeightCross();
Vec3 v12 = atomCoordinates[p2]-atomCoordinates[p1];
Vec3 v13 = atomCoordinates[p3]-atomCoordinates[p1];
Vec3 cross = v12.cross(v13);
atomCoordinates[i] = atomCoordinates[p1] + v12*w12 + v13*w13 + cross*wcross;
}
else if (dynamic_cast<const LocalCoordinatesSite*>(&system.getVirtualSite(i)) != NULL) {
......@@ -70,14 +71,14 @@ void ReferenceVirtualSites::computePositions(const OpenMM::System& system, vecto
const LocalCoordinatesSite& site = dynamic_cast<const LocalCoordinatesSite&>(system.getVirtualSite(i));
int p1 = site.getParticle(0), p2 = site.getParticle(1), p3 = site.getParticle(2);
RealVec originWeights = site.getOriginWeights();
RealVec xWeights = site.getXWeights();
RealVec yWeights = site.getYWeights();
RealVec localPosition = site.getLocalPosition();
RealVec origin = atomCoordinates[p1]*originWeights[0] + atomCoordinates[p2]*originWeights[1] + atomCoordinates[p3]*originWeights[2];
RealVec xdir = atomCoordinates[p1]*xWeights[0] + atomCoordinates[p2]*xWeights[1] + atomCoordinates[p3]*xWeights[2];
RealVec ydir = atomCoordinates[p1]*yWeights[0] + atomCoordinates[p2]*yWeights[1] + atomCoordinates[p3]*yWeights[2];
RealVec zdir = xdir.cross(ydir);
Vec3 originWeights = site.getOriginWeights();
Vec3 xWeights = site.getXWeights();
Vec3 yWeights = site.getYWeights();
Vec3 localPosition = site.getLocalPosition();
Vec3 origin = atomCoordinates[p1]*originWeights[0] + atomCoordinates[p2]*originWeights[1] + atomCoordinates[p3]*originWeights[2];
Vec3 xdir = atomCoordinates[p1]*xWeights[0] + atomCoordinates[p2]*xWeights[1] + atomCoordinates[p3]*xWeights[2];
Vec3 ydir = atomCoordinates[p1]*yWeights[0] + atomCoordinates[p2]*yWeights[1] + atomCoordinates[p3]*yWeights[2];
Vec3 zdir = xdir.cross(ydir);
xdir /= sqrt(xdir.dot(xdir));
zdir /= sqrt(zdir.dot(zdir));
ydir = zdir.cross(xdir);
......@@ -87,16 +88,16 @@ void ReferenceVirtualSites::computePositions(const OpenMM::System& system, vecto
}
void ReferenceVirtualSites::distributeForces(const OpenMM::System& system, const vector<OpenMM::RealVec>& atomCoordinates, vector<OpenMM::RealVec>& forces) {
void ReferenceVirtualSites::distributeForces(const OpenMM::System& system, const vector<OpenMM::Vec3>& atomCoordinates, vector<OpenMM::Vec3>& forces) {
for (int i = 0; i < system.getNumParticles(); i++)
if (system.isVirtualSite(i)) {
RealVec f = forces[i];
Vec3 f = forces[i];
if (dynamic_cast<const TwoParticleAverageSite*>(&system.getVirtualSite(i)) != NULL) {
// A two particle average.
const TwoParticleAverageSite& site = dynamic_cast<const TwoParticleAverageSite&>(system.getVirtualSite(i));
int p1 = site.getParticle(0), p2 = site.getParticle(1);
RealOpenMM w1 = site.getWeight(0), w2 = site.getWeight(1);
double w1 = site.getWeight(0), w2 = site.getWeight(1);
forces[p1] += f*w1;
forces[p2] += f*w2;
}
......@@ -105,7 +106,7 @@ void ReferenceVirtualSites::distributeForces(const OpenMM::System& system, const
const ThreeParticleAverageSite& site = dynamic_cast<const ThreeParticleAverageSite&>(system.getVirtualSite(i));
int p1 = site.getParticle(0), p2 = site.getParticle(1), p3 = site.getParticle(2);
RealOpenMM w1 = site.getWeight(0), w2 = site.getWeight(1), w3 = site.getWeight(2);
double w1 = site.getWeight(0), w2 = site.getWeight(1), w3 = site.getWeight(2);
forces[p1] += f*w1;
forces[p2] += f*w2;
forces[p3] += f*w3;
......@@ -115,15 +116,15 @@ void ReferenceVirtualSites::distributeForces(const OpenMM::System& system, const
const OutOfPlaneSite& site = dynamic_cast<const OutOfPlaneSite&>(system.getVirtualSite(i));
int p1 = site.getParticle(0), p2 = site.getParticle(1), p3 = site.getParticle(2);
RealOpenMM w12 = site.getWeight12(), w13 = site.getWeight13(), wcross = site.getWeightCross();
RealVec v12 = atomCoordinates[p2]-atomCoordinates[p1];
RealVec v13 = atomCoordinates[p3]-atomCoordinates[p1];
RealVec f2(w12*f[0] - wcross*v13[2]*f[1] + wcross*v13[1]*f[2],
wcross*v13[2]*f[0] + w12*f[1] - wcross*v13[0]*f[2],
-wcross*v13[1]*f[0] + wcross*v13[0]*f[1] + w12*f[2]);
RealVec f3(w13*f[0] + wcross*v12[2]*f[1] - wcross*v12[1]*f[2],
-wcross*v12[2]*f[0] + w13*f[1] + wcross*v12[0]*f[2],
wcross*v12[1]*f[0] - wcross*v12[0]*f[1] + w13*f[2]);
double w12 = site.getWeight12(), w13 = site.getWeight13(), wcross = site.getWeightCross();
Vec3 v12 = atomCoordinates[p2]-atomCoordinates[p1];
Vec3 v13 = atomCoordinates[p3]-atomCoordinates[p1];
Vec3 f2(w12*f[0] - wcross*v13[2]*f[1] + wcross*v13[1]*f[2],
wcross*v13[2]*f[0] + w12*f[1] - wcross*v13[0]*f[2],
-wcross*v13[1]*f[0] + wcross*v13[0]*f[1] + w12*f[2]);
Vec3 f3(w13*f[0] + wcross*v12[2]*f[1] - wcross*v12[1]*f[2],
-wcross*v12[2]*f[0] + w13*f[1] + wcross*v12[0]*f[2],
wcross*v12[1]*f[0] - wcross*v12[0]*f[1] + w13*f[2]);
forces[p1] += f-f2-f3;
forces[p2] += f2;
forces[p3] += f3;
......@@ -133,43 +134,43 @@ void ReferenceVirtualSites::distributeForces(const OpenMM::System& system, const
const LocalCoordinatesSite& site = dynamic_cast<const LocalCoordinatesSite&>(system.getVirtualSite(i));
int p1 = site.getParticle(0), p2 = site.getParticle(1), p3 = site.getParticle(2);
RealVec originWeights = site.getOriginWeights();
RealVec wx = site.getXWeights();
RealVec wy = site.getYWeights();
RealVec localPosition = site.getLocalPosition();
RealVec xdir = atomCoordinates[p1]*wx[0] + atomCoordinates[p2]*wx[1] + atomCoordinates[p3]*wx[2];
RealVec ydir = atomCoordinates[p1]*wy[0] + atomCoordinates[p2]*wy[1] + atomCoordinates[p3]*wy[2];
RealVec zdir = xdir.cross(ydir);
RealOpenMM invNormXdir = 1.0/SQRT(xdir.dot(xdir));
RealOpenMM invNormZdir = 1.0/SQRT(zdir.dot(zdir));
RealVec dx = xdir*invNormXdir;
RealVec dz = zdir*invNormZdir;
RealVec dy = dz.cross(dx);
Vec3 originWeights = site.getOriginWeights();
Vec3 wx = site.getXWeights();
Vec3 wy = site.getYWeights();
Vec3 localPosition = site.getLocalPosition();
Vec3 xdir = atomCoordinates[p1]*wx[0] + atomCoordinates[p2]*wx[1] + atomCoordinates[p3]*wx[2];
Vec3 ydir = atomCoordinates[p1]*wy[0] + atomCoordinates[p2]*wy[1] + atomCoordinates[p3]*wy[2];
Vec3 zdir = xdir.cross(ydir);
double invNormXdir = 1.0/sqrt(xdir.dot(xdir));
double invNormZdir = 1.0/sqrt(zdir.dot(zdir));
Vec3 dx = xdir*invNormXdir;
Vec3 dz = zdir*invNormZdir;
Vec3 dy = dz.cross(dx);
// The derivatives for this case are very complicated. They were computed with SymPy then simplified by hand.
RealOpenMM t11 = (wx[0]*ydir[0]-wy[0]*xdir[0])*invNormZdir;
RealOpenMM t12 = (wx[0]*ydir[1]-wy[0]*xdir[1])*invNormZdir;
RealOpenMM t13 = (wx[0]*ydir[2]-wy[0]*xdir[2])*invNormZdir;
RealOpenMM t21 = (wx[1]*ydir[0]-wy[1]*xdir[0])*invNormZdir;
RealOpenMM t22 = (wx[1]*ydir[1]-wy[1]*xdir[1])*invNormZdir;
RealOpenMM t23 = (wx[1]*ydir[2]-wy[1]*xdir[2])*invNormZdir;
RealOpenMM t31 = (wx[2]*ydir[0]-wy[2]*xdir[0])*invNormZdir;
RealOpenMM t32 = (wx[2]*ydir[1]-wy[2]*xdir[1])*invNormZdir;
RealOpenMM t33 = (wx[2]*ydir[2]-wy[2]*xdir[2])*invNormZdir;
RealOpenMM sx1 = t13*dz[1]-t12*dz[2];
RealOpenMM sy1 = t11*dz[2]-t13*dz[0];
RealOpenMM sz1 = t12*dz[0]-t11*dz[1];
RealOpenMM sx2 = t23*dz[1]-t22*dz[2];
RealOpenMM sy2 = t21*dz[2]-t23*dz[0];
RealOpenMM sz2 = t22*dz[0]-t21*dz[1];
RealOpenMM sx3 = t33*dz[1]-t32*dz[2];
RealOpenMM sy3 = t31*dz[2]-t33*dz[0];
RealOpenMM sz3 = t32*dz[0]-t31*dz[1];
RealVec wxScaled = wx*invNormXdir;
RealVec fp1 = localPosition*f[0];
RealVec fp2 = localPosition*f[1];
RealVec fp3 = localPosition*f[2];
double t11 = (wx[0]*ydir[0]-wy[0]*xdir[0])*invNormZdir;
double t12 = (wx[0]*ydir[1]-wy[0]*xdir[1])*invNormZdir;
double t13 = (wx[0]*ydir[2]-wy[0]*xdir[2])*invNormZdir;
double t21 = (wx[1]*ydir[0]-wy[1]*xdir[0])*invNormZdir;
double t22 = (wx[1]*ydir[1]-wy[1]*xdir[1])*invNormZdir;
double t23 = (wx[1]*ydir[2]-wy[1]*xdir[2])*invNormZdir;
double t31 = (wx[2]*ydir[0]-wy[2]*xdir[0])*invNormZdir;
double t32 = (wx[2]*ydir[1]-wy[2]*xdir[1])*invNormZdir;
double t33 = (wx[2]*ydir[2]-wy[2]*xdir[2])*invNormZdir;
double sx1 = t13*dz[1]-t12*dz[2];
double sy1 = t11*dz[2]-t13*dz[0];
double sz1 = t12*dz[0]-t11*dz[1];
double sx2 = t23*dz[1]-t22*dz[2];
double sy2 = t21*dz[2]-t23*dz[0];
double sz2 = t22*dz[0]-t21*dz[1];
double sx3 = t33*dz[1]-t32*dz[2];
double sy3 = t31*dz[2]-t33*dz[0];
double sz3 = t32*dz[0]-t31*dz[1];
Vec3 wxScaled = wx*invNormXdir;
Vec3 fp1 = localPosition*f[0];
Vec3 fp2 = localPosition*f[1];
Vec3 fp3 = localPosition*f[2];
forces[p1][0] += fp1[0]*wxScaled[0]*(1-dx[0]*dx[0]) + fp1[2]*(dz[0]*sx1 ) + fp1[1]*((-dx[0]*dy[0] )*wxScaled[0] + dy[0]*sx1 - dx[1]*t12 - dx[2]*t13) + f[0]*originWeights[0];
forces[p1][1] += fp1[0]*wxScaled[0]*( -dx[0]*dx[1]) + fp1[2]*(dz[0]*sy1+t13) + fp1[1]*((-dx[1]*dy[0]-dz[2])*wxScaled[0] + dy[0]*sy1 + dx[1]*t11);
forces[p1][2] += fp1[0]*wxScaled[0]*( -dx[0]*dx[2]) + fp1[2]*(dz[0]*sz1-t12) + fp1[1]*((-dx[2]*dy[0]+dz[1])*wxScaled[0] + dy[0]*sz1 + dx[2]*t11);
......
......@@ -40,12 +40,12 @@ using namespace OpenMM;
uint32_t SimTKOpenMMUtilities::_randomNumberSeed = 0;
bool SimTKOpenMMUtilities::_randomInitialized = false;
bool SimTKOpenMMUtilities::nextGaussianIsValid = false;
RealOpenMM SimTKOpenMMUtilities::nextGaussian = 0;
double SimTKOpenMMUtilities::nextGaussian = 0;
OpenMM_SFMT::SFMT SimTKOpenMMUtilities::sfmt;
/* ---------------------------------------------------------------------------------------
Allocate 1D RealOpenMM array (Simbios)
Allocate 1D double array (Simbios)
array[i]
......@@ -59,27 +59,18 @@ OpenMM_SFMT::SFMT SimTKOpenMMUtilities::sfmt;
--------------------------------------------------------------------------------------- */
RealOpenMM* SimTKOpenMMUtilities::allocateOneDRealOpenMMArray(int iSize, RealOpenMM* array1D,
int initialize, RealOpenMM initialValue,
double* SimTKOpenMMUtilities::allocateOneDRealOpenMMArray(int iSize, double* array1D,
int initialize, double initialValue,
const std::string& idString) {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nSimTKOpenMMUtilities::allocate1DRealOpenMMArray";
static const RealOpenMM zero = 0.0;
// ---------------------------------------------------------------------------------------
if (array1D == NULL) {
array1D = new RealOpenMM[iSize];
array1D = new double[iSize];
}
if (initialize) {
if (initialValue == zero) {
memset(array1D, 0, iSize*sizeof(RealOpenMM));
if (initialValue == 0.0) {
memset(array1D, 0, iSize*sizeof(double));
} else {
for (int ii = 0; ii < iSize; ii++) {
array1D[ii] = initialValue;
......@@ -92,7 +83,7 @@ RealOpenMM* SimTKOpenMMUtilities::allocateOneDRealOpenMMArray(int iSize, RealOpe
/* ---------------------------------------------------------------------------------------
Allocate 2D RealOpenMM array (Simbios)
Allocate 2D double array (Simbios)
array[i][j]
......@@ -107,23 +98,16 @@ RealOpenMM* SimTKOpenMMUtilities::allocateOneDRealOpenMMArray(int iSize, RealOpe
--------------------------------------------------------------------------------------- */
RealOpenMM** SimTKOpenMMUtilities::allocateTwoDRealOpenMMArray(int iSize, int jSize, RealOpenMM** array2D,
int initialize, RealOpenMM initialValue,
double** SimTKOpenMMUtilities::allocateTwoDRealOpenMMArray(int iSize, int jSize, double** array2D,
int initialize, double initialValue,
const std::string& idString) {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nSimTKOpenMMUtilities::allocate2DRealOpenMMArray";
// ---------------------------------------------------------------------------------------
if (array2D == NULL) {
array2D = new RealOpenMM*[iSize];
array2D = new double*[iSize];
std::string blockString = idString;
blockString.append("Block");
RealOpenMM* block = new RealOpenMM[jSize*iSize];
double* block = new double[jSize*iSize];
for (int ii = 0; ii < iSize; ii++) {
array2D[ii] = block;
......@@ -140,7 +124,7 @@ RealOpenMM** SimTKOpenMMUtilities::allocateTwoDRealOpenMMArray(int iSize, int jS
/* ---------------------------------------------------------------------------------------
Free 2D RealOpenMM array (Simbios)
Free 2D double array (Simbios)
array[i][j]
......@@ -149,14 +133,7 @@ RealOpenMM** SimTKOpenMMUtilities::allocateTwoDRealOpenMMArray(int iSize, int jS
--------------------------------------------------------------------------------------- */
void SimTKOpenMMUtilities::freeTwoDRealOpenMMArray(RealOpenMM** array2D, const std::string& idString) {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nSimTKOpenMMUtilities::freeTwoDRealOpenMMArray";
// ---------------------------------------------------------------------------------------
void SimTKOpenMMUtilities::freeTwoDRealOpenMMArray(double** array2D, const std::string& idString) {
if (array2D != NULL) {
std::string blockString = idString;
......@@ -169,7 +146,7 @@ void SimTKOpenMMUtilities::freeTwoDRealOpenMMArray(RealOpenMM** array2D, const s
/* ---------------------------------------------------------------------------------------
Free 1D RealOpenMM array (Simbios)
Free 1D double array (Simbios)
array[i]
......@@ -178,14 +155,7 @@ void SimTKOpenMMUtilities::freeTwoDRealOpenMMArray(RealOpenMM** array2D, const s
--------------------------------------------------------------------------------------- */
void SimTKOpenMMUtilities::freeOneDRealOpenMMArray(RealOpenMM* array1D, const std::string& idString) {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nSimTKOpenMMUtilities::freeOneDRealOpenMMArray";
// ---------------------------------------------------------------------------------------
void SimTKOpenMMUtilities::freeOneDRealOpenMMArray(double* array1D, const std::string& idString) {
if (array1D != NULL) {
delete[] array1D;
}
......@@ -193,7 +163,7 @@ void SimTKOpenMMUtilities::freeOneDRealOpenMMArray(RealOpenMM* array1D, const st
/* ---------------------------------------------------------------------------------------
Initialize 2D RealOpenMM array (Simbios)
Initialize 2D double array (Simbios)
array[i][j]
......@@ -205,15 +175,8 @@ void SimTKOpenMMUtilities::freeOneDRealOpenMMArray(RealOpenMM* array1D, const st
--------------------------------------------------------------------------------------- */
void SimTKOpenMMUtilities::initialize2DRealOpenMMArray(int iSize, int jSize,
RealOpenMM** array2D,
RealOpenMM initialValue) {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nSimTKOpenMMUtilities::initialize2DRealOpenMMArray";
// ---------------------------------------------------------------------------------------
double** array2D,
double initialValue) {
bool useMemset;
bool useMemsetSingleBlock;
......@@ -231,10 +194,10 @@ void SimTKOpenMMUtilities::initialize2DRealOpenMMArray(int iSize, int jSize,
if (useMemset) {
if (useMemsetSingleBlock) {
memset(array2D[0], 0, iSize*jSize*sizeof(RealOpenMM));
memset(array2D[0], 0, iSize*jSize*sizeof(double));
} else {
for (int ii = 0; ii < iSize; ii++) {
memset(array2D[ii], 0, jSize*sizeof(RealOpenMM));
memset(array2D[ii], 0, jSize*sizeof(double));
}
}
} else {
......@@ -260,16 +223,9 @@ void SimTKOpenMMUtilities::initialize2DRealOpenMMArray(int iSize, int jSize,
--------------------------------------------------------------------------------------- */
void SimTKOpenMMUtilities::crossProductVector3(RealOpenMM* vectorX,
RealOpenMM* vectorY,
RealOpenMM* vectorZ) {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nSimTKOpenMMUtilities::crossProductVector3";
// ---------------------------------------------------------------------------------------
void SimTKOpenMMUtilities::crossProductVector3(double* vectorX,
double* vectorY,
double* vectorZ) {
vectorZ[0] = vectorX[1]*vectorY[2] - vectorX[2]*vectorY[1];
vectorZ[1] = vectorX[2]*vectorY[0] - vectorX[0]*vectorY[2];
vectorZ[2] = vectorX[0]*vectorY[1] - vectorX[1]*vectorY[0];
......@@ -285,7 +241,7 @@ void SimTKOpenMMUtilities::crossProductVector3(RealOpenMM* vectorX,
--------------------------------------------------------------------------------------- */
RealOpenMM SimTKOpenMMUtilities::getNormallyDistributedRandomNumber() {
double SimTKOpenMMUtilities::getNormallyDistributedRandomNumber() {
if (nextGaussianIsValid) {
nextGaussianIsValid = false;
return nextGaussian;
......@@ -298,13 +254,13 @@ RealOpenMM SimTKOpenMMUtilities::getNormallyDistributedRandomNumber() {
// Use the polar form of the Box-Muller transformation to generate two Gaussian random numbers.
RealOpenMM x, y, r2;
double x, y, r2;
do {
x = static_cast<RealOpenMM>(2.0 * genrand_real2(sfmt) - 1.0);
y = static_cast<RealOpenMM>(2.0 * genrand_real2(sfmt) - 1.0);
x = 2.0 * genrand_real2(sfmt) - 1.0;
y = 2.0 * genrand_real2(sfmt) - 1.0;
r2 = x*x + y*y;
} while (r2 >= 1.0 || r2 == 0.0);
RealOpenMM multiplier = static_cast<RealOpenMM>(sqrt((-2.0*log(r2))/r2));
double multiplier = sqrt((-2.0*log(r2))/r2);
nextGaussian = y*multiplier;
nextGaussianIsValid = true;
return x*multiplier;
......@@ -318,13 +274,13 @@ RealOpenMM SimTKOpenMMUtilities::getNormallyDistributedRandomNumber() {
--------------------------------------------------------------------------------------- */
RealOpenMM SimTKOpenMMUtilities::getUniformlyDistributedRandomNumber() {
double SimTKOpenMMUtilities::getUniformlyDistributedRandomNumber() {
if (!_randomInitialized) {
init_gen_rand(_randomNumberSeed, sfmt);
_randomInitialized = true;
nextGaussianIsValid = false;
}
RealOpenMM value = static_cast<RealOpenMM>(genrand_real2(sfmt));
double value = genrand_real2(sfmt);
return value;
}
......@@ -337,13 +293,6 @@ RealOpenMM SimTKOpenMMUtilities::getUniformlyDistributedRandomNumber() {
--------------------------------------------------------------------------------------- */
uint32_t SimTKOpenMMUtilities::getRandomNumberSeed() {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceDynamics::getRandomNumberSeed";
// ---------------------------------------------------------------------------------------
return _randomNumberSeed;
}
......@@ -356,13 +305,6 @@ uint32_t SimTKOpenMMUtilities::getRandomNumberSeed() {
--------------------------------------------------------------------------------------- */
void SimTKOpenMMUtilities::setRandomNumberSeed(uint32_t seed) {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceDynamics::setRandomNumberSeed";
// ---------------------------------------------------------------------------------------
// If the seed is 0, use a unique seed
if (seed == 0)
_randomNumberSeed = (uint32_t) osrngseed();
......@@ -376,7 +318,7 @@ void SimTKOpenMMUtilities::createCheckpoint(std::ostream& stream) {
stream.write((char*) &_randomInitialized, sizeof(bool));
if (_randomInitialized) {
stream.write((char*) &nextGaussianIsValid, sizeof(bool));
stream.write((char*) &nextGaussian, sizeof(RealOpenMM));
stream.write((char*) &nextGaussian, sizeof(double));
sfmt.createCheckpoint(stream);
}
}
......@@ -389,7 +331,7 @@ void SimTKOpenMMUtilities::loadCheckpoint(std::istream& stream) {
if (!prevInitialized)
init_gen_rand(0, sfmt);
stream.read((char*) &nextGaussianIsValid, sizeof(bool));
stream.read((char*) &nextGaussian, sizeof(RealOpenMM));
stream.read((char*) &nextGaussian, sizeof(double));
sfmt.loadCheckpoint(stream);
}
}
......@@ -37,7 +37,7 @@ struct fftpack
int n; /**< Number of points in this dimension. */
int ifac[15]; /**< 15 bytes needed for cfft and rfft */
struct fftpack * next; /**< Pointer to next dimension, or NULL. */
RealOpenMM * work; /**< 1st 4n reserved for cfft, 1st 2n for rfft */
double * work; /**< 1st 4n reserved for cfft, 1st 2n for rfft */
};
......@@ -48,15 +48,15 @@ struct fftpack
static void
fftpack_passf2(int ido,
int l1,
RealOpenMM cc[],
RealOpenMM ch[],
RealOpenMM wa1[],
int isign)
fftpack_passf2(int ido,
int l1,
double cc[],
double ch[],
double wa1[],
int isign)
{
int i, k, ah, ac;
RealOpenMM ti2, tr2;
double ti2, tr2;
if (ido <= 2)
{
......@@ -92,19 +92,19 @@ fftpack_passf2(int ido,
static void
fftpack_passf3(int ido,
int l1,
RealOpenMM cc[],
RealOpenMM ch[],
RealOpenMM wa1[],
RealOpenMM wa2[],
int isign)
fftpack_passf3(int ido,
int l1,
double cc[],
double ch[],
double wa1[],
double wa2[],
int isign)
{
const RealOpenMM taur = (RealOpenMM)-0.5;
const RealOpenMM taui = (RealOpenMM)0.866025403784439;
const double taur = -0.5;
const double taui = 0.866025403784439;
int i, k, ac, ah;
RealOpenMM ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2;
double ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2;
if (ido == 2)
{
......@@ -159,17 +159,17 @@ fftpack_passf3(int ido,
static void
fftpack_passf4(int ido,
int l1,
RealOpenMM cc[],
RealOpenMM ch[],
RealOpenMM wa1[],
RealOpenMM wa2[],
RealOpenMM wa3[],
int isign)
fftpack_passf4(int ido,
int l1,
double cc[],
double ch[],
double wa1[],
double wa2[],
double wa3[],
int isign)
{
int i, k, ac, ah;
RealOpenMM ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
double ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
if (ido == 2)
{
......@@ -232,23 +232,23 @@ fftpack_passf4(int ido,
static void
fftpack_passf5(int ido,
int l1,
RealOpenMM cc[],
RealOpenMM ch[],
RealOpenMM wa1[],
RealOpenMM wa2[],
RealOpenMM wa3[],
RealOpenMM wa4[],
int isign)
fftpack_passf5(int ido,
int l1,
double cc[],
double ch[],
double wa1[],
double wa2[],
double wa3[],
double wa4[],
int isign)
{
const RealOpenMM tr11 = (RealOpenMM)0.309016994374947;
const RealOpenMM ti11 = (RealOpenMM)0.951056516295154;
const RealOpenMM tr12 = (RealOpenMM)-0.809016994374947;
const RealOpenMM ti12 = (RealOpenMM)0.587785252292473;
const double tr11 = 0.309016994374947;
const double ti11 = 0.951056516295154;
const double tr12 = -0.809016994374947;
const double ti12 = 0.587785252292473;
int i, k, ac, ah;
RealOpenMM ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3,
double ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3,
ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5;
if (ido == 2)
......@@ -334,18 +334,18 @@ fftpack_passf5(int ido,
static void
fftpack_passf(int * nac,
int ido,
int ip,
int l1,
int idl1,
RealOpenMM cc[],
RealOpenMM ch[],
RealOpenMM wa[],
int isign)
fftpack_passf(int* nac,
int ido,
int ip,
int l1,
int idl1,
double cc[],
double ch[],
double wa[],
int isign)
{
int idij, idlj, idot, ipph, i, j, k, l, jc, lc, ik, nt, idj, idl, inc,idp;
RealOpenMM wai, war;
double wai, war;
idot = ido / 2;
nt = ip*idl1;
......@@ -495,17 +495,17 @@ fftpack_passf(int * nac,
static void
fftpack_cfftf1(int n,
RealOpenMM c[],
RealOpenMM ch[],
RealOpenMM wa[],
int ifac[15],
int isign)
fftpack_cfftf1(int n,
double c[],
double ch[],
double wa[],
int ifac[15],
int isign)
{
int idot, i;
int k1, l1, l2;
int na, nf, ip, iw, ix2, ix3, ix4, nac, ido, idl1;
RealOpenMM *cinput, *coutput;
double *cinput, *coutput;
nf = ifac[1];
na = 0;
l1 = 1;
......@@ -606,12 +606,12 @@ startloop:
static void
fftpack_cffti1(int n,
RealOpenMM wa[],
int ifac[15])
fftpack_cffti1(int n,
double wa[],
int ifac[15])
{
const RealOpenMM twopi = (RealOpenMM)6.28318530717959;
RealOpenMM arg, argh, argld, fi;
const double twopi = 6.28318530717959;
double arg, argh, argld, fi;
int idot, i, j;
int i1, k1, l1, l2;
int ld, ii, nf, ip;
......@@ -619,7 +619,7 @@ fftpack_cffti1(int n,
fftpack_factorize(n,ifac);
nf = ifac[1];
argh = twopi/(RealOpenMM)n;
argh = twopi/n;
i = 1;
l1 = 1;
for (k1=1; k1<=nf; k1++)
......@@ -783,7 +783,7 @@ fftpack_init_1d(fftpack_t * pfft,
fft->n = nx;
/* Need 4*n storage for 1D complex FFT */
if ((fft->work = (RealOpenMM *)malloc(sizeof(RealOpenMM)*(4*nx))) == NULL)
if ((fft->work = (double *)malloc(sizeof(double)*(4*nx))) == NULL)
{
free(fft);
return ENOMEM;
......@@ -860,7 +860,7 @@ fftpack_init_3d(fftpack_t * pfft,
/* Need 4*nx storage for 1D complex FFT.
*/
if ((fft->work = (RealOpenMM *)malloc(sizeof(RealOpenMM)*(4*nx))) == NULL)
if ((fft->work = (double *)malloc(sizeof(double)*(4*nx))) == NULL)
{
free(fft);
return ENOMEM;
......@@ -887,16 +887,16 @@ fftpack_exec_1d (fftpack_t fft,
t_complex * in_data,
t_complex * out_data)
{
int i,n;
RealOpenMM * p1;
RealOpenMM * p2;
int i, n;
double* p1;
double* p2;
n=fft->n;
if (n==1)
{
p1 = (RealOpenMM *)in_data;
p2 = (RealOpenMM *)out_data;
p1 = (double *)in_data;
p2 = (double *)out_data;
p2[0] = p1[0];
p2[1] = p1[1];
}
......@@ -906,10 +906,10 @@ fftpack_exec_1d (fftpack_t fft,
*/
if (in_data != out_data)
{
p1 = (RealOpenMM *)in_data;
p2 = (RealOpenMM *)out_data;
p1 = (double *)in_data;
p2 = (double *)out_data;
/* n complex = 2*n RealOpenMM elements */
/* n complex = 2*n double elements */
for (i=0;i<2*n;i++)
{
p2[i] = p1[i];
......@@ -922,11 +922,11 @@ fftpack_exec_1d (fftpack_t fft,
if (dir == FFTPACK_FORWARD)
{
fftpack_cfftf1(n,(RealOpenMM *)out_data,fft->work+2*n,fft->work,fft->ifac, -1);
fftpack_cfftf1(n,(double *)out_data,fft->work+2*n,fft->work,fft->ifac, -1);
}
else if (dir == FFTPACK_BACKWARD)
{
fftpack_cfftf1(n,(RealOpenMM *)out_data,fft->work+2*n,fft->work,fft->ifac, 1);
fftpack_cfftf1(n,(double *)out_data,fft->work+2*n,fft->work,fft->ifac, 1);
}
else
{
......
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2017 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "ReferenceTests.h"
#include "TestDispersionPME.h"
void runPlatformTests() {
}
......@@ -37,6 +37,7 @@
#include "openmm/MonteCarloMembraneBarostat.h"
#include "openmm/Context.h"
#include "ReferencePlatform.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/NonbondedForce.h"
#include "openmm/System.h"
#include "openmm/LangevinIntegrator.h"
......@@ -76,8 +77,9 @@ void testIdealGas(MonteCarloMembraneBarostat::XYMode xymode, MonteCarloMembraneB
}
MonteCarloMembraneBarostat* barostat = new MonteCarloMembraneBarostat(pressure, tension, temp[0], xymode, zmode, frequency);
system.addForce(barostat);
ASSERT(barostat->usesPeriodicBoundaryConditions());
ASSERT(system.usesPeriodicBoundaryConditions());
HarmonicBondForce* bonds = new HarmonicBondForce();
bonds->setUsesPeriodicBoundaryConditions(true);
system.addForce(bonds); // So it won't complain the system is non-periodic.
// Test it for three different temperatures.
......@@ -134,8 +136,6 @@ void testRandomSeed() {
system.addForce(forceField);
MonteCarloMembraneBarostat* barostat = new MonteCarloMembraneBarostat(pressure, tension, temp, MonteCarloMembraneBarostat::XYAnisotropic, MonteCarloMembraneBarostat::ZFree, 1);
system.addForce(barostat);
ASSERT(barostat->usesPeriodicBoundaryConditions());
ASSERT(system.usesPeriodicBoundaryConditions());
vector<Vec3> positions(numParticles);
vector<Vec3> velocities(numParticles);
for (int i = 0; i < numParticles; ++i) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment