/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2009 Stanford University and the Authors. *
* Authors: Mark Friedrichs, Mike Houston *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see . *
* -------------------------------------------------------------------------- */
#include
#include "openmm/OpenMMException.h"
#include "BrookStreamInternal.h"
#ifdef _WIN32
#include
#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 WIN32
(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 WIN32
#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 >& 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 >& 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 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 WIN32
#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 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& streams ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookStreamInternal::printStreamsToFile";
// ---------------------------------------------------------------------------------------
FILE* filePtr;
#ifdef WIN32
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
#include
#include
#include
int BrookStreamInternal::loadStreamGivenFileName( std::string& fileName ){
// ---------------------------------------------------------------------------------------
static const std::string methodName = "BrookStreamInternal::loadStreamGivenFileName";
// ---------------------------------------------------------------------------------------
FILE* log = stderr;
/* open file, read header */
FILE* filePtr;
#ifdef WIN32
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( 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& sums ){
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "BrookStreamInternal::sumColumns";
// ---------------------------------------------------------------------------------------
void* dataArrayV = getData( 1 );
float* array = static_cast( 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;
}