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

Optimize updateParametersInContext() (#4610)

* Optimize CustomNonbondedForce.updateParametersInContext()

* Optimized uploading changed values to GPU

* Optimized updateParametersInContext() for lots of bonded forces

* Optimized updateParametersInContext() for CustomExternalForce

* Optimized updateParametersInContext() for NonbondedForce

* Code changes for HIP platform
parent 66064fac
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2011-2021 Stanford University and the Authors. * * Portions copyright (c) 2011-2024 Stanford University and the Authors. *
* Portions copyright (c) 2020-2021 Advanced Micro Devices, Inc. * * Portions copyright (c) 2020-2021 Advanced Micro Devices, Inc. *
* Authors: Peter Eastman, Nicholas Curtis * * Authors: Peter Eastman, Nicholas Curtis *
* Contributors: * * Contributors: *
...@@ -316,9 +316,9 @@ double HipParallelCalcHarmonicBondForceKernel::execute(ContextImpl& context, boo ...@@ -316,9 +316,9 @@ double HipParallelCalcHarmonicBondForceKernel::execute(ContextImpl& context, boo
return 0.0; return 0.0;
} }
void HipParallelCalcHarmonicBondForceKernel::copyParametersToContext(ContextImpl& context, const HarmonicBondForce& force) { void HipParallelCalcHarmonicBondForceKernel::copyParametersToContext(ContextImpl& context, const HarmonicBondForce& force, int firstBond, int lastBond) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstBond, lastBond);
} }
class HipParallelCalcCustomBondForceKernel::Task : public HipContext::WorkTask { class HipParallelCalcCustomBondForceKernel::Task : public HipContext::WorkTask {
...@@ -357,9 +357,9 @@ double HipParallelCalcCustomBondForceKernel::execute(ContextImpl& context, bool ...@@ -357,9 +357,9 @@ double HipParallelCalcCustomBondForceKernel::execute(ContextImpl& context, bool
return 0.0; return 0.0;
} }
void HipParallelCalcCustomBondForceKernel::copyParametersToContext(ContextImpl& context, const CustomBondForce& force) { void HipParallelCalcCustomBondForceKernel::copyParametersToContext(ContextImpl& context, const CustomBondForce& force, int firstBond, int lastBond) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstBond, lastBond);
} }
class HipParallelCalcHarmonicAngleForceKernel::Task : public HipContext::WorkTask { class HipParallelCalcHarmonicAngleForceKernel::Task : public HipContext::WorkTask {
...@@ -398,9 +398,9 @@ double HipParallelCalcHarmonicAngleForceKernel::execute(ContextImpl& context, bo ...@@ -398,9 +398,9 @@ double HipParallelCalcHarmonicAngleForceKernel::execute(ContextImpl& context, bo
return 0.0; return 0.0;
} }
void HipParallelCalcHarmonicAngleForceKernel::copyParametersToContext(ContextImpl& context, const HarmonicAngleForce& force) { void HipParallelCalcHarmonicAngleForceKernel::copyParametersToContext(ContextImpl& context, const HarmonicAngleForce& force, int firstAngle, int lastAngle) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstAngle, lastAngle);
} }
class HipParallelCalcCustomAngleForceKernel::Task : public HipContext::WorkTask { class HipParallelCalcCustomAngleForceKernel::Task : public HipContext::WorkTask {
...@@ -439,9 +439,9 @@ double HipParallelCalcCustomAngleForceKernel::execute(ContextImpl& context, bool ...@@ -439,9 +439,9 @@ double HipParallelCalcCustomAngleForceKernel::execute(ContextImpl& context, bool
return 0.0; return 0.0;
} }
void HipParallelCalcCustomAngleForceKernel::copyParametersToContext(ContextImpl& context, const CustomAngleForce& force) { void HipParallelCalcCustomAngleForceKernel::copyParametersToContext(ContextImpl& context, const CustomAngleForce& force, int firstAngle, int lastAngle) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstAngle, lastAngle);
} }
class HipParallelCalcPeriodicTorsionForceKernel::Task : public HipContext::WorkTask { class HipParallelCalcPeriodicTorsionForceKernel::Task : public HipContext::WorkTask {
...@@ -480,9 +480,9 @@ double HipParallelCalcPeriodicTorsionForceKernel::execute(ContextImpl& context, ...@@ -480,9 +480,9 @@ double HipParallelCalcPeriodicTorsionForceKernel::execute(ContextImpl& context,
return 0.0; return 0.0;
} }
void HipParallelCalcPeriodicTorsionForceKernel::copyParametersToContext(ContextImpl& context, const PeriodicTorsionForce& force) { void HipParallelCalcPeriodicTorsionForceKernel::copyParametersToContext(ContextImpl& context, const PeriodicTorsionForce& force, int firstTorsion, int lastTorsion) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstTorsion, lastTorsion);
} }
class HipParallelCalcRBTorsionForceKernel::Task : public HipContext::WorkTask { class HipParallelCalcRBTorsionForceKernel::Task : public HipContext::WorkTask {
...@@ -603,9 +603,9 @@ double HipParallelCalcCustomTorsionForceKernel::execute(ContextImpl& context, bo ...@@ -603,9 +603,9 @@ double HipParallelCalcCustomTorsionForceKernel::execute(ContextImpl& context, bo
return 0.0; return 0.0;
} }
void HipParallelCalcCustomTorsionForceKernel::copyParametersToContext(ContextImpl& context, const CustomTorsionForce& force) { void HipParallelCalcCustomTorsionForceKernel::copyParametersToContext(ContextImpl& context, const CustomTorsionForce& force, int firstTorsion, int lastTorsion) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstTorsion, lastTorsion);
} }
class HipParallelCalcNonbondedForceKernel::Task : public HipContext::WorkTask { class HipParallelCalcNonbondedForceKernel::Task : public HipContext::WorkTask {
...@@ -644,9 +644,9 @@ double HipParallelCalcNonbondedForceKernel::execute(ContextImpl& context, bool i ...@@ -644,9 +644,9 @@ double HipParallelCalcNonbondedForceKernel::execute(ContextImpl& context, bool i
return 0.0; return 0.0;
} }
void HipParallelCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const NonbondedForce& force) { void HipParallelCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const NonbondedForce& force, int firstParticle, int lastParticle, int firstException, int lastException) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstParticle, lastParticle, firstException, lastException);
} }
void HipParallelCalcNonbondedForceKernel::getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const { void HipParallelCalcNonbondedForceKernel::getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const {
...@@ -693,9 +693,9 @@ double HipParallelCalcCustomNonbondedForceKernel::execute(ContextImpl& context, ...@@ -693,9 +693,9 @@ double HipParallelCalcCustomNonbondedForceKernel::execute(ContextImpl& context,
return 0.0; return 0.0;
} }
void HipParallelCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const CustomNonbondedForce& force) { void HipParallelCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const CustomNonbondedForce& force, int firstParticle, int lastParticle) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstParticle, lastParticle);
} }
class HipParallelCalcCustomExternalForceKernel::Task : public HipContext::WorkTask { class HipParallelCalcCustomExternalForceKernel::Task : public HipContext::WorkTask {
...@@ -734,9 +734,9 @@ double HipParallelCalcCustomExternalForceKernel::execute(ContextImpl& context, b ...@@ -734,9 +734,9 @@ double HipParallelCalcCustomExternalForceKernel::execute(ContextImpl& context, b
return 0.0; return 0.0;
} }
void HipParallelCalcCustomExternalForceKernel::copyParametersToContext(ContextImpl& context, const CustomExternalForce& force) { void HipParallelCalcCustomExternalForceKernel::copyParametersToContext(ContextImpl& context, const CustomExternalForce& force, int firstParticle, int lastParticle) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstParticle, lastParticle);
} }
class HipParallelCalcCustomHbondForceKernel::Task : public HipContext::WorkTask { class HipParallelCalcCustomHbondForceKernel::Task : public HipContext::WorkTask {
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2022 Stanford University and the Authors. * * Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -114,8 +114,12 @@ public: ...@@ -114,8 +114,12 @@ public:
* *
* @param context the context to copy parameters to * @param context the context to copy parameters to
* @param force the NonbondedForce to copy the parameters from * @param force the NonbondedForce to copy the parameters from
* @param firstParticle the index of the first particle whose parameters might have changed
* @param lastParticle the index of the last particle whose parameters might have changed
* @param firstException the index of the first exception whose parameters might have changed
* @param lastException the index of the last exception whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const NonbondedForce& force); void copyParametersToContext(ContextImpl& context, const NonbondedForce& force, int firstParticle, int lastParticle, int firstException, int lastException);
/** /**
* Get the parameters being used for PME. * Get the parameters being used for PME.
* *
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2011-2019 Stanford University and the Authors. * * Portions copyright (c) 2011-2024 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -120,10 +120,10 @@ public: ...@@ -120,10 +120,10 @@ public:
/** /**
* Copy changed parameters over to a context. * Copy changed parameters over to a context.
* *
* @param context the context to copy parameters to * @param firstBond the index of the first bond whose parameters might have changed
* @param force the HarmonicBondForce to copy the parameters from * @param lastBond the index of the last bond whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const HarmonicBondForce& force); void copyParametersToContext(ContextImpl& context, const HarmonicBondForce& force, int firstBond, int lastBond);
private: private:
class Task; class Task;
OpenCLPlatform::PlatformData& data; OpenCLPlatform::PlatformData& data;
...@@ -158,10 +158,10 @@ public: ...@@ -158,10 +158,10 @@ public:
/** /**
* Copy changed parameters over to a context. * Copy changed parameters over to a context.
* *
* @param context the context to copy parameters to * @param firstBond the index of the first bond whose parameters might have changed
* @param force the CustomBondForce to copy the parameters from * @param lastBond the index of the last bond whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const CustomBondForce& force); void copyParametersToContext(ContextImpl& context, const CustomBondForce& force, int firstBond, int lastBond);
private: private:
class Task; class Task;
OpenCLPlatform::PlatformData& data; OpenCLPlatform::PlatformData& data;
...@@ -196,10 +196,10 @@ public: ...@@ -196,10 +196,10 @@ public:
/** /**
* Copy changed parameters over to a context. * Copy changed parameters over to a context.
* *
* @param context the context to copy parameters to * @param firstAngle the index of the first bond whose parameters might have changed
* @param force the HarmonicAngleForce to copy the parameters from * @param lastAngle the index of the last bond whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const HarmonicAngleForce& force); void copyParametersToContext(ContextImpl& context, const HarmonicAngleForce& force, int firstAngle, int lastAngle);
private: private:
class Task; class Task;
OpenCLPlatform::PlatformData& data; OpenCLPlatform::PlatformData& data;
...@@ -234,10 +234,10 @@ public: ...@@ -234,10 +234,10 @@ public:
/** /**
* Copy changed parameters over to a context. * Copy changed parameters over to a context.
* *
* @param context the context to copy parameters to * @param firstAngle the index of the first bond whose parameters might have changed
* @param force the CustomAngleForce to copy the parameters from * @param lastAngle the index of the last bond whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const CustomAngleForce& force); void copyParametersToContext(ContextImpl& context, const CustomAngleForce& force, int firstAngle, int lastAngle);
private: private:
class Task; class Task;
OpenCLPlatform::PlatformData& data; OpenCLPlatform::PlatformData& data;
...@@ -275,8 +275,10 @@ public: ...@@ -275,8 +275,10 @@ public:
* *
* @param context the context to copy parameters to * @param context the context to copy parameters to
* @param force the PeriodicTorsionForce to copy the parameters from * @param force the PeriodicTorsionForce to copy the parameters from
* @param firstTorsion the index of the first torsion whose parameters might have changed
* @param lastTorsion the index of the last torsion whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const PeriodicTorsionForce& force); void copyParametersToContext(ContextImpl& context, const PeriodicTorsionForce& force, int firstTorsion, int lastTorsion);
private: private:
OpenCLPlatform::PlatformData& data; OpenCLPlatform::PlatformData& data;
std::vector<Kernel> kernels; std::vector<Kernel> kernels;
...@@ -388,8 +390,10 @@ public: ...@@ -388,8 +390,10 @@ public:
* *
* @param context the context to copy parameters to * @param context the context to copy parameters to
* @param force the CustomTorsionForce to copy the parameters from * @param force the CustomTorsionForce to copy the parameters from
* @param firstTorsion the index of the first torsion whose parameters might have changed
* @param lastTorsion the index of the last torsion whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const CustomTorsionForce& force); void copyParametersToContext(ContextImpl& context, const CustomTorsionForce& force, int firstTorsion, int lastTorsion);
private: private:
class Task; class Task;
OpenCLPlatform::PlatformData& data; OpenCLPlatform::PlatformData& data;
...@@ -428,8 +432,12 @@ public: ...@@ -428,8 +432,12 @@ public:
* *
* @param context the context to copy parameters to * @param context the context to copy parameters to
* @param force the NonbondedForce to copy the parameters from * @param force the NonbondedForce to copy the parameters from
* @param firstParticle the index of the first particle whose parameters might have changed
* @param lastParticle the index of the last particle whose parameters might have changed
* @param firstException the index of the first exception whose parameters might have changed
* @param lastException the index of the last exception whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const NonbondedForce& force); void copyParametersToContext(ContextImpl& context, const NonbondedForce& force, int firstParticle, int lastParticle, int firstException, int lastException);
/** /**
* Get the parameters being used for PME. * Get the parameters being used for PME.
* *
...@@ -484,8 +492,10 @@ public: ...@@ -484,8 +492,10 @@ public:
* *
* @param context the context to copy parameters to * @param context the context to copy parameters to
* @param force the CustomNonbondedForce to copy the parameters from * @param force the CustomNonbondedForce to copy the parameters from
* @param firstParticle the index of the first particle whose parameters might have changed
* @param lastParticle the index of the last particle whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const CustomNonbondedForce& force); void copyParametersToContext(ContextImpl& context, const CustomNonbondedForce& force, int firstParticle, int lastParticle);
private: private:
class Task; class Task;
OpenCLPlatform::PlatformData& data; OpenCLPlatform::PlatformData& data;
...@@ -522,8 +532,10 @@ public: ...@@ -522,8 +532,10 @@ public:
* *
* @param context the context to copy parameters to * @param context the context to copy parameters to
* @param force the CustomExternalForce to copy the parameters from * @param force the CustomExternalForce to copy the parameters from
* @param firstParticle the index of the first particle whose parameters might have changed
* @param lastParticle the index of the last particle whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const CustomExternalForce& force); void copyParametersToContext(ContextImpl& context, const CustomExternalForce& force, int firstParticle, int lastParticle);
private: private:
class Task; class Task;
OpenCLPlatform::PlatformData& data; OpenCLPlatform::PlatformData& data;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2022 Stanford University and the Authors. * * Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -1071,7 +1071,7 @@ double OpenCLCalcNonbondedForceKernel::execute(ContextImpl& context, bool includ ...@@ -1071,7 +1071,7 @@ double OpenCLCalcNonbondedForceKernel::execute(ContextImpl& context, bool includ
return energy; return energy;
} }
void OpenCLCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const NonbondedForce& force) { void OpenCLCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const NonbondedForce& force, int firstParticle, int lastParticle, int firstException, int lastException) {
// Make sure the new parameters are acceptable. // Make sure the new parameters are acceptable.
if (force.getNumParticles() != cl.getNumAtoms()) if (force.getNumParticles() != cl.getNumAtoms())
...@@ -1111,17 +1111,32 @@ void OpenCLCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& contex ...@@ -1111,17 +1111,32 @@ void OpenCLCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& contex
// Record the per-particle parameters. // Record the per-particle parameters.
if (firstParticle <= lastParticle) {
vector<mm_float4> baseParticleParamVec(cl.getPaddedNumAtoms(), mm_float4(0, 0, 0, 0)); vector<mm_float4> baseParticleParamVec(cl.getPaddedNumAtoms(), mm_float4(0, 0, 0, 0));
for (int i = 0; i < force.getNumParticles(); i++) { for (int i = 0; i < force.getNumParticles(); i++) {
double charge, sigma, epsilon; double charge, sigma, epsilon;
force.getParticleParameters(i, charge, sigma, epsilon); force.getParticleParameters(i, charge, sigma, epsilon);
baseParticleParamVec[i] = mm_float4(charge, sigma, epsilon, 0); baseParticleParamVec[i] = mm_float4(charge, sigma, epsilon, 0);
} }
baseParticleParams.upload(baseParticleParamVec); baseParticleParams.uploadSubArray(&baseParticleParamVec[firstParticle], firstParticle, lastParticle-firstParticle+1);
// Compute the self energy.
ewaldSelfEnergy = 0.0;
if (nonbondedMethod == Ewald || nonbondedMethod == PME || nonbondedMethod == LJPME) {
if (cl.getContextIndex() == 0) {
for (int i = 0; i < force.getNumParticles(); i++) {
ewaldSelfEnergy -= baseParticleParamVec[i].x*baseParticleParamVec[i].x*ONE_4PI_EPS0*alpha/sqrt(M_PI);
if (doLJPME)
ewaldSelfEnergy += baseParticleParamVec[i].z*pow(baseParticleParamVec[i].y*dispersionAlpha, 6)/3.0;
}
}
}
}
// Record the exceptions. // Record the exceptions.
if (numExceptions > 0) { if (firstException <= lastException) {
vector<mm_float4> baseExceptionParamsVec(numExceptions); vector<mm_float4> baseExceptionParamsVec(numExceptions);
for (int i = 0; i < numExceptions; i++) { for (int i = 0; i < numExceptions; i++) {
int particle1, particle2; int particle1, particle2;
...@@ -1136,19 +1151,9 @@ void OpenCLCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& contex ...@@ -1136,19 +1151,9 @@ void OpenCLCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& contex
// Compute other values. // Compute other values.
ewaldSelfEnergy = 0.0;
if (nonbondedMethod == Ewald || nonbondedMethod == PME || nonbondedMethod == LJPME) {
if (cl.getContextIndex() == 0) {
for (int i = 0; i < force.getNumParticles(); i++) {
ewaldSelfEnergy -= baseParticleParamVec[i].x*baseParticleParamVec[i].x*ONE_4PI_EPS0*alpha/sqrt(M_PI);
if (doLJPME)
ewaldSelfEnergy += baseParticleParamVec[i].z*pow(baseParticleParamVec[i].y*dispersionAlpha, 6)/3.0;
}
}
}
if (force.getUseDispersionCorrection() && cl.getContextIndex() == 0 && (nonbondedMethod == CutoffPeriodic || nonbondedMethod == Ewald || nonbondedMethod == PME)) if (force.getUseDispersionCorrection() && cl.getContextIndex() == 0 && (nonbondedMethod == CutoffPeriodic || nonbondedMethod == Ewald || nonbondedMethod == PME))
dispersionCoefficient = NonbondedForceImpl::calcDispersionCorrection(context.getSystem(), force); dispersionCoefficient = NonbondedForceImpl::calcDispersionCorrection(context.getSystem(), force);
cl.invalidateMolecules(info); cl.invalidateMolecules(info, firstParticle <= lastParticle, firstException <= lastException);
recomputeParams = true; recomputeParams = true;
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2011-2023 Stanford University and the Authors. * * Portions copyright (c) 2011-2024 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -247,9 +247,9 @@ double OpenCLParallelCalcHarmonicBondForceKernel::execute(ContextImpl& context, ...@@ -247,9 +247,9 @@ double OpenCLParallelCalcHarmonicBondForceKernel::execute(ContextImpl& context,
return 0.0; return 0.0;
} }
void OpenCLParallelCalcHarmonicBondForceKernel::copyParametersToContext(ContextImpl& context, const HarmonicBondForce& force) { void OpenCLParallelCalcHarmonicBondForceKernel::copyParametersToContext(ContextImpl& context, const HarmonicBondForce& force, int firstBond, int lastBond) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstBond, lastBond);
} }
class OpenCLParallelCalcCustomBondForceKernel::Task : public OpenCLContext::WorkTask { class OpenCLParallelCalcCustomBondForceKernel::Task : public OpenCLContext::WorkTask {
...@@ -288,9 +288,9 @@ double OpenCLParallelCalcCustomBondForceKernel::execute(ContextImpl& context, bo ...@@ -288,9 +288,9 @@ double OpenCLParallelCalcCustomBondForceKernel::execute(ContextImpl& context, bo
return 0.0; return 0.0;
} }
void OpenCLParallelCalcCustomBondForceKernel::copyParametersToContext(ContextImpl& context, const CustomBondForce& force) { void OpenCLParallelCalcCustomBondForceKernel::copyParametersToContext(ContextImpl& context, const CustomBondForce& force, int firstBond, int lastBond) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstBond, lastBond);
} }
class OpenCLParallelCalcHarmonicAngleForceKernel::Task : public OpenCLContext::WorkTask { class OpenCLParallelCalcHarmonicAngleForceKernel::Task : public OpenCLContext::WorkTask {
...@@ -329,9 +329,9 @@ double OpenCLParallelCalcHarmonicAngleForceKernel::execute(ContextImpl& context, ...@@ -329,9 +329,9 @@ double OpenCLParallelCalcHarmonicAngleForceKernel::execute(ContextImpl& context,
return 0.0; return 0.0;
} }
void OpenCLParallelCalcHarmonicAngleForceKernel::copyParametersToContext(ContextImpl& context, const HarmonicAngleForce& force) { void OpenCLParallelCalcHarmonicAngleForceKernel::copyParametersToContext(ContextImpl& context, const HarmonicAngleForce& force, int firstAngle, int lastAngle) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstAngle, lastAngle);
} }
class OpenCLParallelCalcCustomAngleForceKernel::Task : public OpenCLContext::WorkTask { class OpenCLParallelCalcCustomAngleForceKernel::Task : public OpenCLContext::WorkTask {
...@@ -370,9 +370,9 @@ double OpenCLParallelCalcCustomAngleForceKernel::execute(ContextImpl& context, b ...@@ -370,9 +370,9 @@ double OpenCLParallelCalcCustomAngleForceKernel::execute(ContextImpl& context, b
return 0.0; return 0.0;
} }
void OpenCLParallelCalcCustomAngleForceKernel::copyParametersToContext(ContextImpl& context, const CustomAngleForce& force) { void OpenCLParallelCalcCustomAngleForceKernel::copyParametersToContext(ContextImpl& context, const CustomAngleForce& force, int firstAngle, int lastAngle) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstAngle, lastAngle);
} }
class OpenCLParallelCalcPeriodicTorsionForceKernel::Task : public OpenCLContext::WorkTask { class OpenCLParallelCalcPeriodicTorsionForceKernel::Task : public OpenCLContext::WorkTask {
...@@ -411,9 +411,9 @@ double OpenCLParallelCalcPeriodicTorsionForceKernel::execute(ContextImpl& contex ...@@ -411,9 +411,9 @@ double OpenCLParallelCalcPeriodicTorsionForceKernel::execute(ContextImpl& contex
return 0.0; return 0.0;
} }
void OpenCLParallelCalcPeriodicTorsionForceKernel::copyParametersToContext(ContextImpl& context, const PeriodicTorsionForce& force) { void OpenCLParallelCalcPeriodicTorsionForceKernel::copyParametersToContext(ContextImpl& context, const PeriodicTorsionForce& force, int firstTorsion, int lastTorsion) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstTorsion, lastTorsion);
} }
class OpenCLParallelCalcRBTorsionForceKernel::Task : public OpenCLContext::WorkTask { class OpenCLParallelCalcRBTorsionForceKernel::Task : public OpenCLContext::WorkTask {
...@@ -534,9 +534,9 @@ double OpenCLParallelCalcCustomTorsionForceKernel::execute(ContextImpl& context, ...@@ -534,9 +534,9 @@ double OpenCLParallelCalcCustomTorsionForceKernel::execute(ContextImpl& context,
return 0.0; return 0.0;
} }
void OpenCLParallelCalcCustomTorsionForceKernel::copyParametersToContext(ContextImpl& context, const CustomTorsionForce& force) { void OpenCLParallelCalcCustomTorsionForceKernel::copyParametersToContext(ContextImpl& context, const CustomTorsionForce& force, int firstTorsion, int lastTorsion) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstTorsion, lastTorsion);
} }
class OpenCLParallelCalcNonbondedForceKernel::Task : public OpenCLContext::WorkTask { class OpenCLParallelCalcNonbondedForceKernel::Task : public OpenCLContext::WorkTask {
...@@ -575,9 +575,9 @@ double OpenCLParallelCalcNonbondedForceKernel::execute(ContextImpl& context, boo ...@@ -575,9 +575,9 @@ double OpenCLParallelCalcNonbondedForceKernel::execute(ContextImpl& context, boo
return 0.0; return 0.0;
} }
void OpenCLParallelCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const NonbondedForce& force) { void OpenCLParallelCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const NonbondedForce& force, int firstParticle, int lastParticle, int firstException, int lastException) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstParticle, lastParticle, firstException, lastException);
} }
void OpenCLParallelCalcNonbondedForceKernel::getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const { void OpenCLParallelCalcNonbondedForceKernel::getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const {
...@@ -624,9 +624,9 @@ double OpenCLParallelCalcCustomNonbondedForceKernel::execute(ContextImpl& contex ...@@ -624,9 +624,9 @@ double OpenCLParallelCalcCustomNonbondedForceKernel::execute(ContextImpl& contex
return 0.0; return 0.0;
} }
void OpenCLParallelCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const CustomNonbondedForce& force) { void OpenCLParallelCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const CustomNonbondedForce& force, int firstParticle, int lastParticle) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstParticle, lastParticle);
} }
class OpenCLParallelCalcCustomExternalForceKernel::Task : public OpenCLContext::WorkTask { class OpenCLParallelCalcCustomExternalForceKernel::Task : public OpenCLContext::WorkTask {
...@@ -665,9 +665,9 @@ double OpenCLParallelCalcCustomExternalForceKernel::execute(ContextImpl& context ...@@ -665,9 +665,9 @@ double OpenCLParallelCalcCustomExternalForceKernel::execute(ContextImpl& context
return 0.0; return 0.0;
} }
void OpenCLParallelCalcCustomExternalForceKernel::copyParametersToContext(ContextImpl& context, const CustomExternalForce& force) { void OpenCLParallelCalcCustomExternalForceKernel::copyParametersToContext(ContextImpl& context, const CustomExternalForce& force, int firstParticle, int lastParticle) {
for (int i = 0; i < (int) kernels.size(); i++) for (int i = 0; i < (int) kernels.size(); i++)
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force, firstParticle, lastParticle);
} }
class OpenCLParallelCalcCustomHbondForceKernel::Task : public OpenCLContext::WorkTask { class OpenCLParallelCalcCustomHbondForceKernel::Task : public OpenCLContext::WorkTask {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2015 Stanford University and the Authors. * * Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -37,10 +37,11 @@ void testParallelComputation() { ...@@ -37,10 +37,11 @@ void testParallelComputation() {
const int numParticles = 200; const int numParticles = 200;
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
system.addParticle(1.0); system.addParticle(1.0);
CustomAngleForce* force = new CustomAngleForce("(theta-1.1)^2"); CustomAngleForce* force = new CustomAngleForce("k*(theta-theta0)^2");
vector<double> params; force->addPerAngleParameter("k");
force->addPerAngleParameter("theta0");
for (int i = 2; i < numParticles; i++) for (int i = 2; i < numParticles; i++)
force->addAngle(i-2, i-1, i, params); force->addAngle(i-2, i-1, i, {1.0, 1.1});
system.addForce(force); system.addForce(force);
vector<Vec3> positions(numParticles); vector<Vec3> positions(numParticles);
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
...@@ -63,6 +64,21 @@ void testParallelComputation() { ...@@ -63,6 +64,21 @@ void testParallelComputation() {
ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5); ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5);
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5); ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5);
// Try updating some parameters and see if they still match.
vector<double> params;
for (int i = 95; i < 102; i++) {
int p1, p2, p3;
force->getAngleParameters(i, p1, p2, p3, params);
force->setAngleParameters(i, p1, p2, p3, {2.0, 1.2});
}
force->updateParametersInContext(context1);
force->updateParametersInContext(context2);
State state3 = context1.getState(State::Energy);
State state4 = context2.getState(State::Energy);
ASSERT_EQUAL_TOL(state3.getPotentialEnergy(), state4.getPotentialEnergy(), 1e-5);
ASSERT(fabs(state1.getPotentialEnergy()-state3.getPotentialEnergy()) > 0.1);
} }
void runPlatformTests() { void runPlatformTests() {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2015 Stanford University and the Authors. * * Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -37,10 +37,11 @@ void testParallelComputation() { ...@@ -37,10 +37,11 @@ void testParallelComputation() {
const int numParticles = 200; const int numParticles = 200;
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
system.addParticle(1.0); system.addParticle(1.0);
CustomBondForce* force = new CustomBondForce(("(r-1.1)^2")); CustomBondForce* force = new CustomBondForce(("k*(r-r0)^2"));
vector<double> params; force->addPerBondParameter("k");
force->addPerBondParameter("r0");
for (int i = 1; i < numParticles; i++) for (int i = 1; i < numParticles; i++)
force->addBond(i-1, i, params); force->addBond(i-1, i, {1.0, 1.1});
system.addForce(force); system.addForce(force);
vector<Vec3> positions(numParticles); vector<Vec3> positions(numParticles);
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
...@@ -63,6 +64,21 @@ void testParallelComputation() { ...@@ -63,6 +64,21 @@ void testParallelComputation() {
ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5); ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5);
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5); ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5);
// Try updating some parameters and see if they still match.
vector<double> params;
for (int i = 95; i < 102; i++) {
int p1, p2;
force->getBondParameters(i, p1, p2, params);
force->setBondParameters(i, p1, p2, {2.0, 1.2});
}
force->updateParametersInContext(context1);
force->updateParametersInContext(context2);
State state3 = context1.getState(State::Energy);
State state4 = context2.getState(State::Energy);
ASSERT_EQUAL_TOL(state3.getPotentialEnergy(), state4.getPotentialEnergy(), 1e-5);
ASSERT(fabs(state1.getPotentialEnergy()-state3.getPotentialEnergy()) > 0.1);
} }
void runPlatformTests() { void runPlatformTests() {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2015 Stanford University and the Authors. * * Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -37,10 +37,11 @@ void testParallelComputation() { ...@@ -37,10 +37,11 @@ void testParallelComputation() {
const int numParticles = 200; const int numParticles = 200;
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
system.addParticle(1.0); system.addParticle(1.0);
CustomNonbondedForce* force = new CustomNonbondedForce("4*eps*((sigma/r)^12-(sigma/r)^6); sigma=0.5; eps=1"); CustomNonbondedForce* force = new CustomNonbondedForce("4*eps*((sigma/r)^12-(sigma/r)^6); sigma=0.5*(sigma1+sigma2); eps=sqrt(eps1*eps2)");
vector<double> params; force->addPerParticleParameter("sigma");
force->addPerParticleParameter("eps");
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
force->addParticle(params); force->addParticle({0.5, 1.0});
system.addForce(force); system.addForce(force);
OpenMM_SFMT::SFMT sfmt; OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt); init_gen_rand(0, sfmt);
...@@ -71,6 +72,18 @@ void testParallelComputation() { ...@@ -71,6 +72,18 @@ void testParallelComputation() {
ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5); ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5);
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5); ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5);
// Try updating some parameters and see if they still match.
vector<double> params;
for (int i = 95; i < 102; i++)
force->setParticleParameters(i, {0.6, 2.0});
force->updateParametersInContext(context1);
force->updateParametersInContext(context2);
State state3 = context1.getState(State::Energy);
State state4 = context2.getState(State::Energy);
ASSERT_EQUAL_TOL(state3.getPotentialEnergy(), state4.getPotentialEnergy(), 1e-5);
ASSERT(fabs(state1.getPotentialEnergy()-state3.getPotentialEnergy()) > 0.1);
} }
void runPlatformTests() { void runPlatformTests() {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2015 Stanford University and the Authors. * * Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -37,10 +37,11 @@ void testParallelComputation() { ...@@ -37,10 +37,11 @@ void testParallelComputation() {
const int numParticles = 200; const int numParticles = 200;
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
system.addParticle(1.0); system.addParticle(1.0);
CustomTorsionForce* force = new CustomTorsionForce("sin(theta-1.1)"); CustomTorsionForce* force = new CustomTorsionForce("k*sin(theta-theta0)");
vector<double> params; force->addPerTorsionParameter("k");
force->addPerTorsionParameter("theta0");
for (int i = 3; i < numParticles; i++) for (int i = 3; i < numParticles; i++)
force->addTorsion(i-3, i-2, i-1, i, params); force->addTorsion(i-3, i-2, i-1, i, {1.0, 1.1});
system.addForce(force); system.addForce(force);
vector<Vec3> positions(numParticles); vector<Vec3> positions(numParticles);
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
...@@ -63,6 +64,21 @@ void testParallelComputation() { ...@@ -63,6 +64,21 @@ void testParallelComputation() {
ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5); ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5);
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5); ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5);
// Try updating some parameters and see if they still match.
vector<double> params;
for (int i = 95; i < 102; i++) {
int p1, p2, p3, p4;
force->getTorsionParameters(i, p1, p2, p3, p4, params);
force->setTorsionParameters(i, p1, p2, p3, p4, {2.0, 1.2});
}
force->updateParametersInContext(context1);
force->updateParametersInContext(context2);
State state3 = context1.getState(State::Energy);
State state4 = context2.getState(State::Energy);
ASSERT_EQUAL_TOL(state3.getPotentialEnergy(), state4.getPotentialEnergy(), 1e-5);
ASSERT(fabs(state1.getPotentialEnergy()-state3.getPotentialEnergy()) > 0.1);
} }
void runPlatformTests() { void runPlatformTests() {
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2015 Stanford University and the Authors. * * Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -64,6 +64,21 @@ void testParallelComputation() { ...@@ -64,6 +64,21 @@ void testParallelComputation() {
ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5); ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5);
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5); ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5);
// Try updating some parameters and see if they still match.
for (int i = 95; i < 102; i++) {
int p1, p2, p3;
double angle, k;
force->getAngleParameters(i, p1, p2, p3, angle, k);
force->setAngleParameters(i, p1, p2, p3, angle+0.1, 2*k);
}
force->updateParametersInContext(context1);
force->updateParametersInContext(context2);
State state3 = context1.getState(State::Energy);
State state4 = context2.getState(State::Energy);
ASSERT_EQUAL_TOL(state3.getPotentialEnergy(), state4.getPotentialEnergy(), 1e-5);
ASSERT(fabs(state1.getPotentialEnergy()-state3.getPotentialEnergy()) > 0.1);
} }
void runPlatformTests() { void runPlatformTests() {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2015 Stanford University and the Authors. * * Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -63,6 +63,21 @@ void testParallelComputation() { ...@@ -63,6 +63,21 @@ void testParallelComputation() {
ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5); ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5);
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5); ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5);
// Try updating some parameters and see if they still match.
for (int i = 95; i < 102; i++) {
int p1, p2;
double length, k;
force->getBondParameters(i, p1, p2, length, k);
force->setBondParameters(i, p1, p2, length+0.1, 2*k);
}
force->updateParametersInContext(context1);
force->updateParametersInContext(context2);
State state3 = context1.getState(State::Energy);
State state4 = context2.getState(State::Energy);
ASSERT_EQUAL_TOL(state3.getPotentialEnergy(), state4.getPotentialEnergy(), 1e-5);
ASSERT(fabs(state1.getPotentialEnergy()-state3.getPotentialEnergy()) > 0.1);
} }
void runPlatformTests() { void runPlatformTests() {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2021 Stanford University and the Authors. * * Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -90,13 +90,20 @@ void testParallelComputation(NonbondedForce::NonbondedMethod method) { ...@@ -90,13 +90,20 @@ void testParallelComputation(NonbondedForce::NonbondedMethod method) {
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5); ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5);
// Modify some particle parameters and see if they still agree. // Modify some parameters and see if they still agree.
for (int i = 0; i < numParticles; i += 5) { for (int i = 0; i < numParticles; i += 5) {
double charge, sigma, epsilon; double charge, sigma, epsilon;
force->getParticleParameters(i, charge, sigma, epsilon); force->getParticleParameters(i, charge, sigma, epsilon);
force->setParticleParameters(i, 0.9*charge, sigma, epsilon); force->setParticleParameters(i, 0.9*charge, sigma, epsilon);
} }
for (int i = force->getNumExceptions()/2-10; i < force->getNumExceptions()/2+10; i++) {
int p1, p2;
double charge, sigma, epsilon;
force->getExceptionParameters(i, p1, p2, charge, sigma, epsilon);
if (epsilon != 0)
force->setExceptionParameters(i, p1, p2, charge, sigma, 2*epsilon);
}
force->updateParametersInContext(context1); force->updateParametersInContext(context1);
force->updateParametersInContext(context2); force->updateParametersInContext(context2);
state1 = context1.getState(State::Forces | State::Energy); state1 = context1.getState(State::Forces | State::Energy);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2015 Stanford University and the Authors. * * Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -62,6 +62,21 @@ void testParallelComputation() { ...@@ -62,6 +62,21 @@ void testParallelComputation() {
ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5); ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5);
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5); ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5);
// Try updating some parameters and see if they still match.
for (int i = 95; i < 102; i++) {
int p1, p2, p3, p4, periodicity;
double phase, k;
force->getTorsionParameters(i, p1, p2, p3, p4, periodicity, phase, k);
force->setTorsionParameters(i, p1, p2, p3, p4, periodicity, phase+0.1, 2*k);
}
force->updateParametersInContext(context1);
force->updateParametersInContext(context2);
State state3 = context1.getState(State::Energy);
State state4 = context2.getState(State::Energy);
ASSERT_EQUAL_TOL(state3.getPotentialEnergy(), state4.getPotentialEnergy(), 1e-5);
ASSERT(fabs(state1.getPotentialEnergy()-state3.getPotentialEnergy()) > 0.1);
} }
void runPlatformTests() { void runPlatformTests() {
......
...@@ -312,8 +312,10 @@ public: ...@@ -312,8 +312,10 @@ public:
* *
* @param context the context to copy parameters to * @param context the context to copy parameters to
* @param force the HarmonicBondForce to copy the parameters from * @param force the HarmonicBondForce to copy the parameters from
* @param firstBond the index of the first bond whose parameters might have changed
* @param lastBond the index of the last bond whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const HarmonicBondForce& force); void copyParametersToContext(ContextImpl& context, const HarmonicBondForce& force, int firstBond, int lastBond);
private: private:
int numBonds; int numBonds;
std::vector<std::vector<int> >bondIndexArray; std::vector<std::vector<int> >bondIndexArray;
...@@ -348,10 +350,10 @@ public: ...@@ -348,10 +350,10 @@ public:
/** /**
* Copy changed parameters over to a context. * Copy changed parameters over to a context.
* *
* @param context the context to copy parameters to * @param firstBond the index of the first bond whose parameters might have changed
* @param force the CustomBondForce to copy the parameters from * @param lastBond the index of the last bond whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const CustomBondForce& force); void copyParametersToContext(ContextImpl& context, const CustomBondForce& force, int firstBond, int lastBond);
private: private:
int numBonds; int numBonds;
ReferenceCustomBondIxn* ixn; ReferenceCustomBondIxn* ixn;
...@@ -389,10 +391,10 @@ public: ...@@ -389,10 +391,10 @@ public:
/** /**
* Copy changed parameters over to a context. * Copy changed parameters over to a context.
* *
* @param context the context to copy parameters to * @param firstAngle the index of the first bond whose parameters might have changed
* @param force the HarmonicAngleForce to copy the parameters from * @param lastAngle the index of the last bond whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const HarmonicAngleForce& force); void copyParametersToContext(ContextImpl& context, const HarmonicAngleForce& force, int firstAngle, int lastAngle);
private: private:
int numAngles; int numAngles;
std::vector<std::vector<int> >angleIndexArray; std::vector<std::vector<int> >angleIndexArray;
...@@ -427,10 +429,10 @@ public: ...@@ -427,10 +429,10 @@ public:
/** /**
* Copy changed parameters over to a context. * Copy changed parameters over to a context.
* *
* @param context the context to copy parameters to * @param firstAngle the index of the first bond whose parameters might have changed
* @param force the CustomAngleForce to copy the parameters from * @param lastAngle the index of the last bond whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const CustomAngleForce& force); void copyParametersToContext(ContextImpl& context, const CustomAngleForce& force, int firstAngle, int lastAngle);
private: private:
int numAngles; int numAngles;
ReferenceCustomAngleIxn* ixn; ReferenceCustomAngleIxn* ixn;
...@@ -470,8 +472,10 @@ public: ...@@ -470,8 +472,10 @@ public:
* *
* @param context the context to copy parameters to * @param context the context to copy parameters to
* @param force the PeriodicTorsionForce to copy the parameters from * @param force the PeriodicTorsionForce to copy the parameters from
* @param firstTorsion the index of the first torsion whose parameters might have changed
* @param lastTorsion the index of the last torsion whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const PeriodicTorsionForce& force); void copyParametersToContext(ContextImpl& context, const PeriodicTorsionForce& force, int firstTorsion, int lastTorsion);
private: private:
int numTorsions; int numTorsions;
std::vector<std::vector<int> >torsionIndexArray; std::vector<std::vector<int> >torsionIndexArray;
...@@ -582,8 +586,10 @@ public: ...@@ -582,8 +586,10 @@ public:
* *
* @param context the context to copy parameters to * @param context the context to copy parameters to
* @param force the CustomTorsionForce to copy the parameters from * @param force the CustomTorsionForce to copy the parameters from
* @param firstTorsion the index of the first torsion whose parameters might have changed
* @param lastTorsion the index of the last torsion whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const CustomTorsionForce& force); void copyParametersToContext(ContextImpl& context, const CustomTorsionForce& force, int firstTorsion, int lastTorsion);
private: private:
int numTorsions; int numTorsions;
ReferenceCustomTorsionIxn* ixn; ReferenceCustomTorsionIxn* ixn;
...@@ -625,8 +631,12 @@ public: ...@@ -625,8 +631,12 @@ public:
* *
* @param context the context to copy parameters to * @param context the context to copy parameters to
* @param force the NonbondedForce to copy the parameters from * @param force the NonbondedForce to copy the parameters from
* @param firstParticle the index of the first particle whose parameters might have changed
* @param lastParticle the index of the last particle whose parameters might have changed
* @param firstException the index of the first exception whose parameters might have changed
* @param lastException the index of the last exception whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const NonbondedForce& force); void copyParametersToContext(ContextImpl& context, const NonbondedForce& force, int firstParticle, int lastParticle, int firstException, int lastException);
/** /**
* Get the parameters being used for PME. * Get the parameters being used for PME.
* *
...@@ -689,8 +699,10 @@ public: ...@@ -689,8 +699,10 @@ public:
* *
* @param context the context to copy parameters to * @param context the context to copy parameters to
* @param force the CustomNonbondedForce to copy the parameters from * @param force the CustomNonbondedForce to copy the parameters from
* @param firstParticle the index of the first particle whose parameters might have changed
* @param lastParticle the index of the last particle whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const CustomNonbondedForce& force); void copyParametersToContext(ContextImpl& context, const CustomNonbondedForce& force, int firstParticle, int lastParticle);
private: private:
void createExpressions(const CustomNonbondedForce& force); void createExpressions(const CustomNonbondedForce& force);
int numParticles; int numParticles;
...@@ -831,8 +843,10 @@ public: ...@@ -831,8 +843,10 @@ public:
* *
* @param context the context to copy parameters to * @param context the context to copy parameters to
* @param force the CustomExternalForce to copy the parameters from * @param force the CustomExternalForce to copy the parameters from
* @param firstParticle the index of the first particle whose parameters might have changed
* @param lastParticle the index of the last particle whose parameters might have changed
*/ */
void copyParametersToContext(ContextImpl& context, const CustomExternalForce& force); void copyParametersToContext(ContextImpl& context, const CustomExternalForce& force, int firstParticle, int lastParticle);
private: private:
int numParticles; int numParticles;
ReferenceCustomExternalIxn* ixn; ReferenceCustomExternalIxn* ixn;
......
...@@ -390,13 +390,13 @@ double ReferenceCalcHarmonicBondForceKernel::execute(ContextImpl& context, bool ...@@ -390,13 +390,13 @@ double ReferenceCalcHarmonicBondForceKernel::execute(ContextImpl& context, bool
return energy; return energy;
} }
void ReferenceCalcHarmonicBondForceKernel::copyParametersToContext(ContextImpl& context, const HarmonicBondForce& force) { void ReferenceCalcHarmonicBondForceKernel::copyParametersToContext(ContextImpl& context, const HarmonicBondForce& force, int firstBond, int lastBond) {
if (numBonds != force.getNumBonds()) if (numBonds != force.getNumBonds())
throw OpenMMException("updateParametersInContext: The number of bonds has changed"); throw OpenMMException("updateParametersInContext: The number of bonds has changed");
// Record the values. // Record the values.
for (int i = 0; i < numBonds; ++i) { for (int i = firstBond; i <= lastBond; ++i) {
int particle1, particle2; int particle1, particle2;
double length, k; double length, k;
force.getBondParameters(i, particle1, particle2, length, k); force.getBondParameters(i, particle1, particle2, length, k);
...@@ -474,7 +474,7 @@ double ReferenceCalcCustomBondForceKernel::execute(ContextImpl& context, bool in ...@@ -474,7 +474,7 @@ double ReferenceCalcCustomBondForceKernel::execute(ContextImpl& context, bool in
return energy; return energy;
} }
void ReferenceCalcCustomBondForceKernel::copyParametersToContext(ContextImpl& context, const CustomBondForce& force) { void ReferenceCalcCustomBondForceKernel::copyParametersToContext(ContextImpl& context, const CustomBondForce& force, int firstBond, int lastBond) {
if (numBonds != force.getNumBonds()) if (numBonds != force.getNumBonds())
throw OpenMMException("updateParametersInContext: The number of bonds has changed"); throw OpenMMException("updateParametersInContext: The number of bonds has changed");
...@@ -482,7 +482,7 @@ void ReferenceCalcCustomBondForceKernel::copyParametersToContext(ContextImpl& co ...@@ -482,7 +482,7 @@ void ReferenceCalcCustomBondForceKernel::copyParametersToContext(ContextImpl& co
int numParameters = force.getNumPerBondParameters(); int numParameters = force.getNumPerBondParameters();
vector<double> params; vector<double> params;
for (int i = 0; i < numBonds; ++i) { for (int i = firstBond; i <= lastBond; ++i) {
int particle1, particle2; int particle1, particle2;
force.getBondParameters(i, particle1, particle2, params); force.getBondParameters(i, particle1, particle2, params);
if (particle1 != bondIndexArray[i][0] || particle2 != bondIndexArray[i][1]) if (particle1 != bondIndexArray[i][0] || particle2 != bondIndexArray[i][1])
...@@ -521,13 +521,13 @@ double ReferenceCalcHarmonicAngleForceKernel::execute(ContextImpl& context, bool ...@@ -521,13 +521,13 @@ double ReferenceCalcHarmonicAngleForceKernel::execute(ContextImpl& context, bool
return energy; return energy;
} }
void ReferenceCalcHarmonicAngleForceKernel::copyParametersToContext(ContextImpl& context, const HarmonicAngleForce& force) { void ReferenceCalcHarmonicAngleForceKernel::copyParametersToContext(ContextImpl& context, const HarmonicAngleForce& force, int firstAngle, int lastAngle) {
if (numAngles != force.getNumAngles()) if (numAngles != force.getNumAngles())
throw OpenMMException("updateParametersInContext: The number of angles has changed"); throw OpenMMException("updateParametersInContext: The number of angles has changed");
// Record the values. // Record the values.
for (int i = 0; i < numAngles; ++i) { for (int i = firstAngle; i <= lastAngle; ++i) {
int particle1, particle2, particle3; int particle1, particle2, particle3;
double angle, k; double angle, k;
force.getAngleParameters(i, particle1, particle2, particle3, angle, k); force.getAngleParameters(i, particle1, particle2, particle3, angle, k);
...@@ -604,7 +604,7 @@ double ReferenceCalcCustomAngleForceKernel::execute(ContextImpl& context, bool i ...@@ -604,7 +604,7 @@ double ReferenceCalcCustomAngleForceKernel::execute(ContextImpl& context, bool i
return energy; return energy;
} }
void ReferenceCalcCustomAngleForceKernel::copyParametersToContext(ContextImpl& context, const CustomAngleForce& force) { void ReferenceCalcCustomAngleForceKernel::copyParametersToContext(ContextImpl& context, const CustomAngleForce& force, int firstAngle, int lastAngle) {
if (numAngles != force.getNumAngles()) if (numAngles != force.getNumAngles())
throw OpenMMException("updateParametersInContext: The number of angles has changed"); throw OpenMMException("updateParametersInContext: The number of angles has changed");
...@@ -612,7 +612,7 @@ void ReferenceCalcCustomAngleForceKernel::copyParametersToContext(ContextImpl& c ...@@ -612,7 +612,7 @@ void ReferenceCalcCustomAngleForceKernel::copyParametersToContext(ContextImpl& c
int numParameters = force.getNumPerAngleParameters(); int numParameters = force.getNumPerAngleParameters();
vector<double> params; vector<double> params;
for (int i = 0; i < numAngles; ++i) { for (int i = firstAngle; i <= lastAngle; ++i) {
int particle1, particle2, particle3; int particle1, particle2, particle3;
force.getAngleParameters(i, particle1, particle2, particle3, params); force.getAngleParameters(i, particle1, particle2, particle3, params);
if (particle1 != angleIndexArray[i][0] || particle2 != angleIndexArray[i][1] || particle3 != angleIndexArray[i][2]) if (particle1 != angleIndexArray[i][0] || particle2 != angleIndexArray[i][1] || particle3 != angleIndexArray[i][2])
...@@ -653,13 +653,13 @@ double ReferenceCalcPeriodicTorsionForceKernel::execute(ContextImpl& context, bo ...@@ -653,13 +653,13 @@ double ReferenceCalcPeriodicTorsionForceKernel::execute(ContextImpl& context, bo
return energy; return energy;
} }
void ReferenceCalcPeriodicTorsionForceKernel::copyParametersToContext(ContextImpl& context, const PeriodicTorsionForce& force) { void ReferenceCalcPeriodicTorsionForceKernel::copyParametersToContext(ContextImpl& context, const PeriodicTorsionForce& force, int firstTorsion, int lastTorsion) {
if (numTorsions != force.getNumTorsions()) if (numTorsions != force.getNumTorsions())
throw OpenMMException("updateParametersInContext: The number of torsions has changed"); throw OpenMMException("updateParametersInContext: The number of torsions has changed");
// Record the values. // Record the values.
for (int i = 0; i < numTorsions; ++i) { for (int i = firstTorsion; i <= lastTorsion; ++i) {
int particle1, particle2, particle3, particle4, periodicity; int particle1, particle2, particle3, particle4, periodicity;
double phase, k; double phase, k;
force.getTorsionParameters(i, particle1, particle2, particle3, particle4, periodicity, phase, k); force.getTorsionParameters(i, particle1, particle2, particle3, particle4, periodicity, phase, k);
...@@ -865,7 +865,7 @@ double ReferenceCalcCustomTorsionForceKernel::execute(ContextImpl& context, bool ...@@ -865,7 +865,7 @@ double ReferenceCalcCustomTorsionForceKernel::execute(ContextImpl& context, bool
return energy; return energy;
} }
void ReferenceCalcCustomTorsionForceKernel::copyParametersToContext(ContextImpl& context, const CustomTorsionForce& force) { void ReferenceCalcCustomTorsionForceKernel::copyParametersToContext(ContextImpl& context, const CustomTorsionForce& force, int firstTorsion, int lastTorsion) {
if (numTorsions != force.getNumTorsions()) if (numTorsions != force.getNumTorsions())
throw OpenMMException("updateParametersInContext: The number of torsions has changed"); throw OpenMMException("updateParametersInContext: The number of torsions has changed");
...@@ -873,7 +873,7 @@ void ReferenceCalcCustomTorsionForceKernel::copyParametersToContext(ContextImpl& ...@@ -873,7 +873,7 @@ void ReferenceCalcCustomTorsionForceKernel::copyParametersToContext(ContextImpl&
int numParameters = force.getNumPerTorsionParameters(); int numParameters = force.getNumPerTorsionParameters();
vector<double> params; vector<double> params;
for (int i = 0; i < numTorsions; ++i) { for (int i = firstTorsion; i <= lastTorsion; ++i) {
int particle1, particle2, particle3, particle4; int particle1, particle2, particle3, particle4;
force.getTorsionParameters(i, particle1, particle2, particle3, particle4, params); force.getTorsionParameters(i, particle1, particle2, particle3, particle4, params);
if (particle1 != torsionIndexArray[i][0] || particle2 != torsionIndexArray[i][1] || particle3 != torsionIndexArray[i][2] || particle4 != torsionIndexArray[i][3]) if (particle1 != torsionIndexArray[i][0] || particle2 != torsionIndexArray[i][1] || particle3 != torsionIndexArray[i][2] || particle4 != torsionIndexArray[i][3])
...@@ -1035,7 +1035,7 @@ double ReferenceCalcNonbondedForceKernel::execute(ContextImpl& context, bool inc ...@@ -1035,7 +1035,7 @@ double ReferenceCalcNonbondedForceKernel::execute(ContextImpl& context, bool inc
return energy; return energy;
} }
void ReferenceCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const NonbondedForce& force) { void ReferenceCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const NonbondedForce& force, int firstParticle, int lastParticle, int firstException, int lastException) {
if (force.getNumParticles() != numParticles) if (force.getNumParticles() != numParticles)
throw OpenMMException("updateParametersInContext: The number of particles has changed"); throw OpenMMException("updateParametersInContext: The number of particles has changed");
...@@ -1062,7 +1062,7 @@ void ReferenceCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& con ...@@ -1062,7 +1062,7 @@ void ReferenceCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& con
// Record the values. // Record the values.
for (int i = 0; i < numParticles; ++i) for (int i = firstParticle; i <= lastParticle; ++i)
force.getParticleParameters(i, baseParticleParams[i][0], baseParticleParams[i][1], baseParticleParams[i][2]); force.getParticleParameters(i, baseParticleParams[i][0], baseParticleParams[i][1], baseParticleParams[i][2]);
for (int i = 0; i < num14; ++i) { for (int i = 0; i < num14; ++i) {
int particle1, particle2; int particle1, particle2;
...@@ -1321,16 +1321,15 @@ double ReferenceCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bo ...@@ -1321,16 +1321,15 @@ double ReferenceCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bo
return energy; return energy;
} }
void ReferenceCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const CustomNonbondedForce& force) { void ReferenceCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const CustomNonbondedForce& force, int firstParticle, int lastParticle) {
if (numParticles != force.getNumParticles()) if (numParticles != force.getNumParticles())
throw OpenMMException("updateParametersInContext: The number of particles has changed"); throw OpenMMException("updateParametersInContext: The number of particles has changed");
// Record the values. // Record the values.
int numParameters = force.getNumPerParticleParameters(); int numParameters = force.getNumPerParticleParameters();
vector<double> params;
for (int i = 0; i < numParticles; ++i) {
vector<double> parameters; vector<double> parameters;
for (int i = firstParticle; i <= lastParticle; ++i) {
force.getParticleParameters(i, parameters); force.getParticleParameters(i, parameters);
for (int j = 0; j < numParameters; j++) for (int j = 0; j < numParameters; j++)
particleParamArray[i][j] = parameters[j]; particleParamArray[i][j] = parameters[j];
...@@ -1690,7 +1689,7 @@ double ReferenceCalcCustomExternalForceKernel::execute(ContextImpl& context, boo ...@@ -1690,7 +1689,7 @@ double ReferenceCalcCustomExternalForceKernel::execute(ContextImpl& context, boo
return energy; return energy;
} }
void ReferenceCalcCustomExternalForceKernel::copyParametersToContext(ContextImpl& context, const CustomExternalForce& force) { void ReferenceCalcCustomExternalForceKernel::copyParametersToContext(ContextImpl& context, const CustomExternalForce& force, int firstParticle, int lastParticle) {
if (numParticles != force.getNumParticles()) if (numParticles != force.getNumParticles())
throw OpenMMException("updateParametersInContext: The number of particles has changed"); throw OpenMMException("updateParametersInContext: The number of particles has changed");
...@@ -1698,14 +1697,13 @@ void ReferenceCalcCustomExternalForceKernel::copyParametersToContext(ContextImpl ...@@ -1698,14 +1697,13 @@ void ReferenceCalcCustomExternalForceKernel::copyParametersToContext(ContextImpl
int numParameters = force.getNumPerParticleParameters(); int numParameters = force.getNumPerParticleParameters();
vector<double> params; vector<double> params;
for (int i = 0; i < numParticles; ++i) { for (int i = firstParticle; i <= lastParticle; ++i) {
int particle; int particle;
vector<double> parameters; force.getParticleParameters(i, particle, params);
force.getParticleParameters(i, particle, parameters);
if (particle != particles[i]) if (particle != particles[i])
throw OpenMMException("updateParametersInContext: A particle index has changed"); throw OpenMMException("updateParametersInContext: A particle index has changed");
for (int j = 0; j < numParameters; j++) for (int j = 0; j < numParameters; j++)
particleParamArray[i][j] = parameters[j]; particleParamArray[i][j] = params[j];
} }
} }
......
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