diff --git a/bindings/python/ADIOSPy.cpp b/bindings/python/ADIOSPy.cpp index a64b2d8a281d572df963e604d4ef832a63448391..c7d161221a7b91bfbfad7e7957be707de8bb7a14 100644 --- a/bindings/python/ADIOSPy.cpp +++ b/bindings/python/ADIOSPy.cpp @@ -12,15 +12,30 @@ #include "adiosPyTypes.h" +#include "adios2/ADIOSMPI.h" + namespace adios { -ADIOSPy::ADIOSPy(MPI_Comm mpiComm, const bool debug) -: m_DebugMode(debug), m_ADIOS(mpiComm, debug) +ADIOSPy::ADIOSPy(const std::string configFile, MPI_Comm mpiComm, + const bool debugMode) +: m_DebugMode(debugMode), m_ADIOS(configFile, mpiComm, debugMode) { } -ADIOSPy::ADIOSPy(const bool debug) : m_DebugMode(debug), m_ADIOS(debug) {} +ADIOSPy::ADIOSPy(MPI_Comm mpiComm, const bool debugMode) +: ADIOSPy("", mpiComm, debugMode) +{ +} + +ADIOSPy::ADIOSPy(const std::string configFile, const bool debugMode) +: ADIOSPy("", MPI_COMM_SELF, debugMode) +{ +} + +ADIOSPy::ADIOSPy(const bool debugMode) : ADIOSPy("", MPI_COMM_SELF, debugMode) +{ +} IOPy ADIOSPy::DeclareIO(const std::string name) { diff --git a/bindings/python/ADIOSPy.h b/bindings/python/ADIOSPy.h index d8cc68c9e453ebd5d840c07b369c75e3cf98107a..e1ed1f0e1964f600f87d229cadf55ae2b9acabf6 100644 --- a/bindings/python/ADIOSPy.h +++ b/bindings/python/ADIOSPy.h @@ -18,6 +18,7 @@ #include <adios2.h> #include "IOPy.h" +#include "adios2/ADIOSMPICommOnly.h" namespace adios { @@ -26,8 +27,11 @@ class ADIOSPy { public: - ADIOSPy(MPI_Comm mpiComm, const bool debug); - ADIOSPy(const bool debug); + ADIOSPy(const std::string configFile, MPI_Comm mpiComm, + const bool debugMode); + ADIOSPy(MPI_Comm mpiComm, const bool debugMode); + ADIOSPy(const std::string configFile, const bool debugMode); + ADIOSPy(const bool debugMode); ~ADIOSPy() = default; IOPy DeclareIO(const std::string name); diff --git a/bindings/python/gluePyBind11.cpp b/bindings/python/gluePyBind11.cpp index a257180426b998d9537b878bc836ffa97f9960dd..358d3778193bde08867ce9027f5de5afc858c9e8 100644 --- a/bindings/python/gluePyBind11.cpp +++ b/bindings/python/gluePyBind11.cpp @@ -25,6 +25,26 @@ #include "adiosPyTypes.h" #ifdef ADIOS2_HAVE_MPI +adios::ADIOSPy ADIOSPyInitConfig(const std::string configFile, + adios::pyObject &object, const bool debugMode) +{ + MPI_Comm *mpiCommPtr = PyMPIComm_Get(object.ptr()); + + if (import_mpi4py() < 0) + { + throw std::runtime_error("ERROR: could not import mpi4py " + "communicator, in call to ADIOS " + "constructor\n"); + } + + if (mpiCommPtr == nullptr) + { + throw std::runtime_error("ERROR: mpi4py communicator is null, in call " + "to ADIOS constructor\n"); + } + return adios::ADIOSPy(configFile, *mpiCommPtr, debugMode); +} + adios::ADIOSPy ADIOSPyInit(adios::pyObject &object, const bool debugMode) { MPI_Comm *mpiCommPtr = PyMPIComm_Get(object.ptr()); @@ -44,6 +64,12 @@ adios::ADIOSPy ADIOSPyInit(adios::pyObject &object, const bool debugMode) return adios::ADIOSPy(*mpiCommPtr, debugMode); } #else +adios::ADIOSPy ADIOSPyInitConfig(const std::string configFile, + const bool debugMode) +{ + return adios::ADIOSPy(debugMode); +} + adios::ADIOSPy ADIOSPyInit(const bool debugMode) { return adios::ADIOSPy(debugMode); @@ -69,6 +95,8 @@ PYBIND11_PLUGIN(adios2) m.attr("OpenModeAppend") = static_cast<int>(adios::OpenMode::Append); m.attr("OpenModeReadWrite") = static_cast<int>(adios::OpenMode::ReadWrite); m.def("ADIOS", &ADIOSPyInit, "Function that creates an ADIOS class object"); + m.def("ADIOS", &ADIOSPyInitConfig, + "Function that creates an ADIOS class object using a config file"); pybind11::class_<adios::ADIOSPy>(m, "ADIOSPy") .def("DeclareIO", &adios::ADIOSPy::DeclareIO); diff --git a/examples/experimental/runtimeconfig/grandSchema.xml b/examples/experimental/runtimeconfig/grandSchema.xml new file mode 100644 index 0000000000000000000000000000000000000000..71d80bd30be8c3aff11cb1adf55e28493a71fb6d --- /dev/null +++ b/examples/experimental/runtimeconfig/grandSchema.xml @@ -0,0 +1,76 @@ +<?xml version="1.0"?> +<adios-config> + + <io name="Output"> + + <var name="myArray"> <!-- provide a sequence of transforms --> + <transform type='BZip2'> <!-- not implemented yet --> + BlockSize100K=3; <!-- must be a number between 0 and 9--> + </transform> + <transform type="Zfp"> <!-- not implemented yet, mutually exclusive options --> + Tolerance=1e-3; <!-- must be a number between 0 and 9--> + <!-- Rate=1; --> <!-- must be a number between 0 and 9--> + <!-- Precision=1; --> <!-- must be a number between 0 and 9--> + </transform> + </var> + + <engine type="BPSuperEngine"> + Threads=4; <!-- for memory operations and asynchronous tasks --> + Verbose=4; <!-- 0 (default) to 5, not implemented --> + ProfileUnits=Microseconds; <!-- Microseconds (default), Milliseconds, Seconds, Minutes, Hours --> + MaxBufferSize=20Mb; <!-- XXKb, XXMb, or XXXGb supported, 16Mb (default should depend on system) --> + InitialBufferSize=1Mb; <!-- XXKb, XXMb, or XXXGb supported, 16Kb (default shoudl depende on system) --> + BufferGrowthFactor=2; <!-- exponential growth factor > 1, 1.5 (default), for this case: 1, 2, 4, 8, 16, 20 Mb--> + </engine> + + <transport type="File"> + ProfileUnits=Microseconds; <!-- Microseconds, Milliseconds, Seconds, Minutes, Hours --> + Library=stdio; <!-- lowest level IO library, POSIX (default), stdio (C FILE*), fstream (C++), and interop: hdf5, netcdf? --> + CacheSize=8192; <!-- not to be confused with ADIOS heap buffer, this is the low-level setvbuffer, putsetbuf, default is 8192 bytes in most systems --> + CollectiveMetadata=Yes; <!-- this transport requires a collective/global metadata at the end, default = no --> + </transport> + + <transport type="File"> + ProfileUnits=Microseconds; <!-- Microseconds, Milliseconds, Seconds, Minutes, Hours --> + Library=hdf5; <!-- lowest level IO library, POSIX (default), stdio (C FILE*), fstream (C++), and interop: hdf5, netcdf? --> + Name=data.h5; <!-- Mandatory if more than one File transport to avoid conflict --> + </transport> + + <transport type="SharedMemory"> + ProfileUnits=Microseconds; <!-- Microseconds, Milliseconds, Seconds, Minutes, Hours --> + Library=SystemV; <!-- lowest level shared memory library: SystemV (default), Boost (interprocess), IPC (POSIX), IPCMMap (POSIX) --> + Name=data.shmem; <!-- Mandatory to create process key --> + SetSize=10Mb; <!-- Mandatory and fixed size (can't be extended) --> + </transport> + + <transport type="NVRAM"> + ProfileUnits=Microseconds; <!-- Microseconds, Milliseconds, Seconds, Minutes, Hours --> + Library=POSIX; <!-- lowest level library --> + Name=/bb_location/data.bb; <!-- Mandatory --> + SetSize=10Mb; <!-- Mandatory and fixed size (can't be extended) --> + </transport> + + <transport type="WAN"> + ProfileUnits=Microseconds; <!-- Microseconds, Milliseconds, Seconds, Minutes, Hours --> + IPAddress=128.219.4.85; <!-- Mandatory --> + Port=500; <!-- Default=500? --> + Library=zmq; <!-- lowest level IO library, zmq, UDP, etc. --> + CacheSize=8192; <!-- not to be confused with ADIOS heap buffer, this is transport library cache, always in bytes --> + </transport> + + <transport type="RDMA"> <!-- Staging gets more complex depending on library requirements--> + ProfileUnits=Microseconds; <!-- Microseconds, Milliseconds, Seconds, Minutes, Hours --> + Library=ibverbs; <!-- SST (default), Flexpath, Dataspaces, ibverbs --> + Port=18515; <!-- ibverbs --> + IBPort=1; <!-- ibverbs --> + SetSize=1Mb; <!-- Mandatory and fixed size (can't be extended) --> + TXDepth=100; <!-- ibverbs --> + SocketFD=-1; <!-- ibverbs --> + ServerName=NULL; <!-- ibverbs --> + RemoteConnection=NULL; <!-- ibverbs --> + IBDev=NULL; <!-- ibverbs --> + </transport> + + </io> + +</adios-config> \ No newline at end of file diff --git a/examples/experimental/runtimeconfig/multipleIOResolutions.xml b/examples/experimental/runtimeconfig/multipleIOResolutions.xml new file mode 100644 index 0000000000000000000000000000000000000000..28fe854084bc7e8126f68f2a3b70aa65b7dfc6af --- /dev/null +++ b/examples/experimental/runtimeconfig/multipleIOResolutions.xml @@ -0,0 +1,24 @@ +<?xml version="1.0"?> +<adios-config> + + <io name="LowResolution"> + <var name="myArray"> <!-- provide a sequence of transforms --> + <transform type="Zfp"> <!-- not implemented yet, mutually exclusive options --> + Tolerance=1e-2; <!-- must be a number between 0 and 9--> + <!-- Rate=1; --> <!-- must be a number between 0 and 9--> + <!-- Precision=1; --> <!-- must be a number between 0 and 9--> + </transform> + </var> + </io> + + <io name="HighResolution"> + <var name="myArray"> <!-- provide a sequence of transforms --> + <transform type="Zfp"> <!-- not implemented yet, mutually exclusive options --> + Tolerance=1e-5; <!-- must be a number between 0 and 9--> + <!-- Rate=1; --> <!-- must be a number between 0 and 9--> + <!-- Precision=1; --> <!-- must be a number between 0 and 9--> + </transform> + </var> + </io> + +</adios-config> \ No newline at end of file diff --git a/examples/experimental/runtimeconfig/multipleTransformedVariables.xml b/examples/experimental/runtimeconfig/multipleTransformedVariables.xml new file mode 100644 index 0000000000000000000000000000000000000000..8338320d5ce13b1fd8cd5be57c639d52ff58fb5e --- /dev/null +++ b/examples/experimental/runtimeconfig/multipleTransformedVariables.xml @@ -0,0 +1,26 @@ +<?xml version="1.0"?> +<adios-config> + + <io name="LowResolution"> + <transform type="Zfp"> <!-- not implemented yet, mutually exclusive options --> + Tolerance=1e-2; <!-- must be a number between 0 and 9 --> + <!-- Rate=1; --> <!-- must be a number between 0 and 9 --> + <!-- Precision=1; --> <!-- must be a number between 0 and 9 --> + <variable name="myArray1"></variable> + <variable name="myArray2"></variable> + <variable name="myArray3"></variable> + </transform> + </io> + + <io name="HighResolution"> + <transform type="Zfp"> <!-- not implemented yet, mutually exclusive options --> + Tolerance=1e-5; <!-- must be a number between 0 and 9 --> + <!-- Rate=1; --> <!-- must be a number between 0 and 9 --> + <!-- Precision=1; --> <!-- must be a number between 0 and 9 --> + <variable name="myArray1"></variable> + <variable name="myArray2"></variable> + <variable name="myArray3"></variable> + </transform> + </io> + +</adios-config> diff --git a/examples/hello/bpWriter/CMakeLists.txt b/examples/hello/bpWriter/CMakeLists.txt index a3d4cd35a3f9ffd3e32239d26fbda027e69ca8b1..c5707cdf0ed9b9ac1d0de36b7bd77b20f70d9c6f 100644 --- a/examples/hello/bpWriter/CMakeLists.txt +++ b/examples/hello/bpWriter/CMakeLists.txt @@ -9,7 +9,16 @@ if(ADIOS2_HAVE_MPI) add_executable(hello_bpWriter helloBPWriter.cpp) target_include_directories(hello_bpWriter PRIVATE ${MPI_C_INCLUDE_PATH}) target_link_libraries(hello_bpWriter ${MPI_C_LIBRARIES}) + + add_executable(hello_bpWriterXML helloBPWriterXML.cpp) + target_include_directories(hello_bpWriterXML PRIVATE ${MPI_C_INCLUDE_PATH}) + target_link_libraries(hello_bpWriterXML ${MPI_C_LIBRARIES}) + else() add_executable(hello_bpWriter helloBPWriter_nompi.cpp) + add_executable(hello_bpWriterXML helloBPWriterXML_nompi.cpp) + endif() + +target_link_libraries(hello_bpWriterXML adios2) target_link_libraries(hello_bpWriter adios2) diff --git a/examples/hello/bpWriter/config.xml b/examples/hello/bpWriter/config.xml deleted file mode 100644 index 10dfa830e33baed86ec3c2667f0bd6b67b2c8aa1..0000000000000000000000000000000000000000 --- a/examples/hello/bpWriter/config.xml +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0"?> -<adios-config> - - <io name="Output"> - <engine name="BPFileWriter">verbose=4;profile_units=mus</engine> - <transport name= "File"> - profile_units=mus; - abort_on_error; - have_metadata_file - = - no; - </transport> - - <!-- Create a named transform and add variables to it here. - name is optional, required only if it is used outside the definition - options is optional to pass parameters to the transformation - --> - <transform name="LossyCompression" transform="zfp" options="accuracy=0.001"> - <var name="myMatrix"/> - <var name="ThisVarDoesNotExists"/> - </transform> - - <!-- Unnamed transformation --> - <transform transform="bzip2"> - <var name="myMatrix2"/> - </transform> - - <!-- A variable can have its own private transform definition. - Also its own ordered chain of transformations. - Also can refer to a transform defined previously - --> - <var name="myDoubles"> - <transform transform="identity">verbose=DEBUG</transform> - <transform name="LossyCompression"/> - </var> - - <buffer max-size-MB="20"/> - </io> - -</adios-config> - diff --git a/examples/hello/bpWriter/helloBPWriter.py b/examples/hello/bpWriter/helloBPWriter.py index 780507684e067c519173210be2e3f8a855a67082..7332f5e7333b159d00187035f4d3911c239a3f53 100644 --- a/examples/hello/bpWriter/helloBPWriter.py +++ b/examples/hello/bpWriter/helloBPWriter.py @@ -1,32 +1,35 @@ -# clang-format off # # Distributed under the OSI-approved Apache License, Version 2.0. See # accompanying file Copyright.txt for details. # -# test_hello.py +# helloBPWriter.py # Created on: Feb 2, 2017 # Author: William F Godoy godoywf@ornl.gov from mpi4py import MPI +import numpy import adios2 -import numpy as np + +# MPI +comm = MPI.COMM_WORLD +rank = comm.Get_rank() +size = comm.Get_size() # User data -myArray = np.array([1., 2., 3., 4., 5., 6.]) +myArray = numpy.array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]) +Nx = myArray.size -# ADIOS -adios = adios2.ADIOS(MPI.COMM_WORLD, adios2.DebugON) +# ADIOS MPI Communicator, debug mode +adios = adios2.ADIOS(comm, adios2.DebugON) -# IO -bpIO = adios.DeclareIO("BPN2N") +# ADIOS IO +bpIO = adios.DeclareIO("BPFile_N2N") -# Variable +# ADIOS Variable name, shape, start, offset, constant dims ioArray = bpIO.DefineVariable( - "bpArray", [myArray.size], [0], [myArray.size], adios2.ConstantDims) + "bpArray", [size * Nx], [rank * Nx], [Nx], adios2.ConstantDims) -# Engine -bpFileWriter = bpIO.Open("myArray.bp", adios2.OpenModeWrite) -# bpFileWriter = bpIO.Open("myArray.bp", adiosOpenModeWrite, -# MPI.COMM_WORLD) //doesn't work +# ADIOS Engine +bpFileWriter = bpIO.Open("npArray.bp", adios2.OpenModeWrite) bpFileWriter.Write(ioArray, myArray) bpFileWriter.Close() diff --git a/examples/hello/bpWriter/helloBPWriter.xml b/examples/hello/bpWriter/helloBPWriter.xml new file mode 100644 index 0000000000000000000000000000000000000000..bda56e4c18b67f1c4a68d0558c470b80e8c9b616 --- /dev/null +++ b/examples/hello/bpWriter/helloBPWriter.xml @@ -0,0 +1,20 @@ +<?xml version="1.0"?> +<adios-config> + + <io name="BPFile_N2N"> + <engine type="BPFileWriter"> + Threads=1; <!-- for vectorized memory operations and asynchronous tasks --> + ProfileUnits=Microseconds; <!-- Microseconds (default), Milliseconds, Seconds, Minutes, Hours --> + MaxBufferSize=20Mb; <!-- XXKb, XXMb, or XXXGb supported, 16Mb (default should depend on system) --> + InitialBufferSize=1Mb; <!-- XXKb, XXMb, or XXXGb supported, 16Kb (default should depend on system) --> + BufferGrowthFactor=2; <!-- exponential growth factor > 1, 1.5 (default, e.g. STL default=2), for this case: 1, 2, 4, 8, 16, 20 Mb--> + </engine> + + <transport type="File"> + Library=POSIX; + ProfileUnits=Milliseconds; + </transport> + + </io> + +</adios-config> \ No newline at end of file diff --git a/examples/hello/bpWriter/helloBPWriterXML.cpp b/examples/hello/bpWriter/helloBPWriterXML.cpp new file mode 100644 index 0000000000000000000000000000000000000000..807b0c9c32f948dc2aebe694fdd194664eef8653 --- /dev/null +++ b/examples/hello/bpWriter/helloBPWriterXML.cpp @@ -0,0 +1,82 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * helloBPWriter.cpp: Simple self-descriptive example of how to write a variable + * to a BP File that lives in several MPI processes. + * + * Created on: Feb 16, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include <ios> //std::ios_base::failure +#include <iostream> //std::cout +#include <mpi.h> +#include <stdexcept> //std::invalid_argument std::exception +#include <vector> + +#include <adios2.h> + +int main(int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + /** Application variable */ + std::vector<float> myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + const std::size_t Nx = myFloats.size(); + + try + { + /** ADIOS class factory of IO class objects, DebugON is recommended */ + adios::ADIOS adios("helloBPWriter.xml", MPI_COMM_WORLD, adios::DebugON); + + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios::IO &bpIO = adios.DeclareIO("BPFile_N2N"); + + /** global array : name, { shape (total) }, { start (local) }, { count + * (local) }, all are constant dimensions */ + adios::Variable<float> &bpFloats = bpIO.DefineVariable<float>( + "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios::ConstantDims); + + /** Engine derived class, spawned to start IO operations */ + auto bpWriter = bpIO.Open("myVector.bp", adios::OpenMode::Write); + + if (!bpWriter) + { + throw std::ios_base::failure( + "ERROR: bpWriter not created at Open\n"); + } + + /** Write variable for buffering */ + bpWriter->Write<float>(bpFloats, myFloats.data()); + + /** Create bp file, engine becomes unreachable after this*/ + bpWriter->Close(); + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout + << "IO System base failure exception, STOPPING PROGRAM from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + } + + MPI_Finalize(); + + return 0; +} diff --git a/examples/hello/bpWriter/helloBPWriterXML.py b/examples/hello/bpWriter/helloBPWriterXML.py new file mode 100644 index 0000000000000000000000000000000000000000..2d81dd0bd990693198d92fed91eca035e3b81548 --- /dev/null +++ b/examples/hello/bpWriter/helloBPWriterXML.py @@ -0,0 +1,36 @@ +# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +# +# helloBPWriterXML.py +# Created on: Feb 2, 2017 +# Author: William F Godoy godoywf@ornl.gov + +from mpi4py import MPI +import adios2 +import numpy + +# MPI +comm = MPI.COMM_WORLD +rank = comm.Get_rank() +size = comm.Get_size() + +# User data +myArray = numpy.array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]) +Nx = myArray.size + +# ADIOS config file, MPI communicator, debug mode +adios = adios2.ADIOS("helloBPWriter.xml", comm, adios2.DebugON) + +# ADIOS IO, name must be the same as in helloBPWriter.xml for runtime settings +bpIO = adios.DeclareIO("BPFile_N2N") + +# Variable name, shape, start, count, ConstantDims = True +ioArray = bpIO.DefineVariable( + "bpArray", [size * Nx], [rank * Nx], [Nx], adios2.ConstantDims) + +# Engine name, open mode +bpFileWriter = bpIO.Open("npArray.bp", adios2.OpenModeWrite) +# Write variable, numpy object +bpFileWriter.Write(ioArray, myArray) +bpFileWriter.Close() diff --git a/examples/hello/bpWriter/helloBPWriterXML_nompi.cpp b/examples/hello/bpWriter/helloBPWriterXML_nompi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8028787a699932f8f7c4079f30b5de9c67f61630 --- /dev/null +++ b/examples/hello/bpWriter/helloBPWriterXML_nompi.cpp @@ -0,0 +1,71 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * helloBPWriterXML_nompi.cpp: sequential non-mpi version of helloBPWriterXML + * + * Created on: Feb 16, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include <ios> //std::ios_base::failure +#include <iostream> //std::cout +#include <mpi.h> +#include <stdexcept> //std::invalid_argument std::exception +#include <vector> + +#include <adios2.h> + +int main(int argc, char *argv[]) +{ + /** Application variable */ + std::vector<float> myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + const std::size_t Nx = myFloats.size(); + + try + { + /** ADIOS class factory of IO class objects, DebugON is recommended */ + adios::ADIOS adios("helloBPWriter.xml", adios::DebugON); + + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios::IO &bpIO = adios.DeclareIO("BPFile_N2N"); + + /** global array : name, { shape (total) }, { start (local) }, { count + * (local) }, all are constant dimensions */ + adios::Variable<float> &bpFloats = bpIO.DefineVariable<float>( + "bpFloats", {}, {}, {Nx}, adios::ConstantDims); + + /** Engine derived class, spawned to start IO operations */ + auto bpWriter = bpIO.Open("myVector.bp", adios::OpenMode::Write); + + if (!bpWriter) + { + throw std::ios_base::failure( + "ERROR: bpWriter not created at Open\n"); + } + + /** Write variable for buffering */ + bpWriter->Write<float>(bpFloats, myFloats.data()); + + /** Create bp file, engine becomes unreachable after this*/ + bpWriter->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 << "IO System base failure exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank\n"; + std::cout << e.what() << "\n"; + } + + return 0; +} diff --git a/examples/hello/bpWriter/helloBPWriterXML_nompi.py b/examples/hello/bpWriter/helloBPWriterXML_nompi.py new file mode 100644 index 0000000000000000000000000000000000000000..0373d1e67294ef45e72ff7e1ef04e9f767098da7 --- /dev/null +++ b/examples/hello/bpWriter/helloBPWriterXML_nompi.py @@ -0,0 +1,30 @@ +# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +# +# helloBPWriterXML_nompi.py serial non-MPI version of helloBPWriter.py +# Created on: Feb 2, 2017 +# Author: William F Godoy godoywf@ornl.gov + +import numpy +import adios2 + + +# User data +myArray = numpy.array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]) +Nx = myArray.size + +# ADIOS config file, debug mode +adios = adios2.ADIOS("helloBPWriter.xml", adios2.DebugON) + +# ADIOS IO, name must be the same as in helloBPWriter.xml for runtime settings +bpIO = adios.DeclareIO("BPFile_N2N") + +# ADIOS local array: Variable name, shape, start, offset +ioArray = bpIO.DefineVariable( + "bpArray", [], [], [Nx], adios2.ConstantDims) + +# ADIOS Engine +bpFileWriter = bpIO.Open("npArray.bp", adios2.OpenModeWrite) +bpFileWriter.Write(ioArray, myArray) +bpFileWriter.Close() diff --git a/source/adios2/ADIOSMPI.h b/source/adios2/ADIOSMPI.h index 3524532d34ee3e5b81ef977f6269cf25a813047e..95ae7619aebdb9b32af02a9f6adbd7b2488f06a3 100644 --- a/source/adios2/ADIOSMPI.h +++ b/source/adios2/ADIOSMPI.h @@ -14,4 +14,17 @@ #include "adios2/mpidummy.h" #endif +#include <climits> //UXXX_MAX +#include <cstdint> //SIZE_MAX + +#if SIZE_MAX == UINT_MAX +#define ADIOS2_MPI_SIZE_T MPI_UNSIGNED +#elif SIZE_MAX == ULONG_MAX +#define ADIOS2_MPI_SIZE_T MPI_UNSIGNED_LONG +#elif SIZE_MAX == ULLONG_MAX +#define ADIOS2_MPI_SIZE_T MPI_UNSIGNED_LONG_LONG +#else +#error "size_t could not be mapped to a MPI Type" +#endif + #endif /* ADIOS2_ADIOSMPI_H_ */ diff --git a/source/adios2/core/ADIOS.cpp b/source/adios2/core/ADIOS.cpp index ee373fb869ae75a4d98457b0624646fbfb31af55..194dbdddbf081a4f511cf95c17c632a143fe8c79 100644 --- a/source/adios2/core/ADIOS.cpp +++ b/source/adios2/core/ADIOS.cpp @@ -19,6 +19,7 @@ /// \endcond #include "adios2/ADIOSMPI.h" +#include "adios2/helper/adiosFunctions.h" namespace adios { @@ -31,9 +32,14 @@ ADIOS::ADIOS(const std::string configFile, MPI_Comm mpiComm, { CheckMPI(); } - // XML to be implemented later - // InitXML( m_XMLConfigFile, m_MPIComm, m_DebugMode, m_HostLanguage, - // m_Transforms, m_Groups ); + if (!configFile.empty()) + { + if (configFile.substr(configFile.size() - 3) == "xml") + { + InitXML(configFile, m_MPIComm, m_DebugMode, m_Transforms, m_IOs); + } + // TODO expand for other formats + } } ADIOS::ADIOS(const std::string configFile, const bool debugMode) @@ -56,7 +62,7 @@ IO &ADIOS::DeclareIO(const std::string ioName) { if (m_DebugMode) { - if (itIO->second.InConfigFile()) + if (!itIO->second.InConfigFile()) { throw std::invalid_argument( "ERROR: IO class object with name " + ioName + diff --git a/source/adios2/helper/adiosString.cpp b/source/adios2/helper/adiosString.cpp index 90b6399b131dd8f19b513e6d37236d3d63b3a65d..bc7841276e0f8e0490ac6006134e1d618940919b 100644 --- a/source/adios2/helper/adiosString.cpp +++ b/source/adios2/helper/adiosString.cpp @@ -24,9 +24,9 @@ std::string FileToString(const std::string &fileName) { std::ifstream fileStream(fileName); - if (!fileStream.good()) + if (!fileStream) { - throw std::ios_base::failure( + throw std::invalid_argument( "ERROR: file " + fileName + " could not be opened. Check permissions or existence\n"); } diff --git a/source/adios2/helper/adiosSystem.cpp b/source/adios2/helper/adiosSystem.cpp index 9836130796bb035d886d0d8c60bd334c20748ac5..bc8acdcfbd07366e149c0d79f6aa86d9eba3f2b4 100644 --- a/source/adios2/helper/adiosSystem.cpp +++ b/source/adios2/helper/adiosSystem.cpp @@ -16,7 +16,9 @@ #include <chrono> //system_clock, now #include <ctime> //std::ctime +#include "adios2/ADIOSMPI.h" #include "adios2/ADIOSTypes.h" +#include "adios2/helper/adiosString.h" namespace adios { @@ -77,4 +79,41 @@ std::string LocalTimeDate() noexcept return std::string(std::ctime(&now)); } +std::string BroadcastString(const std::string &input, MPI_Comm mpiComm) +{ + std::string receivedInput; + size_t characterCount = 0; + + int rank; + MPI_Comm_rank(mpiComm, &rank); + + if (rank == 0) // sender + { + characterCount = input.size(); + + // broadcast size for allocation + MPI_Bcast(&characterCount, 1, ADIOS2_MPI_SIZE_T, 0, mpiComm); + + // broadcast contents + MPI_Bcast(const_cast<char *>(input.c_str()), + static_cast<int>(characterCount), MPI_CHAR, 0, mpiComm); + + return input; + } + else // receivers + { + // receive size + MPI_Bcast(&characterCount, 1, ADIOS2_MPI_SIZE_T, 0, mpiComm); + + // allocate receiver + std::vector<char> stringReceiver(characterCount); + MPI_Bcast(stringReceiver.data(), static_cast<int>(characterCount), + MPI_CHAR, 0, mpiComm); + + receivedInput.assign(stringReceiver.begin(), stringReceiver.end()); + } + + return receivedInput; +} + } // end namespace adios diff --git a/source/adios2/helper/adiosSystem.h b/source/adios2/helper/adiosSystem.h index 9374d160370839377b6c4897f3b489fbb850216e..389e095dd838048a5503549abe4fea970dbc0eb4 100644 --- a/source/adios2/helper/adiosSystem.h +++ b/source/adios2/helper/adiosSystem.h @@ -17,6 +17,8 @@ #include <vector> /// \endcond +#include "adios2/ADIOSMPICommOnly.h" + namespace adios { @@ -41,6 +43,15 @@ bool IsLittleEndian() noexcept; */ std::string LocalTimeDate() noexcept; +/** + * Rank 0: opens file, dumps contents string and broadcast. + * Others: receive std::vector<char> and copy to a string + * @param fileName + * @param mpiComm + * @return fileContents as a single string + */ +std::string BroadcastString(const std::string &input, MPI_Comm mpiComm); + } // end namespace adios #endif /* ADIOS2_HELPER_ADIOSSYSTEM_H_ */ diff --git a/source/adios2/helper/adiosXML.cpp b/source/adios2/helper/adiosXML.cpp index 746a436145472b910e58d2dccec7e6adc8b9d363..d52968e1ecfc1e24989269973d320b4a2b1dfb4b 100644 --- a/source/adios2/helper/adiosXML.cpp +++ b/source/adios2/helper/adiosXML.cpp @@ -11,386 +11,457 @@ #include "adiosXML.h" /// \cond EXCLUDE_FROM_DOXYGEN +#include <sstream> #include <stdexcept> //std::invalid_argument /// \endcond +#include "adios2/ADIOSTypes.h" +#include "adios2/helper/adiosString.h" + namespace adios { -void GetSubString(const std::string initialTag, const std::string finalTag, - const std::string content, std::string &subString, - std::string::size_type ¤tPosition) +void RemoveCommentsXML(std::string ¤tContent) noexcept { - auto lf_Wipe = [](std::string &subString, - std::string::size_type ¤tPosition) { - subString.clear(); - currentPosition = std::string::npos; - }; + std::string::size_type startComment(currentContent.find("<!--")); + while (startComment != currentContent.npos) + { + std::string::size_type endComment(currentContent.find("-->")); + currentContent.erase(startComment, endComment - startComment + 3); + startComment = currentContent.find("<!--"); + } +} + +TagXML GetTagXML(const std::string tagName, const std::string &content, + std::string::size_type &position) +{ auto lf_SetPositions = - [](const char quote, const std::string::size_type quotePosition, - const std::string &content, std::string::size_type ¤tPosition, - std::string::size_type &closingQuotePosition) { - currentPosition = quotePosition; - closingQuotePosition = content.find(quote, currentPosition + 1); - }; - - // BODY OF FUNCTION STARTS HERE - std::string::size_type start(content.find(initialTag, currentPosition)); - if (start == content.npos) + [](const std::string input, const std::string &content, + std::string::size_type &position) -> std::string::size_type { + + const std::string::size_type inputPosition = + GetStringPositionXML(input, content, position); + + if (inputPosition != std::string::npos) + { + position = inputPosition + input.size(); + } + return inputPosition; + }; + + TagXML tagXML; + + std::string name(tagName); + if (name.back() == ' ') { - lf_Wipe(subString, currentPosition); - return; + name.pop_back(); } - currentPosition = start; - std::string::size_type end(content.find(finalTag, currentPosition)); - if (end == content.npos) + auto openingStart = lf_SetPositions("<" + name, content, position); + auto openingEnd = lf_SetPositions(">", content, position); + + if (openingStart == std::string::npos || openingEnd == std::string::npos) { - lf_Wipe(subString, currentPosition); - return; + tagXML.IsFull = false; + return tagXML; } - // here make sure the finalTag is not a value surrounded by " " or ' ', if - // so - // find next - bool isValue = true; + tagXML.Header = content.substr(openingStart, openingEnd + 1 - openingStart); + + auto closingStart = + GetStringPositionXML("</" + name + ">", content, position); - while (isValue) + if (closingStart == std::string::npos) { - std::string::size_type singleQuotePosition = - content.find('\'', currentPosition); - std::string::size_type doubleQuotePosition = - content.find('\"', currentPosition); + throw std::invalid_argument( + "ERROR: could not find closing tag </" + name + + "> in XML config file, in call to ADIOS constructor\n"); + } + tagXML.IsFull = true; + tagXML.Elements = + content.substr(openingEnd + 1, closingStart - (openingEnd + 1)); + + // std::cout << "START..." << tagXML.Header << "..."; + // std::cout << tagXML.Elements << "...END\n"; + + return tagXML; +} + +std::string::size_type +GetStringPositionXML(const std::string input, const std::string &content, + const std::string::size_type &startPosition) noexcept +{ + std::string::size_type foundPosition(content.find(input, startPosition)); + if (foundPosition == content.npos) + { + return foundPosition; + } + + // check if it is not inside " " or ' ' + std::string::size_type currentPosition(startPosition); + + while (foundPosition != content.npos) + { + const std::string::size_type singleQuotePosition( + content.find('\'', currentPosition)); + const std::string::size_type doubleQuotePosition( + content.find('\"', currentPosition)); if ((singleQuotePosition == content.npos && doubleQuotePosition == content.npos) || (singleQuotePosition == content.npos && - end < doubleQuotePosition) || + foundPosition < doubleQuotePosition) || (doubleQuotePosition == content.npos && - end < singleQuotePosition) || - (end < singleQuotePosition && end < doubleQuotePosition)) + foundPosition < singleQuotePosition) || + (foundPosition < singleQuotePosition && + foundPosition < doubleQuotePosition)) { break; } - // find the closing corresponding quote std::string::size_type closingQuotePosition; - if (singleQuotePosition == content.npos) - { // no ' anywhere - lf_SetPositions('\"', doubleQuotePosition, content, currentPosition, - closingQuotePosition); + if (singleQuotePosition != content.npos && + doubleQuotePosition == content.npos) + { + currentPosition = singleQuotePosition; + closingQuotePosition = content.find('\'', currentPosition + 1); } - else if (doubleQuotePosition == content.npos) - { // no " anywhere - lf_SetPositions('\'', singleQuotePosition, content, currentPosition, - closingQuotePosition); + else if (singleQuotePosition == content.npos && + doubleQuotePosition != content.npos) + { + currentPosition = doubleQuotePosition; + closingQuotePosition = content.find('\"', currentPosition + 1); } else { if (singleQuotePosition < doubleQuotePosition) { - lf_SetPositions('\'', singleQuotePosition, content, - currentPosition, closingQuotePosition); + currentPosition = singleQuotePosition; + closingQuotePosition = content.find('\'', currentPosition + 1); } else - { // find the closing " - lf_SetPositions('\"', doubleQuotePosition, content, - currentPosition, closingQuotePosition); + { + currentPosition = doubleQuotePosition; + closingQuotePosition = content.find('\"', currentPosition + 1); } } - - if (closingQuotePosition == - content.npos) // if can't find closing it's open until the end + // if can't find closing it's open until the end + if (closingQuotePosition == content.npos) { - lf_Wipe(subString, currentPosition); - return; + currentPosition == content.npos; + break; } currentPosition = closingQuotePosition + 1; - if (closingQuotePosition < end) + if (closingQuotePosition < foundPosition) { continue; } + else + { + // if this point is reached it means it's a value inside " " or ' ', + // iterate + foundPosition = content.find(input, currentPosition); + currentPosition = foundPosition; + } + } + + return foundPosition; +} + +Params GetTagAttributesXML(const std::string &tagHeader) +{ + auto lf_GetQuotedValue = [](const char quote, + const std::string::size_type "ePosition, + std::string ¤tTag) -> std::string { + + currentTag = currentTag.substr(quotePosition + 1); + auto nextQuotePosition = currentTag.find(quote); + + if (nextQuotePosition == currentTag.npos) + { + throw std::invalid_argument( + "ERROR: Invalid attribute in..." + currentTag + + "...check XML file, in call to ADIOS constructor\n"); + } + + const std::string value(currentTag.substr(0, nextQuotePosition)); + currentTag = currentTag.substr(nextQuotePosition + 1); + return value; + }; + + auto lf_GetAttributes = [&](const std::string &tag) -> Params { + Params attributes; + std::string currentTag(tag.substr(tag.find_first_of(" \t\n"))); + + while (currentTag.find('=') != currentTag.npos) // equalPosition + { + currentTag = + currentTag.substr(currentTag.find_first_not_of(" \t\n")); + auto equalPosition = currentTag.find('='); + if (currentTag.size() <= equalPosition + 1) + { + throw std::invalid_argument( + "ERROR: tag " + tag + + " is incomplete, check XML config file, " + "in call to ADIOS constructor\n"); + } + + const std::string key(currentTag.substr(0, equalPosition)); + std::string value; + + const char quote = currentTag[equalPosition + 1]; + if (quote == '\'' || quote == '"') + { + value = lf_GetQuotedValue(quote, equalPosition + 1, currentTag); + } + else + { + // throw exception here? + } + + attributes.emplace(key, value); + } + return attributes; + }; + + // BODY of function starts here + Params attributes; + // eliminate < > + std::string openingTag = tagHeader.substr(1, tagHeader.size() - 2); + + if (tagHeader.back() == '/') // last char is / --> "XML empty tag" + { + // attributes = lf_GetAttributes(openingTag); + // throw exception here, ADIOS2 doesn't allow XML empty tags + } + else if (tagHeader[0] == '/') // first char is / ---> closing tag + { + attributes = lf_GetAttributes(openingTag); + if (attributes.size() > 0) + { + throw std::invalid_argument( + "ERROR: closing tag " + tagHeader + + " can't have attributes, in call to ADIOS constructor\n"); + } + } + else // opening tag + { + attributes = lf_GetAttributes(openingTag); + } + return attributes; +} + +void InitXML(const std::string configXML, const MPI_Comm mpiComm, + const bool debugMode, + std::vector<std::shared_ptr<Transform>> &transforms, + std::map<std::string, IO> &ios) +{ + // independent IO + std::string fileContents(FileToString(configXML)); + RemoveCommentsXML(fileContents); + + // adios-config + std::string::size_type position(0); + const TagXML adiosConfigXML( + GetTagXML("adios-config", fileContents, position)); + + // process transforms, not yet implemented + + while (position != std::string::npos) + { + const TagXML transformXML( + GetTagXML("transform ", adiosConfigXML.Elements, position)); - // if this point is reached it means it's a value inside " " or ' ', - // move to - // the next end - end = content.find(finalTag, currentPosition); + if (transformXML.Header.empty()) + { + break; + } + // InitTransform(transformTag, debugMode, transforms); } - subString = content.substr(start, end - start + finalTag.size()); - currentPosition = end; + position = 0; + // process IOs + while (position != std::string::npos) + { + // io + const TagXML ioXML(GetTagXML("io ", adiosConfigXML.Elements, position)); + + if (ioXML.Header.empty()) // no more groups to find + { + break; + } + InitIOXML(ioXML, mpiComm, debugMode, transforms, ios); + } } -void GetQuotedValue(const char quote, - const std::string::size_type "ePosition, - std::string ¤tTag, std::string &value) +void InitIOXML(const TagXML &ioXML, const MPI_Comm mpiComm, + const bool debugMode, + std::vector<std::shared_ptr<Transform>> &transforms, + std::map<std::string, IO> &ios) { - currentTag = currentTag.substr(quotePosition + 1); - auto nextQuotePosition = currentTag.find(quote); + const Params ioAttributes(GetTagAttributesXML(ioXML.Header)); + + std::string ioName; + for (const auto &ioAttribute : ioAttributes) + { + if (ioAttribute.first == "name") + { + ioName = ioAttribute.second; + } + } + + if (debugMode) + { + if (ioName.empty()) + { + throw std::invalid_argument( + "ERROR: io name=\"value\" attribute not found in opening XML " + "tag " + + ioXML.Header + + ", check XML config file, in call to ADIOS constructor\n"); + } + + if (ios.count(ioName) == 1) // io exists + { + throw std::invalid_argument("ERROR: io name " + ioName + + " must be unique in XML config file, " + "in call to ADIOS constructor\n"); + } + } + + // emplace io with inConfigFile argument as true + auto itIO = ios.emplace(ioName, IO(ioName, mpiComm, true, debugMode)); + + // process engine + std::string::size_type position(0); + + TagXML engineXML(GetTagXML("engine ", ioXML.Elements, position)); + if (!engineXML.Header.empty()) // found first one + { + InitEngineXML(engineXML, debugMode, itIO.first->second); + } - if (nextQuotePosition == currentTag.npos) + if (debugMode) { - throw std::invalid_argument("ERROR: Invalid attribute in..." + - currentTag + "...check XML file\n"); + // try finding a 2nd one from current position + TagXML engineXML(GetTagXML("engine ", ioXML.Elements, position)); + if (!engineXML.Header.empty()) // found first one + { + throw std::invalid_argument( + "ERROR: more than one engine found in <io name=" + ioName + + "...>, only one per io tag is allowed in XML " + "config file, in call to " + "ADIOS constructor\n"); + } } - value = currentTag.substr(0, nextQuotePosition); - currentTag = currentTag.substr(nextQuotePosition + 1); + position = 0; + // process transports + while (position != std::string::npos) + { + TagXML transportXML(GetTagXML("transport", ioXML.Elements, position)); + + if (transportXML.Header.empty()) // no more groups to find + { + break; + } + InitTransportXML(transportXML, debugMode, itIO.first->second); + } } -void GetPairs(const std::string tag, - std::vector<std::pair<const std::string, const std::string>> - &pairs) noexcept +void InitEngineXML(const TagXML &engineXML, const bool debugMode, IO &io) { - std::string currentTag( - tag.substr(tag.find_first_of(" \t\n"))); // initialize current tag + const Params attributes = GetTagAttributesXML(engineXML.Header); - while (currentTag.find('=') != currentTag.npos) // equalPosition + std::string type; + for (const auto &attribute : attributes) { - currentTag = currentTag.substr(currentTag.find_first_not_of(" \t\n")); - auto equalPosition = currentTag.find('='); - const std::string field( - currentTag.substr(0, equalPosition)); // get field - std::string value; - - const char quote = currentTag[equalPosition + 1]; - if (quote == '\'' || quote == '"') // single quotes + if (attribute.first == "type") { - GetQuotedValue(quote, equalPosition + 1, currentTag, value); + type = attribute.second; + break; } + } - pairs.push_back( - std::pair<const std::string, const std::string>(field, value)); + if (!type.empty()) + { + io.SetEngine(type); } + + io.SetParameters(ParseParamsXML(engineXML.Elements, debugMode)); } -void GetPairsFromTag( - const std::string &fileContent, const std::string tag, - std::vector<std::pair<const std::string, const std::string>> &pairs) +void InitTransportXML(const TagXML &transportXML, const bool debugMode, IO &io) { - if (tag.back() == '/') // last char is / --> "XML empty tag" + const Params attributes = GetTagAttributesXML(transportXML.Header); + + std::string type; + for (const auto &attribute : attributes) { - GetPairs(tag, pairs); + if (attribute.first == "type") + { + type = attribute.second; + break; + } } - else if (tag[0] == '/') // first char is / ---> closing tag + + if (type.empty()) { + throw std::invalid_argument( + "ERROR: missing transport type in " + transportXML.Header + + ", in XML config file, in call to ADIOS constructor\n"); } - else // opening tag + + io.AddTransport(type, ParseParamsXML(transportXML.Elements, debugMode)); +} + +Params ParseParamsXML(const std::string &tagElements, const bool debugMode) +{ + auto start = tagElements.find_first_not_of(" \t\n"); + auto end = tagElements.find_last_not_of(" \t\n"); + + std::string parametersString(tagElements.substr(start, end - start + 1)); + if (debugMode) { - const std::string tagName(tag.substr(0, tag.find_first_of(" \t\n\r"))); - const std::string closingTagName("</" + tagName + - ">"); // check for closing tagName + if (parametersString.back() != ';') + { + throw std::invalid_argument( + "ERROR: parameters in config XML file must end with a ; " + + tagElements + ", in call to ADIOS constructor\n"); + } + } + + std::istringstream parametersSS(parametersString); + std::string pair; + + Params parameters; + + while (std::getline(parametersSS, pair, ';')) + { + pair = pair.substr(pair.find_first_not_of(" \t\n")); + auto equalPosition = pair.find("="); - if (fileContent.find(closingTagName) == fileContent.npos) + if (debugMode) { - throw std::invalid_argument("ERROR: closing tag " + closingTagName + - " missing, check XML file\n"); + if (equalPosition == std::string::npos || + equalPosition == pair.size()) + { + throw std::invalid_argument("ERROR: wrong parameter " + pair + + " format is " + "key=value in XML config file, in " + "call to ADIOS constructor\n"); + } } - GetPairs(tag, pairs); + const std::string key(pair.substr(0, equalPosition)); + const std::string value(pair.substr(equalPosition + 1)); + parameters.emplace(key, value); } + return parameters; } -// void SetMembers( const std::string& fileContent, const MPI_Comm mpiComm, -// const bool debugMode, -// std::string& hostLanguage, std::vector< -// std::shared_ptr<Transform> >& transforms, -// std::map< std::string, Group >& groups ) -//{ -// //adios-config -// std::string currentContent; -// std::string::size_type currentPosition( 0 ); -// GetSubString( "<adios-config ", "</adios-config>", fileContent, -// currentContent, currentPosition ); -// -// //remove comment sections -// std::string::size_type startComment ( currentContent.find( "<!--" ) ); -// -// while( startComment != currentContent.npos ) -// { -// std::string::size_type endComment( currentContent.find( "-->") ); -// currentContent.erase( startComment, endComment-startComment+3 ); -// startComment = currentContent.find( "<!--" ); -// } -// -// //Tag <adios-config -// currentPosition = 0; -// -// std::string tag; //use for < > tags -// GetSubString( "<adios-config", ">", currentContent, tag, currentPosition -// ); -// tag = tag.substr( 1, tag.size() - 2 ); //eliminate < > -// -// std::vector< std::pair<const std::string, const std::string> > pairs; // -// pairs in tag -// GetPairsFromTag( currentContent, tag, pairs ); -// -// for( auto& pair : pairs ) -// if( pair.first == "host-language" ) -// hostLanguage = pair.second; -// -// if( debugMode ) -// { -// if( Support::HostLanguages.count( hostLanguage ) == 0 ) -// throw std::invalid_argument("ERROR: host language " + hostLanguage -// + " not supported.\n" ); -// -// if( hostLanguage.empty() ) -// throw std::invalid_argument("ERROR: host language is empty.\n" ); -// } -// -// //adios-group -// currentPosition = 0; -// -// while( currentPosition != std::string::npos ) -// { -// std::string xmlGroup; -// GetSubString("<adios-group ", "</adios-group>", currentContent, -// xmlGroup, currentPosition ); //Get all group contents -// -// if( xmlGroup.empty() ) //no more groups to find -// break; -// -// //get group name -// std::string::size_type groupPosition( 0 ); -// GetSubString( "<adios-group ", ">", xmlGroup, tag, groupPosition ); -// if( debugMode ) -// { -// if( tag.size() < 2 ) -// throw std::invalid_argument( "ERROR: wrong tag " + tag + " in -// adios-group\n" ); //check < or <= -// } -// -// tag = tag.substr( 1, tag.size() - 2 ); //eliminate < > -// GetPairsFromTag( xmlGroup, tag, pairs ); -// std::string groupName; -// -// for( auto& pair : pairs ) -// { -// if( pair.first == "name") -// groupName = pair.second; -// } -// -// if( debugMode ) -// { -// if( groupName.empty() ) -// throw std::invalid_argument( "ERROR: group name not found. \n" -// ); -// -// if( groups.count( groupName ) == 1 ) //group exists -// throw std::invalid_argument( "ERROR: group " + groupName + " -// defined twice.\n" ); -// } -// -// groups.emplace( groupName, Group( groupName, xmlGroup, transforms, -// debugMode ) ); -// -// currentContent.erase( currentContent.find( xmlGroup ), xmlGroup.size() -// ); -// currentPosition = 0; -// } -// -// //transport -// //lambda function to check priority and iteration casting to unsigned int -// auto lf_UIntCheck = []( const std::string method, const std::string -// fieldStr, const std::string fieldName, -// const bool debugMode, int& field ) -// { -// field = 0; -// if( !fieldStr.empty()) -// { -// field = std::stoi( fieldStr ); //throws invalid_argument -// -// if( debugMode ) -// { -// if( field < 0 ) -// throw std::invalid_argument("ERROR: " + fieldName + " in -// transport " + method + " can't be negative\n" ); -// } -// } -// }; -// -// //this section will have to change, doing nothing for now -// currentPosition = 0; -// while( currentPosition != std::string::npos ) -// { -// GetSubString( "<transport ", ">", currentContent, tag, currentPosition -// ); -// if( tag.empty() ) break; -// tag = tag.substr( 1, tag.size() - 2 ); //eliminate < > -// pairs.clear(); -// GetPairsFromTag( currentContent, tag, pairs ); -// -// std::string groupName, method, priorityStr, iterationStr; -// for( auto& pair : pairs ) -// { -// if( pair.first == "group" ) groupName = pair.second; -// else if( pair.first == "method" ) method = pair.second; -// else if( pair.first == "priority" ) priorityStr = pair.second; -// else if( pair.first == "iteration" ) iterationStr = pair.second; -// } -// -// auto itGroup = groups.find( groupName ); -// if( debugMode ) -// { -// if( itGroup == groups.end() ) //not found -// throw std::invalid_argument( "ERROR: in transport " + method + -// " group " + groupName + " not found.\n" ); -// } -// -// int priority, iteration; -// lf_UIntCheck( method, priorityStr, "priority", debugMode, priority ); -// lf_UIntCheck( method, iterationStr, "iteration", debugMode, iteration -// ); -// //here do something with the capsule -// } -//} - -// void InitXML( const std::string xmlConfigFile, const MPI_Comm mpiComm, const -// bool debugMode, -// std::string& hostLanguage, std::vector< -// std::shared_ptr<Transform> >& transforms, -// std::map< std::string, Group >& groups ) -//{ -// int xmlFileContentSize; -// std::string xmlFileContent; -// -// int rank; -// MPI_Comm_rank( mpiComm, &rank ); -// -// if( rank == 0 ) //serial part -// { -// DumpFileToString( xmlConfigFile, xmlFileContent ); //in -// ADIOSFunctions.h dumps all XML Config File to xmlFileContent -// xmlFileContentSize = xmlFileContent.size( ) + 1; // add one for the -// null character -// -// MPI_Bcast( &xmlFileContentSize, 1, MPI_INT, 0, mpiComm ); //broadcast -// size for allocation -// MPI_Bcast( (char*)xmlFileContent.c_str(), xmlFileContentSize, -// MPI_CHAR, 0, mpiComm ); //broadcast contents -// } -// else -// { -// MPI_Bcast( &xmlFileContentSize, 1, MPI_INT, 0, mpiComm ); //receive -// size -// -// char* xmlFileContentMPI = new char[ xmlFileContentSize ]; //allocate -// xml C-char -// MPI_Bcast( xmlFileContentMPI, xmlFileContentSize, MPI_CHAR, 0, mpiComm -// ); //receive xml C-char -// xmlFileContent.assign( xmlFileContentMPI ); //copy to a string -// -// delete []( xmlFileContentMPI ); //delete char* needed for MPI, might -// add size is moving to C++14 for optimization, avoid memory leak -// } -// -// SetMembers( xmlFileContent, mpiComm, debugMode, hostLanguage, transforms, -// groups ); -//} - } // end namespace adios diff --git a/source/adios2/helper/adiosXML.h b/source/adios2/helper/adiosXML.h index f3df2990549ed646f2f66457e82a3b2ec5ad55f0..22d6abd8904d0cf1eb39523a6e68e7730ebb76a0 100644 --- a/source/adios2/helper/adiosXML.h +++ b/source/adios2/helper/adiosXML.h @@ -12,95 +12,61 @@ #define ADIOS2_HELPER_ADIOSXML_H_ /// \cond EXCLUDE_FROM_DOXYGEN +#include <map> +#include <memory> //std::shared_ptr #include <string> #include <utility> //std::pair #include <vector> /// \endcond +#include "adios2/core/IO.h" +#include "adios2/core/Transform.h" + namespace adios { -/** - * Extracts a substring between two tags from content - * @param initialTag - * @param finalTag - * @param content full string - * @param subString if found return substring between initialTag and finalTag, - * otherwise returns empty - * @param currentPosition to start the search, moved forward to finalTag - * position - */ -void GetSubString(const std::string initialTag, const std::string finalTag, - const std::string content, std::string &subString, - std::string::size_type ¤tPosition); +struct TagXML +{ + std::string Header; + std::string Elements; + bool IsFull; +}; -/** - * Extracts the value inside quotes in a string currentTag ( Example: currentTag - * --> field1="value1" field2="value2" ) - * @param quote double " or single ' - * @param quotePosition position of the opening quote in currentTag - * @param currentTag initial tag value, modified by cutting the first found " " - * portion, currentTag --> field2="value2" - * @param value value1 in the example above - */ -void GetQuotedValue(const char quote, - const std::string::size_type "ePosition, - std::string ¤tTag, std::string &value); +void RemoveCommentsXML(std::string ¤tContent) noexcept; -/** - * Get attributes field1="value1" field2="value2" by looping through a single - * XML tag - * @param tag field0="value0" field1="value1" in a single string - * @param pairs pairs[0].first=field0 pairs[0].second=value0 - * pairs[1].first=field1 pairs[1].second=value1 - */ -void GetPairs(const std::string tag, - std::vector<std::pair<const std::string, const std::string>> - &pairs) noexcept; +TagXML GetTagXML(const std::string tagName, const std::string &content, + std::string::size_type &position); -/** - * Determine tag type and call GetPairs to populate pairs - * @param fileContent file Content in a single string - * @param tag field0="value0" field1="value1" in a single string - * @param pairs pairs[0].first=field0 pairs[0].second=value0 - * pairs[1].first=field1 pairs[1].second=value1 - */ -void GetPairsFromTag( - const std::string &fileContent, const std::string tag, - std::vector<std::pair<const std::string, const std::string>> &pairs); +std::string::size_type +GetStringPositionXML(const std::string input, const std::string &content, + const std::string::size_type &startPosition) noexcept; -/** - * Set members m_Groups and m_HostLanguage from XML file content, called within - * Init functions - * @param fileContent file Content in a single string - * @param mpiComm MPI Communicator passed from application passed to Transport - * method if required - * @param hostLanguage return the host language from fileContent - * @param transforms return the modified transforms vector if there are - * variables with transformations - * @param groups passed returns the map of groups defined in fileContent - */ -// void SetMembers( const std::string& fileContent, const MPI_Comm mpiComm, -// std::string& hostLanguage, std::vector< -// std::shared_ptr<Transform> >& transforms, -// std::map< std::string, Group >& groups ); +Params GetTagAttributesXML(const std::string &tagHeader); /** - * Called inside the ADIOS XML constructors to get contents from file, broadcast - * and set hostLanguage and groups from ADIOS class - * @param xmlConfigFile xml config file name - * @param mpiComm communicator used from broadcasting - * @param debugMode from ADIOS m_DebugMode passed to CGroup in groups - * @param hostLanguage set from host-language in xml file - * @param transforms return the modified transforms vector if there are - * variables with transformations - * @param groups passed returns the map of groups defined in fileContent + * Called inside the ADIOS XML constructors to get contents from file, + * broadcast and fill transforms and ios + * @param configXMLFile + * @param mpiComm + * @param debugMode + * @param transforms + * @param ios */ -// void InitXML( const std::string xmlConfigFile, const MPI_Comm mpiComm, const -// bool debugMode, -// std::string& hostLanguage, std::vector< -// std::shared_ptr<Transform> >& transforms, -// std::map< std::string, Group >& groups ); +void InitXML(const std::string configXML, const MPI_Comm mpiComm, + const bool debugMode, + std::vector<std::shared_ptr<Transform>> &transforms, + std::map<std::string, IO> &ios); + +void InitIOXML(const TagXML &ioXML, const MPI_Comm mpiComm, + const bool debugMode, + std::vector<std::shared_ptr<Transform>> &transforms, + std::map<std::string, IO> &ios); + +void InitEngineXML(const TagXML &engineXML, const bool debugMode, IO &io); + +void InitTransportXML(const TagXML &transportXML, const bool debugMode, IO &io); + +Params ParseParamsXML(const std::string &tagContents, const bool debugMode); } #endif /* ADIOS2_HELPER_ADIOSXML_H_ */ diff --git a/source/adios2/mpidummy.h b/source/adios2/mpidummy.h index ed2b120584d2a334de31a43edfe6811cbce58dbb..249f9206f653020379d046dc729c7ae429045cf3 100644 --- a/source/adios2/mpidummy.h +++ b/source/adios2/mpidummy.h @@ -54,6 +54,9 @@ typedef int MPI_Fint; #define MPI_INT 1 #define MPI_CHAR 2 #define MPI_DOUBLE 3 +#define MPI_UNSIGNED 4 +#define MPI_UNSIGNED_LONG 5 +#define MPI_UNSIGNED_LONG_LONG 6 #define MPI_ANY_SOURCE 0 #define MPI_ANY_TAG 0