Commit 51828eaa authored by Peter Eastman's avatar Peter Eastman
Browse files

Merge branch 'master' into qc

parents cf8a03e8 5ed9dd65
......@@ -25,6 +25,7 @@
#include <string.h>
#include <sstream>
#include <complex>
#include <algorithm>
#include "SimTKOpenMMCommon.h"
#include "SimTKOpenMMLog.h"
......
......@@ -4,6 +4,7 @@
#include <cmath>
#include <iostream>
#include <cassert>
#include <algorithm>
using namespace std;
......
......@@ -24,6 +24,7 @@
#include <cstring>
#include <sstream>
#include <algorithm>
#include "SimTKOpenMMCommon.h"
#include "SimTKOpenMMLog.h"
......
......@@ -24,6 +24,7 @@
#include <string.h>
#include <sstream>
#include <algorithm>
#include "SimTKOpenMMCommon.h"
#include "SimTKOpenMMLog.h"
......
......@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2012 Stanford University and the Authors. *
* Portions copyright (c) 2012-2014 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -65,6 +65,24 @@ void ReferenceVirtualSites::computePositions(const OpenMM::System& system, vecto
RealVec cross = v12.cross(v13);
atomCoordinates[i] = atomCoordinates[p1] + v12*w12 + v13*w13 + cross*wcross;
}
else if (dynamic_cast<const LocalCoordinatesSite*>(&system.getVirtualSite(i)) != NULL) {
// A local coordinates site.
const LocalCoordinatesSite& site = dynamic_cast<const LocalCoordinatesSite&>(system.getVirtualSite(i));
int p1 = site.getParticle(0), p2 = site.getParticle(1), p3 = site.getParticle(2);
RealVec originWeights = site.getOriginWeights();
RealVec xWeights = site.getXWeights();
RealVec yWeights = site.getYWeights();
RealVec localPosition = site.getLocalPosition();
RealVec origin = atomCoordinates[p1]*originWeights[0] + atomCoordinates[p2]*originWeights[1] + atomCoordinates[p3]*originWeights[2];
RealVec xdir = atomCoordinates[p1]*xWeights[0] + atomCoordinates[p2]*xWeights[1] + atomCoordinates[p3]*xWeights[2];
RealVec ydir = atomCoordinates[p1]*yWeights[0] + atomCoordinates[p2]*yWeights[1] + atomCoordinates[p3]*yWeights[2];
RealVec zdir = xdir.cross(ydir);
xdir /= sqrt(xdir.dot(xdir));
zdir /= sqrt(zdir.dot(zdir));
ydir = zdir.cross(xdir);
atomCoordinates[i] = origin + xdir*localPosition[0] + ydir*localPosition[1] + zdir*localPosition[2];
}
}
}
......@@ -110,5 +128,75 @@ void ReferenceVirtualSites::distributeForces(const OpenMM::System& system, const
forces[p2] += f2;
forces[p3] += f3;
}
else if (dynamic_cast<const LocalCoordinatesSite*>(&system.getVirtualSite(i)) != NULL) {
// A local coordinates site.
const LocalCoordinatesSite& site = dynamic_cast<const LocalCoordinatesSite&>(system.getVirtualSite(i));
int p1 = site.getParticle(0), p2 = site.getParticle(1), p3 = site.getParticle(2);
RealVec originWeights = site.getOriginWeights();
RealVec wx = site.getXWeights();
RealVec wy = site.getYWeights();
RealVec localPosition = site.getLocalPosition();
RealVec xdir = atomCoordinates[p1]*wx[0] + atomCoordinates[p2]*wx[1] + atomCoordinates[p3]*wx[2];
RealVec ydir = atomCoordinates[p1]*wy[0] + atomCoordinates[p2]*wy[1] + atomCoordinates[p3]*wy[2];
RealVec zdir = xdir.cross(ydir);
RealOpenMM invNormXdir = 1.0/SQRT(xdir.dot(xdir));
RealOpenMM invNormZdir = 1.0/SQRT(zdir.dot(zdir));
RealVec dx = xdir*invNormXdir;
RealVec dz = zdir*invNormZdir;
RealVec dy = dz.cross(dx);
// The derivatives for this case are very complicated. They were computed with SymPy then simplified by hand.
RealOpenMM t11 = (wx[0]*ydir[0]-wy[0]*xdir[0])*invNormZdir;
RealOpenMM t12 = (wx[0]*ydir[1]-wy[0]*xdir[1])*invNormZdir;
RealOpenMM t13 = (wx[0]*ydir[2]-wy[0]*xdir[2])*invNormZdir;
RealOpenMM t21 = (wx[1]*ydir[0]-wy[1]*xdir[0])*invNormZdir;
RealOpenMM t22 = (wx[1]*ydir[1]-wy[1]*xdir[1])*invNormZdir;
RealOpenMM t23 = (wx[1]*ydir[2]-wy[1]*xdir[2])*invNormZdir;
RealOpenMM t31 = (wx[2]*ydir[0]-wy[2]*xdir[0])*invNormZdir;
RealOpenMM t32 = (wx[2]*ydir[1]-wy[2]*xdir[1])*invNormZdir;
RealOpenMM t33 = (wx[2]*ydir[2]-wy[2]*xdir[2])*invNormZdir;
RealOpenMM sx1 = t13*dz[1]-t12*dz[2];
RealOpenMM sy1 = t11*dz[2]-t13*dz[0];
RealOpenMM sz1 = t12*dz[0]-t11*dz[1];
RealOpenMM sx2 = t23*dz[1]-t22*dz[2];
RealOpenMM sy2 = t21*dz[2]-t23*dz[0];
RealOpenMM sz2 = t22*dz[0]-t21*dz[1];
RealOpenMM sx3 = t33*dz[1]-t32*dz[2];
RealOpenMM sy3 = t31*dz[2]-t33*dz[0];
RealOpenMM sz3 = t32*dz[0]-t31*dz[1];
RealVec wxScaled = wx*invNormXdir;
RealVec fp1 = localPosition*f[0];
RealVec fp2 = localPosition*f[1];
RealVec fp3 = localPosition*f[2];
forces[p1][0] += fp1[0]*wxScaled[0]*(1-dx[0]*dx[0]) + fp1[2]*(dz[0]*sx1 ) + fp1[1]*((-dx[0]*dy[0] )*wxScaled[0] + dy[0]*sx1 - dx[1]*t12 - dx[2]*t13) + f[0]*originWeights[0];
forces[p1][1] += fp1[0]*wxScaled[0]*( -dx[0]*dx[1]) + fp1[2]*(dz[0]*sy1+t13) + fp1[1]*((-dx[1]*dy[0]-dz[2])*wxScaled[0] + dy[0]*sy1 + dx[1]*t11);
forces[p1][2] += fp1[0]*wxScaled[0]*( -dx[0]*dx[2]) + fp1[2]*(dz[0]*sz1-t12) + fp1[1]*((-dx[2]*dy[0]+dz[1])*wxScaled[0] + dy[0]*sz1 + dx[2]*t11);
forces[p2][0] += fp1[0]*wxScaled[1]*(1-dx[0]*dx[0]) + fp1[2]*(dz[0]*sx2 ) + fp1[1]*((-dx[0]*dy[0] )*wxScaled[1] + dy[0]*sx2 - dx[1]*t22 - dx[2]*t23) + f[0]*originWeights[1];
forces[p2][1] += fp1[0]*wxScaled[1]*( -dx[0]*dx[1]) + fp1[2]*(dz[0]*sy2+t23) + fp1[1]*((-dx[1]*dy[0]-dz[2])*wxScaled[1] + dy[0]*sy2 + dx[1]*t21);
forces[p2][2] += fp1[0]*wxScaled[1]*( -dx[0]*dx[2]) + fp1[2]*(dz[0]*sz2-t22) + fp1[1]*((-dx[2]*dy[0]+dz[1])*wxScaled[1] + dy[0]*sz2 + dx[2]*t21);
forces[p3][0] += fp1[0]*wxScaled[2]*(1-dx[0]*dx[0]) + fp1[2]*(dz[0]*sx3 ) + fp1[1]*((-dx[0]*dy[0] )*wxScaled[2] + dy[0]*sx3 - dx[1]*t32 - dx[2]*t33) + f[0]*originWeights[2];
forces[p3][1] += fp1[0]*wxScaled[2]*( -dx[0]*dx[1]) + fp1[2]*(dz[0]*sy3+t33) + fp1[1]*((-dx[1]*dy[0]-dz[2])*wxScaled[2] + dy[0]*sy3 + dx[1]*t31);
forces[p3][2] += fp1[0]*wxScaled[2]*( -dx[0]*dx[2]) + fp1[2]*(dz[0]*sz3-t32) + fp1[1]*((-dx[2]*dy[0]+dz[1])*wxScaled[2] + dy[0]*sz3 + dx[2]*t31);
forces[p1][0] += fp2[0]*wxScaled[0]*( -dx[1]*dx[0]) + fp2[2]*(dz[1]*sx1-t13) - fp2[1]*(( dx[0]*dy[1]-dz[2])*wxScaled[0] - dy[1]*sx1 - dx[0]*t12);
forces[p1][1] += fp2[0]*wxScaled[0]*(1-dx[1]*dx[1]) + fp2[2]*(dz[1]*sy1 ) - fp2[1]*(( dx[1]*dy[1] )*wxScaled[0] - dy[1]*sy1 + dx[0]*t11 + dx[2]*t13) + f[1]*originWeights[0];
forces[p1][2] += fp2[0]*wxScaled[0]*( -dx[1]*dx[2]) + fp2[2]*(dz[1]*sz1+t11) - fp2[1]*(( dx[2]*dy[1]+dz[0])*wxScaled[0] - dy[1]*sz1 - dx[2]*t12);
forces[p2][0] += fp2[0]*wxScaled[1]*( -dx[1]*dx[0]) + fp2[2]*(dz[1]*sx2-t23) - fp2[1]*(( dx[0]*dy[1]-dz[2])*wxScaled[1] - dy[1]*sx2 - dx[0]*t22);
forces[p2][1] += fp2[0]*wxScaled[1]*(1-dx[1]*dx[1]) + fp2[2]*(dz[1]*sy2 ) - fp2[1]*(( dx[1]*dy[1] )*wxScaled[1] - dy[1]*sy2 + dx[0]*t21 + dx[2]*t23) + f[1]*originWeights[1];
forces[p2][2] += fp2[0]*wxScaled[1]*( -dx[1]*dx[2]) + fp2[2]*(dz[1]*sz2+t21) - fp2[1]*(( dx[2]*dy[1]+dz[0])*wxScaled[1] - dy[1]*sz2 - dx[2]*t22);
forces[p3][0] += fp2[0]*wxScaled[2]*( -dx[1]*dx[0]) + fp2[2]*(dz[1]*sx3-t33) - fp2[1]*(( dx[0]*dy[1]-dz[2])*wxScaled[2] - dy[1]*sx3 - dx[0]*t32);
forces[p3][1] += fp2[0]*wxScaled[2]*(1-dx[1]*dx[1]) + fp2[2]*(dz[1]*sy3 ) - fp2[1]*(( dx[1]*dy[1] )*wxScaled[2] - dy[1]*sy3 + dx[0]*t31 + dx[2]*t33) + f[1]*originWeights[2];
forces[p3][2] += fp2[0]*wxScaled[2]*( -dx[1]*dx[2]) + fp2[2]*(dz[1]*sz3+t31) - fp2[1]*(( dx[2]*dy[1]+dz[0])*wxScaled[2] - dy[1]*sz3 - dx[2]*t32);
forces[p1][0] += fp3[0]*wxScaled[0]*( -dx[2]*dx[0]) + fp3[2]*(dz[2]*sx1+t12) + fp3[1]*((-dx[0]*dy[2]-dz[1])*wxScaled[0] + dy[2]*sx1 + dx[0]*t13);
forces[p1][1] += fp3[0]*wxScaled[0]*( -dx[2]*dx[1]) + fp3[2]*(dz[2]*sy1-t11) + fp3[1]*((-dx[1]*dy[2]+dz[0])*wxScaled[0] + dy[2]*sy1 + dx[1]*t13);
forces[p1][2] += fp3[0]*wxScaled[0]*(1-dx[2]*dx[2]) + fp3[2]*(dz[2]*sz1 ) + fp3[1]*((-dx[2]*dy[2] )*wxScaled[0] + dy[2]*sz1 - dx[0]*t11 - dx[1]*t12) + f[2]*originWeights[0];
forces[p2][0] += fp3[0]*wxScaled[1]*( -dx[2]*dx[0]) + fp3[2]*(dz[2]*sx2+t22) + fp3[1]*((-dx[0]*dy[2]-dz[1])*wxScaled[1] + dy[2]*sx2 + dx[0]*t23);
forces[p2][1] += fp3[0]*wxScaled[1]*( -dx[2]*dx[1]) + fp3[2]*(dz[2]*sy2-t21) + fp3[1]*((-dx[1]*dy[2]+dz[0])*wxScaled[1] + dy[2]*sy2 + dx[1]*t23);
forces[p2][2] += fp3[0]*wxScaled[1]*(1-dx[2]*dx[2]) + fp3[2]*(dz[2]*sz2 ) + fp3[1]*((-dx[2]*dy[2] )*wxScaled[1] + dy[2]*sz2 - dx[0]*t21 - dx[1]*t22) + f[2]*originWeights[1];
forces[p3][0] += fp3[0]*wxScaled[2]*( -dx[2]*dx[0]) + fp3[2]*(dz[2]*sx3+t32) + fp3[1]*((-dx[0]*dy[2]-dz[1])*wxScaled[2] + dy[2]*sx3 + dx[0]*t33);
forces[p3][1] += fp3[0]*wxScaled[2]*( -dx[2]*dx[1]) + fp3[2]*(dz[2]*sy3-t31) + fp3[1]*((-dx[1]*dy[2]+dz[0])*wxScaled[2] + dy[2]*sy3 + dx[1]*t33);
forces[p3][2] += fp3[0]*wxScaled[2]*(1-dx[2]*dx[2]) + fp3[2]*(dz[2]*sz3 ) + fp3[1]*((-dx[2]*dy[2] )*wxScaled[2] + dy[2]*sz3 - dx[0]*t31 - dx[1]*t32) + f[2]*originWeights[2];
}
}
}
......@@ -33,6 +33,9 @@
* This tests the reference implementation of CustomCompoundBondForce.
*/
#ifdef WIN32
#define _USE_MATH_DEFINES // Needed to get M_PI
#endif
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "ReferencePlatform.h"
......@@ -284,7 +287,7 @@ void testMultipleBonds() {
parameters[0] = 1.0;
parameters[1] = 1.0;
parameters[2] = 2 * M_PI / 3;
parameters[3] = sqrt(3) / 2;
parameters[3] = sqrt(3.0) / 2;
vector<int> particles0(3);
particles0[0] = 0;
particles0[1] = 1;
......
File mode changed from 100755 to 100644
......@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2012 Stanford University and the Authors. *
* Portions copyright (c) 2012-2014 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -215,6 +215,85 @@ void testOutOfPlane() {
}
}
/**
* Test a LocalCoordinatesSite virtual site.
*/
void testLocalCoordinates() {
const Vec3 originWeights(0.2, 0.3, 0.5);
const Vec3 xWeights(-1.0, 0.5, 0.5);
const Vec3 yWeights(0.0, -1.0, 1.0);
const Vec3 localPosition(0.4, 0.3, 0.2);
ReferencePlatform platform;
System system;
system.addParticle(1.0);
system.addParticle(1.0);
system.addParticle(1.0);
system.addParticle(0.0);
system.setVirtualSite(3, new LocalCoordinatesSite(0, 1, 2, originWeights, xWeights, yWeights, localPosition));
CustomExternalForce* forceField = new CustomExternalForce("2*x^2+3*y^2+4*z^2");
system.addForce(forceField);
vector<double> params;
forceField->addParticle(0, params);
forceField->addParticle(1, params);
forceField->addParticle(2, params);
forceField->addParticle(3, params);
LangevinIntegrator integrator(300.0, 0.1, 0.002);
Context context(system, integrator, platform);
vector<Vec3> positions(4), positions2(4), positions3(4);
OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt);
for (int i = 0; i < 100; i++) {
// Set the particles at random positions.
Vec3 xdir, ydir, zdir;
do {
for (int j = 0; j < 3; j++)
positions[j] = Vec3(genrand_real2(sfmt), genrand_real2(sfmt), genrand_real2(sfmt));
xdir = positions[0]*xWeights[0] + positions[1]*xWeights[1] + positions[2]*xWeights[2];
ydir = positions[0]*yWeights[0] + positions[1]*yWeights[1] + positions[2]*yWeights[2];
zdir = xdir.cross(ydir);
if (sqrt(xdir.dot(xdir)) > 0.1 && sqrt(ydir.dot(ydir)) > 0.1 && sqrt(zdir.dot(zdir)) > 0.1)
break; // These positions give a reasonable coordinate system.
} while (true);
context.setPositions(positions);
context.applyConstraints(0.0001);
// See if the virtual site is positioned correctly.
State state = context.getState(State::Positions | State::Forces);
const vector<Vec3>& pos = state.getPositions();
Vec3 origin = pos[0]*originWeights[0] + pos[1]*originWeights[1] + pos[2]*originWeights[2];
xdir /= sqrt(xdir.dot(xdir));
zdir /= sqrt(zdir.dot(zdir));
ydir = zdir.cross(xdir);
ASSERT_EQUAL_VEC(origin+xdir*localPosition[0]+ydir*localPosition[1]+zdir*localPosition[2], pos[3], 1e-10);
// Take a small step in the direction of the energy gradient and see whether the potential energy changes by the expected amount.
double norm = 0.0;
for (int i = 0; i < 3; ++i) {
Vec3 f = state.getForces()[i];
norm += f[0]*f[0] + f[1]*f[1] + f[2]*f[2];
}
norm = std::sqrt(norm);
const double delta = 1e-2;
double step = 0.5*delta/norm;
for (int i = 0; i < 3; ++i) {
Vec3 p = positions[i];
Vec3 f = state.getForces()[i];
positions2[i] = Vec3(p[0]-f[0]*step, p[1]-f[1]*step, p[2]-f[2]*step);
positions3[i] = Vec3(p[0]+f[0]*step, p[1]+f[1]*step, p[2]+f[2]*step);
}
context.setPositions(positions2);
context.applyConstraints(0.0001);
State state2 = context.getState(State::Energy);
context.setPositions(positions3);
context.applyConstraints(0.0001);
State state3 = context.getState(State::Energy);
ASSERT_EQUAL_TOL(norm, (state2.getPotentialEnergy()-state3.getPotentialEnergy())/delta, 1e-3)
}
}
/**
* Make sure that energy, linear momentum, and angular momentum are all conserved
* when using virtual sites.
......@@ -282,6 +361,26 @@ void testConservationLaws() {
positions.push_back(Vec3(1, 1, -1));
positions.push_back(Vec3());
// Create a molecule with a LocalCoordinatesSite virtual site.
system.addParticle(1.0);
system.addParticle(1.0);
system.addParticle(1.0);
system.addParticle(0.0);
system.setVirtualSite(14, new LocalCoordinatesSite(11, 12, 13, Vec3(0.3, 0.3, 0.4), Vec3(1.0, -0.5, -0.5), Vec3(0, -1.0, 1.0), Vec3(0.2, 0.2, 1.0)));
system.addConstraint(11, 12, 1.0);
system.addConstraint(11, 13, 1.0);
system.addConstraint(12, 13, sqrt(2.0));
for (int i = 0; i < 4; i++) {
forceField->addParticle(0, 1, 10);
for (int j = 0; j < i; j++)
forceField->addException(i+11, j+11, 0, 1, 0);
}
positions.push_back(Vec3(1, 2, 0));
positions.push_back(Vec3(2, 2, 0));
positions.push_back(Vec3(1, 3, 0));
positions.push_back(Vec3());
// Simulate it and check conservation laws.
VerletIntegrator integrator(0.002);
......@@ -329,6 +428,7 @@ int main() {
testTwoParticleAverage();
testThreeParticleAverage();
testOutOfPlane();
testLocalCoordinates();
testConservationLaws();
}
catch(const exception& e) {
......
#---------------------------------------------------
# OpenMM Amoeba Plugin
#
# Creates OpenMM Amoeba plugin library, base name=OpenMMAmoeba.
# Default libraries are shared & optimized. Variants
# are created for static (_static) and debug (_d).
# Creates OpenMMAmoeba plugin library.
#
# Windows:
# OpenMMAmoeba[_d].dll
# OpenMMAmoeba[_d].lib
# OpenMMAmoeba_static[_d].lib
# OpenMMAmoeba.dll
# OpenMMAmoeba.lib
# OpenMMAmoeba_static.lib
# Unix:
# libOpenMMAmoeba[_d].so
# libOpenMMAmoeba_static[_d].a
# libOpenMMAmoeba.so
# libOpenMMAmoeba_static.a
#----------------------------------------------------
#INCLUDE(Dart)
......@@ -36,12 +34,6 @@ ADD_DEFINITIONS(-DOPENMM_AMOEBA_LIBRARY_NAME=${OPENMM_AMOEBA_LIBRARY_NAME}
SET(SHARED_AMOEBA_TARGET ${OPENMM_AMOEBA_LIBRARY_NAME})
SET(STATIC_AMOEBA_TARGET ${OPENMM_AMOEBA_LIBRARY_NAME}_static)
# But on Unix or Cygwin we have to add the suffix manually
IF (UNIX AND CMAKE_BUILD_TYPE MATCHES Debug)
SET(SHARED_AMOEBA_TARGET ${SHARED_AMOEBA_TARGET}_d)
SET(STATIC_AMOEBA_TARGET ${STATIC_AMOEBA_TARGET}_d)
ENDIF (UNIX AND CMAKE_BUILD_TYPE MATCHES Debug)
# These are all the places to search for header files which are
# to be part of the API.
SET(API_AMOEBA_INCLUDE_DIRS) # start empty
......@@ -123,10 +115,6 @@ IF(DL_LIBRARY)
ENDIF(DL_LIBRARY)
SET( OpenMMLib OpenMM )
# But on Unix or Cygwin we have to add the suffix manually
IF (UNIX AND CMAKE_BUILD_TYPE MATCHES Debug)
SET(OpenMMLib ${OpenMMLib}_d)
ENDIF (UNIX AND CMAKE_BUILD_TYPE MATCHES Debug)
TARGET_LINK_LIBRARIES( ${SHARED_AMOEBA_TARGET} ${SHARED_TARGET} )
IF(OPENMM_BUILD_STATIC_LIB)
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
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