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:
private:
int numParticles, num14;
int **bonded14IndexArray;
double **particleParamArray, **bonded14ParamArray;
float **particleParamArray;
double **bonded14ParamArray;
double nonbondedCutoff, switchingDistance, rfDielectric, ewaldAlpha, dispersionCoefficient;
int kmax[3], gridSize[3];
bool useSwitchingFunction;
std::vector<std::set<int> > exclusions;
std::vector<float> posq;
std::vector<float> forces;
NonbondedMethod nonbondedMethod;
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 @@
* -------------------------------------------------------------------------- */
#include "CpuKernels.h"
#include "CpuNonbondedForce.h"
#include "ReferenceBondForce.h"
#include "ReferenceLJCoulomb14.h"
#include "openmm/Context.h"
#include "openmm/OpenMMException.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/NonbondedForceImpl.h"
#include "RealVec.h"
......@@ -59,6 +63,9 @@ static RealVec& extractBoxSize(ContextImpl& context) {
}
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) {
......@@ -66,6 +73,8 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond
// Identify which exceptions are 1-4 interactions.
numParticles = force.getNumParticles();
posq.resize(4*numParticles, 0);
forces.resize(4*numParticles, 0);
exclusions.resize(numParticles);
vector<int> nb14s;
for (int i = 0; i < force.getNumExceptions(); i++) {
......@@ -81,29 +90,33 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond
// Record the particle parameters.
num14 = nb14s.size();
// bonded14IndexArray = allocateIntArray(num14, 2);
// bonded14ParamArray = allocateRealArray(num14, 3);
// particleParamArray = allocateRealArray(numParticles, 3);
posq.resize(4*numParticles, 0);
bonded14IndexArray = new int*[num14];
for (int i = 0; i < num14; i++)
bonded14IndexArray[i] = new int[2];
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) {
double charge, radius, depth;
force.getParticleParameters(i, charge, radius, depth);
posq[4*i+3] = (float) charge;
// particleParamArray[i][0] = static_cast<RealOpenMM>(0.5*radius);
// particleParamArray[i][1] = static_cast<RealOpenMM>(2.0*sqrt(depth));
// particleParamArray[i][2] = static_cast<RealOpenMM>(charge);
particleParamArray[i][0] = (float) (0.5*radius);
particleParamArray[i][1] = (float) (2.0*sqrt(depth));
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());
nonbondedCutoff = force.getCutoffDistance();
if (nonbondedMethod == NoCutoff)
......@@ -135,7 +148,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
RealVec boxSize = extractBoxSize(context);
float floatBoxSize[3] = {(float) boxSize[0], (float) boxSize[1], (float) boxSize[2]};
double energy = 0;
// CpuLJCoulombIxn clj;
CpuNonbondedForce clj;
bool periodic = (nonbondedMethod == CutoffPeriodic);
bool ewald = (nonbondedMethod == Ewald);
bool pme = (nonbondedMethod == PME);
......@@ -155,75 +168,79 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
posq[4*i+1] = (float) posData[i][1];
posq[4*i+2] = (float) posData[i][2];
}
neighborList.computeNeighborList(numParticles, posq, exclusions, floatBoxSize, periodic || ewald || pme, nonbondedCutoff);
// if (nonbondedMethod != NoCutoff) {
// computeNeighborListVoxelHash(*neighborList, numParticles, posData, exclusions, extractBoxSize(context), periodic || ewald || pme, nonbondedCutoff, 0.0);
// clj.setUseCutoff(nonbondedCutoff, *neighborList, rfDielectric);
// }
// if (periodic || ewald || pme) {
// RealVec& box = extractBoxSize(context);
// double minAllowedSize = 1.999999*nonbondedCutoff;
// 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.");
// clj.setPeriodic(box);
// }
// if (ewald)
// clj.setUseEwald(ewaldAlpha, kmax[0], kmax[1], kmax[2]);
// if (pme)
// clj.setUsePME(ewaldAlpha, gridSize);
// if (useSwitchingFunction)
// clj.setUseSwitchingFunction(switchingDistance);
// clj.calculatePairIxn(numParticles, posData, particleParamArray, exclusions, 0, forceData, 0, includeEnergy ? &energy : NULL, includeDirect, includeReciprocal);
// if (includeDirect) {
// CpuBondForce refBondForce;
// CpuLJCoulomb14 nonbonded14;
// refBondForce.calculateForce(num14, bonded14IndexArray, posData, bonded14ParamArray, forceData, includeEnergy ? &energy : NULL, nonbonded14);
// if (periodic || ewald || pme) {
// RealVec& boxSize = extractBoxSize(context);
// energy += dispersionCoefficient/(boxSize[0]*boxSize[1]*boxSize[2]);
// }
// }
// return energy;
return 0.0;
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);
clj.setUseCutoff(nonbondedCutoff, neighborList.getNeighbors(), rfDielectric);
}
if (periodic || ewald || pme) {
double minAllowedSize = 1.999999*nonbondedCutoff;
if (boxSize[0] < minAllowedSize || boxSize[1] < minAllowedSize || boxSize[2] < minAllowedSize)
throw OpenMMException("The periodic box size has decreased to less than twice the nonbonded cutoff.");
clj.setPeriodic(floatBoxSize);
}
if (ewald)
clj.setUseEwald(ewaldAlpha, kmax[0], kmax[1], kmax[2]);
if (pme)
clj.setUsePME(ewaldAlpha, gridSize);
if (useSwitchingFunction)
clj.setUseSwitchingFunction(switchingDistance);
float directEnergy = 0;
clj.calculatePairIxn(numParticles, &posq[0], particleParamArray, exclusions, 0, &forces[0], includeEnergy ? &directEnergy : NULL, includeDirect, includeReciprocal);
energy += directEnergy;
for (int i = 0; i < numParticles; i++) {
forceData[i][0] += forces[4*i];
forceData[i][1] += forces[4*i+1];
forceData[i][2] += forces[4*i+2];
}
if (includeDirect) {
ReferenceBondForce refBondForce;
ReferenceLJCoulomb14 nonbonded14;
refBondForce.calculateForce(num14, bonded14IndexArray, posData, bonded14ParamArray, forceData, includeEnergy ? &energy : NULL, nonbonded14);
if (periodic || ewald || pme)
energy += dispersionCoefficient/(boxSize[0]*boxSize[1]*boxSize[2]);
}
return energy;
}
void CpuCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const NonbondedForce& force) {
// if (force.getNumParticles() != numParticles)
// throw OpenMMException("updateParametersInContext: The number of particles has changed");
// vector<int> nb14s;
// for (int i = 0; i < force.getNumExceptions(); i++) {
// int particle1, particle2;
// double chargeProd, sigma, epsilon;
// force.getExceptionParameters(i, particle1, particle2, chargeProd, sigma, epsilon);
// if (chargeProd != 0.0 || epsilon != 0.0)
// nb14s.push_back(i);
// }
// if (nb14s.size() != num14)
// throw OpenMMException("updateParametersInContext: The number of non-excluded exceptions has changed");
//
// // Record the values.
//
// for (int i = 0; i < numParticles; ++i) {
// double charge, radius, depth;
// force.getParticleParameters(i, charge, radius, depth);
// particleParamArray[i][0] = static_cast<RealOpenMM>(0.5*radius);
// particleParamArray[i][1] = static_cast<RealOpenMM>(2.0*sqrt(depth));
// particleParamArray[i][2] = static_cast<RealOpenMM>(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);
// }
//
// // Recompute the coefficient for the dispersion correction.
//
// NonbondedForce::NonbondedMethod method = force.getNonbondedMethod();
// if (force.getUseDispersionCorrection() && (method == NonbondedForce::CutoffPeriodic || method == NonbondedForce::Ewald || method == NonbondedForce::PME))
// dispersionCoefficient = NonbondedForceImpl::calcDispersionCorrection(context.getSystem(), force);
if (force.getNumParticles() != numParticles)
throw OpenMMException("updateParametersInContext: The number of particles has changed");
vector<int> nb14s;
for (int i = 0; i < force.getNumExceptions(); i++) {
int particle1, particle2;
double chargeProd, sigma, epsilon;
force.getExceptionParameters(i, particle1, particle2, chargeProd, sigma, epsilon);
if (chargeProd != 0.0 || epsilon != 0.0)
nb14s.push_back(i);
}
if (nb14s.size() != num14)
throw OpenMMException("updateParametersInContext: The number of non-excluded exceptions has changed");
// Record the values.
for (int i = 0; i < numParticles; ++i) {
double charge, radius, depth;
force.getParticleParameters(i, charge, radius, depth);
particleParamArray[i][0] = (float) (0.5*radius);
particleParamArray[i][1] = (float) (2.0*sqrt(depth));
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);
}
// Recompute the coefficient for the dispersion correction.
NonbondedForce::NonbondedMethod method = force.getNonbondedMethod();
if (force.getUseDispersionCorrection() && (method == NonbondedForce::CutoffPeriodic || method == NonbondedForce::Ewald || method == NonbondedForce::PME))
dispersionCoefficient = NonbondedForceImpl::calcDispersionCorrection(context.getSystem(), force);
}
This diff is collapsed.
......@@ -25,6 +25,7 @@
#ifndef __ReferencePairIxn_H__
#define __ReferencePairIxn_H__
#include "RealVec.h"
#include "openmm/internal/windowsExport.h"
// ---------------------------------------------------------------------------------------
......
......@@ -31,7 +31,7 @@
#include "SimTKOpenMMUtilities.h"
#include "ReferenceLJCoulombIxn.h"
#include "ReferenceForce.h"
#include "PME.h"
#include "ReferencePME.h"
// In case we're using some primitive version of Visual Studio this will
// make sure that erf() and erfc() are defined.
......
......@@ -33,7 +33,7 @@
#include <stdio.h>
#include <stdlib.h>
#include "PME.h"
#include "ReferencePME.h"
#include "fftpack.h"
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