Commit 9c52a375 authored by Norbert Podhorszki's avatar Norbert Podhorszki
Browse files

PIMPL implementation of USER-ADIOS to hide internal data from style header file

parent a4b9542b
Loading
Loading
Loading
Loading
+1 −8
Original line number Diff line number Diff line
@@ -3,18 +3,11 @@
# This file is part of LAMMPS
# Created by Christoph Junghans and Richard Berger
if(PKG_USER-ADIOS)
  message(STATUS "Force newer standards because using ADIOS")
  message(STATUS "Force newer standards because of using ADIOS")
  cmake_minimum_required(VERSION 3.6)
  # Force C++11 and C99
  set(CMAKE_CXX_STANDARD 11)
  set(CMAKE_CXX_STANDARD_REQUIRED True)
  # Use meta-compile features if available, otherwise use specific language
  # features
#  if(NOT (CMAKE_VERSION VERSION_LESS 3.9))
#    set(ADIOS2_CXX11_FEATURES cxx_std_11)
#  else()
#    set(ADIOS2_CXX11_FEATURES cxx_auto_type cxx_nullptr)
#  endif()
else()
  cmake_minimum_required(VERSION 2.8.12)
endif()
+150 −125
Original line number Diff line number Diff line
@@ -15,16 +15,17 @@
   Contributing author: Norbert Podhorszki (ORNL)
------------------------------------------------------------------------- */

#include <string.h>
#include "dump_atom_adios.h"
#include "domain.h"
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "error.h"
#include "group.h"
#include "memory.h"
#include "universe.h"
#include "error.h"
#include "update.h"
#include <cstring>

#include "adios2.h"

using namespace LAMMPS_NS;

@@ -32,23 +33,44 @@ using namespace LAMMPS_NS;
#define DUMP_BUF_CHUNK_SIZE 16384
#define DUMP_BUF_INCREMENT_SIZE 4096

namespace LAMMPS_NS
{
class DumpAtomADIOSInternal
{

public:
    DumpAtomADIOSInternal(){};
    ~DumpAtomADIOSInternal() = default;

    // name of adios group, referrable in adios2_config.xml
    const std::string ioName = "atom";
    adios2::ADIOS *ad = nullptr; // adios object
    adios2::IO io;     // adios group of variables and attributes in this dump
    adios2::Engine fh; // adios file/stream handle object
    // one ADIOS output variable we need to change every step
    adios2::Variable<double> varAtoms;
};
}

/* ---------------------------------------------------------------------- */

DumpAtomADIOS::DumpAtomADIOS(LAMMPS *lmp, int narg, char **arg) :
  DumpAtom(lmp, narg, arg)
DumpAtomADIOS::DumpAtomADIOS(LAMMPS *lmp, int narg, char **arg)
: DumpAtom(lmp, narg, arg)
{
    ad = new adios2::ADIOS("adios2_config.xml", world, adios2::DebugON);
    groupSize = 0;
    internal = new DumpAtomADIOSInternal();
    internal->ad =
        new adios2::ADIOS("adios2_config.xml", world, adios2::DebugON);
}

/* ---------------------------------------------------------------------- */

DumpAtomADIOS::~DumpAtomADIOS()
{
    if (fh)
    {
        fh.Close();
    if (internal->fh) {
        internal->fh.Close();
    }
    delete internal->ad;
    delete internal;
}

/* ---------------------------------------------------------------------- */
@@ -62,36 +84,36 @@ void DumpAtomADIOS::openfile()
        char *ptr = strchr(filestar, '*');
        *ptr = '\0';
        if (padflag == 0)
            sprintf(filecurrent,"%s" BIGINT_FORMAT "%s",
            snprintf(filecurrent, sizeof(filecurrent), "%s" BIGINT_FORMAT "%s",
                     filestar, update->ntimestep, ptr + 1);
        else {
            char bif[8], pad[16];
            strcpy(bif, BIGINT_FORMAT);
            sprintf(pad,"%%s%%0%d%s%%s",padflag,&bif[1]);
            sprintf(filecurrent,pad,filestar,update->ntimestep,ptr+1);
            snprintf(pad, sizeof(pad), "%%s%%0%d%s%%s", padflag, &bif[1]);
            snprintf(filecurrent, sizeof(filecurrent), pad, filestar,
                     update->ntimestep, ptr + 1);
        }
        fh = io.Open(filecurrent, adios2::Mode::Write, world);
        if (!fh) {
        internal->fh =
            internal->io.Open(filecurrent, adios2::Mode::Write, world);
        if (!internal->fh) {
            char str[128];
            sprintf(str,"Cannot open dump file %s",filecurrent);
            snprintf(str, sizeof(str), "Cannot open dump file %s", filecurrent);
            error->one(FLERR, str);
        }
        free(filestar);
        delete[] filecurrent;
    }
    else
    {
        if (!singlefile_opened)
        {
            fh = io.Open(filename, adios2::Mode::Write, world);
            if (!fh) {
    } else {
        if (!singlefile_opened) {
            internal->fh =
                internal->io.Open(filename, adios2::Mode::Write, world);
            if (!internal->fh) {
                char str[128];
                sprintf(str,"Cannot open dump file %s",filename);
                snprintf(str, sizeof(str), "Cannot open dump file %s",
                         filename);
                error->one(FLERR, str);
            }
            singlefile_opened = 1;
        }

    }
}

@@ -138,11 +160,12 @@ void DumpAtomADIOS::write()
    size_t startRow = static_cast<size_t>(atomOffset);
    size_t nAtomsLocal = static_cast<size_t>(nme);
    size_t nColumns = static_cast<size_t>(size_one);
    varAtoms.SetShape({nAtomsGlobal,nColumns});
    varAtoms.SetSelection({{startRow, 0}, {nAtomsLocal,nColumns}});
    internal->varAtoms.SetShape({nAtomsGlobal, nColumns});
    internal->varAtoms.SetSelection({{startRow, 0}, {nAtomsLocal, nColumns}});

    // insure buf is sized for packing
    // adios does not limit per-process data size so nme*size_one is not constrained to int
    // adios does not limit per-process data size so nme*size_one is not
    // constrained to int
    // if sorting on IDs also request ID list from pack()
    // sort buf as needed

@@ -157,52 +180,45 @@ void DumpAtomADIOS::write()
        memory->create(ids, maxids, "dump:ids");
    }

    if (sort_flag && sortcol == 0) pack(ids);
    else pack(NULL);
    if (sort_flag) sort();

    // Calculate data size written by this process
    groupSize = nme * size_one * sizeof(double); // size of atoms data on this process
    groupSize += 3*sizeof(uint64_t) + 1*sizeof(int); // scalars written by each process
    if (me == 0) {
        groupSize += 1*sizeof(uint64_t) + 1*sizeof(int) + 6*sizeof(double); // scalars
        if (domain->triclinic) {
            groupSize += 3*sizeof(double); // boxxy, boxxz, boxyz
        }
    }
    if (sort_flag && sortcol == 0)
        pack(ids);
    else
        pack(NULL);
    if (sort_flag)
        sort();

    openfile();
    fh.BeginStep();
    internal->fh.BeginStep();
    // write info on data as scalars (by me==0)
    if (me == 0) {
        fh.Put<uint64_t>("ntimestep",   update->ntimestep);
        fh.Put<int>("nprocs",      nprocs);
        internal->fh.Put<uint64_t>("ntimestep", update->ntimestep);
        internal->fh.Put<int>("nprocs", nprocs);

        fh.Put<double>("boxxlo", boxxlo);
        fh.Put<double>("boxxhi", boxxhi);
        fh.Put<double>("boxylo", boxylo);
        fh.Put<double>("boxyhi", boxyhi);
        fh.Put<double>("boxzlo", boxzlo);
        fh.Put<double>("boxzhi", boxzhi);
        internal->fh.Put<double>("boxxlo", boxxlo);
        internal->fh.Put<double>("boxxhi", boxxhi);
        internal->fh.Put<double>("boxylo", boxylo);
        internal->fh.Put<double>("boxyhi", boxyhi);
        internal->fh.Put<double>("boxzlo", boxzlo);
        internal->fh.Put<double>("boxzhi", boxzhi);

        if (domain->triclinic) {
            fh.Put<double>("boxxy", boxxy);
            fh.Put<double>("boxxz", boxxz);
            fh.Put<double>("boxyz", boxyz);
            internal->fh.Put<double>("boxxy", boxxy);
            internal->fh.Put<double>("boxxz", boxxz);
            internal->fh.Put<double>("boxyz", boxyz);
        }
    }
    // Everyone needs to write scalar variables that are used as dimensions and offsets of arrays
    fh.Put<uint64_t>("natoms",   ntotal);
    fh.Put<int>("ncolumns", size_one);
    fh.Put<uint64_t>("nme",      bnme);
    fh.Put<uint64_t>("offset",   atomOffset);
    // Everyone needs to write scalar variables that are used as dimensions and
    // offsets of arrays
    internal->fh.Put<uint64_t>("natoms", ntotal);
    internal->fh.Put<int>("ncolumns", size_one);
    internal->fh.Put<uint64_t>("nme", bnme);
    internal->fh.Put<uint64_t>("offset", atomOffset);
    // now write the atoms
    fh.Put<double>("atoms",    buf);
    fh.EndStep();// I/O will happen now...
    internal->fh.Put<double>(internal->varAtoms, buf);
    internal->fh.EndStep(); // I/O will happen now...

    if (multifile)
    {
        fh.Close();
    if (multifile) {
        internal->fh.Close();
    }
}

@@ -210,20 +226,23 @@ void DumpAtomADIOS::write()

void DumpAtomADIOS::init_style()
{
    if (image_flag == 0) size_one = 5;
    else size_one = 8;
    if (image_flag == 0)
        size_one = 5;
    else
        size_one = 8;

    // setup boundary string

    domain->boundary_string(boundstr);

    // remove % from filename since ADIOS always writes a global file with data/metadata
    // remove % from filename since ADIOS always writes a global file with
    // data/metadata
    int len = strlen(filename);
    char *ptr = strchr(filename, '%');
    if (ptr) {
        *ptr = '\0';
        char *s = new char[len - 1];
        sprintf(s,"%s%s",filename,ptr+1);
        snprintf(s, sizeof(s), "%s%s", filename, ptr + 1);
        strncpy(filename, s, len);
    }

@@ -253,62 +272,68 @@ void DumpAtomADIOS::init_style()
    else if (scale_flag == 0 && image_flag == 1)
        pack_choice = &DumpAtomADIOS::pack_noscale_image;

    /* Define the group of variables for the atom style here since it's a fixed set */
    io = ad->DeclareIO(ioName);
    if (!io.InConfigFile())
    {
    /* Define the group of variables for the atom style here since it's a fixed
     * set */
    internal->io = internal->ad->DeclareIO(internal->ioName);
    if (!internal->io.InConfigFile()) {
        // if not defined by user, we can change the default settings
        // BPFile is the default writer
        io.SetEngine("BPFile");
        internal->io.SetEngine("BPFile");
        int num_aggregators = multiproc;
        if (num_aggregators == 0)
            num_aggregators = 1;
        char nstreams[128];
        sprintf (nstreams, "%d", num_aggregators);
        io.SetParameters({{"substreams", nstreams}});
        if (me==0 && screen) fprintf(screen, "ADIOS method for %s is n-to-m (aggregation with %s writers)\n", filename, nstreams);
        snprintf(nstreams, sizeof(nstreams), "%d", num_aggregators);
        internal->io.SetParameters({{"substreams", nstreams}});
        if (me == 0 && screen)
            fprintf(
                screen,
                "ADIOS method for %s is n-to-m (aggregation with %s writers)\n",
                filename, nstreams);
    }

    internal->io.DefineVariable<uint64_t>("ntimestep");
    internal->io.DefineVariable<uint64_t>("natoms");

    io.DefineVariable<uint64_t>("ntimestep");
    io.DefineVariable<uint64_t>("natoms");

    io.DefineVariable<int>("nprocs");
    io.DefineVariable<int>("ncolumns");
    internal->io.DefineVariable<int>("nprocs");
    internal->io.DefineVariable<int>("ncolumns");

    io.DefineVariable<double>("boxxlo");
    io.DefineVariable<double>("boxxhi");
    io.DefineVariable<double>("boxylo");
    io.DefineVariable<double>("boxyhi");
    io.DefineVariable<double>("boxzlo");
    io.DefineVariable<double>("boxzhi");
    internal->io.DefineVariable<double>("boxxlo");
    internal->io.DefineVariable<double>("boxxhi");
    internal->io.DefineVariable<double>("boxylo");
    internal->io.DefineVariable<double>("boxyhi");
    internal->io.DefineVariable<double>("boxzlo");
    internal->io.DefineVariable<double>("boxzhi");

    io.DefineVariable<double>("boxxy");
    io.DefineVariable<double>("boxxz");
    io.DefineVariable<double>("boxyz");
    internal->io.DefineVariable<double>("boxxy");
    internal->io.DefineVariable<double>("boxxz");
    internal->io.DefineVariable<double>("boxyz");

    io.DefineAttribute<int>("triclinic",  domain->triclinic);
    io.DefineAttribute<int>("scaled",  scale_flag);
    io.DefineAttribute<int>("image",  image_flag);
    internal->io.DefineAttribute<int>("triclinic", domain->triclinic);
    internal->io.DefineAttribute<int>("scaled", scale_flag);
    internal->io.DefineAttribute<int>("image", image_flag);

    int *boundaryptr = reinterpret_cast<int *>(domain->boundary);
    io.DefineAttribute<int>("boundary", boundaryptr, 6);
    internal->io.DefineAttribute<int>("boundary", boundaryptr, 6);

    io.DefineAttribute<std::string>("columns",  columns);
    io.DefineAttribute<std::string>("boundarystr",  boundstr);
    io.DefineAttribute<std::string>("LAMMPS/dump_style",  "atom");
    io.DefineAttribute<std::string>("LAMMPS/version",  universe->version);
    io.DefineAttribute<std::string>("LAMMPS/num_ver",  universe->num_ver);
    internal->io.DefineAttribute<std::string>("columns", columns);
    internal->io.DefineAttribute<std::string>("boundarystr", boundstr);
    internal->io.DefineAttribute<std::string>("LAMMPS/dump_style", "atom");
    internal->io.DefineAttribute<std::string>("LAMMPS/version",
                                              universe->version);
    internal->io.DefineAttribute<std::string>("LAMMPS/num_ver",
                                              universe->num_ver);

    io.DefineVariable<uint64_t>("nme", {adios2::LocalValueDim}); // local dimension variable
    io.DefineVariable<uint64_t>("offset", {adios2::LocalValueDim}); // local dimension variable
    internal->io.DefineVariable<uint64_t>(
        "nme", {adios2::LocalValueDim}); // local dimension variable
    internal->io.DefineVariable<uint64_t>(
        "offset", {adios2::LocalValueDim}); // local dimension variable

    // atom table size is not known at the moment
    // it will be correctly defined at the moment of write
    size_t UnknownSizeYet = 1;
    size_t nColumns = static_cast<size_t>(size_one);
    varAtoms = io.DefineVariable<double>("atoms", 
                                         {UnknownSizeYet,nColumns}, 
                                         {UnknownSizeYet, 0}, 
    internal->varAtoms = internal->io.DefineVariable<double>(
        "atoms", {UnknownSizeYet, nColumns}, {UnknownSizeYet, 0},
        {UnknownSizeYet, nColumns});
}
+25 −33
Original line number Diff line number Diff line
@@ -12,44 +12,36 @@
------------------------------------------------------------------------- */

#ifdef DUMP_CLASS

// clang-format off
DumpStyle(atom/adios, DumpAtomADIOS)

// clang-format on
#else

#ifndef LMP_DUMP_ATOM_ADIOS_H
#define LMP_DUMP_ATOM_ADIOS_H

#include "dump_atom.h"
#include <stdlib.h>
#include <stdint.h>
#include "adios2.h"

namespace LAMMPS_NS {
namespace LAMMPS_NS
{

class DumpAtomADIOSInternal;

class DumpAtomADIOS : public DumpAtom {
class DumpAtomADIOS : public DumpAtom
{

public:
    DumpAtomADIOS(class LAMMPS *, int, char **);
    virtual ~DumpAtomADIOS();

protected:

  const std::string ioName="atom";   // name of adios group, referrable in adios2_config.xml
  adios2::ADIOS *ad = nullptr; // adios object
  adios2::IO io;    // adios group of variables and attributes in this dump
  adios2::Engine fh; // adios file/stream handle object
  adios2::Variable<double> varAtoms; // one ADIOS output variable we need to change
  uint64_t groupSize; // pre-calculate # of bytes written per processor in a step before writing anything
  uint64_t groupTotalSize; // ADIOS buffer size returned by adios_group_size(), valid only if size is > default 16MB ADIOS buffer
  std::string filecurrent;  // name of file for this round (with % and * replaced)

    virtual void openfile();
    virtual void write();
    virtual void init_style();

private:
    DumpAtomADIOSInternal *internal;
};

}

#endif
+232 −152

File changed.

Preview size limit exceeded, changes collapsed.

+39 −46
Original line number Diff line number Diff line
@@ -12,42 +12,35 @@
------------------------------------------------------------------------- */

#ifdef DUMP_CLASS

// clang-format off
DumpStyle(custom/adios, DumpCustomADIOS)

// clang-format on
#else

#ifndef LMP_DUMP_CUSTOM_ADIOS_H
#define LMP_DUMP_CUSTOM_ADIOS_H

#include "dump_custom.h"
#include <stdlib.h>
#include <stdint.h>
#include "adios2.h"

namespace LAMMPS_NS {
namespace LAMMPS_NS
{

class DumpCustomADIOSInternal;

class DumpCustomADIOS : public DumpCustom {
class DumpCustomADIOS : public DumpCustom
{
public:
    DumpCustomADIOS(class LAMMPS *, int, char **);
    virtual ~DumpCustomADIOS();

protected:

  const std::string ioName="custom";   // name of adios group, referrable in adios2_config.xml
  adios2::ADIOS *ad = nullptr; // adios object
  adios2::IO io;    // adios group of variables and attributes in this dump
  adios2::Engine fh; // adios file/stream handle object
  adios2::Variable<double> varAtoms; // one ADIOS output variable we need to change
  uint64_t groupsize; // pre-calculate # of bytes written per processor in a step before writing anything
  std::vector<std::string>columnNames; // list of column names for the atom table (individual list of 'columns' string)

    virtual void openfile();
    virtual void write();
    virtual void init_style();

private:
    DumpCustomADIOSInternal *internal;
};

}

#endif