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