Unverified Commit 7e72bafb authored by Zheng GONG's avatar Zheng GONG Committed by GitHub
Browse files

Merge pull request #3 from openmm/master

Update from upstream
parents 83b8ea75 f6431a42
/* Portions copyright (c) 2006-2013 Stanford University and Simbios.
* Contributors: Peter Eastman, Pande Group
*
* 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 <cstring>
#include <iostream>
#include <sstream>
#include "openmm/OpenMMException.h"
#include "SimTKOpenMMUtilities.h"
#include "openmm/internal/ContextImpl.h"
#include "ReferenceVelocityVerletDynamics.h"
#include "ReferenceVirtualSites.h"
#include <cstdio>
using std::vector;
using namespace OpenMM;
/**---------------------------------------------------------------------------------------
ReferenceVelocityVerletDynamics constructor
@param numberOfAtoms number of atoms
@param deltaT delta t for dynamics
@param friction friction coefficient
@param temperature temperature
--------------------------------------------------------------------------------------- */
ReferenceVelocityVerletDynamics::ReferenceVelocityVerletDynamics(int numberOfAtoms, double deltaT) :
ReferenceDynamics(numberOfAtoms, deltaT, 0.0) {
xPrime.resize(numberOfAtoms);
inverseMasses.resize(numberOfAtoms);
}
/**---------------------------------------------------------------------------------------
ReferenceVelocityVerletDynamics destructor
--------------------------------------------------------------------------------------- */
ReferenceVelocityVerletDynamics::~ReferenceVelocityVerletDynamics() {
}
/**---------------------------------------------------------------------------------------
Update -- driver routine for performing Velocity Verlet dynamics update of coordinates
and velocities
@param system the System to be integrated
@param atomCoordinates atom coordinates
@param velocities velocities
@param forces forces
@param masses atom masses
@param atomList list of all atoms not involved in a Drude-like pair
@param pairList list of all Drude-like pairs
@param maxPairDistance the maximum separation of any Drude-like pairs
--------------------------------------------------------------------------------------- */
void ReferenceVelocityVerletDynamics::update(OpenMM::ContextImpl &context, const OpenMM::System& system, vector<Vec3>& atomCoordinates,
vector<Vec3>& velocities,
vector<Vec3>& forces, vector<double>& masses, double tolerance, bool &forcesAreValid,
const std::vector<int> & atomList, const std::vector<std::tuple<int, int, double>> &pairList,
double maxPairDistance) {
// first-time-through initialization
if (!forcesAreValid) context.calcForcesAndEnergy(true, false);
int numberOfAtoms = system.getNumParticles();
if (getTimeStep() == 0) {
// invert masses
for (int ii = 0; ii < numberOfAtoms; ii++) {
if (masses[ii] == 0.0)
inverseMasses[ii] = 0.0;
else
inverseMasses[ii] = 1.0/masses[ii];
}
}
//// Perform the integration.
// Regular atoms
for (const auto &atom : atomList) {
if (masses[atom] != 0.0) {
velocities[atom] += 0.5 * inverseMasses[atom]*forces[atom]*getDeltaT();
xPrime[atom] = atomCoordinates[atom];
atomCoordinates[atom] += velocities[atom]*getDeltaT();
}
}
// Connected particles
for (const auto &pair : pairList) {
const auto &atom1 = std::get<0>(pair);
const auto &atom2 = std::get<1>(pair);
double m1 = system.getParticleMass(atom1);
double m2 = system.getParticleMass(atom2);
double mass1fract = m1 / (m1 + m2);
double mass2fract = m2 / (m1 + m2);
double invRedMass = (m1 * m2 != 0.0) ? (m1 + m2)/(m1 * m2) : 0.0;
double invTotMass = (m1 + m2 != 0.0) ? 1.0 /(m1 + m2) : 0.0;
Vec3 comVel = velocities[atom1]*mass1fract + velocities[atom2]*mass2fract;
Vec3 relVel = velocities[atom2] - velocities[atom1];
Vec3 comForce = forces[atom1] + forces[atom2];
Vec3 relForce = mass1fract*forces[atom2] - mass2fract*forces[atom1];
comVel += 0.5 * comForce * getDeltaT() * invTotMass;
relVel += 0.5 * relForce * getDeltaT() * invRedMass;
if (m1 != 0.0) {
velocities[atom1] = comVel - relVel*mass2fract;
xPrime[atom1] = atomCoordinates[atom1];
atomCoordinates[atom1] += velocities[atom1]*getDeltaT();
}
if (m2 != 0.0) {
velocities[atom2] = comVel + relVel*mass1fract;
xPrime[atom2] = atomCoordinates[atom2];
atomCoordinates[atom2] += velocities[atom2]*getDeltaT();
}
}
//
ReferenceConstraintAlgorithm* referenceConstraintAlgorithm = getReferenceConstraintAlgorithm();
if (referenceConstraintAlgorithm)
referenceConstraintAlgorithm->apply(xPrime, atomCoordinates, inverseMasses, tolerance);
// Apply hard wall constraints.
if (maxPairDistance > 0) {
for (const auto & pair : pairList) {
const int atom1 = std::get<0>(pair);
const int atom2 = std::get<1>(pair);
const double hardWallScale = sqrt(std::get<2>(pair)*BOLTZ);
Vec3 delta = atomCoordinates[atom1]-atomCoordinates[atom2];
double r = sqrt(delta.dot(delta));
double rInv = 1/r;
if (rInv*maxPairDistance < 1.0) {
// The constraint has been violated, so make the inter-particle distance "bounce"
// off the hard wall.
//if (rInv*maxPairDistance < 0.5)
// throw OpenMMException("Drude particle moved too far beyond hard wall constraint");
// TODO: Review this - I commented it out to make the NoseHooverThermostat test work
Vec3 bondDir = delta*rInv;
Vec3 vel1 = velocities[atom1];
Vec3 vel2 = velocities[atom2];
double m1 = masses[atom1];
double m2 = masses[atom2];
double invTotMass = (m1 + m2 != 0.0) ? 1.0 /(m1 + m2) : 0.0;
double deltaR = r-maxPairDistance;
double deltaT = getDeltaT();
double dt = getDeltaT();
double dotvr1 = vel1.dot(bondDir);
Vec3 vb1 = bondDir*dotvr1;
Vec3 vp1 = vel1-vb1;
if (m2 == 0) {
// The parent particle is massless, so move only the Drude particle.
if (dotvr1 != 0.0)
deltaT = deltaR/std::abs(dotvr1);
if (deltaT > getDeltaT())
deltaT = getDeltaT();
dotvr1 = -dotvr1*hardWallScale/(std::abs(dotvr1)*sqrt(m1));
double dr = -deltaR + deltaT*dotvr1;
atomCoordinates[atom1] += bondDir*dr;
velocities[atom1] = vp1 + bondDir*dotvr1;
}
else {
// Move both particles.
double dotvr2 = vel2.dot(bondDir);
Vec3 vb2 = bondDir*dotvr2;
Vec3 vp2 = vel2-vb2;
double vbCMass = (m1*dotvr1 + m2*dotvr2)*invTotMass;
dotvr1 -= vbCMass;
dotvr2 -= vbCMass;
if (dotvr1 != dotvr2)
deltaT = deltaR/std::abs(dotvr1-dotvr2);
if (deltaT > dt)
deltaT = dt;
double vBond = hardWallScale/sqrt(m1);
dotvr1 = -dotvr1*vBond*m2*invTotMass/std::abs(dotvr1);
dotvr2 = -dotvr2*vBond*m1*invTotMass/std::abs(dotvr2);
double dr1 = -deltaR*m2*invTotMass + deltaT*dotvr1;
double dr2 = deltaR*m1*invTotMass + deltaT*dotvr2;
dotvr1 += vbCMass;
dotvr2 += vbCMass;
atomCoordinates[atom1] += bondDir*dr1;
atomCoordinates[atom2] += bondDir*dr2;
velocities[atom1] = vp1 + bondDir*dotvr1;
velocities[atom2] = vp2 + bondDir*dotvr2;
}
}
}
} /* end of hard wall constraint part */
ReferenceVirtualSites::computePositions(system, atomCoordinates);
context.calcForcesAndEnergy(true, false);
forcesAreValid = true;
for (int i = 0; i < numberOfAtoms; ++i) {
if (masses[i] != 0.0)
for (int j = 0; j < 3; ++j) {
xPrime[i][j] += velocities[i][j]*getDeltaT();
}
}
// Update the positions and velocities.
// Regular atoms
for (const auto &atom : atomList) {
if (masses[atom] != 0.0) {
velocities[atom] += 0.5 * inverseMasses[atom]*forces[atom]*getDeltaT() + (atomCoordinates[atom] - xPrime[atom])/getDeltaT();
}
}
// Connected particles
for (const auto &pair : pairList) {
const auto &atom1 = std::get<0>(pair);
const auto &atom2 = std::get<1>(pair);
double m1 = system.getParticleMass(atom1);
double m2 = system.getParticleMass(atom2);
double mass1fract = m1 / (m1 + m2);
double mass2fract = m2 / (m1 + m2);
double invRedMass = (m1 * m2 != 0.0) ? (m1 + m2)/(m1 * m2) : 0.0;
double invTotMass = (m1 + m2 != 0.0) ? 1.0 /(m1 + m2) : 0.0;
Vec3 comVel = velocities[atom1]*mass1fract + velocities[atom2]*mass2fract;
Vec3 relVel = velocities[atom2] - velocities[atom1];
Vec3 comForce = forces[atom1] + forces[atom2];
Vec3 relForce = mass1fract*forces[atom2] - mass2fract*forces[atom1];
comVel += 0.5 * comForce * getDeltaT() * invTotMass;
relVel += 0.5 * relForce * getDeltaT() * invRedMass;
if (m1 != 0.0) {
velocities[atom1] = comVel - relVel*mass2fract + (atomCoordinates[atom1] - xPrime[atom1])/getDeltaT();
}
if (m2 != 0.0) {
velocities[atom2] = comVel + relVel*mass1fract + (atomCoordinates[atom2] - xPrime[atom2])/getDeltaT();
}
}
if (referenceConstraintAlgorithm)
referenceConstraintAlgorithm->applyToVelocities(atomCoordinates, velocities, inverseMasses, tolerance);
incrementTimeStep();
}
/* -------------------------------------------------------------------------- *
* 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) 2015 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 "TestNoseHooverIntegrator.h"
void runPlatformTests() {
}
/* -------------------------------------------------------------------------- *
* 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) 2019 Stanford University and the Authors. *
* Authors: Andreas Krämer and Andrew C. Simmonett *
* 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 "TestNoseHooverThermostat.h"
void runPlatformTests() {
}
......@@ -35,5 +35,6 @@
#include "openmm/DrudeForce.h"
#include "openmm/DrudeLangevinIntegrator.h"
#include "openmm/DrudeSCFIntegrator.h"
#include "openmm/DrudeNoseHooverIntegrator.h"
#endif /*OPENMM_DRUDE_H_*/
#ifndef OPENMM_DRUDENOSEHOOVERINTEGRATOR_H_
#define OPENMM_DRUDENOSEHOOVERINTEGRATOR_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) 2019 Stanford University and the Authors. *
* Authors: Andreas Krämer and Andrew C. Simmonett *
* 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/NoseHooverIntegrator.h"
#include "openmm/Kernel.h"
#include "openmm/internal/windowsExportDrude.h"
namespace OpenMM {
/**
* This Integrator simulates systems that include Drude particles. It applies two different Nose-Hoover
* chain thermostats to the different parts of the system. The first is applied to ordinary particles (ones
* that are not part of a Drude particle pair), as well as to the center of mass of each Drude particle pair.
* A second thermostat, typically with a much lower temperature, is applied to the relative internal
* displacement of each pair.
*
* This Integrator requires the System to include a DrudeForce, which it uses to identify the Drude
* particles.
*/
class OPENMM_EXPORT_DRUDE DrudeNoseHooverIntegrator : public NoseHooverIntegrator {
public:
/**
* Create a DrudeNoseHooverIntegrator.
*
* @param temperature the target temperature for the system (in Kelvin).
* @param collisionFrequency the frequency of the system's interaction with the heat bath (in inverse picoseconds).
* @param drudeTemperature the target temperature for the Drude particles, relative to their parent atom (in Kelvin).
* @param drudeCollisionFrequency the frequency of the drude particles' interaction with the heat bath (in inverse picoseconds).
* @param stepSize the step size with which to integrator the system (in picoseconds)
* @param chainLength the number of beads in the Nose-Hoover chain.
* @param numMTS the number of step in the multiple time step chain propagation algorithm.
* @param numYoshidaSuzuki the number of terms in the Yoshida-Suzuki multi time step decomposition
* used in the chain propagation algorithm (must be 1, 3, or 5).
*/
DrudeNoseHooverIntegrator(double temperature, double collisionFrequency,
double drudeTemperature, double drudeCollisionFrequency, double stepSize,
int chainLength = 3, int numMTS = 3, int numYoshidaSuzuki = 3);
virtual ~DrudeNoseHooverIntegrator();
/**
* This will be called by the Context when it is created. It informs the Integrator
* of what context it will be integrating, and gives it a chance to do any necessary initialization.
* It will also get called again if the application calls reinitialize() on the Context.
*/
void initialize(ContextImpl& context);
/**
* Get the maximum distance a Drude particle can ever move from its parent particle, measured in nm. This is implemented
* with a hard wall constraint. If this distance is set to 0 (the default), the hard wall constraint is omitted.
*/
double getMaxDrudeDistance() const;
/**
* Set the maximum distance a Drude particle can ever move from its parent particle, measured in nm. This is implemented
* with a hard wall constraint. If this distance is set to 0 (the default), the hard wall constraint is omitted.
*/
void setMaxDrudeDistance(double distance);
/**
* Compute the kinetic energy of the drude particles at the current time.
*/
double computeDrudeKineticEnergy();
/**
* Compute the kinetic energy of all (real and drude) particles at the current time.
*/
double computeTotalKineticEnergy();
};
} // namespace OpenMM
#endif /*OPENMM_DRUDENOSEHOOVERINTEGRATOR_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) 2019 Stanford University and the Authors. *
* Authors: Andreas Krämer and Andrew C. Simmonett *
* 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/DrudeNoseHooverIntegrator.h"
#include "openmm/Context.h"
#include "openmm/OpenMMException.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/DrudeKernels.h"
#include "openmm/DrudeForce.h"
#include "openmm/CMMotionRemover.h"
#include "openmm/kernels.h"
#include <ctime>
#include <iostream>
#include <string>
#include <set>
using namespace OpenMM;
using std::string;
using std::vector;
DrudeNoseHooverIntegrator::DrudeNoseHooverIntegrator(double temperature, double collisionFrequency,
double drudeTemperature, double drudeCollisionFrequency,
double stepSize, int chainLength, int numMTS, int numYoshidaSuzuki) :
NoseHooverIntegrator(stepSize) {
setMaxDrudeDistance(0);
hasSubsystemThermostats_ = false;
addSubsystemThermostat(std::vector<int>(), std::vector<std::pair<int, int>>(), temperature,
collisionFrequency, drudeTemperature, drudeCollisionFrequency,
chainLength, numMTS, numYoshidaSuzuki);
}
DrudeNoseHooverIntegrator::~DrudeNoseHooverIntegrator() { }
double DrudeNoseHooverIntegrator::getMaxDrudeDistance() const {
return maxPairDistance_;
}
void DrudeNoseHooverIntegrator::setMaxDrudeDistance(double distance) {
if (distance < 0)
throw OpenMMException("setMaxDrudeDistance: Distance cannot be negative");
maxPairDistance_ = distance;
}
void DrudeNoseHooverIntegrator::initialize(ContextImpl& contextRef) {
if (owner != NULL && &contextRef.getOwner() != owner)
throw OpenMMException("This Integrator is already bound to a context");
context = &contextRef;
owner = &contextRef.getOwner();
vvKernel = context->getPlatform().createKernel(IntegrateVelocityVerletStepKernel::Name(), contextRef);
vvKernel.getAs<IntegrateVelocityVerletStepKernel>().initialize(contextRef.getSystem(), *this);
nhcKernel = context->getPlatform().createKernel(NoseHooverChainKernel::Name(), contextRef);
nhcKernel.getAs<NoseHooverChainKernel>().initialize();
forcesAreValid = false;
// check for drude particles and build the Nose-Hoover Chains
const System& system = context->getSystem();
const DrudeForce* drudeForce = NULL;
bool hasCMMotionRemover = false;
for (int i = 0; i < system.getNumForces(); i++){
if (dynamic_cast<const DrudeForce*>(&system.getForce(i)) != NULL) {
if (drudeForce == NULL)
drudeForce = dynamic_cast<const DrudeForce*>(&system.getForce(i));
else
throw OpenMMException("The System contains multiple DrudeForces");
}
if (dynamic_cast<const CMMotionRemover*>(&system.getForce(i))) {
hasCMMotionRemover = true;
}
}
if (drudeForce == NULL)
throw OpenMMException("The System does not contain a DrudeForce");
if (!hasCMMotionRemover) {
std::cout << "Warning: Did not find a center-of-mass motion remover in the system. "
"This is problematic when using Drude." << std::endl;
}
for (auto& thermostat: noseHooverChains){
if ( (thermostat.getThermostatedAtoms().size() == 0) && (thermostat.getThermostatedPairs().size() == 0) ){
std::set<int> realParticlesSet;
vector<int> realParticles, drudeParticles, drudeParents;
vector<std::pair<int, int>> drudePairs;
for (int i = 0; i < system.getNumParticles(); i++) {
if (system.getParticleMass(i) > 0.0) realParticlesSet.insert(i);
}
for (int i = 0; i < drudeForce->getNumParticles(); i++) {
int p, p1, p2, p3, p4;
double charge, polarizability, aniso12, aniso34;
drudeForce->getParticleParameters(i, p, p1, p2, p3, p4, charge, polarizability, aniso12, aniso34);
realParticlesSet.erase(p);
realParticlesSet.erase(p1);
drudePairs.push_back({p,p1});
}
thermostat.setThermostatedPairs(drudePairs);
thermostat.setThermostatedAtoms(std::vector<int>(realParticlesSet.begin(), realParticlesSet.end()));
}
}
initializeThermostats(system);
}
double DrudeNoseHooverIntegrator::computeDrudeKineticEnergy() {
double kE = 0.0;
for (const auto &nhc: noseHooverChains){
if (nhc.getThermostatedPairs().size() != 0) {
kE += nhcKernel.getAs<NoseHooverChainKernel>().computeMaskedKineticEnergy(*context, nhc, true).second;
}
}
return kE;
}
double DrudeNoseHooverIntegrator::computeTotalKineticEnergy() {
return vvKernel.getAs<IntegrateVelocityVerletStepKernel>().computeKineticEnergy(*context, *this);
}
......@@ -5,6 +5,7 @@
ENABLE_TESTING()
INCLUDE_DIRECTORIES(${CUDA_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${OPENMM_DIR}/plugins/drude/tests)
# Automatically create tests using files named "Test*.cpp"
FILE(GLOB TEST_PROGS "*Test*.cpp")
......
/* -------------------------------------------------------------------------- *
* 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) 2013 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 "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/Platform.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "openmm/DrudeForce.h"
#include "CudaPlatform.h"
#include "SimTKOpenMMUtilities.h"
#include <iostream>
#include <vector>
using namespace OpenMM;
using namespace std;
extern "C" OPENMM_EXPORT void registerDrudeCudaKernelFactories();
void runPlatformTests() { }
#include "TestDrudeNoseHoover.h"
Platform& initializePlatform(int argc, char* argv[]) {
registerDrudeCudaKernelFactories();
if (argc > 1) Platform::getPlatformByName("CUDA").setPropertyDefaultValue("Precision", std::string(argv[1]));
return Platform::getPlatformByName("CUDA");
}
......@@ -5,6 +5,7 @@
ENABLE_TESTING()
INCLUDE_DIRECTORIES(${OPENCL_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${OPENMM_DIR}/plugins/drude/tests)
# Automatically create tests using files named "Test*.cpp"
FILE(GLOB TEST_PROGS "*Test*.cpp")
......
/* -------------------------------------------------------------------------- *
* 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) 2013 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 "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/Platform.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "openmm/DrudeForce.h"
#include "OpenCLPlatform.h"
#include "SimTKOpenMMUtilities.h"
#include <iostream>
#include <vector>
using namespace OpenMM;
using namespace std;
extern "C" OPENMM_EXPORT void registerDrudeOpenCLKernelFactories();
void runPlatformTests() { }
#include "TestDrudeNoseHoover.h"
Platform& initializePlatform(int argc, char* argv[]) {
registerDrudeOpenCLKernelFactories();
if (argc > 1) Platform::getPlatformByName("OpenCL").setPropertyDefaultValue("Precision", std::string(argv[1]));
return Platform::getPlatformByName("OpenCL");
}
......@@ -5,6 +5,7 @@ ENABLE_TESTING()
INCLUDE_DIRECTORIES(${OPENMM_DIR}/platforms/reference/include)
INCLUDE_DIRECTORIES(${OPENMM_DIR}/openmmapi/include/openmm)
INCLUDE_DIRECTORIES(${OPENMM_DIR}/platforms/reference/src)
INCLUDE_DIRECTORIES(${OPENMM_DIR}/plugins/drude/tests)
SET(SHARED_OPENMM_DRUDE_TARGET OpenMMDrude)
......
/* -------------------------------------------------------------------------- *
* 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) 2013 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 "openmm/Platform.h"
using namespace OpenMM;
using namespace std;
//extern "C" OPENMM_EXPORT void registerDrudeReferenceKernelFactories();
Platform& initializePlatform(int argc, char* argv[]) {
/* registerDrudeReferenceKernelFactories();
*/
return Platform::getPlatformByName("Reference");
}
#include "TestDrudeNoseHoover.h"
void runPlatformTests() { }
#ifndef OPENMM_DRUDE_NOSE_HOOVER_INTEGRATOR_PROXY_H_
#define OPENMM_DRUDE_NOSE_HOOVER_INTEGRATOR_PROXY_H_
#include "openmm/serialization/SerializationProxy.h"
#include "openmm/internal/windowsExportDrude.h"
namespace OpenMM {
class OPENMM_EXPORT_DRUDE DrudeNoseHooverIntegratorProxy : public SerializationProxy {
public:
DrudeNoseHooverIntegratorProxy();
void serialize(const void* object, SerializationNode& node) const;
void* deserialize(const SerializationNode& node) const;
};
}
#endif /*OPENMM_DRUDE_NOSE_HOOVER_INTEGRATOR_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) 2010 Stanford University and the Authors. *
* Authors: Andrew C. Simmonett, Andreas Krämer *
* 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/DrudeNoseHooverIntegratorProxy.h"
#include "openmm/serialization/SerializationNode.h"
#include "openmm/DrudeNoseHooverIntegrator.h"
#include <vector>
#include <assert.h>
#include <OpenMM.h>
using namespace std;
using namespace OpenMM;
DrudeNoseHooverIntegratorProxy::DrudeNoseHooverIntegratorProxy() : SerializationProxy("DrudeNoseHooverIntegrator") {
}
void DrudeNoseHooverIntegratorProxy::serialize(const void* object, SerializationNode& node) const {
node.setIntProperty("version", 1);
const DrudeNoseHooverIntegrator& integrator = *reinterpret_cast<const DrudeNoseHooverIntegrator*>(object);
node.setDoubleProperty("stepSize", integrator.getStepSize());
node.setDoubleProperty("constraintTolerance", integrator.getConstraintTolerance());
node.setDoubleProperty("maximumPairDistance", integrator.getMaximumPairDistance());
assert(not integrator.hasSubsystemThermostats());
node.setDoubleProperty("temperature", integrator.getTemperature());
node.setDoubleProperty("relativeTemperature", integrator.getRelativeTemperature());
node.setDoubleProperty("collisionFrequency", integrator.getCollisionFrequency());
node.setDoubleProperty("relativeCollisionFrequency", integrator.getRelativeCollisionFrequency());
node.setIntProperty("chainLength", integrator.getThermostat().getChainLength());
node.setIntProperty("numMTS", integrator.getThermostat().getNumMultiTimeSteps());
node.setIntProperty("numYS", integrator.getThermostat().getNumYoshidaSuzukiTimeSteps());
}
void* DrudeNoseHooverIntegratorProxy::deserialize(const SerializationNode& node) const {
if (node.getIntProperty("version") != 1)
throw OpenMMException("Unsupported version number");
DrudeNoseHooverIntegrator* integrator;
integrator = new DrudeNoseHooverIntegrator(
node.getDoubleProperty("temperature"),
node.getDoubleProperty("collisionFrequency"),
node.getDoubleProperty("relativeTemperature"),
node.getDoubleProperty("relativeCollisionFrequency"),
node.getDoubleProperty("stepSize"),
node.getIntProperty("chainLength"),
node.getIntProperty("numMTS"),
node.getIntProperty("numYS")
);
integrator->setConstraintTolerance(node.getDoubleProperty("constraintTolerance"));
integrator->setMaximumPairDistance(node.getDoubleProperty("maximumPairDistance"));
return integrator;
}
......@@ -42,11 +42,13 @@
#include "openmm/DrudeForce.h"
#include "openmm/DrudeLangevinIntegrator.h"
#include "openmm/DrudeNoseHooverIntegrator.h"
#include "openmm/serialization/SerializationProxy.h"
#include "openmm/serialization/DrudeForceProxy.h"
#include "openmm/serialization/DrudeLangevinIntegratorProxy.h"
#include "openmm/serialization/DrudeNoseHooverIntegratorProxy.h"
#if defined(WIN32)
#include <windows.h>
......@@ -65,4 +67,5 @@ using namespace OpenMM;
extern "C" OPENMM_EXPORT_DRUDE void registerDrudeSerializationProxies() {
SerializationProxy::registerProxy(typeid(DrudeForce), new DrudeForceProxy());
SerializationProxy::registerProxy(typeid(DrudeLangevinIntegrator), new DrudeLangevinIntegratorProxy());
SerializationProxy::registerProxy(typeid(DrudeNoseHooverIntegrator), new DrudeNoseHooverIntegratorProxy());
}
/* -------------------------------------------------------------------------- *
* 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) 2010-2014 Stanford University and the Authors. *
* Authors: Andrew C. Simmonett and Andreas Kraemer
* 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/DrudeNoseHooverIntegrator.h"
#include "ReferencePlatform.h"
#include "openmm/serialization/XmlSerializer.h"
#include "openmm/System.h"
#include "openmm/DrudeForce.h"
#include "openmm/Context.h"
#include <iostream>
#include <sstream>
using namespace OpenMM;
using namespace std;
extern "C" void registerDrudeSerializationProxies();
//extern "C" OPENMM_EXPORT void registerDrudeReferenceKernelFactories();
//extern "C" OPENMM_EXPORT void registerKernelFactories();
void assertIntegratorsEqual(const DrudeNoseHooverIntegrator& integrator1, const DrudeNoseHooverIntegrator& integrator2){
ASSERT_EQUAL(integrator1.getStepSize(), integrator2.getStepSize());
ASSERT_EQUAL(integrator1.getConstraintTolerance(), integrator2.getConstraintTolerance());
ASSERT_EQUAL(integrator1.getMaximumPairDistance(), integrator2.getMaximumPairDistance());
ASSERT_EQUAL(integrator1.getNumThermostats(), integrator2.getNumThermostats());
for (int i = 0; i < integrator1.getNumThermostats(); i++) {
const auto &thermostat1 = integrator1.getThermostat(i);
const auto &thermostat2 = integrator2.getThermostat(i);
ASSERT_EQUAL(thermostat1.getTemperature(), thermostat2.getTemperature());
ASSERT_EQUAL(thermostat1.getCollisionFrequency(), thermostat2.getCollisionFrequency());
ASSERT_EQUAL(thermostat1.getRelativeTemperature(), thermostat2.getRelativeTemperature());
ASSERT_EQUAL(thermostat1.getRelativeCollisionFrequency(), thermostat2.getRelativeCollisionFrequency());
ASSERT_EQUAL(thermostat1.getChainLength(), thermostat2.getChainLength());
ASSERT_EQUAL(thermostat1.getNumMultiTimeSteps(), thermostat2.getNumMultiTimeSteps());
ASSERT_EQUAL(thermostat1.getNumYoshidaSuzukiTimeSteps(), thermostat2.getNumYoshidaSuzukiTimeSteps());
ASSERT_EQUAL(thermostat1.getChainID(), thermostat2.getChainID());
const auto &thermostat1Atoms = thermostat1.getThermostatedAtoms();
const auto &thermostat2Atoms = thermostat2.getThermostatedAtoms();
ASSERT_EQUAL(thermostat1Atoms.size(), thermostat2Atoms.size());
for (int j = 0; j < thermostat1Atoms.size(); ++j) {
ASSERT_EQUAL(thermostat1Atoms[j], thermostat2Atoms[j]);
}
const auto &thermostat1Pairs = thermostat1.getThermostatedPairs();
const auto &thermostat2Pairs = thermostat2.getThermostatedPairs();
ASSERT_EQUAL(thermostat1Pairs.size(), thermostat2Pairs.size());
for (int j = 0; j < thermostat1Pairs.size(); ++j) {
ASSERT_EQUAL(thermostat1Pairs[j].first, thermostat2Pairs[j].first);
ASSERT_EQUAL(thermostat1Pairs[j].second, thermostat2Pairs[j].second);
}
}
}
void testSerialization() {
// Check with default constructor
System system;
system.addForce(new DrudeForce());
for (int i=0; i<10; i++) system.addParticle(1.0);
DrudeNoseHooverIntegrator integrator(331, 0.21, 1.1, 0.1, 0.004, 5, 5, 5);
// Serialize and then deserialize it.
stringstream buffer2;
XmlSerializer::serialize<DrudeNoseHooverIntegrator>(&integrator, "Integrator", buffer2);
DrudeNoseHooverIntegrator* copy = XmlSerializer::deserialize<DrudeNoseHooverIntegrator>(buffer2);
ASSERT_EQUAL(copy->getThermostat(0).getThermostatedAtoms().size(), 0);
assertIntegratorsEqual(integrator, *copy);
}
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) 2019 Stanford University and the Authors. *
* Authors: Andreas Krämer and Andrew C. Simmonett *
* 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/NoseHooverChain.h"
#include "openmm/CMMotionRemover.h"
#include "openmm/DrudeNoseHooverIntegrator.h"
#include "openmm/Context.h"
#include "openmm/State.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/VirtualSite.h"
#include "openmm/NonbondedForce.h"
#include "openmm/CustomExternalForce.h"
#include "openmm/System.h"
#include "openmm/DrudeForce.h"
#include "SimTKOpenMMRealType.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <sstream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace OpenMM;
using namespace std;
extern "C" OPENMM_EXPORT void registerDrudeReferenceKernelFactories();
extern "C" OPENMM_EXPORT void registerKernelFactories();
Platform& initializePlatform(int argc, char* argv[]);
void build_waterbox(System &system, int gridSize, double polarizability, vector<Vec3> & positions) {
// Create a box of SWM4-NDP water molecules. This involves constraints, virtual sites,
// and Drude particles.
const int numMolecules = gridSize*gridSize*gridSize;
const double spacing = 0.8;
const double boxSize = spacing*(gridSize+1);
NonbondedForce* nonbonded = new NonbondedForce();
DrudeForce* drude = new DrudeForce();
CMMotionRemover* cmm = new CMMotionRemover(1);
system.addForce(cmm);
system.addForce(nonbonded);
system.addForce(drude);
system.setDefaultPeriodicBoxVectors(Vec3(boxSize, 0, 0), Vec3(0, boxSize, 0), Vec3(0, 0, boxSize));
nonbonded->setNonbondedMethod(NonbondedForce::CutoffPeriodic);
nonbonded->setCutoffDistance(1.2);
nonbonded->setSwitchingDistance(0.8);
for (int i = 0; i < numMolecules; i++) {
int startIndex = system.getNumParticles();
system.addParticle(15.6); // O
system.addParticle(0.4); // D
system.addParticle(1.0); // H1
system.addParticle(1.0); // H2
system.addParticle(0.0); // M
nonbonded->addParticle(1.71636, 0.318395, 0.21094*4.184);
nonbonded->addParticle(-1.71636, 1, 0);
nonbonded->addParticle(0.55733, 1, 0);
nonbonded->addParticle(0.55733, 1, 0);
nonbonded->addParticle(-1.11466, 1, 0);
for (int j = 0; j < 5; j++)
for (int k = 0; k < j; k++)
nonbonded->addException(startIndex+j, startIndex+k, 0, 1, 0);
system.addConstraint(startIndex, startIndex+2, 0.09572);
system.addConstraint(startIndex, startIndex+3, 0.09572);
system.addConstraint(startIndex+2, startIndex+3, 0.15139);
system.setVirtualSite(startIndex+4, new ThreeParticleAverageSite(startIndex, startIndex+2, startIndex+3, 0.786646558, 0.106676721, 0.106676721));
drude->addParticle(startIndex+1, startIndex, -1, -1, -1, -1.71636, polarizability, 1, 1);
}
for (int i = 0; i < gridSize; i++) {
for (int j = 0; j < gridSize; j++) {
for (int k = 0; k < gridSize; k++) {
Vec3 pos(i*spacing, j*spacing, k*spacing);
positions.push_back(pos);
positions.push_back(pos);
positions.push_back(pos+Vec3(0.09572, 0, 0));
positions.push_back(pos+Vec3(-0.023999, 0.092663, 0));
positions.push_back(pos);
}
}
}
}
void testWaterBox(Platform& platform) {
// Create a box of SWM4-NDP water molecules. This involves constraints, virtual sites,
// and Drude particles.
System system;
const int gridSize = 3;
vector<Vec3> positions;
double polarizability = ONE_4PI_EPS0*1.71636*1.71636/(100000*4.184);
build_waterbox(system, gridSize, polarizability, positions);
const int numMolecules = gridSize*gridSize*gridSize;
int numStandardDof = 3*3*numMolecules - system.getNumConstraints();
int numDrudeDof = 3*numMolecules;
int numDof = numStandardDof+numDrudeDof;
const double temperature = 300.0;
const double temperatureDrude = 10.0;
// Simulate it and check the temperature.
int chainLength = 4;
int numMTS = 4;
int numYS = 5;
double frequency = 800.0;
double frequencyDrude = 2000.0;
int randomSeed = 100;
DrudeNoseHooverIntegrator integ(temperature, frequency,
temperatureDrude, frequencyDrude, 0.0005,
chainLength, numMTS, numYS);
Context context(system, integ, platform);
context.setPositions(positions);
context.setVelocitiesToTemperature(temperature, randomSeed);
std::vector<Vec3> velocities = context.getState(State::Velocities).getVelocities();
for (int i = 0; i < numMolecules; i++){
Vec3 noize;
for (int j = 0; j < 3; j++){
noize[j] = float(((i+18311)*(j+18253) * 313419097822414) % 18313) / float(18313);
noize[j] *= sqrt(3 * BOLTZ * temperatureDrude / 0.4);
}
velocities[5*i+1] = velocities[5*i] + noize;
}
context.setVelocities(velocities);
context.applyConstraints(1e-6);
// Equilibrate.
integ.step(500);
// Compute the internal and center of mass temperatures.
double totalKE = 0;
const int numSteps = 4000;
double meanTemp = 0.0;
double meanDrudeTemp = 0.0;
double meanConserved = 0.0;
for (int i = 0; i < numSteps; i++) {
integ.step(1);
State state = context.getState(State::Energy);
double KE = state.getKineticEnergy();
double PE = state.getPotentialEnergy();
double fullKE = integ.computeTotalKineticEnergy();
double drudeKE = integ.computeDrudeKineticEnergy();
double temp = KE/(0.5*numStandardDof*BOLTZ);
double drudeTemp = drudeKE/(0.5*numDrudeDof*BOLTZ);
meanTemp = (i*meanTemp + temp)/(i+1);
meanDrudeTemp = (i*meanDrudeTemp + drudeTemp)/(i+1);
double heatBathEnergy = integ.computeHeatBathEnergy();
double conserved = PE + fullKE + heatBathEnergy;
meanConserved = (i*meanConserved + conserved)/(i+1);
totalKE += KE;
ASSERT(fabs(meanConserved - conserved) < 0.6);
}
totalKE /= numSteps;
ASSERT_USUALLY_EQUAL_TOL(temperature, meanTemp, 0.004);
ASSERT_USUALLY_EQUAL_TOL(temperatureDrude, meanDrudeTemp, 0.004);
}
double testWaterBoxWithHardWallConstraint(Platform& platform, double hardWallConstraint){
// Create a box of SWM4-NDP water molecules. This involves constraints, virtual sites,
// and Drude particles.
System system;
const int gridSize = 3;
vector<Vec3> positions;
double polarizability = 1e-2;
build_waterbox(system, gridSize, polarizability, positions);
const int numMolecules = gridSize*gridSize*gridSize;
int numStandardDof = 3*3*numMolecules - system.getNumConstraints();
int numDrudeDof = 3*numMolecules;
int numDof = numStandardDof+numDrudeDof;
const double temperature = 300.0;
const double temperatureDrude = 10.0;
// Simulate it and check the temperature.
int chainLength = 4;
int numMTS = 3;
int numYS = 3;
double frequency = 25.0;
double frequencyDrude = 25.0;
int randomSeed = 100;
DrudeNoseHooverIntegrator integ(temperature, frequency,
temperatureDrude, frequencyDrude, 0.0005,
chainLength, numMTS, numYS);
integ.setMaxDrudeDistance(hardWallConstraint);
Context context(system, integ, platform);
context.setPositions(positions);
context.setVelocitiesToTemperature(temperature, randomSeed);
std::vector<Vec3> velocities = context.getState(State::Velocities).getVelocities();
for (int i = 0; i < numMolecules; i++){
Vec3 noize;
for (int j = 0; j < 3; j++){
noize[j] = float(((i+18311)*(j+18253) * 313419097822414) % 18313) / float(18313);
noize[j] *= sqrt(3 * BOLTZ * temperatureDrude / 0.4);
}
velocities[5*i+1] = velocities[5*i] + noize;
}
context.setVelocities(velocities);
context.applyConstraints(1e-6);
// Equilibrate.
integ.step(10);
// Compute the internal and center of mass temperatures.
double totalKE = 0;
const int numSteps = 10;
double meanTemp = 0.0;
double meanDrudeTemp = 0.0;
double meanConserved = 0.0;
double maxR = 0.0;
for (int i = 0; i < numSteps; i++) {
integ.step(1);
State state = context.getState(State::Energy | State::Positions);
double KE = state.getKineticEnergy();
double PE = state.getPotentialEnergy();
double fullKE = integ.computeTotalKineticEnergy();
double drudeKE = integ.computeDrudeKineticEnergy();
double temp = KE/(0.5*numStandardDof*BOLTZ);
double drudeTemp = drudeKE/(0.5*numDrudeDof*BOLTZ);
meanTemp = (i*meanTemp + temp)/(i+1);
meanDrudeTemp = (i*meanDrudeTemp + drudeTemp)/(i+1);
double heatBathEnergy = integ.computeHeatBathEnergy();
double conserved = PE + fullKE + heatBathEnergy;
meanConserved = (i*meanConserved + conserved)/(i+1);
const auto & positions = state.getPositions();
for(int mol = 0; mol < gridSize*gridSize*gridSize; ++mol) {
auto dR = positions[5*mol+1] - positions[5*mol];
maxR = std::max(maxR, std::sqrt(dR.dot(dR)));
}
totalKE += KE;
}
totalKE /= numSteps;
return maxR;
}
int main(int argc, char* argv[]) {
try {
registerKernelFactories();
Platform& platform = initializePlatform(argc, argv);
testWaterBox(platform);
double maxDrudeDistance = 0.005;
double observedDrudeDistance = testWaterBoxWithHardWallConstraint(platform, 0.0);
ASSERT(observedDrudeDistance > maxDrudeDistance);
observedDrudeDistance = testWaterBoxWithHardWallConstraint(platform, maxDrudeDistance);
ASSERT(observedDrudeDistance < maxDrudeDistance);
}
catch(const exception& e) {
cout << "exception: " << e.what() << endl;
return 1;
}
cout << "Done" << endl;
return 0;
}
#ifndef OPENMM_NOSE_HOOVER_INTEGRATOR_PROXY_H_
#define OPENMM_NOSE_HOOVER_INTEGRATOR_PROXY_H_
#include "openmm/serialization/XmlSerializer.h"
namespace OpenMM {
class NoseHooverIntegratorProxy : public SerializationProxy {
public:
NoseHooverIntegratorProxy();
void serialize(const void* object, SerializationNode& node) const;
void* deserialize(const SerializationNode& node) const;
};
}
#endif /*OPENMM_NOSE_HOOVER_INTEGRATOR_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) 2010 Stanford University and the Authors. *
* Authors: Andrew C. Simmonett, Andreas Krämer *
* 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/NoseHooverIntegratorProxy.h"
#include <vector>
#include <OpenMM.h>
using namespace std;
using namespace OpenMM;
NoseHooverIntegratorProxy::NoseHooverIntegratorProxy() : SerializationProxy("NoseHooverIntegrator") {
}
void NoseHooverIntegratorProxy::serialize(const void* object, SerializationNode& node) const {
node.setIntProperty("version", 1);
const NoseHooverIntegrator& integrator = *reinterpret_cast<const NoseHooverIntegrator*>(object);
node.setDoubleProperty("stepSize", integrator.getStepSize());
node.setDoubleProperty("constraintTolerance", integrator.getConstraintTolerance());
node.setDoubleProperty("maximumPairDistance", integrator.getMaximumPairDistance());
node.setBoolProperty("hasSubsystemThermostats", integrator.hasSubsystemThermostats());
if (integrator.hasSubsystemThermostats()) {
// Serialize all thermostats separately
for (int i = 0; i < integrator.getNumThermostats(); i++){
const auto& chain = integrator.getThermostat(i);
auto& chainNode = node.createChildNode("Thermostat");
chainNode.setDoubleProperty("temperature", chain.getTemperature());
chainNode.setDoubleProperty("collisionFrequency", chain.getCollisionFrequency());
chainNode.setDoubleProperty("relativeTemperature", chain.getRelativeTemperature());
chainNode.setDoubleProperty("relativeCollisionFrequency", chain.getRelativeCollisionFrequency());
chainNode.setIntProperty("chainLength", chain.getChainLength());
chainNode.setIntProperty("numMTS", chain.getNumMultiTimeSteps());
chainNode.setIntProperty("numYS", chain.getNumYoshidaSuzukiTimeSteps());
auto& particlesNode = chainNode.createChildNode("ThermostatedAtoms");
for (int particle: chain.getThermostatedAtoms()){
particlesNode.createChildNode("Particle").setIntProperty("index", particle);
}
auto& pairsNode = chainNode.createChildNode("ThermostatedPairs");
for (auto& pair: chain.getThermostatedPairs()){
auto& pairNode = pairsNode.createChildNode("Pair");
pairNode.setIntProperty("index1", pair.first);
pairNode.setIntProperty("index2", pair.second);
}
}
} else { // Serialize standard thermostat
node.setDoubleProperty("temperature", integrator.getTemperature());
node.setDoubleProperty("collisionFrequency", integrator.getCollisionFrequency());
node.setIntProperty("chainLength", integrator.getThermostat().getChainLength());
node.setIntProperty("numMTS", integrator.getThermostat().getNumMultiTimeSteps());
node.setIntProperty("numYS", integrator.getThermostat().getNumYoshidaSuzukiTimeSteps());
}
}
void* NoseHooverIntegratorProxy::deserialize(const SerializationNode& node) const {
if (node.getIntProperty("version") != 1)
throw OpenMMException("Unsupported version number");
NoseHooverIntegrator* integrator;
if (node.getBoolProperty("hasSubsystemThermostats")){
// deserialize all chains
integrator = new NoseHooverIntegrator(node.getDoubleProperty("stepSize"));
for (auto& chainNode : node.getChildren()) {
// particles
const auto& particlesNode = chainNode.getChildNode("ThermostatedAtoms");
vector<int> particles;
for (auto& particleNode: particlesNode.getChildren()){
particles.push_back(particleNode.getIntProperty("index"));
}
// pairs
const auto& pairsNode = chainNode.getChildNode("ThermostatedPairs");
vector<pair<int, int>> pairs;
for (auto& pairNode: pairsNode.getChildren()){
pairs.emplace_back(pairNode.getIntProperty("index1"), pairNode.getIntProperty("index2"));
}
integrator->addSubsystemThermostat(
particles, pairs,
chainNode.getDoubleProperty("temperature"),
chainNode.getDoubleProperty("collisionFrequency"),
chainNode.getDoubleProperty("relativeTemperature"),
chainNode.getDoubleProperty("relativeCollisionFrequency"),
chainNode.getIntProperty("chainLength"),
chainNode.getIntProperty("numMTS"),
chainNode.getIntProperty("numYS")
);
}
} else {
integrator = new NoseHooverIntegrator(
node.getDoubleProperty("temperature"),
node.getDoubleProperty("collisionFrequency"),
node.getDoubleProperty("stepSize"),
node.getIntProperty("chainLength"),
node.getIntProperty("numMTS"),
node.getIntProperty("numYS")
);
}
integrator->setConstraintTolerance(node.getDoubleProperty("constraintTolerance"));
integrator->setMaximumPairDistance(node.getDoubleProperty("maximumPairDistance"));
return integrator;
}
......@@ -56,6 +56,7 @@
#include "openmm/MonteCarloBarostat.h"
#include "openmm/MonteCarloMembraneBarostat.h"
#include "openmm/NonbondedForce.h"
#include "openmm/NoseHooverIntegrator.h"
#include "openmm/PeriodicTorsionForce.h"
#include "openmm/RBTorsionForce.h"
#include "openmm/RMSDForce.h"
......@@ -93,6 +94,7 @@
#include "openmm/serialization/MonteCarloBarostatProxy.h"
#include "openmm/serialization/MonteCarloMembraneBarostatProxy.h"
#include "openmm/serialization/NonbondedForceProxy.h"
#include "openmm/serialization/NoseHooverIntegratorProxy.h"
#include "openmm/serialization/PeriodicTorsionForceProxy.h"
#include "openmm/serialization/RBTorsionForceProxy.h"
#include "openmm/serialization/RMSDForceProxy.h"
......@@ -151,6 +153,7 @@ extern "C" void registerSerializationProxies() {
SerializationProxy::registerProxy(typeid(MonteCarloBarostat), new MonteCarloBarostatProxy());
SerializationProxy::registerProxy(typeid(MonteCarloMembraneBarostat), new MonteCarloMembraneBarostatProxy());
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(RMSDForce), new RMSDForceProxy());
......@@ -159,4 +162,4 @@ extern "C" void registerSerializationProxies() {
SerializationProxy::registerProxy(typeid(VariableLangevinIntegrator), new VariableLangevinIntegratorProxy());
SerializationProxy::registerProxy(typeid(VariableVerletIntegrator), new VariableVerletIntegratorProxy());
SerializationProxy::registerProxy(typeid(VerletIntegrator), new VerletIntegratorProxy());
}
\ No newline at end of file
}
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