Commit e2977b91 authored by peastman's avatar peastman
Browse files

Began implementing triclinic boxes in reference platform

parent fa283744
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#ifndef __ReferenceForce_H__ #ifndef __ReferenceForce_H__
#define __ReferenceForce_H__ #define __ReferenceForce_H__
#include "RealVec.h"
#include "lepton/CompiledExpression.h" #include "lepton/CompiledExpression.h"
#include "openmm/internal/windowsExport.h" #include "openmm/internal/windowsExport.h"
...@@ -97,18 +98,20 @@ class OPENMM_EXPORT ReferenceForce { ...@@ -97,18 +98,20 @@ class OPENMM_EXPORT ReferenceForce {
static void getDeltaRPeriodic( const OpenMM::RealVec& atomCoordinatesI, const OpenMM::RealVec& atomCoordinatesJ, static void getDeltaRPeriodic( const OpenMM::RealVec& atomCoordinatesI, const OpenMM::RealVec& atomCoordinatesJ,
const RealOpenMM* boxSize, RealOpenMM* deltaR ); const RealOpenMM* boxSize, RealOpenMM* deltaR );
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
Get deltaR between atomI and atomJ (static method): deltaR: j - i Get deltaR and distance and distance**2 between atomI and atomJ, assuming periodic
boundary conditions (static method); deltaR: j - i
@param atomCoordinatesI atom i coordinates @param atomCoordinatesI atom i coordinates
@param atomCoordinatesI atom j coordinates @param atomCoordinatesI atom j coordinates
@param deltaR deltaX, deltaY, deltaZ upon return @param boxVectors the vectors defining the periodic box
@param deltaR deltaX, deltaY, deltaZ, R2, R upon return
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
static void getDeltaROnly( const RealOpenMM* atomCoordinatesI, const RealOpenMM* atomCoordinatesJ, static void getDeltaRPeriodic( const OpenMM::RealVec& atomCoordinatesI, const OpenMM::RealVec& atomCoordinatesJ,
RealOpenMM* deltaR ); const OpenMM::RealVec* boxVectors, RealOpenMM* deltaR );
/** /**
* Get a pointer to the memory for setting a variable in a CompiledExpression. If the expression * Get a pointer to the memory for setting a variable in a CompiledExpression. If the expression
......
...@@ -40,7 +40,7 @@ class ReferenceLJCoulombIxn { ...@@ -40,7 +40,7 @@ class ReferenceLJCoulombIxn {
bool ewald; bool ewald;
bool pme; bool pme;
const OpenMM::NeighborList* neighborList; const OpenMM::NeighborList* neighborList;
RealOpenMM periodicBoxSize[3]; OpenMM::RealVec periodicBoxVectors[3];
RealOpenMM cutoffDistance, switchingDistance; RealOpenMM cutoffDistance, switchingDistance;
RealOpenMM krf, crf; RealOpenMM krf, crf;
RealOpenMM alphaEwald; RealOpenMM alphaEwald;
...@@ -118,11 +118,11 @@ class ReferenceLJCoulombIxn { ...@@ -118,11 +118,11 @@ class ReferenceLJCoulombIxn {
already been set, and the smallest side of the periodic box is at least twice the cutoff already been set, and the smallest side of the periodic box is at least twice the cutoff
distance. distance.
@param boxSize the X, Y, and Z widths of the periodic box @param vectors the vectors defining the periodic box
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
void setPeriodic( OpenMM::RealVec& boxSize ); void setPeriodic(OpenMM::RealVec* vectors);
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
......
...@@ -22,7 +22,7 @@ void OPENMM_EXPORT computeNeighborListNaive( ...@@ -22,7 +22,7 @@ void OPENMM_EXPORT computeNeighborListNaive(
int nAtoms, int nAtoms,
const AtomLocationList& atomLocations, const AtomLocationList& atomLocations,
const std::vector<std::set<int> >& exclusions, const std::vector<std::set<int> >& exclusions,
const RealVec& periodicBoxSize, const RealVec* periodicBoxVectors,
bool usePeriodic, bool usePeriodic,
double maxDistance, double maxDistance,
double minDistance = 0.0, double minDistance = 0.0,
...@@ -35,9 +35,9 @@ void OPENMM_EXPORT computeNeighborListNaive( ...@@ -35,9 +35,9 @@ void OPENMM_EXPORT computeNeighborListNaive(
void OPENMM_EXPORT computeNeighborListVoxelHash( void OPENMM_EXPORT computeNeighborListVoxelHash(
NeighborList& neighborList, NeighborList& neighborList,
int nAtoms, int nAtoms,
const AtomLocationList& atomLocations, const AtomLocationList& atomLocations,
const std::vector<std::set<int> >& exclusions, const std::vector<std::set<int> >& exclusions,
const RealVec& periodicBoxSize, const RealVec* periodicBoxVectors,
bool usePeriodic, bool usePeriodic,
double maxDistance, double maxDistance,
double minDistance = 0.0, double minDistance = 0.0,
......
...@@ -66,6 +66,7 @@ public: ...@@ -66,6 +66,7 @@ public:
void* velocities; void* velocities;
void* forces; void* forces;
void* periodicBoxSize; void* periodicBoxSize;
void* periodicBoxVectors;
void* constraints; void* constraints;
}; };
} // namespace OpenMM } // namespace OpenMM
......
...@@ -134,6 +134,11 @@ static RealVec& extractBoxSize(ContextImpl& context) { ...@@ -134,6 +134,11 @@ static RealVec& extractBoxSize(ContextImpl& context) {
return *(RealVec*) data->periodicBoxSize; return *(RealVec*) data->periodicBoxSize;
} }
static RealVec* extractBoxVectors(ContextImpl& context) {
ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData());
return (RealVec*) data->periodicBoxVectors;
}
static ReferenceConstraints& extractConstraints(ContextImpl& context) { static ReferenceConstraints& extractConstraints(ContextImpl& context) {
ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData()); ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData());
return *(ReferenceConstraints*) data->constraints; return *(ReferenceConstraints*) data->constraints;
...@@ -256,10 +261,10 @@ void ReferenceUpdateStateDataKernel::getForces(ContextImpl& context, std::vector ...@@ -256,10 +261,10 @@ void ReferenceUpdateStateDataKernel::getForces(ContextImpl& context, std::vector
} }
void ReferenceUpdateStateDataKernel::getPeriodicBoxVectors(ContextImpl& context, Vec3& a, Vec3& b, Vec3& c) const { void ReferenceUpdateStateDataKernel::getPeriodicBoxVectors(ContextImpl& context, Vec3& a, Vec3& b, Vec3& c) const {
RealVec& box = extractBoxSize(context); RealVec* vectors = extractBoxVectors(context);
a = Vec3(box[0], 0, 0); a = vectors[0];
b = Vec3(0, box[1], 0); b = vectors[1];
c = Vec3(0, 0, box[2]); c = vectors[2];
} }
void ReferenceUpdateStateDataKernel::setPeriodicBoxVectors(ContextImpl& context, const Vec3& a, const Vec3& b, const Vec3& c) const { void ReferenceUpdateStateDataKernel::setPeriodicBoxVectors(ContextImpl& context, const Vec3& a, const Vec3& b, const Vec3& c) const {
...@@ -267,6 +272,10 @@ void ReferenceUpdateStateDataKernel::setPeriodicBoxVectors(ContextImpl& context, ...@@ -267,6 +272,10 @@ void ReferenceUpdateStateDataKernel::setPeriodicBoxVectors(ContextImpl& context,
box[0] = (RealOpenMM) a[0]; box[0] = (RealOpenMM) a[0];
box[1] = (RealOpenMM) b[1]; box[1] = (RealOpenMM) b[1];
box[2] = (RealOpenMM) c[2]; box[2] = (RealOpenMM) c[2];
RealVec* vectors = extractBoxVectors(context);
vectors[0] = a;
vectors[1] = b;
vectors[2] = c;
} }
void ReferenceUpdateStateDataKernel::createCheckpoint(ContextImpl& context, ostream& stream) { void ReferenceUpdateStateDataKernel::createCheckpoint(ContextImpl& context, ostream& stream) {
...@@ -854,15 +863,15 @@ double ReferenceCalcNonbondedForceKernel::execute(ContextImpl& context, bool inc ...@@ -854,15 +863,15 @@ double ReferenceCalcNonbondedForceKernel::execute(ContextImpl& context, bool inc
bool ewald = (nonbondedMethod == Ewald); bool ewald = (nonbondedMethod == Ewald);
bool pme = (nonbondedMethod == PME); bool pme = (nonbondedMethod == PME);
if (nonbondedMethod != NoCutoff) { if (nonbondedMethod != NoCutoff) {
computeNeighborListVoxelHash(*neighborList, numParticles, posData, exclusions, extractBoxSize(context), periodic || ewald || pme, nonbondedCutoff, 0.0); computeNeighborListVoxelHash(*neighborList, numParticles, posData, exclusions, extractBoxVectors(context), periodic || ewald || pme, nonbondedCutoff, 0.0);
clj.setUseCutoff(nonbondedCutoff, *neighborList, rfDielectric); clj.setUseCutoff(nonbondedCutoff, *neighborList, rfDielectric);
} }
if (periodic || ewald || pme) { if (periodic || ewald || pme) {
RealVec& box = extractBoxSize(context); RealVec* vectors = extractBoxVectors(context);
double minAllowedSize = 1.999999*nonbondedCutoff; double minAllowedSize = 1.999999*nonbondedCutoff;
if (box[0] < minAllowedSize || box[1] < minAllowedSize || box[2] < minAllowedSize) if (vectors[0][0] < minAllowedSize || vectors[1][1] < minAllowedSize || vectors[2][2] < minAllowedSize)
throw OpenMMException("The periodic box size has decreased to less than twice the nonbonded cutoff."); throw OpenMMException("The periodic box size has decreased to less than twice the nonbonded cutoff.");
clj.setPeriodic(box); clj.setPeriodic(vectors);
} }
if (ewald) if (ewald)
clj.setUseEwald(ewaldAlpha, kmax[0], kmax[1], kmax[2]); clj.setUseEwald(ewaldAlpha, kmax[0], kmax[1], kmax[2]);
...@@ -1018,7 +1027,7 @@ double ReferenceCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bo ...@@ -1018,7 +1027,7 @@ double ReferenceCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bo
ReferenceCustomNonbondedIxn ixn(energyExpression, forceExpression, parameterNames); ReferenceCustomNonbondedIxn ixn(energyExpression, forceExpression, parameterNames);
bool periodic = (nonbondedMethod == CutoffPeriodic); bool periodic = (nonbondedMethod == CutoffPeriodic);
if (nonbondedMethod != NoCutoff) { if (nonbondedMethod != NoCutoff) {
computeNeighborListVoxelHash(*neighborList, numParticles, posData, exclusions, extractBoxSize(context), periodic, nonbondedCutoff, 0.0); computeNeighborListVoxelHash(*neighborList, numParticles, posData, exclusions, extractBoxVectors(context), periodic, nonbondedCutoff, 0.0);
ixn.setUseCutoff(nonbondedCutoff, *neighborList); ixn.setUseCutoff(nonbondedCutoff, *neighborList);
} }
if (periodic) { if (periodic) {
...@@ -1322,7 +1331,7 @@ double ReferenceCalcCustomGBForceKernel::execute(ContextImpl& context, bool incl ...@@ -1322,7 +1331,7 @@ double ReferenceCalcCustomGBForceKernel::execute(ContextImpl& context, bool incl
if (periodic) if (periodic)
ixn.setPeriodic(extractBoxSize(context)); ixn.setPeriodic(extractBoxSize(context));
if (nonbondedMethod != NoCutoff) { if (nonbondedMethod != NoCutoff) {
computeNeighborListVoxelHash(*neighborList, numParticles, posData, exclusions, extractBoxSize(context), periodic, nonbondedCutoff, 0.0); computeNeighborListVoxelHash(*neighborList, numParticles, posData, exclusions, extractBoxVectors(context), periodic, nonbondedCutoff, 0.0);
ixn.setUseCutoff(nonbondedCutoff, *neighborList); ixn.setUseCutoff(nonbondedCutoff, *neighborList);
} }
map<string, double> globalParameters; map<string, double> globalParameters;
......
...@@ -97,6 +97,7 @@ ReferencePlatform::PlatformData::PlatformData(const System& system) : time(0.0), ...@@ -97,6 +97,7 @@ ReferencePlatform::PlatformData::PlatformData(const System& system) : time(0.0),
velocities = new vector<RealVec>(numParticles); velocities = new vector<RealVec>(numParticles);
forces = new vector<RealVec>(numParticles); forces = new vector<RealVec>(numParticles);
periodicBoxSize = new RealVec(); periodicBoxSize = new RealVec();
periodicBoxVectors = new RealVec[3];
constraints = new ReferenceConstraints(system); constraints = new ReferenceConstraints(system);
} }
...@@ -105,5 +106,6 @@ ReferencePlatform::PlatformData::~PlatformData() { ...@@ -105,5 +106,6 @@ ReferencePlatform::PlatformData::~PlatformData() {
delete (vector<RealVec>*) velocities; delete (vector<RealVec>*) velocities;
delete (vector<RealVec>*) forces; delete (vector<RealVec>*) forces;
delete (RealVec*) periodicBoxSize; delete (RealVec*) periodicBoxSize;
delete[] (RealVec*) periodicBoxVectors;
delete (ReferenceConstraints*) constraints; delete (ReferenceConstraints*) constraints;
} }
...@@ -41,13 +41,6 @@ using OpenMM::RealVec; ...@@ -41,13 +41,6 @@ using OpenMM::RealVec;
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
ReferenceForce::ReferenceForce( ){ ReferenceForce::ReferenceForce( ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceForce::ReferenceForce";
// ---------------------------------------------------------------------------------------
} }
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
...@@ -57,13 +50,6 @@ ReferenceForce::ReferenceForce( ){ ...@@ -57,13 +50,6 @@ ReferenceForce::ReferenceForce( ){
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
ReferenceForce::~ReferenceForce( ){ ReferenceForce::~ReferenceForce( ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceForce::~ReferenceForce";
// ---------------------------------------------------------------------------------------
} }
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
...@@ -79,27 +65,8 @@ RealOpenMM ReferenceForce::periodicDifference(RealOpenMM val1, RealOpenMM val2, ...@@ -79,27 +65,8 @@ RealOpenMM ReferenceForce::periodicDifference(RealOpenMM val1, RealOpenMM val2,
} }
/**---------------------------------------------------------------------------------------
Get deltaR and distance and distance**2 between atomI and atomJ (static method)
deltaR: j - i
@param atomCoordinatesI atom i coordinates
@param atomCoordinatesI atom j coordinates
@param deltaR deltaX, deltaY, deltaZ, R2, R upon return
--------------------------------------------------------------------------------------- */
void ReferenceForce::getDeltaR( const RealVec& atomCoordinatesI, const RealVec& atomCoordinatesJ, void ReferenceForce::getDeltaR( const RealVec& atomCoordinatesI, const RealVec& atomCoordinatesJ,
RealOpenMM* deltaR ){ RealOpenMM* deltaR ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "\nReferenceForce::getDeltaR";
// ---------------------------------------------------------------------------------------
deltaR[XIndex] = atomCoordinatesJ[0] - atomCoordinatesI[0]; deltaR[XIndex] = atomCoordinatesJ[0] - atomCoordinatesI[0];
deltaR[YIndex] = atomCoordinatesJ[1] - atomCoordinatesI[1]; deltaR[YIndex] = atomCoordinatesJ[1] - atomCoordinatesI[1];
deltaR[ZIndex] = atomCoordinatesJ[2] - atomCoordinatesI[2]; deltaR[ZIndex] = atomCoordinatesJ[2] - atomCoordinatesI[2];
...@@ -108,27 +75,8 @@ void ReferenceForce::getDeltaR( const RealVec& atomCoordinatesI, const RealVec& ...@@ -108,27 +75,8 @@ void ReferenceForce::getDeltaR( const RealVec& atomCoordinatesI, const RealVec&
deltaR[RIndex] = (RealOpenMM) SQRT( deltaR[R2Index] ); deltaR[RIndex] = (RealOpenMM) SQRT( deltaR[R2Index] );
} }
/**---------------------------------------------------------------------------------------
Get deltaR and distance and distance**2 between atomI and atomJ, assuming periodic
boundary conditions (static method); deltaR: j - i
@param atomCoordinatesI atom i coordinates
@param atomCoordinatesI atom j coordinates
@param boxSize X, Y, and Z sizes of the periodic box
@param deltaR deltaX, deltaY, deltaZ, R2, R upon return
--------------------------------------------------------------------------------------- */
void ReferenceForce::getDeltaRPeriodic( const RealVec& atomCoordinatesI, const RealVec& atomCoordinatesJ, void ReferenceForce::getDeltaRPeriodic( const RealVec& atomCoordinatesI, const RealVec& atomCoordinatesJ,
const RealOpenMM* boxSize, RealOpenMM* deltaR ){ const RealOpenMM* boxSize, RealOpenMM* deltaR ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "\nReferenceForce::getDeltaR";
// ---------------------------------------------------------------------------------------
deltaR[XIndex] = periodicDifference(atomCoordinatesJ[0], atomCoordinatesI[0], boxSize[0]); deltaR[XIndex] = periodicDifference(atomCoordinatesJ[0], atomCoordinatesI[0], boxSize[0]);
deltaR[YIndex] = periodicDifference(atomCoordinatesJ[1], atomCoordinatesI[1], boxSize[1]); deltaR[YIndex] = periodicDifference(atomCoordinatesJ[1], atomCoordinatesI[1], boxSize[1]);
deltaR[ZIndex] = periodicDifference(atomCoordinatesJ[2], atomCoordinatesI[2], boxSize[2]); deltaR[ZIndex] = periodicDifference(atomCoordinatesJ[2], atomCoordinatesI[2], boxSize[2]);
...@@ -137,29 +85,17 @@ void ReferenceForce::getDeltaRPeriodic( const RealVec& atomCoordinatesI, const R ...@@ -137,29 +85,17 @@ void ReferenceForce::getDeltaRPeriodic( const RealVec& atomCoordinatesI, const R
deltaR[RIndex] = (RealOpenMM) SQRT( deltaR[R2Index] ); deltaR[RIndex] = (RealOpenMM) SQRT( deltaR[R2Index] );
} }
/**--------------------------------------------------------------------------------------- void ReferenceForce::getDeltaRPeriodic( const RealVec& atomCoordinatesI, const RealVec& atomCoordinatesJ,
const RealVec* boxVectors, RealOpenMM* deltaR ){
Get deltaR between atomI and atomJ (static method); deltaR: j - i RealVec diff = atomCoordinatesJ-atomCoordinatesI;
diff -= boxVectors[2]*floor(diff[2]/boxVectors[2][2]+0.5);
@param atomCoordinatesI atom i coordinates diff -= boxVectors[1]*floor(diff[1]/boxVectors[1][1]+0.5);
@param atomCoordinatesI atom j coordinates diff -= boxVectors[0]*floor(diff[0]/boxVectors[0][0]+0.5);
@param deltaR deltaX, deltaY, deltaZ upon return deltaR[XIndex] = diff[0];
deltaR[YIndex] = diff[1];
--------------------------------------------------------------------------------------- */ deltaR[ZIndex] = diff[2];
deltaR[R2Index] = diff.dot(diff);
void ReferenceForce::getDeltaROnly( const RealOpenMM* atomCoordinatesI, deltaR[RIndex] = SQRT(deltaR[R2Index]);
const RealOpenMM* atomCoordinatesJ,
RealOpenMM* deltaR ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "\nReferenceForce::getDeltaR";
// ---------------------------------------------------------------------------------------
deltaR[XIndex] = atomCoordinatesJ[0] - atomCoordinatesI[0];
deltaR[YIndex] = atomCoordinatesJ[1] - atomCoordinatesI[1];
deltaR[ZIndex] = atomCoordinatesJ[2] - atomCoordinatesI[2];
} }
double* ReferenceForce::getVariablePointer(Lepton::CompiledExpression& expression, const std::string& name) { double* ReferenceForce::getVariablePointer(Lepton::CompiledExpression& expression, const std::string& name) {
......
...@@ -112,20 +112,20 @@ void ReferenceLJCoulombIxn::setUseSwitchingFunction( RealOpenMM distance ) { ...@@ -112,20 +112,20 @@ void ReferenceLJCoulombIxn::setUseSwitchingFunction( RealOpenMM distance ) {
also been set, and the smallest side of the periodic box is at least twice the cutoff also been set, and the smallest side of the periodic box is at least twice the cutoff
distance. distance.
@param boxSize the X, Y, and Z widths of the periodic box @param vectors the vectors defining the periodic box
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
void ReferenceLJCoulombIxn::setPeriodic( RealVec& boxSize ) { void ReferenceLJCoulombIxn::setPeriodic(OpenMM::RealVec* vectors) {
assert(cutoff); assert(cutoff);
assert(boxSize[0] >= 2.0*cutoffDistance); assert(vectors[0][0] >= 2.0*cutoffDistance);
assert(boxSize[1] >= 2.0*cutoffDistance); assert(vectors[1][1] >= 2.0*cutoffDistance);
assert(boxSize[2] >= 2.0*cutoffDistance); assert(vectors[2][2] >= 2.0*cutoffDistance);
periodic = true; periodic = true;
periodicBoxSize[0] = boxSize[0]; periodicBoxVectors[0] = vectors[0];
periodicBoxSize[1] = boxSize[1]; periodicBoxVectors[1] = vectors[1];
periodicBoxSize[2] = boxSize[2]; periodicBoxVectors[2] = vectors[2];
} }
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
...@@ -197,7 +197,7 @@ void ReferenceLJCoulombIxn::calculateEwaldIxn(int numberOfAtoms, vector<RealVec> ...@@ -197,7 +197,7 @@ void ReferenceLJCoulombIxn::calculateEwaldIxn(int numberOfAtoms, vector<RealVec>
RealOpenMM factorEwald = -1 / (4*alphaEwald*alphaEwald); RealOpenMM factorEwald = -1 / (4*alphaEwald*alphaEwald);
RealOpenMM SQRT_PI = sqrt(PI_M); RealOpenMM SQRT_PI = sqrt(PI_M);
RealOpenMM TWO_PI = 2.0 * PI_M; RealOpenMM TWO_PI = 2.0 * PI_M;
RealOpenMM recipCoeff = (RealOpenMM)(ONE_4PI_EPS0*4*PI_M/(periodicBoxSize[0] * periodicBoxSize[1] * periodicBoxSize[2]) /epsilon); RealOpenMM recipCoeff = (RealOpenMM)(ONE_4PI_EPS0*4*PI_M/(periodicBoxVectors[0][0] * periodicBoxVectors[1][1] * periodicBoxVectors[2][2]) /epsilon);
RealOpenMM totalSelfEwaldEnergy = 0.0; RealOpenMM totalSelfEwaldEnergy = 0.0;
RealOpenMM realSpaceEwaldEnergy = 0.0; RealOpenMM realSpaceEwaldEnergy = 0.0;
...@@ -237,6 +237,7 @@ void ReferenceLJCoulombIxn::calculateEwaldIxn(int numberOfAtoms, vector<RealVec> ...@@ -237,6 +237,7 @@ void ReferenceLJCoulombIxn::calculateEwaldIxn(int numberOfAtoms, vector<RealVec>
vector<RealOpenMM> charges(numberOfAtoms); vector<RealOpenMM> charges(numberOfAtoms);
for (int i = 0; i < numberOfAtoms; i++) for (int i = 0; i < numberOfAtoms; i++)
charges[i] = atomParameters[i][QIndex]; charges[i] = atomParameters[i][QIndex];
RealOpenMM periodicBoxSize[] = {periodicBoxVectors[0][0], periodicBoxVectors[1][1], periodicBoxVectors[2][2]};
pme_exec(pmedata,atomCoordinates,forces,charges,periodicBoxSize,&recipEnergy,virial); pme_exec(pmedata,atomCoordinates,forces,charges,periodicBoxSize,&recipEnergy,virial);
if( totalEnergy ) if( totalEnergy )
...@@ -255,7 +256,7 @@ void ReferenceLJCoulombIxn::calculateEwaldIxn(int numberOfAtoms, vector<RealVec> ...@@ -255,7 +256,7 @@ void ReferenceLJCoulombIxn::calculateEwaldIxn(int numberOfAtoms, vector<RealVec>
// setup reciprocal box // setup reciprocal box
RealOpenMM recipBoxSize[3] = { TWO_PI / periodicBoxSize[0], TWO_PI / periodicBoxSize[1], TWO_PI / periodicBoxSize[2]}; RealOpenMM recipBoxSize[3] = { TWO_PI / periodicBoxVectors[0][0], TWO_PI / periodicBoxVectors[1][1], TWO_PI / periodicBoxVectors[2][2]};
// setup K-vectors // setup K-vectors
...@@ -370,7 +371,7 @@ void ReferenceLJCoulombIxn::calculateEwaldIxn(int numberOfAtoms, vector<RealVec> ...@@ -370,7 +371,7 @@ void ReferenceLJCoulombIxn::calculateEwaldIxn(int numberOfAtoms, vector<RealVec>
int jj = pair.second; int jj = pair.second;
RealOpenMM deltaR[2][ReferenceForce::LastDeltaRIndex]; RealOpenMM deltaR[2][ReferenceForce::LastDeltaRIndex];
ReferenceForce::getDeltaRPeriodic( atomCoordinates[jj], atomCoordinates[ii], periodicBoxSize, deltaR[0] ); ReferenceForce::getDeltaRPeriodic( atomCoordinates[jj], atomCoordinates[ii], periodicBoxVectors, deltaR[0] );
RealOpenMM r = deltaR[0][ReferenceForce::RIndex]; RealOpenMM r = deltaR[0][ReferenceForce::RIndex];
RealOpenMM inverseR = one/(deltaR[0][ReferenceForce::RIndex]); RealOpenMM inverseR = one/(deltaR[0][ReferenceForce::RIndex]);
RealOpenMM switchValue = 1, switchDeriv = 0; RealOpenMM switchValue = 1, switchDeriv = 0;
...@@ -556,7 +557,7 @@ void ReferenceLJCoulombIxn::calculateOneIxn( int ii, int jj, vector<RealVec>& at ...@@ -556,7 +557,7 @@ void ReferenceLJCoulombIxn::calculateOneIxn( int ii, int jj, vector<RealVec>& at
// get deltaR, R2, and R between 2 atoms // get deltaR, R2, and R between 2 atoms
if (periodic) if (periodic)
ReferenceForce::getDeltaRPeriodic( atomCoordinates[jj], atomCoordinates[ii], periodicBoxSize, deltaR[0] ); ReferenceForce::getDeltaRPeriodic( atomCoordinates[jj], atomCoordinates[ii], periodicBoxVectors, deltaR[0] );
else else
ReferenceForce::getDeltaR( atomCoordinates[jj], atomCoordinates[ii], deltaR[0] ); ReferenceForce::getDeltaR( atomCoordinates[jj], atomCoordinates[ii], deltaR[0] );
......
...@@ -12,26 +12,15 @@ namespace OpenMM { ...@@ -12,26 +12,15 @@ namespace OpenMM {
typedef std::vector<AtomIndex> AtomList; typedef std::vector<AtomIndex> AtomList;
static double periodicDifference(double val1, double val2, double period) {
double diff = val1-val2;
double base = floor(diff/period+0.5)*period;
return diff-base;
}
// squared distance between two points // squared distance between two points
static double compPairDistanceSquared(const RealVec& pos1, const RealVec& pos2, const RealVec& periodicBoxSize, bool usePeriodic) { static double compPairDistanceSquared(const RealVec& pos1, const RealVec& pos2, const RealVec* periodicBoxVectors, bool usePeriodic) {
double dx, dy, dz; RealVec diff = pos2-pos1;
if (!usePeriodic) { if (usePeriodic) {
dx = pos2[0] - pos1[0]; diff -= periodicBoxVectors[2]*floor(diff[2]/periodicBoxVectors[2][2]+0.5);
dy = pos2[1] - pos1[1]; diff -= periodicBoxVectors[1]*floor(diff[1]/periodicBoxVectors[1][1]+0.5);
dz = pos2[2] - pos1[2]; diff -= periodicBoxVectors[0]*floor(diff[0]/periodicBoxVectors[0][0]+0.5);
}
else {
dx = periodicDifference(pos2[0], pos1[0], periodicBoxSize[0]);
dy = periodicDifference(pos2[1], pos1[1], periodicBoxSize[1]);
dz = periodicDifference(pos2[2], pos1[2], periodicBoxSize[2]);
} }
return dx*dx + dy*dy + dz*dz; return diff.dot(diff);
} }
// Ridiculous O(n^2) version of neighbor list // Ridiculous O(n^2) version of neighbor list
...@@ -41,7 +30,7 @@ void OPENMM_EXPORT computeNeighborListNaive( ...@@ -41,7 +30,7 @@ void OPENMM_EXPORT computeNeighborListNaive(
int nAtoms, int nAtoms,
const AtomLocationList& atomLocations, const AtomLocationList& atomLocations,
const vector<set<int> >& exclusions, const vector<set<int> >& exclusions,
const RealVec& periodicBoxSize, const RealVec* periodicBoxVectors,
bool usePeriodic, bool usePeriodic,
double maxDistance, double maxDistance,
double minDistance, double minDistance,
...@@ -55,7 +44,7 @@ void OPENMM_EXPORT computeNeighborListNaive( ...@@ -55,7 +44,7 @@ void OPENMM_EXPORT computeNeighborListNaive(
{ {
for (AtomIndex atomJ = atomI + 1; atomJ < (AtomIndex) nAtoms; ++atomJ) for (AtomIndex atomJ = atomI + 1; atomJ < (AtomIndex) nAtoms; ++atomJ)
{ {
double pairDistanceSquared = compPairDistanceSquared(atomLocations[atomI], atomLocations[atomJ], periodicBoxSize, usePeriodic); double pairDistanceSquared = compPairDistanceSquared(atomLocations[atomI], atomLocations[atomJ], periodicBoxVectors, usePeriodic);
if ( (pairDistanceSquared <= maxDistanceSquared) && (pairDistanceSquared >= minDistanceSquared)) if ( (pairDistanceSquared <= maxDistanceSquared) && (pairDistanceSquared >= minDistanceSquared))
if (exclusions[atomI].find(atomJ) == exclusions[atomI].end()) if (exclusions[atomI].find(atomJ) == exclusions[atomI].end())
{ {
...@@ -95,15 +84,15 @@ typedef std::vector< VoxelItem > Voxel; ...@@ -95,15 +84,15 @@ typedef std::vector< VoxelItem > Voxel;
class VoxelHash class VoxelHash
{ {
public: public:
VoxelHash(double vsx, double vsy, double vsz, const RealVec& periodicBoxSize, bool usePeriodic) : VoxelHash(double vsx, double vsy, double vsz, const RealVec* periodicBoxVectors, bool usePeriodic) :
voxelSizeX(vsx), voxelSizeY(vsy), voxelSizeZ(vsz), periodicBoxSize(periodicBoxSize), usePeriodic(usePeriodic) { voxelSizeX(vsx), voxelSizeY(vsy), voxelSizeZ(vsz), periodicBoxVectors(periodicBoxVectors), usePeriodic(usePeriodic) {
if (usePeriodic) { if (usePeriodic) {
nx = (int) floor(periodicBoxSize[0]/voxelSizeX+0.5); nx = (int) floor(periodicBoxVectors[0][0]/voxelSizeX+0.5);
ny = (int) floor(periodicBoxSize[1]/voxelSizeY+0.5); ny = (int) floor(periodicBoxVectors[1][1]/voxelSizeY+0.5);
nz = (int) floor(periodicBoxSize[2]/voxelSizeZ+0.5); nz = (int) floor(periodicBoxVectors[2][2]/voxelSizeZ+0.5);
voxelSizeX = periodicBoxSize[0]/nx; voxelSizeX = periodicBoxVectors[0][0]/nx;
voxelSizeY = periodicBoxSize[1]/ny; voxelSizeY = periodicBoxVectors[1][1]/ny;
voxelSizeZ = periodicBoxSize[2]/nz; voxelSizeZ = periodicBoxVectors[2][2]/nz;
} }
} }
...@@ -118,20 +107,15 @@ public: ...@@ -118,20 +107,15 @@ public:
VoxelIndex getVoxelIndex(const RealVec& location) const { VoxelIndex getVoxelIndex(const RealVec& location) const {
double xperiodic, yperiodic, zperiodic; RealVec r = location;
if (!usePeriodic) { if (usePeriodic) {
xperiodic = location[0]; r -= periodicBoxVectors[2]*floor(r[2]/periodicBoxVectors[2][2]);
yperiodic = location[1]; r -= periodicBoxVectors[1]*floor(r[1]/periodicBoxVectors[1][1]);
zperiodic = location[2]; r -= periodicBoxVectors[0]*floor(r[0]/periodicBoxVectors[0][0]);
}
else {
xperiodic = location[0]-periodicBoxSize[0]*floor(location[0]/periodicBoxSize[0]);
yperiodic = location[1]-periodicBoxSize[1]*floor(location[1]/periodicBoxSize[1]);
zperiodic = location[2]-periodicBoxSize[2]*floor(location[2]/periodicBoxSize[2]);
} }
int x = int(floor(xperiodic / voxelSizeX)); int x = int(floor(r[0]/voxelSizeX));
int y = int(floor(yperiodic / voxelSizeY)); int y = int(floor(r[1]/voxelSizeY));
int z = int(floor(zperiodic / voxelSizeZ)); int z = int(floor(r[2]/voxelSizeZ));
return VoxelIndex(x, y, z); return VoxelIndex(x, y, z);
} }
...@@ -194,7 +178,7 @@ public: ...@@ -194,7 +178,7 @@ public:
// Ignore self hits // Ignore self hits
if (atomI == atomJ) continue; if (atomI == atomJ) continue;
double dSquared = compPairDistanceSquared(locationI, locationJ, periodicBoxSize, usePeriodic); double dSquared = compPairDistanceSquared(locationI, locationJ, periodicBoxVectors, usePeriodic);
if (dSquared > maxDistanceSquared) continue; if (dSquared > maxDistanceSquared) continue;
if (dSquared < minDistanceSquared) continue; if (dSquared < minDistanceSquared) continue;
...@@ -213,7 +197,7 @@ public: ...@@ -213,7 +197,7 @@ public:
private: private:
double voxelSizeX, voxelSizeY, voxelSizeZ; double voxelSizeX, voxelSizeY, voxelSizeZ;
int nx, ny, nz; int nx, ny, nz;
const RealVec& periodicBoxSize; const RealVec* periodicBoxVectors;
const bool usePeriodic; const bool usePeriodic;
std::map<VoxelIndex, Voxel> voxelMap; std::map<VoxelIndex, Voxel> voxelMap;
}; };
...@@ -223,9 +207,9 @@ private: ...@@ -223,9 +207,9 @@ private:
void OPENMM_EXPORT computeNeighborListVoxelHash( void OPENMM_EXPORT computeNeighborListVoxelHash(
NeighborList& neighborList, NeighborList& neighborList,
int nAtoms, int nAtoms,
const AtomLocationList& atomLocations, const AtomLocationList& atomLocations,
const vector<set<int> >& exclusions, const vector<set<int> >& exclusions,
const RealVec& periodicBoxSize, const RealVec* periodicBoxVectors,
bool usePeriodic, bool usePeriodic,
double maxDistance, double maxDistance,
double minDistance, double minDistance,
...@@ -238,11 +222,11 @@ void OPENMM_EXPORT computeNeighborListVoxelHash( ...@@ -238,11 +222,11 @@ void OPENMM_EXPORT computeNeighborListVoxelHash(
if (!usePeriodic) if (!usePeriodic)
edgeSizeX = edgeSizeY = edgeSizeZ = maxDistance; // TODO - adjust this as needed edgeSizeX = edgeSizeY = edgeSizeZ = maxDistance; // TODO - adjust this as needed
else { else {
edgeSizeX = 0.5*periodicBoxSize[0]/floor(periodicBoxSize[0]/maxDistance); edgeSizeX = 0.5*periodicBoxVectors[0][0]/floor(periodicBoxVectors[0][0]/maxDistance);
edgeSizeY = 0.5*periodicBoxSize[1]/floor(periodicBoxSize[1]/maxDistance); edgeSizeY = 0.5*periodicBoxVectors[1][1]/floor(periodicBoxVectors[1][1]/maxDistance);
edgeSizeZ = 0.5*periodicBoxSize[2]/floor(periodicBoxSize[2]/maxDistance); edgeSizeZ = 0.5*periodicBoxVectors[2][2]/floor(periodicBoxVectors[2][2]/maxDistance);
} }
VoxelHash voxelHash(edgeSizeX, edgeSizeY, edgeSizeZ, periodicBoxSize, usePeriodic); VoxelHash voxelHash(edgeSizeX, edgeSizeY, edgeSizeZ, periodicBoxVectors, usePeriodic);
for (AtomIndex atomJ = 0; atomJ < (AtomIndex) nAtoms; ++atomJ) // use "j", because j > i for pairs 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 // 1) Find other atoms that are close to this one
......
...@@ -48,17 +48,17 @@ void testNeighborList() ...@@ -48,17 +48,17 @@ void testNeighborList()
NeighborList neighborList; NeighborList neighborList;
RealVec boxSize; RealVec boxVectors[3];
computeNeighborListNaive(neighborList, 2, particleList, exclusions, boxSize, false, 13.7, 0.01); computeNeighborListNaive(neighborList, 2, particleList, exclusions, boxVectors, false, 13.7, 0.01);
assert(neighborList.size() == 1); assert(neighborList.size() == 1);
computeNeighborListNaive(neighborList, 2, particleList, exclusions, boxSize, false, 13.5, 0.01); computeNeighborListNaive(neighborList, 2, particleList, exclusions, boxVectors, false, 13.5, 0.01);
assert(neighborList.size() == 0); assert(neighborList.size() == 0);
computeNeighborListVoxelHash(neighborList, 2, particleList, exclusions, boxSize, false, 13.7, 0.01); computeNeighborListVoxelHash(neighborList, 2, particleList, exclusions, boxVectors, false, 13.7, 0.01);
assert(neighborList.size() == 1); assert(neighborList.size() == 1);
computeNeighborListVoxelHash(neighborList, 2, particleList, exclusions, boxSize, false, 13.5, 0.01); computeNeighborListVoxelHash(neighborList, 2, particleList, exclusions, boxVectors, false, 13.5, 0.01);
assert(neighborList.size() == 0); assert(neighborList.size() == 0);
} }
...@@ -93,6 +93,10 @@ void testPeriodic() { ...@@ -93,6 +93,10 @@ void testPeriodic() {
const int numParticles = 100; const int numParticles = 100;
const double cutoff = 3.0; const double cutoff = 3.0;
const RealVec periodicBoxSize(20.0, 15.0, 22.0); const RealVec periodicBoxSize(20.0, 15.0, 22.0);
RealVec periodicBoxVectors[3];
periodicBoxVectors[0] = RealVec(20, 0, 0);
periodicBoxVectors[1] = RealVec(0, 15, 0);
periodicBoxVectors[2] = RealVec(0, 0, 22);
vector<RealVec> particleList(numParticles); vector<RealVec> particleList(numParticles);
OpenMM_SFMT::SFMT sfmt; OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt); init_gen_rand(0, sfmt);
...@@ -104,9 +108,9 @@ void testPeriodic() { ...@@ -104,9 +108,9 @@ void testPeriodic() {
} }
vector<set<int> > exclusions(numParticles); vector<set<int> > exclusions(numParticles);
NeighborList neighborList; NeighborList neighborList;
computeNeighborListNaive(neighborList, numParticles, particleList, exclusions, periodicBoxSize, true, cutoff); computeNeighborListNaive(neighborList, numParticles, particleList, exclusions, periodicBoxVectors, true, cutoff);
verifyNeighborList(neighborList, numParticles, particleList, periodicBoxSize, cutoff); verifyNeighborList(neighborList, numParticles, particleList, periodicBoxSize, cutoff);
computeNeighborListVoxelHash(neighborList, numParticles, particleList, exclusions, periodicBoxSize, true, cutoff); computeNeighborListVoxelHash(neighborList, numParticles, particleList, exclusions, periodicBoxVectors, true, cutoff);
verifyNeighborList(neighborList, numParticles, particleList, periodicBoxSize, cutoff); verifyNeighborList(neighborList, numParticles, particleList, periodicBoxSize, cutoff);
} }
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "openmm/VerletIntegrator.h" #include "openmm/VerletIntegrator.h"
#include "SimTKOpenMMRealType.h" #include "SimTKOpenMMRealType.h"
#include "openmm/HarmonicBondForce.h" #include "openmm/HarmonicBondForce.h"
#include "sfmt/SFMT.h"
#include <iostream> #include <iostream>
#include <vector> #include <vector>
...@@ -351,6 +352,69 @@ void testPeriodic() { ...@@ -351,6 +352,69 @@ void testPeriodic() {
ASSERT_EQUAL_TOL(2*ONE_4PI_EPS0*(1.0)*(1.0+krf*1.0-crf), state.getPotentialEnergy(), TOL); ASSERT_EQUAL_TOL(2*ONE_4PI_EPS0*(1.0)*(1.0+krf*1.0-crf), state.getPotentialEnergy(), TOL);
} }
void testTriclinic() {
ReferencePlatform platform;
System system;
system.addParticle(1.0);
system.addParticle(1.0);
Vec3 a(3.1, 0, 0);
Vec3 b(0.4, 3.5, 0);
Vec3 c(-0.1, -0.5, 4.0);
system.setDefaultPeriodicBoxVectors(a, b, c);
VerletIntegrator integrator(0.01);
NonbondedForce* nonbonded = new NonbondedForce();
nonbonded->addParticle(1.0, 1, 0);
nonbonded->addParticle(1.0, 1, 0);
nonbonded->setNonbondedMethod(NonbondedForce::CutoffPeriodic);
const double cutoff = 1.5;
nonbonded->setCutoffDistance(cutoff);
system.addForce(nonbonded);
Context context(system, integrator, platform);
vector<Vec3> positions(2);
OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt);
const double eps = 78.3;
const double krf = (1.0/(cutoff*cutoff*cutoff))*(eps-1.0)/(2.0*eps+1.0);
const double crf = (1.0/cutoff)*(3.0*eps)/(2.0*eps+1.0);
for (int iteration = 0; iteration < 50; iteration++) {
// Generate random positions for the two particles.
positions[0] = a*genrand_real2(sfmt) + b*genrand_real2(sfmt) + c*genrand_real2(sfmt);
positions[1] = a*genrand_real2(sfmt) + b*genrand_real2(sfmt) + c*genrand_real2(sfmt);
context.setPositions(positions);
// Loop over all possible periodic copies and find the nearest one.
Vec3 delta;
double distance2 = 100.0;
for (int i = -1; i < 2; i++)
for (int j = -1; j < 2; j++)
for (int k = -1; k < 2; k++) {
Vec3 d = positions[1]-positions[0]+a*i+b*j+c*k;
if (d.dot(d) < distance2) {
delta = d;
distance2 = d.dot(d);
}
}
double distance = sqrt(distance2);
// See if the force and energy are correct.
State state = context.getState(State::Forces | State::Energy);
if (distance >= cutoff) {
ASSERT_EQUAL(0.0, state.getPotentialEnergy());
ASSERT_EQUAL_VEC(Vec3(0, 0, 0), state.getForces()[0], 0);
ASSERT_EQUAL_VEC(Vec3(0, 0, 0), state.getForces()[1], 0);
}
else {
const Vec3 force = delta*ONE_4PI_EPS0*(-1.0/(distance*distance*distance)+2.0*krf);
ASSERT_EQUAL_TOL(ONE_4PI_EPS0*(1.0/distance+krf*distance*distance-crf), state.getPotentialEnergy(), TOL);
ASSERT_EQUAL_VEC(force, state.getForces()[0], TOL);
ASSERT_EQUAL_VEC(-force, state.getForces()[1], TOL);
}
}
}
void testDispersionCorrection() { void testDispersionCorrection() {
// Create a box full of identical particles. // Create a box full of identical particles.
...@@ -483,6 +547,7 @@ int main() { ...@@ -483,6 +547,7 @@ int main() {
testCutoff(); testCutoff();
testCutoff14(); testCutoff14();
testPeriodic(); testPeriodic();
testTriclinic();
testDispersionCorrection(); testDispersionCorrection();
testSwitchingFunction(NonbondedForce::CutoffNonPeriodic); testSwitchingFunction(NonbondedForce::CutoffNonPeriodic);
testSwitchingFunction(NonbondedForce::PME); testSwitchingFunction(NonbondedForce::PME);
......
...@@ -74,6 +74,11 @@ static RealVec& extractBoxSize(ContextImpl& context) { ...@@ -74,6 +74,11 @@ static RealVec& extractBoxSize(ContextImpl& context) {
return *(RealVec*) data->periodicBoxSize; return *(RealVec*) data->periodicBoxSize;
} }
static RealVec* extractBoxVectors(ContextImpl& context) {
ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData());
return (RealVec*) data->periodicBoxVectors;
}
// *************************************************************************** // ***************************************************************************
ReferenceCalcAmoebaBondForceKernel::ReferenceCalcAmoebaBondForceKernel(std::string name, const Platform& platform, const System& system) : ReferenceCalcAmoebaBondForceKernel::ReferenceCalcAmoebaBondForceKernel(std::string name, const Platform& platform, const System& system) :
...@@ -968,7 +973,7 @@ double ReferenceCalcAmoebaVdwForceKernel::execute(ContextImpl& context, bool inc ...@@ -968,7 +973,7 @@ double ReferenceCalcAmoebaVdwForceKernel::execute(ContextImpl& context, bool inc
RealOpenMM energy; RealOpenMM energy;
if( useCutoff ){ if( useCutoff ){
vdwForce.setCutoff( cutoff ); vdwForce.setCutoff( cutoff );
computeNeighborListVoxelHash( *neighborList, numParticles, posData, allExclusions, extractBoxSize(context), usePBC, cutoff, 0.0); computeNeighborListVoxelHash( *neighborList, numParticles, posData, allExclusions, extractBoxVectors(context), usePBC, cutoff, 0.0);
if( usePBC ){ if( usePBC ){
vdwForce.setNonbondedMethod( AmoebaReferenceVdwForce::CutoffPeriodic); vdwForce.setNonbondedMethod( AmoebaReferenceVdwForce::CutoffPeriodic);
RealVec& box = extractBoxSize(context); RealVec& box = extractBoxSize(context);
......
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