Commit 6ccf6169 authored by Peter Eastman's avatar Peter Eastman
Browse files

Removed Brook platform

parent 82e0bd2f
#ifndef OPENMM_BROOK_LANGEVIN_DYNAMICS_H_
#define OPENMM_BROOK_LANGEVIN_DYNAMICS_H_
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include <vector>
#include <set>
#include "BrookStreamImpl.h"
#include "BrookShakeAlgorithm.h"
#include "BrookRandomNumberGenerator.h"
#include "BrookPlatform.h"
#include "BrookCommon.h"
namespace OpenMM {
/**
*
* Encapsulates stochastic dynamics algorithm
*
*/
class BrookLangevinDynamics : public BrookCommon {
public:
/**
* Constructor
*
*/
BrookLangevinDynamics( );
/**
* Destructor
*
*/
~BrookLangevinDynamics();
/**
* Get tau
*
* @return tau
*/
BrookOpenMMFloat getTau( void ) const;
/**
* Get friction
*
* @return friction
*/
BrookOpenMMFloat getFriction( void ) const;
/**
* Get temperature
*
* @return temperature
*/
BrookOpenMMFloat getTemperature( void ) const;
/**
* Get step size
*
* @return step size
*/
BrookOpenMMFloat getStepSize( void ) const;
/**
*
* Get array of derived parameters indexed by 'DerivedParameters' enums
*
* @return array
*
*/
const BrookOpenMMFloat* getDerivedParameters( void ) const;
/**
* Get LangevinDynamics particle stream width
*
* @return particle stream width
*/
int getLangevinDynamicsParticleStreamWidth( void ) const;
/**
* Get LangevinDynamics particle stream height
*
* @return particle stream height
*/
int getLangevinDynamicsParticleStreamHeight( void ) const;
/**
* Get LangevinDynamics particle stream size
*
* @return particle stream size
*/
int getLangevinDynamicsParticleStreamSize( void ) const;
/**
* Update parameters
*
* @param temperature temperature
* @param friction friction
* @param step size step size
*
* @return DefaultReturnValue
*
*/
int updateParameters( double temperature, double friction, double stepSize );
/**
* Update
*
* @param positions particle positions
* @param velocities particle velocities
* @param forces particle forces
* @param brookShakeAlgorithm BrookShakeAlgorithm reference
* @param brookRandomNumberGenerator BrookRandomNumberGenerator reference
*
* @return DefaultReturnValue
*
*/
int update( BrookStreamImpl& positionStream, BrookStreamImpl& velocityStream,
BrookStreamImpl& forceStream,
BrookShakeAlgorithm& brookShakeAlgorithm,
BrookRandomNumberGenerator& brookRandomNumberGenerator );
/**
* Get array of LangevinDynamics streams
*
* @return array ofstreams
*
*/
BrookFloatStreamInternal** getStreams( void );
/*
* Setup of LangevinDynamics parameters
*
* @param masses particle masses
* @param platform Brook platform
*
* @return ErrorReturnValue value if error, else DefaultReturnValue
*
* */
int setup( const std::vector<double>& masses, const Platform& platform );
/*
* Get contents of object
*
* @param level of dump
*
* @return string containing contents
*
* */
std::string getContentsString( int level = 0 ) const;
/**
* Get SDPC1 stream
*
* @return SDPC1 stream
*
*/
BrookFloatStreamInternal* getSDPC1Stream( void ) const;
/**
* Get SDPC2 stream
*
* @return SDPC2 stream
*
*/
BrookFloatStreamInternal* getSDPC2Stream( void ) const;
/**
* Get SD2X stream
*
* @return SD2X stream
*
*/
BrookFloatStreamInternal* getSD2XStream( void ) const;
/**
* Get SD1V stream
*
* @return SD1V stream
*
*/
BrookFloatStreamInternal* getSD1VStream( void ) const;
/**
* Get V-prime stream
*
* @return V-prime stream
*
*/
BrookFloatStreamInternal* getVPrimeStream( void ) const;
/**
* Get X-prime stream
*
* @return X-prime stream
*
*/
BrookFloatStreamInternal* getXPrimeStream( void ) const;
/**
* Get inverse sqrt masses
*
* @return inverse sqrt masses stream
*
*/
BrookFloatStreamInternal* getInverseMassStream( void ) const;
/**
* Get Temperature
*
* @param velocities velocities
* @param inverseMassStream inverse masses
* @param numberOfConstraints number of constraints
*
* @return temperature
*
*/
float getTemperature( BrookStreamInternal* velocities, BrookFloatStreamInternal* inverseMassStream,
int numberOfConstraints ) const;
/**
* Remove velocity com
*
* @param velocities velocities
* @param inverseMassStream inverse masses
*
* @return DefaultReturnValue
*/
int removeCom( BrookStreamInternal* velocities, BrookFloatStreamInternal* inverseMassStream ) const;
/**
* Reset velocities (diagnostics)
*
* @param velocities velocities
*
* @return DefaultReturnValue
*/
int resetVelocities( BrookStreamInternal* velocities ) const;
private:
enum DerivedParameters { GDT, EPH, EMH, EP, EM, B, C, D, V, X, Yv, Yx,
Sd1pc1, Sd1pc2, Sd1pc3, Sd2pc1, Sd2pc2, MaxDerivedParameters };
BrookOpenMMFloat _derivedParameters[MaxDerivedParameters];
// streams indices
enum BrookLangevinDynamicsStreams {
SDPC1Stream,
SDPC2Stream,
SD2XStream,
SD1VStream,
VPrimeStream,
XPrimeStream,
InverseMassStream,
LastStreamIndex
};
// randomNumberSeed
unsigned int _randomNumberSeed;
BrookOpenMMFloat _tau;
BrookOpenMMFloat _temperature;
BrookOpenMMFloat _stepSize;
// internal step count
int _internalStepCount;
// Particle stream dimensions
int _sdParticleStreamWidth;
int _sdParticleStreamHeight;
int _sdParticleStreamSize;
/**
* Get derived parameter string
*
* @return string
*
*/
//std::string _getDerivedParametersString( BrookLangevinDynamics::DerivedParameters ) const;
std::string _getDerivedParametersString( int id ) const;
/**
* Update derived parameters
*
* @return DefaultReturn
*
*/
int _updateDerivedParameters( void );
/*
* Update streams
*
* @return DefaultReturn
*
*/
int _updateSdStreams( void );
// inverse sqrt masses
BrookOpenMMFloat* _inverseSqrtMasses;
// internal streams
BrookFloatStreamInternal* _sdStreams[LastStreamIndex];
/**
* Set tau
*
* @param tau new tau value
*
* @return DefaultReturn
*
*/
int _setTau( BrookOpenMMFloat tau );
/**
* Set friction = 1/tau
*
* @param friction new friction value
*
* @return DefaultReturn
*
*/
int _setFriction( BrookOpenMMFloat friction );
/**
* Set temperature
*
* @parameter temperature
*
* @return DefaultReturn
*
*/
int _setTemperature( BrookOpenMMFloat temperature );
/**
* Set stepSize
*
* @param stepSize
*
* @return DefaultReturn
*
*/
int _setStepSize( BrookOpenMMFloat stepSize );
/*
* Setup of stream dimensions
*
* @param particleStreamSize particle stream size
* @param particleStreamWidth particle stream width
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
* */
int _initializeStreamSizes( int particleStreamSize, int particleStreamWidth );
/**
* Initialize stream dimensions
*
* @param numberOfParticles number of particles
* @param platform platform
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int _initializeStreamSizes( int numberOfParticles, const Platform& platform );
/**
* Initialize stream dimensions and streams
*
* @param platform platform
*
* @return nonzero value if error
*
*/
int _initializeStreams( const Platform& platform );
/**
* Set masses
*
* @param masses particle masses
*
*/
int _setInverseSqrtMasses( const std::vector<double>& masses );
};
} // namespace OpenMM
#endif /* OPENMM_BROOK_LANGEVIN_DYNAMICS_H_ */
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "BrookNonBonded.h"
#include "BrookPlatform.h"
#include "BrookStreamFactory.h"
#include "openmm/OpenMMException.h"
//#include "kernels/invmap.h"
#include "kernels/kforce.h"
#include <sstream>
using namespace OpenMM;
using namespace std;
/**
* Constructor
*
*/
BrookNonBonded::BrookNonBonded( ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookNonBonded::BrookNonBonded";
// ---------------------------------------------------------------------------------------
_particleSizeCeiling = -1;
_outerUnroll = 4;
_innerUnroll = 4;
_partialForceStreamWidth = 64;
_partialForceStreamHeight = -1;
_partialForceStreamSize = -1;
_duplicationFactor = 4;
_exclusionStreamWidth = -1;
_exclusionStreamHeight = -1;
_exclusionStreamSize = -1;
_jStreamWidth = 16;
_jStreamHeight = -1;
_jStreamSize = -1;
for( int ii = 0; ii < LastStreamIndex; ii++ ){
_nonbondedStreams[ii] = NULL;
}
for( int ii = 0; ii < getNumberOfForceStreams(); ii++ ){
_nonbondedForceStreams[ii] = NULL;
}
}
/**
* Destructor
*
*/
BrookNonBonded::~BrookNonBonded( ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookNonBonded::~BrookNonBonded";
//static const int debug = 1;
// ---------------------------------------------------------------------------------------
for( int ii = 0; ii < LastStreamIndex; ii++ ){
delete _nonbondedStreams[ii];
}
for( int ii = 0; ii < getNumberOfForceStreams(); ii++ ){
delete _nonbondedForceStreams[ii];
}
}
/**
* Get number of force streams
*
* @return number of force streams (fixed value)
*
*/
int BrookNonBonded::getNumberOfForceStreams( void ) const {
return NumberOfForceStreams;
}
/**
* Get inner loop unroll
*
* @return inner loop unroll (fixed value)
*
*/
int BrookNonBonded::getInnerLoopUnroll( void ) const {
return _innerUnroll;
}
/**
* Get outer loop unroll
*
* @return outer loop unroll (fixed value)
*
*/
int BrookNonBonded::getOuterLoopUnroll( void ) const {
return _outerUnroll;
}
/**
* Set outer loop unroll
*
* @param outer loop unroll (fixed value)
*
* @return updated outer loop unroll (fixed value)
*
*/
int BrookNonBonded::setOuterLoopUnroll( int outerUnroll ){
if( outerUnroll != _outerUnroll ){
_particleSizeCeiling = -1;
}
_outerUnroll = _outerUnroll;
return _outerUnroll;
}
/**
* Get particle ceiling parameter
*
* @return particle ceiling parameter
*
*/
int BrookNonBonded::getParticleSizeCeiling( void ) const {
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookNonBonded::getParticleSizeCeiling";
// ---------------------------------------------------------------------------------------
if( _particleSizeCeiling < 0 ){
BrookNonBonded* localThis = const_cast<BrookNonBonded* const>(this);
localThis->_particleSizeCeiling = localThis->getNumberOfParticles() % localThis->getOuterLoopUnroll();
if( localThis->_particleSizeCeiling ){
localThis->_particleSizeCeiling = localThis->getOuterLoopUnroll() - localThis->_particleSizeCeiling;
}
localThis->_particleSizeCeiling += localThis->getNumberOfParticles();
}
return _particleSizeCeiling;
}
/**
* Get duplication factor
*
* @return duplication factor
*
*/
int BrookNonBonded::getDuplicationFactor( void ) const {
return _duplicationFactor;
}
/**
* Set duplication factor
*
* @param duplication factor
*
* @return DefaultReturnValue
*
*/
int BrookNonBonded::setDuplicationFactor( int duplicationFactor ){
_duplicationFactor = duplicationFactor;
return DefaultReturnValue;
}
/**
* Get j-stream width
*
* @return j-stream width
*
*/
int BrookNonBonded::getJStreamWidth( void ) const {
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookNonBonded::getJStreamWidth";
// ---------------------------------------------------------------------------------------
return _jStreamWidth;
}
/**
* Get j-stream height
*
* @return j-stream height
*
*/
int BrookNonBonded::getJStreamHeight( void ) const {
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookNonBonded::getJStreamHeight";
// ---------------------------------------------------------------------------------------
return _jStreamHeight;
}
/**
* Get j-stream size
*
* @return j-stream size
*
*/
int BrookNonBonded::getJStreamSize( void ) const {
return _jStreamSize;
}
/**
* Get partial force stream width
*
* @param platform platform
*
* @return partial force stream width
*
*/
int BrookNonBonded::getPartialForceStreamWidth( const Platform& platform ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookNonBonded::getPartialForceStreamWidth";
// ---------------------------------------------------------------------------------------
// get partial force stream width
if( _partialForceStreamWidth < 0 ){
//_getPartialForceStreamDimensions( platform );
}
return _partialForceStreamWidth;
}
/**
* Get partial force stream width
*
* @return partial force stream width
*
*/
int BrookNonBonded::getPartialForceStreamWidth( void ) const {
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookNonBonded::getPartialForceStreamWidth";
// ---------------------------------------------------------------------------------------
return _partialForceStreamWidth;
}
/**
* Get partial force stream height
*
* @param platform platform
*
* @return partial force stream height
*
*/
int BrookNonBonded::getPartialForceStreamHeight( const Platform& platform ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookNonBonded::getPartialForceStreamHeight";
// ---------------------------------------------------------------------------------------
// get partial force stream height
if( _partialForceStreamHeight < 0 ){
//_getPartialForceStreamDimensions( platform );
}
return _partialForceStreamHeight;
}
/**
* Get partial force stream height
*
* @return partial force stream height
*
*/
int BrookNonBonded::getPartialForceStreamHeight( void ) const {
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookNonBonded::getPartialForceStreamHeight";
// ---------------------------------------------------------------------------------------
return _partialForceStreamHeight;
}
/**
* Get partial force stream size
*
* @param platform platform
*
* @return partial force stream size
*
*/
int BrookNonBonded::getPartialForceStreamSize( const Platform& platform ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookNonBonded::getPartialForceStreamSize";
// ---------------------------------------------------------------------------------------
// get partial force stream size
if( _partialForceStreamSize < 0 ){
//_getPartialForceStreamDimensions( platform );
}
return _partialForceStreamSize;
}
/**
* Get partial force stream size
*
* @return partial force stream size
*
*/
int BrookNonBonded::getPartialForceStreamSize( void ) const {
return _partialForceStreamSize;
}
/**
* Get exclusion stream size
*
* @return exclusion stream size
*
*/
int BrookNonBonded::getExclusionStreamSize( void ) const {
return _exclusionStreamSize;
}
/**
* Get exclusion stream width
*
* @return exclusion stream width
*
*/
int BrookNonBonded::getExclusionStreamWidth( void ) const {
return _exclusionStreamWidth;
}
/**
* Get exclusion stream
*
* @return exclusion stream
*
*/
BrookFloatStreamInternal* BrookNonBonded::getExclusionStream( void ) const {
return _nonbondedStreams[ExclusionStream];
}
/**
* Get vdw stream
*
* @return vdw stream
*
*/
BrookFloatStreamInternal* BrookNonBonded::getOuterVdwStream( void ) const {
return _nonbondedStreams[OuterVdwStream];
}
/**
* Get charge stream
*
* @return charge stream
*
*/
BrookFloatStreamInternal* BrookNonBonded::getChargeStream( void ) const {
return _nonbondedStreams[ChargeStream];
}
/**
* Get sigma stream
*
* @return sigma stream
*
*/
BrookFloatStreamInternal* BrookNonBonded::getInnerSigmaStream( void ) const {
return _nonbondedStreams[InnerSigmaStream];
}
/**
* Get epsilon stream
*
* @return epsilon stream
*
*/
BrookFloatStreamInternal* BrookNonBonded::getInnerEpsilonStream( void ) const {
return _nonbondedStreams[InnerEpsilonStream];
}
/**
* Get force streams
*
* @return force streams
*
*/
BrookFloatStreamInternal** BrookNonBonded::getForceStreams( void ){
return _nonbondedForceStreams;
}
/**
* Return true if force[index] stream is set
*
* @param index into force stream
* @return true if index is valid && force[index] stream is set; else false
*
*/
int BrookNonBonded::isForceStreamSet( int index ) const {
return (index >= 0 && index < getNumberOfForceStreams() && _nonbondedForceStreams[index]) ? 1 : 0;
}
/**
* Initialize stream dimensions
*
* @param numberOfParticles number of particles
* @param platform platform
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int BrookNonBonded::_initializeStreamSizes( int numberOfParticles, const Platform& platform ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookNonBonded::_initializeStreamSizes";
// static const int debug = 1;
// ---------------------------------------------------------------------------------------
int particleStreamSize = getParticleStreamSize( platform );
int particleStreamWidth = getParticleStreamWidth( platform );
_initializeExclusionStreamSize( particleStreamSize, particleStreamWidth );
_initializeJStreamSize( particleStreamSize, particleStreamWidth );
_initializeOuterVdwStreamSize( particleStreamSize, particleStreamWidth );
_initializePartialForceStreamSize( particleStreamSize, particleStreamWidth );
return DefaultReturnValue;
}
/**
* Initialize streams
*
* @param platform platform
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int BrookNonBonded::_initializeStreams( const Platform& platform ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookNonBonded::_initializeStreams";
static const double dangleValue = 0.0;
// static const int debug = 1;
// ---------------------------------------------------------------------------------------
const BrookStreamFactory& brookStreamFactory = dynamic_cast<const BrookStreamFactory&> (platform.getDefaultStreamFactory());
// exclusion
_nonbondedStreams[ExclusionStream] = new BrookFloatStreamInternal( BrookCommon::NonBondedExclusionStream,
getExclusionStreamSize(), getExclusionStreamWidth(),
BrookStreamInternal::Float, dangleValue );
// outer vdw
_nonbondedStreams[OuterVdwStream] = new BrookFloatStreamInternal( BrookCommon::OuterVdwStream, getParticleStreamSize(),
getParticleStreamWidth(), BrookStreamInternal::Float2, dangleValue );
// inner sigma & epsilon
_nonbondedStreams[InnerSigmaStream] = new BrookFloatStreamInternal( BrookCommon::InnerSigmaStream, getJStreamSize(),
getJStreamWidth(), BrookStreamInternal::Float4, dangleValue );
_nonbondedStreams[InnerEpsilonStream] = new BrookFloatStreamInternal( BrookCommon::InnerEpsilonStream, getJStreamSize(),
getJStreamWidth(), BrookStreamInternal::Float4, dangleValue );
// charge stream
_nonbondedStreams[ChargeStream] = new BrookFloatStreamInternal( BrookCommon::NonBondedChargeStream, getParticleStreamSize(),
getParticleStreamWidth(), BrookStreamInternal::Float, dangleValue );
// partial force streams
std::string partialForceStream = BrookCommon::PartialForceStream;
for( int ii = 0; ii < getNumberOfForceStreams(); ii++ ){
std::stringstream name;
name << partialForceStream << ii;
_nonbondedForceStreams[ii] = new BrookFloatStreamInternal( name.str(), getPartialForceStreamSize(),
getPartialForceStreamWidth(), BrookStreamInternal::Float3, dangleValue );
}
return DefaultReturnValue;
}
/**
* Set exclusion (4x4)
*
* @param i particle i index
* @param j particle j index
* @param exclusionStreamWidth exclusion stream width
* @param exclusion array of packed exclusions
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int BrookNonBonded::_setExclusion( int i, int j, int exclusionStreamWidth, BrookOpenMMFloat* exclusion ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookNonBonded::_setExclusion";
// ---------------------------------------------------------------------------------------
int index = ( (j/4)* exclusionStreamWidth + i ); // index is the x coordinate!
int joffset = j % 4;
BrookOpenMMFloat flag;
switch( joffset ) {
case 0:
flag = (BrookOpenMMFloat) 2.0;
break;
case 1:
flag = (BrookOpenMMFloat) 3.0;
break;
case 2:
flag = (BrookOpenMMFloat) 5.0;
break;
case 3 :
flag = (BrookOpenMMFloat) 7.0;
break;
}
exclusion[index] /= flag;
return DefaultReturnValue;
}
/**
* Initialize exclusions
*
* @param exclusions vector of sets containing exclusions (1 set entry for every particle)
* @param platform Brook platform
* @param log optional Log file reference
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int BrookNonBonded::_initializeExclusions( const std::vector<std::set<int> >& exclusionsVector, const Platform& platform ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookNonBonded::_initializeExclusions";
static const int debug = 0;
// ---------------------------------------------------------------------------------------
if( debug && getLog() ){
(void) fprintf( getLog(), "%s exclusions vector size=%d\n", methodName.c_str(), exclusionsVector.size() );
}
int exclusionStreamSize = getExclusionStreamSize();
if( exclusionStreamSize < 1 ){
std::stringstream message;
message << methodName << " exclusionStreamSize=" << exclusionStreamSize << " is not set.";
throw OpenMMException( message.str() );
return ErrorReturnValue;
}
// allocate and initialize exclusions array
BrookOpenMMFloat* exclusions = new BrookOpenMMFloat[exclusionStreamSize];
for( unsigned int ii = 0; ii < (unsigned int) exclusionStreamSize; ii++ ){
exclusions[ii] = (BrookOpenMMFloat) 210.0f;
}
// pack in values
int exclusionStreamWidth = getExclusionStreamWidth();
int numberOfParticles = getNumberOfParticles();
int particleStreamSize = getParticleStreamSize();
for( unsigned int ii = 0; ii < exclusionsVector.size(); ii++ ){
set<int> exclusionIndices = exclusionsVector[ii];
//(void) fprintf( getLog(), "%s particles=%d excludeSz=%d\n", methodName.c_str(), ii, exclusionIndices.size() );
int hitII = 0;
for( set<int>::const_iterator jj = exclusionIndices.begin(); jj != exclusionIndices.end(); jj++ ){
//(void) fprintf( getLog(), "%s particles=%d exclude=%d\n", methodName.c_str(), ii, *jj );
_setExclusion( ii, *jj, exclusionStreamWidth, exclusions );
if( *jj == ii )hitII = 1;
}
if( !hitII ){
_setExclusion( ii, ii, exclusionStreamWidth, exclusions );
}
// explicitly exclude junk particles from interacting w/ particle ii
for( int jj = numberOfParticles; jj < particleStreamSize; jj++ ){
_setExclusion( ii, jj, exclusionStreamWidth, exclusions );
}
}
// explicitly exclude junk particles from interacting w/ all particles
for( int ii = numberOfParticles; ii < particleStreamSize; ii++ ){
for( int jj = 0; jj < particleStreamSize; jj++ ){
_setExclusion( ii, jj, exclusionStreamWidth, exclusions );
}
}
// diagnostics
if( 1 && debug && getLog() ){
FILE* log = getLog();
(void) fprintf( log, "%s particles=%d excl=%d exStrSz=%d w=%d atmStrSz=%d\n", methodName.c_str(), numberOfParticles, exclusionsVector.size(),
exclusionStreamSize, exclusionStreamWidth, particleStreamSize );
/*
for( int ii = 0; ii < exclusionStreamSize; ii++ ){
int index = ii/exclusionStreamWidth;
int offset = ii - index*exclusionStreamWidth;
(void) fprintf( log, " %6d %6d [%6d %6d] %10.0f\n", ii, offset, index*4, index*4+3, exclusions[ii] );
}
*/
for( int ii = 0; ii < numberOfParticles; ii++ ){
(void) fprintf( log, "%6d ", ii );
int count = 0;
for( int jj = 0; jj <= numberOfParticles/4; jj++ ){
int index = jj*exclusionStreamWidth + ii;
(void) fprintf( log, " [%4d %4d] %5.1f", jj*4, jj*4+3, exclusions[index] );
int excludeValue = (int) (exclusions[index] + 0.01);
if( (excludeValue % 2) )count++;
if( (jj*4+1) < numberOfParticles && (excludeValue % 3) )count++;
if( (jj*4+2) < numberOfParticles && (excludeValue % 5) )count++;
if( (jj*4+3) < numberOfParticles && (excludeValue % 7) )count++;
}
(void) fprintf( log, " TtlExcl=%d\n", count );
}
(void) fflush( log );
}
// load stream
_nonbondedStreams[ExclusionStream]->loadFromArray( exclusions );
delete[] exclusions;
return DefaultReturnValue;
}
/**
* Set sigma & epsilon given c6 & c12 (geometric rule)
*
* @param c6 vdw c6
* @param c12 vdw c12
* @param sigma massaged sigma
* @param epsilon massaged epsilon
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int BrookNonBonded::_setSigmaEpsilon( double c6, double c12, double* sigma , double* epsilon ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookNonBonded::_setSigmaEpsilon";
// ---------------------------------------------------------------------------------------
if( fabs( c12 ) < 1.0e-04 ){
*sigma = 1.0;
*epsilon = 0.0;
} else {
//*sigma = 0.5*pow( c12/c6, 1.0/6.0 );
//*epsilon = sqrt( c6*c6/c12 );
*sigma = 0.5*c6;
*epsilon = 2.0*sqrt( c12 );
}
return DefaultReturnValue;
}
/**
* Initialize vdw & charge
*
* @param exclusions vector of sets containing exclusions (1 set entry for every particle)
* @param platform platform
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int BrookNonBonded::_initializeVdwAndCharge( const vector<vector<double> >& nonbondedParameters, const Platform& platform ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookNonBonded::_initializeVdwAndCharge";
static const int debug = 0;
// ---------------------------------------------------------------------------------------
if( debug && getLog() ){
(void) fprintf( getLog(), "%s nonbonded vector size=%d\n", methodName.c_str(), nonbondedParameters.size() );
}
int particleStreamSize = getParticleStreamSize();
// allocate and initialize vdw & charge array
unsigned int vdwParametersSize = 2*particleStreamSize;
BrookOpenMMFloat* vdwParameters = new BrookOpenMMFloat[vdwParametersSize];
memset( vdwParameters, 0, sizeof( BrookOpenMMFloat )*vdwParametersSize );
BrookOpenMMFloat* charges = new BrookOpenMMFloat[particleStreamSize];
memset( charges, 0, sizeof( BrookOpenMMFloat )*particleStreamSize );
// ---------------------------------------------------------------------------------------
// pack in values
int numberOfParticles = getNumberOfParticles();
int trackingIndex = 0;
double sigma, epsilon;
for( unsigned int ii = 0; ii < nonbondedParameters.size(); ii++ ){
vector<double> nonbondedParameterVector
= nonbondedParameters[ii];
double c6 = nonbondedParameterVector[1];
double c12 = nonbondedParameterVector[2];
double charge = nonbondedParameterVector[0];
/*
double charge = nonbondedParameterVector[0];
double sigma = nonbondedParameterVector[1];
double epsilon = nonbondedParameterVector[2];
*/
// geometric combination rules
_setSigmaEpsilon( c6, c12, &sigma, &epsilon );
vdwParameters[trackingIndex++] = (BrookOpenMMFloat) sigma;
vdwParameters[trackingIndex++] = (BrookOpenMMFloat) epsilon;
charges[ii] = (BrookOpenMMFloat) charge;
}
// set outlier particles
for( unsigned int ii = nonbondedParameters.size(); ii < (unsigned int) particleStreamSize; ii++ ){
vdwParameters[trackingIndex++] = (BrookOpenMMFloat) 1.0;
vdwParameters[trackingIndex++] = (BrookOpenMMFloat) 0.0;
}
// ---------------------------------------------------------------------------------------
// load stream
_nonbondedStreams[OuterVdwStream]->loadFromArray( vdwParameters );
_nonbondedStreams[ChargeStream]->loadFromArray( charges );
// diagnostics
if( 1 && debug && getLog() ){
FILE* log = getLog();
int trackingIndex = 0;
(void) fprintf( log, "%s particles=%d strSz=%d\n vdw[Sig Eps] Q\n", methodName.c_str(), numberOfParticles, particleStreamSize );
for( int ii = 0; ii < particleStreamSize; ii++, trackingIndex += 2 ){
(void) fprintf( log, " %d %10.3f %10.3f %10.3f\n", ii, vdwParameters[trackingIndex], vdwParameters[trackingIndex+1], charges[ii] );
}
(void) fflush( log );
}
delete[] vdwParameters;
delete[] charges;
return DefaultReturnValue;
}
/**
* Initialize vdw & charge
*
* @param exclusions vector of sets containing exclusions (1 set entry for every particle)
* @param platform platform
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int BrookNonBonded::_initializeJStreamVdw( const vector<vector<double> >& nonbondedParameters, const Platform& platform ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookNonBonded::_initializeJStreamVdw";
static const int debug = 0;
// ---------------------------------------------------------------------------------------
if( debug && getLog() ){
(void) fprintf( getLog(), "%s nonbonded vector size=%d\n", methodName.c_str(), nonbondedParameters.size() );
}
int jStreamSize = getJStreamSize();
// allocate and initialize vdw & charge array
unsigned int jParametersSize = 4*jStreamSize;
BrookOpenMMFloat* sigmaParameters = new BrookOpenMMFloat[jParametersSize];
//memset( sigmaParameters, 0, sizeof( BrookOpenMMFloat )*jParametersSize );
BrookOpenMMFloat* epsilonParameters = new BrookOpenMMFloat[jParametersSize];
//memset( epsilonParameters, 0, sizeof( BrookOpenMMFloat )*jParametersSize );
// ---------------------------------------------------------------------------------------
// pack in values
int numberOfParticles = getNumberOfParticles();
int trackingIndex = 0;
double sigma, epsilon;
for( unsigned int ii = 0; ii < nonbondedParameters.size(); ii++ ){
vector<double> nonbondedParameterVector
= nonbondedParameters[ii];
double c6 = nonbondedParameterVector[1];
double c12 = nonbondedParameterVector[2];
//double sigma = nonbondedParameterVector[1];
//double epsilon = nonbondedParameterVector[2];
// geometric combination rules
_setSigmaEpsilon( c6, c12, &sigma, &epsilon );
sigmaParameters[ii] = (BrookOpenMMFloat) sigma;
epsilonParameters[ii] = (BrookOpenMMFloat) epsilon;
}
// set outlier particles
for( unsigned int ii = nonbondedParameters.size(); ii < (unsigned int) jParametersSize; ii++ ){
sigmaParameters[ii] = (BrookOpenMMFloat) 1.0;
epsilonParameters[ii] = (BrookOpenMMFloat) 0.0;
}
// ---------------------------------------------------------------------------------------
// load streams
_nonbondedStreams[InnerSigmaStream]->loadFromArray( sigmaParameters );
_nonbondedStreams[InnerEpsilonStream]->loadFromArray( epsilonParameters );
// diagnostics
if( 1 && debug && getLog() ){
FILE* log = getLog();
int trackingIndex = 0;
(void) fprintf( log, "%s particles=%d strSz=%d\n Innervdw[Sig Eps]\n", methodName.c_str(), numberOfParticles, jStreamSize );
for( unsigned int ii = 0; ii < jParametersSize; ii++ ){
(void) fprintf( log, " %d %10.3f %10.3f\n", ii, sigmaParameters[ii], epsilonParameters[ii] );
}
(void) fflush( log );
}
delete[] sigmaParameters;
delete[] epsilonParameters;
return DefaultReturnValue;
}
/*
* Setup of nonbonded ixns
*
* @param numberOfParticles number of particles
* @param nonbondedParameters vector of nonbonded parameters [particleI][0=c6]
* [particleI][1=c12]
* [particleI][2=charge]
* @param platform Brook platform
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
* */
int BrookNonBonded::setup( int numberOfParticles, const std::vector<std::vector<double> >& nonbondedParameters,
const std::vector<std::set<int> >& exclusions, const Platform& platform ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookNonBonded::setup";
// ---------------------------------------------------------------------------------------
setNumberOfParticles( numberOfParticles );
_initializeStreamSizes( numberOfParticles, platform );
_initializeStreams( platform );
_initializeExclusions( exclusions, platform );
_initializeVdwAndCharge( nonbondedParameters, platform );
_initializeJStreamVdw( nonbondedParameters, platform );
setIsActive( 1 );
return DefaultReturnValue;
}
/*
* Setup of stream dimensions for exclusion stream
*
* @param particleStreamSize particle stream size
* @param particleStreamWidth particle stream width
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
* */
int BrookNonBonded::_initializeExclusionStreamSize( int particleStreamSize, int particleStreamWidth ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookNonBonded::_initializeExclusionStreamSize";
//static const int debug = 1;
// ---------------------------------------------------------------------------------------
_exclusionStreamWidth = particleStreamSize;
int innerUnroll = getInnerLoopUnroll();
if( innerUnroll < 1 ){
std::stringstream message;
message << methodName << " innerUnrolls=" << innerUnroll << " is less than 1.";
throw OpenMMException( message.str() );
return ErrorReturnValue;
}
_exclusionStreamHeight = _exclusionStreamWidth/innerUnroll;
_exclusionStreamSize = _exclusionStreamWidth*_exclusionStreamHeight;
return DefaultReturnValue;
}
/*
* Setup of j-stream dimensions
*
* @param particleStreamSize particle stream size
* @param particleStreamWidth particle stream width
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
* @throw OpenMMException if jStreamWidth < 1 || innerUnroll < 1
*
* */
int BrookNonBonded::_initializeJStreamSize( int particleStreamSize, int particleStreamWidth ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookNonBonded::_initializeJStreamSize";
// ---------------------------------------------------------------------------------------
// validate stream width & inner unroll
int jStreamWidth = getJStreamWidth();
if( jStreamWidth < 1 ){
std::stringstream message;
message << methodName << " jStreamWidth=" << jStreamWidth << " is less than 1.";
throw OpenMMException( message.str() );
return ErrorReturnValue;
}
int innerUnroll = getInnerLoopUnroll();
if( innerUnroll < 1 ){
std::stringstream message;
message << methodName << " innerUnroll=" << innerUnroll << " is less than 1.";
throw OpenMMException( message.str() );
return ErrorReturnValue;
}
// set dimesnions
_jStreamSize = particleStreamSize/innerUnroll;
_jStreamHeight = _jStreamSize/jStreamWidth;
_jStreamHeight += ( (_jStreamSize % _jStreamWidth) ? 1 : 0 );
_jStreamSize = jStreamWidth*_jStreamHeight;
return DefaultReturnValue;
}
/*
* Setup of outer vdw stream size
*
* @param particleStreamSize particle stream size
* @param particleStreamWidth particle stream width
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
* @throw OpenMMException if jStreamWidth < 1 || innerUnroll < 1
*
* */
int BrookNonBonded::_initializeOuterVdwStreamSize( int particleStreamSize, int particleStreamWidth ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookNonBonded::initializeOuterVdwStreamSize";
// ---------------------------------------------------------------------------------------
// validate stream width & inner unroll
/*
int jStreamWidth = getJStreamWidth();
if( jStreamWidth < 1 ){
std::stringstream message;
message << methodName << " jStreamWidth=" << jStreamWidth << " is less than 1.";
throw OpenMMException( message.str() );
return ErrorReturnValue;
}
int innerUnroll = getInnerLoopUnroll();
if( innerUnroll < 1 ){
std::stringstream message;
message << methodName << " innerUnroll=" << innerUnroll << " is less than 1.";
throw OpenMMException( message.str() );
return ErrorReturnValue;
}
// set dimesnions
_jStreamSize = particleStreamSize/innerUnroll;
_jStreamHeight = _jStreamSize/jStreamWidth;
_jStreamHeight += ( (_jStreamSize % _jStreamWidth) ? 1 : 0 );
_jStreamSize = jStreamWidth*_jStreamHeight;
*/
return DefaultReturnValue;
}
/*
* Setup of stream dimensions for partial force streams
*
* @param particleStreamSize particle stream size
* @param particleStreamWidth particle stream width
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
* */
int BrookNonBonded::_initializePartialForceStreamSize( int particleStreamSize, int particleStreamWidth ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookNonBonded::_initializePartialForceStreamSize";
// ---------------------------------------------------------------------------------------
int innerUnroll = getInnerLoopUnroll();
if( innerUnroll < 1 ){
std::stringstream message;
message << methodName << " innerUnrolls=" << innerUnroll << " is less than 1.";
throw OpenMMException( message.str() );
return ErrorReturnValue;
}
if( _partialForceStreamWidth < 1 ){
std::stringstream message;
message << methodName << " partial force stream width=" << _partialForceStreamWidth << " is less than 1.";
throw OpenMMException( message.str() );
return ErrorReturnValue;
}
_partialForceStreamSize = particleStreamSize*getDuplicationFactor()/innerUnroll;
_partialForceStreamHeight = _partialForceStreamSize/_partialForceStreamWidth;
_partialForceStreamHeight += ( (_partialForceStreamSize % _partialForceStreamWidth) ? 1 : 0);
return DefaultReturnValue;
}
/*
* Get contents of object
*
* @param level level of dump
*
* @return string containing contents
*
**/
std::string BrookNonBonded::getContentsString( int level ) const {
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookNonBonded::getContentsString";
static const unsigned int MAX_LINE_CHARS = 256;
char value[MAX_LINE_CHARS];
static const char* Set = "Set";
static const char* NotSet = "Not set";
// ---------------------------------------------------------------------------------------
std::stringstream message;
std::string tab = " ";
#ifdef _MSC_VER
#define LOCAL_SPRINTF(a,b,c) sprintf_s( (a), MAX_LINE_CHARS, (b), (c) );
#else
#define LOCAL_SPRINTF(a,b,c) sprintf( (a), (b), (c) );
#endif
(void) LOCAL_SPRINTF( value, "%d", getNumberOfParticles() );
message << _getLine( tab, "Number of particles:", value );
(void) LOCAL_SPRINTF( value, "%d", getNumberOfForceStreams() );
message << _getLine( tab, "Number of force streams:", value );
(void) LOCAL_SPRINTF( value, "%d", getDuplicationFactor() );
message << _getLine( tab, "Duplication factor:", value );
(void) LOCAL_SPRINTF( value, "%d", getInnerLoopUnroll () )
message << _getLine( tab, "Inner loop unroll:", value );
(void) LOCAL_SPRINTF( value, "%d", getOuterLoopUnroll() )
message << _getLine( tab, "Outer loop unroll:", value );
(void) LOCAL_SPRINTF( value, "%d", getParticleSizeCeiling() );
message << _getLine( tab, "Particle ceiling:", value );
(void) LOCAL_SPRINTF( value, "%d", getParticleStreamWidth() );
message << _getLine( tab, "Particle stream width:", value );
(void) LOCAL_SPRINTF( value, "%d", getParticleStreamHeight() );
message << _getLine( tab, "Particle stream height:", value );
(void) LOCAL_SPRINTF( value, "%d", getParticleStreamSize() );
message << _getLine( tab, "Particle stream size:", value );
(void) LOCAL_SPRINTF( value, "%d", getJStreamWidth() );
message << _getLine( tab, "J-stream width:", value );
(void) LOCAL_SPRINTF( value, "%d", getJStreamHeight() );
message << _getLine( tab, "J-stream height:", value );
(void) LOCAL_SPRINTF( value, "%d", getJStreamSize() );
message << _getLine( tab, "J-stream size:", value );
(void) LOCAL_SPRINTF( value, "%d", getPartialForceStreamWidth() );
message << _getLine( tab, "Partial force stream width:", value );
(void) LOCAL_SPRINTF( value, "%d", getPartialForceStreamHeight() );
message << _getLine( tab, "Partial force stream height:", value );
(void) LOCAL_SPRINTF( value, "%d", getPartialForceStreamSize() );
message << _getLine( tab, "Partial force stream size:", value );
(void) LOCAL_SPRINTF( value, "%d", getExclusionStreamWidth() );
message << _getLine( tab, "Exclusion stream width:", value );
//(void) LOCAL_SPRINTF( value, "%d", getExclusionStreamHeight() );
//message << _getLine( tab, "Exclusion stream height:", value );
(void) LOCAL_SPRINTF( value, "%d", getExclusionStreamSize() );
message << _getLine( tab, "Exclusion stream size:", value );
message << _getLine( tab, "Log:", (getLog() ? Set : NotSet) );
message << _getLine( tab, "ExclusionStream:", (getExclusionStream() ? Set : NotSet) );
message << _getLine( tab, "VdwStream:", (getOuterVdwStream() ? Set : NotSet) );
message << _getLine( tab, "ChargeStream:", (getChargeStream() ? Set : NotSet) );
message << _getLine( tab, "SigmaStream:", (getInnerSigmaStream() ? Set : NotSet) );
message << _getLine( tab, "EpsilonStream:", (getInnerEpsilonStream() ? Set : NotSet) );
for( int ii = 0; ii < LastStreamIndex; ii++ ){
message << std::endl;
if( _nonbondedStreams[ii] ){
message << _nonbondedStreams[ii]->getContentsString( );
}
}
// force streams
for( int ii = 0; ii < getNumberOfForceStreams(); ii++ ){
char description[256];
(void) LOCAL_SPRINTF( description, "PartialForceStream %d", ii );
message << _getLine( tab, description, (isForceStreamSet(ii) ? Set : NotSet) );
}
for( int ii = 0; ii < getNumberOfForceStreams(); ii++ ){
message << std::endl;
if( _nonbondedForceStreams[ii] ){
message << _nonbondedForceStreams[ii]->getContentsString( );
}
}
#undef LOCAL_SPRINTF
return message.str();
}
/**
* Compute forces
*
* @param context ContextImpl context
*
*/
void BrookNonBonded::computeForces( BrookStreamImpl& positionStream, BrookStreamImpl& forceStream ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookNonBonded::computeForces";
static int printOn = 0;
static const int MaxErrorMessages = 2;
static int ErrorMessages = 0;
FILE* log;
// ---------------------------------------------------------------------------------------
if( printOn && getLog() ){
log = getLog();
} else {
printOn = 0;
}
// nonbonded forces
float epsfac = 138.935485f;
BrookFloatStreamInternal** nonbondedForceStreams = getForceStreams();
knbforce_CDLJ4(
(float) getNumberOfParticles(),
(float) getParticleSizeCeiling(),
(float) getDuplicationFactor(),
(float) getParticleStreamHeight( ),
(float) getParticleStreamWidth( ),
(float) getJStreamWidth( ),
(float) getPartialForceStreamWidth( ),
epsfac,
positionStream.getBrookStream(),
getChargeStream()->getBrookStream(),
getOuterVdwStream()->getBrookStream(),
getInnerSigmaStream()->getBrookStream(),
getInnerEpsilonStream()->getBrookStream(),
getExclusionStream()->getBrookStream(),
nonbondedForceStreams[0]->getBrookStream(),
nonbondedForceStreams[1]->getBrookStream(),
nonbondedForceStreams[2]->getBrookStream(),
nonbondedForceStreams[3]->getBrookStream()
);
/*
float zerof = 0.0f;
nonbondedForceStreams[0]->fillWithValue( &zerof );
nonbondedForceStreams[1]->fillWithValue( &zerof );
nonbondedForceStreams[2]->fillWithValue( &zerof );
nonbondedForceStreams[3]->fillWithValue( &zerof );
*/
// diagnostics
if( printOn ){
//static int step = 0;
//if( step++ < 1 ){
FILE* log = getLog();
//FILE* log = stderr;
(void) fprintf( log, "%s\n", methodName.c_str() ); (void) fflush( log );
(void) fprintf( log, "Post knbforce_CDLJ4: particles=%6d ceiling=%3d dupFac=%3d\n", getNumberOfParticles(),
getParticleSizeCeiling(),
getDuplicationFactor() );
(void) fprintf( log, " hght=%6d width=%3d jWid=%3d\n", getParticleStreamHeight( ),
getParticleStreamWidth( ),
getJStreamWidth( ) );
(void) fprintf( log, " pFrc=%6d eps=%12.5e\n", getPartialForceStreamWidth( ), epsfac );
(void) fprintf( log, "%s Final NB & bonded forces\n", methodName.c_str() );
(void) fprintf( log, "Forces here should be zero (pregather)\n" );
BrookStreamInternal* brookStreamInternalF = forceStream.getBrookStreamInternal();
brookStreamInternalF->printToFile( log );
(void) fprintf( log, "Coords\n" );
brookStreamInternalF = positionStream.getBrookStreamInternal();
brookStreamInternalF->printToFile( log );
/*
void* dataArrayV = brookStreamInternalF->getData( 1 );
float* ddd = (float*) dataArrayV;
int idx1 = 0;
int idx2 = 3;
(void) fprintf( log, "%d %d %.5e\n", idx1/3, idx2/3, computeDistance( idx1, idx2, ddd ) );
*/
(void) fprintf( log, "\nOuterVdwStreamd\n" );
getOuterVdwStream()->printToFile( log );
(void) fprintf( log, "\nInnerSigmaStream\n" );
getInnerSigmaStream()->printToFile( log );
(void) fprintf( log, "\nInnerEpsilonStream\n" );
getInnerEpsilonStream()->printToFile( log );
// (void) fprintf( log, "\nExclusionStream\n" );
// getExclusionStream()->printToFile( log );
(void) fprintf( log, "\nChargeStream\n" );
getChargeStream()->printToFile( log );
for( int ii = 0; ii < 4; ii++ ){
(void) fprintf( log, "\nForce stream %d\n", ii );
nonbondedForceStreams[ii]->printToFile( log );
}
(void) fflush( log );
}
// ---------------------------------------------------------------------------------------
// gather forces
kMergeFloat3_4_nobranch( (float) getDuplicationFactor(),
(float) getParticleStreamWidth(),
(float) getPartialForceStreamWidth(),
(float) getNumberOfParticles(),
(float) getParticleSizeCeiling(),
(float) getOuterLoopUnroll(),
nonbondedForceStreams[0]->getBrookStream(),
nonbondedForceStreams[1]->getBrookStream(),
nonbondedForceStreams[2]->getBrookStream(),
nonbondedForceStreams[3]->getBrookStream(),
forceStream.getBrookStream() );
// diagnostics
if( printOn ){
(void) fprintf( log, "\n%s NB forces\n", methodName.c_str() );
BrookStreamInternal* brookStreamInternalF = forceStream.getBrookStreamInternal();
brookStreamInternalF->printToFile( log );
(void) fprintf( log, "\n%s Done\n", methodName.c_str() ); (void) fflush( log );
}
return;
}
/*
* Utility to compute distances between two points
*
* @param idx1 index of point1 into array
* @param idx2 index of point2 into array
* @param coords array of points p1={coord[0], coord[1], coord[2] },
* p2={coord[3], coord[4], coord[5] },
* p3={coord[6], coord[7], coord[8] }
*
* @return distance
*
**/
float BrookNonBonded::_computeDistance( int idx1, int idx2, float* coords ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookNonBonded::_computeDistance";
float d1 = sqrtf(
(coords[idx1]-coords[idx2])*(coords[idx1]-coords[idx2]) +
(coords[idx1+1]-coords[idx2+1])*(coords[idx1+1]-coords[idx2+1]) +
(coords[idx1+2]-coords[idx2+2])*(coords[idx1+2]-coords[idx2+2]) );
return d1;
// ---------------------------------------------------------------------------------------
}
#ifndef OPENMM_BROOK_NONBONDED_H_
#define OPENMM_BROOK_NONBONDED_H_
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include <vector>
#include <set>
#include "BrookStreamImpl.h"
#include "BrookPlatform.h"
#include "BrookCommon.h"
namespace OpenMM {
/**
* This kernel is invoked by NonbondedForce to calculate the forces acting on the system.
*/
class BrookNonBonded : public BrookCommon {
public:
BrookNonBonded( );
~BrookNonBonded();
/**
* Return number of force streams
*
* @return number of force streams
*
*/
int getNumberOfForceStreams( void ) const;
/**
* Get duplication factor
*
* @return duplication factor
*
*/
int getDuplicationFactor( void ) const;
/**
* Get particle ceiling parameter
*
* @return particle ceiling parameter
*
*/
int getParticleSizeCeiling( void ) const;
/**
* Get outer loop unroll
*
* @return outer loop unroll (fixed value)
*
*/
int getOuterLoopUnroll( void ) const;
/**
* Set outer loop unroll
*
* @param outer loop unroll (fixed value)
*
* @return updated outer loop unroll (fixed value)
*
*/
int setOuterLoopUnroll( int outerUnroll );
/**
* Return unrolling for inner loops
*
* @return outer loop unrolling
*/
int getInnerLoopUnroll( void ) const;
/**
* Get j-stream width
*
* @param platform platform reference
*
* @return j-stream width
*/
int getJStreamWidth( const Platform& platform );
/**
* Get j-stream width
*
* @return j-stream width
*/
int getJStreamWidth( void ) const;
/**
* Get j-stream height
*
* @param platform platform reference
*
* @return j-stream height
*/
int getJStreamHeight( const Platform& platform );
/**
* Get j-stream height
*
* @return j-stream height
*/
int getJStreamHeight( void ) const;
/**
* Get j-stream size
*
* @param platform platform reference
*
* @return j-stream size
*/
int getJStreamSize( const Platform& platform );
/**
* Get j-stream size
*
* @return j-stream size
*/
int getJStreamSize( void ) const;
/**
* Get partial force stream width
*
* @param platform platform reference
*
* @return partial force stream width
*/
int getPartialForceStreamWidth( const Platform& platform );
/**
* Get partial force stream width
*
* @return partial force stream width
*/
int getPartialForceStreamWidth( void ) const;
/**
* Get partial force stream height
*
* @param platform platform reference
*
* @return partial force stream height
*/
int getPartialForceStreamHeight( const Platform& platform );
/**
* Get partial force stream height
*
* @return partial force stream height
*/
int getPartialForceStreamHeight( void ) const;
/**
* Get partial force stream size
*
* @param platform platform reference
*
* @return partial force stream size
*/
int getPartialForceStreamSize( const Platform& platform );
/**
* Get partial force stream size
*
* @return partial force stream size
*/
int getPartialForceStreamSize( void ) const;
/**
* Get partial force stream size
*
* @return partial force stream size
*/
/**
* Get exclusion stream width
*
* @return exclusion stream width
*/
int getExclusionStreamWidth( void ) const;
/**
* Get exclusion stream size
*
* @return exclusion stream size
*/
int getExclusionStreamSize( void ) const;
/**
* Get exclusion stream
*
* @return exclusion stream
*
*/
BrookFloatStreamInternal* getExclusionStream( void ) const;
/**
* Get vdw stream
*
* @return vdw stream
*
*/
BrookFloatStreamInternal* getOuterVdwStream( void ) const;
/**
* Get charge stream
*
* @return charge stream
*
*/
BrookFloatStreamInternal* getChargeStream( void ) const;
/**
* Get sigma-eps stream
*
* @return sigma-eps stream
*
*/
BrookFloatStreamInternal* getInnerSigmaStream( void ) const;
/**
* Get epsilon stream
*
* @return epsilon stream
*
*/
BrookFloatStreamInternal* getInnerEpsilonStream( void ) const;
/**
* Get force streams
*
* @return force streams
*
*/
BrookFloatStreamInternal** getForceStreams( void );
/**
* Compute forces
*
*/
void computeForces( BrookStreamImpl& positionStream, BrookStreamImpl& forceStream );
/**
* Return true if force[index] stream is set
*
* @return true if index is valid && force[index] stream is set; else false
*
*/
int isForceStreamSet( int index ) const;
/*
* Setup of nonbonded ixns
*
* @param numberOfParticles number of particles
* @param nonbondedParameters vector of nonbonded parameters [particleI][0=c6]
* [particleI][1=c12]
* [particleI][2=charge]
* @param platform Brook platform
* @param log optional Log file reference
*
* @return nonzero value if error
* */
int setup( int numberOfParticles, const std::vector<std::vector<double> >& nonbondedParameters,
const std::vector<std::set<int> >& exclusions, const Platform& platform );
/**
* Set duplication factor
*
* @param duplication factor
*
* @return DefaultReturnValue
*
*/
int setDuplicationFactor( int duplicationFactor );
/*
* Get contents of object
*
* @param level of dump
*
* @return string containing contents
*
* */
std::string getContentsString( int level = 0 ) const;
private:
// fixed number of force streams
static const int NumberOfForceStreams = 4;
// streams indices
enum {
ExclusionStream,
OuterVdwStream,
ChargeStream,
InnerSigmaStream,
InnerEpsilonStream,
LastStreamIndex
};
// particle ceiling
int _particleSizeCeiling;
// unroll in i/j dimensions
int _outerUnroll;
int _innerUnroll;
// duplication factor
int _duplicationFactor;
// force stream width
int _partialForceStreamWidth;
int _partialForceStreamHeight;
int _partialForceStreamSize;
// exclusions stream dimensions
int _exclusionStreamWidth;
int _exclusionStreamHeight;
int _exclusionStreamSize;
// j-stream dimensions
int _jStreamWidth;
int _jStreamHeight;
int _jStreamSize;
// internal streams
BrookFloatStreamInternal* _nonbondedStreams[LastStreamIndex];
BrookFloatStreamInternal* _nonbondedForceStreams[NumberOfForceStreams];
/*
* Setup of stream dimensions for exclusion stream
*
* @param particleStreamSize particle stream size
* @param particleStreamWidth particle stream width
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
* */
int _initializeExclusionStreamSize( int particleStreamSize, int particleStreamWidth );
/**
* Initialize exclusion stream dimensions and stream
*
* @param platform platform
*
* @return nonzero value if error
*
*/
int _initializeExclusionStream( const Platform& platform );
/**
* Set exclusion (4x4)
*
* @param i particle i index
* @param j particle j index
* @param exclusionStreamWidth exclusion stream width
* @param exclusion array of packed exclusions
*
* @return nonzero value if error
*
*/
int _setExclusion( int i, int j, int exclusionStreamWidth, BrookOpenMMFloat* exclusion );
/**
* Initialize exclusions
*
* @param exclusions vector of sets containing exclusions (1 set entry for every particle)
* @param platform platform
*
* @return nonzero value if error
*
*/
int _initializeExclusions( const std::vector<std::set<int> >& exclusionsVector, const Platform& platform );
/**
* Initialize stream dimensions
*
* @param numberOfParticles number of particles
* @param platform platform
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int _initializeStreamSizes( int numberOfParticles, const Platform& platform );
/**
* Initialize stream dimensions and streams
*
* @param platform platform
*
* @return nonzero value if error
*
*/
int _initializeStreams( const Platform& platform );
/*
* Setup of j-stream dimensions
*
* @param particleStreamSize particle stream size
* @param particleStreamWidth particle stream width
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
* @throw OpenMMException if jStreamWidth < 1 || innerUnroll < 1
*
* */
int _initializeJStreamSize( int particleStreamSize, int particleStreamWidth );
/*
* Setup of outer vdw stream size
*
* @param particleStreamSize particle stream size
* @param particleStreamWidth particle stream width
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
* @throw OpenMMException if jStreamWidth < 1 || innerUnroll < 1
*
* */
int _initializeOuterVdwStreamSize( int particleStreamSize, int particleStreamWidth );
/**
* Set sigma & epsilon given c6 & c12 (geometric rule)
*
* @param c6 vdw c6
* @param c12 vdw c12
* @param sigma massaged sigma
* @param epsilon massaged epsilon
*
* @return nonzero value if error
*
*/
int _setSigmaEpsilon( double c6, double c12, double* sigma , double* epsilon );
/**
* Initialize vdw & charge
*
* @param exclusions vector of sets containing exclusions (1 set entry for every particle)
* @param platform platform
*
* @return nonzero value if error
*
*/
int _initializeVdwAndCharge( const std::vector<std::vector<double> >& nonbondedParameters, const Platform& platform );
/**
* Initialize vdw & charge
*
* @param exclusions vector of sets containing exclusions (1 set entry for every particle)
* @param platform platform
*
* @return nonzero value if error
*
*/
int _initializeJStreamVdw( const std::vector<std::vector<double> >& nonbondedParameters, const Platform& platform );
/*
* Setup of stream dimensions for partial force streams
*
* @param particleStreamSize particle stream size
* @param particleStreamWidth particle stream width
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
* */
int _initializePartialForceStreamSize( int particleStreamSize, int particleStreamWidth );
/*
* Utility to compute distances between two points
*
* @param idx1 index of point1 into array
* @param idx2 index of point2 into array
* @param coord array of points p1={coord[0], coord[1], coord[2] },
* p2={coord[3], coord[4], coord[5] },
* p3={coord[6], coord[7], coord[8] }
*
* @return distance
*
* */
float _computeDistance( int idx1, int idx2, float* coord );
};
} // namespace OpenMM
#endif /* OPENMM_BROOK_NONBONDED_H_ */
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "BrookPlatform.h"
#include "BrookKernelFactory.h"
#include "OpenMMBrookInterface.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/OpenMMException.h"
#include "openmm/kernels.h"
#include "../../reference/src/SimTKUtilities/SimTKOpenMMRealType.h"
#include <brook/brook.hpp>
#include <stdlib.h>
#include <sstream>
#include <cctype>
#include <algorithm>
using namespace OpenMM;
extern "C" void initOpenMMPlugin() {
/*
CALuint numberOfDevices = 0;
// validateCALRuntime()
if( calDeviceGetCount( &numberOfDevices ) == CAL_RESULT_OK && numberOfDevices > 0 ){
Platform::registerPlatform(new BrookPlatform());
}
*/
}
/**
* BrookPlatformData constructor
*
*/
BrookPlatformData::BrookPlatformData( void ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookPlatformData::BrookPlatformData";
// ---------------------------------------------------------------------------------------
//_forceKernel = NULL;
_removeCOM = 0;
_useOBC = 0;
_hasBonds = 0;
_hasAngles = 0;
_hasPeriodicTorsions = 0;
_hasRB = 0;
_hasNonbonded = 0;
_cmMotionFrequency = 0;
}
/**
* Get _removeCOM flag
*
* @return _removeCOM
*
*/
int BrookPlatformData::removeCOM( void ) const {
return _removeCOM;
}
/**
* Get _useOBC flag
*
* @return _useOBC
*
*/
int BrookPlatformData::useOBC( void ) const {
return _useOBC;
}
/**
* Get _hasBonds flag
*
* @return _hasBonds
*
*/
int BrookPlatformData::hasBonds( void ) const {
return _hasBonds;
}
/**
* Get _hasAngles
*
* @return _hasAngles
*
*/
int BrookPlatformData::hasAngles( void ) const {
return _hasAngles;
}
/**
* Get _hasPeriodicTorsions
*
* @return _hasPeriodicTorsions
*
*/
int BrookPlatformData::hasPeriodicTorsions( void ) const {
return _hasPeriodicTorsions;
}
/**
* Get _hasRB
*
* @return _hasRB
*
*/
int BrookPlatformData::hasRB( void ) const {
return _hasRB;
}
/**
* Get _hasNonbonded
*
* @return _hasNonbonded
*
*/
int BrookPlatformData::hasNonbonded( void ) const {
return _hasNonbonded;
}
/**
* Get _cmMotionFrequency
*
* @return _cmMotionFrequency
*
*/
int BrookPlatformData::cmMotionFrequency( void ) const {
return _cmMotionFrequency;
}
/**
* Register BrookPlatform
*
* @return BrookPlatform instance
*
*/
BrookPlatform* registerBrookPlatform( void ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookPlatform::registerBrookPlatform";
// ---------------------------------------------------------------------------------------
BrookPlatform* platform = new BrookPlatform();
Platform::registerPlatform(platform);
return platform;
}
BrookPlatform* staticPlatform = registerBrookPlatform( );
/**
* BrookPlatform constructor
*
*/
BrookPlatform::BrookPlatform( ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookPlatform::BrookPlatform(0)";
// ---------------------------------------------------------------------------------------
_particleStreamWidth = DefaultParticleStreamWidth;
_minSuggestedThreads = -1;
_log = NULL;
// get Brook runtime
#ifdef WIN32
char* runtime;
size_t numberOfEnv;
_dupenv_s( &runtime, &numberOfEnv, "brt_runtime" );
#else
char* runtime = getenv( "brt_runtime" );
#endif
// if environment variable 'brt_runtime' not set, default to 'cal' settinh
if( runtime == NULL ){
runtime = _strdup( "cal" );
}
_initializeKernelFactory( );
_setBrookRuntime( runtime );
#ifdef WIN32
free( runtime );
#endif
}
/**
* BrookPlatform constructor
*
* @param defaultParticleStreamWidth stream width
* @param runtime Brook runtime (cal/cpu)
* @param log log file reference
*
*/
BrookPlatform::BrookPlatform( int particleStreamWidth, const std::string& runtime, FILE* log ) : _particleStreamWidth( particleStreamWidth ), _log( log ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookPlatform::BrookPlatform(2)";
// ---------------------------------------------------------------------------------------
_initializeKernelFactory( );
_setBrookRuntime( runtime );
}
/**
* BrookPlatform destructor
*
*/
BrookPlatform::~BrookPlatform( ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookPlatform::BrookPlatform";
// ---------------------------------------------------------------------------------------
}
/**
* Initialize kernel factory
*
*/
void BrookPlatform::_initializeKernelFactory( void ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookPlatform::_initializeKernelFactory";
// ---------------------------------------------------------------------------------------
BrookKernelFactory* factory = new BrookKernelFactory();
registerKernelFactory( CalcForcesAndEnergyKernel::Name(), factory );
registerKernelFactory( CalcHarmonicBondForceKernel::Name(), factory );
registerKernelFactory( CalcHarmonicAngleForceKernel::Name(), factory );
registerKernelFactory( CalcPeriodicTorsionForceKernel::Name(), factory );
registerKernelFactory( CalcRBTorsionForceKernel::Name(), factory );
registerKernelFactory( CalcNonbondedForceKernel::Name(), factory );
registerKernelFactory( CalcGBSAOBCForceKernel::Name(), factory );
registerKernelFactory( IntegrateVerletStepKernel::Name(), factory );
registerKernelFactory( IntegrateLangevinStepKernel::Name(), factory );
registerKernelFactory( UpdateStateDataKernel::Name(), factory );
// registerKernelFactory( IntegrateBrownianStepKernel::Name(), factory );
//registerKernelFactory( ApplyAndersenThermostatKernel::Name(), factory );
registerKernelFactory( CalcKineticEnergyKernel::Name(), factory );
registerKernelFactory( RemoveCMMotionKernel::Name(), factory );
}
/**
* Set & validate runtime
*
* @param runtime Brook runtime (cal/cpu)
*
* @throws exception if runtime is invalid
*/
void BrookPlatform::_setBrookRuntime( const std::string& runtime ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookPlatform::_setBrookRuntime";
// ---------------------------------------------------------------------------------------
// set & validate runtime
_runtime = runtime;
// lower case
std::transform( _runtime.begin(), _runtime.end(), _runtime.begin(), tolower );
if( _runtime != "cal" && _runtime != "cpu" ){
std::stringstream message;
message << methodName << " Brook runtime=" << _runtime << " not recognized.";
throw OpenMMException( message.str() );
}
if( 1 ){
//When compiling with cygwin/cl combo, doesn't
//always work from the environment, so I'm
//hardcoding it here. An alternative might be to getenv() in
//the gromacs code and pass it here. The cygwin getenv() hopefully
//will work more deterministically.
char* info_string = NULL;
int minSuggestedThreads;
brook::initialize( _runtime.c_str(), NULL, &info_string, &minSuggestedThreads );
FILE* log = getLog() ? getLog() : stderr;
(void) fprintf( log, "Using runtime %s; initializing Brook\n", _runtime.c_str() );
fprintf( log, "############\n\nBrook info_string:\n%s\n############\n", info_string );
(void) fflush( log );
if( minSuggestedThreads > 0 ){
_minSuggestedThreads = minSuggestedThreads;
}
} else {
FILE* log = getLog() ? getLog() : stderr;
(void) fprintf( log, "%s Brook initializing to runtime=<%s>\n", methodName.c_str(), _runtime.c_str() );
(void) fflush( log );
brook::initialize( _runtime.c_str(), NULL );
}
}
/**
* Return platform name
*
* @return "Brook"
*/
const std::string& BrookPlatform::getName() const {
static const std::string name = "Brook";
return name;
}
/**
* Get DuplicationFactor
*
* @param numberOfParticles number of particles
*
* @return DuplicationFactor
*/
int BrookPlatform::getDuplicationFactor( int numberOfParticles ) const {
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookPlatform::getDuplicationFactor";
// ---------------------------------------------------------------------------------------
// default value
int duplicationFactor = 4;
if( numberOfParticles < 65 ){
duplicationFactor = 1;
(void) fprintf( stderr, "%s forcing optimization parameter 'duplicationFactor' to %d since number of particles=%d < 65\n",
methodName.c_str(), duplicationFactor, numberOfParticles );
}
// set only if _minSuggestedThreads is available from board
if( _minSuggestedThreads > 0 ){
float threads = static_cast<float>( _minSuggestedThreads );
float numP = static_cast<float>( numberOfParticles );
float iUnroll = 4.0f;
float factor = (threads*iUnroll)/numP;
if( (factor*numP) < (threads*iUnroll) ){
factor += 1.0f;
}
if( factor <= 1.0f ){
duplicationFactor = 1;
} else {
duplicationFactor = static_cast<int>( ceil( factor*0.25f ) );
duplicationFactor *= 4;
}
duplicationFactor = 4;
// (void) fprintf( stderr, "getDuplicationFactor %.1f numiP=%.1f factor=%.1f duplicationFactor=%d\n", threads, numP, factor, duplicationFactor );
}
return duplicationFactor;
}
/**
* Return platform speed
*
* @return speed
*/
double BrookPlatform::getSpeed() const {
return 10.0;
}
/**
* Return particle stream width
*
* @return particle stream width
*/
int BrookPlatform::getParticleStreamWidth() const {
return _particleStreamWidth;
}
/**
* Return true if BrookPlatform supports double precison
*
* @return true if BrookPlatform supports double precison
*/
bool BrookPlatform::supportsDoublePrecision( void ) const {
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookPlatform::supportsDoublePrecision";
// ---------------------------------------------------------------------------------------
return (sizeof(RealOpenMM) >= sizeof(double));
}
/**
* Return Stream factory
*
*/
const StreamFactory& BrookPlatform::getDefaultStreamFactory( void ) const {
return _defaultStreamFactory;
}
/**
*
* Static method
*
* Return stream size and height given size of array and stream width
*
* @param size size of array
* @param streamWidth stream width
* @param outputHeight output stream height
*
* @return stream size; -1 if streamWidth < 1 || size < 1
*
*/
int BrookPlatform::getStreamSize( int size, int streamWidth, int* outputHeight ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookPlatform::getStreamSize";
// ---------------------------------------------------------------------------------------
if( streamWidth < 1 || size < 1 ){
return -1;
}
int height = size/streamWidth;
if( streamWidth*height < size ){
height++;
}
if( outputHeight ){
*outputHeight = height;
}
return height*streamWidth;
}
/**
* Get log file reference
*
* @return log file reference
*
*/
FILE* BrookPlatform::getLog( void ) const {
return _log;
}
/**
* Set log file reference
*
* @param log file reference
*
* @return DefaultReturnValue
*
*/
int BrookPlatform::setLog( FILE* log ){
_log = log;
return BrookPlatform::DefaultErrorValue;
}
/**
*
* This is called whenever a new Context is created. It gives the Platform a chance to initialize
* the context and store platform-specific data in it.
*
*/
void BrookPlatform::contextCreated( ContextImpl& context ) const {
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookPlatform::contextCreated";
// ---------------------------------------------------------------------------------------
int particles = context.getSystem().getNumParticles();
OpenMMBrookInterface* openMMBrookInterface = new OpenMMBrookInterface( getParticleStreamWidth(), getDuplicationFactor( particles ) );
//openMMBrookInterface->setLog( stderr );
context.setPlatformData( openMMBrookInterface );
}
/**
*
* This is called whenever a Context is deleted. It gives the Platform a chance to clean up
* any platform-specific data that was stored in it.
*
*/
void BrookPlatform::contextDestroyed( ContextImpl& context ) const {
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookPlatform::contextDestroyed";
// ---------------------------------------------------------------------------------------
}
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "BrookRandomNumberGenerator.h"
#include "../../reference/src/SimTKUtilities/SimTKOpenMMUtilities.h"
#include "openmm/OpenMMException.h"
#include "kernels/kupdatesd.h"
#include <sstream>
using namespace OpenMM;
using namespace std;
/**
*
* Constructor
*
*/
BrookRandomNumberGenerator::BrookRandomNumberGenerator( ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookRandomNumberGenerator::BrookRandomNumberGenerator";
// ---------------------------------------------------------------------------------------
// fixed for now
_numberOfRandomNumberStreams = 2;
_randomNumberGeneratorStreams = NULL;
// mark stream dimension variables as unset
_randomNumberStreamWidth = -1;
_randomNumberStreamHeight = -1;
_randomNumberStreamSize = -1;
_rvStreamIndex = 0;
_rvStreamOffset = 0;
_numberOfShuffles = 0;
//_maxShuffles = 0;
_maxShuffles = 100;
_loadBuffer = NULL;
_shuffleIndices = NULL;
for( int ii = 0; ii < LastStreamIndex; ii++ ){
_auxiliaryStreams[ii] = NULL;
}
// set randomNumber seed & generator
_randomNumberSeed = 1393;
//_randomNumberGenerator = Mersenne;
_randomNumberGenerator = Kiss;
//_randomNumberGenerator = FixedValue;
//SimTKOpenMMUtilities::setRandomNumberSeed( randomNumberSeed );
}
/**
* Destructor
*
*/
BrookRandomNumberGenerator::~BrookRandomNumberGenerator( ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookRandomNumberGenerator::~BrookRandomNumberGenerator";
// ---------------------------------------------------------------------------------------
for( int ii = 0; ii < LastStreamIndex; ii++ ){
delete _auxiliaryStreams[ii];
}
delete[] _randomNumberGeneratorStreams;
delete[] _loadBuffer;
delete[] _shuffleIndices;
}
/**
* Get number of random number streams
*
* @return number of random number streams
*
*/
int BrookRandomNumberGenerator::getNumberOfRandomNumberStreams( void ) const {
return _numberOfRandomNumberStreams;
}
/**
* Get random number stream width
*
* @return nndom number stream width
*
*/
int BrookRandomNumberGenerator::getRandomNumberStreamWidth( void ) const {
return _randomNumberStreamWidth;
}
/**
* Get random number stream height
*
* @return nndom number stream height
*
*/
int BrookRandomNumberGenerator::getRandomNumberStreamHeight( void ) const {
return _randomNumberStreamHeight;
}
/**
* Get random number seed
*
* @return random number seed
*/
unsigned long int BrookRandomNumberGenerator::getRandomNumberSeed( void ) const {
return _randomNumberSeed;
}
/**
* Increment random number seed
*
* @param increment amount to increment random number seed; default = 1
*
* @return updated random number seed
*/
unsigned long int BrookRandomNumberGenerator::incrementRandomNumberSeed( unsigned long int increment ){
_randomNumberSeed += increment;
return _randomNumberSeed;
}
/**
* Set random number seed
*
* @param new random number seed; default = 1
*
* @return random number seed
*/
unsigned long int BrookRandomNumberGenerator::setRandomNumberSeed( unsigned long int seed ){
_randomNumberSeed = seed;
return _randomNumberSeed;
}
/**
* Generate a random number using algorithm in Gromacs
*
* @param ig seed
*
* @return random number
*
*/
BrookOpenMMFloat BrookRandomNumberGenerator::_generateGromacsRandomNumber( unsigned long int* ig ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "\nBrookRandomNumberGenerator::_generateGromacsRandomNumber";
int irand;
int m = 100000000;
float rm = 100000000.0; /* same number as m, but real format */
int m1 = 10000;
int mult = 31415821;
BrookOpenMMFloat r;
int irandh,irandl,multh,multl;
// ---------------------------------------------------------------------------------------
unsigned long int igg = (*ig > 0) ? *ig : -1*(*ig);
irand = igg % m;
/* multiply irand by mult, but take into account that overflow
* must be discarded, and do not generate an error.
*/
irandh = irand / m1;
irandl = irand % m1;
multh = mult / m1;
multl = mult % m1;
irand = ((irandh*multl+irandl*multh) % m1) * m1 + irandl*multl;
irand = (irand + 1) % m;
/* convert irand to a real random number between 0 and 1. */
r = (BrookOpenMMFloat) (irand / 10);
r = r * 10 / rm;
if ((r <= 0) || (r > 1))
r = 0.0;
*ig = irand;
return r;
}
inline int MaxInt( unsigned int x, unsigned int y ){ return x > y ? x : y; }
/**
* Generate a random number using algorithm in Kiss code
* http://www.helsbreth.org/random/rng_kiss.html
*
* @param randomV1 output random value
* @param randomV2 output random value
* @param randomV3 output random value
* @param state state
*
*/
void BrookRandomNumberGenerator::_generateRandomsKiss( float* randomV1, float* randomV2, float* randomV3,
unsigned int state[4] ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "\nBrookRandomNumberGenerator::_generateRandomsKiss";
unsigned int carry = 0;
// ---------------------------------------------------------------------------------------
state[0] = state[0] * 69069 + 1;
state[1] ^= state[1] << 13;
state[1] ^= state[1] >> 17;
state[1] ^= state[1] << 5;
unsigned int k = (state[2] >> 2) + (state[3] >> 3) + (carry >> 2);
unsigned int m = state[3] + state[3] + state[2] + carry;
state[2] = state[3];
state[3] = m;
carry = k >> 30;
unsigned int z1 = MaxInt(state[0] + state[1] + state[3], 0x00000001);
float x1 = (float) ( (double) z1 / (double)UINT_MAX );
/*
if( x1 < 0.0f ){
unsigned int z1 = MaxInt(state[0] + state[1] + state[3], 0x00000001);
double z2 = (double) z1/((double) UINT_MAX);
(void) fprintf( logFile, "x1=%.6e state[%u %u %u] sum %u %.6e den=%u z2=%.6e\n",
x1, state[0], state[1], state[3],
(state[0] + state[1] + state[3]), (float) (state[0] + state[1] + state[3]), z1, z2 );
}
*/
state[0] = state[0] * 69069 + 1;
state[1] ^= state[1] << 13;
state[1] ^= state[1] >> 17;
state[1] ^= state[1] << 5;
x1 = sqrt(-2.0f * log(x1));
k = (state[2] >> 2) + (state[3] >> 3) + (carry >> 2);
m = state[3] + state[3] + state[2] + carry;
state[2] = state[3];
state[3] = m;
carry = k >> 30;
float x2 = (float)(state[0] + state[1] + state[3]) / (float)UINT_MAX;
state[0] = state[0] * 69069 + 1;
state[1] ^= state[1] << 13;
state[1] ^= state[1] >> 17;
state[1] ^= state[1] << 5;
*randomV1 = x1 * cos(2.0f * 3.14159265f * x2);
k = (state[2] >> 2) + (state[3] >> 3) + (carry >> 2);
m = state[3] + state[3] + state[2] + carry;
state[2] = state[3];
state[3] = m;
carry = k >> 30;
unsigned int z3 = MaxInt(state[0] + state[1] + state[3], 0x00000001);
float x3 = (float) ( (double) z3 / (double)UINT_MAX );
//float x3 = (float)MaxInt(state[0] + state[1] + state[3], 0x00000001) / (float)UINT_MAX;
state[0] = state[0] * 69069 + 1;
state[1] ^= state[1] << 13;
state[1] ^= state[1] >> 17;
state[1] ^= state[1] << 5;
x3 = sqrt(-2.0f * log(x3));
k = (state[2] >> 2) + (state[3] >> 3) + (carry >> 2);
m = state[3] + state[3] + state[2] + carry;
state[2] = state[3];
state[3] = m;
carry = k >> 30;
float x4 = (float)(state[0] + state[1] + state[3]) / (float)UINT_MAX;
state[0] = state[0] * 69069 + 1;
state[1] ^= state[1] << 13;
state[1] ^= state[1] >> 17;
state[1] ^= state[1] << 5;
*randomV2 = x3 * cos(2.0f * 3.14159265f * x4);
k = (state[2] >> 2) + (state[3] >> 3) + (carry >> 2);
m = state[3] + state[3] + state[2] + carry;
state[2] = state[3];
state[3] = m;
carry = k >> 30;
//float x5 = (float)MaxInt(state[0] + state[1] + state[3], 0x00000001) / (float)UINT_MAX;
unsigned int z5 = MaxInt(state[0] + state[1] + state[3], 0x00000001);
float x5 = (float) ( (double) z5 / (double)UINT_MAX );
state[0] = state[0] * 69069 + 1;
state[1] ^= state[1] << 13;
state[1] ^= state[1] >> 17;
state[1] ^= state[1] << 5;
x5 = sqrt(-2.0f * log(x5));
k = (state[2] >> 2) + (state[3] >> 3) + (carry >> 2);
m = state[3] + state[3] + state[2] + carry;
state[2] = state[3];
state[3] = m;
carry = k >> 30;
float x6 = (float)(state[0] + state[1] + state[3]) / (float)UINT_MAX;
*randomV3 = x5 * cos(2.0f * 3.14159265f * x6);
//(void) fprintf( logFile, "rv=%.6e %.6e %.6e\n", *randomV1, *randomV2, *randomV3 );
//exit(0);
return;
}
/**
* Load random number streams using Kiss algorithm
*
*
* @return DefaultReturnValue;
*/
int BrookRandomNumberGenerator::_loadRandomNumberStreamsKiss( void ){
// ---------------------------------------------------------------------------------------
static unsigned int state[4];
static int stateInitialized = 0;
int printOn = 0;
FILE* log;
static const int reseed = 10000;
static std::string methodName = "\nBrookRandomNumberGenerator::_loadRandomNumberStreamsKiss";
// ---------------------------------------------------------------------------------------
if( printOn && getLog() ){
log = getLog();
} else {
printOn = 0;
}
// periodically reset seeds
if( !stateInitialized || !(stateInitialized % reseed) ){
state[0] = rand();
state[1] = rand();
state[2] = rand();
state[3] = rand();
if( printOn ){
(void) fprintf( log, "%s reset state seeds stateInitialized=%d reseed=%d [%u %u %u %u]\n",
methodName.c_str(), stateInitialized, reseed, state[0], state[1], state[2], state[3] );
(void) fflush( log );
}
}
stateInitialized++;
// allocate memory once for download of random nos.
float* loadBuffer = _getLoadBuffer();
if( printOn ){
static float count = 0.0f;
float block = (float) (3*getRandomNumberStreamSize() );
count += 1.0f;
(void) fprintf( log, "%s: count=%.1f ttl=%.3e no./count=%.1f %d %d\n", methodName.c_str(),
count, block*count, block, getRandomNumberStreamSize(), getNumberOfRandomNumberStreams() );
(void) fflush( log );
}
for( int jj = 0; jj < getNumberOfRandomNumberStreams(); jj++ ){
for( int ii = 0; ii < 3*getRandomNumberStreamSize(); ii += 3 ){
float v1,v2,v3;
_generateRandomsKiss( &v1, &v2, &v3, state );
loadBuffer[ii] = v1;
loadBuffer[ii+1] = v2;
loadBuffer[ii+2] = v3;
}
getRandomNumberStream( jj )->loadFromArray( loadBuffer );
}
if( printOn ){
FILE* log = getLog() ? getLog() : stderr;
(void) fprintf( log, "%s: stats\n%s\n", methodName.c_str(), getStatisticsString().c_str() );
(void) fflush( log );
}
return DefaultReturnValue;
}
/**
* Load random number streams using Mersenne algorithm
*
*
* @return DefaultReturnValue;
*/
int BrookRandomNumberGenerator::_loadRandomNumberStreamsMersenne( void ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "\nBrookRandomNumberGenerator::_loadRandomNumberStreamsMersenne";
int printOn = 0;
// ---------------------------------------------------------------------------------------
// allocate memory once for download of random nos.
float* loadBuffer = _getLoadBuffer();
for( int jj = 0; jj < getNumberOfRandomNumberStreams(); jj++ ){
for( int ii = 0; ii < 3*getRandomNumberStreamSize(); ii += 3 ){
loadBuffer[ii] = (float) SimTKOpenMMUtilities::getNormallyDistributedRandomNumber();
loadBuffer[ii+1] = (float) SimTKOpenMMUtilities::getNormallyDistributedRandomNumber();
loadBuffer[ii+2] = (float) SimTKOpenMMUtilities::getNormallyDistributedRandomNumber();
}
getRandomNumberStream( jj )->loadFromArray( loadBuffer );
}
if( printOn ){
FILE* log = getLog() ? getLog() : stderr;
(void) fprintf( log, "%s: stats\n%s\n", methodName.c_str(), getStatisticsString().c_str() );
(void) fflush( log );
}
return DefaultReturnValue;
}
/**
* Load random number streams w/ fixed value
*
*
* @return DefaultReturnValue;
*/
int BrookRandomNumberGenerator::_loadRandomNumberStreamsFixedValue( void ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "\nBrookRandomNumberGenerator::_loadRandomNumberStreamsFixedValue";
int printOn = 0;
// ---------------------------------------------------------------------------------------
// load fixed value
float fixedValue = 0.1f;
for( int jj = 0; jj < getNumberOfRandomNumberStreams(); jj++ ){
getRandomNumberStream( jj )->fillWithValue( &fixedValue );
}
if( printOn ){
FILE* log = getLog() ? getLog() : stderr;
(void) fprintf( log, "%s: stats\n%s\n", methodName.c_str(), getStatisticsString().c_str() );
(void) fflush( log );
}
return DefaultReturnValue;
}
/**
* Load random number streams using original gpu algorithm
*
*
* @return DefaultReturnValue;
*/
int BrookRandomNumberGenerator::_loadGVStreamsOriginal( void ){
// ---------------------------------------------------------------------------------------
unsigned long int jran;
// static const std::string methodName = "\nBrookRandomNumberGenerator::_loadGVStreamsOriginal";
// ---------------------------------------------------------------------------------------
float* loadBuffer = _getLoadBuffer();
jran = getRandomNumberSeed();
for( int jj = 0; jj < getNumberOfRandomNumberStreams(); jj++ ){
for( int ii = 0; ii < 3*getRandomNumberStreamSize(); ii++ ){
loadBuffer[ii] = _generateGromacsRandomNumber( &jran );
}
getRandomNumberStream( jj )->loadFromArray( loadBuffer );
}
incrementRandomNumberSeed( 1 );
return DefaultReturnValue;
}
/**
* Get load buffer
*
* @return ptr to load buffer
*
* @throw OpenMMException if rv stream size is < 1
*
**/
float* BrookRandomNumberGenerator::_getLoadBuffer( void ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "\nBrookRandomNumberGenerator::_getLoadBuffer";
// ---------------------------------------------------------------------------------------
if( getRandomNumberStreamSize() < 1 ){
std::stringstream message;
message << methodName << " rv stream size=" << getRandomNumberStreamSize() << " is less than 1.";
throw OpenMMException( message.str() );
return NULL;
}
if( _loadBuffer == NULL ){
_loadBuffer = (float*) malloc( sizeof(float)*3*getRandomNumberStreamSize() );
}
return _loadBuffer;
}
/**
* Get ptr to shuffle indices
*
* @return ptr to shuffle indices
*
* @throw OpenMMException if size is < 1
*
**/
int* BrookRandomNumberGenerator::_getShuffleIndices( int size ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "\nBrookRandomNumberGenerator::_getShuffleIndices";
// ---------------------------------------------------------------------------------------
if( size < 1 ){
std::stringstream message;
message << methodName << " size=" << size << " is less than 1.";
throw OpenMMException( message.str() );
return NULL;
}
if( _shuffleIndices == NULL ){
_shuffleIndices = (int*) malloc( sizeof(int)*size );
}
return _shuffleIndices;
}
/**
* Loads a permutation of indices from 0 to gvSize-1 in
* sdp->strShuffle. To make sure that the order of the
* permutation is atleast NGVSHUFFLE, we create the
* permutation by introducing a random number of p-cycles
* where p is randomly determined from 2,3,5,7 and 11.
* The LCM of these numbers is 2310.
* Ofcourse the p-cycles are not necessarily disjoint
* the way it's done here, but there's a good chance
* there will enough disjoint cycles to make the
* order of the permutation larger than NGVSHUFFLE
*
*
* This function is only called once at startup
*
* @return DefaultReturnValue;
**/
int BrookRandomNumberGenerator::_loadGVShuffle( void ){
// ---------------------------------------------------------------------------------------
const int p[] = { 2, 3, 5, 7, 11 };
const int np = sizeof(p) / sizeof(p[0]);
const int pmax = p[np-1];
static const std::string methodName = "BrookRandomNumberGenerator::loadGVShuffle";
int printOn = 0;
// ---------------------------------------------------------------------------------------
float* loadBuffer = _getLoadBuffer();
int* indices = _getShuffleIndices( pmax );
int rvSize = getRandomNumberStreamSize();
for ( int ii = 0; ii < rvSize; ii++ ) {
loadBuffer[ii] = (float) ii;
}
//How to come up with this number here?
unsigned long int seed = getRandomNumberSeed();
for( int iter = 0; iter < 1000000; iter++ ) {
//for each p
for( int ii = 0; ii < np; ii++ ){
//Come up with p random indices
//Not checking that they are distinct
//because that should be fairly rare
for ( int jj = 0; jj < p[ii]; jj++ ) {
//indices[j] = (int) ( gmx_rando( &sdp->seed ) * sdp->gvSize );
indices[jj] = (int) ( _generateGromacsRandomNumber( &seed )*rvSize );
}
// do a p-cycle
float tmp = loadBuffer[ indices[0] ];
for ( int jj = 0; jj < p[ii]-1; jj++ ) {
loadBuffer[ indices[jj] ] = loadBuffer[ indices[jj+1] ];
}
loadBuffer[ indices[ p[ii]-1 ] ] = tmp;
}
}
_getShuffleStream()->loadFromArray( loadBuffer );
if( printOn ){
FILE* log = getLog() ? getLog() : stderr;
(void) fprintf( log, "%s: sz=%d pmax=%d np=%d sample indices:\n", methodName.c_str(), rvSize, pmax, np );
float maxIdx = -1.0f;
float minIdx = (float) (rvSize)*2.0f;
for( int ii = 0; ii < rvSize; ii++ ){
if( ii < 30 || ii > (rvSize-30) ){
(void) fprintf( log, " %d %.8f\n", ii, loadBuffer[ii] );
}
if( loadBuffer[ii] < minIdx ){
minIdx = loadBuffer[ii];
}
if( loadBuffer[ii] > maxIdx ){
maxIdx = loadBuffer[ii];
}
}
(void) fprintf( log, "%s: min-max indices: %.8f %.8f\n", methodName.c_str(), minIdx, maxIdx );
}
return DefaultReturnValue;
}
/**
* Shuffle streams
*
* @return DefaultReturnValue;
*/
int BrookRandomNumberGenerator::_shuffleGVStreams( void ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "\nBrookRandomNumberGenerator::_shuffleGVStreams";
// ---------------------------------------------------------------------------------------
int numberOfRvStreams = getNumberOfRandomNumberStreams();
for( int ii = 0; ii < (numberOfRvStreams - 1); ii++ ){
kpermute_vectors( (float) getRandomNumberStreamWidth(),
_getShuffleStream()->getBrookStream(),
getRandomNumberStream( ii + 1 )->getBrookStream(),
getRandomNumberStream( ii )->getBrookStream() );
}
kpermute_vectors( (float) getRandomNumberStreamWidth(),
_getShuffleStream()->getBrookStream(),
getRandomNumberStream( 0 )->getBrookStream(),
getRandomNumberStream( numberOfRvStreams - 1 )->getBrookStream() );
return DefaultReturnValue;
}
/**
* Advances the current position by 2*gpu->particles
* If we run out of rand numbers, we shuffle and
* reuse a few times before reloading from the cpu
*
* @param numberOfRandomValuesConsumedPerIteration number of random values consumed/iteration
*
* @return DefaultReturnValue;
*/
int BrookRandomNumberGenerator::advanceGVCursor( int numberOfRandomValuesConsumedPerIteration ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookRandomNumberGenerator::advanceGVCursor";
int printOn = 0;
FILE* log;
// ---------------------------------------------------------------------------------------
//setLog( stderr );
if( printOn && getLog() ){
log = getLog();
} else {
printOn = 0;
}
int rvStreamSize = getRandomNumberStreamSize();
// use 2 random values per sd
_rvStreamOffset += numberOfRandomValuesConsumedPerIteration;
//Check if we've used up this texture
char* action = "none";
if ( _rvStreamOffset > rvStreamSize - numberOfRandomValuesConsumedPerIteration ){
// next one if available
_rvStreamOffset = 0;
if ( _rvStreamIndex < _numberOfRandomNumberStreams - 1 ){
_rvStreamIndex++;
action = "incremented stream index";
} else {
//No more textures, need to shuffle
if( _numberOfShuffles < _maxShuffles ){
_shuffleGVStreams( );
_numberOfShuffles++;
action = "shuffled streams";
} else { //Need to refresh random numbers from cpu
if( _randomNumberGenerator == Mersenne ){
action = "loaded new values to GPU using Mersenne rng";
_loadRandomNumberStreamsMersenne( );
} else if( _randomNumberGenerator == Kiss ){
action = "loaded new values to GPU using KISS rng";
_loadRandomNumberStreamsKiss( );
} else if( _randomNumberGenerator == Original ){
action = "loaded new values to GPU using original Gromac's rng";
_loadGVStreamsOriginal( );
} else if( _randomNumberGenerator == FixedValue ){
action = "loaded new fixed values to GPU";
_loadRandomNumberStreamsFixedValue( );
}
_numberOfShuffles = 0;
}
_rvStreamIndex = 0;
}
if( printOn ){
(void) fprintf( log, "%s offset=%d consume/itr=%d StrmSz=%d idx=%d shffle=%d action=%s\n",
methodName.c_str(), _rvStreamOffset, numberOfRandomValuesConsumedPerIteration,
rvStreamSize, _rvStreamIndex, _numberOfShuffles, action );
(void) fflush( log );
}
/*
// check rng distribution
static int count = 0;
if( count++ < 2 ){
// accumulate rng -- stats will be in cumulative fields in stat string
int testIterations = 1000;
for( int ii = 0; ii < testIterations; ii++ ){
//_loadRandomNumberStreamsKiss( );
_loadRandomNumberStreamsMersenne( );
getStatisticsString();
}
(void) fprintf( log, "%s: stats\n%s\n", methodName.c_str(), getStatisticsString().c_str() );
}
*/
}
return DefaultReturnValue;
}
/**
* Get random number stream size
*
* @return random number stream size
*
*/
int BrookRandomNumberGenerator::getRandomNumberStreamSize( void ) const {
return _randomNumberStreamSize;
}
/**
* Get Shuffle stream
*
* @return shuffle stream
*
*/
BrookFloatStreamInternal* BrookRandomNumberGenerator::_getShuffleStream( void ) const {
return _auxiliaryStreams[ShuffleStream];
}
/**
* Get random number stream
*
* @param index random number stream index
*
* @return random number stream
*
* @throw OpenMMException if index is invalid or _randomNumberGeneratorStreams not set
*
*/
BrookFloatStreamInternal* BrookRandomNumberGenerator::getRandomNumberStream( int index ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "\nBrookRandomNumberGenerator::getRandomNumberStream";
// ---------------------------------------------------------------------------------------
if( index < 0 || index >= _numberOfRandomNumberStreams ){
std::stringstream message;
message << methodName << " index=" << index << " is out of range: [0," << _numberOfRandomNumberStreams;
throw OpenMMException( message.str() );
return NULL;
}
if( _randomNumberGeneratorStreams == NULL ){
std::stringstream message;
message << methodName << " rv streams not initialized; input index=" << index;
throw OpenMMException( message.str() );
return NULL;
}
return _randomNumberGeneratorStreams[index];
}
/**
* Get random value stream index
*
* @return random value stream index
*
*/
int BrookRandomNumberGenerator::getRvStreamIndex( void ) const {
return _rvStreamIndex;
}
/**
* Get random value stream offset
*
* @return random value stream offset
*
*/
int BrookRandomNumberGenerator::getRvStreamOffset( void ) const {
return _rvStreamOffset;
}
/**
* Get max shuffles
*
* @return max shuffles
*
*/
int BrookRandomNumberGenerator::getMaxShuffles( void ) const {
return _maxShuffles;
}
/**
* Get number of shuffles
*
* @return number of shuffles
*
*/
int BrookRandomNumberGenerator::_getNumberOfShuffles( void ) const {
return _numberOfShuffles;
}
/**
* Initialize stream dimensions
*
* @param numberOfParticles number of particles
* @param platform platform
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int BrookRandomNumberGenerator::_initializeStreamSizes( int numberOfParticles, const Platform& platform ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookRandomNumberGenerator::_initializeStreamSizes";
// ---------------------------------------------------------------------------------------
setNumberOfParticles( numberOfParticles );
// get randomNumber stream dimensions
const BrookPlatform& brookPlatform = dynamic_cast<const BrookPlatform&> (platform);
const BrookStreamFactory& brookStreamFactory = dynamic_cast<const BrookStreamFactory&> (platform.getDefaultStreamFactory() );
_randomNumberStreamWidth = brookStreamFactory.getDefaultRandomNumberStreamWidth();
_randomNumberStreamSize = brookStreamFactory.getDefaultRandomNumberStreamSize();
_randomNumberStreamHeight = (int) ( ((float) _randomNumberStreamSize)/( (float) _randomNumberStreamWidth) + 0.001);
_randomNumberStreamSize = _randomNumberStreamWidth*_randomNumberStreamHeight;
return DefaultReturnValue;
}
/**
* Initialize streams
*
* @param platform platform
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int BrookRandomNumberGenerator::_initializeStreams( const Platform& platform ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookRandomNumberGenerator::_initializeStreams";
float dangleValue = 0.0f;
// ---------------------------------------------------------------------------------------
int randomNumberStreamSize = getRandomNumberStreamSize();
int randomNumberStreamWidth = getRandomNumberStreamWidth();
_auxiliaryStreams[ShuffleStream] = new BrookFloatStreamInternal( BrookCommon::ShuffleStream,
randomNumberStreamSize, randomNumberStreamWidth,
BrookStreamInternal::Float, dangleValue );
// insure number of random number streams is > 0
// delete if already allocated and then initialize
if( _numberOfRandomNumberStreams < 1 ){
_numberOfRandomNumberStreams = 1;
}
if( _randomNumberGeneratorStreams ){
delete[] _randomNumberGeneratorStreams;
}
_randomNumberGeneratorStreams = new BrookFloatStreamInternal*[_numberOfRandomNumberStreams];
for( int ii = 0; ii < _numberOfRandomNumberStreams; ii++ ){
_randomNumberGeneratorStreams[ii] = new BrookFloatStreamInternal( BrookCommon::RandomValuesStream,
randomNumberStreamSize, randomNumberStreamWidth,
BrookStreamInternal::Float3, dangleValue );
}
// create shuffle stream
_loadGVShuffle();
return DefaultReturnValue;
}
/*
* Setup of streams, ... associated w/ random number generator
*
* @param numberOfParticles number of particles
* @param platform Brook platform
*
* @return nonzero value if error
*
* */
int BrookRandomNumberGenerator::setup( int numberOfParticles, const Platform& platform ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookRandomNumberGenerator::setup";
// ---------------------------------------------------------------------------------------
const BrookPlatform& brookPlatform = dynamic_cast<const BrookPlatform&> (platform);
setLog( brookPlatform.getLog() );
// set stream sizes and then create streams
_initializeStreamSizes( numberOfParticles, platform );
_initializeStreams( platform );
if( _randomNumberGenerator == Mersenne ){
_loadRandomNumberStreamsMersenne( );
} else if( _randomNumberGenerator == Kiss ){
_loadRandomNumberStreamsKiss( );
} else if( _randomNumberGenerator == Original ){
_loadGVStreamsOriginal( );
} else if( _randomNumberGenerator == FixedValue ){
_loadRandomNumberStreamsFixedValue( );
}
return DefaultReturnValue;
}
/*
* Get contents of object
*
* @param level level of dump
*
* @return string containing contents
*
* */
std::string BrookRandomNumberGenerator::getContentsString( int level ) const {
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookRandomNumberGenerator::getContentsString";
static const unsigned int MAX_LINE_CHARS = 256;
char value[MAX_LINE_CHARS];
static const char* Set = "Set";
static const char* NotSet = "Not set";
// ---------------------------------------------------------------------------------------
std::stringstream message;
std::string tab = " ";
#ifdef _MSC_VER
#define LOCAL_SPRINTF(a,b,c) sprintf_s( (a), MAX_LINE_CHARS, (b), (c) );
#else
#define LOCAL_SPRINTF(a,b,c) sprintf( (a), (b), (c) );
#endif
if( _randomNumberGenerator == Mersenne ){
(void) LOCAL_SPRINTF( value, "%s", "Mersenne Rng");
} else if( _randomNumberGenerator == Kiss ){
(void) LOCAL_SPRINTF( value, "%s", "Kiss Rng");
} else if( _randomNumberGenerator == Original ){
(void) LOCAL_SPRINTF( value, "%s", "Original Gromacs Rng");
} else if( _randomNumberGenerator == FixedValue ){
(void) LOCAL_SPRINTF( value, "%s", "Fixed value Rng");
}
message << _getLine( tab, "Random number generator:", value );
(void) LOCAL_SPRINTF( value, "%d", getRandomNumberStreamSize() );
message << _getLine( tab, "RandomNumber stream size:", value );
(void) LOCAL_SPRINTF( value, "%d", getRandomNumberStreamWidth() );
message << _getLine( tab, "RandomNumber stream width:", value );
(void) LOCAL_SPRINTF( value, "%d", getRandomNumberStreamHeight() );
message << _getLine( tab, "RandomNumber stream height:", value );
(void) LOCAL_SPRINTF( value, "%d", getNumberOfRandomNumberStreams() );
message << _getLine( tab, "Number of RandomNumber streams:", value );
(void) LOCAL_SPRINTF( value, "%ld", getRandomNumberSeed() );
message << _getLine( tab, "Seed:", value );
(void) LOCAL_SPRINTF( value, "%d", getRvStreamIndex() );
message << _getLine( tab, "Rv stream index:", value );
(void) LOCAL_SPRINTF( value, "%d", getRvStreamOffset() );
message << _getLine( tab, "Rv stream offset:", value );
(void) LOCAL_SPRINTF( value, "%d", _getNumberOfShuffles() );
message << _getLine( tab, "Number of rv stream shuffles:", value );
(void) LOCAL_SPRINTF( value, "%d", getMaxShuffles() );
message << _getLine( tab, "Max number of rv stream shuffles:", value );
message << _getLine( tab, "Log:", (getLog() ? Set : NotSet) );
message << _getLine( tab, "Shuffle:", (_getShuffleStream() ? Set : NotSet) );
// show stats
message << getStatisticsString( );
for( int ii = 0; ii < LastStreamIndex; ii++ ){
message << std::endl;
if( _auxiliaryStreams[ii] ){
message << _auxiliaryStreams[ii]->getContentsString( );
}
}
for( int ii = 0; ii < _numberOfRandomNumberStreams; ii++ ){
message << std::endl;
if( _randomNumberGeneratorStreams[ii] ){
message << _randomNumberGeneratorStreams[ii]->getContentsString();
}
}
#undef LOCAL_SPRINTF
return message.str();
}
/*
* Get statistics
*
* @return string containing contents
*
* */
std::string BrookRandomNumberGenerator::getStatisticsString( void ) const {
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookRandomNumberGenerator::getStatisticsString";
static const unsigned int MAX_LINE_CHARS = 256;
char value[MAX_LINE_CHARS];
static const char* Set = "Set";
static const char* NotSet = "Not set";
static double cumulativeStatistics[7] = { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0e+99, -1.0e+99 };
// ---------------------------------------------------------------------------------------
std::stringstream message;
std::string tab = " ";
#ifdef _MSC_VER
#define LOCAL_SPRINTF(a,b,c) sprintf_s( (a), MAX_LINE_CHARS, (b), (c) );
#else
#define LOCAL_SPRINTF(a,b,c) sprintf( (a), (b), (c) );
#endif
message << "\n Statistics:\n";
double statistics[7];
getStatistics( statistics, -1, cumulativeStatistics );
(void) LOCAL_SPRINTF( value, "%.5e", statistics[4] );
message << _getLine( tab, "Count:", value );
(void) LOCAL_SPRINTF( value, "%.5e", statistics[0] );
message << _getLine( tab, "Average:", value );
(void) LOCAL_SPRINTF( value, "%.5e", statistics[1] );
message << _getLine( tab, "StdDev:", value );
(void) LOCAL_SPRINTF( value, "%.5e", statistics[3] );
message << _getLine( tab, "Kurtosis:", value );
(void) LOCAL_SPRINTF( value, "%.5e", statistics[5] );
message << _getLine( tab, "Min:", value );
(void) LOCAL_SPRINTF( value, "%.6e", statistics[6] );
message << _getLine( tab, "Max:", value );
if( cumulativeStatistics[4] > 1000.0 ){
for( int ii = 0; ii < 7; ii++ ){
statistics[ii] = cumulativeStatistics[ii];
}
statistics[0] /= statistics[4];
statistics[1] = statistics[1] - statistics[4]*statistics[0]*statistics[0];
if( statistics[4] > 1.0 ){
statistics[1] = sqrt( statistics[1]/( statistics[4] - 1.0 ) );
}
statistics[3] = (statistics[3]/(statistics[4]*statistics[1]*statistics[1]) ) - 3.0;
(void) LOCAL_SPRINTF( value, "%.5e", statistics[4] );
message << _getLine( tab, "Cumulative Count:", value );
(void) LOCAL_SPRINTF( value, "%.5e", statistics[0] );
message << _getLine( tab, "Cumulative Average:", value );
(void) LOCAL_SPRINTF( value, "%.5e", statistics[1] );
message << _getLine( tab, "Cumulative StdDev:", value );
(void) LOCAL_SPRINTF( value, "%.5e", statistics[3] );
message << _getLine( tab, "Cumulative Kurtosis:", value );
(void) LOCAL_SPRINTF( value, "%.5e", statistics[5] );
message << _getLine( tab, "Cumulative Min:", value );
(void) LOCAL_SPRINTF( value, "%.6e", statistics[6] );
message << _getLine( tab, "Cumulative Max:", value );
}
#undef LOCAL_SPRINTF
return message.str();
}
/*
* Get statistics
*
* @param statistics array of size 5:
* 0: mean
* 1: std dev
* 2: 3rd moment (not normalized)
* 3: kurtosis
* 4: count
* 5: min
* 6: max
*
* @param streamIndex stream index to analyze
*
* @return DefaultReturnValue
*
* */
int BrookRandomNumberGenerator::getStatistics( double statistics[7], int streamIndex, double cumulativeStatistics[7] ) const {
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookRandomNumberGenerator::";
// ---------------------------------------------------------------------------------------
statistics[0] = 0.0;
statistics[1] = 0.0;
statistics[2] = 0.0;
statistics[3] = 0.0;
statistics[4] = 0.0;
statistics[5] = 1.0e+99;
statistics[6] = -1.0e+99;
for( int ii = 0; ii < _numberOfRandomNumberStreams; ii++ ){
if( streamIndex < 0 || ii == streamIndex ){
void* dataArrayV = _randomNumberGeneratorStreams[ii]->getData( 1 );
int numberOfValues = _randomNumberGeneratorStreams[ii]->getStreamSize()*_randomNumberGeneratorStreams[ii]->getWidth();
const float* dataArray = (float*) dataArrayV;
for( int ii = 0; ii < numberOfValues; ii++ ){
statistics[0] += dataArray[ii];
double rv2 = dataArray[ii]*dataArray[ii];
statistics[1] += rv2;
statistics[2] += rv2*dataArray[ii];
statistics[3] += rv2*rv2;
if( statistics[5] > dataArray[ii] ){
statistics[5] = dataArray[ii];
}
if( statistics[6] < dataArray[ii] ){
statistics[6] = dataArray[ii];
}
}
statistics[4] += (double) numberOfValues;
}
}
// accumulate moments, ... in cumulativeStatistics array
for( int ii = 0; ii < 5; ii++ ){
cumulativeStatistics[ii] += statistics[ii];
}
if( statistics[5] < cumulativeStatistics[5] ){
cumulativeStatistics[5] = statistics[5];
}
if( statistics[6] > cumulativeStatistics[6] ){
cumulativeStatistics[6] = statistics[6];
}
if( statistics[4] > 0.0 ){
statistics[0] /= statistics[4];
statistics[1] = statistics[1] - statistics[4]*statistics[0]*statistics[0];
if( statistics[4] > 1.0 ){
statistics[1] = sqrt( statistics[1]/( statistics[4] - 1.0 ) );
}
statistics[3] = (statistics[3]/(statistics[4]*statistics[1]*statistics[1]) ) - 3.0;
}
return DefaultReturnValue;
}
#ifndef OPENMM_BROOK_RANDOM_NUMBER_GENERATOR_H_
#define OPENMM_BROOK_RANDOM_NUMBER_GENERATOR_H_
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "BrookCommon.h"
namespace OpenMM {
/**
*
* Encapsulates stochastic dynamics algorithm
*
*/
class BrookRandomNumberGenerator : public BrookCommon {
public:
// toggle between original, Mersenne, & Kiss (Nvidia), fixed value random generators
enum Rngs { Original, Kiss, Mersenne, FixedValue };
/**
* Constructor
*
*/
BrookRandomNumberGenerator( );
/**
* Destructor
*
*/
~BrookRandomNumberGenerator();
/**
* Get number of random number streams
*
* @return number of random number streams
*
*/
int getNumberOfRandomNumberStreams( void ) const;
/**
* Get stream width
*
* @return stream width
*/
int getRandomNumberStreamWidth( void ) const;
/**
* Get stream height
*
* @return stream height
*/
int getRandomNumberStreamHeight( void ) const;
/**
* Get stream size
*
* @return stream size
*/
int getRandomNumberStreamSize( void ) const;
/**
* Get array of StochasticDynamics streams
*
* @return array ofstreams
*
*/
BrookFloatStreamInternal** getStreams( void );
/*
* Setup of RNG parameters
*
* @param numberOfParticles number of particles
* @param platform Brook platform
*
* @return ErrorReturnValue value if error, else DefaultReturnValue
*
* */
int setup( int numberOfParticles, const Platform& platform );
/*
* Get contents of object
*
* @param level of dump
*
* @return string containing contents
*
* */
std::string getContentsString( int level = 0 ) const;
/*
* Get stats
*
* @return string containing stats
*
* */
std::string getStatisticsString( void ) const;
/**
* Get random number stream
*
* @param index random number stream index
*
* @return random number stream
*
*/
BrookFloatStreamInternal* getRandomNumberStream( int index );
/**
* Get random number seed
*
* @return random number seed
*/
unsigned long int getRandomNumberSeed( void ) const;
/**
* Increment random number seed
*
* @param increment amount to increment random number seed; default = 1
*
* @return updated random number seed
*/
unsigned long int incrementRandomNumberSeed( unsigned long int increment = 1 );
/**
* Set random number seed
*
* @param new random number seed; default = 1
*
* @return random number seed
*/
unsigned long int setRandomNumberSeed( unsigned long int seed = 1 );
/**
* Get index of rv texture
*
* @return index of rv texture
*/
int getRvStreamIndex( void ) const;
/**
* Get max shuffles
*
* @return max shuffles
*
*/
int getMaxShuffles( void ) const;
/**
* Advance random values stream index
*
* @param numberOfEntriesToAdvance number of entries consumed in previous iteration
*
* @return DefaultReturnValue
*
*/
int advanceGVCursor( int numberOfEntriesToAdvance );
/**
* Get random value stream offset
*
* @return random value stream offset
*
*/
int getRvStreamOffset( void ) const;
/*
* Get statistics
*
* @param statistics array of size 7:
* 0: mean
* 1: std dev
* 2: 3rd moment (not normalized)
* 3: kurtosis
* 4: count
* 5: min
* 6: max
*
* @param streamIndex stream index to analyze
* @param cumulativeStatistics accumulate stats array entries same as statistics
*
* @return DefaultReturnValue
*
**/
int getStatistics( double statistics[7], int streamIndex, double cumulativeStatistics[7] ) const;
// ---------------------------------------------------------------------------------------
private:
// streams indices
enum BrookRandomNumberGeneratorStreams {
ShuffleStream,
LastStreamIndex
};
BrookFloatStreamInternal* _auxiliaryStreams[LastStreamIndex];
BrookFloatStreamInternal** _randomNumberGeneratorStreams;
// randomNumberSeed
unsigned long int _randomNumberSeed;
// number of random number streams
int _numberOfRandomNumberStreams;
// random number stream dimensions
int _randomNumberStreamWidth;
int _randomNumberStreamHeight;
int _randomNumberStreamSize;
// control variables
int _rvStreamIndex;
int _rvStreamOffset;
int _numberOfShuffles;
int _maxShuffles;
float* _loadBuffer;
int* _shuffleIndices;
Rngs _randomNumberGenerator;
/*
* Setup of stream dimensions
*
* @param particleStreamSize particle stream size
* @param particleStreamWidth particle stream width
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
* */
int _initializeStreamSizes( int particleStreamSize, int particleStreamWidth );
/**
* Initialize stream dimensions
*
* @param numberOfParticles number of particles
* @param platform platform
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int _initializeStreamSizes( int numberOfParticles, const Platform& platform );
/**
* Initialize stream dimensions and streams
*
* @param platform platform
*
* @return nonzero value if error
*
*/
int _initializeStreams( const Platform& platform );
/**
* Increment random number offset
*
* @param increment increment for offset
*
* @return random number offset
*/
int _incrementRvOffset( int increment );
/**
* Get shuffle stream
*
* @return Shuffle stream
*
*/
BrookFloatStreamInternal* _getShuffleStream( void ) const;
/**
* Generate a random number using algorithm in Gromacs
*
* @param ig seed
*
* @return random number
*
*/
BrookOpenMMFloat _generateGromacsRandomNumber( unsigned long int* ig );
/**
* Generate a random number using Kiss (algorithm in Kiss code)
* http://www.helsbreth.org/random/rng_kiss.html
*
* @param randomV1 output random value
* @param randomV2 output random value
* @param randomV3 output random value
* @param state state
*
*/
void _generateRandomsKiss( float* randomV1, float* randomV2, float* randomV3,
unsigned int state[4] );
/**
* Load random number streams using Kiss algorithm
*
*
* @return DefaultReturnValue;
*/
int _loadRandomNumberStreamsKiss( void );
/**
* Load random number streams using Mersenne algorithm
*
*
* @return DefaultReturnValue;
*/
int _loadRandomNumberStreamsMersenne( void );
/**
* Load random number streams using original gpu algorithm
*
*
* @return DefaultReturnValue;
*/
int _loadGVStreamsOriginal( void );
/**
* Load fixed value 'random number' streams using original gpu algorithm
* used for diagnostics
*
*
* @return DefaultReturnValue;
*/
int _loadRandomNumberStreamsFixedValue( void );
/**
* Loads a permutation of indices from 0 to gvSize-1 in
* sdp->strShuffle. To make sure that the order of the
* permutation is atleast NGVSHUFFLE, we create the
* permutation by introducing a random number of p-cycles
* where p is randomly determined from 2,3,5,7 and 11.
* The LCM of these numbers is 2310.
* Ofcourse the p-cycles are not necessarily disjoint
* the way it's done here, but there's a good chance
* there will enough disjoint cycles to make the
* order of the permutation larger than NGVSHUFFLE
*
*
* This function is only called once at startup
*
* @return DefaultReturnValue;
**/
int _loadGVShuffle( void );
/**
* Get number of shuffles
*
* @return number of shuffles
*
*/
int _getNumberOfShuffles( void ) const;
/**
* Load buffer
*
* @return ptr to load buffer
*
* @throw OpenMMException if rv stream size is < 1
*
**/
float* _getLoadBuffer( void );
/**
* Get ptr to shuffle indices
*
* @return ptr to shuffle indices
*
* @throw OpenMMException if size is < 1
*
**/
int* _getShuffleIndices( int size );
/**
* Shuffle streams
*
* @return DefaultReturnValue;
*/
int _shuffleGVStreams( void );
};
} // namespace OpenMM
#endif /* OPENMM_BROOK_RANDOM_NUMBER_GENERATOR_H_ */
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "openmm/internal/ContextImpl.h"
#include "openmm/System.h"
#include "BrookRemoveCMMotionKernel.h"
#include "BrookStreamInternal.h"
using namespace OpenMM;
using namespace std;
/**
* BrookRemoveCMMotionKernel constructor
*
* @param name name of the stream to create
* @param platform platform
* @param openMMBrookInterface OpenMM-Brook interface
* @param System System reference
*
*/
BrookRemoveCMMotionKernel::BrookRemoveCMMotionKernel( std::string name, const Platform& platform, OpenMMBrookInterface& openMMBrookInterface, System& system ) :
RemoveCMMotionKernel( name, platform ), _openMMBrookInterface( openMMBrookInterface ), _system( system ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookRemoveCMMotionKernel::BrookRemoveCMMotionKernel";
// ---------------------------------------------------------------------------------------
_frequency = 0;
_log = NULL;
_brookVelocityCenterOfMassRemoval = NULL;
const BrookPlatform& brookPlatform = dynamic_cast<const BrookPlatform&> (platform);
if( brookPlatform.getLog() != NULL ){
setLog( brookPlatform.getLog() );
}
_openMMBrookInterface.setNumberOfParticles( system.getNumParticles() );
}
/**
* BrookRemoveCMMotionKernel destructor
*
*/
BrookRemoveCMMotionKernel::~BrookRemoveCMMotionKernel( ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookRemoveCMMotionKernel::~BrookRemoveCMMotionKernel";
// ---------------------------------------------------------------------------------------
delete _brookVelocityCenterOfMassRemoval;
}
/**
* Initialize the kernel
*
* @param system System reference
* @param force CMMotionRemover reference
*
*/
void BrookRemoveCMMotionKernel::initialize( const System& system, const CMMotionRemover& force ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookRemoveCMMotionKernel::initialize";
static const int PrintOn = 0;
FILE* log = getLog();
// ---------------------------------------------------------------------------------------
_frequency = force.getFrequency();
std::vector<double> masses;
masses.resize( system.getNumParticles() );
for( size_t ii = 0; ii < masses.size(); ii++ ){
masses[ii] = system.getParticleMass(ii);
}
_brookVelocityCenterOfMassRemoval = new BrookVelocityCenterOfMassRemoval();
_brookVelocityCenterOfMassRemoval->setup( masses, getPlatform() );
if( PrintOn && log ){
(void) fprintf( log, "%s\n", methodName.c_str() );
(void) fflush( log );
}
return;
}
/**
* Get log file reference
*
* @return log file reference
*
*/
FILE* BrookRemoveCMMotionKernel::getLog( void ) const {
return _log;
}
/**
* Set log file reference
*
* @param log file reference
*
* @return DefaultReturnValue
*
*/
int BrookRemoveCMMotionKernel::setLog( FILE* log ){
_log = log;
return BrookCommon::DefaultReturnValue;
}
/**
* Get COM removal frequency
*
* @return frequency
*
*/
int BrookRemoveCMMotionKernel::getFrequency( void ) const {
return _frequency;
}
/**
* Execute kernel
*
* @param context ContextImpl reference
*
*/
void BrookRemoveCMMotionKernel::execute( ContextImpl& context ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookRemoveCMMotionKernel::execute";
// ---------------------------------------------------------------------------------------
int step = (int) floor( context.getTime()/context.getIntegrator().getStepSize() );
int frequency = getFrequency();
if( frequency <= 0 || (step % frequency) != 0 ){
return;
}
BrookStreamImpl* velocities = _openMMBrookInterface.getParticleVelocities();
_brookVelocityCenterOfMassRemoval->removeVelocityCenterOfMass( *velocities );
return;
}
#ifndef OPENMM_BROOK_REMOVE_CM_MOTION_KERNEL_H_
#define OPENMM_BROOK_REMOVE_CM_MOTION_KERNEL_H_
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "openmm/kernels.h"
#include "OpenMMBrookInterface.h"
#include "BrookVelocityCenterOfMassRemoval.h"
namespace OpenMM {
/**
* Brook class for removing center-of-mass motion
*/
class BrookRemoveCMMotionKernel : public RemoveCMMotionKernel {
public:
/**
* BrookRemoveCMMotionKernel constructor
*
* @param name name of the stream to create
* @param platform platform
* @param openMMBrookInterface OpenMM-Brook interface
* @param System System reference
*
*/
BrookRemoveCMMotionKernel( std::string name, const Platform& platform, OpenMMBrookInterface& openMMBrookInterface, System& system );
/**
* BrookRemoveCMMotionKernel destructor
*
*/
~BrookRemoveCMMotionKernel();
/**
* Get COM removal frequency
*
* @return frequency
*
*/
int getFrequency( void ) const;
/**
* Set log file reference
*
* @param log file reference
*
* @return DefaultReturnValue
*
*/
int setLog( FILE* log );
/*
* Get contents of object
*
* @param level of dump
*
* @return string containing contents
*
* */
std::string getContents( int level ) const;
/**
* Get log file reference
*
* @return log file reference
*
*/
FILE* getLog( void ) const;
/**
* Initialize the kernel
*
* @param system System reference
* @param force CMMotionRemover reference
*
*/
void initialize( const System& system, const CMMotionRemover& force );
/**
* Execute the kernel.
*
* @param context ContextImpl reference
*
*/
void execute( ContextImpl& context );
private:
int _frequency;
// log file reference
FILE* _log;
BrookVelocityCenterOfMassRemoval* _brookVelocityCenterOfMassRemoval;
// interface
OpenMMBrookInterface& _openMMBrookInterface;
// System reference
System& _system;
};
} // namespace OpenMM
#endif /* OPENMM_BROOK_REMOVE_CM_MOTION_KERNEL_H_ */
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "BrookShakeAlgorithm.h"
#include "BrookPlatform.h"
#include "BrookStreamImpl.h"
using namespace OpenMM;
using namespace std;
/**
*
* Constructor
*
*/
BrookShakeAlgorithm::BrookShakeAlgorithm( ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookShakeAlgorithm::BrookShakeAlgorithm";
BrookOpenMMFloat zero = static_cast<BrookOpenMMFloat>( 0.0 );
BrookOpenMMFloat one = static_cast<BrookOpenMMFloat>( 1.0 );
// ---------------------------------------------------------------------------------------
_numberOfParticles = -1;
_numberOfConstraints = -1;
_maxIterations = 25;
_shakeTolerance = static_cast<BrookOpenMMFloat>(1.0e-04);
// mark stream dimension variables as unset
_shakeParticleStreamWidth = -1;
_shakeParticleStreamHeight = -1;
_shakeParticleStreamSize = -1;
_shakeConstraintStreamSize = -1;
_shakeConstraintStreamWidth = -1;
_shakeConstraintStreamHeight = -1;
for( int ii = 0; ii < LastStreamIndex; ii++ ){
_shakeStreams[ii] = NULL;
}
// setup inverse sqrt masses
_inverseSqrtMasses = NULL;
}
/**
* Destructor
*
*/
BrookShakeAlgorithm::~BrookShakeAlgorithm( ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookShakeAlgorithm::~BrookShakeAlgorithm";
// ---------------------------------------------------------------------------------------
for( int ii = 0; ii < LastStreamIndex; ii++ ){
delete _shakeStreams[ii];
}
delete[] _inverseSqrtMasses;
}
/**
* Get number of constraints
*
* @return number of constraints
*
*/
int BrookShakeAlgorithm::getNumberOfConstraints( void ) const {
return _numberOfConstraints;
}
/**
* Get max iterations
*
* @return max iterations
*
*/
int BrookShakeAlgorithm::getMaxIterations( void ) const {
return _maxIterations;
}
/**
* Set max iterations
*
* @param max iterations
*
* @return DefaultReturnValue
*
*/
int BrookShakeAlgorithm::setMaxIterations( int maxIterations ){
_maxIterations = maxIterations;
return DefaultReturnValue;
}
/**
* Get SHAKE tolerance
*
* @return SHAKE tolerance
*
*/
BrookOpenMMFloat BrookShakeAlgorithm::getShakeTolerance( void ) const {
return _shakeTolerance;
}
/**
* Set SHAKE tolerance
*
* @param SHAKE tolerance
*
* @return DefaultReturnValue
*
*/
int BrookShakeAlgorithm::setShakeTolerance( BrookOpenMMFloat tolerance ){
_shakeTolerance = tolerance;
return DefaultReturnValue;
}
/**
* Get Particle stream size
*
* @return Particle stream size
*
*/
int BrookShakeAlgorithm::getShakeParticleStreamSize( void ) const {
return _shakeParticleStreamSize;
}
/**
* Get particle stream width
*
* @return particle stream width
*
*/
int BrookShakeAlgorithm::getShakeParticleStreamWidth( void ) const {
return _shakeParticleStreamWidth;
}
/**
* Get particle stream height
*
* @return particle stream height
*/
int BrookShakeAlgorithm::getShakeParticleStreamHeight( void ) const {
return _shakeParticleStreamHeight;
}
/**
* Get Constraint stream size
*
* @return Constraint stream size
*
*/
int BrookShakeAlgorithm::getShakeConstraintStreamSize( void ) const {
return _shakeConstraintStreamSize;
}
/**
* Get constraint stream width
*
* @return constraint stream width
*
*/
int BrookShakeAlgorithm::getShakeConstraintStreamWidth( void ) const {
return _shakeConstraintStreamWidth;
}
/**
* Get constraint stream height
*
* @return constraint stream height
*/
int BrookShakeAlgorithm::getShakeConstraintStreamHeight( void ) const {
return _shakeConstraintStreamHeight;
}
/**
* Get Shake particle indices stream
*
* @return Shake particle indices stream
*
*/
BrookFloatStreamInternal* BrookShakeAlgorithm::getShakeParticleIndicesStream( void ) const {
return _shakeStreams[ShakeParticleIndicesStream];
}
/**
* Get Shake particle parameter stream
*
* @return Shake particle parameter sStream
*
*/
BrookFloatStreamInternal* BrookShakeAlgorithm::getShakeParticleParameterStream( void ) const {
return _shakeStreams[ShakeParticleParameterStream];
}
/**
* Get Shake XCons0 stream
*
* @return XCons0 stream
*
*/
BrookFloatStreamInternal* BrookShakeAlgorithm::getShakeXCons0Stream( void ) const {
return _shakeStreams[ShakeXCons0Stream];
}
/**
* Get Shake XCons1 stream
*
* @return XCons1 stream
*
*/
BrookFloatStreamInternal* BrookShakeAlgorithm::getShakeXCons1Stream( void ) const {
return _shakeStreams[ShakeXCons1Stream];
}
/**
* Get Shake XCons2 stream
*
* @return XCons2 stream
*
*/
BrookFloatStreamInternal* BrookShakeAlgorithm::getShakeXCons2Stream( void ) const {
return _shakeStreams[ShakeXCons2Stream];
}
/**
* Get Shake XCons3 stream
*
* @return XCons3 stream
*
*/
BrookFloatStreamInternal* BrookShakeAlgorithm::getShakeXCons3Stream( void ) const {
return _shakeStreams[ShakeXCons3Stream];
}
/**
* Get Shake inverse map stream
*
* @return Shake inverse map stream
*
*/
BrookFloatStreamInternal* BrookShakeAlgorithm::getShakeInverseMapStream( void ) const {
return _shakeStreams[ShakeInverseMapStream];
}
/**
* Initialize stream dimensions
*
* @param numberOfParticles number of particles
* @param numberOfConstraints number of constraints
* @param platform platform
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int BrookShakeAlgorithm::_initializeStreamSizes( int numberOfParticles, int numberOfConstraints,
const Platform& platform ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookShakeAlgorithm::_initializeStreamSizes";
// ---------------------------------------------------------------------------------------
_shakeParticleStreamSize = getParticleStreamSize( platform );
_shakeParticleStreamWidth = getParticleStreamWidth( platform );
_shakeParticleStreamHeight = getParticleStreamHeight( platform );
// get constraint stream width & height, and then set stream size to the product
BrookCommon::getStreamDimensions( numberOfConstraints, &_shakeConstraintStreamWidth, &_shakeConstraintStreamHeight );
_shakeConstraintStreamSize = _shakeConstraintStreamWidth*_shakeConstraintStreamHeight;
return DefaultReturnValue;
}
/**
* Initialize streams
*
* @param platform platform
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int BrookShakeAlgorithm::_initializeStreams( const Platform& platform ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookShakeAlgorithm::_initializeStreams";
BrookOpenMMFloat dangleValue = static_cast<BrookOpenMMFloat>( 0.0 );
// ---------------------------------------------------------------------------------------
int shakeParticleStreamSize = getShakeParticleStreamSize();
int shakeParticleStreamWidth = getShakeParticleStreamWidth();
int shakeConstraintStreamSize = getShakeConstraintStreamSize();
int shakeConstraintStreamWidth = getShakeConstraintStreamWidth();
_shakeStreams[ShakeParticleIndicesStream]
= new BrookFloatStreamInternal( BrookCommon::ShakeParticleIndicesStream,
shakeConstraintStreamSize, shakeConstraintStreamWidth,
BrookStreamInternal::Float4, dangleValue );
_shakeStreams[ShakeParticleParameterStream]
= new BrookFloatStreamInternal( BrookCommon::ShakeParticleParameterStream,
shakeConstraintStreamSize, shakeConstraintStreamWidth,
BrookStreamInternal::Float4, dangleValue );
_shakeStreams[ShakeXCons0Stream] = new BrookFloatStreamInternal( BrookCommon::ShakeXCons0Stream,
shakeConstraintStreamSize, shakeConstraintStreamWidth,
BrookStreamInternal::Float3, dangleValue );
_shakeStreams[ShakeXCons1Stream] = new BrookFloatStreamInternal( BrookCommon::ShakeXCons1Stream,
shakeConstraintStreamSize, shakeConstraintStreamWidth,
BrookStreamInternal::Float3, dangleValue );
_shakeStreams[ShakeXCons2Stream] = new BrookFloatStreamInternal( BrookCommon::ShakeXCons2Stream,
shakeConstraintStreamSize, shakeConstraintStreamWidth,
BrookStreamInternal::Float3, dangleValue );
_shakeStreams[ShakeXCons3Stream] = new BrookFloatStreamInternal( BrookCommon::ShakeXCons3Stream,
shakeConstraintStreamSize, shakeConstraintStreamWidth,
BrookStreamInternal::Float3, dangleValue );
_shakeStreams[ShakeInverseMapStream] = new BrookFloatStreamInternal( BrookCommon::ShakeInverseMapStream,
shakeParticleStreamSize, shakeParticleStreamWidth,
BrookStreamInternal::Float2, dangleValue );
return DefaultReturnValue;
}
/*
* Set Shake streams
*
* @param masses masses
* @param constraintIndices constraint particle indices
* @param constraintLengths constraint lengths
* @param platform platform reference
*
* @return ErrorReturnValue if error
*
* @throw OpenMMException if constraintIndices.size() != constraintLengths.size()
*
*/
int BrookShakeAlgorithm::_setShakeStreams( const std::vector<double>& masses,
const std::vector< std::vector<int> >& constraintIndices,
const std::vector<double>& constraintLengths,
const Platform& platform ){
// ---------------------------------------------------------------------------------------
BrookOpenMMFloat one = static_cast<BrookOpenMMFloat>( 1.0 );
BrookOpenMMFloat half = static_cast<BrookOpenMMFloat>( 0.5 );
static const std::string methodName = "BrookShakeAlgorithm::_updateSdStreams";
// ---------------------------------------------------------------------------------------
FILE* log = getLog();
// check that number of constraints for two input vectors is consistent
if( constraintIndices.size() != constraintLengths.size() ){
std::stringstream message;
message << methodName << " constraintIndices size=" << constraintIndices.size() << " does not equal constraintLengths size=" << constraintLengths.size();
throw OpenMMException( message.str() );
return ErrorReturnValue;
}
// get constraint count for each atom
vector<int> constraintCount( masses.size(), 0);
std::vector< std::vector<int> >::const_iterator particleIterator = constraintIndices.begin();
while( particleIterator != constraintIndices.end() ){
std::vector<int> particleVector = *particleIterator;
int atomI = particleVector[0];
int atomJ = particleVector[1];
// check that atom indices are not out of range
if( atomI < 0 || atomI > (int) masses.size() ){
std::stringstream message;
message << methodName << " constraint I-index=" << atomI << " is out of range [0, " << masses.size() << "]" << std::endl;
throw OpenMMException( message.str() );
return ErrorReturnValue;
}
if( atomJ < 0 || atomJ > (int) masses.size() ){
std::stringstream message;
message << methodName << " constraint J-index=" << atomJ << " is out of range [0, " << masses.size() << "]" << std::endl;
throw OpenMMException( message.str() );
return ErrorReturnValue;
}
constraintCount[atomI]++;
constraintCount[atomJ]++;
particleIterator++;
}
_numberOfConstraints = static_cast<int>(constraintIndices.size());
if( _numberOfConstraints < 1 )return DefaultReturnValue;
// Find clusters consisting of a central atom with up to three peripheral atoms.
particleIterator = constraintIndices.begin();
std::vector<double>::const_iterator distanceIterator = constraintLengths.begin();
while( particleIterator != constraintIndices.end() ){
float distance = static_cast<float>( *distanceIterator );
std::vector<int> particleVector = *particleIterator;
int atomI = particleVector[0];
int atomJ = particleVector[1];
// Determine the central atom.
bool firstIsCentral;
if( constraintCount[atomI] > 1 ){
firstIsCentral = true;
} else if( constraintCount[atomJ] > 1 ){
firstIsCentral = false;
} else if( atomI < atomJ ){
firstIsCentral = true;
} else {
firstIsCentral = false;
}
int centralID, peripheralID;
float centralInvMass, peripheralInvMass;
if( firstIsCentral ){
centralID = atomI;
peripheralID = atomJ;
centralInvMass = static_cast<float>( masses[atomI] );
peripheralInvMass = static_cast<float>( masses[atomJ] );
} else {
centralID = atomJ;
peripheralID = atomI;
centralInvMass = static_cast<float>( masses[atomJ] );
peripheralInvMass = static_cast<float>( masses[atomI] );
}
if( constraintCount[peripheralID] != 1 ){
throw OpenMMException("Only bonds to hydrogens may be constrained");
}
// Add it to the cluster
if( _clusters.find(centralID) == _clusters.end() ){
_clusters[centralID] = ShakeCluster( centralID, 1.0f/centralInvMass );
}
_clusters[centralID].addAtom( peripheralID, distance, 1.0f/peripheralInvMass );
particleIterator++;
distanceIterator++;
}
// allocate space for streams
_initializeStreamSizes( (int) masses.size(), (int) _clusters.size(), platform );
_initializeStreams( platform );
int shakeParticleStreamSize = getShakeParticleStreamSize();
int shakeConstraintStreamSize = getShakeConstraintStreamSize();
// allocate arrays to be read down to board and initialize
BrookOpenMMFloat* particleIndices = new BrookOpenMMFloat[4*shakeConstraintStreamSize];
BrookOpenMMFloat* shakeParameters = new BrookOpenMMFloat[4*shakeConstraintStreamSize];
BrookOpenMMFloat minusOne = static_cast<BrookOpenMMFloat>(-1.0);
for( int ii = 0; ii < 4*shakeConstraintStreamSize; ii++ ){
particleIndices[ii] = minusOne;
}
memset( shakeParameters, 0, 4*shakeConstraintStreamSize*sizeof( BrookOpenMMFloat ) );
// load indices & parameters
int constraintIndex = 0;
for( map<int, ShakeCluster>::const_iterator iter = _clusters.begin(); iter != _clusters.end(); ++iter ){
const ShakeCluster& cluster = iter->second;
particleIndices[constraintIndex] = static_cast<BrookOpenMMFloat>( cluster._centralID );
for( int ii = 0; ii < cluster._size; ii++ ){
particleIndices[constraintIndex+ii+1] = static_cast<BrookOpenMMFloat>( cluster._peripheralID[ii] );
}
shakeParameters[constraintIndex] = static_cast<BrookOpenMMFloat>( cluster._centralInvMass );
shakeParameters[constraintIndex+1] = half/( static_cast<BrookOpenMMFloat>( cluster._centralInvMass + cluster._peripheralInvMass ) );
shakeParameters[constraintIndex+2] = static_cast<BrookOpenMMFloat>( cluster._distance*cluster._distance );
shakeParameters[constraintIndex+3] = static_cast<BrookOpenMMFloat>( cluster._peripheralInvMass );
constraintIndex += 4;
}
// write entries to board
_shakeStreams[ShakeParticleIndicesStream]->loadFromArray( particleIndices );
_shakeStreams[ShakeParticleParameterStream]->loadFromArray( shakeParameters );
delete[] shakeParameters;
// initialize inverse map
BrookOpenMMFloat* inverseMap = new BrookOpenMMFloat[2*shakeParticleStreamSize];
for( int ii = 0; ii < shakeParticleStreamSize*2; ii++ ){
inverseMap[ii] = static_cast<BrookOpenMMFloat>(-1.0);
}
// build inverse map
for( int ii = 0; ii < shakeConstraintStreamSize; ii++ ){
int ii4 = ii << 2;
for( int jj = 0; jj < 4; jj++ ){
if( particleIndices[ii4+jj] > -1.0f ){
int particleIndex = (int) (particleIndices[ii4+jj] + 0.001);
inverseMap[particleIndex*2] = (float) ii;
inverseMap[particleIndex*2+1] = (float) jj;
}
}
}
_shakeStreams[ShakeInverseMapStream]->loadFromArray( inverseMap );
delete[] particleIndices;
delete[] inverseMap;
return DefaultReturnValue;
}
/*
* Setup of Shake parameters
*
* @param masses masses
* @param constraintIndices constraint particle indices
* @param constraintLengths constraint lengths
* @param platform Brook platform
*
* @return ErrorReturnValue if error
*
*/
int BrookShakeAlgorithm::setup( const std::vector<double>& masses, const std::vector<std::vector<int> >& constraintIndices,
const std::vector<double>& constraintLengths, const Platform& platform ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookShakeAlgorithm::setup";
// ---------------------------------------------------------------------------------------
int numberOfParticles = (int) masses.size();
setNumberOfParticles( numberOfParticles );
_setShakeStreams( masses, constraintIndices, constraintLengths, platform );
return DefaultReturnValue;
}
/*
* Check constraints
*
* @param positions atom positions
* @param outputString output message
* @param tolerance tolerance to compare (if < 0, then use algorithm tolerance
*
* @return number of errors
*
*/
int BrookShakeAlgorithm::checkConstraints( BrookStreamInternal* positions, std::string& outputString, float tolerance ) const {
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookShakeAlgorithm::checkConstraints";
static const int maxErrorToPrint = -10;
// ---------------------------------------------------------------------------------------
void* posArrayV = positions->getData( 1 );
const float* posArray = (float*) posArrayV;
/*
fprintf( log, "ShakeCoords\n" );
for( int ii = 0; ii < 30; ii++ ){
if( !(ii % 3 ) )fprintf( log, "%d [", ii );
fprintf( log, "%16.7e ", posArray[ii] );
if( !(ii % 2 ) )fprintf( log, "]\n", posArray[ii] );
} */
// loop over constraints checking if distances are satisfied
// build up message string if errors are detected
// also track max difference in case all constraints satisfied
// to within specified tolerance
std::stringstream message;
int errors = 0;
float maxDiff = -1.0f;
int maxDiffCentralIndex = -1;
int maxDiffPeripheralIndex = -1;
tolerance = tolerance > 0.0f ? tolerance : _shakeTolerance;
for( map<int, ShakeCluster>::const_iterator iter = _clusters.begin(); iter != _clusters.end(); ++iter ){
const ShakeCluster& cluster = iter->second;
// multiply by 3 to get index into 1d array
int centralAtomIndex = 3*cluster._centralID;
for( int ii = 0; ii < cluster._size; ii++ ){
int peripheralAtomIndex = 3*cluster._peripheralID[ii];
if( peripheralAtomIndex > -1 && centralAtomIndex > -1 ){
float distance = sqrtf(
(posArray[centralAtomIndex] - posArray[peripheralAtomIndex] )*(posArray[centralAtomIndex] - posArray[peripheralAtomIndex] ) +
(posArray[centralAtomIndex+1] - posArray[peripheralAtomIndex+1])*(posArray[centralAtomIndex+1] - posArray[peripheralAtomIndex+1]) +
(posArray[centralAtomIndex+2] - posArray[peripheralAtomIndex+2])*(posArray[centralAtomIndex+2] - posArray[peripheralAtomIndex+2]) );
float diff = fabsf( distance - cluster._distance );
if( diff > tolerance && (errors++ < maxErrorToPrint || maxErrorToPrint < 0) ){
char value[1024];
#ifdef _MSC_VER
sprintf_s( value, 1024, "Error: Atom [%6d %6d] d[%16.7e %16.7e] diff=%16.7e [%16.7e %16.7e %16.7e] [%16.7e %16.7e %16.7e]\n",
centralAtomIndex/3, peripheralAtomIndex/3, distance, cluster._distance, diff,
posArray[centralAtomIndex], posArray[centralAtomIndex+1], posArray[centralAtomIndex+2],
posArray[peripheralAtomIndex], posArray[peripheralAtomIndex+1], posArray[peripheralAtomIndex+2] );
#else
sprintf( value, "Error: Atom [%6d %6d] diff=%16.7e d[%16.7e %16.7e] [%16.7e %16.7e %16.7e] [%16.7e %16.7e %16.7e]\n",
centralAtomIndex/3, peripheralAtomIndex/3, diff, distance, cluster._distance,
posArray[centralAtomIndex][0], posArray[centralAtomIndex][1], posArray[centralAtomIndex][2],
posArray[peripheralAtomIndex][0], posArray[peripheralAtomIndex][1], posArray[peripheralAtomIndex][2] );
#endif
message << value;
}
if( diff > maxDiff ){
maxDiffCentralIndex = centralAtomIndex/3;
maxDiffPeripheralIndex = peripheralAtomIndex/3;
maxDiff = diff;
}
}
}
}
// report findings
std::stringstream outputMessage;
char text[1024];
if( errors ){
#ifdef _MSC_VER
(void) sprintf_s( text, 1024, "Shake errors=%d tol=%.3e mxDff=%.3e atoms[%d %d]", errors, tolerance, maxDiff, maxDiffCentralIndex, maxDiffPeripheralIndex );
#else
(void) sprintf( text, "Shake errors=%d tol=%.3e mxDff=%.3e atoms[%d %d]", errors, tolerance, maxDiff, maxDiffCentralIndex, maxDiffPeripheralIndex );
#endif
outputMessage << text;
if( errors >= maxErrorToPrint ){
#ifdef _MSC_VER
(void) sprintf_s( text, 1024, " only printing first %d errors", maxErrorToPrint );
#else
(void) sprintf( text, " only printing first %d errors", maxErrorToPrint );
#endif
outputMessage << text;
}
outputMessage << message.str();
} else {
#ifdef _MSC_VER
(void) sprintf_s( text, 1024, "Shake no errors: tol=%.3e mxDff=%.3e", tolerance, maxDiff );
#else
(void) sprintf( text, "Shake no errors: tol=%.3e mxDff=%.3e", tolerance, maxDiff );
#endif
outputMessage << text;
}
outputString = outputMessage.str();
return errors;
}
/*
* Get contents of object
*
* @param level level of dump
*
* @return string containing contents
*
* */
std::string BrookShakeAlgorithm::getContentsString( int level ) const {
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookShakeAlgorithm::getContentsString";
static const unsigned int MAX_LINE_CHARS = 256;
char value[MAX_LINE_CHARS];
static const char* Set = "Set";
static const char* NotSet = "Not set";
// ---------------------------------------------------------------------------------------
std::stringstream message;
std::string tab = " ";
#ifdef _MSC_VER
#define LOCAL_SPRINTF(a,b,c) sprintf_s( (a), MAX_LINE_CHARS, (b), (c) );
#else
#define LOCAL_SPRINTF(a,b,c) sprintf( (a), (b), (c) );
#endif
(void) LOCAL_SPRINTF( value, "%d", getNumberOfConstraints() );
message << _getLine( tab, "Number of constraints:", value );
(void) LOCAL_SPRINTF( value, "%d", getNumberOfParticles() );
message << _getLine( tab, "Number of particles:", value );
(void) LOCAL_SPRINTF( value, "%d", getMaxIterations() );
message << _getLine( tab, "Max iterations:", value );
(void) LOCAL_SPRINTF( value, "%2e", getShakeTolerance() );
message << _getLine( tab, "Tolerance:", value );
(void) LOCAL_SPRINTF( value, "%d", getParticleStreamWidth() );
message << _getLine( tab, "Particle stream width:", value );
(void) LOCAL_SPRINTF( value, "%d", getParticleStreamHeight() );
message << _getLine( tab, "Particle stream height:", value );
(void) LOCAL_SPRINTF( value, "%d", getParticleStreamSize() );
message << _getLine( tab, "Particle stream size:", value );
(void) LOCAL_SPRINTF( value, "%d", getShakeConstraintStreamWidth() );
message << _getLine( tab, "Constraint stream width:", value );
(void) LOCAL_SPRINTF( value, "%d", getShakeConstraintStreamHeight() );
message << _getLine( tab, "Constraint stream height:", value );
(void) LOCAL_SPRINTF( value, "%d", getShakeConstraintStreamSize() );
message << _getLine( tab, "Constraint stream size:", value );
message << _getLine( tab, "Constraints:", " " );
int index = 0;
for( map<int, ShakeCluster>::const_iterator iter = _clusters.begin(); iter != _clusters.end(); ++iter ){
char buffer[1024];
const ShakeCluster& cluster = iter->second;
#ifdef _MSC_VER
sprintf_s( buffer, 1024, "%5d %6d [%6d %6d %6d] d=%.3f m[%12.5f %12.5f]", index++, cluster._centralID,
cluster._peripheralID[0], cluster._peripheralID[1], cluster._peripheralID[2],
cluster._distance, cluster._centralInvMass, cluster._peripheralInvMass );
#endif
message << _getLine( tab, " ", buffer );
}
message << _getLine( tab, "Log:", (getLog() ? Set : NotSet) );
message << _getLine( tab, "ParticleIndices:", (getShakeParticleIndicesStream() ? Set : NotSet) );
message << _getLine( tab, "ParticleParameters:", (getShakeParticleParameterStream() ? Set : NotSet) );
message << _getLine( tab, "XCons0:", (getShakeXCons0Stream() ? Set : NotSet) );
message << _getLine( tab, "XCons1:", (getShakeXCons1Stream() ? Set : NotSet) );
message << _getLine( tab, "XCons2:", (getShakeXCons2Stream() ? Set : NotSet) );
message << _getLine( tab, "XCons3:", (getShakeXCons3Stream() ? Set : NotSet) );
message << _getLine( tab, "InverseMap:", (getShakeInverseMapStream() ? Set : NotSet) );
for( int ii = 0; ii < LastStreamIndex; ii++ ){
message << std::endl;
if( _shakeStreams[ii] ){
message << _shakeStreams[ii]->getContentsString( );
}
}
#undef LOCAL_SPRINTF
return message.str();
}
#ifndef OPENMM_BROOK_SHAKE_ALGORITHM_H_
#define OPENMM_BROOK_SHAKE_ALGORITHM_H_
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include <vector>
#include <set>
#include <sstream>
#include "BrookFloatStreamInternal.h"
#include "BrookPlatform.h"
#include "BrookCommon.h"
#include "openmm/OpenMMException.h"
namespace OpenMM {
struct ShakeCluster {
int _centralID;
int _peripheralID[3];
int _size;
float _distance;
float _centralInvMass, _peripheralInvMass;
ShakeCluster(){};
ShakeCluster( int centralID, float invMass) : _centralID(centralID), _centralInvMass(invMass), _size(0) {
_peripheralID[0] = _peripheralID[1] = _peripheralID[2] = -1;
};
void addAtom( int id, float dist, float invMass){
if( _size == 3 ){
std::stringstream message;
message << "ShakeCluster::addAtom: " << "atom " << id << " has more than 3 constraints!." << std::endl;
throw OpenMMException( message.str() );
}
if( _size > 0 && dist != _distance ){
std::stringstream message;
message << "ShakeCluster::addAtom: " << "atom " << id << " has different constraint distances: " << dist << " and " << _distance << std::endl;
throw OpenMMException( message.str() );
}
if( _size > 0 && invMass != _peripheralInvMass ){
std::stringstream message;
message << "ShakeCluster::addAtom: " << " constrainted atoms associated w/ atom " << id << " have different masses: " << invMass << " and " << _peripheralInvMass << std::endl;
throw OpenMMException( message.str() );
}
_peripheralID[_size++] = id;
_distance = dist;
_peripheralInvMass = invMass;
}
};
/**
*
* Encapsulates stochastic dynamics algorithm
*
*/
class BrookShakeAlgorithm : public BrookCommon {
public:
/**
* Constructor
*
*/
BrookShakeAlgorithm( );
/**
* Destructor
*
*/
~BrookShakeAlgorithm();
/**
* Get number of constraints
*
* @return number of constraints
*
*/
int getNumberOfConstraints( void ) const;
/**
* Get max iterations
*
* @return max iterations
*
*/
int getMaxIterations( void ) const;
/**
* Set max iterations
*
* @param max iterations
*
* @return DefaultReturnValue
*
*/
int setMaxIterations( int maxIterations );
/**
* Get SHAKE tolerance
*
* @return SHAKE tolerance
*
*/
BrookOpenMMFloat getShakeTolerance( void ) const;
/**
* Set SHAKE tolerance
*
* @param SHAKE tolerance
*
* @return DefaultReturnValue
*
*/
int setShakeTolerance( BrookOpenMMFloat tolerance );
/**
* Get Shake particle stream width
*
* @return particle stream width
*/
int getShakeParticleStreamWidth( void ) const;
/**
* Get Shake particle stream height
*
* @return particle stream height
*/
int getShakeParticleStreamHeight( void ) const;
/**
* Get Shake particle stream size
*
* @return particle stream size
*/
int getShakeParticleStreamSize( void ) const;
/**
* Get Shake constraint stream width
*
* @return constraint stream width
*/
int getShakeConstraintStreamWidth( void ) const;
/**
* Get Shake constraint stream height
*
* @return constraint stream height
*/
int getShakeConstraintStreamHeight( void ) const;
/**
* Get Shake constraint stream size
*
* @return constraint stream size
*/
int getShakeConstraintStreamSize( void ) const;
/**
* Get array of Shake streams
*
* @return array ofstreams
*
*/
BrookFloatStreamInternal** getStreams( void );
/*
* Setup of Shake parameters
*
* @param masses masses
* @param constraintIndices constraint particle indices
* @param constraintLengths constraint lengths
* @param platform Brook platform
*
* @return ErrorReturnValue if error
*
*/
int setup( const std::vector<double>& masses, const std::vector< std::vector<int> >& constraintIndices,
const std::vector<double>& constraintLengths, const Platform& platform );
/*
* Get contents of object
*
* @param level of dump
*
* @return string containing contents
*
* */
std::string getContentsString( int level = 0 ) const;
/**
* Get Shake particle indices stream
*
* @return Shake particle indices stream
*
*/
BrookFloatStreamInternal* getShakeParticleIndicesStream( void ) const;
/**
* Get Shake particle parameter stream
*
* @return Shake particle parameter stream
*
*/
BrookFloatStreamInternal* getShakeParticleParameterStream( void ) const;
/**
* Get XCons0 stream
*
* @return XCons0 stream
*
*/
BrookFloatStreamInternal* getShakeXCons0Stream( void ) const;
/**
* Get XCons1 stream
*
* @return XCons1 stream
*
*/
BrookFloatStreamInternal* getShakeXCons1Stream( void ) const;
/**
* Get XCons2 stream
*
* @return XCons2 stream
*
*/
BrookFloatStreamInternal* getShakeXCons2Stream( void ) const;
/**
* Get XCons3 stream
*
* @return XCons3 stream
*
*/
BrookFloatStreamInternal* getShakeXCons3Stream( void ) const;
/**
* Get Shake inverse map stream
*
* @return Shake inverse map stream
*
*/
BrookFloatStreamInternal* getShakeInverseMapStream( void ) const;
/*
* Check constraints
*
* @param positions atom positions
* @param outputString output message
* @param tolerance tolerance to compare (if < 0, then use algorithm tolerance
*
* @return number of errors
*
*/
int checkConstraints( BrookStreamInternal* positions, std::string& outputString, float tolerance ) const;
private:
// streams indices
enum BrookShakeAlgorithmStreams {
ShakeParticleIndicesStream,
ShakeParticleParameterStream,
ShakeXCons0Stream,
ShakeXCons1Stream,
ShakeXCons2Stream,
ShakeXCons3Stream,
ShakeInverseMapStream,
LastStreamIndex
};
// number of constraints
int _numberOfConstraints;
// max iterations
int _maxIterations;
// particle stream dimensions
int _shakeParticleStreamWidth;
int _shakeParticleStreamHeight;
int _shakeParticleStreamSize;
// constraint stream dimensions
int _shakeConstraintStreamSize;
int _shakeConstraintStreamWidth;
int _shakeConstraintStreamHeight;
// SHAKE tolerance
BrookOpenMMFloat _shakeTolerance;
// inverse sqrt masses
BrookOpenMMFloat* _inverseSqrtMasses;
// internal streams
BrookFloatStreamInternal* _shakeStreams[LastStreamIndex];
// Shake cluster (used for debugging)
std::map<int, ShakeCluster> _clusters;
/*
* Setup of stream dimensions
*
* @param particleStreamSize particle stream size
* @param particleStreamWidth particle stream width
*
* @return ErrorReturnValue if error, else DefaultReturnValueValue
*
* */
int _initializeStreamSizes( int particleStreamSize, int particleStreamWidth );
/**
* Initialize stream dimensions
*
* @param numberOfParticles number of particles
* @param numberOfConstraints number of constraints
* @param platform platform
*
* @return ErrorReturnValue if error, else DefaultReturnValueValue
*
*/
int _initializeStreamSizes( int numberOfParticles, int numberOfConstraints, const Platform& platform );
/**
* Initialize stream dimensions and streams
*
* @param platform platform
*
* @return nonzero value if error
*
*/
int _initializeStreams( const Platform& platform );
/*
* Set Shake streams
*
* @param masses masses
* @param constraintIndices constraint particle indices
* @param constraintLengths constraint lengths
* @param platform platform reference
*
* @return ErrorReturnValue if error
*
* @throw OpenMMException if constraintIndices.size() != constraintLengths.size()
*
*/
int _setShakeStreams( const std::vector<double>& masses, const std::vector< std::vector<int> >& constraintIndices,
const std::vector<double>& constraintLengths, const Platform& platform );
};
} // namespace OpenMM
#endif /* OPENMM_BROOK_SHAKE_ALGORITHM_H_ */
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "openmm/OpenMMException.h"
#include "BrookStreamFactory.h"
#include "BrookStreamImpl.h"
#include "openmm/internal/ContextImpl.h"
#include "OpenMMBrookInterface.h"
#include <sstream>
using namespace OpenMM;
const std::string BrookStreamFactory::ParticlePositions = "particlePositions";
const std::string BrookStreamFactory::ParticleVelocities = "particleVelocities";
const std::string BrookStreamFactory::ParticleForces = "particleForces";
const double DefaultDangleValue = 1.0e+08;
/**
* BrookStreamFactory constructor
*
* @return BrookStreamFactory
*/
BrookStreamFactory::BrookStreamFactory( void ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookStreamFactory::BrookStreamFactory";
// ---------------------------------------------------------------------------------------
_defaultDangleValue = 1.0e+08;
_defaultParticleStreamWidth = DefaultStreamParticleWidth;
_defaultStreamRandomNumberWidth = DefaultStreamRandomNumberWidth;
_defaultStreamRandomNumberSize = DefaultStreamRandomNumberSize;
}
/**
* BrookStreamFactory destructor
*
*/
BrookStreamFactory::~BrookStreamFactory( ){
}
/**
* Get particle stream width
*
* @return particleStreamWidth
*
*/
int BrookStreamFactory::getDefaultParticleStreamWidth( void ) const {
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookStreamFactory::getDefaultParticleStreamWidth";
// ---------------------------------------------------------------------------------------
return _defaultParticleStreamWidth;
}
/**
* Set particle stream width
*
* @param particleStreamWidth particle stream width
*
* @return DefaultReturnValue
*
* @throw OpenMMException if particleStreamWidth < 1
*
*/
int BrookStreamFactory::setDefaultParticleStreamWidth( int particleStreamWidth ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookStreamFactory::setDefaultParticleStreamWidth";
// ---------------------------------------------------------------------------------------
// validate particle stream width
if( particleStreamWidth < 1 ){
std::stringstream message;
message << methodName << " particleStreamWidth=" << particleStreamWidth << " is less than 1.";
throw OpenMMException( message.str() );
return ErrorReturnValue;
}
_defaultParticleStreamWidth = particleStreamWidth;
return DefaultReturnValue;
}
/**
* Get randomNumber stream width
*
* @return randomNumberStreamWidth
*
*/
int BrookStreamFactory::getDefaultRandomNumberStreamWidth( void ) const {
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookStreamFactory::getDefaultRandomNumberStreamWidth";
// ---------------------------------------------------------------------------------------
return _defaultStreamRandomNumberWidth;
}
/**
* Set randomNumber stream width
*
* @param randomNumberStreamWidth randomNumber stream width
*
* @return DefaultReturnValue
*
* @throw OpenMMException if randomNumberStreamWidth < 1
*
*/
int BrookStreamFactory::setDefaultRandomNumberStreamWidth( int randomNumberStreamWidth ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookStreamFactory::setDefaultRandomNumberStreamWidth";
// ---------------------------------------------------------------------------------------
// validate randomNumber stream width
if( randomNumberStreamWidth < 1 ){
std::stringstream message;
message << methodName << " randomNumberStreamWidth=" << randomNumberStreamWidth << " is less than 1.";
throw OpenMMException( message.str() );
return ErrorReturnValue;
}
_defaultStreamRandomNumberWidth = randomNumberStreamWidth;
return DefaultReturnValue;
}
/*
* Get randomNumber stream size
*
* @return randomNumberStreamSize
*
*/
int BrookStreamFactory::getDefaultRandomNumberStreamSize( void ) const {
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookStreamFactory::getDefaultRandomNumberStreamSize";
// ---------------------------------------------------------------------------------------
return _defaultStreamRandomNumberSize;
}
/**
* Set randomNumber stream size
*
* @param randomNumberStreamSize randomNumber stream size
*
* @return DefaultReturnValue
*
* @throw OpenMMException if randomNumberStreamSize < 1
*
*/
int BrookStreamFactory::setDefaultRandomNumberStreamSize( int randomNumberStreamSize ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookStreamFactory::setDefaultRandomNumberStreamSize";
// ---------------------------------------------------------------------------------------
// validate randomNumber stream size
if( randomNumberStreamSize < 1 ){
std::stringstream message;
message << methodName << " randomNumberStreamSize=" << randomNumberStreamSize << " is less than 1.";
throw OpenMMException( message.str() );
return ErrorReturnValue;
}
_defaultStreamRandomNumberSize = randomNumberStreamSize;
return DefaultReturnValue;
}
/**
* Get default dangle value
*
* @return default dangle value
*
*/
double BrookStreamFactory::getDefaultDangleValue( void ) const {
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookStreamFactory::getDefaultDangleValue";
// ---------------------------------------------------------------------------------------
return _defaultDangleValue;
}
/**
* Set default dangle value
*
* @param DefaultDangleValue default dangle value
*
* @return DefaultReturnValue
*
*/
int BrookStreamFactory::setDefaultDangleValue( double defaultDangleValue ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookStreamFactory::setDefaultDangleValue";
// ---------------------------------------------------------------------------------------
_defaultDangleValue = defaultDangleValue;
return DefaultReturnValue;
}
/**
* Create StreamInternal
*
* @param name stream name
* @param size stream size
* @param type data type (float, float2, ...)
* @param platform platform reference
* @param context context (currently ignored)
*
* @return StreamInternal
*/
StreamImpl* BrookStreamFactory::createStreamImpl( std::string name, int size, Stream::DataType type,
const Platform& platform, ContextImpl& context ) const {
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookStreamFactory::createStreamImpl";
// ---------------------------------------------------------------------------------------
// stream width hould be based on name & value set in platform; for now only particle stream types
int streamWidth = getDefaultParticleStreamWidth();
BrookStreamImpl* brookStreamImpl = new BrookStreamImpl( name, size, streamWidth, type, platform );
OpenMMBrookInterface& openMMBrookInterface = *static_cast<OpenMMBrookInterface*>(context.getPlatformData());
if( name == ParticlePositions ){
openMMBrookInterface.setParticlePositions( brookStreamImpl );
} else if( name == ParticleVelocities ){
openMMBrookInterface.setParticleVelocities( brookStreamImpl );
} else if( name == ParticleForces ){
openMMBrookInterface.setParticleForces( brookStreamImpl );
}
return brookStreamImpl;
}
/**
* Create StreamInternal
*
* @param name stream name
* @param size stream size
* @param type data type (float, float2, ...)
* @param platform platform reference
*
* @return StreamInternal
*/
StreamImpl* BrookStreamFactory::createStreamImpl( std::string name, int size, Stream::DataType type,
const Platform& platform ) const {
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookStreamFactory::createStreamImpl";
// ---------------------------------------------------------------------------------------
// stream width hould be based on name & value set in platform; for now only particle stream types
int streamWidth = getDefaultParticleStreamWidth();
BrookStreamImpl* brookStreamImpl = new BrookStreamImpl( name, size, streamWidth, type, platform );
return brookStreamImpl;
}
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "openmm/OpenMMException.h"
#include "BrookStreamImpl.h"
#include <sstream>
using namespace OpenMM;
using namespace std;
/**
* BrookStreamImpl constructor
*
* @param name stream name
* @param size stream size
* @param streamWidth stream width
* @param type StreamImpl data type (float, float2, ...)
* @param platform platform reference
*
*/
BrookStreamImpl::BrookStreamImpl( const std::string& name, int size, int streamWidth, Stream::DataType type, const Platform& platform ) :
StreamImpl( name, size, type, platform ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookStreamImpl::BrookStreamImpl";
// ---------------------------------------------------------------------------------------
int isFloat;
BrookStreamInternal::DataType internalType = getTypeMap( type, &isFloat );
if( isFloat == 1 || isFloat == 2 ){
double dangleValue = 0.0;
_brookStreamInternal = new BrookFloatStreamInternal( name, size, streamWidth, internalType, dangleValue );
} else if( isFloat == 0 ){
int dangleValue = 0;
_brookStreamInternal = new BrookIntStreamInternal( name, size, streamWidth, internalType, dangleValue );
} else {
std::stringstream message;
message << methodName << " type=" << type << " for stream=" << name << " is invalid.";
throw OpenMMException( message.str() );
}
}
/**
* BrookStreamImpl destructor
*
*/
BrookStreamImpl::~BrookStreamImpl( ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookStreamImpl::~BrookStreamImpl";
// ---------------------------------------------------------------------------------------
}
/**
* BrookStreamImpl constructor
*
* @param type StreamImpl data type (float, float2, ...)
* @param isFloat on output = 1 if float
* 2 if double
* 0 if integer
*
* @return BrookStreamInternal::DataType mapping to Stream::DataType type
* if no match, return BrookStreamInternal::Unknown
*
*/
BrookStreamInternal::DataType BrookStreamImpl::getTypeMap( Stream::DataType type, int* isFloat ) const {
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookStreamImpl::getTypeMap";
// ---------------------------------------------------------------------------------------
*isFloat = 0;
BrookStreamInternal::DataType internalType = BrookStreamInternal::Unknown;
switch ( type ){
case Stream::Float:
internalType = BrookStreamInternal::Float;
*isFloat = 1;
break;
case Stream::Float2:
internalType = BrookStreamInternal::Float2;
*isFloat = 1;
break;
case Stream::Float3:
internalType = BrookStreamInternal::Float3;
*isFloat = 1;
break;
case Stream::Float4:
internalType = BrookStreamInternal::Float4;
*isFloat = 1;
break;
case Stream::Double:
internalType = BrookStreamInternal::Double;
*isFloat = 2;
break;
case Stream::Double2:
internalType = BrookStreamInternal::Double2;
*isFloat = 2;
break;
case Stream::Double3:
internalType = BrookStreamInternal::Double3;
*isFloat = 2;
break;
case Stream::Double4:
internalType = BrookStreamInternal::Double4;
*isFloat = 2;
break;
case Stream::Integer:
internalType = BrookStreamInternal::Integer;
*isFloat = 0;
break;
case Stream::Integer2:
internalType = BrookStreamInternal::Integer2;
*isFloat = 0;
break;
case Stream::Integer3:
internalType = BrookStreamInternal::Integer3;
*isFloat = 0;
break;
case Stream::Integer4:
internalType = BrookStreamInternal::Integer4;
*isFloat = 0;
break;
}
return internalType;
}
/**
* Get width
*
* @return width
*/
int BrookStreamImpl::getWidth( void ) const {
return _brookStreamInternal->getWidth();
}
/**
* Get stream width
*
* @return stream width
*/
int BrookStreamImpl::getStreamWidth( void ) const {
return _brookStreamInternal->getStreamWidth();
}
/**
* Get stream height
*
* @return stream height
*/
int BrookStreamImpl::getStreamHeight( void ) const {
return _brookStreamInternal->getStreamHeight();
}
/**
* Get stream size
*
* @return stream size
*/
int BrookStreamImpl::getStreamSize( void ) const {
return _brookStreamInternal->getStreamSize();
}
/**
* Copy the contents of an array into this stream.
*
* @param array a pointer to the start of the array. The array is assumed to have the same length as this stream,
* and to contain elements of the correct data type for this stream. If the stream has a compound data type, all
* the values should be packed into a single array: all the values for the first element, followed by all the values
* for the next element, etc.
*/
void BrookStreamImpl::loadFromArray( const void* array ){
return _brookStreamInternal->loadFromArray( array );
}
/**
* Copy the contents of this stream into an array.
*
* @param array a pointer to the start of the array. The array is assumed to have the same length as this stream,
* and to contain elements of the correct data type for this stream. If the stream has a compound data type, all
* the values should be packed into a single array: all the values for the first element, followed by all the values
* for the next element, etc.
*/
void BrookStreamImpl::saveToArray( void* array ){
return _brookStreamInternal->saveToArray( array );
}
/**
* Set every element of this stream to the same value.
*
* @param a pointer to the value. It is assumed to be of the correct data type for this stream.
*/
void BrookStreamImpl::fillWithValue( void* value ){
return _brookStreamInternal->fillWithValue( value );
}
/**
* Set every element of this stream to the same value.
*
* @return data array
*/
void* BrookStreamImpl::getData( void ){
return _brookStreamInternal->getData( );
}
/**
* Set every element of this stream to the same value.
*
* @param readFromBoard if set, read data from board
*
* @return data array
*/
void* BrookStreamImpl::getData( int readFromBoard ){
return _brookStreamInternal->getData( readFromBoard );
}
/**
* Get Brook stream
*
* @return Brook stream reference
*/
brook::stream& BrookStreamImpl::getBrookStream( void ){
return _brookStreamInternal->getBrookStream( );
}
/**
* Get Brook stream impl
*
* @return Brook stream impl
*/
BrookStreamInternal* BrookStreamImpl::getBrookStreamInternal( void ) const {
return _brookStreamInternal;
}
#ifndef OPENMM_BROOK_STREAM_IMPL_H_
#define OPENMM_BROOK_STREAM_IMPL_H_
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "openmm/StreamImpl.h"
#include "BrookFloatStreamInternal.h"
#include "BrookIntStreamInternal.h"
namespace OpenMM {
/**
* This is the base class of Float and Double streams in the Brook Platform.
*/
class BrookStreamImpl : public StreamImpl {
public:
/**
* BrookStreamImpl constructor
*
* @param name name of the stream to create
* @param size number of elements in the stream
* @param streamWidth stream width
* @param type data type of each element in the stream
* @param platform platform
*
*/
BrookStreamImpl( const std::string& name, int size, int streamWidth, Stream::DataType type, const Platform& platform );
/**
* BrookStreamImpl destructor
*
*/
~BrookStreamImpl( );
/**
* BrookStreamImpl constructor
*
* @param type StreamImpl data type (float, float2, ...)
* @param isFloat on output = 1 if float
* 2 if double
* 0 if integer
*
* @return BrookStreamInternal::DataType mapping to Stream::DataType type
* if no match, return BrookStreamInternal::Unknown
*
*/
BrookStreamInternal::DataType getTypeMap( Stream::DataType type, int* isFloat ) const;
/**
* Copy the contents of an array into this stream.
*
* @param array a pointer to the start of the array. The array is assumed to have the same length as this stream,
* and to contain elements of the correct data type for this stream. If the stream has a compound data type, all
* the values should be packed into a single array: all the values for the first element, followed by all the values
* for the next element, etc.
*/
void loadFromArray( const void* array );
/**
* Copy the contents of this stream into an array.
*
* @param array a pointer to the start of the array. The array is assumed to have the same length as this stream,
* and to contain elements of the correct data type for this stream. If the stream has a compound data type, all
* the values should be packed into a single array: all the values for the first element, followed by all the values
* for the next element, etc.
*/
void saveToArray( void* array );
/**
* Set every element of this stream to the same value.
*
* @param a pointer to the value. It is assumed to be of the correct data type for this stream.
*/
void fillWithValue( void* value );
/**
* Get data array
*
* @return data array
*/
void* getData( void );
void* getData( int readFromBoard );
/**
* Get Brook stream
*
* @return Brook stream reference
*/
brook::stream& getBrookStream( void );
/**
* Get width
*
* @return width
*/
int getWidth( void ) const;
/**
* Get stream width
*
* @return stream width
*/
int getStreamWidth( void ) const;
/**
* Get stream height
*
* @return stream height
*/
int getStreamHeight( void ) const;
/**
* Get stream size
*
* @return stream size
*/
int getStreamSize( void ) const;
/*
* Get contents of object
*
*
* @param level level of dump
*
* @return string containing contents
*
* */
//const std::string getContentsString( int level = 0 ) const;
/**
* Get Brook stream impl
*
* @return Brook stream impl
*/
BrookStreamInternal* getBrookStreamInternal( void ) const;
protected:
BrookStreamInternal* _brookStreamInternal;
};
} // namespace OpenMM
#endif /* OPENMM_BROOK_STREAM_IMPL_H_ */
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "openmm/OpenMMException.h"
#include "BrookStreamInternal.h"
#include <sstream>
#ifdef _MSC_VER
#include <float.h>
#define isnan _isnan
#define isinf !_finite
#endif
using namespace OpenMM;
using namespace std;
BrookStreamInternal::BrookStreamInternal( const std::string& name, int size, int streamWidth, BrookStreamInternal::DataType type ) :
_name(name), _size(size), _streamWidth(streamWidth), _type(type) {
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookStreamInternal::BrookStreamInternal";
// ---------------------------------------------------------------------------------------
_streamHeight = _size/_streamWidth + ( (_size % _streamWidth) ? 1 : 0);
_streamSize = _streamWidth*_streamHeight;
_baseType = BrookStreamInternal::Unknown;
// _aStream = 0;
}
BrookStreamInternal::~BrookStreamInternal( ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookStreamInternal::~BrookStreamInternal";
// ---------------------------------------------------------------------------------------
// _aStream is not ptr
// delete _aStream;
}
/**
* Get name
*
* @return name
*/
const std::string& BrookStreamInternal::getName( void ) const {
return _name;
}
/**
* Get size
*
* @return size
*/
int BrookStreamInternal::getSize( void ) const {
return _size;
}
/**
* Get data type
*
* @return data type
*/
BrookStreamInternal::DataType BrookStreamInternal::getDataType( void ) const {
return _type;
}
/**
* Get base data type
*
* @return base data type ( float, double, int )
*/
BrookStreamInternal::DataType BrookStreamInternal::getBaseDataType( void ) const {
return _baseType;
}
/**
* Get width
*
* @return width
*/
int BrookStreamInternal::getWidth( void ) const {
return _width;
}
/**
* Get stream width
*
* @return stream width
*/
int BrookStreamInternal::getStreamWidth( void ) const {
return _streamWidth;
}
/**
* Get stream height
*
* @return stream height
*/
int BrookStreamInternal::getStreamHeight( void ) const {
return _streamHeight;
}
/**
* Get Brook stream
*
* @return Brook stream
*/
brook::stream& BrookStreamInternal::getBrookStream( void ){
return _aStream;
}
/**
* Get stream size
*
* @return stream size
*/
int BrookStreamInternal::getStreamSize( void ) const {
return _streamSize;
}
/**
* Get type string
*
* @param type BrookStreamInternal data type (float, float2, ...)
*
* @return string matching type or "Unknown"
*
*/
std::string BrookStreamInternal::getTypeString( BrookStreamInternal::DataType type ) const {
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookStreamImpl::getTypeString";
// ---------------------------------------------------------------------------------------
std::string typeString;
switch ( type ){
case BrookStreamInternal::Float:
typeString = "Float";
break;
case BrookStreamInternal::Float2:
typeString = "Float2";
break;
case BrookStreamInternal::Float3:
typeString = "Float3";
break;
case BrookStreamInternal::Float4:
typeString = "Float4";
break;
case BrookStreamInternal::Double:
typeString = "Double";
break;
case BrookStreamInternal::Double2:
typeString = "Double2";
break;
case BrookStreamInternal::Double3:
typeString = "Double3";
break;
case BrookStreamInternal::Double4:
typeString = "Double4";
break;
case BrookStreamInternal::Integer:
typeString = "Integer";
break;
case BrookStreamInternal::Integer2:
typeString = "Integer2";
break;
case BrookStreamInternal::Integer3:
typeString = "Integer3";
break;
case BrookStreamInternal::Integer4:
typeString = "Integer4";
break;
default:
typeString = "Unknown";
break;
}
return typeString;
}
/*
* Get contents of object
*
* @param tab tab
* @param description description
* @param value value
*
* @return string containing contents
*
* */
std::string BrookStreamInternal::_getLine( const std::string& tab,
const std::string& description,
const std::string& value ) const {
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookStreamInternal::_getLine";
static const unsigned int MAX_LINE_CHARS = 256;
char line[MAX_LINE_CHARS];
// ---------------------------------------------------------------------------------------
std::stringstream message;
memset( line, ' ', MAX_LINE_CHARS );
#ifdef _MSC_VER
(void) sprintf_s( line, MAX_LINE_CHARS, "%s %-40s %s", tab.c_str(), description.c_str(), value.c_str() );
#else
(void) sprintf( line, "%s %-40s %s", tab.c_str(), description.c_str(), value.c_str() );
#endif
message << std::string( line ) << std::endl;
return message.str();
}
/*
* Print contents of object to file
*
* @param log file to print to
* @param maxPrint max values to print; if < 0, then all values printed; default value is -1
*
* @return DefaultReturnValue
*
* */
int BrookStreamInternal::printToFile( FILE* log, int maxPrint ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookStreamInternal::printToFile";
// ---------------------------------------------------------------------------------------
if( log == NULL ){
log = stderr;
}
std::string contents = getContentsString();
(void) fprintf( log, "%s\n", contents.c_str() );
_bodyPrintToFile( log, maxPrint );
return DefaultReturnValue;
}
/*
* Get contents of object
*
* @param level level of dump
*
* @return string containing contents
*
* */
const std::string BrookStreamInternal::getContentsString( int level ) const {
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookStreamInternal::getContentsString";
static const unsigned int MAX_LINE_CHARS = 256;
char value[MAX_LINE_CHARS];
//static const char* Set = "Set";
//static const char* NotSet = "Not set";
// ---------------------------------------------------------------------------------------
std::stringstream message;
std::string tab = " ";
#ifdef _MSC_VER
#define LOCAL_SPRINTF(a,b,c) sprintf_s( (a), MAX_LINE_CHARS, (b), (c) );
#else
#define LOCAL_SPRINTF(a,b,c) sprintf( (a), (b), (c) );
#endif
(void) LOCAL_SPRINTF( value, "%s", getName().c_str() );
message << _getLine( tab, "Name:", value );
(void) LOCAL_SPRINTF( value, "%d", getWidth() );
message << _getLine( tab, "Width:", value );
(void) LOCAL_SPRINTF( value, "%d", getStreamSize() );
message << _getLine( tab, "Stream size:", value );
(void) LOCAL_SPRINTF( value, "%d", getStreamWidth() );
message << _getLine( tab, "Stream width:", value );
(void) LOCAL_SPRINTF( value, "%d", getStreamHeight() );
message << _getLine( tab, "Stream height:", value );
return message.str();
}
/*
* Get stats (virtual method -- only BrookStreamInternalFloat implemented for now)
*
* @param statistics output vector of stats
* @param maxScan number of points to use in computing stats
*
* @return 0
*
* */
int BrookStreamInternal::getStatistics( std::vector<std::vector<double> >& statistics, int maxScan ){
return 0;
}
/*
* Get stat string
*
* @param tag id tag
* @param statistics stat vector
*
* @return stat string
*
* */
std::string BrookStreamInternal::printStatistics( std::string tag, std::vector<std::vector<double> >& statistics ) const {
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookStreamInternal::getContentsString";
static const unsigned int MAX_LINE_CHARS = 256;
char value[MAX_LINE_CHARS];
std::string tab = " ";
static int initialized = 0;
static std::vector<std::string> header;
// ---------------------------------------------------------------------------------------
// row headers
if( !initialized ){
initialized = 1;
header.push_back( "Average" );
header.push_back( "StdDev" );
header.push_back( "|Average|" );
header.push_back( "RawSum" );
header.push_back( "Min" );
header.push_back( "MinIndex" );
header.push_back( "Max" );
header.push_back( "MaxIndex" );
header.push_back( "Count" );
}
#ifdef _MSC_VER
#define LOCAL_SPRINTF(a,b,c) sprintf_s( (a), MAX_LINE_CHARS, (b), (c) );
#else
#define LOCAL_SPRINTF(a,b,c) sprintf( (a), (b), (c) );
#endif
std::stringstream message;
// loop over rows (Average, StdDev, ... )
// building message string: tag + header + tab + values
for( unsigned int ii = 0; ii < statistics.size(); ii++ ){
std::vector<double> row = statistics[ii];
std::stringstream head;
std::stringstream valueString;
head << tag << " ";
if( ii < header.size() ){
head << header[ii];
}
head << " ";
valueString << "[ ";
for( unsigned int jj = 0; jj < row.size(); jj++ ){
(void) LOCAL_SPRINTF( value, "%16.7e ", row[jj] );
valueString << value;
}
valueString << "]";
message << _getLine( tab, head.str(), valueString.str() );
}
return message.str();
}
/*
* Print streams to file
*
* @param fileName file name
* @param streams streams to print
*
* @return DefaultReturnValue
*
**/
int BrookStreamInternal::printStreamsToFile( std::string fileName, std::vector<BrookStreamInternal*>& streams ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookStreamInternal::printStreamsToFile";
// ---------------------------------------------------------------------------------------
FILE* filePtr;
#ifdef _MSC_VER
fopen_s( &filePtr, fileName.c_str(), "w" );
#else
filePtr = fopen( fileName.c_str(), "w" );
#endif
if( !filePtr ){
(void) fprintf( stderr, "%s could not open file=<%s>\n", methodName.c_str(), fileName.c_str() );
(void) fflush( stderr );
return ErrorReturnValue;
}
// gather arrays, widths for eah stream, and set index for each stream
// also set minimum of stream sizes
int minIndex = 10000000;
float** arrays = new float*[streams.size()];
float** sums = new float*[streams.size()];
int* widths = new int[streams.size()];
int* indices = new int[streams.size()];
for( unsigned int ii = 0; ii < streams.size(); ii++ ){
BrookStreamInternal* stream = streams[ii];
void* dataArrayV = stream->getData( 1 );
arrays[ii] = (float*) dataArrayV;
widths[ii] = stream->getWidth();
indices[ii] = 0;
sums[ii] = new float[4];
sums[ii][0] = sums[ii][1] = sums[ii][2] = sums[ii][3] = 0.0f;
if( minIndex > stream->getSize() ){
minIndex = stream->getSize();
}
}
// sum columns
for( int ii = 0; ii < minIndex; ii++ ){
for( unsigned int kk = 0; kk < streams.size(); kk++ ){
for( int jj = 0; jj < widths[kk]; jj++ ){
sums[kk][jj] += arrays[kk][indices[kk]++];
}
}
}
// reinitialize indices
for( unsigned int kk = 0; kk < streams.size(); kk++ ){
indices[kk] = 0;
}
// show column sums
for( unsigned int kk = 0; kk < streams.size(); kk++ ){
(void) fprintf( filePtr, "Sms " );
for( int jj = 0; jj < widths[kk]; jj++ ){
(void) fprintf( filePtr, "%15.5e ", sums[kk][jj] );
}
}
(void) fprintf( filePtr, "\n" );
for( int ii = 0; ii < minIndex; ii++ ){
(void) fprintf( filePtr, "%6d ", ii );
// streams
for( unsigned int kk = 0; kk < streams.size(); kk++ ){
// (void) fprintf( filePtr, "[ " );
// ii elements of stream kk
for( int jj = 0; jj < widths[kk]; jj++ ){
(void) fprintf( filePtr, "%15.5e ", arrays[kk][indices[kk]++] );
}
// (void) fprintf( filePtr, " ]", ii );
}
(void) fprintf( filePtr, "\n", ii );
}
// cleanup
(void) fclose( filePtr );
delete[] arrays;
delete[] widths;
delete[] indices;
for( unsigned int ii = 0; ii < streams.size(); ii++ ){
delete[] sums[ii];
}
delete[] sums;
return DefaultReturnValue;
}
/*
* Load data into stream from file
*
* @param fileName file name
*
* @return DefaultReturnValue
*
**/
typedef struct {
unsigned int type;
unsigned int dimensions;
unsigned int dims[4];
} STREAM_HEADER;
#include <winsock.h>
#include <stdarg.h>
#include <limits>
#include <set>
int BrookStreamInternal::loadStreamGivenFileName( std::string& fileName ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookStreamInternal::loadStreamGivenFileName";
// ---------------------------------------------------------------------------------------
FILE* log = stderr;
/* open file, read header */
FILE* filePtr;
#ifdef _MSC_VER
fopen_s( &filePtr, fileName.c_str(), "rb" );
#else
filePtr = fopen( fileName.c_str(), "rb" );
#endif
if( filePtr == NULL ){
(void) fprintf( log, "%s Unable to open/read %s for stream creation\n", methodName.c_str(), fileName.c_str() );
return ErrorReturnValue;
}
STREAM_HEADER header;
if( 1 != fread( &header, sizeof( header ), 1, filePtr ) ){
(void) fprintf( log, "%s Unable to read %s header for stream %s\n", methodName.c_str(), fileName.c_str() );
(void) fclose( filePtr );
return ErrorReturnValue;
}
/* fix endian */
// header.type = ntohl( header.type );
// header.dimensions = ntohl( header.dimensions );
/*
for( int ii = 0; ii < 4; ii++ ){
// header.dims[ii] = ntohl( header.dims[ii] );
(void) fprintf( log, "%s header %d %d for stream %s from %s\n", methodName.c_str(), ii, header.dims[ii], getName().c_str(), filename.c_str() );
}
(void) fflush( log );
*/
/*
if( header.dimensions[0]
(unsigned int) header.dimensions, (const ::brook::StreamType *) &type,
(bool) false );
*/
/* ok, load in the data */
/*
if( getStreamSize()*getWidth() != header.dims[0]*header.dims[1] ){
(void) fprintf( log, "%s dimension inconsistency for stream %s from %s dim:[%d %d %d %d] sz=%d != sz=%d containerW=%d\n",
methodName.c_str(), getName().c_str(), filename.c_str(),
header.dims[0], header.dims[1], header.dims[2], header.dims[3], header.dims[0]*header.dims[1],
getStreamSize(), getWidth() );
(void) fclose( filePtr );
return ErrorReturnValue;
}
*/
// always float
int bytesToRead = getStreamSize()*getWidth()*sizeof( float );
void* dataBuffer = (void*) malloc( bytesToRead );
if( dataBuffer == NULL ){
(void) fprintf( log, "%s Memory Error for file=%s\n", methodName.c_str(), fileName.c_str() );
(void) fclose( filePtr );
return ErrorReturnValue;
}
size_t bytesRead = fread( dataBuffer, bytesToRead, 1, filePtr );
if( bytesRead != 1 ){
(void) fprintf( log, "%s Unable to read %d bytes=%d stream from %s\n", methodName.c_str(), bytesRead, bytesToRead, fileName.c_str() );
free( dataBuffer );
(void) fclose( filePtr );
return ErrorReturnValue;
}
// float/integer case -- nothing more to do but load; if double, then convert float to double
if( getBaseDataType() == Float || getBaseDataType() == Integer ){
loadFromArray( dataBuffer );
} else {
double* loadBuffer = (double*) malloc( bytesToRead*2 );
float* readBuffer = (float*) dataBuffer;
for( int ii = 0; ii < getStreamSize()*getWidth(); ii++ ){
loadBuffer[ii] = (double) readBuffer[ii];
}
loadFromArray( loadBuffer );
free( loadBuffer );
}
(void) fclose( filePtr );
free( dataBuffer );
(void) fprintf( log, "%s read %d bytes for stream %s from %s dim:[%d %d %d %d] container=%d %d\n", methodName.c_str(), bytesToRead, getName().c_str(), fileName.c_str(),
header.dims[0], header.dims[0], header.dims[0], header.dims[0], getStreamSize(), getWidth() );
(void) fflush( log );
return DefaultReturnValue;
}
/*
* Check for NANs
*
* @return number of Nans found
*
**/
int BrookStreamInternal::checkForNans( void ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookStreamInternal::checkForNans";
// ---------------------------------------------------------------------------------------
int numberOfNans = 0;
void* dataArrayV = getData( 1 );
float* array = static_cast<float*>( dataArrayV );
int width = getWidth();
int streamSize = getSize();
for( int ii = 0; ii < width*streamSize; ii++ ){
if( isnan( array[ii] ) || isinf( array[ii] ) ){
numberOfNans++;
}
}
return numberOfNans;
}
/*
* Sum columns
*
* @param sums output vector of column sums
*
* @return DefaultReturnValue
*
**/
int BrookStreamInternal::sumColumns( std::vector<float>& sums ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookStreamInternal::sumColumns";
// ---------------------------------------------------------------------------------------
void* dataArrayV = getData( 1 );
float* array = static_cast<float*>( dataArrayV );
int width = getWidth();
sums.resize( width );
for( int ii = 0; ii < width; ii++ ){
sums[ii] = 0.0f;
}
int streamSize = getSize();
int index = 0;
for( int ii = 0; ii < streamSize; ii++ ){
for( int jj = 0; jj < width; jj++ ){
sums[jj] += array[index++];
}
}
return DefaultReturnValue;
}
#ifndef OPENMM_BROOK_STREAM_INTERNAL_H_
#define OPENMM_BROOK_STREAM_INTERNAL_H_
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include <brook/brook.hpp>
namespace OpenMM {
/**
* This is the implementation of Float and Double streams in the Brook Platform.
*/
class BrookStreamInternal {
public:
/**
* This is an enumeration of the allowed data types for a Stream.
*/
enum DataType { Float, Float2, Float3, Float4, Double, Double2, Double3, Double4, Integer, Integer2, Integer3, Integer4, Unknown };
// return values
static const int DefaultReturnValue = 0;
static const int ErrorReturnValue = -1;
// ---------------------------------------------------------------------------------------
/**
* BrookStreamInternal constructor
*
* @param name name of the stream to create
* @param size number of elements in the stream
* @param streamWidth stream width
* @param type data type of each element in the stream
*
*/
BrookStreamInternal( const std::string& name, int size, int streamWidth, BrookStreamInternal::DataType type );
/**
* BrookStreamInternal destructor
*
*/
~BrookStreamInternal( );
/**
* Get the name of this stream.
*/
const std::string& getName( void ) const;
/**
* Get the number of elements in this stream.
*/
int getSize( void ) const;
/**
* Get the data type of each element in the stream.
*/
BrookStreamInternal::DataType getDataType( void ) const;
/**
* Get base data type of each element in the stream ( float, double, int )
*/
BrookStreamInternal::DataType getBaseDataType( void ) const;
/**
* Copy the contents of an array into this stream.
*
* @param array a pointer to the start of the array. The array is assumed to have the same length as this stream,
* and to contain elements of the correct data type for this stream. If the stream has a compound data type, all
* the values should be packed into a single array: all the values for the first element, followed by all the values
* for the next element, etc.
*/
virtual void loadFromArray( const void* array ) = 0;
/**
* Copy the contents of an array into this stream.
*
* @param array a pointer to the start of the array. The array is assumed to have the same length as this stream,
* and to contain elements of the correct data type for this stream. If the stream has a compound data type, all
* the values should be packed into a single array: all the values for the first element, followed by all the values
* for the next element, etc.
*/
virtual void loadFromArray( const void* array, BrookStreamInternal::DataType baseType ) = 0;
/**
* Copy the contents of this stream into an array.
*
* @param array a pointer to the start of the array. The array is assumed to have the same length as this stream,
* and to contain elements of the correct data type for this stream. If the stream has a compound data type, all
* the values should be packed into a single array: all the values for the first element, followed by all the values
* for the next element, etc.
*/
virtual void saveToArray( void* array ) = 0;
/**
* Set every element of this stream to the same value.
*
* @param a pointer to the value. It is assumed to be of the correct data type for this stream.
*/
virtual void fillWithValue( void* value ) = 0;
/**
* Get data
*
* @return data array
*/
virtual void* getData( void ) = 0;
/**
* Get data
*
* @param readFromBoard read data from board
*
* @return data array
*/
virtual void* getData( int readFromBoard ) = 0;
/**
* Get array of appropritate size for loading data
*
* @return data array -- user's responsibility to free
*/
virtual void* getDataArray( void ) = 0;
/**
* Get type string
*
* @param type BrookStreamInternal data type (float, float2, ...)
*
* @return string matching type or "Unknown"
*
*/
std::string getTypeString( BrookStreamInternal::DataType type ) const;
/**
* Get Brook stream reference
*
* @return Brook stream reference
*/
brook::stream& getBrookStream( void );
/**
* Get width
*
* @return width
*/
int getWidth( void ) const;
/**
* Get stream width
*
* @return stream width
*/
int getStreamWidth( void ) const;
/**
* Get stream height
*
* @return stream height
*/
int getStreamHeight( void ) const;
/**
* Get stream size
*
* @return stream size
*/
int getStreamSize( void ) const;
/*
* Get contents of object
*
*
* @param level level of dump
*
* @return string containing contents
*
* */
const std::string getContentsString( int level = 0 ) const;
/*
* Print to file
*
* @param log log file
* @param maxPrint max values to print; if < 0, then all values printed; default value is -1
*
* @return DefaultReturnValue
*
* */
int printToFile( FILE* log, int maxPrint = -1 );
/**
* Sum over stream dimensions
*
* @param stopIndex index to stop sum
* @param sum array of size=getWidth()
*
* @return DefaultReturnValue
*
* @throw exception if stopIndex is too large
*/
int sumByDimension( int stopIndex, double* sum );
/*
* Get stats
*
* @param statistics output vector of stats
* @param maxScan number of points to use in computing stats
*
* @return statistics vector
*
* */
virtual int getStatistics( std::vector<std::vector<double>>& statVector, int maxScan );
/*
* Get stat string
*
* @param tag id tag
* @param statistics stat vector
*
* @return stat string
*
**/
std::string printStatistics( std::string tag, std::vector<std::vector<double> >& statistics ) const;
/*
* Read stream from file
*
* @param fileName file name
*
* @return DefaultReturnValue or ErrorReturnValue if problems
*
**/
int loadStreamGivenFileName( std::string& filename );
/*
* Print streams to file
*
* @param fileName file name
* @param streams streams to print
*
* @return DefaultReturnValue
*
**/
static int printStreamsToFile( std::string fileName, std::vector<BrookStreamInternal*>& streams );
/*
* Check for NANs
*
* @return number of Nans found
*
**/
int checkForNans( void );
/*
* Sum columns
*
* @param sums output vector of column sums
*
* @return DefaultReturnValue
*
**/
int sumColumns( std::vector<float>& sums );
protected:
std::string _name;
BrookStreamInternal::DataType _type;
BrookStreamInternal::DataType _baseType;
int _size;
int _width;
int _streamWidth;
int _streamHeight;
int _streamSize;
brook::stream _aStream;
/*
* Get contents of object
*
* @param tab tab
* @param description description
* @param value value
*
* @return string containing contents
*
* */
std::string _getLine( const std::string& tab, const std::string& description,
const std::string& value ) const;
/*
* Print array to file
*
* @param log log file
*
* @return DefaultReturnValue
*
* */
virtual int _bodyPrintToFile( FILE* log, int maxPrint ) = 0;
};
} // namespace OpenMM
#endif /* OPENMM_BROOK_STREAM_INTERNAL_H_ */
/* -------------------------------------------------------------------------- *
* 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, Peter Eastman *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "openmm/OpenMMException.h"
#include "BrookUpdateTimeKernel.h"
#include <sstream>
using namespace OpenMM;
using namespace std;
/**
* BrookUpdateTimeKernel constructor
*
* @param name kernel name
* @param platform platform
* @param openMMBrookInterface OpenMMBrookInterface reference
*
*/
BrookUpdateTimeKernel::BrookUpdateTimeKernel( std::string name, const Platform& platform, OpenMMBrookInterface& openMMBrookInterface ) :
UpdateStateDataKernel( name, platform ), _openMMBrookInterface(openMMBrookInterface){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookUpdateTimeKernel::BrookUpdateTimeKernel";
// ---------------------------------------------------------------------------------------
_log = NULL;
const BrookPlatform& brookPlatform = dynamic_cast<const BrookPlatform&> (platform);
if( brookPlatform.getLog() != NULL ){
setLog( brookPlatform.getLog() );
}
}
/**
* BrookInitializeForcesKernel destructor
*
*/
BrookUpdateTimeKernel::~BrookUpdateTimeKernel( ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "BrookUpdateTimeKernel::~BrookUpdateTimeKernel";
// ---------------------------------------------------------------------------------------
}
/**
* Get log file reference
*
* @return log file reference
*
*/
FILE* BrookUpdateTimeKernel::getLog( void ) const {
return _log;
}
/**
* Set log file reference
*
* @param log file reference
*
* @return DefaultReturnValue
*
*/
int BrookUpdateTimeKernel::setLog( FILE* log ){
_log = log;
return BrookCommon::DefaultReturnValue;
}
/**
* Initialize
*
* @param system System reference
*
* @return DefaultReturnValue
*
*/
void BrookUpdateTimeKernel::initialize( const System& system ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookUpdateTimeKernel::initialize";
// ---------------------------------------------------------------------------------------
//FILE* log = getLog();
}
/**
* Get the current time (in picoseconds).
*
* @param context the context in which to execute this kernel
*/
double BrookUpdateTimeKernel::getTime(const ContextImpl& context) const {
return _openMMBrookInterface.getTime();
}
/**
* Set the current time (in picoseconds).
*
* @param context the context in which to execute this kernel
* @param time the time
*/
void BrookUpdateTimeKernel::setTime(ContextImpl& context, double time) {
_openMMBrookInterface.setTime(time);
}
#ifndef OPENMM_BROOK_UPDATE_TIME_KERNEL_H_
#define OPENMM_BROOK_UPDATE_TIME_KERNEL_H_
/* -------------------------------------------------------------------------- *
* 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, Peter Eastman *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "openmm/kernels.h"
#include "OpenMMBrookInterface.h"
namespace OpenMM {
/**
* This kernel initializes the forces
*/
class BrookUpdateTimeKernel : public UpdateStateDataKernel {
public:
BrookUpdateTimeKernel( std::string name, const Platform& platform, OpenMMBrookInterface& openMMBrookInterface );
~BrookUpdateTimeKernel();
/**
* Initialize the kernel
*
* @param system the System this kernel will be applied to
*/
void initialize( const System& system );
/**
* Get the current time (in picoseconds).
*
* @param context the context in which to execute this kernel
*/
double getTime(const ContextImpl& context) const;
/**
* Set the current time (in picoseconds).
*
* @param context the context in which to execute this kernel
* @param time the time
*/
void setTime(ContextImpl& context, double time);
/**
* Set log file reference
*
* @param log file reference
*
* @return DefaultReturnValue
*
*/
int setLog( FILE* log );
/*
* Get contents of object
*
* @param level of dump
*
* @return string containing contents
*
* */
std::string getContents( int level ) const;
/**
* Get log file reference
*
* @return log file reference
*
*/
FILE* getLog( void ) const;
private:
// log file reference
FILE* _log;
// interface
OpenMMBrookInterface& _openMMBrookInterface;
};
} // namespace OpenMM
#endif /* OPENMM_BROOK_UPDATE_TIME_KERNEL_H_ */
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "BrookVelocityCenterOfMassRemoval.h"
#include "BrookPlatform.h"
#include "openmm/OpenMMException.h"
#include "BrookStreamImpl.h"
#include "kernels/kcom.h"
#include <sstream>
using namespace OpenMM;
using namespace std;
/**
*
* Constructor
*
*/
BrookVelocityCenterOfMassRemoval::BrookVelocityCenterOfMassRemoval( ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookVelocityCenterOfMassRemoval::BrookVelocityCenterOfMassRemoval";
BrookOpenMMFloat zero = static_cast<BrookOpenMMFloat>( 0.0 );
// ---------------------------------------------------------------------------------------
_numberOfParticles = -1;
// mark stream dimension variables as unset
_particleStreamWidth = -1;
_particleStreamHeight = -1;
_particleStreamSize = -1;
_totalInverseMass = zero;
for( int ii = 0; ii < LastStreamIndex; ii++ ){
_streams[ii] = NULL;
}
}
/**
* Destructor
*
*/
BrookVelocityCenterOfMassRemoval::~BrookVelocityCenterOfMassRemoval( ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookVelocityCenterOfMassRemoval::~BrookVelocityCenterOfMassRemoval";
// ---------------------------------------------------------------------------------------
for( int ii = 0; ii < LastStreamIndex; ii++ ){
delete _streams[ii];
}
}
/**
* Get inverse of total mass
*
* @return inverse of total mass
*
*/
BrookOpenMMFloat BrookVelocityCenterOfMassRemoval::getTotalInverseMass( void ) const {
return _totalInverseMass;
}
/**
* Get inverse mass stream
*
* @return inverse mass stream
*
*/
BrookFloatStreamInternal* BrookVelocityCenterOfMassRemoval::getMassStream( void ) const {
return _streams[MassStream];
}
/**
* Get work stream
*
* @return work stream
*
*/
BrookFloatStreamInternal* BrookVelocityCenterOfMassRemoval::getWorkStream( void ) const {
return _streams[WorkStream];
}
/**
* Get linear momentum stream
*
* @return linear momentum stream
*
*/
BrookFloatStreamInternal* BrookVelocityCenterOfMassRemoval::getLinearMomentumStream( void ) const {
return _streams[LinearMomentumStream];
}
/**
* Get velocity-COM
*
* @param velocities velocities
* @param velocityCom output velocity com
*
* @return DefaultReturnValue
*
*/
int BrookVelocityCenterOfMassRemoval::getVelocityCenterOfMass( BrookStreamImpl& vStream, BrookOpenMMFloat velocityCom[3], BrookOpenMMFloat* ke ){
// ---------------------------------------------------------------------------------------
// static const std::string methodName = "\nBrookVelocityCenterOfMassRemoval::getVelocityCenterOfMass";
BrookOpenMMFloat zero = static_cast<BrookOpenMMFloat>( 0.0 );
// ---------------------------------------------------------------------------------------
// calculate linear momentum via reduction
// subtract it (/totalMass) from velocities
BrookStreamInternal* velocityStream = dynamic_cast<BrookStreamInternal*> (vStream.getBrookStreamInternal());
*ke = zero;
void* velV = velocityStream->getData( 1 );
const float* vArray = static_cast<float*>( velV );
void* massV = getMassStream()->getData( 1 );
const float* mArray = static_cast<float*>( massV );
int numberOfParticles = getNumberOfParticles();
int index = 0;
velocityCom[0] = velocityCom[1] = velocityCom[2] = zero;
for( int ii = 0; ii < numberOfParticles; ii++, index += 3 ){
velocityCom[0] += mArray[ii]*vArray[index];
velocityCom[1] += mArray[ii]*vArray[index+1];
velocityCom[2] += mArray[ii]*vArray[index+2];
*ke += mArray[ii]*( vArray[index]*vArray[index] + vArray[index+1]*vArray[index+1] + vArray[index+2]*vArray[index+2] );
if( 0 && ii < 3 ){
fprintf( stderr, "getVelocityCenterOfMass %5d %5d m=%15.6e v[%15.6e %15.6e %15.6e ] %d\n", ii, index, mArray[ii], vArray[index], vArray[index+1], vArray[index+2], numberOfParticles );
}
}
return DefaultReturnValue;
}
/**
* Get Particle stream size
*
* @return Particle stream size
*
*/
int BrookVelocityCenterOfMassRemoval::getComParticleStreamSize( void ) const {
return _particleStreamSize;
}
/**
* Get particle stream width
*
* @return particle stream width
*
*/
int BrookVelocityCenterOfMassRemoval::getComParticleStreamWidth( void ) const {
return _particleStreamWidth;
}
/**
* Get particle stream height
*
* @return particle stream height
*/
int BrookVelocityCenterOfMassRemoval::getComParticleStreamHeight( void ) const {
return _particleStreamHeight;
}
/**
* Initialize stream dimensions
*
* @param numberOfParticles number of particles
* @param platform platform
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int BrookVelocityCenterOfMassRemoval::_initializeStreamSizes( int numberOfParticles, const Platform& platform ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookVelocityCenterOfMassRemoval::_initializeStreamSizes";
// ---------------------------------------------------------------------------------------
_particleStreamSize = getParticleStreamSize( platform );
_particleStreamWidth = getParticleStreamWidth( platform );
_particleStreamHeight = getParticleStreamHeight( platform );
return DefaultReturnValue;
}
/**
* Initialize streams
*
* @param platform platform
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int BrookVelocityCenterOfMassRemoval::_initializeStreams( const Platform& platform ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookVelocityCenterOfMassRemoval::_initializeStreams";
BrookOpenMMFloat dangleValue = static_cast<BrookOpenMMFloat>( 0.0 );
// ---------------------------------------------------------------------------------------
int particleStreamSize = getComParticleStreamSize();
int particleStreamWidth = getComParticleStreamWidth();
_streams[WorkStream] = new BrookFloatStreamInternal( BrookCommon::BrookVelocityCenterOfMassRemovalWorkStream,
particleStreamSize, particleStreamWidth,
BrookStreamInternal::Float3, dangleValue );
_streams[MassStream] = new BrookFloatStreamInternal( BrookCommon::BrookVelocityCenterOfMassRemovalMassStream,
particleStreamSize, particleStreamWidth,
BrookStreamInternal::Float, dangleValue );
_streams[LinearMomentumStream] = new BrookFloatStreamInternal( "LinearMomentumStream",
1, 1, BrookStreamInternal::Float3, dangleValue );
return DefaultReturnValue;
}
/**
* Set masses & _totalInverseMass
*
* @param masses particle masses
*
*/
int BrookVelocityCenterOfMassRemoval::_setMasses( const std::vector<double>& masses ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookVelocityCenterOfMassRemoval::_setMasses";
BrookOpenMMFloat zero = static_cast<BrookOpenMMFloat>( 0.0 );
BrookOpenMMFloat one = static_cast<BrookOpenMMFloat>( 1.0 );
// ---------------------------------------------------------------------------------------
// check that masses vector is not larger than expected
if( (int) masses.size() > getComParticleStreamSize() ){
std::stringstream message;
message << methodName << " mass array size=" << masses.size() << " is larger than stream size=" << getComParticleStreamSize();
throw OpenMMException( message.str() );
}
// setup masses
BrookOpenMMFloat* localMasses = new BrookOpenMMFloat[getComParticleStreamSize()];
memset( localMasses, 0, sizeof( BrookOpenMMFloat )*getComParticleStreamSize() );
int index = 0;
_totalInverseMass = zero;
for( std::vector<double>::const_iterator ii = masses.begin(); ii != masses.end(); ii++, index++ ){
if( *ii != 0.0 ){
BrookOpenMMFloat value = static_cast<BrookOpenMMFloat>(*ii);
localMasses[index] = value;
_totalInverseMass += value;
}
}
// 1/Sum[masses]
if( _totalInverseMass > zero ){
_totalInverseMass = one/_totalInverseMass;
}
// write masses to board
_streams[MassStream]->loadFromArray( localMasses );
delete[] localMasses;
return DefaultReturnValue;
}
/*
* Setup of StochasticDynamics parameters
*
* @param masses masses
* @param platform Brook platform
*
* @return nonzero value if error
*
* */
int BrookVelocityCenterOfMassRemoval::setup( const std::vector<double>& masses, const Platform& platform ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookVelocityCenterOfMassRemoval::setup";
// ---------------------------------------------------------------------------------------
const BrookPlatform& brookPlatform = dynamic_cast<const BrookPlatform&> (platform);
setLog( brookPlatform.getLog() );
int numberOfParticles = (int) masses.size();
setNumberOfParticles( numberOfParticles );
// set stream sizes and then create streams
_initializeStreamSizes( numberOfParticles, platform );
_initializeStreams( platform );
_setMasses( masses );
if( 1 && getLog() ){
FILE* log = getLog();
std::string contents = getContentsString( 0 );
(void) fprintf( log, "%s contents:\n%s\n", methodName.c_str(), contents.c_str() );
(void) fflush( log );
}
return DefaultReturnValue;
}
/*
* Get contents of object
*
* @param level level of dump
*
* @return string containing contents
*
* */
std::string BrookVelocityCenterOfMassRemoval::getContentsString( int level ) const {
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookVelocityCenterOfMassRemoval::getContentsString";
static const unsigned int MAX_LINE_CHARS = 256;
char value[MAX_LINE_CHARS];
static const char* Set = "Set";
static const char* NotSet = "Not set";
// ---------------------------------------------------------------------------------------
std::stringstream message;
std::string tab = " ";
#ifdef _MSC_VER
#define LOCAL_SPRINTF(a,b,c) sprintf_s( (a), MAX_LINE_CHARS, (b), (c) );
#else
#define LOCAL_SPRINTF(a,b,c) sprintf( (a), (b), (c) );
#endif
(void) LOCAL_SPRINTF( value, "%d", getNumberOfParticles() );
message << _getLine( tab, "Number of particles:", value );
(void) LOCAL_SPRINTF( value, "%d", getComParticleStreamWidth() );
message << _getLine( tab, "Particle stream width:", value );
(void) LOCAL_SPRINTF( value, "%d", getComParticleStreamHeight() );
message << _getLine( tab, "Particle stream height:", value );
(void) LOCAL_SPRINTF( value, "%d", getComParticleStreamSize() );
message << _getLine( tab, "Particle stream size:", value );
(void) LOCAL_SPRINTF( value, "%.5e", getTotalInverseMass() );
message << _getLine( tab, "TotalInverseMass:", value );
message << _getLine( tab, "Log:", (getLog() ? Set : NotSet) );
message << _getLine( tab, "Mass:", (getMassStream() ? Set : NotSet) );
message << _getLine( tab, "Work:", (getWorkStream() ? Set : NotSet) );
message << _getLine( tab, "LinearMomentum:", (getLinearMomentumStream() ? Set : NotSet) );
for( int ii = 0; ii < LastStreamIndex; ii++ ){
message << std::endl;
if( _streams[ii] ){
message << _streams[ii]->getContentsString( );
}
}
#undef LOCAL_SPRINTF
return message.str();
}
/**
* Remove velocity-COM
*
* @param velocities velocities
*
* @return DefaultReturnValue
*
*/
int BrookVelocityCenterOfMassRemoval::removeVelocityCenterOfMass( BrookStreamImpl& velocityStream ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookVelocityCenterOfMassRemoval::removeVelocityCenterOfMass";
static int printOn = 0;
static const double boltz = 8.3145112119486e-03;
FILE* log;
BrookOpenMMFloat ke;
// ---------------------------------------------------------------------------------------
//setLog( stderr );
if( printOn && getLog() ){
log = getLog();
} else {
printOn = 0;
}
// diagnostics
if( printOn ){
BrookOpenMMFloat com[3];
getVelocityCenterOfMass( velocityStream, com, &ke );
BrookOpenMMFloat denomiator = static_cast<float>( 3*getNumberOfParticles())*static_cast<float>( boltz );
(void) fprintf( log, "%s Pre removal com: [%12.5e %12.5e %12.5e] ke=%.3f ~T=%.3f\n",
methodName.c_str(), com[0], com[1], com[2], ke, ke/denomiator );
BrookStreamInternal* outputVelocityStream = dynamic_cast<BrookStreamInternal*> (velocityStream.getBrookStreamInternal());
void* velV = outputVelocityStream->getData( 1 );
const float* vArray = static_cast<float*>( velV );
int index = 0;
if( printOn > 1 ){
for( int ii = 0; ii < getNumberOfParticles(); ii++, index += 3 ){
(void) fprintf( log, "V %d [%12.5e %12.5e %12.5e]\n", ii, vArray[index], vArray[index+1], vArray[index+2] );
}
}
(void) fflush( log );
}
// calculate linear momentum via reduction
// subtract it (/totalMass) from velocities
kCalculateLinearMomentum( getMassStream()->getBrookStream(), velocityStream.getBrookStream(), getWorkStream()->getBrookStream() );
kSumLinearMomentum( (float) getComParticleStreamWidth(), (float) getNumberOfParticles(), (float) getTotalInverseMass(),
getWorkStream()->getBrookStream(), getLinearMomentumStream()->getBrookStream() );
kRemoveLinearMomentum( getLinearMomentumStream()->getBrookStream(), velocityStream.getBrookStream(), velocityStream.getBrookStream() );
// diagnostics
if( printOn ){
BrookOpenMMFloat com[3];
getVelocityCenterOfMass( velocityStream, com, &ke );
BrookOpenMMFloat denomiator = static_cast<float>( 3*getNumberOfParticles() )*static_cast<float>( boltz );
(void) fprintf( log, "%s strW=%d iatm=%d invMass=%.4e\n Post removal com: [%12.5e %12.5e %12.5e] ke=%.3f ~T=%.3f\n",
methodName.c_str(),
getComParticleStreamWidth(), getNumberOfParticles(), getTotalInverseMass(), com[0], com[1], com[2],
ke, ke/denomiator );
void* linMoV = getLinearMomentumStream()->getData( 1 );
float* linMo = static_cast<float*>( linMoV );
(void) fprintf( log, " LM [%12.5e %12.5e %12.5e]\n", linMo[0], linMo[1], linMo[2] );
BrookStreamInternal* outputVelocityStream = dynamic_cast<BrookStreamInternal*> (velocityStream.getBrookStreamInternal());
void* velV = outputVelocityStream->getData( 1 );
const float* vArray = static_cast<float*>( velV );
void* w1 = getWorkStream()->getData( 1 );
const float* w2 = static_cast<float*>( w1 );
if( printOn > 1 ){
int index = 0;
for( int ii = 0; ii < getNumberOfParticles(); ii++, index += 3 ){
(void) fprintf( log, "V %d [%12.5e %12.5e %12.5e] [%12.5e %12.5e %12.5e]\n", ii,
vArray[index], vArray[index+1], vArray[index+2], w2[index], w2[index+1], w2[index+2] );
}
}
(void) fflush( log );
//exit(0);
}
return DefaultReturnValue;
}
#ifndef OPENMM_BROOK_VELOCITY_CENTER_OF_MASS_REMOVAL_H_
#define OPENMM_BROOK_VELOCITY_CENTER_OF_MASS_REMOVAL_H_
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include <vector>
#include <set>
#include "BrookStreamImpl.h"
//#include "BrookFloatStreamInternal.h"
#include "BrookPlatform.h"
#include "BrookCommon.h"
namespace OpenMM {
/**
*
* Encapsulates removal of center of mass
*
*/
class BrookVelocityCenterOfMassRemoval : public BrookCommon {
public:
/**
* Constructor
*
*/
BrookVelocityCenterOfMassRemoval( );
/**
* Destructor
*
*/
~BrookVelocityCenterOfMassRemoval( );
/**
* Get particle stream width
*
* @return particle stream width
*/
int getComParticleStreamWidth( void ) const;
/**
* Get particle stream height
*
* @return particle stream height
*/
int getComParticleStreamHeight( void ) const;
/**
* Get particle stream size
*
* @return particle stream size
*/
int getComParticleStreamSize( void ) const;
/**
* Remove velocity center-of-mass
*
* @param velocities particle velocities
*
* @return DefaultReturnValue
*
*/
int removeVelocityCenterOfMass( BrookStreamImpl& velocityStream );
/**
* Get velocity center-of-mass and kinetic energy (used for diagnostics)
*
* @param velocities particle velocities
* @param velocityCom output velocity com
* @param ke output kinetic energy
*
* @return DefaultReturnValue
*
*/
int getVelocityCenterOfMass( BrookStreamImpl& vStream, BrookOpenMMFloat velocityCom[3], BrookOpenMMFloat* ke );
/*
* Setup of parameters
*
* @param masses particle masses
* @param platform Brook platform
*
* @return ErrorReturnValue value if error, else DefaultReturnValue
*
* */
int setup( const std::vector<double>& masses, const Platform& platform );
/*
* Get contents of object
*
* @param level of dump
*
* @return string containing contents
*
* */
std::string getContentsString( int level = 0 ) const;
/**
* Get inverse of total mass
*
* @return inverse of total mass
*
*/
BrookOpenMMFloat getTotalInverseMass( void ) const;
/**
* Get inverse mass stream
*
* @return inverse mass stream
*
*/
BrookFloatStreamInternal* getMassStream( void ) const;
/**
* Get work stream
*
* @return work stream
*
*/
BrookFloatStreamInternal* getWorkStream( void ) const;
/**
* Get linear momentum stream
*
* @return linear momentum stream
*
*/
BrookFloatStreamInternal* getLinearMomentumStream( void ) const;
private:
// streams indices
enum BrookVelocityCenterOfMassRemovalStreams {
MassStream,
WorkStream,
LinearMomentumStream,
LastStreamIndex
};
BrookOpenMMFloat _totalInverseMass;
// Particle stream dimensions
int _particleStreamWidth;
int _particleStreamHeight;
int _particleStreamSize;
// internal streams
BrookFloatStreamInternal* _streams[LastStreamIndex];
/*
* Setup of stream dimensions
*
* @param particleStreamSize particle stream size
* @param particleStreamWidth particle stream width
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
* */
int _initializeStreamSizes( int particleStreamSize, int particleStreamWidth );
/**
* Initialize stream dimensions
*
* @param numberOfParticles number of particles
* @param platform platform
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int _initializeStreamSizes( int numberOfParticles, const Platform& platform );
/**
* Initialize stream dimensions and streams
*
* @param platform platform
*
* @return nonzero value if error
*
*/
int _initializeStreams( const Platform& platform );
/**
* Set inverse masses
*
* @param masses particle masses
*
*/
int _setMasses( const std::vector<double>& masses );
};
} // namespace OpenMM
#endif /* OPENMM_BROOK_VELOCITY_CENTER_OF_MASS_REMOVAL_H_ */
/* -------------------------------------------------------------------------- *
* 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 <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "BrookVerletDynamics.h"
#include "BrookPlatform.h"
#include "openmm/OpenMMException.h"
#include "BrookStreamImpl.h"
#include "kernels/kshakeh.h"
#include "kernels/kupdatemd.h"
#include "kernels/kcommon.h"
#include <sstream>
using namespace OpenMM;
using namespace std;
/**
*
* Constructor
*
*/
BrookVerletDynamics::BrookVerletDynamics( ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookVerletDynamics::BrookVerletDynamics";
BrookOpenMMFloat zero = static_cast<BrookOpenMMFloat>( 0.0 );
BrookOpenMMFloat one = static_cast<BrookOpenMMFloat>( 1.0 );
BrookOpenMMFloat oneMinus = static_cast<BrookOpenMMFloat>( -1.0 );
// ---------------------------------------------------------------------------------------
_numberOfParticles = -1;
_internalStepCount = 0;
// mark stream dimension variables as unset
_verletParticleStreamWidth = -1;
_verletParticleStreamHeight = -1;
_verletParticleStreamSize = -1;
for( int ii = 0; ii < LastStreamIndex; ii++ ){
_verletStreams[ii] = NULL;
}
_stepSize = oneMinus;
// setup inverse sqrt masses
_inverseMasses = NULL;
}
/**
* Destructor
*
*/
BrookVerletDynamics::~BrookVerletDynamics( ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookVerletDynamics::~BrookVerletDynamics";
// ---------------------------------------------------------------------------------------
for( int ii = 0; ii < LastStreamIndex; ii++ ){
delete _verletStreams[ii];
}
delete[] _inverseMasses;
}
/**
* Get stepSize
*
* @return stepSize
*
*/
BrookOpenMMFloat BrookVerletDynamics::getStepSize( void ) const {
return _stepSize;
}
/**
* Set stepSize
*
* @param stepSize
*
* @return DefaultReturnValue
*
*/
int BrookVerletDynamics::_setStepSize( BrookOpenMMFloat stepSize ){
_stepSize = stepSize;
return DefaultReturnValue;
}
/**
* Update parameters -- only way parameters can be set
*
* @param step size step size
*
* @return DefaultReturnValue
*
*/
int BrookVerletDynamics::updateParameters( double stepSize ){
// ---------------------------------------------------------------------------------------
static int showUpdate = 1;
static int maxShowUpdate = 3;
static const std::string methodName = "BrookVerletDynamics::updateParameters";
// ---------------------------------------------------------------------------------------
_setStepSize( (BrookOpenMMFloat) stepSize );
_updateVerletStreams( );
// show update
if( showUpdate && getLog() && (showUpdate++ < maxShowUpdate) ){
std::string contents = getContentsString( );
(void) fprintf( getLog(), "%s contents\n%s", methodName.c_str(), contents.c_str() );
(void) fflush( getLog() );
}
return DefaultReturnValue;
}
/**
* Get Particle stream size
*
* @return Particle stream size
*
*/
int BrookVerletDynamics::getVerletDynamicsParticleStreamSize( void ) const {
return _verletParticleStreamSize;
}
/**
* Get particle stream width
*
* @return particle stream width
*
*/
int BrookVerletDynamics::getVerletDynamicsParticleStreamWidth( void ) const {
return _verletParticleStreamWidth;
}
/**
* Get particle stream height
*
* @return particle stream height
*/
int BrookVerletDynamics::getVerletDynamicsParticleStreamHeight( void ) const {
return _verletParticleStreamHeight;
}
/**
* Get VPrime stream
*
* @return Vprime stream
*
*/
BrookFloatStreamInternal* BrookVerletDynamics::getVPrimeStream( void ) const {
return _verletStreams[VPrimeStream];
}
/**
* Get XPrime stream
*
* @return Xprime stream
*
*/
BrookFloatStreamInternal* BrookVerletDynamics::getXPrimeStream( void ) const {
return _verletStreams[XPrimeStream];
}
/**
* Get InverseMass stream
*
* @return inverse mass stream
*
*/
BrookFloatStreamInternal* BrookVerletDynamics::getInverseMassStream( void ) const {
return _verletStreams[InverseMassStream];
}
/**
* Initialize stream dimensions
*
* @param numberOfParticles number of particles
* @param platform platform
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int BrookVerletDynamics::_initializeStreamSizes( int numberOfParticles, const Platform& platform ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookVerletDynamics::_initializeStreamSizes";
// ---------------------------------------------------------------------------------------
_verletParticleStreamSize = getParticleStreamSize( platform );
_verletParticleStreamWidth = getParticleStreamWidth( platform );
_verletParticleStreamHeight = getParticleStreamHeight( platform );
return DefaultReturnValue;
}
/**
* Initialize streams
*
* @param platform platform
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int BrookVerletDynamics::_initializeStreams( const Platform& platform ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookVerletDynamics::_initializeStreams";
BrookOpenMMFloat dangleValue = (BrookOpenMMFloat) 0.0;
// ---------------------------------------------------------------------------------------
int sdParticleStreamSize = getVerletDynamicsParticleStreamSize();
int sdParticleStreamWidth = getVerletDynamicsParticleStreamWidth();
_verletStreams[VPrimeStream] = new BrookFloatStreamInternal( BrookCommon::VPrimeStream,
sdParticleStreamSize, sdParticleStreamWidth,
BrookStreamInternal::Float3, dangleValue );
_verletStreams[XPrimeStream] = new BrookFloatStreamInternal( BrookCommon::XPrimeStream,
sdParticleStreamSize, sdParticleStreamWidth,
BrookStreamInternal::Float3, dangleValue );
_verletStreams[InverseMassStream] = new BrookFloatStreamInternal( BrookCommon::InverseMassStream,
sdParticleStreamSize, sdParticleStreamWidth,
BrookStreamInternal::Float, dangleValue );
return DefaultReturnValue;
}
/**
* Update sd streams -- called after parameters change
*
* @return ErrorReturnValue if error, else DefaultReturnValue
*
*/
int BrookVerletDynamics::_updateVerletStreams( void ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookVerletDynamics::_updateVerletStreams";
// ---------------------------------------------------------------------------------------
int particleStreamSize = getVerletDynamicsParticleStreamSize();
BrookOpenMMFloat* inverseMass = new BrookOpenMMFloat[particleStreamSize];
memset( inverseMass, 0, particleStreamSize*sizeof( BrookOpenMMFloat ) );
int numberOfParticles = getNumberOfParticles();
for( int ii = 0; ii < numberOfParticles; ii++ ){
inverseMass[ii] = _inverseMasses[ii];
}
_verletStreams[InverseMassStream]->loadFromArray( inverseMass );
delete[] inverseMass;
return DefaultReturnValue;
}
/**
* Set masses
*
* @param masses particle masses
*
*/
int BrookVerletDynamics::_setInverseMasses( const std::vector<double>& masses ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookVerletDynamics::_setInverseSqrtMasses";
BrookOpenMMFloat zero = (BrookOpenMMFloat) 0.0;
BrookOpenMMFloat one = (BrookOpenMMFloat) 1.0;
// ---------------------------------------------------------------------------------------
// setup inverse sqrt masses
_inverseMasses = new BrookOpenMMFloat[masses.size()];
int index = 0;
for( std::vector<double>::const_iterator ii = masses.begin(); ii != masses.end(); ii++, index++ ){
if( *ii != 0.0 ){
BrookOpenMMFloat value = static_cast<BrookOpenMMFloat>(*ii);
_inverseMasses[index] = ( one/value );
} else {
_inverseMasses[index] = zero;
}
}
return DefaultReturnValue;
}
/*
* Setup of VerletDynamics parameters
*
* @param masses masses
* @param platform Brook platform
*
* @return nonzero value if error
*
* */
int BrookVerletDynamics::setup( const std::vector<double>& masses, const Platform& platform ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookVerletDynamics::setup";
// ---------------------------------------------------------------------------------------
const BrookPlatform& brookPlatform = dynamic_cast<const BrookPlatform&> (platform);
setLog( brookPlatform.getLog() );
int numberOfParticles = (int) masses.size();
setNumberOfParticles( numberOfParticles );
// set stream sizes and then create streams
_initializeStreamSizes( numberOfParticles, platform );
_initializeStreams( platform );
_setInverseMasses( masses );
return DefaultReturnValue;
}
/*
* Get contents of object
*
* @param level level of dump
*
* @return string containing contents
*
* */
std::string BrookVerletDynamics::getContentsString( int level ) const {
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookVerletDynamics::getContentsString";
static const unsigned int MAX_LINE_CHARS = 256;
char value[MAX_LINE_CHARS];
static const char* Set = "Set";
static const char* NotSet = "Not set";
// ---------------------------------------------------------------------------------------
std::stringstream message;
std::string tab = " ";
#ifdef _MSC_VER
#define LOCAL_SPRINTF(a,b,c) sprintf_s( (a), MAX_LINE_CHARS, (b), (c) );
#else
#define LOCAL_SPRINTF(a,b,c) sprintf( (a), (b), (c) );
#endif
(void) LOCAL_SPRINTF( value, "%d", getNumberOfParticles() );
message << _getLine( tab, "Number of particles:", value );
(void) LOCAL_SPRINTF( value, "%d", getParticleStreamWidth() );
message << _getLine( tab, "Particle stream width:", value );
(void) LOCAL_SPRINTF( value, "%d", getParticleStreamHeight() );
message << _getLine( tab, "Particle stream height:", value );
(void) LOCAL_SPRINTF( value, "%d", getParticleStreamSize() );
message << _getLine( tab, "Particle stream size:", value );
(void) LOCAL_SPRINTF( value, "%.5f", getStepSize() );
message << _getLine( tab, "Step size:", value );
message << _getLine( tab, "Log:", (getLog() ? Set : NotSet) );
for( int ii = 0; ii < LastStreamIndex; ii++ ){
message << std::endl;
if( _verletStreams[ii] ){
message << _verletStreams[ii]->getContentsString( );
}
}
#undef LOCAL_SPRINTF
return message.str();
}
/**
* Update
*
* @param positions particle positions
* @param velocities particle velocities
* @param forces particle forces
* @param brookShakeAlgorithm BrookShakeAlgorithm reference
*
* @return DefaultReturnValue
*
*/
int BrookVerletDynamics::update( BrookStreamImpl& positionStream, BrookStreamImpl& velocityStream,
const BrookStreamImpl& forceStreamC,
BrookShakeAlgorithm& brookShakeAlgorithm ){
// ---------------------------------------------------------------------------------------
static std::string methodName = "\nBrookVerletDynamics::update";
static int printOn = 0;
FILE* log;
// ---------------------------------------------------------------------------------------
_internalStepCount++;
//setLog( stderr );
if( printOn && getLog() ){
log = getLog();;
} else {
printOn = 0;
}
BrookStreamImpl& forceStream = const_cast<BrookStreamImpl&> (forceStreamC);
if( printOn ){
static int showAux = 1;
if( showAux ){
showAux = 0;
/*
std::string contents = _brookVelocityCenterOfMassRemoval->getContentsString( );
(void) fprintf( log, "%s VelocityCenterOfMassRemoval contents\n%s", methodName, contents.c_str() );
*/
(void) fprintf( log, "%s step=%d \n%s\n\nShake contents\n%s", methodName.c_str(), _internalStepCount, getContentsString().c_str(),
brookShakeAlgorithm.getContentsString().c_str() );
(void) fflush( log );
}
}
// To Shake or not to Shake
if( brookShakeAlgorithm.getNumberOfConstraints() > 0 ){
// integration step
kupdate_md1( (float) getStepSize(),
positionStream.getBrookStream(),
velocityStream.getBrookStream(),
forceStream.getBrookStream(),
getInverseMassStream()->getBrookStream(),
getXPrimeStream()->getBrookStream()
);
// diagnostics
if( printOn ){
(void) fprintf( log, "\n%s step=%d Post kupdate_md1: particleStrW=%3d step=%.5f",
methodName.c_str(), _internalStepCount, getVerletDynamicsParticleStreamWidth(), getStepSize() );
(void) fprintf( log, "\nInverseMassStream %d\n", _internalStepCount );
getInverseMassStream()->printToFile( log );
BrookStreamInternal* brookStreamInternalPos = positionStream.getBrookStreamInternal();
(void) fprintf( log, "\nPositionStream %d\n", _internalStepCount );
brookStreamInternalPos->printToFile( log );
(void) fprintf( log, "\nForceStream %d\n", _internalStepCount );
BrookStreamInternal* brookStreamInternalF = forceStream.getBrookStreamInternal();
std::vector<std::vector<double> > forceStatistics;
brookStreamInternalF->getStatistics( forceStatistics, getNumberOfParticles() );
std::stringstream tag;
tag << _internalStepCount << " Fxx ";
std::string stats = brookStreamInternalF->printStatistics( tag.str(), forceStatistics );
(void) fprintf( log, "\nStep %d Force stats:\n%s", _internalStepCount, stats.c_str() );
brookStreamInternalF->printToFile( log );
BrookStreamInternal* brookStreamInternalV = velocityStream.getBrookStreamInternal();
std::vector<std::vector<double> > velocityStatistics;
brookStreamInternalV->getStatistics( velocityStatistics, getNumberOfParticles() );
std::stringstream tagV;
tagV << _internalStepCount << " Vxx ";
stats = brookStreamInternalPos->printStatistics( tagV.str(), velocityStatistics );
(void) fprintf( log, "\nStep %d Velocity stats:\n%s", _internalStepCount, stats.c_str() );
(void) fprintf( log, "\nVelocityStream %d\n", _internalStepCount );
brookStreamInternalV->printToFile( log );
(void) fprintf( log, "\nXPrimeStream %d\n", _internalStepCount );
getXPrimeStream()->printToFile( log );
}
// Shake
kshakeh_fix1(
(float) brookShakeAlgorithm.getMaxIterations(),
(float) getVerletDynamicsParticleStreamWidth(),
brookShakeAlgorithm.getShakeTolerance(),
brookShakeAlgorithm.getShakeParticleIndicesStream()->getBrookStream(),
positionStream.getBrookStream(),
getXPrimeStream()->getBrookStream(),
brookShakeAlgorithm.getShakeParticleParameterStream()->getBrookStream(),
brookShakeAlgorithm.getShakeXCons0Stream()->getBrookStream(),
brookShakeAlgorithm.getShakeXCons1Stream()->getBrookStream(),
brookShakeAlgorithm.getShakeXCons2Stream()->getBrookStream(),
brookShakeAlgorithm.getShakeXCons3Stream()->getBrookStream() );
if( printOn ){
(void) fprintf( log, "\n%s Post kshakeh_fix1: particleStrW=%3d", methodName.c_str(), getVerletDynamicsParticleStreamWidth() );
(void) fprintf( log, "\nShakeParticleIndicesStream %d\n", _internalStepCount );
brookShakeAlgorithm.getShakeParticleIndicesStream()->printToFile( log );
BrookStreamInternal* brookStreamInternalPos = positionStream.getBrookStreamInternal();
(void) fprintf( log, "\nPositionStream %d\n", _internalStepCount );
brookStreamInternalPos->printToFile( log );
(void) fprintf( log, "\nXPrimeStream %d\n", _internalStepCount );
getXPrimeStream()->printToFile( log );
(void) fprintf( log, "\nShakeParticleParameterStream %d\n", _internalStepCount );
brookShakeAlgorithm.getShakeParticleParameterStream()->printToFile( log );
(void) fprintf( log, "\nShakeXCons0\n" );
brookShakeAlgorithm.getShakeXCons0Stream()->printToFile( log );
(void) fprintf( log, "\nShakeXCons1\n" );
brookShakeAlgorithm.getShakeXCons1Stream()->printToFile( log );
(void) fprintf( log, "\nShakeXCons2\n" );
brookShakeAlgorithm.getShakeXCons2Stream()->printToFile( log );
(void) fprintf( log, "\nShakeXCons3\n" );
brookShakeAlgorithm.getShakeXCons3Stream()->printToFile( log );
}
// Shake gather
kshakeh_update1_fix1(
(float) brookShakeAlgorithm.getShakeConstraintStreamWidth(),
brookShakeAlgorithm.getShakeInverseMapStream()->getBrookStream(),
getXPrimeStream()->getBrookStream(),
brookShakeAlgorithm.getShakeXCons0Stream()->getBrookStream(),
brookShakeAlgorithm.getShakeXCons1Stream()->getBrookStream(),
brookShakeAlgorithm.getShakeXCons2Stream()->getBrookStream(),
brookShakeAlgorithm.getShakeXCons3Stream()->getBrookStream(),
getXPrimeStream()->getBrookStream() );
//positionStream.getBrookStream() );
if( printOn ){
(void) fprintf( log, "\n%s Post kshakeh_update1_fix1: step=%d ShakeConstraintStreamWidth=%3d",
methodName.c_str(), _internalStepCount, brookShakeAlgorithm.getShakeConstraintStreamWidth() );
(void) fprintf( log, "\nShakeInverseMapStream %d\n", _internalStepCount );
brookShakeAlgorithm.getShakeInverseMapStream()->printToFile( log );
BrookStreamInternal* brookStreamInternalPos = positionStream.getBrookStreamInternal();
(void) fprintf( log, "\nPositionStream %d\n", _internalStepCount );
brookStreamInternalPos->printToFile( log );
(void) fprintf( log, "\nXPrimeStream %d\n", _internalStepCount );
getXPrimeStream()->printToFile( log );
(void) fprintf( log, "\nShakeXCons0\n" );
brookShakeAlgorithm.getShakeXCons0Stream()->printToFile( log );
(void) fprintf( log, "\nShakeXCons1\n" );
brookShakeAlgorithm.getShakeXCons1Stream()->printToFile( log );
(void) fprintf( log, "\nShakeXCons2\n" );
brookShakeAlgorithm.getShakeXCons2Stream()->printToFile( log );
(void) fprintf( log, "\nShakeXCons3\n" );
brookShakeAlgorithm.getShakeXCons3Stream()->printToFile( log );
}
// second integration step
float inverseStepSize = 1.0f/getStepSize();
kupdate_md2( inverseStepSize,
getXPrimeStream()->getBrookStream(),
positionStream.getBrookStream(),
velocityStream.getBrookStream(),
positionStream.getBrookStream() );
if( printOn ){
(void) fprintf( log, "\n%s step=%d Post kupdate_md2: inverseStepSize=%3e",
methodName.c_str(), _internalStepCount, inverseStepSize );
BrookStreamInternal* brookStreamInternalPos = positionStream.getBrookStreamInternal();
std::string violationString;
brookShakeAlgorithm.checkConstraints( brookStreamInternalPos, violationString, 0.0001f );
(void) fprintf( log, "Shake: %s\n", violationString.c_str() );
(void) fprintf( log, "\nPositionStream %d\n", _internalStepCount );
brookStreamInternalPos->printToFile( log );
(void) fprintf( log, "\nXPrimeStream %d\n", _internalStepCount );
getXPrimeStream()->printToFile( log );
brookStreamInternalPos = velocityStream.getBrookStreamInternal();
(void) fprintf( log, "\nVelocityStream %d\n", _internalStepCount );
brookStreamInternalPos->printToFile( log );
}
} else {
kupdateMdNoShake( getStepSize(),
positionStream.getBrookStream(),
velocityStream.getBrookStream(),
forceStream.getBrookStream(),
getInverseMassStream()->getBrookStream(),
velocityStream.getBrookStream(),
positionStream.getBrookStream() );
}
// diagnostics
if( 0 && (_internalStepCount % 100) == 0 ){
FILE* log1 = stderr;
float epsilon = 1.0e-01f;
BrookStreamInternal* brookStreamInternalPos = positionStream.getBrookStreamInternal();
BrookStreamInternal* brookStreamInternalVel = velocityStream.getBrookStreamInternal();
BrookStreamInternal* brookStreamInternalFrc = forceStream.getBrookStreamInternal();
// check for nan and infinities
int coordinateNans = brookStreamInternalPos->checkForNans( );
int velocityNans = brookStreamInternalVel->checkForNans( );
int forceNans = brookStreamInternalFrc->checkForNans( );
int abort = abs( coordinateNans ) + abs( velocityNans ) + abs( forceNans );
// Shake violations
std::string violationString;
if( brookShakeAlgorithm.getNumberOfConstraints() > 0 ){
int constraintViolations = brookShakeAlgorithm.checkConstraints( brookStreamInternalPos, violationString, 0.0001f );
abort += abs( constraintViolations );
} else {
violationString = "Shake not active";
}
// force sums ~ 0?
std::vector<float> sums;
brookStreamInternalFrc->sumColumns( sums );
// check if should abort
(void) fprintf( log1, "%d Nans: x=%d v=%d f=%d ", _internalStepCount, coordinateNans, velocityNans, forceNans );
(void) fprintf( log1, " Fsum[" );
for( int ii = 0; ii < 3; ii++ ){
if( fabsf( sums[ii] ) > epsilon ){
abort++;
}
(void) fprintf( log1, "%12.4e ", sums[ii] );
}
(void) fprintf( log1, "] %s abort=%d\n", violationString.c_str(), abort );
(void) fflush( log1 );
if( abort ){
(void) fprintf( log1, "Aborting:\n" );
brookStreamInternalPos->printToFile( log1 );
brookStreamInternalVel->printToFile( log1 );
brookStreamInternalFrc->printToFile( log1 );
exit(1);
}
/*
std::vector<std::vector<double> > velocityStatistics;
brookStreamInternalPos->getStatistics( velocityStatistics, getNumberOfParticles() );
std::stringstream tagV;
tagV << _internalStepCount << " Vxx ";
std::string stats = brookStreamInternalPos->printStatistics( tagV.str(), velocityStatistics );
(void) fprintf( log1, "\nStep %d Velocity stats:\n%s", _internalStepCount, stats.c_str() );
*/
//removeCom( brookStreamInternalPos, getInverseMassStream() );
}
//_brookVelocityCenterOfMassRemoval->removeVelocityCenterOfMass( velocities );
return DefaultReturnValue;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment