Commit 5e3a0a05 authored by Peter Eastman's avatar Peter Eastman
Browse files

Began implementing triclinic boxes for reference AmoebaMultipoleForce (not yet debugged)

parent 3b2579a5
...@@ -644,12 +644,12 @@ AmoebaReferenceMultipoleForce* ReferenceCalcAmoebaMultipoleForceKernel::setupAmo ...@@ -644,12 +644,12 @@ AmoebaReferenceMultipoleForce* ReferenceCalcAmoebaMultipoleForceKernel::setupAmo
amoebaReferencePmeMultipoleForce->setAlphaEwald( alphaEwald ); amoebaReferencePmeMultipoleForce->setAlphaEwald( alphaEwald );
amoebaReferencePmeMultipoleForce->setCutoffDistance( cutoffDistance ); amoebaReferencePmeMultipoleForce->setCutoffDistance( cutoffDistance );
amoebaReferencePmeMultipoleForce->setPmeGridDimensions( pmeGridDimension ); amoebaReferencePmeMultipoleForce->setPmeGridDimensions( pmeGridDimension );
RealVec& box = extractBoxSize(context); RealVec* boxVectors = extractBoxVectors(context);
double minAllowedSize = 1.999999*cutoffDistance; double minAllowedSize = 1.999999*cutoffDistance;
if (box[0] < minAllowedSize || box[1] < minAllowedSize || box[2] < minAllowedSize){ if (boxVectors[0][0] < minAllowedSize || boxVectors[1][1] < minAllowedSize || boxVectors[2][2] < minAllowedSize){
throw OpenMMException("The periodic box size has decreased to less than twice the nonbonded cutoff."); throw OpenMMException("The periodic box size has decreased to less than twice the nonbonded cutoff.");
} }
amoebaReferencePmeMultipoleForce->setPeriodicBoxSize(box); amoebaReferencePmeMultipoleForce->setPeriodicBoxSize(boxVectors);
amoebaReferenceMultipoleForce = static_cast<AmoebaReferenceMultipoleForce*>(amoebaReferencePmeMultipoleForce); amoebaReferenceMultipoleForce = static_cast<AmoebaReferenceMultipoleForce*>(amoebaReferencePmeMultipoleForce);
} else { } else {
......
...@@ -4608,22 +4608,24 @@ void AmoebaReferencePmeMultipoleForce::setPmeGridDimensions(vector<int>& pmeGrid ...@@ -4608,22 +4608,24 @@ void AmoebaReferencePmeMultipoleForce::setPmeGridDimensions(vector<int>& pmeGrid
initializeBSplineModuli(); initializeBSplineModuli();
}; };
void AmoebaReferencePmeMultipoleForce::setPeriodicBoxSize(RealVec& boxSize) void AmoebaReferencePmeMultipoleForce::setPeriodicBoxSize(OpenMM::RealVec* vectors)
{ {
if (boxSize[0] == 0.0 || boxSize[1] == 0.0 || boxSize[2] == 0.0) { if (vectors[0][0] == 0.0 || vectors[1][1] == 0.0 || vectors[2][2] == 0.0) {
std::stringstream message; std::stringstream message;
message << "Box size of zero is invalid."; message << "Box size of zero is invalid.";
throw OpenMMException(message.str()); throw OpenMMException(message.str());
} }
_periodicBoxSize = boxSize; _periodicBoxVectors[0] = vectors[0];
_periodicBoxVectors[1] = vectors[1];
_invPeriodicBoxSize[0] = 1.0/boxSize[0]; _periodicBoxVectors[2] = vectors[2];
_invPeriodicBoxSize[1] = 1.0/boxSize[1]; RealOpenMM determinant = vectors[0][0]*vectors[1][1]*vectors[2][2];
_invPeriodicBoxSize[2] = 1.0/boxSize[2]; assert(determinant > 0);
RealOpenMM scale = 1.0/determinant;
return; _recipBoxVectors[0] = RealVec(vectors[1][1]*vectors[2][2], 0, 0)*scale;
_recipBoxVectors[1] = RealVec(-vectors[1][0]*vectors[2][2], vectors[0][0]*vectors[2][2], 0)*scale;
_recipBoxVectors[2] = RealVec(vectors[1][0]*vectors[2][1]-vectors[1][1]*vectors[2][0], -vectors[0][0]*vectors[2][1], vectors[0][0]*vectors[1][1])*scale;
}; };
int compareInt2(const int2& v1, const int2& v2) int compareInt2(const int2& v1, const int2& v2)
...@@ -4672,16 +4674,9 @@ void AmoebaReferencePmeMultipoleForce::initializePmeGrid() ...@@ -4672,16 +4674,9 @@ void AmoebaReferencePmeMultipoleForce::initializePmeGrid()
void AmoebaReferencePmeMultipoleForce::getPeriodicDelta(RealVec& deltaR) const void AmoebaReferencePmeMultipoleForce::getPeriodicDelta(RealVec& deltaR) const
{ {
deltaR[0] -= FLOOR(deltaR[0]*_invPeriodicBoxSize[0]+0.5)*_periodicBoxSize[0]; deltaR -= _periodicBoxVectors[2]*FLOOR(deltaR[2]*_recipBoxVectors[2][2]+0.5);
deltaR[1] -= FLOOR(deltaR[1]*_invPeriodicBoxSize[1]+0.5)*_periodicBoxSize[1]; deltaR -= _periodicBoxVectors[1]*FLOOR(deltaR[1]*_recipBoxVectors[1][1]+0.5);
deltaR[2] -= FLOOR(deltaR[2]*_invPeriodicBoxSize[2]+0.5)*_periodicBoxSize[2]; deltaR -= _periodicBoxVectors[0]*FLOOR(deltaR[0]*_recipBoxVectors[0][0]+0.5);
}
void AmoebaReferencePmeMultipoleForce::getPmeScale(RealVec& scale) const
{
scale[0] = static_cast<RealOpenMM>(_pmeGridDimensions[0])*_invPeriodicBoxSize[0];
scale[1] = static_cast<RealOpenMM>(_pmeGridDimensions[1])*_invPeriodicBoxSize[1];
scale[2] = static_cast<RealOpenMM>(_pmeGridDimensions[2])*_invPeriodicBoxSize[2];
} }
void AmoebaReferencePmeMultipoleForce::getDampedInverseDistances(const MultipoleParticleData& particleI, void AmoebaReferencePmeMultipoleForce::getDampedInverseDistances(const MultipoleParticleData& particleI,
...@@ -5039,7 +5034,7 @@ void AmoebaReferencePmeMultipoleForce::computeAmoebaBsplines(const vector<Multip ...@@ -5039,7 +5034,7 @@ void AmoebaReferencePmeMultipoleForce::computeAmoebaBsplines(const vector<Multip
IntVec igrid; IntVec igrid;
for (unsigned int jj = 0; jj < 3; jj++) { for (unsigned int jj = 0; jj < 3; jj++) {
RealOpenMM w = position[jj]*_invPeriodicBoxSize[jj]; RealOpenMM w = position[0]*_recipBoxVectors[0][jj]+position[1]*_recipBoxVectors[1][jj]+position[2]*_recipBoxVectors[2][jj];
RealOpenMM fr = _pmeGridDimensions[jj]*(w-(int)(w+0.5)+0.5); RealOpenMM fr = _pmeGridDimensions[jj]*(w-(int)(w+0.5)+0.5);
int ifr = static_cast<int>(fr); int ifr = static_cast<int>(fr);
w = fr - ifr; w = fr - ifr;
...@@ -5095,8 +5090,8 @@ void AmoebaReferencePmeMultipoleForce::findAmoebaAtomRangeForGrid(const vector<M ...@@ -5095,8 +5090,8 @@ void AmoebaReferencePmeMultipoleForce::findAmoebaAtomRangeForGrid(const vector<M
for (unsigned int ii = 0; ii < _numParticles; ii++) { for (unsigned int ii = 0; ii < _numParticles; ii++) {
RealOpenMM posz = particleData[_pmeAtomGridIndex[ii][0]].position[2]; RealOpenMM posz = particleData[_pmeAtomGridIndex[ii][0]].position[2];
posz -= FLOOR(posz*_invPeriodicBoxSize[2])*_periodicBoxSize[2]; posz -= FLOOR(posz*_recipBoxVectors[2][2])*_periodicBoxVectors[2][2];
RealOpenMM w = posz*_invPeriodicBoxSize[2]; RealOpenMM w = posz*_recipBoxVectors[2][2];
RealOpenMM fr = _pmeGridDimensions[2]*(w-(int)(w+0.5)+0.5); RealOpenMM fr = _pmeGridDimensions[2]*(w-(int)(w+0.5)+0.5);
int z = (static_cast<int>(fr)) - AMOEBA_PME_ORDER + 1; int z = (static_cast<int>(fr)) - AMOEBA_PME_ORDER + 1;
_pmeAtomGridIndex[ii][1] = z; _pmeAtomGridIndex[ii][1] = z;
...@@ -5116,8 +5111,7 @@ void AmoebaReferencePmeMultipoleForce::getGridPointGivenGridIndex(int gridIndex, ...@@ -5116,8 +5111,7 @@ void AmoebaReferencePmeMultipoleForce::getGridPointGivenGridIndex(int gridIndex,
return; return;
} }
RealOpenMM AmoebaReferencePmeMultipoleForce::computeFixedMultipolesGridValue(const vector<MultipoleParticleData>& particleData, RealOpenMM AmoebaReferencePmeMultipoleForce::computeFixedMultipolesGridValue(const int2& particleGridIndices,
const int2& particleGridIndices, const RealVec& scale,
int ix, int iy, const IntVec& gridPoint) const int ix, int iy, const IntVec& gridPoint) const
{ {
...@@ -5131,17 +5125,17 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeFixedMultipolesGridValue(con ...@@ -5131,17 +5125,17 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeFixedMultipolesGridValue(con
iz -= _pmeGridDimensions[2]; iz -= _pmeGridDimensions[2];
} }
RealOpenMM atomCharge = particleData[atomIndex].charge; RealOpenMM atomCharge = _transformed[atomIndex].charge;
RealVec atomDipole = RealVec(scale[0]*particleData[atomIndex].dipole[0], RealVec atomDipole = RealVec(_transformed[atomIndex].dipole[0],
scale[1]*particleData[atomIndex].dipole[1], _transformed[atomIndex].dipole[1],
scale[2]*particleData[atomIndex].dipole[2]); _transformed[atomIndex].dipole[2]);
RealOpenMM atomQuadrupoleXX = scale[0]*scale[0]*particleData[atomIndex].quadrupole[QXX]; RealOpenMM atomQuadrupoleXX = _transformed[atomIndex].quadrupole[QXX];
RealOpenMM atomQuadrupoleXY = 2.0*scale[0]*scale[1]*particleData[atomIndex].quadrupole[QXY]; RealOpenMM atomQuadrupoleXY = _transformed[atomIndex].quadrupole[QXY];
RealOpenMM atomQuadrupoleXZ = 2.0*scale[0]*scale[2]*particleData[atomIndex].quadrupole[QXZ]; RealOpenMM atomQuadrupoleXZ = _transformed[atomIndex].quadrupole[QXZ];
RealOpenMM atomQuadrupoleYY = scale[1]*scale[1]*particleData[atomIndex].quadrupole[QYY]; RealOpenMM atomQuadrupoleYY = _transformed[atomIndex].quadrupole[QYY];
RealOpenMM atomQuadrupoleYZ = 2.0*scale[1]*scale[2]*particleData[atomIndex].quadrupole[QYZ]; RealOpenMM atomQuadrupoleYZ = _transformed[atomIndex].quadrupole[QYZ];
RealOpenMM atomQuadrupoleZZ = scale[2]*scale[2]*particleData[atomIndex].quadrupole[QZZ]; RealOpenMM atomQuadrupoleZZ = _transformed[atomIndex].quadrupole[QZZ];
RealOpenMM4 t = _thetai[0][atomIndex*AMOEBA_PME_ORDER+ix]; RealOpenMM4 t = _thetai[0][atomIndex*AMOEBA_PME_ORDER+ix];
RealOpenMM4 u = _thetai[1][atomIndex*AMOEBA_PME_ORDER+iy]; RealOpenMM4 u = _thetai[1][atomIndex*AMOEBA_PME_ORDER+iy];
...@@ -5154,11 +5148,86 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeFixedMultipolesGridValue(con ...@@ -5154,11 +5148,86 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeFixedMultipolesGridValue(con
return gridValue; return gridValue;
} }
void AmoebaReferencePmeMultipoleForce::transformMultipolesToFractionalCoordinates(const vector<MultipoleParticleData>& particleData) {
// Build matrices for transforming the dipoles and quadrupoles.
RealVec a[3];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a[j][i] = _pmeGridDimensions[j]*_recipBoxVectors[i][j];
int index1[] = {0, 0, 0, 1, 1, 2};
int index2[] = {0, 1, 2, 1, 2, 2};
RealOpenMM b[6][6];
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 6; j++) {
b[i][j] = a[index1[i]][index1[j]]*a[index2[i]][index2[j]];
if (index1[i] != index2[i])
b[i][j] += a[index1[i]][index2[j]]*a[index2[i]][index1[j]];
}
}
// Transform the multipoles.
_transformed.resize(particleData.size());
double quadScale[] = {1, 2, 2, 1, 2, 1};
for (int i = 0; i < (int) particleData.size(); i++) {
_transformed[i].charge = particleData[i].charge;
_transformed[i].dipole = Vec3();
for (int j = 0; j < 3; j++)
for (int k = 0; k < 3; k++)
_transformed[i].dipole[j] += a[j][k]*particleData[i].dipole[k];
for (int j = 0; j < 6; j++) {
_transformed[i].quadrupole[j] = 0;
for (int k = 0; k < 6; k++)
_transformed[i].quadrupole[j] += quadScale[k]*b[j][k]*particleData[i].quadrupole[k];
}
}
}
void AmoebaReferencePmeMultipoleForce::transformPotentialToCartesianCoordinates(const vector<RealOpenMM>& fphi, vector<RealOpenMM>& cphi) const {
// Build a matrix for transforming the potential.
RealVec a[3];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a[i][j] = _pmeGridDimensions[j]*_recipBoxVectors[i][j];
int index1[] = {0, 1, 2, 0, 0, 1};
int index2[] = {0, 1, 2, 1, 2, 2};
RealOpenMM b[6][6];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 6; j++) {
b[i][j] = a[index1[i]][index1[j]]*a[index2[i]][index2[j]];
if (index1[i] != index2[i])
b[i][j] *= 2;
}
}
for (int i = 3; i < 6; i++) {
for (int j = 0; j < 6; j++) {
b[i][j] = a[index1[i]][index1[j]]*a[index2[i]][index2[j]];
if (index1[i] != index2[i])
b[i][j] += a[index1[i]][index2[j]]*a[index2[i]][index1[j]];
}
}
// Transform the potential.
for (int i = 0; i < _numParticles; i++) {
cphi[10*i] = fphi[20*i];
cphi[10*i+1] = a[0][0]*fphi[20*i+1] + a[0][1]*fphi[20*i+2] + a[0][2]*fphi[20*i+3];
cphi[10*i+2] = a[1][0]*fphi[20*i+1] + a[1][1]*fphi[20*i+2] + a[1][2]*fphi[20*i+3];
cphi[10*i+3] = a[2][0]*fphi[20*i+1] + a[2][1]*fphi[20*i+2] + a[2][2]*fphi[20*i+3];
for (int j = 0; j < 6; j++) {
cphi[10*i+4+j] = 0;
for (int k = 0; k < 6; k++)
cphi[10*i+4+j] += b[j][k]*fphi[20*i+4+k];
}
}
}
void AmoebaReferencePmeMultipoleForce::spreadFixedMultipolesOntoGrid(const vector<MultipoleParticleData>& particleData) void AmoebaReferencePmeMultipoleForce::spreadFixedMultipolesOntoGrid(const vector<MultipoleParticleData>& particleData)
{ {
RealVec scale; transformMultipolesToFractionalCoordinates(particleData);
getPmeScale(scale);
for (int gridIndex = 0; gridIndex < _totalGridSize; gridIndex++) { for (int gridIndex = 0; gridIndex < _totalGridSize; gridIndex++) {
...@@ -5179,13 +5248,13 @@ void AmoebaReferencePmeMultipoleForce::spreadFixedMultipolesOntoGrid(const vecto ...@@ -5179,13 +5248,13 @@ void AmoebaReferencePmeMultipoleForce::spreadFixedMultipolesOntoGrid(const vecto
int2 particleGridIndices; int2 particleGridIndices;
particleGridIndices[0] = x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+z1; particleGridIndices[0] = x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+z1;
particleGridIndices[1] = x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+z2; particleGridIndices[1] = x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+z2;
result += computeFixedMultipolesGridValue(particleData, particleGridIndices, scale, ix, iy, gridPoint); result += computeFixedMultipolesGridValue(particleGridIndices, ix, iy, gridPoint);
if (z1 > gridPoint[2]) { if (z1 > gridPoint[2]) {
particleGridIndices[0] = x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]; particleGridIndices[0] = x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2];
particleGridIndices[1] = x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+gridPoint[2]; particleGridIndices[1] = x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+gridPoint[2];
result += computeFixedMultipolesGridValue(particleData, particleGridIndices, scale, ix, iy, gridPoint); result += computeFixedMultipolesGridValue(particleGridIndices, ix, iy, gridPoint);
} }
} }
} }
...@@ -5198,7 +5267,7 @@ void AmoebaReferencePmeMultipoleForce::performAmoebaReciprocalConvolution() ...@@ -5198,7 +5267,7 @@ void AmoebaReferencePmeMultipoleForce::performAmoebaReciprocalConvolution()
{ {
RealOpenMM expFactor = (M_PI*M_PI)/(_alphaEwald*_alphaEwald); RealOpenMM expFactor = (M_PI*M_PI)/(_alphaEwald*_alphaEwald);
RealOpenMM scaleFactor = 1.0/(M_PI*_periodicBoxSize[0]*_periodicBoxSize[1]*_periodicBoxSize[2]); RealOpenMM scaleFactor = 1.0/(M_PI*_periodicBoxVectors[0][0]*_periodicBoxVectors[1][1]*_periodicBoxVectors[2][2]);
for (int index = 0; index < _totalGridSize; index++) for (int index = 0; index < _totalGridSize; index++)
{ {
...@@ -5216,9 +5285,9 @@ void AmoebaReferencePmeMultipoleForce::performAmoebaReciprocalConvolution() ...@@ -5216,9 +5285,9 @@ void AmoebaReferencePmeMultipoleForce::performAmoebaReciprocalConvolution()
int my = (ky < (_pmeGridDimensions[1]+1)/2) ? ky : (ky-_pmeGridDimensions[1]); int my = (ky < (_pmeGridDimensions[1]+1)/2) ? ky : (ky-_pmeGridDimensions[1]);
int mz = (kz < (_pmeGridDimensions[2]+1)/2) ? kz : (kz-_pmeGridDimensions[2]); int mz = (kz < (_pmeGridDimensions[2]+1)/2) ? kz : (kz-_pmeGridDimensions[2]);
RealOpenMM mhx = mx*_invPeriodicBoxSize[0]; RealOpenMM mhx = mx*_recipBoxVectors[0][0];
RealOpenMM mhy = my*_invPeriodicBoxSize[1]; RealOpenMM mhy = mx*_recipBoxVectors[1][0]+my*_recipBoxVectors[1][1];
RealOpenMM mhz = mz*_invPeriodicBoxSize[2]; RealOpenMM mhz = mx*_recipBoxVectors[2][0]+my*_recipBoxVectors[2][1]+mz*_recipBoxVectors[2][2];
RealOpenMM bx = _pmeBsplineModuli[0][kx]; RealOpenMM bx = _pmeBsplineModuli[0][kx];
RealOpenMM by = _pmeBsplineModuli[1][ky]; RealOpenMM by = _pmeBsplineModuli[1][ky];
...@@ -5341,7 +5410,7 @@ void AmoebaReferencePmeMultipoleForce::computeFixedPotentialFromGrid() ...@@ -5341,7 +5410,7 @@ void AmoebaReferencePmeMultipoleForce::computeFixedPotentialFromGrid()
} }
} }
t_complex AmoebaReferencePmeMultipoleForce::computeInducedDipoleGridValue(const int2& particleGridIndices, const RealVec& scale, int ix, int iy, t_complex AmoebaReferencePmeMultipoleForce::computeInducedDipoleGridValue(const int2& particleGridIndices, const RealVec* fracToCart, int ix, int iy,
const IntVec& gridPoint, const IntVec& gridPoint,
const vector<RealVec>& inputInducedDipole, const vector<RealVec>& inputInducedDipole,
const vector<RealVec>& inputInducedDipolePolar) const const vector<RealVec>& inputInducedDipolePolar) const
...@@ -5361,13 +5430,16 @@ t_complex AmoebaReferencePmeMultipoleForce::computeInducedDipoleGridValue(const ...@@ -5361,13 +5430,16 @@ t_complex AmoebaReferencePmeMultipoleForce::computeInducedDipoleGridValue(const
if (iz >= _pmeGridDimensions[2]) { if (iz >= _pmeGridDimensions[2]) {
iz -= _pmeGridDimensions[2]; iz -= _pmeGridDimensions[2];
} }
RealVec inducedDipole = RealVec(scale[0]*inputInducedDipole[atomIndex][0], RealVec inducedDipole = RealVec(inputInducedDipole[atomIndex][0]*fracToCart[0][0] + inputInducedDipole[atomIndex][1]*fracToCart[0][1] + inputInducedDipole[atomIndex][2]*fracToCart[0][2],
scale[1]*inputInducedDipole[atomIndex][1], inputInducedDipole[atomIndex][0]*fracToCart[1][0] + inputInducedDipole[atomIndex][1]*fracToCart[1][1] + inputInducedDipole[atomIndex][2]*fracToCart[1][2],
scale[2]*inputInducedDipole[atomIndex][2]); inputInducedDipole[atomIndex][0]*fracToCart[2][0] + inputInducedDipole[atomIndex][1]*fracToCart[2][1] + inputInducedDipole[atomIndex][2]*fracToCart[2][2]);
RealVec inducedDipolePolar = RealVec(inputInducedDipolePolar[atomIndex][0]*fracToCart[0][0] + inputInducedDipolePolar[atomIndex][1]*fracToCart[0][1] + inputInducedDipolePolar[atomIndex][2]*fracToCart[0][2],
inputInducedDipolePolar[atomIndex][0]*fracToCart[1][0] + inputInducedDipolePolar[atomIndex][1]*fracToCart[1][1] + inputInducedDipolePolar[atomIndex][2]*fracToCart[1][2],
inputInducedDipolePolar[atomIndex][0]*fracToCart[2][0] + inputInducedDipolePolar[atomIndex][1]*fracToCart[2][1] + inputInducedDipolePolar[atomIndex][2]*fracToCart[2][2]);
RealVec inducedDipolePolar = RealVec(scale[0]*inputInducedDipolePolar[atomIndex][0], // RealVec inducedDipolePolar = RealVec(scale[0]*inputInducedDipolePolar[atomIndex][0],
scale[1]*inputInducedDipolePolar[atomIndex][1], // scale[1]*inputInducedDipolePolar[atomIndex][1],
scale[2]*inputInducedDipolePolar[atomIndex][2]); // scale[2]*inputInducedDipolePolar[atomIndex][2]);
RealOpenMM4 t = _thetai[0][atomIndex*AMOEBA_PME_ORDER+ix]; RealOpenMM4 t = _thetai[0][atomIndex*AMOEBA_PME_ORDER+ix];
RealOpenMM4 u = _thetai[1][atomIndex*AMOEBA_PME_ORDER+iy]; RealOpenMM4 u = _thetai[1][atomIndex*AMOEBA_PME_ORDER+iy];
...@@ -5388,8 +5460,10 @@ t_complex AmoebaReferencePmeMultipoleForce::computeInducedDipoleGridValue(const ...@@ -5388,8 +5460,10 @@ t_complex AmoebaReferencePmeMultipoleForce::computeInducedDipoleGridValue(const
void AmoebaReferencePmeMultipoleForce::spreadInducedDipolesOnGrid(const vector<RealVec>& inputInducedDipole, void AmoebaReferencePmeMultipoleForce::spreadInducedDipolesOnGrid(const vector<RealVec>& inputInducedDipole,
const vector<RealVec>& inputInducedDipolePolar) const vector<RealVec>& inputInducedDipolePolar)
{ {
RealVec scale; RealVec fracToCart[3];
getPmeScale(scale); for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
fracToCart[i][j] = _pmeGridDimensions[j]*_recipBoxVectors[i][j];
for (int gridIndex = 0; gridIndex < _totalGridSize; gridIndex++) for (int gridIndex = 0; gridIndex < _totalGridSize; gridIndex++)
{ {
...@@ -5412,13 +5486,13 @@ void AmoebaReferencePmeMultipoleForce::spreadInducedDipolesOnGrid(const vector<R ...@@ -5412,13 +5486,13 @@ void AmoebaReferencePmeMultipoleForce::spreadInducedDipolesOnGrid(const vector<R
int2 particleGridIndices; int2 particleGridIndices;
particleGridIndices[0] = x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+z1; particleGridIndices[0] = x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+z1;
particleGridIndices[1] = x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+z2; particleGridIndices[1] = x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+z2;
gridValue += computeInducedDipoleGridValue(particleGridIndices, scale, ix, iy, gridPoint, inputInducedDipole, inputInducedDipolePolar); gridValue += computeInducedDipoleGridValue(particleGridIndices, fracToCart, ix, iy, gridPoint, inputInducedDipole, inputInducedDipolePolar);
if (z1 > gridPoint[2]) if (z1 > gridPoint[2])
{ {
particleGridIndices[0] = x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]; particleGridIndices[0] = x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2];
particleGridIndices[1] = x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+gridPoint[2]; particleGridIndices[1] = x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+gridPoint[2];
gridValue += computeInducedDipoleGridValue(particleGridIndices, scale, ix, iy, gridPoint, inputInducedDipole, inputInducedDipolePolar); gridValue += computeInducedDipoleGridValue(particleGridIndices, fracToCart, ix, iy, gridPoint, inputInducedDipole, inputInducedDipolePolar);
} }
} }
} }
...@@ -5638,8 +5712,14 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeReciprocalSpaceFixedMultipol ...@@ -5638,8 +5712,14 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeReciprocalSpaceFixedMultipol
const int deriv1[] = {1, 4, 7, 8, 10, 15, 17, 13, 14, 19}; const int deriv1[] = {1, 4, 7, 8, 10, 15, 17, 13, 14, 19};
const int deriv2[] = {2, 7, 5, 9, 13, 11, 18, 15, 19, 16}; const int deriv2[] = {2, 7, 5, 9, 13, 11, 18, 15, 19, 16};
const int deriv3[] = {3, 8, 9, 6, 14, 16, 12, 19, 17, 18}; const int deriv3[] = {3, 8, 9, 6, 14, 16, 12, 19, 17, 18};
RealVec scale; vector<RealOpenMM> cphi(10*_numParticles);
getPmeScale(scale); transformPotentialToCartesianCoordinates(_phi, cphi);
// RealVec scale;
// getPmeScale(scale);
RealVec fracToCart[3];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
fracToCart[i][j] = _pmeGridDimensions[j]*_recipBoxVectors[i][j];
RealOpenMM energy = 0.0; RealOpenMM energy = 0.0;
for (int i = 0; i < _numParticles; i++) { for (int i = 0; i < _numParticles; i++) {
...@@ -5659,46 +5739,73 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeReciprocalSpaceFixedMultipol ...@@ -5659,46 +5739,73 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeReciprocalSpaceFixedMultipol
multipole[8] = particleData[i].quadrupole[QXZ]*2.0; multipole[8] = particleData[i].quadrupole[QXZ]*2.0;
multipole[9] = particleData[i].quadrupole[QYZ]*2.0; multipole[9] = particleData[i].quadrupole[QYZ]*2.0;
const RealOpenMM* phi = &_phi[20*i]; // const RealOpenMM* phi = &_phi[20*i];
torques[i][0] += _electric*(multipole[3]*scale[1]*phi[2] - multipole[2]*scale[2]*phi[3] // torques[i][0] += _electric*(multipole[3]*scale[1]*phi[2] - multipole[2]*scale[2]*phi[3]
+ 2.0*(multipole[6]-multipole[5])*scale[1]*scale[2]*phi[9] // + 2.0*(multipole[6]-multipole[5])*scale[1]*scale[2]*phi[9]
+ multipole[8]*scale[0]*scale[1]*phi[7] + multipole[9]*scale[1]*scale[1]*phi[5] // + multipole[8]*scale[0]*scale[1]*phi[7] + multipole[9]*scale[1]*scale[1]*phi[5]
- multipole[7]*scale[0]*scale[2]*phi[8] - multipole[9]*scale[2]*scale[2]*phi[6]); // - multipole[7]*scale[0]*scale[2]*phi[8] - multipole[9]*scale[2]*scale[2]*phi[6]);
//
torques[i][1] += _electric*(multipole[1]*scale[2]*phi[3] - multipole[3]*scale[0]*phi[1] // torques[i][1] += _electric*(multipole[1]*scale[2]*phi[3] - multipole[3]*scale[0]*phi[1]
+ 2.0*(multipole[4]-multipole[6])*scale[0]*scale[2]*phi[8] // + 2.0*(multipole[4]-multipole[6])*scale[0]*scale[2]*phi[8]
+ multipole[7]*scale[1]*scale[2]*phi[9] + multipole[8]*scale[2]*scale[2]*phi[6] // + multipole[7]*scale[1]*scale[2]*phi[9] + multipole[8]*scale[2]*scale[2]*phi[6]
- multipole[8]*scale[0]*scale[0]*phi[4] - multipole[9]*scale[0]*scale[1]*phi[7]); // - multipole[8]*scale[0]*scale[0]*phi[4] - multipole[9]*scale[0]*scale[1]*phi[7]);
//
torques[i][2] += _electric*(multipole[2]*scale[0]*phi[1] - multipole[1]*scale[1]*phi[2] // torques[i][2] += _electric*(multipole[2]*scale[0]*phi[1] - multipole[1]*scale[1]*phi[2]
+ 2.0*(multipole[5]-multipole[4])*scale[0]*scale[1]*phi[7] // + 2.0*(multipole[5]-multipole[4])*scale[0]*scale[1]*phi[7]
+ multipole[7]*scale[0]*scale[0]*phi[4] + multipole[9]*scale[0]*scale[2]*phi[8] // + multipole[7]*scale[0]*scale[0]*phi[4] + multipole[9]*scale[0]*scale[2]*phi[8]
- multipole[7]*scale[1]*scale[1]*phi[5] - multipole[8]*scale[1]*scale[2]*phi[9]); // - multipole[7]*scale[1]*scale[1]*phi[5] - multipole[8]*scale[1]*scale[2]*phi[9]);
const RealOpenMM* phi = &cphi[10*i];
torques[i][0] += _electric*(multipole[3]*phi[2] - multipole[2]*phi[3]
+ 2.0*(multipole[6]-multipole[5])*phi[9]
+ multipole[8]*phi[7] + multipole[9]*phi[5]
- multipole[7]*phi[8] - multipole[9]*phi[6]);
torques[i][1] += _electric*(multipole[1]*phi[3] - multipole[3]*phi[1]
+ 2.0*(multipole[4]-multipole[6])*phi[8]
+ multipole[7]*phi[9] + multipole[8]*phi[6]
- multipole[8]*phi[4] - multipole[9]*phi[7]);
torques[i][2] += _electric*(multipole[2]*phi[1] - multipole[1]*phi[2]
+ 2.0*(multipole[5]-multipole[4])*phi[7]
+ multipole[7]*phi[4] + multipole[9]*phi[8]
- multipole[7]*phi[5] - multipole[8]*phi[9]);
// Compute the force and energy. // Compute the force and energy.
multipole[1] *= scale[0]; multipole[1] = _transformed[i].dipole[0];
multipole[2] *= scale[1]; multipole[2] = _transformed[i].dipole[1];
multipole[3] *= scale[2]; multipole[3] = _transformed[i].dipole[2];
multipole[4] *= scale[0]*scale[0]; multipole[4] = _transformed[i].quadrupole[QXX];
multipole[5] *= scale[1]*scale[1]; multipole[5] = _transformed[i].quadrupole[QYY];
multipole[6] *= scale[2]*scale[2]; multipole[6] = _transformed[i].quadrupole[QZZ];
multipole[7] *= scale[0]*scale[1]; multipole[7] = _transformed[i].quadrupole[QXY];
multipole[8] *= scale[0]*scale[2]; multipole[8] = _transformed[i].quadrupole[QXZ];
multipole[9] *= scale[1]*scale[2]; multipole[9] = _transformed[i].quadrupole[QYZ];
// multipole[1] *= scale[0];
// multipole[2] *= scale[1];
// multipole[3] *= scale[2];
// multipole[4] *= scale[0]*scale[0];
// multipole[5] *= scale[1]*scale[1];
// multipole[6] *= scale[2]*scale[2];
// multipole[7] *= scale[0]*scale[1];
// multipole[8] *= scale[0]*scale[2];
// multipole[9] *= scale[1]*scale[2];
RealVec f = RealVec(0.0, 0.0, 0.0); RealVec f = RealVec(0.0, 0.0, 0.0);
for (int k = 0; k < 10; k++) { for (int k = 0; k < 10; k++) {
energy += multipole[k]*phi[k]; energy += multipole[k]*_phi[20*i+k];
f[0] += multipole[k]*phi[deriv1[k]]; f[0] += multipole[k]*_phi[20*i+deriv1[k]];
f[1] += multipole[k]*phi[deriv2[k]]; f[1] += multipole[k]*_phi[20*i+deriv2[k]];
f[2] += multipole[k]*phi[deriv3[k]]; f[2] += multipole[k]*_phi[20*i+deriv3[k]];
} }
f[0] *= scale[0]; // f[0] *= scale[0];
f[1] *= scale[1]; // f[1] *= scale[1];
f[2] *= scale[2]; // f[2] *= scale[2];
f *= (_electric); f *= (_electric);
forces[i] -= f; forces[i] -= RealVec(f[0]*fracToCart[0][0] + f[1]*fracToCart[0][1] + f[2]*fracToCart[0][2],
f[0]*fracToCart[1][0] + f[1]*fracToCart[1][1] + f[2]*fracToCart[1][2],
f[0]*fracToCart[2][0] + f[1]*fracToCart[2][1] + f[2]*fracToCart[2][2]);
} }
return (0.5*_electric*energy); return (0.5*_electric*energy);
...@@ -5719,8 +5826,14 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeReciprocalSpaceInducedDipole ...@@ -5719,8 +5826,14 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeReciprocalSpaceInducedDipole
const int deriv1[] = {1, 4, 7, 8, 10, 15, 17, 13, 14, 19}; const int deriv1[] = {1, 4, 7, 8, 10, 15, 17, 13, 14, 19};
const int deriv2[] = {2, 7, 5, 9, 13, 11, 18, 15, 19, 16}; const int deriv2[] = {2, 7, 5, 9, 13, 11, 18, 15, 19, 16};
const int deriv3[] = {3, 8, 9, 6, 14, 16, 12, 19, 17, 18}; const int deriv3[] = {3, 8, 9, 6, 14, 16, 12, 19, 17, 18};
RealVec scale; vector<RealOpenMM> cphi(10*_numParticles);
getPmeScale(scale); transformPotentialToCartesianCoordinates(_phidp, cphi);
RealVec cartToFrac[3], fracToCart[3];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
cartToFrac[j][i] = fracToCart[i][j] = _pmeGridDimensions[j]*_recipBoxVectors[i][j];
// RealVec scale;
// getPmeScale(scale);
RealOpenMM energy = 0.0; RealOpenMM energy = 0.0;
for (int i = 0; i < _numParticles; i++) { for (int i = 0; i < _numParticles; i++) {
...@@ -5741,45 +5854,54 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeReciprocalSpaceInducedDipole ...@@ -5741,45 +5854,54 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeReciprocalSpaceInducedDipole
multipole[8] = particleData[i].quadrupole[QXZ]*2.0; multipole[8] = particleData[i].quadrupole[QXZ]*2.0;
multipole[9] = particleData[i].quadrupole[QYZ]*2.0; multipole[9] = particleData[i].quadrupole[QYZ]*2.0;
torques[iIndex][0] += 0.5*_electric*(multipole[3]*scale[1]*_phidp[20*i+2] - multipole[2]*scale[2]*_phidp[20*i+3] const RealOpenMM* phi = &cphi[10*i];
+ 2.0*(multipole[6]-multipole[5])*scale[1]*scale[2]*_phidp[20*i+9] torques[iIndex][0] += 0.5*_electric*(multipole[3]*phi[2] - multipole[2]*phi[3]
+ multipole[8]*scale[0]*scale[1]*_phidp[20*i+7] + multipole[9]*scale[1]*scale[1]*_phidp[20*i+5] + 2.0*(multipole[6]-multipole[5])*phi[9]
- multipole[7]*scale[0]*scale[2]*_phidp[20*i+8] - multipole[9]*scale[2]*scale[2]*_phidp[20*i+6]); + multipole[8]*phi[7] + multipole[9]*phi[5]
- multipole[7]*phi[8] - multipole[9]*phi[6]);
torques[iIndex][1] += 0.5*_electric*(multipole[1]*scale[2]*_phidp[20*i+3] - multipole[3]*scale[0]*_phidp[20*i+1] torques[iIndex][1] += 0.5*_electric*(multipole[1]*phi[3] - multipole[3]*phi[1]
+ 2.0*(multipole[4]-multipole[6])*scale[0]*scale[2]*_phidp[20*i+8] + 2.0*(multipole[4]-multipole[6])*phi[8]
+ multipole[7]*scale[1]*scale[2]*_phidp[20*i+9] + multipole[8]*scale[2]*scale[2]*_phidp[20*i+6] + multipole[7]*phi[9] + multipole[8]*phi[6]
- multipole[8]*scale[0]*scale[0]*_phidp[20*i+4] - multipole[9]*scale[0]*scale[1]*_phidp[20*i+7]); - multipole[8]*phi[4] - multipole[9]*phi[7]);
torques[iIndex][2] += 0.5*_electric*(multipole[2]*scale[0]*_phidp[20*i+1] - multipole[1]*scale[1]*_phidp[20*i+2] torques[iIndex][2] += 0.5*_electric*(multipole[2]*phi[1] - multipole[1]*phi[2]
+ 2.0*(multipole[5]-multipole[4])*scale[0]*scale[1]*_phidp[20*i+7] + 2.0*(multipole[5]-multipole[4])*phi[7]
+ multipole[7]*scale[0]*scale[0]*_phidp[20*i+4] + multipole[9]*scale[0]*scale[2]*_phidp[20*i+8] + multipole[7]*phi[4] + multipole[9]*phi[8]
- multipole[7]*scale[1]*scale[1]*_phidp[20*i+5] - multipole[8]*scale[1]*scale[2]*_phidp[20*i+9]); - multipole[7]*phi[5] - multipole[8]*phi[9]);
// Compute the force and energy. // Compute the force and energy.
multipole[1] *= scale[0]; multipole[1] = _transformed[i].dipole[0];
multipole[2] *= scale[1]; multipole[2] = _transformed[i].dipole[1];
multipole[3] *= scale[2]; multipole[3] = _transformed[i].dipole[2];
multipole[4] = _transformed[i].quadrupole[QXX];
multipole[4] *= scale[0]*scale[0]; multipole[5] = _transformed[i].quadrupole[QYY];
multipole[5] *= scale[1]*scale[1]; multipole[6] = _transformed[i].quadrupole[QZZ];
multipole[6] *= scale[2]*scale[2]; multipole[7] = _transformed[i].quadrupole[QXY];
multipole[7] *= scale[0]*scale[1]; multipole[8] = _transformed[i].quadrupole[QXZ];
multipole[8] *= scale[0]*scale[2]; multipole[9] = _transformed[i].quadrupole[QYZ];
multipole[9] *= scale[1]*scale[2]; // multipole[1] *= scale[0];
// multipole[2] *= scale[1];
inducedDipole[0] = _inducedDipole[i][0]; // multipole[3] *= scale[2];
inducedDipole[1] = _inducedDipole[i][1]; //
inducedDipole[2] = _inducedDipole[i][2]; // multipole[4] *= scale[0]*scale[0];
// multipole[5] *= scale[1]*scale[1];
inducedDipolePolar[0] = _inducedDipolePolar[i][0]; // multipole[6] *= scale[2]*scale[2];
inducedDipolePolar[1] = _inducedDipolePolar[i][1]; // multipole[7] *= scale[0]*scale[1];
inducedDipolePolar[2] = _inducedDipolePolar[i][2]; // multipole[8] *= scale[0]*scale[2];
// multipole[9] *= scale[1]*scale[2];
energy += scale[0]*inducedDipole[0]*_phi[20*i+1];
energy += scale[1]*inducedDipole[1]*_phi[20*i+2]; inducedDipole[0] = _inducedDipole[i][0]*cartToFrac[0][0] + _inducedDipole[i][1]*cartToFrac[0][1] + _inducedDipole[i][2]*cartToFrac[0][2];
energy += scale[2]*inducedDipole[2]*_phi[20*i+3]; inducedDipole[1] = _inducedDipole[i][0]*cartToFrac[1][0] + _inducedDipole[i][1]*cartToFrac[1][1] + _inducedDipole[i][2]*cartToFrac[1][2];
inducedDipole[2] = _inducedDipole[i][0]*cartToFrac[2][0] + _inducedDipole[i][1]*cartToFrac[2][1] + _inducedDipole[i][2]*cartToFrac[2][2];
inducedDipolePolar[0] = _inducedDipolePolar[i][0]*cartToFrac[0][0] + _inducedDipolePolar[i][1]*cartToFrac[0][1] + _inducedDipolePolar[i][2]*cartToFrac[0][2];
inducedDipolePolar[1] = _inducedDipolePolar[i][0]*cartToFrac[1][0] + _inducedDipolePolar[i][1]*cartToFrac[1][1] + _inducedDipolePolar[i][2]*cartToFrac[1][2];
inducedDipolePolar[2] = _inducedDipolePolar[i][0]*cartToFrac[2][0] + _inducedDipolePolar[i][1]*cartToFrac[2][1] + _inducedDipolePolar[i][2]*cartToFrac[2][2];
energy += inducedDipole[0]*_phi[20*i+1];
energy += inducedDipole[1]*_phi[20*i+2];
energy += inducedDipole[2]*_phi[20*i+3];
RealVec f = RealVec(0.0, 0.0, 0.0); RealVec f = RealVec(0.0, 0.0, 0.0);
...@@ -5789,47 +5911,49 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeReciprocalSpaceInducedDipole ...@@ -5789,47 +5911,49 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeReciprocalSpaceInducedDipole
int j2 = deriv2[k+1]; int j2 = deriv2[k+1];
int j3 = deriv3[k+1]; int j3 = deriv3[k+1];
f[0] += (inducedDipole[k]+inducedDipolePolar[k])*_phi[20*i+j1]*(scale[k]/scale[0]); f[0] += (inducedDipole[k]+inducedDipolePolar[k])*_phi[20*i+j1];
f[1] += (inducedDipole[k]+inducedDipolePolar[k])*_phi[20*i+j2]*(scale[k]/scale[1]); f[1] += (inducedDipole[k]+inducedDipolePolar[k])*_phi[20*i+j2];
f[2] += (inducedDipole[k]+inducedDipolePolar[k])*_phi[20*i+j3]*(scale[k]/scale[2]); f[2] += (inducedDipole[k]+inducedDipolePolar[k])*_phi[20*i+j3];
if (polarizationType == AmoebaReferenceMultipoleForce::Mutual) if (polarizationType == AmoebaReferenceMultipoleForce::Mutual)
{ {
f[0] += (inducedDipole[k]*_phip[10*i+j1] + inducedDipolePolar[k]*_phid[10*i+j1])*(scale[k]/scale[0]); f[0] += (inducedDipole[k]*_phip[10*i+j1] + inducedDipolePolar[k]*_phid[10*i+j1]);
f[1] += (inducedDipole[k]*_phip[10*i+j2] + inducedDipolePolar[k]*_phid[10*i+j2])*(scale[k]/scale[1]); f[1] += (inducedDipole[k]*_phip[10*i+j2] + inducedDipolePolar[k]*_phid[10*i+j2]);
f[2] += (inducedDipole[k]*_phip[10*i+j3] + inducedDipolePolar[k]*_phid[10*i+j3])*(scale[k]/scale[2]); f[2] += (inducedDipole[k]*_phip[10*i+j3] + inducedDipolePolar[k]*_phid[10*i+j3]);
} }
} }
f[0] *= scale[0];
f[1] *= scale[1];
f[2] *= scale[2];
for (int k = 0; k < 10; k++) { for (int k = 0; k < 10; k++) {
f[0] += multipole[k]*_phidp[20*i+deriv1[k]]; f[0] += multipole[k]*_phidp[20*i+deriv1[k]];
f[1] += multipole[k]*_phidp[20*i+deriv2[k]]; f[1] += multipole[k]*_phidp[20*i+deriv2[k]];
f[2] += multipole[k]*_phidp[20*i+deriv3[k]]; f[2] += multipole[k]*_phidp[20*i+deriv3[k]];
} }
f[0] *= scale[0]; // f[0] *= scale[0];
f[1] *= scale[1]; // f[1] *= scale[1];
f[2] *= scale[2]; // f[2] *= scale[2];
f *= (0.5*_electric); f *= (0.5*_electric);
forces[iIndex] -= f; forces[iIndex] -= RealVec(f[0]*fracToCart[0][0] + f[1]*fracToCart[0][1] + f[2]*fracToCart[0][2],
f[0]*fracToCart[1][0] + f[1]*fracToCart[1][1] + f[2]*fracToCart[1][2],
f[0]*fracToCart[2][0] + f[1]*fracToCart[2][1] + f[2]*fracToCart[2][2]);
} }
return (0.5*_electric*energy); return (0.5*_electric*energy);
} }
void AmoebaReferencePmeMultipoleForce::recordFixedMultipoleField() void AmoebaReferencePmeMultipoleForce::recordFixedMultipoleField()
{ {
RealVec scale; // RealVec scale;
getPmeScale(scale); // getPmeScale(scale);
scale *= -1.0; // scale *= -1.0;
RealVec fracToCart[3];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
fracToCart[i][j] = _pmeGridDimensions[j]*_recipBoxVectors[i][j];
for (int i = 0; i < _numParticles; i++) { for (int i = 0; i < _numParticles; i++) {
_fixedMultipoleField[i][0] = scale[0]*_phi[20*i+1]; _fixedMultipoleField[i][0] = -(_phi[20*i+1]*fracToCart[0][0] + _phi[20*i+2]*fracToCart[0][1] + _phi[20*i+3]*fracToCart[0][2]);
_fixedMultipoleField[i][1] = scale[1]*_phi[20*i+2]; _fixedMultipoleField[i][1] = -(_phi[20*i+1]*fracToCart[1][0] + _phi[20*i+2]*fracToCart[1][1] + _phi[20*i+3]*fracToCart[1][2]);
_fixedMultipoleField[i][2] = scale[2]*_phi[20*i+3]; _fixedMultipoleField[i][2] = -(_phi[20*i+1]*fracToCart[2][0] + _phi[20*i+2]*fracToCart[2][1] + _phi[20*i+3]*fracToCart[2][2]);
} }
return; return;
} }
...@@ -5844,18 +5968,22 @@ void AmoebaReferencePmeMultipoleForce::initializeInducedDipoles(vector<UpdateInd ...@@ -5844,18 +5968,22 @@ void AmoebaReferencePmeMultipoleForce::initializeInducedDipoles(vector<UpdateInd
void AmoebaReferencePmeMultipoleForce::recordInducedDipoleField(vector<RealVec>& field, vector<RealVec>& fieldPolar) void AmoebaReferencePmeMultipoleForce::recordInducedDipoleField(vector<RealVec>& field, vector<RealVec>& fieldPolar)
{ {
RealVec scale; // RealVec scale;
getPmeScale(scale); // getPmeScale(scale);
scale *= -1.0; // scale *= -1.0;
RealVec fracToCart[3];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
fracToCart[i][j] = _pmeGridDimensions[j]*_recipBoxVectors[i][j];
for (int i = 0; i < _numParticles; i++) { for (int i = 0; i < _numParticles; i++) {
field[i][0] += scale[0]*_phid[10*i+1]; field[i][0] -= _phid[10*i+1]*fracToCart[0][0] + _phid[10*i+2]*fracToCart[0][1] + _phid[10*i+3]*fracToCart[0][2];
field[i][1] += scale[1]*_phid[10*i+2]; field[i][1] -= _phid[10*i+1]*fracToCart[1][0] + _phid[10*i+2]*fracToCart[1][1] + _phid[10*i+3]*fracToCart[1][2];
field[i][2] += scale[2]*_phid[10*i+3]; field[i][2] -= _phid[10*i+1]*fracToCart[2][0] + _phid[10*i+2]*fracToCart[2][1] + _phid[10*i+3]*fracToCart[2][2];
fieldPolar[i][0] += scale[0]*_phip[10*i+1]; fieldPolar[i][0] -= _phip[10*i+1]*fracToCart[0][0] + _phip[10*i+2]*fracToCart[0][1] + _phip[10*i+3]*fracToCart[0][2];
fieldPolar[i][1] += scale[1]*_phip[10*i+2]; fieldPolar[i][1] -= _phip[10*i+1]*fracToCart[1][0] + _phip[10*i+2]*fracToCart[1][1] + _phip[10*i+3]*fracToCart[1][2];
fieldPolar[i][2] += scale[2]*_phip[10*i+3]; fieldPolar[i][2] -= _phip[10*i+1]*fracToCart[2][0] + _phip[10*i+2]*fracToCart[2][1] + _phip[10*i+3]*fracToCart[2][2];
} }
return; return;
} }
......
...@@ -592,6 +592,16 @@ protected: ...@@ -592,6 +592,16 @@ protected:
RealOpenMM polarity; RealOpenMM polarity;
}; };
/**
* Particle parameters transformed into fractional coordinates
*/
class TransformedMultipole {
public:
RealOpenMM charge;
RealVec dipole;
RealOpenMM quadrupole[6];
};
/* /*
* Helper class used in calculating induced dipoles * Helper class used in calculating induced dipoles
*/ */
...@@ -618,6 +628,7 @@ protected: ...@@ -618,6 +628,7 @@ protected:
RealOpenMM _mScale[5]; RealOpenMM _mScale[5];
RealOpenMM _uScale[5]; RealOpenMM _uScale[5];
std::vector<TransformedMultipole> _transformed;
std::vector<RealVec> _fixedMultipoleField; std::vector<RealVec> _fixedMultipoleField;
std::vector<RealVec> _fixedMultipoleFieldPolar; std::vector<RealVec> _fixedMultipoleFieldPolar;
std::vector<RealVec> _inducedDipole; std::vector<RealVec> _inducedDipole;
...@@ -1327,9 +1338,9 @@ public: ...@@ -1327,9 +1338,9 @@ public:
/** /**
* Set periodic box size. * Set periodic box size.
* *
* @param boxSize box dimensions * @param vectors the vectors defining the periodic box
*/ */
void setPeriodicBoxSize(RealVec& boxSize); void setPeriodicBoxSize(OpenMM::RealVec* vectors);
private: private:
...@@ -1340,8 +1351,8 @@ private: ...@@ -1340,8 +1351,8 @@ private:
RealOpenMM _cutoffDistance; RealOpenMM _cutoffDistance;
RealOpenMM _cutoffDistanceSquared; RealOpenMM _cutoffDistanceSquared;
RealVec _invPeriodicBoxSize; RealVec _recipBoxVectors[3];
RealVec _periodicBoxSize; RealVec _periodicBoxVectors[3];
int _totalGridSize; int _totalGridSize;
IntVec _pmeGridDimensions; IntVec _pmeGridDimensions;
...@@ -1382,12 +1393,6 @@ private: ...@@ -1382,12 +1393,6 @@ private:
*/ */
void getPeriodicDelta(RealVec& deltaR) const; void getPeriodicDelta(RealVec& deltaR) const;
/**
* Get PME scale.
*
*/
void getPmeScale(RealVec& scale) const;
/** /**
* Calculate damped inverse distances. * Calculate damped inverse distances.
* *
...@@ -1460,7 +1465,6 @@ private: ...@@ -1460,7 +1465,6 @@ private:
/** /**
* Compute induced dipole grid value. * Compute induced dipole grid value.
* *
* @param particleData vector of particle positions and parameters (charge, labFrame dipoles, quadrupoles, ...)
* @param particleGridIndices particle grid indices * @param particleGridIndices particle grid indices
* @param scale integer grid dimension/box size for each dimension * @param scale integer grid dimension/box size for each dimension
* @param ix x-dimension offset value * @param ix x-dimension offset value
...@@ -1469,8 +1473,17 @@ private: ...@@ -1469,8 +1473,17 @@ private:
* @param inputInducedDipole induced dipole value * @param inputInducedDipole induced dipole value
* @param inputInducedDipolePolar induced dipole value * @param inputInducedDipolePolar induced dipole value
*/ */
RealOpenMM computeFixedMultipolesGridValue(const vector<MultipoleParticleData>& particleData, RealOpenMM computeFixedMultipolesGridValue(const int2& particleGridIndices, int ix, int iy, const IntVec& gridPoint) const;
const int2& particleGridIndices, const RealVec& scale, int ix, int iy, const IntVec& gridPoint) const;
/**
* Transform multipoles from cartesian coordinates to fractional coordinates.
*/
void transformMultipolesToFractionalCoordinates(const vector<MultipoleParticleData>& particleData);
/**
* Transform potential from fractional coordinates to cartesian coordinates.
*/
void transformPotentialToCartesianCoordinates(const std::vector<RealOpenMM>& fphi, std::vector<RealOpenMM>& cphi) const;
/** /**
* Spread fixed multipoles onto PME grid. * Spread fixed multipoles onto PME grid.
...@@ -1568,7 +1581,7 @@ private: ...@@ -1568,7 +1581,7 @@ private:
* @param inputInducedDipole induced dipole value * @param inputInducedDipole induced dipole value
* @param inputInducedDipolePolar induced dipole polar value * @param inputInducedDipolePolar induced dipole polar value
*/ */
t_complex computeInducedDipoleGridValue(const int2& atomIndices, const RealVec& scale, int ix, int iy, const IntVec& gridPoint, t_complex computeInducedDipoleGridValue(const int2& atomIndices, const RealVec* fracToCart, int ix, int iy, const IntVec& gridPoint,
const std::vector<RealVec>& inputInducedDipole, const std::vector<RealVec>& inputInducedDipole,
const std::vector<RealVec>& inputInducedDipolePolar) const; const std::vector<RealVec>& inputInducedDipolePolar) const;
......
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