Commit 9bc194b9 authored by peastman's avatar peastman
Browse files

Began creating optimized implementation of direct space nonbonded calculation

parent 50d4f9d0
...@@ -75,12 +75,14 @@ public: ...@@ -75,12 +75,14 @@ public:
private: private:
int numParticles, num14; int numParticles, num14;
int **bonded14IndexArray; int **bonded14IndexArray;
double **particleParamArray, **bonded14ParamArray; float **particleParamArray;
double **bonded14ParamArray;
double nonbondedCutoff, switchingDistance, rfDielectric, ewaldAlpha, dispersionCoefficient; double nonbondedCutoff, switchingDistance, rfDielectric, ewaldAlpha, dispersionCoefficient;
int kmax[3], gridSize[3]; int kmax[3], gridSize[3];
bool useSwitchingFunction; bool useSwitchingFunction;
std::vector<std::set<int> > exclusions; std::vector<std::set<int> > exclusions;
std::vector<float> posq; std::vector<float> posq;
std::vector<float> forces;
NonbondedMethod nonbondedMethod; NonbondedMethod nonbondedMethod;
CpuNeighborList neighborList; CpuNeighborList neighborList;
}; };
......
/* Portions copyright (c) 2006-2013 Stanford University and Simbios.
* Contributors: Pande Group
*
* 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.
*/
#ifndef OPENMM_CPU_NONBONDED_FORCE_H__
#define OPENMM_CPU_NONBONDED_FORCE_H__
#include "ReferencePairIxn.h"
#include <set>
#include <utility>
#include <vector>
// ---------------------------------------------------------------------------------------
class CpuNonbondedForce {
private:
bool cutoff;
bool useSwitch;
bool periodic;
bool ewald;
bool pme;
const std::vector<std::pair<int, int> >* neighborList;
float periodicBoxSize[3];
float cutoffDistance, switchingDistance;
float krf, crf;
float alphaEwald;
int numRx, numRy, numRz;
int meshDim[3];
// parameter indices
static const int SigIndex = 0;
static const int EpsIndex = 1;
static const int QIndex = 2;
/**---------------------------------------------------------------------------------------
Calculate LJ Coulomb pair ixn between two atoms
@param atom1 the index of the first atom
@param atom2 the index of the second atom
@param atomCoordinates atom coordinates
@param atomParameters atom parameters (charges, c6, c12, ...) atomParameters[atomIndex][paramterIndex]
@param forces force array (forces added)
@param totalEnergy total energy
--------------------------------------------------------------------------------------- */
void calculateOneIxn( int atom1, int atom2, float* atomCoordinates,
float** atomParameters, float* forces,
float* totalEnergy ) const;
public:
/**---------------------------------------------------------------------------------------
Constructor
--------------------------------------------------------------------------------------- */
CpuNonbondedForce( );
/**---------------------------------------------------------------------------------------
Destructor
--------------------------------------------------------------------------------------- */
~CpuNonbondedForce( );
/**---------------------------------------------------------------------------------------
Set the force to use a cutoff.
@param distance the cutoff distance
@param neighbors the neighbor list to use
@param solventDielectric the dielectric constant of the bulk solvent
--------------------------------------------------------------------------------------- */
void setUseCutoff( float distance, const std::vector<std::pair<int, int> >& neighbors, float solventDielectric );
/**---------------------------------------------------------------------------------------
Set the force to use a switching function on the Lennard-Jones interaction.
@param distance the switching distance
--------------------------------------------------------------------------------------- */
void setUseSwitchingFunction( float distance );
/**---------------------------------------------------------------------------------------
Set the force to use periodic boundary conditions. This requires that a cutoff has
already been set, and the smallest side of the periodic box is at least twice the cutoff
distance.
@param boxSize the X, Y, and Z widths of the periodic box
--------------------------------------------------------------------------------------- */
void setPeriodic( float* boxSize );
/**---------------------------------------------------------------------------------------
Set the force to use Ewald summation.
@param alpha the Ewald separation parameter
@param kmaxx the largest wave vector in the x direction
@param kmaxy the largest wave vector in the y direction
@param kmaxz the largest wave vector in the z direction
--------------------------------------------------------------------------------------- */
void setUseEwald(float alpha, int kmaxx, int kmaxy, int kmaxz);
/**---------------------------------------------------------------------------------------
Set the force to use Particle-Mesh Ewald (PME) summation.
@param alpha the Ewald separation parameter
@param gridSize the dimensions of the mesh
--------------------------------------------------------------------------------------- */
void setUsePME(float alpha, int meshSize[3]);
/**---------------------------------------------------------------------------------------
Calculate LJ Coulomb pair ixn
@param numberOfAtoms number of atoms
@param atomCoordinates atom coordinates
@param atomParameters atom parameters (charges, c6, c12, ...) atomParameters[atomIndex][paramterIndex]
@param exclusions atom exclusion indices
exclusions[atomIndex] contains the list of exclusions for that atom
@param fixedParameters non atom parameters (not currently used)
@param forces force array (forces added)
@param totalEnergy total energy
@param includeDirect true if direct space interactions should be included
@param includeReciprocal true if reciprocal space interactions should be included
--------------------------------------------------------------------------------------- */
void calculatePairIxn(int numberOfAtoms, float* atomCoordinates,
float** atomParameters, std::vector<std::set<int> >& exclusions,
float* fixedParameters, float* forces,
float* totalEnergy, bool includeDirect, bool includeReciprocal) const;
private:
/**---------------------------------------------------------------------------------------
Calculate Ewald ixn
@param numberOfAtoms number of atoms
@param atomCoordinates atom coordinates
@param atomParameters atom parameters (charges, c6, c12, ...) atomParameters[atomIndex][paramterIndex]
@param exclusions atom exclusion indices
exclusions[atomIndex] contains the list of exclusions for that atom
@param fixedParameters non atom parameters (not currently used)
@param forces force array (forces added)
@param totalEnergy total energy
@param includeDirect true if direct space interactions should be included
@param includeReciprocal true if reciprocal space interactions should be included
--------------------------------------------------------------------------------------- */
void calculateEwaldIxn(int numberOfAtoms, float* atomCoordinates,
float** atomParameters, std::vector<std::set<int> >& exclusions,
float* fixedParameters, float* forces,
float* totalEnergy, bool includeDirect, bool includeReciprocal) const;
void getDeltaR(const float* atomCoordinatesI, const float* atomCoordinatesJ,
const float* boxSize, float* deltaR, bool periodic) const;
};
// ---------------------------------------------------------------------------------------
#endif // OPENMM_CPU_NONBONDED_FORCE_H__
...@@ -30,7 +30,11 @@ ...@@ -30,7 +30,11 @@
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
#include "CpuKernels.h" #include "CpuKernels.h"
#include "CpuNonbondedForce.h"
#include "ReferenceBondForce.h"
#include "ReferenceLJCoulomb14.h"
#include "openmm/Context.h" #include "openmm/Context.h"
#include "openmm/OpenMMException.h"
#include "openmm/internal/ContextImpl.h" #include "openmm/internal/ContextImpl.h"
#include "openmm/internal/NonbondedForceImpl.h" #include "openmm/internal/NonbondedForceImpl.h"
#include "RealVec.h" #include "RealVec.h"
...@@ -59,6 +63,9 @@ static RealVec& extractBoxSize(ContextImpl& context) { ...@@ -59,6 +63,9 @@ static RealVec& extractBoxSize(ContextImpl& context) {
} }
CpuCalcNonbondedForceKernel::~CpuCalcNonbondedForceKernel() { CpuCalcNonbondedForceKernel::~CpuCalcNonbondedForceKernel() {
delete bonded14IndexArray; // Do this properly
delete bonded14ParamArray; // Do this properly
delete particleParamArray; // Do this properly
} }
void CpuCalcNonbondedForceKernel::initialize(const System& system, const NonbondedForce& force) { void CpuCalcNonbondedForceKernel::initialize(const System& system, const NonbondedForce& force) {
...@@ -66,6 +73,8 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond ...@@ -66,6 +73,8 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond
// Identify which exceptions are 1-4 interactions. // Identify which exceptions are 1-4 interactions.
numParticles = force.getNumParticles(); numParticles = force.getNumParticles();
posq.resize(4*numParticles, 0);
forces.resize(4*numParticles, 0);
exclusions.resize(numParticles); exclusions.resize(numParticles);
vector<int> nb14s; vector<int> nb14s;
for (int i = 0; i < force.getNumExceptions(); i++) { for (int i = 0; i < force.getNumExceptions(); i++) {
...@@ -81,29 +90,33 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond ...@@ -81,29 +90,33 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond
// Record the particle parameters. // Record the particle parameters.
num14 = nb14s.size(); num14 = nb14s.size();
// bonded14IndexArray = allocateIntArray(num14, 2); bonded14IndexArray = new int*[num14];
// bonded14ParamArray = allocateRealArray(num14, 3); for (int i = 0; i < num14; i++)
// particleParamArray = allocateRealArray(numParticles, 3); bonded14IndexArray[i] = new int[2];
posq.resize(4*numParticles, 0); bonded14ParamArray = new double*[num14];
for (int i = 0; i < num14; i++)
bonded14ParamArray[i] = new double[3];
particleParamArray = new float*[numParticles];
for (int i = 0; i < numParticles; i++)
particleParamArray[i] = new float[3];
for (int i = 0; i < numParticles; ++i) { for (int i = 0; i < numParticles; ++i) {
double charge, radius, depth; double charge, radius, depth;
force.getParticleParameters(i, charge, radius, depth); force.getParticleParameters(i, charge, radius, depth);
posq[4*i+3] = (float) charge; posq[4*i+3] = (float) charge;
// particleParamArray[i][0] = static_cast<RealOpenMM>(0.5*radius); particleParamArray[i][0] = (float) (0.5*radius);
// particleParamArray[i][1] = static_cast<RealOpenMM>(2.0*sqrt(depth)); particleParamArray[i][1] = (float) (2.0*sqrt(depth));
// particleParamArray[i][2] = static_cast<RealOpenMM>(charge); particleParamArray[i][2] = (float) (charge);
}
for (int i = 0; i < num14; ++i) {
int particle1, particle2;
double charge, radius, depth;
force.getExceptionParameters(nb14s[i], particle1, particle2, charge, radius, depth);
bonded14IndexArray[i][0] = particle1;
bonded14IndexArray[i][1] = particle2;
bonded14ParamArray[i][0] = static_cast<RealOpenMM>(radius);
bonded14ParamArray[i][1] = static_cast<RealOpenMM>(4.0*depth);
bonded14ParamArray[i][2] = static_cast<RealOpenMM>(charge);
} }
// this->exclusions = exclusions;
// for (int i = 0; i < num14; ++i) {
// int particle1, particle2;
// double charge, radius, depth;
// force.getExceptionParameters(nb14s[i], particle1, particle2, charge, radius, depth);
// bonded14IndexArray[i][0] = particle1;
// bonded14IndexArray[i][1] = particle2;
// bonded14ParamArray[i][0] = static_cast<RealOpenMM>(radius);
// bonded14ParamArray[i][1] = static_cast<RealOpenMM>(4.0*depth);
// bonded14ParamArray[i][2] = static_cast<RealOpenMM>(charge);
// }
nonbondedMethod = CalcNonbondedForceKernel::NonbondedMethod(force.getNonbondedMethod()); nonbondedMethod = CalcNonbondedForceKernel::NonbondedMethod(force.getNonbondedMethod());
nonbondedCutoff = force.getCutoffDistance(); nonbondedCutoff = force.getCutoffDistance();
if (nonbondedMethod == NoCutoff) if (nonbondedMethod == NoCutoff)
...@@ -135,7 +148,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo ...@@ -135,7 +148,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
RealVec boxSize = extractBoxSize(context); RealVec boxSize = extractBoxSize(context);
float floatBoxSize[3] = {(float) boxSize[0], (float) boxSize[1], (float) boxSize[2]}; float floatBoxSize[3] = {(float) boxSize[0], (float) boxSize[1], (float) boxSize[2]};
double energy = 0; double energy = 0;
// CpuLJCoulombIxn clj; CpuNonbondedForce clj;
bool periodic = (nonbondedMethod == CutoffPeriodic); bool periodic = (nonbondedMethod == CutoffPeriodic);
bool ewald = (nonbondedMethod == Ewald); bool ewald = (nonbondedMethod == Ewald);
bool pme = (nonbondedMethod == PME); bool pme = (nonbondedMethod == PME);
...@@ -155,75 +168,79 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo ...@@ -155,75 +168,79 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
posq[4*i+1] = (float) posData[i][1]; posq[4*i+1] = (float) posData[i][1];
posq[4*i+2] = (float) posData[i][2]; posq[4*i+2] = (float) posData[i][2];
} }
for (int i = 0; i < 4*numParticles; i++)
forces[i] = 0.0f;
if (nonbondedMethod != NoCutoff) {
neighborList.computeNeighborList(numParticles, posq, exclusions, floatBoxSize, periodic || ewald || pme, nonbondedCutoff); neighborList.computeNeighborList(numParticles, posq, exclusions, floatBoxSize, periodic || ewald || pme, nonbondedCutoff);
// if (nonbondedMethod != NoCutoff) { clj.setUseCutoff(nonbondedCutoff, neighborList.getNeighbors(), rfDielectric);
// computeNeighborListVoxelHash(*neighborList, numParticles, posData, exclusions, extractBoxSize(context), periodic || ewald || pme, nonbondedCutoff, 0.0); }
// clj.setUseCutoff(nonbondedCutoff, *neighborList, rfDielectric); if (periodic || ewald || pme) {
// } double minAllowedSize = 1.999999*nonbondedCutoff;
// if (periodic || ewald || pme) { if (boxSize[0] < minAllowedSize || boxSize[1] < minAllowedSize || boxSize[2] < minAllowedSize)
// RealVec& box = extractBoxSize(context); throw OpenMMException("The periodic box size has decreased to less than twice the nonbonded cutoff.");
// double minAllowedSize = 1.999999*nonbondedCutoff; clj.setPeriodic(floatBoxSize);
// if (box[0] < minAllowedSize || box[1] < minAllowedSize || box[2] < minAllowedSize) }
// throw OpenMMException("The periodic box size has decreased to less than twice the nonbonded cutoff."); if (ewald)
// clj.setPeriodic(box); clj.setUseEwald(ewaldAlpha, kmax[0], kmax[1], kmax[2]);
// } if (pme)
// if (ewald) clj.setUsePME(ewaldAlpha, gridSize);
// clj.setUseEwald(ewaldAlpha, kmax[0], kmax[1], kmax[2]); if (useSwitchingFunction)
// if (pme) clj.setUseSwitchingFunction(switchingDistance);
// clj.setUsePME(ewaldAlpha, gridSize); float directEnergy = 0;
// if (useSwitchingFunction) clj.calculatePairIxn(numParticles, &posq[0], particleParamArray, exclusions, 0, &forces[0], includeEnergy ? &directEnergy : NULL, includeDirect, includeReciprocal);
// clj.setUseSwitchingFunction(switchingDistance); energy += directEnergy;
// clj.calculatePairIxn(numParticles, posData, particleParamArray, exclusions, 0, forceData, 0, includeEnergy ? &energy : NULL, includeDirect, includeReciprocal); for (int i = 0; i < numParticles; i++) {
// if (includeDirect) { forceData[i][0] += forces[4*i];
// CpuBondForce refBondForce; forceData[i][1] += forces[4*i+1];
// CpuLJCoulomb14 nonbonded14; forceData[i][2] += forces[4*i+2];
// refBondForce.calculateForce(num14, bonded14IndexArray, posData, bonded14ParamArray, forceData, includeEnergy ? &energy : NULL, nonbonded14); }
// if (periodic || ewald || pme) { if (includeDirect) {
// RealVec& boxSize = extractBoxSize(context); ReferenceBondForce refBondForce;
// energy += dispersionCoefficient/(boxSize[0]*boxSize[1]*boxSize[2]); ReferenceLJCoulomb14 nonbonded14;
// } refBondForce.calculateForce(num14, bonded14IndexArray, posData, bonded14ParamArray, forceData, includeEnergy ? &energy : NULL, nonbonded14);
// } if (periodic || ewald || pme)
// return energy; energy += dispersionCoefficient/(boxSize[0]*boxSize[1]*boxSize[2]);
return 0.0; }
return energy;
} }
void CpuCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const NonbondedForce& force) { void CpuCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const NonbondedForce& force) {
// if (force.getNumParticles() != numParticles) if (force.getNumParticles() != numParticles)
// throw OpenMMException("updateParametersInContext: The number of particles has changed"); throw OpenMMException("updateParametersInContext: The number of particles has changed");
// vector<int> nb14s; vector<int> nb14s;
// for (int i = 0; i < force.getNumExceptions(); i++) { for (int i = 0; i < force.getNumExceptions(); i++) {
// int particle1, particle2; int particle1, particle2;
// double chargeProd, sigma, epsilon; double chargeProd, sigma, epsilon;
// force.getExceptionParameters(i, particle1, particle2, chargeProd, sigma, epsilon); force.getExceptionParameters(i, particle1, particle2, chargeProd, sigma, epsilon);
// if (chargeProd != 0.0 || epsilon != 0.0) if (chargeProd != 0.0 || epsilon != 0.0)
// nb14s.push_back(i); nb14s.push_back(i);
// } }
// if (nb14s.size() != num14) if (nb14s.size() != num14)
// throw OpenMMException("updateParametersInContext: The number of non-excluded exceptions has changed"); throw OpenMMException("updateParametersInContext: The number of non-excluded exceptions has changed");
//
// // Record the values. // Record the values.
//
// for (int i = 0; i < numParticles; ++i) { for (int i = 0; i < numParticles; ++i) {
// double charge, radius, depth; double charge, radius, depth;
// force.getParticleParameters(i, charge, radius, depth); force.getParticleParameters(i, charge, radius, depth);
// particleParamArray[i][0] = static_cast<RealOpenMM>(0.5*radius); particleParamArray[i][0] = (float) (0.5*radius);
// particleParamArray[i][1] = static_cast<RealOpenMM>(2.0*sqrt(depth)); particleParamArray[i][1] = (float) (2.0*sqrt(depth));
// particleParamArray[i][2] = static_cast<RealOpenMM>(charge); particleParamArray[i][2] = (float) (charge);
// } }
// for (int i = 0; i < num14; ++i) { for (int i = 0; i < num14; ++i) {
// int particle1, particle2; int particle1, particle2;
// double charge, radius, depth; double charge, radius, depth;
// force.getExceptionParameters(nb14s[i], particle1, particle2, charge, radius, depth); force.getExceptionParameters(nb14s[i], particle1, particle2, charge, radius, depth);
// bonded14IndexArray[i][0] = particle1; bonded14IndexArray[i][0] = particle1;
// bonded14IndexArray[i][1] = particle2; bonded14IndexArray[i][1] = particle2;
// bonded14ParamArray[i][0] = static_cast<RealOpenMM>(radius); bonded14ParamArray[i][0] = static_cast<RealOpenMM>(radius);
// bonded14ParamArray[i][1] = static_cast<RealOpenMM>(4.0*depth); bonded14ParamArray[i][1] = static_cast<RealOpenMM>(4.0*depth);
// bonded14ParamArray[i][2] = static_cast<RealOpenMM>(charge); bonded14ParamArray[i][2] = static_cast<RealOpenMM>(charge);
// } }
//
// // Recompute the coefficient for the dispersion correction. // Recompute the coefficient for the dispersion correction.
//
// NonbondedForce::NonbondedMethod method = force.getNonbondedMethod(); NonbondedForce::NonbondedMethod method = force.getNonbondedMethod();
// if (force.getUseDispersionCorrection() && (method == NonbondedForce::CutoffPeriodic || method == NonbondedForce::Ewald || method == NonbondedForce::PME)) if (force.getUseDispersionCorrection() && (method == NonbondedForce::CutoffPeriodic || method == NonbondedForce::Ewald || method == NonbondedForce::PME))
// dispersionCoefficient = NonbondedForceImpl::calcDispersionCorrection(context.getSystem(), force); dispersionCoefficient = NonbondedForceImpl::calcDispersionCorrection(context.getSystem(), force);
} }
This diff is collapsed.
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#ifndef __ReferencePairIxn_H__ #ifndef __ReferencePairIxn_H__
#define __ReferencePairIxn_H__ #define __ReferencePairIxn_H__
#include "RealVec.h"
#include "openmm/internal/windowsExport.h" #include "openmm/internal/windowsExport.h"
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include "SimTKOpenMMUtilities.h" #include "SimTKOpenMMUtilities.h"
#include "ReferenceLJCoulombIxn.h" #include "ReferenceLJCoulombIxn.h"
#include "ReferenceForce.h" #include "ReferenceForce.h"
#include "PME.h" #include "ReferencePME.h"
// In case we're using some primitive version of Visual Studio this will // In case we're using some primitive version of Visual Studio this will
// make sure that erf() and erfc() are defined. // make sure that erf() and erfc() are defined.
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "PME.h" #include "ReferencePME.h"
#include "fftpack.h" #include "fftpack.h"
using std::vector; using std::vector;
......
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