Commit 7a36f461 authored by Mark Friedrichs's avatar Mark Friedrichs
Browse files

dded GB/VI to Cuda platform

Free energy plugin added
Plugin will not run w/ Obc or GB/VI forces unless line 2004 of gpu.cpp (gpu->sim.totalNonbondOutputBuffers  = 2*gpu->sim.nonbondOutputBuffers;) is commented in -- working on removing this constraint
Also unit tests for GB/VI currently fail 
parent 43ebedfb
/* Portions copyright (c) 2006-2009 Stanford University and Simbios.
* Contributors: Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <string.h>
#include <sstream>
#include "../SimTKUtilities/SimTKOpenMMCommon.h"
#include "../SimTKUtilities/SimTKOpenMMLog.h"
#include "../SimTKUtilities/SimTKOpenMMUtilities.h"
#include "CpuGBVISoftcore.h"
#include "../SimTKReference/ReferenceForce.h"
#include <math.h>
static const double CAL_TO_JOULE = 0.4184;
/**---------------------------------------------------------------------------------------
CpuGBVISoftcore constructor
gbviParameters gbviParameters object
--------------------------------------------------------------------------------------- */
CpuGBVISoftcore::CpuGBVISoftcore( ImplicitSolventParameters* gbviParameters ) : CpuImplicitSolvent( gbviParameters ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuGBVISoftcore::CpuGBVISoftcore";
// ---------------------------------------------------------------------------------------
_initializeGBVISoftcoreDataMembers( );
_gbviParameters = static_cast<GBVISoftcoreParameters*> (gbviParameters);
}
/**---------------------------------------------------------------------------------------
CpuGBVISoftcore destructor
--------------------------------------------------------------------------------------- */
CpuGBVISoftcore::~CpuGBVISoftcore( ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuGBVISoftcore::~CpuGBVISoftcore";
// ---------------------------------------------------------------------------------------
delete _switchDeriviative;
//if( _gbviParameters != NULL ){
// delete _gbviParameters;
//}
}
/**---------------------------------------------------------------------------------------
Initialize data members
--------------------------------------------------------------------------------------- */
void CpuGBVISoftcore::_initializeGBVISoftcoreDataMembers( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuGBVISoftcore::initializeDataMembers";
// ---------------------------------------------------------------------------------------
_gbviParameters = NULL;
_switchDeriviative = NULL;
}
/**---------------------------------------------------------------------------------------
Get GBVISoftcoreParameters reference
@return GBVISoftcoreParameters reference
--------------------------------------------------------------------------------------- */
GBVISoftcoreParameters* CpuGBVISoftcore::getGBVISoftcoreParameters( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuGBVISoftcore::getGBVISoftcoreParameters";
// ---------------------------------------------------------------------------------------
return _gbviParameters;
}
/**---------------------------------------------------------------------------------------
Set GBVISoftcoreParameters reference
@param GBVISoftcoreParameters reference
@return SimTKOpenMMCommon::DefaultReturn;
--------------------------------------------------------------------------------------- */
int CpuGBVISoftcore::setGBVISoftcoreParameters( GBVISoftcoreParameters* gbviParameters ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuGBVISoftcore::setGBVISoftcoreParameters";
// ---------------------------------------------------------------------------------------
_gbviParameters = gbviParameters;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Return OBC chain derivative: size = _obcSoftcoreParameters->getNumberOfAtoms()
On first call, memory for array is allocated if not set
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* CpuGBVISoftcore::getSwitchDeriviative( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuGBVISoftcore::getSwitchDeriviative";
// ---------------------------------------------------------------------------------------
if( _switchDeriviative == NULL && _gbviParameters != NULL ){
_switchDeriviative = new RealOpenMM[_gbviParameters->getNumberOfAtoms()];
}
return _switchDeriviative;
}
/**---------------------------------------------------------------------------------------
Return switching function derivative
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* CpuGBVISoftcore::getSwitchDeriviativeConst( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuGBVISoftcore::getSwitchDeriviative";
// ---------------------------------------------------------------------------------------
return _switchDeriviative;
}
/**---------------------------------------------------------------------------------------
Compute quintic spline value and associated derviative
@param x value to compute spline at
@param rl lower cutoff value
@param ru upper cutoff value
@param outValue value of spline at x
@param outDerivative value of derivative of spline at x
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
#define GBVISoftcoreDebug 0
int CpuGBVISoftcore::quinticSpline( RealOpenMM x, RealOpenMM rl, RealOpenMM ru,
RealOpenMM* outValue, RealOpenMM* outDerivative ){
// ---------------------------------------------------------------------------------------
static const RealOpenMM one = (RealOpenMM) 1.0;
static const RealOpenMM minusSix = (RealOpenMM) -6.0;
static const RealOpenMM minusTen = (RealOpenMM) -10.0;
static const RealOpenMM minusThirty = (RealOpenMM) -30.0;
static const RealOpenMM fifteen = (RealOpenMM) 15.0;
static const RealOpenMM sixty = (RealOpenMM) 60.0;
// static const char* methodName = "CpuGBVISoftcore::quinticSpline";
// ---------------------------------------------------------------------------------------
RealOpenMM numerator = x - rl;
RealOpenMM denominator = ru - rl;
RealOpenMM ratio = numerator/denominator;
RealOpenMM ratio2 = ratio*ratio;
RealOpenMM ratio3 = ratio2*ratio;
*outValue = one + ratio3*(minusTen + fifteen*ratio + minusSix*ratio2);
*outDerivative = ratio2*(minusThirty + sixty*ratio + minusThirty*ratio2)/denominator;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Compute Born radii based on Eq. 3 of Labute paper [JCC 29 p. 1693-1698 2008])
and quintic splice switching function
@param atomicRadius3 atomic radius cubed
@param bornSum Born sum (volume integral)
@param gbviParameters Gbvi parameters (parameters used in spline
QuinticLowerLimitFactor & QuinticUpperBornRadiusLimit)
@param bornRadius output Born radius
@param switchDeriviative output switching function deriviative
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
#define GBVISoftcoreDebug 0
int CpuGBVISoftcore::computeBornRadiiUsingQuinticSpline( RealOpenMM atomicRadius3, RealOpenMM bornSum,
GBVISoftcoreParameters* gbviParameters,
RealOpenMM* bornRadius, RealOpenMM* switchDeriviative ){
// ---------------------------------------------------------------------------------------
static const RealOpenMM zero = (RealOpenMM) 0.0;
static const RealOpenMM one = (RealOpenMM) 1.0;
static const RealOpenMM minusOne = (RealOpenMM) -1.0;
static const RealOpenMM minusThree = (RealOpenMM) -3.0;
static const RealOpenMM oneEighth = (RealOpenMM) 0.125;
static const RealOpenMM minusOneThird = (RealOpenMM) (-1.0/3.0);
static const RealOpenMM three = (RealOpenMM) 3.0;
static const char* methodName = "CpuGBVISoftcore::computeBornRadiiUsingQuinticSpline";
// ---------------------------------------------------------------------------------------
#if( GBVISoftcoreDebug == 1 )
FILE* logFile = stderr;
#endif
// R = [ S(V)*(A - V) ]**(-1/3)
// S(V) = 1 V < L
// S(V) = qSpline + U/(A-V) L < V < A
// S(V) = U/(A-V) U < V
// dR/dr = (-1/3)*[ S(V)*(A - V) ]**(-4/3)*[ d{ S(V)*(A-V) }/dr
// d{ S(V)*(A-V) }/dr = (dV/dr)*[ (A-V)*dS/dV - S(V) ]
// (A - V)*dS/dV - S(V) = 0 - 1 V < L
// (A - V)*dS/dV - S(V) = (A-V)*d(qSpline) + (A-V)*U/(A-V)**2 - qSpline - U/(A-V)
// = (A-V)*d(qSpline) - qSpline L < V < A**(-3)
// (A - V)*dS/dV - S(V) = (A-V)*U*/(A-V)**2 - U/(A-V) = 0 U < V
RealOpenMM splineL = gbviParameters->getQuinticLowerLimitFactor()*atomicRadius3;
RealOpenMM sum;
if( bornSum > splineL ){
if( bornSum < atomicRadius3 ){
RealOpenMM splineValue, splineDerivative;
quinticSpline( bornSum, splineL, atomicRadius3, &splineValue, &splineDerivative );
sum = (atomicRadius3 - bornSum)*splineValue + gbviParameters->getQuinticUpperSplineLimit();
*switchDeriviative = splineValue - (atomicRadius3 - bornSum)*splineDerivative;
#if( GBVISoftcoreDebug == 1 )
(void) fprintf( logFile, " Qv=%14.6e splnDrvtv=%14.6e spline[%10.3e %10.3e] ", splineValue, splineDerivative,
splineL, gbviParameters->getQuinticUpperSplineLimit() );
#endif
} else {
sum = gbviParameters->getQuinticUpperSplineLimit();
*switchDeriviative = zero;
}
} else {
sum = atomicRadius3 - bornSum;
*switchDeriviative = one;
}
*bornRadius = POW( sum, minusOneThird );
return 0;
}
#undef GBVISoftcoreDebug
/**---------------------------------------------------------------------------------------
Get Born radii based on Eq. 3 of Labute paper [JCC 29 p. 1693-1698 2008])
@param atomCoordinates atomic coordinates
@param bornRadii output array of Born radii
@param chain not used here
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
#define GBVISoftcoreDebug 0
int CpuGBVISoftcore::computeBornRadii( RealOpenMM** atomCoordinates, RealOpenMM* bornRadii, RealOpenMM* switchDeriviative ){
// ---------------------------------------------------------------------------------------
static const RealOpenMM zero = (RealOpenMM) 0.0;
static const RealOpenMM one = (RealOpenMM) 1.0;
static const RealOpenMM minusThree = (RealOpenMM) -3.0;
static const RealOpenMM oneEighth = (RealOpenMM) 0.125;
static const RealOpenMM minusOneThird = (RealOpenMM) (-1.0/3.0);
static const RealOpenMM three = (RealOpenMM) 3.0;
static const char* methodName = "CpuGBVISoftcore::computeBornRadii";
// ---------------------------------------------------------------------------------------
GBVISoftcoreParameters* gbviParameters = getGBVISoftcoreParameters();
int numberOfAtoms = gbviParameters->getNumberOfAtoms();
RealOpenMM* atomicRadii = gbviParameters->getAtomicRadii();
const RealOpenMM* scaledRadii = gbviParameters->getScaledRadii();
const RealOpenMM* bornRadiusScaleFactors = gbviParameters->getBornRadiusScaleFactors();
if( switchDeriviative == NULL ){
switchDeriviative = getSwitchDeriviative();
}
// ---------------------------------------------------------------------------------------
#if( GBVISoftcoreDebug == 1 )
FILE* logFile = stderr;
(void) fprintf( logFile, "\n%s\n", methodName );
#endif
// calculate Born radii
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
RealOpenMM radiusI = atomicRadii[atomI];
RealOpenMM sum = zero;
// sum over volumes
for( int atomJ = 0; atomJ < numberOfAtoms; atomJ++ ){
if( atomJ != atomI ){
RealOpenMM deltaR[ReferenceForce::LastDeltaRIndex];
if (_gbviParameters->getPeriodic())
ReferenceForce::getDeltaRPeriodic( atomCoordinates[atomI], atomCoordinates[atomJ], _gbviParameters->getPeriodicBox(), deltaR );
else
ReferenceForce::getDeltaR( atomCoordinates[atomI], atomCoordinates[atomJ], deltaR );
RealOpenMM r = deltaR[ReferenceForce::RIndex];
if (_gbviParameters->getUseCutoff() && r > _gbviParameters->getCutoffDistance())
continue;
sum += bornRadiusScaleFactors[atomJ]*CpuGBVISoftcore::getVolume( r, radiusI, scaledRadii[atomJ] );
#if( GBVISoftcoreDebug == -1 )
if( atomI == 0 || atomI == 1 ){
(void) fprintf( logFile, "%d addJ=%d scR=%14.6e %14.6e sum=%14.6e rI=%14.6e r=%14.6e S-R=%14.6e\n",
atomI, atomJ, scaledRadii[atomJ], getVolume( r, radiusI, scaledRadii[atomJ] ), sum,
radiusI, r, (scaledRadii[atomJ]-radiusI) );
}
#endif
}
}
#if( GBVISoftcoreDebug == 1 )
(void) fprintf( logFile, "%6d BornSum=%14.6e r=%14.6e r3=%14.6e (r3-sum)=%14.6e method=%d ",
atomI, sum, radiusI, POW( radiusI, minusThree ), (POW( radiusI, minusThree ) - sum), _gbviParameters->getBornRadiusScalingSoftcoreMethod() );
#endif
RealOpenMM atomicRadius3 = POW( radiusI, minusThree );
if( _gbviParameters->getBornRadiusScalingSoftcoreMethod() == GBVISoftcoreParameters::NoScaling ){
sum = atomicRadius3 - sum;
bornRadii[atomI] = POW( sum, minusOneThird );
switchDeriviative[atomI] = one;
} else if( _gbviParameters->getBornRadiusScalingSoftcoreMethod() == GBVISoftcoreParameters::QuinticSpline ){
computeBornRadiiUsingQuinticSpline( atomicRadius3, sum, gbviParameters,
bornRadii + atomI, switchDeriviative + atomI );
}
#if( GBVISoftcoreDebug == 1 )
(void) fprintf( logFile, "br=%14.6e swDrvtv=%14.6e %s\n", bornRadii[atomI], switchDeriviative[atomI], (fabs( switchDeriviative[atomI] - 1.0 ) > 1.0e-05 ? "SWWWWW" : "") );
#endif
}
return SimTKOpenMMCommon::DefaultReturn;
}
#undef GBVISoftcoreDebug
/**---------------------------------------------------------------------------------------
Get volume Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return volume
--------------------------------------------------------------------------------------- */
RealOpenMM CpuGBVISoftcore::getVolume( RealOpenMM r, RealOpenMM R, RealOpenMM S ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "CpuGBVISoftcore::getVolume";
static const RealOpenMM zero = (RealOpenMM) 0.0;
static const RealOpenMM minusThree = (RealOpenMM) -3.0;
RealOpenMM diff = (S - R);
if( FABS( diff ) < r ){
RealOpenMM lowerBound = (R > (r - S)) ? R : (r - S);
return (CpuGBVISoftcore::getL( r, (r + S), S ) -
CpuGBVISoftcore::getL( r, lowerBound, S ));
} else if( r <= diff ){
return CpuGBVISoftcore::getL( r, (r + S), S ) -
CpuGBVISoftcore::getL( r, (r - S), S ) +
POW( R, minusThree );
} else {
return zero;
}
}
/**---------------------------------------------------------------------------------------
Get L (used in analytical solution for volume integrals)
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return L value (Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
RealOpenMM CpuGBVISoftcore::getL( RealOpenMM r, RealOpenMM x, RealOpenMM S ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "CpuGBVISoftcore::getL";
static const RealOpenMM one = (RealOpenMM) 1.0;
static const RealOpenMM threeHalves = (RealOpenMM) 1.5;
static const RealOpenMM third = (RealOpenMM) (1.0/3.0);
static const RealOpenMM fourth = (RealOpenMM) 0.25;
static const RealOpenMM eighth = (RealOpenMM) 0.125;
// ---------------------------------------------------------------------------------------
RealOpenMM rInv = one/r;
RealOpenMM xInv = one/x;
RealOpenMM xInv2 = xInv*xInv;
RealOpenMM diff2 = (r + S)*(r - S);
return (threeHalves*xInv2)*( (fourth*rInv) - (xInv*third) + (diff2*xInv2*eighth*rInv) );
}
/**---------------------------------------------------------------------------------------
Get partial derivative of L wrt r
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return partial derivative based on Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
RealOpenMM CpuGBVISoftcore::dL_dr( RealOpenMM r, RealOpenMM x, RealOpenMM S ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuGBVISoftcore::dL_dr";
static const RealOpenMM one = (RealOpenMM) 1.0;
static const RealOpenMM threeHalves = (RealOpenMM) 1.5;
static const RealOpenMM threeEights = (RealOpenMM) 0.375;
static const RealOpenMM third = (RealOpenMM) (1.0/3.0);
static const RealOpenMM fourth = (RealOpenMM) 0.25;
static const RealOpenMM eighth = (RealOpenMM) 0.125;
// ---------------------------------------------------------------------------------------
RealOpenMM rInv = one/r;
RealOpenMM rInv2 = rInv*rInv;
RealOpenMM xInv = one/x;
RealOpenMM xInv2 = xInv*xInv;
RealOpenMM xInv3 = xInv2*xInv;
RealOpenMM diff2 = (r + S)*(r - S);
return ( (-threeHalves*xInv2*rInv2)*( fourth + eighth*diff2*xInv2 ) + threeEights*xInv3*xInv );
}
/**---------------------------------------------------------------------------------------
Get partial derivative of L wrt x
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return partial derivative based on Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
RealOpenMM CpuGBVISoftcore::dL_dx( RealOpenMM r, RealOpenMM x, RealOpenMM S ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "CpuGBVISoftcore::dL_dx";
static const RealOpenMM one = (RealOpenMM) 1.0;
static const RealOpenMM half = (RealOpenMM) 0.5;
static const RealOpenMM threeHalvesM = (RealOpenMM) -1.5;
static const RealOpenMM third = (RealOpenMM) (1.0/3.0);
// ---------------------------------------------------------------------------------------
RealOpenMM rInv = one/r;
RealOpenMM xInv = one/x;
RealOpenMM xInv2 = xInv*xInv;
RealOpenMM xInv3 = xInv2*xInv;
RealOpenMM diff = (r + S)*(r - S);
return (threeHalvesM*xInv3)*( (half*rInv) - xInv + (half*diff*xInv2*rInv) );
}
/**---------------------------------------------------------------------------------------
Sgb function
@param t r*r*G_i*G_j
@return Sgb (top of p. 1694 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
RealOpenMM CpuGBVISoftcore::Sgb( RealOpenMM t ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "CpuGBVISoftcore::Sgb";
static const RealOpenMM zero = (RealOpenMM) 0.0;
static const RealOpenMM one = (RealOpenMM) 1.0;
static const RealOpenMM fourth = (RealOpenMM) 0.25;
// ---------------------------------------------------------------------------------------
return ( (t != zero) ? one/SQRT( (one + (fourth*EXP( -t ))/t) ) : zero);
}
#define GBVISoftcoreDebug 0
/**---------------------------------------------------------------------------------------
Get GB/VI energy
@param bornRadii Born radii
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@return energy
--------------------------------------------------------------------------------------- */
RealOpenMM CpuGBVISoftcore::computeBornEnergy( const RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges ){
// ---------------------------------------------------------------------------------------
static const char* methodName = "CpuGBVISoftcore::computeBornEnergy";
static const RealOpenMM zero = (RealOpenMM) 0.0;
static const RealOpenMM one = (RealOpenMM) 1.0;
static const RealOpenMM two = (RealOpenMM) 2.0;
static const RealOpenMM three = (RealOpenMM) 3.0;
static const RealOpenMM four = (RealOpenMM) 4.0;
static const RealOpenMM half = (RealOpenMM) 0.5;
static const RealOpenMM fourth = (RealOpenMM) 0.25;
static const RealOpenMM eighth = (RealOpenMM) 0.125;
// ---------------------------------------------------------------------------------------
const GBVISoftcoreParameters* gbviParameters = getGBVISoftcoreParameters();
const RealOpenMM preFactor = gbviParameters->getElectricConstant();
const int numberOfAtoms = gbviParameters->getNumberOfAtoms();
const RealOpenMM* atomicRadii = gbviParameters->getAtomicRadii();
const RealOpenMM* gammaParameters = gbviParameters->getGammaParameters();
if( bornRadii == NULL ){
bornRadii = getBornRadii();
}
#if( GBVISoftcoreDebug == 1 )
FILE* logFile = stderr;
(void) fprintf( logFile, "\n%s\n", methodName );
(void) fflush( logFile );
#endif
// ---------------------------------------------------------------------------------------
// Eq.2 of Labute paper [JCC 29 p. 1693-1698 2008]
// to minimze roundoff error sum cavityEnergy separately since in general much
// smaller than other contributions
RealOpenMM energy = zero;
RealOpenMM cavityEnergy = zero;
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
RealOpenMM partialChargeI = partialCharges[atomI];
// self-energy term
RealOpenMM atomIEnergy = half*partialChargeI/bornRadii[atomI];
// cavity term
RealOpenMM ratio = (atomicRadii[atomI]/bornRadii[atomI]);
cavityEnergy += gammaParameters[atomI]*ratio*ratio*ratio;
/*
RealOpenMM e1 = partialChargeI*partialCharges[atomI]/bornRadii[atomI];
RealOpenMM e2 = gammaParameters[atomI]*ratio*ratio*ratio;
(void) fprintf( stderr, "E %d self=%.4e gamma=%.4e e=%.4e\n", atomI, e1, e2, energy );
*/
for( int atomJ = atomI + 1; atomJ < numberOfAtoms; atomJ++ ){
RealOpenMM deltaR[ReferenceForce::LastDeltaRIndex];
if (_gbviParameters->getPeriodic())
ReferenceForce::getDeltaRPeriodic( atomCoordinates[atomI], atomCoordinates[atomJ], _gbviParameters->getPeriodicBox(), deltaR );
else
ReferenceForce::getDeltaR( atomCoordinates[atomI], atomCoordinates[atomJ], deltaR );
if (_gbviParameters->getUseCutoff() && deltaR[ReferenceForce::RIndex] > _gbviParameters->getCutoffDistance())
continue;
RealOpenMM r2 = deltaR[ReferenceForce::R2Index];
RealOpenMM t = fourth*r2/(bornRadii[atomI]*bornRadii[atomJ]);
atomIEnergy += partialCharges[atomJ]*Sgb( t )/deltaR[ReferenceForce::RIndex];
/*
RealOpenMM e3 = -partialChargeI2*partialCharges[atomJ]*Sgb( t )/deltaR[ReferenceForce::RIndex];
(void) fprintf( stderr, "E %d %d e3=%.4e r2=%4e t=%.3e sgb=%.4e e=%.5e\n", atomI, atomJ, e3, r2, t, Sgb( t ), energy );
*/
}
energy += two*partialChargeI*atomIEnergy;
}
energy *= CAL_TO_JOULE*preFactor;
energy -= cavityEnergy;
#if( GBVISoftcoreDebug == 1 )
(void) fprintf( logFile, "ElectricConstant=%.4e Tau=%.4e e=%.5e eOut=%.5e\n", preFactor, gbviParameters->getTau(), energy, gbviParameters->getTau()*energy );
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
(void) fprintf( logFile, "bR %d bR=%16.8e\n", atomI, bornRadii[atomI] );
}
(void) fflush( logFile );
#endif
RealOpenMM conversion = (RealOpenMM)(gbviParameters->getTau());
return (conversion*energy);
}
#undef GBVISoftcoreDebug
#define GBVISoftcoreDebug 0
/**---------------------------------------------------------------------------------------
Get GB/VI forces
@param bornRadii Born radii
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@param forces forces
@return SimTKOpenMMCommon::DefaultReturn;
--------------------------------------------------------------------------------------- */
int CpuGBVISoftcore::computeBornForces( const RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** inputForces ){
// ---------------------------------------------------------------------------------------
static const char* methodName = "CpuGBVISoftcore::computeBornEnergyForces";
static const RealOpenMM zero = (RealOpenMM) 0.0;
static const RealOpenMM one = (RealOpenMM) 1.0;
static const RealOpenMM two = (RealOpenMM) 2.0;
static const RealOpenMM three = (RealOpenMM) 3.0;
static const RealOpenMM four = (RealOpenMM) 4.0;
static const RealOpenMM half = (RealOpenMM) 0.5;
static const RealOpenMM oneThird = (RealOpenMM) (1.0/3.0);
static const RealOpenMM fourth = (RealOpenMM) 0.25;
static const RealOpenMM eighth = (RealOpenMM) 0.125;
// ---------------------------------------------------------------------------------------
#if( GBVISoftcoreDebug == 1 || GBVISoftcoreDebug == 2 )
FILE* logFile = stderr;
(void) fprintf( logFile, "\n%s\n", methodName );
(void) fflush( logFile );
#endif
const GBVISoftcoreParameters* gbviParameters = getGBVISoftcoreParameters();
const int numberOfAtoms = gbviParameters->getNumberOfAtoms();
const RealOpenMM* atomicRadii = gbviParameters->getAtomicRadii();
const RealOpenMM* gammaParameters = gbviParameters->getGammaParameters();
if( bornRadii == NULL ){
bornRadii = getBornRadii();
}
// ---------------------------------------------------------------------------------------
// constants
const RealOpenMM preFactor = two*gbviParameters->getElectricConstant();
// ---------------------------------------------------------------------------------------
// set energy/forces to zero
const unsigned int arraySzInBytes = sizeof( RealOpenMM )*numberOfAtoms;
RealOpenMM** forces = new RealOpenMM*[numberOfAtoms];
RealOpenMM* block = new RealOpenMM[numberOfAtoms*3];
memset( block, 0, sizeof( RealOpenMM )*numberOfAtoms*3 );
RealOpenMM* blockPtr = block;
for( int ii = 0; ii < numberOfAtoms; ii++ ){
forces[ii] = blockPtr;
blockPtr += 3;
}
RealOpenMM* bornForces = getBornForce();
memset( bornForces, 0, arraySzInBytes );
// ---------------------------------------------------------------------------------------
// first main loop
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
// partial of polar term wrt Born radius
// and (dGpol/dr)(dr/dx)
RealOpenMM partialChargeI = preFactor*partialCharges[atomI];
for( int atomJ = atomI; atomJ < numberOfAtoms; atomJ++ ){
RealOpenMM deltaR[ReferenceForce::LastDeltaRIndex];
if (_gbviParameters->getPeriodic())
ReferenceForce::getDeltaRPeriodic( atomCoordinates[atomI], atomCoordinates[atomJ], _gbviParameters->getPeriodicBox(), deltaR );
else
ReferenceForce::getDeltaR( atomCoordinates[atomI], atomCoordinates[atomJ], deltaR );
if (_gbviParameters->getUseCutoff() && deltaR[ReferenceForce::RIndex] > _gbviParameters->getCutoffDistance())
continue;
RealOpenMM r2 = deltaR[ReferenceForce::R2Index];
RealOpenMM deltaX = deltaR[ReferenceForce::XIndex];
RealOpenMM deltaY = deltaR[ReferenceForce::YIndex];
RealOpenMM deltaZ = deltaR[ReferenceForce::ZIndex];
RealOpenMM alpha2_ij = bornRadii[atomI]*bornRadii[atomJ];
RealOpenMM D_ij = r2/(four*alpha2_ij);
RealOpenMM expTerm = EXP( -D_ij );
RealOpenMM denominator2 = r2 + alpha2_ij*expTerm;
RealOpenMM denominator = SQRT( denominator2 );
RealOpenMM Gpol = (partialChargeI*partialCharges[atomJ])/denominator;
RealOpenMM dGpol_dr = -Gpol*( one - fourth*expTerm )/denominator2;
RealOpenMM dGpol_dalpha2_ij = -half*Gpol*expTerm*( one + D_ij )/denominator2;
if( atomI != atomJ ){
bornForces[atomJ] += dGpol_dalpha2_ij*bornRadii[atomI];
deltaX *= dGpol_dr;
deltaY *= dGpol_dr;
deltaZ *= dGpol_dr;
forces[atomI][0] += deltaX;
forces[atomI][1] += deltaY;
forces[atomI][2] += deltaZ;
forces[atomJ][0] -= deltaX;
forces[atomJ][1] -= deltaY;
forces[atomJ][2] -= deltaZ;
}
// 3 FLOP
#if 0
if( atomI == 0 ){
(void) fprintf( logFile, "bFCalc: %6d %6d %14.6e %14.6e %14.6e %14.6e\n", atomI, atomJ, dGpol_dalpha2_ij, bornRadii[atomJ], bornForces[atomI], bornRadii[atomI] );
}
#endif
bornForces[atomI] += dGpol_dalpha2_ij*bornRadii[atomJ];
}
}
#if( GBVISoftcoreDebug == 1 )
{
double stupidFactor = three/CAL_TO_JOULE;
RealOpenMM conversion = (RealOpenMM)(CAL_TO_JOULE*gbviParameters->getTau());
int maxPrint = 200000;
const RealOpenMM* scaledRadii = gbviParameters->getScaledRadii();
RealOpenMM* switchDeriviative = getSwitchDeriviative();
(void) fprintf( logFile, "F1: Conversion=%14.6e %14.6e*%14.6e (tau)\n", conversion, CAL_TO_JOULE, gbviParameters->getTau() );
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
RealOpenMM R = atomicRadii[atomI];
RealOpenMM ratio = (atomicRadii[atomI]/bornRadii[atomI]);
RealOpenMM bF = bornForces[atomI] + (stupidFactor*gammaParameters[atomI]*ratio*ratio*ratio)/bornRadii[atomI];
RealOpenMM b2 = bornRadii[atomI]*bornRadii[atomI];
double xx = switchDeriviative[atomI]*bF*oneThird*b2*b2;
// xx*conversion should agree w/ values pulled out of kReduceGBVISoftcoreBornForces_kernel in kForces.cu
(void) fprintf( logFile, "F1 %6d r/sclR[%14.6e %14.6e] bR=%14.6e bF=%14.6e sw=%14.6e %14.6e f[%14.6e %14.6e %14.6e](cnvrtd)"
" x[%14.6e %14.6e %14.6e]\n",
atomI, atomicRadii[atomI], scaledRadii[atomI], bornRadii[atomI], bF, switchDeriviative[atomI], xx*conversion,
conversion*forces[atomI][0], conversion*forces[atomI][1], conversion*forces[atomI][2],
atomCoordinates[atomI][0], atomCoordinates[atomI][1], atomCoordinates[atomI][2] );
if( atomI == maxPrint ){
atomI = numberOfAtoms - maxPrint;
if( atomI < maxPrint )atomI = maxPrint;
}
}
(void) fflush( logFile );
}
#endif
#if( GBVISoftcoreDebug == 2 )
{
double stupidFactor = three/CAL_TO_JOULE;
RealOpenMM conversion = (RealOpenMM)(CAL_TO_JOULE*gbviParameters->getTau());
int maxPrint = 1000000;
const RealOpenMM* scaledRadii = gbviParameters->getScaledRadii();
RealOpenMM* switchDeriviative = getSwitchDeriviative();
(void) fprintf( logFile, "F1: Conversion=%14.6e %14.6e*%14.6e (tau)\n", conversion, CAL_TO_JOULE, gbviParameters->getTau() );
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
RealOpenMM R = atomicRadii[atomI];
RealOpenMM ratio = (atomicRadii[atomI]/bornRadii[atomI]);
RealOpenMM bF = bornForces[atomI] + (stupidFactor*gammaParameters[atomI]*ratio*ratio*ratio)/bornRadii[atomI];
RealOpenMM b2 = bornRadii[atomI]*bornRadii[atomI];
double xx = switchDeriviative[atomI]*bF*oneThird*b2*b2;
// xx*conversion should agree w/ values pulled out of kReduceGBVISoftcoreBornForces_kernel in kForces.cu
/*
(void) fprintf( logFile, "F1 %6d r/sclR[%14.6e %14.6e] bR=%14.6e sw=%14.6e bF=%14.6e %14.6e f[%14.6e %14.6e %14.6e](cnvrtd)"
" x[%14.6e %14.6e %14.6e]\n",
atomI, atomicRadii[atomI], scaledRadii[atomI], bornRadii[atomI], bF, switchDeriviative[atomI], xx*conversion,
conversion*forces[atomI][0], conversion*forces[atomI][1], conversion*forces[atomI][2],
atomCoordinates[atomI][0], atomCoordinates[atomI][1], atomCoordinates[atomI][2] );
*/
(void) fprintf( logFile, "%6d %14.6e %14.6e %14.6e %14.6e %14.6e %14.6e %14.6e %14.6e %14.6e %14.6e %14.6e %14.6e\n",
atomI, atomicRadii[atomI], scaledRadii[atomI], bornRadii[atomI], bF, xx*conversion,
conversion*forces[atomI][0], conversion*forces[atomI][1], conversion*forces[atomI][2],
atomCoordinates[atomI][0], atomCoordinates[atomI][1], atomCoordinates[atomI][2], switchDeriviative[atomI] );
}
(void) fflush( logFile );
}
#endif
// ---------------------------------------------------------------------------------------
// second main loop: (dGpol/dBornRadius)(dBornRadius/dr)(dr/dx)
// dGpol/dBornRadius) = bornForces[]
// dBornRadius/dr = (1/3)*(bR**4)*(dV/dr)
#if 0
(void) fprintf( logFile, "Clearing forces before loop2 periodic=%d cutoff=%d cutoffR=%14.7e\n",
_gbviParameters->getPeriodic(), _gbviParameters->getUseCutoff(), _gbviParameters->getCutoffDistance() );
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
forces[atomI][0] = zero;
forces[atomI][1] = zero;
forces[atomI][2] = zero;
}
(void) fflush( logFile );
#endif
const RealOpenMM* scaledRadii = gbviParameters->getScaledRadii();
RealOpenMM* switchDeriviative = getSwitchDeriviative();
double stupidFactor = three/CAL_TO_JOULE;
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
RealOpenMM R = atomicRadii[atomI];
// partial of cavity term wrt Born radius
RealOpenMM ratio = (atomicRadii[atomI]/bornRadii[atomI]);
bornForces[atomI] += (stupidFactor*gammaParameters[atomI]*ratio*ratio*ratio)/bornRadii[atomI];
RealOpenMM b2 = bornRadii[atomI]*bornRadii[atomI];
bornForces[atomI] *= switchDeriviative[atomI]*oneThird*b2*b2;
for( int atomJ = 0; atomJ < numberOfAtoms; atomJ++ ){
if( atomJ != atomI ){
RealOpenMM deltaX = atomCoordinates[atomJ][0] - atomCoordinates[atomI][0];
RealOpenMM deltaY = atomCoordinates[atomJ][1] - atomCoordinates[atomI][1];
RealOpenMM deltaZ = atomCoordinates[atomJ][2] - atomCoordinates[atomI][2];
RealOpenMM deltaR[ReferenceForce::LastDeltaRIndex];
if (_gbviParameters->getPeriodic())
ReferenceForce::getDeltaRPeriodic( atomCoordinates[atomI], atomCoordinates[atomJ], _gbviParameters->getPeriodicBox(), deltaR );
else
ReferenceForce::getDeltaR( atomCoordinates[atomI], atomCoordinates[atomJ], deltaR );
if (_gbviParameters->getUseCutoff() && deltaR[ReferenceForce::RIndex] > _gbviParameters->getCutoffDistance())
continue;
RealOpenMM r2 = deltaR[ReferenceForce::R2Index];
deltaX = deltaR[ReferenceForce::XIndex];
deltaY = deltaR[ReferenceForce::YIndex];
deltaZ = deltaR[ReferenceForce::ZIndex];
RealOpenMM r = SQRT( r2 );
RealOpenMM S = scaledRadii[atomJ];
RealOpenMM diff = (S - R);
RealOpenMM de = zero;
// find dRb/dr, where Rb is the Born radius
de = CpuGBVISoftcore::dL_dr( r, r+S, S ) + CpuGBVISoftcore::dL_dx( r, r+S, S );
if( FABS( diff ) < r ){
if( R > (r - S) ){
de -= CpuGBVISoftcore::dL_dr( r, R, S );
} else {
de -= ( CpuGBVISoftcore::dL_dr( r, (r-S), S ) + CpuGBVISoftcore::dL_dx( r, (r-S), S ) );
}
} else if( r < (S - R) ){
de -= ( CpuGBVISoftcore::dL_dr( r, r-S, S ) + CpuGBVISoftcore::dL_dx( r, r-S, S ) );
}
#if 0
RealOpenMM delta = (RealOpenMM) 1.0e-02;
(void) fprintf( stderr, "\n" );
for( int kk = 0; kk < 5; kk++ ){
RealOpenMM V1 = CpuGBVISoftcore::getVolume( r, R, S );
RealOpenMM V2 = CpuGBVISoftcore::getVolume( r+delta, R, S );
RealOpenMM df = (V2-V1)/delta;
(void) fprintf( stderr, "df %d %d [%14.6e %14.6e] V[%14.6e %14.6e] %.2e\n", atomI, atomJ, de, df, V2, V1, delta );
delta *= (RealOpenMM) 0.1;
}
double deltaD = 1.0e-02;
double ded = CpuGBVISoftcore::dL_drD( (double) r, r+S, S ) + CpuGBVISoftcore::dL_dxD( r, r+S, S ) - ( CpuGBVISoftcore::dL_drD( r, (r-S), S ) + CpuGBVISoftcore::dL_dxD( r, (r-S), S ) );
for( int kk = 0; kk < 5; kk++ ){
double V1 = CpuGBVISoftcore::getVolumeD( r, R, S );
double V2 = CpuGBVISoftcore::getVolumeD( r+deltaD, R, S );
double df = (V2-V1)/deltaD;
(void) fprintf( stderr, "df %d %d [%14.6e %14.6e] V[%14.6e %14.6e] %.2e\n", atomI, atomJ, ded, df, V2, V1, deltaD );
deltaD *= 0.1;
}
#endif
// de = (dG/dRb)(dRb/dr)
de *= bornForces[atomI]/r;
deltaX *= de;
deltaY *= de;
deltaZ *= de;
forces[atomI][0] += deltaX;
forces[atomI][1] += deltaY;
forces[atomI][2] += deltaZ;
forces[atomJ][0] -= deltaX;
forces[atomJ][1] -= deltaY;
forces[atomJ][2] -= deltaZ;
}
}
}
#if( GBVISoftcoreDebug == 1 )
{
(void) fprintf( logFile, "\nPre conversion\n" );
(void) fprintf( logFile, "Atom ScaledRadii BornRadii BornForce SwitchDrv Forces\n" );
double forceSum[3] = { 0.0, 0.0, 0.0 };
RealOpenMM conversion = (RealOpenMM)(CAL_TO_JOULE*gbviParameters->getTau());
const RealOpenMM* scaledRadii = gbviParameters->getScaledRadii();
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
forceSum[0] += forces[atomI][0];
forceSum[1] += forces[atomI][1];
forceSum[2] += forces[atomI][2];
(void) fprintf( logFile, "%6d %14.6e %14.6e %14.6e %14.6e [%14.6e %14.6e %14.6e]\n",
atomI, scaledRadii[atomI], bornRadii[atomI], conversion*bornForces[atomI], switchDeriviative[atomI],
conversion*forces[atomI][0], conversion*forces[atomI][1], conversion*forces[atomI][2] );
}
(void) fprintf( logFile, "F sum=[%14.6e %14.6e %14.6e]\n", forceSum[0], forceSum[1], forceSum[2] );
(void) fflush( logFile );
}
#endif
// convert from cal to Joule & apply prefactor tau = (1/diel_solute - 1/diel_solvent)
RealOpenMM conversion = (RealOpenMM)(CAL_TO_JOULE*gbviParameters->getTau());
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
inputForces[atomI][0] += conversion*forces[atomI][0];
inputForces[atomI][1] += conversion*forces[atomI][1];
inputForces[atomI][2] += conversion*forces[atomI][2];
}
#if( GBVISoftcoreDebug == 1 )
{
(void) fprintf( logFile, "\nPost conversion\n" );
(void) fprintf( logFile, "Atom BornRadii BornForce SwitchDrv Forces\n" );
int maxPrint = 1000000;
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
(void) fprintf( logFile, "%6d %14.6e %14.6e %14.6e [%14.6e %14.6e %14.6e] %s\n", atomI, bornRadii[atomI], conversion*bornForces[atomI],
switchDeriviative[atomI], inputForces[atomI][0], inputForces[atomI][1], inputForces[atomI][2], (fabs( switchDeriviative[atomI] - 1.0 ) > 1.0e-05 ? "SWWWWW" : "") );
if( atomI == maxPrint ){
atomI = numberOfAtoms - maxPrint;
if( atomI < maxPrint )atomI = numberOfAtoms;
}
}
(void) fflush( logFile );
}
#endif
#if( GBVISoftcoreDebug == 2 )
{
(void) fprintf( logFile, "\nAtom BornRadii BornForce SwitchDrv Forces Post conversion\n" );
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
(void) fprintf( logFile, "%6d %14.6e %14.6e %14.6e %14.6e %14.6e %14.6e\n", atomI, bornRadii[atomI], conversion*bornForces[atomI],
inputForces[atomI][0], inputForces[atomI][1], inputForces[atomI][2], switchDeriviative[atomI] );
}
(void) fflush( logFile );
}
#endif
#undef GBVISoftcoreDebug
delete[] forces;
delete[] block;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get string w/ state
@param title title (optional)
@return string containing state
--------------------------------------------------------------------------------------- */
std::string CpuGBVISoftcore::getStateString( const char* title ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::getStateString";
// ---------------------------------------------------------------------------------------
std::stringstream message;
message << CpuImplicitSolvent::getStateString( title );
return message.str();
}
/**---------------------------------------------------------------------------------------
Write Born energy and forces (Simbios)
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@param forces forces
@param resultsFileName output file name
@return SimTKOpenMMCommon::DefaultReturn unless
file cannot be opened
in which case return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
int CpuGBVISoftcore::writeBornEnergyForces( RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces,
const std::string& resultsFileName ) const {
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nCpuGBVISoftcore::writeBornEnergyForces";
// ---------------------------------------------------------------------------------------
/*
ImplicitSolventParameters* implicitSolventParameters = getImplicitSolventParameters();
const GBVISoftcoreParameters* gbviParameters = static_cast<const GBVISoftcoreParameters*>(implicitSolventParameters);
int numberOfAtoms = gbviParameters->getNumberOfAtoms();
const RealOpenMM* atomicRadii = gbviParameters->getAtomicRadii();
const RealOpenMM* bornRadii = getBornRadiiConst();
const RealOpenMM* scaledRadii = gbviParameters->getScaledRadiusFactors();
const RealOpenMM* gbviChain = getObcChainConst();
const RealOpenMM energy = getEnergy();
// ---------------------------------------------------------------------------------------
// open file -- return if unsuccessful
FILE* implicitSolventResultsFile = NULL;
#ifdef WIN32
fopen_s( &implicitSolventResultsFile, resultsFileName.c_str(), "w" );
#else
implicitSolventResultsFile = fopen( resultsFileName.c_str(), "w" );
#endif
// diganostics
std::stringstream message;
message << methodName;
if( implicitSolventResultsFile != NULL ){
std::stringstream message;
message << methodName;
message << " Opened file=<" << resultsFileName << ">.";
SimTKOpenMMLog::printMessage( message );
} else {
std::stringstream message;
message << methodName;
message << " could not open file=<" << resultsFileName << "> -- abort output.";
SimTKOpenMMLog::printMessage( message );
return SimTKOpenMMCommon::ErrorReturn;
}
// header
(void) fprintf( implicitSolventResultsFile, "# %d atoms E=%.7e format: coords(3) bornRadii(input) q atomicRadii scaleFactors forces gbviChain\n",
numberOfAtoms, energy );
RealOpenMM forceConversion = (RealOpenMM) 1.0;
RealOpenMM lengthConversion = (RealOpenMM) 1.0;
// output
if( forces != NULL && atomCoordinates != NULL && partialCharges != NULL && atomicRadii != NULL ){
for( int ii = 0; ii < numberOfAtoms; ii++ ){
(void) fprintf( implicitSolventResultsFile, "%.7e %.7e %.7e %.7e %.5f %.5f %.5f %.7e %.7e %.7e %.7e\n",
lengthConversion*atomCoordinates[ii][0],
lengthConversion*atomCoordinates[ii][1],
lengthConversion*atomCoordinates[ii][2],
(bornRadii != NULL ? lengthConversion*bornRadii[ii] : 0.0),
partialCharges[ii], lengthConversion*atomicRadii[ii], scaledRadii[ii],
forceConversion*forces[ii][0],
forceConversion*forces[ii][1],
forceConversion*forces[ii][2],
forceConversion*gbviChain[ii]
);
}
}
(void) fclose( implicitSolventResultsFile );
*/
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Write results from first loop
@param numberOfAtoms number of atoms
@param forces forces
@param bornForce Born force prefactor
@param outputFileName output file name
@return SimTKOpenMMCommon::DefaultReturn unless
file cannot be opened
in which case return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
int CpuGBVISoftcore::writeForceLoop1( int numberOfAtoms, RealOpenMM** forces, const RealOpenMM* bornForce,
const std::string& outputFileName ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuGBVISoftcore::writeForceLoop1";
// ---------------------------------------------------------------------------------------
int chunkSize;
if( bornForce ){
chunkSize = 3;
} else {
chunkSize = 4;
}
StringVector lineVector;
std::stringstream header;
lineVector.push_back( "# bornF F" );
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
std::stringstream line;
line << (atomI+1) << " ";
SimTKOpenMMUtilities::formatRealStringStream( line, forces[atomI], chunkSize );
if( bornForce ){
line << " " << bornForce[atomI];
}
lineVector.push_back( line.str() );
}
return SimTKOpenMMUtilities::writeFile( lineVector, outputFileName );
}
/**---------------------------------------------------------------------------------------
Write results
@param numberOfAtoms number of atoms
@param chunkSizes vector of chunk sizes for realRealOpenMMVector
@param realRealOpenMMVector vector of RealOpenMM**
@param realVector vector of RealOpenMM*
@param outputFileName output file name
@return SimTKOpenMMCommon::DefaultReturn unless
file cannot be opened
in which case return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
int CpuGBVISoftcore::writeForceLoop( int numberOfAtoms, const IntVector& chunkSizes,
const RealOpenMMPtrPtrVector& realRealOpenMMVector,
const RealOpenMMPtrVector& realVector,
const std::string& outputFileName ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuGBVISoftcore::writeForceLoop";
static const int maxChunks = 10;
int chunks[maxChunks];
// ---------------------------------------------------------------------------------------
for( int ii = 0; ii < (int) chunkSizes.size(); ii++ ){
chunks[ii] = chunkSizes[ii];
}
for( int ii = (int) chunkSizes.size(); ii < maxChunks; ii++ ){
chunks[ii] = 3;
}
StringVector lineVector;
std::stringstream header;
// lineVector.push_back( "# " );
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
std::stringstream line;
char buffer[128];
(void) sprintf( buffer, "%4d ", atomI );
line << buffer;
int index = 0;
for( RealOpenMMPtrPtrVectorCI ii = realRealOpenMMVector.begin(); ii != realRealOpenMMVector.end(); ii++ ){
RealOpenMM** forces = *ii;
(void) sprintf( buffer, "%11.5f %11.5f %11.5f ", forces[atomI][0], forces[atomI][1], forces[atomI][2] );
line << buffer;
// SimTKOpenMMUtilities::formatRealStringStream( line, forces[atomI], chunks[index++] );
// line << " ";
}
for( RealOpenMMPtrVectorCI ii = realVector.begin(); ii != realVector.end(); ii++ ){
RealOpenMM* array = *ii;
(void) sprintf( buffer, "%11.5f ", array[atomI] );
line << buffer;
}
lineVector.push_back( line.str() );
}
return SimTKOpenMMUtilities::writeFile( lineVector, outputFileName );
}
/**---------------------------------------------------------------------------------------
Get Obc Born energy and forces -- used debugging
@param bornRadii Born radii -- optional; if NULL, then GBVISoftcoreParameters
entry is used
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@param forces forces
@return SimTKOpenMMCommon::DefaultReturn;
The array bornRadii is also updated and the obcEnergy
--------------------------------------------------------------------------------------- */
int CpuGBVISoftcore::computeBornEnergyForces( RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuGBVISoftcore::computeBornEnergyForcesPrint";
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Use double precision
Get volume Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return volume
--------------------------------------------------------------------------------------- */
double CpuGBVISoftcore::getVolumeD( double r, double R, double S ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "CpuGBVISoftcore::getVolume";
static const double zero = 0.0;
static const double minusThree = -3.0;
double diff = (S - R);
if( fabs( diff ) < r ){
double lowerBound = (R > (r - S)) ? R : (r - S);
return (CpuGBVISoftcore::getLD( r, (r + S), S ) -
CpuGBVISoftcore::getLD( r, lowerBound, S ));
} else if( r < diff ){
return CpuGBVISoftcore::getLD( r, (r + S), S ) -
CpuGBVISoftcore::getLD( r, (r - S), S ) +
pow( R, minusThree );
} else {
return zero;
}
}
/**---------------------------------------------------------------------------------------
Use double precision
Get L (used in analytical solution for volume integrals)
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return L value (Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
double CpuGBVISoftcore::getLD( double r, double x, double S ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "CpuGBVISoftcore::getL";
static const double one = 1.0;
static const double threeHalves = 1.5;
static const double third = 1.0/3.0;
static const double fourth = 0.25;
static const double eighth = 0.125;
// ---------------------------------------------------------------------------------------
double rInv = one/r;
double xInv = one/x;
double xInv2 = xInv*xInv;
double xInv3 = xInv2*xInv;
double diff2 = (r + S)*(r - S);
return (threeHalves*xInv)*( (xInv*fourth*rInv) - (xInv2*third) + (diff2*xInv3*eighth*rInv) );
}
/**---------------------------------------------------------------------------------------
Use double precision
Get partial derivative of L wrt r
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return partial derivative based on Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
double CpuGBVISoftcore::dL_drD( double r, double x, double S ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "CpuGBVISoftcore::dL_dr";
static const double one = 1.0;
static const double threeHalves = 1.5;
static const double threeEights = 0.375;
static const double third = 1.0/3.0;
static const double fourth = 0.25;
static const double eighth = 0.125;
// ---------------------------------------------------------------------------------------
double rInv = one/r;
double rInv2 = rInv*rInv;
double xInv = one/x;
double xInv2 = xInv*xInv;
double xInv3 = xInv2*xInv;
double diff2 = (r + S)*(r - S);
return ( (-threeHalves*xInv2*rInv2)*( fourth + eighth*diff2*xInv2 ) + threeEights*xInv3*xInv );
}
/**---------------------------------------------------------------------------------------
Use double precision
Get partial derivative of L wrt x
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return partial derivative based on Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
double CpuGBVISoftcore::dL_dxD( double r, double x, double S ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "CpuGBVISoftcore::dL_dx";
static const double one = 1.0;
static const double half = 0.5;
static const double threeHalvesM = -1.5;
static const double third = 1.0/3.0;
// ---------------------------------------------------------------------------------------
double rInv = one/r;
double xInv = one/x;
double xInv2 = xInv*xInv;
double xInv3 = xInv2*xInv;
double diff = (r + S)*(r - S);
return (threeHalvesM*xInv3)*( (half*rInv) - xInv + (half*diff*xInv2*rInv) );
}
/* Portions copyright (c) 2006 Stanford University and Simbios.
* Contributors: Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __CpuGBVISoftcore_H__
#define __CpuGBVISoftcore_H__
#include "GBVISoftcoreParameters.h"
#include "gbsa/CpuImplicitSolvent.h"
// ---------------------------------------------------------------------------------------
class CpuGBVISoftcore : public CpuImplicitSolvent {
private:
// GB/VI parameters
GBVISoftcoreParameters* _gbviParameters;
// arrays containing switching function derivative
RealOpenMM* _switchDeriviative;
// initialize data members (more than
// one constructor, so centralize intialization here)
void _initializeGBVISoftcoreDataMembers( void );
public:
/**---------------------------------------------------------------------------------------
Constructor
@param implicitSolventParameters ImplicitSolventParameters reference
@return CpuImplicitSolvent object
--------------------------------------------------------------------------------------- */
CpuGBVISoftcore( ImplicitSolventParameters* gbviParameters );
/**---------------------------------------------------------------------------------------
Destructor
--------------------------------------------------------------------------------------- */
~CpuGBVISoftcore( );
/**---------------------------------------------------------------------------------------
Return GBVISoftcoreParameters
@return GBVISoftcoreParameters
--------------------------------------------------------------------------------------- */
GBVISoftcoreParameters* getGBVISoftcoreParameters( void ) const;
/**---------------------------------------------------------------------------------------
Set ImplicitSolventParameters
@param ImplicitSolventParameters
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setGBVISoftcoreParameters( GBVISoftcoreParameters* gbviParameters );
/**---------------------------------------------------------------------------------------
Return OBC chain derivative: size = _implicitSolventParameters->getNumberOfAtoms()
On first call, memory for array is allocated if not set
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* getSwitchDeriviative( void );
RealOpenMM* getSwitchDeriviativeConst( void ) const;
/**---------------------------------------------------------------------------------------
Get Born radii based on Eq. 3 of Labute paper [JCC 29 p. 1693-1698 2008])
@param atomCoordinates atomic coordinates
@param bornRadii output array of Born radii
@param switchDeriviative derivative of switch function
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int computeBornRadii( RealOpenMM** atomCoordinates, RealOpenMM* bornRadii,
RealOpenMM* switchDeriviative = NULL );
/**---------------------------------------------------------------------------------------
Get Born energy and forces (not used)
@param bornRadii Born radii
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@param forces forces
@return force array
--------------------------------------------------------------------------------------- */
int computeBornEnergyForces( RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces );
int computeBornEnergyForcesPrint( RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces );
/**---------------------------------------------------------------------------------------
Get state
title title (optional)
@return state string
--------------------------------------------------------------------------------------- */
std::string getStateString( const char* title ) const;
/**---------------------------------------------------------------------------------------
Write Born energy and forces (Simbios)
@param atomCoordinates atomic coordinates
@param partialCharges partial atom charges
@param forces force array
@param resultsFileName output file name
@return SimTKOpenMMCommon::DefaultReturn if file opened; else return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
int writeBornEnergyForces( RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces,
const std::string& resultsFileName ) const;
/**---------------------------------------------------------------------------------------
Write results from first loop
@param atomCoordinates atomic coordinates
@param RealOpenMM forces forces
@param outputFileName output file name
@return SimTKOpenMMCommon::DefaultReturn unless
file cannot be opened
in which case return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
static int writeForceLoop1( int numberOfAtoms, RealOpenMM** forces, const RealOpenMM* bornForce,
const std::string& outputFileName );
/**---------------------------------------------------------------------------------------
Write results
@param numberOfAtoms number of atoms
@param chunkSizes vector of chunk sizes for realRealOpenMMVector
@param realRealOpenMMVector vector of RealOpenMM**
@param realVector vector of RealOpenMM*
@param outputFileName output file name
@return SimTKOpenMMCommon::DefaultReturn unless
file cannot be opened
in which case return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
static int writeForceLoop( int numberOfAtoms, const IntVector& chunkSizes,
const RealOpenMMPtrPtrVector& realRealOpenMMVector,
const RealOpenMMPtrVector& realVector,
const std::string& outputFileName );
/**---------------------------------------------------------------------------------------
Get volume Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return volume
--------------------------------------------------------------------------------------- */
static RealOpenMM getVolume( RealOpenMM r, RealOpenMM R, RealOpenMM S );
/**---------------------------------------------------------------------------------------
Get L (analytical solution for volume integrals)
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return L value (Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
static RealOpenMM getL( RealOpenMM r, RealOpenMM x, RealOpenMM S );
/**---------------------------------------------------------------------------------------
Get partial derivative of L wrt r
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return partial derivative based on Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
static RealOpenMM dL_dr( RealOpenMM r, RealOpenMM x, RealOpenMM S );
/**---------------------------------------------------------------------------------------
Get partial derivative of L wrt x
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return partial derivative based on Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
static RealOpenMM dL_dx( RealOpenMM r, RealOpenMM x, RealOpenMM S );
/**---------------------------------------------------------------------------------------
Sgb function
@param t r*r*G_i*G_j
@return Sgb (p. 1694 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
static RealOpenMM Sgb( RealOpenMM t );
/**---------------------------------------------------------------------------------------
Get GB/VI energy
@param bornRadii Born radii
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@return energy
--------------------------------------------------------------------------------------- */
RealOpenMM computeBornEnergy( const RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges );
/**---------------------------------------------------------------------------------------
Get GB/VI forces
@param bornRadii Born radii
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@param forces output forces
@return SimTKOpenMMCommon::DefaultReturn;
--------------------------------------------------------------------------------------- */
int computeBornForces( const RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** inputForces );
/**---------------------------------------------------------------------------------------
Get volume Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return volume
--------------------------------------------------------------------------------------- */
static double getVolumeD( double r, double R, double S );
/**---------------------------------------------------------------------------------------
Get L (analytical solution for volume integrals)
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return L value (Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
static double getLD( double r, double x, double S );
/**---------------------------------------------------------------------------------------
Get partial derivative of L wrt r
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return partial derivative based on Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
static double dL_drD( double r, double x, double S );
/**---------------------------------------------------------------------------------------
Get partial derivative of L wrt x
@param r distance between atoms i & j
@param R atomic radius
@param S scaled atomic radius
@return partial derivative based on Eq. 4 of Labute paper [JCC 29 p. 1693-1698 2008])
--------------------------------------------------------------------------------------- */
static double dL_dxD( double r, double x, double S );
/**---------------------------------------------------------------------------------------
Compute quintic spline value and associated derviative
@param x value to compute spline at
@param rl lower cutoff value
@param ru upper cutoff value
@param outValue value of spline at x
@param outDerivative value of derivative of spline at x
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int quinticSpline( RealOpenMM x, RealOpenMM rl, RealOpenMM ru, RealOpenMM* outValue, RealOpenMM* outDerivative );
/**---------------------------------------------------------------------------------------
Compute Born radii based on Eq. 3 of Labute paper [JCC 29 p. 1693-1698 2008])
and quintic splice switching function
@param atomicRadius3 atomic radius cubed
@param bornSum Born sum (volume integral)
@param gbviParameters Gbvi parameters (parameters used in spline
QuinticLowerLimitFactor & QuinticUpperLimit)
@param bornRadius output Born radius
@param switchDeriviative output switching function deriviative
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int computeBornRadiiUsingQuinticSpline( RealOpenMM atomicRadius3, RealOpenMM bornSum,
GBVISoftcoreParameters* gbviParameters,
RealOpenMM* bornRadius, RealOpenMM* switchDeriviative );
};
// ---------------------------------------------------------------------------------------
#endif // __CpuGBVISoftcore_H__
/* Portions copyright (c) 2006-2009 Stanford University and Simbios.
* Contributors: Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <string.h>
#include <sstream>
#include "../SimTKUtilities/SimTKOpenMMCommon.h"
#include "../SimTKUtilities/SimTKOpenMMLog.h"
#include "../SimTKUtilities/SimTKOpenMMUtilities.h"
#include "CpuObcSoftcore.h"
#include "../SimTKReference/ReferenceForce.h"
#include <cmath>
#include <cstdio>
/**---------------------------------------------------------------------------------------
CpuObcSoftcore constructor
obcSoftcoreParameters obcSoftcoreParameters object
--------------------------------------------------------------------------------------- */
CpuObcSoftcore::CpuObcSoftcore( ImplicitSolventParameters* obcSoftcoreParameters ) : CpuImplicitSolvent( obcSoftcoreParameters ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObcSoftcore::CpuObcSoftcore";
// ---------------------------------------------------------------------------------------
_initializeObcDataMembers( );
_obcSoftcoreParameters = static_cast<ObcSoftcoreParameters*> (obcSoftcoreParameters);
}
/**---------------------------------------------------------------------------------------
CpuObcSoftcore destructor
--------------------------------------------------------------------------------------- */
CpuObcSoftcore::~CpuObcSoftcore( ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObcSoftcore::~CpuObcSoftcore";
// ---------------------------------------------------------------------------------------
//if( _obcSoftcoreParameters != NULL ){
// delete _obcSoftcoreParameters;
//}
delete[] _obcChain;
delete[] _obcChainTemp;
}
/**---------------------------------------------------------------------------------------
Initialize data members
--------------------------------------------------------------------------------------- */
void CpuObcSoftcore::_initializeObcDataMembers( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObcSoftcore::initializeDataMembers";
// ---------------------------------------------------------------------------------------
_obcSoftcoreParameters = NULL;
_obcChain = NULL;
_obcChainTemp = NULL;
}
/**---------------------------------------------------------------------------------------
Get ObcSoftcoreParameters reference
@return ObcSoftcoreParameters reference
--------------------------------------------------------------------------------------- */
ObcSoftcoreParameters* CpuObcSoftcore::getObcSoftcoreParameters( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObcSoftcore::getObcSoftcoreParameters";
// ---------------------------------------------------------------------------------------
return _obcSoftcoreParameters;
}
/**---------------------------------------------------------------------------------------
Set ObcSoftcoreParameters reference
@param ObcSoftcoreParameters reference
@return SimTKOpenMMCommon::DefaultReturn;
--------------------------------------------------------------------------------------- */
int CpuObcSoftcore::setObcSoftcoreParameters( ObcSoftcoreParameters* obcSoftcoreParameters ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObcSoftcore::setObcSoftcoreParameters";
// ---------------------------------------------------------------------------------------
_obcSoftcoreParameters = obcSoftcoreParameters;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Return OBC chain derivative: size = _obcSoftcoreParameters->getNumberOfAtoms()
On first call, memory for array is allocated if not set
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* CpuObcSoftcore::getObcChain( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObcSoftcore::getObcChain";
// ---------------------------------------------------------------------------------------
if( _obcChain == NULL ){
_obcChain = new RealOpenMM[_obcSoftcoreParameters->getNumberOfAtoms()];
}
return _obcChain;
}
/**---------------------------------------------------------------------------------------
Return OBC chain derivative: size = _obcSoftcoreParameters->getNumberOfAtoms()
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* CpuObcSoftcore::getObcChainConst( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObcSoftcore::getObcChain";
// ---------------------------------------------------------------------------------------
return _obcChain;
}
/**---------------------------------------------------------------------------------------
Return OBC chain temp work array of size=_obcSoftcoreParameters->getNumberOfAtoms()
On first call, memory for array is allocated if not set
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* CpuObcSoftcore::getObcChainTemp( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObcSoftcore::getImplicitSolventObcChainTemp";
// ---------------------------------------------------------------------------------------
if( _obcChainTemp == NULL ){
_obcChainTemp = new RealOpenMM[_obcSoftcoreParameters->getNumberOfAtoms()];
}
return _obcChainTemp;
}
/**---------------------------------------------------------------------------------------
Get Born radii based on papers:
J. Phys. Chem. 1996 100, 19824-19839 (HCT paper)
Proteins: Structure, Function, and Bioinformatcis 55:383-394 (2004) (OBC paper)
@param atomCoordinates atomic coordinates
@param bornRadii output array of Born radii
@return array of Born radii
--------------------------------------------------------------------------------------- */
int CpuObcSoftcore::computeBornRadii( RealOpenMM** atomCoordinates, RealOpenMM* bornRadii, RealOpenMM* obcChain ){
// ---------------------------------------------------------------------------------------
static const RealOpenMM zero = (RealOpenMM) 0.0;
static const RealOpenMM one = (RealOpenMM) 1.0;
static const RealOpenMM two = (RealOpenMM) 2.0;
static const RealOpenMM three = (RealOpenMM) 3.0;
static const RealOpenMM half = (RealOpenMM) 0.5;
static const RealOpenMM fourth = (RealOpenMM) 0.25;
static const char* methodName = "\nCpuObcSoftcore::computeBornRadii";
// ---------------------------------------------------------------------------------------
ObcSoftcoreParameters* obcSoftcoreParameters = getObcSoftcoreParameters();
int numberOfAtoms = obcSoftcoreParameters->getNumberOfAtoms();
RealOpenMM* atomicRadii = obcSoftcoreParameters->getAtomicRadii();
const RealOpenMM* scaledRadiusFactor = obcSoftcoreParameters->getScaledRadiusFactors();
if( !obcChain ){
obcChain = getObcChain();
}
const RealOpenMM* nonPolarScaleFactors = obcSoftcoreParameters->getNonPolarScaleFactors();
RealOpenMM dielectricOffset = obcSoftcoreParameters->getDielectricOffset();
RealOpenMM alphaObc = obcSoftcoreParameters->getAlphaObc();
RealOpenMM betaObc = obcSoftcoreParameters->getBetaObc();
RealOpenMM gammaObc = obcSoftcoreParameters->getGammaObc();
// ---------------------------------------------------------------------------------------
// calculate Born radii
//FILE* logFile = SimTKOpenMMLog::getSimTKOpenMMLogFile( );
//FILE* logFile = NULL;
//FILE* logFile = fopen( "bR", "w" );
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
RealOpenMM radiusI = atomicRadii[atomI];
RealOpenMM offsetRadiusI = radiusI - dielectricOffset;
RealOpenMM radiusIInverse = one/offsetRadiusI;
RealOpenMM sum = zero;
// HCT code
for( int atomJ = 0; atomJ < numberOfAtoms; atomJ++ ){
if( atomJ != atomI ){
RealOpenMM deltaR[ReferenceForce::LastDeltaRIndex];
if (_obcSoftcoreParameters->getPeriodic())
ReferenceForce::getDeltaRPeriodic( atomCoordinates[atomI], atomCoordinates[atomJ], _obcSoftcoreParameters->getPeriodicBox(), deltaR );
else
ReferenceForce::getDeltaR( atomCoordinates[atomI], atomCoordinates[atomJ], deltaR );
RealOpenMM r = deltaR[ReferenceForce::RIndex];
if (_obcSoftcoreParameters->getUseCutoff() && r > _obcSoftcoreParameters->getCutoffDistance())
continue;
RealOpenMM offsetRadiusJ = atomicRadii[atomJ] - dielectricOffset;
RealOpenMM scaledRadiusJ = offsetRadiusJ*scaledRadiusFactor[atomJ];
RealOpenMM rScaledRadiusJ = r + scaledRadiusJ;
if( offsetRadiusI < rScaledRadiusJ ){
RealOpenMM rInverse = one/r;
RealOpenMM l_ij = offsetRadiusI > FABS( r - scaledRadiusJ ) ? offsetRadiusI : FABS( r - scaledRadiusJ );
l_ij = one/l_ij;
RealOpenMM u_ij = one/rScaledRadiusJ;
RealOpenMM l_ij2 = l_ij*l_ij;
RealOpenMM u_ij2 = u_ij*u_ij;
RealOpenMM ratio = LN( (u_ij/l_ij) );
RealOpenMM term = l_ij - u_ij + fourth*r*(u_ij2 - l_ij2) + ( half*rInverse*ratio) + (fourth*scaledRadiusJ*scaledRadiusJ*rInverse)*(l_ij2 - u_ij2);
// this case (atom i completely inside atom j) is not considered in the original paper
// Jay Ponder and the authors of Tinker recognized this and
// worked out the details
if( offsetRadiusI < (scaledRadiusJ - r) ){
term += two*( radiusIInverse - l_ij);
}
sum += nonPolarScaleFactors[atomJ]*term;
/*
if( logFile && atomI == 0 ){
(void) fprintf( logFile, "\nRR %d %d r=%.4f rads[%.6f %.6f] scl=[%.3f %.3f] sum=%12.6e %12.6e %12.6e %12.6e",
atomI, atomJ, r, offsetRadiusI, offsetRadiusJ, scaledRadiusFactor[atomI], scaledRadiusFactor[atomJ], 0.5f*sum,
l_ij, u_ij, term );
}
*/
}
}
}
// OBC-specific code (Eqs. 6-8 in paper)
sum *= half*offsetRadiusI;
RealOpenMM sum2 = sum*sum;
RealOpenMM sum3 = sum*sum2;
RealOpenMM tanhSum = TANH( alphaObc*sum - betaObc*sum2 + gammaObc*sum3 );
bornRadii[atomI] = one/( one/offsetRadiusI - tanhSum/radiusI );
obcChain[atomI] = offsetRadiusI*( alphaObc - two*betaObc*sum + three*gammaObc*sum2 );
obcChain[atomI] = (one - tanhSum*tanhSum)*obcChain[atomI]/radiusI;
#if 0
if( logFile && atomI >= 0 ){
(void) fprintf( logFile, "\nRRQ %d sum %12.6e tanhS %12.6e radI %.5f %.5f born %18.10e obc %12.6e",
atomI, sum, tanhSum, radiusI, offsetRadiusI, bornRadii[atomI], obcChain[atomI] );
}
#endif
}
#if 0
if( logFile ){
(void) fclose( logFile );
}
#endif
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get nonpolar solvation force constribution via ACE approximation
@param obcSoftcoreParameters parameters
@param vdwRadii Vdw radii
@param bornRadii Born radii
@param energy energy (output): value is incremented from input value
@param forces forces: values are incremented from input values
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int CpuObcSoftcore::computeAceNonPolarForce( const ObcSoftcoreParameters* obcSoftcoreParameters,
const RealOpenMM* bornRadii, RealOpenMM* energy,
RealOpenMM* forces ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::computeAceNonPolarForce";
static const RealOpenMM minusSix = -6.0;
// ---------------------------------------------------------------------------------------
// compute the nonpolar solvation via ACE approximation
const RealOpenMM probeRadius = obcSoftcoreParameters->getProbeRadius();
const RealOpenMM surfaceAreaFactor = obcSoftcoreParameters->getPi4Asolv();
const RealOpenMM* atomicRadii = obcSoftcoreParameters->getAtomicRadii();
const RealOpenMM* nonPolarScaleFactors = obcSoftcoreParameters->getNonPolarScaleFactors();
int numberOfAtoms = obcSoftcoreParameters->getNumberOfAtoms();
// 1 + 1 + pow + 3 + 1 + 2 FLOP
// the original ACE equation is based on Eq.2 of
// M. Schaefer, C. Bartels and M. Karplus, "Solution Conformations
// and Thermodynamics of Structured Peptides: Molecular Dynamics
// Simulation with an Implicit Solvation Model", J. Mol. Biol.,
// 284, 835-848 (1998) (ACE Method)
// The original equation includes the factor (atomicRadii[atomI]/bornRadii[atomI]) to the first power,
// whereas here the ratio is raised to the sixth power: (atomicRadii[atomI]/bornRadii[atomI])**6
// This modification was made by Jay Ponder who observed it gave better correlations w/
// observed values. He did not think it was important enough to write up, so there is
// no paper to cite.
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
if( bornRadii[atomI] > 0.0 ){
RealOpenMM r = atomicRadii[atomI] + probeRadius;
RealOpenMM ratio6 = POW( atomicRadii[atomI]/bornRadii[atomI], (RealOpenMM) 6.0 );
RealOpenMM saTerm = nonPolarScaleFactors[atomI]*surfaceAreaFactor*r*r*ratio6;
*energy += saTerm;
forces[atomI] += minusSix*saTerm/bornRadii[atomI];
}
}
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get Obc Born energy and forces
@param bornRadii Born radii -- optional; if NULL, then ObcSoftcoreParameters
entry is used
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@param forces forces
@return SimTKOpenMMCommon::DefaultReturn;
The array bornRadii is also updated and the obcEnergy
--------------------------------------------------------------------------------------- */
int CpuObcSoftcore::computeBornEnergyForces( RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** inputForces ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObcSoftcore::computeBornEnergyForces";
static const RealOpenMM zero = (RealOpenMM) 0.0;
static const RealOpenMM one = (RealOpenMM) 1.0;
static const RealOpenMM two = (RealOpenMM) 2.0;
static const RealOpenMM three = (RealOpenMM) 3.0;
static const RealOpenMM four = (RealOpenMM) 4.0;
static const RealOpenMM half = (RealOpenMM) 0.5;
static const RealOpenMM fourth = (RealOpenMM) 0.25;
static const RealOpenMM eighth = (RealOpenMM) 0.125;
// ---------------------------------------------------------------------------------------
const ObcSoftcoreParameters* obcSoftcoreParameters = getObcSoftcoreParameters();
const int numberOfAtoms = obcSoftcoreParameters->getNumberOfAtoms();
if( bornRadii == NULL ){
bornRadii = getBornRadii();
}
// ---------------------------------------------------------------------------------------
// constants
const RealOpenMM preFactor = obcSoftcoreParameters->getPreFactor();
const RealOpenMM dielectricOffset = obcSoftcoreParameters->getDielectricOffset();
// ---------------------------------------------------------------------------------------
#if 0
{
RealOpenMM* atomicRadii = obcSoftcoreParameters->getAtomicRadii();
const RealOpenMM* scaledRadiusFactor = obcSoftcoreParameters->getScaledRadiusFactors();
RealOpenMM* obcChain = getObcChain();
FILE* logFile = fopen( "bornParameters", "w" );
(void) fprintf( logFile, "%5d dielOff=%.4e rad::hct::q::bR::Chain::coords\n", numberOfAtoms, dielectricOffset );
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
(void) fprintf( logFile, "%5d %10.5f %10.5f %10.5f %14.7e %14.7e %14.7e %14.7e %14.7e\n", atomI,
atomicRadii[atomI], scaledRadiusFactor[atomI], partialCharges[atomI], bornRadii[atomI], obcChain[atomI],
atomCoordinates[atomI][0], atomCoordinates[atomI][1], atomCoordinates[atomI][2] );
}
(void) fclose( logFile );
}
#endif
// set energy/forces to zero
RealOpenMM obcEnergy = zero;
const unsigned int arraySzInBytes = sizeof( RealOpenMM )*numberOfAtoms;
RealOpenMM** forces = (RealOpenMM**) malloc( sizeof( RealOpenMM* )*numberOfAtoms );
RealOpenMM* block = (RealOpenMM*) malloc( sizeof( RealOpenMM )*numberOfAtoms*3 );
memset( block, 0, sizeof( RealOpenMM )*numberOfAtoms*3 );
RealOpenMM* blockPtr = block;
for( int ii = 0; ii < numberOfAtoms; ii++ ){
forces[ii] = blockPtr;
blockPtr += 3;
}
RealOpenMM* bornForces = getBornForce();
memset( bornForces, 0, arraySzInBytes );
// ---------------------------------------------------------------------------------------
// N*( 8 + pow) ACE
// compute the nonpolar solvation via ACE approximation
if( includeAceApproximation() ){
computeAceNonPolarForce( obcSoftcoreParameters, bornRadii, &obcEnergy, bornForces );
}
// ---------------------------------------------------------------------------------------
// first main loop
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
RealOpenMM partialChargeI = preFactor*partialCharges[atomI];
for( int atomJ = atomI; atomJ < numberOfAtoms; atomJ++ ){
RealOpenMM deltaR[ReferenceForce::LastDeltaRIndex];
if (_obcSoftcoreParameters->getPeriodic())
ReferenceForce::getDeltaRPeriodic( atomCoordinates[atomI], atomCoordinates[atomJ], _obcSoftcoreParameters->getPeriodicBox(), deltaR );
else
ReferenceForce::getDeltaR( atomCoordinates[atomI], atomCoordinates[atomJ], deltaR );
if (_obcSoftcoreParameters->getUseCutoff() && deltaR[ReferenceForce::RIndex] > _obcSoftcoreParameters->getCutoffDistance())
continue;
RealOpenMM r2 = deltaR[ReferenceForce::R2Index];
RealOpenMM deltaX = deltaR[ReferenceForce::XIndex];
RealOpenMM deltaY = deltaR[ReferenceForce::YIndex];
RealOpenMM deltaZ = deltaR[ReferenceForce::ZIndex];
// 3 FLOP
RealOpenMM alpha2_ij = bornRadii[atomI]*bornRadii[atomJ];
RealOpenMM D_ij = r2/(four*alpha2_ij);
// exp + 2 + sqrt FLOP
RealOpenMM expTerm = EXP( -D_ij );
RealOpenMM denominator2 = r2 + alpha2_ij*expTerm;
RealOpenMM denominator = SQRT( denominator2 );
// 6 FLOP
RealOpenMM Gpol = (partialChargeI*partialCharges[atomJ])/denominator;
RealOpenMM dGpol_dr = -Gpol*( one - fourth*expTerm )/denominator2;
// 5 FLOP
RealOpenMM dGpol_dalpha2_ij = -half*Gpol*expTerm*( one + D_ij )/denominator2;
// 11 FLOP
if( atomI != atomJ ){
bornForces[atomJ] += dGpol_dalpha2_ij*bornRadii[atomI];
deltaX *= dGpol_dr;
deltaY *= dGpol_dr;
deltaZ *= dGpol_dr;
forces[atomI][0] += deltaX;
forces[atomI][1] += deltaY;
forces[atomI][2] += deltaZ;
forces[atomJ][0] -= deltaX;
forces[atomJ][1] -= deltaY;
forces[atomJ][2] -= deltaZ;
} else {
Gpol *= half;
}
// 3 FLOP
obcEnergy += Gpol;
bornForces[atomI] += dGpol_dalpha2_ij*bornRadii[atomJ];
}
}
//obcEnergy *= getEnergyConversionFactor();
// ---------------------------------------------------------------------------------------
// second main loop
// initialize Born radii & ObcChain temp arrays -- contain values
// used in next iteration
RealOpenMM* bornRadiiTemp = getBornRadiiTemp();
memset( bornRadiiTemp, 0, arraySzInBytes );
RealOpenMM* obcChainTemp = getObcChainTemp();
memset( obcChainTemp, 0, arraySzInBytes );
RealOpenMM* obcChain = getObcChain();
const RealOpenMM* atomicRadii = obcSoftcoreParameters->getAtomicRadii();
const RealOpenMM alphaObc = obcSoftcoreParameters->getAlphaObc();
const RealOpenMM betaObc = obcSoftcoreParameters->getBetaObc();
const RealOpenMM gammaObc = obcSoftcoreParameters->getGammaObc();
const RealOpenMM* scaledRadiusFactor = obcSoftcoreParameters->getScaledRadiusFactors();
// compute factor that depends only on the outer loop index
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
bornForces[atomI] *= bornRadii[atomI]*bornRadii[atomI]*obcChain[atomI];
}
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
// radius w/ dielectric offset applied
RealOpenMM radiusI = atomicRadii[atomI];
RealOpenMM offsetRadiusI = radiusI - dielectricOffset;
// used to compute Born radius for next iteration
RealOpenMM bornSum = zero;
for( int atomJ = 0; atomJ < numberOfAtoms; atomJ++ ){
if( atomJ != atomI ){
RealOpenMM deltaR[ReferenceForce::LastDeltaRIndex];
if (_obcSoftcoreParameters->getPeriodic())
ReferenceForce::getDeltaRPeriodic( atomCoordinates[atomI], atomCoordinates[atomJ], _obcSoftcoreParameters->getPeriodicBox(), deltaR );
else
ReferenceForce::getDeltaR( atomCoordinates[atomI], atomCoordinates[atomJ], deltaR );
if (_obcSoftcoreParameters->getUseCutoff() && deltaR[ReferenceForce::RIndex] > _obcSoftcoreParameters->getCutoffDistance())
continue;
RealOpenMM deltaX = deltaR[ReferenceForce::XIndex];
RealOpenMM deltaY = deltaR[ReferenceForce::YIndex];
RealOpenMM deltaZ = deltaR[ReferenceForce::ZIndex];
RealOpenMM r = deltaR[ReferenceForce::RIndex];
// radius w/ dielectric offset applied
RealOpenMM offsetRadiusJ = atomicRadii[atomJ] - dielectricOffset;
RealOpenMM scaledRadiusJ = offsetRadiusJ*scaledRadiusFactor[atomJ];
RealOpenMM scaledRadiusJ2 = scaledRadiusJ*scaledRadiusJ;
RealOpenMM rScaledRadiusJ = r + scaledRadiusJ;
// dL/dr & dU/dr are zero (this can be shown analytically)
// removed from calculation
if( offsetRadiusI < rScaledRadiusJ ){
RealOpenMM l_ij = offsetRadiusI > FABS( r - scaledRadiusJ ) ? offsetRadiusI : FABS( r - scaledRadiusJ );
l_ij = one/l_ij;
RealOpenMM u_ij = one/rScaledRadiusJ;
RealOpenMM l_ij2 = l_ij*l_ij;
RealOpenMM u_ij2 = u_ij*u_ij;
RealOpenMM rInverse = one/r;
RealOpenMM r2Inverse = rInverse*rInverse;
RealOpenMM t3 = eighth*(one + scaledRadiusJ2*r2Inverse)*(l_ij2 - u_ij2) + fourth*LN( u_ij/l_ij )*r2Inverse;
RealOpenMM de = bornForces[atomI]*t3*rInverse;
deltaX *= de;
deltaY *= de;
deltaZ *= de;
forces[atomI][0] -= deltaX;
forces[atomI][1] -= deltaY;
forces[atomI][2] -= deltaZ;
forces[atomJ][0] += deltaX;
forces[atomJ][1] += deltaY;
forces[atomJ][2] += deltaZ;
// Born radius term
RealOpenMM term = l_ij - u_ij + fourth*r*(u_ij2 - l_ij2) + (half*rInverse)*LN(u_ij/l_ij) +
(fourth*scaledRadiusJ*scaledRadiusJ*rInverse)*(l_ij2-u_ij2);
if( offsetRadiusI < (scaledRadiusJ - r) ){
term += two*( (one/offsetRadiusI) - l_ij);
}
bornSum += term;
}
}
}
// OBC-specific code (Eqs. 6-8 in paper)
bornSum *= half*offsetRadiusI;
RealOpenMM sum2 = bornSum*bornSum;
RealOpenMM sum3 = bornSum*sum2;
RealOpenMM tanhSum = TANH( alphaObc*bornSum - betaObc*sum2 + gammaObc*sum3 );
bornRadiiTemp[atomI] = one/( one/offsetRadiusI - tanhSum/radiusI );
obcChainTemp[atomI] = offsetRadiusI*( alphaObc - two*betaObc*bornSum + three*gammaObc*sum2 );
obcChainTemp[atomI] = (one - tanhSum*tanhSum)*obcChainTemp[atomI]/radiusI;
}
// cal to Joule conversion
RealOpenMM conversion = (RealOpenMM)0.4184;
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
inputForces[atomI][0] += conversion*forces[atomI][0];
inputForces[atomI][1] += conversion*forces[atomI][1];
inputForces[atomI][2] += conversion*forces[atomI][2];
}
setEnergy( obcEnergy*conversion );
#if 1
{
RealOpenMM* atomicRadii = obcSoftcoreParameters->getAtomicRadii();
const RealOpenMM* scaledRadiusFactor = obcSoftcoreParameters->getScaledRadiusFactors();
RealOpenMM* obcChain = getObcChain();
//FILE* logFile = fopen( "bornParameters", "w" );
FILE* logFile = stderr;
(void) fprintf( logFile, "%5d dielOff=%.4e rad::hct::q::bR::Chain::bF::f::coords\n", numberOfAtoms, dielectricOffset );
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
(void) fprintf( logFile, "%5d %10.5f %10.5f q=%10.5f b[%14.7e %14.7e %14.7e] f[%14.7e %14.7e %14.7e] x[%14.7e %14.7e %14.7e]\n", atomI,
atomicRadii[atomI], scaledRadiusFactor[atomI], partialCharges[atomI], bornRadii[atomI], obcChain[atomI],
conversion*bornForces[atomI],
conversion*forces[atomI][0], conversion*forces[atomI][1], conversion*forces[atomI][2],
atomCoordinates[atomI][0], atomCoordinates[atomI][1], atomCoordinates[atomI][2] );
}
if( logFile != stderr || logFile != stdout ){
(void) fclose( logFile );
}
}
#endif
// copy new Born radii and obcChain values into permanent array
memcpy( bornRadii, bornRadiiTemp, arraySzInBytes );
memcpy( obcChain, obcChainTemp, arraySzInBytes );
free( (char*) block );
free( (char*) forces );
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get string w/ state
@param title title (optional)
@return string containing state
--------------------------------------------------------------------------------------- */
std::string CpuObcSoftcore::getStateString( const char* title ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::getStateString";
// ---------------------------------------------------------------------------------------
std::stringstream message;
message << CpuImplicitSolvent::getStateString( title );
return message.str();
}
/**---------------------------------------------------------------------------------------
Write Born energy and forces (Simbios)
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@param forces forces
@param resultsFileName output file name
@return SimTKOpenMMCommon::DefaultReturn unless
file cannot be opened
in which case return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
int CpuObcSoftcore::writeBornEnergyForces( RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces,
const std::string& resultsFileName ) const {
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nCpuObcSoftcore::writeBornEnergyForces";
// ---------------------------------------------------------------------------------------
ImplicitSolventParameters* implicitSolventParameters = getImplicitSolventParameters();
const ObcSoftcoreParameters* obcSoftcoreParameters = static_cast<const ObcSoftcoreParameters*>(implicitSolventParameters);
int numberOfAtoms = obcSoftcoreParameters->getNumberOfAtoms();
const RealOpenMM* atomicRadii = obcSoftcoreParameters->getAtomicRadii();
const RealOpenMM* bornRadii = getBornRadiiConst();
const RealOpenMM* scaledRadii = obcSoftcoreParameters->getScaledRadiusFactors();
const RealOpenMM* obcChain = getObcChainConst();
const RealOpenMM energy = getEnergy();
// ---------------------------------------------------------------------------------------
// open file -- return if unsuccessful
FILE* implicitSolventResultsFile = NULL;
#ifdef _MSC_VER
fopen_s( &implicitSolventResultsFile, resultsFileName.c_str(), "w" );
#else
implicitSolventResultsFile = fopen( resultsFileName.c_str(), "w" );
#endif
// diganostics
std::stringstream message;
message << methodName;
if( implicitSolventResultsFile != NULL ){
std::stringstream message;
message << methodName;
message << " Opened file=<" << resultsFileName << ">.";
SimTKOpenMMLog::printMessage( message );
} else {
std::stringstream message;
message << methodName;
message << " could not open file=<" << resultsFileName << "> -- abort output.";
SimTKOpenMMLog::printMessage( message );
return SimTKOpenMMCommon::ErrorReturn;
}
// header
(void) fprintf( implicitSolventResultsFile, "# %d atoms E=%.7e format: coords(3) bornRadii(input) q atomicRadii scaleFactors forces obcChain\n",
numberOfAtoms, energy );
RealOpenMM forceConversion = (RealOpenMM) 1.0;
RealOpenMM lengthConversion = (RealOpenMM) 1.0;
// output
if( forces != NULL && atomCoordinates != NULL && partialCharges != NULL && atomicRadii != NULL ){
for( int ii = 0; ii < numberOfAtoms; ii++ ){
(void) fprintf( implicitSolventResultsFile, "%.7e %.7e %.7e %.7e %.5f %.5f %.5f %.7e %.7e %.7e %.7e\n",
lengthConversion*atomCoordinates[ii][0],
lengthConversion*atomCoordinates[ii][1],
lengthConversion*atomCoordinates[ii][2],
(bornRadii != NULL ? lengthConversion*bornRadii[ii] : 0.0),
partialCharges[ii], lengthConversion*atomicRadii[ii], scaledRadii[ii],
forceConversion*forces[ii][0],
forceConversion*forces[ii][1],
forceConversion*forces[ii][2],
forceConversion*obcChain[ii]
);
}
}
(void) fclose( implicitSolventResultsFile );
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Write results from first loop
@param numberOfAtoms number of atoms
@param forces forces
@param bornForce Born force prefactor
@param outputFileName output file name
@return SimTKOpenMMCommon::DefaultReturn unless
file cannot be opened
in which case return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
int CpuObcSoftcore::writeForceLoop1( int numberOfAtoms, RealOpenMM** forces, const RealOpenMM* bornForce,
const std::string& outputFileName ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObcSoftcore::writeForceLoop1";
// ---------------------------------------------------------------------------------------
int chunkSize;
if( bornForce ){
chunkSize = 3;
} else {
chunkSize = 4;
}
StringVector lineVector;
std::stringstream header;
lineVector.push_back( "# bornF F" );
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
std::stringstream line;
line << (atomI+1) << " ";
SimTKOpenMMUtilities::formatRealStringStream( line, forces[atomI], chunkSize );
if( bornForce ){
line << " " << bornForce[atomI];
}
lineVector.push_back( line.str() );
}
return SimTKOpenMMUtilities::writeFile( lineVector, outputFileName );
}
/**---------------------------------------------------------------------------------------
Write results
@param numberOfAtoms number of atoms
@param chunkSizes vector of chunk sizes for realRealOpenMMVector
@param realRealOpenMMVector vector of RealOpenMM**
@param realVector vector of RealOpenMM*
@param outputFileName output file name
@return SimTKOpenMMCommon::DefaultReturn unless
file cannot be opened
in which case return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
int CpuObcSoftcore::writeForceLoop( int numberOfAtoms, const IntVector& chunkSizes,
const RealOpenMMPtrPtrVector& realRealOpenMMVector,
const RealOpenMMPtrVector& realVector,
const std::string& outputFileName ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObcSoftcore::writeForceLoop";
static const int maxChunks = 10;
int chunks[maxChunks];
// ---------------------------------------------------------------------------------------
for( int ii = 0; ii < (int) chunkSizes.size(); ii++ ){
chunks[ii] = chunkSizes[ii];
}
for( int ii = (int) chunkSizes.size(); ii < maxChunks; ii++ ){
chunks[ii] = 3;
}
StringVector lineVector;
std::stringstream header;
// lineVector.push_back( "# " );
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
std::stringstream line;
char buffer[128];
(void) sprintf( buffer, "%4d ", atomI );
line << buffer;
int index = 0;
for( RealOpenMMPtrPtrVectorCI ii = realRealOpenMMVector.begin(); ii != realRealOpenMMVector.end(); ii++ ){
RealOpenMM** forces = *ii;
(void) sprintf( buffer, "%11.5f %11.5f %11.5f ", forces[atomI][0], forces[atomI][1], forces[atomI][2] );
line << buffer;
// SimTKOpenMMUtilities::formatRealStringStream( line, forces[atomI], chunks[index++] );
// line << " ";
}
for( RealOpenMMPtrVectorCI ii = realVector.begin(); ii != realVector.end(); ii++ ){
RealOpenMM* array = *ii;
(void) sprintf( buffer, "%11.5f ", array[atomI] );
line << buffer;
}
lineVector.push_back( line.str() );
}
return SimTKOpenMMUtilities::writeFile( lineVector, outputFileName );
}
/**---------------------------------------------------------------------------------------
Get Obc Born energy and forces -- used debugging
@param bornRadii Born radii -- optional; if NULL, then ObcSoftcoreParameters
entry is used
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@param forces forces
@return SimTKOpenMMCommon::DefaultReturn;
The array bornRadii is also updated and the obcEnergy
--------------------------------------------------------------------------------------- */
int CpuObcSoftcore::computeBornEnergyForcesPrint( RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObcSoftcore::computeBornEnergyForcesPrint";
static const RealOpenMM zero = (RealOpenMM) 0.0;
static const RealOpenMM one = (RealOpenMM) 1.0;
static const RealOpenMM two = (RealOpenMM) 2.0;
static const RealOpenMM three = (RealOpenMM) 3.0;
static const RealOpenMM four = (RealOpenMM) 4.0;
static const RealOpenMM half = (RealOpenMM) 0.5;
static const RealOpenMM fourth = (RealOpenMM) 0.25;
static const RealOpenMM eighth = (RealOpenMM) 0.125;
// ---------------------------------------------------------------------------------------
const ObcSoftcoreParameters* obcSoftcoreParameters = getObcSoftcoreParameters();
const int numberOfAtoms = obcSoftcoreParameters->getNumberOfAtoms();
if( bornRadii == NULL ){
bornRadii = getBornRadii();
}
// suppress warning about fopen in Visual Studio
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4996)
#endif
FILE* logFile = NULL;
//FILE* logFile = SimTKOpenMMLog::getSimTKOpenMMLogFile( );
//FILE* logFile = fopen( "bF", "w" );
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
// ---------------------------------------------------------------------------------------
// constants
const RealOpenMM preFactor = obcSoftcoreParameters->getPreFactor();
const RealOpenMM dielectricOffset = obcSoftcoreParameters->getDielectricOffset();
// ---------------------------------------------------------------------------------------
// set energy/forces to zero
RealOpenMM obcEnergy = zero;
const unsigned int arraySzInBytes = sizeof( RealOpenMM )*numberOfAtoms;
for( int ii = 0; ii < numberOfAtoms; ii++ ){
memset( forces[ii], 0, 3*sizeof( RealOpenMM ) );
}
RealOpenMM* bornForces = getBornForce();
memset( bornForces, 0, arraySzInBytes );
// ---------------------------------------------------------------------------------------
// N*( 8 + pow) ACE
// compute the nonpolar solvation via ACE approximation
if( includeAceApproximation() ){
computeAceNonPolarForce( obcSoftcoreParameters, bornRadii, &obcEnergy, bornForces );
if( logFile ){
(void) fprintf( logFile, "\nACE E=%.5e\n", obcEnergy );
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
(void) fprintf( logFile, " %d bR=%.6e bF=%.6e\n", atomI, bornRadii[atomI], bornForces[atomI] );
}
}
}
// ---------------------------------------------------------------------------------------
// first main loop
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
RealOpenMM partialChargeI = preFactor*partialCharges[atomI];
for( int atomJ = atomI; atomJ < numberOfAtoms; atomJ++ ){
RealOpenMM deltaR[ReferenceForce::LastDeltaRIndex];
if (_obcSoftcoreParameters->getPeriodic())
ReferenceForce::getDeltaRPeriodic( atomCoordinates[atomI], atomCoordinates[atomJ], _obcSoftcoreParameters->getPeriodicBox(), deltaR );
else
ReferenceForce::getDeltaR( atomCoordinates[atomI], atomCoordinates[atomJ], deltaR );
if (_obcSoftcoreParameters->getUseCutoff() && deltaR[ReferenceForce::RIndex] > _obcSoftcoreParameters->getCutoffDistance())
continue;
RealOpenMM r2 = deltaR[ReferenceForce::R2Index];
RealOpenMM deltaX = deltaR[ReferenceForce::XIndex];
RealOpenMM deltaY = deltaR[ReferenceForce::YIndex];
RealOpenMM deltaZ = deltaR[ReferenceForce::ZIndex];
// 3 FLOP
RealOpenMM alpha2_ij = bornRadii[atomI]*bornRadii[atomJ];
RealOpenMM D_ij = r2/(four*alpha2_ij);
// exp + 2 + sqrt FLOP
RealOpenMM expTerm = EXP( -D_ij );
RealOpenMM denominator2 = r2 + alpha2_ij*expTerm;
RealOpenMM denominator = SQRT( denominator2 );
// 6 FLOP
RealOpenMM Gpol = (partialChargeI*partialCharges[atomJ])/denominator;
// dGpol/dr = -1/2*(Gpol/denominator2)*(2r - r/2*exp() )
RealOpenMM dGpol_dr = -Gpol*( one - fourth*expTerm )/denominator2;
// 5 FLOP
RealOpenMM dGpol_dalpha2_ij = -half*Gpol*expTerm*( one + D_ij )/denominator2;
// 11 FLOP
if( atomI != atomJ ){
bornForces[atomJ] += dGpol_dalpha2_ij*bornRadii[atomI];
deltaX *= dGpol_dr;
deltaY *= dGpol_dr;
deltaZ *= dGpol_dr;
forces[atomI][0] += deltaX;
forces[atomI][1] += deltaY;
forces[atomI][2] += deltaZ;
forces[atomJ][0] -= deltaX;
forces[atomJ][1] -= deltaY;
forces[atomJ][2] -= deltaZ;
} else {
Gpol *= half;
}
// 3 FLOP
obcEnergy += Gpol;
bornForces[atomI] += dGpol_dalpha2_ij*bornRadii[atomJ];
//if( logFile && (atomI == -1 || atomJ == -1) ){
// (void) fprintf( logFile, "\nWWX %d %d F[%.6e %.6e %.6e] bF=[%.6e %.6e] Gpl[%.6e %.6e %.6e] rb[%6.4f %7.4f] rs[%6.4f %7.4f] ",
// atomI, atomJ,
// forces[atomI][0], forces[atomI][1], forces[atomI][2],
// bornForces[atomI], bornForces[atomJ],
// Gpol,dGpol_dr,dGpol_dalpha2_ij,
// bornRadii[atomI],bornRadii[atomJ],atomicRadii[atomI],atomicRadii[atomJ] );
//
// (void) fprintf( logFile, "\nWWX %d %d %.1f r2=%.4f q=%.2f bF=[%.6e %.6e] Gpl[%.6e %.6e %.6e] rb[%.5f %.5f] add[%.6e %.6e] ",
// atomI, atomJ, preFactor, r2, partialCharges[atomJ],
// bornForces[atomI], bornForces[atomJ],
// Gpol,dGpol_dr,dGpol_dalpha2_ij,
// bornRadii[atomI], bornRadii[atomJ],
// dGpol_dalpha2_ij*bornRadii[atomJ], dGpol_dalpha2_ij*bornRadii[atomI] );
//}
}
}
if( logFile ){
(void) fprintf( logFile, "\nWXX bF & F E=%.8e preFactor=%.5f", obcEnergy, preFactor );
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
(void) fprintf( logFile, "\nWXX %d q=%.4f bR=%.5e bF=%.3f F[%.6e %.6e %.6e] ",
atomI, partialCharges[atomI], bornRadii[atomI], bornForces[atomI], forces[atomI][0], forces[atomI][1], forces[atomI][2] );
}
}
if( 1 ){
std::string outputFileName = "Loop1Cpu.txt";
CpuObcSoftcore::writeForceLoop1( numberOfAtoms, forces, bornForces, outputFileName );
/*
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
forces[atomI][0] = forces[atomI][1] = forces[atomI][2] = (RealOpenMM) 0.0;
}
*/
}
// ---------------------------------------------------------------------------------------
// second main loop
// initialize Born radii & ObcChain temp arrays -- contain values
// used in next iteration
RealOpenMM* bornRadiiTemp = getBornRadiiTemp();
memset( bornRadiiTemp, 0, arraySzInBytes );
RealOpenMM* obcChainTemp = getObcChainTemp();
memset( obcChainTemp, 0, arraySzInBytes );
RealOpenMM* obcChain = getObcChain();
const RealOpenMM* atomicRadii = obcSoftcoreParameters->getAtomicRadii();
const RealOpenMM alphaObc = obcSoftcoreParameters->getAlphaObc();
const RealOpenMM betaObc = obcSoftcoreParameters->getBetaObc();
const RealOpenMM gammaObc = obcSoftcoreParameters->getGammaObc();
const RealOpenMM* scaledRadiusFactor = obcSoftcoreParameters->getScaledRadiusFactors();
// compute factor that depends only on the outer loop index
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
bornForces[atomI] *= bornRadii[atomI]*bornRadii[atomI]*obcChain[atomI];
}
if( 1 ){
std::string outputFileName = "PostLoop1Cpu.txt";
IntVector chunkVector;
chunkVector.push_back( 3 );
RealOpenMMPtrPtrVector realPtrPtrVector;
realPtrPtrVector.push_back( forces );
RealOpenMMPtrVector realPtrVector;
realPtrVector.push_back( bornRadii );
realPtrVector.push_back( bornForces );
realPtrVector.push_back( obcChain );
CpuObcSoftcore::writeForceLoop( numberOfAtoms, chunkVector, realPtrPtrVector, realPtrVector, outputFileName );
}
RealOpenMM* bornSumArray = (RealOpenMM*) malloc( sizeof( RealOpenMM )*numberOfAtoms );
memset( bornSumArray, 0, sizeof( RealOpenMM )*numberOfAtoms );
/*
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
forces[atomI][0] = 0.0;
forces[atomI][1] = 0.0;
forces[atomI][2] = 0.0;
} */
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
// radius w/ dielectric offset applied
RealOpenMM radiusI = atomicRadii[atomI];
RealOpenMM offsetRadiusI = radiusI - dielectricOffset;
// used to compute Born radius for next iteration
RealOpenMM bornSum = zero;
for( int atomJ = 0; atomJ < numberOfAtoms; atomJ++ ){
if( atomJ != atomI ){
RealOpenMM deltaR[ReferenceForce::LastDeltaRIndex];
if (_obcSoftcoreParameters->getPeriodic())
ReferenceForce::getDeltaRPeriodic( atomCoordinates[atomI], atomCoordinates[atomJ], _obcSoftcoreParameters->getPeriodicBox(), deltaR );
else
ReferenceForce::getDeltaR( atomCoordinates[atomI], atomCoordinates[atomJ], deltaR );
if (_obcSoftcoreParameters->getUseCutoff() && deltaR[ReferenceForce::RIndex] > _obcSoftcoreParameters->getCutoffDistance())
continue;
RealOpenMM deltaX = deltaR[ReferenceForce::XIndex];
RealOpenMM deltaY = deltaR[ReferenceForce::YIndex];
RealOpenMM deltaZ = deltaR[ReferenceForce::ZIndex];
RealOpenMM r = deltaR[ReferenceForce::RIndex];
// radius w/ dielectric offset applied
RealOpenMM radiusJ = atomicRadii[atomJ] - dielectricOffset;
RealOpenMM scaledRadiusJ = radiusJ*scaledRadiusFactor[atomJ];
RealOpenMM scaledRadiusJ2 = scaledRadiusJ*scaledRadiusJ;
RealOpenMM rScaledRadiusJ = r + scaledRadiusJ;
// L_ij != 1 && U_ij != 1
// dL/dr & dU/dr are zero (this can be shown analytically)
// removed from calculation
if( offsetRadiusI < rScaledRadiusJ ){
RealOpenMM l_ij = offsetRadiusI > FABS( r - scaledRadiusJ ) ? offsetRadiusI : FABS( r - scaledRadiusJ );
l_ij = one/l_ij;
RealOpenMM l_ij2 = l_ij*l_ij;
RealOpenMM u_ij = one/rScaledRadiusJ;
RealOpenMM u_ij2 = u_ij*u_ij;
RealOpenMM rInverse = one/r;
RealOpenMM r2Inverse = rInverse*rInverse;
RealOpenMM logRatio = LN( u_ij/l_ij );
RealOpenMM t3 = eighth*(one + scaledRadiusJ2*r2Inverse)*(l_ij2 - u_ij2) + fourth*logRatio*r2Inverse;
RealOpenMM de = bornForces[atomI]*t3*rInverse;
deltaX *= de;
deltaY *= de;
deltaZ *= de;
forces[atomI][0] -= deltaX;
forces[atomI][1] -= deltaY;
forces[atomI][2] -= deltaZ;
forces[atomJ][0] += deltaX;
forces[atomJ][1] += deltaY;
forces[atomJ][2] += deltaZ;
// Born radius term
RealOpenMM term = l_ij - u_ij + fourth*r*(u_ij2 - l_ij2) + (half*rInverse)*logRatio + (fourth*scaledRadiusJ*scaledRadiusJ*rInverse)*(l_ij2-u_ij2);
if( offsetRadiusI < (scaledRadiusJ - r) ){
term += two*( (one/offsetRadiusI) - l_ij);
}
bornSum += term;
if( atomI == -1 || atomJ == -1 ){
(void) fprintf( logFile, "\nXXY %d %d de=%.6e bF[%.6e %6e] t3=%.6e r=%.6e trm=%.6e bSm=%.6e f[%.6e %.6e %.6e]",
atomI, atomJ, de,
bornForces[atomI], obcChain[atomI],
t3, r, term, bornSum, forces[atomI][0], forces[atomI][1], forces[atomI][2] );
}
}
}
}
bornSumArray[atomI] = bornSum;
// OBC-specific code (Eqs. 6-8 in paper)
bornSum *= half*offsetRadiusI;
RealOpenMM sum2 = bornSum*bornSum;
RealOpenMM sum3 = bornSum*sum2;
RealOpenMM tanhSum = TANH( alphaObc*bornSum - betaObc*sum2 + gammaObc*sum3 );
bornRadiiTemp[atomI] = one/( one/offsetRadiusI - tanhSum/radiusI);
obcChainTemp[atomI] = offsetRadiusI*( alphaObc - two*betaObc*bornSum + three*gammaObc*sum2 );
obcChainTemp[atomI] = (one - tanhSum*tanhSum)*obcChainTemp[atomI]/radiusI;
if( logFile && atomI >= 0 ){
(void) fprintf( logFile, "\nXXX %d bSum[%.6e %.6e %.6e] bRt=[%.6e %6e] obc=%.6e rI=[%.5f %.5f]",
atomI, bornSumArray[atomI], bornSum, tanhSum, bornRadii[atomI], bornRadiiTemp[atomI], obcChainTemp[atomI], radiusI, offsetRadiusI );
}
}
RealOpenMM conversion = (RealOpenMM)0.4184;
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
forces[atomI][0] *= conversion;
forces[atomI][1] *= conversion;
forces[atomI][2] *= conversion;
}
setEnergy( obcEnergy*conversion );
if( 1 ){
std::string outputFileName = "Loop2Cpu.txt";
IntVector chunkVector;
chunkVector.push_back( 3 );
RealOpenMMPtrPtrVector realPtrPtrVector;
realPtrPtrVector.push_back( forces );
RealOpenMMPtrVector realPtrVector;
realPtrVector.push_back( bornSumArray );
// realPtrVector.push_back( bornRadiiTemp );
// realPtrVector.push_back( obcChainTemp );
CpuObcSoftcore::writeForceLoop( numberOfAtoms, chunkVector, realPtrPtrVector, realPtrVector, outputFileName );
}
if( bornSumArray ){
free( (char*) bornSumArray );
}
// 6 FLOP
/*
RealOpenMM forceFactor = getForceConversionFactor();
RealOpenMM constantFactor = 1.0f/electricConstant;
if( fabs(forceFactor - 1.0f) > 1.0e-04 ){
constantFactor *= forceFactor;
for( int ii = 0; ii < numberOfAtoms; ii++ ){
forces[ii][0] *= forceFactor;
forces[ii][1] *= forceFactor;
forces[ii][2] *= forceFactor;
}
} */
// copy new Born radii and obcChain values into permanent array
//(void) fprintf( logFile, "\nBorn radii not being updated!!!!" );
memcpy( bornRadii, bornRadiiTemp, arraySzInBytes );
memcpy( obcChain, obcChainTemp, arraySzInBytes );
if( logFile ){
(void) fclose( logFile );
}
return SimTKOpenMMCommon::DefaultReturn;
}
/* Portions copyright (c) 2006 Stanford University and Simbios.
* Contributors: Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __CpuObcSoftcore_H__
#define __CpuObcSoftcore_H__
#include "ObcSoftcoreParameters.h"
#include "gbsa/CpuImplicitSolvent.h"
// ---------------------------------------------------------------------------------------
class CpuObcSoftcore : public CpuImplicitSolvent {
private:
// GBSA/OBC parameters
ObcSoftcoreParameters* _obcSoftcoreParameters;
// arrays containing OBC chain derivative
RealOpenMM* _obcChain;
RealOpenMM* _obcChainTemp;
// initialize data members (more than
// one constructor, so centralize intialization here)
void _initializeObcDataMembers( void );
public:
/**---------------------------------------------------------------------------------------
Constructor
@param implicitSolventParameters ImplicitSolventParameters reference
@return CpuImplicitSolvent object
--------------------------------------------------------------------------------------- */
CpuObcSoftcore( ImplicitSolventParameters* obcSoftcoreParameters );
/**---------------------------------------------------------------------------------------
Destructor
--------------------------------------------------------------------------------------- */
~CpuObcSoftcore( );
/**---------------------------------------------------------------------------------------
Return ObcSoftcoreParameters
@return ObcSoftcoreParameters
--------------------------------------------------------------------------------------- */
ObcSoftcoreParameters* getObcSoftcoreParameters( void ) const;
/**---------------------------------------------------------------------------------------
Set ImplicitSolventParameters
@param ImplicitSolventParameters
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setObcSoftcoreParameters( ObcSoftcoreParameters* obcSoftcoreParameters );
/**---------------------------------------------------------------------------------------
Return OBC chain derivative: size = _implicitSolventParameters->getNumberOfAtoms()
On first call, memory for array is allocated if not set
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* getObcChain( void );
RealOpenMM* getObcChainConst( void ) const;
/**---------------------------------------------------------------------------------------
Return OBC chain temp work array of size=_implicitSolventParameters->getNumberOfAtoms()
On first call, memory for array is allocated if not set
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* getObcChainTemp( void );
/**---------------------------------------------------------------------------------------
Get Born radii based on OBC
@param atomCoordinates atomic coordinates
@param bornRadii output array of Born radii
@param obcChain output array of OBC chain derivative factors; if NULL,
then ignored
@return array of Born radii
--------------------------------------------------------------------------------------- */
int computeBornRadii( RealOpenMM** atomCoordinates, RealOpenMM* bornRadii,
RealOpenMM* obcChain = NULL );
/**---------------------------------------------------------------------------------------
Get nonpolar solvation force constribution via ACE approximation
@param obcSoftcoreParameters parameters
@param vdwRadii Vdw radii
@param bornRadii Born radii
@param energy energy (output): value is incremented from input value
@param forces forces: values are incremented from input values
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int computeAceNonPolarForce( const ObcSoftcoreParameters* obcSoftcoreParameters,
const RealOpenMM* bornRadii, RealOpenMM* energy,
RealOpenMM* forces ) const;
/**---------------------------------------------------------------------------------------
Get Born energy and forces based on OBC
@param bornRadii Born radii
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@param forces forces
@return force array
--------------------------------------------------------------------------------------- */
int computeBornEnergyForces( RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces );
int computeBornEnergyForcesPrint( RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces );
/**---------------------------------------------------------------------------------------
Get state
title title (optional)
@return state string
--------------------------------------------------------------------------------------- */
std::string getStateString( const char* title ) const;
/**---------------------------------------------------------------------------------------
Write Born energy and forces (Simbios)
@param atomCoordinates atomic coordinates
@param partialCharges partial atom charges
@param forces force array
@param resultsFileName output file name
@return SimTKOpenMMCommon::DefaultReturn if file opened; else return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
int writeBornEnergyForces( RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces,
const std::string& resultsFileName ) const;
/**---------------------------------------------------------------------------------------
Write results from first loop
@param atomCoordinates atomic coordinates
@param RealOpenMM forces forces
@param outputFileName output file name
@return SimTKOpenMMCommon::DefaultReturn unless
file cannot be opened
in which case return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
static int writeForceLoop1( int numberOfAtoms, RealOpenMM** forces, const RealOpenMM* bornForce,
const std::string& outputFileName );
/**---------------------------------------------------------------------------------------
Write results
@param numberOfAtoms number of atoms
@param chunkSizes vector of chunk sizes for realRealOpenMMVector
@param realRealOpenMMVector vector of RealOpenMM**
@param realVector vector of RealOpenMM*
@param outputFileName output file name
@return SimTKOpenMMCommon::DefaultReturn unless
file cannot be opened
in which case return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
static int writeForceLoop( int numberOfAtoms, const IntVector& chunkSizes,
const RealOpenMMPtrPtrVector& realRealOpenMMVector,
const RealOpenMMPtrVector& realVector,
const std::string& outputFileName );
};
// ---------------------------------------------------------------------------------------
#endif // __CpuObcSoftcore_H__
/* Portions copyright (c) 2006-2009 Stanford University and Simbios.
* Contributors: Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <math.h>
#include <sstream>
#include "GBVISoftcoreParameters.h"
#include "../SimTKUtilities/SimTKOpenMMCommon.h"
#include "../SimTKUtilities/SimTKOpenMMLog.h"
#include "../SimTKUtilities/SimTKOpenMMUtilities.h"
// #define UseGromacsMalloc 1
#ifdef UseGromacsMalloc
extern "C" {
#include "smalloc.h"
}
#endif
const std::string GBVISoftcoreParameters::ParameterFileName = std::string( "params.agb" );
/**---------------------------------------------------------------------------------------
GBVISoftcoreParameters:
Calculates for each atom
(1) the van der Waal radii
(2) volume
(3) fixed terms in Obc equation gPol
(4) list of atoms that should be excluded in calculating
force -- nonbonded atoms (1-2, and 1-3 atoms)
Implementation:
Slightly different sequence of calls when running on CPU vs GPU.
Difference arise because the CPU-side data arrays for the Brook
streams are allocated by the BrookStreamWrapper objects. These
arrays are then used by GBVISoftcoreParameters when initializing the
the values (vdwRadii, volume, ...) to be used in the calculation.
Cpu:
GBVISoftcoreParameters* gb_VIParameters = new GBVISoftcoreParameters( numberOfAtoms, log );
gb_VIParameters->initializeParameters( top );
Gpu:
gb_VIParameters = new GBVISoftcoreParameters( gpu->natoms, log );
// set arrays for cpu using stream data field;
// initializeParameters() only allocates space for arrays if they are not set (==NULL)
// also set flag so that GBVISoftcoreParameters destructor does not free arrays
gb_VIParameters->setVdwRadii( getBrookStreamWrapperAtIndex( GpuObc::gb_VIVdwRadii )->getData() );
gb_VIParameters->setVolume( getBrookStreamWrapperAtIndex( GpuObc::gb_VIVolume )->getData() );
gb_VIParameters->setGPolFixed( getBrookStreamWrapperAtIndex( GpuObc::gb_VIGpolFixed )->getData() );
gb_VIParameters->setBornRadii( getBrookStreamWrapperAtIndex( GpuObc::gb_VIBornRadii )->getData() );
gb_VIParameters->setFreeArrays( false );
gb_VIParameters->initializeParameters( top );
Issues:
Tinker's atom radii are used.
The logic for mapping the Gromacs atom names to Tinker type may be incomplete;
only tested for generic proteins
see mapGmxAtomNameToTinkerAtomNumber()
--------------------------------------------------------------------------------------- */
/**---------------------------------------------------------------------------------------
GBVISoftcoreParameters constructor (Simbios)
@param numberOfAtoms number of atoms
--------------------------------------------------------------------------------------- */
GBVISoftcoreParameters::GBVISoftcoreParameters( int numberOfAtoms ) : ImplicitSolventParameters( numberOfAtoms ), cutoff(false), periodic(false) {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nGBVISoftcoreParameters::GBVISoftcoreParameters";
// ---------------------------------------------------------------------------------------
_ownScaledRadii = 0;
_scaledRadii = NULL;
_ownGammaParameters = 0;
_gammaParameters = NULL;
_ownBornRadiusScaleFactors = 0;
_bornRadiusScaleFactors = NULL;
_bornRadiusScalingSoftcoreMethod = NoScaling;
_quinticLowerLimitFactor = static_cast<RealOpenMM>(0.8);
setQuinticUpperBornRadiusLimit( static_cast<RealOpenMM>(5.0) );
}
/**---------------------------------------------------------------------------------------
GBVISoftcoreParameters destructor (Simbios)
--------------------------------------------------------------------------------------- */
GBVISoftcoreParameters::~GBVISoftcoreParameters( ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nGBVISoftcoreParameters::~GBVISoftcoreParameters";
// ---------------------------------------------------------------------------------------
// in GPU runs, arrays may be 'owned' by BrookStreamWrapper -- hence they should not
// be freed here, i.e., _freeArrays should be 'false'
#ifdef UseGromacsMalloc
/*
if( _freeArrays ){
if( _vdwRadii != NULL ){
save_free( "_vdwRadii", __FILE__, __LINE__, _vdwRadii );
}
} */
#else
if( _ownScaledRadii ){
delete[] _scaledRadii;
}
delete[] _gammaParameters;
delete[] _bornRadiusScaleFactors;
/*
if( getFreeArrays() ){
} */
#endif
}
/**---------------------------------------------------------------------------------------
Get the quintic spline lower limit factor
@return quintic spline lower limit factor
--------------------------------------------------------------------------------------- */
RealOpenMM GBVISoftcoreParameters::getQuinticLowerLimitFactor( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "GBVISoftcoreParameters::getQuinticLowerLimitFactor:";
// ---------------------------------------------------------------------------------------
return _quinticLowerLimitFactor;
}
/**---------------------------------------------------------------------------------------
Set the quintic spline lower limit factor
@param quintic spline lower limit factor
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setQuinticLowerLimitFactor( RealOpenMM quinticLowerLimitFactor ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "GBVISoftcoreParameters::setQuinticLowerLimitFactor:";
// ---------------------------------------------------------------------------------------
_quinticLowerLimitFactor = quinticLowerLimitFactor;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get the quintic spline upper limit
@return quintic spline upper limit
--------------------------------------------------------------------------------------- */
RealOpenMM GBVISoftcoreParameters::getQuinticUpperBornRadiusLimit( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "GBVISoftcoreParameters::getQuinticUpperBornRadiusLimit:";
// ---------------------------------------------------------------------------------------
return _quinticUpperBornRadiusLimit;
}
/**---------------------------------------------------------------------------------------
Set the quintic spline upper limit
@param quintic spline upper limit
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setQuinticUpperBornRadiusLimit( RealOpenMM quinticUpperBornRadiusLimit ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "GBVISoftcoreParameters::setQuinticUpperBornRadiusLimit:";
// ---------------------------------------------------------------------------------------
_quinticUpperBornRadiusLimit = quinticUpperBornRadiusLimit;
_quinticUpperSplineLimit = POW( _quinticUpperBornRadiusLimit, static_cast<RealOpenMM>(-3.0) );
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get the quintic upper spline limit
@return the quintic upper spline limit
--------------------------------------------------------------------------------------- */
float GBVISoftcoreParameters::getQuinticUpperSplineLimit( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "GBVISoftcoreParameters::getQuinticUpperSplineLimit:";
// ---------------------------------------------------------------------------------------
return _quinticUpperSplineLimit;
}
/**---------------------------------------------------------------------------------------
Get AtomicRadii array
@return array of atomic radii
--------------------------------------------------------------------------------------- */
RealOpenMM* GBVISoftcoreParameters::getAtomicRadii( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::getAtomicRadii:";
// ---------------------------------------------------------------------------------------
RealOpenMM* atomicRadii = ImplicitSolventParameters::getAtomicRadii();
return atomicRadii;
}
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii array of atomic radii
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setAtomicRadii( RealOpenMM* atomicRadii ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nGBVISoftcoreParameters::setAtomicRadii:";
// ---------------------------------------------------------------------------------------
return ImplicitSolventParameters::setAtomicRadii( atomicRadii );
}
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii vector of atomic radii
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setAtomicRadii( const RealOpenMMVector& atomicRadii ){
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nGBVISoftcoreParameters::setAtomicRadii:";
// ---------------------------------------------------------------------------------------
return ImplicitSolventParameters::setAtomicRadii( atomicRadii );
}
/**---------------------------------------------------------------------------------------
Return scaled radii
If not previously set, allocate space
@return array
--------------------------------------------------------------------------------------- */
const RealOpenMM* GBVISoftcoreParameters::getScaledRadii( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nGBVISoftcoreParameters::getScaledRadii";
// ---------------------------------------------------------------------------------------
if( _scaledRadii == NULL ){
GBVISoftcoreParameters* localThis = const_cast<GBVISoftcoreParameters* const>(this);
localThis->_scaledRadii = new RealOpenMM[getNumberOfAtoms()];
localThis->_ownScaledRadii = true;
memset( _scaledRadii, 0, sizeof( RealOpenMM )*getNumberOfAtoms() );
}
return _scaledRadii;
}
/**---------------------------------------------------------------------------------------
Set flag indicating whether scale factors array should be deleted
@param ownScaledRadii flag indicating whether scale factors
array should be deleted
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setOwnScaledRadii( int ownScaledRadii ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nGBVISoftcoreParameters::setOwnScaleFactors";
// ---------------------------------------------------------------------------------------
_ownScaledRadii = ownScaledRadii;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Set scaled radii
@param scaledRadii scaledRadii
@return SimTKOpenMMCommon::DefaultReturn always
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setScaledRadii( RealOpenMM* scaledRadii ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::setScaledRadii";
// ---------------------------------------------------------------------------------------
if( _ownScaledRadii && _scaledRadii != scaledRadii ){
delete[] _scaledRadii;
_ownScaledRadii = false;
}
_scaledRadii = scaledRadii;
return SimTKOpenMMCommon::DefaultReturn;
}
#if RealOpenMMType == 2
/**---------------------------------------------------------------------------------------
Set scaled radii
@param scaledRadii scaledRadii
@return SimTKOpenMMCommon::DefaultReturn always
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setScaledRadii( float* scaledRadii ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nGBVISoftcoreParameters::setScaledRadii";
// ---------------------------------------------------------------------------------------
if( _scaledRadii == NULL ){
_scaledRadii = new RealOpenMM[getNumberOfAtoms()];
_ownScaledRadii = true;
}
for( int ii = 0; ii < getNumberOfAtoms(); ii++ ){
_scaledRadii[ii] = (RealOpenMM) scaledRadii[ii];
}
return SimTKOpenMMCommon::DefaultReturn;
}
#endif
/**---------------------------------------------------------------------------------------
Set scaled radii
@param scaledRadii scaledRadii
@return SimTKOpenMMCommon::DefaultReturn always
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setScaledRadii( const RealOpenMMVector& scaledRadii ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::setScaledRadii";
// ---------------------------------------------------------------------------------------
if( _ownScaledRadii && _scaledRadii != NULL ){
delete[] _scaledRadii;
}
_ownScaledRadii = true;
_scaledRadii = new RealOpenMM[getNumberOfAtoms()];
for( int ii = 0; ii < (int) scaledRadii.size(); ii++ ){
_scaledRadii[ii] = scaledRadii[ii];
}
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Return gamma parameters
If not previously set, allocate space
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* GBVISoftcoreParameters::getGammaParameters( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nGBVISoftcoreParameters::getGammaParameters";
// ---------------------------------------------------------------------------------------
if( _gammaParameters == NULL ){
GBVISoftcoreParameters* localThis = const_cast<GBVISoftcoreParameters* const>(this);
localThis->_gammaParameters = new RealOpenMM[getNumberOfAtoms()];
localThis->_ownGammaParameters = true;
memset( _gammaParameters, 0, sizeof( RealOpenMM )*getNumberOfAtoms() );
}
return _gammaParameters;
}
/**---------------------------------------------------------------------------------------
Set flag indicating whether scale factors array should be deleted
@param ownGammaParameters flag indicating whether gamma parameter
array should be deleted
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setOwnGammaParameters( int ownGammaParameters ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nGBVISoftcoreParameters::setOwnScaleFactors";
// ---------------------------------------------------------------------------------------
_ownGammaParameters = ownGammaParameters;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Set gamma parameters
@param gammas gamma parameters
@return SimTKOpenMMCommon::DefaultReturn always
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setGammaParameters( RealOpenMM* gammas ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::setGammas";
// ---------------------------------------------------------------------------------------
if( _ownGammaParameters && _gammaParameters != gammas ){
delete[] _gammaParameters;
_ownGammaParameters = false;
}
_gammaParameters = gammas;
return SimTKOpenMMCommon::DefaultReturn;
}
#if RealOpenMMType == 2
/**---------------------------------------------------------------------------------------
Set gamma parameters
@param gammas gammas
@return SimTKOpenMMCommon::DefaultReturn always
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setGammaParameters( float* gammas ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nGBVISoftcoreParameters::setGammas";
// ---------------------------------------------------------------------------------------
if( _gammaParameters == NULL ){
_gammaParameters = new RealOpenMM[getNumberOfAtoms()];
_ownGammaParameters = true;
}
for( int ii = 0; ii < getNumberOfAtoms(); ii++ ){
_gammaParameters[ii] = (RealOpenMM) gammas[ii];
}
return SimTKOpenMMCommon::DefaultReturn;
}
#endif
/**---------------------------------------------------------------------------------------
Set gamma parameters
@param gammas gammas
@return SimTKOpenMMCommon::DefaultReturn always
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setGammaParameters( const RealOpenMMVector& gammas ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::setGammas";
// ---------------------------------------------------------------------------------------
if( _ownGammaParameters && _gammaParameters != NULL ){
delete[] _gammaParameters;
}
_ownGammaParameters = true;
_gammaParameters = new RealOpenMM[getNumberOfAtoms()];
for( int ii = 0; ii < (int) gammas.size(); ii++ ){
_gammaParameters[ii] = gammas[ii];
}
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Return BornRadiusScaleFactors
If not previously set, allocate space
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* GBVISoftcoreParameters::getBornRadiusScaleFactors( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nGBVISoftcoreParameters::getBornRadiusScaleFactors";
// ---------------------------------------------------------------------------------------
if( _bornRadiusScaleFactors == NULL ){
GBVISoftcoreParameters* localThis = const_cast<GBVISoftcoreParameters* const>(this);
localThis->_bornRadiusScaleFactors = new RealOpenMM[getNumberOfAtoms()];
localThis->_ownBornRadiusScaleFactors = true;
memset( _bornRadiusScaleFactors, 0, sizeof( RealOpenMM )*getNumberOfAtoms() );
}
return _bornRadiusScaleFactors;
}
/**---------------------------------------------------------------------------------------
Set flag indicating whether scale factors array should be deleted
@param ownBornRadiusScaleFactors flag indicating whether Born radius scale factors
array should be deleted
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setOwnBornRadiusScaleFactors( int ownBornRadiusScaleFactorsParameters ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nGBVISoftcoreParameters::setOwnScaleFactors";
// ---------------------------------------------------------------------------------------
_ownBornRadiusScaleFactors = ownBornRadiusScaleFactorsParameters;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Set BornRadiusScaleFactors
@param bornRadiusScaleFactors Born radius scale factors
@return SimTKOpenMMCommon::DefaultReturn always
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setBornRadiusScaleFactors( RealOpenMM* bornRadiusScaleFactors ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::setBornRadiusScaleFactors";
// ---------------------------------------------------------------------------------------
if( _ownBornRadiusScaleFactors && _bornRadiusScaleFactors != bornRadiusScaleFactors ){
delete[] _bornRadiusScaleFactors;
_ownBornRadiusScaleFactors = false;
}
_bornRadiusScaleFactors = bornRadiusScaleFactors;
return SimTKOpenMMCommon::DefaultReturn;
}
#if RealOpenMMType == 2
/**---------------------------------------------------------------------------------------
Set bornRadiusScaleFactors parameters
@param bornRadiusScaleFactorss bornRadiusScaleFactorss
@return SimTKOpenMMCommon::DefaultReturn always
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setBornRadiusScaleFactors( float* bornRadiusScaleFactorss ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nGBVISoftcoreParameters::setBornRadiusScaleFactors";
// ---------------------------------------------------------------------------------------
if( _bornRadiusScaleFactors == NULL ){
_bornRadiusScaleFactors = new RealOpenMM[getNumberOfAtoms()];
_ownBornRadiusScaleFactors = true;
}
for( int ii = 0; ii < getNumberOfAtoms(); ii++ ){
_bornRadiusScaleFactors[ii] = (RealOpenMM) bornRadiusScaleFactorss[ii];
}
return SimTKOpenMMCommon::DefaultReturn;
}
#endif
/**---------------------------------------------------------------------------------------
Set bornRadiusScaleFactors parameters
@param bornRadiusScaleFactors bornRadiusScaleFactors
@return SimTKOpenMMCommon::DefaultReturn always
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setBornRadiusScaleFactors( const RealOpenMMVector& bornRadiusScaleFactors ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::setBornRadiusScaleFactors";
// ---------------------------------------------------------------------------------------
if( _ownBornRadiusScaleFactors && _bornRadiusScaleFactors != NULL ){
delete[] _bornRadiusScaleFactors;
}
_ownBornRadiusScaleFactors = true;
_bornRadiusScaleFactors = new RealOpenMM[getNumberOfAtoms()];
for( int ii = 0; ii < (int) bornRadiusScaleFactors.size(); ii++ ){
_bornRadiusScaleFactors[ii] = bornRadiusScaleFactors[ii];
}
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get string w/ state
@param title title (optional)
@return string
--------------------------------------------------------------------------------------- */
std::string GBVISoftcoreParameters::getStateString( const char* title ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nGBVISoftcoreParameters::getStateString";
// ---------------------------------------------------------------------------------------
std::stringstream message;
message << ImplicitSolventParameters::getStateString( title );
std::string tab = getStringTab();
return message.str();
}
/**---------------------------------------------------------------------------------------
Return zero value if all parameters set; else return nonzero
@return ready status
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::isNotReady( void ) const {
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nGBVISoftcoreParameters::isNotReady";
// ---------------------------------------------------------------------------------------
int isReady = ImplicitSolventParameters::isNotReady();
int errors = 0;
std::stringstream message;
message << methodName;
const RealOpenMM* scaledRadii = getScaledRadii();
if( scaledRadii == NULL || scaledRadii[0] <= 0.0 ){
errors++;
message << "\n scaledRadii are not set";
}
const RealOpenMM* gamma = getGammaParameters();
if( gamma == NULL ){
errors++;
message << "\n gamma parameters are not set";
}
// check scale factors are in correct units
RealOpenMM average, stdDev, maxValue, minValue;
int minIndex, maxIndex;
SimTKOpenMMUtilities::getArrayStatistics( getNumberOfAtoms(), scaledRadii, &average,
&stdDev, &minValue, &minIndex,
&maxValue, &maxIndex );
if( average < 0.3 || average > 2.0 || minValue < 0.1 ){
errors++;
message << "\n scale factors for atomic radii appear not to be set correctly -- radii should be in nm";
message << "\n average radius=" << average << " min radius=" << minValue << " at atom index=" << minIndex;
}
if( errors ){
message << std::endl;
SimTKOpenMMLog::printMessage( message );
}
errors += isReady;
return errors;
}
/**---------------------------------------------------------------------------------------
Set the force to use a cutoff.
@param distance the cutoff distance
@return ReferenceForce::DefaultReturn
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setUseCutoff( RealOpenMM distance ) {
cutoff = true;
cutoffDistance = distance;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get whether to use a cutoff.
--------------------------------------------------------------------------------------- */
bool GBVISoftcoreParameters::getUseCutoff() {
return cutoff;
}
/**---------------------------------------------------------------------------------------
Get the cutoff distance.
--------------------------------------------------------------------------------------- */
RealOpenMM GBVISoftcoreParameters::getCutoffDistance() {
return cutoffDistance;
}
/**---------------------------------------------------------------------------------------
Set the force to use periodic boundary conditions. This requires that a cutoff has
also been set, and the smallest side of the periodic box is at least twice the cutoff
distance.
@param boxSize the X, Y, and Z widths of the periodic box
@return ReferenceForce::DefaultReturn
--------------------------------------------------------------------------------------- */
int GBVISoftcoreParameters::setPeriodic( RealOpenMM* boxSize ) {
assert(cutoff);
assert(boxSize[0] >= 2.0*cutoffDistance);
assert(boxSize[1] >= 2.0*cutoffDistance);
assert(boxSize[2] >= 2.0*cutoffDistance);
periodic = true;
periodicBoxSize[0] = boxSize[0];
periodicBoxSize[1] = boxSize[1];
periodicBoxSize[2] = boxSize[2];
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get whether to use periodic boundary conditions.
--------------------------------------------------------------------------------------- */
bool GBVISoftcoreParameters::getPeriodic() {
return periodic;
}
/**---------------------------------------------------------------------------------------
Get the periodic box dimension
--------------------------------------------------------------------------------------- */
const RealOpenMM* GBVISoftcoreParameters::getPeriodicBox() {
return periodicBoxSize;
}
/**---------------------------------------------------------------------------------------
Get tau prefactor
@return (1/e1 - 1/e0), where e1 = solute dielectric, e0 = solvent dielectric
--------------------------------------------------------------------------------------- */
RealOpenMM GBVISoftcoreParameters::getTau( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nGBVISoftcoreParameters::getTau:";
static const RealOpenMM zero = 0.0;
static const RealOpenMM one = 1.0;
// ---------------------------------------------------------------------------------------
RealOpenMM tau;
if( getSoluteDielectric() != zero && getSolventDielectric() != zero ){
tau = (one/getSoluteDielectric()) - (one/getSolventDielectric());
} else {
tau = zero;
}
return tau;
}
/**---------------------------------------------------------------------------------------
Get Born radii switching function method
@return method
--------------------------------------------------------------------------------------- */
GBVISoftcoreParameters::BornRadiusScalingSoftcoreMethod GBVISoftcoreParameters::getBornRadiusScalingSoftcoreMethod( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = " GBVISoftcoreParameters::getBornRadiusScalingSoftcoreMethod:";
// ---------------------------------------------------------------------------------------
return _bornRadiusScalingSoftcoreMethod;
}
/**---------------------------------------------------------------------------------------
Set Born radii switching function method
@param method
--------------------------------------------------------------------------------------- */
void GBVISoftcoreParameters::setBornRadiusScalingSoftcoreMethod( BornRadiusScalingSoftcoreMethod bornRadiusScalingSoftcoreMethod ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = " GBVISoftcoreParameters::setBornRadiusScalingSoftcoreMethod:";
// ---------------------------------------------------------------------------------------
_bornRadiusScalingSoftcoreMethod = bornRadiusScalingSoftcoreMethod;
}
/* Portions copyright (c) 2006-2009 Stanford University and Simbios.
* Contributors: Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __GBVISoftcoreParameters_H__
#define __GBVISoftcoreParameters_H__
#include "SimTKUtilities/SimTKOpenMMCommon.h"
#include "gbsa/ImplicitSolventParameters.h"
// ---------------------------------------------------------------------------------------
class GBVISoftcoreParameters : public ImplicitSolventParameters {
public:
static const std::string ParameterFileName;
/**
* This is an enumeration of the different methods that may be used for scaling of the Born radii.
*/
enum BornRadiusScalingSoftcoreMethod {
/**
* No scaling method is applied.
*/
NoScaling = 0,
/**
* Use the method outlined in Proteins 55, 383-394 (2004), Eq. 6
*/
Tanh = 1,
/**
* Use quintic spline scaling function
*/
QuinticSpline = 2
};
private:
// scaled radii
int _ownScaledRadii;
RealOpenMM* _scaledRadii;
// gamma parameters
int _ownGammaParameters;
RealOpenMM* _gammaParameters;
// BornRadiusScaleFactors parameters
int _ownBornRadiusScaleFactors;
RealOpenMM* _bornRadiusScaleFactors;
// cutoff and periodic boundary conditions
bool cutoff;
bool periodic;
RealOpenMM periodicBoxSize[3];
RealOpenMM cutoffDistance;
// Born radii switching function params
BornRadiusScalingSoftcoreMethod _bornRadiusScalingSoftcoreMethod;
RealOpenMM _quinticLowerLimitFactor;
RealOpenMM _quinticUpperBornRadiusLimit;
RealOpenMM _quinticUpperSplineLimit;
public:
/**---------------------------------------------------------------------------------------
GBVISoftcoreParameters constructor (Simbios)
@param numberOfAtoms number of atoms
--------------------------------------------------------------------------------------- */
GBVISoftcoreParameters( int numberOfAtoms );
/**---------------------------------------------------------------------------------------
GBVISoftcoreParameters destructor (Simbios)
--------------------------------------------------------------------------------------- */
~GBVISoftcoreParameters( );
/**---------------------------------------------------------------------------------------
Return scaled radii
@return array
--------------------------------------------------------------------------------------- */
const RealOpenMM* getScaledRadii( void ) const;
/**---------------------------------------------------------------------------------------
Return scaled radii
@return array
--------------------------------------------------------------------------------------- */
int setScaledRadii( RealOpenMM* scaledRadii );
#if RealOpenMMType == 2
int setScaledRadii( float* scaledRadii );
#endif
int setScaledRadii( const RealOpenMMVector& scaledRadii );
/**---------------------------------------------------------------------------------------
Set flag indicating whether scaled radii array should be deleted
@param ownScaledRadiusFactors flag indicating whether scaled radii
array should be deleted
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setOwnScaledRadii( int ownScaledRadii );
/**---------------------------------------------------------------------------------------
Get AtomicRadii array w/ dielectric offset applied
@return array of atom volumes
--------------------------------------------------------------------------------------- */
RealOpenMM* getAtomicRadii( void ) const;
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii array of atomic radii
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setAtomicRadii( RealOpenMM* atomicRadii );
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii vector of atomic radii
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setAtomicRadii( const RealOpenMMVector& atomicRadii );
/**---------------------------------------------------------------------------------------
Set flag indicating whether gamma parameter array should be deleted
@param ownGammaParameters flag indicating whether gamma parameter
array should be deleted
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setOwnGammaParameters( int ownGammaParameters );
/**---------------------------------------------------------------------------------------
Get GammaParameters array
@return array of gamma values
--------------------------------------------------------------------------------------- */
RealOpenMM* getGammaParameters( void ) const;
/**---------------------------------------------------------------------------------------
Set GammaParameters array
@param gammaParameters array of gamma parameters
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setGammaParameters( RealOpenMM* gammaParameters );
/**---------------------------------------------------------------------------------------
Set GammaParameters array
@param gammaParameters array of gamma parameters
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setGammaParameters( const RealOpenMMVector& gammaParameters );
/**---------------------------------------------------------------------------------------
Set flag indicating whether bornRadiusScaleFactor parameter array should be deleted
@param ownBornRadiusScaleFactors flag indicating whether bornRadiusScaleFactor parameter
array should be deleted
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setOwnBornRadiusScaleFactors( int ownBornRadiusScaleFactors );
/**---------------------------------------------------------------------------------------
Get BornRadiusScaleFactors array
@return array of bornRadiusScaleFactor values
--------------------------------------------------------------------------------------- */
RealOpenMM* getBornRadiusScaleFactors( void ) const;
/**---------------------------------------------------------------------------------------
Set BornRadiusScaleFactors array
@param bornRadiusScaleFactors array of bornRadiusScaleFactor parameters
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setBornRadiusScaleFactors( RealOpenMM* bornRadiusScaleFactors );
/**---------------------------------------------------------------------------------------
Set BornRadiusScaleFactors array
@param bornRadiusScaleFactors array of bornRadiusScaleFactor parameters
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setBornRadiusScaleFactors( const RealOpenMMVector& bornRadiusScaleFactors );
/**---------------------------------------------------------------------------------------
Get string w/ state
@param title title (optional)
@return string
--------------------------------------------------------------------------------------- */
std::string getStateString( const char* title ) const;
/**---------------------------------------------------------------------------------------
Return zero value if all parameters set; else return nonzero
@return ready status
--------------------------------------------------------------------------------------- */
int isNotReady( void ) const;
/**---------------------------------------------------------------------------------------
Set the force to use a cutoff.
@param distance the cutoff distance
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setUseCutoff( RealOpenMM distance );
/**---------------------------------------------------------------------------------------
Get whether to use a cutoff.
--------------------------------------------------------------------------------------- */
bool getUseCutoff();
/**---------------------------------------------------------------------------------------
Get the cutoff distance.
--------------------------------------------------------------------------------------- */
RealOpenMM getCutoffDistance();
/**---------------------------------------------------------------------------------------
Set the force to use periodic boundary conditions. This requires that a cutoff has
already been set, and the smallest side of the periodic box is at least twice the cutoff
distance.
@param boxSize the X, Y, and Z widths of the periodic box
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setPeriodic( RealOpenMM* boxSize );
/**---------------------------------------------------------------------------------------
Get whether to use periodic boundary conditions.
--------------------------------------------------------------------------------------- */
bool getPeriodic();
/**---------------------------------------------------------------------------------------
Get the periodic box dimension
--------------------------------------------------------------------------------------- */
const RealOpenMM* getPeriodicBox();
/**---------------------------------------------------------------------------------------
Get the quintic spline lower limit factor
--------------------------------------------------------------------------------------- */
RealOpenMM getQuinticLowerLimitFactor( void ) const;
/**---------------------------------------------------------------------------------------
Set the quintic spline lower limit factor
--------------------------------------------------------------------------------------- */
int setQuinticLowerLimitFactor( RealOpenMM quinticLowerLimitFactor );
/**---------------------------------------------------------------------------------------
Get the quintic spline upper limit
--------------------------------------------------------------------------------------- */
RealOpenMM getQuinticUpperBornRadiusLimit( void ) const;
RealOpenMM getQuinticUpperSplineLimit( void ) const;
/**---------------------------------------------------------------------------------------
Set the quintic spline upper limit
--------------------------------------------------------------------------------------- */
int setQuinticUpperBornRadiusLimit( RealOpenMM quinticUpperBornRadiusLimit );
/**---------------------------------------------------------------------------------------
Get tau prefactor
@return (1/e1 - 1/e0), where e1 = solute dielectric, e0 = solvent dielectric
--------------------------------------------------------------------------------------- */
RealOpenMM getTau( void ) const;
/**---------------------------------------------------------------------------------------
Get BornRadiusScalingSoftcoreMethod
@return scaling method
--------------------------------------------------------------------------------------- */
BornRadiusScalingSoftcoreMethod getBornRadiusScalingSoftcoreMethod( void ) const;
/**---------------------------------------------------------------------------------------
Set BornRadiusScalingSoftcoreMethod
@param scaling method
--------------------------------------------------------------------------------------- */
void setBornRadiusScalingSoftcoreMethod( BornRadiusScalingSoftcoreMethod method );
};
#endif // __GBVISoftcoreParameters_H__
/* Portions copyright (c) 2006-2009 Stanford University and Simbios.
* Contributors: Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <math.h>
#include <sstream>
#include "ObcSoftcoreParameters.h"
#include "../SimTKUtilities/SimTKOpenMMCommon.h"
#include "../SimTKUtilities/SimTKOpenMMLog.h"
#include "../SimTKUtilities/SimTKOpenMMUtilities.h"
// #define UseGromacsMalloc 1
#ifdef UseGromacsMalloc
extern "C" {
#include "smalloc.h"
}
#endif
const std::string ObcSoftcoreParameters::ParameterFileName = std::string( "params.agb" );
/**---------------------------------------------------------------------------------------
ObcSoftcoreParameters:
Calculates for each atom
(1) the van der Waal radii
(2) volume
(3) fixed terms in Obc equation gPol
(4) list of atoms that should be excluded in calculating
force -- nonbonded atoms (1-2, and 1-3 atoms)
Implementation:
Slightly different sequence of calls when running on CPU vs GPU.
Difference arise because the CPU-side data arrays for the Brook
streams are allocated by the BrookStreamWrapper objects. These
arrays are then used by ObcSoftcoreParameters when initializing the
the values (vdwRadii, volume, ...) to be used in the calculation.
Cpu:
ObcSoftcoreParameters* obcParameters = new ObcSoftcoreParameters( numberOfAtoms, log );
obcParameters->initializeParameters( top );
Gpu:
obcParameters = new ObcSoftcoreParameters( gpu->natoms, log );
// set arrays for cpu using stream data field;
// initializeParameters() only allocates space for arrays if they are not set (==NULL)
// also set flag so that ObcSoftcoreParameters destructor does not free arrays
obcParameters->setVdwRadii( getBrookStreamWrapperAtIndex( GpuObc::obcVdwRadii )->getData() );
obcParameters->setVolume( getBrookStreamWrapperAtIndex( GpuObc::obcVolume )->getData() );
obcParameters->setGPolFixed( getBrookStreamWrapperAtIndex( GpuObc::obcGpolFixed )->getData() );
obcParameters->setBornRadii( getBrookStreamWrapperAtIndex( GpuObc::obcBornRadii )->getData() );
obcParameters->setFreeArrays( false );
obcParameters->initializeParameters( top );
Issues:
Tinker's atom radii are used.
The logic for mapping the Gromacs atom names to Tinker type may be incomplete;
only tested for generic proteins
see mapGmxAtomNameToTinkerAtomNumber()
--------------------------------------------------------------------------------------- */
/**---------------------------------------------------------------------------------------
ObcSoftcoreParameters constructor (Simbios)
@param numberOfAtoms number of atoms
@param obcType OBC type (Eq. 7 or 8 in paper)
--------------------------------------------------------------------------------------- */
ObcSoftcoreParameters::ObcSoftcoreParameters( int numberOfAtoms, ObcSoftcoreParameters::ObcType obcType ) : ImplicitSolventParameters( numberOfAtoms ), cutoff(false), periodic(false) {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcSoftcoreParameters::ObcSoftcoreParameters";
// ---------------------------------------------------------------------------------------
_obcType = obcType;
_dielectricOffset = 0.009f;
_ownScaledRadiusFactors = 0;
_scaledRadiusFactors = NULL;
_ownNonPolarScaleFactors = 0;
_nonPolarScaleFactors = NULL;
_nonPolarPreFactor = 0.054;
setObcTypeParameters( obcType );
}
/**---------------------------------------------------------------------------------------
ObcSoftcoreParameters destructor (Simbios)
--------------------------------------------------------------------------------------- */
ObcSoftcoreParameters::~ObcSoftcoreParameters( ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcSoftcoreParameters::~ObcSoftcoreParameters";
// ---------------------------------------------------------------------------------------
// in GPU runs, arrays may be 'owned' by BrookStreamWrapper -- hence they should not
// be freed here, i.e., _freeArrays should be 'false'
#ifdef UseGromacsMalloc
/*
if( _freeArrays ){
if( _vdwRadii != NULL ){
save_free( "_vdwRadii", __FILE__, __LINE__, _vdwRadii );
}
} */
#else
if( _ownScaledRadiusFactors ){
delete[] _scaledRadiusFactors;
}
if( _ownNonPolarScaleFactors ){
delete[] _nonPolarScaleFactors;
}
/*
if( getFreeArrays() ){
} */
#endif
}
/**---------------------------------------------------------------------------------------
Get OBC type
@return OBC type
--------------------------------------------------------------------------------------- */
ObcSoftcoreParameters::ObcType ObcSoftcoreParameters::getObcType( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcSoftcoreParameters::getObcType:";
// ---------------------------------------------------------------------------------------
return _obcType;
}
/**---------------------------------------------------------------------------------------
Set OBC type specific parameters
@param obcType OBC type (ObcTypeI or ObcTypeII -- Eq. 7 or 8)
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ObcSoftcoreParameters::setObcTypeParameters( ObcSoftcoreParameters::ObcType obcType ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcSoftcoreParameters::setObcTypeParameters:";
// ---------------------------------------------------------------------------------------
if( obcType == ObcTypeI ){
_alphaObc = 0.8f;
_betaObc = 0.0f;
_gammaObc = 2.91f;
} else {
_alphaObc = 1.0f;
_betaObc = 0.8f;
_gammaObc = 4.85f;
}
_obcType = obcType;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get dielectricOffset
@return _dielectricOffset
--------------------------------------------------------------------------------------- */
RealOpenMM ObcSoftcoreParameters::getDielectricOffset( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcSoftcoreParameters::getDielectricOffset:";
// ---------------------------------------------------------------------------------------
return _dielectricOffset;
}
/**---------------------------------------------------------------------------------------
Get alpha OBC (Eqs. 6 & 7) in Proteins paper
@return alphaObc
--------------------------------------------------------------------------------------- */
RealOpenMM ObcSoftcoreParameters::getAlphaObc( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcSoftcoreParameters::getAlphaObc:";
// ---------------------------------------------------------------------------------------
return _alphaObc;
}
/**---------------------------------------------------------------------------------------
Get beta OBC (Eqs. 6 & 7) in Proteins paper
@return betaObc
--------------------------------------------------------------------------------------- */
RealOpenMM ObcSoftcoreParameters::getBetaObc( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcSoftcoreParameters::getBetaObc:";
// ---------------------------------------------------------------------------------------
return _betaObc;
}
/**---------------------------------------------------------------------------------------
Get gamma OBC (Eqs. 6 & 7) in Proteins paper
@return gammaObc
--------------------------------------------------------------------------------------- */
RealOpenMM ObcSoftcoreParameters::getGammaObc( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcSoftcoreParameters::getGammaObc:";
// ---------------------------------------------------------------------------------------
return _gammaObc;
}
/**---------------------------------------------------------------------------------------
Get AtomicRadii array
@return array of atomic radii
--------------------------------------------------------------------------------------- */
RealOpenMM* ObcSoftcoreParameters::getAtomicRadii( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::getAtomicRadii:";
// ---------------------------------------------------------------------------------------
RealOpenMM* atomicRadii = ImplicitSolventParameters::getAtomicRadii();
// if dielectric offset applied, then unapply
return atomicRadii;
}
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii array of atomic radii
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ObcSoftcoreParameters::setAtomicRadii( RealOpenMM* atomicRadii ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcSoftcoreParameters::setAtomicRadii:";
// ---------------------------------------------------------------------------------------
return ImplicitSolventParameters::setAtomicRadii( atomicRadii );
}
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii vector of atomic radii
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ObcSoftcoreParameters::setAtomicRadii( const RealOpenMMVector& atomicRadii ){
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nObcSoftcoreParameters::setAtomicRadii:";
// ---------------------------------------------------------------------------------------
return ImplicitSolventParameters::setAtomicRadii( atomicRadii );
}
/**---------------------------------------------------------------------------------------
Return OBC scale factors
If not previously set, allocate space
@return array
--------------------------------------------------------------------------------------- */
const RealOpenMM* ObcSoftcoreParameters::getScaledRadiusFactors( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::getScaledRadiusFactors";
// ---------------------------------------------------------------------------------------
if( _scaledRadiusFactors == NULL ){
ObcSoftcoreParameters* localThis = const_cast<ObcSoftcoreParameters* const>(this);
localThis->_scaledRadiusFactors = new RealOpenMM[getNumberOfAtoms()];
localThis->_ownScaledRadiusFactors = true;
memset( _scaledRadiusFactors, 0, sizeof( RealOpenMM )*getNumberOfAtoms() );
}
return _scaledRadiusFactors;
}
/**---------------------------------------------------------------------------------------
Set flag indicating whether scale factors array should be deleted
@param ownScaledRadiusFactors flag indicating whether scale factors
array should be deleted
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ObcSoftcoreParameters::setOwnScaleFactors( int ownScaledRadiusFactors ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::setOwnScaleFactors";
// ---------------------------------------------------------------------------------------
_ownScaledRadiusFactors = ownScaledRadiusFactors;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Set OBC scale factors
@param scaledRadiusFactors scaledRadiusFactors
@return SimTKOpenMMCommon::DefaultReturn always
--------------------------------------------------------------------------------------- */
int ObcSoftcoreParameters::setScaledRadiusFactors( RealOpenMM* scaledRadiusFactors ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::setScaledRadiusFactors";
// ---------------------------------------------------------------------------------------
if( _ownScaledRadiusFactors && _scaledRadiusFactors != scaledRadiusFactors ){
delete[] _scaledRadiusFactors;
_ownScaledRadiusFactors = false;
}
_scaledRadiusFactors = scaledRadiusFactors;
return SimTKOpenMMCommon::DefaultReturn;
}
#if RealOpenMMType == 2
/**---------------------------------------------------------------------------------------
Set OBC scale factors
@param scaledRadiusFactors scaledRadiusFactors
@return SimTKOpenMMCommon::DefaultReturn always
--------------------------------------------------------------------------------------- */
int ObcSoftcoreParameters::setScaledRadiusFactors( float* scaledRadiusFactors ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::setScaledRadiusFactors";
// ---------------------------------------------------------------------------------------
if( _scaledRadiusFactors == NULL ){
_scaledRadiusFactors = new RealOpenMM[getNumberOfAtoms()];
_ownScaledRadiusFactors = true;
}
for( int ii = 0; ii < getNumberOfAtoms(); ii++ ){
_scaledRadiusFactors[ii] = (RealOpenMM) scaledRadiusFactors[ii];
}
return SimTKOpenMMCommon::DefaultReturn;
}
#endif
/**---------------------------------------------------------------------------------------
Set OBC scale factors
@param scaledRadiusFactors scaledRadiusFactors
@return SimTKOpenMMCommon::DefaultReturn always
--------------------------------------------------------------------------------------- */
int ObcSoftcoreParameters::setScaledRadiusFactors( const RealOpenMMVector& scaledRadiusFactors ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::setScaledRadiusFactors";
// ---------------------------------------------------------------------------------------
if( _ownScaledRadiusFactors && _scaledRadiusFactors != NULL ){
delete[] _scaledRadiusFactors;
}
_ownScaledRadiusFactors = true;
_scaledRadiusFactors = new RealOpenMM[getNumberOfAtoms()];
for( int ii = 0; ii < (int) scaledRadiusFactors.size(); ii++ ){
_scaledRadiusFactors[ii] = scaledRadiusFactors[ii];
}
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Map Gmx atom name to Tinker atom number (Simbios)
@param atomName atom name (CA, HA, ...); upper and lower case should both work
@param log if set, then print error messages to log file
@return Tinker atom number if atom name is valid; else return -1
--------------------------------------------------------------------------------------- */
int ObcSoftcoreParameters::mapGmxAtomNameToTinkerAtomNumber( const char* atomName, FILE* log ) const {
// ---------------------------------------------------------------------------------------
static int mapCreated = 0;
static int atomNameMap[26];
// ---------------------------------------------------------------------------------------
// set up atomNameMap array on first call to this method
// atomNameMap[ii] = Tinker atom number
// where ii = (the ASCII index - 65) of the first character in the
// input atom name; name may be lower case
if( !mapCreated ){
mapCreated = 1;
for( int ii = 0; ii < 26; ii++ ){
atomNameMap[ii] = -1;
}
// H
atomNameMap[7] = 1;
// C
atomNameMap[2] = 6;
// N
atomNameMap[13] = 7;
// O
atomNameMap[14] = 8;
// S
atomNameMap[18] = 16;
}
// map first letter in atom name to Tinker atom number
int firstAsciiValue = ((int) atomName[0]) - 65;
// check for lower case
if( firstAsciiValue > 25 ){
firstAsciiValue -= 32;
}
// validate
if( firstAsciiValue < 0 || firstAsciiValue > 25 ){
if( log != NULL ){
(void) fprintf( log, "Atom name=<%s> unrecognized.", atomName );
}
(void) fprintf( stderr, "Atom name=<%s> unrecognized.", atomName );
return -1;
}
return atomNameMap[firstAsciiValue];
}
/**---------------------------------------------------------------------------------------
Get string w/ state
@param title title (optional)
@return string
--------------------------------------------------------------------------------------- */
std::string ObcSoftcoreParameters::getStateString( const char* title ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcSoftcoreParameters::getStateString";
// ---------------------------------------------------------------------------------------
std::stringstream message;
message << ImplicitSolventParameters::getStateString( title );
std::string tab = getStringTab();
if( getObcType() == ObcTypeI ){
message << tab << "OBC type: Type I";
} else {
message << tab << "OBC type: Type II";
}
message << tab << "Alpha: " << getAlphaObc();
message << tab << "Beta: " << getBetaObc();
message << tab << "Gamma: " << getGammaObc();
return message.str();
}
/**---------------------------------------------------------------------------------------
Return zero value if all parameters set; else return nonzero
@return ready status
--------------------------------------------------------------------------------------- */
int ObcSoftcoreParameters::isNotReady( void ) const {
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nObcSoftcoreParameters::isNotReady";
// ---------------------------------------------------------------------------------------
int isReady = ImplicitSolventParameters::isNotReady();
int errors = 0;
std::stringstream message;
message << methodName;
const RealOpenMM* scaledRadiusFactors = getScaledRadiusFactors();
if( scaledRadiusFactors == NULL || scaledRadiusFactors[0] <= 0.0 ){
errors++;
message << "\n scaledRadiusFactors is not set";
}
// check scale factors are in correct units
RealOpenMM average, stdDev, maxValue, minValue;
int minIndex, maxIndex;
SimTKOpenMMUtilities::getArrayStatistics( getNumberOfAtoms(), scaledRadiusFactors, &average,
&stdDev, &minValue, &minIndex,
&maxValue, &maxIndex );
if( average < 0.3 || average > 2.0 || minValue < 0.1 ){
errors++;
message << "\n scale factors for atomic radii appear not to be set correctly -- radii should be in nm";
message << "\n average radius=" << average << " min radius=" << minValue << " at atom index=" << minIndex;
}
if( errors ){
message << std::endl;
SimTKOpenMMLog::printMessage( message );
}
errors += isReady;
return errors;
}
/**---------------------------------------------------------------------------------------
Set the force to use a cutoff.
@param distance the cutoff distance
@return ReferenceForce::DefaultReturn
--------------------------------------------------------------------------------------- */
int ObcSoftcoreParameters::setUseCutoff( RealOpenMM distance ) {
cutoff = true;
cutoffDistance = distance;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get whether to use a cutoff.
--------------------------------------------------------------------------------------- */
bool ObcSoftcoreParameters::getUseCutoff() {
return cutoff;
}
/**---------------------------------------------------------------------------------------
Get the cutoff distance.
--------------------------------------------------------------------------------------- */
RealOpenMM ObcSoftcoreParameters::getCutoffDistance() {
return cutoffDistance;
}
/**---------------------------------------------------------------------------------------
Set the force to use periodic boundary conditions. This requires that a cutoff has
also been set, and the smallest side of the periodic box is at least twice the cutoff
distance.
@param boxSize the X, Y, and Z widths of the periodic box
@return ReferenceForce::DefaultReturn
--------------------------------------------------------------------------------------- */
int ObcSoftcoreParameters::setPeriodic( RealOpenMM* boxSize ) {
assert(cutoff);
assert(boxSize[0] >= 2.0*cutoffDistance);
assert(boxSize[1] >= 2.0*cutoffDistance);
assert(boxSize[2] >= 2.0*cutoffDistance);
periodic = true;
periodicBoxSize[0] = boxSize[0];
periodicBoxSize[1] = boxSize[1];
periodicBoxSize[2] = boxSize[2];
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get whether to use periodic boundary conditions.
--------------------------------------------------------------------------------------- */
bool ObcSoftcoreParameters::getPeriodic() {
return periodic;
}
/**---------------------------------------------------------------------------------------
Get the periodic box dimension
--------------------------------------------------------------------------------------- */
const RealOpenMM* ObcSoftcoreParameters::getPeriodicBox() {
return periodicBoxSize;
}
/**---------------------------------------------------------------------------------------
Return non-polar scale factors
If not previously set, allocate space
@return array
--------------------------------------------------------------------------------------- */
const RealOpenMM* ObcSoftcoreParameters::getNonPolarScaleFactors( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "ObcSoftcoreParameters::getNonPolarScaleFactors";
// ---------------------------------------------------------------------------------------
if( _nonPolarScaleFactors == NULL ){
ObcSoftcoreParameters* localThis = const_cast<ObcSoftcoreParameters* const>(this);
localThis->_nonPolarScaleFactors = new RealOpenMM[getNumberOfAtoms()];
localThis->_ownNonPolarScaleFactors = true;
memset( _nonPolarScaleFactors, 0, sizeof( RealOpenMM )*getNumberOfAtoms() );
}
return _nonPolarScaleFactors;
}
/**---------------------------------------------------------------------------------------
Set flag indicating whether scale factors array should be deleted
@param ownNonPolarScaleFactors flag indicating whether scale factors
array should be deleted
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ObcSoftcoreParameters::setOwnNonPolarScaleFactors( int ownNonPolarScaleFactors ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::setOwnScaleFactors";
// ---------------------------------------------------------------------------------------
_ownNonPolarScaleFactors = ownNonPolarScaleFactors;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Set non-polar scale factors
@param nonPolarScaleFactors nonPolarScaleFactors
@return SimTKOpenMMCommon::DefaultReturn always
--------------------------------------------------------------------------------------- */
int ObcSoftcoreParameters::setNonPolarScaleFactors( const RealOpenMMVector& nonPolarScaleFactors ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::setNonPolarScaleFactors";
// ---------------------------------------------------------------------------------------
if( _ownNonPolarScaleFactors ){
delete[] _nonPolarScaleFactors;
}
_ownNonPolarScaleFactors = true;
_nonPolarScaleFactors = new RealOpenMM[nonPolarScaleFactors.size()];
for( int ii = 0; ii < getNumberOfAtoms(); ii++ ){
_nonPolarScaleFactors[ii] = nonPolarScaleFactors[ii];
}
return SimTKOpenMMCommon::DefaultReturn;
}
#if RealOpenMMType == 2
/**---------------------------------------------------------------------------------------
Set non-polar scale factors
@param nonPolarScaleFactors nonPolarScaleFactors
@return SimTKOpenMMCommon::DefaultReturn always
--------------------------------------------------------------------------------------- */
int ObcSoftcoreParameters::setNonPolarScaleFactors( float* nonPolarScaleFactors ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::setNonPolarScaleFactors";
// ---------------------------------------------------------------------------------------
if( _nonPolarScaleFactors == NULL ){
_nonPolarScaleFactors = new RealOpenMM[getNumberOfAtoms()];
_ownNonPolarScaleFactors = true;
}
for( int ii = 0; ii < getNumberOfAtoms(); ii++ ){
_nonPolarScaleFactors[ii] = (RealOpenMM) nonPolarScaleFactors[ii];
}
return SimTKOpenMMCommon::DefaultReturn;
}
#endif
/**---------------------------------------------------------------------------------------
Set OBC scale factors
@param nonPolarScaleFactors nonPolarScaleFactors
@return SimTKOpenMMCommon::DefaultReturn always
--------------------------------------------------------------------------------------- */
int ObcSoftcoreParameters::setNonPolarPrefactor( RealOpenMM nonPolarPreFactor ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::setNonPolarScaleFactors";
// ---------------------------------------------------------------------------------------
_nonPolarPreFactor = nonPolarPreFactor;
return SimTKOpenMMCommon::DefaultReturn;
}
/* Portions copyright (c) 2006-2009 Stanford University and Simbios.
* Contributors: Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ObcSoftcoreParameters_H__
#define __ObcSoftcoreParameters_H__
#include "../SimTKUtilities/SimTKOpenMMCommon.h"
#include "gbsa/ImplicitSolventParameters.h"
// ---------------------------------------------------------------------------------------
class ObcSoftcoreParameters : public ImplicitSolventParameters {
public:
// OBC types
enum ObcType { ObcTypeI, ObcTypeII };
static const std::string ParameterFileName;
private:
// OBC constants & parameters
RealOpenMM _dielectricOffset;
RealOpenMM _alphaObc;
RealOpenMM _betaObc;
RealOpenMM _gammaObc;
ObcType _obcType;
RealOpenMM _nonPolarPreFactor;
// scaling factors for nonpolar term
int _ownNonPolarScaleFactors;
RealOpenMM* _nonPolarScaleFactors;
// scaled radius factors (S_kk in HCT paper)
int _ownScaledRadiusFactors;
RealOpenMM* _scaledRadiusFactors;
// cutoff and periodic boundary conditions
bool cutoff;
bool periodic;
RealOpenMM periodicBoxSize[3];
RealOpenMM cutoffDistance;
/**---------------------------------------------------------------------------------------
Set solvent dielectric (Simbios)
@param dielectricOffset solvent dielectric
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setDielectricOffset( RealOpenMM dielectricOffset );
public:
/**---------------------------------------------------------------------------------------
ObcSoftcoreParameters constructor (Simbios)
@param numberOfAtoms number of atoms
--------------------------------------------------------------------------------------- */
ObcSoftcoreParameters( int numberOfAtoms, ObcSoftcoreParameters::ObcType obcType = ObcTypeII );
/**---------------------------------------------------------------------------------------
ObcSoftcoreParameters destructor (Simbios)
--------------------------------------------------------------------------------------- */
~ObcSoftcoreParameters( );
/**---------------------------------------------------------------------------------------
Get OBC type
@return OBC type
--------------------------------------------------------------------------------------- */
ObcSoftcoreParameters::ObcType getObcType( void ) const;
/**---------------------------------------------------------------------------------------
Set OBC type specific parameters
@param obcType OBC type (ObcTypeI or ObcTypeII -- Eq. 7 or 8)
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setObcTypeParameters( ObcSoftcoreParameters::ObcType obcType );
/**---------------------------------------------------------------------------------------
Get alpha OBC (Eqs. 6 & 7) in Proteins paper
@return alphaObc
--------------------------------------------------------------------------------------- */
RealOpenMM getAlphaObc( void ) const;
/**---------------------------------------------------------------------------------------
Get beta OBC (Eqs. 6 & 7) in Proteins paper
@return betaObc
--------------------------------------------------------------------------------------- */
RealOpenMM getBetaObc( void ) const;
/**---------------------------------------------------------------------------------------
Get gamma OBC (Eqs. 6 & 7) in Proteins paper
@return gammaObc
--------------------------------------------------------------------------------------- */
RealOpenMM getGammaObc( void ) const;
/**---------------------------------------------------------------------------------------
Get solvent dielectric (Simbios)
@return dielectricOffset dielectric offset
--------------------------------------------------------------------------------------- */
RealOpenMM getDielectricOffset( void ) const;
/**---------------------------------------------------------------------------------------
Return OBC scale factors
@return array
--------------------------------------------------------------------------------------- */
const RealOpenMM* getScaledRadiusFactors( void ) const;
/**---------------------------------------------------------------------------------------
Return OBC scale factors
@return array
--------------------------------------------------------------------------------------- */
int setScaledRadiusFactors( RealOpenMM* scaledRadiusFactors );
#if RealOpenMMType == 2
int setScaledRadiusFactors( float* scaledRadiusFactors );
#endif
int setScaledRadiusFactors( const RealOpenMMVector& scaledRadiusFactors );
/**---------------------------------------------------------------------------------------
Set flag indicating whether scale factors arra should be deleted
@param ownScaledRadiusFactors flag indicating whether scale factors
array should be deleted
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setOwnScaleFactors( int ownScaledRadiusFactors );
/**---------------------------------------------------------------------------------------
Assign standard radii for GB/SA methods other than ACE;
taken from Macromodel and OPLS-AA, except for hydrogens (Simbios)
Logic based on logic in Tinker's ksolv.f
Currently only works for standard amino acid atoms
If invalid atom name is encountered, a message is printed to log file and the
radius for that atom is set to 1.0f
@param numberOfAtoms number of atoms
@param atomNames array of atom names from GMX top data struct
@param radii array to store Macromodel radii for each atom
@param log if set, then print error messages to log file
@return SimTKOpenMMCommon::DefaultReturn always
--------------------------------------------------------------------------------------- */
int getMacroModelAtomicRadii( int numberOfAtoms,
char*** atomNames, RealOpenMM* radii, FILE* log );
/**---------------------------------------------------------------------------------------
Get AtomicRadii array w/ dielectric offset applied
@return array of atom volumes
--------------------------------------------------------------------------------------- */
RealOpenMM* getAtomicRadii( void ) const;
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii array of atomic radii
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setAtomicRadii( RealOpenMM* atomicRadii );
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii vector of atomic radii
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setAtomicRadii( const RealOpenMMVector& atomicRadii );
/**---------------------------------------------------------------------------------------
Map Gmx atom name to Tinker atom number (Simbios)
@param atomName atom name (CA, HA, ...); upper and lower case should both work
@param log if set, then print error messages to log file
return Tinker atom number if atom name is valid; else return -1
--------------------------------------------------------------------------------------- */
int mapGmxAtomNameToTinkerAtomNumber( const char* atomName, FILE* log ) const;
/**---------------------------------------------------------------------------------------
Get string w/ state
@param title title (optional)
@return string
--------------------------------------------------------------------------------------- */
std::string getStateString( const char* title ) const;
/**---------------------------------------------------------------------------------------
Return zero value if all parameters set; else return nonzero
@return ready status
--------------------------------------------------------------------------------------- */
int isNotReady( void ) const;
/**---------------------------------------------------------------------------------------
Set the force to use a cutoff.
@param distance the cutoff distance
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setUseCutoff( RealOpenMM distance );
/**---------------------------------------------------------------------------------------
Get whether to use a cutoff.
--------------------------------------------------------------------------------------- */
bool getUseCutoff();
/**---------------------------------------------------------------------------------------
Get the cutoff distance.
--------------------------------------------------------------------------------------- */
RealOpenMM getCutoffDistance();
/**---------------------------------------------------------------------------------------
Set the force to use periodic boundary conditions. This requires that a cutoff has
already been set, and the smallest side of the periodic box is at least twice the cutoff
distance.
@param boxSize the X, Y, and Z widths of the periodic box
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setPeriodic( RealOpenMM* boxSize );
/**---------------------------------------------------------------------------------------
Get whether to use periodic boundary conditions.
--------------------------------------------------------------------------------------- */
bool getPeriodic();
/**---------------------------------------------------------------------------------------
Get the periodic box dimension
--------------------------------------------------------------------------------------- */
const RealOpenMM* getPeriodicBox();
/**---------------------------------------------------------------------------------------
Set flag indicating whether scale factors array should be deleted
@param ownNonPolarScaleFactors flag indicating whether scale factors
array should be deleted
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setOwnNonPolarScaleFactors( int ownNonPolarScaleFactors );
/**---------------------------------------------------------------------------------------
Return non-polar scale factors
If not previously set, allocate space
@return array
--------------------------------------------------------------------------------------- */
const RealOpenMM* getNonPolarScaleFactors( void ) const;
/**---------------------------------------------------------------------------------------
Set non-polar scale factors
@param nonPolarScaleFactors nonpolar scale factors
@return array
--------------------------------------------------------------------------------------- */
int setNonPolarScaleFactors( const RealOpenMMVector& nonPolarScaleFactors );
/**---------------------------------------------------------------------------------------
Set nonPolarPrefactor
@param nonPolarPrefactor solute dielectric
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setNonPolarPrefactor( RealOpenMM nonPolarPrefactor );
};
/**---------------------------------------------------------------------------------------
Qsort/heapsort integer comparison (Simbios)
@parma a first value to compare
@param b second value to compare
@return -1, 0, 1
--------------------------------------------------------------------------------------- */
int integerComparison( const void *a, const void *b);
// ---------------------------------------------------------------------------------------
#endif // __ObcSoftcoreParameters_H__
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