From c26190e8d6fd9fa6ea845e18394b2dcc8f7c2b61 Mon Sep 17 00:00:00 2001 From: Norbert Podhorszki <pnorbert@ornl.gov> Date: Mon, 27 Mar 2017 15:18:54 -0400 Subject: [PATCH] Added ADIOS1 Engine for writing with pre-installed ADIOS 1.x library. mpi dummy collision prevents building examples in nompi mode. --- Makefile | 2 +- Makefile.libs | 14 + buildADIOS1.sh | 53 +++ examples/hello/adios1Writer/Makefile | 36 ++ .../hello/adios1Writer/helloADIOS1Writer.cpp | 105 +++++ .../adios1Writer/helloADIOS1Writer_nompi.cpp | 80 ++++ include/core/VariableBase.h | 21 + include/engine/adios1/ADIOS1Reader.h | 104 +++++ include/engine/adios1/ADIOS1Writer.h | 118 ++++++ src/ADIOS.cpp | 14 + src/engine/adios1/ADIOS1Reader.cpp | 178 +++++++++ src/engine/adios1/ADIOS1Writer.cpp | 369 ++++++++++++++++++ 12 files changed, 1093 insertions(+), 1 deletion(-) create mode 100755 buildADIOS1.sh create mode 100644 examples/hello/adios1Writer/Makefile create mode 100644 examples/hello/adios1Writer/helloADIOS1Writer.cpp create mode 100644 examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp create mode 100644 include/engine/adios1/ADIOS1Reader.h create mode 100644 include/engine/adios1/ADIOS1Writer.h create mode 100644 src/engine/adios1/ADIOS1Reader.cpp create mode 100644 src/engine/adios1/ADIOS1Writer.cpp diff --git a/Makefile b/Makefile index ea705d1d4..f8f63f7b4 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ HFiles:=$(shell find ./include -type f -name "*.h") CPPFiles:=$(shell find ./src -type f -name "*.cpp") INC:=-I./include VPATH = ./src ./src/core ./src/functions \ - ./src/engine/bp ./src/engine/dataman \ + ./src/engine/bp ./src/engine/dataman ./src/engine/adios1 \ ./src/transport/file ./src/transport/wan \ ./src/capsule/heap ./src/capsule/shmem \ ./src/transform \ diff --git a/Makefile.libs b/Makefile.libs index ce4e77094..2f736c1e9 100644 --- a/Makefile.libs +++ b/Makefile.libs @@ -30,6 +30,20 @@ else endif +ifeq ($(HAVE_ADIOS1),yes) + ADIOS1_DIR=/opt/adios/lean/1.11# need to change this to your local adios 1.x installation + CFLAGS += -DHAVE_ADIOS1 + INC += -I$(ADIOS1_DIR)/include + LIBS += $(shell ${ADIOS1_DIR}/bin/adios_config -l) +else + HFiles:=$(filter-out $(ENGINE_INC)/adios1/ADIOS1Writer.h,$(HFiles)) + HFiles:=$(filter-out $(ENGINE_INC)/adios1/ADIOS1Reader.h,$(HFiles)) + CPPFiles:=$(filter-out $(ENGINE_SRC)/adios1/ADIOS1Writer.cpp,$(CPPFiles)) + CPPFiles:=$(filter-out $(ENGINE_SRC)/adios1/ADIOS1Reader.cpp,$(CPPFiles)) +endif + + + #EXTERNAL DEPENDENCIES ifeq ($(HAVE_NETCDF),yes) LIBS += -lnetcdf diff --git a/buildADIOS1.sh b/buildADIOS1.sh new file mode 100755 index 000000000..42c099583 --- /dev/null +++ b/buildADIOS1.sh @@ -0,0 +1,53 @@ +#!/bin/bash + + +# buildTest.sh for ADIOS1 Writer example +# Created on: Mar 27, 2017 +# Author: pnb +# Recommended: do a "make clean" the first time + +MPICOMPILER=mpic++ +ADIOS1_DIR=/opt/adios/1.11 + +if [ "$(uname)" == "Darwin" ]; then + CCOMPILER=clang++ +elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then + CCOMPILER=g++ +fi +echo "######################################################################################" +echo "Start building ADIOS ./lib/libadios.a ./libadios_nompi.a" +echo "######################################################################################" +echo +make -j4 HAVE_ADIOS1=yes ADIOS1_DIR=${ADIOS1_DIR} CC=$CCOMPILER MPICC=$MPICOMPILER #build the ./lib/libadios.a and ./libadios_nompi.a +echo +echo "#################################################################" +echo "Building BPWriter example" +echo "#################################################################" +make -j4 -C ./examples/hello/bpWriter CC=$CCOMPILER MPICC=$MPICOMPILER +#make -j4 -C ./examples/hello/bpReader CC=$CCOMPILER MPICC=$MPICOMPILER +echo +echo +echo +echo "#################################################################" +echo "Running nompi.exe example" +echo "#################################################################" +echo +echo +echo "#################################################################" +echo "BP writer" +echo "#################################################################" +./examples/hello/bpWriter/helloBPWriter_nompi.exe +echo "DONE...check for myDoubles_nompi.bp directory" + +echo "#################################################################" +echo "BP reader..not ready yet" +echo "#################################################################" +#./examples/hello/bpWriter/helloBPReader.exe +echo +echo +echo "#################################################################" +echo "To run mpi version with 4 mpi processes: " +echo "mpirun -n 4 ./examples/hello/bpWriter/helloBPWriter.exe" +echo "mpirun -n 4 ./examples/hello/bpReader/helloBPReader.exe" +echo "END" +echo "################################################################" diff --git a/examples/hello/adios1Writer/Makefile b/examples/hello/adios1Writer/Makefile new file mode 100644 index 000000000..43e252235 --- /dev/null +++ b/examples/hello/adios1Writer/Makefile @@ -0,0 +1,36 @@ +# Makefile for testing purposes, will build helloADIOS1Writer (make or make mpi) or helloADIOS1Writer_nompi (make nompi) +# Created on: Mar 27, 2017 +# Author: pnb + +BASE_NAME=helloADIOS1Writer + +#COMPILERS +CC=g++ +MPICC=mpic++ + +#ADIOS 1.x LOCATION +ADIOS1_DIR=/opt/adios/1.11 +ADIOS1_LIB=$(shell ${ADIOS1_DIR}/bin/adios_config -l) +ADIOS1_NOMPI_LIB=$(shell ${ADIOS1_DIR}/bin/adios_config -ls) + +#ADIOS 2.x LOCATION +ADIOS_DIR=../../.. +ADIOS_INCLUDE=-I$(ADIOS_DIR)/include +ADIOS_LIB=$(ADIOS_DIR)/lib/libadios.a +ADIOS_NOMPI_LIB=$(ADIOS_DIR)/lib/libadios_nompi.a + +#FLAGS +CFLAGS=-Wall -Wpedantic -std=c++11 -O0 -g +LDFLAGS= + +all: mpi nompi + +mpi: $(ADIOS_LIB) $(ADIOS_HFiles) + $(MPICC) $(CFLAGS) $(ADIOS_INCLUDE) $(BASE_NAME).cpp -o $(BASE_NAME).exe $(ADIOS_LIB) $(ADIOS1_LIB) $(LDFLAGS) -lpthread + +nompi: $(ADIOS_NOMPI_LIB) $(NoMPI_HFiles) + $(CC) $(CFLAGS) $(ADIOS_INCLUDE) -DADIOS_NOMPI $(BASE_NAME)_nompi.cpp -o $(BASE_NAME)_nompi.exe $(ADIOS_NOMPI_LIB) $(ADIOS1_NOMPI_LIB) $(LDFLAGS) -lpthread + +clean: + rm *.exe + diff --git a/examples/hello/adios1Writer/helloADIOS1Writer.cpp b/examples/hello/adios1Writer/helloADIOS1Writer.cpp new file mode 100644 index 000000000..18d26d34d --- /dev/null +++ b/examples/hello/adios1Writer/helloADIOS1Writer.cpp @@ -0,0 +1,105 @@ +/* + * helloWriter.cpp + * + * Created on: Feb 16, 2017 + * Author: wfg + */ + + + +#include <vector> +#include <iostream> + + +#include <mpi.h> + + +#include "ADIOS_CPP.h" + + +int main( int argc, char* argv [] ) +{ + MPI_Init( &argc, &argv ); + int rank, nproc; + MPI_Comm_rank( MPI_COMM_WORLD, &rank ); + MPI_Comm_size( MPI_COMM_WORLD, &nproc ); + const bool adiosDebug = true; + adios::ADIOS adios( MPI_COMM_WORLD, adios::Verbose::INFO, adiosDebug ); + + //Application variable + float frank = (float)rank; + std::vector<double> myDoubles = { frank, frank+0.1f, frank+0.2f, frank+0.3f, frank+0.4f, frank+0.5f, + frank+0.6f, frank+0.7f, frank+0.8f, frank+0.9f }; + const std::size_t Nx = myDoubles.size(); + + const std::size_t rows = 3; + const std::size_t columns = 3; + + std::vector<float> myMatrix; + myMatrix.reserve( rows * columns ); + myMatrix.push_back( frank+0.0 ); myMatrix.push_back( frank+0.1 ), myMatrix.push_back( frank+0.2 ); + myMatrix.push_back( frank+0.3 ); myMatrix.push_back( frank+0.4 ), myMatrix.push_back( frank+0.5 ); + myMatrix.push_back( frank+0.6 ); myMatrix.push_back( frank+0.7 ), myMatrix.push_back( frank+0.8 ); + + frank = -(float)rank; + std::vector<float> myMatrix2 = {frank-0.1f, frank-0.2f, frank-0.3f, + frank-0.4f, frank-0.5f, frank-0.6f, + frank-0.7f, frank-0.8f, frank-0.9f }; + + try + { + //Define variable and local size + adios::Variable<double>& ioMyDoubles = adios.DefineVariable<double>( "myDoubles", {1,Nx}, {nproc,Nx}, {rank,0} ); + adios::Variable<float>& ioMyMatrix = adios.DefineVariable<float>( "myMatrix", {rows,columns}, {nproc*rows,columns}, {rank*rows,0} ); + adios::Variable<float>& ioMyMatrix2 = adios.DefineVariable<float>( "myMatrix2", {rows,columns}, {rows,nproc*columns}, {0,rank*columns} ); + + //Define method for engine creation, it is basically straight-forward parameters + adios::Method& bpWriterSettings = adios.DeclareMethod( "SingleFile" ); //default method type is BPWriter + bpWriterSettings.SetEngine( "ADIOS1Writer" ); + bpWriterSettings.SetParameters( "profile_units=mus" ); + bpWriterSettings.AddTransport( "File", "profile_units=mus", "have_metadata_file=no" ); //uses default POSIX library + + //Create engine smart pointer due to polymorphism, + //Open returns a smart pointer to Engine containing the Derived class Writer + auto bpWriter = adios.Open( "myDoubles.bp", "w", bpWriterSettings, adios::IOMode::COLLECTIVE ); + + if( bpWriter == nullptr ) + throw std::ios_base::failure( "ERROR: couldn't create bpWriter at Open\n" ); + + bpWriter->Write<double>( ioMyDoubles, myDoubles.data() ); // Base class Engine own the Write<T> that will call overloaded Write from Derived + + bpWriter->Write<float>( ioMyMatrix, myMatrix.data() ); + bpWriter->Write<float>( ioMyMatrix2, myMatrix2.data() ); + + bpWriter->Close( ); + } + catch( std::invalid_argument& e ) + { + if( rank == 0 ) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + } + catch( std::ios_base::failure& e ) + { + if( rank == 0 ) + { + std::cout << "System exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + } + catch( std::exception& e ) + { + if( rank == 0 ) + { + std::cout << "Exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + } + + MPI_Finalize( ); + + return 0; + +} diff --git a/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp b/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp new file mode 100644 index 000000000..c78fd0878 --- /dev/null +++ b/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp @@ -0,0 +1,80 @@ +/* + * helloADIOSNoXML_OOP.cpp + * + * Created on: Jan 9, 2017 + * Author: wfg + */ + +#include <vector> +#include <iostream> + +#include "ADIOS_CPP.h" + + +int main( int argc, char* argv [] ) + { + const bool adiosDebug = true; + adios::ADIOS adios( adiosDebug ); + + //Application variable + std::vector<double> myDoubles = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + const std::size_t Nx = myDoubles.size(); + + const std::size_t rows = 3; + const std::size_t columns = 3; + std::vector<float> myMatrix = { 1, 2, 3, + 4, 5, 6, + 7, 8, 9 }; + + std::vector<float> myMatrix2 = { -1, -2, -3, + -4, -5, -6, + -7, -8, -9 }; + + try + { + //Define variable and local size + adios::Variable<double>& ioMyDoubles = adios.DefineVariable<double>( "myDoubles", adios::Dims{Nx} ); + adios::Variable<float>& ioMyMatrix = adios.DefineVariable<float>( "myMatrix", adios::Dims{rows,columns} ); + adios::Variable<float>& ioMyMatrix2 = adios.DefineVariable<float>( "myMatrix2", adios::Dims{rows,columns} ); + adios::Variable<float>& ioMyMatrix3 = adios.DefineVariable<float>( "myMatrix3", adios::Dims{rows,columns} ); + + //Define method for engine creation, it is basically straight-forward parameters + adios::Method& bpWriterSettings = adios.DeclareMethod( "SinglePOSIXFile" ); //default method type is Writer + bpWriterSettings.SetParameters( "profile_units=mus" ); + bpWriterSettings.AddTransport( "File", "have_metadata_file=yes", "profile_units=mus" ); + + //Create engine smart pointer due to polymorphism, + //Open returns a smart pointer to Engine containing the Derived class Writer + auto bpFileWriter = adios.Open( "myDoubles_nompi.bp", "w", bpWriterSettings, adios::IOMode::COLLECTIVE ); + + if( bpFileWriter == nullptr ) + throw std::ios_base::failure( "ERROR: couldn't create bpWriter at Open\n" ); + + bpFileWriter->Write<double>( ioMyDoubles, myDoubles.data() ); // Base class Engine own the Write<T> that will call overloaded Write from Derived + bpFileWriter->Write<float>( ioMyMatrix, myMatrix.data() ); //2d Example + bpFileWriter->Write<float>( ioMyMatrix2, myMatrix2.data() ); //2d Example + bpFileWriter->Write<float>( ioMyMatrix3, myMatrix2.data() ); //2d Example + bpFileWriter->Close( ); + // + } + catch( std::invalid_argument& e ) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + catch( std::ios_base::failure& e ) + { + std::cout << "System exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + catch( std::exception& e ) + { + std::cout << "Exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + + return 0; +} + + + diff --git a/include/core/VariableBase.h b/include/core/VariableBase.h index 4bf492354..4dddf13b7 100644 --- a/include/core/VariableBase.h +++ b/include/core/VariableBase.h @@ -11,6 +11,8 @@ /// \cond EXCLUDE_FROM_DOXYGEN #include <vector> #include <string> +#include <sstream> +#include <iterator> /// \endcond #include "functions/adiosFunctions.h" //GetTotalSize @@ -83,6 +85,25 @@ public: const bool m_DebugMode = false; + std::string GetDimensionAsString() { return dimsToString( m_Dimensions ); } + std::string GetGlobalDimensionAsString() { return dimsToString( m_GlobalDimensions ); } + std::string GetOffsetsAsString() { return dimsToString( m_GlobalOffsets ); } + + +private: + std::string dimsToString( Dims dims ) + { + std::ostringstream oss; + if (!dims.empty()) + { + // Convert all but the last element to avoid a trailing "," + std::copy(dims.begin(), dims.end()-1, + std::ostream_iterator<std::size_t>(oss, ",")); + // Now add the last element with no delimiter + oss << dims.back(); + } + return oss.str(); + } }; diff --git a/include/engine/adios1/ADIOS1Reader.h b/include/engine/adios1/ADIOS1Reader.h new file mode 100644 index 000000000..7a91b9a6c --- /dev/null +++ b/include/engine/adios1/ADIOS1Reader.h @@ -0,0 +1,104 @@ +/* + * ADIOS1Reader.h + * Class to read files using old adios 1.x library. + * It requires adios 1.x installed + * + * Created on: Mar 27, 2017 + * Author: pnb + */ + +#ifndef BPFILEREADER_H_ +#define BPFILEREADER_H_ + +#include <iostream> //this must go away + +#include "core/Engine.h" + +//supported capsules +#include "capsule/heap/STLVector.h" + + +namespace adios +{ + + +class BPFileReader : public Engine +{ + +public: + + /** + * Constructor for single BP capsule engine, writes in BP format into a single heap capsule + * @param name unique name given to the engine + * @param accessMode + * @param mpiComm + * @param method + * @param debugMode + * @param hostLanguage + */ + BPFileReader( ADIOS& adios, const std::string name, const std::string accessMode, MPI_Comm mpiComm, + const Method& method, const IOMode iomode, const float timeout_sec, + const bool debugMode = false, const unsigned int nthreads = 1 ); + + ~BPFileReader( ); + + + Variable<void>* InquireVariable( const std::string name, const bool readIn = true ); + Variable<char>* InquireVariableChar( const std::string name, const bool readIn = true ); + Variable<unsigned char>* InquireVariableUChar( const std::string name, const bool readIn = true ); + Variable<short>* InquireVariableShort( const std::string name, const bool readIn = true ); + Variable<unsigned short>* InquireVariableUShort( const std::string name, const bool readIn = true ); + Variable<int>* InquireVariableInt( const std::string name, const bool readIn = true ); + Variable<unsigned int>* InquireVariableUInt( const std::string name, const bool readIn = true ); + Variable<long int>* InquireVariableLInt( const std::string name, const bool readIn = true ); + Variable<unsigned long int>* InquireVariableULInt( const std::string name, const bool readIn = true ); + Variable<long long int>* InquireVariableLLInt( const std::string name, const bool readIn = true ); + Variable<unsigned long long int>* InquireVariableULLInt( const std::string name, const bool readIn = true ); + Variable<float>* InquireVariableFloat( const std::string name, const bool readIn = true ); + Variable<double>* InquireVariableDouble( const std::string name, const bool readIn = true ); + Variable<long double>* InquireVariableLDouble( const std::string name, const bool readIn = true ); + Variable<std::complex<float>>* InquireVariableCFloat( const std::string name, const bool readIn = true ); + Variable<std::complex<double>>* InquireVariableCDouble( const std::string name, const bool readIn = true ); + Variable<std::complex<long double>>* InquireVariableCLDouble( const std::string name, const bool readIn = true ); + + /** + * Not implemented + * @param name + * @param readIn + * @return + */ + VariableCompound* InquireVariableCompound( const std::string name, const bool readIn = true ); + + + void Close( const int transportIndex = -1 ); + +private: + + capsule::STLVector m_Buffer; ///< heap capsule, contains data and metadata buffers + //format::BP1Writer m_BP1Writer; ///< format object will provide the required BP functionality to be applied on m_Buffer and m_Transports + + void Init( ); ///< calls InitCapsules and InitTransports based on Method, called from constructor + void InitCapsules( ); + void InitTransports( ); ///< from Transports + + std::string GetMdtmParameter( const std::string parameter, const std::map<std::string,std::string>& mdtmParameters ); + + + template< class T > + Variable<T>* InquireVariableCommon( const std::string name, const bool readIn ) + { + std::cout << "Hello BPReaderCommon\n"; + + //here read variable metadata (dimensions, type, etc.)...then create a Variable like below: + //Variable<T>& variable = m_ADIOS.DefineVariable<T>( m_Name + "/" + name, ) + //return &variable; //return address if success + return nullptr; //on failure + } +}; + + + +} //end namespace adios + + +#endif /* BPFILEREADER_H_ */ diff --git a/include/engine/adios1/ADIOS1Writer.h b/include/engine/adios1/ADIOS1Writer.h new file mode 100644 index 000000000..bfa235ba0 --- /dev/null +++ b/include/engine/adios1/ADIOS1Writer.h @@ -0,0 +1,118 @@ +/* + * ADIOS1Writer.h + * Class to write files using old adios 1.x library. + * It requires adios 1.x installed + * + * Created on: Mar 27, 2017 + * Author: pnb + */ + +#ifndef ADIOS1WRITER_H_ +#define ADIOS1WRITER_H_ + +#include "core/Engine.h" + + +namespace adios +{ + +#ifdef ADIOS_NOMPI +# define _NOMPI 1 +#endif +#include "adios.h" // this is adios 1.x header file + + +class ADIOS1Writer : public Engine +{ + +public: + + /** + * Constructor for Writer writes in ADIOS 1.x BP format + * @param name unique name given to the engine + * @param accessMode + * @param mpiComm + * @param method + * @param debugMode + */ + ADIOS1Writer( ADIOS& adios, const std::string name, const std::string accessMode, MPI_Comm mpiComm, + const Method& method, const IOMode iomode, const float timeout_sec, + const bool debugMode = false, const unsigned int nthreads = 1 ); + + ~ADIOS1Writer( ); + + void Write( Variable<char>& variable, const char* values ); + void Write( Variable<unsigned char>& variable, const unsigned char* values ); + void Write( Variable<short>& variable, const short* values ); + void Write( Variable<unsigned short>& variable, const unsigned short* values ); + void Write( Variable<int>& variable, const int* values ); + void Write( Variable<unsigned int>& variable, const unsigned int* values ); + void Write( Variable<long int>& variable, const long int* values ); + void Write( Variable<unsigned long int>& variable, const unsigned long int* values ); + void Write( Variable<long long int>& variable, const long long int* values ); + void Write( Variable<unsigned long long int>& variable, const unsigned long long int* values ); + void Write( Variable<float>& variable, const float* values ); + void Write( Variable<double>& variable, const double* values ); + void Write( Variable<long double>& variable, const long double* values ); + void Write( Variable<std::complex<float>>& variable, const std::complex<float>* values ); + void Write( Variable<std::complex<double>>& variable, const std::complex<double>* values ); + void Write( Variable<std::complex<long double>>& variable, const std::complex<long double>* values ); + void Write( VariableCompound& variable, const void* values ); + + void Write( const std::string variableName, const char* values ); + void Write( const std::string variableName, const unsigned char* values ); + void Write( const std::string variableName, const short* values ); + void Write( const std::string variableName, const unsigned short* values ); + void Write( const std::string variableName, const int* values ); + void Write( const std::string variableName, const unsigned int* values ); + void Write( const std::string variableName, const long int* values ); + void Write( const std::string variableName, const unsigned long int* values ); + void Write( const std::string variableName, const long long int* values ); + void Write( const std::string variableName, const unsigned long long int* values ); + void Write( const std::string variableName, const float* values ); + void Write( const std::string variableName, const double* values ); + void Write( const std::string variableName, const long double* values ); + void Write( const std::string variableName, const std::complex<float>* values ); + void Write( const std::string variableName, const std::complex<double>* values ); + void Write( const std::string variableName, const std::complex<long double>* values ); + void Write( const std::string variableName, const void* values ); + + void Advance( ); + + /** + * Closes a single transport or all transports + * @param transportIndex, if -1 (default) closes all transports, otherwise it closes a transport in m_Transport[transportIndex]. In debug mode the latter is bounds-checked. + */ + void Close( const int transportIndex = -1 ); + + +private: + + const char * m_groupname; ///< ADIOS1 group name created from the method's name. Must be a unique group name. + const char * m_filename; ///< Save file name from constructor for Advance() when we re-open in ADIOS1 + MPI_Comm m_comm; ///< Save MPI communicator from constructor for Advance() when we re-open in ADIOS1 + + bool m_initialized = false; ///< set to true after calling adios_init() + int64_t m_adios_file = 0; ///< ADIOS1 file handler returned by adios_open() + int64_t m_adios_group = 0; ///< ADIOS1 group pointer that holds the ADIOS1 variable definitions + bool m_IsFileOpen = false; + + void Init( ); + // these are unused yet, keeping here to see if we need them + void InitParameters( ); + void InitTransports( ); + void InitProcessGroup( ); + + bool ReOpenAsNeeded( ); // return true if file is open or reopened + void DefineVariable( std::string name, bool isScalar, enum ADIOS_DATATYPES vartype, + std::string ldims, std::string gdims, std::string offs ); + void WriteVariable( std::string name, bool isScalar, enum ADIOS_DATATYPES vartype, + std::string ldims, std::string gdims, std::string offs, const void * values ); + +}; + + +} //end namespace adios + + +#endif /* ADIOS1WRITER_H_ */ diff --git a/src/ADIOS.cpp b/src/ADIOS.cpp index 6e17fcd13..bc9889d99 100644 --- a/src/ADIOS.cpp +++ b/src/ADIOS.cpp @@ -24,6 +24,12 @@ #include "engine/dataman/DataManReader.h" #endif + +#ifdef HAVE_ADIOS1 //external dependencies +#include "engine/adios1/ADIOS1Writer.h" +#include "engine/adios1/ADIOS1Reader.h" +#endif + namespace adios { @@ -141,6 +147,14 @@ std::shared_ptr<Engine> ADIOS::Open( const std::string name, const std::string a throw std::invalid_argument( "ERROR: this version didn't compile with Dataman library, can't Open DataManReader\n" ); #endif } + else if( type == "ADIOS1Writer" ) + { + #ifdef HAVE_ADIOS1 + return std::make_shared<ADIOS1Writer>( *this, name, accessMode, mpiComm, method, iomode, timeout_sec, m_DebugMode, method.m_nThreads ); + #else + throw std::invalid_argument( "ERROR: this version didn't compile with ADIOS 1.x library, can't Open ADIOS1Writer\n" ); + #endif + } else if( type == "Vis" ) { //return std::make_shared<Vis>( *this, name, accessMode, mpiComm, method, iomode, timeout_sec, m_DebugMode, method.m_nThreads ); diff --git a/src/engine/adios1/ADIOS1Reader.cpp b/src/engine/adios1/ADIOS1Reader.cpp new file mode 100644 index 000000000..edff32aad --- /dev/null +++ b/src/engine/adios1/ADIOS1Reader.cpp @@ -0,0 +1,178 @@ +/* + * BPFileReader.cpp + * + * Created on: Feb 27, 2017 + * Author: wfg + */ + + + +#include "engine/bp/BPFileReader.h" + +#include "transport/file/FileDescriptor.h" // uses POSIX +#include "transport/file/FilePointer.h" // uses C FILE* +#include "core/Support.h" +#include "functions/adiosFunctions.h" //CSVToVector + +//supported transports +#include "transport/file/FStream.h" // uses C++ fstream + + +namespace adios +{ + +BPFileReader::BPFileReader( ADIOS& adios, const std::string name, const std::string accessMode, MPI_Comm mpiComm, + const Method& method, const IOMode iomode, const float timeout_sec, + const bool debugMode, const unsigned int nthreads ): + Engine( adios, "BPFileReader", name, accessMode, mpiComm, method, debugMode, nthreads, " BPFileReader constructor (or call to ADIOS Open).\n" ), + m_Buffer( accessMode, m_RankMPI, m_DebugMode ) +{ + Init( ); +} + +BPFileReader::~BPFileReader( ) +{ } + + +Variable<void>* BPFileReader::InquireVariable( const std::string name, const bool readIn ) //not yet implemented +{ return nullptr; } + +Variable<char>* BPFileReader::InquireVariableChar( const std::string name, const bool readIn ) +{ return InquireVariableCommon<char>( name, readIn ); } + +Variable<unsigned char>* BPFileReader::InquireVariableUChar( const std::string name, const bool readIn ) +{ return InquireVariableCommon<unsigned char>( name, readIn ); } + +Variable<short>* BPFileReader::InquireVariableShort( const std::string name, const bool readIn ) +{ return InquireVariableCommon<short>( name, readIn ); } + +Variable<unsigned short>* BPFileReader::InquireVariableUShort( const std::string name, const bool readIn ) +{ return InquireVariableCommon<unsigned short>( name, readIn ); } + +Variable<int>* BPFileReader::InquireVariableInt( const std::string name, const bool readIn ) +{ return InquireVariableCommon<int>( name, readIn ); } + +Variable<unsigned int>* BPFileReader::InquireVariableUInt( const std::string name, const bool readIn ) +{ return InquireVariableCommon<unsigned int>( name, readIn ); } + +Variable<long int>* BPFileReader::InquireVariableLInt( const std::string name, const bool readIn ) +{ return InquireVariableCommon<long int>( name, readIn ); } + +Variable<unsigned long int>* BPFileReader::InquireVariableULInt( const std::string name, const bool readIn ) +{ return InquireVariableCommon<unsigned long int>( name, readIn ); } + +Variable<long long int>* BPFileReader::InquireVariableLLInt( const std::string name, const bool readIn ) +{ return InquireVariableCommon<long long int>( name, readIn ); } + +Variable<unsigned long long int>* BPFileReader::InquireVariableULLInt( const std::string name, const bool readIn ) +{ return InquireVariableCommon<unsigned long long int>( name, readIn ); } + +Variable<float>* BPFileReader::InquireVariableFloat( const std::string name, const bool readIn ) +{ return InquireVariableCommon<float>( name, readIn ); } + +Variable<double>* BPFileReader::InquireVariableDouble( const std::string name, const bool readIn ) +{ return InquireVariableCommon<double>( name, readIn ); } + +Variable<long double>* BPFileReader::InquireVariableLDouble( const std::string name, const bool readIn ) +{ return InquireVariableCommon<long double>( name, readIn ); } + +Variable<std::complex<float>>* BPFileReader::InquireVariableCFloat( const std::string name, const bool readIn ) +{ return InquireVariableCommon<std::complex<float>>( name, readIn ); } + +Variable<std::complex<double>>* BPFileReader::InquireVariableCDouble( const std::string name, const bool readIn ) +{ return InquireVariableCommon<std::complex<double>>( name, readIn ); } + +Variable<std::complex<long double>>* BPFileReader::InquireVariableCLDouble( const std::string name, const bool readIn ) +{ return InquireVariableCommon<std::complex<long double>>( name, readIn ); } + +VariableCompound* BPFileReader::InquireVariableCompound( const std::string name, const bool readIn ) +{ return nullptr; } + + +void BPFileReader::Close( const int transportIndex ) +{ + +} + + +//PRIVATE +void BPFileReader::Init( ) +{ + if( m_DebugMode == true ) + { + if( m_AccessMode != "r" && m_AccessMode != "read" ) + throw std::invalid_argument( "ERROR: BPFileReader doesn't support access mode " + m_AccessMode + + ", in call to ADIOS Open or BPFileReader constructor\n" ); + } + + InitCapsules( ); + InitTransports( ); +} + + +void BPFileReader::InitCapsules( ) +{ + //here init memory capsules +} + + +void BPFileReader::InitTransports( ) //maybe move this? +{ + if( m_DebugMode == true ) + { + if( TransportNamesUniqueness( ) == false ) + { + throw std::invalid_argument( "ERROR: two transports of the same kind (e.g file IO) " + "can't have the same name, modify with name= in Method AddTransport\n" ); + } + } + + for( const auto& parameters : m_Method.m_TransportParameters ) + { + auto itTransport = parameters.find( "transport" ); + if( itTransport->second == "file" || itTransport->second == "File" ) + { + auto itLibrary = parameters.find( "library" ); + if( itLibrary == parameters.end() || itLibrary->second == "POSIX" ) //use default POSIX + { + auto file = std::make_shared<transport::FileDescriptor>( m_MPIComm, m_DebugMode ); + //m_BP1Reader.OpenRankFiles( m_Name, m_AccessMode, *file ); + m_Transports.push_back( std::move( file ) ); + } + else if( itLibrary->second == "FILE*" || itLibrary->second == "stdio.h" ) + { + auto file = std::make_shared<transport::FilePointer>( m_MPIComm, m_DebugMode ); + //m_BP1Reader.OpenRankFiles( m_Name, m_AccessMode, *file ); + m_Transports.push_back( std::move( file ) ); + + } + else if( itLibrary->second == "fstream" || itLibrary->second == "std::fstream" ) + { + auto file = std::make_shared<transport::FStream>( m_MPIComm, m_DebugMode ); + //m_BP1Reader.OpenRankFiles( m_Name, m_AccessMode, *file ); + m_Transports.push_back( std::move( file ) ); + } + else if( itLibrary->second == "MPI-IO" ) + { + + } + else + { + if( m_DebugMode == true ) + throw std::invalid_argument( "ERROR: file transport library " + itLibrary->second + " not supported, in " + + m_Name + m_EndMessage ); + } + } + else + { + if( m_DebugMode == true ) + throw std::invalid_argument( "ERROR: transport " + itTransport->second + " (you mean File?) not supported, in " + + m_Name + m_EndMessage ); + } + } +} + + +} //end namespace + + diff --git a/src/engine/adios1/ADIOS1Writer.cpp b/src/engine/adios1/ADIOS1Writer.cpp new file mode 100644 index 000000000..0adc032e6 --- /dev/null +++ b/src/engine/adios1/ADIOS1Writer.cpp @@ -0,0 +1,369 @@ +/* + * ADIOS1Writer.cpp + * Class to write files using old adios 1.x library. + * It requires adios 1.x installed + * + * Created on: Mar 27, 2017 + * Author: pnb + */ + +#include "engine/adios1/ADIOS1Writer.h" +#include "ADIOS.h" + +extern int adios_verbose_level; +extern int adios_errno; + +namespace adios +{ + + +ADIOS1Writer::ADIOS1Writer( ADIOS& adios, const std::string name, const std::string accessMode, MPI_Comm mpiComm, + const Method& method, const IOMode iomode, const float timeout_sec, + const bool debugMode, const unsigned int nthreads ): + Engine( adios, "ADIOS1Writer", name, accessMode, mpiComm, method, debugMode, nthreads, " ADIOS1Writer constructor (or call to ADIOS Open).\n" ), + m_groupname{method.m_Name.c_str()}, + m_filename{name.c_str()}, + m_comm{mpiComm} +{ + Init( ); + adios_open( &m_adios_file, m_groupname, m_filename, accessMode.c_str(), m_comm ); + if( adios_errno == err_no_error ) + { + m_IsFileOpen = true; + } +} + + +ADIOS1Writer::~ADIOS1Writer( ) +{ + if (m_IsFileOpen ) + { + adios_close( m_adios_file ); + m_IsFileOpen = false; + } +} + + +void ADIOS1Writer::Init( ) +{ + if( !m_initialized ) + { + adios_init_noxml( m_comm ); + m_initialized = true; + } + adios_declare_group( &m_adios_group, m_groupname, "", adios_stat_default ); + + InitParameters( ); + InitTransports( ); +} + +bool ADIOS1Writer::ReOpenAsNeeded( ) +{ + if( !m_IsFileOpen ) + { + adios_open( &m_adios_file, m_groupname, m_filename, "a", m_comm ); + if( adios_errno == err_no_error ) + { + m_IsFileOpen = true; + adios_delete_vardefs( m_adios_group ); + } + } + return m_IsFileOpen; +} + +void ADIOS1Writer::DefineVariable ( std::string name, bool isScalar, enum ADIOS_DATATYPES vartype, + std::string ldims, std::string gdims, std::string offs ) +{ + if( isScalar ) + { + adios_define_var( m_adios_group, name.c_str(), "", vartype, "", "", "" ); + } + else + { + adios_define_var( m_adios_group, name.c_str(), "", vartype, ldims.c_str(), gdims.c_str(), offs.c_str()); + } +} + +void ADIOS1Writer::WriteVariable ( std::string name, bool isScalar, enum ADIOS_DATATYPES vartype, + std::string ldims, std::string gdims, std::string offs, const void * values ) +{ + if( ReOpenAsNeeded() ) + { + DefineVariable( name, isScalar, vartype, ldims, gdims, offs ); + adios_write( m_adios_file, name.c_str(), values ); + } +} + + +void ADIOS1Writer::Write( Variable<char>& variable, const char* values ) +{ + WriteVariable( variable.m_Name, variable.m_IsScalar, adios_byte, + variable.GetDimensionAsString(), variable.GetGlobalDimensionAsString(), variable.GetOffsetsAsString(), + values); +} + +void ADIOS1Writer::Write( Variable<unsigned char>& variable, const unsigned char* values ) +{ + WriteVariable( variable.m_Name, variable.m_IsScalar, adios_unsigned_byte, + variable.GetDimensionAsString(), variable.GetGlobalDimensionAsString(), variable.GetOffsetsAsString(), + values); +} + +void ADIOS1Writer::Write( Variable<short>& variable, const short* values ) +{ + WriteVariable( variable.m_Name, variable.m_IsScalar, adios_short, + variable.GetDimensionAsString(), variable.GetGlobalDimensionAsString(), variable.GetOffsetsAsString(), + values); +} + +void ADIOS1Writer::Write( Variable<unsigned short>& variable, const unsigned short* values ) +{ + WriteVariable( variable.m_Name, variable.m_IsScalar, adios_unsigned_short, + variable.GetDimensionAsString(), variable.GetGlobalDimensionAsString(), variable.GetOffsetsAsString(), + values); +} + +void ADIOS1Writer::Write( Variable<int>& variable, const int* values ) +{ + WriteVariable( variable.m_Name, variable.m_IsScalar, adios_integer, + variable.GetDimensionAsString(), variable.GetGlobalDimensionAsString(), variable.GetOffsetsAsString(), + values); +} + +void ADIOS1Writer::Write( Variable<unsigned int>& variable, const unsigned int* values ) +{ + WriteVariable( variable.m_Name, variable.m_IsScalar, adios_unsigned_integer, + variable.GetDimensionAsString(), variable.GetGlobalDimensionAsString(), variable.GetOffsetsAsString(), + values); +} + +void ADIOS1Writer::Write( Variable<long int>& variable, const long int* values ) +{ + enum ADIOS_DATATYPES type = adios_integer; // long int is usually 4 bytes which is adios_integer + if( sizeof(long int) == 8 ) + { + type = adios_long; + } + WriteVariable( variable.m_Name, variable.m_IsScalar, type, + variable.GetDimensionAsString(), variable.GetGlobalDimensionAsString(), variable.GetOffsetsAsString(), + values); +} + +void ADIOS1Writer::Write( Variable<unsigned long int>& variable, const unsigned long int* values ) +{ + enum ADIOS_DATATYPES type = adios_unsigned_integer; // long int is usually 4 bytes + if( sizeof(long int) == 8 ) + { + type = adios_unsigned_long; + } + WriteVariable( variable.m_Name, variable.m_IsScalar, type, + variable.GetDimensionAsString(), variable.GetGlobalDimensionAsString(), variable.GetOffsetsAsString(), + values); +} + +void ADIOS1Writer::Write( Variable<long long int>& variable, const long long int* values ) +{ + WriteVariable( variable.m_Name, variable.m_IsScalar, adios_long, + variable.GetDimensionAsString(), variable.GetGlobalDimensionAsString(), variable.GetOffsetsAsString(), + values); +} + +void ADIOS1Writer::Write( Variable<unsigned long long int>& variable, const unsigned long long int* values ) +{ + WriteVariable( variable.m_Name, variable.m_IsScalar, adios_unsigned_long, + variable.GetDimensionAsString(), variable.GetGlobalDimensionAsString(), variable.GetOffsetsAsString(), + values); +} + +void ADIOS1Writer::Write( Variable<float>& variable, const float* values ) +{ + WriteVariable( variable.m_Name, variable.m_IsScalar, adios_real, + variable.GetDimensionAsString(), variable.GetGlobalDimensionAsString(), variable.GetOffsetsAsString(), + values); +} + +void ADIOS1Writer::Write( Variable<double>& variable, const double* values ) +{ + WriteVariable( variable.m_Name, variable.m_IsScalar, adios_double, + variable.GetDimensionAsString(), variable.GetGlobalDimensionAsString(), variable.GetOffsetsAsString(), + values); +} + +void ADIOS1Writer::Write( Variable<long double>& variable, const long double* values ) +{ + /* TODO: This is faulty: adios_long_double expects 16 bytes per elements, but long double is compiler dependent */ + WriteVariable( variable.m_Name, variable.m_IsScalar, adios_long_double, + variable.GetDimensionAsString(), variable.GetGlobalDimensionAsString(), variable.GetOffsetsAsString(), + values); +} + +void ADIOS1Writer::Write( Variable<std::complex<float>>& variable, const std::complex<float>* values ) +{ + WriteVariable( variable.m_Name, variable.m_IsScalar, adios_complex, + variable.GetDimensionAsString(), variable.GetGlobalDimensionAsString(), variable.GetOffsetsAsString(), + values); +} + +void ADIOS1Writer::Write( Variable<std::complex<double>>& variable, const std::complex<double>* values ) +{ + WriteVariable( variable.m_Name, variable.m_IsScalar, adios_double_complex, + variable.GetDimensionAsString(), variable.GetGlobalDimensionAsString(), variable.GetOffsetsAsString(), + values); +} + +void ADIOS1Writer::Write( Variable<std::complex<long double>>& variable, const std::complex<long double>* values ) +{ + throw std::invalid_argument( "ERROR: Adios 1.x does not support complex<long double> type, so it cannot write variable " + + variable.m_Name + "\n"); +} + +void ADIOS1Writer::Write( VariableCompound& variable, const void* values ) +{ + throw std::invalid_argument( "ERROR: Adios 1.x does not support compound types, so it cannot write variable " + + variable.m_Name + "\n"); +} + +//String version +void ADIOS1Writer::Write( const std::string variableName, const char* values ) +{ Write( m_ADIOS.GetVariable<char>( variableName ), values ); } + +void ADIOS1Writer::Write( const std::string variableName, const unsigned char* values ) +{ Write( m_ADIOS.GetVariable<unsigned char>( variableName ), values ); } + +void ADIOS1Writer::Write( const std::string variableName, const short* values ) +{ Write( m_ADIOS.GetVariable<short>( variableName ), values ); } + +void ADIOS1Writer::Write( const std::string variableName, const unsigned short* values ) +{ Write( m_ADIOS.GetVariable<unsigned short>( variableName ), values ); } + +void ADIOS1Writer::Write( const std::string variableName, const int* values ) +{ Write( m_ADIOS.GetVariable<int>( variableName ), values ); } + +void ADIOS1Writer::Write( const std::string variableName, const unsigned int* values ) +{ Write( m_ADIOS.GetVariable<unsigned int>( variableName ), values ); } + +void ADIOS1Writer::Write( const std::string variableName, const long int* values ) +{ Write( m_ADIOS.GetVariable<long int>( variableName ), values ); } + +void ADIOS1Writer::Write( const std::string variableName, const unsigned long int* values ) +{ Write( m_ADIOS.GetVariable<unsigned long int>( variableName ), values ); } + +void ADIOS1Writer::Write( const std::string variableName, const long long int* values ) +{ Write( m_ADIOS.GetVariable<long long int>( variableName ), values ); } + +void ADIOS1Writer::Write( const std::string variableName, const unsigned long long int* values ) +{ Write( m_ADIOS.GetVariable<unsigned long long int>( variableName ), values ); } + +void ADIOS1Writer::Write( const std::string variableName, const float* values ) +{ Write( m_ADIOS.GetVariable<float>( variableName ), values ); } + +void ADIOS1Writer::Write( const std::string variableName, const double* values ) +{ Write( m_ADIOS.GetVariable<double>( variableName ), values ); } + +void ADIOS1Writer::Write( const std::string variableName, const long double* values ) +{ Write( m_ADIOS.GetVariable<long double>( variableName ), values ); } + +void ADIOS1Writer::Write( const std::string variableName, const std::complex<float>* values ) +{ Write( m_ADIOS.GetVariable<std::complex<float>>( variableName ), values ); } + +void ADIOS1Writer::Write( const std::string variableName, const std::complex<double>* values ) +{ Write( m_ADIOS.GetVariable<std::complex<double>>( variableName ), values ); } + +void ADIOS1Writer::Write( const std::string variableName, const std::complex<long double>* values ) +{ Write( m_ADIOS.GetVariable<std::complex<long double>>( variableName ), values ); } + +void ADIOS1Writer::Write( const std::string variableName, const void* values ) //Compound type +{ + throw std::invalid_argument( "ERROR: Adios 1.x does not support compound types, so it cannot write variable " + + variableName + "\n"); +} + + +void ADIOS1Writer::Advance( ) +{ + if (m_IsFileOpen ) + { + adios_close( m_adios_file ); + m_IsFileOpen = false; + } +} + + +void ADIOS1Writer::Close( const int transportIndex ) +{ + if (m_IsFileOpen ) + { + adios_close( m_adios_file ); + m_IsFileOpen = false; + } +} + + +//PRIVATE FUNCTIONS +void ADIOS1Writer::InitParameters( ) +{ + auto itMaxBufferSize = m_Method.m_Parameters.find( "max_size_MB" ); + if( itMaxBufferSize != m_Method.m_Parameters.end() ) + { + adios_set_max_buffer_size( std::stoul( itMaxBufferSize->second ) ); + } + + auto itVerbosity = m_Method.m_Parameters.find( "verbose" ); + if( itVerbosity != m_Method.m_Parameters.end() ) + { + int verbosity = std::stoi( itVerbosity->second ); + if( m_DebugMode == true ) + { + if( verbosity < 0 || verbosity > 5 ) + throw std::invalid_argument( "ERROR: Method verbose argument must be an integer in the range [0,5], in call to Open or Engine constructor\n" ); + } + adios_verbose_level = verbosity; + } +} + + +void ADIOS1Writer::InitTransports( ) +{ + if( m_DebugMode == true ) + { + if( TransportNamesUniqueness( ) == false ) + { + throw std::invalid_argument( "ERROR: two transports of the same kind (e.g file IO) " + "can't have the same name, modify with name= in Method AddTransport\n" ); + } + } + + for( const auto& parameters : m_Method.m_TransportParameters ) + { + auto itTransport = parameters.find( "transport" ); + + if( itTransport->second == "file" || itTransport->second == "File" ) + { + auto itLibrary = parameters.find( "library" ); + if( itLibrary == parameters.end() || itLibrary->second == "POSIX" ) //use default POSIX + { + adios_select_method( m_adios_group, "POSIX", "", "" ); + } + else if( itLibrary->second == "MPI_File" || itLibrary->second == "MPI-IO" ) + { + adios_select_method( m_adios_group, "MPI", "", "" ); + } + else + { + if( m_DebugMode == true ) + throw std::invalid_argument( "ERROR: file transport library " + itLibrary->second + " not supported, in " + + m_Name + m_EndMessage ); + } + } + else + { + if( m_DebugMode == true ) + throw std::invalid_argument( "ERROR: transport " + itTransport->second + " (you mean File?) not supported, in " + + m_Name + m_EndMessage ); + } + } +} + + + +} //end namespace adios -- GitLab