Commit 0e5d3fb1 authored by Peter Eastman's avatar Peter Eastman
Browse files

Using fast approximation for erfc instead of tabulated values

parent d9029f61
...@@ -41,7 +41,6 @@ ...@@ -41,7 +41,6 @@
#include "lepton/Parser.h" #include "lepton/Parser.h"
#include "lepton/ParsedExpression.h" #include "lepton/ParsedExpression.h"
#include "../src/SimTKUtilities/SimTKOpenMMRealType.h" #include "../src/SimTKUtilities/SimTKOpenMMRealType.h"
#include "openmm/internal/MSVC_erfc.h"
#include <cmath> #include <cmath>
#include <set> #include <set>
...@@ -1154,8 +1153,6 @@ OpenCLCalcNonbondedForceKernel::~OpenCLCalcNonbondedForceKernel() { ...@@ -1154,8 +1153,6 @@ OpenCLCalcNonbondedForceKernel::~OpenCLCalcNonbondedForceKernel() {
delete pmeAtomRange; delete pmeAtomRange;
if (pmeAtomGridIndex != NULL) if (pmeAtomGridIndex != NULL)
delete pmeAtomGridIndex; delete pmeAtomGridIndex;
if (erfcTable != NULL)
delete erfcTable;
if (sort != NULL) if (sort != NULL)
delete sort; delete sort;
if (fft != NULL) if (fft != NULL)
...@@ -1341,19 +1338,6 @@ void OpenCLCalcNonbondedForceKernel::initialize(const System& system, const Nonb ...@@ -1341,19 +1338,6 @@ void OpenCLCalcNonbondedForceKernel::initialize(const System& system, const Nonb
} }
else else
ewaldSelfEnergy = 0.0; ewaldSelfEnergy = 0.0;
// Tabulate values of erfc().
if (force.getNonbondedMethod() == NonbondedForce::Ewald || force.getNonbondedMethod() == NonbondedForce::PME) {
const int tableSize = 2048;
defines["ERFC_TABLE_SCALE"] = doubleToString((tableSize-1)/(alpha*force.getCutoffDistance()));
erfcTable = new OpenCLArray<cl_float>(cl, tableSize, "ErfcTable", false, CL_MEM_READ_ONLY);
vector<cl_float> erfcVector(tableSize);
for (int i = 0; i < tableSize; ++i)
erfcVector[i] = (float) erfc(i*(alpha*force.getCutoffDistance())/(tableSize-1));
erfcTable->upload(erfcVector);
cl.getNonbondedUtilities().addArgument(OpenCLNonbondedUtilities::ParameterInfo("erfcTable", "float", 1, sizeof(cl_float), erfcTable->getDeviceBuffer()));
}
// Add the interaction to the default nonbonded kernel. // Add the interaction to the default nonbonded kernel.
......
...@@ -477,7 +477,7 @@ public: ...@@ -477,7 +477,7 @@ public:
OpenCLCalcNonbondedForceKernel(std::string name, const Platform& platform, OpenCLContext& cl, System& system) : CalcNonbondedForceKernel(name, platform), OpenCLCalcNonbondedForceKernel(std::string name, const Platform& platform, OpenCLContext& cl, System& system) : CalcNonbondedForceKernel(name, platform),
hasInitializedKernel(false), cl(cl), sigmaEpsilon(NULL), exceptionParams(NULL), exceptionIndices(NULL), cosSinSums(NULL), pmeGrid(NULL), hasInitializedKernel(false), cl(cl), sigmaEpsilon(NULL), exceptionParams(NULL), exceptionIndices(NULL), cosSinSums(NULL), pmeGrid(NULL),
pmeBsplineModuliX(NULL), pmeBsplineModuliY(NULL), pmeBsplineModuliZ(NULL), pmeBsplineTheta(NULL), pmeBsplineDtheta(NULL), pmeAtomRange(NULL), pmeBsplineModuliX(NULL), pmeBsplineModuliY(NULL), pmeBsplineModuliZ(NULL), pmeBsplineTheta(NULL), pmeBsplineDtheta(NULL), pmeAtomRange(NULL),
pmeAtomGridIndex(NULL), erfcTable(NULL), sort(NULL), fft(NULL) { pmeAtomGridIndex(NULL), sort(NULL), fft(NULL) {
} }
~OpenCLCalcNonbondedForceKernel(); ~OpenCLCalcNonbondedForceKernel();
/** /**
...@@ -511,7 +511,6 @@ private: ...@@ -511,7 +511,6 @@ private:
OpenCLArray<mm_float4>* pmeBsplineDtheta; OpenCLArray<mm_float4>* pmeBsplineDtheta;
OpenCLArray<cl_int>* pmeAtomRange; OpenCLArray<cl_int>* pmeAtomRange;
OpenCLArray<mm_int2>* pmeAtomGridIndex; OpenCLArray<mm_int2>* pmeAtomGridIndex;
OpenCLArray<cl_float>* erfcTable;
OpenCLSort<mm_int2>* sort; OpenCLSort<mm_int2>* sort;
OpenCLFFT3D* fft; OpenCLFFT3D* fft;
cl::Kernel exceptionsKernel; cl::Kernel exceptionsKernel;
......
...@@ -4,15 +4,13 @@ if (!isExcluded || needCorrection) { ...@@ -4,15 +4,13 @@ if (!isExcluded || needCorrection) {
const float prefactor = 138.935456f*posq1.w*posq2.w*invR; const float prefactor = 138.935456f*posq1.w*posq2.w*invR;
float alphaR = EWALD_ALPHA*r; float alphaR = EWALD_ALPHA*r;
float erfcAlphaR = 0.0f; float erfcAlphaR = 0.0f;
if (r2 < CUTOFF_SQUARED) { if (r2 < CUTOFF_SQUARED || needCorrection) {
float normalized = ERFC_TABLE_SCALE*alphaR; // This approximation for erfc is from Abramowitz and Stegun (1964) p. 299. They cite the following as
int tableIndex = (int) normalized; // the original source: C. Hastings, Jr., Approximations for Digital Computers (1955).
float fract2 = normalized-tableIndex;
float fract1 = 1.0f-fract2; float t = 1.0f/(1.0f+0.47047f*alphaR);
erfcAlphaR = fract1*erfcTable[tableIndex] + fract2*erfcTable[tableIndex+1]; erfcAlphaR = (t*(0.3480242f+t*(-0.0958798f+t*0.7478556f)))*exp(-alphaR*alphaR);
} }
else if (needCorrection)
erfcAlphaR = erfc(alphaR);
float tempForce = 0.0f; float tempForce = 0.0f;
if (needCorrection) { if (needCorrection) {
// Subtract off the part of this interaction that was included in the reciprocal space contribution. // Subtract off the part of this interaction that was included in the reciprocal space contribution.
......
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