Skip to content
Snippets Groups Projects
ADIOS.cpp 11.5 KiB
Newer Older
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * ADIOS.cpp
 *
 *  Created on: Sep 29, 2016
 *      Author: William F Godoy
 */

/// \cond EXCLUDE_FROM_DOXYGEN
#include <fstream>
#include <iostream>
#include <sstream>
#include <utility>
/// \endcond

#include "ADIOS.h"
#include "functions/adiosFunctions.h"

// Engines
#include "engine/bp/BPFileReader.h"
#include "engine/bp/BPFileWriter.h"

#ifdef HAVE_DATAMAN // external dependencies
#include "engine/dataman/DataManReader.h"
#include "engine/dataman/DataManWriter.h"
#endif

#ifdef HAVE_ADIOS1 // external dependencies
#include "engine/adios1/ADIOS1Reader.h"
#include "engine/adios1/ADIOS1Writer.h"
#endif

namespace adios
{

ADIOS::ADIOS(const Verbose /*verbose*/, const bool debugMode)
: m_DebugMode{debugMode}
ADIOS::ADIOS(std::string config, const Verbose /*verbose*/,
             const bool debugMode)
: m_ConfigFile{std::move(config)}, m_DebugMode{debugMode}
{
  InitMPI();
  // InitXML( m_ConfigFile, m_MPIComm, m_DebugMode, m_Transforms );
}

ADIOS::ADIOS(std::string config, MPI_Comm mpiComm, const Verbose /*verbose*/,
             const bool debugMode)
: m_MPIComm{mpiComm}, m_ConfigFile{std::move(config)}, m_DebugMode{debugMode}
{
  InitMPI();
  // InitXML( m_XMLConfigFile, m_MPIComm, m_DebugMode, m_HostLanguage,
  // m_Transforms, m_Groups );
}

ADIOS::ADIOS(MPI_Comm mpiComm, const Verbose /*verbose*/, const bool debugMode)
: m_MPIComm{mpiComm}, m_DebugMode{debugMode}
// ADIOS::~ADIOS() {}

void ADIOS::InitMPI()
{
  if (m_DebugMode == true)
  {
    if (m_MPIComm == MPI_COMM_NULL)
      throw std::ios_base::failure(
          "ERROR: engine communicator is MPI_COMM_NULL,"
          " in call to ADIOS Open or Constructor\n");
  }

  MPI_Comm_rank(m_MPIComm, &m_RankMPI);
  MPI_Comm_size(m_MPIComm, &m_SizeMPI);
}

Method &ADIOS::DeclareMethod(const std::string &methodName)
{
  if (m_DebugMode == true)
  {
    if (m_Methods.count(methodName) == 1)
      throw std::invalid_argument("ERROR: method " + methodName +
                                  " already declared, from DeclareMethod\n");
  }
  m_Methods.emplace(methodName, Method(methodName, m_DebugMode));
  return m_Methods.at(methodName);
}

std::shared_ptr<Engine> ADIOS::Open(const std::string &name,
                                    const std::string &accessMode,
                                    MPI_Comm mpiComm, const Method &method,
                                    const IOMode iomode,
                                    const float timeout_sec)
{
  if (m_DebugMode == true)
  {
    if (m_EngineNames.count(name) == 1) // Check if Engine already exists
      throw std::invalid_argument(
          "ERROR: engine name " + name +
          " already created by Open, in call from Open.\n");
  }

  m_EngineNames.insert(name);

  const std::string type(method.m_Type);

  const bool isDefaultWriter = (accessMode == "w" || accessMode == "write" ||
                                accessMode == "a" || accessMode == "append") &&
                                       type.empty()
                                   ? true
                                   : false;

  const bool isDefaultReader =
      (accessMode == "r" || accessMode == "read") && type.empty() ? true
                                                                  : false;

  if (isDefaultWriter || type == "BPFileWriter" || type == "bpfilewriter")
  {
    return std::make_shared<BPFileWriter>(*this, name, accessMode, mpiComm,
                                          method, iomode, timeout_sec,
                                          m_DebugMode, method.m_nThreads);
  }
  else if (isDefaultReader || type == "BPReader" || type == "bpreader")
  {
    return std::make_shared<BPFileReader>(*this, name, accessMode, mpiComm,
                                          method, iomode, timeout_sec,
                                          m_DebugMode, method.m_nThreads);
  }
  else if (type == "SIRIUS" || type == "sirius" || type == "Sirius")
  {
    // not yet supported
    // return std::make_shared<engine::DataMan>( *this, name, accessMode,
    // mpiComm, method, iomode, timeout_sec, m_DebugMode, method.m_nThreads );
  }
  else if (type == "DataManWriter")
  {
#ifdef HAVE_DATAMAN
    return std::make_shared<DataManWriter>(*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 "
                                "Dataman library, can't Open DataManWriter\n");
#endif
  }
  else if (type == "DataManReader")
  {
#ifdef HAVE_DATAMAN
    return std::make_shared<DataManReader>(*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 "
                                "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 );
  }
  else
  {
    if (m_DebugMode == true)
      throw std::invalid_argument("ERROR: method type " + type +
                                  " not supported for " + name +
                                  ", in call to Open\n");
  }

  return nullptr; // if debug mode is off
}

std::shared_ptr<Engine> ADIOS::Open(const std::string &streamName,
                                    const std::string &accessMode,
                                    const Method &method, const IOMode iomode,
                                    const float timeout_sec)
{
  return Open(streamName, accessMode, m_MPIComm, method, iomode, timeout_sec);
}

std::shared_ptr<Engine>
ADIOS::Open(const std::string &name, const std::string &accessMode,
            MPI_Comm mpiComm, const std::string &methodName,
            const IOMode iomode, const float timeout_sec)
{
  auto itMethod = m_Methods.find(methodName);

  if (m_DebugMode == true)
  {
    CheckMethod(itMethod, methodName, " in call to Open\n");
  }

  return Open(name, accessMode, mpiComm, itMethod->second, iomode, timeout_sec);
}

std::shared_ptr<Engine> ADIOS::Open(const std::string &name,
                                    const std::string &accessMode,
                                    const std::string &methodName,
                                    const IOMode iomode,
                                    const float timeout_sec)
{
  return Open(name, accessMode, m_MPIComm, methodName, iomode, timeout_sec);
}

std::shared_ptr<Engine> ADIOS::OpenFileReader(const std::string &name,
                                              MPI_Comm /*mpiComm*/,
                                              const Method &method,
                                              const IOMode iomode)
{
  return Open(name, "r", m_MPIComm, method, iomode);
}

std::shared_ptr<Engine> ADIOS::OpenFileReader(const std::string &name,
                                              MPI_Comm /*mpiComm*/,
                                              const std::string &methodName,
                                              const IOMode iomode)
{
  auto itMethod = m_Methods.find(methodName);

  if (m_DebugMode == true)
  {
    CheckMethod(itMethod, methodName, " in call to Open\n");
  }

  return Open(name, "r", m_MPIComm, itMethod->second, iomode);
}

VariableCompound &ADIOS::GetVariableCompound(const std::string &name)
{
  return m_Compound.at(GetVariableIndex<void>(name));
}

void ADIOS::MonitorVariables(std::ostream &logStream)
{
  logStream << "\tVariable \t Type\n";

  for (auto &variablePair : m_Variables)
  {
    const std::string name(variablePair.first);
    const std::string type(variablePair.second.first);

    if (type == GetType<char>())
      GetVariable<char>(name).Monitor(logStream);
    else if (type == GetType<unsigned char>())
      GetVariable<unsigned char>(name).Monitor(logStream);
    else if (type == GetType<short>())
      GetVariable<short>(name).Monitor(logStream);
    else if (type == GetType<unsigned short>())
      GetVariable<unsigned short>(name).Monitor(logStream);
    else if (type == GetType<int>())
      GetVariable<int>(name).Monitor(logStream);
    else if (type == GetType<unsigned int>())
      GetVariable<unsigned int>(name).Monitor(logStream);
    else if (type == GetType<long int>())
      GetVariable<long int>(name).Monitor(logStream);
    else if (type == GetType<unsigned long int>())
      GetVariable<unsigned long int>(name).Monitor(logStream);
    else if (type == GetType<long long int>())
      GetVariable<long long int>(name).Monitor(logStream);
    else if (type == GetType<unsigned long long int>())
      GetVariable<unsigned long long int>(name).Monitor(logStream);
    else if (type == GetType<float>())
      GetVariable<float>(name).Monitor(logStream);
    else if (type == GetType<double>())
      GetVariable<double>(name).Monitor(logStream);
    else if (type == GetType<long double>())
      GetVariable<long double>(name).Monitor(logStream);
    else if (type == GetType<std::complex<float>>())
      GetVariable<std::complex<float>>(name).Monitor(logStream);
    else if (type == GetType<std::complex<double>>())
      GetVariable<std::complex<double>>(name).Monitor(logStream);
    else if (type == GetType<std::complex<long double>>())
      GetVariable<std::complex<long double>>(name).Monitor(logStream);
  }
}

// PRIVATE FUNCTIONS BELOW
void ADIOS::CheckVariableInput(const std::string &name,
                               const Dims &dimensions) const
{
  if (m_DebugMode == true)
  {
    if (m_Variables.count(name) == 1)
      throw std::invalid_argument(
          "ERROR: variable " + name +
          " already exists, in call to DefineVariable\n");

    if (dimensions.empty() == true)
      throw std::invalid_argument(
          "ERROR: variable " + name +
          " dimensions can't be empty, in call to DefineVariable\n");
  }
}

void ADIOS::CheckVariableName(
    std::map<std::string, std::pair<std::string, unsigned int>>::const_iterator
        itVariable,
    const std::string &name, const std::string &hint) const
{
  if (m_DebugMode == true)
  {
    if (itVariable == m_Variables.end())
      throw std::invalid_argument("ERROR: variable " + name +
                                  " does not exist " + hint + "\n");
  }
}

void ADIOS::CheckMethod(std::map<std::string, Method>::const_iterator itMethod,
                        const std::string &methodName,
                        const std::string &hint) const
{
  if (itMethod == m_Methods.end())
    throw std::invalid_argument("ERROR: method " + methodName + " not found " +
                                hint + "\n");
} // end namespace adios