Unverified Commit 74912095 authored by Peter Eastman's avatar Peter Eastman Committed by GitHub
Browse files

Refactor reference PME (#5131)

parent c24c619e
......@@ -255,28 +255,26 @@ void CpuNonbondedForce::calculateReciprocalIxn(int numberOfAtoms, float* posq, c
float recipCoeff = (float)(ONE_4PI_EPS0*4*PI_M/(periodicBoxVectors[0][0] * periodicBoxVectors[1][1] * periodicBoxVectors[2][2]) /epsilon);
if (pme) {
pme_t pmedata;
pme_init(&pmedata, alphaEwald, numberOfAtoms, meshDim, 5, 1);
ReferencePME pme(alphaEwald, numberOfAtoms, meshDim, 5, 1);
vector<double> charges(numberOfAtoms);
for (int i = 0; i < numberOfAtoms; i++)
charges[i] = posq[4*i+3];
double recipEnergy = 0.0;
pme_exec(pmedata, atomCoordinates, forces, charges, periodicBoxVectors, &recipEnergy);
pme.exec(atomCoordinates, forces, charges, periodicBoxVectors, recipEnergy);
if (totalEnergy)
*totalEnergy += recipEnergy;
pme_destroy(pmedata);
if (ljpme) {
// Dispersion reciprocal space terms
pme_init(&pmedata,alphaDispersionEwald,numberOfAtoms,dispersionMeshDim,5,1);
ReferencePME ljpme(alphaDispersionEwald,numberOfAtoms,dispersionMeshDim,5,1);
std::vector<Vec3> dpmeforces;
vector<Vec3> dpmeforces;
for (int i = 0; i < numberOfAtoms; i++){
charges[i] = C6params[i];
dpmeforces.push_back(Vec3());
}
double recipDispersionEnergy = 0.0;
pme_exec_dpme(pmedata,atomCoordinates,dpmeforces,charges,periodicBoxVectors,&recipDispersionEnergy);
ljpme.exec_dpme(atomCoordinates, dpmeforces, charges, periodicBoxVectors, recipDispersionEnergy);
for (int i = 0; i < numberOfAtoms; i++){
forces[i][0] += dpmeforces[i][0];
forces[i][1] += dpmeforces[i][1];
......@@ -284,8 +282,6 @@ void CpuNonbondedForce::calculateReciprocalIxn(int numberOfAtoms, float* posq, c
}
if (totalEnergy)
*totalEnergy += recipDispersionEnergy;
pme_destroy(pmedata);
}
}
......
......@@ -90,14 +90,14 @@ public:
* @param elecToSys mapping from electrode particle indices to system particle indices
* @param electrodeParamArray electrode particle parameters
* @param conp constant potential derivative evaluation class
* @param pmeData reference PME solver
* @param pme reference PME solver
*/
virtual void solve(int numParticles, int numElectrodeParticles,
const std::vector<Vec3>& posData, std::vector<double>& charges,
const std::vector<std::set<int>>& exclusions,
const std::vector<int>& sysToElec, const std::vector<int>& elecToSys,
const std::vector<std::array<double, 3> >& electrodeParamArray,
ReferenceConstantPotential& conp, pme_t pmeData) = 0;
ReferenceConstantPotential& conp, ReferencePME& pme) = 0;
};
/**
......@@ -149,14 +149,14 @@ public:
* @param elecToSys mapping from electrode particle indices to system particle indices
* @param electrodeParamArray electrode particle parameters
* @param conp constant potential derivative evaluation class
* @param pmeData reference PME solver
* @param pme reference PME solver
*/
void solve(int numParticles, int numElectrodeParticles,
const std::vector<Vec3>& posData, std::vector<double>& charges,
const std::vector<std::set<int>>& exclusions,
const std::vector<int>& sysToElec, const std::vector<int>& elecToSys,
const std::vector<std::array<double, 3> >& electrodeParamArray,
ReferenceConstantPotential& conp, pme_t pmeData);
ReferenceConstantPotential& conp, ReferencePME& pme);
};
/**
......@@ -208,14 +208,14 @@ public:
* @param elecToSys mapping from electrode particle indices to system particle indices
* @param electrodeParamArray electrode particle parameters
* @param conp constant potential derivative evaluation class
* @param pmeData reference PME solver
* @param pme reference PME solver
*/
void solve(int numParticles, int numElectrodeParticles,
const std::vector<Vec3>& posData, std::vector<double>& charges,
const std::vector<std::set<int>>& exclusions,
const std::vector<int>& sysToElec, const std::vector<int>& elecToSys,
const std::vector<std::array<double, 3> >& electrodeParamArray,
ReferenceConstantPotential& conp, pme_t pmeData);
ReferenceConstantPotential& conp, ReferencePME& pme);
};
/**
......@@ -313,7 +313,7 @@ private:
* @param elecToSys mapping from electrode particle indices to system particle indices
* @param electrodeParamArray electrode particle parameters
* @param energy output system energy
* @param pmeData reference PME solver
* @param pme reference PME solver
*/
void getEnergyForces(int numParticles, int numElectrodeParticles,
const std::vector<Vec3>& posData, std::vector<Vec3>& forceData,
......@@ -321,7 +321,7 @@ private:
const std::vector<std::set<int>>& exclusions,
const std::vector<int>& sysToElec, const std::vector<int>& elecToSys,
const std::vector<std::array<double, 3> >& electrodeParamArray,
double* energy, pme_t pmeData);
double* energy, ReferencePME& pme);
/**
* Computes energy derivatives with respect to charges.
*
......@@ -334,14 +334,14 @@ private:
* @param elecToSys mapping from electrode particle indices to system particle indices
* @param electrodeParamArray electrode particle parameters
* @param chargeDerivatives output charge derivatives
* @param pmeData reference PME solver
* @param pme reference PME solver
*/
void getDerivatives(int numParticles, int numElectrodeParticles,
const std::vector<Vec3>& posData, std::vector<double>& charges,
const std::vector<std::set<int>>& exclusions,
const std::vector<int>& sysToElec, const std::vector<int>& elecToSys,
const std::vector<std::array<double, 3> >& electrodeParamArray,
std::vector<double>& chargeDerivatives, pme_t pmeData);
std::vector<double>& chargeDerivatives, ReferencePME& pme);
};
} // namespace OpenMM
......
/*
* Reference implementation of PME reciprocal space interactions.
*
* Copyright (c) 2009, Erik Lindahl, Rossen Apostolov, Szilard Pall
* Copyright (c) 2009-2025 Erik Lindahl, Rossen Apostolov, Szilard Pall, Peter Eastman
* All rights reserved.
* Contact: lindahl@cbr.su.se Stockholm University, Sweden.
*
......@@ -34,22 +34,19 @@
#include "openmm/Vec3.h"
#include "openmm/internal/windowsExport.h"
#include <array>
#include <complex>
#include <vector>
namespace OpenMM {
typedef double rvec[3];
typedef struct pme *
pme_t;
/*
class OPENMM_EXPORT ReferencePME {
public:
/*
* Initialize a PME calculation and set up data structures
*
* Arguments:
*
* ppme Pointer to an opaque pme_t object
* ewaldcoeff Coefficient derived from the beta factor to participate
* direct/reciprocal space. See gromacs code for documentation!
* We assume that you are using nm units...
......@@ -58,77 +55,96 @@ pme_t;
* pme_order Interpolation order, almost always 4
* epsilon_r Dielectric coefficient, typically 1.0.
*/
int OPENMM_EXPORT
pme_init(pme_t* ppme,
double ewaldcoeff,
int natoms,
const int ngrid[3],
int pme_order,
double epsilon_r);
ReferencePME(double ewaldcoeff, int natoms, const int ngrid[3], int pme_order, double epsilon_r);
/*
/*
* Evaluate reciprocal space PME energy and forces.
*
* Args:
*
* pme Opaque pme_t object, must have been initialized with pme_init()
* atomCoordinates Pointer to coordinate data array (nm)
* forces Pointer to force data array (will be written as kJ/mol/nm)
* charges Array of charges (units of e)
* periodicBoxVectors Simulation cell dimensions (nm)
* energy Total energy (will be written in units of kJ/mol)
*/
int OPENMM_EXPORT
pme_exec(pme_t pme,
const std::vector<OpenMM::Vec3>& atomCoordinates,
std::vector<OpenMM::Vec3>& forces,
const std::vector<double>& charges,
const OpenMM::Vec3 periodicBoxVectors[3],
double* energy);
void exec(const std::vector<OpenMM::Vec3>& atomCoordinates, std::vector<OpenMM::Vec3>& forces, const std::vector<double>& charges,
const OpenMM::Vec3 periodicBoxVectors[3], double& energy);
/*
/*
* Evaluate reciprocal space PME energy and charge derivatives.
*
* Args:
*
* pme Opaque pme_t object, must have been initialized with pme_init()
* atomCoordinates Pointer to coordinate data array (nm)
* chargeDerivatives Pointer to charge derivative data array (will be written as kJ/mol/e)
* chargeIndices Pointer to array of indices of particles to compute charge derivatives for
* charges Array of charges (units of e)
* periodicBoxVectors Simulation cell dimensions (nm)
*/
int OPENMM_EXPORT
pme_exec_charge_derivatives(pme_t pme,
const std::vector<OpenMM::Vec3>& atomCoordinates,
std::vector<double>& chargeDerivatives,
const std::vector<int>& chargeIndices,
const std::vector<double>& charges,
const OpenMM::Vec3 periodicBoxVectors[3]);
void exec_charge_derivatives(const std::vector<OpenMM::Vec3>& atomCoordinates, std::vector<double>& chargeDerivatives,
const std::vector<int>& chargeIndices, const std::vector<double>& charges, const OpenMM::Vec3 periodicBoxVectors[3]);
/**
/**
* Evaluate reciprocal space PME dispersion energy and forces.
*
* Args:
*
* pme Opaque pme_t object, must have been initialized with pme_init()
* atomCoordinates Pointer to coordinate data array (nm)
* forces Pointer to force data array (will be written as kJ/mol/nm)
* c6s Array of c6 coefficients (units of sqrt(kJ/mol).nm^3 )
* periodicBoxVectors Simulation cell dimensions (nm)
* energy Total energy (will be written in units of kJ/mol)
*/
int OPENMM_EXPORT
pme_exec_dpme(pme_t pme,
const std::vector<OpenMM::Vec3>& atomCoordinates,
std::vector<OpenMM::Vec3>& forces,
const std::vector<double>& c6s,
const OpenMM::Vec3 periodicBoxVectors[3],
double* energy);
void exec_dpme(const std::vector<OpenMM::Vec3>& atomCoordinates, std::vector<OpenMM::Vec3>& forces, const std::vector<double>& c6s,
const OpenMM::Vec3 periodicBoxVectors[3], double& energy);
private:
void calculate_bsplines_moduli();
void update_grid_index_and_fraction(const std::vector<Vec3>& atomCoordinates, const Vec3 recipBoxVectors[3]);
void update_bsplines();
void grid_spread_charge(const std::vector<double>& charges);
void pme_reciprocal_convolution(const Vec3 periodicBoxVectors[3], const Vec3 recipBoxVectors[3], double& energy);
void dpme_reciprocal_convolution(const Vec3 periodicBoxVectors[3], const Vec3 recipBoxVectors[3], double& energy);
void grid_interpolate_force(const Vec3 recipBoxVectors[3], const std::vector<double>& charges, std::vector<Vec3>& forces);
void grid_interpolate_charge_derivatives(const Vec3 recipBoxVectors[3], const std::vector<double>& charges,
std::vector<double>& chargeDerivatives, const std::vector<int>& chargeIndices);
int natoms;
double ewaldcoeff;
std::vector<std::complex<double> > grid; /* Memory for the grid we spread charges on.
* Element (i,j,k) is accessed as:
* grid[i*ngrid[1]*ngrid[2] + j*ngrid[2] + k] */
int ngrid[3]; /* Total grid dimensions (all data is complex!) */
int order; /* PME interpolation order. Almost always 4 */
/* Data for bspline interpolation, see the Essman PME paper */
std::vector<double> bsplines_moduli[3]; /* 3 pointers, to x/y/z bspline moduli, each of length ngrid[x/y/z] */
std::vector<double> bsplines_theta[3]; /* each of x/y/z has length order*natoms */
std::vector<double> bsplines_dtheta[3]; /* each of x/y/z has length order*natoms */
std::vector<std::array<int, 3> > particleindex; /* Array of length natoms. Each element is
* three ints that specify the grid
* indices for that particular atom. Updated every step! */
std::vector<Vec3> particlefraction; /* Array of length natoms. Fractional offset in the grid for
* each atom in all three dimensions. */
/* Further explanation of index/fraction:
*
* Assume we have a cell of size 10*10*10nm, and a total grid dimension of 100*100*100 cells.
* In other words, each cell is 0.1*0.1*0.1 nm.
*
* If particle i has coordinates { 0.543 , 6.235 , -0.73 }, we will get:
*
* particleindex[i] = { 5 , 62 , 92 } (-0.73 + 10 = 9.27, we always apply PBC for grid calculations!)
* particlefraction[i] = { 0.43 , 0.35 , 0.7 } (this is the fraction of the cell length where the atom is)
*
* (The reason for precaculating / storing these is that it gets a bit more complex for triclinic cells :-)
*
* In the current code version we might assume that a particle is not more than a whole box length away from
* the central cell, i.e., in this case we would assume all coordinates fall in -10 nm < x,y,z < 20 nm.
*/
/* Release all memory in pme structure */
int OPENMM_EXPORT
pme_destroy(pme_t pme);
double epsilon_r; /* Dielectric coefficient to use, typically 1.0 */
};
} // namespace OpenMM
......
......@@ -29,7 +29,6 @@
#include "ReferenceConstantPotential.h"
#include "ReferenceForce.h"
#include "ReferencePME.h"
#include "SimTKOpenMMUtilities.h"
#include "openmm/OpenMMException.h"
#include "openmm/internal/MSVC_erfc.h"
......@@ -97,22 +96,21 @@ void ReferenceConstantPotentialMatrixSolver::update(
std::vector<double> dUdQ0(numElectrodeParticles);
std::vector<double> dUdQ(numElectrodeParticles);
pme_t pmeData;
pme_init(&pmeData, conp.ewaldAlpha, numParticles, conp.gridSize, 5, 1);
ReferencePME pme(conp.ewaldAlpha, numParticles, conp.gridSize, 5, 1);
// Get derivatives when all electrode charges are zeroed.
std::vector<double> q(charges);
for (int ii = 0; ii < numElectrodeParticles; ii++) {
q[elecToSys[ii]] = 0.0;
}
conp.getDerivatives(numParticles, numElectrodeParticles, posData, q, exclusions, sysToElec, elecToSys, electrodeParamArray, dUdQ0, pmeData);
conp.getDerivatives(numParticles, numElectrodeParticles, posData, q, exclusions, sysToElec, elecToSys, electrodeParamArray, dUdQ0, pme);
for (int ii = 0; ii < numElectrodeParticles; ii++) {
int i = elecToSys[ii];
// Get derivatives when one electrode charge is set.
q[i] = 1.0;
conp.getDerivatives(numParticles, numElectrodeParticles, posData, q, exclusions, sysToElec, elecToSys, electrodeParamArray, dUdQ, pmeData);
conp.getDerivatives(numParticles, numElectrodeParticles, posData, q, exclusions, sysToElec, elecToSys, electrodeParamArray, dUdQ, pme);
q[i] = 0.0;
// Set matrix elements, subtracting zero charge derivatives so that the
......@@ -123,8 +121,6 @@ void ReferenceConstantPotentialMatrixSolver::update(
A[ii][ii] = dUdQ[ii] - dUdQ0[ii];
}
pme_destroy(pmeData);
// Compute Cholesky decomposition representation of the inverse.
capacitance = JAMA::Cholesky<double>(A);
if (!capacitance.is_spd()) {
......@@ -162,7 +158,7 @@ void ReferenceConstantPotentialMatrixSolver::solve(
const std::vector<int>& elecToSys,
const std::vector<std::array<double, 3> >& electrodeParamArray,
ReferenceConstantPotential& conp,
pme_t pmeData
ReferencePME& pme
) {
// Solves for charges using the matrix method.
......@@ -171,7 +167,7 @@ void ReferenceConstantPotentialMatrixSolver::solve(
charges[elecToSys[ii]] = 0.0;
}
std::vector<double> b(numElectrodeParticles);
conp.getDerivatives(numParticles, numElectrodeParticles, posData, charges, exclusions, sysToElec, elecToSys, electrodeParamArray, b, pmeData);
conp.getDerivatives(numParticles, numElectrodeParticles, posData, charges, exclusions, sysToElec, elecToSys, electrodeParamArray, b, pme);
for (int ii = 0; ii < numElectrodeParticles; ii++) {
b[ii] = -b[ii];
}
......@@ -236,14 +232,12 @@ void ReferenceConstantPotentialCGSolver::update(
// calculation. This will actually vary slightly with position but only due
// to finite accuracy of the PME splines, so it is fine to assume it will be
// constant for the preconditioner.
pme_t pmeData;
pme_init(&pmeData, conp.ewaldAlpha, 1, conp.gridSize, 5, 1);
ReferencePME pme(conp.ewaldAlpha, 1, conp.gridSize, 5, 1);
std::vector<Vec3> pmePosData(1);
std::vector<double> pmeChargeDerivatives(1);
std::vector<int> pmeElectrodeIndices(1);
std::vector<double> pmeCharges(1, 1.0);
pme_exec_charge_derivatives(pmeData, pmePosData, pmeChargeDerivatives, pmeElectrodeIndices, pmeCharges, boxVectors);
pme_destroy(pmeData);
pme.exec_charge_derivatives(pmePosData, pmeChargeDerivatives, pmeElectrodeIndices, pmeCharges, boxVectors);
// The diagonal has a contribution from reciprocal space, Ewald
// self-interaction, Ewald neutralizing plasma, Gaussian self-interaction,
......@@ -274,7 +268,7 @@ void ReferenceConstantPotentialCGSolver::solve(
const std::vector<int>& elecToSys,
const std::vector<std::array<double, 3> >& electrodeParamArray,
ReferenceConstantPotential& conp,
pme_t pmeData
ReferencePME& pme
) {
// Solves for charges using the conjugate gradient method.
......@@ -302,7 +296,7 @@ void ReferenceConstantPotentialCGSolver::solve(
}
// Evaluate the initial gradient Aq - b.
conp.getDerivatives(numParticles, numElectrodeParticles, posData, charges, exclusions, sysToElec, elecToSys, electrodeParamArray, grad, pmeData);
conp.getDerivatives(numParticles, numElectrodeParticles, posData, charges, exclusions, sysToElec, elecToSys, electrodeParamArray, grad, pme);
// Project the initial gradient without preconditioning.
offset = 0.0;
......@@ -332,7 +326,7 @@ void ReferenceConstantPotentialCGSolver::solve(
q[ii] = charges[i];
charges[i] = 0.0;
}
conp.getDerivatives(numParticles, numElectrodeParticles, posData, charges, exclusions, sysToElec, elecToSys, electrodeParamArray, grad0, pmeData);
conp.getDerivatives(numParticles, numElectrodeParticles, posData, charges, exclusions, sysToElec, elecToSys, electrodeParamArray, grad0, pme);
// Project the initial gradient with preconditioning.
if (precond) {
......@@ -362,7 +356,7 @@ void ReferenceConstantPotentialCGSolver::solve(
for (int ii = 0; ii < numElectrodeParticles; ii++) {
charges[elecToSys[ii]] = qStep[ii];
}
conp.getDerivatives(numParticles, numElectrodeParticles, posData, charges, exclusions, sysToElec, elecToSys, electrodeParamArray, gradStep, pmeData);
conp.getDerivatives(numParticles, numElectrodeParticles, posData, charges, exclusions, sysToElec, elecToSys, electrodeParamArray, gradStep, pme);
for (int ii = 0; ii < numElectrodeParticles; ii++) {
gradStep[ii] -= grad0[ii];
}
......@@ -417,7 +411,7 @@ void ReferenceConstantPotentialCGSolver::solve(
for (int ii = 0; ii < numElectrodeParticles; ii++) {
charges[elecToSys[ii]] = q[ii];
}
conp.getDerivatives(numParticles, numElectrodeParticles, posData, charges, exclusions, sysToElec, elecToSys, electrodeParamArray, grad, pmeData);
conp.getDerivatives(numParticles, numElectrodeParticles, posData, charges, exclusions, sysToElec, elecToSys, electrodeParamArray, grad, pme);
}
else {
for (int ii = 0; ii < numElectrodeParticles; ii++) {
......@@ -542,13 +536,9 @@ void ReferenceConstantPotential::execute(
double* energy,
ReferenceConstantPotentialSolver* solver
) {
pme_t pmeData;
pme_init(&pmeData, ewaldAlpha, numParticles, gridSize, 5, 1);
solver->solve(numParticles, numElectrodeParticles, posData, charges, exclusions, sysToElec, elecToSys, electrodeParamArray, *this, pmeData);
getEnergyForces(numParticles, numElectrodeParticles, posData, forceData, charges, exclusions, sysToElec, elecToSys, electrodeParamArray, energy, pmeData);
pme_destroy(pmeData);
ReferencePME pme(ewaldAlpha, numParticles, gridSize, 5, 1);
solver->solve(numParticles, numElectrodeParticles, posData, charges, exclusions, sysToElec, elecToSys, electrodeParamArray, *this, pme);
getEnergyForces(numParticles, numElectrodeParticles, posData, forceData, charges, exclusions, sysToElec, elecToSys, electrodeParamArray, energy, pme);
}
void ReferenceConstantPotential::getCharges(
......@@ -562,12 +552,8 @@ void ReferenceConstantPotential::getCharges(
const std::vector<std::array<double, 3> >& electrodeParamArray,
ReferenceConstantPotentialSolver* solver
) {
pme_t pmeData;
pme_init(&pmeData, ewaldAlpha, numParticles, gridSize, 5, 1);
solver->solve(numParticles, numElectrodeParticles, posData, charges, exclusions, sysToElec, elecToSys, electrodeParamArray, *this, pmeData);
pme_destroy(pmeData);
ReferencePME pme(ewaldAlpha, numParticles, gridSize, 5, 1);
solver->solve(numParticles, numElectrodeParticles, posData, charges, exclusions, sysToElec, elecToSys, electrodeParamArray, *this, pme);
}
void ReferenceConstantPotential::getEnergyForces(
......@@ -581,7 +567,7 @@ void ReferenceConstantPotential::getEnergyForces(
const std::vector<int>& elecToSys,
const std::vector<std::array<double, 3> >& electrodeParamArray,
double* energy,
pme_t pmeData
ReferencePME& pme
) {
const double SQRT_PI = sqrt(PI_M);
const double TWO_OVER_SQRT_PI = 2.0 / SQRT_PI;
......@@ -671,7 +657,7 @@ void ReferenceConstantPotential::getEnergyForces(
// Reciprocal space.
double pmeEnergy = 0.0;
pme_exec(pmeData, posData, forceData, charges, boxVectors, &pmeEnergy);
pme.exec(posData, forceData, charges, boxVectors, pmeEnergy);
energyAccum += pmeEnergy;
// Ewald self-interaction and external field contributions (all particles).
......@@ -710,7 +696,7 @@ void ReferenceConstantPotential::getDerivatives(
const std::vector<int>& elecToSys,
const std::vector<std::array<double, 3> >& electrodeParamArray,
std::vector<double>& chargeDerivatives,
pme_t pmeData
ReferencePME& pme
) {
const double SQRT_PI = sqrt(PI_M);
const double SELF_ALPHA_SCALE = 2.0 * ONE_4PI_EPS0 / SQRT_PI;
......@@ -757,7 +743,7 @@ void ReferenceConstantPotential::getDerivatives(
}
// Reciprocal space.
pme_exec_charge_derivatives(pmeData, posData, chargeDerivatives, elecToSys, charges, boxVectors);
pme.exec_charge_derivatives(posData, chargeDerivatives, elecToSys, charges, boxVectors);
// Ewald neutralizing plasma precalculation.
double qTotal = 0.0;
......
......@@ -243,33 +243,28 @@ void ReferenceLJCoulombIxn::calculateEwaldIxn(int numberOfAtoms, vector<Vec3>& a
// PME
if (pme && includeReciprocal) {
pme_t pmedata; /* abstract handle for PME data */
pme_init(&pmedata,alphaEwald,numberOfAtoms,meshDim,5,1);
ReferencePME pme(alphaEwald,numberOfAtoms,meshDim,5,1);
vector<double> charges(numberOfAtoms);
for (int i = 0; i < numberOfAtoms; i++)
charges[i] = atomParameters[i][QIndex];
pme_exec(pmedata,atomCoordinates,forces,charges,periodicBoxVectors,&recipEnergy);
pme.exec(atomCoordinates, forces, charges, periodicBoxVectors, recipEnergy);
if (totalEnergy)
*totalEnergy += recipEnergy;
pme_destroy(pmedata);
if (ljpme) {
// Dispersion reciprocal space terms
pme_init(&pmedata,alphaDispersionEwald,numberOfAtoms,dispersionMeshDim,5,1);
ReferencePME ljpme(alphaDispersionEwald,numberOfAtoms,dispersionMeshDim,5,1);
std::vector<Vec3> dpmeforces(numberOfAtoms);
for (int i = 0; i < numberOfAtoms; i++)
charges[i] = 8.0*pow(atomParameters[i][SigIndex], 3.0) * atomParameters[i][EpsIndex];
pme_exec_dpme(pmedata,atomCoordinates,dpmeforces,charges,periodicBoxVectors,&recipDispersionEnergy);
ljpme.exec_dpme(atomCoordinates, dpmeforces, charges, periodicBoxVectors, recipDispersionEnergy);
for (int i = 0; i < numberOfAtoms; i++)
forces[i] += dpmeforces[i];
if (totalEnergy)
*totalEnergy += recipDispersionEnergy;
pme_destroy(pmedata);
}
}
// Ewald method
......
......@@ -59,14 +59,13 @@ void testReferencePmeDerivatives() {
double ewaldAlpha = 1.752;
int gridSize[3] = {54, 49, 43};
pme_t pme;
pme_init(&pme, ewaldAlpha, numParticles, gridSize, 5, 1);
ReferencePME pme(ewaldAlpha, numParticles, gridSize, 5, 1);
double dummyEnergy=0;
vector<Vec3> dummyForces(numParticles);
vector<Vec3> testForces(numParticles);
pme_exec(pme, positions, testForces, charges, boxVectors, &dummyEnergy);
pme.exec(positions, testForces, charges, boxVectors, dummyEnergy);
for (int i = 0; i < numParticles; i++) {
for (int j = 0; j < 3; j++) {
......@@ -74,11 +73,11 @@ void testReferencePmeDerivatives() {
double energyLess = 0.0;
positions[i][j] = referencePosition - DELTA;
pme_exec(pme, positions, dummyForces, charges, boxVectors, &energyLess);
pme.exec(positions, dummyForces, charges, boxVectors, energyLess);
double energyMore = 0.0;
positions[i][j] = referencePosition + DELTA;
pme_exec(pme, positions, dummyForces, charges, boxVectors, &energyMore);
pme.exec(positions, dummyForces, charges, boxVectors, energyMore);
positions[i][j] = referencePosition;
......@@ -87,25 +86,23 @@ void testReferencePmeDerivatives() {
}
vector<double> testDerivatives(numParticles);
pme_exec_charge_derivatives(pme, positions, testDerivatives, indices, charges, boxVectors);
pme.exec_charge_derivatives(positions, testDerivatives, indices, charges, boxVectors);
for (int i = 0; i < numParticles; i++) {
double referenceCharge = charges[i];
double energyLess = 0.0;
charges[i] = referenceCharge - DELTA;
pme_exec(pme, positions, dummyForces, charges, boxVectors, &energyLess);
pme.exec(positions, dummyForces, charges, boxVectors, energyLess);
double energyMore = 0.0;
charges[i] = referenceCharge + DELTA;
pme_exec(pme, positions, dummyForces, charges, boxVectors, &energyMore);
pme.exec(positions, dummyForces, charges, boxVectors, energyMore);
charges[i] = referenceCharge;
ASSERT_EQUAL_TOL((energyMore - energyLess) / (2 * DELTA), testDerivatives[i], EPSILON);
}
pme_destroy(pme);
}
void runPlatformTests() {
......
......@@ -2873,8 +2873,7 @@ double AmoebaReferencePmeHippoNonbondedForce::calculateDispersionPairIxn(const M
}
double AmoebaReferencePmeHippoNonbondedForce::computeReciprocalSpaceDispersionForceAndEnergy(const vector<MultipoleParticleData>& particleData, vector<Vec3>& forces) const {
pme_t pmedata;
pme_init(&pmedata, _dalphaEwald, _numParticles, _dpmeGridDimensions, 5, 1);
ReferencePME pme(_dalphaEwald, _numParticles, _dpmeGridDimensions, 5, 1);
vector<double> charges(_numParticles);
vector<Vec3> dpmeforces(_numParticles, Vec3()), coords;
for (int i = 0; i < _numParticles; i++) {
......@@ -2882,8 +2881,7 @@ double AmoebaReferencePmeHippoNonbondedForce::computeReciprocalSpaceDispersionFo
coords.push_back(particleData[i].position);
}
double recipDispersionEnergy;
pme_exec_dpme(pmedata, coords, dpmeforces, charges, _periodicBoxVectors, &recipDispersionEnergy);
pme_destroy(pmedata);
pme.exec_dpme(coords, dpmeforces, charges, _periodicBoxVectors, recipDispersionEnergy);
for (int i = 0; i < _numParticles; i++)
forces[i] += dpmeforces[i];
return recipDispersionEnergy;
......
......@@ -650,12 +650,10 @@ void testPME(bool triclinic, bool nonNeutral) {
// Get charge derivatives from the reference PME implementation.
pme_t referencePme;
int gridSize[3] = {gridx, gridy, gridz};
pme_init(&referencePme, alpha, numParticles, gridSize, 5, 1);
ReferencePME referencePme(alpha, numParticles, gridSize, 5, 1);
vector<double> testDerivatives(numParticles);
pme_exec_charge_derivatives(referencePme, positions, testDerivatives, testIndices, testCharges, boxVectors);
pme_destroy(referencePme);
referencePme.exec_charge_derivatives(positions, testDerivatives, testIndices, testCharges, boxVectors);
// See if they match.
for (int i = 0; i < numParticles; i++) {
......
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