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

Radius of gyration force (#5031)

* Reference implementation of RGForce

* GPU implementation of RGForce

* Serialization

* Documentation

* Fix compilation error

* Fixed error building API docs
parent 6e2f213f
......@@ -1148,6 +1148,33 @@ private:
std::vector<int> particles;
};
/**
* This kernel is invoked by RGForce to calculate the forces acting on the system and the energy of the system.
*/
class ReferenceCalcRGForceKernel : public CalcRGForceKernel {
public:
ReferenceCalcRGForceKernel(std::string name, const Platform& platform) : CalcRGForceKernel(name, platform) {
}
/**
* Initialize the kernel.
*
* @param system the System this kernel will be applied to
* @param force the RGForce this kernel will be used for
*/
void initialize(const System& system, const RGForce& force);
/**
* Execute the kernel to calculate the forces and/or energy.
*
* @param context the context in which to execute this kernel
* @param includeForces true if forces should be calculated
* @param includeEnergy true if the energy should be calculated
* @return the potential energy due to the force
*/
double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
private:
std::vector<int> particles;
};
/**
* This kernel is invoked by VerletIntegrator to take one time step.
*/
......
/* Portions copyright (c) 2025 Stanford University and Simbios.
* Contributors: Peter Eastman
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ReferenceRGForce_H__
#define __ReferenceRGForce_H__
#include "openmm/RGForce.h"
#include <vector>
namespace OpenMM {
class ReferenceRGForce {
private:
std::vector<int> particles;
public:
/**
* Constructor
*/
ReferenceRGForce(std::vector<int>& particles);
/**
* Calculate the interaction.
*
* @param atomCoordinates atom coordinates
* @param forces the forces are added to this
* @return the energy of the interaction
*/
double calculateIxn(std::vector<OpenMM::Vec3>& atomCoordinates, std::vector<OpenMM::Vec3>& forces) const;
};
} // namespace OpenMM
#endif // __ReferenceRGForce_H__
......@@ -84,6 +84,8 @@ KernelImpl* ReferenceKernelFactory::createKernelImpl(std::string name, const Pla
return new ReferenceCalcATMForceKernel(name, platform);
if (name == CalcCustomCPPForceKernel::Name())
return new ReferenceCalcCustomCPPForceKernel(name, platform);
if (name == CalcRGForceKernel::Name())
return new ReferenceCalcRGForceKernel(name, platform);
if (name == CalcRMSDForceKernel::Name())
return new ReferenceCalcRMSDForceKernel(name, platform);
if (name == CalcCustomManyParticleForceKernel::Name())
......
......@@ -62,6 +62,7 @@
#include "ReferenceProperDihedralBond.h"
#include "ReferenceQTBDynamics.h"
#include "ReferenceRbDihedralBond.h"
#include "ReferenceRGForce.h"
#include "ReferenceRMSDForce.h"
#include "ReferenceTabulatedFunction.h"
#include "ReferenceVariableStochasticDynamics.h"
......@@ -2308,6 +2309,20 @@ void ReferenceCalcRMSDForceKernel::copyParametersToContext(ContextImpl& context,
p -= center;
}
void ReferenceCalcRGForceKernel::initialize(const System& system, const RGForce& force) {
particles = force.getParticles();
if (particles.size() == 0)
for (int i = 0; i < system.getNumParticles(); i++)
particles.push_back(i);
}
double ReferenceCalcRGForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) {
vector<Vec3>& posData = extractPositions(context);
vector<Vec3>& forceData = extractForces(context);
ReferenceRGForce rg(particles);
return rg.calculateIxn(posData, forceData);
}
ReferenceIntegrateVerletStepKernel::~ReferenceIntegrateVerletStepKernel() {
if (dynamics)
delete dynamics;
......
......@@ -65,6 +65,7 @@ ReferencePlatform::ReferencePlatform() {
registerKernelFactory(CalcCustomCPPForceKernel::Name(), factory);
registerKernelFactory(CalcCustomCVForceKernel::Name(), factory);
registerKernelFactory(CalcATMForceKernel::Name(), factory);
registerKernelFactory(CalcRGForceKernel::Name(), factory);
registerKernelFactory(CalcRMSDForceKernel::Name(), factory);
registerKernelFactory(CalcCustomManyParticleForceKernel::Name(), factory);
registerKernelFactory(CalcGayBerneForceKernel::Name(), factory);
......
/* Portions copyright (c) 2025 Stanford University and Simbios.
* Contributors: Peter Eastman
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "ReferenceRGForce.h"
#include <cmath>
using namespace OpenMM;
using namespace std;
ReferenceRGForce::ReferenceRGForce(vector<int>& particles) : particles(particles) {
}
double ReferenceRGForce::calculateIxn(vector<Vec3>& atomCoordinates, vector<Vec3>& forces) const {
// Compute the center position.
int numParticles = particles.size();
Vec3 center;
for (int i : particles)
center += atomCoordinates[i];
center /= numParticles;
// Compute the radius of gyration.
double sum = 0.0;
for (int i = 0; i < numParticles; i++) {
Vec3 delta = atomCoordinates[particles[i]]-center;
sum += delta.dot(delta);
}
double rg = sqrt(sum/numParticles);
// Compute the forces.
double scale = 1.0/(rg*numParticles);
for (int i = 0; i < numParticles; i++) {
Vec3 delta = atomCoordinates[particles[i]]-center;
forces[particles[i]] -= scale*delta;
}
return rg;
}
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* 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) 2025 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "ReferenceTests.h"
#include "TestRGForce.h"
void runPlatformTests() {
}
#ifndef OPENMM_RGFORCE_PROXY_H_
#define OPENMM_RGFORCE_PROXY_H_
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* 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) 2025 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/internal/windowsExport.h"
#include "openmm/serialization/SerializationProxy.h"
namespace OpenMM {
/**
* This is a proxy for serializing RGForce objects.
*/
class OPENMM_EXPORT RGForceProxy : public SerializationProxy {
public:
RGForceProxy();
void serialize(const void* object, SerializationNode& node) const;
void* deserialize(const SerializationNode& node) const;
};
} // namespace OpenMM
#endif /*OPENMM_RGFORCE_PROXY_H_*/
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* 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) 2025 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/serialization/RGForceProxy.h"
#include "openmm/serialization/SerializationNode.h"
#include "openmm/Force.h"
#include "openmm/RGForce.h"
#include <sstream>
using namespace OpenMM;
using namespace std;
RGForceProxy::RGForceProxy() : SerializationProxy("RGForce") {
}
void RGForceProxy::serialize(const void* object, SerializationNode& node) const {
node.setIntProperty("version", 0);
const RGForce& force = *reinterpret_cast<const RGForce*>(object);
node.setIntProperty("forceGroup", force.getForceGroup());
node.setStringProperty("name", force.getName());
SerializationNode& particlesNode = node.createChildNode("Particles");
for (int i : force.getParticles())
particlesNode.createChildNode("Particle").setIntProperty("index", i);
}
void* RGForceProxy::deserialize(const SerializationNode& node) const {
int version = node.getIntProperty("version");
if (version != 0)
throw OpenMMException("Unsupported version number");
RGForce* force = NULL;
try {
vector<int> particles;
for (auto& particle : node.getChildNode("Particles").getChildren())
particles.push_back(particle.getIntProperty("index"));
force = new RGForce(particles);
force->setForceGroup(node.getIntProperty("forceGroup", 0));
force->setName(node.getStringProperty("name", force->getName()));
return force;
}
catch (...) {
if (force != NULL)
delete force;
throw;
}
}
......@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010-2021 Stanford University and the Authors. *
* Portions copyright (c) 2010-2025 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -64,6 +64,7 @@
#include "openmm/PeriodicTorsionForce.h"
#include "openmm/QTBIntegrator.h"
#include "openmm/RBTorsionForce.h"
#include "openmm/RGForce.h"
#include "openmm/RMSDForce.h"
#include "openmm/System.h"
#include "openmm/TabulatedFunction.h"
......@@ -107,6 +108,7 @@
#include "openmm/serialization/PeriodicTorsionForceProxy.h"
#include "openmm/serialization/QTBIntegratorProxy.h"
#include "openmm/serialization/RBTorsionForceProxy.h"
#include "openmm/serialization/RGForceProxy.h"
#include "openmm/serialization/RMSDForceProxy.h"
#include "openmm/serialization/StateProxy.h"
#include "openmm/serialization/SystemProxy.h"
......@@ -169,8 +171,9 @@ extern "C" void registerSerializationProxies() {
SerializationProxy::registerProxy(typeid(NonbondedForce), new NonbondedForceProxy());
SerializationProxy::registerProxy(typeid(NoseHooverIntegrator), new NoseHooverIntegratorProxy());
SerializationProxy::registerProxy(typeid(PeriodicTorsionForce), new PeriodicTorsionForceProxy());
SerializationProxy::registerProxy(typeid(RBTorsionForce), new RBTorsionForceProxy());
SerializationProxy::registerProxy(typeid(QTBIntegrator), new QTBIntegratorProxy());
SerializationProxy::registerProxy(typeid(RBTorsionForce), new RBTorsionForceProxy());
SerializationProxy::registerProxy(typeid(RGForce), new RGForceProxy());
SerializationProxy::registerProxy(typeid(RMSDForce), new RMSDForceProxy());
SerializationProxy::registerProxy(typeid(System), new SystemProxy());
SerializationProxy::registerProxy(typeid(State), new StateProxy());
......
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* 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) 2025 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/RGForce.h"
#include "openmm/serialization/XmlSerializer.h"
#include <iostream>
#include <sstream>
using namespace OpenMM;
using namespace std;
void testSerialization() {
// Create a Force.
vector<int> particles;
for (int i = 0; i < 5; i++)
particles.push_back(i*i);
RGForce force(particles);
force.setForceGroup(3);
force.setName("custom name");
// Serialize and then deserialize it.
stringstream buffer;
XmlSerializer::serialize<RGForce>(&force, "Force", buffer);
RGForce* copy = XmlSerializer::deserialize<RGForce>(buffer);
// Compare the two forces to see if they are identical.
RGForce& force2 = *copy;
ASSERT_EQUAL(force.getForceGroup(), force2.getForceGroup());
ASSERT_EQUAL(force.getName(), force2.getName());
ASSERT_EQUAL(force.getParticles().size(), force2.getParticles().size());
for (int i = 0; i < force.getParticles().size(); i++)
ASSERT_EQUAL(force.getParticles()[i], force2.getParticles()[i]);
}
int main() {
try {
testSerialization();
}
catch(const exception& e) {
cout << "exception: " << e.what() << endl;
return 1;
}
cout << "Done" << endl;
return 0;
}
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* 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) 2025 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/RGForce.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "sfmt/SFMT.h"
#include <cmath>
#include <iostream>
#include <vector>
using namespace OpenMM;
using namespace std;
void testRG(bool allParticles) {
const int numParticles = 30;
System system;
vector<Vec3> positions(numParticles);
vector<int> particles;
OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt);
for (int i = 0; i < numParticles; ++i) {
system.addParticle(1.0);
if (genrand_real2(sfmt) < 0.5 || allParticles)
particles.push_back(i);
}
if (allParticles)
system.addForce(new RGForce()); // Omitting the list of particles should mean all particles.
else
system.addForce(new RGForce(particles));
VerletIntegrator integrator(0.001);
Context context(system, integrator, platform);
for (int i = 0; i < 10; i++) {
// Set all particles to random positions.
for (int j = 0; j < numParticles; j++)
positions[j] = Vec3(genrand_real2(sfmt), genrand_real2(sfmt), genrand_real2(sfmt))*5;
context.setPositions(positions);
// Compute Rg.
Vec3 center;
for (int j : particles)
center += positions[j];
center /= particles.size();
double sum = 0;
for (int j : particles) {
Vec3 v = positions[j]-center;
sum += v.dot(v);
}
double rg = sqrt(sum/particles.size());
// Compare to the value computed by the force.
State state = context.getState(State::Energy | State::Forces);
ASSERT_EQUAL_TOL(rg, state.getPotentialEnergy(), 1e-6);
// Take a small step in the direction of the energy gradient and see whether the potential energy changes by the expected amount.
const vector<Vec3>& forces = state.getForces();
double norm = 0.0;
for (int j = 0; j < (int) forces.size(); ++j)
norm += forces[j].dot(forces[j]);
norm = sqrt(norm);
const double stepSize = 0.1;
double step = 0.5*stepSize/norm;
vector<Vec3> positions2(numParticles), positions3(numParticles);
for (int j = 0; j < positions.size(); ++j) {
Vec3 p = positions[j];
Vec3 f = forces[j];
positions2[j] = Vec3(p[0]-f[0]*step, p[1]-f[1]*step, p[2]-f[2]*step);
positions3[j] = Vec3(p[0]+f[0]*step, p[1]+f[1]*step, p[2]+f[2]*step);
}
context.setPositions(positions2);
State state2 = context.getState(State::Energy);
context.setPositions(positions3);
State state3 = context.getState(State::Energy);
ASSERT_EQUAL_TOL(norm, (state2.getPotentialEnergy()-state3.getPotentialEnergy())/stepSize, 1e-4);
}
}
void testEnergyConservation() {
const int numParticles = 50;
System system;
vector<Vec3> positions(numParticles);
vector<int> particles;
OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt);
NonbondedForce* nb = new NonbondedForce(); // Add a nonbonded force to activate reordering on the GPU
nb->setNonbondedMethod(NonbondedForce::CutoffNonPeriodic);
system.addForce(nb);
for (int i = 0; i < numParticles; ++i) {
system.addParticle(2.0);
nb->addParticle(0.0, 0.1, 0.01);
positions[i] = Vec3(genrand_real2(sfmt), genrand_real2(sfmt), genrand_real2(sfmt))*5;
if (genrand_real2(sfmt) < 0.5)
particles.push_back(i);
}
system.addForce(new RGForce(particles));
VerletIntegrator integrator(0.001);
Context context(system, integrator, platform);
context.setPositions(positions);
context.setVelocitiesToTemperature(300.0, 0);
integrator.step(5);
State initialState = context.getState(State::Energy);
double energy = initialState.getPotentialEnergy()+initialState.getKineticEnergy();
for (int i = 0; i < 100; i++) {
integrator.step(5);
State state = context.getState(State::Energy);
ASSERT_EQUAL_TOL(energy, state.getPotentialEnergy()+state.getKineticEnergy(), 1e-4);
}
}
void runPlatformTests();
int main(int argc, char* argv[]) {
try {
initializeTests(argc, argv);
testRG(true);
testRG(false);
testEnergyConservation();
runPlatformTests();
}
catch(const exception& e) {
cout << "exception: " << e.what() << endl;
return 1;
}
cout << "Done" << endl;
return 0;
}
......@@ -491,6 +491,7 @@ UNITS = {
("RMSDForce", "getReferencePositions") : ("unit.nanometer", ()),
("RMSDForce", "setReferencePositions") : (None, ("unit.nanometer",)),
("RMSDForce", "getParticles") : (None, ()),
("RGForce", "getParticles") : (None, ()),
("NoseHooverChain", "NoseHooverChain") : (None, ("unit.kelvin", "unit.kelvin", "unit.picosecond**-1", "unit.picosecond**-1", None, None, None, None, None, None, None)),
("NoseHooverChain", "getThermostatedPairs") : (None, ()),
("NoseHooverChain", "getThermostatedAtoms") : (None, ()),
......
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