Commit 505824d6 authored by peastman's avatar peastman
Browse files

Finished reference implementation of GayBerneForce

parent 4452d437
...@@ -44,20 +44,19 @@ namespace OpenMM { ...@@ -44,20 +44,19 @@ namespace OpenMM {
/** /**
* This class implements the Gay-Berne anisotropic potential. This is similar to a Lennard-Jones potential, * This class implements the Gay-Berne anisotropic potential. This is similar to a Lennard-Jones potential,
* but it represents the particles as ellipsoids rather than point particles. In addition to the standard * but it represents the particles as ellipsoids rather than point particles. In addition to the standard
* sigma and epsilon parameters, each particle has three radii r_x, r_y, and r_z that give the size of the * sigma and epsilon parameters, each particle has three widths sx, sy, and sz that give the diameter of the
* ellipsoid along each axis. It also has three scale factors e_x, e_y, and e_z that scale the strength * ellipsoid along each axis. It also has three scale factors ex, ey, and ez that scale the strength
* of the interaction along each axis. You can think of this force as a Lennard-Jones interaction computed * of the interaction along each axis. You can think of this force as a Lennard-Jones interaction computed
* based on the distance between the nearest points on two ellipsoids. The interpretation of the scale * based on the distance between the nearest points on two ellipsoids. The scale factors act as multipliers
* factors is slightly complicated, but roughly speaking, the strength of the interaction along the ellipsoid's * for epsilon along each axis, so the strength of the interaction along the ellipsoid's x axis is multiplied by
* x axis is divided by e_x^2, and likewise for the other axes. If two particles each have all their * ex, and likewise for the other axes. If two particles each have all their widths set to sigma and all their
* radii set to sigma/2 and all their scale factors set 1, the interaction simplifies to a standard Lennard-Jones * scale factors set to 1, the interaction simplifies to a standard Lennard-Jones force between point particles.
* force between point particles.
* *
* The orientation of a particle's ellipsoid is determined based on the positions of two other particles. * The orientation of a particle's ellipsoid is determined based on the positions of two other particles.
* The vector to the first particle sets the direction of the x axis. The vector to the second particle * The vector to the first particle sets the direction of the x axis. The vector to the second particle
* (after subtracting out any x component) sets the direction of the y axis. If the ellipsoid is axially * (after subtracting out any x component) sets the direction of the y axis. If the ellipsoid is axially
* symmetric (r_y=r_z and e_y=e_z), you can omit the second particle and define only an x axis direction. * symmetric (sy=sz and ey=ez), you can omit the second particle and define only an x axis direction.
* If the ellipsoid is a sphere (all three radii and all three scale factors are equal), both particles * If the ellipsoid is a sphere (all three widths and all three scale factors are equal), both particles
* can be omitted. * can be omitted.
* *
* To determine the values of sigma and epsilon for an interaction, this class uses Lorentz-Berthelot * To determine the values of sigma and epsilon for an interaction, this class uses Lorentz-Berthelot
...@@ -166,15 +165,15 @@ public: ...@@ -166,15 +165,15 @@ public:
* @param epsilon the epsilon parameter (corresponding to the well depth of the van der Waals interaction), measured in kJ/mol * @param epsilon the epsilon parameter (corresponding to the well depth of the van der Waals interaction), measured in kJ/mol
* @param xparticle the index of the particle whose position defines the ellipsoid's x axis, or -1 if the ellipsoid is a sphere * @param xparticle the index of the particle whose position defines the ellipsoid's x axis, or -1 if the ellipsoid is a sphere
* @param yparticle the index of the particle whose position defines the ellipsoid's y axis, or -1 if the ellipsoid is axially symmetric * @param yparticle the index of the particle whose position defines the ellipsoid's y axis, or -1 if the ellipsoid is axially symmetric
* @param rx the radius of the ellipsoid along its x axis * @param sx the diameter of the ellipsoid along its x axis
* @param ry the radius of the ellipsoid along its y axis * @param sy the diameter of the ellipsoid along its y axis
* @param rz the radius of the ellipsoid along its z axis * @param sz the diameter of the ellipsoid along its z axis
* @param ex the factor by which epsilon is scaled along the ellipsoid's x axis * @param ex the factor by which epsilon is scaled along the ellipsoid's x axis
* @param ey the factor by which epsilon is scaled along the ellipsoid's y axis * @param ey the factor by which epsilon is scaled along the ellipsoid's y axis
* @param ez the factor by which epsilon is scaled along the ellipsoid's z axis * @param ez the factor by which epsilon is scaled along the ellipsoid's z axis
* @return the index of the particle that was added * @return the index of the particle that was added
*/ */
int addParticle(double sigma, double epsilon, int xparticle, int yparticle, double rx, double ry, double rz, double ex, double ey, double ez); int addParticle(double sigma, double epsilon, int xparticle, int yparticle, double sx, double sy, double sz, double ex, double ey, double ez);
/** /**
* Get the parameters for a particle. * Get the parameters for a particle.
* *
...@@ -183,14 +182,14 @@ public: ...@@ -183,14 +182,14 @@ public:
* @param[out] epsilon the epsilon parameter (corresponding to the well depth of the van der Waals interaction), measured in kJ/mol * @param[out] epsilon the epsilon parameter (corresponding to the well depth of the van der Waals interaction), measured in kJ/mol
* @param[out] xparticle the index of the particle whose position defines the ellipsoid's x axis, or -1 if the ellipsoid is a sphere * @param[out] xparticle the index of the particle whose position defines the ellipsoid's x axis, or -1 if the ellipsoid is a sphere
* @param[out] yparticle the index of the particle whose position defines the ellipsoid's y axis, or -1 if the ellipsoid is axially symmetric * @param[out] yparticle the index of the particle whose position defines the ellipsoid's y axis, or -1 if the ellipsoid is axially symmetric
* @param[out] rx the radius of the ellipsoid along its x axis * @param[out] sx the diameter of the ellipsoid along its x axis
* @param[out] ry the radius of the ellipsoid along its y axis * @param[out] sy the diameter of the ellipsoid along its y axis
* @param[out] rz the radius of the ellipsoid along its z axis * @param[out] sz the diameter of the ellipsoid along its z axis
* @param[out] ex the factor by which epsilon is scaled along the ellipsoid's x axis * @param[out] ex the factor by which epsilon is scaled along the ellipsoid's x axis
* @param[out] ey the factor by which epsilon is scaled along the ellipsoid's y axis * @param[out] ey the factor by which epsilon is scaled along the ellipsoid's y axis
* @param[out] ez the factor by which epsilon is scaled along the ellipsoid's z axis * @param[out] ez the factor by which epsilon is scaled along the ellipsoid's z axis
*/ */
void getParticleParameters(int index, double& sigma, double& epsilon, int& xparticle, int& yparticle, double& rx, double& ry, double& rz, double& ex, double& ey, double& ez) const; void getParticleParameters(int index, double& sigma, double& epsilon, int& xparticle, int& yparticle, double& sx, double& sy, double& sz, double& ex, double& ey, double& ez) const;
/** /**
* Set the parameters for a particle. * Set the parameters for a particle.
* *
...@@ -199,14 +198,14 @@ public: ...@@ -199,14 +198,14 @@ public:
* @param epsilon the epsilon parameter (corresponding to the well depth of the van der Waals interaction), measured in kJ/mol * @param epsilon the epsilon parameter (corresponding to the well depth of the van der Waals interaction), measured in kJ/mol
* @param xparticle the index of the particle whose position defines the ellipsoid's x axis, or -1 if the ellipsoid is a sphere * @param xparticle the index of the particle whose position defines the ellipsoid's x axis, or -1 if the ellipsoid is a sphere
* @param yparticle the index of the particle whose position defines the ellipsoid's y axis, or -1 if the ellipsoid is axially symmetric * @param yparticle the index of the particle whose position defines the ellipsoid's y axis, or -1 if the ellipsoid is axially symmetric
* @param rx the radius of the ellipsoid along its x axis * @param sx the diameter of the ellipsoid along its x axis
* @param ry the radius of the ellipsoid along its y axis * @param sy the diameter of the ellipsoid along its y axis
* @param rz the radius of the ellipsoid along its z axis * @param sz the diameter of the ellipsoid along its z axis
* @param ex the factor by which epsilon is scaled along the ellipsoid's x axis * @param ex the factor by which epsilon is scaled along the ellipsoid's x axis
* @param ey the factor by which epsilon is scaled along the ellipsoid's y axis * @param ey the factor by which epsilon is scaled along the ellipsoid's y axis
* @param ez the factor by which epsilon is scaled along the ellipsoid's z axis * @param ez the factor by which epsilon is scaled along the ellipsoid's z axis
*/ */
void setParticleParameters(int index, double sigma, double epsilon, int xparticle, int yparticle, double rx, double ry, double rz, double ex, double ey, double ez); void setParticleParameters(int index, double sigma, double epsilon, int xparticle, int yparticle, double sx, double sy, double sz, double ex, double ey, double ez);
/** /**
* Add an interaction to the list of exceptions that should be calculated differently from other interactions. If * Add an interaction to the list of exceptions that should be calculated differently from other interactions. If
* epsilon is equal to 0, this will cause the interaction to be completely omitted from force and energy calculations. * epsilon is equal to 0, this will cause the interaction to be completely omitted from force and energy calculations.
...@@ -284,13 +283,13 @@ private: ...@@ -284,13 +283,13 @@ private:
class GayBerneForce::ParticleInfo { class GayBerneForce::ParticleInfo {
public: public:
int xparticle, yparticle; int xparticle, yparticle;
double sigma, epsilon, rx, ry, rz, ex, ey, ez; double sigma, epsilon, sx, sy, sz, ex, ey, ez;
ParticleInfo() { ParticleInfo() {
xparticle = yparticle = -1; xparticle = yparticle = -1;
sigma = epsilon = rx = ry = rz = ex = ey = ez = 0.0; sigma = epsilon = sx = sy = sz = ex = ey = ez = 0.0;
} }
ParticleInfo(double sigma, double epsilon, int xparticle, int yparticle, double rx, double ry, double rz, double ex, double ey, double ez) : ParticleInfo(double sigma, double epsilon, int xparticle, int yparticle, double sx, double sy, double sz, double ex, double ey, double ez) :
sigma(sigma), epsilon(epsilon), xparticle(xparticle), yparticle(yparticle), rx(rx), ry(ry), rz(rz), ex(ex), ey(ey), ez(ez) { sigma(sigma), epsilon(epsilon), xparticle(xparticle), yparticle(yparticle), sx(sx), sy(sy), sz(sz), ex(ex), ey(ey), ez(ez) {
} }
}; };
......
...@@ -82,36 +82,36 @@ void GayBerneForce::setSwitchingDistance(double distance) { ...@@ -82,36 +82,36 @@ void GayBerneForce::setSwitchingDistance(double distance) {
switchingDistance = distance; switchingDistance = distance;
} }
int GayBerneForce::addParticle(double sigma, double epsilon, int xparticle, int yparticle, double rx, double ry, double rz, double ex, double ey, double ez) { int GayBerneForce::addParticle(double sigma, double epsilon, int xparticle, int yparticle, double sx, double sy, double sz, double ex, double ey, double ez) {
if (yparticle == -1 && (ry != rz || ey != ez)) if (yparticle == -1 && (sy != sz || ey != ez))
throw OpenMMException("GayBerneForce: yparticle is -1 for a particle that is not axially symmetric"); throw OpenMMException("GayBerneForce: yparticle is -1 for a particle that is not axially symmetric");
if (xparticle == -1 && (rx != rz || ex != ez)) if (xparticle == -1 && (sx != sz || ex != ez))
throw OpenMMException("GayBerneForce: xparticle is -1 for a particle that is not spherical"); throw OpenMMException("GayBerneForce: xparticle is -1 for a particle that is not spherical");
if (xparticle == -1 && yparticle != -1) if (xparticle == -1 && yparticle != -1)
throw OpenMMException("GayBerneForce: xparticle cannot be -1 if yparticle is not also -1"); throw OpenMMException("GayBerneForce: xparticle cannot be -1 if yparticle is not also -1");
particles.push_back(ParticleInfo(sigma, epsilon, xparticle, yparticle, rx, ry, rz, ex, ey, ez)); particles.push_back(ParticleInfo(sigma, epsilon, xparticle, yparticle, sx, sy, sz, ex, ey, ez));
return particles.size()-1; return particles.size()-1;
} }
void GayBerneForce::getParticleParameters(int index, double& sigma, double& epsilon, int& xparticle, int& yparticle, double& rx, double& ry, double& rz, double& ex, double& ey, double& ez) const { void GayBerneForce::getParticleParameters(int index, double& sigma, double& epsilon, int& xparticle, int& yparticle, double& sx, double& sy, double& sz, double& ex, double& ey, double& ez) const {
ASSERT_VALID_INDEX(index, particles); ASSERT_VALID_INDEX(index, particles);
sigma = particles[index].sigma; sigma = particles[index].sigma;
epsilon = particles[index].epsilon; epsilon = particles[index].epsilon;
xparticle = particles[index].xparticle; xparticle = particles[index].xparticle;
yparticle = particles[index].yparticle; yparticle = particles[index].yparticle;
rx = particles[index].rx; sx = particles[index].sx;
ry = particles[index].ry; sy = particles[index].sy;
rz = particles[index].rz; sz = particles[index].sz;
ex = particles[index].ex; ex = particles[index].ex;
ey = particles[index].ey; ey = particles[index].ey;
ez = particles[index].ez; ez = particles[index].ez;
} }
void GayBerneForce::setParticleParameters(int index, double sigma, double epsilon, int xparticle, int yparticle, double rx, double ry, double rz, double ex, double ey, double ez) { void GayBerneForce::setParticleParameters(int index, double sigma, double epsilon, int xparticle, int yparticle, double sx, double sy, double sz, double ex, double ey, double ez) {
ASSERT_VALID_INDEX(index, particles); ASSERT_VALID_INDEX(index, particles);
if (yparticle == -1 && (ry != rz || ey != ez)) if (yparticle == -1 && (sy != sz || ey != ez))
throw OpenMMException("GayBerneForce: yparticle is -1 for a particle that is not axially symmetric"); throw OpenMMException("GayBerneForce: yparticle is -1 for a particle that is not axially symmetric");
if (xparticle == -1 && (rx != rz || ex != ez)) if (xparticle == -1 && (sx != sz || ex != ez))
throw OpenMMException("GayBerneForce: xparticle is -1 for a particle that is not spherical"); throw OpenMMException("GayBerneForce: xparticle is -1 for a particle that is not spherical");
if (xparticle == -1 && yparticle != -1) if (xparticle == -1 && yparticle != -1)
throw OpenMMException("GayBerneForce: xparticle cannot be -1 if yparticle is not also -1"); throw OpenMMException("GayBerneForce: xparticle cannot be -1 if yparticle is not also -1");
...@@ -119,9 +119,9 @@ void GayBerneForce::setParticleParameters(int index, double sigma, double epsilo ...@@ -119,9 +119,9 @@ void GayBerneForce::setParticleParameters(int index, double sigma, double epsilo
particles[index].epsilon = epsilon; particles[index].epsilon = epsilon;
particles[index].xparticle = xparticle; particles[index].xparticle = xparticle;
particles[index].yparticle = yparticle; particles[index].yparticle = yparticle;
particles[index].rx = rx; particles[index].sx = sx;
particles[index].ry = ry; particles[index].sy = sy;
particles[index].rz = rx; particles[index].sz = sz;
particles[index].ex = ex; particles[index].ex = ex;
particles[index].ey = ey; particles[index].ey = ey;
particles[index].ez = ez; particles[index].ez = ez;
......
...@@ -71,6 +71,8 @@ private: ...@@ -71,6 +71,8 @@ private:
void computeEllipsoidFrames(const std::vector<RealVec>& positions); void computeEllipsoidFrames(const std::vector<RealVec>& positions);
void applyTorques(const std::vector<RealVec>& positions, std::vector<RealVec>& forces, const std::vector<RealVec>& torques);
RealOpenMM computeOneInteraction(int particle1, int particle2, RealOpenMM sigma, RealOpenMM epsilon, const std::vector<RealVec>& positions, RealOpenMM computeOneInteraction(int particle1, int particle2, RealOpenMM sigma, RealOpenMM epsilon, const std::vector<RealVec>& positions,
std::vector<RealVec>& forces, std::vector<RealVec>& torques, const RealVec* boxVectors); std::vector<RealVec>& forces, std::vector<RealVec>& torques, const RealVec* boxVectors);
}; };
...@@ -134,7 +136,7 @@ struct ReferenceGayBerneForce::Matrix { ...@@ -134,7 +136,7 @@ struct ReferenceGayBerneForce::Matrix {
}; };
static RealVec operator*(const RealVec& r, ReferenceGayBerneForce::Matrix& m) { static RealVec operator*(const RealVec& r, ReferenceGayBerneForce::Matrix& m) {
return RealVec(m.v[0][0]*r[0] + m.v[1][1]*r[1] + m.v[2][2]*r[2], return RealVec(m.v[0][0]*r[0] + m.v[1][0]*r[1] + m.v[2][0]*r[2],
m.v[0][1]*r[0] + m.v[1][1]*r[1] + m.v[2][1]*r[2], m.v[0][1]*r[0] + m.v[1][1]*r[1] + m.v[2][1]*r[2],
m.v[0][2]*r[0] + m.v[1][2]*r[1] + m.v[2][2]*r[2]); m.v[0][2]*r[0] + m.v[1][2]*r[1] + m.v[2][2]*r[2]);
} }
......
...@@ -44,7 +44,11 @@ ReferenceGayBerneForce::ReferenceGayBerneForce(const GayBerneForce& force) { ...@@ -44,7 +44,11 @@ ReferenceGayBerneForce::ReferenceGayBerneForce(const GayBerneForce& force) {
particles.resize(numParticles); particles.resize(numParticles);
for (int i = 0; i < numParticles; i++) { for (int i = 0; i < numParticles; i++) {
ParticleInfo& p = particles[i]; ParticleInfo& p = particles[i];
force.getParticleParameters(i, p.sigma, p.epsilon, p.xparticle, p.yparticle, p.rx, p.ry, p.rz, p.ex, p.ey, p.ez); double sx, sy, sz;
force.getParticleParameters(i, p.sigma, p.epsilon, p.xparticle, p.yparticle, sx, sy, sz, p.ex, p.ey, p.ez);
p.rx = 0.5*sx;
p.ry = 0.5*sy;
p.rz = 0.5*sz;
} }
int numExceptions = force.getNumExceptions(); int numExceptions = force.getNumExceptions();
exceptions.resize(numExceptions); exceptions.resize(numExceptions);
...@@ -110,6 +114,10 @@ RealOpenMM ReferenceGayBerneForce::calculateForce(const vector<RealVec>& positio ...@@ -110,6 +114,10 @@ RealOpenMM ReferenceGayBerneForce::calculateForce(const vector<RealVec>& positio
ExceptionInfo& e = exceptions[i]; ExceptionInfo& e = exceptions[i];
energy += computeOneInteraction(e.particle1, e.particle2, e.sigma, e.epsilon, positions, forces, torques, boxVectors); energy += computeOneInteraction(e.particle1, e.particle2, e.sigma, e.epsilon, positions, forces, torques, boxVectors);
} }
// Apply torques.
applyTorques(positions, forces, torques);
return energy; return energy;
} }
...@@ -156,7 +164,7 @@ void ReferenceGayBerneForce::computeEllipsoidFrames(const vector<RealVec>& posit ...@@ -156,7 +164,7 @@ void ReferenceGayBerneForce::computeEllipsoidFrames(const vector<RealVec>& posit
a[2][1] = zdir[1]; a[2][1] = zdir[1];
a[2][2] = zdir[2]; a[2][2] = zdir[2];
RealVec r2(p.rx*p.rx, p.ry*p.ry, p.rz*p.rz); RealVec r2(p.rx*p.rx, p.ry*p.ry, p.rz*p.rz);
RealVec e2(p.ex*p.ex, p.ey*p.ey, p.ez*p.ez); RealVec e2(1/sqrt(p.ex), 1/sqrt(p.ey), 1/sqrt(p.ez));
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++) { for (int j = 0; j < 3; j++) {
b[i][j] = 0; b[i][j] = 0;
...@@ -169,6 +177,34 @@ void ReferenceGayBerneForce::computeEllipsoidFrames(const vector<RealVec>& posit ...@@ -169,6 +177,34 @@ void ReferenceGayBerneForce::computeEllipsoidFrames(const vector<RealVec>& posit
} }
} }
void ReferenceGayBerneForce::applyTorques(const vector<RealVec>& positions, vector<RealVec>& forces, const vector<RealVec>& torques) {
int numParticles = particles.size();
for (int particle = 0; particle < numParticles; particle++) {
ParticleInfo& p = particles[particle];
RealVec pos = positions[particle];
if (p.xparticle != -1) {
// Apply a force to the x particle.
RealVec dx = positions[p.xparticle]-pos;
double dx2 = dx.dot(dx);
RealVec f = torques[particle].cross(dx)/dx2;
forces[p.xparticle] += f;
forces[particle] -= f;
if (p.yparticle != -1) {
// Apply a force to the y particle. This is based on the component of the torque
// that was not already applied to the x particle.
RealVec dy = positions[p.yparticle]-pos;
double dy2 = dy.dot(dy);
RealVec torque = dx*(torques[particle].dot(dx)/dx2);
f = torque.cross(dy)/dy2;
forces[p.yparticle] += f;
forces[particle] -= f;
}
}
}
}
RealOpenMM ReferenceGayBerneForce::computeOneInteraction(int particle1, int particle2, RealOpenMM sigma, RealOpenMM epsilon, const vector<RealVec>& positions, RealOpenMM ReferenceGayBerneForce::computeOneInteraction(int particle1, int particle2, RealOpenMM sigma, RealOpenMM epsilon, const vector<RealVec>& positions,
vector<RealVec>& forces, vector<RealVec>& torques, const RealVec* boxVectors) { vector<RealVec>& forces, vector<RealVec>& torques, const RealVec* boxVectors) {
// Compute the displacement and check against the cutoff. // Compute the displacement and check against the cutoff.
...@@ -195,8 +231,6 @@ RealOpenMM ReferenceGayBerneForce::computeOneInteraction(int particle1, int part ...@@ -195,8 +231,6 @@ RealOpenMM ReferenceGayBerneForce::computeOneInteraction(int particle1, int part
// Estimate the distance between the ellipsoids and compute the first terms needed for the energy. // Estimate the distance between the ellipsoids and compute the first terms needed for the energy.
ParticleInfo& p1 = particles[particle1];
ParticleInfo& p2 = particles[particle2];
RealOpenMM sigma12 = 1/SQRT(0.5*drUnit.dot(G12inv*drUnit)); RealOpenMM sigma12 = 1/SQRT(0.5*drUnit.dot(G12inv*drUnit));
RealOpenMM h12 = r - sigma12; RealOpenMM h12 = r - sigma12;
RealOpenMM rho = sigma/(h12+sigma); RealOpenMM rho = sigma/(h12+sigma);
...@@ -224,11 +258,12 @@ RealOpenMM ReferenceGayBerneForce::computeOneInteraction(int particle1, int part ...@@ -224,11 +258,12 @@ RealOpenMM ReferenceGayBerneForce::computeOneInteraction(int particle1, int part
for (int j = 0; j < 2; j++) { for (int j = 0; j < 2; j++) {
int particle = (j == 0 ? particle1 : particle2); int particle = (j == 0 ? particle1 : particle2);
RealVec dudq = A[particle]*((kappa*G[particle]).cross(kappa*temp)); RealVec dudq = (kappa*G[particle]).cross(kappa*(temp*dUSLJdr));
RealVec dchidq = (A[particle]*((iota*B[particle]).cross(iota)))*(-4*rInv2); RealVec dchidq = (iota*B[particle]).cross(iota)*(-4*rInv2);
RealOpenMM (&g12)[3][3] = G12.v; RealOpenMM (&g12)[3][3] = G12.v;
RealOpenMM (&a)[3][3] = A[particle].v; RealOpenMM (&a)[3][3] = A[particle].v;
RealVec scale = RealVec(particles[particle].rx, particles[particle].ry, particles[particle].rz)*(-eta/detG12); ParticleInfo& p = particles[particle];
RealVec scale = RealVec(p.rx*p.rx, p.ry*p.ry, p.rz*p.rz)*(-0.5*eta/detG12);
Matrix D; Matrix D;
RealOpenMM (&d)[3][3] = D.v; RealOpenMM (&d)[3][3] = D.v;
d[0][0] = scale[0]*(g12[1][2]*g12[0][1]*a[0][2] + 2*g12[1][1]*g12[2][2]*a[0][0] - d[0][0] = scale[0]*(g12[1][2]*g12[0][1]*a[0][2] + 2*g12[1][1]*g12[2][2]*a[0][0] -
...@@ -280,7 +315,7 @@ RealOpenMM ReferenceGayBerneForce::computeOneInteraction(int particle1, int part ...@@ -280,7 +315,7 @@ RealOpenMM ReferenceGayBerneForce::computeOneInteraction(int particle1, int part
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
detadq += RealVec(a[i][0], a[i][1], a[i][2]).cross(RealVec(d[i][0], d[i][1], d[i][2])); detadq += RealVec(a[i][0], a[i][1], a[i][2]).cross(RealVec(d[i][0], d[i][1], d[i][2]));
RealVec torque = dchidq*(u*eta) + detadq*(u*chi) + dudq*(eta*chi); RealVec torque = dchidq*(u*eta) + detadq*(u*chi) + dudq*(eta*chi);
torques[particle] += torque; torques[particle] -= torque;
} }
return u*eta*chi; return u*eta*chi;
} }
...@@ -64,7 +64,7 @@ void testPointParticles() { ...@@ -64,7 +64,7 @@ void testPointParticles() {
init_gen_rand(0, sfmt); init_gen_rand(0, sfmt);
for (int i = 0; i < numParticles; i++) { for (int i = 0; i < numParticles; i++) {
system.addParticle(1.0); system.addParticle(1.0);
gb->addParticle(sigma, epsilon, -1, -1, sigma/2, sigma/2, sigma/2, 1, 1, 1); gb->addParticle(sigma, epsilon, -1, -1, sigma, sigma, sigma, 1, 1, 1);
nb->addParticle(0, sigma, epsilon); nb->addParticle(0, sigma, epsilon);
positions.push_back(Vec3(2.0*genrand_real2(sfmt), 2.0*genrand_real2(sfmt), 2.0*genrand_real2(sfmt))); positions.push_back(Vec3(2.0*genrand_real2(sfmt), 2.0*genrand_real2(sfmt), 2.0*genrand_real2(sfmt)));
} }
...@@ -91,10 +91,10 @@ void testEnergyScales() { ...@@ -91,10 +91,10 @@ void testEnergyScales() {
system.addParticle(1.0); system.addParticle(1.0);
GayBerneForce* gb = new GayBerneForce(); GayBerneForce* gb = new GayBerneForce();
system.addForce(gb); system.addForce(gb);
gb->addParticle(sigma, epsilon, 1, 2, sigma/2, sigma/2, sigma/2, 1.1, 1.5, 1.8); gb->addParticle(sigma, epsilon, 1, 2, sigma, sigma, sigma, 1.1, 1.5, 1.8);
gb->addParticle(1, 0, -1, -1, 1, 1, 1, 1, 1, 1); gb->addParticle(1, 0, -1, -1, 1, 1, 1, 1, 1, 1);
gb->addParticle(1, 0, -1, -1, 1, 1, 1, 1, 1, 1); gb->addParticle(1, 0, -1, -1, 1, 1, 1, 1, 1, 1);
gb->addParticle(sigma, epsilon, 4, 5, sigma/2, sigma/2, sigma/2, 1.2, 1.6, 1.7); gb->addParticle(sigma, epsilon, 4, 5, sigma, sigma, sigma, 1.2, 1.6, 1.7);
gb->addParticle(1, 0, -1, -1, 1, 1, 1, 1, 1, 1); gb->addParticle(1, 0, -1, -1, 1, 1, 1, 1, 1, 1);
gb->addParticle(1, 0, -1, -1, 1, 1, 1, 1, 1, 1); gb->addParticle(1, 0, -1, -1, 1, 1, 1, 1, 1, 1);
vector<Vec3> positions(6); vector<Vec3> positions(6);
...@@ -113,7 +113,7 @@ void testEnergyScales() { ...@@ -113,7 +113,7 @@ void testEnergyScales() {
double expectedEnergy = 4*epsilon*(pow(sigma, 12.0)-pow(sigma, 6.0)); double expectedEnergy = 4*epsilon*(pow(sigma, 12.0)-pow(sigma, 6.0));
double expectedForce = 4*epsilon*(12*pow(sigma, 12.0)-6*pow(sigma, 6.0)); double expectedForce = 4*epsilon*(12*pow(sigma, 12.0)-6*pow(sigma, 6.0));
double expectedScale = pow(2.0/(1.1*1.1+1.2*1.2), 2.0); double expectedScale = pow(2.0/(1/sqrt(1.1) + 1/sqrt(1.2)), 2.0);
State state = context.getState(State::Forces | State::Energy); State state = context.getState(State::Forces | State::Energy);
ASSERT_EQUAL_TOL(expectedEnergy*expectedScale, state.getPotentialEnergy(), 1e-5); ASSERT_EQUAL_TOL(expectedEnergy*expectedScale, state.getPotentialEnergy(), 1e-5);
ASSERT_EQUAL_VEC(Vec3(expectedForce*expectedScale, 0, 0), state.getForces()[3], 1e-5); ASSERT_EQUAL_VEC(Vec3(expectedForce*expectedScale, 0, 0), state.getForces()[3], 1e-5);
...@@ -121,7 +121,7 @@ void testEnergyScales() { ...@@ -121,7 +121,7 @@ void testEnergyScales() {
positions[4] = Vec3(1, 1, 0); positions[4] = Vec3(1, 1, 0);
positions[5] = Vec3(0, 2, 0); positions[5] = Vec3(0, 2, 0);
context.setPositions(positions); context.setPositions(positions);
expectedScale = pow(2.0/(1.5*1.5+1.6*1.6), 2.0); expectedScale = pow(2.0/(1/sqrt(1.5) + 1/sqrt(1.6)), 2.0);
state = context.getState(State::Forces | State::Energy); state = context.getState(State::Forces | State::Energy);
ASSERT_EQUAL_TOL(expectedEnergy*expectedScale, state.getPotentialEnergy(), 1e-5); ASSERT_EQUAL_TOL(expectedEnergy*expectedScale, state.getPotentialEnergy(), 1e-5);
ASSERT_EQUAL_VEC(Vec3(0, expectedForce*expectedScale, 0), state.getForces()[3], 1e-5); ASSERT_EQUAL_VEC(Vec3(0, expectedForce*expectedScale, 0), state.getForces()[3], 1e-5);
...@@ -129,7 +129,7 @@ void testEnergyScales() { ...@@ -129,7 +129,7 @@ void testEnergyScales() {
positions[4] = Vec3(1, 1, 0); positions[4] = Vec3(1, 1, 0);
positions[5] = Vec3(0, 1, 1); positions[5] = Vec3(0, 1, 1);
context.setPositions(positions); context.setPositions(positions);
expectedScale = pow(2.0/(1.5*1.5+1.7*1.7), 2.0); expectedScale = pow(2.0/(1/sqrt(1.5) + 1/sqrt(1.7)), 2.0);
state = context.getState(State::Forces | State::Energy); state = context.getState(State::Forces | State::Energy);
ASSERT_EQUAL_TOL(expectedEnergy*expectedScale, state.getPotentialEnergy(), 1e-5); ASSERT_EQUAL_TOL(expectedEnergy*expectedScale, state.getPotentialEnergy(), 1e-5);
ASSERT_EQUAL_VEC(Vec3(0, expectedForce*expectedScale, 0), state.getForces()[3], 1e-5); ASSERT_EQUAL_VEC(Vec3(0, expectedForce*expectedScale, 0), state.getForces()[3], 1e-5);
...@@ -154,7 +154,7 @@ void testEnergyConservation() { ...@@ -154,7 +154,7 @@ void testEnergyConservation() {
system.addParticle(10.0); system.addParticle(10.0);
system.addParticle(1.0); system.addParticle(1.0);
system.addParticle(1.0); system.addParticle(1.0);
gb->addParticle(0.2, 2.0, first+1, first+2, 0.2, 0.25, 0.3, 0.9, 1.0, 1.1); gb->addParticle(0.2, 10.0, first+1, first+2, 0.2, 0.25, 0.3, 0.9, 1.0, 1.1);
gb->addParticle(1.0, 0.0, -1, -1, 1, 1, 1, 1, 1, 1); gb->addParticle(1.0, 0.0, -1, -1, 1, 1, 1, 1, 1, 1);
gb->addParticle(1.0, 0.0, -1, -1, 1, 1, 1, 1, 1, 1); gb->addParticle(1.0, 0.0, -1, -1, 1, 1, 1, 1, 1, 1);
positions.push_back(Vec3(x, y, z)); positions.push_back(Vec3(x, y, z));
...@@ -166,22 +166,19 @@ void testEnergyConservation() { ...@@ -166,22 +166,19 @@ void testEnergyConservation() {
} }
} }
} }
VerletIntegrator integ(0.001); VerletIntegrator integ(0.0005);
Context context(system, integ, platform); Context context(system, integ, platform);
context.setPositions(positions); context.setPositions(positions);
context.setVelocitiesToTemperature(300.0); context.setVelocitiesToTemperature(300.0);
double initialEnergy;
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
integ.step(5);
State state = context.getState(State::Energy); State state = context.getState(State::Energy);
printf("%d %g\n", i, state.getPotentialEnergy()+state.getKineticEnergy()); double energy = state.getPotentialEnergy()+state.getKineticEnergy();
integ.step(10); if (i == 0)
} initialEnergy = energy;
else
State state = context.getState(State::Positions); ASSERT_EQUAL_TOL(initialEnergy, energy, 1e-3);
for (int i = 0; i < 9; i++) {
Vec3 p1 = state.getPositions()[3*i];
Vec3 p2 = state.getPositions()[3*i+1];
Vec3 p3 = state.getPositions()[3*i+2];
printf("%g %g %g, %g %g %g, %g %g %g\n", p1[0], p1[1], p1[2], p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2], p3[0]-p1[0], p3[1]-p1[1], p3[2]-p1[2]);
} }
} }
......
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