/* -------------------------------------------------------------------------- *
* 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) 2009 Stanford University and the Authors. *
* Authors: Peter Eastman, Mark Friedrichs *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see . *
* -------------------------------------------------------------------------- */
/**
* Tests:
* (1) the relative differences between the Cuda and Reference forces agree to within specified tolerance
* (2) energy and forces are consistent
* (3) energy conservation (Verlet)/thermal stability (Langevin)
*
*/
#include "../../../tests/AssertionUtilities.h"
#include "CudaPlatform.h"
#include "ReferencePlatform.h"
#include "openmm/Context.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/HarmonicAngleForce.h"
#include "openmm/PeriodicTorsionForce.h"
#include "openmm/RBTorsionForce.h"
#include "openmm/GBSAOBCForce.h"
#include "openmm/GBVIForce.h"
#include "openmm/NonbondedForce.h"
#include "openmm/CMMotionRemover.h"
#include "openmm/System.h"
#include "openmm/LangevinIntegrator.h"
#include "openmm/VariableLangevinIntegrator.h"
#include "openmm/VerletIntegrator.h"
#include "openmm/VariableVerletIntegrator.h"
#include "openmm/BrownianIntegrator.h"
#include "../src/sfmt/SFMT.h"
// free-energy plugin includes
#define INCLUDE_FREE_ENERGY_PLUGIN
#ifdef INCLUDE_FREE_ENERGY_PLUGIN
#include "OpenMMFreeEnergy.h"
#include "openmm/freeEnergyKernels.h"
#include "ReferenceFreeEnergyKernelFactory.h"
#include "CudaFreeEnergyKernelFactory.h"
#endif
#include
#include
#include
#include
#include
#include
#include
#ifdef _MSC_VER
#define isinf !_finite
#define isnan _isnan
#endif
// max entries to print for default output
#define MAX_PRINT 5
// force names
std::string HARMONIC_BOND_FORCE = "HarmonicBond";
std::string HARMONIC_ANGLE_FORCE = "HarmonicAngle";
std::string PERIODIC_TORSION_FORCE = "PeriodicTorsion";
std::string RB_TORSION_FORCE = "RbTorsion";
std::string NB_FORCE = "Nb";
std::string NB_SOFTCORE_FORCE = "NbSoftcore";
std::string NB_EXCEPTION_FORCE = "NbException";
std::string NB_EXCEPTION_SOFTCORE_FORCE = "NbExceptionSoftcore";
std::string GBSA_OBC_FORCE = "Obc";
std::string GBSA_OBC_SOFTCORE_FORCE = "ObcSoftcore";
std::string GBVI_FORCE = "GBVI";
std::string GBVI_SOFTCORE_FORCE = "GBVISoftcore";
#define BOLTZMANN (1.380658e-23) /* (J/K) */
#define AVOGADRO (6.0221367e23) /* () */
#define RGAS (BOLTZMANN*AVOGADRO) /* (J/(mol K)) */
#define BOLTZ (RGAS/1.0e+03) /* (kJ/(mol K)) */
using namespace OpenMM;
using namespace std;
// the following are used in parsing parameter file
typedef std::vector StringVector;
typedef StringVector::iterator StringVectorI;
typedef StringVector::const_iterator StringVectorCI;
typedef std::vector > VectorOfVectors;
typedef VectorOfVectors::iterator VectorOfVectorsI;
typedef VectorOfVectors::const_iterator VectorOfVectorsCI;
typedef std::map< std::string, VectorOfVectors > MapStringVectorOfVectors;
typedef MapStringVectorOfVectors::iterator MapStringVectorOfVectorsI;
typedef MapStringVectorOfVectors::const_iterator MapStringVectorOfVectorsCI;
typedef std::map< std::string, std::string > MapStringString;
typedef MapStringString::iterator MapStringStringI;
typedef MapStringString::const_iterator MapStringStringCI;
typedef std::map< std::string, int > MapStringInt;
typedef MapStringInt::iterator MapStringIntI;
typedef MapStringInt::const_iterator MapStringIntCI;
/* --------------------------------------------------------------------------------------- */
// internal routines
char* readLine( FILE* filePtr, StringVector& tokens, int* lineCount, FILE* log );
int readVec3( FILE* filePtr, const StringVector& tokens, std::vector& coordinates, int* lineCount, FILE* log );
/* --------------------------------------------------------------------------------------- */
// default return value from methods
static const int DefaultReturnValue = 0;
/**---------------------------------------------------------------------------------------
Find stats for vec3
@param array array
@param statVector vector of stats
@return 0
--------------------------------------------------------------------------------------- */
static int findStatsForVec3( const std::vector& array, std::vector& statVector ){
// ---------------------------------------------------------------------------------------
static const int STAT_AVG = 0;
static const int STAT_STD = 1;
static const int STAT_MIN = 2;
static const int STAT_ID1 = 3;
static const int STAT_MAX = 4;
static const int STAT_ID2 = 5;
static const int STAT_CNT = 6;
//static const char* methodName = "\nfindStatsForVec3: ";
// ---------------------------------------------------------------------------------------
statVector.resize( STAT_CNT + 1 );
double avgValue = 0.0;
double stdValue = 0.0;
double minValue = 1.0e+30;
double maxValue = -1.0e+30;
int minValueIndex = 0;
int maxValueIndex = 0;
for( unsigned int ii = 0; ii < array.size(); ii++ ){
double norm2 = array[ii][0]*array[ii][0] + array[ii][1]*array[ii][1] + array[ii][2]*array[ii][2];
double norm = std::sqrt( norm2 );
avgValue += norm;
stdValue += norm2;
if( norm > maxValue ){
maxValue = norm;
maxValueIndex = ii;
}
if( norm < minValue ){
minValue = norm;
minValueIndex = ii;
}
}
double count = static_cast(array.size());
double iCount = count > 0.0 ? 1.0/count : 0.0;
statVector[STAT_AVG] = avgValue*iCount;
statVector[STAT_STD] = stdValue - avgValue*avgValue*count;
if( count > 1.0 ){
statVector[STAT_STD] = std::sqrt( stdValue/( count - 1.0 ) );
}
statVector[STAT_MIN] = minValue;
statVector[STAT_ID1] = static_cast(minValueIndex);
statVector[STAT_MAX] = maxValue;
statVector[STAT_ID2] = static_cast(maxValueIndex);
statVector[STAT_CNT] = count;
return DefaultReturnValue;
}
/* ---------------------------------------------------------------------------------------
Compute cross product of two 3-vectors and place in 3rd vector -- helper method
vectorZ = vectorX x vectorY
@param vectorX x-vector
@param vectorY y-vector
@param vectorZ z-vector
@return vector is vectorZ
--------------------------------------------------------------------------------------- */
void crossProductVector3D( double* vectorX, double* vectorY, double* vectorZ ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "crossProductVector3D";
// ---------------------------------------------------------------------------------------
vectorZ[0] = vectorX[1]*vectorY[2] - vectorX[2]*vectorY[1];
vectorZ[1] = vectorX[2]*vectorY[0] - vectorX[0]*vectorY[2];
vectorZ[2] = vectorX[0]*vectorY[1] - vectorX[1]*vectorY[0];
return;
}
/* ---------------------------------------------------------------------------------------
Compute cross product of two 3-vectors and place in 3rd vector -- helper method
vectorZ = vectorX x vectorY
@param vectorX x-vector
@param vectorY y-vector
@param vectorZ z-vector
@return vector is vectorZ
--------------------------------------------------------------------------------------- */
void crossProductVector3F( float* vectorX, float* vectorY, float* vectorZ ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "crossProductVector3D";
// ---------------------------------------------------------------------------------------
vectorZ[0] = vectorX[1]*vectorY[2] - vectorX[2]*vectorY[1];
vectorZ[1] = vectorX[2]*vectorY[0] - vectorX[0]*vectorY[2];
vectorZ[2] = vectorX[0]*vectorY[1] - vectorX[1]*vectorY[0];
return;
}
/* ---------------------------------------------------------------------------------------
Return nonzero if all entries in array targets match all entries in array bond (order unimportant)
@param numberIndices number of entries in array
@param targets array of numberIndices ints
@param bond array of numberIndices ints
@return nonzero if all entries in targets match all entries in bond (order unimportant)
--------------------------------------------------------------------------------------- */
static int checkBondIndices( int numberIndices, const int* targets, const int* bond ){
// ---------------------------------------------------------------------------------------
// static const char* methodName = "checkBondIndices";
// ---------------------------------------------------------------------------------------
for( int ii = 0; ii < numberIndices; ii++ ){
int hit = 0;
for( int jj = 0; jj < numberIndices && hit == 0; jj++ ){
if( targets[ii] == bond[jj] )hit = 1;
}
if( hit == 0 )return 0;
}
return 1;
}
/**---------------------------------------------------------------------------------------
Find stats for double array
@param array array
@param statVector vector of stats
@return 0
--------------------------------------------------------------------------------------- */
static int findStatsForDouble( const std::vector& array, std::vector& statVector ){
// ---------------------------------------------------------------------------------------
static const int STAT_AVG = 0;
static const int STAT_STD = 1;
static const int STAT_MIN = 2;
static const int STAT_ID1 = 3;
static const int STAT_MAX = 4;
static const int STAT_ID2 = 5;
static const int STAT_CNT = 6;
//static const char* methodName = "\nfindStatsForDouble: ";
// ---------------------------------------------------------------------------------------
statVector.resize( STAT_CNT + 1 );
double avgValue = 0.0;
double stdValue = 0.0;
double minValue = 1.0e+30;
double maxValue = -1.0e+30;
int minValueIndex = 0;
int maxValueIndex = 0;
for( unsigned int ii = 0; ii < array.size(); ii++ ){
double norm = array[ii];
avgValue += norm;
stdValue += norm*norm;
if( norm > maxValue ){
maxValue = norm;
maxValueIndex = ii;
}
if( norm < minValue ){
minValue = norm;
minValueIndex = ii;
}
}
double count = static_cast(array.size());
double iCount = count > 0.0 ? 1.0/count : 0.0;
statVector[STAT_AVG] = avgValue*iCount;
statVector[STAT_STD] = stdValue - avgValue*avgValue*count;
if( count > 1.0 ){
statVector[STAT_STD] = std::sqrt( stdValue/( count - 1.0 ) );
}
statVector[STAT_MIN] = minValue;
statVector[STAT_ID1] = static_cast(minValueIndex);
statVector[STAT_MAX] = maxValue;
statVector[STAT_ID2] = static_cast(maxValueIndex);
statVector[STAT_CNT] = count;
return DefaultReturnValue;
}
/**
* Write vec3 array to file
*
* @param filePtr file ptr to output data
* @param vect3Array array to output
*
* @return 0
*/
static int writeFileVec3( FILE* filePtr, const std::vector& vect3Array ){
for( unsigned int ii = 0; ii < vect3Array.size(); ii++ ){
(void) fprintf( filePtr, "%8d %14.7e %14.7e %14.7e\n", ii,
vect3Array[ii][0], vect3Array[ii][1], vect3Array[ii][2] );
}
return 0;
}
/**---------------------------------------------------------------------------------------
* Write context to file
*
* @param fileName file name
* @param context OpenMM::Context used to get current positions
* @param stateFlag State::Positions | State::Velocities | State::Forces | State::Energy
* @param log log file
*
* @return 0
--------------------------------------------------------------------------------------- */
static int writeContextToFile( std::string fileName, Context& context, int stateFlag, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "writeContextToFile";
// ---------------------------------------------------------------------------------------
// open file
FILE* filePtr;
#ifdef _MSC_VER
fopen_s( &filePtr, fileName.c_str(), "w" );
#else
filePtr = fopen( fileName.c_str(), "w" );
#endif
if( filePtr == NULL ){
char buffer[1024];
(void) sprintf( buffer, "%s file=<%s> not opened.\n", methodName.c_str(), fileName.c_str());
throwException(__FILE__, __LINE__, buffer );
exit(-1);
} else if( log ){
(void) fprintf( log, "%s opened file %s.\n", methodName.c_str(), fileName.c_str());
}
State state = context.getState( stateFlag );
if( stateFlag && State::Positions ){
std::vector positions = state.getPositions();
(void) fprintf( filePtr, "Positions %u\n", positions.size() );
writeFileVec3( filePtr, positions );
}
if( stateFlag && State::Velocities ){
std::vector velocities = state.getVelocities();
(void) fprintf( filePtr, "Velocities %u\n", velocities.size() );
writeFileVec3( filePtr, velocities );
}
if( stateFlag && State::Forces ){
std::vector forces = state.getForces();
(void) fprintf( filePtr, "Forces %u\n", forces.size() );
writeFileVec3( filePtr, forces );
}
if( stateFlag && State::Energy ){
(void) fprintf( filePtr, "KineticEnergy %14.7e\n", state.getKineticEnergy() );
(void) fprintf( filePtr, "PotentialEnergy %14.7e\n", state.getPotentialEnergy() );
}
(void) fclose( filePtr );
return 0;
}
/**---------------------------------------------------------------------------------------
* Read context from file
*
* @param fileName file name
* @param context OpenMM::Context to update
* @param stateFlag State::Positions | State::Velocities | State::Forces | State::Energy
* @param log log file
*
* @return 0
--------------------------------------------------------------------------------------- */
static int readContextFromFile( std::string fileName, Context& context, int stateFlag, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readContextFromFile";
// ---------------------------------------------------------------------------------------
// open file
FILE* filePtr;
#ifdef _MSC_VER
fopen_s( &filePtr, fileName.c_str(), "r" );
#else
filePtr = fopen( fileName.c_str(), "r" );
#endif
if( filePtr == NULL ){
char buffer[1024];
(void) sprintf( buffer, "%s file=<%s> not opened.\n", methodName.c_str(), fileName.c_str());
throwException(__FILE__, __LINE__, buffer );
exit(-1);
} else if( log ){
(void) fprintf( log, "%s opened file %s.\n", methodName.c_str(), fileName.c_str());
}
std::vector coordinates;
std::vector velocities;
std::vector forces;
double kineticEnergy, potentialEnergy;
std::string version;
int lineCount = 0;
char* isNotEof = "1";
while( isNotEof ){
// read line and continue if not EOF and tokens found on line
StringVector tokens;
isNotEof = readLine( filePtr, tokens, &lineCount, log );
if( isNotEof && tokens.size() > 0 ){
std::string field = tokens[0];
if( log ){
(void) fprintf( log, "Field=<%s> at line=%d\n", field.c_str(), lineCount );
}
if( field.compare( "Version" ) == 0 ){
if( tokens.size() > 1 ){
version = tokens[1];
if( log ){
(void) fprintf( log, "Version=<%s> at line=%d\n", version.c_str(), lineCount );
}
}
} else if( field.compare( "Positions" ) == 0 ){
readVec3( filePtr, tokens, coordinates, &lineCount, log );
} else if( field.compare( "Velocities" ) == 0 ){
readVec3( filePtr, tokens, velocities, &lineCount, log );
} else if( field.compare( "Forces" ) == 0 ){
readVec3( filePtr, tokens, forces, &lineCount, log );
} else if( field.compare( "KineticEnergy" ) == 0 ||
field.compare( "PotentialEnergy" ) == 0 ){
double value = 0.0;
if( tokens.size() > 1 ){
value = atof( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s =%s\n", tokens[0].c_str(), tokens[1].c_str());
}
} else {
char buffer[1024];
(void) sprintf( buffer, "Missing energy for field=<%s> at line=%d\n", field.c_str(), lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
if( field.compare( "KineticEnergy" ) == 0 ){
kineticEnergy = value;
} else {
potentialEnergy = value;
}
} else {
char buffer[1024];
(void) sprintf( buffer, "Field=<%s> not recognized at line=%d\n", field.c_str(), lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
}
// close file
(void) fclose( filePtr );
System& system = context.getSystem();
if( stateFlag & State::Positions ){
if( system.getNumParticles() != coordinates.size() ){
char buffer[1024];
(void) sprintf( buffer, "%s: number of positions=%u does not agree w/ number in system=%d\n",
methodName.c_str(), coordinates.size(), system.getNumParticles() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
} else if( log ){
(void) fprintf( log, "%s setting positions from context file.\n", methodName.c_str() );
}
context.setPositions( coordinates );
}
if( stateFlag & State::Velocities ){
if( system.getNumParticles() != velocities.size() ){
char buffer[1024];
(void) sprintf( buffer, "%s: number of velocities=%u does not agree w/ number in system=%d\n",
methodName.c_str(), velocities.size(), system.getNumParticles() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
} else if( log ){
(void) fprintf( log, "%s setting velocities from context file.\n", methodName.c_str() );
}
context.setVelocities( velocities );
}
return 0;
}
/**---------------------------------------------------------------------------------------
* Check constraints
*
* @param context OpenMM::Context used to get current positions
* @param system OpenMM::System to be created
* @param tolerance constraint tolerance
* @param maxViolation output max constraint violation
* @param log log file
*
* @return return number of violations
--------------------------------------------------------------------------------------- */
static int checkConstraints( const Context& context, const System& system, double tolerance,
double* maxViolation, FILE* log ) {
// ---------------------------------------------------------------------------------------
int totalPrints = 0;
int violations = 0;
// ---------------------------------------------------------------------------------------
*maxViolation = -1.0e-10;
State state = context.getState(State::Positions);
const std::vector& pos = state.getPositions();
for( int ii = 0; ii < system.getNumConstraints(); ii++ ){
int particle1;
int particle2;
double distance;
system.getConstraintParameters( ii, particle1, particle2, distance );
double actualDistance = sqrt(
(pos[particle2][0] - pos[particle1][0])*(pos[particle2][0] - pos[particle1][0]) +
(pos[particle2][1] - pos[particle1][1])*(pos[particle2][1] - pos[particle1][1]) +
(pos[particle2][2] - pos[particle1][2])*(pos[particle2][2] - pos[particle1][2]) );
double delta = fabs( actualDistance - distance );
if( delta > tolerance ){
violations++;
if( delta > *maxViolation ){
*maxViolation = delta;
}
if( log && totalPrints++ < 10 ){
(void) fprintf( log, "CnstrViolation: %6d %6d particles[%6d %6d] delta=%10.3e d[%12.5e %12.5e] \n",
ii, violations, particle1, particle2, delta, distance, actualDistance );
}
}
}
if( log && violations ){
(void) fprintf( log, "CnstrViolation: total violations=%d out of %d constraints; maxViolation=%13.6e tolerance=%.3e.\n",
violations, system.getNumConstraints(), *maxViolation, tolerance );
}
return violations;
}
/**---------------------------------------------------------------------------------------
Sum forces
@param context OpenMM::Context used to get current positions
@param system OpenMM::System to be created
@param forceSum on return, sum of forces
@param step step index
@param log log reference (stdlog in md.c)
@return DefaultReturnValue
--------------------------------------------------------------------------------------- */
static int sumForces( const Context& context, const System& system, double forceSum[3], int step, FILE* log ){
// ---------------------------------------------------------------------------------------
double sum;
// ---------------------------------------------------------------------------------------
State state = context.getState(State::Forces);
const std::vector& forces = state.getForces();
// sum forces and track max value
forceSum[0] = forceSum[1] = forceSum[2] = 0.0;
double forceMax = -1.0;
int forceMaxIndex = -1;
for( int ii = 0; ii < system.getNumParticles(); ii++ ){
forceSum[0] += forces[ii][0];
forceSum[1] += forces[ii][1];
forceSum[2] += forces[ii][2];
double forceMagnitude = forces[ii][0]*forces[ii][0] + forces[ii][1]*forces[ii][1] + forces[ii][2]*forces[ii][2];
if( forceMagnitude > forceMax ){
forceMax = forceMagnitude;
forceMaxIndex = ii;
}
}
if( 0 ){
sum = fabs( forceSum[0] ) + fabs( forceSum[1] ) + fabs( forceSum[2] );
(void) fprintf( log, "Force: Step=%d %.4e f[%.4e %.4e %.4e] Max=%.3e at index=%d\n", step, sum,
forceSum[0], forceSum[1], forceSum[2], sqrt( forceMax ), forceMaxIndex );
}
return 0;
}
/**---------------------------------------------------------------------------------------
Check kinetic energy
@param numberOfAtoms number of atoms
@param nrdf number of degrees of freedom
@param v velocities
@param mass masses
@param temperature temperature
@param step step index
@param log log reference (stdlog in md.c)
@return DefaultReturnValue if k.e. ~ temp;
--------------------------------------------------------------------------------------- */
static int checkKineticEnergy( const Context& context, const System& system, double temperature, int step, FILE* log ){
// ---------------------------------------------------------------------------------------
double kineticEnergy;
int status = 0;
int print = 1;
double cutoff = 200.0;
static double average = 0.0;
static double stddev = 0.0;
static double count = 0.0;
// ---------------------------------------------------------------------------------------
// calculate kineticEnergy
State state = context.getState(State::Energy);
kineticEnergy = 2.0*state.getKineticEnergy();
int nrdf = 3*system.getNumParticles() - system.getNumConstraints() - 3;
kineticEnergy /= (((double) BOLTZ)*((double) nrdf));
if( print ){
double averageL, stddevL;
average += kineticEnergy;
stddev += kineticEnergy*kineticEnergy;
count += 1.0;
averageL = average/count;
stddevL = stddev - averageL*averageL*count;
if( stddevL > 0.0 && count > 1 ){
stddevL = sqrt( stddevL/(count - 1.0 ) );
}
(void) (void) fprintf( log, "checkKineticEnergy: Step=%d T=%.3f avg=%g std=%.3f nrdf=%d\n", step, kineticEnergy, averageL, stddevL, nrdf);
}
// only check if calculated T is > specified T
/*
if( (kineticEnergy - temperature) > cutoff ){
(void) (void) fprintf( log, "checkKineticEnergy: ERROR Step=%d T=%.3f tpr-T=%.3f diff=%.3f cutoff=%.3f\n",
step, kineticEnergy, temperature, (kineticEnergy - temperature), cutoff );
(void) fflush( NULL );
status = 1;
}
*/
// ignore calculation prior to 2000 steps
return 0;
}
/**---------------------------------------------------------------------------------------
Replacement of sorts for strtok()
Used to parse parameter file lines
@param lineBuffer string to tokenize
@param delimiter token delimter
@return number of args
--------------------------------------------------------------------------------------- */
char* strsepLocal( char** lineBuffer, const char* delimiter ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "strsepLocal";
char *s;
const char *spanp;
int c, sc;
char *tok;
// ---------------------------------------------------------------------------------------
s = *lineBuffer;
if( s == NULL ){
return (NULL);
}
for( tok = s;; ){
c = *s++;
spanp = delimiter;
do {
if( (sc = *spanp++) == c ){
if( c == 0 ){
s = NULL;
} else {
s[-1] = 0;
}
/*
if( *s == '\n' ){
*s = NULL;
}
*/
*lineBuffer = s;
return( tok );
}
} while( sc != 0 );
}
}
/**---------------------------------------------------------------------------------------
Tokenize a string
@param lineBuffer string to tokenize
@param tokenArray upon return vector of tokens
@param delimiter token delimter
@return number of tokens
--------------------------------------------------------------------------------------- */
int tokenizeString( char* lineBuffer, StringVector& tokenArray, const std::string delimiter ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "tokenizeString";
// ---------------------------------------------------------------------------------------
char *ptr_c = NULL;
for( ; (ptr_c = strsepLocal( &lineBuffer, delimiter.c_str() )) != NULL; ){
if( *ptr_c ){
/*
char* endOfLine = ptr_c;
while( endOfLine ){
printf( "%c", *endOfLine ); fflush( stdout );
if( *endOfLine == '\n' )*endOfLine = '\0';
endOfLine++;
}
*/
tokenArray.push_back( std::string( ptr_c ) );
}
}
return (int) tokenArray.size();
}
/**---------------------------------------------------------------------------------------
Read a line from a file and tokenize into an array of strings
@param filePtr file to read from
@param tokens array of token strings
@param lineCount line count
@param log optional file ptr for logging
@return ptr to string containing line
--------------------------------------------------------------------------------------- */
char* readLine( FILE* filePtr, StringVector& tokens, int* lineCount, FILE* log ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "readLine";
std::string delimiter = " \n";
const int bufferSize = 4096;
char buffer[bufferSize];
// ---------------------------------------------------------------------------------------
char* isNotEof = fgets( buffer, bufferSize, filePtr );
if( isNotEof ){
(*lineCount)++;
tokenizeString( buffer, tokens, delimiter );
}
return isNotEof;
}
/**---------------------------------------------------------------------------------------
Read vector of double vectors
@param filePtr file pointer to parameter file
@param tokens array of strings from first line of parameter file for this block of parameters
@param vectorOfVectors output of vector of vectors
@param lineCount used to track line entries read from parameter file
@param typeName id of entries being read
@param log log file pointer -- may be NULL
@return number of entries read
--------------------------------------------------------------------------------------- */
static int readVectorOfVectors( FILE* filePtr, const StringVector& tokens, std::vector< std::vector >& vectorOfVectors,
int* lineCount, std::string typeName, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readVec3";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no Coordinates terms entry???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
int numberToRead = atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s number of %s to read: %d\n", methodName.c_str(), typeName.c_str(), numberToRead );
(void) fflush( log );
}
for( int ii = 0; ii < numberToRead; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 1 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
std::vector nextEntry;
for( unsigned int jj = 1; jj < lineTokens.size(); jj++ ){
double value = atof( lineTokens[jj].c_str() );
nextEntry.push_back( value );
}
vectorOfVectors.push_back( nextEntry );
} else {
char buffer[1024];
(void) sprintf( buffer, "%s %s tokens incomplete at line=%d\n", methodName.c_str(), typeName.c_str(), *lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
// diagnostics
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
unsigned int arraySize = vectorOfVectors.size();
(void) fprintf( log, "%s: sample of %s size=%u\n", methodName.c_str(), typeName.c_str(), arraySize );
for( unsigned int ii = 0; ii < vectorOfVectors.size(); ii++ ){
(void) fprintf( log, "%6u [", ii );
for( unsigned int jj = 0; jj < vectorOfVectors[ii].size(); jj++ ){
(void) fprintf( log, "%14.7e ", vectorOfVectors[ii][jj] );
}
(void) fprintf( log, "]\n" );
// skip to end
if( ii == maxPrint && (arraySize - maxPrint) > ii ){
ii = arraySize - maxPrint - 1;
if( ii < maxPrint )ii = maxPrint;
}
}
}
return static_cast(vectorOfVectors.size());
}
/**---------------------------------------------------------------------------------------
* Set field if in map
*
* @param argumentMap map to check
* @param fieldToCheck key
* @param fieldToSet field to set
*
* @return 1 if argument set, else 0
*
--------------------------------------------------------------------------------------- */
static int setStringFromMap( MapStringString& argumentMap, std::string fieldToCheck, std::string& fieldToSet ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "setStringFromMap";
// ---------------------------------------------------------------------------------------
MapStringStringCI check = argumentMap.find( fieldToCheck );
if( check != argumentMap.end() ){
fieldToSet = (*check).second;
return 1;
}
return 0;
}
/**---------------------------------------------------------------------------------------
* Set field if in map
*
* @param argumentMap map to check
* @param fieldToCheck key
* @param fieldToSet field to set
*
* @return 1 if argument set, else 0
*
--------------------------------------------------------------------------------------- */
static int setIntFromMap( MapStringString& argumentMap, std::string fieldToCheck, int& fieldToSet ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "setIntFromMap";
// ---------------------------------------------------------------------------------------
MapStringStringCI check = argumentMap.find( fieldToCheck );
if( check != argumentMap.end() ){
fieldToSet = atoi( (*check).second.c_str() );
return 1;
}
return 0;
}
/**---------------------------------------------------------------------------------------
* Set field if in map
*
* @param argumentMap map to check
* @param fieldToCheck key
* @param fieldToSet field to set
*
* @return 1 if argument set, else 0
*
--------------------------------------------------------------------------------------- */
static int setDoubleFromMap( MapStringString& argumentMap, std::string fieldToCheck, double& fieldToSet ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "setDoubleFromMap";
// ---------------------------------------------------------------------------------------
MapStringStringCI check = argumentMap.find( fieldToCheck );
if( check != argumentMap.end() ){
fieldToSet = atof( (*check).second.c_str() );
return 1;
}
return 0;
}
/**---------------------------------------------------------------------------------------
Read particles count
@param filePtr file pointer to parameter file
@param tokens array of strings from first line of parameter file for this block of parameters
@param system System reference
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return number of parameters read
--------------------------------------------------------------------------------------- */
static int readParticles( FILE* filePtr, const StringVector& tokens, System& system, int* lineCount, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readParticles";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no particles number entry???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
int numberOfParticles = atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s particles=%d\n", methodName.c_str(), numberOfParticles );
}
return numberOfParticles;
}
/**---------------------------------------------------------------------------------------
Read particle masses
@param filePtr file pointer to parameter file
@param tokens array of strings from first line of parameter file for this block of parameters
@param system System reference
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return number of masses read
--------------------------------------------------------------------------------------- */
static int readMasses( FILE* filePtr, const StringVector& tokens, System& system, int* lineCount, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readMasses";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no particles number entry???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
int numberOfParticles = atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s particle masses=%d\n", methodName.c_str(), numberOfParticles );
}
for( int ii = 0; ii < numberOfParticles; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() >= 1 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
double mass = atof( lineTokens[tokenIndex++].c_str() );
system.addParticle( mass );
} else {
char buffer[1024];
(void) sprintf( buffer, "%s particle tokens incomplete at line=%d\n", methodName.c_str(), *lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
// diagnostics
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
unsigned int arraySize = static_cast(system.getNumParticles());
(void) fprintf( log, "%s: sample of masses\n", methodName.c_str() );
for( unsigned int ii = 0; ii < arraySize; ii++ ){
(void) fprintf( log, "%6u %14.7e \n", ii, system.getParticleMass( ii ) );
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
return system.getNumParticles();
}
/**---------------------------------------------------------------------------------------
Read harmonic bond parameters
@param filePtr file pointer to parameter file
@param forceFlag flag signalling whether force is to be added to system
if force == 0 || forceFlag & HARMONIC_BOND_FORCE, then included
@param tokens array of strings from first line of parameter file for this block of parameters
@param system System reference
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return number of bonds
--------------------------------------------------------------------------------------- */
static int readHarmonicBondForce( FILE* filePtr, MapStringInt& forceMap, const StringVector& tokens, System& system, int* lineCount, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readHarmonicBondForce";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no bonds number entry???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
HarmonicBondForce* bondForce = new HarmonicBondForce();
MapStringIntI forceActive = forceMap.find( HARMONIC_BOND_FORCE );
if( forceActive != forceMap.end() && (*forceActive).second ){
system.addForce( bondForce );
if( log ){
(void) fprintf( log, "harmonic bond force is being included.\n" );
}
} else if( log ){
(void) fprintf( log, "harmonic bond force is not being included.\n" );
}
int numberOfBonds = atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s number of HarmonicBondForce terms=%d\n", methodName.c_str(), numberOfBonds );
}
for( int ii = 0; ii < numberOfBonds; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 4 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
int particle1 = atoi( lineTokens[tokenIndex++].c_str() );
int particle2 = atoi( lineTokens[tokenIndex++].c_str() );
double length = atof( lineTokens[tokenIndex++].c_str() );
double k = atof( lineTokens[tokenIndex++].c_str() );
bondForce->addBond( particle1, particle2, length, k );
} else {
(void) fprintf( log, "%s HarmonicBondForce tokens incomplete at line=%d\n", methodName.c_str(), *lineCount );
exit(-1);
}
}
// diagnostics
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
unsigned int arraySize = static_cast(bondForce->getNumBonds());
(void) fprintf( log, "%s: sample of HarmonicBondForce parameters\n", methodName.c_str() );
for( unsigned int ii = 0; ii < arraySize; ii++ ){
int particle1, particle2;
double length, k;
bondForce->getBondParameters( ii, particle1, particle2, length, k );
(void) fprintf( log, "%8d %8d %8d %14.7e %14.7e\n", ii, particle1, particle2, length, k);
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
return bondForce->getNumBonds();
}
/**---------------------------------------------------------------------------------------
Read harmonic angle parameters
@param filePtr file pointer to parameter file
@param forceFlag flag signalling whether force is to be added to system
if force == 0 || forceFlag & HARMONIC_ANGLE_FORCE, then included
@param tokens array of strings from first line of parameter file for this block of parameters
@param system System reference
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return number of bonds
--------------------------------------------------------------------------------------- */
static int readHarmonicAngleForce( FILE* filePtr, MapStringInt& forceMap, const StringVector& tokens,
System& system, int* lineCount, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readHarmonicAngleForce";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no angle bonds number entry???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
}
HarmonicAngleForce* bondForce = new HarmonicAngleForce();
MapStringIntI forceActive = forceMap.find( HARMONIC_ANGLE_FORCE );
if( forceActive != forceMap.end() && (*forceActive).second ){
system.addForce( bondForce );
if( log ){
(void) fprintf( log, "harmonic angle force is being included.\n" );
}
} else if( log ){
(void) fprintf( log, "harmonic angle force is not being included.\n" );
}
int numberOfAngles = atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s number of HarmonicAngleForce terms=%d\n", methodName.c_str(), numberOfAngles );
}
for( int ii = 0; ii < numberOfAngles; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 5 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
int particle1 = atoi( lineTokens[tokenIndex++].c_str() );
int particle2 = atoi( lineTokens[tokenIndex++].c_str() );
int particle3 = atoi( lineTokens[tokenIndex++].c_str() );
double angle = atof( lineTokens[tokenIndex++].c_str() );
double k = atof( lineTokens[tokenIndex++].c_str() );
bondForce->addAngle( particle1, particle2, particle3, angle, k );
} else {
char buffer[1024];
(void) sprintf( buffer, "%s HarmonicAngleForce tokens incomplete at line=%d\n", methodName.c_str(), *lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
// diagnostics
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
unsigned int arraySize = static_cast(bondForce->getNumAngles());
(void) fprintf( log, "%s: sample of HarmonicAngleForce parameters\n", methodName.c_str() );
for( unsigned int ii = 0; ii < arraySize; ii++ ){
int particle1, particle2, particle3;
double angle, k;
bondForce->getAngleParameters( ii, particle1, particle2, particle3, angle, k );
(void) fprintf( log, "%8d %8d %8d %8d %14.7e %14.7e\n", ii, particle1, particle2, particle3, angle, k);
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
return bondForce->getNumAngles();
}
/**---------------------------------------------------------------------------------------
Read PeriodicTorsionForce parameters
@param filePtr file pointer to parameter file
@param forceFlag flag signalling whether force is to be added to system
if force == 0 || forceFlag & PERIODIC_TORSION_FORCE, then included
@param tokens array of strings from first line of parameter file for this block of parameters
@param system System reference
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return number of torsion bonds read
--------------------------------------------------------------------------------------- */
static int readPeriodicTorsionForce( FILE* filePtr, MapStringInt& forceMap, const StringVector& tokens, System& system, int* lineCount, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readPeriodicTorsionForce";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no PeriodicTorsion bonds number entry???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
PeriodicTorsionForce* bondForce = new PeriodicTorsionForce();
MapStringIntI forceActive = forceMap.find( PERIODIC_TORSION_FORCE );
if( forceActive != forceMap.end() && (*forceActive).second ){
system.addForce( bondForce );
if( log ){
(void) fprintf( log, "periodic torsion force is being included.\n" );
}
} else if( log ){
(void) fprintf( log, "periodic torsion force is not being included.\n" );
}
int numberOfTorsions = atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s number of PeriodicTorsionForce terms=%d\n", methodName.c_str(), numberOfTorsions );
}
for( int ii = 0; ii < numberOfTorsions; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 7 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
int particle1 = atoi( lineTokens[tokenIndex++].c_str() );
int particle2 = atoi( lineTokens[tokenIndex++].c_str() );
int particle3 = atoi( lineTokens[tokenIndex++].c_str() );
int particle4 = atoi( lineTokens[tokenIndex++].c_str() );
int periodicity = atoi( lineTokens[tokenIndex++].c_str() );
double phase = atof( lineTokens[tokenIndex++].c_str() );
double k = atof( lineTokens[tokenIndex++].c_str() );
bondForce->addTorsion( particle1, particle2, particle3, particle4, periodicity, phase, k );
} else {
char buffer[1024];
(void) sprintf( buffer, "%s PeriodicTorsionForce tokens incomplete at line=%d\n", methodName.c_str(), *lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
// diagnostics
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
unsigned int arraySize = static_cast(bondForce->getNumTorsions());
(void) fprintf( log, "%s: sample of PeriodicTorsionForce parameters\n", methodName.c_str() );
for( unsigned int ii = 0; ii < arraySize; ii++ ){
int particle1, particle2, particle3, particle4, periodicity;
double phase, k;
bondForce->getTorsionParameters( ii, particle1, particle2, particle3, particle4, periodicity, phase, k );
(void) fprintf( log, "%8d %8d %8d %8d %8d %8d %14.7e %14.7e\n", ii, particle1, particle2, particle3, particle4, periodicity, phase, k );
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
return bondForce->getNumTorsions();
}
/**---------------------------------------------------------------------------------------
Read RBTorsionForce parameters
@param filePtr file pointer to parameter file
@param forceFlag flag signalling whether force is to be added to system
if force == 0 || forceFlag & RB_TORSION_FORCE, then included
@param tokens array of strings from first line of parameter file for this block of parameters
@param system System reference
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return number of torsion bonds read
--------------------------------------------------------------------------------------- */
static int readRBTorsionForce( FILE* filePtr, MapStringInt& forceMap, const StringVector& tokens, System& system, int* lineCount, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readRBTorsionForce";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no RBTorsion bonds number entry???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
RBTorsionForce* bondForce = new RBTorsionForce();
MapStringIntI forceActive = forceMap.find( RB_TORSION_FORCE );
if( forceActive != forceMap.end() && (*forceActive).second ){
system.addForce( bondForce );
if( log ){
(void) fprintf( log, "RB torsion force is being included.\n" );
}
} else if( log ){
(void) fprintf( log, "RB torsion force is not being included.\n" );
}
int numberOfTorsions = atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s number of RBTorsionForce terms=%d\n", methodName.c_str(), numberOfTorsions );
(void) fflush( log );
}
#if 0
static int nextIndex = 0;
static int parity = 0;
int targets[12][4] = {
{ 315,318,319,320 },
{ 315,318,319,321 },
{ 327,318,319,320 },
{ 327,318,319,321 },
{ 319,318,327,325 },
{ 319,318,327,328 },
{ 318,319,321,322 },
{ 318,319,321,323 },
{ 320,319,321,322 },
{ 320,319,321,323 },
{ 319,321,323,324 },
{ 319,321,323,325 } };
#endif
for( int ii = 0; ii < numberOfTorsions; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 10 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
int particle1 = atoi( lineTokens[tokenIndex++].c_str() );
int particle2 = atoi( lineTokens[tokenIndex++].c_str() );
int particle3 = atoi( lineTokens[tokenIndex++].c_str() );
int particle4 = atoi( lineTokens[tokenIndex++].c_str() );
double c0 = atof( lineTokens[tokenIndex++].c_str() );
double c1 = atof( lineTokens[tokenIndex++].c_str() );
double c2 = atof( lineTokens[tokenIndex++].c_str() );
double c3 = atof( lineTokens[tokenIndex++].c_str() );
double c4 = atof( lineTokens[tokenIndex++].c_str() );
double c5 = atof( lineTokens[tokenIndex++].c_str() );
#if 0
int bond[4] = { particle1, particle2, particle3, particle4 };
if( nextIndex >= 12 )nextIndex = 0;
int isBond = checkBondIndices( 4, targets[nextIndex], bond );
if( isBond ){
if( log )
(void) fprintf( log, "TGT %d %d [%d %d %d %d]\n", nextIndex, parity, targets[nextIndex][0], targets[nextIndex][1], targets[nextIndex][2], targets[nextIndex][3] );
bondForce->addTorsion( particle1, particle2, particle3, particle4, c0, c1, c2, c3, c4, c5 );
}
#else
bondForce->addTorsion( particle1, particle2, particle3, particle4, c0, c1, c2, c3, c4, c5 );
#endif
} else {
char buffer[1024];
(void) sprintf( buffer, "%s RBTorsionForce tokens incomplete at line=%d\n", methodName.c_str(), *lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
#if 0
if( parity ){
nextIndex++;
parity = 0;
} else {
parity = 1;
}
#endif
// diagnostics
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
unsigned int arraySize = static_cast(bondForce->getNumTorsions());
(void) fprintf( log, "%s: sample of RBTorsionForce parameters\n", methodName.c_str() );
for( unsigned int ii = 0; ii < arraySize; ii++ ){
int particle1, particle2, particle3, particle4;
double c0, c1, c2, c3, c4, c5;
bondForce->getTorsionParameters( ii, particle1, particle2, particle3, particle4, c0, c1, c2, c3, c4, c5 );
(void) fprintf( log, "%8d %8d %8d %8d %8d %14.7e %14.7e %14.7e %14.7e %14.7e %14.7e\n",
ii, particle1, particle2, particle3, particle4, c0, c1, c2, c3, c4, c5 );
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
return bondForce->getNumTorsions();
}
/**---------------------------------------------------------------------------------------
Read NonbondedExceptions parameters
@param filePtr file pointer to parameter file
@param includeNonbondedExceptions if set, then include exceptions; otherwise set charge and epsilon to zero and
sigma to 1
@param tokens array of strings from first line of parameter file for this block of parameters
@param nonbondedForce NonBondedForce reference
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return number of parameters read
--------------------------------------------------------------------------------------- */
static int readNonbondedExceptions( FILE* filePtr, int includeNonbondedExceptions, const StringVector& tokens, NonbondedForce& nonbondedForce, int* lineCount, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readNonbondedExceptions";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no Nonbonded bonds number entry???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
int numberOfExceptions = atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s number of NonbondedExceptions terms=%d\n", methodName.c_str(), numberOfExceptions );
(void) fflush( log );
}
for( int ii = 0; ii < numberOfExceptions; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 5 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
int particle1 = atoi( lineTokens[tokenIndex++].c_str() );
int particle2 = atoi( lineTokens[tokenIndex++].c_str() );
double charge = includeNonbondedExceptions ? atof( lineTokens[tokenIndex++].c_str() ) : 0.0;
double sigma = includeNonbondedExceptions ? atof( lineTokens[tokenIndex++].c_str() ) : 1.0;
double epsilon = includeNonbondedExceptions ? atof( lineTokens[tokenIndex++].c_str() ) : 0.0;
#if 0
if( log && ii < 2 )
(void) fprintf( log, "************************ Setting q to zero ************************\n" );
charge = 0.0;
// sigma = 1.0;
// epsilon = 0.0;
#endif
nonbondedForce.addException( particle1, particle2, charge, sigma, epsilon );
} else if( log ){
char buffer[1024];
(void) sprintf( buffer, "%s readNonbondedExceptions tokens incomplete at line=%d\n", methodName.c_str(), *lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
// diagnostics
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
unsigned int arraySize = static_cast(nonbondedForce.getNumExceptions());
(void) fprintf( log, "%s: sample of NonbondedExceptions parameters\n", methodName.c_str() );
for( unsigned int ii = 0; ii < arraySize; ii++ ){
int particle1, particle2;
double chargeProd, sigma, epsilon;
nonbondedForce.getExceptionParameters( ii, particle1, particle2, chargeProd, sigma, epsilon );
(void) fprintf( log, "%8d %8d %8d %14.7e %14.7e %14.7e\n", ii, particle1, particle2, chargeProd, sigma, epsilon );
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
return nonbondedForce.getNumExceptions();
}
/**---------------------------------------------------------------------------------------
Read NonbondedSoftcoreExceptions parameters
@param filePtr file pointer to parameter file
@param includeNonbondedSoftcoreExceptions
if set, then include exceptions; otherwise set charge and epsilon to zero and
sigma to 1
@param tokens array of strings from first line of parameter file for this block of parameters
@param nonbondedForce NonBondedForce reference
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return number of parameters read
--------------------------------------------------------------------------------------- */
#ifdef INCLUDE_FREE_ENERGY_PLUGIN
static int readNonbondedSoftcoreExceptions( FILE* filePtr, int includeNonbondedSoftcoreExceptions,
const StringVector& tokens, NonbondedSoftcoreForce& nonbondedForce,
int* lineCount, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readNonbondedSoftcoreExceptions";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no Nonbonded softcore exceptions ???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
int numberOfExceptions = atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s number of NonbondedSoftcoreExceptions terms=%d\n", methodName.c_str(), numberOfExceptions );
(void) fflush( log );
}
for( int ii = 0; ii < numberOfExceptions; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 5 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
int particle1 = atoi( lineTokens[tokenIndex++].c_str() );
int particle2 = atoi( lineTokens[tokenIndex++].c_str() );
double charge = includeNonbondedSoftcoreExceptions ? atof( lineTokens[tokenIndex++].c_str() ) : 0.0;
double sigma = includeNonbondedSoftcoreExceptions ? atof( lineTokens[tokenIndex++].c_str() ) : 1.0;
double epsilon = includeNonbondedSoftcoreExceptions ? atof( lineTokens[tokenIndex++].c_str() ) : 0.0;
double softcoreLJLambda = 1.0;
if( includeNonbondedSoftcoreExceptions && lineTokens.size() > tokenIndex ){
softcoreLJLambda = atof( lineTokens[tokenIndex++].c_str() );
}
nonbondedForce.addException( particle1, particle2, charge, sigma, epsilon, softcoreLJLambda );
} else if( log ){
char buffer[1024];
(void) sprintf( buffer, "%s readNonbondedSoftcoreExceptions tokens incomplete at line=%d\n", methodName.c_str(), *lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
// diagnostics
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
unsigned int arraySize = static_cast(nonbondedForce.getNumExceptions());
(void) fprintf( log, "%s: sample of NonbondedSoftcoreExceptions parameters\n", methodName.c_str() );
for( unsigned int ii = 0; ii < arraySize; ii++ ){
int particle1, particle2;
double chargeProd, sigma, epsilon, softcoreLJLambda;
nonbondedForce.getExceptionParameters( ii, particle1, particle2, chargeProd, sigma, epsilon, softcoreLJLambda );
(void) fprintf( log, "%8d %8d %8d %14.7e %14.7e %14.7e %14.7e\n", ii, particle1, particle2, chargeProd, sigma, epsilon, softcoreLJLambda );
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
return nonbondedForce.getNumExceptions();
}
#endif
/**---------------------------------------------------------------------------------------
Set NonbondedForce method
@param nonbondedForce force method is to be set for (optional)
@param nonbondedForceMethod nonbonded force method name
@param log log file pointer -- may be NULL
@return NonbondedForce enum
--------------------------------------------------------------------------------------- */
static int setNonbondedForceMethod( NonbondedForce* nonbondedForce, std::string nonbondedForceMethod, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "setNonbondedForceMethod";
// ---------------------------------------------------------------------------------------
if( log ){
(void) fprintf( log, "%s Nonbonded force is being set %s.\n", methodName.c_str(), nonbondedForceMethod.c_str() );
}
NonbondedForce::NonbondedMethod method = NonbondedForce::NoCutoff;
if( nonbondedForceMethod.compare( "NoCutoff" ) == 0 ){
method = NonbondedForce::NoCutoff;
} else if( nonbondedForceMethod.compare( "CutoffNonPeriodic" ) == 0 ){
method = NonbondedForce::CutoffNonPeriodic;
} else if( nonbondedForceMethod.compare( "CutoffPeriodic" ) == 0 ){
method = NonbondedForce::CutoffPeriodic;
} else if( nonbondedForceMethod.compare( "Ewald" ) == 0 ){
method = NonbondedForce::Ewald;
} else if( nonbondedForceMethod.compare( "PME" ) == 0 ){
method = NonbondedForce::PME;
} else {
char buffer[1024];
(void) sprintf( buffer, "nonbondedForce NonbondedForceMethod <%s> is not recognized.\n", nonbondedForceMethod.c_str() );
if( log ){
(void) fprintf( log, "%s", buffer ); (void) fflush( log );
}
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
if( nonbondedForce ){
if( log ){
(void) fprintf( log, "%s Nonbonded force is being set %s %d.\n", methodName.c_str(), nonbondedForceMethod.c_str(), method );
}
nonbondedForce->setNonbondedMethod( method );
}
return method;
}
/**---------------------------------------------------------------------------------------
Set NonbondedSoftcoreForce method
@param nonbondedSoftcoreForce force method is to be set for (optional)
@param nonbondedSoftcoreForceMethod nonbonded force method name
@param log log file pointer -- may be NULL
@return NonbondedSoftcoreForce enum
--------------------------------------------------------------------------------------- */
#ifdef INCLUDE_FREE_ENERGY_PLUGIN
static int setNonbondedSoftcoreForceMethod( NonbondedSoftcoreForce* nonbondedSoftcoreForce, std::string nonbondedSoftcoreForceMethod, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "setNonbondedSoftcoreForceMethod";
// ---------------------------------------------------------------------------------------
if( log ){
(void) fprintf( log, "%s Nonbonded softcore force is being set %s.\n", methodName.c_str(), nonbondedSoftcoreForceMethod.c_str() );
}
NonbondedSoftcoreForce::NonbondedSoftcoreMethod method = NonbondedSoftcoreForce::NoCutoff;
if( nonbondedSoftcoreForceMethod.compare( "NoCutoff" ) == 0 ){
method = NonbondedSoftcoreForce::NoCutoff;
} else if( nonbondedSoftcoreForceMethod.compare( "CutoffNonPeriodic" ) == 0 ){
method = NonbondedSoftcoreForce::CutoffNonPeriodic;
} else if( nonbondedSoftcoreForceMethod.compare( "CutoffPeriodic" ) == 0 ){
method = NonbondedSoftcoreForce::CutoffPeriodic;
} else if( nonbondedSoftcoreForceMethod.compare( "Ewald" ) == 0 ){
method = NonbondedSoftcoreForce::Ewald;
} else if( nonbondedSoftcoreForceMethod.compare( "PME" ) == 0 ){
method = NonbondedSoftcoreForce::PME;
} else {
char buffer[1024];
(void) sprintf( buffer, "nonbondedSoftcoreForce NonbondedSoftcoreForceMethod <%s> is not recognized.\n", nonbondedSoftcoreForceMethod.c_str() );
if( log ){
(void) fprintf( log, "%s", buffer ); (void) fflush( log );
}
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
if( nonbondedSoftcoreForce ){
if( log ){
(void) fprintf( log, "%s Nonbonded softcore force is being set %s %d.\n", methodName.c_str(), nonbondedSoftcoreForceMethod.c_str(), method );
}
nonbondedSoftcoreForce->setNonbondedMethod( method );
}
return method;
}
#endif
/**---------------------------------------------------------------------------------------
Read NonbondedForce parameters
@param filePtr file pointer to parameter file
@param tokens array of strings from first line of parameter file for this block of parameters
@param system System reference
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return number of parameters read
--------------------------------------------------------------------------------------- */
static int readNonbondedForce( FILE* filePtr, MapStringInt& forceMap, const StringVector& tokens,
System& system, int* lineCount, MapStringString& inputArgumentMap, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readNonbondedForce";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no Nonbonded bonds number entry???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
NonbondedForce* nonbondedForce = new NonbondedForce();
MapStringIntI forceActive = forceMap.find( NB_FORCE );
MapStringIntI forceExceptionsActive = forceMap.find( NB_EXCEPTION_FORCE );
int includeNonbonded = ( forceActive != forceMap.end() && (*forceActive).second ) ? 1 : 0;
int includeNonbondedExceptions = ( forceExceptionsActive != forceMap.end() && (*forceExceptionsActive).second ) ? 1 : 0;
if( includeNonbonded || includeNonbondedExceptions ){
system.addForce( nonbondedForce );
if( log ){
if( includeNonbonded ){
(void) fprintf( log, "nonbonded force is being included.\n" );
} else {
(void) fprintf( log, "nonbonded force is not being included.\n" );
}
if( includeNonbondedExceptions ){
(void) fprintf( log, "nonbonded exceptions are being included.\n" );
} else {
(void) fprintf( log, "nonbonded exceptions are not being included.\n" );
}
}
} else if( log ){
(void) fprintf( log, "nonbonded force is not being included.\n" );
}
int numberOfParticles = atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s number of NonbondedForce terms=%d\n", methodName.c_str(), numberOfParticles );
(void) fflush( log );
}
// get charge, sigma, epsilon for each particle
for( int ii = 0; ii < numberOfParticles; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 3 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
double charge = includeNonbonded ? atof( lineTokens[tokenIndex++].c_str() ) : 0.0;
double sigma = includeNonbonded ? atof( lineTokens[tokenIndex++].c_str() ) : 1.0;
double epsilon = includeNonbonded ? atof( lineTokens[tokenIndex++].c_str() ) : 0.0;
nonbondedForce->addParticle( charge, sigma, epsilon );
} else {
char buffer[1024];
(void) sprintf( buffer, "%s NonbondedForce tokens incomplete at line=%d\n", methodName.c_str(), *lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
// get cutoff distance, exceptions, periodic box, method,
char* isNotEof = "1";
int hits = 0;
while( hits < 5 ){
StringVector tokens;
isNotEof = readLine( filePtr, tokens, lineCount, log );
if( isNotEof && tokens.size() > 0 ){
std::string field = tokens[0];
if( field.compare( "#" ) == 0 ){
// skip
if( log ){
(void) fprintf( log, "skip <%s>\n", field.c_str());
}
} else if( field.compare( "CutoffDistance" ) == 0 ){
nonbondedForce->setCutoffDistance( atof( tokens[1].c_str() ) );
hits++;
} else if( field.compare( "RFDielectric" ) == 0 ){
nonbondedForce->setReactionFieldDielectric( atof( tokens[1].c_str() ) );
hits++;
} else if( field.compare( "EwaldRTolerance" ) == 0 ){
nonbondedForce->setEwaldErrorTolerance( atof( tokens[1].c_str() ) );
hits++;
} else if( field.compare( "NonbondedForceExceptions" ) == 0 ){
readNonbondedExceptions( filePtr, includeNonbondedExceptions, tokens, *nonbondedForce, lineCount, log );
hits++;
} else if( field.compare( "NonbondedForceMethod" ) == 0 ){
setNonbondedForceMethod( nonbondedForce, tokens[1], log );
hits++;
}
}
}
// overrides
double cutoffDistance = nonbondedForce->getCutoffDistance( );
if( setDoubleFromMap( inputArgumentMap, "nonbondedCutoffDistance", cutoffDistance ) ){
nonbondedForce->setCutoffDistance( cutoffDistance );
}
double ewaldTolerance = nonbondedForce->getEwaldErrorTolerance( );
if( setDoubleFromMap( inputArgumentMap, "nonbondedEwaldTolerance", ewaldTolerance ) ){
nonbondedForce->setEwaldErrorTolerance( ewaldTolerance );
}
double rFDielectric = nonbondedForce->getReactionFieldDielectric( );
if( setDoubleFromMap( inputArgumentMap, "nonbondedRFDielectric", rFDielectric ) ){
nonbondedForce->setReactionFieldDielectric( rFDielectric );
}
std::string nonbondedMethod;
if( setStringFromMap( inputArgumentMap, "nonbondedForceMethod", nonbondedMethod) ){
setNonbondedForceMethod( nonbondedForce, nonbondedMethod, log );
}
// diagnostics
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
unsigned int arraySize = static_cast(nonbondedForce->getNumParticles());
(void) fprintf( log, "%s: nonbonded parameters\n", methodName.c_str() );
// cutoff distance and box
(void) fprintf( log, "CutoffDistance %14.7e\n", nonbondedForce->getCutoffDistance() );
// nonbond method
std::string nonbondedForceMethod;
switch( nonbondedForce->getNonbondedMethod() ){
case NonbondedForce::NoCutoff:
nonbondedForceMethod = "NoCutoff";
break;
case NonbondedForce::CutoffNonPeriodic:
nonbondedForceMethod = "CutoffNonPeriodic";
break;
case NonbondedForce::CutoffPeriodic:
nonbondedForceMethod = "CutoffPeriodic";
break;
case NonbondedForce::Ewald:
nonbondedForceMethod = "Ewald";
break;
case NonbondedForce::PME:
nonbondedForceMethod = "PME";
break;
default:
nonbondedForceMethod = "Unknown";
}
(void) fprintf( log, "NonbondedForceMethod=%s\n", nonbondedForceMethod.c_str() );
(void) fprintf( log, "charge, sigma, epsilon\n" );
for( unsigned int ii = 0; ii < arraySize; ii++ ){
double charge, sigma, epsilon;
nonbondedForce->getParticleParameters( ii, charge, sigma, epsilon );
(void) fprintf( log, "%8d %14.7e %14.7e %14.7e\n", ii, charge, sigma, epsilon );
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
return nonbondedForce->getNumParticles();
}
/**---------------------------------------------------------------------------------------
Read NonbondedSoftcoreForce parameters
@param filePtr file pointer to parameter file
@param tokens array of strings from first line of parameter file for this block of parameters
@param system System reference
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return number of parameters read
--------------------------------------------------------------------------------------- */
#ifdef INCLUDE_FREE_ENERGY_PLUGIN
static int readNonbondedSoftcoreForce( FILE* filePtr, MapStringInt& forceMap, const StringVector& tokens,
System& system, int* lineCount, MapStringString& inputArgumentMap, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readNonbondedSoftcoreForce";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no Nonbonded softcore entries???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
NonbondedSoftcoreForce* nonbondedSoftcore = new NonbondedSoftcoreForce();
MapStringIntI forceActive = forceMap.find( NB_SOFTCORE_FORCE );
MapStringIntI forceExceptionsActive = forceMap.find( NB_EXCEPTION_SOFTCORE_FORCE );
int includeNonbonded = ( forceActive != forceMap.end() && (*forceActive).second ) ? 1 : 0;
int includeNonbondedExceptions = ( forceExceptionsActive != forceMap.end() && (*forceExceptionsActive).second ) ? 1 : 0;
if( includeNonbonded || includeNonbondedExceptions ){
system.addForce( nonbondedSoftcore );
if( log ){
if( includeNonbonded ){
(void) fprintf( log, "nonbonded softcore force is being included.\n" );
} else {
(void) fprintf( log, "nonbonded softcore force is not being included.\n" );
}
if( includeNonbondedExceptions ){
(void) fprintf( log, "nonbonded softcore exceptions are being included.\n" );
} else {
(void) fprintf( log, "nonbonded softcore exceptions are not being included.\n" );
}
}
} else if( log ){
(void) fprintf( log, "nonbonded softcore force is not being included.\n" );
}
int numberOfParticles = atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s number of NonbondedSoftcoreForce terms=%d\n", methodName.c_str(), numberOfParticles );
(void) fflush( log );
}
// get charge, sigma, epsilon for each particle
for( int ii = 0; ii < numberOfParticles; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 3 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
double charge = includeNonbonded ? atof( lineTokens[tokenIndex++].c_str() ) : 0.0;
double sigma = includeNonbonded ? atof( lineTokens[tokenIndex++].c_str() ) : 1.0;
double epsilon = includeNonbonded ? atof( lineTokens[tokenIndex++].c_str() ) : 0.0;
double softcoreLJLambda = 1.0;
if( includeNonbonded && lineTokens.size() > tokenIndex ){
softcoreLJLambda = atof( lineTokens[tokenIndex++].c_str() );
}
nonbondedSoftcore->addParticle( charge, sigma, epsilon, softcoreLJLambda );
} else {
char buffer[1024];
(void) sprintf( buffer, "%s NonbondedForce tokens incomplete at line=%d\n", methodName.c_str(), *lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
// get cutoff distance, exceptions, periodic box, method,
char* isNotEof = "1";
int hits = 0;
while( hits < 5 ){
StringVector tokens;
isNotEof = readLine( filePtr, tokens, lineCount, log );
if( isNotEof && tokens.size() > 0 ){
std::string field = tokens[0];
if( field.compare( "#" ) == 0 ){
// skip
if( log ){
(void) fprintf( log, "skip <%s>\n", field.c_str());
}
} else if( field.compare( "CutoffDistance" ) == 0 ){
nonbondedSoftcore->setCutoffDistance( atof( tokens[1].c_str() ) );
hits++;
} else if( field.compare( "RFDielectric" ) == 0 ){
nonbondedSoftcore->setReactionFieldDielectric( atof( tokens[1].c_str() ) );
hits++;
} else if( field.compare( "EwaldRTolerance" ) == 0 ){
nonbondedSoftcore->setEwaldErrorTolerance( atof( tokens[1].c_str() ) );
hits++;
} else if( field.compare( "NonbondedSoftcoreForceExceptions" ) == 0 ){
readNonbondedSoftcoreExceptions( filePtr, includeNonbondedExceptions, tokens, *nonbondedSoftcore, lineCount, log );
hits++;
} else if( field.compare( "NonbondedSoftcoreForceMethod" ) == 0 ){
setNonbondedSoftcoreForceMethod( nonbondedSoftcore, tokens[1], log );
hits++;
}
}
}
// overrides
double cutoffDistance = nonbondedSoftcore->getCutoffDistance( );
if( setDoubleFromMap( inputArgumentMap, "nonbondedCutoffDistance", cutoffDistance ) ){
nonbondedSoftcore->setCutoffDistance( cutoffDistance );
}
double ewaldTolerance = nonbondedSoftcore->getEwaldErrorTolerance( );
if( setDoubleFromMap( inputArgumentMap, "nonbondedEwaldTolerance", ewaldTolerance ) ){
nonbondedSoftcore->setEwaldErrorTolerance( ewaldTolerance );
}
double rFDielectric = nonbondedSoftcore->getReactionFieldDielectric( );
if( setDoubleFromMap( inputArgumentMap, "nonbondedRFDielectric", rFDielectric ) ){
nonbondedSoftcore->setReactionFieldDielectric( rFDielectric );
}
std::string nonbondedMethod;
if( setStringFromMap( inputArgumentMap, "nonbondedSoftcoreMethod", nonbondedMethod) ){
setNonbondedSoftcoreForceMethod( nonbondedSoftcore, nonbondedMethod, log );
}
// diagnostics
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
unsigned int arraySize = static_cast(nonbondedSoftcore->getNumParticles());
(void) fprintf( log, "%s: nonbonded parameters\n", methodName.c_str() );
// cutoff distance and box
(void) fprintf( log, "CutoffDistance %14.7e\n", nonbondedSoftcore->getCutoffDistance() );
// nonbond method
std::string nonbondedSoftcoreMethod;
switch( nonbondedSoftcore->getNonbondedMethod() ){
case NonbondedForce::NoCutoff:
nonbondedSoftcoreMethod = "NoCutoff";
break;
case NonbondedForce::CutoffNonPeriodic:
nonbondedSoftcoreMethod = "CutoffNonPeriodic";
break;
case NonbondedForce::CutoffPeriodic:
nonbondedSoftcoreMethod = "CutoffPeriodic";
break;
case NonbondedForce::Ewald:
nonbondedSoftcoreMethod = "Ewald";
break;
case NonbondedForce::PME:
nonbondedSoftcoreMethod = "PME";
break;
default:
nonbondedSoftcoreMethod = "Unknown";
}
(void) fprintf( log, "NonbondedForceMethod=%s\n", nonbondedSoftcoreMethod.c_str() );
(void) fprintf( log, "charge, sigma, epsilon\n" );
for( unsigned int ii = 0; ii < arraySize; ii++ ){
double charge, sigma, epsilon, softcoreLJLambda;
nonbondedSoftcore->getParticleParameters( ii, charge, sigma, epsilon, softcoreLJLambda );
(void) fprintf( log, "%8d %14.7e %14.7e %14.7e %14.7e\n", ii, charge, sigma, epsilon, softcoreLJLambda );
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
return nonbondedSoftcore->getNumParticles();
}
#endif
/**---------------------------------------------------------------------------------------
Read GBSAOBCForce parameters
@param filePtr file pointer to parameter file
@param forceFlag flag signalling whether force is to be added to system
if force == 0 || forceFlag & GBSA_OBC_FORCE, then included
@param tokens array of strings from first line of parameter file for this block of parameters
@param system System reference
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return number of parameters read
--------------------------------------------------------------------------------------- */
static int readGBSAOBCForce( FILE* filePtr, MapStringInt& forceMap, const StringVector& tokens, System& system, int* lineCount, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readGBSAOBCForce";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no GBSAOBC terms entry???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
GBSAOBCForce* gbsaObcForce = new GBSAOBCForce();
MapStringIntI forceActive = forceMap.find( GBSA_OBC_FORCE );
if( forceActive != forceMap.end() && (*forceActive).second ){
system.addForce( gbsaObcForce );
if( log ){
(void) fprintf( log, "GBSA OBC force is being included.\n" );
}
} else if( log ){
(void) fprintf( log, "GBSA OBC force is not being included.\n" );
}
int numberOfParticles = atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s number of GBSAOBCForce terms=%d\n", methodName.c_str(), numberOfParticles );
(void) fflush( log );
}
for( int ii = 0; ii < numberOfParticles; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 3 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
double charge = atof( lineTokens[tokenIndex++].c_str() );
double radius = atof( lineTokens[tokenIndex++].c_str() );
double scalingFactor = atof( lineTokens[tokenIndex++].c_str() );
gbsaObcForce->addParticle( charge, radius, scalingFactor );
} else {
char buffer[1024];
(void) sprintf( buffer, "%s GBSAOBCForce tokens incomplete at line=%d\n", methodName.c_str(), *lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
char* isNotEof = "1";
int hits = 0;
while( hits < 2 ){
StringVector tokens;
isNotEof = readLine( filePtr, tokens, lineCount, log );
if( isNotEof && tokens.size() > 0 ){
std::string field = tokens[0];
if( field.compare( "SoluteDielectric" ) == 0 ){
gbsaObcForce->setSoluteDielectric( atof( tokens[1].c_str() ) );
hits++;
} else if( field.compare( "SolventDielectric" ) == 0 ){
gbsaObcForce->setSolventDielectric( atof( tokens[1].c_str() ) );
hits++;
} else {
char buffer[1024];
(void) sprintf( buffer, "%s read past GBSA Obc block at line=%d\n", methodName.c_str(), lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
} else {
char buffer[1024];
(void) sprintf( buffer, "%s invalid token count at line=%d?\n", methodName.c_str(), lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
unsigned int arraySize = static_cast(gbsaObcForce->getNumParticles());
(void) fprintf( log, "%s: sample of GBSA OBC Force parameters; no. of particles=%d\n",
methodName.c_str(), gbsaObcForce->getNumParticles() );
(void) fprintf( log, "solute/solvent dielectrics: [%10.4f %10.4f]\n",
gbsaObcForce->getSoluteDielectric(), gbsaObcForce->getSolventDielectric() );
for( unsigned int ii = 0; ii < arraySize; ii++ ){
double charge, radius, scalingFactor;
gbsaObcForce->getParticleParameters( ii, charge, radius, scalingFactor );
(void) fprintf( log, "%8d %14.7e %14.7e %14.7e\n", ii, charge, radius, scalingFactor );
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
return gbsaObcForce->getNumParticles();
}
/**---------------------------------------------------------------------------------------
Read GBSAOBCSoftcoreForce parameters
@param filePtr file pointer to parameter file
@param forceFlag flag signalling whether force is to be added to system
if force == 0 || forceFlag & GBSA_OBCSoftcore_FORCE, then included
@param tokens array of strings from first line of parameter file for this block of parameters
@param system System reference
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return number of parameters read
--------------------------------------------------------------------------------------- */
#ifdef INCLUDE_FREE_ENERGY_PLUGIN
static int readGBSAOBCSoftcoreForce( FILE* filePtr, MapStringInt& forceMap, const StringVector& tokens, System& system, int* lineCount, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readGBSAOBCSoftcoreForce";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no GBSAOBCSoftcore terms entry???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
GBSAOBCSoftcoreForce* gbsaObcSoftcoreForce = new GBSAOBCSoftcoreForce();
MapStringIntI forceActive = forceMap.find( GBSA_OBC_SOFTCORE_FORCE );
if( forceActive != forceMap.end() && (*forceActive).second ){
system.addForce( gbsaObcSoftcoreForce );
if( log ){
(void) fprintf( log, "GBSA OBCSoftcore force is being included.\n" );
}
} else if( log ){
(void) fprintf( log, "GBSA OBCSoftcore force is not being included.\n" );
}
int numberOfParticles = atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s number of GBSAOBCSoftcoreForce terms=%d\n", methodName.c_str(), numberOfParticles );
(void) fflush( log );
}
for( int ii = 0; ii < numberOfParticles; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 3 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
double charge = atof( lineTokens[tokenIndex++].c_str() );
double radius = atof( lineTokens[tokenIndex++].c_str() );
double scalingFactor = atof( lineTokens[tokenIndex++].c_str() );
double saScale = atof( lineTokens[tokenIndex++].c_str() );
gbsaObcSoftcoreForce->addParticle( charge, radius, scalingFactor, saScale );
} else {
char buffer[1024];
(void) sprintf( buffer, "%s GBSAOBCSoftcoreForce tokens incomplete at line=%d\n", methodName.c_str(), *lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
char* isNotEof = "1";
int hits = 0;
while( hits < 2 ){
StringVector tokens;
isNotEof = readLine( filePtr, tokens, lineCount, log );
if( isNotEof && tokens.size() > 0 ){
std::string field = tokens[0];
if( field.compare( "SoluteDielectric" ) == 0 ){
gbsaObcSoftcoreForce->setSoluteDielectric( atof( tokens[1].c_str() ) );
hits++;
} else if( field.compare( "SolventDielectric" ) == 0 ){
gbsaObcSoftcoreForce->setSolventDielectric( atof( tokens[1].c_str() ) );
hits++;
} else {
char buffer[1024];
(void) sprintf( buffer, "%s read past GBSA Obc softcore block at line=%d\n", methodName.c_str(), lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
} else {
char buffer[1024];
(void) sprintf( buffer, "%s invalid token count at line=%d?\n", methodName.c_str(), lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
unsigned int arraySize = static_cast(gbsaObcSoftcoreForce->getNumParticles());
(void) fprintf( log, "%s: sample of GBSA OBCSoftcore Force parameters; no. of particles=%d\n",
methodName.c_str(), gbsaObcSoftcoreForce->getNumParticles() );
(void) fprintf( log, "solute/solvent dielectrics: [%10.4f %10.4f]\n",
gbsaObcSoftcoreForce->getSoluteDielectric(), gbsaObcSoftcoreForce->getSolventDielectric() );
for( unsigned int ii = 0; ii < arraySize; ii++ ){
double charge, radius, scalingFactor, nonpolarScaleFactor;
gbsaObcSoftcoreForce->getParticleParameters( ii, charge, radius, scalingFactor, nonpolarScaleFactor );
(void) fprintf( log, "%8d %14.7e %14.7e %14.7e %14.7e\n", ii, charge, radius, scalingFactor, nonpolarScaleFactor );
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
return gbsaObcSoftcoreForce->getNumParticles();
}
#endif
/**---------------------------------------------------------------------------------------
Read GBVIForce parameters
@param filePtr file pointer to parameter file
@param forceFlag flag signalling whether force is to be added to system
if force == 0 || forceFlag & GBVI_FORCE, then included
@param tokens array of strings from first line of parameter file for this block of parameters
@param system System reference
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return number of parameters read
--------------------------------------------------------------------------------------- */
static int readGBVIForceMod( FILE* filePtr, MapStringInt& forceMap, const StringVector& tokens, System& system, int* lineCount, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readGBVIForce";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no GBVI terms entry???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
// GBVIForce* gbviForce = new GBVIForce();
MapStringIntI forceActive = forceMap.find( GBVI_FORCE );
if( forceActive != forceMap.end() && (*forceActive).second ){
forceMap[GBVI_SOFTCORE_FORCE] = 0;
// system.addForce( gbviForce );
if( log ){
(void) fprintf( log, "GBVI force is being included & GBVI softcore force excluded.\n" );
}
} else if( log ){
(void) fprintf( log, "GBVI force is not being included.\n" );
}
int numberOfParticles = atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s number of GBVIForce terms=%d\n", methodName.c_str(), numberOfParticles );
(void) fflush( log );
}
for( int ii = 0; ii < numberOfParticles; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 3 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
double charge = atof( lineTokens[tokenIndex++].c_str() );
double radius = atof( lineTokens[tokenIndex++].c_str() );
double gamma = atof( lineTokens[tokenIndex++].c_str() );
// gbviForce->addParticle( charge, radius, gamma );
} else {
char buffer[1024];
(void) sprintf( buffer, "%s GBVIForce tokens incomplete at line=%d\n", methodName.c_str(), *lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
char* isNotEof = "1";
int hits = 0;
while( hits < 3 ){
StringVector tokens;
isNotEof = readLine( filePtr, tokens, lineCount, log );
if( isNotEof && tokens.size() > 0 ){
std::string field = tokens[0];
if( field.compare( "SoluteDielectric" ) == 0 ){
// gbviForce->setSoluteDielectric( atof( tokens[1].c_str() ) );
hits++;
} else if( field.compare( "SolventDielectric" ) == 0 ){
// gbviForce->setSolventDielectric( atof( tokens[1].c_str() ) );
hits++;
} else if( field.compare( "GBVIBonds" ) == 0 ){
int numberOfBonds = atoi( tokens[1].c_str() );
for( int ii = 0; ii < numberOfBonds; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 3 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
int atomI = atoi( lineTokens[tokenIndex++].c_str() );
int atomJ = atoi( lineTokens[tokenIndex++].c_str() );
double bondLength = atof( lineTokens[tokenIndex++].c_str() );
// gbviForce->addBond( atomI, atomJ, bondLength );
}
}
hits++;
} else {
char buffer[1024];
(void) sprintf( buffer, "%s read past GBSA Obc block at line=%d\n", methodName.c_str(), lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
} else {
char buffer[1024];
(void) sprintf( buffer, "%s invalid token count at line=%d?\n", methodName.c_str(), lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
#if 0
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
unsigned int arraySize = static_cast(gbviForce->getNumParticles());
(void) fprintf( log, "%s: sample of GBVI Force parameters; no. of particles=%d\n",
methodName.c_str(), gbviForce->getNumParticles() );
(void) fprintf( log, "solute/solvent dielectrics: [%10.4f %10.4f]\n",
gbviForce->getSoluteDielectric(), gbviForce->getSolventDielectric() );
for( unsigned int ii = 0; ii < arraySize; ii++ ){
double charge, radius, gamma;
gbviForce->getParticleParameters( ii, charge, radius, gamma );
(void) fprintf( log, "%8d %14.7e %14.7e %14.7e\n", ii, charge, radius, gamma);
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
arraySize = static_cast(gbviForce->getNumBonds());
(void) fprintf( log, "%s: sample of GBVI: no. of bonds=%d\n",
methodName.c_str(), gbviForce->getNumBonds() );
for( unsigned int ii = 0; ii < arraySize; ii++ ){
int atomI, atomJ;
double bondLength;
gbviForce->getBondParameters( ii, atomI, atomJ, bondLength );
(void) fprintf( log, "%8d %8d %8d %14.7e\n", ii, atomI, atomJ, bondLength );
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
return gbviForce->getNumParticles();
#endif
return numberOfParticles;
}
/**---------------------------------------------------------------------------------------
Read GBVIForce parameters
@param filePtr file pointer to parameter file
@param forceFlag flag signalling whether force is to be added to system
if force == 0 || forceFlag & GBVI_FORCE, then included
@param tokens array of strings from first line of parameter file for this block of parameters
@param system System reference
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return number of parameters read
--------------------------------------------------------------------------------------- */
static int readGBVIForce( FILE* filePtr, MapStringInt& forceMap, const StringVector& tokens, System& system, int* lineCount, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readGBVIForce";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no GBVI terms entry???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
GBVIForce* gbviForce = new GBVIForce();
MapStringIntI forceActive = forceMap.find( GBVI_FORCE );
if( forceActive != forceMap.end() && (*forceActive).second ){
forceMap[GBVI_SOFTCORE_FORCE] = 0;
system.addForce( gbviForce );
if( log ){
(void) fprintf( log, "GBVI force is being included & GBVI softcore force excluded.\n" );
}
} else if( log ){
(void) fprintf( log, "GBVI force is not being included.\n" );
}
int numberOfParticles = atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s number of GBVIForce terms=%d\n", methodName.c_str(), numberOfParticles );
(void) fflush( log );
}
for( int ii = 0; ii < numberOfParticles; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 3 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
double charge = atof( lineTokens[tokenIndex++].c_str() );
double radius = atof( lineTokens[tokenIndex++].c_str() );
double gamma = atof( lineTokens[tokenIndex++].c_str() );
gbviForce->addParticle( charge, radius, gamma );
} else {
char buffer[1024];
(void) sprintf( buffer, "%s GBVIForce tokens incomplete at line=%d\n", methodName.c_str(), *lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
char* isNotEof = "1";
int hits = 0;
while( hits < 3 ){
StringVector tokens;
isNotEof = readLine( filePtr, tokens, lineCount, log );
if( isNotEof && tokens.size() > 0 ){
std::string field = tokens[0];
if( field.compare( "SoluteDielectric" ) == 0 ){
gbviForce->setSoluteDielectric( atof( tokens[1].c_str() ) );
hits++;
} else if( field.compare( "SolventDielectric" ) == 0 ){
gbviForce->setSolventDielectric( atof( tokens[1].c_str() ) );
hits++;
} else if( field.compare( "GBVIBonds" ) == 0 ){
int numberOfBonds = atoi( tokens[1].c_str() );
for( int ii = 0; ii < numberOfBonds; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 3 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
int atomI = atoi( lineTokens[tokenIndex++].c_str() );
int atomJ = atoi( lineTokens[tokenIndex++].c_str() );
double bondLength = atof( lineTokens[tokenIndex++].c_str() );
gbviForce->addBond( atomI, atomJ, bondLength );
}
}
hits++;
} else {
char buffer[1024];
(void) sprintf( buffer, "%s read past GBSA Obc block at line=%d\n", methodName.c_str(), lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
} else {
char buffer[1024];
(void) sprintf( buffer, "%s invalid token count at line=%d?\n", methodName.c_str(), lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
unsigned int arraySize = static_cast(gbviForce->getNumParticles());
(void) fprintf( log, "%s: sample of GBVI Force parameters; no. of particles=%d\n",
methodName.c_str(), gbviForce->getNumParticles() );
(void) fprintf( log, "solute/solvent dielectrics: [%10.4f %10.4f]\n",
gbviForce->getSoluteDielectric(), gbviForce->getSolventDielectric() );
for( unsigned int ii = 0; ii < arraySize; ii++ ){
double charge, radius, gamma;
gbviForce->getParticleParameters( ii, charge, radius, gamma );
(void) fprintf( log, "%8d %14.7e %14.7e %14.7e\n", ii, charge, radius, gamma);
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
arraySize = static_cast(gbviForce->getNumBonds());
(void) fprintf( log, "%s: sample of GBVI: no. of bonds=%d\n",
methodName.c_str(), gbviForce->getNumBonds() );
for( unsigned int ii = 0; ii < arraySize; ii++ ){
int atomI, atomJ;
double bondLength;
gbviForce->getBondParameters( ii, atomI, atomJ, bondLength );
(void) fprintf( log, "%8d %8d %8d %14.7e\n", ii, atomI, atomJ, bondLength );
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
return gbviForce->getNumParticles();
}
/**---------------------------------------------------------------------------------------
Read GBVISoftcoreForce parameters
@param filePtr file pointer to parameter file
@param forceFlag flag signalling whether force is to be added to system
if force == 0 || forceFlag & GBVISoftcore_FORCE, then included
@param tokens array of strings from first line of parameter file for this block of parameters
@param system System reference
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return number of parameters read
--------------------------------------------------------------------------------------- */
#ifdef INCLUDE_FREE_ENERGY_PLUGIN
static int readGBVISoftcoreForce( FILE* filePtr, MapStringInt& forceMap, const StringVector& tokens, System& system, int* lineCount, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readGBVISoftcoreForce";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no GBVISoftcore terms entry???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
GBVISoftcoreForce* gbviForce = new GBVISoftcoreForce();
MapStringIntI forceActive = forceMap.find( GBVI_SOFTCORE_FORCE );
if( forceActive != forceMap.end() && (*forceActive).second ){
system.addForce( gbviForce );
forceMap[GBVI_FORCE] = 0;
if( log ){
(void) fprintf( log, "GBVISoftcore force is being included and GBVI excluded.\n" );
}
} else if( log ){
(void) fprintf( log, "GBVISoftcore force is not being included.\n" );
}
int numberOfParticles = atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s number of GBVISoftcoreForce terms=%d\n", methodName.c_str(), numberOfParticles );
(void) fflush( log );
}
for( int ii = 0; ii < numberOfParticles; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 3 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
double charge = atof( lineTokens[tokenIndex++].c_str() );
double radius = atof( lineTokens[tokenIndex++].c_str() );
double gamma = atof( lineTokens[tokenIndex++].c_str() );
double bornRadiusScaleFactor = 1.0;
if( lineTokens.size() > tokenIndex ){
bornRadiusScaleFactor = atof( lineTokens[tokenIndex++].c_str() );
}
gbviForce->addParticle( charge, radius, gamma, bornRadiusScaleFactor );
} else {
char buffer[1024];
(void) sprintf( buffer, "%s GBVISoftcoreForce tokens incomplete at line=%d\n", methodName.c_str(), *lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
char* isNotEof = "1";
int hits = 0;
while( hits < 6 ){
StringVector tokens;
isNotEof = readLine( filePtr, tokens, lineCount, log );
if( isNotEof && tokens.size() > 0 ){
std::string field = tokens[0];
if( field.compare( "SoluteDielectric" ) == 0 ){
gbviForce->setSoluteDielectric( atof( tokens[1].c_str() ) );
hits++;
} else if( field.compare( "SolventDielectric" ) == 0 ){
gbviForce->setSolventDielectric( atof( tokens[1].c_str() ) );
hits++;
} else if( field.compare( "BornRadiusScalingMethod" ) == 0 ){
int method = atoi( tokens[1].c_str() );
//method = 0;
//(void) fprintf( log, "%s: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! BornRadiusScalingMethod forced to NoScale!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", methodName.c_str() );
if( method == 0 ){
gbviForce->setBornRadiusScalingMethod( GBVISoftcoreForce::NoScaling );
} else if( method == 1 ){
gbviForce->setBornRadiusScalingMethod( GBVISoftcoreForce::Tanh );
} else if( method == 2 ){
gbviForce->setBornRadiusScalingMethod( GBVISoftcoreForce::QuinticSpline );
} else {
// not recognized force error
(void) fprintf( log, "%s: BornRadiusScalingMethod id=%s not recognized.\n", methodName.c_str(), tokens[1].c_str() );
(void) fprintf( stderr, "%s: BornRadiusScalingMethod id=%s not recognized.\n", methodName.c_str(), tokens[1].c_str() );
(void) fflush( NULL );
exit(0);
}
hits++;
} else if( field.compare( "QuinticLowerLimitFactor" ) == 0 ){
gbviForce->setQuinticLowerLimitFactor( atof( tokens[1].c_str() ) );
hits++;
} else if( field.compare( "QuinticUpperBornRadiusLimit" ) == 0 ){
gbviForce->setQuinticUpperBornRadiusLimit( atof( tokens[1].c_str() ) );
hits++;
} else if( field.compare( "GBVISoftcoreBonds" ) == 0 ){
int numberOfBonds = atoi( tokens[1].c_str() );
for( int ii = 0; ii < numberOfBonds; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 3 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
int atomI = atoi( lineTokens[tokenIndex++].c_str() );
int atomJ = atoi( lineTokens[tokenIndex++].c_str() );
double bondLength = atof( lineTokens[tokenIndex++].c_str() );
gbviForce->addBond( atomI, atomJ, bondLength );
}
}
hits++;
} else {
char buffer[1024];
(void) sprintf( buffer, "%s read past GBSA Obc block at line=%d\n", methodName.c_str(), lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
} else {
char buffer[1024];
(void) sprintf( buffer, "%s invalid token count at line=%d?\n", methodName.c_str(), lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
unsigned int arraySize = static_cast(gbviForce->getNumParticles());
(void) fprintf( log, "%s: sample of GBVISoftcore Force parameters; no. of particles=%d\n",
methodName.c_str(), gbviForce->getNumParticles() );
(void) fprintf( log, "solute/solvent dielectrics: [%10.4f %10.4f]\n",
gbviForce->getSoluteDielectric(), gbviForce->getSolventDielectric() );
(void) fprintf( log, "Born radius scaling method=%d: param[%10.4f %10.4f] [0=none, 1=tanh (not implemented), 2=quintic]\n",
gbviForce->getBornRadiusScalingMethod(),
gbviForce->getQuinticLowerLimitFactor(), gbviForce->getQuinticUpperBornRadiusLimit() );
for( unsigned int ii = 0; ii < arraySize; ii++ ){
double charge, radius, gamma, bornRadiusScaleFactor;
gbviForce->getParticleParameters( ii, charge, radius, gamma, bornRadiusScaleFactor );
(void) fprintf( log, "%8d %14.7e %14.7e %14.7e %14.7e\n", ii, charge, radius, gamma, bornRadiusScaleFactor);
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
arraySize = static_cast(gbviForce->getNumBonds());
(void) fprintf( log, "%s: sample of GBVISoftcore: no. of bonds=%d\n",
methodName.c_str(), gbviForce->getNumBonds() );
for( unsigned int ii = 0; ii < arraySize; ii++ ){
int atomI, atomJ;
double bondLength;
gbviForce->getBondParameters( ii, atomI, atomJ, bondLength );
(void) fprintf( log, "%8d %8d %8d %14.7e\n", ii, atomI, atomJ, bondLength );
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
return gbviForce->getNumParticles();
}
#endif
/**---------------------------------------------------------------------------------------
Read Constraints
@param filePtr file pointer to parameter file
@param tokens array of strings from first line of parameter file for this block of parameters
@param system System reference
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return number of parameters read
--------------------------------------------------------------------------------------- */
static int readConstraints( FILE* filePtr, const StringVector& tokens, System& system, int* lineCount, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readConstraints";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no Constraints terms entry???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
int numberOfConstraints = atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s number of constraints=%d\n", methodName.c_str(), numberOfConstraints );
(void) fflush( log );
}
for( int ii = 0; ii < numberOfConstraints; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 3 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
int particle1 = atoi( lineTokens[tokenIndex++].c_str() );
int particle2 = atoi( lineTokens[tokenIndex++].c_str() );
double distance = atof( lineTokens[tokenIndex++].c_str() );
system.addConstraint( particle1, particle2, distance );
} else {
char buffer[1024];
(void) sprintf( buffer, "%s constraint tokens incomplete at line=%d\n", methodName.c_str(), *lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
unsigned int arraySize = static_cast(system.getNumConstraints());
(void) fprintf( log, "%s: sample constraints\n", methodName.c_str() );
for( unsigned int ii = 0; ii < arraySize && ii < maxPrint; ii++ ){
int particle1, particle2;
double distance;
system.getConstraintParameters( ii, particle1, particle2, distance );
(void) fprintf( log, "%8d %8d %8d %14.7e\n", ii, particle1, particle2, distance );
if( ii == maxPrint ){
ii = arraySize - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
return system.getNumConstraints();
}
/**---------------------------------------------------------------------------------------
Read integrator
@param filePtr file pointer to parameter file
@param tokens array of strings from first line of parameter file for this block of parameters
@param system System reference
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return integrator
--------------------------------------------------------------------------------------- */
static Integrator* readIntegrator( FILE* filePtr, const StringVector& tokens, System& system, int* lineCount, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readIntegrator";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s integrator name missing?\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
std::string integratorName = tokens[1];
if( log ){
(void) fprintf( log, "%s integrator=%s\n", methodName.c_str(), integratorName.c_str() );
(void) fflush( log );
}
// set number of parameters (lines to read)
int readLines;
if( integratorName.compare( "LangevinIntegrator" ) == 0 ){
readLines = 5;
} else if( integratorName.compare( "VariableLangevinIntegrator" ) == 0 ){
readLines = 6;
} else if( integratorName.compare( "VerletIntegrator" ) == 0 ){
readLines = 2;
} else if( integratorName.compare( "VariableVerletIntegrator" ) == 0 ){
readLines = 3;
} else if( integratorName.compare( "BrownianIntegrator" ) == 0 ){
readLines = 5;
} else {
(void) fprintf( log, "%s integrator=%s not recognized.\n", methodName.c_str(), integratorName.c_str() );
(void) fflush( log );
exit(-1);
}
// read in parameters
double stepSize = 0.001;
double constraintTolerance = 1.0e-05;
double temperature = 300.0;
double friction = 0.01099;
double errorTolerance = 1.0e-05;
int randomNumberSeed = 1993;
for( int ii = 0; ii < readLines; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
if( lineTokens.size() > 1 ){
if( lineTokens[0].compare( "StepSize" ) == 0 ){
stepSize = atof( lineTokens[1].c_str() );
} else if( lineTokens[0].compare( "ConstraintTolerance" ) == 0 ){
constraintTolerance = atof( lineTokens[1].c_str() );
} else if( lineTokens[0].compare( "Temperature" ) == 0 ){
temperature = atof( lineTokens[1].c_str() );
} else if( lineTokens[0].compare( "Friction" ) == 0 ){
friction = atof( lineTokens[1].c_str() );
} else if( lineTokens[0].compare( "ErrorTolerance" ) == 0 ){
errorTolerance = atof( lineTokens[1].c_str() );
} else if( lineTokens[0].compare( "RandomNumberSeed" ) == 0 ){
randomNumberSeed = atoi( lineTokens[1].c_str() );
} else {
(void) fprintf( log, "%s integrator field=%s not recognized.\n", methodName.c_str(), lineTokens[0].c_str() );
(void) fflush( log );
exit(-1);
}
} else {
char buffer[1024];
(void) sprintf( buffer, "%s integrator parameters incomplete at line=%d\n", methodName.c_str(), *lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
// build integrator
Integrator* returnIntegrator = NULL;
if( integratorName.compare( "LangevinIntegrator" ) == 0 ){
returnIntegrator = new LangevinIntegrator( temperature, friction, stepSize );
// returnIntegrator->setRandomNumberSeed( randomNumberSeed );
} else if( integratorName.compare( "VariableLangevinIntegrator" ) == 0 ){
returnIntegrator = new VariableLangevinIntegrator( temperature, friction, errorTolerance );
returnIntegrator->setStepSize( stepSize );
// returnIntegrator->setRandomNumberSeed( randomNumberSeed );
} else if( integratorName.compare( "VerletIntegrator" ) == 0 ){
returnIntegrator = new VerletIntegrator( stepSize );
} else if( integratorName.compare( "VariableVerletIntegrator" ) == 0 ){
returnIntegrator = new VariableVerletIntegrator( errorTolerance );
returnIntegrator->setStepSize( stepSize );
} else if( integratorName.compare( "BrownianIntegrator" ) == 0 ){
returnIntegrator = new BrownianIntegrator( temperature, friction, stepSize );
// returnIntegrator->setRandomNumberSeed( randomNumberSeed );
}
returnIntegrator->setConstraintTolerance( constraintTolerance );
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
(void) fprintf( log, "%s: parameters\n", methodName.c_str() );
(void) fprintf( log, "StepSize=%14.7e constraint tolerance=%14.7e ", stepSize, constraintTolerance );
if( integratorName.compare( "LangevinIntegrator" ) == 0 ||
integratorName.compare( "BrownianIntegrator" ) == 0 ||
integratorName.compare( "VariableLangevinIntegrator" ) == 0 ){
(void) fprintf( log, "Temperature=%14.7e friction=%14.7e seed=%d (seed may not be set!) ", temperature, friction, randomNumberSeed );
}
if( integratorName.compare( "VariableLangevinIntegrator" ) == 0 ||
integratorName.compare( "VariableVerletIntegrator" ) == 0 ){
(void) fprintf( log, "Error tolerance=%14.7e", errorTolerance);
}
(void) fprintf( log, "\n" );
}
return returnIntegrator;
}
/**---------------------------------------------------------------------------------------
Read arrays of Vec3s (coordinates/velocities/forces/...)
@param filePtr file pointer to parameter file
@param tokens array of strings from first line of parameter file for this block of parameters
@param coordinates Vec3 array
@param lineCount used to track line entries read from parameter file
@param log log file pointer -- may be NULL
@return number of entries read
--------------------------------------------------------------------------------------- */
int readVec3( FILE* filePtr, const StringVector& tokens, std::vector& coordinates, int* lineCount, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readVec3";
// ---------------------------------------------------------------------------------------
if( tokens.size() < 1 ){
char buffer[1024];
(void) sprintf( buffer, "%s no Coordinates terms entry???\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
int numberOfCoordinates= atoi( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s number of coordinates=%d\n", methodName.c_str(), numberOfCoordinates );
(void) fflush( log );
}
for( int ii = 0; ii < numberOfCoordinates; ii++ ){
StringVector lineTokens;
char* isNotEof = readLine( filePtr, lineTokens, lineCount, log );
int tokenIndex = 0;
if( lineTokens.size() > 3 ){
int index = atoi( lineTokens[tokenIndex++].c_str() );
double xCoord = atof( lineTokens[tokenIndex++].c_str() );
double yCoord = atof( lineTokens[tokenIndex++].c_str() );
double zCoord = atof( lineTokens[tokenIndex++].c_str() );
coordinates.push_back( Vec3( xCoord, yCoord, zCoord ) );
} else {
char buffer[1024];
(void) sprintf( buffer, "%s coordinates tokens incomplete at line=%d\n", methodName.c_str(), *lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
// diagnostics
if( log ){
static const unsigned int maxPrint = MAX_PRINT;
(void) fprintf( log, "%s: sample of vec3: %u\n", methodName.c_str(), coordinates.size() );
for( unsigned int ii = 0; ii < coordinates.size(); ii++ ){
(void) fprintf( log, "%6u [%14.7e %14.7e %14.7e]\n", ii,
coordinates[ii][0], coordinates[ii][1], coordinates[ii][2] );
if( ii == maxPrint ){
ii = coordinates.size() - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
return static_cast(coordinates.size());
}
/**---------------------------------------------------------------------------------------
Read parameter file
@param inputParameterFile input parameter file name
@param system system to which forces based on parameters are to be added
@param coordinates Vec3 array containing coordinates on output
@param velocities Vec3 array containing velocities on output
@param inputLog log file pointer -- may be NULL
@return number of lines read
--------------------------------------------------------------------------------------- */
Integrator* readParameterFile( const std::string& inputParameterFile, MapStringInt& forceMap, System& system,
std::vector& coordinates,
std::vector& velocities,
std::vector& forces, double* kineticEnergy, double* potentialEnergy,
MapStringVectorOfVectors& supplementary,
MapStringString& inputArgumentMap, FILE* inputLog ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "readParameterFile";
int PrintOn = 1;
// ---------------------------------------------------------------------------------------
FILE* log;
if( PrintOn == 0 && inputLog ){
log = NULL;
} else {
log = inputLog;
}
if( log ){
(void) fprintf( log, "%s\n", methodName.c_str() );
(void) fflush( log );
}
// open parameter file
FILE* filePtr;
#ifdef _MSC_VER
fopen_s( &filePtr, inputParameterFile.c_str(), "r" );
#else
filePtr = fopen( inputParameterFile.c_str(), "r" );
#endif
if( filePtr == NULL ){
char buffer[1024];
(void) sprintf( buffer, "Input parameter file=<%s> could not be opened -- aborting.\n", methodName.c_str(), inputParameterFile.c_str() );
throwException(__FILE__, __LINE__, buffer );
(void) fflush( stderr);
exit(-1);
} else if( log ){
(void) fprintf( log, "Input parameter file=<%s> opened.\n", methodName.c_str(), inputParameterFile.c_str() );
}
int lineCount = 0;
std::string version = "0.1";
char* isNotEof = "1";
Integrator* returnIntegrator = NULL;
// loop over lines in file
while( isNotEof ){
// read line and continue if not EOF and tokens found on line
StringVector tokens;
isNotEof = readLine( filePtr, tokens, &lineCount, log );
if( isNotEof && tokens.size() > 0 ){
std::string field = tokens[0];
if( log ){
(void) fprintf( log, "Field=<%s> at line=%d\n", field.c_str(), lineCount );
}
if( field.compare( "Version" ) == 0 ){
if( tokens.size() > 1 ){
version = tokens[1];
if( log ){
(void) fprintf( log, "Version=<%s> at line=%d\n", version.c_str(), lineCount );
}
}
} else if( field.compare( "Particles" ) == 0 ){
readParticles( filePtr, tokens, system, &lineCount, log );
} else if( field.compare( "Masses" ) == 0 ){
readMasses( filePtr, tokens, system, &lineCount, log );
} else if( field.compare( "NumberOfForces" ) == 0 ){
// skip
} else if( field.compare( "Box" ) == 0 ){
std::vector< Vec3 > box;
box.resize( 3 );
int xyzIndex = 0;
int boxIndex = 0;
for( int ii = 1; ii < 10; ii++ ){
box[boxIndex][xyzIndex++] = atof( tokens[ii].c_str() );
if( xyzIndex == 3 ){
xyzIndex = 0;
boxIndex++;
}
}
system.setPeriodicBoxVectors( box[0], box[1], box[2] );
Vec3 a, b, c;
system.getPeriodicBoxVectors( a, b, c);
if( log ){
(void) fprintf( log, "Box [%14.7f %14.7f %14.7f]\n [%14.7f %14.7f %14.7f]\n [%14.7f %14.7f %14.7f]\n",
a[0], a[1], a[2], b[0], b[1], b[2], c[0], c[1], c[2] );
}
} else if( field.compare( "CMMotionRemover" ) == 0 ){
int frequency = atoi( tokens[1].c_str() );
system.addForce( new CMMotionRemover( frequency ) );
if( log ){
(void) fprintf( log, "CMMotionRemover added w/ frequency=%d at line=%d\n", frequency, lineCount );
}
} else if( field.compare( "HarmonicBondForce" ) == 0 ){
readHarmonicBondForce( filePtr, forceMap, tokens, system, &lineCount, log );
} else if( field.compare( "HarmonicAngleForce" ) == 0 ){
readHarmonicAngleForce( filePtr, forceMap, tokens, system, &lineCount, log );
} else if( field.compare( "PeriodicTorsionForce" ) == 0 ){
readPeriodicTorsionForce( filePtr, forceMap, tokens, system, &lineCount, log );
} else if( field.compare( "RBTorsionForce" ) == 0 ){
readRBTorsionForce( filePtr, forceMap, tokens, system, &lineCount, log );
} else if( field.compare( "NonbondedForce" ) == 0 ){
readNonbondedForce( filePtr, forceMap, tokens, system, &lineCount, inputArgumentMap, log );
#ifdef INCLUDE_FREE_ENERGY_PLUGIN
} else if( field.compare( "NonbondedSoftcoreForce" ) == 0 ){
readNonbondedSoftcoreForce( filePtr, forceMap, tokens, system, &lineCount, inputArgumentMap, log );
#endif
} else if( field.compare( "GBSAOBCForce" ) == 0 ){
readGBSAOBCForce( filePtr, forceMap, tokens, system, &lineCount, log );
#ifdef INCLUDE_FREE_ENERGY_PLUGIN
} else if( field.compare( "GBSAOBCSoftcoreForce" ) == 0 ){
readGBSAOBCSoftcoreForce( filePtr, forceMap, tokens, system, &lineCount, log );
#endif
} else if( field.compare( "GBVIForce" ) == 0 ){
readGBVIForce( filePtr, forceMap, tokens, system, &lineCount, log );
#ifdef INCLUDE_FREE_ENERGY_PLUGIN
} else if( field.compare( "GBVISoftcoreForce" ) == 0 ){
readGBVISoftcoreForce( filePtr, forceMap, tokens, system, &lineCount, log );
#endif
} else if( field.compare( "Constraints" ) == 0 ){
readConstraints( filePtr, tokens, system, &lineCount, log );
} else if( field.compare( "Integrator" ) == 0 ){
returnIntegrator = readIntegrator( filePtr, tokens, system, &lineCount, log );
} else if( field.compare( "Positions" ) == 0 ){
readVec3( filePtr, tokens, coordinates, &lineCount, log );
} else if( field.compare( "Velocities" ) == 0 ){
readVec3( filePtr, tokens, velocities, &lineCount, log );
} else if( field.compare( "Forces" ) == 0 ){
readVec3( filePtr, tokens, forces, &lineCount, log );
} else if( field.compare( "GromacsHarmonicBondForce" ) == 0 ||
field.compare( "GromacsHarmonicAngleForce" ) == 0 ||
field.compare( "GromacsPeriodicTorsionForce" ) == 0 ||
field.compare( "GromacsRBTorsionForce" ) == 0 ||
field.compare( "GromacsNonbondedForceExceptions" ) == 0 ||
field.compare( "GromacsNonbondedForce" ) == 0 ){
std::vector< std::vector > vectorOfVectors;
readVectorOfVectors( filePtr, tokens, vectorOfVectors, &lineCount, field, log );
if( supplementary.find( field ) == supplementary.end() ){
supplementary[field] = vectorOfVectors;
}
} else if( field.compare( "KineticEnergy" ) == 0 ||
field.compare( "PotentialEnergy" ) == 0 ){
double value = 0.0;
if( tokens.size() > 1 ){
value = atof( tokens[1].c_str() );
if( log ){
(void) fprintf( log, "%s =%s\n", tokens[0].c_str(), tokens[1].c_str());
}
} else {
char buffer[1024];
(void) sprintf( buffer, "Missing energy for field=<%s> at line=%d\n", field.c_str(), lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
if( field.compare( "KineticEnergy" ) == 0 ){
*kineticEnergy = value;
} else {
*potentialEnergy = value;
}
} else {
char buffer[1024];
(void) sprintf( buffer, "Field=<%s> not recognized at line=%d\n", field.c_str(), lineCount );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
}
// close file
(void) fclose( filePtr );
if( log ){
(void) fprintf( log, "Read %d lines from file=<%s>\n", lineCount, inputParameterFile.c_str() );
(void) fflush( log );
}
return returnIntegrator;
}
/**---------------------------------------------------------------------------------------
* Get integrator
*
* @param integratorName integratorName (VerletIntegrator, BrownianIntegrator, LangevinIntegrator, ...)
* @param timeStep time step
* @param friction (ps) friction
* @param temperature temperature
* @param shakeTolerance Shake tolerance
* @param errorTolerance Error tolerance
* @param randomNumberSeed seed
*
* @return DefaultReturnValue or ErrorReturnValue
*
--------------------------------------------------------------------------------------- */
Integrator* _getIntegrator( std::string& integratorName, double timeStep,
double friction, double temperature,
double shakeTolerance, double errorTolerance,
int randomNumberSeed, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "_getIntegrator";
// ---------------------------------------------------------------------------------------
// Create an integrator
Integrator* integrator;
if( integratorName.compare( "VerletIntegrator" ) == 0 ){
integrator = new VerletIntegrator( timeStep );
} else if( integratorName.compare( "VariableVerletIntegrator" ) == 0 ){
integrator = new VariableVerletIntegrator( errorTolerance );
} else if( integratorName.compare( "BrownianIntegrator" ) == 0 ){
integrator = new BrownianIntegrator( temperature, friction, timeStep );
} else if( integratorName.compare( "LangevinIntegrator" ) == 0 ){
integrator = new LangevinIntegrator( temperature, friction, timeStep );
LangevinIntegrator* langevinIntegrator = dynamic_cast(integrator);
if( randomNumberSeed <= 0 ){
time_t zero = time(NULL);
langevinIntegrator->setRandomNumberSeed(static_cast(zero));
} else {
langevinIntegrator->setRandomNumberSeed( randomNumberSeed );
}
} else if( integratorName.compare( "VariableLangevinIntegrator" ) == 0 ){
integrator = new VariableLangevinIntegrator( temperature, friction, errorTolerance );
VariableLangevinIntegrator* langevinIntegrator = dynamic_cast(integrator);
if( randomNumberSeed <= 0 ){
time_t zero = time(NULL);
langevinIntegrator->setRandomNumberSeed(static_cast(zero));
} else {
langevinIntegrator->setRandomNumberSeed( randomNumberSeed );
}
} else {
char buffer[1024];
(void) sprintf( buffer, "%s integrator=<%s> not recognized.\n", methodName.c_str(), integratorName.c_str() );
if( log ){
(void) fprintf( log , "%s", buffer );
(void) fflush( log );
}
throwException(__FILE__, __LINE__, buffer );
return NULL;
}
integrator->setConstraintTolerance( shakeTolerance );
return integrator;
}
/**---------------------------------------------------------------------------------------
* Get integrator type
*
* @param integrator
*
* @return name or "NotFound"
*
--------------------------------------------------------------------------------------- */
static std::string _getIntegratorName( Integrator* integrator ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "_getIntegratorName";
// ---------------------------------------------------------------------------------------
// LangevinIntegrator
try {
LangevinIntegrator& langevinIntegrator = dynamic_cast(*integrator);
return "LangevinIntegrator";
} catch( std::bad_cast ){
}
// VariableLangevinIntegrator
try {
VariableLangevinIntegrator& langevinIntegrator = dynamic_cast(*integrator);
return "VariableLangevinIntegrator";
} catch( std::bad_cast ){
}
// VerletIntegrator
try {
VerletIntegrator& verletIntegrator = dynamic_cast(*integrator);
return "VerletIntegrator";
} catch( std::bad_cast ){
}
// VariableVerletIntegrator
try {
VariableVerletIntegrator & variableVerletIntegrator = dynamic_cast(*integrator);
return "VariableVerletIntegrator";
} catch( std::bad_cast ){
}
// BrownianIntegrator
try {
BrownianIntegrator& brownianIntegrator = dynamic_cast(*integrator);
return "BrownianIntegrator";
} catch( std::bad_cast ){
}
return "NotFound";
}
/**---------------------------------------------------------------------------------------
* Set velocities based on temperature
*
* @param system System reference -- retrieve particle masses
* @param velocities array of Vec3 for velocities (size must be set)
* @param temperature temperature
* @param log optional log reference
*
* @return DefaultReturnValue
*
--------------------------------------------------------------------------------------- */
static int _setVelocitiesBasedOnTemperature( const System& system, std::vector& velocities, double temperature, FILE* log ) {
// ---------------------------------------------------------------------------------------
static const std::string methodName = "setVelocitiesBasedOnTemperature";
double randomValues[3];
// ---------------------------------------------------------------------------------------
// set velocities based on temperature
temperature *= BOLTZ;
double randMax = static_cast(RAND_MAX);
randMax = 1.0/randMax;
for( unsigned int ii = 0; ii < velocities.size(); ii++ ){
double velocityScale = std::sqrt( temperature/system.getParticleMass(ii) );
randomValues[0] = randMax*( (double) rand() );
randomValues[1] = randMax*( (double) rand() );
randomValues[2] = randMax*( (double) rand() );
velocities[ii] = Vec3( randomValues[0]*velocityScale, randomValues[1]*velocityScale, randomValues[2]*velocityScale );
}
return DefaultReturnValue;
}
/**---------------------------------------------------------------------------------------
* Print Integrator info to log
*
* @param integrator integrator
* @param log optional log reference
*
* @return DefaultReturnValue
*
--------------------------------------------------------------------------------------- */
static int _printIntegratorInfo( Integrator* integrator, FILE* log ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "_printIntegratorInfo";
// ---------------------------------------------------------------------------------------
std::string integratorName = _getIntegratorName( integrator );
(void) fprintf( log, "Integrator=%s stepSize=%.3f ShakeTol=%.3e\n",
integratorName.c_str(), integrator->getStepSize(), integrator->getConstraintTolerance() );
// stochastic integrators (seed, friction, temperature)
if( integratorName.compare( "LangevinIntegrator" ) == 0 || integratorName.compare( "VariableLangevinIntegrator" ) == 0 ||
integratorName.compare( "BrownianIntegrator" ) == 0 ){
double temperature = 300.0;
double friction = 100.0;
int seed = 0;
if( integratorName.compare( "LangevinIntegrator" ) == 0 ){
LangevinIntegrator* langevinIntegrator = dynamic_cast(integrator);
temperature = langevinIntegrator->getTemperature();
friction = langevinIntegrator->getFriction();
seed = langevinIntegrator->getRandomNumberSeed();
} else if( integratorName.compare( "VariableLangevinIntegrator" ) == 0 ){
VariableLangevinIntegrator* langevinIntegrator = dynamic_cast(integrator);
temperature = langevinIntegrator->getTemperature();
friction = langevinIntegrator->getFriction();
seed = langevinIntegrator->getRandomNumberSeed();
} else if( integratorName.compare( "BrownianIntegrator" ) == 0 ){
BrownianIntegrator* brownianIntegrator = dynamic_cast(integrator);
temperature = brownianIntegrator->getTemperature();
friction = brownianIntegrator->getFriction();
// seed = brownianIntegrator->getRandomNumberSeed();
}
(void) fprintf( log, "T=%.3f friction=%.3f seed=%d\n", temperature, friction, seed );
}
// variable integrators -- error tolerance
if( integratorName.compare( "VariableLangevinIntegrator" ) == 0 || integratorName.compare( "VariableVerletIntegrator" ) == 0 ){
double errorTolerance = 0.0;
if( integratorName.compare( "VariableLangevinIntegrator" ) == 0 ){
VariableLangevinIntegrator* langevinIntegrator = dynamic_cast(integrator);
errorTolerance = langevinIntegrator->getErrorTolerance();
} else {
VariableVerletIntegrator* verletIntegrator = dynamic_cast(integrator);
errorTolerance = verletIntegrator->getErrorTolerance();
}
(void) fprintf( log, "Error tolerance=%.3e\n", errorTolerance );
}
(void) fflush( log );
return DefaultReturnValue;
}
/**---------------------------------------------------------------------------------------
Set the velocities/positions of context2 to those of context1
@param context1 context1
@param context2 context2
@return 0
--------------------------------------------------------------------------------------- */
static int _synchContexts( const Context& context1, Context& context2 ){
// ---------------------------------------------------------------------------------------
//static const char* methodName = "\n_synchContexts: ";
// ---------------------------------------------------------------------------------------
const State state = context1.getState(State::Positions | State::Velocities);
const std::vector& positions = state.getPositions();
const std::vector& velocities = state.getVelocities();
context2.setPositions( positions );
context2.setVelocities( velocities );
return DefaultReturnValue;
}
/**---------------------------------------------------------------------------------------
* Get context
*
* @param system system
* @param inputContext input context -- if set, the newly created context is updated w/ positions & velocities
* @param inputIntegrator input integrator for new context
* @param platformName name of platform( ReferencePlatform, CudaPlatform)
* @param idString diagnostic string (used in logging)
* @param deviceId deviceId (Cuda only)
* @param log log file reference
*
* @return OpenMM context
*
--------------------------------------------------------------------------------------- */
Context* _getContext( System* system, Context* inputContext, Integrator* inputIntegrator, const std::string& platformName,
const std::string& idString, std::string deviceId, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "_getContext";
// ---------------------------------------------------------------------------------------
// Create a context and initialize it.
Context* context;
ReferencePlatform referencePlatform;
if( platformName.compare( "ReferencePlatform" ) == 0 ){
context = new Context( *system, *inputIntegrator, Platform::getPlatform("Reference") );
} else {
context = new Context( *system, *inputIntegrator, Platform::getPlatform("Cuda") );
}
if( log ){
(void) fprintf( log, "%s Using Platform: %s device=%s\n", idString.c_str(), context->getPlatform().getName().c_str(), deviceId.c_str() );
(void) fflush( log );
}
if( inputContext ){
_synchContexts( *inputContext, *context );
}
return context;
}
/**---------------------------------------------------------------------------------------
Get statistics of elements in array
@param array array to collect stats
@param statistics statistics of array
index = 0 mean
index = 1 stddev
index = 2 min
index = 3 index of min value
index = 4 max
index = 5 index of max value
index = 6 size of array
@return DefaultReturnValue
--------------------------------------------------------------------------------------- */
static int _getStatistics( const std::vector & array, std::vector & statistics ){
// ---------------------------------------------------------------------------------------
static const char* methodName = "_getStatistics";
static const int mean = 0;
static const int stddev = 1;
static const int min = 2;
static const int minIndex = 3;
static const int max = 4;
static const int maxIndex = 5;
static const int size = 6;
// ---------------------------------------------------------------------------------------
// initialize stat array
statistics.resize( 10 );
for( unsigned int jj = 0; jj < statistics.size(); jj++ ){
statistics[jj] = 0.0;
}
statistics[min] = 1.0e+30;
statistics[max] = -1.0e+30;
// collect stats
int index = 0;
for( std::vector::const_iterator ii = array.begin(); ii != array.end(); ii++ ){
// first/second moments
statistics[mean] += *ii;
statistics[stddev] += (*ii)*(*ii);
// min/max
if( *ii < statistics[min] ){
statistics[min] = *ii;
statistics[minIndex] = index;
}
if( *ii > statistics[max] ){
statistics[max] = *ii;
statistics[maxIndex] = index;
}
index++;
}
// compute mean & std dev
double arraySz = (double) index;
statistics[size] = arraySz;
if( index ){
statistics[mean] /= arraySz;
statistics[stddev] = statistics[stddev] - arraySz*statistics[mean]*statistics[mean];
if( index > 1 ){
statistics[stddev] = std::sqrt( statistics[stddev] / ( arraySz - 1.0 ) );
}
}
return DefaultReturnValue;
}
static int getForceStrings( System& system, StringVector& forceStringArray, FILE* log ){
// print active forces and relevant parameters
for( int ii = 0; ii < system.getNumForces(); ii++ ) {
int hit = 0;
Force& force = system.getForce(ii);
// bond
if( !hit ){
try {
HarmonicBondForce& harmonicBondForce = dynamic_cast(force);
forceStringArray.push_back( HARMONIC_BOND_FORCE );
hit++;
} catch( std::bad_cast ){
}
}
// angle
if( !hit ){
try {
HarmonicAngleForce& harmonicAngleForce = dynamic_cast(force);
forceStringArray.push_back( HARMONIC_ANGLE_FORCE );
hit++;
} catch( std::bad_cast ){
}
}
// PeriodicTorsionForce
if( !hit ){
try {
PeriodicTorsionForce & periodicTorsionForce = dynamic_cast(force);
forceStringArray.push_back( PERIODIC_TORSION_FORCE );
hit++;
} catch( std::bad_cast ){
}
}
// RBTorsionForce
if( !hit ){
try {
RBTorsionForce& rBTorsionForce = dynamic_cast(force);
forceStringArray.push_back( RB_TORSION_FORCE );
hit++;
} catch( std::bad_cast ){
}
}
// nonbonded
if( !hit ){
try {
NonbondedForce& nbForce = dynamic_cast(force);
std::stringstream nonbondedForceMethod;
hit++;
switch( nbForce.getNonbondedMethod() ){
case NonbondedForce::NoCutoff:
nonbondedForceMethod << "NoCutoff";
break;
case NonbondedForce::CutoffNonPeriodic:
nonbondedForceMethod << "CutoffNonPeriodic_Cut=";
nonbondedForceMethod << nbForce.getCutoffDistance();
break;
case NonbondedForce::CutoffPeriodic:
nonbondedForceMethod << "CutoffPeriodic_Cut=";
nonbondedForceMethod << nbForce.getCutoffDistance();
break;
case NonbondedForce::Ewald:
nonbondedForceMethod << "Ewald_Tol=";
nonbondedForceMethod << nbForce.getEwaldErrorTolerance();
break;
case NonbondedForce::PME:
nonbondedForceMethod << "PME";
break;
default:
nonbondedForceMethod << "Unknown";
}
forceStringArray.push_back( NB_FORCE + nonbondedForceMethod.str() );
int nbExceptions = 0;
for( int ii = 0; ii < nbForce.getNumExceptions() && nbExceptions == 0; ii++ ){
int particle1, particle2;
double chargeProd, sigma, epsilon;
nbForce.getExceptionParameters(ii, particle1, particle2, chargeProd, sigma, epsilon);
if( fabs( chargeProd ) > 0.0 || fabs( epsilon ) > 0.0 ){
nbExceptions = 1;
}
}
if( nbExceptions ){
forceStringArray.push_back( NB_EXCEPTION_FORCE );
}
} catch( std::bad_cast ){
}
}
// nonbonded softcore
#ifdef INCLUDE_FREE_ENERGY_PLUGIN
if( !hit ){
try {
NonbondedSoftcoreForce& nbForce = dynamic_cast(force);
std::stringstream nonbondedForceMethod;
hit++;
switch( nbForce.getNonbondedMethod() ){
case NonbondedSoftcoreForce::NoCutoff:
nonbondedForceMethod << "NoCutoff";
break;
case NonbondedForce::CutoffNonPeriodic:
nonbondedForceMethod << "CutoffNonPeriodic_Cut=";
nonbondedForceMethod << nbForce.getCutoffDistance();
break;
case NonbondedForce::CutoffPeriodic:
nonbondedForceMethod << "CutoffPeriodic_Cut=";
nonbondedForceMethod << nbForce.getCutoffDistance();
break;
case NonbondedForce::Ewald:
nonbondedForceMethod << "Ewald_Tol=";
nonbondedForceMethod << nbForce.getEwaldErrorTolerance();
break;
case NonbondedForce::PME:
nonbondedForceMethod << "PME";
break;
default:
nonbondedForceMethod << "Unknown";
}
forceStringArray.push_back( NB_SOFTCORE_FORCE + nonbondedForceMethod.str() );
int nbExceptions = 0;
for( int ii = 0; ii < nbForce.getNumExceptions() && nbExceptions == 0; ii++ ){
int particle1, particle2;
double chargeProd, sigma, epsilon;
nbForce.getExceptionParameters(ii, particle1, particle2, chargeProd, sigma, epsilon);
if( fabs( chargeProd ) > 0.0 || fabs( epsilon ) > 0.0 ){
nbExceptions = 1;
}
}
if( nbExceptions ){
forceStringArray.push_back( NB_EXCEPTION_SOFTCORE_FORCE );
}
} catch( std::bad_cast ){
}
}
#endif
// GBSA OBC
if( !hit ){
try {
GBSAOBCForce& obcForce = dynamic_cast(force);
forceStringArray.push_back( GBSA_OBC_FORCE );
hit++;
} catch( std::bad_cast ){
}
}
// GBSA OBC softcore
#ifdef INCLUDE_FREE_ENERGY_PLUGIN
if( !hit ){
try {
GBSAOBCSoftcoreForce& obcForce = dynamic_cast(force);
forceStringArray.push_back( GBSA_OBC_SOFTCORE_FORCE );
hit++;
} catch( std::bad_cast ){
}
}
#endif
// GBVI
if( !hit ){
try {
GBVIForce& gbviForce = dynamic_cast(force);
forceStringArray.push_back( GBVI_FORCE );
hit++;
} catch( std::bad_cast ){
}
}
// GBVI softcore
#ifdef INCLUDE_FREE_ENERGY_PLUGIN
if( !hit ){
try {
GBVISoftcoreForce& gbviForce = dynamic_cast(force);
forceStringArray.push_back( GBVI_SOFTCORE_FORCE );
hit++;
} catch( std::bad_cast ){
}
}
#endif
// COM
if( !hit ){
try {
CMMotionRemover& cMMotionRemover = dynamic_cast(force);
hit++;
} catch( std::bad_cast ){
}
}
if( !hit && log ){
(void) fprintf( log, " entry=%2d force not recognized XXXX\n", ii );
}
}
return 0;
}
/**
* Check that energy and force are consistent
*
* @return DefaultReturnValue or ErrorReturnValue
*
*/
static int checkEnergyForceConsistent( Context& context, MapStringString& inputArgumentMap,
FILE* log, FILE* summaryFile ) {
// ---------------------------------------------------------------------------------------
int applyAssertion = 1;
double delta = 1.0e-04;
double tolerance = 0.01;
static const std::string methodName = "checkEnergyForceConsistent";
// ---------------------------------------------------------------------------------------
setIntFromMap( inputArgumentMap, "applyAssertion", applyAssertion );
setDoubleFromMap( inputArgumentMap, "energyForceDelta", delta );
setDoubleFromMap( inputArgumentMap, "energyForceTolerance", tolerance );
StringVector forceStringArray;
System system = context.getSystem();
getForceStrings( system, forceStringArray, log );
if( log ){
(void) fprintf( log, "%s delta=%.3e tolerance=%.3e applyAssertion=%d\n", methodName.c_str(), delta, tolerance, applyAssertion );
(void) fprintf( log, "\nForces:\n" );
for( StringVectorCI ii = forceStringArray.begin(); ii != forceStringArray.end(); ii++ ){
(void) fprintf( log, " %s\n", (*ii).c_str() );
}
(void) fflush( log );
}
int returnStatus = 0;
// get positions, forces and potential energy
int types = State::Positions | State::Velocities | State::Forces | State::Energy;
State state = context.getState( types );
std::vector coordinates = state.getPositions();
std::vector velocities = state.getVelocities();
std::vector forces = state.getForces();
double kineticEnergy = state.getKineticEnergy();
double potentialEnergy = state.getPotentialEnergy();
// compute norm of force
double forceNorm = 0.0;
for( unsigned int ii = 0; ii < forces.size(); ii++ ){
#if 0
(void) fprintf( log, "%6u x[%14.7e %14.7e %14.7e] f[%14.7e %14.7e %14.7e]\n", ii,
coordinates[ii][0], coordinates[ii][1], coordinates[ii][2],
forces[ii][0], forces[ii][1], forces[ii][2] );
#endif
forceNorm += forces[ii][0]*forces[ii][0] + forces[ii][1]*forces[ii][1] + forces[ii][2]*forces[ii][2];
}
// check norm is not nan
if( isinf( forceNorm ) || isnan( forceNorm ) ){
if( log ){
(void) fprintf( log, "%s norm of force is nan -- aborting.\n", methodName.c_str() );
unsigned int hitNan = 0;
for( unsigned int ii = 0; (ii < forces.size()) && (hitNan < 10); ii++ ){
if( isinf( forces[ii][0] ) || isnan( forces[ii][0] ) ||
isinf( forces[ii][1] ) || isnan( forces[ii][1] ) ||
isinf( forces[ii][2] ) || isnan( forces[ii][2] ) )hitNan++;
(void) fprintf( log, "%6u x[%14.7e %14.7e %14.7e] f[%14.7e %14.7e %14.7e]\n", ii,
coordinates[ii][0], coordinates[ii][1], coordinates[ii][2],
forces[ii][0], forces[ii][1], forces[ii][2] );
}
char buffer[1024];
(void) sprintf( buffer, "%s : nans detected -- aborting.\n", methodName.c_str() );
throwException(__FILE__, __LINE__, buffer );
}
}
forceNorm = std::sqrt( forceNorm );
if( forceNorm <= 0.0 ){
if( log ){
(void) fprintf( log, "%s norm of force is <= 0 norm=%.3e\n", methodName.c_str(), forceNorm );
(void) fflush( log );
}
return returnStatus;
}
// take step in direction of energy gradient
double step = delta/forceNorm;
std::vector perturbedPositions;
perturbedPositions.resize( forces.size() );
for( unsigned int ii = 0; ii < forces.size(); ii++ ){
perturbedPositions[ii] = Vec3( coordinates[ii][0] - step*forces[ii][0], coordinates[ii][1] - step*forces[ii][1], coordinates[ii][2] - step*forces[ii][2] );
}
context.setPositions( perturbedPositions );
// get new potential energy
state = context.getState( types );
// report energies
double perturbedPotentialEnergy = state.getPotentialEnergy();
double deltaEnergy = ( perturbedPotentialEnergy - potentialEnergy )/delta;
double difference = fabs( deltaEnergy - forceNorm );
double denominator = forceNorm;
if( denominator > 0.0 ){
difference /= denominator;
}
if( log ){
(void) fprintf( log, "%s difference=%14.8e dE=%14.8e Pe2/1 [%16.10e %16.10e] delta=%10.4e nrm=%16.10e\n",
methodName.c_str(), difference, deltaEnergy, perturbedPotentialEnergy,
potentialEnergy, delta, forceNorm );
(void) fflush( log );
}
if( summaryFile ){
std::string forceString;
if( forceStringArray.size() > 5 ){
forceString = "All";
} else {
for( StringVectorCI ii = forceStringArray.begin(); ii != forceStringArray.end(); ii++ ){
forceString += (*ii) + "_";
}
}
if( forceString.size() < 1 ){
forceString = "NA";
}
(void) fprintf( summaryFile, "EnergyForceConsistent %s\nForce %s\nCalculated %14.6e\nExpected %14.7e\nDiffNorm %14.7e\nE0 %14.7e\nE1 %14.7e\nForceNorm %14.7e\nDelta %14.7e\n",
context.getPlatform().getName().c_str(), forceString.c_str(), deltaEnergy, forceNorm, difference, potentialEnergy, perturbedPotentialEnergy, forceNorm, delta );
}
if( applyAssertion ){
ASSERT( difference < tolerance );
if( log ){
(void) fprintf( log, "\n%s passed\n", methodName.c_str() );
(void) fflush( log );
}
}
return returnStatus;
}
/**---------------------------------------------------------------------------------------
Find stats for vec3
@param array array
@param statVector vector of stats
@return 0
--------------------------------------------------------------------------------------- */
int compareForces( const std::vector& forceArray1, const std::string& f1Name, std::vector& forceArray1Sum, std::vector& forceArray1Stats,
const std::vector& forceArray2, const std::string& f2Name, std::vector& forceArray2Sum, std::vector& forceArray2Stats,
double* maxDelta, int* maxDeltaIndex, double* maxRelativeDelta, int* maxRelativeDeltaIndex, double* maxDot, double forceTolerance, FILE* inputLog ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "compareForces";
int PrintOn = 1;
// ---------------------------------------------------------------------------------------
FILE* log;
if( PrintOn == 0 && inputLog ){
log = NULL;
} else {
log = inputLog;
}
if( log ){
(void) fprintf( log, "%s\n", methodName.c_str() );
(void) fflush( log );
}
*maxDelta = -1.0e+30;
*maxRelativeDelta = -1.0e+30;
*maxDot = -1.0e+30;
*maxDeltaIndex = -1;
*maxRelativeDeltaIndex = -1;
std::vector forceArray1Norms;
std::vector forceArray2Norms;
forceArray1Sum.resize( 3 );
forceArray2Sum.resize( 3 );
for( unsigned int ii = 0; ii < 3; ii++ ){
forceArray1Sum[ii] = forceArray2Sum[ii] = 0.0;
}
(void) fprintf( log, " Id delta relDelta dot %4s norm force %4s norm force\n",
f1Name.c_str(), f2Name.c_str() );
for( unsigned int ii = 0; ii < forceArray2.size(); ii++ ){
Vec3 f1 = forceArray1[ii];
double normF1 = std::sqrt( (f1[0]*f1[0]) + (f1[1]*f1[1]) + (f1[2]*f1[2]) );
forceArray1Norms.push_back( normF1 );
forceArray1Sum[0] += f1[0];
forceArray1Sum[1] += f1[1];
forceArray1Sum[2] += f1[2];
Vec3 f2 = forceArray2[ii];
double normF2 = std::sqrt( (f2[0]*f2[0]) + (f2[1]*f2[1]) + (f2[2]*f2[2]) );
forceArray2Norms.push_back( normF2 );
forceArray2Sum[0] += f2[0];
forceArray2Sum[1] += f2[1];
forceArray2Sum[2] += f2[2];
double delta = std::sqrt( (f1[0]-f2[0])*(f1[0]-f2[0]) + (f1[1]-f2[1])*(f1[1]-f2[1]) + (f1[2]-f2[2])*(f1[2]-f2[2]) );
double dotProduct = f1[0]*f2[0] + f1[1]*f2[1] + f1[2]*f2[2];
if( (normF1*normF2) > 0.0 ){
dotProduct /= (normF1*normF2);
dotProduct = 1.0 - dotProduct;
} else {
dotProduct = 0.0;
}
double relativeDelta = (delta*2.0)/(normF1+normF2);
int print = 0;
if( delta > forceTolerance ){
print++;
}
if( *maxRelativeDelta < relativeDelta ){
print++;
*maxRelativeDelta = relativeDelta;
*maxRelativeDeltaIndex = static_cast(ii);
}
if( *maxDot < dotProduct ){
*maxDot = dotProduct;
if( dotProduct > 1.0e-06 )print++;
}
if( *maxDelta < delta ){
*maxDelta = delta;
*maxDeltaIndex = static_cast(ii);
}
if( print && log ){
// (void) fprintf( log, "%5d delta=%9.3e relDelta=%9.3e dot=%9.3e %s %13.7e [%14.7e %14.7e %14.7e] %s %13.7e [%14.7e %14.7e %14.7e]\n",
// ii, delta, relativeDelta, dotProduct, f1Name.c_str(), normF1, f1[0], f1[1], f1[2], f2Name.c_str(), normF2, f2[0], f2[1], f2[2] );
(void) fprintf( log, "%5d %9.3e %9.3e %9.3e %13.7e [%14.7e %14.7e %14.7e] %13.7e [%14.7e %14.7e %14.7e] %s\n",
ii, delta, relativeDelta, dotProduct, normF1, f1[0], f1[1], f1[2], normF2, f2[0], f2[1], f2[2], ((normF1 > 1.0e+06 || normF2 > 1.0e+06) ? "!!!" : "") );
(void) fflush( log );
}
}
findStatsForDouble( forceArray1Norms, forceArray1Stats );
findStatsForDouble( forceArray2Norms, forceArray2Stats );
return 0;
}
/**---------------------------------------------------------------------------------------
* Check energy conservation
*
* @param context context to run test on
* @param totalSimulationSteps total number of simulation steps
* @param log log file reference
*
* @return DefaultReturnValue or ErrorReturnValue
*
--------------------------------------------------------------------------------------- */
static int checkForcesDuringSimulation( int currentStep, Context& cudaContext, Context& referenceContext, FILE* log ) {
// ---------------------------------------------------------------------------------------
static const std::string methodName = "checkForcesDuringSimulation";
// ---------------------------------------------------------------------------------------
_synchContexts( cudaContext, referenceContext );
State referenceState = referenceContext.getState( State::Energy | State::Forces );
double referenceKineticEnergy = referenceState.getKineticEnergy();
double referencePotentialEnergy = referenceState.getPotentialEnergy();
double referenceTotalEnergy = referenceKineticEnergy + referencePotentialEnergy;
State cudaState = cudaContext.getState( State::Energy | State::Forces );
double cudaKineticEnergy = cudaState.getKineticEnergy();
double cudaPotentialEnergy = cudaState.getPotentialEnergy();
double cudaTotalEnergy = cudaKineticEnergy + cudaPotentialEnergy;
(void) fprintf( log, "%6d PE=%14.7e %14.7e KE=%14.7e %14.7e E=%14.7e %14.7ed\n",
currentStep, referencePotentialEnergy, cudaPotentialEnergy,
referenceKineticEnergy, cudaKineticEnergy,
referenceTotalEnergy, cudaTotalEnergy );
// compare reference vs cuda forces
std::vector referenceForces = referenceState.getForces();
std::vector cudaForces = cudaState.getForces();
double maxDeltaRefCud = -1.0e+30;
double maxRelativeDeltaRefCud = -1.0e+30;
double maxDotRefCud = -1.0e+30;
double maxDeltaPrmCud = -1.0e+30;
double maxRelativeDeltaPrmCud = -1.0e+30;
double maxDotPrmCud = -1.0e+30;
double forceTolerance = 1.0e-01;
int maxDeltaIndex;
int maxRelativeDeltaRefCudIndex;
std::vector forceArray1Sum;
std::vector forceArray2Sum;
std::vector forceArray3Sum;
std::vector referenceForceStats;
std::vector cudaForceStats;
compareForces( referenceForces, "fRef", forceArray1Sum, referenceForceStats,
cudaForces, "fCud", forceArray2Sum, cudaForceStats,
&maxDeltaRefCud, &maxDeltaIndex, &maxRelativeDeltaRefCud, &maxRelativeDeltaRefCudIndex, &maxDotRefCud, forceTolerance, log );
(void) fprintf( log, "MaxDelta=%13.7e at %d MaxRelativeDelta=%13.7e at %d maxDotRefCud=%14.6e\n",
maxDeltaRefCud, maxDeltaIndex, maxRelativeDeltaRefCud, maxRelativeDeltaRefCudIndex, maxDotRefCud );
(void) fprintf( log, "Reference force average=%14.7e stddev=%14.7e min=%14.7e at %6.0f max=%14.7e at %6.0f\n",
referenceForceStats[0], referenceForceStats[1], referenceForceStats[2], referenceForceStats[3],
referenceForceStats[4], referenceForceStats[5] );
(void) fprintf( log, " Cuda force average=%14.7e stddev=%14.7e min=%14.7e at %6.0f max=%14.7e at %6.0f\n",
cudaForceStats[0], cudaForceStats[1], cudaForceStats[2], cudaForceStats[3],
cudaForceStats[4], cudaForceStats[5] );
(void) fflush( log );
return 0;
}
/**---------------------------------------------------------------------------------------
* Check energy conservation
*
* @param context context to run test on
* @param totalSimulationSteps total number of simulation steps
* @param log log file reference
*
* @return DefaultReturnValue or ErrorReturnValue
*
--------------------------------------------------------------------------------------- */
static int checkEnergyConservation( Context& context, MapStringString& inputArgumentMap, FILE* log,
FILE* summaryFile ) {
// ---------------------------------------------------------------------------------------
static const std::string methodName = "checkEnergyConservation";
// tolerance for thermostat
double temperatureTolerance = 3.0;
// tolerance for energy conservation test
double energyTolerance = 0.05;
std::string equilibrationIntegratorName = "LangevinIntegrator";
//std::string equilibrationIntegratorName = "VerletIntegrator";
int equilibrationTotalSteps = 1000;
double equilibrationStepsBetweenReportsRatio = 0.1;
double equilibrationTimeStep = 0.002;
double equilibrationFriction = 91.0;
double equilibrationShakeTolerance = 1.0e-05;
double equilibrationErrorTolerance = 1.0e-05;
double equilibrationTemperature = 300.0;
int equilibrationSeed = 1993;
int equilibrationWriteContext = 0;
std::string simulationIntegratorName = "VerletIntegrator";
int simulationTotalSteps = 10000;
double simulationStepsBetweenReportsRatio = 0.01;
double simulationTimeStep = 0.001;
double simulationFriction = 91.0;
double simulationShakeTolerance = 1.0e-06;
double simulationErrorTolerance = 1.0e-05;
double simulationTemperature = 300.0;
int simulationSeed = 1993;
int simulationWriteContext = 0;
int applyAssertion = 1;
std::string deviceId = "0";
std::string runId = "RunId";
// ---------------------------------------------------------------------------------------
setIntFromMap( inputArgumentMap, "applyAssertion", applyAssertion );
setStringFromMap( inputArgumentMap, "cudaDeviceId", deviceId );
setStringFromMap( inputArgumentMap, "runId", runId );
setStringFromMap( inputArgumentMap, "equilibrationIntegrator", equilibrationIntegratorName );
setIntFromMap( inputArgumentMap, "equilibrationTotalSteps", equilibrationTotalSteps );
setDoubleFromMap( inputArgumentMap, "equilibrationStepsBetweenReportsRatio", equilibrationStepsBetweenReportsRatio );
setDoubleFromMap( inputArgumentMap, "equilibrationTimeStep", equilibrationTimeStep );
setDoubleFromMap( inputArgumentMap, "equilibrationFriction", equilibrationFriction );
setDoubleFromMap( inputArgumentMap, "equilibrationShakeTolerance", equilibrationShakeTolerance );
setDoubleFromMap( inputArgumentMap, "equilibrationErrorTolerance", equilibrationErrorTolerance );
setDoubleFromMap( inputArgumentMap, "equilibrationTemperature", equilibrationTemperature );
setIntFromMap( inputArgumentMap, "equilibrationSeed", equilibrationSeed );
setIntFromMap( inputArgumentMap, "equilibrationWriteContext", equilibrationWriteContext );
setStringFromMap( inputArgumentMap, "simulationIntegrator", simulationIntegratorName );
setIntFromMap( inputArgumentMap, "simulationTotalSteps", simulationTotalSteps );
setDoubleFromMap( inputArgumentMap, "simulationStepsBetweenReportsRatio", simulationStepsBetweenReportsRatio );
setDoubleFromMap( inputArgumentMap, "simulationTimeStep", simulationTimeStep );
setDoubleFromMap( inputArgumentMap, "simulationFriction", simulationFriction );
setDoubleFromMap( inputArgumentMap, "simulationShakeTolerance", simulationShakeTolerance );
setDoubleFromMap( inputArgumentMap, "simulationErrorTolerance", simulationErrorTolerance );
setDoubleFromMap( inputArgumentMap, "simulationTemperature", simulationTemperature );
setIntFromMap( inputArgumentMap, "simulationSeed", simulationSeed );
setIntFromMap( inputArgumentMap, "simulationWriteContext", simulationWriteContext );
if( log ){
(void) fprintf( log, "%s Equilbration: %s steps=%d ratioRport=%.2f timeStep=%.4f T=%8.3f friction=%8.3f\n"
"ShakeTol=%3e ErrorTol=%.3e seed=%d\n", methodName.c_str(),
equilibrationIntegratorName.c_str(), equilibrationTotalSteps, equilibrationStepsBetweenReportsRatio,
equilibrationTimeStep, equilibrationTemperature, equilibrationFriction,
equilibrationShakeTolerance, equilibrationErrorTolerance, equilibrationSeed );
(void) fprintf( log, "%s Simulation: %s steps=%d ratioRport=%.2f timeStep=%.4f T=%8.3f friction=%8.3f\n"
"ShakeTol=%3e ErrorTol=%.3e seed=%d\n", methodName.c_str(),
simulationIntegratorName.c_str(), simulationTotalSteps, simulationStepsBetweenReportsRatio,
simulationTimeStep, simulationTemperature, simulationFriction,
simulationShakeTolerance, simulationErrorTolerance, simulationSeed );
(void) fprintf( log, "deviceId=%s applyAssertion=%d\n", deviceId.c_str(), applyAssertion );
(void) fflush( log );
}
int returnStatus = 0;
clock_t totalEquilibrationTime = 0;
clock_t totalSimulationTime = 0;
clock_t cpuTime;
int allTypes = State::Positions | State::Velocities | State::Forces | State::Energy;
// set velocities based on temperature
System& system = context.getSystem();
int numberOfAtoms = system.getNumParticles();
std::vector velocities;
//velocities.resize( numberOfAtoms );
//_setVelocitiesBasedOnTemperature( system, velocities, initialTemperature, log );
// get integrator for equilibration and context
Integrator* integrator = _getIntegrator( equilibrationIntegratorName, equilibrationTimeStep,
equilibrationFriction, equilibrationTemperature,
equilibrationShakeTolerance, equilibrationErrorTolerance, equilibrationSeed, log );
if( log ){
_printIntegratorInfo( integrator, log );
}
Context* equilibrationContext = _getContext( &system, &context, integrator, "CudaPlatform", "EquilibrationContext", deviceId, log );
// equilibration loop
int constraintViolations = 0;
int constraintChecks = 0;
int currentStep = 0;
int equilibrationStepsBetweenReports = static_cast(static_cast(equilibrationTotalSteps)*equilibrationStepsBetweenReportsRatio);
if( equilibrationStepsBetweenReports < 1 )equilibrationStepsBetweenReports = 1;
if( log ){
(void) fprintf( log, "equilibrationTotalSteps=%d equilibrationStepsBetweenReports=%d ratio=%.4f\n",
equilibrationTotalSteps, equilibrationStepsBetweenReports, equilibrationStepsBetweenReportsRatio);
(void) fflush( log );
}
while( currentStep < equilibrationTotalSteps ){
int nextStep = currentStep + equilibrationStepsBetweenReports;
if( nextStep > equilibrationTotalSteps ){
equilibrationStepsBetweenReports = equilibrationTotalSteps - currentStep;
}
// integrate
cpuTime = clock();
integrator->step(equilibrationStepsBetweenReports);
totalEquilibrationTime += clock() - cpuTime;
currentStep += equilibrationStepsBetweenReports;
// get energies, check for constraint violations and nans
State state = equilibrationContext->getState( State::Energy | State::Forces );
double kineticEnergy = state.getKineticEnergy();
double potentialEnergy = state.getPotentialEnergy();
double totalEnergy = kineticEnergy + potentialEnergy;
double maxViolation;
int violations = checkConstraints( *equilibrationContext, system, equilibrationShakeTolerance, &maxViolation, log );
constraintViolations += violations;
constraintChecks++;
if( log ){
(void) fprintf( log, "Equilibration: %6d KE=%14.7e PE=%14.7e E=%14.7e violations=%6d max=%13.6e totalViolation=%6d\n",
currentStep, kineticEnergy, potentialEnergy, totalEnergy, violations, maxViolation, constraintViolations );
(void) fflush( log );
}
// compare reference and gpu forces, if violations found
if( violations && log ){
checkForcesDuringSimulation( currentStep, *equilibrationContext, context, log );
}
// output context?
if( equilibrationWriteContext ){
std::stringstream fileName;
fileName << "EquilCnxt_" << runId << "_" << currentStep << ".txt";
writeContextToFile( fileName.str(), *equilibrationContext, (State::Positions | State::Velocities | State::Forces | State::Energy), log );
}
// nans
if( isinf( totalEnergy ) || isnan( totalEnergy ) ){
char buffer[1024];
(void) sprintf( buffer, "%s Equilibration: nans detected at step %d -- aborting.\n", methodName.c_str(), currentStep );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
double kineticEnergy;
double potentialEnergy;
double totalEnergy;
// report energies
if( log ){
State state = equilibrationContext->getState( State::Energy );
kineticEnergy = state.getKineticEnergy();
potentialEnergy = state.getPotentialEnergy();
totalEnergy = kineticEnergy + potentialEnergy;
double totalTime = static_cast(totalEquilibrationTime)/static_cast(CLOCKS_PER_SEC);
double timePerStep = totalTime/static_cast(equilibrationTotalSteps);
double timePerStepPerAtom = timePerStep/static_cast(numberOfAtoms);
(void) fprintf( log, "Final Equilibration energies: %6d E=%14.7e [%14.7e %14.7e] cpu time=%.3f time/step=%.3e time/step/atom=%.3e\n",
currentStep, (kineticEnergy + potentialEnergy), kineticEnergy, potentialEnergy,
totalTime, timePerStep, timePerStepPerAtom );
(void) fflush( log );
}
// get simulation integrator & context
Integrator* simulationIntegrator = _getIntegrator( simulationIntegratorName, simulationTimeStep,
simulationFriction, simulationTemperature,
simulationShakeTolerance, simulationErrorTolerance,
simulationSeed, log );
if( log ){
_printIntegratorInfo( simulationIntegrator, log );
}
//delete equilibrationContext;
Context* simulationContext = _getContext( &system, equilibrationContext, simulationIntegrator, "CudaPlatform", "SimulationContext", deviceId, log );
//Context* simulationContext = _getContext( &system, equilibrationContext, simulationIntegrator, "ReferencePlatform", "SimulationContext", deviceId, log );
//Context* simulationContext = equilibrationContext;
//Context* simulationContext = _getContext( &system, &context, simulationIntegrator, "CudaPlatform", "SimulationContext", deviceId, log );
//Context* simulationContext = _getContext( &system, &context, simulationIntegrator, "ReferencePlatform", "SimulationContext", deviceId, log );
//Context* simulationContext = _getContext( &system, &context, simulationIntegrator, "ReferencePlatform", "SimulationContext", deviceId, log );
// create/initialize arrays used to track energies
std::vector stepIndexArray;
std::vector kineticEnergyArray;
std::vector potentialEnergyArray;
std::vector totalEnergyArray;
State state = simulationContext->getState( State::Energy );
kineticEnergy = state.getKineticEnergy();
potentialEnergy = state.getPotentialEnergy();
totalEnergy = kineticEnergy + potentialEnergy;
stepIndexArray.push_back( 0.0 );
kineticEnergyArray.push_back( kineticEnergy );
potentialEnergyArray.push_back( potentialEnergy );
totalEnergyArray.push_back( totalEnergy );
// log
if( log ){
(void) fprintf( log, "Initial Simulation energies: E=%14.7e [%14.7e %14.7e]\n",
(kineticEnergy + potentialEnergy), kineticEnergy, potentialEnergy );
(void) fflush( log );
}
/* -------------------------------------------------------------------------------------------------------------- */
// prelude for simulation
int simulationStepsBetweenReports = static_cast(static_cast(simulationTotalSteps)*simulationStepsBetweenReportsRatio);
if( simulationStepsBetweenReports < 1 )simulationStepsBetweenReports = 1;
currentStep = 0;
if( log ){
(void) fprintf( log, "simulationTotalSteps=%d simulationStepsBetweenReports=%d ratio=%.4f\n",
simulationTotalSteps, simulationStepsBetweenReports, simulationStepsBetweenReportsRatio );
(void) fflush( log );
}
// write initial context
if( simulationWriteContext ){
std::stringstream fileName;
fileName << "SimulCnxt_" << runId << "_" << currentStep << ".txt";
writeContextToFile( fileName.str(), *simulationContext, (State::Positions | State::Velocities | State::Forces | State::Energy), log );
}
// main simulation loop
while( currentStep < simulationTotalSteps ){
// set step increment, perform integration, update step
int nextStep = currentStep + simulationStepsBetweenReports;
if( nextStep > simulationTotalSteps ){
simulationStepsBetweenReports = simulationTotalSteps - currentStep;
}
cpuTime = clock();
simulationIntegrator->step( simulationStepsBetweenReports );
totalSimulationTime += clock() - cpuTime;
currentStep += simulationStepsBetweenReports;
// record energies
State state = simulationContext->getState( State::Energy );
double kineticEnergy = state.getKineticEnergy();
double potentialEnergy = state.getPotentialEnergy();
double totalEnergy = kineticEnergy + potentialEnergy;
double maxViolation;
int violations = checkConstraints( *simulationContext, system, simulationShakeTolerance, &maxViolation, log );
constraintViolations += violations;
constraintChecks++;
stepIndexArray.push_back( (double) currentStep );
kineticEnergyArray.push_back( kineticEnergy );
potentialEnergyArray.push_back( potentialEnergy );
totalEnergyArray.push_back( totalEnergy );
// diagnostics & check for nans
if( log ){
(void) fprintf( log, "Simulation: %6d KE=%14.7e PE=%14.7e E=%14.7e violations=%6d max=%13.6e totalViolation=%6d\n",
currentStep, kineticEnergy, potentialEnergy, totalEnergy, violations, maxViolation, constraintViolations );
(void) fflush( log );
}
if( violations && log ){
checkForcesDuringSimulation( currentStep, *simulationContext, context, log );
}
// output context?
if( simulationWriteContext ){
std::stringstream fileName;
fileName << "SimulCnxt_" << runId << "_" << currentStep << ".txt";
writeContextToFile( fileName.str(), *simulationContext, (State::Positions | State::Velocities | State::Forces | State::Energy), log );
}
// check nans
if( isinf( totalEnergy ) || isnan( totalEnergy ) ){
char buffer[1024];
(void) sprintf( buffer, "%s Simulation: nans detected at step %d -- aborting.\n", methodName.c_str(), currentStep );
throwException(__FILE__, __LINE__, buffer );
exit(-1);
}
}
state = simulationContext->getState( State::Energy );
kineticEnergy = state.getKineticEnergy();
potentialEnergy = state.getPotentialEnergy();
totalEnergy = kineticEnergy + potentialEnergy;
// log times and energies
if( log ){
double totalTime = static_cast(totalSimulationTime)/static_cast(CLOCKS_PER_SEC);
double timePerStep = totalTime/static_cast(simulationTotalSteps);
double timePerStepPerAtom = timePerStep/static_cast(numberOfAtoms);
(void) fprintf( log, "Final Simulation: %6d E=%14.7e [%14.7e %14.7e] cpu time=%.3f time/step=%.3e time/step/atom=%.3e\n",
currentStep, (kineticEnergy + potentialEnergy), kineticEnergy, potentialEnergy,
totalTime, timePerStep, timePerStepPerAtom );
(void) fflush( log );
}
// set dof
double degreesOfFreedom = static_cast(3*numberOfAtoms - system.getNumConstraints() - 3 );
double conversionFactor = degreesOfFreedom*0.5*BOLTZ;
conversionFactor = 1.0/conversionFactor;
if( summaryFile ){
(void) fprintf( summaryFile, "Platform %s\nIntegrator %s\nSteps %d\nTimeStepSize %14.7e\nAtoms %d\n",
// crashes???
// simulationContext->getPlatform().getName().c_str(),
"Cuda", simulationIntegratorName.c_str(), simulationTotalSteps, simulationTimeStep, numberOfAtoms );
}
// if Langevin or Brownian integrator, then check that temperature constant
// else (Verlet integrator) check that energy drift is acceptable
if( (simulationIntegratorName.compare( "LangevinIntegrator" ) == 0 ||
simulationIntegratorName.compare( "VariableLangevinIntegrator" ) == 0 ||
simulationIntegratorName.compare( "BrownianIntegrator" ) == 0) && numberOfAtoms > 0 ){
// check that temperature constant
// convert KE to temperature
std::vector temperature;
for( std::vector::const_iterator ii = kineticEnergyArray.begin(); ii != kineticEnergyArray.end(); ii++ ){
temperature.push_back( (*ii)*conversionFactor );
}
// get temperature stats
std::vector temperatureStatistics;
_getStatistics( temperature, temperatureStatistics );
if( log ){
(void) fprintf( log, "Simulation temperature results: mean=%14.7e stddev=%14.7e min=%14.7e %d max=%14.7e %d\n",
temperatureStatistics[0], temperatureStatistics[1], temperatureStatistics[2],
(int) (temperatureStatistics[3] + 0.001), temperatureStatistics[4],
(int) (temperatureStatistics[5] + 0.001) );
}
// summary info
if( summaryFile ){
double totalTime = static_cast(totalSimulationTime)/static_cast(CLOCKS_PER_SEC);
double timePerStep = totalTime/static_cast(simulationTotalSteps);
(void) fprintf( summaryFile, "T %14.7e\nCalcT %14.7e\nStddevT %14.7e\nMinT %14.7e\nMaxT %14.7e\n",
simulationTemperature, temperatureStatistics[0], temperatureStatistics[1], temperatureStatistics[2],
temperatureStatistics[4] );
}
// check that is within tolerance
if( applyAssertion ){
ASSERT_EQUAL_TOL( temperatureStatistics[0], simulationTemperature, temperatureTolerance );
}
} else {
// total energy constant
std::vector statistics;
_getStatistics( totalEnergyArray, statistics );
std::vector kineticEnergyStatistics;
_getStatistics( kineticEnergyArray, kineticEnergyStatistics );
double temperature = kineticEnergyStatistics[0]*conversionFactor;
double kT = temperature*BOLTZ;
// compute stddev in units of kT/dof/ns
double stddevE = statistics[1]/kT;
stddevE /= degreesOfFreedom;
stddevE /= simulationTotalSteps*simulationTimeStep*0.001;
if( log ){
(void) fprintf( log, "Simulation results: mean=%14.7e stddev=%14.7e kT/dof/ns=%14.7e kT=%14.7e min=%14.7e %d max=%14.7e %d\n",
statistics[0], statistics[1], stddevE, kT, statistics[2], (int) (statistics[3] + 0.001), statistics[4], (int) (statistics[5] + 0.001) );
}
// summary info
if( summaryFile ){
double totalTime = static_cast(totalSimulationTime)/static_cast(CLOCKS_PER_SEC);
double timePerStep = totalTime/static_cast(simulationTotalSteps);
(void) fprintf( summaryFile, "DriftE %14.7e\nAvgE %14.7e\nStddevE %14.7e\n"
"Dof %d\nMinE %14.7e\nMinE_Idx %d\nMaxE %14.7e\nMax_E_Idx %d\n",
stddevE, // drift
statistics[0], statistics[1], // mean & stddev
(3*numberOfAtoms - system.getNumConstraints() - 3), // dof
statistics[2], (int) (statistics[3] + 0.001), // min & index
statistics[4], (int) (statistics[5] + 0.001) ); // max index
}
// check that energy fluctuation is within tolerance
if( applyAssertion ){
ASSERT_EQUAL_TOL( stddevE, 0.0, energyTolerance );
}
}
// summary info
if( summaryFile ){
double totalTime = static_cast(totalSimulationTime)/static_cast(CLOCKS_PER_SEC);
double timePerStep = totalTime/static_cast(simulationTotalSteps);
(void) fprintf( summaryFile, "ConstraintViolations %d\nConstraintChecks %d\nWallTime %.3e\nWallTimePerStep %.3e\n",
constraintViolations, constraintChecks, totalTime, timePerStep );
(void) fclose( summaryFile );
}
if( applyAssertion && log ){
(void) fprintf( log, "\n%s passed\n", methodName.c_str() );
(void) fflush( log );
}
return returnStatus;
}
/**---------------------------------------------------------------------------------------
Create context using content in parameter file (parameters/coordinates/velocities)
@param parameterFileName parameter file name
@param forceFlag flag controlling which forces are to be included
@param platform platform reference
@param log FILE ptr; if NULL, diagnostic messages are not printed
@return context
--------------------------------------------------------------------------------------- */
Context* testSetup( std::string parameterFileName, MapStringInt& forceMap, Platform& platform, std::vector& forces,
double* kineticEnergy, double* potentialEnergy, MapStringVectorOfVectors& supplementary,
MapStringString& inputArgumentMap, FILE* log ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "testSetup";
double timeStep = 0.001;
double constraintTolerance = 1.0e-05;
// ---------------------------------------------------------------------------------------
System* system = new System();
std::vector coordinates;
std::vector velocities;
// read parameters into system and coord/velocities into appropriate arrays
Integrator* integrator =
readParameterFile( parameterFileName, forceMap, *system, coordinates, velocities,
forces, kineticEnergy, potentialEnergy, supplementary, inputArgumentMap, log );
Context* context;
context = new Context( *system, *integrator, platform);
StringVector forceStringArray;
getForceStrings( *system, forceStringArray, log );
if( log ){
(void) fprintf( log, "\n%s Active Forces:\n", methodName.c_str() );
for( StringVectorCI ii = forceStringArray.begin(); ii != forceStringArray.end(); ii++ ){
(void) fprintf( log, " %s\n", (*ii).c_str() );
}
(void) fflush( log );
}
// read context if present in inputArgumentMap
MapStringStringI readContext = inputArgumentMap.find( "readContext" );
if( readContext != inputArgumentMap.end() ){
readContextFromFile( (*readContext).second, *context, (State::Positions | State::Velocities), log );
} else {
context->setPositions( coordinates );
context->setVelocities( velocities );
}
return context;
}
void testReferenceCudaForces( std::string parameterFileName, MapStringInt& forceMap,
MapStringString& inputArgumentMap, FILE* inputLog, FILE* summaryFile ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "testReferenceCudaForces";
int PrintOn = 1;
int compareParameterForces = 0;
double forceTolerance = 0.01;
double energyTolerance = 0.01;
int numberOfSteps = 1;
int steps = 0;
int applyAssertion = 1;
// ---------------------------------------------------------------------------------------
FILE* log;
if( PrintOn == 0 && inputLog ){
log = NULL;
} else {
log = inputLog;
}
setIntFromMap( inputArgumentMap, "applyAssertion", applyAssertion );
if( log ){
(void) fprintf( log, "%s force tolerance=%.3e energy tolerance=%.3e step=%d\n",
methodName.c_str(), forceTolerance, energyTolerance, numberOfSteps );
(void) fflush( log );
}
Platform& referencePlatform = Platform::getPlatform("Reference");
Platform& cudaPlatform = Platform::getPlatform("Cuda");;
double parameterKineticEnergy, parameterPotentialEnergy;
std::vector parameterForces;
std::vector parameterForces2;
MapStringVectorOfVectors supplementary;
Context* referenceContext = testSetup( parameterFileName, forceMap, referencePlatform,
parameterForces, ¶meterKineticEnergy, ¶meterPotentialEnergy,
supplementary, inputArgumentMap, log );
Context* cudaContext = testSetup( parameterFileName, forceMap, cudaPlatform,
parameterForces2, ¶meterKineticEnergy, ¶meterPotentialEnergy,
supplementary, inputArgumentMap, log );
Integrator& referenceIntegrator = referenceContext->getIntegrator();
Integrator& cudaIntegrator = cudaContext->getIntegrator();
// Run several steps and see if relative force difference is within tolerance
int includeEnergy = 1;
for( int step = 0; step < numberOfSteps; step++ ){
// pull info out of contexts
int types = State::Positions | State::Velocities | State::Forces;
if( includeEnergy ){
types |= State::Energy;
}
State cudaState = cudaContext->getState( types );
State referenceState = referenceContext->getState( types );
std::vector referenceCoordinates = referenceState.getPositions();
std::vector referenceVelocities = referenceState.getVelocities();
std::vector referenceForces = referenceState.getForces();
double referenceKineticEnergy;
double referencePotentialEnergy;
if( includeEnergy ){
referenceKineticEnergy = referenceState.getKineticEnergy();
referencePotentialEnergy = referenceState.getPotentialEnergy();
} else {
referenceKineticEnergy = 0.0;
referencePotentialEnergy = 0.0;
}
std::vector cudaCoordinates = cudaState.getPositions();
std::vector cudaVelocities = cudaState.getVelocities();
std::vector cudaForces = cudaState.getForces();
double cudaKineticEnergy = cudaState.getKineticEnergy();
double cudaPotentialEnergy = cudaState.getPotentialEnergy();
if( includeEnergy ){
cudaKineticEnergy = cudaState.getKineticEnergy();
cudaPotentialEnergy = cudaState.getPotentialEnergy();
} else {
cudaKineticEnergy = 0.0;
cudaPotentialEnergy = 0.0;
}
// diagnostics
if( log ){
//static const unsigned int maxPrint = MAX_PRINT;
static const unsigned int maxPrint = 1000000;
// print x,y,z components separately, if formatType == 1
// else print reference, cuda and parameter forces in blocks of 3
static const unsigned int formatType = 1;
(void) fprintf( log, "%s\n", methodName.c_str() );
if( compareParameterForces ){
(void) fprintf( log, "Kinetic energies: r=%14.7e c=%14.7e, p=%14.7e\n", referenceKineticEnergy, cudaKineticEnergy, parameterKineticEnergy );
(void) fprintf( log, "Potential energies: r=%14.7e c=%14.7e, p=%14.7e\n", referencePotentialEnergy, cudaPotentialEnergy, parameterPotentialEnergy );
(void) fprintf( log, "Sample of forces: %u (r=reference, c=cuda, p=parameter) file forces\n", referenceForces.size() );
} else {
(void) fprintf( log, "Kinetic energies: r=%14.7e c=%14.7e\n", referenceKineticEnergy, cudaKineticEnergy );
(void) fprintf( log, "Potential energies: r=%14.7e c=%14.7e\n", referencePotentialEnergy, cudaPotentialEnergy );
(void) fprintf( log, "Sample of forces: %u (r=reference, c=cuda) file forces\n", referenceForces.size() );
}
if( formatType == 1 ){
(void) fprintf( log, "%s: atoms=%d [reference, cuda %s]\n", methodName.c_str(), referenceForces.size(), (compareParameterForces ? ", parameter" : "") );
if( compareParameterForces ){
for( unsigned int ii = 0; ii < referenceForces.size(); ii++ ){
(void) fprintf( log, "%6u 0[%14.7e %14.7e %14.7e] 1[%14.7e %14.7e %14.7e] 2[%14.7e %14.7e %14.7e]\n", ii,
referenceForces[ii][0], cudaForces[ii][0], parameterForces[ii][0],
referenceForces[ii][1], cudaForces[ii][1], parameterForces[ii][1],
referenceForces[ii][2], cudaForces[ii][2], parameterForces[ii][2] );
if( ii == maxPrint ){
ii = referenceForces.size()- maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
} else {
for( unsigned int ii = 0; ii < referenceForces.size(); ii++ ){
(void) fprintf( log, "%6u 0[%14.7e %14.7e] 1[%14.7e %14.7e] 2[%14.7e %14.7e]\n", ii,
referenceForces[ii][0], cudaForces[ii][0],
referenceForces[ii][1], cudaForces[ii][1],
referenceForces[ii][2], cudaForces[ii][2] );
if( ii == maxPrint ){
ii = referenceForces.size() - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
} else {
if( compareParameterForces ){
for( unsigned int ii = 0; ii < referenceForces.size(); ii++ ){
(void) fprintf( log, "%6u r[%14.7e %14.7e %14.7e] c[%14.7e %14.7e %14.7e] p[%14.7e %14.7e %14.7e]\n", ii,
referenceForces[ii][0], referenceForces[ii][1], referenceForces[ii][2],
cudaForces[ii][0], cudaForces[ii][1], cudaForces[ii][2],
parameterForces[ii][0], parameterForces[ii][1], parameterForces[ii][2] );
if( ii == maxPrint ){
ii = referenceForces.size() - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
} else {
for( unsigned int ii = 0; ii < referenceForces.size(); ii++ ){
(void) fprintf( log, "%6u r[%14.7e %14.7e %14.7e] c[%14.7e %14.7e %14.7e]\n", ii,
referenceForces[ii][0], referenceForces[ii][1], referenceForces[ii][2],
cudaForces[ii][0], cudaForces[ii][1], cudaForces[ii][2] );
if( ii == maxPrint ){
ii = referenceForces.size() - maxPrint;
if( ii < maxPrint )ii = maxPrint;
}
}
}
}
}
// compare reference vs cuda forces
double maxDeltaRefCud = -1.0e+30;
double maxRelativeDeltaRefCud = -1.0e+30;
double maxDotRefCud = -1.0e+30;
double maxDeltaPrmCud = -1.0e+30;
double maxRelativeDeltaPrmCud = -1.0e+30;
double maxDotPrmCud = -1.0e+30;
int maxDeltaIndex;
int maxRelativeDeltaRefCudIndex;
std::vector forceArray1Sum;
std::vector forceArray2Sum;
std::vector forceArray3Sum;
std::vector referenceForceStats;
std::vector cudaForceStats;
std::vector cudaForceStats1;
std::vector paramForceStats;
compareForces( referenceForces, "fRef", forceArray1Sum, referenceForceStats,
cudaForces, "fCud", forceArray2Sum, cudaForceStats,
&maxDeltaRefCud, &maxDeltaIndex, &maxRelativeDeltaRefCud,
&maxRelativeDeltaRefCudIndex, &maxDotRefCud, forceTolerance, log );
(void) fflush( log );
if( compareParameterForces ){
// compare cuda & forces retreived from parameter file
/*
compareForces( parameterForces, "fPrm", forceArray3Sum, paramForceStats,
cudaForces, "fCud", forceArray2Sum, cudaForceStats1,
&maxDeltaPrmCud, &maxRelativeDeltaPrmCud, &maxDotPrmCud, forceTolerance, log );
*/
}
// summary file info
if( summaryFile ){
StringVector forceStringArray;
System system = referenceContext->getSystem();
getForceStrings( system, forceStringArray, log );
std::string forceString;
if( forceStringArray.size() > 5 ){
forceString = "All";
} else {
for( StringVectorCI ii = forceStringArray.begin(); ii != forceStringArray.end(); ii++ ){
forceString += *ii;
}
}
if( forceString.size() < 1 ){
forceString = "NA";
}
(void) fprintf( summaryFile, "Force %s\nAtoms %u\nMaxDelta %14.7e\nMaxRelDelta %14.7e\nMaxDot %14.7e\n",
forceString.c_str(), referenceForces.size(), maxDeltaRefCud, maxRelativeDeltaRefCud, maxDotRefCud);
double sum = ( fabs(forceArray1Sum[0] ) + fabs( forceArray1Sum[1] ) + fabs( forceArray1Sum[2]) )*0.33333;
(void) fprintf( summaryFile, "SumRef %14.7e\n", sum );
sum = ( fabs(forceArray2Sum[0] ) + fabs( forceArray2Sum[1] ) + fabs( forceArray2Sum[2]) )*0.33333;
(void) fprintf( summaryFile, "SumCuda %14.7e\n", sum );
double difference = fabs( referencePotentialEnergy - cudaPotentialEnergy );
double relativeDifference = difference/( fabs( referencePotentialEnergy ) + fabs( cudaPotentialEnergy ) + 1.0e-10);
(void) fprintf( summaryFile, "RefPE %14.7e\nCudaPE %14.7e\nDiffPE %14.7e\nRelDiffPE %14.7e\n",
referencePotentialEnergy, cudaPotentialEnergy, difference, relativeDifference );
}
if( log ){
(void) fprintf( log, "max delta=%13.7e at %d maxRelDelta=%13.7e at %d maxDot=%14.7e\n",
maxDeltaRefCud, maxDeltaIndex, maxRelativeDeltaRefCud, maxRelativeDeltaRefCudIndex, maxDotRefCud );
(void) fprintf( log, "Reference force sum [%14.7e %14.7e %14.7e]\n", forceArray1Sum[0], forceArray1Sum[1], forceArray1Sum[2] );
(void) fprintf( log, "Cuda force sum [%14.7e %14.7e %14.7e]\n", forceArray2Sum[0], forceArray2Sum[1], forceArray2Sum[2] );
if( compareParameterForces ){
(void) fprintf( log, "Parameter force sum [%14.7e %14.7e %14.7e]\n", forceArray3Sum[0], forceArray3Sum[1], forceArray3Sum[2] );
}
(void) fprintf( log, "Reference force average=%14.7e stddev=%14.7e min=%14.7e at %6.0f max=%14.7e at %6.0f\n",
referenceForceStats[0], referenceForceStats[1], referenceForceStats[2], referenceForceStats[3],
referenceForceStats[4], referenceForceStats[5] );
(void) fprintf( log, " Cuda force average=%14.7e stddev=%14.7e min=%14.7e at %6.0f max=%14.7e at %6.0f\n",
cudaForceStats[0], cudaForceStats[1], cudaForceStats[2], cudaForceStats[3],
cudaForceStats[4], cudaForceStats[5] );
if( compareParameterForces ){
(void) fprintf( log, " Param force average=%14.7e stddev=%14.7e min=%14.7e at %6.0f max=%14.7e at %6.0f\n",
paramForceStats[0], paramForceStats[1], paramForceStats[2], paramForceStats[3],
paramForceStats[4], paramForceStats[5] );
}
(void) fflush( log );
}
// check that relative force difference is small
if( applyAssertion ){
ASSERT( maxRelativeDeltaRefCud < forceTolerance );
// check energies
ASSERT_EQUAL_TOL( referenceKineticEnergy, cudaKineticEnergy, energyTolerance );
ASSERT_EQUAL_TOL( referencePotentialEnergy, cudaPotentialEnergy, energyTolerance );
if( compareParameterForces ){
ASSERT_EQUAL_TOL( referencePotentialEnergy, parameterPotentialEnergy, energyTolerance );
}
}
/*
double energy = state.getKineticEnergy()+state.getPotentialEnergy();
if( PrintOn > 1 ){
(void) fprintf( log, "%s %d e[%.5e %.5e] ke=%.5e pe=%.5e\n",
methodName.c_str(), i, initialEnergy, energy, state.getKineticEnergy(), state.getPotentialEnergy() ); (void) fflush( log );
}
if( i == 1 ){
initialEnergy = energy;
} else if( i > 1 ){
ASSERT_EQUAL_TOL(initialEnergy, energy, 0.5);
}
*/
if( steps ){
cudaIntegrator.step( steps );
_synchContexts( *cudaContext, *referenceContext );
}
}
if( log ){
if( applyAssertion ){
(void) fprintf( log, "\n%s tests passed\n", methodName.c_str() );
} else {
(void) fprintf( log, "\n%s tests off\n", methodName.c_str() );
}
(void) fflush( log );
}
}
void testInputForces( std::string parameterFileName, MapStringInt& forceMap,
MapStringString& inputArgumentMap, FILE* inputLog, FILE* summaryFile ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "testInputForces";
int PrintOn = 1;
int compareParameterForces = 0;
double forceTolerance = 0.01;
double energyTolerance = 0.01;
int numberOfSteps = 1;
int steps = 0;
int applyAssertion = 1;
std::string inputForceToCompare;
// ---------------------------------------------------------------------------------------
FILE* log;
if( PrintOn == 0 && inputLog ){
log = NULL;
} else {
log = inputLog;
}
setIntFromMap( inputArgumentMap, "applyAssertion", applyAssertion );
if( setStringFromMap( inputArgumentMap, "inputForceToCompare", inputForceToCompare ) == 0 ){
if( log ){
(void) fprintf( log, "%s inputForceToCompare field not set.\n", methodName.c_str() );
(void) fflush( log );
}
return;
}
if( log ){
(void) fprintf( log, "%s force tolerance=%.3e energy tolerance=%.3e step=%d\n",
methodName.c_str(), forceTolerance, energyTolerance, numberOfSteps );
(void) fflush( log );
}
ReferencePlatform referencePlatform;
double parameterKineticEnergy, parameterPotentialEnergy;
std::vector parameterForces;
std::vector parameterForces2;
MapStringVectorOfVectors supplementary;
Context* referenceContext = testSetup( parameterFileName, forceMap, referencePlatform,
parameterForces, ¶meterKineticEnergy, ¶meterPotentialEnergy,
supplementary, inputArgumentMap, log );
MapStringVectorOfVectorsI forceVectorI = supplementary.find( inputForceToCompare );
if( forceVectorI == supplementary.end() ){
if( log ){
(void) fprintf( log, "%s inputForceToCompare=<%s> is missing.\n", methodName.c_str(), inputForceToCompare.c_str() );
(void) fflush( log );
}
return;
}
VectorOfVectors forceVectorToCompare = (*forceVectorI).second;
Integrator& referenceIntegrator = referenceContext->getIntegrator();
// Run several steps and see if relative force difference is within tolerance
#if 0
for( int step = 0; step < numberOfSteps; step++ ){
// pull info out of contexts
int types = State::Positions | State::Velocities | State::Forces | State::Energy;
State referenceState = referenceContext->getState( types );
std::vector referenceCoordinates = referenceState.getPositions();
std::vector referenceVelocities = referenceState.getVelocities();
std::vector referenceForces = referenceState.getForces();
double referenceKineticEnergy = referenceState.getKineticEnergy();
double referencePotentialEnergy = referenceState.getPotentialEnergy();
// diagnostics
if( log ){
//static const unsigned int maxPrint = MAX_PRINT;
static const unsigned int maxPrint = 1000000;
// print x,y,z components separately, if formatType == 1
// else print reference, cuda and parameter forces in blocks of 3
static const unsigned int formatType = 1;
(void) fprintf( log, "%s\n", methodName.c_str() );
#if 0
if( compareParameterForces ){
(void) fprintf( log, "Kinetic energies: r=%14.7e c=%14.7e, p=%14.7e\n", referenceKineticEnergy, cudaKineticEnergy, parameterKineticEnergy );
(void) fprintf( log, "Potential energies: r=%14.7e c=%14.7e, p=%14.7e\n", referencePotentialEnergy, cudaPotentialEnergy, parameterPotentialEnergy );
(void) fprintf( log, "Sample of forces: %u (r=reference, c=cuda, p=parameter) file forces\n", referenceForces.size() );
} else {
(void) fprintf( log, "Kinetic energies: r=%14.7e c=%14.7e\n", referenceKineticEnergy, cudaKineticEnergy );
(void) fprintf( log, "Potential energies: r=%14.7e c=%14.7e\n", referencePotentialEnergy, cudaPotentialEnergy );
(void) fprintf( log, "Sample of forces: %u (r=reference, c=cuda) file forces\n", referenceForces.size() );
}
#endif
for( unsigned int ii = 0; ii < referenceForces.size() && ii < maxPrint; ii++ ){
(void) fprintf( log, "%6u 0[%14.7e %14.7e] 1[%14.7e %14.7e] 2[%14.7e %14.7e]\n", ii,
referenceForces[ii][0], forceVectorToCompare[ii][0],
referenceForces[ii][1], forceVectorToCompare[ii][1],
referenceForces[ii][2], forceVectorToCompare[ii][2] );
}
if( referenceForces.size() > maxPrint ){
for( unsigned int ii = referenceForces.size() - maxPrint; ii < referenceForces.size(); ii++ ){
(void) fprintf( log, "%6u 0[%14.7e %14.7e] 1[%14.7e %14.7e] 2[%14.7e %14.7e]\n", ii,
referenceForces[ii][0], forceVectorToCompare[ii][0],
referenceForces[ii][1], forceVectorToCompare[ii][1],
referenceForces[ii][2], forceVectorToCompare[ii][2] );
}
}
} else {
for( unsigned int ii = 0; ii < referenceForces.size() && ii < maxPrint; ii++ ){
(void) fprintf( log, "%6u r[%14.7e %14.7e %14.7e] c[%14.7e %14.7e %14.7e]\n", ii,
referenceForces[ii][0], referenceForces[ii][1], referenceForces[ii][2],
forceVectorToCompare[ii][0], forceVectorToCompare[ii][1], forceVectorToCompare[ii][2] );
}
if( referenceForces.size() > maxPrint ){
for( unsigned int ii = referenceForces.size() - maxPrint; ii < referenceForces.size(); ii++ ){
(void) fprintf( log, "%6u r[%14.7e %14.7e %14.7e] c[%14.7e %14.7e %14.7e]\n", ii,
referenceForces[ii][0], referenceForces[ii][1], referenceForces[ii][2],
forceVectorToCompare[ii][0], forceVectorToCompare[ii][1], forceVectorToCompare[ii][2] );
}
}
}
}
#endif
// compare reference vs cuda forces
#if 0
double maxDeltaRefCud = -1.0e+30;
double maxRelativeDeltaRefCud = -1.0e+30;
double maxDotRefCud = -1.0e+30;
double maxDeltaPrmCud = -1.0e+30;
double maxRelativeDeltaPrmCud = -1.0e+30;
double maxDotPrmCud = -1.0e+30;
std::vector forceArray1Sum;
std::vector forceArray2Sum;
std::vector forceArray3Sum;
std::vector referenceForceStats;
std::vector cudaForceStats;
std::vector cudaForceStats1;
std::vector paramForceStats;
compareForces( referenceForces, "fRef", forceArray1Sum, referenceForceStats,
forceVectorToCompare, "fCud", forceArray2Sum, cudaForceStats,
&maxDeltaRefCud, &maxRelativeDeltaRefCud, &maxDotRefCud, forceTolerance, log );
(void) fflush( log );
// summary file info
if( summaryFile ){
StringVector forceStringArray;
System system = referenceContext->getSystem();
getForceStrings( system, forceStringArray, log );
std::string forceString;
if( forceStringArray.size() > 5 ){
forceString = "All";
} else {
for( StringVectorCI ii = forceStringArray.begin(); ii != forceStringArray.end(); ii++ ){
forceString += *ii;
}
}
if( forceString.size() < 1 ){
forceString = "NA";
}
(void) fprintf( summaryFile, "Force %s\nAtoms %u\nMaxDelta %14.7e\nMaxRelDelta %14.7e\nMaxDot %14.7e\n",
forceString.c_str(), referenceForces.size(), maxDeltaRefCud, maxRelativeDeltaRefCud, maxDotRefCud);
double sum = ( fabs(forceArray1Sum[0] ) + fabs( forceArray1Sum[1] ) + fabs( forceArray1Sum[2]) )*0.33333;
(void) fprintf( summaryFile, "SumRef %14.7e\n", sum );
sum = ( fabs(forceArray2Sum[0] ) + fabs( forceArray2Sum[1] ) + fabs( forceArray2Sum[2]) )*0.33333;
(void) fprintf( summaryFile, "SumCuda %14.7e\n", sum );
double difference = fabs( referencePotentialEnergy - cudaPotentialEnergy );
double relativeDifference = difference/( fabs( referencePotentialEnergy ) + fabs( cudaPotentialEnergy ) + 1.0e-10);
(void) fprintf( summaryFile, "RefPE %14.7e\nCudaPE %14.7e\nDiffPE %14.7e\nRelDiffPE %14.7e\n",
referencePotentialEnergy, cudaPotentialEnergy, difference, relativeDifference );
}
if( log ){
(void) fprintf( log, "max delta=%14.7e maxRelDelta=%14.7e maxDot=%14.7e\n", maxDeltaRefCud, maxRelativeDeltaRefCud, maxDotRefCud);
(void) fprintf( log, "Reference force sum [%14.7e %14.7e %14.7e]\n", forceArray1Sum[0], forceArray1Sum[1], forceArray1Sum[2] );
(void) fprintf( log, "Cuda force sum [%14.7e %14.7e %14.7e]\n", forceArray2Sum[0], forceArray2Sum[1], forceArray2Sum[2] );
if( compareParameterForces ){
(void) fprintf( log, "Parameter force sum [%14.7e %14.7e %14.7e]\n", forceArray3Sum[0], forceArray3Sum[1], forceArray3Sum[2] );
}
(void) fprintf( log, "Reference force average=%14.7e stddev=%14.7e min=%14.7e at %6.0f max=%14.7e at %6.0f\n",
referenceForceStats[0], referenceForceStats[1], referenceForceStats[2], referenceForceStats[3],
referenceForceStats[4], referenceForceStats[5] );
(void) fprintf( log, " Cuda force average=%14.7e stddev=%14.7e min=%14.7e at %6.0f max=%14.7e at %6.0f\n",
cudaForceStats[0], cudaForceStats[1], cudaForceStats[2], cudaForceStats[3],
cudaForceStats[4], cudaForceStats[5] );
(void) fflush( log );
}
// check that relative force difference is small
if( applyAssertion ){
ASSERT( maxRelativeDeltaRefCud < forceTolerance );
// check energies
ASSERT_EQUAL_TOL( referenceKineticEnergy, cudaKineticEnergy, energyTolerance );
ASSERT_EQUAL_TOL( referencePotentialEnergy, cudaPotentialEnergy, energyTolerance );
if( compareParameterForces ){
ASSERT_EQUAL_TOL( referencePotentialEnergy, parameterPotentialEnergy, energyTolerance );
}
}
/*
double energy = state.getKineticEnergy()+state.getPotentialEnergy();
if( PrintOn > 1 ){
(void) fprintf( log, "%s %d e[%.5e %.5e] ke=%.5e pe=%.5e\n",
methodName.c_str(), i, initialEnergy, energy, state.getKineticEnergy(), state.getPotentialEnergy() ); (void) fflush( log );
}
if( i == 1 ){
initialEnergy = energy;
} else if( i > 1 ){
ASSERT_EQUAL_TOL(initialEnergy, energy, 0.5);
}
*/
if( steps ){
cudaIntegrator.step( steps );
_synchContexts( *cudaContext, *referenceContext );
}
}
if( log ){
if( applyAssertion ){
(void) fprintf( log, "\n%s tests passed\n", methodName.c_str() );
} else {
(void) fprintf( log, "\n%s tests off\n", methodName.c_str() );
}
(void) fflush( log );
}
#endif
}
void testEnergyForcesConsistent( std::string parameterFileName, MapStringInt& forceMap, MapStringString& inputArgumentMap,
FILE* inputLog, FILE* summaryFilePtr ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "testEnergyForcesConsistent";
int PrintOn = 1;
// ---------------------------------------------------------------------------------------
FILE* log;
if( PrintOn == 0 && inputLog ){
log = NULL;
} else {
log = inputLog;
}
if( log ){
(void) fprintf( log, "%s\n", methodName.c_str() );
(void) fflush( log );
}
// get platform to test (1=cuda, 2=reference)
std::string platformName;
int platformInclude = -1;
if( setStringFromMap( inputArgumentMap, "platform", platformName ) == 0 ){
if( log ){
(void) fprintf( log, "%s platform not set -- aborting.\n", methodName.c_str() );
(void) fflush( log );
}
return;
} else if( platformName.compare( "Cuda" ) == 0 ){
platformInclude = 1;
if( log ){
(void) fprintf( log, "%s Using Cuda platform.\n", methodName.c_str() );
}
} else if( platformName.compare( "Reference" ) == 0 ){
platformInclude = 2;
if( log ){
(void) fprintf( log, "%s Using Reference platform.\n", methodName.c_str() );
}
} else {
if( log ){
(void) fprintf( log, "%s platform name not recognized: %s (valid names are Cuda & Reference).\n", methodName.c_str(), platformName.c_str() );
(void) fflush( log );
}
return;
}
double parameterKineticEnergy, parameterPotentialEnergy;
std::vector parameterForces;
std::vector parameterForces2;
MapStringVectorOfVectors supplementary;
if( platformInclude == 1 ){
if( log ){
(void) fprintf( log, "%s Testing cuda platform\n", methodName.c_str() );
(void) fflush( log );
}
Platform& cudaPlatform = Platform::getPlatform( "Cuda");;
Context* cudaContext = testSetup( parameterFileName, forceMap, cudaPlatform,
parameterForces2, ¶meterKineticEnergy, ¶meterPotentialEnergy,
supplementary, inputArgumentMap, log );
checkEnergyForceConsistent( *cudaContext, inputArgumentMap, log, summaryFilePtr );
} else {
Platform& referencePlatform = Platform::getPlatform( "Reference");
if( log ){
(void) fprintf( log, "%s Testing reference platform\n", methodName.c_str() );
(void) fflush( log );
}
Context* referenceContext = testSetup( parameterFileName, forceMap, referencePlatform,
parameterForces, ¶meterKineticEnergy, ¶meterPotentialEnergy,
supplementary, inputArgumentMap, log );
checkEnergyForceConsistent( *referenceContext, inputArgumentMap, log, summaryFilePtr );
}
return;
}
void testEnergyConservation( std::string parameterFileName, MapStringInt& forceMap,
MapStringString& inputArgumentMap, FILE* inputLog, FILE* summaryFile ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "testEnergyConservation";
int PrintOn = 1;
// ---------------------------------------------------------------------------------------
FILE* log;
if( PrintOn == 0 && inputLog ){
log = NULL;
} else {
log = inputLog;
}
if( log ){
(void) fprintf( log, "%s\n", methodName.c_str() );
(void) fflush( log );
}
Platform& referencePlatform = Platform::getPlatform( "Reference");
double parameterKineticEnergy, parameterPotentialEnergy;
std::vector parameterForces;
std::vector parameterForces2;
MapStringVectorOfVectors supplementary;
Context* referenceContext = testSetup( parameterFileName, forceMap, referencePlatform,
parameterForces2, ¶meterKineticEnergy, ¶meterPotentialEnergy,
supplementary, inputArgumentMap, log );
if( log ){
(void) fprintf( log, "%s Testing cuda platform\n", methodName.c_str() );
(void) fflush( log );
}
checkEnergyConservation( *referenceContext, inputArgumentMap, log, summaryFile );
}
/**---------------------------------------------------------------------------------------
Print usage to screen and exit
@param defaultParameterFileName default parameter name
@return 0
--------------------------------------------------------------------------------------- */
int printUsage( std::string defaultParameterFileName ){
(void) printf( "Usage:\nTestCudaUsingParameterFile\n" );
(void) printf( " -help this message\n" );
(void) printf( " -log log info to stdout for now\n" );
(void) printf( " -logFileName (default=stdout)\n" );
(void) printf( " -summaryFileName (default=no summary)\n" );
(void) printf( " -applyAssertion if set, apply assertion (default=apply)\n" );
(void) printf( "\n" );
(void) printf( " -parameterFileName (default=%s)\n", defaultParameterFileName.c_str() );
(void) printf( "\n" );
(void) printf( " -checkEnergyForceConsistent do not check that force/energy are consistent\n" );
(void) printf( " +checkEnergyForceConsistent check that force/energy are consistent\n" );
(void) printf( " -delta is size of perturbation used in numerically calculating force in checkEnergyForceConsistent test\n" );
(void) printf( " default value is 1.0e-04\n" );
(void) printf( "\n" );
(void) printf( " -checkEnergyConservation do not check that energy conservation\n" );
(void) printf( " +checkEnergyForceConsistent check energy conservation\n" );
(void) printf( "\n" );
(void) printf( " -checkInputForces check that cuda/reference forces agree w/ input forces\n" );
(void) printf( "\n" );
(void) printf( " -checkForces do not check that cuda/reference forces agree\n" );
(void) printf( " +checkForces check that cuda/reference forces agree\n" );
(void) printf( " +all include all forces (typically followed by -force entries)\n" );
(void) printf( " -force cr +force where force equals\n" );
(void) printf( " HarmonicBond \n" );
(void) printf( " HarmonicAngle\n" );
(void) printf( " PeriodicTorsion\n" );
(void) printf( " RBTorsion\n" );
(void) printf( " NB\n" );
(void) printf( " NbExceptions\n" );
(void) printf( " GbsaObc\n" );
(void) printf( " Note: multiple force entries are allowed.\n" );
(void) printf( " +force adds in the force; -force removes the force\n" );
(void) printf( " The arguments are case-insensitive\n" );
(void) printf( " The defaults is to include all forces represented in parameter file.\n" );
(void) printf( " Examples:\n\n" );
(void) printf( " To include all forces but the GBSA Obc force:\n" );
(void) printf( " TestCudaUsingParameterFile -parameterFileName %s +all -GbsaObc\n\n", defaultParameterFileName.c_str() );
(void) printf( " To include only the harmonic bond force:\n" );
(void) printf( " TestCudaUsingParameterFile -parameterFileName %s +HarmonicBond\n\n", defaultParameterFileName.c_str() );
(void) printf( " To include only the bond forces:\n" );
(void) printf( " TestCudaUsingParameterFile -parameterFileName %s +HarmonicBond +HarmonicAngle +PeriodicTorsion +RBTorsion\n\n",
defaultParameterFileName.c_str() );
exit(0);
return 0;
}
/**---------------------------------------------------------------------------------------
* Return forceEnum value if input argument matches one of the
* force names (HarmonicBond, HarmonicAngle, ...
* The value returned is signed depending on whether the argument
* contained a + or - (+HarmonicBond or -HarmonicBond)
*
* @param inputArgument command-line argument
* @param forceEnum retrurn value
*
* @return 0 if argument is not a forceEnum argument
--------------------------------------------------------------------------------------- */
int getForceOffset( int argIndex, int maxArgs, char* inputArgument[], MapStringInt& forceMap ){
// skip over '-'
char* argument = inputArgument[argIndex];
argument++;
MapStringIntI forcePresent = forceMap.find( argument );
if( forcePresent != forceMap.end() && argIndex < maxArgs ){
(*forcePresent).second = atoi( inputArgument[argIndex+1] );
return 1;
}
return 0;
}
/**---------------------------------------------------------------------------------------
* Initialize forceMap
*
* @param forceMap has w/ force name as key and int as value
* @param initialValue initial value
*
*
--------------------------------------------------------------------------------------- */
void initializeForceMap( MapStringInt& forceMap, int initialValue ){
forceMap[HARMONIC_BOND_FORCE] = initialValue;
forceMap[HARMONIC_ANGLE_FORCE] = initialValue;
forceMap[PERIODIC_TORSION_FORCE] = initialValue;
forceMap[RB_TORSION_FORCE] = initialValue;
forceMap[NB_FORCE] = initialValue;
forceMap[NB_SOFTCORE_FORCE] = initialValue;
forceMap[NB_EXCEPTION_FORCE] = initialValue;
forceMap[NB_EXCEPTION_SOFTCORE_FORCE] = initialValue;
forceMap[GBSA_OBC_FORCE] = initialValue;
forceMap[GBSA_OBC_SOFTCORE_FORCE] = initialValue;
forceMap[GBVI_FORCE] = initialValue;
forceMap[GBVI_SOFTCORE_FORCE] = initialValue;
return;
}
// ---------------------------------------------------------------------------------------
int main( int numberOfArguments, char* argv[] ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "TestCudaFromFile";
int checkForces = 0;
int checkEnergyForceConsistent = 0;
int checkEnergyConservation = 0;
int checkInputForces = 0;
MapStringString inputArgumentMap;
FILE* log = NULL;
FILE* summaryFile = NULL;
// ---------------------------------------------------------------------------------------
std::string defaultParameterFileName = "OpenParameters.txt";
if( numberOfArguments < 2 ){
printUsage( defaultParameterFileName );
}
std::string parameterFileName = defaultParameterFileName;
std::string pluginDirectoryName = Platform::getDefaultPluginsDirectory();
MapStringInt forceMap;
initializeForceMap( forceMap, 0 );
int logFileNameIndex = -1;
int summaryFileNameIndex = -1;
// parse arguments
#ifdef _MSC_VER
#define STRCASECMP(X,Y) stricmp(X,Y)
#define STRNCASECMP(X,Y,Z) strnicmp(X,Y,Z)
#else
#define STRCASECMP(X,Y) strcasecmp(X,Y)
#define STRNCASECMP(X,Y,Z) strncasecmp(X,Y,Z)
#endif
for( int ii = 1; ii < numberOfArguments; ii++ ){
int addToMap = 0;
if( STRCASECMP( argv[ii], "-parameterFileName" ) == 0 ){
parameterFileName = argv[ii+1];
ii++;
} else if( STRCASECMP( argv[ii], "-logFileName" ) == 0 ){
logFileNameIndex = ii + 1;
ii++;
} else if( STRCASECMP( argv[ii], "-summaryFileName" ) == 0 ){
summaryFileNameIndex = ii + 1;
ii++;
} else if( STRCASECMP( argv[ii], "-checkForces" ) == 0 ){
checkForces = atoi( argv[ii+1] );
ii++;
} else if( STRCASECMP( argv[ii], "-checkInputForces" ) == 0 ){
checkInputForces = atoi( argv[ii+1] );
ii++;
} else if( STRCASECMP( argv[ii], "-checkEnergyForceConsistent" ) == 0 ){
checkEnergyForceConsistent = atoi( argv[ii+1] );
ii++;
} else if( STRCASECMP( argv[ii], "-checkEnergyConservation" ) == 0 ){
checkEnergyConservation = atoi( argv[ii+1] );;
ii++;
} else if( STRCASECMP( argv[ii], "-energyForceDelta" ) == 0 ||
STRCASECMP( argv[ii], "-energyForceTolerance" ) == 0 ||
STRCASECMP( argv[ii], "-cudaDeviceId" ) == 0 ||
STRCASECMP( argv[ii], "-platform" ) == 0 ||
STRCASECMP( argv[ii], "-applyAssertion" ) == 0 ){
addToMap = ii;
ii++;
} else if( STRCASECMP( argv[ii], "-allForces" ) == 0 ){
int flag = atoi( argv[ii+1] );
ii++;
initializeForceMap( forceMap, flag );
} else if( STRCASECMP( argv[ii], "-log" ) == 0 ){
if( atoi( argv[ii+1] ) != 0 ){
log = stderr;
} else {
log = NULL;
}
ii++;
} else if( STRCASECMP( argv[ii], "-help" ) == 0 ){
printUsage( defaultParameterFileName );
} else if( getForceOffset( ii, numberOfArguments, argv, forceMap ) ){
ii++;
} else if( STRNCASECMP( argv[ii], "-equilibration", 14 ) == 0 ||
STRNCASECMP( argv[ii], "-simulation", 11 ) == 0 ||
STRNCASECMP( argv[ii], "-runId", 6 ) == 0 ||
STRNCASECMP( argv[ii], "-nonbonded", 10 ) == 0 ||
STRNCASECMP( argv[ii], "-readContext", 12 ) == 0 ){
addToMap = ii;
ii++;
} else {
(void) printf( "Argument=<%s> not recognized -- aborting\n", argv[ii] );
exit(-1);
}
if( addToMap && ii >= 1 ){
char* key = argv[addToMap];
key++;
inputArgumentMap[key] = argv[addToMap+1];
// (void) printf( "ArgumentMap =<%s> <%s>\n", argv[addToMap], argv[addToMap+1] );
}
}
// open log file
if( log && logFileNameIndex > -1 ){
#ifdef _MSC_VER
fopen_s( &log, argv[logFileNameIndex], "w" );
#else
log = fopen( argv[logFileNameIndex], "w" );
#endif
}
// summary file
if( summaryFileNameIndex > -1 ){
#ifdef _MSC_VER
fopen_s( &summaryFile, argv[summaryFileNameIndex], "w" );
#else
summaryFile = fopen( argv[summaryFileNameIndex], "w" );
#endif
}
// log info
if( log ){
(void) fprintf( log, "Input arguments:\n" );
for( int ii = 1; ii < numberOfArguments-1; ii += 2 ){
(void) fprintf( log, " %3d %30s %15s\n", ii, argv[ii], argv[ii+1] );
}
(void) fprintf( log, "parameter file=<%s>\n", parameterFileName.c_str() );
if( summaryFileNameIndex > -1 ){
(void) fprintf( log, "summary file=<%s>\n", argv[summaryFileNameIndex] );
} else {
(void) fprintf( log, "no summary file\n" );
}
(void) fprintf( log, "pluginDirectoryName %s\n", pluginDirectoryName.c_str() );
(void) fprintf( log, "checkEnergyForceConsistent %d\n", checkEnergyForceConsistent );
(void) fprintf( log, "checkEnergyConservation %d\n", checkEnergyConservation );
(void) fprintf( log, "checkInputForces %d\n", checkInputForces );
(void) fprintf( log, "ForceMap: %u\n", forceMap.size() );
for( MapStringIntCI ii = forceMap.begin(); ii != forceMap.end(); ii++ ){
(void) fprintf( log, " %20s %d\n", (*ii).first.c_str(), (*ii).second );
}
(void) fprintf( log, "Argument map: %u\n", inputArgumentMap.size() );
for( MapStringStringCI ii = inputArgumentMap.begin(); ii != inputArgumentMap.end(); ii++ ){
(void) fprintf( log, "Map %s %s\n", (*ii).first.c_str(), (*ii).second.c_str() );
}
(void) fflush( log );
}
Platform::loadPluginsFromDirectory(pluginDirectoryName);
// check forces
if( checkForces ){
try {
testReferenceCudaForces( parameterFileName, forceMap, inputArgumentMap, log, summaryFile );
} catch( const exception& e ){
(void) fprintf( stderr, "Exception checkForces %s %s\n", methodName.c_str(), e.what() ); (void) fflush( stderr );
return 1;
}
}
// compare w/ input forces
if( checkInputForces ){
try {
testInputForces( parameterFileName, forceMap, inputArgumentMap, log, summaryFile );
} catch( const exception& e ){
(void) fprintf( stderr, "Exception testInputForces %s %s\n", methodName.c_str(), e.what() ); (void) fflush( stderr );
return 1;
}
}
// check energy/force consistent
if( checkEnergyForceConsistent ){
try {
testEnergyForcesConsistent( parameterFileName, forceMap, inputArgumentMap, log, summaryFile );
} catch( const exception& e ){
(void) fprintf( stderr, "Exception checkEnergyForceConsistent %s %s\n", methodName.c_str(), e.what() ); (void) fflush( stderr );
return 1;
}
}
// check energy conservation or thermal stability
if( checkEnergyConservation ){
try {
testEnergyConservation( parameterFileName, forceMap, inputArgumentMap, log, summaryFile );
} catch( const exception& e ){
(void) fprintf( stderr, "Exception checkEnergyConservation %s %s\n", methodName.c_str(), e.what() ); (void) fflush( stderr );
return 1;
}
}
if( log ){
(void) fprintf( log, "\n%s done\n", methodName.c_str() ); (void) fflush( log );
}
if( summaryFile ){
(void) fclose( summaryFile );
}
return 0;
}