/* -------------------------------------------------------------------------- * * OpenMMAmoeba * * -------------------------------------------------------------------------- * * This is part of the OpenMM molecular simulation toolkit originating from * * Simbios, the NIH National Center for Physics-Based Simulation of * * Biological Structures at Stanford, funded under the NIH Roadmap for * * Medical Research, grant U54 GM072970. See https://simtk.org. * * * * Portions copyright (c) 2008-2009 Stanford University and the Authors. * * Authors: * * Contributors: * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as published * * by the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public License * * along with this program. If not, see . * * -------------------------------------------------------------------------- */ #include "AmoebaReferenceKernels.h" #include "AmoebaReferenceBondForce.h" #include "AmoebaReferenceAngleForce.h" #include "AmoebaReferenceInPlaneAngleForce.h" #include "AmoebaReferencePiTorsionForce.h" #include "AmoebaReferenceStretchBendForce.h" #include "AmoebaReferenceOutOfPlaneBendForce.h" #include "AmoebaReferenceTorsionTorsionForce.h" #include "AmoebaReferenceVdwForce.h" #include "AmoebaReferenceWcaDispersionForce.h" #include "AmoebaReferenceGeneralizedKirkwoodForce.h" #include "openmm/internal/AmoebaTorsionTorsionForceImpl.h" #include "openmm/internal/AmoebaWcaDispersionForceImpl.h" #include "ReferencePlatform.h" #include "openmm/internal/ContextImpl.h" #include "openmm/AmoebaMultipoleForce.h" #include "openmm/internal/AmoebaMultipoleForceImpl.h" #include "openmm/internal/AmoebaVdwForceImpl.h" #include "openmm/internal/AmoebaGeneralizedKirkwoodForceImpl.h" #include "openmm/NonbondedForce.h" #include "openmm/internal/NonbondedForceImpl.h" #include #ifdef _MSC_VER #include #endif using namespace OpenMM; using namespace std; static vector& extractPositions(ContextImpl& context) { ReferencePlatform::PlatformData* data = reinterpret_cast(context.getPlatformData()); return *((vector*) data->positions); } static vector& extractVelocities(ContextImpl& context) { ReferencePlatform::PlatformData* data = reinterpret_cast(context.getPlatformData()); return *((vector*) data->velocities); } static vector& extractForces(ContextImpl& context) { ReferencePlatform::PlatformData* data = reinterpret_cast(context.getPlatformData()); return *((vector*) data->forces); } static RealVec& extractBoxSize(ContextImpl& context) { ReferencePlatform::PlatformData* data = reinterpret_cast(context.getPlatformData()); return *(RealVec*) data->periodicBoxSize; } static RealVec* extractBoxVectors(ContextImpl& context) { ReferencePlatform::PlatformData* data = reinterpret_cast(context.getPlatformData()); return (RealVec*) data->periodicBoxVectors; } // *************************************************************************** ReferenceCalcAmoebaBondForceKernel::ReferenceCalcAmoebaBondForceKernel(std::string name, const Platform& platform, const System& system) : CalcAmoebaBondForceKernel(name, platform), system(system) { } ReferenceCalcAmoebaBondForceKernel::~ReferenceCalcAmoebaBondForceKernel() { } void ReferenceCalcAmoebaBondForceKernel::initialize(const System& system, const AmoebaBondForce& force) { numBonds = force.getNumBonds(); for (int ii = 0; ii < numBonds; ii++) { int particle1Index, particle2Index; double lengthValue, kValue; force.getBondParameters(ii, particle1Index, particle2Index, lengthValue, kValue); particle1.push_back(particle1Index); particle2.push_back(particle2Index); length.push_back(static_cast(lengthValue)); kQuadratic.push_back(static_cast(kValue)); } globalBondCubic = static_cast(force.getAmoebaGlobalBondCubic()); globalBondQuartic = static_cast(force.getAmoebaGlobalBondQuartic()); } double ReferenceCalcAmoebaBondForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) { vector& posData = extractPositions(context); vector& forceData = extractForces(context); AmoebaReferenceBondForce amoebaReferenceBondForce; RealOpenMM energy = amoebaReferenceBondForce.calculateForceAndEnergy(numBonds, posData, particle1, particle2, length, kQuadratic, globalBondCubic, globalBondQuartic, forceData); return static_cast(energy); } void ReferenceCalcAmoebaBondForceKernel::copyParametersToContext(ContextImpl& context, const AmoebaBondForce& force) { if (numBonds != force.getNumBonds()) throw OpenMMException("updateParametersInContext: The number of bonds has changed"); // Record the values. for (int i = 0; i < numBonds; ++i) { int particle1Index, particle2Index; double lengthValue, kValue; force.getBondParameters(i, particle1Index, particle2Index, lengthValue, kValue); if (particle1Index != particle1[i] || particle2Index != particle2[i]) throw OpenMMException("updateParametersInContext: The set of particles in a bond has changed"); length[i] = (RealOpenMM) lengthValue; kQuadratic[i] = (RealOpenMM) kValue; } } // *************************************************************************** ReferenceCalcAmoebaAngleForceKernel::ReferenceCalcAmoebaAngleForceKernel(std::string name, const Platform& platform, const System& system) : CalcAmoebaAngleForceKernel(name, platform), system(system) { } ReferenceCalcAmoebaAngleForceKernel::~ReferenceCalcAmoebaAngleForceKernel() { } void ReferenceCalcAmoebaAngleForceKernel::initialize(const System& system, const AmoebaAngleForce& force) { numAngles = force.getNumAngles(); for (int ii = 0; ii < numAngles; ii++) { int particle1Index, particle2Index, particle3Index; double angleValue, k; force.getAngleParameters(ii, particle1Index, particle2Index, particle3Index, angleValue, k); particle1.push_back(particle1Index); particle2.push_back(particle2Index); particle3.push_back(particle3Index); angle.push_back(static_cast(angleValue)); kQuadratic.push_back(static_cast(k)); } globalAngleCubic = static_cast(force.getAmoebaGlobalAngleCubic()); globalAngleQuartic = static_cast(force.getAmoebaGlobalAngleQuartic()); globalAnglePentic = static_cast(force.getAmoebaGlobalAnglePentic()); globalAngleSextic = static_cast(force.getAmoebaGlobalAngleSextic()); } double ReferenceCalcAmoebaAngleForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) { vector& posData = extractPositions(context); vector& forceData = extractForces(context); AmoebaReferenceAngleForce amoebaReferenceAngleForce; RealOpenMM energy = amoebaReferenceAngleForce.calculateForceAndEnergy(numAngles, posData, particle1, particle2, particle3, angle, kQuadratic, globalAngleCubic, globalAngleQuartic, globalAnglePentic, globalAngleSextic, forceData); return static_cast(energy); } void ReferenceCalcAmoebaAngleForceKernel::copyParametersToContext(ContextImpl& context, const AmoebaAngleForce& force) { if (numAngles != force.getNumAngles()) throw OpenMMException("updateParametersInContext: The number of angles has changed"); // Record the values. for (int i = 0; i < numAngles; ++i) { int particle1Index, particle2Index, particle3Index; double angleValue, k; force.getAngleParameters(i, particle1Index, particle2Index, particle3Index, angleValue, k); if (particle1Index != particle1[i] || particle2Index != particle2[i] || particle3Index != particle3[i]) throw OpenMMException("updateParametersInContext: The set of particles in an angle has changed"); angle[i] = (RealOpenMM) angleValue; kQuadratic[i] = (RealOpenMM) k; } } ReferenceCalcAmoebaInPlaneAngleForceKernel::ReferenceCalcAmoebaInPlaneAngleForceKernel(std::string name, const Platform& platform, const System& system) : CalcAmoebaInPlaneAngleForceKernel(name, platform), system(system) { } ReferenceCalcAmoebaInPlaneAngleForceKernel::~ReferenceCalcAmoebaInPlaneAngleForceKernel() { } void ReferenceCalcAmoebaInPlaneAngleForceKernel::initialize(const System& system, const AmoebaInPlaneAngleForce& force) { numAngles = force.getNumAngles(); for (int ii = 0; ii < numAngles; ii++) { int particle1Index, particle2Index, particle3Index, particle4Index; double angleValue, k; force.getAngleParameters(ii, particle1Index, particle2Index, particle3Index, particle4Index, angleValue, k); particle1.push_back(particle1Index); particle2.push_back(particle2Index); particle3.push_back(particle3Index); particle4.push_back(particle4Index); angle.push_back(static_cast(angleValue)); kQuadratic.push_back(static_cast(k)); } globalInPlaneAngleCubic = static_cast(force.getAmoebaGlobalInPlaneAngleCubic()); globalInPlaneAngleQuartic = static_cast(force.getAmoebaGlobalInPlaneAngleQuartic()); globalInPlaneAnglePentic = static_cast(force.getAmoebaGlobalInPlaneAnglePentic()); globalInPlaneAngleSextic = static_cast(force.getAmoebaGlobalInPlaneAngleSextic()); } double ReferenceCalcAmoebaInPlaneAngleForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) { vector& posData = extractPositions(context); vector& forceData = extractForces(context); AmoebaReferenceInPlaneAngleForce amoebaReferenceInPlaneAngleForce; RealOpenMM energy = amoebaReferenceInPlaneAngleForce.calculateForceAndEnergy(numAngles, posData, particle1, particle2, particle3, particle4, angle, kQuadratic, globalInPlaneAngleCubic, globalInPlaneAngleQuartic, globalInPlaneAnglePentic, globalInPlaneAngleSextic, forceData); return static_cast(energy); } void ReferenceCalcAmoebaInPlaneAngleForceKernel::copyParametersToContext(ContextImpl& context, const AmoebaInPlaneAngleForce& force) { if (numAngles != force.getNumAngles()) throw OpenMMException("updateParametersInContext: The number of angles has changed"); // Record the values. for (int i = 0; i < numAngles; ++i) { int particle1Index, particle2Index, particle3Index, particle4Index; double angleValue, k; force.getAngleParameters(i, particle1Index, particle2Index, particle3Index, particle4Index, angleValue, k); if (particle1Index != particle1[i] || particle2Index != particle2[i] || particle3Index != particle3[i] || particle4Index != particle4[i]) throw OpenMMException("updateParametersInContext: The set of particles in an angle has changed"); angle[i] = (RealOpenMM) angleValue; kQuadratic[i] = (RealOpenMM) k; } } ReferenceCalcAmoebaPiTorsionForceKernel::ReferenceCalcAmoebaPiTorsionForceKernel(std::string name, const Platform& platform, const System& system) : CalcAmoebaPiTorsionForceKernel(name, platform), system(system) { } ReferenceCalcAmoebaPiTorsionForceKernel::~ReferenceCalcAmoebaPiTorsionForceKernel() { } void ReferenceCalcAmoebaPiTorsionForceKernel::initialize(const System& system, const AmoebaPiTorsionForce& force) { numPiTorsions = force.getNumPiTorsions(); for (int ii = 0; ii < numPiTorsions; ii++) { int particle1Index, particle2Index, particle3Index, particle4Index, particle5Index, particle6Index; double kTorsionParameter; force.getPiTorsionParameters(ii, particle1Index, particle2Index, particle3Index, particle4Index, particle5Index, particle6Index, kTorsionParameter); particle1.push_back(particle1Index); particle2.push_back(particle2Index); particle3.push_back(particle3Index); particle4.push_back(particle4Index); particle5.push_back(particle5Index); particle6.push_back(particle6Index); kTorsion.push_back(static_cast(kTorsionParameter)); } } double ReferenceCalcAmoebaPiTorsionForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) { vector& posData = extractPositions(context); vector& forceData = extractForces(context); AmoebaReferencePiTorsionForce amoebaReferencePiTorsionForce; RealOpenMM energy = amoebaReferencePiTorsionForce.calculateForceAndEnergy(numPiTorsions, posData, particle1, particle2, particle3, particle4, particle5, particle6, kTorsion, forceData); return static_cast(energy); } void ReferenceCalcAmoebaPiTorsionForceKernel::copyParametersToContext(ContextImpl& context, const AmoebaPiTorsionForce& force) { if (numPiTorsions != force.getNumPiTorsions()) throw OpenMMException("updateParametersInContext: The number of torsions has changed"); // Record the values. for (int i = 0; i < numPiTorsions; ++i) { int particle1Index, particle2Index, particle3Index, particle4Index, particle5Index, particle6Index; double kTorsionParameter; force.getPiTorsionParameters(i, particle1Index, particle2Index, particle3Index, particle4Index, particle5Index, particle6Index, kTorsionParameter); if (particle1Index != particle1[i] || particle2Index != particle2[i] || particle3Index != particle3[i] || particle4Index != particle4[i] || particle5Index != particle5[i] || particle6Index != particle6[i]) throw OpenMMException("updateParametersInContext: The set of particles in a torsion has changed"); kTorsion[i] = (RealOpenMM) kTorsionParameter; } } ReferenceCalcAmoebaStretchBendForceKernel::ReferenceCalcAmoebaStretchBendForceKernel(std::string name, const Platform& platform, const System& system) : CalcAmoebaStretchBendForceKernel(name, platform), system(system) { } ReferenceCalcAmoebaStretchBendForceKernel::~ReferenceCalcAmoebaStretchBendForceKernel() { } void ReferenceCalcAmoebaStretchBendForceKernel::initialize(const System& system, const AmoebaStretchBendForce& force) { numStretchBends = force.getNumStretchBends(); for (int ii = 0; ii < numStretchBends; ii++) { int particle1Index, particle2Index, particle3Index; double lengthAB, lengthCB, angle, k1, k2; force.getStretchBendParameters(ii, particle1Index, particle2Index, particle3Index, lengthAB, lengthCB, angle, k1, k2); particle1.push_back(particle1Index); particle2.push_back(particle2Index); particle3.push_back(particle3Index); lengthABParameters.push_back(static_cast(lengthAB)); lengthCBParameters.push_back(static_cast(lengthCB)); angleParameters.push_back(static_cast(angle)); k1Parameters.push_back(static_cast(k1)); k2Parameters.push_back(static_cast(k2)); } } double ReferenceCalcAmoebaStretchBendForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) { vector& posData = extractPositions(context); vector& forceData = extractForces(context); AmoebaReferenceStretchBendForce amoebaReferenceStretchBendForce; RealOpenMM energy = amoebaReferenceStretchBendForce.calculateForceAndEnergy(numStretchBends, posData, particle1, particle2, particle3, lengthABParameters, lengthCBParameters, angleParameters, k1Parameters, k2Parameters, forceData); return static_cast(energy); } void ReferenceCalcAmoebaStretchBendForceKernel::copyParametersToContext(ContextImpl& context, const AmoebaStretchBendForce& force) { if (numStretchBends != force.getNumStretchBends()) throw OpenMMException("updateParametersInContext: The number of stretch-bends has changed"); // Record the values. for (int i = 0; i < numStretchBends; ++i) { int particle1Index, particle2Index, particle3Index; double lengthAB, lengthCB, angle, k1, k2; force.getStretchBendParameters(i, particle1Index, particle2Index, particle3Index, lengthAB, lengthCB, angle, k1, k2); if (particle1Index != particle1[i] || particle2Index != particle2[i] || particle3Index != particle3[i]) throw OpenMMException("updateParametersInContext: The set of particles in a stretch-bend has changed"); lengthABParameters[i] = (RealOpenMM) lengthAB; lengthCBParameters[i] = (RealOpenMM) lengthCB; angleParameters[i] = (RealOpenMM) angle; k1Parameters[i] = (RealOpenMM) k1; k2Parameters[i] = (RealOpenMM) k2; } } ReferenceCalcAmoebaOutOfPlaneBendForceKernel::ReferenceCalcAmoebaOutOfPlaneBendForceKernel(std::string name, const Platform& platform, const System& system) : CalcAmoebaOutOfPlaneBendForceKernel(name, platform), system(system) { } ReferenceCalcAmoebaOutOfPlaneBendForceKernel::~ReferenceCalcAmoebaOutOfPlaneBendForceKernel() { } void ReferenceCalcAmoebaOutOfPlaneBendForceKernel::initialize(const System& system, const AmoebaOutOfPlaneBendForce& force) { numOutOfPlaneBends = force.getNumOutOfPlaneBends(); for (int ii = 0; ii < numOutOfPlaneBends; ii++) { int particle1Index, particle2Index, particle3Index, particle4Index; double k; force.getOutOfPlaneBendParameters(ii, particle1Index, particle2Index, particle3Index, particle4Index, k); particle1.push_back(particle1Index); particle2.push_back(particle2Index); particle3.push_back(particle3Index); particle4.push_back(particle4Index); kParameters.push_back(static_cast(k)); } globalOutOfPlaneBendAngleCubic = static_cast(force.getAmoebaGlobalOutOfPlaneBendCubic()); globalOutOfPlaneBendAngleQuartic = static_cast(force.getAmoebaGlobalOutOfPlaneBendQuartic()); globalOutOfPlaneBendAnglePentic = static_cast(force.getAmoebaGlobalOutOfPlaneBendPentic()); globalOutOfPlaneBendAngleSextic = static_cast(force.getAmoebaGlobalOutOfPlaneBendSextic()); } double ReferenceCalcAmoebaOutOfPlaneBendForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) { vector& posData = extractPositions(context); vector& forceData = extractForces(context); AmoebaReferenceOutOfPlaneBendForce amoebaReferenceOutOfPlaneBendForce; RealOpenMM energy = amoebaReferenceOutOfPlaneBendForce.calculateForceAndEnergy(numOutOfPlaneBends, posData, particle1, particle2, particle3, particle4, kParameters, globalOutOfPlaneBendAngleCubic, globalOutOfPlaneBendAngleQuartic, globalOutOfPlaneBendAnglePentic, globalOutOfPlaneBendAngleSextic, forceData); return static_cast(energy); } void ReferenceCalcAmoebaOutOfPlaneBendForceKernel::copyParametersToContext(ContextImpl& context, const AmoebaOutOfPlaneBendForce& force) { if (numOutOfPlaneBends != force.getNumOutOfPlaneBends()) throw OpenMMException("updateParametersInContext: The number of out-of-plane bends has changed"); // Record the values. for (int i = 0; i < numOutOfPlaneBends; ++i) { int particle1Index, particle2Index, particle3Index, particle4Index; double k; force.getOutOfPlaneBendParameters(i, particle1Index, particle2Index, particle3Index, particle4Index, k); if (particle1Index != particle1[i] || particle2Index != particle2[i] || particle3Index != particle3[i] || particle4Index != particle4[i]) throw OpenMMException("updateParametersInContext: The set of particles in an out-of-plane bend has changed"); kParameters[i] = (RealOpenMM) k; } } ReferenceCalcAmoebaTorsionTorsionForceKernel::ReferenceCalcAmoebaTorsionTorsionForceKernel(std::string name, const Platform& platform, const System& system) : CalcAmoebaTorsionTorsionForceKernel(name, platform), system(system) { } ReferenceCalcAmoebaTorsionTorsionForceKernel::~ReferenceCalcAmoebaTorsionTorsionForceKernel() { } void ReferenceCalcAmoebaTorsionTorsionForceKernel::initialize(const System& system, const AmoebaTorsionTorsionForce& force) { numTorsionTorsions = force.getNumTorsionTorsions(); // torsion-torsion parameters for (int ii = 0; ii < numTorsionTorsions; ii++) { int particle1Index, particle2Index, particle3Index, particle4Index, particle5Index, chiralCheckAtomIndex, gridIndex; force.getTorsionTorsionParameters(ii, particle1Index, particle2Index, particle3Index, particle4Index, particle5Index, chiralCheckAtomIndex, gridIndex); particle1.push_back(particle1Index); particle2.push_back(particle2Index); particle3.push_back(particle3Index); particle4.push_back(particle4Index); particle5.push_back(particle5Index); chiralCheckAtom.push_back(chiralCheckAtomIndex); gridIndices.push_back(gridIndex); } // torsion-torsion grids numTorsionTorsionGrids = force.getNumTorsionTorsionGrids(); torsionTorsionGrids.resize(numTorsionTorsionGrids); for (int ii = 0; ii < numTorsionTorsionGrids; ii++) { const TorsionTorsionGrid grid = force.getTorsionTorsionGrid(ii); torsionTorsionGrids[ii].resize(grid.size()); // check if grid needs to be reordered: x-angle should be 'slow' index TorsionTorsionGrid reorderedGrid; int reorder = 0; if (grid[0][0][0] != grid[0][1][0]) { AmoebaTorsionTorsionForceImpl::reorderGrid(grid, reorderedGrid); reorder = 1; } for (unsigned int kk = 0; kk < grid.size(); kk++) { torsionTorsionGrids[ii][kk].resize(grid[kk].size()); for (unsigned int jj = 0; jj < grid[kk].size(); jj++) { torsionTorsionGrids[ii][kk][jj].resize(grid[kk][jj].size()); if (reorder) { for (unsigned int ll = 0; ll < grid[ll][jj].size(); ll++) { torsionTorsionGrids[ii][kk][jj][ll] = static_cast(reorderedGrid[kk][jj][ll]); } } else { for (unsigned int ll = 0; ll < grid[ll][jj].size(); ll++) { torsionTorsionGrids[ii][kk][jj][ll] = static_cast(grid[kk][jj][ll]); } } } } } } double ReferenceCalcAmoebaTorsionTorsionForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) { vector& posData = extractPositions(context); vector& forceData = extractForces(context); AmoebaReferenceTorsionTorsionForce amoebaReferenceTorsionTorsionForce; RealOpenMM energy = amoebaReferenceTorsionTorsionForce.calculateForceAndEnergy(numTorsionTorsions, posData, particle1, particle2, particle3, particle4, particle5, chiralCheckAtom, gridIndices, torsionTorsionGrids, forceData); return static_cast(energy); } /* -------------------------------------------------------------------------- * * AmoebaMultipole * * -------------------------------------------------------------------------- */ ReferenceCalcAmoebaMultipoleForceKernel::ReferenceCalcAmoebaMultipoleForceKernel(std::string name, const Platform& platform, const System& system) : CalcAmoebaMultipoleForceKernel(name, platform), system(system), numMultipoles(0), mutualInducedMaxIterations(60), mutualInducedTargetEpsilon(1.0e-03), usePme(false),alphaEwald(0.0), cutoffDistance(1.0) { } ReferenceCalcAmoebaMultipoleForceKernel::~ReferenceCalcAmoebaMultipoleForceKernel() { } void ReferenceCalcAmoebaMultipoleForceKernel::initialize(const System& system, const AmoebaMultipoleForce& force) { numMultipoles = force.getNumMultipoles(); charges.resize(numMultipoles); dipoles.resize(3*numMultipoles); quadrupoles.resize(9*numMultipoles); tholes.resize(numMultipoles); dampingFactors.resize(numMultipoles); polarity.resize(numMultipoles); axisTypes.resize(numMultipoles); multipoleAtomZs.resize(numMultipoles); multipoleAtomXs.resize(numMultipoles); multipoleAtomYs.resize(numMultipoles); multipoleAtomCovalentInfo.resize(numMultipoles); int dipoleIndex = 0; int quadrupoleIndex = 0; int maxCovalentRange = 0; double totalCharge = 0.0; for (int ii = 0; ii < numMultipoles; ii++) { // multipoles int axisType, multipoleAtomZ, multipoleAtomX, multipoleAtomY; double charge, tholeD, dampingFactorD, polarityD; std::vector dipolesD; std::vector quadrupolesD; force.getMultipoleParameters(ii, charge, dipolesD, quadrupolesD, axisType, multipoleAtomZ, multipoleAtomX, multipoleAtomY, tholeD, dampingFactorD, polarityD); totalCharge += charge; axisTypes[ii] = axisType; multipoleAtomZs[ii] = multipoleAtomZ; multipoleAtomXs[ii] = multipoleAtomX; multipoleAtomYs[ii] = multipoleAtomY; charges[ii] = static_cast(charge); tholes[ii] = static_cast(tholeD); dampingFactors[ii] = static_cast(dampingFactorD); polarity[ii] = static_cast(polarityD); dipoles[dipoleIndex++] = static_cast(dipolesD[0]); dipoles[dipoleIndex++] = static_cast(dipolesD[1]); dipoles[dipoleIndex++] = static_cast(dipolesD[2]); quadrupoles[quadrupoleIndex++] = static_cast(quadrupolesD[0]); quadrupoles[quadrupoleIndex++] = static_cast(quadrupolesD[1]); quadrupoles[quadrupoleIndex++] = static_cast(quadrupolesD[2]); quadrupoles[quadrupoleIndex++] = static_cast(quadrupolesD[3]); quadrupoles[quadrupoleIndex++] = static_cast(quadrupolesD[4]); quadrupoles[quadrupoleIndex++] = static_cast(quadrupolesD[5]); quadrupoles[quadrupoleIndex++] = static_cast(quadrupolesD[6]); quadrupoles[quadrupoleIndex++] = static_cast(quadrupolesD[7]); quadrupoles[quadrupoleIndex++] = static_cast(quadrupolesD[8]); // covalent info std::vector< std::vector > covalentLists; force.getCovalentMaps(ii, covalentLists); multipoleAtomCovalentInfo[ii] = covalentLists; } polarizationType = force.getPolarizationType(); if (polarizationType == AmoebaMultipoleForce::Mutual) { mutualInducedMaxIterations = force.getMutualInducedMaxIterations(); mutualInducedTargetEpsilon = force.getMutualInducedTargetEpsilon(); } // PME nonbondedMethod = force.getNonbondedMethod(); if (nonbondedMethod == AmoebaMultipoleForce::PME) { usePme = true; alphaEwald = force.getAEwald(); cutoffDistance = force.getCutoffDistance(); force.getPmeGridDimensions(pmeGridDimension); if (pmeGridDimension[0] == 0 || alphaEwald == 0.0) { NonbondedForce nb; nb.setEwaldErrorTolerance(force.getEwaldErrorTolerance()); nb.setCutoffDistance(force.getCutoffDistance()); int gridSizeX, gridSizeY, gridSizeZ; NonbondedForceImpl::calcPMEParameters(system, nb, alphaEwald, gridSizeX, gridSizeY, gridSizeZ); pmeGridDimension[0] = gridSizeX; pmeGridDimension[1] = gridSizeY; pmeGridDimension[2] = gridSizeZ; } } else { usePme = false; } return; } AmoebaReferenceMultipoleForce* ReferenceCalcAmoebaMultipoleForceKernel::setupAmoebaReferenceMultipoleForce(ContextImpl& context) { // amoebaReferenceMultipoleForce is set to AmoebaReferenceGeneralizedKirkwoodForce if AmoebaGeneralizedKirkwoodForce is present // amoebaReferenceMultipoleForce is set to AmoebaReferencePmeMultipoleForce if 'usePme' is set // amoebaReferenceMultipoleForce is set to AmoebaReferenceMultipoleForce otherwise // check if AmoebaGeneralizedKirkwoodForce is present ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel* gkKernel = NULL; for (unsigned int ii = 0; ii < context.getForceImpls().size() && gkKernel == NULL; ii++) { AmoebaGeneralizedKirkwoodForceImpl* gkImpl = dynamic_cast(context.getForceImpls()[ii]); if (gkImpl != NULL) { gkKernel = dynamic_cast(&gkImpl->getKernel().getImpl()); } } AmoebaReferenceMultipoleForce* amoebaReferenceMultipoleForce = NULL; if (gkKernel) { // amoebaReferenceGeneralizedKirkwoodForce is deleted in AmoebaReferenceGeneralizedKirkwoodMultipoleForce // destructor AmoebaReferenceGeneralizedKirkwoodForce* amoebaReferenceGeneralizedKirkwoodForce = new AmoebaReferenceGeneralizedKirkwoodForce(); amoebaReferenceGeneralizedKirkwoodForce->setNumParticles(gkKernel->getNumParticles()); amoebaReferenceGeneralizedKirkwoodForce->setSoluteDielectric(gkKernel->getSoluteDielectric()); amoebaReferenceGeneralizedKirkwoodForce->setSolventDielectric(gkKernel->getSolventDielectric()); amoebaReferenceGeneralizedKirkwoodForce->setDielectricOffset(gkKernel->getDielectricOffset()); amoebaReferenceGeneralizedKirkwoodForce->setProbeRadius(gkKernel->getProbeRadius()); amoebaReferenceGeneralizedKirkwoodForce->setSurfaceAreaFactor(gkKernel->getSurfaceAreaFactor()); amoebaReferenceGeneralizedKirkwoodForce->setIncludeCavityTerm(gkKernel->getIncludeCavityTerm()); amoebaReferenceGeneralizedKirkwoodForce->setDirectPolarization(gkKernel->getDirectPolarization()); vector parameters; gkKernel->getAtomicRadii(parameters); amoebaReferenceGeneralizedKirkwoodForce->setAtomicRadii(parameters); gkKernel->getScaleFactors(parameters); amoebaReferenceGeneralizedKirkwoodForce->setScaleFactors(parameters); gkKernel->getCharges(parameters); amoebaReferenceGeneralizedKirkwoodForce->setCharges(parameters); // calculate Grycuk Born radii vector& posData = extractPositions(context); amoebaReferenceGeneralizedKirkwoodForce->calculateGrycukBornRadii(posData); amoebaReferenceMultipoleForce = new AmoebaReferenceGeneralizedKirkwoodMultipoleForce(amoebaReferenceGeneralizedKirkwoodForce); } else if (usePme) { AmoebaReferencePmeMultipoleForce* amoebaReferencePmeMultipoleForce = new AmoebaReferencePmeMultipoleForce(); amoebaReferencePmeMultipoleForce->setAlphaEwald(alphaEwald); amoebaReferencePmeMultipoleForce->setCutoffDistance(cutoffDistance); amoebaReferencePmeMultipoleForce->setPmeGridDimensions(pmeGridDimension); RealVec* boxVectors = extractBoxVectors(context); double minAllowedSize = 1.999999*cutoffDistance; if (boxVectors[0][0] < minAllowedSize || boxVectors[1][1] < minAllowedSize || boxVectors[2][2] < minAllowedSize) { throw OpenMMException("The periodic box size has decreased to less than twice the nonbonded cutoff."); } amoebaReferencePmeMultipoleForce->setPeriodicBoxSize(boxVectors); amoebaReferenceMultipoleForce = static_cast(amoebaReferencePmeMultipoleForce); } else { amoebaReferenceMultipoleForce = new AmoebaReferenceMultipoleForce(AmoebaReferenceMultipoleForce::NoCutoff); } // set polarization type if (polarizationType == AmoebaMultipoleForce::Mutual) { amoebaReferenceMultipoleForce->setPolarizationType(AmoebaReferenceMultipoleForce::Mutual); amoebaReferenceMultipoleForce->setMutualInducedDipoleTargetEpsilon(mutualInducedTargetEpsilon); amoebaReferenceMultipoleForce->setMaximumMutualInducedDipoleIterations(mutualInducedMaxIterations); } else if (polarizationType == AmoebaMultipoleForce::Direct) { amoebaReferenceMultipoleForce->setPolarizationType(AmoebaReferenceMultipoleForce::Direct); } else { throw OpenMMException("Polarization type not recognzied."); } return amoebaReferenceMultipoleForce; } double ReferenceCalcAmoebaMultipoleForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) { AmoebaReferenceMultipoleForce* amoebaReferenceMultipoleForce = setupAmoebaReferenceMultipoleForce(context); vector& posData = extractPositions(context); vector& forceData = extractForces(context); RealOpenMM energy = amoebaReferenceMultipoleForce->calculateForceAndEnergy(posData, charges, dipoles, quadrupoles, tholes, dampingFactors, polarity, axisTypes, multipoleAtomZs, multipoleAtomXs, multipoleAtomYs, multipoleAtomCovalentInfo, forceData); delete amoebaReferenceMultipoleForce; return static_cast(energy); } void ReferenceCalcAmoebaMultipoleForceKernel::getInducedDipoles(ContextImpl& context, vector& outputDipoles) { int numParticles = context.getSystem().getNumParticles(); outputDipoles.resize(numParticles); // Create an AmoebaReferenceMultipoleForce to do the calculation. AmoebaReferenceMultipoleForce* amoebaReferenceMultipoleForce = setupAmoebaReferenceMultipoleForce(context); vector& posData = extractPositions(context); // Retrieve the induced dipoles. vector inducedDipoles; amoebaReferenceMultipoleForce->calculateInducedDipoles(posData, charges, dipoles, quadrupoles, tholes, dampingFactors, polarity, axisTypes, multipoleAtomZs, multipoleAtomXs, multipoleAtomYs, multipoleAtomCovalentInfo, inducedDipoles); for (int i = 0; i < numParticles; i++) outputDipoles[i] = inducedDipoles[i]; delete amoebaReferenceMultipoleForce; } void ReferenceCalcAmoebaMultipoleForceKernel::getElectrostaticPotential(ContextImpl& context, const std::vector< Vec3 >& inputGrid, std::vector< double >& outputElectrostaticPotential) { AmoebaReferenceMultipoleForce* amoebaReferenceMultipoleForce = setupAmoebaReferenceMultipoleForce(context); vector& posData = extractPositions(context); vector grid(inputGrid.size()); vector potential(inputGrid.size()); for (unsigned int ii = 0; ii < inputGrid.size(); ii++) { grid[ii] = inputGrid[ii]; } amoebaReferenceMultipoleForce->calculateElectrostaticPotential(posData, charges, dipoles, quadrupoles, tholes, dampingFactors, polarity, axisTypes, multipoleAtomZs, multipoleAtomXs, multipoleAtomYs, multipoleAtomCovalentInfo, grid, potential); outputElectrostaticPotential.resize(inputGrid.size()); for (unsigned int ii = 0; ii < inputGrid.size(); ii++) { outputElectrostaticPotential[ii] = potential[ii]; } delete amoebaReferenceMultipoleForce; } void ReferenceCalcAmoebaMultipoleForceKernel::getSystemMultipoleMoments(ContextImpl& context, std::vector< double >& outputMultipoleMoments) { // retrieve masses const System& system = context.getSystem(); vector masses; for (int i = 0; i < system.getNumParticles(); ++i) { masses.push_back(static_cast(system.getParticleMass(i))); } AmoebaReferenceMultipoleForce* amoebaReferenceMultipoleForce = setupAmoebaReferenceMultipoleForce(context); vector& posData = extractPositions(context); amoebaReferenceMultipoleForce->calculateAmoebaSystemMultipoleMoments(masses, posData, charges, dipoles, quadrupoles, tholes, dampingFactors, polarity, axisTypes, multipoleAtomZs, multipoleAtomXs, multipoleAtomYs, multipoleAtomCovalentInfo, outputMultipoleMoments); delete amoebaReferenceMultipoleForce; } void ReferenceCalcAmoebaMultipoleForceKernel::copyParametersToContext(ContextImpl& context, const AmoebaMultipoleForce& force) { if (numMultipoles != force.getNumMultipoles()) throw OpenMMException("updateParametersInContext: The number of multipoles has changed"); // Record the values. int dipoleIndex = 0; int quadrupoleIndex = 0; for (int i = 0; i < numMultipoles; ++i) { int axisType, multipoleAtomZ, multipoleAtomX, multipoleAtomY; double charge, tholeD, dampingFactorD, polarityD; std::vector dipolesD; std::vector quadrupolesD; force.getMultipoleParameters(i, charge, dipolesD, quadrupolesD, axisType, multipoleAtomZ, multipoleAtomX, multipoleAtomY, tholeD, dampingFactorD, polarityD); axisTypes[i] = axisType; multipoleAtomZs[i] = multipoleAtomZ; multipoleAtomXs[i] = multipoleAtomX; multipoleAtomYs[i] = multipoleAtomY; charges[i] = (RealOpenMM) charge; tholes[i] = (RealOpenMM) tholeD; dampingFactors[i] = (RealOpenMM) dampingFactorD; polarity[i] = (RealOpenMM) polarityD; dipoles[dipoleIndex++] = (RealOpenMM) dipolesD[0]; dipoles[dipoleIndex++] = (RealOpenMM) dipolesD[1]; dipoles[dipoleIndex++] = (RealOpenMM) dipolesD[2]; quadrupoles[quadrupoleIndex++] = (RealOpenMM) quadrupolesD[0]; quadrupoles[quadrupoleIndex++] = (RealOpenMM) quadrupolesD[1]; quadrupoles[quadrupoleIndex++] = (RealOpenMM) quadrupolesD[2]; quadrupoles[quadrupoleIndex++] = (RealOpenMM) quadrupolesD[3]; quadrupoles[quadrupoleIndex++] = (RealOpenMM) quadrupolesD[4]; quadrupoles[quadrupoleIndex++] = (RealOpenMM) quadrupolesD[5]; quadrupoles[quadrupoleIndex++] = (RealOpenMM) quadrupolesD[6]; quadrupoles[quadrupoleIndex++] = (RealOpenMM) quadrupolesD[7]; quadrupoles[quadrupoleIndex++] = (RealOpenMM) quadrupolesD[8]; } } void ReferenceCalcAmoebaMultipoleForceKernel::getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const { if (!usePme) throw OpenMMException("getPMEParametersInContext: This Context is not using PME"); alpha = alphaEwald; nx = pmeGridDimension[0]; ny = pmeGridDimension[1]; nz = pmeGridDimension[2]; } /* -------------------------------------------------------------------------- * * AmoebaGeneralizedKirkwood * * -------------------------------------------------------------------------- */ ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel::ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel(std::string name, const Platform& platform, const System& system) : CalcAmoebaGeneralizedKirkwoodForceKernel(name, platform), system(system) { } ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel::~ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel() { } int ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel::getNumParticles() const { return numParticles; } int ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel::getIncludeCavityTerm() const { return includeCavityTerm; } int ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel::getDirectPolarization() const { return directPolarization; } RealOpenMM ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel::getSoluteDielectric() const { return soluteDielectric; } RealOpenMM ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel::getSolventDielectric() const { return solventDielectric; } RealOpenMM ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel::getDielectricOffset() const { return dielectricOffset; } RealOpenMM ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel::getProbeRadius() const { return probeRadius; } RealOpenMM ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel::getSurfaceAreaFactor() const { return surfaceAreaFactor; } void ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel::getAtomicRadii(vector& outputAtomicRadii) const { outputAtomicRadii.resize(atomicRadii.size()); copy(atomicRadii.begin(), atomicRadii.end(), outputAtomicRadii.begin()); } void ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel::getScaleFactors(vector& outputScaleFactors) const { outputScaleFactors.resize(scaleFactors.size()); copy(scaleFactors.begin(), scaleFactors.end(), outputScaleFactors.begin()); } void ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel::getCharges(vector& outputCharges) const { outputCharges.resize(charges.size()); copy(charges.begin(), charges.end(), outputCharges.begin()); } void ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel::initialize(const System& system, const AmoebaGeneralizedKirkwoodForce& force) { // check that AmoebaMultipoleForce is present const AmoebaMultipoleForce* amoebaMultipoleForce = NULL; for (int ii = 0; ii < system.getNumForces() && amoebaMultipoleForce == NULL; ii++) { amoebaMultipoleForce = dynamic_cast(&system.getForce(ii)); } if (amoebaMultipoleForce == NULL) { throw OpenMMException("AmoebaGeneralizedKirkwoodForce requires the System to also contain an AmoebaMultipoleForce."); } if (amoebaMultipoleForce->getNonbondedMethod() != AmoebaMultipoleForce::NoCutoff) { throw OpenMMException("AmoebaGeneralizedKirkwoodForce requires the AmoebaMultipoleForce use the NoCutoff nonbonded method."); } numParticles = system.getNumParticles(); for (int ii = 0; ii < numParticles; ii++) { double particleCharge, particleRadius, scalingFactor; force.getParticleParameters(ii, particleCharge, particleRadius, scalingFactor); atomicRadii.push_back(static_cast(particleRadius)); scaleFactors.push_back(static_cast(scalingFactor)); charges.push_back(static_cast(particleCharge)); // Make sure the charge matches the one specified by the AmoebaMultipoleForce. double charge2, thole, damping, polarity; int axisType, atomX, atomY, atomZ; vector dipole, quadrupole; amoebaMultipoleForce->getMultipoleParameters(ii, charge2, dipole, quadrupole, axisType, atomZ, atomX, atomY, thole, damping, polarity); if (particleCharge != charge2) { throw OpenMMException("AmoebaGeneralizedKirkwoodForce and AmoebaMultipoleForce must specify the same charge for every atom."); } } includeCavityTerm = force.getIncludeCavityTerm(); soluteDielectric = static_cast(force.getSoluteDielectric()); solventDielectric = static_cast(force.getSolventDielectric()); dielectricOffset = static_cast(0.009); probeRadius = static_cast(force.getProbeRadius()), surfaceAreaFactor = static_cast(force.getSurfaceAreaFactor()); directPolarization = amoebaMultipoleForce->getPolarizationType() == AmoebaMultipoleForce::Direct ? 1 : 0; } double ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) { // handled in AmoebaReferenceGeneralizedKirkwoodMultipoleForce, a derived class of the class AmoebaReferenceMultipoleForce return 0.0; } void ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel::copyParametersToContext(ContextImpl& context, const AmoebaGeneralizedKirkwoodForce& force) { if (numParticles != force.getNumParticles()) throw OpenMMException("updateParametersInContext: The number of particles has changed"); // Record the values. for (int i = 0; i < numParticles; ++i) { double particleCharge, particleRadius, scalingFactor; force.getParticleParameters(i, particleCharge, particleRadius, scalingFactor); atomicRadii[i] = particleRadius; scaleFactors[i] = scalingFactor; charges[i] = particleCharge; } } ReferenceCalcAmoebaVdwForceKernel::ReferenceCalcAmoebaVdwForceKernel(std::string name, const Platform& platform, const System& system) : CalcAmoebaVdwForceKernel(name, platform), system(system) { useCutoff = 0; usePBC = 0; cutoff = 1.0e+10; neighborList = NULL; } ReferenceCalcAmoebaVdwForceKernel::~ReferenceCalcAmoebaVdwForceKernel() { if (neighborList) { delete neighborList; } } void ReferenceCalcAmoebaVdwForceKernel::initialize(const System& system, const AmoebaVdwForce& force) { // per-particle parameters numParticles = system.getNumParticles(); indexIVs.resize(numParticles); allExclusions.resize(numParticles); sigmas.resize(numParticles); epsilons.resize(numParticles); reductions.resize(numParticles); for (int ii = 0; ii < numParticles; ii++) { int indexIV; double sigma, epsilon, reduction; std::vector exclusions; force.getParticleParameters(ii, indexIV, sigma, epsilon, reduction); force.getParticleExclusions(ii, exclusions); for (unsigned int jj = 0; jj < exclusions.size(); jj++) { allExclusions[ii].insert(exclusions[jj]); } indexIVs[ii] = indexIV; sigmas[ii] = static_cast(sigma); epsilons[ii] = static_cast(epsilon); reductions[ii] = static_cast(reduction); } sigmaCombiningRule = force.getSigmaCombiningRule(); epsilonCombiningRule = force.getEpsilonCombiningRule(); useCutoff = (force.getNonbondedMethod() != AmoebaVdwForce::NoCutoff); usePBC = (force.getNonbondedMethod() == AmoebaVdwForce::CutoffPeriodic); cutoff = force.getCutoff(); neighborList = useCutoff ? new NeighborList() : NULL; dispersionCoefficient = force.getUseDispersionCorrection() ? AmoebaVdwForceImpl::calcDispersionCorrection(system, force) : 0.0; } double ReferenceCalcAmoebaVdwForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) { vector& posData = extractPositions(context); vector& forceData = extractForces(context); AmoebaReferenceVdwForce vdwForce(sigmaCombiningRule, epsilonCombiningRule); RealOpenMM energy; if (useCutoff) { vdwForce.setCutoff(cutoff); computeNeighborListVoxelHash(*neighborList, numParticles, posData, allExclusions, extractBoxVectors(context), usePBC, cutoff, 0.0); if (usePBC) { vdwForce.setNonbondedMethod(AmoebaReferenceVdwForce::CutoffPeriodic); RealVec* boxVectors = extractBoxVectors(context); double minAllowedSize = 1.999999*cutoff; if (boxVectors[0][0] < minAllowedSize || boxVectors[1][1] < minAllowedSize || boxVectors[2][2] < minAllowedSize) { throw OpenMMException("The periodic box size has decreased to less than twice the cutoff."); } vdwForce.setPeriodicBox(boxVectors); energy = vdwForce.calculateForceAndEnergy(numParticles, posData, indexIVs, sigmas, epsilons, reductions, *neighborList, forceData); energy += dispersionCoefficient/(boxVectors[0][0]*boxVectors[1][1]*boxVectors[2][2]); } else { vdwForce.setNonbondedMethod(AmoebaReferenceVdwForce::CutoffNonPeriodic); } } else { vdwForce.setNonbondedMethod(AmoebaReferenceVdwForce::NoCutoff); energy = vdwForce.calculateForceAndEnergy(numParticles, posData, indexIVs, sigmas, epsilons, reductions, allExclusions, forceData); } return static_cast(energy); } void ReferenceCalcAmoebaVdwForceKernel::copyParametersToContext(ContextImpl& context, const AmoebaVdwForce& force) { if (numParticles != force.getNumParticles()) throw OpenMMException("updateParametersInContext: The number of particles has changed"); // Record the values. for (int i = 0; i < numParticles; ++i) { int indexIV; double sigma, epsilon, reduction; force.getParticleParameters(i, indexIV, sigma, epsilon, reduction); indexIVs[i] = indexIV; sigmas[i] = (RealOpenMM) sigma; epsilons[i] = (RealOpenMM) epsilon; reductions[i]= (RealOpenMM) reduction; } } /* -------------------------------------------------------------------------- * * AmoebaWcaDispersion * * -------------------------------------------------------------------------- */ ReferenceCalcAmoebaWcaDispersionForceKernel::ReferenceCalcAmoebaWcaDispersionForceKernel(std::string name, const Platform& platform, const System& system) : CalcAmoebaWcaDispersionForceKernel(name, platform), system(system) { } ReferenceCalcAmoebaWcaDispersionForceKernel::~ReferenceCalcAmoebaWcaDispersionForceKernel() { } void ReferenceCalcAmoebaWcaDispersionForceKernel::initialize(const System& system, const AmoebaWcaDispersionForce& force) { // per-particle parameters numParticles = system.getNumParticles(); radii.resize(numParticles); epsilons.resize(numParticles); for (int ii = 0; ii < numParticles; ii++) { double radius, epsilon; force.getParticleParameters(ii, radius, epsilon); radii[ii] = static_cast(radius); epsilons[ii] = static_cast(epsilon); } totalMaximumDispersionEnergy = static_cast(AmoebaWcaDispersionForceImpl::getTotalMaximumDispersionEnergy(force)); epso = static_cast(force.getEpso()); epsh = static_cast(force.getEpsh()); rmino = static_cast(force.getRmino()); rminh = static_cast(force.getRminh()); awater = static_cast(force.getAwater()); shctd = static_cast(force.getShctd()); dispoff = static_cast(force.getDispoff()); slevy = static_cast(force.getSlevy()); } double ReferenceCalcAmoebaWcaDispersionForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) { vector& posData = extractPositions(context); vector& forceData = extractForces(context); AmoebaReferenceWcaDispersionForce amoebaReferenceWcaDispersionForce(epso, epsh, rmino, rminh, awater, shctd, dispoff, slevy); RealOpenMM energy = amoebaReferenceWcaDispersionForce.calculateForceAndEnergy(numParticles, posData, radii, epsilons, totalMaximumDispersionEnergy, forceData); return static_cast(energy); } void ReferenceCalcAmoebaWcaDispersionForceKernel::copyParametersToContext(ContextImpl& context, const AmoebaWcaDispersionForce& force) { if (numParticles != force.getNumParticles()) throw OpenMMException("updateParametersInContext: The number of particles has changed"); // Record the values. for (int i = 0; i < numParticles; ++i) { double radius, epsilon; force.getParticleParameters(i, radius, epsilon); radii[i] = (RealOpenMM) radius; epsilons[i] = (RealOpenMM) epsilon; } totalMaximumDispersionEnergy = (RealOpenMM) AmoebaWcaDispersionForceImpl::getTotalMaximumDispersionEnergy(force); }