/* -------------------------------------------------------------------------- * * 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: Mark Friedrichs, Mike Houston * * 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 . * * -------------------------------------------------------------------------- */ #include "openmm/LangevinIntegrator.h" #include "ReferencePlatform.h" #include "openmm/internal/ContextImpl.h" #include "openmm/OpenMMException.h" #include "BrookStreamImpl.h" #include "OpenMMBrookInterface.h" #include "kernels/kcommon.h" #include #include #include using namespace OpenMM; using namespace std; /** * OpenMMBrookInterface constructor * */ OpenMMBrookInterface::OpenMMBrookInterface( int streamWidth, int duplicationFactor ) : _particleStreamWidth(streamWidth){ // --------------------------------------------------------------------------------------- // static const std::string methodName = "OpenMMBrookInterface::OpenMMBrookInterface"; // --------------------------------------------------------------------------------------- _numberOfParticles = 0; _triggerForceKernel = NULL; _triggerEnergyKernel = NULL; _positions = NULL; _velocities = NULL; _forces = NULL; _log = NULL; //_log = stderr; _time = 0.0; _particleStreamSize = -1; for( int ii = 0; ii < LastBondForce; ii++ ){ _bondParameters[ii] = NULL; } if( duplicationFactor < 1 ){ duplicationFactor = 4; } _brookNonBonded.setDuplicationFactor( duplicationFactor ); _brookGbsa.setDuplicationFactor( duplicationFactor ); } /** * OpenMMBrookInterface destructor * */ OpenMMBrookInterface::~OpenMMBrookInterface( ){ // --------------------------------------------------------------------------------------- // static const std::string methodName = "OpenMMBrookInterface::OpenMMBrookInterface"; // --------------------------------------------------------------------------------------- for( int ii = 0; ii < LastBondForce; ii++ ){ delete _bondParameters[ii]; } } /** * Get number of particles * * @return number of particles * */ int OpenMMBrookInterface::getNumberOfParticles( void ) const { return _numberOfParticles; } /** * Set number of particles * * @param numberOfParticles number of particles * */ int OpenMMBrookInterface::setNumberOfParticles( int numberOfParticles ){ _numberOfParticles = numberOfParticles; return BrookCommon::DefaultReturnValue; } /** * Get the current time * * @return the current time * */ double OpenMMBrookInterface::getTime( void ) const { return _time; } /** * Set the current time * * @param time the current time * * @return DefaultReturnValue * */ int OpenMMBrookInterface::setTime( double time) { _time = time; return BrookCommon::DefaultReturnValue; } /** * Get particle stream width * * @return particle stream width * */ int OpenMMBrookInterface::getParticleStreamWidth( void ) const { return _particleStreamWidth; } /** * Get particle stream size * * @return particle stream size * */ int OpenMMBrookInterface::getParticleStreamSize( void ) const { if( _particleStreamSize < 0 && _numberOfParticles > 0 ){ OpenMMBrookInterface* localThis = const_cast(this); localThis->_particleStreamSize = BrookPlatform::getStreamSize( _numberOfParticles, _particleStreamWidth, NULL ); } return _particleStreamSize; } /** * Get log file reference * * @return log file reference * */ FILE* OpenMMBrookInterface::getLog( void ) const { return _log; } /** * Set log file reference * * @param log file reference * * @return DefaultReturnValue * */ int OpenMMBrookInterface::setLog( FILE* log ){ _log = log; _brookBonded.setLog( log ); _brookNonBonded.setLog( log ); _brookGbsa.setLog( log ); return BrookCommon::DefaultReturnValue; } /** * Get BrookBondParameters at specified index * * @param index * * @return BrookBondParameters* object * */ BrookBondParameters* OpenMMBrookInterface::_getBondParameters( BondParameterIndices index ) const { return _bondParameters[index]; } /** * Set BrookBondParameters at specified index * * @param index * @param brookBondParameters brookBondParameters for BrookBondParameters * * @return DefaultReturnValue * */ int OpenMMBrookInterface::_setBondParameters( BondParameterIndices index, BrookBondParameters* brookBondParameters ){ if( brookBondParameters && brookBondParameters->getNumberOfBonds() > 0 ){ _brookBonded.setIsActive( 1 ); } _bondParameters[index] = brookBondParameters; if( !brookBondParameters || brookBondParameters->getNumberOfBonds() < 1 ){ int isActive = 0; for( int ii = 0; ii < LastBondForce && !isActive; ii++ ){ isActive = (_bondParameters[ii] != NULL && brookBondParameters->getNumberOfBonds() > 0) ? 1 : 0; } _brookBonded.setIsActive( isActive ); } return BrookCommon::DefaultReturnValue; } /** * Get BrookBondParameters for harmonic bond force * * @return brookBondParameters for harmonic bond force * */ BrookBondParameters* OpenMMBrookInterface::getHarmonicBondForceParameters( void ) const { return _getBondParameters( HarmonicBondIndex ); } /** * Set BrookBondParameters for harmonic bond force * * @param brookBondParameters brookBondParameters for harmonic bond force * * @return DefaultReturnValue * */ int OpenMMBrookInterface::setHarmonicBondForceParameters( BrookBondParameters* brookBondParameters ){ _brookBonded.setupCompleted( 0 ); return _setBondParameters( HarmonicBondIndex, brookBondParameters ); } /** * Get BrookBondParameters for harmonic angle force * * @return brookBondParameters for harmonic angle force * */ BrookBondParameters* OpenMMBrookInterface::getHarmonicAngleForceParameters( void ) const { return _getBondParameters( HarmonicAngleIndex ); } /** * Set BrookBondParameters for harmonic angle force * * @param brookBondParameters brookBondParameters for harmonic angle force * * @return DefaultReturnValue * */ int OpenMMBrookInterface::setHarmonicAngleForceParameters( BrookBondParameters* brookBondParameters ){ _brookBonded.setupCompleted( 0 ); return _setBondParameters( HarmonicAngleIndex, brookBondParameters ); } /** * Get BrookBondParameters for periodic torsion force * * @return brookBondParameters for periodic torsion force * */ BrookBondParameters* OpenMMBrookInterface::getPeriodicTorsionForceParameters( void ) const { return _getBondParameters( PeriodicTorsionForceIndex ); } /** * Set BrookBondParameters for periodic torsion force * * @param brookBondParameters brookBondParameters for periodic torsion force * * @return DefaultReturnValue * */ int OpenMMBrookInterface::setPeriodicTorsionForceParameters( BrookBondParameters* brookBondParameters ){ _brookBonded.setupCompleted( 0 ); return _setBondParameters( PeriodicTorsionForceIndex, brookBondParameters ); } /** * Get BrookBondParameters for rb torsion force * * @return brookBondParameters for rb torsion force * */ BrookBondParameters* OpenMMBrookInterface::getRBTorsionForceParameters( void ) const { return _getBondParameters( RbTorsionForceIndex ); } /** * Set BrookBondParameters for RB torsion force * * @param brookBondParameters brookBondParameters for RB torsion force * * @return DefaultReturnValue * */ int OpenMMBrookInterface::setRBTorsionForceParameters( BrookBondParameters* brookBondParameters ){ _brookBonded.setupCompleted( 0 ); return _setBondParameters( RbTorsionForceIndex, brookBondParameters ); } /** * Get BrookBondParameters for LJ 14 force * * @return brookBondParameters for LJ 14 force * */ BrookBondParameters* OpenMMBrookInterface::getNonBonded14ForceParameters( void ) const { return _getBondParameters( LJ14Index ); } /** * Set BrookBondParameters for LJ 14 force * * @param brookBondParameters brookBondParameters for LJ 14 force * * @return DefaultReturnValue * */ int OpenMMBrookInterface::setNonBonded14ForceParameters( BrookBondParameters* brookBondParameters ){ _brookBonded.setupCompleted( 0 ); return _setBondParameters( LJ14Index, brookBondParameters ); } /** * Get positions stream * * @return particle positions * */ BrookStreamImpl* OpenMMBrookInterface::getParticlePositions( void ){ return _positions; } /** * Set positions stream * * @param positions Brook stream containing particle positions * * @return DefaultReturnValue * */ int OpenMMBrookInterface::setParticlePositions( BrookStreamImpl* positions ){ _positions = positions; return DefaultReturnValue; } /** * Get velocities stream * * @return particle velocities * */ BrookStreamImpl* OpenMMBrookInterface::getParticleVelocities( void ){ return _velocities; } /** * Set velocities stream * * @param velocities Brook stream containing particle velocities * * @return DefaultReturnValue * */ int OpenMMBrookInterface::setParticleVelocities( BrookStreamImpl* velocities ){ _velocities = velocities; return DefaultReturnValue; } /** * Get forces stream * * @return ParticleForces * */ BrookStreamImpl* OpenMMBrookInterface::getParticleForces( void ){ return _forces; } /** * Set forces stream * * @param forces Brook stream containing particle forces * * @return DefaultReturnValue * */ int OpenMMBrookInterface::setParticleForces( BrookStreamImpl* forces ){ _forces = forces; return DefaultReturnValue; } /** * Set trigger Force Kernel * * @param triggerForceKernel kernel to calculate force * */ void OpenMMBrookInterface::setTriggerForceKernel( void* triggerForceKernel ){ _triggerForceKernel = triggerForceKernel; } /** * Get trigger Force Kernel * * @return triggerForceKernel kernel to calculate force * */ void* OpenMMBrookInterface::getTriggerForceKernel( void ) const { return _triggerForceKernel; } /** * Set trigger Energy Kernel * * @param triggerEnergyKernel kernel to calculate force * */ void OpenMMBrookInterface::setTriggerEnergyKernel( void* triggerEnergyKernel ){ _triggerEnergyKernel = triggerEnergyKernel; } /** * Get trigger Energy Kernel * * @return triggerEnergyKernel kernel to calculate force * */ void* OpenMMBrookInterface::getTriggerEnergyKernel( void ) const { return _triggerEnergyKernel; } /** * Get Brook non bonded * * @return BrookNonBonded reference * */ BrookNonBonded& OpenMMBrookInterface::getBrookNonBonded( void ){ return _brookNonBonded; } /** * Get Brook GBSA * * @return BrookGbsa reference * */ BrookGbsa& OpenMMBrookInterface::getBrookGbsa( void ){ return _brookGbsa; } /** * Zero forces * * @param context context * */ void OpenMMBrookInterface::zeroForces( ContextImpl& context ){ // --------------------------------------------------------------------------------------- //static const std::string methodName = "OpenMMBrookInterface::zeroForces"; // --------------------------------------------------------------------------------------- // zero forces BrookStreamImpl* forces = getParticleForces(); kzerof3( forces->getBrookStream() ); // --------------------------------------------------------------------------------------- } /** * Compute forces * * @param context context * */ void OpenMMBrookInterface::computeForces( ContextImpl& context ){ // --------------------------------------------------------------------------------------- static const std::string methodName = "OpenMMBrookInterface::executeForces"; static int printOn = 0; static const int MaxErrorMessages = 2; static int ErrorMessages = 0; FILE* log; // --------------------------------------------------------------------------------------- //setLog( stderr ); if( printOn && getLog() ){ log = getLog(); } else { printOn = 0; } BrookStreamImpl* positions = getParticlePositions(); BrookStreamImpl* forces = getParticleForces(); // info if( printOn > 0 ){ //if( 1 ){ printForcesToFile( context ); } // nonbonded forces if( _brookNonBonded.isActive() ){ _brookNonBonded.computeForces( *positions, *forces ); } // --------------------------------------------------------------------------------------- // bonded forces if( printOn ){ (void) fprintf( log, "%s done nonbonded: bonded=%d completed=%d\n", methodName.c_str(), _brookBonded.isActive(), _brookBonded.isSetupCompleted() ); (void) fflush( log ); } if( _brookBonded.isActive() ){ // perform setup first time through if( _brookBonded.isSetupCompleted() == 0 ){ _brookBonded.setup( getNumberOfParticles(), getHarmonicBondForceParameters(), getHarmonicAngleForceParameters(), getPeriodicTorsionForceParameters(), getRBTorsionForceParameters(), getNonBonded14ForceParameters(), getParticleStreamWidth(), getParticleStreamSize() ); } _brookBonded.computeForces( *positions, *forces ); // diagnostics if( printOn ){ static int step = 0; static const int stopStep = 10; (void) fprintf( log, "%s done bonded computeForces\n", methodName.c_str() ); (void) fflush( log ); /* (void) fprintf( getLog(), "\nFinal NB & bonded forces" ); BrookStreamInternal* brookStreamInternalF = forceStream.getBrookStreamInternal(); brookStreamInternalF->printToFile( getLog() ); void* dataV = brookStreamInternalF->getData(1); float* data = (float*) dataV; (void) fprintf( getLog(), "\nFinal NB & bonded forces RAW\n" ); for( int ii = 0; ii < _brookNonBonded->getNumberOfParticles()*3; ii += 3 ){ (void) fprintf( getLog(), "%d [%.6e %.6e %.6e]\n", ii, data[ii], data[ii+1], data[ii+2] ); } */ if( step++ >= stopStep ){ exit(0); } } } // GBSA OBC forces if( _brookGbsa.isActive() ){ _brookGbsa.computeForces( *positions, *forces ); } // --------------------------------------------------------------------------------------- } /** * Print forces to file * * @param context context * */ void OpenMMBrookInterface::printForcesToFile( ContextImpl& context ){ // --------------------------------------------------------------------------------------- static const std::string methodName = "OpenMMBrookInterface::printForcesToFile"; float zero = 0.0f; static int step = 0; // --------------------------------------------------------------------------------------- // first step only? if( step > 1 ){ return; } std::stringstream fileNameBaseS; //fileNameBase << "Brook_" << context.getTime() << "_"; fileNameBaseS << "Brook_" << step++ << "_"; std::string fileNameBase = fileNameBaseS.str(); // create vector of streams for output BrookStreamImpl* positions = getParticlePositions(); BrookStreamImpl* forces = getParticleForces(); std::vector streams; streams.push_back( positions->getBrookStreamInternal() ); streams.push_back( forces->getBrookStreamInternal() ); // --------------------------------------------------------------------------------------- // nonbonded forces if( _brookNonBonded.isActive() ){ forces->fillWithValue( &zero ); _brookNonBonded.computeForces( *positions, *forces ); std::string fileName = fileNameBase + "NonBonded.txt"; BrookStreamInternal::printStreamsToFile( fileName, streams ); } // --------------------------------------------------------------------------------------- // bonded forces if( _brookBonded.isActive() ){ // perform setup first time through if( _brookBonded.isSetupCompleted() == 0 ){ _brookBonded.setup( getNumberOfParticles(), getHarmonicBondForceParameters(), getHarmonicAngleForceParameters(), getPeriodicTorsionForceParameters(), getRBTorsionForceParameters(), getNonBonded14ForceParameters(), getParticleStreamWidth(), getParticleStreamSize() ); } forces->fillWithValue( &zero ); _brookBonded.computeForces( *positions, *forces ); std::string fileName = fileNameBase + "Bonded.txt"; BrookStreamInternal::printStreamsToFile( fileName, streams ); } // --------------------------------------------------------------------------------------- // GBSA OBC forces if( _brookGbsa.isActive() ){ forces->fillWithValue( &zero ); _brookGbsa.computeForces( *positions, *forces ); std::string fileName = fileNameBase + "Obc.txt"; BrookStreamInternal::printStreamsToFile( fileName, streams ); } // --------------------------------------------------------------------------------------- // all forces if( 1 ){ forces->fillWithValue( &zero ); if( _brookNonBonded.isActive() ){ _brookNonBonded.computeForces( *positions, *forces ); } if( _brookBonded.isActive() ){ _brookBonded.computeForces( *positions, *forces ); } if( _brookGbsa.isActive() ){ _brookGbsa.computeForces( *positions, *forces ); } std::string fileName = fileNameBase + "AllF.txt"; BrookStreamInternal::printStreamsToFile( fileName, streams ); } forces->fillWithValue( &zero ); // --------------------------------------------------------------------------------------- } /** * Compute energy * * @param context context * @param system system reference * */ double OpenMMBrookInterface::computeEnergy( ContextImpl& context, System& system ){ // --------------------------------------------------------------------------------------- //static const std::string methodName = "OpenMMBrookInterface::computeEnergy"; // --------------------------------------------------------------------------------------- // We don't currently have GPU kernels to calculate energy, so instead we have the reference // platform do it. This is VERY slow. LangevinIntegrator integrator(0.0, 1.0, 0.0); ReferencePlatform platform; Context refContext( system, integrator, platform ); const Stream& positions = context.getPositions(); double* posData = new double[positions.getSize()*3]; positions.saveToArray(posData); vector pos(positions.getSize()); for( unsigned int ii = 0; ii < pos.size(); ii++ ){ pos[ii] = Vec3(posData[3*ii], posData[3*ii+1], posData[3*ii+2]); } delete[] posData; refContext.setPositions(pos); return refContext.getState(State::Energy).getPotentialEnergy(); }