Skip to content
Snippets Groups Projects
ADIOS.h 14.9 KiB
Newer Older
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * ADIOS.h
 *
 *  Created on: Oct 3, 2016
 *      Author: wfg
 */

#ifndef ADIOS_H_
#define ADIOS_H_

/// \cond EXCLUDE_FROM_DOXYGEN
#include <complex>
#include <map>
#include <memory> //std::shared_ptr
wfg's avatar
wfg committed
#include <set>
#include <string>
#include <vector>
#include "ADIOS_MPI.h"
#include "core/Method.h"
#include "core/Support.h"
wfg's avatar
wfg committed
#include "core/Transform.h"
#include "core/Variable.h"
#include "core/VariableCompound.h"
wfg's avatar
wfg committed
#include "functions/adiosTemplates.h"

namespace adios
{
wfg's avatar
wfg committed

class Engine;

 * @brief Unique class interface between user application and ADIOS library
 */
class ADIOS
{
public:
    MPI_Comm m_MPIComm = MPI_COMM_SELF; ///< only used as reference to MPI
                                        /// communicator passed from parallel
    /// constructor, MPI_Comm is a pointer
    /// itself. Public as called from C

    int m_RankMPI = 0; ///< current MPI rank process
    int m_SizeMPI = 1; ///< current MPI processes size

    std::string m_HostLanguage = "C++";

    /**
     * @brief ADIOS empty constructor. Used for non XML config file API calls.
     */
    ADIOS(const Verbose verbose = Verbose::WARN, const bool debugMode = false);

    /**
     * @brief Serial constructor for config file, only allowed and compiled in
     * libadios_nompi.a
     * @param config XML config file
     * @param debugMode true: on throws exceptions and do additional checks,
     * false: off (faster, but unsafe)
     */
    ADIOS(std::string config, const Verbose verbose = Verbose::WARN,
          const bool debugMode = false);

    /**
     * @brief Parallel constructor for XML config file and MPI
     * @param config XML config file
     * @param mpiComm MPI communicator ...const to be discussed
     * @param debugMode true: on, false: off (faster, but unsafe)
     */

    ADIOS(std::string config, MPI_Comm mpiComm,
          const Verbose verbose = Verbose::WARN, const bool debugMode = false);

    /**
     * @brief Parallel MPI communicator without XML config file
     * @param mpiComm MPI communicator passed to m_MPIComm*
     * @param debugMode true: on, false: off (faster)
     */
    ADIOS(MPI_Comm mpiComm, const Verbose verbose = Verbose::WARN,
          const bool debugMode = false);

    ~ADIOS() = default;

    void InitMPI(); ///< sets rank and size in m_rank and m_Size, respectively.

    /**
     * Look for template specialization
     * @param name
     * @param dimensions
     * @param globalDimensions
     * @param globalOffsets
     * @return
     */
    template <class T>
    Variable<T> &DefineVariable(const std::string &name,
                                const Dims dimensions = Dims{1},
                                const Dims globalDimensions = Dims(),
                                const Dims globalOffsets = Dims());
    Variable<T> &GetVariable(const std::string &name);
    VariableCompound &
    DefineVariableCompound(const std::string &name,
                           const Dims dimensions = Dims{1},
                           const Dims globalDimensions = Dims(),
                           const Dims globalOffsets = Dims());

    VariableCompound &GetVariableCompound(const std::string &name);

    /**
     * Declares a new method. If the method is defined in the user config file,
     * it will be already created during processing the config file,
     * the method is set up with the user settings and this function just
     * returns
     * that method.
     * Otherwise it will create and return a new Method with default settings.
     * Use method.isUserDefined() to distinguish between the two cases.
     * @param methodName must be unique
     */
    Method &DeclareMethod(const std::string &methodName);

    /**
     * @brief Open to Write, Read. Creates a new engine from previously defined
     * method
     * @param streamName unique stream or file name
     * @param accessMode "w" or "write", "r" or "read", "a" or "append", "u" or
     * "update"
     * @param mpiComm option to modify communicator from ADIOS class constructor
     * @param method looks for corresponding Method object in ADIOS to
     * initialize
     * the engine
     * @param iomode Independent or collective open/advance by writers/readers?
     * Write() operations are always independent.
     * @param timeout_sec Wait some time before reporting on missing stream
     * (i.e.
     * wait for it for a while)
      * @return Derived class of base Engine depending on Method parameters,
     * shared_ptr for potential flexibility
     */
    std::shared_ptr<Engine> Open(const std::string &streamName,
                                 const std::string &accessMode,
                                 MPI_Comm mpiComm, const Method &method,
                                 const IOMode iomode = IOMode::INDEPENDENT,
                                 const float timeout_sec = 0.0);

    /**
     * @brief Open to Write, Read. Creates a new engine from previously defined
     * method.
     * Reuses MPI communicator from ADIOS constructor.
     * @param streamName unique stream or file name
     * @param accessMode "w" or "write", "r" or "read", "a" or "append", "u" or
     * "update"
     * @param method contains engine parameters
     * @param iomode Independent or collective open/advance by writers/readers?
     * Write() operations are always independent.
     * @param timeout_sec Wait some time before reporting on missing stream
     * (i.e.
     * wait for it for a while)
      * @return Derived class of base Engine depending on Method parameters,
     * shared_ptr for potential flexibility
     */
    std::shared_ptr<Engine> Open(const std::string &streamName,
                                 const std::string &accessMode,
                                 const Method &method,
                                 const IOMode iomode = IOMode::INDEPENDENT,
                                 const float timeout_sec = 0.0);

    /**
     * Version required by the XML config file implementation, searches method
     * inside ADIOS through a unique name
     * @param streamName unique stream or file name
     * @param accessMode "w" or "write", "r" or "read", "a" or "append"
     * @param mpiComm mpi Communicator
     * @param methodName used to search method object inside ADIOS object
     * @param iomode Independent or collective open/advance by writers/readers?
     * Write() operations are always independent.
     * @param timeout_sec Wait some time before reporting on missing stream
     * (i.e.
     * wait for it for a while)
     * @return Derived class of base Engine depending on Method parameters,
     * shared_ptr for potential flexibility
     */
    std::shared_ptr<Engine> Open(const std::string &streamName,
                                 const std::string &accessMode,
                                 MPI_Comm mpiComm,
                                 const std::string &methodName,
                                 const IOMode iomode = IOMode::INDEPENDENT,
                                 const float timeout_sec = 0.0);

    /**
     * Version required by the XML config file implementation, searches method
     * inside ADIOS through a unique name.
     * Reuses ADIOS MPI Communicator from constructor.
     * @param streamName unique stream or file name
     * @param accessMode "w" or "write", "r" or "read", "a" or "append"
     * @param methodName used to search method object inside ADIOS object
     * @param iomode Independent or collective open/advance by writers/readers?
     * Write() operations are always independent.
     * @param timeout_sec Wait some time before reporting on missing stream
     * (i.e.
     * wait for it for a while)
     * @return Derived class of base Engine depending on Method parameters,
     * shared_ptr for potential flexibility
     */
    std::shared_ptr<Engine> Open(const std::string &streamName,
                                 const std::string &accessMode,
                                 const std::string &methodName,
                                 const IOMode iomode = IOMode::INDEPENDENT,
                                 const float timeout_sec = 0.0);

    /**
     * @brief Open to Read all steps from a file. No streaming, advancing is
     * possible here. All steps in the file
     * are immediately available for reading. Creates a new engine from
     * previously
     * defined method.
     * @param fileName file name
     * @param mpiComm option to modify communicator from ADIOS class constructor
     * @param method looks for corresponding Method object in ADIOS to
     * initialize
     * the engine
     * @param iomode Independent or collective open/advance by writers/readers?
     * Write() operations are always independent.
     * @return Derived class of base Engine depending on Method parameters,
     * shared_ptr for potential flexibility
     */
    std::shared_ptr<Engine>
    OpenFileReader(const std::string &fileName, MPI_Comm mpiComm,
                   const Method &method,
                   const IOMode iomode = IOMode::INDEPENDENT);

    /**
     * @brief Open to Read all steps from a file. No streaming, advancing is
     * possible here. All steps in the file
     * are immediately available for reading. Creates a new engine from
     * previously
     * defined method.
     * Version required by the XML config file implementation, searches method
     * inside ADIOS through a unique name.
     * @param fileName file name
     * @param mpiComm option to modify communicator from ADIOS class constructor
     * @param methodName used to search method object inside ADIOS object
      * @param iomode Independent or collective open/advance by writers/readers?
     * Write() operations are always independent.
     * @return Derived class of base Engine depending on Method parameters,
     * shared_ptr for potential flexibility
     */
    std::shared_ptr<Engine>
    OpenFileReader(const std::string &fileName, MPI_Comm mpiComm,
                   const std::string &methodName,
                   const IOMode iomode = IOMode::INDEPENDENT);

    /**
     * @brief Dumps groups information to a file stream or standard output.
     * Note that either the user closes this fileStream or it's closed at the
     * end.
     * @param logStream either std::cout standard output, or a std::ofstream
     * file
     */
    void MonitorVariables(std::ostream &logStream);

protected: // no const to allow default empty and copy constructors
    std::map<unsigned int, Variable<char>> m_Char;
    std::map<unsigned int, Variable<unsigned char>> m_UChar;
    std::map<unsigned int, Variable<short>> m_Short;
    std::map<unsigned int, Variable<unsigned short>> m_UShort;
    std::map<unsigned int, Variable<int>> m_Int;
    std::map<unsigned int, Variable<unsigned int>> m_UInt;
    std::map<unsigned int, Variable<long int>> m_LInt;
    std::map<unsigned int, Variable<unsigned long int>> m_ULInt;
    std::map<unsigned int, Variable<long long int>> m_LLInt;
    std::map<unsigned int, Variable<unsigned long long int>> m_ULLInt;
    std::map<unsigned int, Variable<float>> m_Float;
    std::map<unsigned int, Variable<double>> m_Double;
    std::map<unsigned int, Variable<long double>> m_LDouble;
    std::map<unsigned int, Variable<std::complex<float>>> m_CFloat;
    std::map<unsigned int, Variable<std::complex<double>>> m_CDouble;
    std::map<unsigned int, Variable<std::complex<long double>>> m_CLDouble;
    std::map<unsigned int, VariableCompound> m_Compound;

    std::string m_ConfigFile; ///< XML File to be read containing configuration
                              /// information
    bool m_DebugMode = false; ///< if true will do more checks, exceptions,
                              /// warnings, expect slower code

    // Variables
    std::map<std::string, std::pair<std::string, unsigned int>>
        m_Variables; ///< Makes variable name unique, key: variable name,
                     /// value:
    /// pair.first = type, pair.second = index in corresponding
    /// vector of Variable

    std::vector<std::shared_ptr<Transform>>
        m_Transforms; ///< transforms associated with ADIOS run

    /**
     * @brief List of Methods (engine metadata) defined from either ADIOS XML
     * configuration file or the DeclareMethod function.
     * <pre>
     *     Key: std::string unique method name
     *     Value: Method class
     * </pre>
     */
    std::map<std::string, Method> m_Methods;
    std::set<std::string> m_EngineNames; ///< set used to check Engine name
                                         /// uniqueness in debug mode

    /**
     * @brief Checks for group existence in m_Groups, if failed throws
     * std::invalid_argument exception
     * @param itGroup m_Groups iterator, usually from find function
     * @param groupName unique name, passed for thrown exception only
     * @param hint adds information to thrown exception
     */
    void CheckVariableInput(const std::string &name,
                            const Dims &dimensions) const;

    /**
     * Checks for variable name, if not found throws an invalid exception
     * @param itVariable iterator pointing to the variable name in m_Variables
     * @param name variable name
     * @param hint message to be thrown for debugging purporses
     */
    void CheckVariableName(
        std::map<std::string,
                 std::pair<std::string, unsigned int>>::const_iterator
            itVariable,
        const std::string &name, const std::string &hint) const;

    /**
     * @brief Checks for method existence in m_Methods, if failed throws
     * std::invalid_argument exception
     * @param itMethod m_Methods iterator, usually from find function
     * @param methodName unique name, passed for thrown exception only
     * @param hint adds information to thrown exception
     */
    void CheckMethod(std::map<std::string, Method>::const_iterator itMethod,
                     const std::string &methodName,
                     const std::string &hint) const;

    unsigned int GetVariableIndex(const std::string &name);
    // Helper function for DefineVariable
    template <class T>
    std::map<unsigned int, Variable<T>> &GetVarMap();
};
template <class T>
VariableCompound &ADIOS::DefineVariableCompound(const std::string &name,
                                                const Dims dimensions,
                                                const Dims globalDimensions,
                                                const Dims globalOffsets)
    CheckVariableInput(name, dimensions);
    const unsigned int size = m_Compound.size();
    m_Compound.emplace(size, VariableCompound(name, sizeof(T), dimensions,
                                              globalDimensions, globalOffsets,
                                              m_DebugMode));
    m_Variables.emplace(name, std::make_pair(GetType<T>(), size));
    return m_Compound.at(size);

#endif /* ADIOS_H_ */