Commit 09fb3811 authored by Mark Friedrichs's avatar Mark Friedrichs
Browse files

Added checkChiral for chiral systems (Reference/Cuda)

Added support for missing axis types (Cuda only)
Removed rotationMatrix
parent 562cfb39
...@@ -63,7 +63,7 @@ public: ...@@ -63,7 +63,7 @@ public:
PME = 1 PME = 1
}; };
enum MultipoleAxisTypes { ZThenX, Bisector }; enum MultipoleAxisTypes { ZThenX, Bisector, ZBisect, ThreeFold, ZOnly, LastAxisTypeIndex };
// Algorithm used to converge mutual induced dipoles: // Algorithm used to converge mutual induced dipoles:
// SOR: successive-over-relaxation // SOR: successive-over-relaxation
......
...@@ -62,12 +62,17 @@ void AmoebaMultipoleForceImpl::initialize(ContextImpl& context) { ...@@ -62,12 +62,17 @@ void AmoebaMultipoleForceImpl::initialize(ContextImpl& context) {
owner.getMultipoleParameters( ii, charge, molecularDipole, molecularQuadrupole, axisType, multipoleAtomZ, multipoleAtomX, multipoleAtomY, owner.getMultipoleParameters( ii, charge, molecularDipole, molecularQuadrupole, axisType, multipoleAtomZ, multipoleAtomX, multipoleAtomY,
thole, dampingFactor, polarity ); thole, dampingFactor, polarity );
// only 'Z-then-X' or 'Bisector' currently handled // only 'Z-then-X', 'Bisector', Z-Bisect, ThreeFold currently handled
if( axisType != AmoebaMultipoleForce::ZThenX && axisType != AmoebaMultipoleForce::Bisector ){ if( axisType != AmoebaMultipoleForce::ZThenX && axisType != AmoebaMultipoleForce::Bisector &&
axisType != AmoebaMultipoleForce::ZBisect && axisType != AmoebaMultipoleForce::ThreeFold &&
axisType != AmoebaMultipoleForce::ZOnly ) {
std::stringstream buffer; std::stringstream buffer;
buffer << "AmoebaMultipoleForce: axis type=" << axisType; buffer << "AmoebaMultipoleForce: axis type=" << axisType;
buffer << " not currently handled - only axisTypes[ " << AmoebaMultipoleForce::ZThenX << ", " << AmoebaMultipoleForce::Bisector << "] (ZThenX, Bisector) currently handled ."; buffer << " not currently handled - only axisTypes[ ";
buffer << AmoebaMultipoleForce::ZThenX << ", " << AmoebaMultipoleForce::Bisector << ", ";
buffer << AmoebaMultipoleForce::ZBisect << ", " << AmoebaMultipoleForce::ThreeFold;
buffer << "] (ZThenX, Bisector, Z-Bisect, ThreeFold) currently handled .";
throw OpenMMException(buffer.str()); throw OpenMMException(buffer.str());
} }
} }
......
...@@ -338,11 +338,20 @@ void gpuPrintCudaAmoebaGmxSimulation(amoebaGpuContext amoebaGpu, FILE* log ) ...@@ -338,11 +338,20 @@ void gpuPrintCudaAmoebaGmxSimulation(amoebaGpuContext amoebaGpu, FILE* log )
(void) fprintf( log, " pAmoebaUreyBradleyID %p\n", amoebaGpu->amoebaSim.pAmoebaUreyBradleyID ); (void) fprintf( log, " pAmoebaUreyBradleyID %p\n", amoebaGpu->amoebaSim.pAmoebaUreyBradleyID );
(void) fprintf( log, " pAmoebaUreyBradleyParameter %p\n", amoebaGpu->amoebaSim.pAmoebaUreyBradleyParameter ); (void) fprintf( log, " pAmoebaUreyBradleyParameter %p\n", amoebaGpu->amoebaSim.pAmoebaUreyBradleyParameter );
if( amoebaGpu->psRotationMatrix)(void) fprintf( log, "\n" ); // if( amoebaGpu->psRotationMatrix)(void) fprintf( log, "\n" );
gpuPrintCudaStreamFloat( amoebaGpu->psRotationMatrix, log ); // gpuPrintCudaStreamFloat( amoebaGpu->psRotationMatrix, log );
// (void) fprintf( log, " pRotationMatrix %p\n", amoebaGpu->amoebaSim.pRotationMatrix);
gpuPrintCudaStreamInt4( amoebaGpu->psMultipoleParticlesIdsAndAxisType, log ); gpuPrintCudaStreamInt4( amoebaGpu->psMultipoleParticlesIdsAndAxisType, log );
(void) fprintf( log, " pMultipoleParticlesIdsAndAxisType %p\n", amoebaGpu->amoebaSim.pMultipoleParticlesIdsAndAxisType);
gpuPrintCudaStreamInt( amoebaGpu->psMultipoleAxisOffset, log );
(void) fprintf( log, " pMultipoleAxisOffset %p\n", amoebaGpu->amoebaSim.pMultipoleAxisOffset);
gpuPrintCudaStreamFloat( amoebaGpu->psMolecularDipole, log ); gpuPrintCudaStreamFloat( amoebaGpu->psMolecularDipole, log );
(void) fprintf( log, " pMolecularDipole %p\n", amoebaGpu->amoebaSim.pMolecularDipole);
gpuPrintCudaStreamFloat( amoebaGpu->psMolecularQuadrupole, log ); gpuPrintCudaStreamFloat( amoebaGpu->psMolecularQuadrupole, log );
(void) fprintf( log, " pMolecularQuadrupole %p\n", amoebaGpu->amoebaSim.pMolecularQuadrupole );
gpuPrintCudaStreamFloat( amoebaGpu->psLabFrameDipole, log ); gpuPrintCudaStreamFloat( amoebaGpu->psLabFrameDipole, log );
gpuPrintCudaStreamFloat( amoebaGpu->psLabFrameQuadrupole, log ); gpuPrintCudaStreamFloat( amoebaGpu->psLabFrameQuadrupole, log );
...@@ -1276,7 +1285,7 @@ static void gpuRotationToLabFrameAllocate( amoebaGpuContext amoebaGpu ) ...@@ -1276,7 +1285,7 @@ static void gpuRotationToLabFrameAllocate( amoebaGpuContext amoebaGpu )
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
if( amoebaGpu->psRotationMatrix != NULL ){ if( amoebaGpu->psMultipoleParticlesIdsAndAxisType != NULL ){
return; return;
} }
...@@ -1289,23 +1298,33 @@ static void gpuRotationToLabFrameAllocate( amoebaGpuContext amoebaGpu ) ...@@ -1289,23 +1298,33 @@ static void gpuRotationToLabFrameAllocate( amoebaGpuContext amoebaGpu )
// work space // work space
amoebaGpu->psRotationMatrix = new CUDAStream<float>(9*amoebaGpu->paddedNumberOfAtoms, 1, "RotationMatrix"); // amoebaGpu->psRotationMatrix = new CUDAStream<float>(9*amoebaGpu->paddedNumberOfAtoms, 1, "RotationMatrix");
// amoebaGpu->amoebaSim.pRotationMatrix = amoebaGpu->psRotationMatrix->_pDevStream[0];
// parameters // parameters
amoebaGpu->psMultipoleParticlesIdsAndAxisType = new CUDAStream<int4>(amoebaGpu->paddedNumberOfAtoms, 1, "MultipoleParticlesIdsAndAxisType"); amoebaGpu->psMultipoleParticlesIdsAndAxisType = new CUDAStream<int4>(amoebaGpu->paddedNumberOfAtoms, 1, "MultipoleParticlesIdsAndAxisType");
amoebaGpu->psMolecularDipole = new CUDAStream<float>(3*amoebaGpu->paddedNumberOfAtoms, 1, "MolecularDipole"); amoebaGpu->amoebaSim.pMultipoleParticlesIdsAndAxisType = amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pDevStream[0];
amoebaGpu->psMolecularQuadrupole = new CUDAStream<float>(9*amoebaGpu->paddedNumberOfAtoms, 1, "MolecularQuadrupole");
amoebaGpu->psMultipoleAxisOffset = new CUDAStream<int>(amoebaGpu->paddedNumberOfAtoms, 1, "psMultipoleAxisOffset");
amoebaGpu->amoebaSim.pMultipoleAxisOffset = amoebaGpu->psMultipoleAxisOffset->_pDevStream[0];
amoebaGpu->psMolecularDipole = new CUDAStream<float>(3*amoebaGpu->paddedNumberOfAtoms, 1, "MolecularDipole");
amoebaGpu->amoebaSim.pMolecularDipole = amoebaGpu->psMolecularDipole->_pDevStream[0];
amoebaGpu->psMolecularQuadrupole = new CUDAStream<float>(9*amoebaGpu->paddedNumberOfAtoms, 1, "MolecularQuadrupole");
amoebaGpu->amoebaSim.pMolecularQuadrupole = amoebaGpu->psMolecularQuadrupole->_pDevStream[0];
// output // output
amoebaGpu->psLabFrameDipole = new CUDAStream<float>(3*amoebaGpu->paddedNumberOfAtoms, 1, "LabFrameDipole"); amoebaGpu->psLabFrameDipole = new CUDAStream<float>(3*amoebaGpu->paddedNumberOfAtoms, 1, "LabFrameDipole");
amoebaGpu->amoebaSim.pLabFrameDipole = amoebaGpu->psLabFrameDipole->_pDevStream[0]; amoebaGpu->amoebaSim.pLabFrameDipole = amoebaGpu->psLabFrameDipole->_pDevStream[0];
amoebaGpu->psLabFrameQuadrupole = new CUDAStream<float>(9*amoebaGpu->paddedNumberOfAtoms, 1, "LabFrameQuadrupole"); amoebaGpu->psLabFrameQuadrupole = new CUDAStream<float>(9*amoebaGpu->paddedNumberOfAtoms, 1, "LabFrameQuadrupole");
amoebaGpu->amoebaSim.pLabFrameQuadrupole = amoebaGpu->psLabFrameQuadrupole->_pDevStream[0]; amoebaGpu->amoebaSim.pLabFrameQuadrupole = amoebaGpu->psLabFrameQuadrupole->_pDevStream[0];
memset( amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0], 0, sizeof(int)*4*amoebaGpu->paddedNumberOfAtoms ); memset( amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0], 0, sizeof(int)*4*amoebaGpu->paddedNumberOfAtoms );
memset( amoebaGpu->psMultipoleAxisOffset->_pSysStream[0], 0, sizeof(int)*amoebaGpu->paddedNumberOfAtoms );
} }
static void gpuFixedEFieldAllocate( amoebaGpuContext amoebaGpu ) static void gpuFixedEFieldAllocate( amoebaGpuContext amoebaGpu )
...@@ -1597,7 +1616,7 @@ void gpuSetAmoebaMultipoleParameters(amoebaGpuContext amoebaGpu, const std::vect ...@@ -1597,7 +1616,7 @@ void gpuSetAmoebaMultipoleParameters(amoebaGpuContext amoebaGpu, const std::vect
std::vector<int> maxIndices; std::vector<int> maxIndices;
for( unsigned int ii = 0; ii < charges.size(); ii++ ){ for( unsigned int ii = 0; ii < charges.size(); ii++ ){
maxIndices.push_back(ii); maxIndices.push_back(ii);
amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].z = ii; amoebaGpu->psMultipoleAxisOffset->_pSysStream[0][ii] = ii;
} }
if( nonbondedMethod == 0 ){ if( nonbondedMethod == 0 ){
...@@ -1623,37 +1642,64 @@ void gpuSetAmoebaMultipoleParameters(amoebaGpuContext amoebaGpu, const std::vect ...@@ -1623,37 +1642,64 @@ void gpuSetAmoebaMultipoleParameters(amoebaGpuContext amoebaGpu, const std::vect
amoebaGpu->amoebaSim.dielec = 1.0f; amoebaGpu->amoebaSim.dielec = 1.0f;
} }
static const int maxAxisType = 5;
int axisTypeCount[maxAxisType+1] = { 0, 0, 0, 0, 0, 0 };
for( int ii = 0; ii < static_cast<int>(charges.size()); ii++ ){ for( int ii = 0; ii < static_cast<int>(charges.size()); ii++ ){
// axis type & multipole particles ids // axis type & multipole particles ids
amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].x = multipoleParticleZ[ii]; amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].x = multipoleParticleX[ii];
amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].y = multipoleParticleX[ii]; amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].y = multipoleParticleY[ii];
amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].z = multipoleParticleZ[ii];
amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].w = axisType[ii]; amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].w = axisType[ii];
if( axisType[ii] < (maxAxisType) && axisType[ii] > -1 ){
axisTypeCount[axisType[ii]]++;
} else {
axisTypeCount[maxAxisType]++;
}
// for z-only need to add access to random numbers
// and need test system
if( axisType[ii] == 4 ){
//fprintf( stderr, "Axis type z-only (atom=%d) not fully implemented -- aborting.\n", ii );
fprintf( stderr, "Warning: Axis type z-only (atom=%d) not fully implemented.\n", ii );
// exit(0);
}
int axisParticleIndex = multipoleParticleZ[ii]; int axisParticleIndex = multipoleParticleZ[ii];
if( maxIndices[axisParticleIndex] < ii ){ if( maxIndices[axisParticleIndex] < ii ){
maxIndices[axisParticleIndex] = ii; maxIndices[axisParticleIndex] = ii;
} }
if( amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][axisParticleIndex].z > ii ){ if( amoebaGpu->psMultipoleAxisOffset->_pSysStream[0][axisParticleIndex] > ii ){
amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][axisParticleIndex].z = ii; amoebaGpu->psMultipoleAxisOffset->_pSysStream[0][axisParticleIndex] = ii;
} }
axisParticleIndex = multipoleParticleX[ii]; axisParticleIndex = multipoleParticleX[ii];
if( maxIndices[axisParticleIndex] < ii ){ if( maxIndices[axisParticleIndex] < ii ){
maxIndices[axisParticleIndex] = ii; maxIndices[axisParticleIndex] = ii;
} }
if( amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][axisParticleIndex].z > ii ){ if( amoebaGpu->psMultipoleAxisOffset->_pSysStream[0][axisParticleIndex] > ii ){
amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][axisParticleIndex].z = ii; amoebaGpu->psMultipoleAxisOffset->_pSysStream[0][axisParticleIndex] = ii;
}
axisParticleIndex = multipoleParticleY[ii];
if( axisParticleIndex > -1 ){
if( maxIndices[axisParticleIndex] < ii ){
maxIndices[axisParticleIndex] = ii;
}
if( amoebaGpu->psMultipoleAxisOffset->_pSysStream[0][axisParticleIndex] > ii ){
amoebaGpu->psMultipoleAxisOffset->_pSysStream[0][axisParticleIndex] = ii;
}
} }
if( 0 && amoebaGpu->log ) if( 0 && amoebaGpu->log )
fprintf( amoebaGpu->log, "Z1 %4d [%4d %4d] %4d %4d %4d %4d %d %d\n", ii, fprintf( amoebaGpu->log, "Z1 %4d [%4d %4d] %4d %4d %4d %4d %d %d\n", ii,
multipoleParticleZ[ii], multipoleParticleX[ii], multipoleParticleX[ii], multipoleParticleY[ii], multipoleParticleZ[ii],
amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][multipoleParticleZ[ii]].z, amoebaGpu->psMultipoleAxisOffset->_pSysStream[0][multipoleParticleZ[ii]],
maxIndices[multipoleParticleZ[ii]], maxIndices[multipoleParticleZ[ii]],
amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][multipoleParticleX[ii]].z, amoebaGpu->psMultipoleAxisOffset->_pSysStream[0][multipoleParticleX[ii]],
maxIndices[multipoleParticleX[ii]], maxIndices[multipoleParticleX[ii]],
amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][0].z, maxIndices[0] ); amoebaGpu->psMultipoleAxisOffset->_pSysStream[0][0], maxIndices[0] );
// charges // charges
...@@ -1733,17 +1779,16 @@ void gpuSetAmoebaMultipoleParameters(amoebaGpuContext amoebaGpu, const std::vect ...@@ -1733,17 +1779,16 @@ void gpuSetAmoebaMultipoleParameters(amoebaGpuContext amoebaGpu, const std::vect
} }
#ifdef AMOEBA_DEBUG #ifdef AMOEBA_DEBUG
//if( amoebaGpu->log && ( ( ( ii < maxPrint ) || (ii >= (charges.size() - maxPrint) ) ) || ( ii == targetAtoms[0] || ii == targetAtoms[1]) ) ){
if( (amoebaGpu->log && ( ( ( ii < maxPrint ) || (ii >= (charges.size() - maxPrint) )) ) ) ){ if( (amoebaGpu->log && ( ( ( ii < maxPrint ) || (ii >= (charges.size() - maxPrint) )) ) ) ){
// axis particles // axis particles
(void) fprintf( amoebaGpu->log,"%u axis particles [%6d %6d %6d diff=%d %d] ", ii, (void) fprintf( amoebaGpu->log,"%u axis particles [%6d %6d %6d] axis=%d max=%d diff=%d ", ii,
amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].x, amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].x,
amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].y, amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].y,
amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].z, amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].z,
maxIndices[ii], maxIndices[ii] - amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].z, amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].w,
amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].w ); maxIndices[ii], maxIndices[ii] - amoebaGpu->psMultipoleAxisOffset->_pSysStream[0][ii] );
// dipole // dipole
...@@ -1886,6 +1931,13 @@ void gpuSetAmoebaMultipoleParameters(amoebaGpuContext amoebaGpu, const std::vect ...@@ -1886,6 +1931,13 @@ void gpuSetAmoebaMultipoleParameters(amoebaGpuContext amoebaGpu, const std::vect
} }
if( amoebaGpu->log ){
std::string axisLabel[maxAxisType+1] = { "ZThenX", "Bisector", "ZBisect", "ThreeFold", "ZOnly", "Unknown"};
for( unsigned int kk = 0; kk < (maxAxisType+1); kk++ ){
(void) fprintf( amoebaGpu->log, "%2u %10s atom count=%d\n", kk, axisLabel[kk].c_str(), axisTypeCount[kk] );
}
}
#if 0 #if 0
if( amoebaGpu->log ){ if( amoebaGpu->log ){
FILE* filePtr = fopen( "oldScale.txt", "w" ); FILE* filePtr = fopen( "oldScale.txt", "w" );
...@@ -1916,7 +1968,7 @@ void gpuSetAmoebaMultipoleParameters(amoebaGpuContext amoebaGpu, const std::vect ...@@ -1916,7 +1968,7 @@ void gpuSetAmoebaMultipoleParameters(amoebaGpuContext amoebaGpu, const std::vect
// axis type & multipole particles ids // axis type & multipole particles ids
int diff = maxIndices[ii] - amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pSysStream[0][ii].z; int diff = maxIndices[ii] - amoebaGpu->psMultipoleAxisOffset->_pSysStream[0][ii];
if( diff > amoebaGpu->maxMapTorqueDifference ){ if( diff > amoebaGpu->maxMapTorqueDifference ){
amoebaGpu->maxMapTorqueDifference = diff; amoebaGpu->maxMapTorqueDifference = diff;
} }
...@@ -1944,6 +1996,7 @@ void gpuSetAmoebaMultipoleParameters(amoebaGpuContext amoebaGpu, const std::vect ...@@ -1944,6 +1996,7 @@ void gpuSetAmoebaMultipoleParameters(amoebaGpuContext amoebaGpu, const std::vect
amoebaGpu->amoebaSim.paddedNumberOfAtoms = amoebaGpu->paddedNumberOfAtoms; amoebaGpu->amoebaSim.paddedNumberOfAtoms = amoebaGpu->paddedNumberOfAtoms;
amoebaGpu->psMultipoleParticlesIdsAndAxisType->Upload(); amoebaGpu->psMultipoleParticlesIdsAndAxisType->Upload();
amoebaGpu->psMultipoleAxisOffset->Upload();
amoebaGpu->psMolecularDipole->Upload(); amoebaGpu->psMolecularDipole->Upload();
amoebaGpu->psMolecularQuadrupole->Upload(); amoebaGpu->psMolecularQuadrupole->Upload();
amoebaGpu->psCovalentDegree->Upload(); amoebaGpu->psCovalentDegree->Upload();
...@@ -2707,8 +2760,9 @@ void amoebaGpuShutDown(amoebaGpuContext gpu) ...@@ -2707,8 +2760,9 @@ void amoebaGpuShutDown(amoebaGpuContext gpu)
// molecular frame multipoles // molecular frame multipoles
delete gpu->psRotationMatrix; //delete gpu->psRotationMatrix;
delete gpu->psMultipoleParticlesIdsAndAxisType; delete gpu->psMultipoleParticlesIdsAndAxisType;
delete gpu->psMultipoleAxisOffset;
delete gpu->psMolecularDipole; delete gpu->psMolecularDipole;
delete gpu->psMolecularQuadrupole; delete gpu->psMolecularQuadrupole;
delete gpu->psLabFrameDipole; delete gpu->psLabFrameDipole;
......
...@@ -139,6 +139,11 @@ struct cudaAmoebaGmxSimulation { ...@@ -139,6 +139,11 @@ struct cudaAmoebaGmxSimulation {
float scalingDistanceCutoff; // scaling cutoff float scalingDistanceCutoff; // scaling cutoff
float2* pDampingFactorAndThole; // Thole & damping factors float2* pDampingFactorAndThole; // Thole & damping factors
float* pRotationMatrix;
int4* pMultipoleParticlesIdsAndAxisType;
int* pMultipoleAxisOffset;
float* pMolecularDipole;
float* pMolecularQuadrupole;
float* pLabFrameDipole; float* pLabFrameDipole;
float* pLabFrameQuadrupole; float* pLabFrameQuadrupole;
float* pInducedDipole; float* pInducedDipole;
......
...@@ -129,6 +129,7 @@ struct _amoebaGpuContext { ...@@ -129,6 +129,7 @@ struct _amoebaGpuContext {
// multipole parameters // multipole parameters
CUDAStream<int4>* psMultipoleParticlesIdsAndAxisType; CUDAStream<int4>* psMultipoleParticlesIdsAndAxisType;
CUDAStream<int>* psMultipoleAxisOffset;
CUDAStream<float>* psMolecularDipole; CUDAStream<float>* psMolecularDipole;
CUDAStream<float>* psMolecularQuadrupole; CUDAStream<float>* psMolecularQuadrupole;
......
...@@ -52,6 +52,11 @@ __device__ static float normVector3( float* vector ) ...@@ -52,6 +52,11 @@ __device__ static float normVector3( float* vector )
#undef AMOEBA_DEBUG #undef AMOEBA_DEBUG
// ZThenX == 0
// Bisector == 1
// ZBisect == 2
// ThreeFold == 3
__global__ __global__
#if (__CUDA_ARCH__ >= 200) #if (__CUDA_ARCH__ >= 200)
__launch_bounds__(GF1XX_THREADS_PER_BLOCK, 1) __launch_bounds__(GF1XX_THREADS_PER_BLOCK, 1)
...@@ -60,145 +65,336 @@ __launch_bounds__(GT2XX_THREADS_PER_BLOCK, 1) ...@@ -60,145 +65,336 @@ __launch_bounds__(GT2XX_THREADS_PER_BLOCK, 1)
#else #else
__launch_bounds__(G8X_THREADS_PER_BLOCK, 1) __launch_bounds__(G8X_THREADS_PER_BLOCK, 1)
#endif #endif
void kCudaComputeLabFrameMoments_kernel( void kCudaComputeCheckChiral_kernel( void )
int numOfAtoms,
float *rotationMatrix,
float4 *atomCoord,
int4 *multiPoleAtoms,
float *molecularDipole, float *molecularQuadrupole,
float *labFrameDipole, float *labFrameQuadrupole )
{ {
float* vectorX; const int AD = 0;
float* vectorY; const int BD = 1;
float* vectorZ; const int CD = 2;
const int C = 3;
// --------------------------------------------------------------------------------------- float delta[4][3];
float4* atomCoord = cSim.pPosq;
int4* multiPoleAtoms = cAmoebaSim.pMultipoleParticlesIdsAndAxisType;
float* molecularDipole = cAmoebaSim.pMolecularDipole;
float* molecularQuadrupole = cAmoebaSim.pMolecularQuadrupole;
float* labFrameDipole = cAmoebaSim.pLabFrameDipole;
float* labFrameQuadrupole = cAmoebaSim.pLabFrameQuadrupole;
// ---------------------------------------------------------------------------------------
int atomIndex = blockIdx.x;
int axisType = multiPoleAtoms[atomIndex].w;
float* molDipole = &(molecularDipole[atomIndex*3]);
float* labDipole = &(labFrameDipole[atomIndex*3]);
labDipole[0] = molDipole[0];
labDipole[1] = molDipole[1];
labDipole[2] = molDipole[2];
float* molQuadrupole = &(molecularQuadrupole[atomIndex*9]);
float* labQuadrupole = &(labFrameQuadrupole[atomIndex*9]);
labQuadrupole[0] = molQuadrupole[0];
labQuadrupole[1] = molQuadrupole[1];
labQuadrupole[2] = molQuadrupole[2];
labQuadrupole[3] = molQuadrupole[3];
labQuadrupole[4] = molQuadrupole[4];
labQuadrupole[5] = molQuadrupole[5];
labQuadrupole[6] = molQuadrupole[6];
labQuadrupole[7] = molQuadrupole[7];
labQuadrupole[8] = molQuadrupole[8];
// skip z-then-x
if( axisType == 0 )return;
// ---------------------------------------------------------------------------------------
int atomA = atomIndex;
int atomB = multiPoleAtoms[atomIndex].z;
int atomC = multiPoleAtoms[atomIndex].x;
int atomD = multiPoleAtoms[atomIndex].y;
delta[AD][0] = atomCoord[atomA].x - atomCoord[atomD].x;
delta[AD][1] = atomCoord[atomA].y - atomCoord[atomD].y;
delta[AD][2] = atomCoord[atomA].z - atomCoord[atomD].z;
delta[BD][0] = atomCoord[atomB].x - atomCoord[atomD].x;
delta[BD][1] = atomCoord[atomB].y - atomCoord[atomD].y;
delta[BD][2] = atomCoord[atomB].z - atomCoord[atomD].z;
delta[CD][0] = atomCoord[atomC].x - atomCoord[atomD].x;
delta[CD][1] = atomCoord[atomC].y - atomCoord[atomD].y;
delta[CD][2] = atomCoord[atomC].z - atomCoord[atomD].z;
delta[C][0] = delta[BD][1]*delta[CD][2] - delta[BD][2]*delta[CD][1];
delta[C][1] = delta[CD][1]*delta[AD][2] - delta[CD][2]*delta[AD][1];
delta[C][2] = delta[AD][1]*delta[BD][2] - delta[AD][2]*delta[BD][1];
float volume = delta[C][0]*delta[AD][0] + delta[C][1]*delta[BD][0] + delta[C][2]*delta[CD][0];
if( volume < 0.0 ){
labDipole[1] *= -1.0f; // pole(3,i)
labQuadrupole[1] *= -1.0f; // pole(6,i) && pole(8,i)
labQuadrupole[3] *= -1.0f; // pole(10,i) && pole(12,i)
labQuadrupole[5] *= -1.0f; // pole(6,i) && pole(8,i)
labQuadrupole[7] *= -1.0f; // pole(10,i) && pole(12,i)
}
int atomIndex = blockIdx.x;//__mul24(blockIdx.x,blockDim.x) + threadIdx.x ; }
// --------------------------------------------------------------------------------------- __global__
#if (__CUDA_ARCH__ >= 200)
__launch_bounds__(GF1XX_THREADS_PER_BLOCK, 1)
#elif (__CUDA_ARCH__ >= 130)
__launch_bounds__(GT2XX_THREADS_PER_BLOCK, 1)
#else
__launch_bounds__(G8X_THREADS_PER_BLOCK, 1)
#endif
void kCudaComputeLabFrameMoments_kernel( void )
{
// get coordinates of this atom and the z & x axis atoms float vectorX[3];
// compute the vector between the atoms and 1/sqrt(d2), d2 is distance between float vectorY[3];
// this atom and the axis atom float vectorZ[3];
int numOfAtoms = cSim.atoms;
//float* rotationMatrix = cAmoebaSim.pRotationMatrix;
float4* atomCoord = cSim.pPosq;
int4* multiPoleAtoms = cAmoebaSim.pMultipoleParticlesIdsAndAxisType;
float* labFrameDipole = cAmoebaSim.pLabFrameDipole;
float* labFrameQuadrupole = cAmoebaSim.pLabFrameQuadrupole;
// ---------------------------------------------------------------------------------------
int atomIndex = blockIdx.x;
// ---------------------------------------------------------------------------------------
// get coordinates of this atom and the z & x axis atoms
// compute the vector between the atoms and 1/sqrt(d2), d2 is distance between
// this atom and the axis atom
// this atom is referred to as the k-atom in notes below
// code common to ZThenX and Bisector
/*
vectorX = &(rotationMatrix[atomIndex*9]);
vectorY = &(rotationMatrix[atomIndex*9+ 3]);
vectorZ = &(rotationMatrix[atomIndex*9+ 6]);
*/
float4 coordinatesThisAtom = atomCoord[atomIndex];
int multipoleAtomIndex = multiPoleAtoms[atomIndex].z;
float4 coordinatesAxisAtom = atomCoord[multipoleAtomIndex];
vectorZ[0] = coordinatesAxisAtom.x - coordinatesThisAtom.x;
vectorZ[1] = coordinatesAxisAtom.y - coordinatesThisAtom.y;
vectorZ[2] = coordinatesAxisAtom.z - coordinatesThisAtom.z;
multipoleAtomIndex = multiPoleAtoms[atomIndex].x;
coordinatesAxisAtom = atomCoord[multipoleAtomIndex];
vectorX[0] = coordinatesAxisAtom.x - coordinatesThisAtom.x;
vectorX[1] = coordinatesAxisAtom.y - coordinatesThisAtom.y;
vectorX[2] = coordinatesAxisAtom.z - coordinatesThisAtom.z;
int axisType = multiPoleAtoms[atomIndex].w;
/*
z-only
(1) norm z
(2) select random x
(3) x = x - (x.z)z
(4) norm x
z-then-x
(1) norm z
(2) norm x (not needed)
(3) x = x - (x.z)z
(4) norm x
bisector
(1) norm z
(2) norm x
(3) z = x + z
(4) norm z
(5) x = x - (x.z)z
(6) norm x
z-bisect
(1) norm z
(2) norm x
(3) norm y
(3) x = x + y
(4) norm x
(5) x = x - (x.z)z
(6) norm x
3-fold
(1) norm z
(2) norm x
(3) norm y
(4) z = x + y + z
(5) norm z
(6) x = x - (x.z)z
(7) norm x
*/
// branch based on axis type
float sum = normVector3( vectorZ );
// this atom is referred to as the k-atom in notes below if( axisType == 1 ){
// code common to ZThenX and Bisector // bisector
sum = normVector3( vectorX );
vectorZ[0] += vectorX[0];
vectorZ[1] += vectorX[1];
vectorZ[2] += vectorX[2];
vectorX = &(rotationMatrix[atomIndex*9]); sum = normVector3( vectorZ );
vectorY = &(rotationMatrix[atomIndex*9+ 3]);
vectorZ = &(rotationMatrix[atomIndex*9+ 6]); } else if( axisType == 2 || axisType == 3 ){
float4 coordinatesThisAtom = atomCoord[atomIndex]; // z-bisect
multipoleAtomIndex = multiPoleAtoms[atomIndex].y;
coordinatesAxisAtom = atomCoord[multipoleAtomIndex];
vectorY[0] = coordinatesAxisAtom.x - coordinatesThisAtom.x;
vectorY[1] = coordinatesAxisAtom.y - coordinatesThisAtom.y;
vectorY[2] = coordinatesAxisAtom.z - coordinatesThisAtom.z;
sum = normVector3( vectorY );
sum = normVector3( vectorX );
if( axisType == 2 ){
vectorX[0] += vectorY[0];
vectorX[1] += vectorY[1];
vectorX[2] += vectorY[2];
sum = normVector3( vectorX );
} else {
// 3-fold
vectorZ[0] += vectorX[0] + vectorY[0];
vectorZ[1] += vectorX[1] + vectorY[1];
vectorZ[2] += vectorX[2] + vectorY[2];
sum = normVector3( vectorZ );
}
} else if( axisType == 4 ){
int multipoleAtomIndex = multiPoleAtoms[atomIndex].x; vectorX[0] = 0.1f;
float4 coordinatesAxisAtom = atomCoord[multipoleAtomIndex]; vectorX[1] = 0.1f;
vectorX[2] = 0.1f;
}
// x = x - (x.z)z
vectorZ[0] = coordinatesAxisAtom.x - coordinatesThisAtom.x; float dot = vectorZ[0]*vectorX[0] + vectorZ[1]*vectorX[1] + vectorZ[2]*vectorX[2];
vectorZ[1] = coordinatesAxisAtom.y - coordinatesThisAtom.y;
vectorZ[2] = coordinatesAxisAtom.z - coordinatesThisAtom.z; vectorX[0] -= dot*vectorZ[0];
vectorX[1] -= dot*vectorZ[1];
vectorX[2] -= dot*vectorZ[2];
multipoleAtomIndex = multiPoleAtoms[atomIndex].y; sum = normVector3( vectorX );
coordinatesAxisAtom = atomCoord[multipoleAtomIndex];
vectorX[0] = coordinatesAxisAtom.x - coordinatesThisAtom.x; vectorY[0] = (vectorZ[1]*vectorX[2]) - (vectorZ[2]*vectorX[1]);
vectorX[1] = coordinatesAxisAtom.y - coordinatesThisAtom.y; vectorY[1] = (vectorZ[2]*vectorX[0]) - (vectorZ[0]*vectorX[2]);
vectorX[2] = coordinatesAxisAtom.z - coordinatesThisAtom.z; vectorY[2] = (vectorZ[0]*vectorX[1]) - (vectorZ[1]*vectorX[0]);
// use identity rotation matrix for unrecognized axis types
int axisType = multiPoleAtoms[atomIndex].w; if( axisType < 0 || axisType > 4 ){
float sum = normVector3( vectorZ );
// branch based on axis type
if( axisType == 1 ){
// bisector vectorX[0] = 1.0f;
// dx = dx1 + dx2 (in Tinker code) vectorX[1] = 0.0f;
vectorX[2] = 0.0f;
sum = normVector3( vectorX );
vectorZ[0] += vectorX[0];
vectorZ[1] += vectorX[1];
vectorZ[2] += vectorX[2];
sum = normVector3( vectorZ ); vectorY[0] = 0.0f;
vectorY[1] = 1.0f;
vectorY[2] = 0.0f;
} vectorZ[0] = 0.0f;
vectorZ[1] = 0.0f;
float dot = vectorZ[0]*vectorX[0] + vectorZ[1]*vectorX[1] + vectorZ[2]*vectorX[2]; vectorZ[2] = 1.0f;
}
vectorX[0] -= dot*vectorZ[0];
vectorX[1] -= dot*vectorZ[1];
vectorX[2] -= dot*vectorZ[2];
sum = normVector3( vectorX ); float molDipole[3];
float* labDipole = &(labFrameDipole[atomIndex*3]);
vectorY[0] = (vectorZ[1]*vectorX[2]) - (vectorZ[2]*vectorX[1]); molDipole[0] = labDipole[0];
vectorY[1] = (vectorZ[2]*vectorX[0]) - (vectorZ[0]*vectorX[2]); molDipole[1] = labDipole[1];
vectorY[2] = (vectorZ[0]*vectorX[1]) - (vectorZ[1]*vectorX[0]); molDipole[2] = labDipole[2];
// set out-of-range elements to 0.0f
labDipole[0] = atomIndex >= numOfAtoms ? 0.0f : molDipole[0]*vectorX[0] + molDipole[1]*vectorY[0] + molDipole[2]*vectorZ[0];
labDipole[1] = atomIndex >= numOfAtoms ? 0.0f : molDipole[0]*vectorX[1] + molDipole[1]*vectorY[1] + molDipole[2]*vectorZ[1];
labDipole[2] = atomIndex >= numOfAtoms ? 0.0f : molDipole[0]*vectorX[2] + molDipole[1]*vectorY[2] + molDipole[2]*vectorZ[2];
// ---------------------------------------------------------------------------------------
float* rPole[3];
float mPole[3][3];
float* labQuadrupole = &(labFrameQuadrupole[atomIndex*9]);
for( int ii = 0; ii < 3; ii++ ){
mPole[ii][0] = labQuadrupole[3*ii+0];
mPole[ii][1] = labQuadrupole[3*ii+1];
mPole[ii][2] = labQuadrupole[3*ii+2];
float* molDipole = &(molecularDipole[atomIndex*3]); rPole[ii] = labQuadrupole + ii*3;
float* labDipole = &(labFrameDipole[atomIndex*3]); rPole[ii][0] = 0.0f;
rPole[ii][1] = 0.0f;
// set out-of-range elements to 0.0f rPole[ii][2] = 0.0f;
labDipole[0] = atomIndex >= numOfAtoms ? 0.0f : molDipole[0]*vectorX[0] + molDipole[1]*vectorY[0] + molDipole[2]*vectorZ[0]; }
labDipole[1] = atomIndex >= numOfAtoms ? 0.0f : molDipole[0]*vectorX[1] + molDipole[1]*vectorY[1] + molDipole[2]*vectorZ[1];
labDipole[2] = atomIndex >= numOfAtoms ? 0.0f : molDipole[0]*vectorX[2] + molDipole[1]*vectorY[2] + molDipole[2]*vectorZ[2]; int ii = threadIdx.x;
if( ii < 3 ){
// --------------------------------------------------------------------------------------- for( int jj = ii; jj < 3; jj++ ){
const float * mPole[3]; rPole[ii][jj] += vectorX[ii]*vectorX[jj]*mPole[0][0];
float* rPole[3]; rPole[ii][jj] += vectorX[ii]*vectorY[jj]*mPole[0][1];
rPole[ii][jj] += vectorX[ii]*vectorZ[jj]*mPole[0][2];
float* molQuadrupole = &(molecularQuadrupole[atomIndex*9]);
float* labQuadrupole = &(labFrameQuadrupole[atomIndex*9]); rPole[ii][jj] += vectorY[ii]*vectorX[jj]*mPole[1][0];
rPole[ii][jj] += vectorY[ii]*vectorY[jj]*mPole[1][1];
for( int ii = 0; ii < 3; ii++ ){ rPole[ii][jj] += vectorY[ii]*vectorZ[jj]*mPole[1][2];
mPole[ii] = molQuadrupole + ii*3;
rPole[ii] = labQuadrupole + ii*3; rPole[ii][jj] += vectorZ[ii]*vectorX[jj]*mPole[2][0];
rPole[ii][0] = rPole[ii][1] = rPole[ii][2] = 0.0f; rPole[ii][jj] += vectorZ[ii]*vectorY[jj]*mPole[2][1];
} rPole[ii][jj] += vectorZ[ii]*vectorZ[jj]*mPole[2][2];
}
int ii = threadIdx.x; }
if( ii < 3 ){
for( int jj = ii; jj < 3; jj++ ){ __syncthreads();
rPole[ii][jj] += vectorX[ii]*vectorX[jj]*mPole[0][0];
rPole[ii][jj] += vectorX[ii]*vectorY[jj]*mPole[0][1]; rPole[1][0] = rPole[0][1];
rPole[ii][jj] += vectorX[ii]*vectorZ[jj]*mPole[0][2]; rPole[2][0] = rPole[0][2];
rPole[2][1] = rPole[1][2];
rPole[ii][jj] += vectorY[ii]*vectorX[jj]*mPole[1][0];
rPole[ii][jj] += vectorY[ii]*vectorY[jj]*mPole[1][1]; // set out-of-range elements to 0.0f
rPole[ii][jj] += vectorY[ii]*vectorZ[jj]*mPole[1][2];
labQuadrupole[0] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[0];
rPole[ii][jj] += vectorZ[ii]*vectorX[jj]*mPole[2][0]; labQuadrupole[1] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[1];
rPole[ii][jj] += vectorZ[ii]*vectorY[jj]*mPole[2][1]; labQuadrupole[2] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[2];
rPole[ii][jj] += vectorZ[ii]*vectorZ[jj]*mPole[2][2]; labQuadrupole[3] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[3];
} labQuadrupole[4] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[4];
} labQuadrupole[5] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[5];
labQuadrupole[6] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[6];
__syncthreads(); labQuadrupole[7] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[7];
labQuadrupole[8] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[8];
rPole[1][0] = rPole[0][1];
rPole[2][0] = rPole[0][2];
rPole[2][1] = rPole[1][2];
// set out-of-range elements to 0.0f
labQuadrupole[0] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[0];
labQuadrupole[1] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[1];
labQuadrupole[2] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[2];
labQuadrupole[3] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[3];
labQuadrupole[4] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[4];
labQuadrupole[5] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[5];
labQuadrupole[6] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[6];
labQuadrupole[7] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[7];
labQuadrupole[8] = atomIndex >= numOfAtoms ? 0.0f : labQuadrupole[8];
} }
void cudaComputeAmoebaLabFrameMoments( amoebaGpuContext amoebaGpu ) void cudaComputeAmoebaLabFrameMoments( amoebaGpuContext amoebaGpu )
...@@ -240,16 +436,10 @@ void cudaComputeAmoebaLabFrameMoments( amoebaGpuContext amoebaGpu ) ...@@ -240,16 +436,10 @@ void cudaComputeAmoebaLabFrameMoments( amoebaGpuContext amoebaGpu )
double kernelTime = 0.0; double kernelTime = 0.0;
#endif #endif
kCudaComputeLabFrameMoments_kernel<<< numBlocks, numThreads>>> ( kCudaComputeCheckChiral_kernel<<< numBlocks, numThreads>>> ( );
gpu->natoms, LAUNCHERROR("kCudaComputeCheckChiral");
amoebaGpu->psRotationMatrix->_pDevStream[0],
gpu->psPosq4->_pDevStream[0], kCudaComputeLabFrameMoments_kernel<<< numBlocks, numThreads>>> ( );
amoebaGpu->psMultipoleParticlesIdsAndAxisType->_pDevStream[0],
amoebaGpu->psMolecularDipole->_pDevStream[0],
amoebaGpu->psMolecularQuadrupole->_pDevStream[0],
amoebaGpu->psLabFrameDipole->_pDevStream[0],
amoebaGpu->psLabFrameQuadrupole->_pDevStream[0]
);
LAUNCHERROR(methodName); LAUNCHERROR(methodName);
#ifdef AMOEBA_DEBUG #ifdef AMOEBA_DEBUG
......
...@@ -483,9 +483,9 @@ void ReferenceCalcAmoebaMultipoleForceKernel::initialize(const System& system, c ...@@ -483,9 +483,9 @@ void ReferenceCalcAmoebaMultipoleForceKernel::initialize(const System& system, c
totalCharge += charge; totalCharge += charge;
axisTypes[ii] = axisType; axisTypes[ii] = axisType;
multipoleAtomZs[ii] = multipoleAtomZ; multipoleAtomZs[ii] = multipoleAtomZ;
multipoleAtomXs[ii] = multipoleAtomX; multipoleAtomXs[ii] = multipoleAtomX;
multipoleAtomYs[ii] = multipoleAtomY; multipoleAtomYs[ii] = multipoleAtomY;
charges[ii] = static_cast<RealOpenMM>(charge); charges[ii] = static_cast<RealOpenMM>(charge);
tholes[ii] = static_cast<RealOpenMM>(tholeD); tholes[ii] = static_cast<RealOpenMM>(tholeD);
......
...@@ -382,6 +382,46 @@ void AmoebaReferenceMultipoleForce::loadParticleData( RealOpenMM** particlePosit ...@@ -382,6 +382,46 @@ void AmoebaReferenceMultipoleForce::loadParticleData( RealOpenMM** particlePosit
} }
} }
void AmoebaReferenceMultipoleForce::checkChiral( MultipoleParticleData& particleI, int axisType,
MultipoleParticleData& particleZ, MultipoleParticleData& particleX,
MultipoleParticleData& particleY ) const {
// ---------------------------------------------------------------------------------------
static const RealOpenMM one = 1.0;
static const std::string methodName = "AmoebaReferenceMultipoleForce::checkChiral";
static const int AD = 0;
static const int BD = 1;
static const int CD = 2;
static const int C = 3;
double delta[4][3];
// ---------------------------------------------------------------------------------------
if( axisType == AmoebaMultipoleForce::ZThenX ){
return;
}
getDelta( particleY, particleI, delta[AD] );
getDelta( particleY, particleZ, delta[BD] );
getDelta( particleY, particleX, delta[CD] );
delta[C][0] = delta[BD][1]*delta[CD][2] - delta[BD][2]*delta[CD][1];
delta[C][1] = delta[CD][1]*delta[AD][2] - delta[CD][2]*delta[AD][1];
delta[C][2] = delta[AD][1]*delta[BD][2] - delta[AD][2]*delta[BD][1];
RealOpenMM volume = delta[C][0]*delta[AD][0] + delta[C][1]*delta[BD][0] + delta[C][2]*delta[CD][0];
if( volume < 0.0 ){
particleI.dipole[1] *= -one; // pole(3,i)
particleI.quadrupole[QXY] *= -one; // pole(6,i) && pole(8,i)
particleI.quadrupole[QYZ] *= -one; // pole(10,i) && pole(12,i)
}
return;
}
void AmoebaReferenceMultipoleForce::applyRotationMatrix( MultipoleParticleData& particleI, void AmoebaReferenceMultipoleForce::applyRotationMatrix( MultipoleParticleData& particleI,
const MultipoleParticleData& particleZ, const MultipoleParticleData& particleZ,
const MultipoleParticleData& particleX, int axisType ) const { const MultipoleParticleData& particleX, int axisType ) const {
...@@ -1460,7 +1500,7 @@ RealOpenMM AmoebaReferenceMultipoleForce::calculateNoCutoffElectrostatic( std::v ...@@ -1460,7 +1500,7 @@ RealOpenMM AmoebaReferenceMultipoleForce::calculateNoCutoffElectrostatic( std::v
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
// initialize forces/energy and scaleing factors // initialize forces/energy and scaling factors
std::vector<Vec3> torques( particleData.size() ); std::vector<Vec3> torques( particleData.size() );
for( unsigned int ii = 0; ii < particleData.size(); ii++ ){ for( unsigned int ii = 0; ii < particleData.size(); ii++ ){
...@@ -1580,6 +1620,16 @@ RealOpenMM AmoebaReferenceMultipoleForce::calculateNoCutoffForceAndEnergy( unsig ...@@ -1580,6 +1620,16 @@ RealOpenMM AmoebaReferenceMultipoleForce::calculateNoCutoffForceAndEnergy( unsig
loadParticleData( particlePositions, charges, dipoles, quadrupoles, loadParticleData( particlePositions, charges, dipoles, quadrupoles,
tholes, dampingFactors, polarity, particleData ); tholes, dampingFactors, polarity, particleData );
// check for chiral centers that need multipoles inverted
for( unsigned int ii = 0; ii < numParticles; ii++ ){
if( multipoleAtomYs[ii] ){
checkChiral( particleData[ii], axisTypes[ii], particleData[multipoleAtomZs[ii]], particleData[multipoleAtomXs[ii]], particleData[multipoleAtomYs[ii]] );
}
}
// apply rotation matrix
for( unsigned int ii = 0; ii < numParticles; ii++ ){ for( unsigned int ii = 0; ii < numParticles; ii++ ){
if( multipoleAtomZs[ii] >= 0 && multipoleAtomXs[ii] >= 0 ){ if( multipoleAtomZs[ii] >= 0 && multipoleAtomXs[ii] >= 0 ){
applyRotationMatrix( particleData[ii], particleData[multipoleAtomZs[ii]], particleData[multipoleAtomXs[ii]], axisTypes[ii] ); applyRotationMatrix( particleData[ii], particleData[multipoleAtomZs[ii]], particleData[multipoleAtomXs[ii]], axisTypes[ii] );
......
...@@ -407,6 +407,24 @@ private: ...@@ -407,6 +407,24 @@ private:
void getAndScaleInverseRs( RealOpenMM dampI, RealOpenMM dampJ, RealOpenMM tholeI, RealOpenMM tholeJ, void getAndScaleInverseRs( RealOpenMM dampI, RealOpenMM dampJ, RealOpenMM tholeI, RealOpenMM tholeJ,
RealOpenMM r, std::vector<RealOpenMM>& rrI ) const; RealOpenMM r, std::vector<RealOpenMM>& rrI ) const;
/**---------------------------------------------------------------------------------------
Check multipoles at chiral sites
inverts atomic multipole moments as necessary
at sites with chiral local reference frame definitions
@param particleI particleI data
@param axisType axis type
@param particleZ z-axis particle to particleI
@param particleX x-axis particle to particleI
@param particleY y-axis particle to particleI
--------------------------------------------------------------------------------------- */
void checkChiral( MultipoleParticleData& particleI, int axisType, MultipoleParticleData& particleZ,
MultipoleParticleData& particleX, MultipoleParticleData& particleY ) const;
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
Apply roatation matrix to molecular dipole/quadrupoles to get corresponding lab frame values Apply roatation matrix to molecular dipole/quadrupoles to get corresponding lab frame values
......
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