Commit 661fa97f authored by Mark Friedrichs's avatar Mark Friedrichs
Browse files

The differences in the Ewald energies between the Reference and Cuda platforms...

The differences in the Ewald energies between the Reference and Cuda platforms were traced to roundoff error in the 
computation of the Vdw and Coulomb ixns for the short-range energy contribution (verified using double precision in the sum); the vdw and Coulomb terms are now accumulated separately and then added to the total energy 
parent 5a4103d7
...@@ -243,9 +243,10 @@ int ReferenceLJCoulombIxn::calculateEwaldIxn( int numberOfAtoms, RealOpenMM** at ...@@ -243,9 +243,10 @@ int ReferenceLJCoulombIxn::calculateEwaldIxn( int numberOfAtoms, RealOpenMM** at
RealOpenMM TWO_PI = 2.0 * PI; RealOpenMM TWO_PI = 2.0 * PI;
RealOpenMM recipCoeff = (RealOpenMM)(4*PI/(periodicBoxSize[0] * periodicBoxSize[1] * periodicBoxSize[2]) /epsilon); RealOpenMM recipCoeff = (RealOpenMM)(4*PI/(periodicBoxSize[0] * periodicBoxSize[1] * periodicBoxSize[2]) /epsilon);
RealOpenMM selfEwaldEnergy = 0.0; RealOpenMM totalSelfEwaldEnergy = 0.0;
RealOpenMM realSpaceEwaldEnergy = 0.0; RealOpenMM realSpaceEwaldEnergy = 0.0;
RealOpenMM recipEnergy = 0.0; RealOpenMM recipEnergy = 0.0;
RealOpenMM totalRecipEnergy = 0.0;
RealOpenMM vdwEnergy = 0.0; RealOpenMM vdwEnergy = 0.0;
// ************************************************************************************** // **************************************************************************************
...@@ -253,16 +254,18 @@ int ReferenceLJCoulombIxn::calculateEwaldIxn( int numberOfAtoms, RealOpenMM** at ...@@ -253,16 +254,18 @@ int ReferenceLJCoulombIxn::calculateEwaldIxn( int numberOfAtoms, RealOpenMM** at
// ************************************************************************************** // **************************************************************************************
for( int atomID = 0; atomID < numberOfAtoms; atomID++ ){ for( int atomID = 0; atomID < numberOfAtoms; atomID++ ){
selfEwaldEnergy = atomParameters[atomID][QIndex]*atomParameters[atomID][QIndex] * alphaEwald/SQRT_PI; RealOpenMM selfEwaldEnergy = atomParameters[atomID][QIndex]*atomParameters[atomID][QIndex] * alphaEwald/SQRT_PI;
totalSelfEwaldEnergy -= selfEwaldEnergy;
if( totalEnergy )
*totalEnergy -= selfEwaldEnergy;
if( energyByAtom ){ if( energyByAtom ){
energyByAtom[atomID] -= selfEwaldEnergy; energyByAtom[atomID] -= selfEwaldEnergy;
} }
} }
if( totalEnergy ){
*totalEnergy += totalSelfEwaldEnergy;
}
// ************************************************************************************** // **************************************************************************************
// RECIPROCAL SPACE EWALD ENERGY AND FORCES // RECIPROCAL SPACE EWALD ENERGY AND FORCES
// ************************************************************************************** // **************************************************************************************
...@@ -333,7 +336,6 @@ int ReferenceLJCoulombIxn::calculateEwaldIxn( int numberOfAtoms, RealOpenMM** at ...@@ -333,7 +336,6 @@ int ReferenceLJCoulombIxn::calculateEwaldIxn( int numberOfAtoms, RealOpenMM** at
// calculate reciprocal space energy and forces // calculate reciprocal space energy and forces
int lowry = 0; int lowry = 0;
int lowrz = 1; int lowrz = 1;
...@@ -386,7 +388,8 @@ int ReferenceLJCoulombIxn::calculateEwaldIxn( int numberOfAtoms, RealOpenMM** at ...@@ -386,7 +388,8 @@ int ReferenceLJCoulombIxn::calculateEwaldIxn( int numberOfAtoms, RealOpenMM** at
forces[n][2] += 2 * recipCoeff * force * kz ; forces[n][2] += 2 * recipCoeff * force * kz ;
} }
recipEnergy = recipCoeff * ak * ( cs * cs + ss * ss); recipEnergy = recipCoeff * ak * ( cs * cs + ss * ss);
totalRecipEnergy += recipEnergy;
if( totalEnergy ) if( totalEnergy )
*totalEnergy += recipEnergy; *totalEnergy += recipEnergy;
...@@ -408,10 +411,14 @@ int ReferenceLJCoulombIxn::calculateEwaldIxn( int numberOfAtoms, RealOpenMM** at ...@@ -408,10 +411,14 @@ int ReferenceLJCoulombIxn::calculateEwaldIxn( int numberOfAtoms, RealOpenMM** at
SimTKOpenMMLog::printError( message ); SimTKOpenMMLog::printError( message );
} }
// ************************************************************************************** // **************************************************************************************
// SHORT-RANGE ENERGY AND FORCES // SHORT-RANGE ENERGY AND FORCES
// ************************************************************************************** // **************************************************************************************
RealOpenMM totalVdwEnergy = 0.0f;
RealOpenMM totalRealSpaceEwaldEnergy = 0.0f;
for (int i = 0; i < (int) neighborList->size(); i++) { for (int i = 0; i < (int) neighborList->size(); i++) {
OpenMM::AtomPair pair = (*neighborList)[i]; OpenMM::AtomPair pair = (*neighborList)[i];
int ii = pair.first; int ii = pair.first;
...@@ -445,11 +452,11 @@ int ReferenceLJCoulombIxn::calculateEwaldIxn( int numberOfAtoms, RealOpenMM** at ...@@ -445,11 +452,11 @@ int ReferenceLJCoulombIxn::calculateEwaldIxn( int numberOfAtoms, RealOpenMM** at
// accumulate energies // accumulate energies
realSpaceEwaldEnergy = (RealOpenMM) (atomParameters[ii][QIndex]*atomParameters[jj][QIndex]*inverseR*erfc(alphaR)); realSpaceEwaldEnergy = (RealOpenMM) (atomParameters[ii][QIndex]*atomParameters[jj][QIndex]*inverseR*erfc(alphaR));
vdwEnergy = eps*(sig6-one)*sig6; vdwEnergy = eps*(sig6-one)*sig6;
if( totalEnergy ) totalVdwEnergy += vdwEnergy;
*totalEnergy += realSpaceEwaldEnergy + vdwEnergy; totalRealSpaceEwaldEnergy += realSpaceEwaldEnergy;
if( energyByAtom ){ if( energyByAtom ){
energyByAtom[ii] += realSpaceEwaldEnergy + vdwEnergy; energyByAtom[ii] += realSpaceEwaldEnergy + vdwEnergy;
...@@ -458,8 +465,12 @@ int ReferenceLJCoulombIxn::calculateEwaldIxn( int numberOfAtoms, RealOpenMM** at ...@@ -458,8 +465,12 @@ int ReferenceLJCoulombIxn::calculateEwaldIxn( int numberOfAtoms, RealOpenMM** at
} }
if( totalEnergy )
*totalEnergy += totalRealSpaceEwaldEnergy + totalVdwEnergy;
// Now subtract off the exclusions, since they were implicitly included in the reciprocal space sum. // Now subtract off the exclusions, since they were implicitly included in the reciprocal space sum.
RealOpenMM totalExclusionEnergy = 0.0f;
for (int i = 0; i < numberOfAtoms; i++) for (int i = 0; i < numberOfAtoms; i++)
for (int j = 1; j <= exclusions[i][0]; j++) for (int j = 1; j <= exclusions[i][0]; j++)
if (exclusions[i][j] > i) { if (exclusions[i][j] > i) {
...@@ -486,17 +497,17 @@ int ReferenceLJCoulombIxn::calculateEwaldIxn( int numberOfAtoms, RealOpenMM** at ...@@ -486,17 +497,17 @@ int ReferenceLJCoulombIxn::calculateEwaldIxn( int numberOfAtoms, RealOpenMM** at
realSpaceEwaldEnergy = (RealOpenMM) (atomParameters[ii][QIndex]*atomParameters[jj][QIndex]*inverseR*erf(alphaR)); realSpaceEwaldEnergy = (RealOpenMM) (atomParameters[ii][QIndex]*atomParameters[jj][QIndex]*inverseR*erf(alphaR));
if( totalEnergy ) totalExclusionEnergy += realSpaceEwaldEnergy;
*totalEnergy -= realSpaceEwaldEnergy; if( energyByAtom ){
if( energyByAtom ){
energyByAtom[ii] -= realSpaceEwaldEnergy; energyByAtom[ii] -= realSpaceEwaldEnergy;
energyByAtom[jj] -= realSpaceEwaldEnergy; energyByAtom[jj] -= realSpaceEwaldEnergy;
} }
} }
// *********************************************************************** if( totalEnergy )
*totalEnergy -= totalExclusionEnergy;
// ***********************************************************************
return ReferenceForce::DefaultReturn; return ReferenceForce::DefaultReturn;
} }
......
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