"vscode:/vscode.git/clone" did not exist on "9acf1009edfac5003e7ca599d8493351a9e713da"
Commit f028c07d authored by Lee-Ping Wang's avatar Lee-Ping Wang
Browse files

Modified the AmoebaMultipoleForce.getSystemMultipoleMoments method with two...

Modified the AmoebaMultipoleForce.getSystemMultipoleMoments method with two extra arguments; toggle whether to evaluate energy/force and select maximum multipole order.

parent 1f7b71c5
...@@ -319,16 +319,21 @@ public: ...@@ -319,16 +319,21 @@ public:
* <i>lowest nonvanishing moment</i> has a well defined value. This means that if the system has a net * <i>lowest nonvanishing moment</i> has a well defined value. This means that if the system has a net
* nonzero charge, the dipole and quadrupole moments are not well defined and should be ignored. If the * nonzero charge, the dipole and quadrupole moments are not well defined and should be ignored. If the
* net charge is zero, the dipole moment is well defined (and really represents a dipole density), but * net charge is zero, the dipole moment is well defined (and really represents a dipole density), but
* the quadrupole moment is still undefined and should be ignored. * the quadrupole moment is still undefined and should be ignored. Specify "compute = True" if you want
* to do an energy and force calculation prior to getting the moments; if compute = False, it will be faster
* but we will lose accuracy. Specify "order" for the maximum order computed (order = 2 means we go up
* through quadrupoles.)
* *
* @param context context * @param context context
* @param compute Whether to compute energies and forces first
* @param order Maximum order to go through, above 2 for quadrupole has no effect
* @param outputMultipoleMonents (charge, * @param outputMultipoleMonents (charge,
dipole_x, dipole_y, dipole_z, dipole_x, dipole_y, dipole_z,
quadrupole_xx, quadrupole_xy, quadrupole_xz, quadrupole_xx, quadrupole_xy, quadrupole_xz,
quadrupole_yx, quadrupole_yy, quadrupole_yz, quadrupole_yx, quadrupole_yy, quadrupole_yz,
quadrupole_zx, quadrupole_zy, quadrupole_zz) quadrupole_zx, quadrupole_zy, quadrupole_zz)
*/ */
void getSystemMultipoleMoments(Context& context, std::vector< double >& outputMultipoleMoments); void getSystemMultipoleMoments(Context& context, bool compute, int order, std::vector< double >& outputMultipoleMoments);
/** /**
* Update the multipole parameters in a Context to match those stored in this Force object. This method * Update the multipole parameters in a Context to match those stored in this Force object. This method
* provides an efficient method to update certain parameters in an existing Context without needing to reinitialize it. * provides an efficient method to update certain parameters in an existing Context without needing to reinitialize it.
......
...@@ -351,7 +351,7 @@ public: ...@@ -351,7 +351,7 @@ public:
virtual void getElectrostaticPotential( ContextImpl& context, const std::vector< Vec3 >& inputGrid, virtual void getElectrostaticPotential( ContextImpl& context, const std::vector< Vec3 >& inputGrid,
std::vector< double >& outputElectrostaticPotential ) = 0; std::vector< double >& outputElectrostaticPotential ) = 0;
virtual void getSystemMultipoleMoments( ContextImpl& context, std::vector< double >& outputMultipoleMonents ) = 0; virtual void getSystemMultipoleMoments( ContextImpl& context, bool compute, int order, std::vector< double >& outputMultipoleMonents ) = 0;
/** /**
* Copy changed parameters over to a context. * Copy changed parameters over to a context.
* *
......
...@@ -85,7 +85,7 @@ public: ...@@ -85,7 +85,7 @@ public:
void getElectrostaticPotential( ContextImpl& context, const std::vector< Vec3 >& inputGrid, void getElectrostaticPotential( ContextImpl& context, const std::vector< Vec3 >& inputGrid,
std::vector< double >& outputElectrostaticPotential ); std::vector< double >& outputElectrostaticPotential );
void getSystemMultipoleMoments( ContextImpl& context, std::vector< double >& outputMultipoleMonents ); void getSystemMultipoleMoments( ContextImpl& context, bool compute, int order, std::vector< double >& outputMultipoleMonents );
void updateParametersInContext(ContextImpl& context); void updateParametersInContext(ContextImpl& context);
......
...@@ -230,8 +230,8 @@ void AmoebaMultipoleForce::getElectrostaticPotential( const std::vector< Vec3 >& ...@@ -230,8 +230,8 @@ void AmoebaMultipoleForce::getElectrostaticPotential( const std::vector< Vec3 >&
dynamic_cast<AmoebaMultipoleForceImpl&>(getImplInContext(context)).getElectrostaticPotential(getContextImpl(context), inputGrid, outputElectrostaticPotential); dynamic_cast<AmoebaMultipoleForceImpl&>(getImplInContext(context)).getElectrostaticPotential(getContextImpl(context), inputGrid, outputElectrostaticPotential);
} }
void AmoebaMultipoleForce::getSystemMultipoleMoments(Context& context, std::vector< double >& outputMultipoleMonents ){ void AmoebaMultipoleForce::getSystemMultipoleMoments(Context& context, bool compute, int order, std::vector< double >& outputMultipoleMonents ){
dynamic_cast<AmoebaMultipoleForceImpl&>(getImplInContext(context)).getSystemMultipoleMoments(getContextImpl(context), outputMultipoleMonents); dynamic_cast<AmoebaMultipoleForceImpl&>(getImplInContext(context)).getSystemMultipoleMoments(getContextImpl(context), compute, order, outputMultipoleMonents);
} }
ForceImpl* AmoebaMultipoleForce::createImpl() { ForceImpl* AmoebaMultipoleForce::createImpl() {
......
...@@ -188,8 +188,8 @@ void AmoebaMultipoleForceImpl::getElectrostaticPotential( ContextImpl& context, ...@@ -188,8 +188,8 @@ void AmoebaMultipoleForceImpl::getElectrostaticPotential( ContextImpl& context,
kernel.getAs<CalcAmoebaMultipoleForceKernel>().getElectrostaticPotential(context, inputGrid, outputElectrostaticPotential); kernel.getAs<CalcAmoebaMultipoleForceKernel>().getElectrostaticPotential(context, inputGrid, outputElectrostaticPotential);
} }
void AmoebaMultipoleForceImpl::getSystemMultipoleMoments( ContextImpl& context, std::vector< double >& outputMultipoleMonents ){ void AmoebaMultipoleForceImpl::getSystemMultipoleMoments( ContextImpl& context, bool compute, int order, std::vector< double >& outputMultipoleMonents ){
kernel.getAs<CalcAmoebaMultipoleForceKernel>().getSystemMultipoleMoments(context, outputMultipoleMonents); kernel.getAs<CalcAmoebaMultipoleForceKernel>().getSystemMultipoleMoments(context, compute, order, outputMultipoleMonents);
} }
void AmoebaMultipoleForceImpl::updateParametersInContext(ContextImpl& context) { void AmoebaMultipoleForceImpl::updateParametersInContext(ContextImpl& context) {
......
...@@ -1596,7 +1596,7 @@ void CudaCalcAmoebaMultipoleForceKernel::getElectrostaticPotential(ContextImpl& ...@@ -1596,7 +1596,7 @@ void CudaCalcAmoebaMultipoleForceKernel::getElectrostaticPotential(ContextImpl&
} }
template <class T, class T4, class M4> template <class T, class T4, class M4>
void CudaCalcAmoebaMultipoleForceKernel::computeSystemMultipoleMoments(ContextImpl& context, vector<double>& outputMultipoleMoments) { void CudaCalcAmoebaMultipoleForceKernel::computeSystemMultipoleMoments(ContextImpl& context, int order, vector<double>& outputMultipoleMoments) {
// Compute the local coordinates relative to the center of mass. // Compute the local coordinates relative to the center of mass.
int numAtoms = cu.getNumAtoms(); int numAtoms = cu.getNumAtoms();
vector<T4> posq; vector<T4> posq;
...@@ -1641,17 +1641,24 @@ void CudaCalcAmoebaMultipoleForceKernel::computeSystemMultipoleMoments(ContextIm ...@@ -1641,17 +1641,24 @@ void CudaCalcAmoebaMultipoleForceKernel::computeSystemMultipoleMoments(ContextIm
double zyqdp = 0.0; double zyqdp = 0.0;
double zzqdp = 0.0; double zzqdp = 0.0;
vector<T> labDipoleVec, inducedDipoleVec, quadrupoleVec; vector<T> labDipoleVec, inducedDipoleVec, quadrupoleVec;
if (order >= 1) {
labFrameDipoles->download(labDipoleVec); labFrameDipoles->download(labDipoleVec);
inducedDipole->download(inducedDipoleVec); inducedDipole->download(inducedDipoleVec);
}
if (order >= 2) {
labFrameQuadrupoles->download(quadrupoleVec); labFrameQuadrupoles->download(quadrupoleVec);
}
for (int i = 0; i < numAtoms; i++) { for (int i = 0; i < numAtoms; i++) {
totalCharge += posqLocal[i].w; totalCharge += posqLocal[i].w;
double netDipoleX = (labDipoleVec[3*i] + inducedDipoleVec[3*i]); double netDipoleX = (labDipoleVec[3*i] + inducedDipoleVec[3*i]);
double netDipoleY = (labDipoleVec[3*i+1] + inducedDipoleVec[3*i+1]); double netDipoleY = (labDipoleVec[3*i+1] + inducedDipoleVec[3*i+1]);
double netDipoleZ = (labDipoleVec[3*i+2] + inducedDipoleVec[3*i+2]); double netDipoleZ = (labDipoleVec[3*i+2] + inducedDipoleVec[3*i+2]);
if (order >= 1) {
xdpl += posqLocal[i].x*posqLocal[i].w + netDipoleX; xdpl += posqLocal[i].x*posqLocal[i].w + netDipoleX;
ydpl += posqLocal[i].y*posqLocal[i].w + netDipoleY; ydpl += posqLocal[i].y*posqLocal[i].w + netDipoleY;
zdpl += posqLocal[i].z*posqLocal[i].w + netDipoleZ; zdpl += posqLocal[i].z*posqLocal[i].w + netDipoleZ;
}
if (order >= 2) {
xxqdp += posqLocal[i].x*posqLocal[i].x*posqLocal[i].w + 2*posqLocal[i].x*netDipoleX; xxqdp += posqLocal[i].x*posqLocal[i].x*posqLocal[i].w + 2*posqLocal[i].x*netDipoleX;
xyqdp += posqLocal[i].x*posqLocal[i].y*posqLocal[i].w + posqLocal[i].x*netDipoleY + posqLocal[i].y*netDipoleX; xyqdp += posqLocal[i].x*posqLocal[i].y*posqLocal[i].w + posqLocal[i].x*netDipoleY + posqLocal[i].y*netDipoleX;
xzqdp += posqLocal[i].x*posqLocal[i].z*posqLocal[i].w + posqLocal[i].x*netDipoleZ + posqLocal[i].z*netDipoleX; xzqdp += posqLocal[i].x*posqLocal[i].z*posqLocal[i].w + posqLocal[i].x*netDipoleZ + posqLocal[i].z*netDipoleX;
...@@ -1662,9 +1669,11 @@ void CudaCalcAmoebaMultipoleForceKernel::computeSystemMultipoleMoments(ContextIm ...@@ -1662,9 +1669,11 @@ void CudaCalcAmoebaMultipoleForceKernel::computeSystemMultipoleMoments(ContextIm
zyqdp += posqLocal[i].z*posqLocal[i].y*posqLocal[i].w + posqLocal[i].z*netDipoleY + posqLocal[i].y*netDipoleZ; zyqdp += posqLocal[i].z*posqLocal[i].y*posqLocal[i].w + posqLocal[i].z*netDipoleY + posqLocal[i].y*netDipoleZ;
zzqdp += posqLocal[i].z*posqLocal[i].z*posqLocal[i].w + 2*posqLocal[i].z*netDipoleZ; zzqdp += posqLocal[i].z*posqLocal[i].z*posqLocal[i].w + 2*posqLocal[i].z*netDipoleZ;
} }
}
// Convert the quadrupole from traced to traceless form. // Convert the quadrupole from traced to traceless form.
if (order >= 2) {
double qave = (xxqdp + yyqdp + zzqdp)/3; double qave = (xxqdp + yyqdp + zzqdp)/3;
xxqdp = 1.5*(xxqdp-qave); xxqdp = 1.5*(xxqdp-qave);
xyqdp = 1.5*xyqdp; xyqdp = 1.5*xyqdp;
...@@ -1689,8 +1698,9 @@ void CudaCalcAmoebaMultipoleForceKernel::computeSystemMultipoleMoments(ContextIm ...@@ -1689,8 +1698,9 @@ void CudaCalcAmoebaMultipoleForceKernel::computeSystemMultipoleMoments(ContextIm
zyqdp = zyqdp + 3*quadrupoleVec[5*i+4]; zyqdp = zyqdp + 3*quadrupoleVec[5*i+4];
zzqdp = zzqdp + -3*(quadrupoleVec[5*i]+quadrupoleVec[5*i+3]); zzqdp = zzqdp + -3*(quadrupoleVec[5*i]+quadrupoleVec[5*i+3]);
} }
}
double debye = 4.80321; double debye = 48.0321; // If we use 4.80321 then the result is ten times too small.
outputMultipoleMoments.resize(13); outputMultipoleMoments.resize(13);
outputMultipoleMoments[0] = totalCharge; outputMultipoleMoments[0] = totalCharge;
outputMultipoleMoments[1] = xdpl*debye; outputMultipoleMoments[1] = xdpl*debye;
...@@ -1707,14 +1717,15 @@ void CudaCalcAmoebaMultipoleForceKernel::computeSystemMultipoleMoments(ContextIm ...@@ -1707,14 +1717,15 @@ void CudaCalcAmoebaMultipoleForceKernel::computeSystemMultipoleMoments(ContextIm
outputMultipoleMoments[12] = zzqdp*debye; outputMultipoleMoments[12] = zzqdp*debye;
} }
void CudaCalcAmoebaMultipoleForceKernel::getSystemMultipoleMoments(ContextImpl& context, vector<double>& outputMultipoleMoments) { void CudaCalcAmoebaMultipoleForceKernel::getSystemMultipoleMoments(ContextImpl& context, bool compute, int order, vector<double>& outputMultipoleMoments) {
if (compute)
context.calcForcesAndEnergy(false, false, -1); context.calcForcesAndEnergy(false, false, -1);
if (cu.getUseDoublePrecision()) if (cu.getUseDoublePrecision())
computeSystemMultipoleMoments<double, double4, double4>(context, outputMultipoleMoments); computeSystemMultipoleMoments<double, double4, double4>(context, order, outputMultipoleMoments);
else if (cu.getUseMixedPrecision()) else if (cu.getUseMixedPrecision())
computeSystemMultipoleMoments<float, float4, double4>(context, outputMultipoleMoments); computeSystemMultipoleMoments<float, float4, double4>(context, order, outputMultipoleMoments);
else else
computeSystemMultipoleMoments<float, float4, float4>(context, outputMultipoleMoments); computeSystemMultipoleMoments<float, float4, float4>(context, order, outputMultipoleMoments);
} }
void CudaCalcAmoebaMultipoleForceKernel::copyParametersToContext(ContextImpl& context, const AmoebaMultipoleForce& force) { void CudaCalcAmoebaMultipoleForceKernel::copyParametersToContext(ContextImpl& context, const AmoebaMultipoleForce& force) {
......
...@@ -341,13 +341,15 @@ public: ...@@ -341,13 +341,15 @@ public:
* Get the system multipole moments * Get the system multipole moments
* *
* @param context context * @param context context
* @param compute Whether to compute energies and forces first
* @param order Maximum order to go through, above 2 for quadrupole has no effect
* @param outputMultipoleMoments (charge, * @param outputMultipoleMoments (charge,
* dipole_x, dipole_y, dipole_z, * dipole_x, dipole_y, dipole_z,
* quadrupole_xx, quadrupole_xy, quadrupole_xz, * quadrupole_xx, quadrupole_xy, quadrupole_xz,
* quadrupole_yx, quadrupole_yy, quadrupole_yz, * quadrupole_yx, quadrupole_yy, quadrupole_yz,
* quadrupole_zx, quadrupole_zy, quadrupole_zz ) * quadrupole_zx, quadrupole_zy, quadrupole_zz )
*/ */
void getSystemMultipoleMoments(ContextImpl& context, std::vector<double>& outputMultipoleMoments); void getSystemMultipoleMoments(ContextImpl& context, bool compute, int order, std::vector<double>& outputMultipoleMoments);
/** /**
* Copy changed parameters over to a context. * Copy changed parameters over to a context.
* *
...@@ -368,7 +370,7 @@ private: ...@@ -368,7 +370,7 @@ private:
const char* getSortKey() const {return "value.y";} const char* getSortKey() const {return "value.y";}
}; };
void initializeScaleFactors(); void initializeScaleFactors();
template <class T, class T4, class M4> void computeSystemMultipoleMoments(ContextImpl& context, std::vector<double>& outputMultipoleMoments); template <class T, class T4, class M4> void computeSystemMultipoleMoments(ContextImpl& context, int order, std::vector<double>& outputMultipoleMoments);
int numMultipoles, maxInducedIterations; int numMultipoles, maxInducedIterations;
int fixedFieldThreads, inducedFieldThreads, electrostaticsThreads; int fixedFieldThreads, inducedFieldThreads, electrostaticsThreads;
double inducedEpsilon; double inducedEpsilon;
......
...@@ -2009,7 +2009,7 @@ static void setupAndGetForcesEnergyMultipoleLargeWater( AmoebaMultipoleForce::No ...@@ -2009,7 +2009,7 @@ static void setupAndGetForcesEnergyMultipoleLargeWater( AmoebaMultipoleForce::No
context.setPositions(positions); context.setPositions(positions);
if( testName == "testSystemMultipoleMoments" ){ if( testName == "testSystemMultipoleMoments" ){
amoebaMultipoleForce->getSystemMultipoleMoments(context, outputMultipoleMoments ); amoebaMultipoleForce->getSystemMultipoleMoments(context, 1, 2, outputMultipoleMoments );
} else if( testName == "testMultipoleGridPotential" ){ } else if( testName == "testMultipoleGridPotential" ){
amoebaMultipoleForce->getElectrostaticPotential( inputGrid, context, outputGridPotential ); amoebaMultipoleForce->getElectrostaticPotential( inputGrid, context, outputGridPotential );
} else { } else {
......
...@@ -708,7 +708,7 @@ void ReferenceCalcAmoebaMultipoleForceKernel::getElectrostaticPotential(ContextI ...@@ -708,7 +708,7 @@ void ReferenceCalcAmoebaMultipoleForceKernel::getElectrostaticPotential(ContextI
return; return;
} }
void ReferenceCalcAmoebaMultipoleForceKernel::getSystemMultipoleMoments(ContextImpl& context, std::vector< double >& outputMultipoleMoments){ void ReferenceCalcAmoebaMultipoleForceKernel::getSystemMultipoleMoments(ContextImpl& context, bool compute, int order, std::vector< double >& outputMultipoleMoments){
// retrieve masses // retrieve masses
......
...@@ -380,6 +380,8 @@ public: ...@@ -380,6 +380,8 @@ public:
* Get the system multipole moments. * Get the system multipole moments.
* *
* @param context context * @param context context
* @param compute Whether to compute energies and forces first
* @param order Maximum order to go through, above 2 for quadrupole has no effect
* @param outputMultipoleMonents vector of multipole moments: * @param outputMultipoleMonents vector of multipole moments:
(charge, (charge,
dipole_x, dipole_y, dipole_z, dipole_x, dipole_y, dipole_z,
...@@ -387,7 +389,7 @@ public: ...@@ -387,7 +389,7 @@ public:
quadrupole_yx, quadrupole_yy, quadrupole_yz, quadrupole_yx, quadrupole_yy, quadrupole_yz,
quadrupole_zx, quadrupole_zy, quadrupole_zz ) quadrupole_zx, quadrupole_zy, quadrupole_zz )
*/ */
void getSystemMultipoleMoments(ContextImpl& context, std::vector< double >& outputMultipoleMoments); void getSystemMultipoleMoments(ContextImpl& context, bool compute, int order, std::vector< double >& outputMultipoleMoments);
/** /**
* Copy changed parameters over to a context. * Copy changed parameters over to a context.
* *
......
...@@ -1915,7 +1915,7 @@ static void setupAndGetForcesEnergyMultipoleLargeWater( AmoebaMultipoleForce::No ...@@ -1915,7 +1915,7 @@ static void setupAndGetForcesEnergyMultipoleLargeWater( AmoebaMultipoleForce::No
context.setPositions(positions); context.setPositions(positions);
if( testName == "testSystemMultipoleMoments" ){ if( testName == "testSystemMultipoleMoments" ){
amoebaMultipoleForce->getSystemMultipoleMoments( context, outputMultipoleMoments ); amoebaMultipoleForce->getSystemMultipoleMoments( context, 1, 2, outputMultipoleMoments );
} else if( testName == "testMultipoleGridPotential" ){ } else if( testName == "testMultipoleGridPotential" ){
amoebaMultipoleForce->getElectrostaticPotential( inputGrid, context, outputGridPotential ); amoebaMultipoleForce->getElectrostaticPotential( inputGrid, context, outputGridPotential );
} else { } else {
......
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