Commit 8df54762 authored by Lee-Ping Wang's avatar Lee-Ping Wang
Browse files

Merge branch 'master' of github.com:leeping/openmm

parents 3cb25ad8 59854c5e
/* Portions copyright (c) 2006 Stanford University and Simbios.
* Contributors: 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.
*/
#ifndef __ReferenceConstraint_H__
#define __ReferenceConstraint_H__
// ---------------------------------------------------------------------------------------
class ReferenceConstraint {
private:
public:
/**---------------------------------------------------------------------------------------
Constructor
--------------------------------------------------------------------------------------- */
ReferenceConstraint( );
/**---------------------------------------------------------------------------------------
Destructor
--------------------------------------------------------------------------------------- */
~ReferenceConstraint( );
};
class ReferenceShakeConstraint : public ReferenceConstraint {
private:
// force heavy atom into index 0
int _atomIndices[2];
RealOpenMM _inverseMasses[2];
RealOpenMM _constraintDistance;
public:
/**---------------------------------------------------------------------------------------
Constructor
@param atomIndex1 atom index 1
@param atomIndex2 atom index 2
@param distance distance constraint
@param inverseMass1 inverseMass of atom 1
@param inverseMass2 inverseMass of atom 2
--------------------------------------------------------------------------------------- */
ReferenceShakeConstraint( int atomIndex1, int atomIndex2, RealOpenMM distance,
RealOpenMM inverseMass1, RealOpenMM inverseMass2 );
/**---------------------------------------------------------------------------------------
Destructor
--------------------------------------------------------------------------------------- */
~ReferenceShakeConstraint( );
/**---------------------------------------------------------------------------------------
Get constraint distance
@return distance
--------------------------------------------------------------------------------------- */
RealOpenMM getConstraintDistance( void );
/**---------------------------------------------------------------------------------------
Get inverse mass of heavy atom
@return inverse mass
--------------------------------------------------------------------------------------- */
RealOpenMM getHeavyAtomInverseMass( void );
/**---------------------------------------------------------------------------------------
Get inverse mass of light atom
@return inverse mass
--------------------------------------------------------------------------------------- */
RealOpenMM getLightAtomInverseMass( void );
/**---------------------------------------------------------------------------------------
Get index of heavy atom
@return index
--------------------------------------------------------------------------------------- */
int getHeavyAtomIndex( void );
/**---------------------------------------------------------------------------------------
Get index of light atom
@return index
--------------------------------------------------------------------------------------- */
int getLightAtomIndex( void );
};
// ---------------------------------------------------------------------------------------
#endif // __ReferenceShakeConstraint_H__
/* Portions copyright (c) 2009 Stanford University and Simbios. /* Portions copyright (c) 2009-2013 Stanford University and Simbios.
* Contributors: Peter Eastman * Contributors: Peter Eastman
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -36,54 +36,34 @@ public: ...@@ -36,54 +36,34 @@ public:
virtual ~ReferenceConstraintAlgorithm() {}; virtual ~ReferenceConstraintAlgorithm() {};
/**--------------------------------------------------------------------------------------- /**
* Get the constraint tolerance.
Get the constraint tolerance */
--------------------------------------------------------------------------------------- */
virtual RealOpenMM getTolerance() const = 0; virtual RealOpenMM getTolerance() const = 0;
/**--------------------------------------------------------------------------------------- /**
* Set the constraint tolerance.
Set the constraint tolerance */
--------------------------------------------------------------------------------------- */
virtual void setTolerance(RealOpenMM tolerance) = 0; virtual void setTolerance(RealOpenMM tolerance) = 0;
/**--------------------------------------------------------------------------------------- /**
* Apply the constraint algorithm.
Apply constraint algorithm *
* @param atomCoordinates the original atom coordinates
@param numberOfAtoms number of atoms * @param atomCoordinatesP the new atom coordinates
@param atomCoordinates atom coordinates * @param inverseMasses 1/mass
@param atomCoordinatesP atom coordinates prime */
@param inverseMasses 1/mass virtual void apply(std::vector<OpenMM::RealVec>& atomCoordinates,
@return SimTKOpenMMCommon::DefaultReturn if converge; else
return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
virtual int apply(int numberOfAtoms, std::vector<OpenMM::RealVec>& atomCoordinates,
std::vector<OpenMM::RealVec>& atomCoordinatesP, std::vector<RealOpenMM>& inverseMasses) = 0; std::vector<OpenMM::RealVec>& atomCoordinatesP, std::vector<RealOpenMM>& inverseMasses) = 0;
/**--------------------------------------------------------------------------------------- /**
* Apply the constraint algorithm to velocities.
Apply constraint algorithm to velocities. *
* @param atomCoordinates the atom coordinates
@param numberOfAtoms number of atoms * @param atomCoordinatesP the velocities to modify
@param atomCoordinates atom coordinates * @param inverseMasses 1/mass
@param velocities atom velocities */
@param inverseMasses 1/mass virtual void applyToVelocities(std::vector<OpenMM::RealVec>& atomCoordinates,
@return SimTKOpenMMCommon::DefaultReturn if converge; else
return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
virtual int applyToVelocities(int numberOfAtoms, std::vector<OpenMM::RealVec>& atomCoordinates,
std::vector<OpenMM::RealVec>& velocities, std::vector<RealOpenMM>& inverseMasses) = 0; std::vector<OpenMM::RealVec>& velocities, std::vector<RealOpenMM>& inverseMasses) = 0;
}; };
......
#ifndef OPENMM_REFERENCECONSTRAINTS_H_
#define OPENMM_REFERENCECONSTRAINTS_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) 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 "ReferenceConstraintAlgorithm.h"
#include "ReferenceCCMAAlgorithm.h"
#include "ReferenceSETTLEAlgorithm.h"
#include "openmm/System.h"
namespace OpenMM {
/**
* This class uses multiple algorithms to apply constraints as efficiently as possible. It identifies clusters
* of three atoms that can be handled by SETTLE, and creates a ReferenceSETTLEAlgorithm object to handle them.
* It then creates a ReferenceCCMAAlgorithm object to handle any remaining constraints.
*/
class OPENMM_EXPORT ReferenceConstraints : public ReferenceConstraintAlgorithm {
public:
ReferenceConstraints(const System& system, RealOpenMM tolerance);
~ReferenceConstraints();
/**
* Get the constraint tolerance.
*/
RealOpenMM getTolerance() const;
/**
* Set the constraint tolerance.
*/
void setTolerance(RealOpenMM tolerance);
/**
* Apply the constraint algorithm.
*
* @param atomCoordinates the original atom coordinates
* @param atomCoordinatesP the new atom coordinates
* @param inverseMasses 1/mass
*/
void apply(std::vector<OpenMM::RealVec>& atomCoordinates, std::vector<OpenMM::RealVec>& atomCoordinatesP, std::vector<RealOpenMM>& inverseMasses);
/**
* Apply the constraint algorithm to velocities.
*
* @param atomCoordinates the atom coordinates
* @param atomCoordinatesP the velocities to modify
* @param inverseMasses 1/mass
*/
void applyToVelocities(std::vector<OpenMM::RealVec>& atomCoordinates, std::vector<OpenMM::RealVec>& velocities, std::vector<RealOpenMM>& inverseMasses);
private:
RealOpenMM tolerance;
ReferenceCCMAAlgorithm* ccma;
ReferenceSETTLEAlgorithm* settle;
};
} // namespace OpenMM
#endif /*OPENMM_REFERENCECONSTRAINTS_H_*/
/* Portions copyright (c) 2010 Stanford University and Simbios. /* Portions copyright (c) 2010-2013 Stanford University and Simbios.
* Contributors: Peter Eastman * Contributors: Peter Eastman
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -25,17 +25,20 @@ ...@@ -25,17 +25,20 @@
#define __ReferenceCustomAngleIxn_H__ #define __ReferenceCustomAngleIxn_H__
#include "ReferenceBondIxn.h" #include "ReferenceBondIxn.h"
#include "lepton/ExpressionProgram.h" #include "lepton/CompiledExpression.h"
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
class ReferenceCustomAngleIxn : public ReferenceBondIxn { class ReferenceCustomAngleIxn : public ReferenceBondIxn {
private: private:
Lepton::ExpressionProgram energyExpression; Lepton::CompiledExpression energyExpression;
Lepton::ExpressionProgram forceExpression; Lepton::CompiledExpression forceExpression;
std::vector<std::string> paramNames; std::vector<double*> energyParams;
std::map<std::string, double> globalParameters; std::vector<double*> forceParams;
double* energyTheta;
double* forceTheta;
int numParameters;
public: public:
...@@ -45,7 +48,7 @@ class ReferenceCustomAngleIxn : public ReferenceBondIxn { ...@@ -45,7 +48,7 @@ class ReferenceCustomAngleIxn : public ReferenceBondIxn {
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
ReferenceCustomAngleIxn(const Lepton::ExpressionProgram& energyExpression, const Lepton::ExpressionProgram& forceExpression, ReferenceCustomAngleIxn(const Lepton::CompiledExpression& energyExpression, const Lepton::CompiledExpression& forceExpression,
const std::vector<std::string>& parameterNames, std::map<std::string, double> globalParameters); const std::vector<std::string>& parameterNames, std::map<std::string, double> globalParameters);
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
......
/* Portions copyright (c) 2009 Stanford University and Simbios. /* Portions copyright (c) 2009-2013 Stanford University and Simbios.
* Contributors: Peter Eastman * Contributors: Peter Eastman
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -26,17 +26,20 @@ ...@@ -26,17 +26,20 @@
#define __ReferenceCustomBondIxn_H__ #define __ReferenceCustomBondIxn_H__
#include "ReferenceBondIxn.h" #include "ReferenceBondIxn.h"
#include "lepton/ExpressionProgram.h" #include "lepton/CompiledExpression.h"
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
class ReferenceCustomBondIxn : public ReferenceBondIxn { class ReferenceCustomBondIxn : public ReferenceBondIxn {
private: private:
Lepton::ExpressionProgram energyExpression; Lepton::CompiledExpression energyExpression;
Lepton::ExpressionProgram forceExpression; Lepton::CompiledExpression forceExpression;
std::vector<std::string> paramNames; std::vector<double*> energyParams;
std::map<std::string, double> globalParameters; std::vector<double*> forceParams;
double* energyR;
double* forceR;
int numParameters;
public: public:
...@@ -46,7 +49,7 @@ class ReferenceCustomBondIxn : public ReferenceBondIxn { ...@@ -46,7 +49,7 @@ class ReferenceCustomBondIxn : public ReferenceBondIxn {
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
ReferenceCustomBondIxn(const Lepton::ExpressionProgram& energyExpression, const Lepton::ExpressionProgram& forceExpression, ReferenceCustomBondIxn(const Lepton::CompiledExpression& energyExpression, const Lepton::CompiledExpression& forceExpression,
const std::vector<std::string>& parameterNames, std::map<std::string, double> globalParameters); const std::vector<std::string>& parameterNames, std::map<std::string, double> globalParameters);
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
......
/* Portions copyright (c) 2009 Stanford University and Simbios. /* Portions copyright (c) 2009-2013 Stanford University and Simbios.
* Contributors: Peter Eastman * Contributors: Peter Eastman
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -26,19 +26,26 @@ ...@@ -26,19 +26,26 @@
#define __ReferenceCustomExternalIxn_H__ #define __ReferenceCustomExternalIxn_H__
#include "ReferenceCustomExternalIxn.h" #include "ReferenceCustomExternalIxn.h"
#include "lepton/ExpressionProgram.h" #include "lepton/CompiledExpression.h"
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
class ReferenceCustomExternalIxn { class ReferenceCustomExternalIxn {
private: private:
Lepton::ExpressionProgram energyExpression; Lepton::CompiledExpression energyExpression;
Lepton::ExpressionProgram forceExpressionX; Lepton::CompiledExpression forceExpressionX;
Lepton::ExpressionProgram forceExpressionY; Lepton::CompiledExpression forceExpressionY;
Lepton::ExpressionProgram forceExpressionZ; Lepton::CompiledExpression forceExpressionZ;
std::vector<std::string> paramNames; std::vector<double*> energyParams;
std::map<std::string, double> globalParameters; std::vector<double*> forceXParams;
std::vector<double*> forceYParams;
std::vector<double*> forceZParams;
double *energyX, *energyY, *energyZ;
double *forceXX, *forceXY, *forceXZ;
double *forceYX, *forceYY, *forceYZ;
double *forceZX, *forceZY, *forceZZ;
int numParameters;
public: public:
...@@ -48,8 +55,8 @@ class ReferenceCustomExternalIxn { ...@@ -48,8 +55,8 @@ class ReferenceCustomExternalIxn {
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
ReferenceCustomExternalIxn(const Lepton::ExpressionProgram& energyExpression, const Lepton::ExpressionProgram& forceExpressionX, ReferenceCustomExternalIxn(const Lepton::CompiledExpression& energyExpression, const Lepton::CompiledExpression& forceExpressionX,
const Lepton::ExpressionProgram& forceExpressionY, const Lepton::ExpressionProgram& forceExpressionZ, const Lepton::CompiledExpression& forceExpressionY, const Lepton::CompiledExpression& forceExpressionZ,
const std::vector<std::string>& parameterNames, std::map<std::string, double> globalParameters); const std::vector<std::string>& parameterNames, std::map<std::string, double> globalParameters);
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
......
/* Portions copyright (c) 2009 Stanford University and Simbios. /* Portions copyright (c) 2009-2013 Stanford University and Simbios.
* Contributors: Peter Eastman * Contributors: Peter Eastman
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include "ReferencePairIxn.h" #include "ReferencePairIxn.h"
#include "ReferenceNeighborList.h" #include "ReferenceNeighborList.h"
#include "lepton/ExpressionProgram.h" #include "lepton/CompiledExpression.h"
#include <map> #include <map>
#include <set> #include <set>
#include <utility> #include <utility>
...@@ -45,10 +45,13 @@ class ReferenceCustomNonbondedIxn { ...@@ -45,10 +45,13 @@ class ReferenceCustomNonbondedIxn {
const OpenMM::NeighborList* neighborList; const OpenMM::NeighborList* neighborList;
RealOpenMM periodicBoxSize[3]; RealOpenMM periodicBoxSize[3];
RealOpenMM cutoffDistance, switchingDistance; RealOpenMM cutoffDistance, switchingDistance;
Lepton::ExpressionProgram energyExpression; Lepton::CompiledExpression energyExpression;
Lepton::ExpressionProgram forceExpression; Lepton::CompiledExpression forceExpression;
std::vector<std::string> paramNames; std::vector<std::string> paramNames;
std::vector<std::string> particleParamNames; std::vector<double*> energyParticleParams;
std::vector<double*> forceParticleParams;
double* energyR;
double* forceR;
std::vector<std::pair<std::set<int>, std::set<int> > > interactionGroups; std::vector<std::pair<std::set<int>, std::set<int> > > interactionGroups;
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
...@@ -65,9 +68,8 @@ class ReferenceCustomNonbondedIxn { ...@@ -65,9 +68,8 @@ class ReferenceCustomNonbondedIxn {
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
void calculateOneIxn( int atom1, int atom2, std::vector<OpenMM::RealVec>& atomCoordinates, void calculateOneIxn( int atom1, int atom2, std::vector<OpenMM::RealVec>& atomCoordinates, std::vector<OpenMM::RealVec>& forces,
std::map<std::string, double>& variables, std::vector<OpenMM::RealVec>& forces, RealOpenMM* energyByAtom, RealOpenMM* totalEnergy );
RealOpenMM* energyByAtom, RealOpenMM* totalEnergy ) const;
public: public:
...@@ -78,7 +80,7 @@ class ReferenceCustomNonbondedIxn { ...@@ -78,7 +80,7 @@ class ReferenceCustomNonbondedIxn {
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
ReferenceCustomNonbondedIxn(const Lepton::ExpressionProgram& energyExpression, const Lepton::ExpressionProgram& forceExpression, ReferenceCustomNonbondedIxn(const Lepton::CompiledExpression& energyExpression, const Lepton::CompiledExpression& forceExpression,
const std::vector<std::string>& parameterNames); const std::vector<std::string>& parameterNames);
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
...@@ -153,7 +155,7 @@ class ReferenceCustomNonbondedIxn { ...@@ -153,7 +155,7 @@ class ReferenceCustomNonbondedIxn {
void calculatePairIxn( int numberOfAtoms, std::vector<OpenMM::RealVec>& atomCoordinates, void calculatePairIxn( int numberOfAtoms, std::vector<OpenMM::RealVec>& atomCoordinates,
RealOpenMM** atomParameters, std::vector<std::set<int> >& exclusions, RealOpenMM** atomParameters, std::vector<std::set<int> >& exclusions,
RealOpenMM* fixedParameters, const std::map<std::string, double>& globalParameters, RealOpenMM* fixedParameters, const std::map<std::string, double>& globalParameters,
std::vector<OpenMM::RealVec>& forces, RealOpenMM* energyByAtom, RealOpenMM* totalEnergy ) const; std::vector<OpenMM::RealVec>& forces, RealOpenMM* energyByAtom, RealOpenMM* totalEnergy );
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
......
/* Portions copyright (c) 2010 Stanford University and Simbios. /* Portions copyright (c) 2010-2013 Stanford University and Simbios.
* Contributors: Peter Eastman * Contributors: Peter Eastman
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -25,17 +25,20 @@ ...@@ -25,17 +25,20 @@
#define __ReferenceCustomTorsionIxn_H__ #define __ReferenceCustomTorsionIxn_H__
#include "ReferenceBondIxn.h" #include "ReferenceBondIxn.h"
#include "lepton/ExpressionProgram.h" #include "lepton/CompiledExpression.h"
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
class ReferenceCustomTorsionIxn : public ReferenceBondIxn { class ReferenceCustomTorsionIxn : public ReferenceBondIxn {
private: private:
Lepton::ExpressionProgram energyExpression; Lepton::CompiledExpression energyExpression;
Lepton::ExpressionProgram forceExpression; Lepton::CompiledExpression forceExpression;
std::vector<std::string> paramNames; std::vector<double*> energyParams;
std::map<std::string, double> globalParameters; std::vector<double*> forceParams;
double* energyTheta;
double* forceTheta;
int numParameters;
public: public:
...@@ -45,7 +48,7 @@ class ReferenceCustomTorsionIxn : public ReferenceBondIxn { ...@@ -45,7 +48,7 @@ class ReferenceCustomTorsionIxn : public ReferenceBondIxn {
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
ReferenceCustomTorsionIxn(const Lepton::ExpressionProgram& energyExpression, const Lepton::ExpressionProgram& forceExpression, ReferenceCustomTorsionIxn(const Lepton::CompiledExpression& energyExpression, const Lepton::CompiledExpression& forceExpression,
const std::vector<std::string>& parameterNames, std::map<std::string, double> globalParameters); const std::vector<std::string>& parameterNames, std::map<std::string, double> globalParameters);
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
......
/* Portions copyright (c) 2006-2013 Stanford University and Simbios.
/* Portions copyright (c) 2006 Stanford University and Simbios.
* Contributors: Pande Group * Contributors: Pande Group
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -25,6 +24,7 @@ ...@@ -25,6 +24,7 @@
#ifndef __ReferenceForce_H__ #ifndef __ReferenceForce_H__
#define __ReferenceForce_H__ #define __ReferenceForce_H__
#include "lepton/CompiledExpression.h"
#include "openmm/internal/windowsExport.h" #include "openmm/internal/windowsExport.h"
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
...@@ -109,6 +109,18 @@ class OPENMM_EXPORT ReferenceForce { ...@@ -109,6 +109,18 @@ class OPENMM_EXPORT ReferenceForce {
static void getDeltaROnly( const RealOpenMM* atomCoordinatesI, const RealOpenMM* atomCoordinatesJ, static void getDeltaROnly( const RealOpenMM* atomCoordinatesI, const RealOpenMM* atomCoordinatesJ,
RealOpenMM* deltaR ); RealOpenMM* deltaR );
/**
* Get a pointer to the memory for setting a variable in a CompiledExpression. If the expression
* does not use the specified variable, return NULL.
*/
static double* getVariablePointer(Lepton::CompiledExpression& expression, const std::string& name);
/**
* Set the value of a variable in a CompiledExpression, using the pointer that was returned by getVariablePointer().
*/
static void setVariable(double* pointer, double value);
}; };
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "openmm/kernels.h" #include "openmm/kernels.h"
#include "SimTKOpenMMRealType.h" #include "SimTKOpenMMRealType.h"
#include "ReferenceNeighborList.h" #include "ReferenceNeighborList.h"
#include "lepton/CompiledExpression.h"
#include "lepton/ExpressionProgram.h" #include "lepton/ExpressionProgram.h"
class CpuObc; class CpuObc;
...@@ -316,7 +317,7 @@ private: ...@@ -316,7 +317,7 @@ private:
int numBonds; int numBonds;
int **bondIndexArray; int **bondIndexArray;
RealOpenMM **bondParamArray; RealOpenMM **bondParamArray;
Lepton::ExpressionProgram energyExpression, forceExpression; Lepton::CompiledExpression energyExpression, forceExpression;
std::vector<std::string> parameterNames, globalParameterNames; std::vector<std::string> parameterNames, globalParameterNames;
}; };
...@@ -392,7 +393,7 @@ private: ...@@ -392,7 +393,7 @@ private:
int numAngles; int numAngles;
int **angleIndexArray; int **angleIndexArray;
RealOpenMM **angleParamArray; RealOpenMM **angleParamArray;
Lepton::ExpressionProgram energyExpression, forceExpression; Lepton::CompiledExpression energyExpression, forceExpression;
std::vector<std::string> parameterNames, globalParameterNames; std::vector<std::string> parameterNames, globalParameterNames;
}; };
...@@ -534,7 +535,7 @@ private: ...@@ -534,7 +535,7 @@ private:
int numTorsions; int numTorsions;
int **torsionIndexArray; int **torsionIndexArray;
RealOpenMM **torsionParamArray; RealOpenMM **torsionParamArray;
Lepton::ExpressionProgram energyExpression, forceExpression; Lepton::CompiledExpression energyExpression, forceExpression;
std::vector<std::string> parameterNames, globalParameterNames; std::vector<std::string> parameterNames, globalParameterNames;
}; };
...@@ -621,7 +622,7 @@ private: ...@@ -621,7 +622,7 @@ private:
CustomNonbondedForce* forceCopy; CustomNonbondedForce* forceCopy;
std::map<std::string, double> globalParamValues; std::map<std::string, double> globalParamValues;
std::vector<std::set<int> > exclusions; std::vector<std::set<int> > exclusions;
Lepton::ExpressionProgram energyExpression, forceExpression; Lepton::CompiledExpression energyExpression, forceExpression;
std::vector<std::string> parameterNames, globalParameterNames; std::vector<std::string> parameterNames, globalParameterNames;
std::vector<std::pair<std::set<int>, std::set<int> > > interactionGroups; std::vector<std::pair<std::set<int>, std::set<int> > > interactionGroups;
NonbondedMethod nonbondedMethod; NonbondedMethod nonbondedMethod;
...@@ -781,7 +782,7 @@ private: ...@@ -781,7 +782,7 @@ private:
int numParticles; int numParticles;
std::vector<int> particles; std::vector<int> particles;
RealOpenMM **particleParamArray; RealOpenMM **particleParamArray;
Lepton::ExpressionProgram energyExpression, forceExpressionX, forceExpressionY, forceExpressionZ; Lepton::CompiledExpression energyExpression, forceExpressionX, forceExpressionY, forceExpressionZ;
std::vector<std::string> parameterNames, globalParameterNames; std::vector<std::string> parameterNames, globalParameterNames;
}; };
......
...@@ -54,11 +54,11 @@ pme_t; ...@@ -54,11 +54,11 @@ pme_t;
*/ */
int int
pme_init(pme_t * ppme, pme_init(pme_t * ppme,
RealOpenMM ewaldcoeff, RealOpenMM ewaldcoeff,
int natoms, int natoms,
const int ngrid[3], const int ngrid[3],
int pme_order, int pme_order,
RealOpenMM epsilon_r); RealOpenMM epsilon_r);
/* /*
* Evaluate reciprocal space PME energy and forces. * Evaluate reciprocal space PME energy and forces.
...@@ -75,9 +75,9 @@ pme_init(pme_t * ppme, ...@@ -75,9 +75,9 @@ pme_init(pme_t * ppme,
*/ */
int int
pme_exec(pme_t pme, pme_exec(pme_t pme,
std::vector<OpenMM::RealVec>& atomCoordinates, const std::vector<OpenMM::RealVec>& atomCoordinates,
std::vector<OpenMM::RealVec>& forces, std::vector<OpenMM::RealVec>& forces,
RealOpenMM ** atomParameters, const std::vector<RealOpenMM>& charges,
const RealOpenMM periodicBoxSize[3], const RealOpenMM periodicBoxSize[3],
RealOpenMM * energy, RealOpenMM * energy,
RealOpenMM pme_virial[3][3]); RealOpenMM pme_virial[3][3]);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#ifndef __ReferencePairIxn_H__ #ifndef __ReferencePairIxn_H__
#define __ReferencePairIxn_H__ #define __ReferencePairIxn_H__
#include "RealVec.h"
#include "openmm/internal/windowsExport.h" #include "openmm/internal/windowsExport.h"
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
......
#ifndef OPENMM_REFERENCESETTLEALGORITHM_H_
#define OPENMM_REFERENCESETTLEALGORITHM_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) 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 "ReferenceConstraintAlgorithm.h"
#include <vector>
namespace OpenMM {
/**
* This implements the SETTLE algorithm for constraining water molecules.
*/
class OPENMM_EXPORT ReferenceSETTLEAlgorithm : public ReferenceConstraintAlgorithm {
public:
ReferenceSETTLEAlgorithm(const std::vector<int>& atom1, const std::vector<int>& atom2, const std::vector<int>& atom3,
const std::vector<RealOpenMM>& distance1, const std::vector<RealOpenMM>& distance2, std::vector<RealOpenMM>& masses, RealOpenMM tolerance);
/**
* Get the constraint tolerance.
*/
RealOpenMM getTolerance() const;
/**
* Set the constraint tolerance.
*/
void setTolerance(RealOpenMM tolerance);
/**
* Apply the constraint algorithm.
*
* @param atomCoordinates the original atom coordinates
* @param atomCoordinatesP the new atom coordinates
* @param inverseMasses 1/mass
*/
void apply(std::vector<OpenMM::RealVec>& atomCoordinates, std::vector<OpenMM::RealVec>& atomCoordinatesP, std::vector<RealOpenMM>& inverseMasses);
/**
* Apply the constraint algorithm to velocities.
*
* @param atomCoordinates the atom coordinates
* @param atomCoordinatesP the velocities to modify
* @param inverseMasses 1/mass
*/
void applyToVelocities(std::vector<OpenMM::RealVec>& atomCoordinates, std::vector<OpenMM::RealVec>& velocities, std::vector<RealOpenMM>& inverseMasses);
private:
RealOpenMM tolerance;
std::vector<int> atom1;
std::vector<int> atom2;
std::vector<int> atom3;
std::vector<RealOpenMM> distance1;
std::vector<RealOpenMM> distance2;
std::vector<RealOpenMM> masses;
};
} // namespace OpenMM
#endif /*OPENMM_REFERENCESETTLEALGORITHM_H_*/
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "ReferenceBrownianDynamics.h" #include "ReferenceBrownianDynamics.h"
#include "ReferenceCCMAAlgorithm.h" #include "ReferenceCCMAAlgorithm.h"
#include "ReferenceCMAPTorsionIxn.h" #include "ReferenceCMAPTorsionIxn.h"
#include "ReferenceConstraints.h"
#include "ReferenceCustomAngleIxn.h" #include "ReferenceCustomAngleIxn.h"
#include "ReferenceCustomBondIxn.h" #include "ReferenceCustomBondIxn.h"
#include "ReferenceCustomCompoundBondIxn.h" #include "ReferenceCustomCompoundBondIxn.h"
...@@ -132,20 +133,6 @@ static RealVec& extractBoxSize(ContextImpl& context) { ...@@ -132,20 +133,6 @@ static RealVec& extractBoxSize(ContextImpl& context) {
return *(RealVec*) data->periodicBoxSize; return *(RealVec*) data->periodicBoxSize;
} }
static void findAnglesForCCMA(const System& system, vector<ReferenceCCMAAlgorithm::AngleInfo>& angles) {
for (int i = 0; i < system.getNumForces(); i++) {
const HarmonicAngleForce* force = dynamic_cast<const HarmonicAngleForce*>(&system.getForce(i));
if (force != NULL) {
for (int j = 0; j < force->getNumAngles(); j++) {
int atom1, atom2, atom3;
double angle, k;
force->getAngleParameters(j, atom1, atom2, atom3, angle, k);
angles.push_back(ReferenceCCMAAlgorithm::AngleInfo(atom1, atom2, atom3, (RealOpenMM)angle));
}
}
}
}
/** /**
* Compute the kinetic energy of the system, possibly shifting the velocities in time to account * Compute the kinetic energy of the system, possibly shifting the velocities in time to account
* for a leapfrog integrator. * for a leapfrog integrator.
...@@ -173,7 +160,7 @@ static double computeShiftedKineticEnergy(ContextImpl& context, vector<double>& ...@@ -173,7 +160,7 @@ static double computeShiftedKineticEnergy(ContextImpl& context, vector<double>&
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
inverseMasses[i] = (masses[i] == 0 ? 0 : 1/masses[i]); inverseMasses[i] = (masses[i] == 0 ? 0 : 1/masses[i]);
constraints->setTolerance(1e-4); constraints->setTolerance(1e-4);
constraints->applyToVelocities(numParticles, posData, shiftedVel, inverseMasses); constraints->applyToVelocities(posData, shiftedVel, inverseMasses);
} }
// Compute the kinetic energy. // Compute the kinetic energy.
...@@ -315,17 +302,16 @@ void ReferenceApplyConstraintsKernel::initialize(const System& system) { ...@@ -315,17 +302,16 @@ void ReferenceApplyConstraintsKernel::initialize(const System& system) {
masses[i] = static_cast<RealOpenMM>(system.getParticleMass(i)); masses[i] = static_cast<RealOpenMM>(system.getParticleMass(i));
inverseMasses[i] = 1.0/masses[i]; inverseMasses[i] = 1.0/masses[i];
} }
numConstraints = system.getNumConstraints(); for (int i = 0; i < system.getNumConstraints(); ++i) {
constraintIndices.resize(numConstraints);
constraintDistances.resize(numConstraints);
for (int i = 0; i < numConstraints; ++i) {
int particle1, particle2; int particle1, particle2;
double distance; double distance;
system.getConstraintParameters(i, particle1, particle2, distance); system.getConstraintParameters(i, particle1, particle2, distance);
constraintIndices[i].first = particle1; if (system.getParticleMass(particle1) != 0 || system.getParticleMass(particle2) != 0) {
constraintIndices[i].second = particle2; constraintIndices.push_back(make_pair(particle1, particle2));
constraintDistances[i] = static_cast<RealOpenMM>(distance); constraintDistances.push_back(distance);
}
} }
numConstraints = constraintIndices.size();
} }
ReferenceApplyConstraintsKernel::~ReferenceApplyConstraintsKernel() { ReferenceApplyConstraintsKernel::~ReferenceApplyConstraintsKernel() {
...@@ -334,27 +320,21 @@ ReferenceApplyConstraintsKernel::~ReferenceApplyConstraintsKernel() { ...@@ -334,27 +320,21 @@ ReferenceApplyConstraintsKernel::~ReferenceApplyConstraintsKernel() {
} }
void ReferenceApplyConstraintsKernel::apply(ContextImpl& context, double tol) { void ReferenceApplyConstraintsKernel::apply(ContextImpl& context, double tol) {
if (constraints == NULL) { if (constraints == NULL)
vector<ReferenceCCMAAlgorithm::AngleInfo> angles; constraints = new ReferenceConstraints(context.getSystem(), (RealOpenMM) tol);
findAnglesForCCMA(context.getSystem(), angles);
constraints = new ReferenceCCMAAlgorithm(context.getSystem().getNumParticles(), numConstraints, constraintIndices, constraintDistances, masses, angles, tol);
}
vector<RealVec>& positions = extractPositions(context); vector<RealVec>& positions = extractPositions(context);
constraints->setTolerance(tol); constraints->setTolerance(tol);
constraints->apply(data.numParticles, positions, positions, inverseMasses); constraints->apply(positions, positions, inverseMasses);
ReferenceVirtualSites::computePositions(context.getSystem(), positions); ReferenceVirtualSites::computePositions(context.getSystem(), positions);
} }
void ReferenceApplyConstraintsKernel::applyToVelocities(ContextImpl& context, double tol) { void ReferenceApplyConstraintsKernel::applyToVelocities(ContextImpl& context, double tol) {
if (constraints == NULL) { if (constraints == NULL)
vector<ReferenceCCMAAlgorithm::AngleInfo> angles; constraints = new ReferenceConstraints(context.getSystem(), (RealOpenMM) tol);
findAnglesForCCMA(context.getSystem(), angles);
constraints = new ReferenceCCMAAlgorithm(context.getSystem().getNumParticles(), numConstraints, constraintIndices, constraintDistances, masses, angles, tol);
}
vector<RealVec>& positions = extractPositions(context); vector<RealVec>& positions = extractPositions(context);
vector<RealVec>& velocities = extractVelocities(context); vector<RealVec>& velocities = extractVelocities(context);
constraints->setTolerance(tol); constraints->setTolerance(tol);
constraints->applyToVelocities(data.numParticles, positions, velocities, inverseMasses); constraints->applyToVelocities(positions, velocities, inverseMasses);
} }
void ReferenceVirtualSitesKernel::initialize(const System& system) { void ReferenceVirtualSitesKernel::initialize(const System& system) {
...@@ -440,8 +420,8 @@ void ReferenceCalcCustomBondForceKernel::initialize(const System& system, const ...@@ -440,8 +420,8 @@ void ReferenceCalcCustomBondForceKernel::initialize(const System& system, const
// Parse the expression used to calculate the force. // Parse the expression used to calculate the force.
Lepton::ParsedExpression expression = Lepton::Parser::parse(force.getEnergyFunction()).optimize(); Lepton::ParsedExpression expression = Lepton::Parser::parse(force.getEnergyFunction()).optimize();
energyExpression = expression.createProgram(); energyExpression = expression.createCompiledExpression();
forceExpression = expression.differentiate("r").optimize().createProgram(); forceExpression = expression.differentiate("r").createCompiledExpression();
for (int i = 0; i < numParameters; i++) for (int i = 0; i < numParameters; i++)
parameterNames.push_back(force.getPerBondParameterName(i)); parameterNames.push_back(force.getPerBondParameterName(i));
for (int i = 0; i < force.getNumGlobalParameters(); i++) for (int i = 0; i < force.getNumGlobalParameters(); i++)
...@@ -554,8 +534,8 @@ void ReferenceCalcCustomAngleForceKernel::initialize(const System& system, const ...@@ -554,8 +534,8 @@ void ReferenceCalcCustomAngleForceKernel::initialize(const System& system, const
// Parse the expression used to calculate the force. // Parse the expression used to calculate the force.
Lepton::ParsedExpression expression = Lepton::Parser::parse(force.getEnergyFunction()).optimize(); Lepton::ParsedExpression expression = Lepton::Parser::parse(force.getEnergyFunction()).optimize();
energyExpression = expression.createProgram(); energyExpression = expression.createCompiledExpression();
forceExpression = expression.differentiate("theta").optimize().createProgram(); forceExpression = expression.differentiate("theta").createCompiledExpression();
for (int i = 0; i < numParameters; i++) for (int i = 0; i < numParameters; i++)
parameterNames.push_back(force.getPerAngleParameterName(i)); parameterNames.push_back(force.getPerAngleParameterName(i));
for (int i = 0; i < force.getNumGlobalParameters(); i++) for (int i = 0; i < force.getNumGlobalParameters(); i++)
...@@ -764,8 +744,8 @@ void ReferenceCalcCustomTorsionForceKernel::initialize(const System& system, con ...@@ -764,8 +744,8 @@ void ReferenceCalcCustomTorsionForceKernel::initialize(const System& system, con
// Parse the expression used to calculate the force. // Parse the expression used to calculate the force.
Lepton::ParsedExpression expression = Lepton::Parser::parse(force.getEnergyFunction()).optimize(); Lepton::ParsedExpression expression = Lepton::Parser::parse(force.getEnergyFunction()).optimize();
energyExpression = expression.createProgram(); energyExpression = expression.createCompiledExpression();
forceExpression = expression.differentiate("theta").optimize().createProgram(); forceExpression = expression.differentiate("theta").createCompiledExpression();
for (int i = 0; i < numParameters; i++) for (int i = 0; i < numParameters; i++)
parameterNames.push_back(force.getPerTorsionParameterName(i)); parameterNames.push_back(force.getPerTorsionParameterName(i));
for (int i = 0; i < force.getNumGlobalParameters(); i++) for (int i = 0; i < force.getNumGlobalParameters(); i++)
...@@ -1048,8 +1028,8 @@ void ReferenceCalcCustomNonbondedForceKernel::initialize(const System& system, c ...@@ -1048,8 +1028,8 @@ void ReferenceCalcCustomNonbondedForceKernel::initialize(const System& system, c
// Parse the various expressions used to calculate the force. // Parse the various expressions used to calculate the force.
Lepton::ParsedExpression expression = Lepton::Parser::parse(force.getEnergyFunction(), functions).optimize(); Lepton::ParsedExpression expression = Lepton::Parser::parse(force.getEnergyFunction(), functions).optimize();
energyExpression = expression.createProgram(); energyExpression = expression.createCompiledExpression();
forceExpression = expression.differentiate("r").optimize().createProgram(); forceExpression = expression.differentiate("r").createCompiledExpression();
for (int i = 0; i < numParameters; i++) for (int i = 0; i < numParameters; i++)
parameterNames.push_back(force.getPerParticleParameterName(i)); parameterNames.push_back(force.getPerParticleParameterName(i));
for (int i = 0; i < force.getNumGlobalParameters(); i++) { for (int i = 0; i < force.getNumGlobalParameters(); i++) {
...@@ -1446,10 +1426,10 @@ void ReferenceCalcCustomExternalForceKernel::initialize(const System& system, co ...@@ -1446,10 +1426,10 @@ void ReferenceCalcCustomExternalForceKernel::initialize(const System& system, co
// Parse the expression used to calculate the force. // Parse the expression used to calculate the force.
Lepton::ParsedExpression expression = Lepton::Parser::parse(force.getEnergyFunction()).optimize(); Lepton::ParsedExpression expression = Lepton::Parser::parse(force.getEnergyFunction()).optimize();
energyExpression = expression.createProgram(); energyExpression = expression.createCompiledExpression();
forceExpressionX = expression.differentiate("x").optimize().createProgram(); forceExpressionX = expression.differentiate("x").createCompiledExpression();
forceExpressionY = expression.differentiate("y").optimize().createProgram(); forceExpressionY = expression.differentiate("y").createCompiledExpression();
forceExpressionZ = expression.differentiate("z").optimize().createProgram(); forceExpressionZ = expression.differentiate("z").createCompiledExpression();
for (int i = 0; i < numParameters; i++) for (int i = 0; i < numParameters; i++)
parameterNames.push_back(force.getPerParticleParameterName(i)); parameterNames.push_back(force.getPerParticleParameterName(i));
for (int i = 0; i < force.getNumGlobalParameters(); i++) for (int i = 0; i < force.getNumGlobalParameters(); i++)
...@@ -1715,20 +1695,19 @@ void ReferenceIntegrateVerletStepKernel::initialize(const System& system, const ...@@ -1715,20 +1695,19 @@ void ReferenceIntegrateVerletStepKernel::initialize(const System& system, const
masses.resize(numParticles); masses.resize(numParticles);
for (int i = 0; i < numParticles; ++i) for (int i = 0; i < numParticles; ++i)
masses[i] = static_cast<RealOpenMM>(system.getParticleMass(i)); masses[i] = static_cast<RealOpenMM>(system.getParticleMass(i));
numConstraints = system.getNumConstraints(); vector<pair<int, int> > constraintIndices;
vector<pair<int, int> > constraintIndices(numConstraints); vector<RealOpenMM> constraintDistances;
vector<RealOpenMM> constraintDistances(numConstraints); for (int i = 0; i < system.getNumConstraints(); ++i) {
for (int i = 0; i < numConstraints; ++i) {
int particle1, particle2; int particle1, particle2;
double distance; double distance;
system.getConstraintParameters(i, particle1, particle2, distance); system.getConstraintParameters(i, particle1, particle2, distance);
constraintIndices[i].first = particle1; if (system.getParticleMass(particle1) != 0 || system.getParticleMass(particle2) != 0) {
constraintIndices[i].second = particle2; constraintIndices.push_back(make_pair(particle1, particle2));
constraintDistances[i] = static_cast<RealOpenMM>(distance); constraintDistances.push_back(distance);
}
} }
vector<ReferenceCCMAAlgorithm::AngleInfo> angles; numConstraints = constraintIndices.size();
findAnglesForCCMA(system, angles); constraints = new ReferenceConstraints(system, (RealOpenMM) integrator.getConstraintTolerance());
constraints = new ReferenceCCMAAlgorithm(system.getNumParticles(), numConstraints, constraintIndices, constraintDistances, masses, angles, (RealOpenMM)integrator.getConstraintTolerance());
} }
void ReferenceIntegrateVerletStepKernel::execute(ContextImpl& context, const VerletIntegrator& integrator) { void ReferenceIntegrateVerletStepKernel::execute(ContextImpl& context, const VerletIntegrator& integrator) {
...@@ -1767,21 +1746,20 @@ void ReferenceIntegrateLangevinStepKernel::initialize(const System& system, cons ...@@ -1767,21 +1746,20 @@ void ReferenceIntegrateLangevinStepKernel::initialize(const System& system, cons
masses.resize(numParticles); masses.resize(numParticles);
for (int i = 0; i < numParticles; ++i) for (int i = 0; i < numParticles; ++i)
masses[i] = static_cast<RealOpenMM>(system.getParticleMass(i)); masses[i] = static_cast<RealOpenMM>(system.getParticleMass(i));
numConstraints = system.getNumConstraints(); vector<pair<int, int> > constraintIndices;
vector<pair<int, int> > constraintIndices(numConstraints); vector<RealOpenMM> constraintDistances;
vector<RealOpenMM> constraintDistances(numConstraints); for (int i = 0; i < system.getNumConstraints(); ++i) {
for (int i = 0; i < numConstraints; ++i) {
int particle1, particle2; int particle1, particle2;
double distance; double distance;
system.getConstraintParameters(i, particle1, particle2, distance); system.getConstraintParameters(i, particle1, particle2, distance);
constraintIndices[i].first = particle1; if (system.getParticleMass(particle1) != 0 || system.getParticleMass(particle2) != 0) {
constraintIndices[i].second = particle2; constraintIndices.push_back(make_pair(particle1, particle2));
constraintDistances[i] = static_cast<RealOpenMM>(distance); constraintDistances.push_back(distance);
}
} }
numConstraints = constraintIndices.size();
SimTKOpenMMUtilities::setRandomNumberSeed((unsigned int) integrator.getRandomNumberSeed()); SimTKOpenMMUtilities::setRandomNumberSeed((unsigned int) integrator.getRandomNumberSeed());
vector<ReferenceCCMAAlgorithm::AngleInfo> angles; constraints = new ReferenceConstraints(system, (RealOpenMM) integrator.getConstraintTolerance());
findAnglesForCCMA(system, angles);
constraints = new ReferenceCCMAAlgorithm(system.getNumParticles(), numConstraints, constraintIndices, constraintDistances, masses, angles, (RealOpenMM)integrator.getConstraintTolerance());
} }
void ReferenceIntegrateLangevinStepKernel::execute(ContextImpl& context, const LangevinIntegrator& integrator) { void ReferenceIntegrateLangevinStepKernel::execute(ContextImpl& context, const LangevinIntegrator& integrator) {
...@@ -1829,21 +1807,20 @@ void ReferenceIntegrateBrownianStepKernel::initialize(const System& system, cons ...@@ -1829,21 +1807,20 @@ void ReferenceIntegrateBrownianStepKernel::initialize(const System& system, cons
masses.resize(numParticles); masses.resize(numParticles);
for (int i = 0; i < numParticles; ++i) for (int i = 0; i < numParticles; ++i)
masses[i] = static_cast<RealOpenMM>(system.getParticleMass(i)); masses[i] = static_cast<RealOpenMM>(system.getParticleMass(i));
numConstraints = system.getNumConstraints(); vector<pair<int, int> > constraintIndices;
vector<pair<int, int> > constraintIndices(numConstraints); vector<RealOpenMM> constraintDistances;
vector<RealOpenMM> constraintDistances(numConstraints); for (int i = 0; i < system.getNumConstraints(); ++i) {
for (int i = 0; i < numConstraints; ++i) {
int particle1, particle2; int particle1, particle2;
double distance; double distance;
system.getConstraintParameters(i, particle1, particle2, distance); system.getConstraintParameters(i, particle1, particle2, distance);
constraintIndices[i].first = particle1; if (system.getParticleMass(particle1) != 0 || system.getParticleMass(particle2) != 0) {
constraintIndices[i].second = particle2; constraintIndices.push_back(make_pair(particle1, particle2));
constraintDistances[i] = static_cast<RealOpenMM>(distance); constraintDistances.push_back(distance);
}
} }
numConstraints = constraintIndices.size();
SimTKOpenMMUtilities::setRandomNumberSeed((unsigned int) integrator.getRandomNumberSeed()); SimTKOpenMMUtilities::setRandomNumberSeed((unsigned int) integrator.getRandomNumberSeed());
vector<ReferenceCCMAAlgorithm::AngleInfo> angles; constraints = new ReferenceConstraints(system, (RealOpenMM) integrator.getConstraintTolerance());
findAnglesForCCMA(system, angles);
constraints = new ReferenceCCMAAlgorithm(system.getNumParticles(), numConstraints, constraintIndices, constraintDistances, masses, angles, (RealOpenMM)integrator.getConstraintTolerance());
} }
void ReferenceIntegrateBrownianStepKernel::execute(ContextImpl& context, const BrownianIntegrator& integrator) { void ReferenceIntegrateBrownianStepKernel::execute(ContextImpl& context, const BrownianIntegrator& integrator) {
...@@ -1890,21 +1867,20 @@ void ReferenceIntegrateVariableLangevinStepKernel::initialize(const System& syst ...@@ -1890,21 +1867,20 @@ void ReferenceIntegrateVariableLangevinStepKernel::initialize(const System& syst
masses.resize(numParticles); masses.resize(numParticles);
for (int i = 0; i < numParticles; ++i) for (int i = 0; i < numParticles; ++i)
masses[i] = static_cast<RealOpenMM>(system.getParticleMass(i)); masses[i] = static_cast<RealOpenMM>(system.getParticleMass(i));
numConstraints = system.getNumConstraints(); vector<pair<int, int> > constraintIndices;
vector<pair<int, int> > constraintIndices(numConstraints); vector<RealOpenMM> constraintDistances;
vector<RealOpenMM> constraintDistances(numConstraints); for (int i = 0; i < system.getNumConstraints(); ++i) {
for (int i = 0; i < numConstraints; ++i) {
int particle1, particle2; int particle1, particle2;
double distance; double distance;
system.getConstraintParameters(i, particle1, particle2, distance); system.getConstraintParameters(i, particle1, particle2, distance);
constraintIndices[i].first = particle1; if (system.getParticleMass(particle1) != 0 || system.getParticleMass(particle2) != 0) {
constraintIndices[i].second = particle2; constraintIndices.push_back(make_pair(particle1, particle2));
constraintDistances[i] = static_cast<RealOpenMM>(distance); constraintDistances.push_back(distance);
}
} }
numConstraints = constraintIndices.size();
SimTKOpenMMUtilities::setRandomNumberSeed((unsigned int) integrator.getRandomNumberSeed()); SimTKOpenMMUtilities::setRandomNumberSeed((unsigned int) integrator.getRandomNumberSeed());
vector<ReferenceCCMAAlgorithm::AngleInfo> angles; constraints = new ReferenceConstraints(system, (RealOpenMM) integrator.getConstraintTolerance());
findAnglesForCCMA(system, angles);
constraints = new ReferenceCCMAAlgorithm(system.getNumParticles(), numConstraints, constraintIndices, constraintDistances, masses, angles, (RealOpenMM)integrator.getConstraintTolerance());
} }
double ReferenceIntegrateVariableLangevinStepKernel::execute(ContextImpl& context, const VariableLangevinIntegrator& integrator, double maxTime) { double ReferenceIntegrateVariableLangevinStepKernel::execute(ContextImpl& context, const VariableLangevinIntegrator& integrator, double maxTime) {
...@@ -1952,20 +1928,19 @@ void ReferenceIntegrateVariableVerletStepKernel::initialize(const System& system ...@@ -1952,20 +1928,19 @@ void ReferenceIntegrateVariableVerletStepKernel::initialize(const System& system
masses.resize(numParticles); masses.resize(numParticles);
for (int i = 0; i < numParticles; ++i) for (int i = 0; i < numParticles; ++i)
masses[i] = static_cast<RealOpenMM>(system.getParticleMass(i)); masses[i] = static_cast<RealOpenMM>(system.getParticleMass(i));
numConstraints = system.getNumConstraints(); vector<pair<int, int> > constraintIndices;
vector<pair<int, int> > constraintIndices(numConstraints); vector<RealOpenMM> constraintDistances;
vector<RealOpenMM> constraintDistances(numConstraints); for (int i = 0; i < system.getNumConstraints(); ++i) {
for (int i = 0; i < numConstraints; ++i) {
int particle1, particle2; int particle1, particle2;
double distance; double distance;
system.getConstraintParameters(i, particle1, particle2, distance); system.getConstraintParameters(i, particle1, particle2, distance);
constraintIndices[i].first = particle1; if (system.getParticleMass(particle1) != 0 || system.getParticleMass(particle2) != 0) {
constraintIndices[i].second = particle2; constraintIndices.push_back(make_pair(particle1, particle2));
constraintDistances[i] = static_cast<RealOpenMM>(distance); constraintDistances.push_back(distance);
}
} }
vector<ReferenceCCMAAlgorithm::AngleInfo> angles; numConstraints = constraintIndices.size();
findAnglesForCCMA(system, angles); constraints = new ReferenceConstraints(system, (RealOpenMM) integrator.getConstraintTolerance());
constraints = new ReferenceCCMAAlgorithm(system.getNumParticles(), numConstraints, constraintIndices, constraintDistances, masses, angles, (RealOpenMM)integrator.getConstraintTolerance());
} }
double ReferenceIntegrateVariableVerletStepKernel::execute(ContextImpl& context, const VariableVerletIntegrator& integrator, double maxTime) { double ReferenceIntegrateVariableVerletStepKernel::execute(ContextImpl& context, const VariableVerletIntegrator& integrator, double maxTime) {
...@@ -2008,17 +1983,18 @@ void ReferenceIntegrateCustomStepKernel::initialize(const System& system, const ...@@ -2008,17 +1983,18 @@ void ReferenceIntegrateCustomStepKernel::initialize(const System& system, const
masses.resize(numParticles); masses.resize(numParticles);
for (int i = 0; i < numParticles; ++i) for (int i = 0; i < numParticles; ++i)
masses[i] = static_cast<RealOpenMM>(system.getParticleMass(i)); masses[i] = static_cast<RealOpenMM>(system.getParticleMass(i));
numConstraints = system.getNumConstraints(); vector<pair<int, int> > constraintIndices;
vector<pair<int, int> > constraintIndices(numConstraints); vector<RealOpenMM> constraintDistances;
vector<RealOpenMM> constraintDistances(numConstraints); for (int i = 0; i < system.getNumConstraints(); ++i) {
for (int i = 0; i < numConstraints; ++i) {
int particle1, particle2; int particle1, particle2;
double distance; double distance;
system.getConstraintParameters(i, particle1, particle2, distance); system.getConstraintParameters(i, particle1, particle2, distance);
constraintIndices[i].first = particle1; if (system.getParticleMass(particle1) != 0 || system.getParticleMass(particle2) != 0) {
constraintIndices[i].second = particle2; constraintIndices.push_back(make_pair(particle1, particle2));
constraintDistances[i] = static_cast<RealOpenMM>(distance); constraintDistances.push_back(distance);
}
} }
numConstraints = constraintIndices.size();
perDofValues.resize(integrator.getNumPerDofVariables()); perDofValues.resize(integrator.getNumPerDofVariables());
for (int i = 0; i < (int) perDofValues.size(); i++) for (int i = 0; i < (int) perDofValues.size(); i++)
perDofValues[i].resize(numParticles); perDofValues[i].resize(numParticles);
...@@ -2026,9 +2002,8 @@ void ReferenceIntegrateCustomStepKernel::initialize(const System& system, const ...@@ -2026,9 +2002,8 @@ void ReferenceIntegrateCustomStepKernel::initialize(const System& system, const
// Create the computation objects. // Create the computation objects.
dynamics = new ReferenceCustomDynamics(system.getNumParticles(), integrator); dynamics = new ReferenceCustomDynamics(system.getNumParticles(), integrator);
vector<ReferenceCCMAAlgorithm::AngleInfo> angles; SimTKOpenMMUtilities::setRandomNumberSeed((unsigned int) integrator.getRandomNumberSeed());
findAnglesForCCMA(system, angles); constraints = new ReferenceConstraints(system, (RealOpenMM) integrator.getConstraintTolerance());
constraints = new ReferenceCCMAAlgorithm(system.getNumParticles(), numConstraints, constraintIndices, constraintDistances, masses, angles, (RealOpenMM)integrator.getConstraintTolerance());
dynamics->setReferenceConstraintAlgorithm(constraints); dynamics->setReferenceConstraintAlgorithm(constraints);
} }
......
/* Portions copyright (c) 2006-2012 Stanford University and Simbios. /* Portions copyright (c) 2006-2013 Stanford University and Simbios.
* Contributors: Peter Eastman, Pande Group * Contributors: Peter Eastman, Pande Group
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -161,8 +161,8 @@ void ReferenceBrownianDynamics::update(const OpenMM::System& system, vector<Real ...@@ -161,8 +161,8 @@ void ReferenceBrownianDynamics::update(const OpenMM::System& system, vector<Real
} }
} }
ReferenceConstraintAlgorithm* referenceConstraintAlgorithm = getReferenceConstraintAlgorithm(); ReferenceConstraintAlgorithm* referenceConstraintAlgorithm = getReferenceConstraintAlgorithm();
if( referenceConstraintAlgorithm ) if (referenceConstraintAlgorithm)
referenceConstraintAlgorithm->apply( numberOfAtoms, atomCoordinates, xPrime, inverseMasses ); referenceConstraintAlgorithm->apply(atomCoordinates, xPrime, inverseMasses);
// Update the positions and velocities. // Update the positions and velocities.
......
/* Portions copyright (c) 2006-2009 Stanford University and Simbios. /* Portions copyright (c) 2006-2013 Stanford University and Simbios.
* Contributors: Peter Eastman, Pande Group * Contributors: Peter Eastman, Pande Group
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "ReferenceCCMAAlgorithm.h" #include "ReferenceCCMAAlgorithm.h"
#include "ReferenceDynamics.h" #include "ReferenceDynamics.h"
#include "quern.h" #include "quern.h"
#include "openmm/OpenMMException.h"
#include "openmm/Vec3.h" #include "openmm/Vec3.h"
#include <map> #include <map>
...@@ -38,501 +39,269 @@ using std::map; ...@@ -38,501 +39,269 @@ using std::map;
using std::pair; using std::pair;
using std::vector; using std::vector;
using std::set; using std::set;
using OpenMM::OpenMMException;
using OpenMM::Vec3; using OpenMM::Vec3;
using OpenMM::RealVec; using OpenMM::RealVec;
/**--------------------------------------------------------------------------------------- ReferenceCCMAAlgorithm::ReferenceCCMAAlgorithm(int numberOfAtoms,
ReferenceCCMAAlgorithm constructor
@param numberOfAtoms number of atoms
@param numberOfConstraints number of constraints
@param atomIndices atom indices for contraints
@param distance distances for constraints
@param masses atom masses
@param angles angle force field terms
@param tolerance constraint tolerance
--------------------------------------------------------------------------------------- */
ReferenceCCMAAlgorithm::ReferenceCCMAAlgorithm( int numberOfAtoms,
int numberOfConstraints, int numberOfConstraints,
const vector<pair<int, int> >& atomIndices, const vector<pair<int, int> >& atomIndices,
const vector<RealOpenMM>& distance, const vector<RealOpenMM>& distance,
vector<RealOpenMM>& masses, vector<RealOpenMM>& masses,
vector<AngleInfo>& angles, vector<AngleInfo>& angles,
RealOpenMM tolerance){ RealOpenMM tolerance) {
_numberOfConstraints = numberOfConstraints;
// --------------------------------------------------------------------------------------- _atomIndices = atomIndices;
_distance = distance;
// static const char* methodName = "\nReferenceCCMAAlgorithm::ReferenceCCMAAlgorithm";
static const RealOpenMM zero = 0.0;
static const RealOpenMM one = 1.0;
static const RealOpenMM two = 2.0;
static const RealOpenMM three = 3.0;
static const RealOpenMM oneM = -1.0;
static const int threeI = 3;
// ---------------------------------------------------------------------------------------
_numberOfConstraints = numberOfConstraints;
_atomIndices = atomIndices;
_distance = distance;
_maximumNumberOfIterations = 150;
_tolerance = tolerance;
_hasInitializedMasses = false;
// work arrays
if (_numberOfConstraints > 0) {
_r_ij.resize(numberOfConstraints);
_d_ij2 = SimTKOpenMMUtilities::allocateOneDRealOpenMMArray( numberOfConstraints, NULL, 1, zero, "dij_2" );
_distanceTolerance = SimTKOpenMMUtilities::allocateOneDRealOpenMMArray( numberOfConstraints, NULL, 1, zero, "distanceTolerance" );
_reducedMasses = SimTKOpenMMUtilities::allocateOneDRealOpenMMArray( numberOfConstraints, NULL, 1, zero, "reducedMasses" );
}
if (numberOfConstraints > 0)
{
// Compute the constraint coupling matrix
vector<vector<int> > atomAngles(numberOfAtoms);
for (int i = 0; i < (int) angles.size(); i++)
atomAngles[angles[i].atom2].push_back(i);
vector<vector<pair<int, double> > > matrix(numberOfConstraints);
for (int j = 0; j < numberOfConstraints; j++) {
for (int k = 0; k < numberOfConstraints; k++) {
if (j == k) {
matrix[j].push_back(pair<int, double>(j, 1.0));
continue;
}
double scale;
int atomj0 = _atomIndices[j].first;
int atomj1 = _atomIndices[j].second;
int atomk0 = _atomIndices[k].first;
int atomk1 = _atomIndices[k].second;
RealOpenMM invMass0 = one/masses[atomj0];
RealOpenMM invMass1 = one/masses[atomj1];
int atoma, atomb, atomc;
if (atomj0 == atomk0) {
atoma = atomj1;
atomb = atomj0;
atomc = atomk1;
scale = invMass0/(invMass0+invMass1);
}
else if (atomj1 == atomk1) {
atoma = atomj0;
atomb = atomj1;
atomc = atomk0;
scale = invMass1/(invMass0+invMass1);
}
else if (atomj0 == atomk1) {
atoma = atomj1;
atomb = atomj0;
atomc = atomk0;
scale = invMass0/(invMass0+invMass1);
}
else if (atomj1 == atomk0) {
atoma = atomj0;
atomb = atomj1;
atomc = atomk1;
scale = invMass1/(invMass0+invMass1);
}
else
continue; // These constraints are not connected.
// Look for a third constraint forming a triangle with these two.
bool foundConstraint = false;
for (int other = 0; other < numberOfConstraints; other++) {
if ((_atomIndices[other].first == atoma && _atomIndices[other].second == atomc) || (_atomIndices[other].first == atomc && _atomIndices[other].second == atoma)) {
double d1 = _distance[j];
double d2 = _distance[k];
double d3 = _distance[other];
matrix[j].push_back(pair<int, double>(k, scale*(d1*d1+d2*d2-d3*d3)/(2.0*d1*d2)));
foundConstraint = true;
break;
}
}
if (!foundConstraint) {
// We didn't find one, so look for an angle force field term.
const vector<int>& angleCandidates = atomAngles[atomb];
for (vector<int>::const_iterator iter = angleCandidates.begin(); iter != angleCandidates.end(); iter++) {
const AngleInfo& angle = angles[*iter];
if ((angle.atom1 == atoma && angle.atom3 == atomc) || (angle.atom3 == atoma && angle.atom1 == atomc)) {
matrix[j].push_back(pair<int, double>(k, scale*cos(angle.angle)));
break;
}
}
}
}
}
// Invert it using QR.
vector<int> matrixRowStart;
vector<int> matrixColIndex;
vector<double> matrixValue;
for (int i = 0; i < numberOfConstraints; i++) {
matrixRowStart.push_back(matrixValue.size());
for (int j = 0; j < (int) matrix[i].size(); j++) {
pair<int, double> element = matrix[i][j];
matrixColIndex.push_back(element.first);
matrixValue.push_back(element.second);
}
}
matrixRowStart.push_back(matrixValue.size());
int *qRowStart, *qColIndex, *rRowStart, *rColIndex;
double *qValue, *rValue;
QUERN_compute_qr(numberOfConstraints, numberOfConstraints, &matrixRowStart[0], &matrixColIndex[0], &matrixValue[0], NULL,
&qRowStart, &qColIndex, &qValue, &rRowStart, &rColIndex, &rValue);
vector<double> rhs(numberOfConstraints);
_matrix.resize(numberOfConstraints);
for (int i = 0; i < numberOfConstraints; i++) {
// Extract column i of the inverse matrix.
for (int j = 0; j < numberOfConstraints; j++)
rhs[j] = (i == j ? 1.0 : 0.0);
QUERN_multiply_with_q_transpose(numberOfConstraints, qRowStart, qColIndex, qValue, &rhs[0]);
QUERN_solve_with_r(numberOfConstraints, rRowStart, rColIndex, rValue, &rhs[0], &rhs[0]);
for (int j = 0; j < numberOfConstraints; j++) {
double value = rhs[j]*_distance[i]/_distance[j];
if (FABS((RealOpenMM)value) > 0.02)
_matrix[j].push_back(pair<int, RealOpenMM>(i, (RealOpenMM) value));
}
}
QUERN_free_result(qRowStart, qColIndex, qValue);
QUERN_free_result(rRowStart, rColIndex, rValue);
}
}
/**---------------------------------------------------------------------------------------
ReferenceCCMAAlgorithm destructor _maximumNumberOfIterations = 150;
_tolerance = tolerance;
_hasInitializedMasses = false;
--------------------------------------------------------------------------------------- */ // work arrays
ReferenceCCMAAlgorithm::~ReferenceCCMAAlgorithm( ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceCCMAAlgorithm::~ReferenceCCMAAlgorithm";
// ---------------------------------------------------------------------------------------
if (_numberOfConstraints > 0) { if (_numberOfConstraints > 0) {
SimTKOpenMMUtilities::freeOneDRealOpenMMArray( _d_ij2, "d_ij2" ); _r_ij.resize(numberOfConstraints);
SimTKOpenMMUtilities::freeOneDRealOpenMMArray( _distanceTolerance, "distanceTolerance" ); _d_ij2 = SimTKOpenMMUtilities::allocateOneDRealOpenMMArray(numberOfConstraints, NULL, 1, 0.0, "dij_2");
SimTKOpenMMUtilities::freeOneDRealOpenMMArray( _reducedMasses, "reducedMasses" ); _distanceTolerance = SimTKOpenMMUtilities::allocateOneDRealOpenMMArray(numberOfConstraints, NULL, 1, 0.0, "distanceTolerance");
_reducedMasses = SimTKOpenMMUtilities::allocateOneDRealOpenMMArray(numberOfConstraints, NULL, 1, 0.0, "reducedMasses");
}
if (numberOfConstraints > 0)
{
// Compute the constraint coupling matrix
vector<vector<int> > atomAngles(numberOfAtoms);
for (int i = 0; i < (int) angles.size(); i++)
atomAngles[angles[i].atom2].push_back(i);
vector<vector<pair<int, double> > > matrix(numberOfConstraints);
for (int j = 0; j < numberOfConstraints; j++) {
for (int k = 0; k < numberOfConstraints; k++) {
if (j == k) {
matrix[j].push_back(pair<int, double>(j, 1.0));
continue;
}
double scale;
int atomj0 = _atomIndices[j].first;
int atomj1 = _atomIndices[j].second;
int atomk0 = _atomIndices[k].first;
int atomk1 = _atomIndices[k].second;
RealOpenMM invMass0 = 1/masses[atomj0];
RealOpenMM invMass1 = 1/masses[atomj1];
int atoma, atomb, atomc;
if (atomj0 == atomk0) {
atoma = atomj1;
atomb = atomj0;
atomc = atomk1;
scale = invMass0/(invMass0+invMass1);
}
else if (atomj1 == atomk1) {
atoma = atomj0;
atomb = atomj1;
atomc = atomk0;
scale = invMass1/(invMass0+invMass1);
}
else if (atomj0 == atomk1) {
atoma = atomj1;
atomb = atomj0;
atomc = atomk0;
scale = invMass0/(invMass0+invMass1);
}
else if (atomj1 == atomk0) {
atoma = atomj0;
atomb = atomj1;
atomc = atomk1;
scale = invMass1/(invMass0+invMass1);
}
else
continue; // These constraints are not connected.
// Look for a third constraint forming a triangle with these two.
bool foundConstraint = false;
for (int other = 0; other < numberOfConstraints; other++) {
if ((_atomIndices[other].first == atoma && _atomIndices[other].second == atomc) || (_atomIndices[other].first == atomc && _atomIndices[other].second == atoma)) {
double d1 = _distance[j];
double d2 = _distance[k];
double d3 = _distance[other];
matrix[j].push_back(pair<int, double>(k, scale*(d1*d1+d2*d2-d3*d3)/(2.0*d1*d2)));
foundConstraint = true;
break;
}
}
if (!foundConstraint) {
// We didn't find one, so look for an angle force field term.
const vector<int>& angleCandidates = atomAngles[atomb];
for (vector<int>::const_iterator iter = angleCandidates.begin(); iter != angleCandidates.end(); iter++) {
const AngleInfo& angle = angles[*iter];
if ((angle.atom1 == atoma && angle.atom3 == atomc) || (angle.atom3 == atoma && angle.atom1 == atomc)) {
matrix[j].push_back(pair<int, double>(k, scale*cos(angle.angle)));
break;
}
}
}
}
}
// Invert it using QR.
vector<int> matrixRowStart;
vector<int> matrixColIndex;
vector<double> matrixValue;
for (int i = 0; i < numberOfConstraints; i++) {
matrixRowStart.push_back(matrixValue.size());
for (int j = 0; j < (int) matrix[i].size(); j++) {
pair<int, double> element = matrix[i][j];
matrixColIndex.push_back(element.first);
matrixValue.push_back(element.second);
}
}
matrixRowStart.push_back(matrixValue.size());
int *qRowStart, *qColIndex, *rRowStart, *rColIndex;
double *qValue, *rValue;
QUERN_compute_qr(numberOfConstraints, numberOfConstraints, &matrixRowStart[0], &matrixColIndex[0], &matrixValue[0], NULL,
&qRowStart, &qColIndex, &qValue, &rRowStart, &rColIndex, &rValue);
vector<double> rhs(numberOfConstraints);
_matrix.resize(numberOfConstraints);
for (int i = 0; i < numberOfConstraints; i++) {
// Extract column i of the inverse matrix.
for (int j = 0; j < numberOfConstraints; j++)
rhs[j] = (i == j ? 1.0 : 0.0);
QUERN_multiply_with_q_transpose(numberOfConstraints, qRowStart, qColIndex, qValue, &rhs[0]);
QUERN_solve_with_r(numberOfConstraints, rRowStart, rColIndex, rValue, &rhs[0], &rhs[0]);
for (int j = 0; j < numberOfConstraints; j++) {
double value = rhs[j]*_distance[i]/_distance[j];
if (FABS((RealOpenMM)value) > 0.02)
_matrix[j].push_back(pair<int, RealOpenMM>(i, (RealOpenMM) value));
}
}
QUERN_free_result(qRowStart, qColIndex, qValue);
QUERN_free_result(rRowStart, rColIndex, rValue);
} }
} }
/**--------------------------------------------------------------------------------------- ReferenceCCMAAlgorithm::~ReferenceCCMAAlgorithm() {
if (_numberOfConstraints > 0) {
Get number of constraints SimTKOpenMMUtilities::freeOneDRealOpenMMArray(_d_ij2, "d_ij2");
SimTKOpenMMUtilities::freeOneDRealOpenMMArray(_distanceTolerance, "distanceTolerance");
@return number of constraints SimTKOpenMMUtilities::freeOneDRealOpenMMArray(_reducedMasses, "reducedMasses");
}
--------------------------------------------------------------------------------------- */
int ReferenceCCMAAlgorithm::getNumberOfConstraints( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceCCMAAlgorithm::getNumberOfConstraints";
// ---------------------------------------------------------------------------------------
return _numberOfConstraints;
} }
/**--------------------------------------------------------------------------------------- int ReferenceCCMAAlgorithm::getNumberOfConstraints() const {
return _numberOfConstraints;
Get maximum number of iterations
@return maximum number of iterations
--------------------------------------------------------------------------------------- */
int ReferenceCCMAAlgorithm::getMaximumNumberOfIterations( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceCCMAAlgorithm::getMaximumNumberOfIterations";
// ---------------------------------------------------------------------------------------
return _maximumNumberOfIterations;
} }
/**--------------------------------------------------------------------------------------- int ReferenceCCMAAlgorithm::getMaximumNumberOfIterations() const {
return _maximumNumberOfIterations;
Set maximum number of iterations
@param maximumNumberOfIterations new maximum number of iterations
--------------------------------------------------------------------------------------- */
void ReferenceCCMAAlgorithm::setMaximumNumberOfIterations( int maximumNumberOfIterations ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceCCMAAlgorithm::setMaximumNumberOfIterations";
// ---------------------------------------------------------------------------------------
_maximumNumberOfIterations = maximumNumberOfIterations;
} }
/**--------------------------------------------------------------------------------------- void ReferenceCCMAAlgorithm::setMaximumNumberOfIterations(int maximumNumberOfIterations) {
_maximumNumberOfIterations = maximumNumberOfIterations;
Get tolerance
@return tolerance
--------------------------------------------------------------------------------------- */
RealOpenMM ReferenceCCMAAlgorithm::getTolerance( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceCCMAAlgorithm::getTolerance";
// ---------------------------------------------------------------------------------------
return _tolerance;
} }
/**--------------------------------------------------------------------------------------- RealOpenMM ReferenceCCMAAlgorithm::getTolerance() const {
return _tolerance;
Set tolerance
@param tolerance new tolerance
--------------------------------------------------------------------------------------- */
void ReferenceCCMAAlgorithm::setTolerance( RealOpenMM tolerance ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceCCMAAlgorithm::setTolerance";
// ---------------------------------------------------------------------------------------
_tolerance = tolerance;;
} }
/**--------------------------------------------------------------------------------------- void ReferenceCCMAAlgorithm::setTolerance(RealOpenMM tolerance) {
_tolerance = tolerance;
Apply CCMA algorithm }
@param numberOfAtoms number of atoms
@param atomCoordinates atom coordinates
@param atomCoordinatesP atom coordinates prime
@param inverseMasses 1/mass
@return SimTKOpenMMCommon::DefaultReturn if converge; else
return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
int ReferenceCCMAAlgorithm::apply( int numberOfAtoms, vector<RealVec>& atomCoordinates, void ReferenceCCMAAlgorithm::apply(vector<RealVec>& atomCoordinates,
vector<RealVec>& atomCoordinatesP, vector<RealVec>& atomCoordinatesP,
vector<RealOpenMM>& inverseMasses ){ vector<RealOpenMM>& inverseMasses) {
return applyConstraints(numberOfAtoms, atomCoordinates, atomCoordinatesP, inverseMasses, false); applyConstraints(atomCoordinates, atomCoordinatesP, inverseMasses, false);
} }
/**--------------------------------------------------------------------------------------- void ReferenceCCMAAlgorithm::applyToVelocities(std::vector<OpenMM::RealVec>& atomCoordinates,
Apply constraint algorithm to velocities.
@param numberOfAtoms number of atoms
@param atomCoordinates atom coordinates
@param velocities atom velocities
@param inverseMasses 1/mass
@return SimTKOpenMMCommon::DefaultReturn if converge; else
return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
int ReferenceCCMAAlgorithm::applyToVelocities(int numberOfAtoms, std::vector<OpenMM::RealVec>& atomCoordinates,
std::vector<OpenMM::RealVec>& velocities, std::vector<RealOpenMM>& inverseMasses) { std::vector<OpenMM::RealVec>& velocities, std::vector<RealOpenMM>& inverseMasses) {
return applyConstraints(numberOfAtoms, atomCoordinates, velocities, inverseMasses, true); applyConstraints(atomCoordinates, velocities, inverseMasses, true);
} }
int ReferenceCCMAAlgorithm::applyConstraints(int numberOfAtoms, vector<RealVec>& atomCoordinates, void ReferenceCCMAAlgorithm::applyConstraints(vector<RealVec>& atomCoordinates,
vector<RealVec>& atomCoordinatesP, vector<RealVec>& atomCoordinatesP,
vector<RealOpenMM>& inverseMasses, bool constrainingVelocities){ vector<RealOpenMM>& inverseMasses, bool constrainingVelocities) {
// --------------------------------------------------------------------------------------- // temp arrays
static const char* methodName = "\nReferenceCCMAAlgorithm::apply"; vector<RealVec>& r_ij = _r_ij;
RealOpenMM* d_ij2 = _d_ij2;
static const RealOpenMM zero = 0.0; RealOpenMM* reducedMasses = _reducedMasses;
static const RealOpenMM one = 1.0;
static const RealOpenMM two = 2.0; // calculate reduced masses on 1st pass
static const RealOpenMM half = 0.5;
if (!_hasInitializedMasses) {
static const RealOpenMM epsilon6 = (RealOpenMM) 1.0e-06; _hasInitializedMasses = true;
for (int ii = 0; ii < _numberOfConstraints; ii++) {
// --------------------------------------------------------------------------------------- int atomI = _atomIndices[ii].first;
int atomJ = _atomIndices[ii].second;
// temp arrays reducedMasses[ii] = 0.5/(inverseMasses[atomI] + inverseMasses[atomJ]);
}
vector<RealVec>& r_ij = _r_ij; }
RealOpenMM* d_ij2 = _d_ij2;
RealOpenMM* reducedMasses = _reducedMasses;
// calculate reduced masses on 1st pass
if( !_hasInitializedMasses ){
_hasInitializedMasses = true;
for( int ii = 0; ii < _numberOfConstraints; ii++ ){
int atomI = _atomIndices[ii].first;
int atomJ = _atomIndices[ii].second;
reducedMasses[ii] = half/( inverseMasses[atomI] + inverseMasses[atomJ] );
}
}
// setup: r_ij for each (i,j) constraint
RealOpenMM tolerance = getTolerance();
tolerance *= two;
for( int ii = 0; ii < _numberOfConstraints; ii++ ){
int atomI = _atomIndices[ii].first;
int atomJ = _atomIndices[ii].second;
r_ij[ii] = atomCoordinates[atomI] - atomCoordinates[atomJ];
d_ij2[ii] = r_ij[ii].dot(r_ij[ii]);
}
RealOpenMM lowerTol = one-two*getTolerance()+getTolerance()*getTolerance();
RealOpenMM upperTol = one+two*getTolerance()+getTolerance()*getTolerance();
// main loop
int iterations = 0;
int numberConverged = 0;
vector<RealOpenMM> constraintDelta(_numberOfConstraints);
vector<RealOpenMM> tempDelta(_numberOfConstraints);
while (iterations < getMaximumNumberOfIterations()) {
numberConverged = 0;
for( int ii = 0; ii < _numberOfConstraints; ii++ ){
int atomI = _atomIndices[ii].first;
int atomJ = _atomIndices[ii].second;
RealVec rp_ij = atomCoordinatesP[atomI] - atomCoordinatesP[atomJ];
if (constrainingVelocities) {
RealOpenMM rrpr = rp_ij.dot(r_ij[ii]);
constraintDelta[ii] = -2*reducedMasses[ii]*rrpr/d_ij2[ii];
if (fabs(constraintDelta[ii]) <= getTolerance())
numberConverged++;
}
else {
RealOpenMM rp2 = rp_ij.dot(rp_ij);
RealOpenMM dist2 = _distance[ii]*_distance[ii];
RealOpenMM diff = dist2 - rp2;
constraintDelta[ii] = zero;
RealOpenMM rrpr = DOT3( rp_ij, r_ij[ii] );
if( rrpr < d_ij2[ii]*epsilon6 ){
std::stringstream message;
message << iterations <<" "<<atomI<<" "<<atomJ<< " Error: sign of rrpr < 0?\n";
SimTKOpenMMLog::printMessage( message );
} else {
constraintDelta[ii] = reducedMasses[ii]*diff/rrpr;
}
if (rp2 >= lowerTol*dist2 && rp2 <= upperTol*dist2)
numberConverged++;
}
}
if( numberConverged == _numberOfConstraints )
break;
iterations++;
if (_matrix.size() > 0) {
for (int i = 0; i < _numberOfConstraints; i++) {
RealOpenMM sum = 0.0;
for (int j = 0; j < (int) _matrix[i].size(); j++) {
pair<int, RealOpenMM> element = _matrix[i][j];
sum += element.second*constraintDelta[element.first];
}
tempDelta[i] = sum;
}
constraintDelta = tempDelta;
}
for( int ii = 0; ii < _numberOfConstraints; ii++ ){
int atomI = _atomIndices[ii].first;
int atomJ = _atomIndices[ii].second;
RealVec dr = r_ij[ii]*constraintDelta[ii];
atomCoordinatesP[atomI] += dr*inverseMasses[atomI];
atomCoordinatesP[atomJ] -= dr*inverseMasses[atomJ];
}
}
return (numberConverged == _numberOfConstraints ? SimTKOpenMMCommon::DefaultReturn : SimTKOpenMMCommon::ErrorReturn);
}
/**---------------------------------------------------------------------------------------
Report any violated constriants
@param numberOfAtoms number of atoms
@param atomCoordinates atom coordinates
@param message report
@return number of violated constraints
--------------------------------------------------------------------------------------- */
int ReferenceCCMAAlgorithm::reportCCMA( int numberOfAtoms, vector<RealVec>& atomCoordinates,
std::stringstream& message ){
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nReferenceCCMAAlgorithm::reportCCMA";
static const RealOpenMM zero = 0.0;
static const RealOpenMM one = 1.0;
static const RealOpenMM two = 2.0;
static const RealOpenMM three = 3.0;
static const RealOpenMM oneM = -1.0;
static const RealOpenMM half = 0.5;
// ---------------------------------------------------------------------------------------
int numberOfConstraints = getNumberOfConstraints();
// loop over constraints calculating distance and comparing to
// expected distance -- report any contraints that are violated
int numberConverged = 0;
RealOpenMM tolerance = getTolerance();
for( int ii = 0; ii < _numberOfConstraints; ii++ ){
int atomI = _atomIndices[ii].first;
int atomJ = _atomIndices[ii].second;
RealOpenMM rp2 = zero;
for( int jj = 0; jj < 3; jj++ ){
rp2 += (atomCoordinates[atomI][jj] - atomCoordinates[atomJ][jj])*(atomCoordinates[atomI][jj] - atomCoordinates[atomJ][jj]);
}
RealOpenMM diff = FABS( rp2 - (_distance[ii]*_distance[ii]) );
if( diff > tolerance ){
message << ii << " constraint violated: " << atomI << " " << atomJ << "] d=" << SQRT( rp2 ) << " " << rp2 << " d0=" << _distance[ii];
message << " diff=" << diff;
message << " [" << atomCoordinates[atomI][0] << " " << atomCoordinates[atomI][1] << " " << atomCoordinates[atomI][2] << "] ";
message << " [" << atomCoordinates[atomJ][0] << " " << atomCoordinates[atomJ][1] << " " << atomCoordinates[atomJ][2] << "] ";
message << "\n";
} else {
numberConverged++;
}
}
return (numberOfConstraints-numberConverged); // setup: r_ij for each (i,j) constraint
RealOpenMM tolerance = getTolerance()*2;
for (int ii = 0; ii < _numberOfConstraints; ii++) {
int atomI = _atomIndices[ii].first;
int atomJ = _atomIndices[ii].second;
r_ij[ii] = atomCoordinates[atomI] - atomCoordinates[atomJ];
d_ij2[ii] = r_ij[ii].dot(r_ij[ii]);
}
RealOpenMM lowerTol = 1-2*getTolerance()+getTolerance()*getTolerance();
RealOpenMM upperTol = 1+2*getTolerance()+getTolerance()*getTolerance();
// main loop
int iterations = 0;
int numberConverged = 0;
vector<RealOpenMM> constraintDelta(_numberOfConstraints);
vector<RealOpenMM> tempDelta(_numberOfConstraints);
while (iterations < getMaximumNumberOfIterations()) {
numberConverged = 0;
for (int ii = 0; ii < _numberOfConstraints; ii++) {
int atomI = _atomIndices[ii].first;
int atomJ = _atomIndices[ii].second;
RealVec rp_ij = atomCoordinatesP[atomI] - atomCoordinatesP[atomJ];
if (constrainingVelocities) {
RealOpenMM rrpr = rp_ij.dot(r_ij[ii]);
constraintDelta[ii] = -2*reducedMasses[ii]*rrpr/d_ij2[ii];
if (fabs(constraintDelta[ii]) <= getTolerance())
numberConverged++;
}
else {
RealOpenMM rp2 = rp_ij.dot(rp_ij);
RealOpenMM dist2 = _distance[ii]*_distance[ii];
RealOpenMM diff = dist2 - rp2;
constraintDelta[ii] = 0;
RealOpenMM rrpr = DOT3(rp_ij, r_ij[ii]);
constraintDelta[ii] = reducedMasses[ii]*diff/rrpr;
if (rp2 >= lowerTol*dist2 && rp2 <= upperTol*dist2)
numberConverged++;
}
}
if (numberConverged == _numberOfConstraints)
break;
iterations++;
if (_matrix.size() > 0) {
for (int i = 0; i < _numberOfConstraints; i++) {
RealOpenMM sum = 0.0;
for (int j = 0; j < (int) _matrix[i].size(); j++) {
pair<int, RealOpenMM> element = _matrix[i][j];
sum += element.second*constraintDelta[element.first];
}
tempDelta[i] = sum;
}
constraintDelta = tempDelta;
}
for (int ii = 0; ii < _numberOfConstraints; ii++) {
int atomI = _atomIndices[ii].first;
int atomJ = _atomIndices[ii].second;
RealVec dr = r_ij[ii]*constraintDelta[ii];
atomCoordinatesP[atomI] += dr*inverseMasses[atomI];
atomCoordinatesP[atomJ] -= dr*inverseMasses[atomJ];
}
}
} }
/* Portions copyright (c) 2006 Stanford University and Simbios.
* Contributors: 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 <string.h>
#include <sstream>
#include "SimTKOpenMMCommon.h"
#include "SimTKOpenMMLog.h"
#include "SimTKOpenMMUtilities.h"
#include "ReferenceConstraint.h"
#include "ReferenceDynamics.h"
/**---------------------------------------------------------------------------------------
ReferenceConstraint constructor
--------------------------------------------------------------------------------------- */
ReferenceConstraint::ReferenceConstraint( ){
// ---------------------------------------------------------------------------------------
//static const char* methodName = "\nReferenceConstraint::ReferenceConstraint";
// ---------------------------------------------------------------------------------------
}
/**---------------------------------------------------------------------------------------
ReferenceConstraint destructor
--------------------------------------------------------------------------------------- */
ReferenceConstraint::~ReferenceConstraint( ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceConstraint::~ReferenceConstraint";
// ---------------------------------------------------------------------------------------
}
/**---------------------------------------------------------------------------------------
ReferenceShakeConstraint constructor
@param numberOfAtoms number of atoms
@param deltaT delta t for dynamics
@param tau viscosity
@param temperature temperature
--------------------------------------------------------------------------------------- */
ReferenceShakeConstraint::ReferenceShakeConstraint( int atomIndex1, int atomIndex2,
RealOpenMM constraintDistance,
RealOpenMM inverseMass1,
RealOpenMM inverseMass2 ) : ReferenceConstraint( ) {
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nReferenceShakeConstraint::ReferenceShakeConstraint";
// ---------------------------------------------------------------------------------------
// insure heavy atom is in 0 slot
if( inverseMass1 > inverseMass2 ){
int temp = atomIndex1;
atomIndex1 = atomIndex2;
atomIndex2 = temp;
RealOpenMM tempR = inverseMass1;
inverseMass1 = inverseMass2;
inverseMass2 = tempR;
}
_atomIndices[0] = atomIndex1;
_atomIndices[1] = atomIndex2;
_inverseMasses[0] = inverseMass1;
_inverseMasses[1] = inverseMass2;
_constraintDistance = constraintDistance;
}
/**---------------------------------------------------------------------------------------
ReferenceShakeConstraint destructor
--------------------------------------------------------------------------------------- */
ReferenceShakeConstraint::~ReferenceShakeConstraint( ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceShakeConstraint::~ReferenceShakeConstraint";
// ---------------------------------------------------------------------------------------
}
/**---------------------------------------------------------------------------------------
Get constraint distance
@return constraintDistance
--------------------------------------------------------------------------------------- */
RealOpenMM ReferenceShakeConstraint::getConstraintDistance( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceShakeConstraint::getConstraintDistance";
// ---------------------------------------------------------------------------------------
return _constraintDistance;
}
/**---------------------------------------------------------------------------------------
Get inverse mass of heavy atom
@return inverse mass
--------------------------------------------------------------------------------------- */
RealOpenMM ReferenceShakeConstraint::getHeavyAtomInverseMass( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceShakeConstraint::getHeavyAtomInverseMass";
// ---------------------------------------------------------------------------------------
return _inverseMasses[0];
}
/**---------------------------------------------------------------------------------------
Get inverse mass of light atom
@return inverse mass
--------------------------------------------------------------------------------------- */
RealOpenMM ReferenceShakeConstraint::getLightAtomInverseMass( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceShakeConstraint::getLightAtomInverseMass";
// ---------------------------------------------------------------------------------------
return _inverseMasses[1];
}
/**---------------------------------------------------------------------------------------
Get index of heavy atom
@return index
--------------------------------------------------------------------------------------- */
int ReferenceShakeConstraint::getHeavyAtomIndex( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceShakeConstraint::getHeavyAtomIndex";
// ---------------------------------------------------------------------------------------
return _atomIndices[0];
}
/**---------------------------------------------------------------------------------------
Get index of light atom
@return index
--------------------------------------------------------------------------------------- */
int ReferenceShakeConstraint::getLightAtomIndex( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nReferenceShakeConstraint::getLightAtomIndex";
// ---------------------------------------------------------------------------------------
return _atomIndices[1];
}
/* -------------------------------------------------------------------------- *
* 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 "ReferenceConstraints.h"
#include "openmm/HarmonicAngleForce.h"
#include "openmm/OpenMMException.h"
#include <map>
#include <utility>
#include <vector>
using namespace OpenMM;
using namespace std;
ReferenceConstraints::ReferenceConstraints(const System& system, RealOpenMM tolerance) : ccma(NULL), settle(NULL) {
this->tolerance = tolerance;
int numParticles = system.getNumParticles();
vector<RealOpenMM> masses(numParticles);
for (int i = 0; i < numParticles; ++i)
masses[i] = (RealOpenMM) system.getParticleMass(i);
// Record the set of constraints and how many constraints each atom is involved in.
vector<int> atom1;
vector<int> atom2;
vector<double> distance;
vector<int> constraintCount(numParticles, 0);
for (int i = 0; i < system.getNumConstraints(); i++) {
int p1, p2;
double d;
system.getConstraintParameters(i, p1, p2, d);
if (masses[p1] != 0 || masses[p2] != 0) {
atom1.push_back(p1);
atom2.push_back(p2);
distance.push_back(d);
constraintCount[p1]++;
constraintCount[p2]++;
}
}
// Identify clusters of three atoms that can be treated with SETTLE. First, for every
// atom that might be part of such a cluster, make a list of the two other atoms it is
// connected to.
vector<map<int, float> > settleConstraints(numParticles);
for (int i = 0; i < (int)atom1.size(); i++) {
if (constraintCount[atom1[i]] == 2 && constraintCount[atom2[i]] == 2) {
settleConstraints[atom1[i]][atom2[i]] = (float) distance[i];
settleConstraints[atom2[i]][atom1[i]] = (float) distance[i];
}
}
// Now remove the ones that don't actually form closed loops of three atoms.
vector<int> settleClusters;
for (int i = 0; i < (int)settleConstraints.size(); i++) {
if (settleConstraints[i].size() == 2) {
int partner1 = settleConstraints[i].begin()->first;
int partner2 = (++settleConstraints[i].begin())->first;
if (settleConstraints[partner1].size() != 2 || settleConstraints[partner2].size() != 2 ||
settleConstraints[partner1].find(partner2) == settleConstraints[partner1].end())
settleConstraints[i].clear();
else if (i < partner1 && i < partner2)
settleClusters.push_back(i);
}
else
settleConstraints[i].clear();
}
// Record the SETTLE clusters.
vector<bool> isSettleAtom(numParticles, false);
int numSETTLE = settleClusters.size();
if (numSETTLE > 0) {
vector<int> atom1(numSETTLE);
vector<int> atom2(numSETTLE);
vector<int> atom3(numSETTLE);
vector<RealOpenMM> distance1(numSETTLE);
vector<RealOpenMM> distance2(numSETTLE);
for (int i = 0; i < numSETTLE; i++) {
int p1 = settleClusters[i];
int p2 = settleConstraints[p1].begin()->first;
int p3 = (++settleConstraints[p1].begin())->first;
float dist12 = settleConstraints[p1].find(p2)->second;
float dist13 = settleConstraints[p1].find(p3)->second;
float dist23 = settleConstraints[p2].find(p3)->second;
if (dist12 == dist13) {
// p1 is the central atom
atom1[i] = p1;
atom2[i] = p2;
atom3[i] = p3;
distance1[i] = dist12;
distance2[i] = dist23;
}
else if (dist12 == dist23) {
// p2 is the central atom
atom1[i] = p2;
atom2[i] = p1;
atom3[i] = p3;
distance1[i] = dist12;
distance2[i] = dist13;
}
else if (dist13 == dist23) {
// p3 is the central atom
atom1[i] = p3;
atom2[i] = p1;
atom3[i] = p2;
distance1[i] = dist13;
distance2[i] = dist12;
}
else
throw OpenMMException("Two of the three distances constrained with SETTLE must be the same.");
isSettleAtom[p1] = true;
isSettleAtom[p2] = true;
isSettleAtom[p3] = true;
}
settle = new ReferenceSETTLEAlgorithm(atom1, atom2, atom3, distance1, distance2, masses, tolerance);
}
// All other constraints are handled with CCMA.
vector<int> ccmaConstraints;
for (unsigned i = 0; i < atom1.size(); i++)
if (!isSettleAtom[atom1[i]])
ccmaConstraints.push_back(i);
int numCCMA = ccmaConstraints.size();
if (numCCMA > 0) {
// Record particles and distances for CCMA.
vector<pair<int, int> > ccmaIndices(numCCMA);
vector<RealOpenMM> ccmaDistance(numCCMA);
for (int i = 0; i < numCCMA; i++) {
int index = ccmaConstraints[i];
ccmaIndices[i] = make_pair(atom1[index], atom2[index]);
ccmaDistance[i] = distance[index];
}
// Look up angles for CCMA.
vector<ReferenceCCMAAlgorithm::AngleInfo> angles;
for (int i = 0; i < system.getNumForces(); i++) {
const HarmonicAngleForce* force = dynamic_cast<const HarmonicAngleForce*>(&system.getForce(i));
if (force != NULL) {
for (int j = 0; j < force->getNumAngles(); j++) {
int atom1, atom2, atom3;
double angle, k;
force->getAngleParameters(j, atom1, atom2, atom3, angle, k);
angles.push_back(ReferenceCCMAAlgorithm::AngleInfo(atom1, atom2, atom3, (RealOpenMM) angle));
}
}
}
// Create the CCMA object.
ccma = new ReferenceCCMAAlgorithm(numParticles, numCCMA, ccmaIndices, ccmaDistance, masses, angles, tolerance);
}
}
ReferenceConstraints::~ReferenceConstraints() {
if (ccma != NULL)
delete ccma;
if (settle != NULL)
delete settle;
}
RealOpenMM ReferenceConstraints::getTolerance() const {
return tolerance;
}
void ReferenceConstraints::setTolerance(RealOpenMM tolerance) {
this->tolerance = tolerance;
if (ccma != NULL)
ccma->setTolerance(tolerance);
if (settle != NULL)
settle->setTolerance(tolerance);
}
void ReferenceConstraints::apply(vector<OpenMM::RealVec>& atomCoordinates, vector<OpenMM::RealVec>& atomCoordinatesP, vector<RealOpenMM>& inverseMasses) {
if (ccma != NULL)
ccma->apply(atomCoordinates, atomCoordinatesP, inverseMasses);
if (settle != NULL)
settle->apply(atomCoordinates, atomCoordinatesP, inverseMasses);
}
void ReferenceConstraints::applyToVelocities(vector<OpenMM::RealVec>& atomCoordinates, vector<OpenMM::RealVec>& velocities, vector<RealOpenMM>& inverseMasses) {
if (ccma != NULL)
ccma->applyToVelocities(atomCoordinates, velocities, inverseMasses);
if (settle != NULL)
settle->applyToVelocities(atomCoordinates, velocities, inverseMasses);
}
/* Portions copyright (c) 2010 Stanford University and Simbios. /* Portions copyright (c) 2010-2013 Stanford University and Simbios.
* Contributors: Peter Eastman * Contributors: Peter Eastman
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -39,16 +39,21 @@ using namespace std; ...@@ -39,16 +39,21 @@ using namespace std;
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
ReferenceCustomAngleIxn::ReferenceCustomAngleIxn(const Lepton::ExpressionProgram& energyExpression, ReferenceCustomAngleIxn::ReferenceCustomAngleIxn(const Lepton::CompiledExpression& energyExpression,
const Lepton::ExpressionProgram& forceExpression, const vector<string>& parameterNames, map<string, double> globalParameters) : const Lepton::CompiledExpression& forceExpression, const vector<string>& parameterNames, map<string, double> globalParameters) :
energyExpression(energyExpression), forceExpression(forceExpression), paramNames(parameterNames), globalParameters(globalParameters) { energyExpression(energyExpression), forceExpression(forceExpression) {
// --------------------------------------------------------------------------------------- energyTheta = ReferenceForce::getVariablePointer(this->energyExpression, "theta");
forceTheta = ReferenceForce::getVariablePointer(this->forceExpression, "theta");
// static const char* methodName = "\nReferenceCustomAngleIxn::ReferenceCustomAngleIxn"; numParameters = parameterNames.size();
for (int i = 0; i < (int) numParameters; i++) {
// --------------------------------------------------------------------------------------- energyParams.push_back(ReferenceForce::getVariablePointer(this->energyExpression, parameterNames[i]));
forceParams.push_back(ReferenceForce::getVariablePointer(this->forceExpression, parameterNames[i]));
}
for (map<string, double>::const_iterator iter = globalParameters.begin(); iter != globalParameters.end(); ++iter) {
ReferenceForce::setVariable(ReferenceForce::getVariablePointer(this->energyExpression, iter->first), iter->second);
ReferenceForce::setVariable(ReferenceForce::getVariablePointer(this->forceExpression, iter->first), iter->second);
}
} }
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
...@@ -91,9 +96,10 @@ void ReferenceCustomAngleIxn::calculateBondIxn( int* atomIndices, ...@@ -91,9 +96,10 @@ void ReferenceCustomAngleIxn::calculateBondIxn( int* atomIndices,
static const RealOpenMM one = 1.0; static const RealOpenMM one = 1.0;
RealOpenMM deltaR[2][ReferenceForce::LastDeltaRIndex]; RealOpenMM deltaR[2][ReferenceForce::LastDeltaRIndex];
map<string, double> variables = globalParameters; for (int i = 0; i < numParameters; i++) {
for (int i = 0; i < (int) paramNames.size(); ++i) ReferenceForce::setVariable(energyParams[i], parameters[i]);
variables[paramNames[i]] = parameters[i]; ReferenceForce::setVariable(forceParams[i], parameters[i]);
}
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
...@@ -118,12 +124,13 @@ void ReferenceCustomAngleIxn::calculateBondIxn( int* atomIndices, ...@@ -118,12 +124,13 @@ void ReferenceCustomAngleIxn::calculateBondIxn( int* atomIndices,
angle = PI_M; angle = PI_M;
else else
angle = ACOS(cosine); angle = ACOS(cosine);
variables["theta"] = angle; ReferenceForce::setVariable(energyTheta, angle);
ReferenceForce::setVariable(forceTheta, angle);
// Compute the force and energy, and apply them to the atoms. // Compute the force and energy, and apply them to the atoms.
RealOpenMM energy = (RealOpenMM) energyExpression.evaluate(variables); RealOpenMM energy = (RealOpenMM) energyExpression.evaluate();
RealOpenMM dEdR = (RealOpenMM) forceExpression.evaluate(variables); RealOpenMM dEdR = (RealOpenMM) forceExpression.evaluate();
RealOpenMM termA = dEdR/(deltaR[0][ReferenceForce::R2Index]*rp); RealOpenMM termA = dEdR/(deltaR[0][ReferenceForce::R2Index]*rp);
RealOpenMM termC = -dEdR/(deltaR[1][ReferenceForce::R2Index]*rp); RealOpenMM termC = -dEdR/(deltaR[1][ReferenceForce::R2Index]*rp);
......
/* Portions copyright (c) 2009 Stanford University and Simbios. /* Portions copyright (c) 2009-2013 Stanford University and Simbios.
* Contributors: Peter Eastman * Contributors: Peter Eastman
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -40,16 +40,20 @@ using namespace OpenMM; ...@@ -40,16 +40,20 @@ using namespace OpenMM;
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
ReferenceCustomBondIxn::ReferenceCustomBondIxn(const Lepton::ExpressionProgram& energyExpression, ReferenceCustomBondIxn::ReferenceCustomBondIxn(const Lepton::CompiledExpression& energyExpression,
const Lepton::ExpressionProgram& forceExpression, const vector<string>& parameterNames, map<string, double> globalParameters) : const Lepton::CompiledExpression& forceExpression, const vector<string>& parameterNames, map<string, double> globalParameters) :
energyExpression(energyExpression), forceExpression(forceExpression), paramNames(parameterNames), globalParameters(globalParameters) { energyExpression(energyExpression), forceExpression(forceExpression) {
energyR = ReferenceForce::getVariablePointer(this->energyExpression, "r");
// --------------------------------------------------------------------------------------- forceR = ReferenceForce::getVariablePointer(this->forceExpression, "r");
numParameters = parameterNames.size();
// static const char* methodName = "\nReferenceCustomBondIxn::ReferenceCustomBondIxn"; for (int i = 0; i < (int) numParameters; i++) {
energyParams.push_back(ReferenceForce::getVariablePointer(this->energyExpression, parameterNames[i]));
// --------------------------------------------------------------------------------------- forceParams.push_back(ReferenceForce::getVariablePointer(this->forceExpression, parameterNames[i]));
}
for (map<string, double>::const_iterator iter = globalParameters.begin(); iter != globalParameters.end(); ++iter) {
ReferenceForce::setVariable(ReferenceForce::getVariablePointer(this->energyExpression, iter->first), iter->second);
ReferenceForce::setVariable(ReferenceForce::getVariablePointer(this->forceExpression, iter->first), iter->second);
}
} }
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
...@@ -95,9 +99,10 @@ void ReferenceCustomBondIxn::calculateBondIxn( int* atomIndices, ...@@ -95,9 +99,10 @@ void ReferenceCustomBondIxn::calculateBondIxn( int* atomIndices,
static const RealOpenMM half = 0.5; static const RealOpenMM half = 0.5;
RealOpenMM deltaR[ReferenceForce::LastDeltaRIndex]; RealOpenMM deltaR[ReferenceForce::LastDeltaRIndex];
map<string, double> variables = globalParameters; for (int i = 0; i < numParameters; i++) {
for (int i = 0; i < (int) paramNames.size(); ++i) ReferenceForce::setVariable(energyParams[i], parameters[i]);
variables[paramNames[i]] = parameters[i]; ReferenceForce::setVariable(forceParams[i], parameters[i]);
}
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
...@@ -106,8 +111,10 @@ void ReferenceCustomBondIxn::calculateBondIxn( int* atomIndices, ...@@ -106,8 +111,10 @@ void ReferenceCustomBondIxn::calculateBondIxn( int* atomIndices,
int atomAIndex = atomIndices[0]; int atomAIndex = atomIndices[0];
int atomBIndex = atomIndices[1]; int atomBIndex = atomIndices[1];
ReferenceForce::getDeltaR( atomCoordinates[atomAIndex], atomCoordinates[atomBIndex], deltaR ); ReferenceForce::getDeltaR( atomCoordinates[atomAIndex], atomCoordinates[atomBIndex], deltaR );
variables["r"] = deltaR[ReferenceForce::RIndex];
RealOpenMM dEdR = (RealOpenMM) forceExpression.evaluate(variables); ReferenceForce::setVariable(energyR, deltaR[ReferenceForce::RIndex]);
ReferenceForce::setVariable(forceR, deltaR[ReferenceForce::RIndex]);
RealOpenMM dEdR = (RealOpenMM) forceExpression.evaluate();
dEdR = deltaR[ReferenceForce::RIndex] > zero ? (dEdR/deltaR[ReferenceForce::RIndex]) : zero; dEdR = deltaR[ReferenceForce::RIndex] > zero ? (dEdR/deltaR[ReferenceForce::RIndex]) : zero;
forces[atomAIndex][0] += dEdR*deltaR[ReferenceForce::XIndex]; forces[atomAIndex][0] += dEdR*deltaR[ReferenceForce::XIndex];
...@@ -119,5 +126,5 @@ void ReferenceCustomBondIxn::calculateBondIxn( int* atomIndices, ...@@ -119,5 +126,5 @@ void ReferenceCustomBondIxn::calculateBondIxn( int* atomIndices,
forces[atomBIndex][2] -= dEdR*deltaR[ReferenceForce::ZIndex]; forces[atomBIndex][2] -= dEdR*deltaR[ReferenceForce::ZIndex];
if (totalEnergy != NULL) if (totalEnergy != NULL)
*totalEnergy += (RealOpenMM) energyExpression.evaluate(variables); *totalEnergy += (RealOpenMM) energyExpression.evaluate();
} }
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