/* -------------------------------------------------------------------------- * * 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.setDefaultPeriodicBoxVectors( box[0], box[1], box[2] ); Vec3 a, b, c; system.getDefaultPeriodicBoxVectors( 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::getPlatformByName("Reference") ); } else { context = new Context( *system, *inputIntegrator, Platform::getPlatformByName("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::getPlatformByName("Reference"); Platform& cudaPlatform = Platform::getPlatformByName("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::getPlatformByName( "Cuda");; Context* cudaContext = testSetup( parameterFileName, forceMap, cudaPlatform, parameterForces2, ¶meterKineticEnergy, ¶meterPotentialEnergy, supplementary, inputArgumentMap, log ); checkEnergyForceConsistent( *cudaContext, inputArgumentMap, log, summaryFilePtr ); } else { Platform& referencePlatform = Platform::getPlatformByName( "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::getPlatformByName( "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; }