Commit 2cfc6821 authored by Peter Eastman's avatar Peter Eastman
Browse files

Continuing to implement ReferencePlatform (implemented GBSA kernels, added...

Continuing to implement ReferencePlatform (implemented GBSA kernels, added test case for SHAKE and fixed some bugs in it)
parent 5d9ae810
......@@ -106,13 +106,11 @@ public:
/**
* Initialize the kernel, setting up the values of all the force field parameters.
*
* @param bornRadii the initial value of the Born radius for each atom
* @param atomParameters the force parameters (charge, atomic radius, scaling factor) for each atom
* @param solventDielectric the dielectric constant of the solvent
* @param soluteDielectric the dielectric constant of the solute
*/
virtual void initialize(const std::vector<double>& bornRadii, const std::vector<std::vector<double> >& atomParameters,
double solventDielectric, double soluteDielectric) = 0;
virtual void initialize(const std::vector<std::vector<double> >& atomParameters, double solventDielectric, double soluteDielectric) = 0;
/**
* Execute the kernel to calculate the forces.
*
......
......@@ -36,7 +36,7 @@
using namespace OpenMM;
GBSAOBCForceField::GBSAOBCForceField(int numAtoms) : atoms(numAtoms) {
GBSAOBCForceField::GBSAOBCForceField(int numAtoms) : atoms(numAtoms), solventDielectric(78.3), soluteDielectric(1.0) {
}
void GBSAOBCForceField::getAtomParameters(int index, double& charge, double& radius, double& scalingFactor) const {
......
......@@ -43,9 +43,7 @@ GBSAOBCForceFieldImpl::GBSAOBCForceFieldImpl(GBSAOBCForceField& owner, OpenMMCon
void GBSAOBCForceFieldImpl::initialize(OpenMMContextImpl& context) {
hasInitialized = true;
kernel = context.getPlatform().createKernel(CalcGBSAOBCForceFieldKernel::Name());
std::vector<double> bornRadii;
// TODO calculate the initial Born radii.
vector<vector<double> > atomParameters;
vector<vector<double> > atomParameters(owner.getNumAtoms());
for (int i = 0; i < owner.getNumAtoms(); ++i) {
double charge, radius, scalingFactor;
owner.getAtomParameters(i, charge, radius, scalingFactor);
......@@ -53,8 +51,7 @@ void GBSAOBCForceFieldImpl::initialize(OpenMMContextImpl& context) {
atomParameters[i].push_back(radius);
atomParameters[i].push_back(scalingFactor);
}
dynamic_cast<CalcGBSAOBCForceFieldKernel&>(kernel.getImpl()).initialize(bornRadii, atomParameters,
owner.getSolventDielectric(), owner.getSoluteDielectric());
dynamic_cast<CalcGBSAOBCForceFieldKernel&>(kernel.getImpl()).initialize(atomParameters, owner.getSolventDielectric(), owner.getSoluteDielectric());
}
void GBSAOBCForceFieldImpl::calcForces(OpenMMContextImpl& context, Stream& forces) {
......
......@@ -31,6 +31,7 @@
#include "ReferenceKernels.h"
#include "ReferenceFloatStreamImpl.h"
#include "gbsa/CpuObc.h"
#include "SimTKReference/ReferenceAngleBondIxn.h"
#include "SimTKReference/ReferenceBondForce.h"
#include "SimTKReference/ReferenceHarmonicBondIxn.h"
......@@ -209,17 +210,44 @@ double ReferenceCalcStandardMMForceFieldKernel::executeEnergy(const Stream& posi
return energy;
}
void ReferenceCalcGBSAOBCForceFieldKernel::initialize(const vector<double>& bornRadii, const vector<vector<double> >& atomParameters,
double solventDielectric, double soluteDielectric) {
ReferenceCalcGBSAOBCForceFieldKernel::~ReferenceCalcGBSAOBCForceFieldKernel() {
if (obc) {
delete obc->getObcParameters();
delete obc;
}
}
void ReferenceCalcGBSAOBCForceFieldKernel::initialize(const vector<vector<double> >& atomParameters, double solventDielectric, double soluteDielectric) {
int numAtoms = atomParameters.size();
charges.resize(numAtoms);
vector<RealOpenMM> atomicRadii(numAtoms);
vector<RealOpenMM> scaleFactors(numAtoms);
for (int i = 0; i < numAtoms; ++i) {
charges[i] = atomParameters[i][0];
atomicRadii[i] = atomParameters[i][1];
scaleFactors[i] = atomParameters[i][2];
}
ObcParameters* obcParameters = new ObcParameters(numAtoms, ObcParameters::ObcTypeII);
obcParameters->setAtomicRadii(atomicRadii, SimTKOpenMMCommon::KcalAngUnits);
obcParameters->setScaledRadiusFactors(scaleFactors);
obcParameters->setSolventDielectric(solventDielectric);
obcParameters->setSoluteDielectric(soluteDielectric);
obc = new CpuObc(obcParameters);
obc->setIncludeAceApproximation(true);
}
void ReferenceCalcGBSAOBCForceFieldKernel::executeForces(const Stream& positions, Stream& forces) {
RealOpenMM** posData = const_cast<RealOpenMM**>(((ReferenceFloatStreamImpl&) positions.getImpl()).getData()); // Reference code needs to be made const correct
RealOpenMM** forceData = ((ReferenceFloatStreamImpl&) forces.getImpl()).getData();
obc->computeImplicitSolventForces(posData, &charges[0], forceData, 0);
}
double ReferenceCalcGBSAOBCForceFieldKernel::executeEnergy(const Stream& positions) {
return 0.0; // TODO implement correctly
RealOpenMM** posData = const_cast<RealOpenMM**>(((ReferenceFloatStreamImpl&) positions.getImpl()).getData()); // Reference code needs to be made const correct
RealOpenMM** forceData = allocateRealArray(positions.getSize(), 3);
obc->computeImplicitSolventForces(posData, &charges[0], forceData, 1);
disposeRealArray(forceData, positions.getSize());
return obc->getEnergy();
}
void ReferenceIntegrateVerletStepKernel::initialize(const vector<double>& masses, const vector<vector<int> >& constraintIndices,
......
......@@ -35,6 +35,7 @@
#include "kernels.h"
#include "SimTKUtilities/SimTKOpenMMRealType.h"
class CpuObc;
class ReferenceStochasticDynamics;
class ReferenceShakeAlgorithm;
......@@ -102,16 +103,15 @@ class ReferenceCalcGBSAOBCForceFieldKernel : public CalcGBSAOBCForceFieldKernel
public:
ReferenceCalcGBSAOBCForceFieldKernel(std::string name, const Platform& platform) : CalcGBSAOBCForceFieldKernel(name, platform) {
}
~ReferenceCalcGBSAOBCForceFieldKernel();
/**
* Initialize the kernel, setting up the values of all the force field parameters.
*
* @param bornRadii the initial value of the Born radius for each atom
* @param atomParameters the force parameters (charge, atomic radius, scaling factor) for each atom
* @param solventDielectric the dielectric constant of the solvent
* @param soluteDielectric the dielectric constant of the solute
*/
void initialize(const std::vector<double>& bornRadii, const std::vector<std::vector<double> >& atomParameters,
double solventDielectric, double soluteDielectric);
void initialize(const std::vector<std::vector<double> >& atomParameters, double solventDielectric, double soluteDielectric);
/**
* Execute the kernel to calculate the forces.
*
......@@ -127,6 +127,9 @@ public:
* @return the potential energy due to the GBSAOBCForceField
*/
double executeEnergy(const Stream& positions);
private:
CpuObc* obc;
std::vector<RealOpenMM> charges;
};
/**
......
......@@ -65,6 +65,7 @@ ReferenceShakeAlgorithm::ReferenceShakeAlgorithm( int numberOfConstraints,
_maximumNumberOfIterations = 15;
_tolerance = (RealOpenMM) 1.0e-04;
_hasInitializedMasses = false;
// work arrays
......@@ -237,7 +238,6 @@ int ReferenceShakeAlgorithm::applyShake( int numberOfAtoms, RealOpenMM** atomCoo
static const RealOpenMM epsilon6 = (RealOpenMM) 1.0e-06;
static int firstPass = 1;
static int debug = 0;
// ---------------------------------------------------------------------------------------
......@@ -253,8 +253,8 @@ int ReferenceShakeAlgorithm::applyShake( int numberOfAtoms, RealOpenMM** atomCoo
// calculate reduced masses on 1st pass
if( firstPass ){
firstPass = 0;
if( !_hasInitializedMasses ){
_hasInitializedMasses = true;
for( int ii = 0; ii < _numberOfConstraints; ii++ ){
int atomI = _atomIndices[ii][0];
int atomJ = _atomIndices[ii][1];
......@@ -298,7 +298,8 @@ int ReferenceShakeAlgorithm::applyShake( int numberOfAtoms, RealOpenMM** atomCoo
}
RealOpenMM rp2 = DOT3( rp_ij, rp_ij );
RealOpenMM diff = d_ij2[ii] - rp2;
RealOpenMM dist2= _shakeParameters[ii][0]*_shakeParameters[ii][0];
RealOpenMM diff = dist2 - rp2;
int iconv = (int) ( FABS( diff )*distanceTolerance[ii] );
if( iconv ){
RealOpenMM rrpr = DOT3( rp_ij, r_ij[ii] );
......
......@@ -42,6 +42,7 @@ class ReferenceShakeAlgorithm {
RealOpenMM* _d_ij2;
RealOpenMM* _distanceTolerance;
RealOpenMM* _reducedMasses;
bool _hasInitializedMasses;
public:
......
/* 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.
*/
#include "../SimTKUtilities/SimTKOpenMMCommon.h"
#include "../SimTKUtilities/SimTKOpenMMLog.h"
#include "../SimTKUtilities/SimTKOpenMMUtilities.h"
#include "CpuImplicitSolvent.h"
//#define UseGromacsMalloc 1
// Replacement new/delete w/ Gromac's smalloc() and sfree()
// static data member created by call to cpuSetImplicitSolventParameters()
// stores parameter settings, ...
// used to calculate GBSA forces/energy
CpuImplicitSolvent* CpuImplicitSolvent::_cpuImplicitSolvent = NULL;
// info file related-stuff
std::string CpuImplicitSolvent::_defaultInfoFileName = std::string( "CpuImplicitSolventInfo" );
// key for info file: base file name
const std::string CpuImplicitSolvent::CpuImplicitSolventBaseFileName = std::string( "CpuImplicitSolventBaseFileName" );
// key for info file: file generation frequency
const std::string CpuImplicitSolvent::CpuImplicitSolventFileGenerationFrequency = std::string( "CpuImplicitSolventFileGenerationFrequency" );
/**---------------------------------------------------------------------------------------
CpuImplicitSolvent constructor
@param implicitSolventParameters implicitSolventParameters object
--------------------------------------------------------------------------------------- */
CpuImplicitSolvent::CpuImplicitSolvent( ImplicitSolventParameters* implicitSolventParameters ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::CpuImplicitSolvent(2)";
// ---------------------------------------------------------------------------------------
_initializeDataMembers( );
_implicitSolventParameters = implicitSolventParameters;
}
/**---------------------------------------------------------------------------------------
CpuImplicitSolvent destructor
--------------------------------------------------------------------------------------- */
CpuImplicitSolvent::~CpuImplicitSolvent( ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::~CpuImplicitSolvent";
// ---------------------------------------------------------------------------------------
//#ifdef UseGromacsMalloc
// save_free( "_bornForce", __FILE__, __LINE__, _bornForce );
//#else
// delete[] _bornForce;
//#endif
delete _implicitSolventParameters;
delete[] _bornForce;
delete[] _bornRadii;
delete[] _tempBornRadii;
}
/**---------------------------------------------------------------------------------------
Initialize data members
--------------------------------------------------------------------------------------- */
void CpuImplicitSolvent::_initializeDataMembers( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::_initializeDataMembers";
// ---------------------------------------------------------------------------------------
_bornRadii = NULL;
_tempBornRadii = NULL;
_bornForce = NULL;
_includeAceApproximation = 0;
_forceConversionFactor = (RealOpenMM) 1.0;
_energyConversionFactor = (RealOpenMM) 1.0;
_forceCallIndex = 0;
_implicitSolventEnergy = (RealOpenMM) 0.0;
_baseFileName = SimTKOpenMMCommon::NotSet;
_outputFileFrequency = 1;
}
/**---------------------------------------------------------------------------------------
Return number of atoms
@return number of atoms
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::getNumberOfAtoms( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::getNumberOfAtoms";
// ---------------------------------------------------------------------------------------
return _implicitSolventParameters->getNumberOfAtoms();
}
/**---------------------------------------------------------------------------------------
Return energy
@return energy
--------------------------------------------------------------------------------------- */
RealOpenMM CpuImplicitSolvent::getEnergy( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::getEnergy";
// ---------------------------------------------------------------------------------------
return _implicitSolventEnergy;
}
/**---------------------------------------------------------------------------------------
Delete static _cpuImplicitSolvent object if set
@return SimTKOpenMMCommon::DefaultReturn if _cpuImplicitSolvent was set;
otherwise return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::deleteCpuImplicitSolvent( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::deleteCpuImplicitSolvent";
// ---------------------------------------------------------------------------------------
if( _cpuImplicitSolvent != NULL ){
delete _cpuImplicitSolvent;
_cpuImplicitSolvent = NULL;
return SimTKOpenMMCommon::DefaultReturn;
} else {
return SimTKOpenMMCommon::ErrorReturn;
}
}
/**---------------------------------------------------------------------------------------
Set static member _cpuImplicitSolvent
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::setCpuImplicitSolvent( CpuImplicitSolvent* cpuImplicitSolvent ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::setCpuImplicitSolvent";
// ---------------------------------------------------------------------------------------
_cpuImplicitSolvent = cpuImplicitSolvent;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get static member cpuImplicitSolvent
@return static member cpuImplicitSolvent
--------------------------------------------------------------------------------------- */
CpuImplicitSolvent* CpuImplicitSolvent::getCpuImplicitSolvent( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::getCpuImplicitSolvent";
// ---------------------------------------------------------------------------------------
return _cpuImplicitSolvent;
}
/**---------------------------------------------------------------------------------------
Set energy
@param energy
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::setEnergy( RealOpenMM energy ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::setEnergy";
// ---------------------------------------------------------------------------------------
_implicitSolventEnergy = energy;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Return ImplicitSolventParameters
@return ImplicitSolventParameters
--------------------------------------------------------------------------------------- */
ImplicitSolventParameters* CpuImplicitSolvent::getImplicitSolventParameters( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::getImplicitSolventParameters";
// ---------------------------------------------------------------------------------------
return _implicitSolventParameters;
}
/**---------------------------------------------------------------------------------------
Set ImplicitSolventParameters
@param ImplicitSolventParameters
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::setImplicitSolventParameters( ImplicitSolventParameters* implicitSolventParameters ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::setImplicitSolventParameters";
// ---------------------------------------------------------------------------------------
_implicitSolventParameters = implicitSolventParameters;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Return flag signalling whether AceApproximation for nonpolar term is to be included
@return flag
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::includeAceApproximation( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::includeAceApproximation";
// ---------------------------------------------------------------------------------------
return _includeAceApproximation;
}
/**---------------------------------------------------------------------------------------
Set flag indicating whether AceApproximation is to be included
@param includeAceApproximation new includeAceApproximation value
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::setIncludeAceApproximation( int includeAceApproximation ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::setImplicitSolventParameters";
// ---------------------------------------------------------------------------------------
_includeAceApproximation = includeAceApproximation;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Return ForceConversionFactor for units
@return ForceConversionFactor
--------------------------------------------------------------------------------------- */
RealOpenMM CpuImplicitSolvent::getForceConversionFactor( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::getForceConversionFactor";
// ---------------------------------------------------------------------------------------
return _forceConversionFactor;
}
/**---------------------------------------------------------------------------------------
Set ForceConversionFactor
@param ForceConversionFactor (units conversion)
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::setForceConversionFactor( RealOpenMM forceConversionFactor ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::setForceConversionFactor";
// ---------------------------------------------------------------------------------------
_forceConversionFactor = forceConversionFactor;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Return EnergyConversionFactor for units
@return EnergyConversionFactor
--------------------------------------------------------------------------------------- */
RealOpenMM CpuImplicitSolvent::getEnergyConversionFactor( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::getEnergyConversionFactor";
// ---------------------------------------------------------------------------------------
return _energyConversionFactor;
}
/**---------------------------------------------------------------------------------------
Set EnergyConversionFactor
@param EnergyConversionFactor (units conversion)
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::setEnergyConversionFactor( RealOpenMM energyConversionFactor ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::setEnergyConversionFactor";
// ---------------------------------------------------------------------------------------
_energyConversionFactor = energyConversionFactor;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Return ForceCallIndex -- number of times forces have been calculated
@return ForceCallIndex
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::getForceCallIndex( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::getForceCallIndex";
// ---------------------------------------------------------------------------------------
return _forceCallIndex;
}
/**---------------------------------------------------------------------------------------
Increment ForceCallIndex
@return incremented forceCallIndex
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::incrementForceCallIndex( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::incrementForceCallIndex";
// ---------------------------------------------------------------------------------------
_forceCallIndex++;
return _forceCallIndex;
}
/**---------------------------------------------------------------------------------------
Return bornForce, a work array of size _implicitSolventParameters->getNumberOfAtoms()*sizeof( RealOpenMM )
On first call, memory for array is allocated if not set
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* CpuImplicitSolvent::getBornForce( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::getImplicitSolventBornForce";
// ---------------------------------------------------------------------------------------
if( _bornForce == NULL ){
_bornForce = new RealOpenMM[_implicitSolventParameters->getNumberOfAtoms()];
}
return _bornForce;
}
/**---------------------------------------------------------------------------------------
Return Born radii: size = _implicitSolventParameters->getNumberOfAtoms()
On first call, memory for array is allocated if it is not set
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* CpuImplicitSolvent::getBornRadii( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::getBornRadii";
// ---------------------------------------------------------------------------------------
if( _bornRadii == NULL ){
_bornRadii = new RealOpenMM[_implicitSolventParameters->getNumberOfAtoms()];
_bornRadii[0] = 0.0;
}
return _bornRadii;
}
/**---------------------------------------------------------------------------------------
Return Born radii: size = _implicitSolventParameters->getNumberOfAtoms()
@return array
--------------------------------------------------------------------------------------- */
const RealOpenMM* CpuImplicitSolvent::getBornRadiiConst( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::getBornRadii";
// ---------------------------------------------------------------------------------------
return _bornRadii;
}
/**---------------------------------------------------------------------------------------
Return Born radii temp work array of size=_implicitSolventParameters->getNumberOfAtoms()
On first call, memory for array is allocated if not set
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* CpuImplicitSolvent::getBornRadiiTemp( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::getImplicitSolventBornRadiiTemp";
// ---------------------------------------------------------------------------------------
if( _tempBornRadii == NULL ){
_tempBornRadii = new RealOpenMM[_implicitSolventParameters->getNumberOfAtoms()];
}
return _tempBornRadii;
}
/**---------------------------------------------------------------------------------------
Compute Born radii
@param atomCoordinates atomic coordinates
@param bornRadii output array of Born radii
@param obcChain output array of Obc chain derivatives
@return SimTKOpenMMCommon::DefaultReturn or SimTKOpenMMCommon::ErrorReturn
if problems encountered
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::computeBornRadii( RealOpenMM** atomCoordinates, RealOpenMM* bornRadii,
RealOpenMM* obcChain ){
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nCpuImplicitSolvent::computeBornRadii";
// ---------------------------------------------------------------------------------------
std::stringstream message;
message << methodName;
message << " Error: calling from base class.";
SimTKOpenMMLog::printError( message );
return SimTKOpenMMCommon::ErrorReturn;
}
/**---------------------------------------------------------------------------------------
Get Born energy and forces
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@param forces forces (output)
@param updateBornRadii if set, then Born radii are updated for current configuration;
otherwise radii correspond to configuration from previous iteration
@return SimTKOpenMMCommon::DefaultReturn; abort if cpuImplicitSolvent is not set
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::computeImplicitSolventForces( RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges,
RealOpenMM** forces, int updateBornRadii ){
// ---------------------------------------------------------------------------------------
int printSampleOutput = 0;
static const char* methodName = "\nCpuImplicitSolvent::computeImplicitSolventForces";
// ---------------------------------------------------------------------------------------
int callId = incrementForceCallIndex();
// check parameters have been initialized
ImplicitSolventParameters* implicitSolventParameters = getImplicitSolventParameters();
if( !implicitSolventParameters ){
std::stringstream message;
message << methodName;
message << " implicitSolventParameters has not been initialized!";
SimTKOpenMMLog::printError( message );
return SimTKOpenMMCommon::ErrorReturn;
}
// check if parameters good-to-go
// radii and scalefactors (OBC) need to be set
if( callId == 1 ){
if( implicitSolventParameters->isNotReady() ){
std::stringstream message;
message << methodName;
message << " implicitSolventParameters are not set for force calculations!";
SimTKOpenMMLog::printError( message );
return SimTKOpenMMCommon::ErrorReturn;
} else {
std::stringstream message;
message << methodName;
message << " implicitSolventParameters appear to be set.";
// SimTKOpenMMLog::printMessage( message );
}
}
// check to see if Born radii have been previously calculated
// if not, then calculate;
// logic here assumes that the radii are intitialized to zero
// and then once computed, always greater than zero.
// after first iteration Born radii are updated in force calculation (computeBornEnergyForces())
// unless updateBornRadii is set
RealOpenMM* bornRadii = getBornRadii();
if( updateBornRadii || bornRadii[0] < (RealOpenMM) 0.0001 || callId == 1 ){
computeBornRadii( atomCoordinates, bornRadii );
// diagnostics
if( printSampleOutput ){
RealOpenMM* atomicRadii = implicitSolventParameters->getAtomicRadii();
std::stringstream message;
message.precision( 6 );
message.width( 12 );
message << methodName;
int numberOfAtoms = implicitSolventParameters->getNumberOfAtoms();
message << " initialize Born radii for " << numberOfAtoms << " atoms on call=" << callId;
for( int ii = 0; ii < printSampleOutput && ii < numberOfAtoms; ii++ ){
message << "\n " << ii << " rad=" << atomicRadii[ii] << " q=" << partialCharges[ii] << " bR=" << bornRadii[ii] << " X[";
SimTKOpenMMUtilities::formatRealStringStream( message, atomCoordinates[ii] );
message << "]";
}
message << "\n";
int startIndex = implicitSolventParameters->getNumberOfAtoms() - printSampleOutput > 0 ?
implicitSolventParameters->getNumberOfAtoms() - printSampleOutput : numberOfAtoms;
for( int ii = startIndex; ii < numberOfAtoms; ii++ ){
message << "\n " << ii << " " << atomicRadii[ii] << " " << bornRadii[ii] << " X[";
SimTKOpenMMUtilities::formatRealStringStream( message, atomCoordinates[ii] );
message << "]";
}
SimTKOpenMMLog::printMessage( message );
}
}
// compute forces
computeBornEnergyForces( getBornRadii(), atomCoordinates,
partialCharges, forces );
// diagnostics
if( printSampleOutput && callId == 1 ){
static int internalId = 0;
int processId = internalId++ + callId;
std::stringstream message;
message.precision( 6 );
message.width( 12 );
int numberOfAtoms = implicitSolventParameters->getNumberOfAtoms();
message << methodName;
message << " call=" << callId << " E=" << getEnergy() << " " << numberOfAtoms << " atoms.";
for( int ii = 0; ii < printSampleOutput && ii < numberOfAtoms; ii++ ){
message << "\n " << ii << " [ ";
SimTKOpenMMUtilities::formatRealStringStream( message, forces[ii] );
message << "] bRad=" << bornRadii[ii];
}
message << "\n";
int startIndex = implicitSolventParameters->getNumberOfAtoms() - printSampleOutput > 0 ?
implicitSolventParameters->getNumberOfAtoms() - printSampleOutput : numberOfAtoms;
for( int ii = startIndex; ii < numberOfAtoms; ii++ ){
message << "\n " << ii << " [ ";
SimTKOpenMMUtilities::formatRealStringStream( message, forces[ii] );
message << "] bRad=" << bornRadii[ii];
}
SimTKOpenMMLog::printMessage( message );
// write Born forces
std::stringstream resultsFileName;
resultsFileName << getBaseFileName() << "." << processId << ".gbsa0";
writeBornEnergyForces( atomCoordinates, partialCharges, forces, resultsFileName.str() );
}
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get Born energy and forces based on J. Phys. Chem. A V101 No 16, p. 3005 (Simbios)
@param bornRadii Born radii -- optional; if NULL, then ImplicitSolventParameters
entry is used
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@param forces forces
@return SimTKOpenMMCommon::ErrorReturn since the call should be implemented
in a derived class
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::computeBornEnergyForces( RealOpenMM* bornRadii,
RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges,
RealOpenMM** forces ){
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nCpuImplicitSolvent::computeBornEnergyForces";
// ---------------------------------------------------------------------------------------
std::stringstream message;
message << methodName;
message << " Error: calling from base class.";
SimTKOpenMMLog::printError( message );
return SimTKOpenMMCommon::ErrorReturn;
}
/**---------------------------------------------------------------------------------------
Get nonpolar solvation force constribution via ACE approximation
@param implicitSolventParameters 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 CpuImplicitSolvent::computeAceNonPolarForce( const ImplicitSolventParameters* implicitSolventParameters,
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 = implicitSolventParameters->getProbeRadius();
const RealOpenMM surfaceAreaFactor = implicitSolventParameters->getPi4Asolv();
const RealOpenMM* atomicRadii = implicitSolventParameters->getAtomicRadii();
int numberOfAtoms = implicitSolventParameters->getNumberOfAtoms();
// 1 + 1 + pow + 3 + 1 + 2 FLOP
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 = surfaceAreaFactor*r*r*ratio6;
*energy += saTerm;
forces[atomI] += minusSix*saTerm/bornRadii[atomI];
}
}
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Write Born energy and forces (Simbios)
@param atomCoordinates atomic coordinates
@param forces forces
@param resultsFileName output file name
@return SimTKOpenMMCommon::DefaultReturn unless
file cannot be opened
in which case return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::writeBornEnergyForces( RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges,
RealOpenMM** forces,
const std::string& resultsFileName ) const {
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nCpuImplicitSolvent::writeBornEnergyForces";
// ---------------------------------------------------------------------------------------
ImplicitSolventParameters* implicitSolventParameters = getImplicitSolventParameters();
int numberOfAtoms = implicitSolventParameters->getNumberOfAtoms();
const RealOpenMM* atomicRadii = implicitSolventParameters->getAtomicRadii();
const RealOpenMM* bornRadii = getBornRadiiConst();
// ---------------------------------------------------------------------------------------
// 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 format: coords bornRadii q atomicRadii forces\n", numberOfAtoms );
RealOpenMM forceConversion = 1.0;
RealOpenMM lengthConversion = 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 %.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],
forceConversion*forces[ii][0],
forceConversion*forces[ii][1],
forceConversion*forces[ii][2]
);
}
}
(void) fclose( implicitSolventResultsFile );
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get BaseFileName
@return baseFileName
--------------------------------------------------------------------------------------- */
const std::string& CpuImplicitSolvent::getBaseFileName( void ) const {
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "\nCpuImplicitSolvent::getBaseFileName";
// ---------------------------------------------------------------------------------------
return _baseFileName;
}
/**---------------------------------------------------------------------------------------
Set BaseFileName
@param input baseFileName
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::setBaseFileName( const std::string& baseFileName ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "\nCpuImplicitSolvent::setBaseFileName";
// ---------------------------------------------------------------------------------------
_baseFileName = baseFileName;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Set OutputFileFrequency
@param input outputFileFrequency
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::setOutputFileFrequency( int outputFileFrequency ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "\nCpuImplicitSolvent::setOutputFileFrequency";
// ---------------------------------------------------------------------------------------
_outputFileFrequency = outputFileFrequency;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get OutputFileFrequency
@return output file frequency
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::getOutputFileFrequency( void ) const {
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "\nCpuImplicitSolvent::getOutputFileFrequency";
// ---------------------------------------------------------------------------------------
return _outputFileFrequency;
}
/**---------------------------------------------------------------------------------------
Read info file
@param infoFileName file name to read
@return SimTKOpenMMCommon::DefaultReturn if ok; else SimTKOpenMMCommon::ErrorReturn; if major
problem, program will exit
--------------------------------------------------------------------------------------- */
int CpuImplicitSolvent::readInfoFile( const std::string infoFileName ){
// ---------------------------------------------------------------------------------------
const int bufferSize = 2048;
char buffer[bufferSize];
static const std::string methodName = "\nCpuImplicitSolvent::readInfoFile";
// ---------------------------------------------------------------------------------------
FILE* infoFile = NULL;
#ifdef WIN32
fopen_s( &infoFile, infoFileName.c_str(), "r" );
#else
infoFile = fopen( infoFileName.c_str(), "r" );
#endif
if( infoFile == NULL ){
#ifdef WIN32
fopen_s( &infoFile, _defaultInfoFileName.c_str(), "r" );
#else
infoFile = fopen( _defaultInfoFileName.c_str(), "r" );
#endif
if( infoFile == NULL ){
std::stringstream message;
message << methodName << " fopen failed on info file=<" << _defaultInfoFileName << "> and file=<" << infoFileName << ">";
SimTKOpenMMLog::printMessage( message );
return SimTKOpenMMCommon::ErrorReturn;
} else {
std::stringstream message;
message << methodName << " opened info file=<" << _defaultInfoFileName << ">.";
SimTKOpenMMLog::printMessage( message );
}
} else {
std::stringstream message;
message << methodName << " opened info file=<" << infoFileName << ">.";
SimTKOpenMMLog::printMessage( message );
}
/* Sample file:
*/
int errors = 0;
while( fgets( buffer, bufferSize, infoFile ) ){
std::stringstream message;
std::string fileName = std::string( );
size_t bufferLen = strlen( buffer );
if( bufferLen > 0 ){
buffer[bufferLen-1] = '\0';
}
message << "\n<" << buffer << ">";
//fprintf( amoebaLog->getLogFile(), "\nreadInfoFile <%s>", buffer );
//fflush( amoebaLog->getLogFile() );
StringVector tokens;
SimTKOpenMMUtilities::tokenizeString( buffer, tokens );
bool done = false;
for( StringVectorI ii = tokens.begin(); ii != tokens.end() && !done; ii++ ){
std::string token = *ii;
size_t tokenLength = token.length();
bool recognized = false;
// skip comments and blank lines
if( tokenLength < 2 || !token.compare( "#" ) ){
done = true;
recognized = true;
// base file name
} else if( !token.compare( CpuImplicitSolvent::CpuImplicitSolventBaseFileName ) ){
recognized = true;
setBaseFileName( *(++ii) );
// file frequency
} else if( !token.compare( CpuImplicitSolvent::CpuImplicitSolventFileGenerationFrequency ) ){
recognized = true;
std::string value = *(++ii);
if( SimTKOpenMMUtilities::isValidInteger( value ) ){
setOutputFileFrequency( atoi( value.c_str() ) );
} else {
message << "\nToken=<" << token << "> is not a valid integer for key=" << CpuImplicitSolvent::CpuImplicitSolventFileGenerationFrequency;
}
// keys used by objects other than 'CpuImplicitSolvent'
} else {
/*
recognized = true;
std::string key = *ii;
ii++;
if( ii != tokens.end() ){
_inputArguments[key] = *ii;
} else {
_inputArguments[key] = CpuImplicitSolventCommon::Comment;
}
*/
}
if( !recognized ){
message << "\nToken=<" << token << "> not recognized.";
}
}
SimTKOpenMMLog::printMessage( message );
}
(void) fclose( infoFile );
// report if errors
if( errors ){
std::stringstream message;
message << "\nErrors -- aborting.\n";
SimTKOpenMMLog::printMessage( message );
exit(-1);
} else {
std::stringstream message;
message << "\nNo errors detected parsing info file " << infoFileName << "\n";
/*
message << "\nNumber of hash arguments=" << _amoebaInputArguments.size() << " <key,value> pairs listed below:\n";
for( StringStringMapCI ii = _amoebaInputArguments.begin(); ii != _amoebaInputArguments.end(); ii++ ){
message << "\n <" << (*ii).first << ">=<" << (*ii).second << ">";
}
*/
message << "\n\n";
SimTKOpenMMLog::printMessage( message );
}
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get string w/ state
@param title title (optional)
@return string containing state
--------------------------------------------------------------------------------------- */
std::string CpuImplicitSolvent::getStateString( const char* title ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuImplicitSolvent::getStateString";
// ---------------------------------------------------------------------------------------
std::stringstream message;
if( title ){
message << title;
}
message << "\nImplicitSolvent info:";
message << "\nForce conversion=" << getForceConversionFactor() << " Energy conversion=" << getEnergyConversionFactor();
message << "\nInclude ACE approximation=";
if( includeAceApproximation() ){
message << "Y";
} else {
message << "N";
}
// get parameters
message << getImplicitSolventParameters()->getStateString( NULL );
return message.str();
}
/* ---------------------------------------------------------------------------------------
Override C++ new w/ Gromac's smalloc/sfree (Simbios)
@param size bytes to allocate
@return ptr to allocated memory
--------------------------------------------------------------------------------------- */
/*
void* CpuImplicitSolvent::operator new( size_t size ){
void *ptr;
smalloc(ptr, (int) size);
// (void) fprintf( stdout, "\nCpuImplicitSolvent new called -- size=%u", size );
// (void) fflush( stdout );
return ptr;
} */
/* ---------------------------------------------------------------------------------------
Override C++ delete w/ Gromac's sfree (Simbios)
@param ptr ptr to block to free
--------------------------------------------------------------------------------------- */
/*
void CpuImplicitSolvent::operator delete( void *ptr ){
// (void) fprintf( stdout, "\nCpuImplicitSolvent delete called." );
// (void) fflush( stdout );
sfree( ptr );
} */
/* ---------------------------------------------------------------------------------------
Override C++ new w/ Gromac's smalloc/sfree (Simbios)
@param size bytes to allocate
@return ptr to allocated memory
--------------------------------------------------------------------------------------- */
/*
void* CpuImplicitSolvent::operator new[]( size_t size ){
void *ptr;
smalloc(ptr, (int) size);
// (void) fprintf( stdout, "\nCpuImplicitSolvent new[] called -- size=%u", size );
// (void) fflush( stdout );
return ptr;
} */
/* ---------------------------------------------------------------------------------------
Override C++ delete w/ Gromac's sfree (Simbios)
@param ptr ptr to block to free
--------------------------------------------------------------------------------------- */
/*
void CpuImplicitSolvent::operator delete[]( void *ptr ){
// (void) fprintf( stdout, "\nCpuImplicitSolvent delete[] called." );
// (void) fflush( stdout );
sfree( ptr );
}
*/
/* 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 __CpuImplicitSolvent_H__
#define __CpuImplicitSolvent_H__
#include "ImplicitSolventParameters.h"
// ---------------------------------------------------------------------------------------
class CpuImplicitSolvent {
public:
// fields in info file
const static std::string CpuImplicitSolventBaseFileName;
const static std::string CpuImplicitSolventFileGenerationFrequency;
private:
// default info file name
static std::string _defaultInfoFileName;
// base file name
std::string _baseFileName;
// frequency to output diagnostic files
int _outputFileFrequency;
// used for direct calls
static CpuImplicitSolvent* _cpuImplicitSolvent;
// parameters
ImplicitSolventParameters* _implicitSolventParameters;
// flag to signal whether ACE approximation
// is to be included
int _includeAceApproximation;
// force index call
int _forceCallIndex;
// work arrays
RealOpenMM* _bornForce;
// Born radii and force
RealOpenMM* _bornRadii;
RealOpenMM* _tempBornRadii;
// convert units for energy/force
RealOpenMM _forceConversionFactor;
RealOpenMM _energyConversionFactor;
// Ed, 2007-04-27: Store the energy internally
RealOpenMM _implicitSolventEnergy;
/**---------------------------------------------------------------------------------------
Initialize data members -- potentially more than
one constructor, so centralize intialization here
--------------------------------------------------------------------------------------- */
void _initializeDataMembers( void );
protected:
/**---------------------------------------------------------------------------------------
Return implicitSolventBornForce, a work array of size _implicitSolventParameters->getNumberOfAtoms()*sizeof( RealOpenMM )
On first call, memory for array is allocated if not set
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* getBornForce( void );
/**---------------------------------------------------------------------------------------
Return Born radii temp work array of size=_implicitSolventParameters->getNumberOfAtoms()
On first call, memory for array is allocated if not set
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* getBornRadiiTemp( void );
/**---------------------------------------------------------------------------------------
Set energy
@param energy new energy
ireturn SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setEnergy( RealOpenMM energy );
public:
/**---------------------------------------------------------------------------------------
Constructor
@param implicitSolventParameters ImplicitSolventParameters reference
@return CpuImplicitSolvent object
--------------------------------------------------------------------------------------- */
CpuImplicitSolvent( ImplicitSolventParameters* implicitSolventParameters );
/**---------------------------------------------------------------------------------------
Destructor
--------------------------------------------------------------------------------------- */
~CpuImplicitSolvent( );
// override of new/delete -- used when run in PS3 framework(?)
// static void* operator new( size_t size );
// static void operator delete( void *p );
// static void* operator new[]( size_t size );
// static void operator delete[]( void *p );
/**---------------------------------------------------------------------------------------
Delete static _cpuImplicitSolvent object if set
@return SimTKOpenMMCommon::DefaultReturn if _cpuImplicitSolvent was set;
otherwise return SimTKOpenMMCommon::ErrorReturn
--------------------------------------------------------------------------------------- */
static int deleteCpuImplicitSolvent( void );
/**---------------------------------------------------------------------------------------
Set static member _cpuImplicitSolvent
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
static int setCpuImplicitSolvent( CpuImplicitSolvent* cpuImplicitSolvent );
/**---------------------------------------------------------------------------------------
Get static member cpuImplicitSolvent
@return static member cpuImplicitSolvent
--------------------------------------------------------------------------------------- */
static CpuImplicitSolvent* getCpuImplicitSolvent( void );
/**---------------------------------------------------------------------------------------
Get number of atoms
@return number of atoms
--------------------------------------------------------------------------------------- */
int getNumberOfAtoms( void ) const;
/**---------------------------------------------------------------------------------------
Get energy
@return energy
--------------------------------------------------------------------------------------- */
RealOpenMM getEnergy( void ) const;
/**---------------------------------------------------------------------------------------
Return ImplicitSolventParameters
@return ImplicitSolventParameters
--------------------------------------------------------------------------------------- */
ImplicitSolventParameters* getImplicitSolventParameters( void ) const;
/**---------------------------------------------------------------------------------------
Set ImplicitSolventParameters
@param ImplicitSolventParameters
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setImplicitSolventParameters( ImplicitSolventParameters* implicitSolventParameters );
/**---------------------------------------------------------------------------------------
Return flag signalling whether AceApproximation for nonpolar term is to be included
@return flag
--------------------------------------------------------------------------------------- */
int includeAceApproximation( void ) const;
/**---------------------------------------------------------------------------------------
Set flag indicating whether AceApproximation is to be included
@param includeAceApproximation new includeAceApproximation value
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setIncludeAceApproximation( int includeAceApproximation );
/**---------------------------------------------------------------------------------------
Return ForceConversionFactor for units
@return ForceConversionFactor
--------------------------------------------------------------------------------------- */
RealOpenMM getForceConversionFactor( void ) const;
/**---------------------------------------------------------------------------------------
Set ForceConversionFactor
@param ForceConversionFactor (units conversion)
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setForceConversionFactor( RealOpenMM forceConversionFactor );
/**---------------------------------------------------------------------------------------
Return EnergyConversionFactor for units
@return EnergyConversionFactor
--------------------------------------------------------------------------------------- */
RealOpenMM getEnergyConversionFactor( void ) const;
/**---------------------------------------------------------------------------------------
Set EnergyConversionFactor
@param EnergyConversionFactor (units conversion)
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setEnergyConversionFactor( RealOpenMM energyConversionFactor );
/**---------------------------------------------------------------------------------------
Return ForceCallIndex -- number of times forces have been calculated
@return ForceCallIndex
--------------------------------------------------------------------------------------- */
int getForceCallIndex( void ) const;
/**---------------------------------------------------------------------------------------
Increment ForceCallIndex
@return incremented forceCallIndex
--------------------------------------------------------------------------------------- */
int incrementForceCallIndex( void );
/**---------------------------------------------------------------------------------------
Return Born radii: size = _implicitSolventParameters->getNumberOfAtoms()
On first call, memory for array is allocated if not set
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* getBornRadii( void );
/**---------------------------------------------------------------------------------------
Return Born radii: size = _implicitSolventParameters->getNumberOfAtoms()
@return array
--------------------------------------------------------------------------------------- */
const RealOpenMM* getBornRadiiConst( void ) const;
/**---------------------------------------------------------------------------------------
Get Born energy and forces
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@param forces forces (output); if not set on input, then memory is allocated
@param updateBornRadii if set, then Born radii are updated for current configuration;
otherwise radii correspond to configuration from previous iteration
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int computeImplicitSolventForces( RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges,
RealOpenMM** forces, int updateBornRadii = 0 );
/**---------------------------------------------------------------------------------------
Get Born radii based on J. Phys. Chem. A V101 No 16, p. 3005 (Simbios)
@param atomCoordinates atomic coordinates dimension: [0-numberAtoms-1][0-2]
@param bornRadii output array of Born radii
@param obcChain output array of OBC chain derivative
@return array of Born radii
--------------------------------------------------------------------------------------- */
virtual int computeBornRadii( RealOpenMM** atomCoordinates, RealOpenMM* bornRadii,
RealOpenMM* obcChain = NULL );
/**---------------------------------------------------------------------------------------
Get Born energy and forces based on J. Phys. Chem. A V101 No 16, p. 3005 (Simbios)
@param bornRadii Born radii
@param atomCoordinates atomic coordinates
@param partialCharges partial charges
@param forces forces
@return force array
--------------------------------------------------------------------------------------- */
virtual int computeBornEnergyForces( RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces );
/**---------------------------------------------------------------------------------------
Get nonpolar solvation force constribution via ACE approximation
@param implicitSolventParameters parameters
@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 ImplicitSolventParameters* implicitSolventParameters,
const RealOpenMM* bornRadii, RealOpenMM* energy,
RealOpenMM* forces ) 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
--------------------------------------------------------------------------------------- */
virtual int writeBornEnergyForces( RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces,
const std::string& resultsFileName ) const;
/**---------------------------------------------------------------------------------------
Get string w/ state
@param title title (optional)
@return string containing state
--------------------------------------------------------------------------------------- */
std::string getStateString( const char* title ) const;
/**---------------------------------------------------------------------------------------
Get BaseFileName
@return baseFileName
--------------------------------------------------------------------------------------- */
const std::string& getBaseFileName( void ) const;
/**---------------------------------------------------------------------------------------
Set BaseFileName
@param input baseFileName
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setBaseFileName( const std::string& baseFileName );
/**---------------------------------------------------------------------------------------
Get OutputFileFrequency
@return outputFileFrequency
--------------------------------------------------------------------------------------- */
int getOutputFileFrequency( void ) const;
/**---------------------------------------------------------------------------------------
Set OutputFileFrequency
@param input outputFileFrequency
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setOutputFileFrequency( int outputFileFrequency );
/**---------------------------------------------------------------------------------------
Read info file
@param infoFileName file name to read
@return CpuImplicitSolventCommon::DefaultReturn if ok; else CpuImplicitSolventCommon::ErrorReturn; if major
problem, program will exit
--------------------------------------------------------------------------------------- */
int readInfoFile( const std::string infoFileName );
/**---------------------------------------------------------------------------------------
Get output file name (helper method) (Simbios)
fileName = (inputFileName || getBaseFileName()) . getForceCallIndex() . suffix
if inputFileName is NULL, then use getBaseFileName() as base file name
if getForceCallIndex() > 0, insert '.getForceCallIndex()'
append suffix, if not NULL
@param inputFileName inputFileName
@param suffix file suffix
@return file name
--------------------------------------------------------------------------------------- */
std::string getOutputFileName( const std::string* inputFileName, const std::string* suffix ) const;
/**---------------------------------------------------------------------------------------
Write Tinker xyz file (Simbios)
@param numberOfAtoms number of atoms
@param atomCoordinates atom coordinates
@param atomNames atom names
@param header header
@param xyzFileName output file name
@param bondsArray bond array -- used to print 1-2 bonds
@return 0 unless error detected
Currently no attempt is made to get the atom name/type to accurately
reflect the Tinker names/types. Rather method is used to output atoms
in Gromacs order and then reorder those in a corresponding xyz file
w/ the correct atom names/types so that they match the Gromacs order
This makes it easier to compare results between Gromacs and Tinker
--------------------------------------------------------------------------------------- */
/*
static int writeXyzFile( int numberOfAtoms, const RealOpenMM** atomCoordinates,
const char** atomNames,
const std::string& header, const std::string& xyzFileName,
const implicitSolventBonds** bondsArray ); */
};
// ---------------------------------------------------------------------------------------
#endif // __CpuImplicitSolvent_H__
/* 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.
*/
#include <string.h>
#include <sstream>
#include "../SimTKUtilities/SimTKOpenMMCommon.h"
#include "../SimTKUtilities/SimTKOpenMMLog.h"
#include "../SimTKUtilities/SimTKOpenMMUtilities.h"
#include "CpuObc.h"
#include <math.h>
/**---------------------------------------------------------------------------------------
CpuObc constructor
obcParameters obcParameters object
--------------------------------------------------------------------------------------- */
CpuObc::CpuObc( ImplicitSolventParameters* obcParameters ) : CpuImplicitSolvent( obcParameters ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::CpuObc";
// ---------------------------------------------------------------------------------------
_initializeObcDataMembers( );
_obcParameters = static_cast<ObcParameters*> (obcParameters);
}
/**---------------------------------------------------------------------------------------
CpuObc destructor
--------------------------------------------------------------------------------------- */
CpuObc::~CpuObc( ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::~CpuObc";
// ---------------------------------------------------------------------------------------
//if( _obcParameters != NULL ){
// delete _obcParameters;
//}
delete[] _obcChain;
delete[] _obcChainTemp;
}
/**---------------------------------------------------------------------------------------
Initialize data members
--------------------------------------------------------------------------------------- */
void CpuObc::_initializeObcDataMembers( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::initializeDataMembers";
// ---------------------------------------------------------------------------------------
_obcParameters = NULL;
_obcChain = NULL;
_obcChainTemp = NULL;
}
/**---------------------------------------------------------------------------------------
Get ObcParameters reference
@return ObcParameters reference
--------------------------------------------------------------------------------------- */
ObcParameters* CpuObc::getObcParameters( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::getObcParameters";
// ---------------------------------------------------------------------------------------
return _obcParameters;
}
/**---------------------------------------------------------------------------------------
Set ObcParameters reference
@param ObcParameters reference
@return SimTKOpenMMCommon::DefaultReturn;
--------------------------------------------------------------------------------------- */
int CpuObc::setObcParameters( ObcParameters* obcParameters ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::setObcParameters";
// ---------------------------------------------------------------------------------------
_obcParameters = obcParameters;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Return OBC chain derivative: size = _obcParameters->getNumberOfAtoms()
On first call, memory for array is allocated if not set
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* CpuObc::getObcChain( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::getObcChain";
// ---------------------------------------------------------------------------------------
if( _obcChain == NULL ){
_obcChain = new RealOpenMM[_obcParameters->getNumberOfAtoms()];
}
return _obcChain;
}
/**---------------------------------------------------------------------------------------
Return OBC chain derivative: size = _obcParameters->getNumberOfAtoms()
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* CpuObc::getObcChainConst( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::getObcChain";
// ---------------------------------------------------------------------------------------
return _obcChain;
}
/**---------------------------------------------------------------------------------------
Return OBC chain temp work array of size=_obcParameters->getNumberOfAtoms()
On first call, memory for array is allocated if not set
@return array
--------------------------------------------------------------------------------------- */
RealOpenMM* CpuObc::getObcChainTemp( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::getImplicitSolventObcChainTemp";
// ---------------------------------------------------------------------------------------
if( _obcChainTemp == NULL ){
_obcChainTemp = new RealOpenMM[_obcParameters->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 CpuObc::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 = "\nCpuObc::computeBornRadii";
// ---------------------------------------------------------------------------------------
ObcParameters* obcParameters = getObcParameters();
int numberOfAtoms = obcParameters->getNumberOfAtoms();
RealOpenMM* atomicRadii = obcParameters->getAtomicRadii();
const RealOpenMM* scaledRadiusFactor = obcParameters->getScaledRadiusFactors();
if( !obcChain ){
obcChain = getObcChain();
}
RealOpenMM dielectricOffset = obcParameters->getDielectricOffset();
RealOpenMM alphaObc = obcParameters->getAlphaObc();
RealOpenMM betaObc = obcParameters->getBetaObc();
RealOpenMM gammaObc = obcParameters->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 deltaX = atomCoordinates[atomJ][0] - atomCoordinates[atomI][0];
RealOpenMM deltaY = atomCoordinates[atomJ][1] - atomCoordinates[atomI][1];
RealOpenMM deltaZ = atomCoordinates[atomJ][2] - atomCoordinates[atomI][2];
RealOpenMM r2 = deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ;
RealOpenMM r = SQRT( r2 );
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);
if( offsetRadiusI < (scaledRadiusJ - r) ){
term += two*( radiusIInverse - l_ij);
}
sum += 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( logFile && atomI >= 0 ){
(void) fprintf( logFile, "\nRRQ %d sum=%12.6e tanhS=%12.6e radI=%.5f %.5f born=%12.6e obc=%12.6e",
atomI, sum, tanhSum, radiusI, offsetRadiusI, bornRadii[atomI], obcChain[atomI] );
}
*/
}
/*
if( logFile ){
(void) fclose( logFile );
}
*/
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get Obc Born energy and forces
@param bornRadii Born radii -- optional; if NULL, then ObcParameters
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 CpuObc::computeBornEnergyForces( RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::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 ObcParameters* obcParameters = getObcParameters();
const int numberOfAtoms = obcParameters->getNumberOfAtoms();
if( bornRadii == NULL ){
bornRadii = getBornRadii();
}
// ---------------------------------------------------------------------------------------
// constants
const RealOpenMM preFactor = obcParameters->getPreFactor();
const RealOpenMM electricConstant = obcParameters->getElectricConstant();
const RealOpenMM dielectricOffset = obcParameters->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( obcParameters, 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++ ){
// 3 FLOP
RealOpenMM deltaX = atomCoordinates[atomJ][0] - atomCoordinates[atomI][0];
RealOpenMM deltaY = atomCoordinates[atomJ][1] - atomCoordinates[atomI][1];
RealOpenMM deltaZ = atomCoordinates[atomJ][2] - atomCoordinates[atomI][2];
// 5 FLOP
RealOpenMM r2 = deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ;
// 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 = obcParameters->getAtomicRadii();
const RealOpenMM alphaObc = obcParameters->getAlphaObc();
const RealOpenMM betaObc = obcParameters->getBetaObc();
const RealOpenMM gammaObc = obcParameters->getGammaObc();
const RealOpenMM* scaledRadiusFactor = obcParameters->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 deltaX = atomCoordinates[atomJ][0] - atomCoordinates[atomI][0];
RealOpenMM deltaY = atomCoordinates[atomJ][1] - atomCoordinates[atomI][1];
RealOpenMM deltaZ = atomCoordinates[atomJ][2] - atomCoordinates[atomI][2];
RealOpenMM r2 = deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ;
RealOpenMM r = SQRT( r2 );
// 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;
}
setEnergy( obcEnergy );
// copy new Born radii and obcChain values into permanent array
memcpy( bornRadii, bornRadiiTemp, arraySzInBytes );
memcpy( obcChain, obcChainTemp, arraySzInBytes );
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get string w/ state
@param title title (optional)
@return string containing state
--------------------------------------------------------------------------------------- */
std::string CpuObc::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 CpuObc::writeBornEnergyForces( RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces,
const std::string& resultsFileName ) const {
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nCpuObc::writeBornEnergyForces";
// ---------------------------------------------------------------------------------------
ImplicitSolventParameters* implicitSolventParameters = getImplicitSolventParameters();
const ObcParameters* obcParameters = static_cast<const ObcParameters*>(implicitSolventParameters);
int numberOfAtoms = obcParameters->getNumberOfAtoms();
const RealOpenMM* atomicRadii = obcParameters->getAtomicRadii();
const RealOpenMM* bornRadii = getBornRadiiConst();
const RealOpenMM* scaledRadii = obcParameters->getScaledRadiusFactors();
const RealOpenMM* obcChain = 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 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 CpuObc::writeForceLoop1( int numberOfAtoms, RealOpenMM** forces, const RealOpenMM* bornForce,
const std::string& outputFileName ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::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 CpuObc::writeForceLoop( int numberOfAtoms, const IntVector& chunkSizes,
const RealOpenMMPtrPtrVector& realRealOpenMMVector,
const RealOpenMMPtrVector& realVector,
const std::string& outputFileName ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::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;
line << (atomI+1) << " ";
int index = 0;
for( RealOpenMMPtrPtrVectorCI ii = realRealOpenMMVector.begin(); ii != realRealOpenMMVector.end(); ii++ ){
RealOpenMM** forces = *ii;
SimTKOpenMMUtilities::formatRealStringStream( line, forces[atomI], chunks[index++] );
line << " ";
}
for( RealOpenMMPtrVectorCI ii = realVector.begin(); ii != realVector.end(); ii++ ){
RealOpenMM* array = *ii;
line << array[atomI] << " ";
}
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 ObcParameters
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 CpuObc::computeBornEnergyForcesPrint( RealOpenMM* bornRadii, RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges, RealOpenMM** forces ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::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 ObcParameters* obcParameters = getObcParameters();
const int numberOfAtoms = obcParameters->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 = obcParameters->getPreFactor();
const RealOpenMM electricConstant = obcParameters->getElectricConstant();
const RealOpenMM dielectricOffset = obcParameters->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( obcParameters, 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++ ){
// 3 FLOP
RealOpenMM deltaX = atomCoordinates[atomJ][0] - atomCoordinates[atomI][0];
RealOpenMM deltaY = atomCoordinates[atomJ][1] - atomCoordinates[atomI][1];
RealOpenMM deltaZ = atomCoordinates[atomJ][2] - atomCoordinates[atomI][2];
// 5 FLOP
RealOpenMM r2 = deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ;
// 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", obcEnergy );
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
(void) fprintf( logFile, "\nWXX %d %.6e q=%.3f F[%.6e %.6e %.6e] ",
atomI, partialCharges[atomI], bornForces[atomI], forces[atomI][0], forces[atomI][1], forces[atomI][2] );
}
}
if( 0 ){
std::string outputFileName = "Loop1Cpu.txt";
CpuObc::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 = obcParameters->getAtomicRadii();
const RealOpenMM alphaObc = obcParameters->getAlphaObc();
const RealOpenMM betaObc = obcParameters->getBetaObc();
const RealOpenMM gammaObc = obcParameters->getGammaObc();
const RealOpenMM* scaledRadiusFactor = obcParameters->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( 0 ){
std::string outputFileName = "PostLoop1Cpu.txt";
IntVector chunkVector;
chunkVector.push_back( 3 );
RealOpenMMPtrPtrVector realPtrPtrVector;
realPtrPtrVector.push_back( forces );
RealOpenMMPtrVector realPtrVector;
realPtrVector.push_back( obcChain );
realPtrVector.push_back( bornRadii );
realPtrVector.push_back( bornForces );
CpuObc::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 deltaX = atomCoordinates[atomJ][0] - atomCoordinates[atomI][0];
RealOpenMM deltaY = atomCoordinates[atomJ][1] - atomCoordinates[atomI][1];
RealOpenMM deltaZ = atomCoordinates[atomJ][2] - atomCoordinates[atomI][2];
RealOpenMM r2 = deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ;
RealOpenMM r = SQRT( r2 );
// 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 );
}
}
setEnergy( obcEnergy );
if( 0 ){
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 );
CpuObc::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 __CpuObc_H__
#define __CpuObc_H__
#include "ObcParameters.h"
#include "CpuImplicitSolvent.h"
// ---------------------------------------------------------------------------------------
class CpuObc : public CpuImplicitSolvent {
private:
// GBSA/OBC parameters
ObcParameters* _obcParameters;
// 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
--------------------------------------------------------------------------------------- */
CpuObc( ImplicitSolventParameters* obcParameters );
/**---------------------------------------------------------------------------------------
Destructor
--------------------------------------------------------------------------------------- */
~CpuObc( );
/**---------------------------------------------------------------------------------------
Return ObcParameters
@return ObcParameters
--------------------------------------------------------------------------------------- */
ObcParameters* getObcParameters( void ) const;
/**---------------------------------------------------------------------------------------
Set ImplicitSolventParameters
@param ImplicitSolventParameters
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setObcParameters( ObcParameters* obcParameters );
/**---------------------------------------------------------------------------------------
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 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 // __CpuObc_H__
/* 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.
*/
#include "../SimTKUtilities/SimTKOpenMMCommon.h"
#include "../SimTKUtilities/SimTKOpenMMLog.h"
#include "../SimTKUtilities/SimTKOpenMMUtilities.h"
#include "ImplicitSolventParameters.h"
#include <sstream>
/**---------------------------------------------------------------------------------------
ImplicitSolventParameters:
Calculates for each atom
(1) the van der Waal radii
(2) volume
(3) fixed terms in ImplicitSolvent 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 ImplicitSolventParameters when initializing the
the values (vdwRadii, volume, ...) to be used in the calculation.
Cpu:
ImplicitSolventParameters* implicitSolventParameters = new ImplicitSolventParameters( numberOfAtoms, log );
implicitSolventParameters->initializeParameters( top );
Gpu:
implicitSolventParameters = new ImplicitSolventParameters( 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 ImplicitSolventParameters destructor does not free arrays
implicitSolventParameters->setVdwRadii( getBrookStreamWrapperAtIndex( GpuImplicitSolvent::implicitSolventVdwRadii )->getData() );
implicitSolventParameters->setVolume( getBrookStreamWrapperAtIndex( GpuImplicitSolvent::implicitSolventVolume )->getData() );
implicitSolventParameters->setGPolFixed( getBrookStreamWrapperAtIndex( GpuImplicitSolvent::implicitSolventGpolFixed )->getData() );
implicitSolventParameters->setAtomicRadii( getBrookStreamWrapperAtIndex( GpuImplicitSolvent::implicitSolventAtomicRadii )->getData() );
implicitSolventParameters->setFreeArrays( false );
implicitSolventParameters->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()
--------------------------------------------------------------------------------------- */
/**---------------------------------------------------------------------------------------
ImplicitSolventParameters constructor (Simbios)
@param numberOfAtoms number of atoms
--------------------------------------------------------------------------------------- */
ImplicitSolventParameters::ImplicitSolventParameters( int numberOfAtoms ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::ImplicitSolventParameters";
// ---------------------------------------------------------------------------------------
_numberOfAtoms = numberOfAtoms;
_ownAtomicRadii = false;
_atomicRadii = NULL;
// see comments in ~ImplicitSolventParameters for explanation
_freeArrays = false;
_initializeImplicitSolventConstants();
}
/**---------------------------------------------------------------------------------------
ImplicitSolventParameters destructor (Simbios)
--------------------------------------------------------------------------------------- */
ImplicitSolventParameters::~ImplicitSolventParameters( ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::~ImplicitSolventParameters";
// ---------------------------------------------------------------------------------------
if( _ownAtomicRadii ){
delete[] _atomicRadii;
}
}
/**---------------------------------------------------------------------------------------
Get number of atoms
@return number of atoms
--------------------------------------------------------------------------------------- */
int ImplicitSolventParameters::getNumberOfAtoms( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::getNumberOfAtoms:";
// ---------------------------------------------------------------------------------------
return _numberOfAtoms;
}
/**---------------------------------------------------------------------------------------
Get solvent dielectric
@return solvent dielectric
--------------------------------------------------------------------------------------- */
RealOpenMM ImplicitSolventParameters::getSolventDielectric( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::getSolventDielectric:";
// ---------------------------------------------------------------------------------------
return _solventDielectric;
}
/**---------------------------------------------------------------------------------------
Set solvent dielectric
@param solventDielectric solvent dielectric
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ImplicitSolventParameters::setSolventDielectric( RealOpenMM solventDielectric ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::setSolventDielectric:";
// ---------------------------------------------------------------------------------------
_solventDielectric = solventDielectric;
_resetPreFactor();
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get solute dielectric
@return soluteDielectric
--------------------------------------------------------------------------------------- */
RealOpenMM ImplicitSolventParameters::getSoluteDielectric( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::getSoluteDielectric:";
// ---------------------------------------------------------------------------------------
return _soluteDielectric;
}
/**---------------------------------------------------------------------------------------
Set solute dielectric
@param soluteDielectric solute dielectric
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ImplicitSolventParameters::setSoluteDielectric( RealOpenMM soluteDielectric ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::setSoluteDielectric:";
// ---------------------------------------------------------------------------------------
_soluteDielectric = soluteDielectric;
_resetPreFactor();
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get electric constant (Simbios)
@return electricConstant
--------------------------------------------------------------------------------------- */
RealOpenMM ImplicitSolventParameters::getElectricConstant( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::getElectricConstant:";
// ---------------------------------------------------------------------------------------
return _electricConstant;
}
/**---------------------------------------------------------------------------------------
Set electric constant (Simbios)
@param electricConstant electric constant
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ImplicitSolventParameters::setElectricConstant( RealOpenMM electricConstant ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::setElectricConstant:";
// ---------------------------------------------------------------------------------------
_electricConstant = electricConstant;
_resetPreFactor();
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get probe radius (Simbios)
@return probeRadius
--------------------------------------------------------------------------------------- */
RealOpenMM ImplicitSolventParameters::getProbeRadius( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::getProbeRadius:";
// ---------------------------------------------------------------------------------------
return _probeRadius;
}
/**---------------------------------------------------------------------------------------
Set probe radius (Simbios)
@param probeRadius probe radius
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ImplicitSolventParameters::setProbeRadius( RealOpenMM probeRadius ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::setProbeRadius:";
// ---------------------------------------------------------------------------------------
_probeRadius = probeRadius;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get pi*4*Asolv: used in ACE approximation for nonpolar term
((RealOpenMM) M_PI)*4.0f*0.0049*1000.0; (Still)
((RealOpenMM) M_PI)*4.0f*0.0054*1000.0; (OBC)
@return pi4Asolv
--------------------------------------------------------------------------------------- */
RealOpenMM ImplicitSolventParameters::getPi4Asolv( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::getPi4Asolv:";
// ---------------------------------------------------------------------------------------
return _pi4Asolv;
}
/**---------------------------------------------------------------------------------------
Get prefactor
@return prefactor
--------------------------------------------------------------------------------------- */
RealOpenMM ImplicitSolventParameters::getPreFactor( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::getPreFactor:";
// ---------------------------------------------------------------------------------------
return _preFactor;
}
/**---------------------------------------------------------------------------------------
Set pi4Asolv: used in ACE approximation for nonpolar term
((RealOpenMM) M_PI)*4.0f*0.0049*1000.0; (Still)
((RealOpenMM) M_PI)*4.0f*0.0054*1000.0; (OBC)
@param pi4Asolv probe radius
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ImplicitSolventParameters::setPi4Asolv( RealOpenMM pi4Asolv ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::setPi4Asolv:";
// ---------------------------------------------------------------------------------------
_pi4Asolv = pi4Asolv;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get conversion factor for kcal/A -> kJ/nm (Simbios)
@return kcalA_To_kJNm factor
--------------------------------------------------------------------------------------- */
RealOpenMM ImplicitSolventParameters::getKcalA_To_kJNm( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::getKcalA_To_kJNm:";
// ---------------------------------------------------------------------------------------
return _kcalA_To_kJNm;
}
/**---------------------------------------------------------------------------------------
Set KcalA_To_kJNm
@param kcalA_To_kJNm probe radius
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ImplicitSolventParameters::setKcalA_To_kJNm( RealOpenMM kcalA_To_kJNm ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::setKcalA_To_kJNm:";
// ---------------------------------------------------------------------------------------
_kcalA_To_kJNm = kcalA_To_kJNm;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get AtomicRadii array
@return array of atomic radii
--------------------------------------------------------------------------------------- */
RealOpenMM* ImplicitSolventParameters::getAtomicRadii( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::getAtomicRadii:";
// ---------------------------------------------------------------------------------------
if( _atomicRadii == NULL ){
ImplicitSolventParameters* localThis = const_cast<ImplicitSolventParameters* const>(this);
localThis->_atomicRadii = new RealOpenMM[getNumberOfAtoms()];
localThis->_ownAtomicRadii = true;
memset( localThis->_atomicRadii, 0, sizeof( RealOpenMM )*getNumberOfAtoms() );
}
return _atomicRadii;
}
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii array of atomic radii
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ImplicitSolventParameters::setAtomicRadii( RealOpenMM* atomicRadii ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::setAtomicRadii:";
// ---------------------------------------------------------------------------------------
if( _ownAtomicRadii && atomicRadii != _atomicRadii ){
delete[] _atomicRadii;
_ownAtomicRadii = false;
}
_atomicRadii = atomicRadii;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii array of atomic radii
@param units units flag: SimTKOpenMMCommon::KcalAngUnits or
SimTKOpenMMCommon::MdUnits
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ImplicitSolventParameters::setAtomicRadii( const RealOpenMMVector& atomicRadii, int units ){
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nImplicitSolventParameters::setAtomicRadii:";
// ---------------------------------------------------------------------------------------
int numberOfAtoms = getNumberOfAtoms();
if( _ownAtomicRadii ){
delete[] _atomicRadii;
_atomicRadii = new RealOpenMM[numberOfAtoms];
} else if( _atomicRadii == NULL ){
_atomicRadii = new RealOpenMM[numberOfAtoms];
_ownAtomicRadii = true;
}
if( numberOfAtoms != (int) atomicRadii.size() ){
std::stringstream message;
message << methodName;
message << " number of object atoms=" << numberOfAtoms << " does not match number in input vector=" << atomicRadii.size();
SimTKOpenMMLog::printWarning( message );
numberOfAtoms = numberOfAtoms < (int) atomicRadii.size() ? numberOfAtoms : (int) atomicRadii.size();
}
// force kcal/A units
if( units == SimTKOpenMMCommon::MdUnits ){
RealOpenMM ten = (RealOpenMM) 10.0;
for( int ii = 0; ii < numberOfAtoms; ii++ ){
_atomicRadii[ii] = ten*atomicRadii[ii];
}
} else {
for( int ii = 0; ii < numberOfAtoms; ii++ ){
_atomicRadii[ii] = atomicRadii[ii];
}
}
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii array of atomic radii
@param units units flag: SimTKOpenMMCommon::KcalAngUnits or
SimTKOpenMMCommon::MdUnits
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ImplicitSolventParameters::setAtomicRadii( RealOpenMM* atomicRadii, int units ){
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nImplicitSolventParameters::setAtomicRadii:";
// ---------------------------------------------------------------------------------------
int numberOfAtoms = getNumberOfAtoms();
if( _ownAtomicRadii ){
delete[] _atomicRadii;
_atomicRadii = new RealOpenMM[numberOfAtoms];
} else if( _atomicRadii == NULL ){
_atomicRadii = new RealOpenMM[numberOfAtoms];
_ownAtomicRadii = true;
}
// force kcal/A units
if( units == SimTKOpenMMCommon::MdUnits ){
RealOpenMM ten = (RealOpenMM) 10.0;
for( int ii = 0; ii < numberOfAtoms; ii++ ){
_atomicRadii[ii] = ten*atomicRadii[ii];
}
} else {
for( int ii = 0; ii < numberOfAtoms; ii++ ){
_atomicRadii[ii] = atomicRadii[ii];
}
}
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii vector of atomic radii
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ImplicitSolventParameters::setOwnAtomicRadii( int ownAtomicRadii ){
// ---------------------------------------------------------------------------------------
//static const char* methodName = "\nImplicitSolventParameters::setOwnAtomicRadii:";
// ---------------------------------------------------------------------------------------
_ownAtomicRadii = ownAtomicRadii;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get free array flag -- if set then work arrays are freed when destructor is called
@return freeArrays flag
--------------------------------------------------------------------------------------- */
int ImplicitSolventParameters::getFreeArrays( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::setFreeArrays:";
// ---------------------------------------------------------------------------------------
return _freeArrays;
}
/**---------------------------------------------------------------------------------------
Set free array flag -- if set then work arrays are freed when destructor is called
@param freeArrays flag
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ImplicitSolventParameters::setFreeArrays( int freeArrays ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::setFreeArrays:";
// ---------------------------------------------------------------------------------------
_freeArrays = freeArrays;
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Initialize ImplicitSolvent Parameters (Simbios)
--------------------------------------------------------------------------------------- */
void ImplicitSolventParameters::_initializeImplicitSolventConstants( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::_initializeImplicitSolventConstants:";
// ---------------------------------------------------------------------------------------
_soluteDielectric = (RealOpenMM) 1.0;
_solventDielectric = (RealOpenMM) 78.3;
_kcalA_To_kJNm = (RealOpenMM) 0.4184;
_probeRadius = (RealOpenMM) 1.4;
_electricConstant = (RealOpenMM) -166.02691;
// _pi4Asolv = (RealOpenMM) PI_M*4.0*0.0049*1000.0;
//_pi4Asolv = (RealOpenMM) PI_M*19.6;
// _pi4Asolv = (RealOpenMM) PI_M*4.0*0.0054;
_pi4Asolv = (RealOpenMM) (PI_M*0.0216);
_resetPreFactor();
}
/**---------------------------------------------------------------------------------------
Reset prefactor (Simbios)
called when _electricConstant, _soluteDielectric, or _solventDielectric are modified
--------------------------------------------------------------------------------------- */
void ImplicitSolventParameters::_resetPreFactor( void ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::_resetPreFactor:";
static const RealOpenMM zero = 0.0;
static const RealOpenMM one = 1.0;
static const RealOpenMM two = 2.0;
// ---------------------------------------------------------------------------------------
if( getSoluteDielectric() != zero && getSolventDielectric() != zero ){
_preFactor = two*getElectricConstant()*( (one/getSoluteDielectric()) - (one/getSolventDielectric()) );
} else {
_preFactor = zero;
}
}
/**---------------------------------------------------------------------------------------
Get state (Simbios)
@param title title (optional)
@return SimTKOpenMMCommon::DefaultReturn always
--------------------------------------------------------------------------------------- */
std::string ImplicitSolventParameters::getStateString( const char* title ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::getStateString";
// ---------------------------------------------------------------------------------------
std::stringstream message;
if( title ){
message << title;
}
std::string tab = getStringTab();
message << "\nImplicitSolventParameters :";
message << tab << "Solute dielectric: " << getSoluteDielectric();
message << tab << "Solvent dielectric: " << getSolventDielectric();
message << tab << "Electric constant: " << getElectricConstant();
message << tab << "Probe radius: " << getProbeRadius();
message << tab << "Number of atoms: " << getNumberOfAtoms();
message << tab << "Free arrays: " << getFreeArrays();
return message.str();
}
/**---------------------------------------------------------------------------------------
Return zero value if all parameters set; else return nonzero
@return ready status
--------------------------------------------------------------------------------------- */
int ImplicitSolventParameters::isNotReady( void ) const {
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nImplicitSolventParameters::isNotReady";
// ---------------------------------------------------------------------------------------
int errors = 0;
int warning = 0;
std::stringstream message;
message << methodName;
if( getNumberOfAtoms() <= 0 ){
errors++;
message << "\n number of atoms=" << getNumberOfAtoms() << " is invalid.";
}
RealOpenMM* atomicRadii = getAtomicRadii();
if( atomicRadii == NULL ){
errors++;
message << "\n scaledRadiusFactors is not set";
}
// check radii are in correct units
RealOpenMM average, stdDev, maxValue, minValue;
int minIndex, maxIndex;
SimTKOpenMMUtilities::getArrayStatistics( getNumberOfAtoms(), atomicRadii, &average,
&stdDev, &minValue, &minIndex,
&maxValue, &maxIndex );
if( average < 1.0 || average > 10.0 || minValue < 0.5 ){
errors++;
message << "\n atomic radii appear not to be set correctly -- radii should be in Angstroms";
message << "\n average radius=" << average << " min radius=" << minValue << " at atom index=" << minIndex;
}
if( getPreFactor() == 0.0 ){
errors++;
message << "\n prefactor is not set.";
}
if( getSolventDielectric() <= 0.0 ){
errors++;
message << "\n solvent dielectric=" << getSolventDielectric() << " is invalid.";
}
if( getSolventDielectric() >= 1000.0 ){
warning++;
message << "\n Warning: solvent dielectric=" << getSolventDielectric() << " is large.";
}
if( getSoluteDielectric() <= 0.0 ){
errors++;
message << "\n solute dielectric=" << getSoluteDielectric() << " is invalid.";
}
if( getSoluteDielectric() >= 1000.0 ){
warning++;
message << "\n Warning: solute dielectric=" << getSoluteDielectric() << " is large.";
}
if( getElectricConstant() >= 0.0 ){
errors++;
message << "\n electric constant=" << getElectricConstant() << " is invalid.";
}
if( getElectricConstant() >= 1000.0 ){
warning++;
message << "\n Warning: electric constant=" << getElectricConstant() << " is large.";
}
if( getProbeRadius() <= 0.0 ){
errors++;
message << "\n probe radius=" << getProbeRadius() << " is invalid.";
}
if( getProbeRadius() >= 10.0 ){
warning++;
message << "\n Warning: probe radius=" << getProbeRadius() << " is large.";
}
if( getPi4Asolv() <= 0.0 ){
errors++;
message << "\n Pi4Asolv=" << getPi4Asolv() << " is invalid.";
}
if( getPi4Asolv() >= 1000.0 ){
warning++;
message << "\n Warning: Pi4Asolv=" << getPi4Asolv() << " is large.";
}
if( errors || warning ){
message << std::endl;
SimTKOpenMMLog::printMessage( message );
}
return errors;
}
/**---------------------------------------------------------------------------------------
Get string tab -- centralized
@return tab string
--------------------------------------------------------------------------------------- */
std::string ImplicitSolventParameters::getStringTab( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nImplicitSolventParameters::getStringTab";
// ---------------------------------------------------------------------------------------
return std::string( "\n " );
}
/* 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 __ImplicitSolventParameters_H__
#define __ImplicitSolventParameters_H__
#include "../SimTKUtilities/SimTKOpenMMRealType.h"
#include <string>
// ---------------------------------------------------------------------------------------
class ImplicitSolventParameters {
protected:
// parameters common to implicit solvent models
RealOpenMM _solventDielectric;
RealOpenMM _soluteDielectric;
RealOpenMM _kcalA_To_kJNm;
RealOpenMM _electricConstant;
RealOpenMM _probeRadius;
RealOpenMM _pi4Asolv;
RealOpenMM _preFactor;
// ---------------------------------------------------------------------------------------
// atom count
int _numberOfAtoms;
// flag signalling whether arrays are to be freed
int _freeArrays;
// atomic radii
int _ownAtomicRadii;
RealOpenMM* _atomicRadii;
/**---------------------------------------------------------------------------------------
Initialize ImplicitSolvent Parameters (Simbios)
--------------------------------------------------------------------------------------- */
void _initializeImplicitSolventConstants( void );
/**---------------------------------------------------------------------------------------
Set KcalA_To_kJNm
@param kcalA_To_kJNm probe radius
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setKcalA_To_kJNm( RealOpenMM kcalA_To_kJNm );
/**---------------------------------------------------------------------------------------
Set free array flag -- if set then work arrays are freed when destructor is called
@param freeArrays flag
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setFreeArrays( int freeArrays );
/**---------------------------------------------------------------------------------------
Reset prefactor (Simbios)
called when _electricConstant, _soluteDielectric, or _solventDielectric are modified
--------------------------------------------------------------------------------------- */
void _resetPreFactor( void );
public:
/**---------------------------------------------------------------------------------------
ImplicitSolventParameters constructor (Simbios)
@param numberOfAtoms number of atoms
--------------------------------------------------------------------------------------- */
ImplicitSolventParameters( int numberOfAtoms );
/**---------------------------------------------------------------------------------------
ImplicitSolventParameters destructor (Simbios)
--------------------------------------------------------------------------------------- */
~ImplicitSolventParameters( );
// override of new/delete
//static void* operator new( size_t size );
//static void operator delete( void *p );
//static void* operator new[]( size_t size );
//static void operator delete[]( void *p );
/**---------------------------------------------------------------------------------------
Get number of atoms
@return number of atoms
--------------------------------------------------------------------------------------- */
int getNumberOfAtoms( void ) const;
/**---------------------------------------------------------------------------------------
Get free array flag -- if set then work arrays are freed when destructor is called
@return freeArrays flag
--------------------------------------------------------------------------------------- */
int getFreeArrays( void ) const;
/**---------------------------------------------------------------------------------------
Get solvent dielectric
@return solvent dielectric
--------------------------------------------------------------------------------------- */
RealOpenMM getSolventDielectric( void ) const;
/**---------------------------------------------------------------------------------------
Set solvent dielectric
@param solventDielectric solvent dielectric
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setSolventDielectric( RealOpenMM solventDielectric );
/**---------------------------------------------------------------------------------------
Get solute dielectric
@return soluteDielectric
--------------------------------------------------------------------------------------- */
RealOpenMM getSoluteDielectric( void ) const;
/**---------------------------------------------------------------------------------------
Set solute dielectric
@param soluteDielectric solute dielectric
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setSoluteDielectric( RealOpenMM soluteDielectric );
/**---------------------------------------------------------------------------------------
Get conversion factor for kcal/A -> kJ/nm (Simbios)
@return kcalA_To_kJNm factor
--------------------------------------------------------------------------------------- */
RealOpenMM getKcalA_To_kJNm( void ) const;
/**---------------------------------------------------------------------------------------
Get electric constant (Simbios)
@return electricConstant
--------------------------------------------------------------------------------------- */
RealOpenMM getElectricConstant( void ) const;
/**---------------------------------------------------------------------------------------
Set electric constant (Simbios)
@param electricConstant electric constant
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setElectricConstant( RealOpenMM electricConstant );
/**---------------------------------------------------------------------------------------
Get probe radius (Simbios)
@return probeRadius
--------------------------------------------------------------------------------------- */
RealOpenMM getProbeRadius( void ) const;
/**---------------------------------------------------------------------------------------
Set probe radius (Simbios)
@param probeRadius probe radius
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setProbeRadius( RealOpenMM probeRadius );
/**---------------------------------------------------------------------------------------
Get pi4Asolv: used in ACE approximation for nonpolar term
((RealOpenMM) M_PI)*4.0f*0.0049f*1000.0f; (Simbios)
@return pi4Asolv
--------------------------------------------------------------------------------------- */
RealOpenMM getPi4Asolv( void ) const;
/**---------------------------------------------------------------------------------------
Get prefactor
@returnpreFactor
--------------------------------------------------------------------------------------- */
RealOpenMM getPreFactor( void ) const;
/**---------------------------------------------------------------------------------------
Set values used in ACE approximation for nonpolar term
((RealOpenMM) M_PI)*4.0f*0.0049f*1000.0f; (Simbios)
@param pi4Asolv see above
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setPi4Asolv( RealOpenMM pi4Asolv );
/**---------------------------------------------------------------------------------------
Get AtomicRadii array
@return array of atom volumes
--------------------------------------------------------------------------------------- */
virtual RealOpenMM* getAtomicRadii( void ) const;
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii array of atomic radii
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
virtual int setAtomicRadii( RealOpenMM* atomicRadii );
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii vector of atomic radii
@param units units flag SimTKOpenMMCommon::MdUnits or
SimTKOpenMMCommon::KcalAngUnits
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
virtual int setAtomicRadii( const RealOpenMMVector& atomicRadii,
int units = SimTKOpenMMCommon::MdUnits );
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii array of atomic radii
@param units units flag: SimTKOpenMMCommon::KcalAngUnits or
SimTKOpenMMCommon::MdUnits
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
virtual int setAtomicRadii( RealOpenMM* atomicRadii, int units );
/**---------------------------------------------------------------------------------------
Set flag indicating whether AtomicRadii array is owned by
object; if flag is set, then when the object is deleted,
the array will be freed
@param ownAtomicRadii flag indicating whether array of atomic radii
should be freed
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setOwnAtomicRadii( int ownAtomicRadii );
/**---------------------------------------------------------------------------------------
Print state to log file (Simbios)
@param title title (optional)
@param log print state to log file
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
virtual std::string getStateString( const char* title ) const;
/**---------------------------------------------------------------------------------------
Get string tab -- centralized
@return tab string
--------------------------------------------------------------------------------------- */
std::string getStringTab( void ) const;
/**---------------------------------------------------------------------------------------
Return nonzero value errors
@return ready status
--------------------------------------------------------------------------------------- */
virtual int isNotReady( void ) const;
};
// ---------------------------------------------------------------------------------------
#endif // __ImplicitSolventParameters_H__
/* 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.
*/
#include <math.h>
#include <sstream>
#include "ObcParameters.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 ObcParameters::ParameterFileName = std::string( "params.agb" );
/**---------------------------------------------------------------------------------------
ObcParameters:
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 ObcParameters when initializing the
the values (vdwRadii, volume, ...) to be used in the calculation.
Cpu:
ObcParameters* obcParameters = new ObcParameters( numberOfAtoms, log );
obcParameters->initializeParameters( top );
Gpu:
obcParameters = new ObcParameters( 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 ObcParameters 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()
--------------------------------------------------------------------------------------- */
/**---------------------------------------------------------------------------------------
ObcParameters constructor (Simbios)
@param numberOfAtoms number of atoms
@param obcType OBC type (Eq. 7 or 8 in paper)
--------------------------------------------------------------------------------------- */
ObcParameters::ObcParameters( int numberOfAtoms, ObcParameters::ObcType obcType ) : ImplicitSolventParameters( numberOfAtoms ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcParameters::ObcParameters";
// ---------------------------------------------------------------------------------------
_obcType = obcType;
_dielectricOffset = 0.09f;
_ownScaledRadiusFactors = 0;
_scaledRadiusFactors = NULL;
setObcTypeParameters( obcType );
}
/**---------------------------------------------------------------------------------------
ObcParameters destructor (Simbios)
--------------------------------------------------------------------------------------- */
ObcParameters::~ObcParameters( ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcParameters::~ObcParameters";
// ---------------------------------------------------------------------------------------
// 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( getFreeArrays() ){
} */
#endif
}
/**---------------------------------------------------------------------------------------
Get OBC type
@return OBC type
--------------------------------------------------------------------------------------- */
ObcParameters::ObcType ObcParameters::getObcType( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcParameters::getObcType:";
// ---------------------------------------------------------------------------------------
return _obcType;
}
/**---------------------------------------------------------------------------------------
Set OBC type specific parameters
@param obcType OBC type (ObcTypeI or ObcTypeII -- Eq. 7 or 8)
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ObcParameters::setObcTypeParameters( ObcParameters::ObcType obcType ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcParameters::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 ObcParameters::getDielectricOffset( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcParameters::getDielectricOffset:";
// ---------------------------------------------------------------------------------------
return _dielectricOffset;
}
/**---------------------------------------------------------------------------------------
Get alpha OBC (Eqs. 6 & 7) in Proteins paper
@return alphaObc
--------------------------------------------------------------------------------------- */
RealOpenMM ObcParameters::getAlphaObc( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcParameters::getAlphaObc:";
// ---------------------------------------------------------------------------------------
return _alphaObc;
}
/**---------------------------------------------------------------------------------------
Get beta OBC (Eqs. 6 & 7) in Proteins paper
@return betaObc
--------------------------------------------------------------------------------------- */
RealOpenMM ObcParameters::getBetaObc( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcParameters::getBetaObc:";
// ---------------------------------------------------------------------------------------
return _betaObc;
}
/**---------------------------------------------------------------------------------------
Get gamma OBC (Eqs. 6 & 7) in Proteins paper
@return gammaObc
--------------------------------------------------------------------------------------- */
RealOpenMM ObcParameters::getGammaObc( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcParameters::getGammaObc:";
// ---------------------------------------------------------------------------------------
return _gammaObc;
}
/**---------------------------------------------------------------------------------------
Get AtomicRadii array
@return array of atomic radii
--------------------------------------------------------------------------------------- */
RealOpenMM* ObcParameters::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
@param units units flag: SimTKOpenMMCommon::KcalAngUnits or
SimTKOpenMMCommon::MdUnits
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ObcParameters::setAtomicRadii( RealOpenMM* atomicRadii, int units ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcParameters::setAtomicRadii:";
// ---------------------------------------------------------------------------------------
return ImplicitSolventParameters::setAtomicRadii( atomicRadii, units );
}
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii vector of atomic radii
@param units units flag: SimTKOpenMMCommon::KcalAngUnits or
SimTKOpenMMCommon::MdUnits
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int ObcParameters::setAtomicRadii( const RealOpenMMVector& atomicRadii, int units ){
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nObcParameters::setAtomicRadii:";
// ---------------------------------------------------------------------------------------
return ImplicitSolventParameters::setAtomicRadii( atomicRadii, units );
}
/**---------------------------------------------------------------------------------------
Return OBC scale factors
If not previously set, allocate space
@return array
--------------------------------------------------------------------------------------- */
const RealOpenMM* ObcParameters::getScaledRadiusFactors( void ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nCpuObc::getScaledRadiusFactors";
// ---------------------------------------------------------------------------------------
if( _scaledRadiusFactors == NULL ){
ObcParameters* localThis = const_cast<ObcParameters* 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 ObcParameters::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 ObcParameters::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 ObcParameters::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 ObcParameters::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 ObcParameters::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 ObcParameters::getStateString( const char* title ) const {
// ---------------------------------------------------------------------------------------
// static const char* methodName = "\nObcParameters::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 ObcParameters::isNotReady( void ) const {
// ---------------------------------------------------------------------------------------
static const char* methodName = "\nObcParameters::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 Angstroms";
message << "\n average radius=" << average << " min radius=" << minValue << " at atom index=" << minIndex;
}
if( errors ){
message << std::endl;
SimTKOpenMMLog::printMessage( message );
}
errors += isReady;
return errors;
}
/* 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 __ObcParameters_H__
#define __ObcParameters_H__
#include "../SimTKUtilities/SimTKOpenMMCommon.h"
#include "ImplicitSolventParameters.h"
// ---------------------------------------------------------------------------------------
class ObcParameters : 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;
// scaled radius factors (S_kk in HCT paper)
int _ownScaledRadiusFactors;
RealOpenMM* _scaledRadiusFactors;
/**---------------------------------------------------------------------------------------
Set solvent dielectric (Simbios)
@param dielectricOffset solvent dielectric
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setDielectricOffset( RealOpenMM dielectricOffset );
public:
/**---------------------------------------------------------------------------------------
ObcParameters constructor (Simbios)
@param numberOfAtoms number of atoms
--------------------------------------------------------------------------------------- */
ObcParameters( int numberOfAtoms, ObcParameters::ObcType obcType = ObcTypeII );
/**---------------------------------------------------------------------------------------
ObcParameters destructor (Simbios)
--------------------------------------------------------------------------------------- */
~ObcParameters( );
// override of new/delete
//static void* operator new( size_t size );
//static void operator delete( void *p );
//static void* operator new[]( size_t size );
//static void operator delete[]( void *p );
/**---------------------------------------------------------------------------------------
Get OBC type
@return OBC type
--------------------------------------------------------------------------------------- */
ObcParameters::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( ObcParameters::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
@param units units flag: SimTKOpenMMCommon::KcalAngUnits or
SimTKOpenMMCommon::MdUnits
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setAtomicRadii( RealOpenMM* atomicRadii, int units = SimTKOpenMMCommon::MdUnits );
/**---------------------------------------------------------------------------------------
Set AtomicRadii array
@param atomicRadii vector of atomic radii
@param units units flag: SimTKOpenMMCommon::KcalAngUnits or
SimTKOpenMMCommon::MdUnits
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
int setAtomicRadii( const RealOpenMMVector& atomicRadii, int units = SimTKOpenMMCommon::MdUnits );
/**---------------------------------------------------------------------------------------
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;
};
/**---------------------------------------------------------------------------------------
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 // __ObcParameters_H__
The OBC Generalized Born model is based on the following papers:
J. Phys. Chem. 1996 100, 19824-19839 (HCT paper)
Proteins: Structure, Function, and Bioinformatics 55:383-394 (2004) (OBC paper)
---------------------------------------------------------------------------------------
The two main interface methods perform the following tasks:
(1) set the GBSA parameters; this method is called once prior to execution of
the main simulation loop
(2) calculate the GBSA forces/energy given the atom coordinates and charges
for each simulation step
The two methods and helper methods are in the file cpuObcInterface.cpp
---------------------------------------------------------------------------------------
The setup call is
cpuSetObcParameters( int numberOfAtoms, RealOpenMM* atomicRadii, RealOpenMM* obcScaleFactors,
int includeAceApproximation,
RealOpenMM soluteDielectric, RealOpenMM solventDielectric, FILE* log );
The parameters include the following:
(1) number of atoms
(2) the OBC atomic radii (akin to VDW radii, but optimized for GBSA calculations)
(3) the OBC scale factors for each atom
(4) a flag indicating whether the nonpolar ACE approximation is to be included
in calculating the forces and energy: I do not have a reference for this term
(5-6) the solute and solvent dielectric (typically 1.0 & 78.3)
(7) a log file reference; the reference may be set to NULL,
if logging is unwanted. Note: if the reference is NULL, warnings, ... will be output to stderr
cpuSetObcParameters() creates a static CpuObc object which is then referenced when the
GBSA forces and energy are to be calculated
The default OBC model is the Type II model: Eq. 8 in the 2004 OBC paper;
for the Type I model, replace the call
ObcParameters* obcParameters = new ObcParameters( numberOfAtoms, ObcParameters::ObcTypeII );
with
ObcParameters* obcParameters = new ObcParameters( numberOfAtoms, ObcParameters::ObcTypeI );
---------------------------------------------------------------------------------------
The OBC scale factors may be obtained via calls to either of the following 'helper' methods
getObcScaleFactors( int numberOfAtoms, const int* atomicNumber, RealOpenMM* scaleFactors )
or
getObcScaleFactorsGivenAtomMasses( int numberOfAtoms, const RealOpenMM* masses, RealOpenMM* scaleFactors )
Documentation for the inputs to these routines is contained in the file, cpuObcInterface.cpp.
The scale factors are those used in Tinker5, and are based on the element type
of each atom (H, C, N, O, ...).
---------------------------------------------------------------------------------------
The OBC radii may be obtained via the helper method:
getGbsaRadii( int numberOfAtoms, const int* atomicNumber,
const int* numberOfCovalentPartners, const int* indexOfCovalentPartner,
RealOpenMM* gbsaRadii );
Documentation for the inputs to this routine is contained in the file, cpuObcInterface.cpp.
The radii are based on the atom type (methyl C, carbonyl C, ...). The value for a hydrogen
depends on its covalent heavy atom partner. As for the OBC scale factors, the values
hardwired into the method are the same as those used in Tinker5.
---------------------------------------------------------------------------------------
The energy/forces are calculated via the call
cpuCalculateImplicitSolventForces( RealOpenMM** atomCoordinates, const RealOpenMM* partialCharges,
RealOpenMM** forces, RealOpenMM* energy, int updateBornRadii );
The coordinate and force arrays should have the layout: atomCoordinates[atomIndex][3] &
forces[atomIndex][3]
If updateBornRadii = 0, then the Born radii from the previous iteration are used; this reduces the
number of O(N**2) loops from 3 to 2.
If updateBornRadii != 0, then the Born radii are calculated for the input configuration.
For MD runs, setting updateBornRadii = 0 is relatively safe since the radii change little
from one iteration to the next. However, for minimization techniques updateBornRadii
should probably be set to a nonzero value since the configuarations can change significantly
between adjacent calls.
---------------------------------------------------------------------------------------
Notes:
(1) The type (float or double) for floating-point numbers is set in the file SimTKOpenMMRealType.h.
If 'RealOpenMMType' is set to 1 in the file, the calculations are performed in
single-precision; otherwise they are performed in double-precision
(2) The units are Angstroms for the spatial dimensions, kcal/mol for energy, and kcal/mol.A for the forces
(3) The code in gromacsCpuObcInterface.cpp provides an example of the parameter setup, ... used for
interfacing w/ Gromacs; the details are somewhat different from the code in cpuObcInterface.cpp
(4) Output from Tinker for a singles ubiquitin configuration are in the directory 'Examples'.
The xyz file gives the coordinates and atom types (Amber99 -- note the charge for atom type 268
(line 2008 in the Tinker amber99.prm file) was changed from -0.2737 to -0.2774 to agree w/
the value used in the version of Gromacs we have access to.)
The key file specifies that OBC should be used for the implicit solvent.
The results are in the files 111UBQ.gbsaAce and 111UBQ.gbsaNoAce. The first file includes the
ACE approximation, while the second does not. On the first line of each file, the number of atoms
and GBSA energy are reported. The remaining lines (one for each atom) give the coordinates (3 entries),
Born radius, partial charge, GBSA radius (rsolv in Tinker), the OBC scaling factor, and the forces (3). The
last three fields give the atomic number, Tinker Amber99 atom name and type.
---------------------------------------------------------------------------------------
/* 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 __SimTKOpenMMWindowLinux_H_
#define __SimTKOpenMMWindowLinux_H__
#ifdef WIN32
#define FOPEN fopen_s
#else
#define FOPEN fopen
#endif
#endif // __SimTKOpenMMWindowLinux_H__
/* 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.
*/
#include "cpuObcInterface.h"
#include "../SimTKUtilities/SimTKOpenMMLog.h"
#include "../SimTKUtilities/SimTKOpenMMUtilities.h"
// #include "SimTKOpenMMGromacsUtilities.h"
#include "ObcParameters.h"
#include "CpuObc.h"
/**---------------------------------------------------------------------------------------
Setup for Obc calculations from Gromacs
@param numberOfAtoms number of atoms
@param obcScaleFactors array of OBC scale factors (one entry each atom)
@param atomicRadii atomic radii in Angstrom (one entry each atom)
@param includeAceApproximation if true, then include nonpolar
ACE term in calculations
@param soluteDielectric solute dielectric
@param solventDielectric solvent dielectric
@param log log reference -- if NULL, then errors/warnings
output to stderr
The method creates a CpuObc instance -- currently the OBC type II model is the
default (see paper). If the OBC type I model is desired change
ObcParameters* obcParameters = new ObcParameters( numberOfAtoms, ObcParameters::ObcTypeII );
to
ObcParameters* obcParameters = new ObcParameters( numberOfAtoms, ObcParameters::ObcTypeI );
The created object is a static member of the class CpuObc;
when the force routine, cpuCalculateObcForces(), is called,
the static object is used to compute the forces and energy
@return 0
--------------------------------------------------------------------------------------- */
extern "C" int
cpuSetObcParameters( int numberOfAtoms, RealOpenMM* atomicRadii, RealOpenMM* obcScaleFactors,
int includeAceApproximation,
RealOpenMM soluteDielectric, RealOpenMM solventDielectric, FILE* log ){
// ---------------------------------------------------------------------------------------
static const char* methodName = "\ncpuSetObcParameters: ";
// ---------------------------------------------------------------------------------------
// set log file if not NULL
if( log ){
SimTKOpenMMLog::setSimTKOpenMMLog( log );
}
// set OBC parameters (Type II)
ObcParameters* obcParameters = new ObcParameters( numberOfAtoms, ObcParameters::ObcTypeII );
obcParameters->setScaledRadiusFactors( obcScaleFactors );
obcParameters->setAtomicRadii( atomicRadii, SimTKOpenMMCommon::KcalAngUnits );
// dielectric constants
obcParameters->setSolventDielectric( solventDielectric );
obcParameters->setSoluteDielectric( soluteDielectric );
// ---------------------------------------------------------------------------------------
// create CpuObc instance that will calculate forces
CpuObc* cpuObc = new CpuObc( obcParameters );
// set static member for subsequent calls to calculate forces/energy
CpuImplicitSolvent::setCpuImplicitSolvent( cpuObc );
// set base file name, ...
//cpuObc->readInfoFile( "CpuImplicitSolventInfo" );
// include/do not include ACE approximation (nonpolar solvation)
cpuObc->setIncludeAceApproximation( includeAceApproximation );
// ---------------------------------------------------------------------------------------
// diagnostics
if( log ){
std::string state = cpuObc->getStateString( methodName );
(void) fprintf( log, "\n%s\nDone w/ setup\n", state.c_str() );
(void) fflush( log );
}
// ---------------------------------------------------------------------------------------
return 0;
}
/**---------------------------------------------------------------------------------------
Calculate implicit solvent forces and energy
@param atomCoordinates atom coordinates in Angstrom; format of array is
atomCoordinates[atom][3] in Angstrom
@param partialCharges partial charges
@param forces output forces in kcal/mol.A; format of array is
forces[atom][3]
@param energy output energy in kcal/mol
@param updateBornRadii if set, then Born radii are updated for current configuration;
otherwise radii correspond to configuration from previous iteration
Function calls a static method in CpuImplicitSolvent class to calculate forces/energy
@return result from CpuImplicitSolvent::computeImplicitSolventForces
--------------------------------------------------------------------------------------- */
extern "C" int
cpuCalculateImplicitSolventForces( RealOpenMM** atomCoordinates,
const RealOpenMM* partialCharges,
RealOpenMM** forces, RealOpenMM* energy,
int updateBornRadii ){
// ---------------------------------------------------------------------------------------
//static const char* methodName = "\ncpuCalculateImplicitSolventForces: ";
// ---------------------------------------------------------------------------------------
int status = CpuImplicitSolvent::getCpuImplicitSolvent()->computeImplicitSolventForces( atomCoordinates, partialCharges,
forces, updateBornRadii );
*energy = CpuImplicitSolvent::getCpuImplicitSolvent()->getEnergy();
// printf( "\ncpuCalculateImplicitSolventForcesE=%.5e", *energy );
return status;
}
/**---------------------------------------------------------------------------------------
Retrieve the calculated energy from the static class member
The energy is calculated in cpuCalculateImplicitSolventForces()
along w/ the forces
@return the calculated energy from the static class member
--------------------------------------------------------------------------------------- */
extern "C" RealOpenMM cpuGetImplicitSolventEnergy( void ){
// ---------------------------------------------------------------------------------------
//static const char* methodName = "\ncpuGetImplicitSolventEnergy: ";
// ---------------------------------------------------------------------------------------
RealOpenMM energy = CpuImplicitSolvent::getCpuImplicitSolvent()->getEnergy();
// printf( "\ncpuGetImplicitSolventEnergy E=%.5e", energy );
return energy;
}
/**---------------------------------------------------------------------------------------
Delete the Obc associated object(s)
@return 0 if static CpuObc object was set; else return -1
--------------------------------------------------------------------------------------- */
extern "C" int cpuDeleteObcParameters( void ){
return CpuImplicitSolvent::deleteCpuImplicitSolvent();
}
/**---------------------------------------------------------------------------------------
Get OBC scale factors given masses
@param numberOfAtoms number of atoms
@param masses input masses
@param scaleFactors output atomic numbers
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
extern "C" int getObcScaleFactorsGivenAtomMasses( int numberOfAtoms, const RealOpenMM* masses,
RealOpenMM* scaleFactors ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "\ngetObcScaleFactorsGivenAtomMasses";
// ---------------------------------------------------------------------------------------
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
double scaleFactor = 0.8;
RealOpenMM mass = masses[atomI];
if ( mass < 1.2 && mass >= 1.0 ){ // hydrogen
scaleFactor = 0.85;
} else if( mass > 11.8 && mass < 12.2 ){ // carbon
scaleFactor = 0.72;
} else if( mass > 14.0 && mass < 15.0 ){ // nitrogen
scaleFactor = 0.79;
} else if( mass > 15.5 && mass < 16.5 ){ // oxygen
scaleFactor = 0.85;
} else if( mass > 31.5 && mass < 32.5 ){ // sulphur
scaleFactor = 0.96;
} else if( mass > 29.5 && mass < 30.5 ){ // phosphorus
scaleFactor = 0.86;
} else {
std::stringstream message;
message << methodName;
message << " Warning: mass for atom " << atomI << " mass=" << mass << "> not recognized.";
SimTKOpenMMLog::printMessage( message );
}
scaleFactors[atomI] = (RealOpenMM) scaleFactor;
}
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get OBC scale factors given atomic numbers
@param numberOfAtoms number of atoms
@param atomicNumber input atomic number for each atom
@param scaleFactors output atomic numbers
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
extern "C" int getObcScaleFactors( int numberOfAtoms, const int* atomicNumber, RealOpenMM* scaleFactors ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "\ngetObcScaleFactors";
// ---------------------------------------------------------------------------------------
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
double scaleFactor;
switch( atomicNumber[atomI] ){
case 1: // hydrogen
scaleFactor = 0.85;
break;
case 6: // carbon
scaleFactor = 0.72;
break;
case 7: // nitrogen
scaleFactor = 0.79;
break;
case 8: // oxygen
scaleFactor = 0.85;
break;
case 15: // phosphorus
scaleFactor = 0.86;
break;
case 16: // sulphur
scaleFactor = 0.85;
break;
default:
scaleFactor = 0.8;
std::stringstream message;
message << methodName;
message << " Warning: atom number=" << atomicNumber[atomI] << " for atom " << atomI << "> not handled -- useing default value.";
SimTKOpenMMLog::printMessage( message );
break;
}
scaleFactors[atomI] = (RealOpenMM) scaleFactor;
}
return SimTKOpenMMCommon::DefaultReturn;
}
/**---------------------------------------------------------------------------------------
Get GBSA radii
@param numberOfAtoms number of atoms
@param atomicNumber input atomic number for each atom
@param numberOfCovalentPartners input number of covalent partners for each atom
1 for H, 2,3,4 for C, ...;
the values are only used for C, N & O
@param indexOfCovalentPartner index of covalent partner -- used only for H
e.g. if atom 22 is a H and it is bonded to atom 24,
then indexOfCovalentPartner[22] = 24
@param gbsaRadii output GBSA radii
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
extern "C" int getGbsaRadii( int numberOfAtoms, const int* atomicNumber,
const int* numberOfCovalentPartners,
const int* indexOfCovalentPartner,
RealOpenMM* gbsaRadii ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "\ngetGbsaRadii";
// ---------------------------------------------------------------------------------------
// loop over atoms
for( int atomI = 0; atomI < numberOfAtoms; atomI++ ){
// branch based on atomic number
double radius;
int atomIndex;
switch ( atomicNumber[atomI] ){
case 1: // H
// get index of covalent partner and validate
// radius is modified if heavy atom is N or O
atomIndex = indexOfCovalentPartner[atomI];
if( atomIndex < 0 || atomIndex >= numberOfAtoms ){
std::stringstream message;
message << methodName;
message << " Warning: atomIndex for covalent partner=" << atomIndex << " for atom " << atomI << " is invalid.";
SimTKOpenMMLog::printMessage( message );
} else if( atomicNumber[atomIndex] == 7 ){
radius = 1.15;
} else if( atomicNumber[atomIndex] == 8 ){
radius = 1.05;
} else {
radius = 1.25;
}
break;
case 3: // Li
radius = 2.432;
break;
case 6: // C
if( numberOfCovalentPartners[atomI] == 2 ){
radius = 1.825;
} else if( numberOfCovalentPartners[atomI] == 3 ){
radius = 1.875;
} else {
radius = 1.90;
}
break;
case 7: // N
if( numberOfCovalentPartners[atomI] == 4 ){
radius = 1.625;
} else if( numberOfCovalentPartners[atomI] == 1 ){
radius = 1.60;
} else {
radius = 1.7063;
}
break;
case 8: // O
if( numberOfCovalentPartners[atomI] == 1 ){
radius = 1.48;
} else {
radius = 1.535;
}
break;
case 9:
radius = 1.47;
break;
case 10:
radius = 1.39;
break;
case 11:
radius = 1.992;
break;
case 12:
radius = 1.70;
break;
case 14:
radius = 1.80;
break;
case 15:
radius = 1.87;
break;
case 16:
radius = 1.775;
break;
case 17:
radius = 1.735;
break;
case 18:
radius = 1.70;
break;
case 19:
radius = 2.123;
break;
case 20:
radius = 1.817;
break;
case 35:
radius = 1.90;
break;
case 36:
radius = 1.812;
break;
case 37:
radius = 2.26;
break;
case 53:
radius = 2.10;
break;
case 54:
radius = 1.967;
break;
case 55:
radius = 2.507;
break;
case 56:
radius = 2.188;
break;
default:
radius = 2.0;
break;
}
gbsaRadii[atomI] = (RealOpenMM) radius;
}
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 __CpuObcInterface_H__
#define __CpuObcInterface_H__
#ifdef __cplusplus
#define externC extern "C"
#else
#define externC extern
#endif
#include "../SimTKUtilities/SimTKOpenMMRealType.h"
#include <stdio.h>
/**---------------------------------------------------------------------------------------
Retrieve the calculated implicit solvation energy from the static class member
@return the calculated energy from the static class member
--------------------------------------------------------------------------------------- */
externC RealOpenMM cpuGetImplicitSolventEnergy( void );
/**---------------------------------------------------------------------------------------
Delete the Obc associated object(s)
@return 0 if static CpuObc object was set; else return -1
--------------------------------------------------------------------------------------- */
externC int cpuDeleteObcParameters( void );
/**---------------------------------------------------------------------------------------
Setup for Obc calculations from Gromacs
@param numberOfAtoms number of atoms
@param obcScaleFactors array of OBC scale factors (one entry each atom)
@param atomicRadii atomic radii in Angstrom (one entry each atom)
@param includeAceApproximation if true, then include nonpolar
ACE term in calculations
@param soluteDielectric solute dielectric
@param solventDielectric solvent dielectric
@param log log reference -- if NULL, then errors/warnings
output to stderr
The method creates a CpuObc instance -- currently the OBC type II model is the
default (see paper). If the OBC type I model is desired change
ObcParameters* obcParameters = new ObcParameters( numberOfAtoms, ObcParameters::ObcTypeII );
to
ObcParameters* obcParameters = new ObcParameters( numberOfAtoms, ObcParameters::ObcTypeI );
The created object is a static member of the class CpuObc;
when the force routine, cpuCalculateObcForces(), is called,
the static object is used to compute the forces and energy
@return 0
--------------------------------------------------------------------------------------- */
externC
int cpuSetObcParameters( int numberOfAtoms, RealOpenMM* atomicRadii, RealOpenMM* obcScaleFactors,
int includeAceApproximation, RealOpenMM soluteDielectric,
RealOpenMM solventDielectric, FILE* log );
/**---------------------------------------------------------------------------------------
Calculate implicit solvent forces and energy
@param atomCoordinates atom coordinates in Angstrom; format of array is
atomCoordinates[atom][3]
@param partialCharges partial atom charges
@param forces output forces in kcal/mol.A; format of array is
forces[atom][3]
@param energy energy
@param updateBornRadii if set, then Born radii are updated for current configuration;
otherwise radii correspond to configuration from previous iteration
Function calls a static method in CpuImplicitSolvent class to calculate forces/energy
@return result from CpuImplicitSolvent::computeImplicitSolventForces
--------------------------------------------------------------------------------------- */
externC int cpuCalculateImplicitSolventForces( RealOpenMM** atomCoordinates,
const RealOpenMM* partialChargesIn,
RealOpenMM** forces, RealOpenMM* energy,
int updateBornRadii );
/**---------------------------------------------------------------------------------------
Get OBC scale factors given masses
@param numberOfAtoms number of atoms
@param masses input masses
@param scaleFactors output atomic numbers
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
externC int getObcScaleFactorsGivenAtomMasses( int numberOfAtoms, const RealOpenMM* masses,
RealOpenMM* scaleFactors );
/**---------------------------------------------------------------------------------------
Get OBC scale factors given atomic numbers
@param numberOfAtoms number of atoms
@param atomicNumber input atomic number for each atom
@param scaleFactors output atomic numbers
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
externC int getObcScaleFactors( int numberOfAtoms, const int* atomicNumber,
RealOpenMM* scaleFactors );
/**---------------------------------------------------------------------------------------
Get GBSA radii
@param numberOfAtoms number of atoms
@param atomicNumber input atomic number for each atom
@param numberOfCovalentPartners input number of covalent partners for each atom
1 for H, ...; only used for C, N & O
@param indexOfCovalentPartner index of covalent partner -- only used for H
e.g. if atom 22 is a H and it is bonded to atom 24
then indexOfCovalentPartner[22] = 24
@param gbsaRadii output GBSA radii
@return SimTKOpenMMCommon::DefaultReturn
--------------------------------------------------------------------------------------- */
externC int getGbsaRadii( int numberOfAtoms, const int* atomicNumber,
const int* numberOfCovalentPartners,
const int* indexOfCovalentPartner, RealOpenMM* gbsaRadii );
#undef externC
#endif
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* 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. *
* -------------------------------------------------------------------------- */
/**
* This tests the reference implementation of GBSAOBCForceField.
*/
#include "../../../tests/AssertionUtilities.h"
#include "OpenMMContext.h"
#include "ReferencePlatform.h"
#include "GBSAOBCForceField.h"
#include "System.h"
#include "LangevinIntegrator.h"
#include "../src/SimTKUtilities/SimTKOpenMMRealType.h"
#include "../src/sfmt/SFMT.h"
#include <iostream>
#include <vector>
using namespace OpenMM;
using namespace std;
const double TOL = 1e-5;
void testSingleAtom() {
ReferencePlatform platform;
System system(1, 0);
system.setAtomMass(0, 2.0);
LangevinIntegrator integrator(0, 0.1, 0.01);
GBSAOBCForceField* forceField = new GBSAOBCForceField(1);
forceField->setAtomParameters(0, 0.5, 1.5, 1);
system.addForce(forceField);
OpenMMContext context(system, integrator, platform);
vector<Vec3> positions(1);
positions[0] = Vec3(0, 0, 0);
context.setPositions(positions);
State state = context.getState(State::Energy);
double bornRadius = 1.5-0.09; // dielectric offset
double eps0 = EPSILON0*A2NM*CAL2JOULE;
double bornEnergy = (-0.5*0.5/(8*PI_M*eps0))*(1.0/forceField->getSoluteDielectric()-1.0/forceField->getSolventDielectric())/bornRadius;
double extendedRadius = bornRadius+1.4; // probe radius
double nonpolarEnergy = PI_M*0.0216*extendedRadius*extendedRadius*std::pow(1.5/bornRadius, 6.0); // Where did this formula come from? Just copied it from CpuImplicitSolvent.cpp
ASSERT_EQUAL_TOL(bornEnergy+nonpolarEnergy, state.getPotentialEnergy(), 0.01);
}
void testForce() {
ReferencePlatform platform;
const int numAtoms = 10;
System system(numAtoms, 0);
LangevinIntegrator integrator(0, 0.1, 0.01);
GBSAOBCForceField* forceField = new GBSAOBCForceField(numAtoms);
for (int i = 0; i < numAtoms; ++i)
forceField->setAtomParameters(i, i%2 == 0 ? -1 : 1, 1.5, 1);
system.addForce(forceField);
OpenMMContext context(system, integrator, platform);
// Set random positions for all the atoms.
vector<Vec3> positions(numAtoms);
init_gen_rand(0);
for (int i = 0; i < numAtoms; ++i)
positions[i] = Vec3(5.0*genrand_real2(), 5.0*genrand_real2(), 5.0*genrand_real2());
context.setPositions(positions);
State state = context.getState(State::Forces | State::Energy);
// Take a small step in the direction of the energy gradient.
double norm = 0.0;
for (int i = 0; i < numAtoms; ++i) {
Vec3 f = state.getForces()[i];
norm += f[0]*f[0] + f[1]*f[1] + f[2]*f[2];
}
norm = std::sqrt(norm);
const double delta = 1e-3;
double step = delta/norm;
for (int i = 0; i < numAtoms; ++i) {
Vec3 p = positions[i];
Vec3 f = state.getForces()[i];
positions[i] = Vec3(p[0]-f[0]*step, p[1]-f[1]*step, p[2]-f[2]*step);
}
context.setPositions(positions);
// See whether the potential energy changed by the expected amount.
State state2 = context.getState(State::Energy);
ASSERT_EQUAL_TOL(norm, (state2.getPotentialEnergy()-state.getPotentialEnergy())/delta, 0.01)
}
int main() {
try {
testSingleAtom();
testForce();
}
catch(const exception& e) {
cout << "exception: " << e.what() << endl;
return 1;
}
cout << "Done" << endl;
return 0;
}
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