update and improve ADIOS support
- modernize code - remove dead code and unused definitions, enums, and includes - create default adios2_config.xml file if it doesn't exist - enable and apply clang-format - update documentation
This commit is contained in:
@ -35,13 +35,21 @@ Examples
|
|||||||
Description
|
Description
|
||||||
"""""""""""
|
"""""""""""
|
||||||
|
|
||||||
Dump a snapshot of atom coordinates every N timesteps in the
|
Dump a snapshot of atom coordinates every N timesteps in the `ADIOS
|
||||||
`ADIOS <adios_>`_ based "BP" file format, or using different I/O solutions in ADIOS,
|
<adios_>`_ based "BP" file format, or using different I/O solutions in
|
||||||
to a stream that can be read on-line by another program.
|
ADIOS, to a stream that can be read on-line by another program.
|
||||||
ADIOS-BP files are binary, portable and self-describing.
|
ADIOS-BP files are binary, portable and self-describing.
|
||||||
|
|
||||||
.. _adios: https://github.com/ornladios/ADIOS2
|
.. _adios: https://github.com/ornladios/ADIOS2
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
To be able to use ADIOS, a file ``adios2_config.xml`` with specific
|
||||||
|
configuration settings is expected in the current working directory.
|
||||||
|
If the file is not present, LAMMPS will try to create a minimal
|
||||||
|
default file. Please refer to the ADIOS documentation for details on
|
||||||
|
how to adjust this file for optimal performance and desired features.
|
||||||
|
|
||||||
**Use from write_dump:**
|
**Use from write_dump:**
|
||||||
|
|
||||||
It is possible to use these dump styles with the
|
It is possible to use these dump styles with the
|
||||||
|
|||||||
39
src/ADIOS/adios_common.h
Normal file
39
src/ADIOS/adios_common.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/* -*- c++ -*- ----------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
https://www.lammps.org/, Sandia National Laboratories
|
||||||
|
Steve Plimpton, sjplimp@sandia.gov
|
||||||
|
|
||||||
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||||
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||||
|
certain rights in this software. This software is distributed under
|
||||||
|
the GNU General Public License.
|
||||||
|
|
||||||
|
See the README file in the top-level LAMMPS directory.
|
||||||
|
|
||||||
|
Contributed by Norbert Podhorszki (Oak Ridge National Laboratory)
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifndef LMP_ADIOS_COMMON_H
|
||||||
|
#define LMP_ADIOS_COMMON_H
|
||||||
|
|
||||||
|
// common definitions for all ADIOS package classes
|
||||||
|
|
||||||
|
static const char default_config[] = "<?xml version=\"1.0\"?>\n"
|
||||||
|
"<adios-config>\n"
|
||||||
|
" <io name=\"atom\">\n"
|
||||||
|
" <engine type=\"BP4\">\n"
|
||||||
|
" <parameter key=\"substreams\" value=\"1\"/>\n"
|
||||||
|
" </engine>\n"
|
||||||
|
" </io>\n"
|
||||||
|
" <io name=\"custom\">\n"
|
||||||
|
" <engine type=\"BP4\">\n"
|
||||||
|
" <parameter key=\"substreams\" value=\"1\"/>\n"
|
||||||
|
" </engine>\n"
|
||||||
|
" </io>\n"
|
||||||
|
" <io name=\"read_dump\">\n"
|
||||||
|
" <engine type=\"BP4\">\n"
|
||||||
|
" </engine>\n"
|
||||||
|
" </io>\n"
|
||||||
|
"</adios-config>\n";
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -1,4 +1,3 @@
|
|||||||
// clang-format off
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
https://www.lammps.org/, Sandia National Laboratories
|
https://www.lammps.org/, Sandia National Laboratories
|
||||||
@ -24,61 +23,58 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "universe.h"
|
#include "universe.h"
|
||||||
#include "update.h"
|
#include "update.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "adios2.h"
|
#include "adios2.h"
|
||||||
|
#include "adios_common.h"
|
||||||
|
|
||||||
using namespace LAMMPS_NS;
|
using namespace LAMMPS_NS;
|
||||||
|
|
||||||
#define MAX_TEXT_HEADER_SIZE 4096
|
namespace LAMMPS_NS {
|
||||||
#define DUMP_BUF_CHUNK_SIZE 16384
|
class DumpAtomADIOSInternal {
|
||||||
#define DUMP_BUF_INCREMENT_SIZE 4096
|
|
||||||
|
|
||||||
namespace LAMMPS_NS
|
public:
|
||||||
{
|
DumpAtomADIOSInternal(){};
|
||||||
class DumpAtomADIOSInternal
|
~DumpAtomADIOSInternal() = default;
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
// name of adios group, referrable in adios2_config.xml
|
||||||
DumpAtomADIOSInternal() {};
|
const std::string ioName = "atom";
|
||||||
~DumpAtomADIOSInternal() = default;
|
adios2::ADIOS *ad = nullptr; // adios object
|
||||||
|
adios2::IO io; // adios group of variables and attributes in this dump
|
||||||
// name of adios group, referrable in adios2_config.xml
|
adios2::Engine fh; // adios file/stream handle object
|
||||||
const std::string ioName = "atom";
|
// one ADIOS output variable we need to change every step
|
||||||
adios2::ADIOS *ad = nullptr; // adios object
|
adios2::Variable<double> varAtoms;
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
} // namespace LAMMPS_NS
|
} // namespace LAMMPS_NS
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
DumpAtomADIOS::DumpAtomADIOS(LAMMPS *lmp, int narg, char **arg)
|
DumpAtomADIOS::DumpAtomADIOS(LAMMPS *lmp, int narg, char **arg) : DumpAtom(lmp, narg, arg)
|
||||||
: DumpAtom(lmp, narg, arg)
|
|
||||||
{
|
{
|
||||||
internal = new DumpAtomADIOSInternal();
|
// create a default adios2_config.xml if it doesn't exist yet.
|
||||||
try {
|
FILE *cfgfp = fopen("adios2_config.xml", "r");
|
||||||
internal->ad =
|
if (!cfgfp) {
|
||||||
new adios2::ADIOS("adios2_config.xml", world, adios2::DebugON);
|
cfgfp = fopen("adios2_config.xml", "w");
|
||||||
} catch (std::ios_base::failure &e) {
|
if (cfgfp) fputs(default_config, cfgfp);
|
||||||
char str[256];
|
}
|
||||||
snprintf(str, sizeof(str), "ADIOS initialization failed with error: %s",
|
if (cfgfp) fclose(cfgfp);
|
||||||
e.what());
|
|
||||||
error->one(FLERR, str);
|
internal = new DumpAtomADIOSInternal();
|
||||||
}
|
try {
|
||||||
|
internal->ad = new adios2::ADIOS("adios2_config.xml", world, adios2::DebugON);
|
||||||
|
} catch (std::ios_base::failure &e) {
|
||||||
|
error->all(FLERR, "ADIOS initialization failed with error: {}", e.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
DumpAtomADIOS::~DumpAtomADIOS()
|
DumpAtomADIOS::~DumpAtomADIOS()
|
||||||
{
|
{
|
||||||
if (internal->fh) {
|
if (internal->fh) internal->fh.Close();
|
||||||
internal->fh.Close();
|
delete internal->ad;
|
||||||
}
|
delete internal;
|
||||||
delete internal->ad;
|
|
||||||
delete internal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
@ -129,228 +125,215 @@ void DumpAtomADIOS::openfile()
|
|||||||
|
|
||||||
void DumpAtomADIOS::write()
|
void DumpAtomADIOS::write()
|
||||||
{
|
{
|
||||||
if (domain->triclinic == 0) {
|
if (domain->triclinic == 0) {
|
||||||
boxxlo = domain->boxlo[0];
|
boxxlo = domain->boxlo[0];
|
||||||
boxxhi = domain->boxhi[0];
|
boxxhi = domain->boxhi[0];
|
||||||
boxylo = domain->boxlo[1];
|
boxylo = domain->boxlo[1];
|
||||||
boxyhi = domain->boxhi[1];
|
boxyhi = domain->boxhi[1];
|
||||||
boxzlo = domain->boxlo[2];
|
boxzlo = domain->boxlo[2];
|
||||||
boxzhi = domain->boxhi[2];
|
boxzhi = domain->boxhi[2];
|
||||||
} else {
|
} else {
|
||||||
boxxlo = domain->boxlo_bound[0];
|
boxxlo = domain->boxlo_bound[0];
|
||||||
boxxhi = domain->boxhi_bound[0];
|
boxxhi = domain->boxhi_bound[0];
|
||||||
boxylo = domain->boxlo_bound[1];
|
boxylo = domain->boxlo_bound[1];
|
||||||
boxyhi = domain->boxhi_bound[1];
|
boxyhi = domain->boxhi_bound[1];
|
||||||
boxzlo = domain->boxlo_bound[2];
|
boxzlo = domain->boxlo_bound[2];
|
||||||
boxzhi = domain->boxhi_bound[2];
|
boxzhi = domain->boxhi_bound[2];
|
||||||
boxxy = domain->xy;
|
boxxy = domain->xy;
|
||||||
boxxz = domain->xz;
|
boxxz = domain->xz;
|
||||||
boxyz = domain->yz;
|
boxyz = domain->yz;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nme = # of dump lines this proc contributes to dump
|
||||||
|
|
||||||
|
nme = count();
|
||||||
|
|
||||||
|
// ntotal = total # of atoms in snapshot
|
||||||
|
// atomOffset = sum of # of atoms up to this proc (exclusive prefix sum)
|
||||||
|
|
||||||
|
bigint bnme = nme;
|
||||||
|
MPI_Allreduce(&bnme, &ntotal, 1, MPI_LMP_BIGINT, MPI_SUM, world);
|
||||||
|
|
||||||
|
bigint atomOffset; // sum of all atoms on processes 0..me-1
|
||||||
|
MPI_Scan(&bnme, &atomOffset, 1, MPI_LMP_BIGINT, MPI_SUM, world);
|
||||||
|
atomOffset -= nme; // exclusive prefix sum needed
|
||||||
|
|
||||||
|
// Now we know the global size and the local subset size and offset
|
||||||
|
// of the atoms table
|
||||||
|
size_t nAtomsGlobal = static_cast<size_t>(ntotal);
|
||||||
|
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);
|
||||||
|
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
|
||||||
|
// if sorting on IDs also request ID list from pack()
|
||||||
|
// sort buf as needed
|
||||||
|
|
||||||
|
if (nme > maxbuf) {
|
||||||
|
maxbuf = nme;
|
||||||
|
memory->destroy(buf);
|
||||||
|
memory->create(buf, (maxbuf * size_one), "dump:buf");
|
||||||
|
}
|
||||||
|
if (sort_flag && sortcol == 0 && nme > maxids) {
|
||||||
|
maxids = nme;
|
||||||
|
memory->destroy(ids);
|
||||||
|
memory->create(ids, maxids, "dump:ids");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sort_flag && sortcol == 0)
|
||||||
|
pack(ids);
|
||||||
|
else
|
||||||
|
pack(nullptr);
|
||||||
|
if (sort_flag) sort();
|
||||||
|
|
||||||
|
openfile();
|
||||||
|
internal->fh.BeginStep();
|
||||||
|
// write info on data as scalars (by me==0)
|
||||||
|
if (me == 0) {
|
||||||
|
internal->fh.Put<uint64_t>("ntimestep", update->ntimestep);
|
||||||
|
internal->fh.Put<int>("nprocs", nprocs);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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
|
||||||
|
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
|
||||||
|
internal->fh.Put<double>(internal->varAtoms, buf);
|
||||||
|
internal->fh.EndStep(); // I/O will happen now...
|
||||||
|
|
||||||
// nme = # of dump lines this proc contributes to dump
|
if (multifile) internal->fh.Close();
|
||||||
|
|
||||||
nme = count();
|
|
||||||
|
|
||||||
// ntotal = total # of atoms in snapshot
|
|
||||||
// atomOffset = sum of # of atoms up to this proc (exclusive prefix sum)
|
|
||||||
|
|
||||||
bigint bnme = nme;
|
|
||||||
MPI_Allreduce(&bnme, &ntotal, 1, MPI_LMP_BIGINT, MPI_SUM, world);
|
|
||||||
|
|
||||||
bigint atomOffset; // sum of all atoms on processes 0..me-1
|
|
||||||
MPI_Scan(&bnme, &atomOffset, 1, MPI_LMP_BIGINT, MPI_SUM, world);
|
|
||||||
atomOffset -= nme; // exclusive prefix sum needed
|
|
||||||
|
|
||||||
// Now we know the global size and the local subset size and offset
|
|
||||||
// of the atoms table
|
|
||||||
size_t nAtomsGlobal = static_cast<size_t>(ntotal);
|
|
||||||
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);
|
|
||||||
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
|
|
||||||
// if sorting on IDs also request ID list from pack()
|
|
||||||
// sort buf as needed
|
|
||||||
|
|
||||||
if (nme > maxbuf) {
|
|
||||||
maxbuf = nme;
|
|
||||||
memory->destroy(buf);
|
|
||||||
memory->create(buf, (maxbuf * size_one), "dump:buf");
|
|
||||||
}
|
|
||||||
if (sort_flag && sortcol == 0 && nme > maxids) {
|
|
||||||
maxids = nme;
|
|
||||||
memory->destroy(ids);
|
|
||||||
memory->create(ids, maxids, "dump:ids");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sort_flag && sortcol == 0)
|
|
||||||
pack(ids);
|
|
||||||
else
|
|
||||||
pack(nullptr);
|
|
||||||
if (sort_flag)
|
|
||||||
sort();
|
|
||||||
|
|
||||||
openfile();
|
|
||||||
internal->fh.BeginStep();
|
|
||||||
// write info on data as scalars (by me==0)
|
|
||||||
if (me == 0) {
|
|
||||||
internal->fh.Put<uint64_t>("ntimestep", update->ntimestep);
|
|
||||||
internal->fh.Put<int>("nprocs", nprocs);
|
|
||||||
|
|
||||||
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) {
|
|
||||||
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
|
|
||||||
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
|
|
||||||
internal->fh.Put<double>(internal->varAtoms, buf);
|
|
||||||
internal->fh.EndStep(); // I/O will happen now...
|
|
||||||
|
|
||||||
if (multifile) {
|
|
||||||
internal->fh.Close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
void DumpAtomADIOS::init_style()
|
void DumpAtomADIOS::init_style()
|
||||||
{
|
{
|
||||||
if (image_flag == 0)
|
if (image_flag == 0)
|
||||||
size_one = 5;
|
size_one = 5;
|
||||||
else
|
else
|
||||||
size_one = 8;
|
size_one = 8;
|
||||||
|
|
||||||
// setup boundary string
|
// setup boundary string
|
||||||
|
|
||||||
domain->boundary_string(boundstr);
|
domain->boundary_string(boundstr);
|
||||||
|
|
||||||
// remove % from filename since ADIOS always writes a global file with
|
// remove % from filename since ADIOS always writes a global file with
|
||||||
// data/metadata
|
// data/metadata.
|
||||||
int len = strlen(filename);
|
char *ptr = strchr(filename, '%');
|
||||||
char *ptr = strchr(filename, '%');
|
if (ptr) {
|
||||||
if (ptr) {
|
while (*ptr) {
|
||||||
*ptr = '\0';
|
ptr[0] = ptr[1];
|
||||||
char *s = new char[len - 1];
|
++ptr;
|
||||||
snprintf(s, sizeof(s), "%s%s", filename, ptr + 1);
|
|
||||||
strncpy(filename, s, len);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// setup column string
|
// setup column string
|
||||||
|
|
||||||
std::vector<std::string> columnNames;
|
std::vector<std::string> columnNames;
|
||||||
|
|
||||||
if (scale_flag == 0 && image_flag == 0) {
|
if (scale_flag == 0 && image_flag == 0) {
|
||||||
columns = (char *)"id type x y z";
|
columns = (char *) "id type x y z";
|
||||||
columnNames = {"id", "type", "x", "y", "z"};
|
columnNames = {"id", "type", "x", "y", "z"};
|
||||||
} else if (scale_flag == 0 && image_flag == 1) {
|
} else if (scale_flag == 0 && image_flag == 1) {
|
||||||
columns = (char *)"id type x y z ix iy iz";
|
columns = (char *) "id type x y z ix iy iz";
|
||||||
columnNames = {"id", "type", "x", "y", "z", "ix", "iy", "iz"};
|
columnNames = {"id", "type", "x", "y", "z", "ix", "iy", "iz"};
|
||||||
} else if (scale_flag == 1 && image_flag == 0) {
|
} else if (scale_flag == 1 && image_flag == 0) {
|
||||||
columns = (char *)"id type xs ys zs";
|
columns = (char *) "id type xs ys zs";
|
||||||
columnNames = {"id", "type", "xs", "ys", "zs"};
|
columnNames = {"id", "type", "xs", "ys", "zs"};
|
||||||
} else if (scale_flag == 1 && image_flag == 1) {
|
} else if (scale_flag == 1 && image_flag == 1) {
|
||||||
columns = (char *)"id type xs ys zs ix iy iz";
|
columns = (char *) "id type xs ys zs ix iy iz";
|
||||||
columnNames = {"id", "type", "xs", "ys", "zs", "ix", "iy", "iz"};
|
columnNames = {"id", "type", "xs", "ys", "zs", "ix", "iy", "iz"};
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup function ptrs
|
// setup function ptrs
|
||||||
|
|
||||||
if (scale_flag == 1 && image_flag == 0 && domain->triclinic == 0)
|
if (scale_flag == 1 && image_flag == 0 && domain->triclinic == 0)
|
||||||
pack_choice = &DumpAtomADIOS::pack_scale_noimage;
|
pack_choice = &DumpAtomADIOS::pack_scale_noimage;
|
||||||
else if (scale_flag == 1 && image_flag == 1 && domain->triclinic == 0)
|
else if (scale_flag == 1 && image_flag == 1 && domain->triclinic == 0)
|
||||||
pack_choice = &DumpAtomADIOS::pack_scale_image;
|
pack_choice = &DumpAtomADIOS::pack_scale_image;
|
||||||
else if (scale_flag == 1 && image_flag == 0 && domain->triclinic == 1)
|
else if (scale_flag == 1 && image_flag == 0 && domain->triclinic == 1)
|
||||||
pack_choice = &DumpAtomADIOS::pack_scale_noimage_triclinic;
|
pack_choice = &DumpAtomADIOS::pack_scale_noimage_triclinic;
|
||||||
else if (scale_flag == 1 && image_flag == 1 && domain->triclinic == 1)
|
else if (scale_flag == 1 && image_flag == 1 && domain->triclinic == 1)
|
||||||
pack_choice = &DumpAtomADIOS::pack_scale_image_triclinic;
|
pack_choice = &DumpAtomADIOS::pack_scale_image_triclinic;
|
||||||
else if (scale_flag == 0 && image_flag == 0)
|
else if (scale_flag == 0 && image_flag == 0)
|
||||||
pack_choice = &DumpAtomADIOS::pack_noscale_noimage;
|
pack_choice = &DumpAtomADIOS::pack_noscale_noimage;
|
||||||
else if (scale_flag == 0 && image_flag == 1)
|
else if (scale_flag == 0 && image_flag == 1)
|
||||||
pack_choice = &DumpAtomADIOS::pack_noscale_image;
|
pack_choice = &DumpAtomADIOS::pack_noscale_image;
|
||||||
|
|
||||||
/* Define the group of variables for the atom style here since it's a fixed
|
/* Define the group of variables for the atom style here since it's a fixed
|
||||||
* set */
|
* set */
|
||||||
internal->io = internal->ad->DeclareIO(internal->ioName);
|
internal->io = internal->ad->DeclareIO(internal->ioName);
|
||||||
if (!internal->io.InConfigFile()) {
|
if (!internal->io.InConfigFile()) {
|
||||||
// if not defined by user, we can change the default settings
|
// if not defined by user, we can change the default settings
|
||||||
// BPFile is the default writer
|
// BPFile is the default writer
|
||||||
internal->io.SetEngine("BPFile");
|
internal->io.SetEngine("BPFile");
|
||||||
int num_aggregators = multiproc;
|
int num_aggregators = multiproc;
|
||||||
if (num_aggregators == 0)
|
if (num_aggregators == 0) num_aggregators = 1;
|
||||||
num_aggregators = 1;
|
auto nstreams = std::to_string(num_aggregators);
|
||||||
char nstreams[128];
|
internal->io.SetParameters({{"substreams", nstreams}});
|
||||||
snprintf(nstreams, sizeof(nstreams), "%d", num_aggregators);
|
if (me == 0)
|
||||||
internal->io.SetParameters({{"substreams", nstreams}});
|
utils::logmesg(lmp, "ADIOS method for {} is n-to-m (aggregation with {} writers)\n", filename,
|
||||||
if (me == 0 && screen)
|
nstreams);
|
||||||
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>("ntimestep");
|
||||||
internal->io.DefineVariable<uint64_t>("natoms");
|
internal->io.DefineVariable<uint64_t>("natoms");
|
||||||
|
|
||||||
internal->io.DefineVariable<int>("nprocs");
|
internal->io.DefineVariable<int>("nprocs");
|
||||||
internal->io.DefineVariable<int>("ncolumns");
|
internal->io.DefineVariable<int>("ncolumns");
|
||||||
|
|
||||||
internal->io.DefineVariable<double>("boxxlo");
|
internal->io.DefineVariable<double>("boxxlo");
|
||||||
internal->io.DefineVariable<double>("boxxhi");
|
internal->io.DefineVariable<double>("boxxhi");
|
||||||
internal->io.DefineVariable<double>("boxylo");
|
internal->io.DefineVariable<double>("boxylo");
|
||||||
internal->io.DefineVariable<double>("boxyhi");
|
internal->io.DefineVariable<double>("boxyhi");
|
||||||
internal->io.DefineVariable<double>("boxzlo");
|
internal->io.DefineVariable<double>("boxzlo");
|
||||||
internal->io.DefineVariable<double>("boxzhi");
|
internal->io.DefineVariable<double>("boxzhi");
|
||||||
|
|
||||||
internal->io.DefineVariable<double>("boxxy");
|
internal->io.DefineVariable<double>("boxxy");
|
||||||
internal->io.DefineVariable<double>("boxxz");
|
internal->io.DefineVariable<double>("boxxz");
|
||||||
internal->io.DefineVariable<double>("boxyz");
|
internal->io.DefineVariable<double>("boxyz");
|
||||||
|
|
||||||
internal->io.DefineAttribute<int>("triclinic", domain->triclinic);
|
internal->io.DefineAttribute<int>("triclinic", domain->triclinic);
|
||||||
internal->io.DefineAttribute<int>("scaled", scale_flag);
|
internal->io.DefineAttribute<int>("scaled", scale_flag);
|
||||||
internal->io.DefineAttribute<int>("image", image_flag);
|
internal->io.DefineAttribute<int>("image", image_flag);
|
||||||
|
|
||||||
int *boundaryptr = reinterpret_cast<int *>(domain->boundary);
|
int *boundaryptr = reinterpret_cast<int *>(domain->boundary);
|
||||||
internal->io.DefineAttribute<int>("boundary", boundaryptr, 6);
|
internal->io.DefineAttribute<int>("boundary", boundaryptr, 6);
|
||||||
|
|
||||||
size_t nColumns = static_cast<size_t>(size_one);
|
size_t nColumns = static_cast<size_t>(size_one);
|
||||||
internal->io.DefineAttribute<std::string>("columns", columnNames.data(),
|
internal->io.DefineAttribute<std::string>("columns", columnNames.data(), nColumns);
|
||||||
nColumns);
|
internal->io.DefineAttribute<std::string>("columnstr", columns);
|
||||||
internal->io.DefineAttribute<std::string>("columnstr", columns);
|
internal->io.DefineAttribute<std::string>("boundarystr", boundstr);
|
||||||
internal->io.DefineAttribute<std::string>("boundarystr", boundstr);
|
internal->io.DefineAttribute<std::string>("LAMMPS/dump_style", "atom");
|
||||||
internal->io.DefineAttribute<std::string>("LAMMPS/dump_style", "atom");
|
internal->io.DefineAttribute<std::string>("LAMMPS/version", lmp->version);
|
||||||
internal->io.DefineAttribute<std::string>("LAMMPS/version",
|
internal->io.DefineAttribute<std::string>("LAMMPS/num_ver", std::to_string(lmp->num_ver));
|
||||||
lmp->version);
|
|
||||||
internal->io.DefineAttribute<std::string>("LAMMPS/num_ver",
|
|
||||||
std::to_string(lmp->num_ver));
|
|
||||||
|
|
||||||
internal->io.DefineVariable<uint64_t>(
|
// local dimension variables
|
||||||
"nme", {adios2::LocalValueDim}); // local dimension variable
|
internal->io.DefineVariable<uint64_t>("nme", {adios2::LocalValueDim});
|
||||||
internal->io.DefineVariable<uint64_t>(
|
internal->io.DefineVariable<uint64_t>("offset", {adios2::LocalValueDim});
|
||||||
"offset", {adios2::LocalValueDim}); // local dimension variable
|
|
||||||
|
|
||||||
// atom table size is not known at the moment
|
// atom table size is not known at the moment
|
||||||
// it will be correctly defined at the moment of write
|
// it will be correctly defined at the moment of write
|
||||||
size_t UnknownSizeYet = 1;
|
size_t UnknownSizeYet = 1;
|
||||||
internal->varAtoms = internal->io.DefineVariable<double>(
|
internal->varAtoms = internal->io.DefineVariable<double>(
|
||||||
"atoms", {UnknownSizeYet, nColumns}, {UnknownSizeYet, 0},
|
"atoms", {UnknownSizeYet, nColumns}, {UnknownSizeYet, 0}, {UnknownSizeYet, nColumns});
|
||||||
{UnknownSizeYet, nColumns});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// clang-format off
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
https://www.lammps.org/, Sandia National Laboratories
|
https://www.lammps.org/, Sandia National Laboratories
|
||||||
@ -17,152 +16,77 @@
|
|||||||
------------------------------------------------------------------------- */
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#include "dump_custom_adios.h"
|
#include "dump_custom_adios.h"
|
||||||
|
|
||||||
#include "atom.h"
|
#include "atom.h"
|
||||||
#include "compute.h"
|
#include "compute.h"
|
||||||
#include "domain.h"
|
#include "domain.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "fix.h"
|
#include "fix.h"
|
||||||
#include "force.h"
|
|
||||||
#include "group.h"
|
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "modify.h"
|
#include "modify.h"
|
||||||
#include "region.h"
|
|
||||||
#include "universe.h"
|
|
||||||
#include "update.h"
|
#include "update.h"
|
||||||
#include "variable.h"
|
#include "variable.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "adios2.h"
|
#include "adios2.h"
|
||||||
|
#include "adios_common.h"
|
||||||
|
|
||||||
using namespace LAMMPS_NS;
|
using namespace LAMMPS_NS;
|
||||||
|
|
||||||
#define MAX_TEXT_HEADER_SIZE 4096
|
namespace LAMMPS_NS {
|
||||||
#define DUMP_BUF_CHUNK_SIZE 16384
|
class DumpCustomADIOSInternal {
|
||||||
#define DUMP_BUF_INCREMENT_SIZE 4096
|
|
||||||
|
|
||||||
enum {
|
public:
|
||||||
ID,
|
DumpCustomADIOSInternal(){};
|
||||||
MOL,
|
~DumpCustomADIOSInternal() = default;
|
||||||
TYPE,
|
|
||||||
ELEMENT,
|
// name of adios group, referrable in adios2_config.xml
|
||||||
MASS,
|
const std::string ioName = "custom";
|
||||||
X,
|
adios2::ADIOS *ad = nullptr; // adios object
|
||||||
Y,
|
adios2::IO io; // adios group of variables and attributes in this dump
|
||||||
Z,
|
adios2::Engine fh; // adios file/stream handle object
|
||||||
XS,
|
// one ADIOS output variable we need to change every step
|
||||||
YS,
|
adios2::Variable<double> varAtoms;
|
||||||
ZS,
|
// list of column names for the atom table
|
||||||
XSTRI,
|
// (individual list of 'columns' string)
|
||||||
YSTRI,
|
std::vector<std::string> columnNames;
|
||||||
ZSTRI,
|
|
||||||
XU,
|
|
||||||
YU,
|
|
||||||
ZU,
|
|
||||||
XUTRI,
|
|
||||||
YUTRI,
|
|
||||||
ZUTRI,
|
|
||||||
XSU,
|
|
||||||
YSU,
|
|
||||||
ZSU,
|
|
||||||
XSUTRI,
|
|
||||||
YSUTRI,
|
|
||||||
ZSUTRI,
|
|
||||||
IX,
|
|
||||||
IY,
|
|
||||||
IZ,
|
|
||||||
VX,
|
|
||||||
VY,
|
|
||||||
VZ,
|
|
||||||
FX,
|
|
||||||
FY,
|
|
||||||
FZ,
|
|
||||||
Q,
|
|
||||||
MUX,
|
|
||||||
MUY,
|
|
||||||
MUZ,
|
|
||||||
MU,
|
|
||||||
RADIUS,
|
|
||||||
DIAMETER,
|
|
||||||
OMEGAX,
|
|
||||||
OMEGAY,
|
|
||||||
OMEGAZ,
|
|
||||||
ANGMOMX,
|
|
||||||
ANGMOMY,
|
|
||||||
ANGMOMZ,
|
|
||||||
TQX,
|
|
||||||
TQY,
|
|
||||||
TQZ,
|
|
||||||
SPIN,
|
|
||||||
ERADIUS,
|
|
||||||
ERVEL,
|
|
||||||
ERFORCE,
|
|
||||||
COMPUTE,
|
|
||||||
FIX,
|
|
||||||
VARIABLE
|
|
||||||
};
|
};
|
||||||
enum { LT, LE, GT, GE, EQ, NEQ };
|
} // namespace LAMMPS_NS
|
||||||
enum { INT, DOUBLE, STRING, BIGINT }; // same as in DumpCustom
|
|
||||||
|
|
||||||
namespace LAMMPS_NS
|
|
||||||
{
|
|
||||||
class DumpCustomADIOSInternal
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
DumpCustomADIOSInternal() {};
|
|
||||||
~DumpCustomADIOSInternal() = default;
|
|
||||||
|
|
||||||
// name of adios group, referrable in adios2_config.xml
|
|
||||||
const std::string ioName = "custom";
|
|
||||||
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;
|
|
||||||
// list of column names for the atom table
|
|
||||||
// (individual list of 'columns' string)
|
|
||||||
std::vector<std::string> columnNames;
|
|
||||||
};
|
|
||||||
} // namespace LAMMPS_NS
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
DumpCustomADIOS::DumpCustomADIOS(LAMMPS *lmp, int narg, char **arg)
|
DumpCustomADIOS::DumpCustomADIOS(LAMMPS *lmp, int narg, char **arg) : DumpCustom(lmp, narg, arg)
|
||||||
: DumpCustom(lmp, narg, arg)
|
|
||||||
{
|
{
|
||||||
internal = new DumpCustomADIOSInternal();
|
// create a default adios2_config.xml if it doesn't exist yet.
|
||||||
try {
|
FILE *cfgfp = fopen("adios2_config.xml", "r");
|
||||||
internal->ad =
|
if (!cfgfp) {
|
||||||
new adios2::ADIOS("adios2_config.xml", world, adios2::DebugON);
|
cfgfp = fopen("adios2_config.xml", "w");
|
||||||
} catch (std::ios_base::failure &e) {
|
if (cfgfp) fputs(default_config, cfgfp);
|
||||||
char str[256];
|
}
|
||||||
snprintf(str, sizeof(str), "ADIOS initialization failed with error: %s",
|
if (cfgfp) fclose(cfgfp);
|
||||||
e.what());
|
|
||||||
error->one(FLERR, str);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (screen) fprintf(screen, "DumpCustomADIOS constructor: nvariable=%d
|
internal = new DumpCustomADIOSInternal();
|
||||||
// id_variable=%p, variables=%p, nfield=%d, earg=%p\n", nvariable,
|
try {
|
||||||
// id_variable, variable, nfield, earg);
|
internal->ad = new adios2::ADIOS("adios2_config.xml", world, adios2::DebugON);
|
||||||
internal->columnNames.reserve(nfield);
|
} catch (std::ios_base::failure &e) {
|
||||||
for (int i = 0; i < nfield; ++i) {
|
error->all(FLERR, "ADIOS initialization failed with error: {}", e.what());
|
||||||
internal->columnNames.push_back(earg[i]);
|
}
|
||||||
// if (screen) fprintf(screen, "earg[%d] = '%s'\n", i, earg[i]);
|
|
||||||
}
|
internal->columnNames.reserve(nfield);
|
||||||
|
for (int i = 0; i < nfield; ++i) { internal->columnNames.push_back(earg[i]); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
DumpCustomADIOS::~DumpCustomADIOS()
|
DumpCustomADIOS::~DumpCustomADIOS()
|
||||||
{
|
{
|
||||||
internal->columnNames.clear();
|
internal->columnNames.clear();
|
||||||
if (internal->fh) {
|
if (internal->fh) { internal->fh.Close(); }
|
||||||
internal->fh.Close();
|
delete internal->ad;
|
||||||
}
|
delete internal;
|
||||||
delete internal->ad;
|
|
||||||
delete internal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
@ -211,233 +135,214 @@ void DumpCustomADIOS::openfile()
|
|||||||
|
|
||||||
void DumpCustomADIOS::write()
|
void DumpCustomADIOS::write()
|
||||||
{
|
{
|
||||||
if (domain->triclinic == 0) {
|
if (domain->triclinic == 0) {
|
||||||
boxxlo = domain->boxlo[0];
|
boxxlo = domain->boxlo[0];
|
||||||
boxxhi = domain->boxhi[0];
|
boxxhi = domain->boxhi[0];
|
||||||
boxylo = domain->boxlo[1];
|
boxylo = domain->boxlo[1];
|
||||||
boxyhi = domain->boxhi[1];
|
boxyhi = domain->boxhi[1];
|
||||||
boxzlo = domain->boxlo[2];
|
boxzlo = domain->boxlo[2];
|
||||||
boxzhi = domain->boxhi[2];
|
boxzhi = domain->boxhi[2];
|
||||||
} else {
|
} else {
|
||||||
boxxlo = domain->boxlo_bound[0];
|
boxxlo = domain->boxlo_bound[0];
|
||||||
boxxhi = domain->boxhi_bound[0];
|
boxxhi = domain->boxhi_bound[0];
|
||||||
boxylo = domain->boxlo_bound[1];
|
boxylo = domain->boxlo_bound[1];
|
||||||
boxyhi = domain->boxhi_bound[1];
|
boxyhi = domain->boxhi_bound[1];
|
||||||
boxzlo = domain->boxlo_bound[2];
|
boxzlo = domain->boxlo_bound[2];
|
||||||
boxzhi = domain->boxhi_bound[2];
|
boxzhi = domain->boxhi_bound[2];
|
||||||
boxxy = domain->xy;
|
boxxy = domain->xy;
|
||||||
boxxz = domain->xz;
|
boxxz = domain->xz;
|
||||||
boxyz = domain->yz;
|
boxyz = domain->yz;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nme = # of dump lines this proc contributes to dump
|
||||||
|
|
||||||
|
nme = count();
|
||||||
|
|
||||||
|
// ntotal = total # of atoms in snapshot
|
||||||
|
// atomOffset = sum of # of atoms up to this proc (exclusive prefix sum)
|
||||||
|
|
||||||
|
bigint bnme = nme;
|
||||||
|
MPI_Allreduce(&bnme, &ntotal, 1, MPI_LMP_BIGINT, MPI_SUM, world);
|
||||||
|
|
||||||
|
bigint atomOffset; // sum of all atoms on processes 0..me-1
|
||||||
|
MPI_Scan(&bnme, &atomOffset, 1, MPI_LMP_BIGINT, MPI_SUM, world);
|
||||||
|
atomOffset -= nme; // exclusive prefix sum needed
|
||||||
|
|
||||||
|
// Now we know the global size and the local subset size and offset
|
||||||
|
// of the atoms table
|
||||||
|
size_t nAtomsGlobal = static_cast<size_t>(ntotal);
|
||||||
|
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);
|
||||||
|
internal->varAtoms.SetShape({nAtomsGlobal, nColumns});
|
||||||
|
internal->varAtoms.SetSelection({{startRow, 0}, {nAtomsLocal, nColumns}});
|
||||||
|
|
||||||
|
// insure filewriter proc can receive everyone's info
|
||||||
|
// limit nmax*size_one to int since used as arg in MPI_Rsend() below
|
||||||
|
// pack my data into buf
|
||||||
|
// if sorting on IDs also request ID list from pack()
|
||||||
|
// sort buf as needed
|
||||||
|
|
||||||
|
if (nme > maxbuf) {
|
||||||
|
if ((bigint) nme * size_one > MAXSMALLINT) error->all(FLERR, "Too much per-proc info for dump");
|
||||||
|
maxbuf = nme;
|
||||||
|
memory->destroy(buf);
|
||||||
|
memory->create(buf, (maxbuf * size_one), "dump:buf");
|
||||||
|
}
|
||||||
|
if (sort_flag && sortcol == 0 && nme > maxids) {
|
||||||
|
maxids = nme;
|
||||||
|
memory->destroy(ids);
|
||||||
|
memory->create(ids, maxids, "dump:ids");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sort_flag && sortcol == 0)
|
||||||
|
pack(ids);
|
||||||
|
else
|
||||||
|
pack(nullptr);
|
||||||
|
if (sort_flag) sort();
|
||||||
|
|
||||||
|
openfile();
|
||||||
|
internal->fh.BeginStep();
|
||||||
|
// write info on data as scalars (by me==0)
|
||||||
|
if (me == 0) {
|
||||||
|
internal->fh.Put<uint64_t>("ntimestep", update->ntimestep);
|
||||||
|
internal->fh.Put<int>("nprocs", nprocs);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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
|
||||||
|
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
|
||||||
|
internal->fh.Put<double>("atoms", buf);
|
||||||
|
internal->fh.EndStep(); // I/O will happen now...
|
||||||
|
|
||||||
// nme = # of dump lines this proc contributes to dump
|
if (multifile) { internal->fh.Close(); }
|
||||||
|
|
||||||
nme = count();
|
|
||||||
|
|
||||||
// ntotal = total # of atoms in snapshot
|
|
||||||
// atomOffset = sum of # of atoms up to this proc (exclusive prefix sum)
|
|
||||||
|
|
||||||
bigint bnme = nme;
|
|
||||||
MPI_Allreduce(&bnme, &ntotal, 1, MPI_LMP_BIGINT, MPI_SUM, world);
|
|
||||||
|
|
||||||
bigint atomOffset; // sum of all atoms on processes 0..me-1
|
|
||||||
MPI_Scan(&bnme, &atomOffset, 1, MPI_LMP_BIGINT, MPI_SUM, world);
|
|
||||||
atomOffset -= nme; // exclusive prefix sum needed
|
|
||||||
|
|
||||||
// Now we know the global size and the local subset size and offset
|
|
||||||
// of the atoms table
|
|
||||||
size_t nAtomsGlobal = static_cast<size_t>(ntotal);
|
|
||||||
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);
|
|
||||||
internal->varAtoms.SetShape({nAtomsGlobal, nColumns});
|
|
||||||
internal->varAtoms.SetSelection({{startRow, 0}, {nAtomsLocal, nColumns}});
|
|
||||||
|
|
||||||
// insure filewriter proc can receive everyone's info
|
|
||||||
// limit nmax*size_one to int since used as arg in MPI_Rsend() below
|
|
||||||
// pack my data into buf
|
|
||||||
// if sorting on IDs also request ID list from pack()
|
|
||||||
// sort buf as needed
|
|
||||||
|
|
||||||
if (nme > maxbuf) {
|
|
||||||
if ((bigint)nme * size_one > MAXSMALLINT)
|
|
||||||
error->all(FLERR, "Too much per-proc info for dump");
|
|
||||||
maxbuf = nme;
|
|
||||||
memory->destroy(buf);
|
|
||||||
memory->create(buf, (maxbuf * size_one), "dump:buf");
|
|
||||||
}
|
|
||||||
if (sort_flag && sortcol == 0 && nme > maxids) {
|
|
||||||
maxids = nme;
|
|
||||||
memory->destroy(ids);
|
|
||||||
memory->create(ids, maxids, "dump:ids");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sort_flag && sortcol == 0)
|
|
||||||
pack(ids);
|
|
||||||
else
|
|
||||||
pack(nullptr);
|
|
||||||
if (sort_flag)
|
|
||||||
sort();
|
|
||||||
|
|
||||||
openfile();
|
|
||||||
internal->fh.BeginStep();
|
|
||||||
// write info on data as scalars (by me==0)
|
|
||||||
if (me == 0) {
|
|
||||||
internal->fh.Put<uint64_t>("ntimestep", update->ntimestep);
|
|
||||||
internal->fh.Put<int>("nprocs", nprocs);
|
|
||||||
|
|
||||||
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) {
|
|
||||||
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
|
|
||||||
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
|
|
||||||
internal->fh.Put<double>("atoms", buf);
|
|
||||||
internal->fh.EndStep(); // I/O will happen now...
|
|
||||||
|
|
||||||
if (multifile) {
|
|
||||||
internal->fh.Close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
void DumpCustomADIOS::init_style()
|
void DumpCustomADIOS::init_style()
|
||||||
{
|
{
|
||||||
|
// setup boundary string
|
||||||
|
|
||||||
// setup boundary string
|
domain->boundary_string(boundstr);
|
||||||
|
|
||||||
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
|
char *ptr = strchr(filename, '%');
|
||||||
// data/metadata
|
if (ptr) {
|
||||||
int len = strlen(filename);
|
while (*ptr) {
|
||||||
char *ptr = strchr(filename, '%');
|
ptr[0] = ptr[1];
|
||||||
if (ptr) {
|
++ptr;
|
||||||
*ptr = '\0';
|
|
||||||
char *s = new char[len - 1];
|
|
||||||
sprintf(s, "%s%s", filename, ptr + 1);
|
|
||||||
strncpy(filename, s, len);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* The next four loops are copied from dump_custom_mpiio, but nothing is
|
/* The next four loops are copied from dump_custom_mpiio, but nothing is
|
||||||
* done with them.
|
* done with them.
|
||||||
* It is unclear why we need them here.
|
* It is unclear why we need them here.
|
||||||
* For metadata, variable[] will be written out as an ADIOS attribute if
|
* For metadata, variable[] will be written out as an ADIOS attribute if
|
||||||
* nvariable>0
|
* nvariable>0
|
||||||
*/
|
*/
|
||||||
// find current ptr for each compute,fix,variable
|
// find current ptr for each compute,fix,variable
|
||||||
// check that fix frequency is acceptable
|
// check that fix frequency is acceptable
|
||||||
int icompute;
|
int icompute;
|
||||||
for (int i = 0; i < ncompute; i++) {
|
for (int i = 0; i < ncompute; i++) {
|
||||||
icompute = modify->find_compute(id_compute[i]);
|
icompute = modify->find_compute(id_compute[i]);
|
||||||
if (icompute < 0)
|
if (icompute < 0) error->all(FLERR, "Could not find dump custom compute ID");
|
||||||
error->all(FLERR, "Could not find dump custom compute ID");
|
compute[i] = modify->compute[icompute];
|
||||||
compute[i] = modify->compute[icompute];
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int ifix;
|
int ifix;
|
||||||
for (int i = 0; i < nfix; i++) {
|
for (int i = 0; i < nfix; i++) {
|
||||||
ifix = modify->find_fix(id_fix[i]);
|
ifix = modify->find_fix(id_fix[i]);
|
||||||
if (ifix < 0)
|
if (ifix < 0) error->all(FLERR, "Could not find dump custom fix ID");
|
||||||
error->all(FLERR, "Could not find dump custom fix ID");
|
fix[i] = modify->fix[ifix];
|
||||||
fix[i] = modify->fix[ifix];
|
if (nevery % modify->fix[ifix]->peratom_freq)
|
||||||
if (nevery % modify->fix[ifix]->peratom_freq)
|
error->all(FLERR, "Dump custom and fix not computed at compatible times");
|
||||||
error->all(FLERR,
|
}
|
||||||
"Dump custom and fix not computed at compatible times");
|
|
||||||
}
|
|
||||||
|
|
||||||
int ivariable;
|
int ivariable;
|
||||||
for (int i = 0; i < nvariable; i++) {
|
for (int i = 0; i < nvariable; i++) {
|
||||||
ivariable = input->variable->find(id_variable[i]);
|
ivariable = input->variable->find(id_variable[i]);
|
||||||
if (ivariable < 0)
|
if (ivariable < 0) error->all(FLERR, "Could not find dump custom variable name");
|
||||||
error->all(FLERR, "Could not find dump custom variable name");
|
variable[i] = ivariable;
|
||||||
variable[i] = ivariable;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// set index and check validity of region
|
// set index and check validity of region
|
||||||
if (iregion >= 0) {
|
if (iregion >= 0) {
|
||||||
iregion = domain->find_region(idregion);
|
iregion = domain->find_region(idregion);
|
||||||
if (iregion == -1)
|
if (iregion == -1) error->all(FLERR, "Region ID for dump custom does not exist");
|
||||||
error->all(FLERR, "Region ID for dump custom does not exist");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Define the group of variables for the atom style here since it's a fixed
|
/* Define the group of variables for the atom style here since it's a fixed
|
||||||
* set */
|
* set */
|
||||||
internal->io = internal->ad->DeclareIO(internal->ioName);
|
internal->io = internal->ad->DeclareIO(internal->ioName);
|
||||||
if (!internal->io.InConfigFile()) {
|
if (!internal->io.InConfigFile()) {
|
||||||
// if not defined by user, we can change the default settings
|
// if not defined by user, we can change the default settings
|
||||||
// BPFile is the default writer
|
// BPFile is the default writer
|
||||||
internal->io.SetEngine("BPFile");
|
internal->io.SetEngine("BPFile");
|
||||||
int num_aggregators = multiproc;
|
int num_aggregators = multiproc;
|
||||||
if (num_aggregators == 0)
|
if (num_aggregators == 0) num_aggregators = 1;
|
||||||
num_aggregators = 1;
|
auto nstreams = std::to_string(num_aggregators);
|
||||||
char nstreams[128];
|
internal->io.SetParameters({{"substreams", nstreams}});
|
||||||
sprintf(nstreams, "%d", num_aggregators);
|
if (me == 0)
|
||||||
internal->io.SetParameters({{"substreams", nstreams}});
|
utils::logmesg(lmp, "ADIOS method for {} is n-to-m (aggregation with {} writers)\n", filename,
|
||||||
if (me == 0 && screen)
|
nstreams);
|
||||||
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>("ntimestep");
|
||||||
internal->io.DefineVariable<uint64_t>("natoms");
|
internal->io.DefineVariable<uint64_t>("natoms");
|
||||||
|
|
||||||
internal->io.DefineVariable<int>("nprocs");
|
internal->io.DefineVariable<int>("nprocs");
|
||||||
internal->io.DefineVariable<int>("ncolumns");
|
internal->io.DefineVariable<int>("ncolumns");
|
||||||
|
|
||||||
internal->io.DefineVariable<double>("boxxlo");
|
internal->io.DefineVariable<double>("boxxlo");
|
||||||
internal->io.DefineVariable<double>("boxxhi");
|
internal->io.DefineVariable<double>("boxxhi");
|
||||||
internal->io.DefineVariable<double>("boxylo");
|
internal->io.DefineVariable<double>("boxylo");
|
||||||
internal->io.DefineVariable<double>("boxyhi");
|
internal->io.DefineVariable<double>("boxyhi");
|
||||||
internal->io.DefineVariable<double>("boxzlo");
|
internal->io.DefineVariable<double>("boxzlo");
|
||||||
internal->io.DefineVariable<double>("boxzhi");
|
internal->io.DefineVariable<double>("boxzhi");
|
||||||
|
|
||||||
internal->io.DefineVariable<double>("boxxy");
|
internal->io.DefineVariable<double>("boxxy");
|
||||||
internal->io.DefineVariable<double>("boxxz");
|
internal->io.DefineVariable<double>("boxxz");
|
||||||
internal->io.DefineVariable<double>("boxyz");
|
internal->io.DefineVariable<double>("boxyz");
|
||||||
|
|
||||||
internal->io.DefineAttribute<int>("triclinic", domain->triclinic);
|
internal->io.DefineAttribute<int>("triclinic", domain->triclinic);
|
||||||
|
|
||||||
int *boundaryptr = reinterpret_cast<int *>(domain->boundary);
|
int *boundaryptr = reinterpret_cast<int *>(domain->boundary);
|
||||||
internal->io.DefineAttribute<int>("boundary", boundaryptr, 6);
|
internal->io.DefineAttribute<int>("boundary", boundaryptr, 6);
|
||||||
|
|
||||||
size_t nColumns = static_cast<size_t>(size_one);
|
size_t nColumns = static_cast<size_t>(size_one);
|
||||||
internal->io.DefineAttribute<std::string>(
|
internal->io.DefineAttribute<std::string>("columns", internal->columnNames.data(), nColumns);
|
||||||
"columns", internal->columnNames.data(), nColumns);
|
internal->io.DefineAttribute<std::string>("columnstr", columns);
|
||||||
internal->io.DefineAttribute<std::string>("columnstr", columns);
|
internal->io.DefineAttribute<std::string>("boundarystr", boundstr);
|
||||||
internal->io.DefineAttribute<std::string>("boundarystr", boundstr);
|
internal->io.DefineAttribute<std::string>("LAMMPS/dump_style", "custom");
|
||||||
internal->io.DefineAttribute<std::string>("LAMMPS/dump_style", "custom");
|
internal->io.DefineAttribute<std::string>("LAMMPS/version", lmp->version);
|
||||||
internal->io.DefineAttribute<std::string>("LAMMPS/version",
|
internal->io.DefineAttribute<std::string>("LAMMPS/num_ver", std::to_string(lmp->num_ver));
|
||||||
lmp->version);
|
|
||||||
internal->io.DefineAttribute<std::string>("LAMMPS/num_ver",
|
|
||||||
std::to_string(lmp->num_ver));
|
|
||||||
|
|
||||||
internal->io.DefineVariable<uint64_t>(
|
internal->io.DefineVariable<uint64_t>("nme",
|
||||||
"nme", {adios2::LocalValueDim}); // local dimension variable
|
{adios2::LocalValueDim}); // local dimension variable
|
||||||
internal->io.DefineVariable<uint64_t>(
|
internal->io.DefineVariable<uint64_t>("offset",
|
||||||
"offset", {adios2::LocalValueDim}); // local dimension variable
|
{adios2::LocalValueDim}); // local dimension variable
|
||||||
|
|
||||||
// atom table size is not known at the moment
|
// atom table size is not known at the moment
|
||||||
// it will be correctly defined at the moment of write
|
// it will be correctly defined at the moment of write
|
||||||
size_t UnknownSizeYet = 1;
|
size_t UnknownSizeYet = 1;
|
||||||
internal->varAtoms = internal->io.DefineVariable<double>(
|
internal->varAtoms = internal->io.DefineVariable<double>(
|
||||||
"atoms", {UnknownSizeYet, nColumns}, {UnknownSizeYet, 0},
|
"atoms", {UnknownSizeYet, nColumns}, {UnknownSizeYet, 0}, {UnknownSizeYet, nColumns});
|
||||||
{UnknownSizeYet, nColumns});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// clang-format off
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
https://www.lammps.org/, Sandia National Laboratories
|
https://www.lammps.org/, Sandia National Laboratories
|
||||||
@ -17,20 +16,20 @@
|
|||||||
------------------------------------------------------------------------- */
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#include "reader_adios.h"
|
#include "reader_adios.h"
|
||||||
|
|
||||||
#include "comm.h"
|
#include "comm.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "adios2.h"
|
#include "adios2.h"
|
||||||
#include "math_const.h"
|
#include "adios_common.h"
|
||||||
|
|
||||||
using namespace LAMMPS_NS;
|
using namespace LAMMPS_NS;
|
||||||
|
|
||||||
using namespace MathConst;
|
|
||||||
|
|
||||||
// also in read_dump.cpp
|
// also in read_dump.cpp
|
||||||
|
|
||||||
enum { ID, TYPE, X, Y, Z, VX, VY, VZ, Q, IX, IY, IZ, FX, FY, FZ };
|
enum { ID, TYPE, X, Y, Z, VX, VY, VZ, Q, IX, IY, IZ, FX, FY, FZ };
|
||||||
@ -38,78 +37,69 @@ enum { UNSET, NOSCALE_NOWRAP, NOSCALE_WRAP, SCALE_NOWRAP, SCALE_WRAP };
|
|||||||
|
|
||||||
#define SMALL 1.0e-6
|
#define SMALL 1.0e-6
|
||||||
|
|
||||||
// true if the difference between two floats is "small".
|
namespace LAMMPS_NS {
|
||||||
// cannot use fabsf() since it is not fully portable.
|
class ReadADIOSInternal {
|
||||||
static bool is_smalldiff(const float &val1, const float &val2)
|
|
||||||
{
|
|
||||||
return (fabs(static_cast<double>(val1 - val2)) < SMALL);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace LAMMPS_NS
|
public:
|
||||||
{
|
ReadADIOSInternal(){};
|
||||||
class ReadADIOSInternal
|
~ReadADIOSInternal() = default;
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
// name of adios group, referrable in adios2_config.xml
|
||||||
ReadADIOSInternal() {};
|
const std::string ioName = "read_dump";
|
||||||
~ReadADIOSInternal() = default;
|
adios2::ADIOS *ad = nullptr; // adios object
|
||||||
|
adios2::IO io; // adios group of variables and attributes in this dump
|
||||||
// name of adios group, referrable in adios2_config.xml
|
adios2::Engine fh; // adios file/stream handle object
|
||||||
const std::string ioName = "read_dump";
|
// ADIOS input variables we need to change every step
|
||||||
adios2::ADIOS *ad = nullptr; // adios object
|
adios2::Variable<uint64_t> varNtimestep;
|
||||||
adios2::IO io; // adios group of variables and attributes in this dump
|
adios2::Variable<uint64_t> varNatoms;
|
||||||
adios2::Engine fh; // adios file/stream handle object
|
adios2::Variable<double> varAtoms;
|
||||||
// ADIOS input variables we need to change every step
|
// list of column names for the atom table
|
||||||
adios2::Variable<uint64_t> varNtimestep;
|
// (individual list of 'columns' string)
|
||||||
adios2::Variable<uint64_t> varNatoms;
|
std::vector<std::string> columnNames;
|
||||||
adios2::Variable<double> varAtoms;
|
float timeout = 0.0;
|
||||||
// list of column names for the atom table
|
|
||||||
// (individual list of 'columns' string)
|
|
||||||
std::vector<std::string> columnNames;
|
|
||||||
float timeout = 0.0;
|
|
||||||
};
|
};
|
||||||
} // namespace LAMMPS_NS
|
} // namespace LAMMPS_NS
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
ReaderADIOS::ReaderADIOS(LAMMPS *lmp) : Reader(lmp)
|
ReaderADIOS::ReaderADIOS(LAMMPS *lmp) : Reader(lmp)
|
||||||
{
|
{
|
||||||
fieldindex = nullptr;
|
fieldindex = nullptr;
|
||||||
nAtoms = 0;
|
nAtoms = 0;
|
||||||
nAtomsTotal = 0;
|
nAtomsTotal = 0;
|
||||||
atomOffset = 0;
|
atomOffset = 0;
|
||||||
nstep = 0;
|
nstep = 0;
|
||||||
nid = 0;
|
nid = 0;
|
||||||
me = comm->me;
|
me = comm->me;
|
||||||
|
|
||||||
internal = new ReadADIOSInternal();
|
// create a default adios2_config.xml if it doesn't exist yet.
|
||||||
try {
|
FILE *cfgfp = fopen("adios2_config.xml", "r");
|
||||||
internal->ad =
|
if (!cfgfp) {
|
||||||
new adios2::ADIOS("adios2_config.xml", world, adios2::DebugON);
|
cfgfp = fopen("adios2_config.xml", "w");
|
||||||
} catch (std::ios_base::failure &e) {
|
if (cfgfp) fputs(default_config, cfgfp);
|
||||||
char str[256];
|
}
|
||||||
snprintf(str, sizeof(str), "ADIOS initialization failed with error: %s",
|
if (cfgfp) fclose(cfgfp);
|
||||||
e.what());
|
|
||||||
error->one(FLERR, str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Define the group holding all variables and attributes */
|
internal = new ReadADIOSInternal();
|
||||||
internal->io = internal->ad->DeclareIO(internal->ioName);
|
try {
|
||||||
|
internal->ad = new adios2::ADIOS("adios2_config.xml", world, adios2::DebugON);
|
||||||
|
} catch (std::ios_base::failure &e) {
|
||||||
|
error->one(FLERR, "ADIOS initialization failed with error: {}", e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Define the group holding all variables and attributes */
|
||||||
|
internal->io = internal->ad->DeclareIO(internal->ioName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
ReaderADIOS::~ReaderADIOS()
|
ReaderADIOS::~ReaderADIOS()
|
||||||
{
|
{
|
||||||
if (me == 0) {
|
if (me == 0) memory->destroy(fieldindex);
|
||||||
memory->destroy(fieldindex);
|
internal->columnNames.clear();
|
||||||
}
|
if (internal->fh) internal->fh.Close();
|
||||||
internal->columnNames.clear();
|
delete internal->ad;
|
||||||
if (internal->fh) {
|
delete internal;
|
||||||
internal->fh.Close();
|
|
||||||
}
|
|
||||||
delete internal->ad;
|
|
||||||
delete internal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
@ -118,23 +108,19 @@ ReaderADIOS::~ReaderADIOS()
|
|||||||
------------------------------------------------------------------------- */
|
------------------------------------------------------------------------- */
|
||||||
void ReaderADIOS::settings(int narg, char **arg)
|
void ReaderADIOS::settings(int narg, char **arg)
|
||||||
{
|
{
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
while (idx < narg) {
|
while (idx < narg) {
|
||||||
if (!strcmp(arg[idx], "timeout")) {
|
if (!strcmp(arg[idx], "timeout")) {
|
||||||
if (idx + 1 < narg) {
|
if (idx + 1 < narg) {
|
||||||
internal->timeout = std::stof(arg[idx + 1]);
|
internal->timeout = std::stof(arg[idx + 1]);
|
||||||
internal->io.SetParameter("OpenTimeoutSecs", arg[idx + 1]);
|
internal->io.SetParameter("OpenTimeoutSecs", arg[idx + 1]);
|
||||||
++idx;
|
|
||||||
} else {
|
|
||||||
char str[128];
|
|
||||||
snprintf(str, sizeof(str),
|
|
||||||
"Missing value for 'timeout' option for ADIOS "
|
|
||||||
"read_dump command");
|
|
||||||
error->one(FLERR, str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++idx;
|
++idx;
|
||||||
|
} else {
|
||||||
|
error->one(FLERR, "Missing value for 'timeout' option for ADIOS read_dump command");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
@ -142,26 +128,17 @@ void ReaderADIOS::settings(int narg, char **arg)
|
|||||||
Every process must call this Collective operation
|
Every process must call this Collective operation
|
||||||
------------------------------------------------------------------------- */
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void ReaderADIOS::open_file(const char *file)
|
void ReaderADIOS::open_file(const std::string &file)
|
||||||
{
|
{
|
||||||
int rv;
|
// close open file, if needed.
|
||||||
char str[1024];
|
if (internal->fh) internal->fh.Close();
|
||||||
|
|
||||||
// close open file, if needed.
|
try {
|
||||||
if (internal->fh)
|
internal->fh = internal->io.Open(file, adios2::Mode::Read, world);
|
||||||
internal->fh.Close();
|
} catch (std::ios_base::failure &e) {
|
||||||
|
error->one(FLERR, "Error opening file {}: {}", file, e.what());
|
||||||
try {
|
}
|
||||||
internal->fh = internal->io.Open(file, adios2::Mode::Read, world);
|
if (!internal->fh) error->one(FLERR, "Cannot open file {} using ADIOS", file);
|
||||||
} catch (std::ios_base::failure &e) {
|
|
||||||
char str[256];
|
|
||||||
snprintf(str, sizeof(str), "%s", e.what());
|
|
||||||
error->one(FLERR, str);
|
|
||||||
}
|
|
||||||
if (!internal->fh) {
|
|
||||||
snprintf(str, sizeof(str), "Cannot open file %s using ADIOS", file);
|
|
||||||
error->one(FLERR, str);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
@ -171,10 +148,8 @@ void ReaderADIOS::open_file(const char *file)
|
|||||||
|
|
||||||
void ReaderADIOS::close_file()
|
void ReaderADIOS::close_file()
|
||||||
{
|
{
|
||||||
// close open file, if needed.
|
// close open file, if needed.
|
||||||
if (internal->fh) {
|
if (internal->fh) { internal->fh.Close(); }
|
||||||
internal->fh.Close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
@ -185,34 +160,24 @@ void ReaderADIOS::close_file()
|
|||||||
|
|
||||||
int ReaderADIOS::read_time(bigint &ntimestep)
|
int ReaderADIOS::read_time(bigint &ntimestep)
|
||||||
{
|
{
|
||||||
char str[1024];
|
adios2::StepStatus status = internal->fh.BeginStep(adios2::StepMode::Read, internal->timeout);
|
||||||
|
|
||||||
adios2::StepStatus status =
|
switch (status) {
|
||||||
internal->fh.BeginStep(adios2::StepMode::Read, internal->timeout);
|
|
||||||
|
|
||||||
switch (status) {
|
|
||||||
case adios2::StepStatus::EndOfStream:
|
case adios2::StepStatus::EndOfStream:
|
||||||
case adios2::StepStatus::NotReady:
|
case adios2::StepStatus::NotReady:
|
||||||
case adios2::StepStatus::OtherError:
|
case adios2::StepStatus::OtherError:
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal->varNtimestep =
|
internal->varNtimestep = internal->io.InquireVariable<uint64_t>("ntimestep");
|
||||||
internal->io.InquireVariable<uint64_t>("ntimestep");
|
|
||||||
|
|
||||||
if (!internal->varNtimestep) {
|
if (!internal->varNtimestep)
|
||||||
snprintf(str, sizeof(str),
|
error->one(FLERR, "Did not find 'ntimestep' variable in ADIOS file {}", internal->fh.Name());
|
||||||
"Did not find 'ntimestep' variable in ADIOS file %s",
|
|
||||||
internal->fh.Name().c_str());
|
|
||||||
error->one(FLERR, str);
|
|
||||||
}
|
|
||||||
|
|
||||||
ntimestep = static_cast<bigint>(internal->varNtimestep.Max());
|
ntimestep = static_cast<bigint>(internal->varNtimestep.Max());
|
||||||
// std::cerr << " **** ReaderADIOS::read_time found step " << ntimestep
|
return 0;
|
||||||
// << " **** " << std::endl;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
@ -220,7 +185,10 @@ int ReaderADIOS::read_time(bigint &ntimestep)
|
|||||||
Called by all processors.
|
Called by all processors.
|
||||||
------------------------------------------------------------------------- */
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void ReaderADIOS::skip() { internal->fh.EndStep(); }
|
void ReaderADIOS::skip()
|
||||||
|
{
|
||||||
|
internal->fh.EndStep();
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
read remaining header info:
|
read remaining header info:
|
||||||
@ -236,234 +204,205 @@ void ReaderADIOS::skip() { internal->fh.EndStep(); }
|
|||||||
only called by proc 0
|
only called by proc 0
|
||||||
------------------------------------------------------------------------- */
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
bigint ReaderADIOS::read_header(double box[3][3], int &boxinfo, int &triclinic,
|
bigint ReaderADIOS::read_header(double box[3][3], int &boxinfo, int &triclinic, int fieldinfo,
|
||||||
int fieldinfo, int nfield, int *fieldtype,
|
int nfield, int *fieldtype, char **fieldlabel, int scaleflag,
|
||||||
char **fieldlabel, int scaleflag, int wrapflag,
|
int wrapflag, int &fieldflag, int &xflag, int &yflag, int &zflag)
|
||||||
int &fieldflag, int &xflag, int &yflag,
|
|
||||||
int &zflag)
|
|
||||||
{
|
{
|
||||||
char str[1024];
|
nid = 0;
|
||||||
nid = 0;
|
|
||||||
|
|
||||||
// signal that we have no box info at all so far.
|
// signal that we have no box info at all so far.
|
||||||
|
|
||||||
internal->varNatoms = internal->io.InquireVariable<uint64_t>("natoms");
|
internal->varNatoms = internal->io.InquireVariable<uint64_t>("natoms");
|
||||||
if (!internal->varNatoms) {
|
if (!internal->varNatoms)
|
||||||
snprintf(str, sizeof(str),
|
error->one(FLERR, "Did not find 'natoms' variable in ADIOS file {}", internal->fh.Name());
|
||||||
"Did not find 'natoms' variable in ADIOS file %s",
|
|
||||||
internal->fh.Name().c_str());
|
/* nAtoms */
|
||||||
error->one(FLERR, str);
|
nAtomsTotal = internal->varNatoms.Max();
|
||||||
|
uint64_t rem = nAtomsTotal % comm->nprocs;
|
||||||
|
nAtoms = nAtomsTotal / comm->nprocs;
|
||||||
|
atomOffset = comm->me * nAtoms;
|
||||||
|
if (comm->me < (int)rem) {
|
||||||
|
++nAtoms;
|
||||||
|
atomOffset += comm->me;
|
||||||
|
} else {
|
||||||
|
atomOffset += rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* triclinic */
|
||||||
|
adios2::Attribute<int32_t> attTriclinic = internal->io.InquireAttribute<int32_t>("triclinic");
|
||||||
|
if (!attTriclinic)
|
||||||
|
error->one(FLERR, "Did not find 'triclinic' attribute in ADIOS file {}", internal->fh.Name());
|
||||||
|
|
||||||
|
triclinic = attTriclinic.Data()[0];
|
||||||
|
|
||||||
|
/* read Box */
|
||||||
|
adios2::Variable<double> varBoxxlo = internal->io.InquireVariable<double>("boxxlo");
|
||||||
|
adios2::Variable<double> varBoxxhi = internal->io.InquireVariable<double>("boxxhi");
|
||||||
|
adios2::Variable<double> varBoxylo = internal->io.InquireVariable<double>("boxylo");
|
||||||
|
adios2::Variable<double> varBoxyhi = internal->io.InquireVariable<double>("boxyhi");
|
||||||
|
adios2::Variable<double> varBoxzlo = internal->io.InquireVariable<double>("boxzlo");
|
||||||
|
adios2::Variable<double> varBoxzhi = internal->io.InquireVariable<double>("boxzhi");
|
||||||
|
|
||||||
|
box[0][0] = varBoxxlo.Max();
|
||||||
|
box[0][1] = varBoxxhi.Max();
|
||||||
|
box[0][2] = 0.0;
|
||||||
|
box[1][0] = varBoxylo.Max();
|
||||||
|
box[1][1] = varBoxyhi.Max();
|
||||||
|
box[1][2] = 0.0;
|
||||||
|
box[2][0] = varBoxzlo.Max();
|
||||||
|
box[2][1] = varBoxzhi.Max();
|
||||||
|
box[2][2] = 0.0;
|
||||||
|
|
||||||
|
if (triclinic) {
|
||||||
|
adios2::Variable<double> varBoxxy = internal->io.InquireVariable<double>("boxxy");
|
||||||
|
adios2::Variable<double> varBoxxz = internal->io.InquireVariable<double>("boxxz");
|
||||||
|
adios2::Variable<double> varBoxyz = internal->io.InquireVariable<double>("boxyz");
|
||||||
|
|
||||||
|
box[0][2] = varBoxxy.Max();
|
||||||
|
box[1][2] = varBoxxz.Max();
|
||||||
|
box[2][2] = varBoxyz.Max();
|
||||||
|
}
|
||||||
|
|
||||||
|
boxinfo = 1;
|
||||||
|
|
||||||
|
// if no field info requested, just return
|
||||||
|
|
||||||
|
if (!fieldinfo) return nAtoms;
|
||||||
|
|
||||||
|
memory->create(fieldindex, nfield, "read_dump:fieldindex");
|
||||||
|
|
||||||
|
/* Columns */
|
||||||
|
adios2::Attribute<std::string> attColumns = internal->io.InquireAttribute<std::string>("columns");
|
||||||
|
|
||||||
|
std::vector<std::string> labelVector = attColumns.Data();
|
||||||
|
int nwords = labelVector.size();
|
||||||
|
std::map<std::string, int> labels;
|
||||||
|
for (int i = 0; i < nwords; ++i) { labels.emplace(labelVector[i], i); }
|
||||||
|
|
||||||
|
int s_index, u_index, su_index;
|
||||||
|
xflag = UNSET;
|
||||||
|
yflag = UNSET;
|
||||||
|
zflag = UNSET;
|
||||||
|
|
||||||
|
// copy fieldtype list for supported fields
|
||||||
|
|
||||||
|
for (int i = 0; i < nfield; i++) {
|
||||||
|
if (fieldlabel[i]) {
|
||||||
|
fieldindex[i] = find_label(fieldlabel[i], labels);
|
||||||
|
if (fieldtype[i] == X)
|
||||||
|
xflag = 2 * scaleflag + wrapflag + 1;
|
||||||
|
else if (fieldtype[i] == Y)
|
||||||
|
yflag = 2 * scaleflag + wrapflag + 1;
|
||||||
|
else if (fieldtype[i] == Z)
|
||||||
|
zflag = 2 * scaleflag + wrapflag + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* nAtoms */
|
else if (fieldtype[i] == ID)
|
||||||
nAtomsTotal = internal->varNatoms.Max();
|
fieldindex[i] = find_label("id", labels);
|
||||||
uint64_t rem = nAtomsTotal % comm->nprocs;
|
else if (fieldtype[i] == TYPE)
|
||||||
nAtoms = nAtomsTotal / comm->nprocs;
|
fieldindex[i] = find_label("type", labels);
|
||||||
atomOffset = comm->me * nAtoms;
|
|
||||||
if (comm->me < rem) {
|
|
||||||
++nAtoms;
|
|
||||||
atomOffset += comm->me;
|
|
||||||
} else {
|
|
||||||
atomOffset += rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* triclinic */
|
else if (fieldtype[i] == X) {
|
||||||
adios2::Attribute<int32_t> attTriclinic =
|
fieldindex[i] = find_label("x", labels);
|
||||||
internal->io.InquireAttribute<int32_t>("triclinic");
|
xflag = NOSCALE_WRAP;
|
||||||
if (!attTriclinic) {
|
if (fieldindex[i] < 0) {
|
||||||
snprintf(str, sizeof(str),
|
fieldindex[i] = nwords;
|
||||||
"Did not find 'triclinic' attribute in ADIOS file %s",
|
s_index = find_label("xs", labels);
|
||||||
internal->fh.Name().c_str());
|
u_index = find_label("xu", labels);
|
||||||
error->one(FLERR, str);
|
su_index = find_label("xsu", labels);
|
||||||
}
|
if (s_index >= 0 && s_index < fieldindex[i]) {
|
||||||
|
fieldindex[i] = s_index;
|
||||||
triclinic = attTriclinic.Data()[0];
|
xflag = SCALE_WRAP;
|
||||||
|
|
||||||
/* read Box */
|
|
||||||
adios2::Variable<double> varBoxxlo =
|
|
||||||
internal->io.InquireVariable<double>("boxxlo");
|
|
||||||
adios2::Variable<double> varBoxxhi =
|
|
||||||
internal->io.InquireVariable<double>("boxxhi");
|
|
||||||
adios2::Variable<double> varBoxylo =
|
|
||||||
internal->io.InquireVariable<double>("boxylo");
|
|
||||||
adios2::Variable<double> varBoxyhi =
|
|
||||||
internal->io.InquireVariable<double>("boxyhi");
|
|
||||||
adios2::Variable<double> varBoxzlo =
|
|
||||||
internal->io.InquireVariable<double>("boxzlo");
|
|
||||||
adios2::Variable<double> varBoxzhi =
|
|
||||||
internal->io.InquireVariable<double>("boxzhi");
|
|
||||||
|
|
||||||
box[0][0] = varBoxxlo.Max();
|
|
||||||
box[0][1] = varBoxxhi.Max();
|
|
||||||
box[0][2] = 0.0;
|
|
||||||
box[1][0] = varBoxylo.Max();
|
|
||||||
box[1][1] = varBoxyhi.Max();
|
|
||||||
box[1][2] = 0.0;
|
|
||||||
box[2][0] = varBoxzlo.Max();
|
|
||||||
box[2][1] = varBoxzhi.Max();
|
|
||||||
box[2][2] = 0.0;
|
|
||||||
|
|
||||||
if (triclinic) {
|
|
||||||
adios2::Variable<double> varBoxxy =
|
|
||||||
internal->io.InquireVariable<double>("boxxy");
|
|
||||||
adios2::Variable<double> varBoxxz =
|
|
||||||
internal->io.InquireVariable<double>("boxxz");
|
|
||||||
adios2::Variable<double> varBoxyz =
|
|
||||||
internal->io.InquireVariable<double>("boxyz");
|
|
||||||
|
|
||||||
box[0][2] = varBoxxy.Max();
|
|
||||||
box[1][2] = varBoxxz.Max();
|
|
||||||
box[2][2] = varBoxyz.Max();
|
|
||||||
}
|
|
||||||
|
|
||||||
boxinfo = 1;
|
|
||||||
|
|
||||||
// if no field info requested, just return
|
|
||||||
|
|
||||||
if (!fieldinfo)
|
|
||||||
return nAtoms;
|
|
||||||
|
|
||||||
memory->create(fieldindex, nfield, "read_dump:fieldindex");
|
|
||||||
|
|
||||||
/* Columns */
|
|
||||||
adios2::Attribute<std::string> attColumns =
|
|
||||||
internal->io.InquireAttribute<std::string>("columns");
|
|
||||||
|
|
||||||
std::vector<std::string> labelVector = attColumns.Data();
|
|
||||||
int nwords = labelVector.size();
|
|
||||||
std::map<std::string, int> labels;
|
|
||||||
for (int i = 0; i < nwords; ++i) {
|
|
||||||
labels.emplace(labelVector[i], i);
|
|
||||||
}
|
|
||||||
|
|
||||||
int s_index, u_index, su_index;
|
|
||||||
xflag = UNSET;
|
|
||||||
yflag = UNSET;
|
|
||||||
zflag = UNSET;
|
|
||||||
|
|
||||||
// copy fieldtype list for supported fields
|
|
||||||
|
|
||||||
for (int i = 0; i < nfield; i++) {
|
|
||||||
if (fieldlabel[i]) {
|
|
||||||
fieldindex[i] = find_label(fieldlabel[i], labels);
|
|
||||||
if (fieldtype[i] == X)
|
|
||||||
xflag = 2 * scaleflag + wrapflag + 1;
|
|
||||||
else if (fieldtype[i] == Y)
|
|
||||||
yflag = 2 * scaleflag + wrapflag + 1;
|
|
||||||
else if (fieldtype[i] == Z)
|
|
||||||
zflag = 2 * scaleflag + wrapflag + 1;
|
|
||||||
}
|
}
|
||||||
|
if (u_index >= 0 && u_index < fieldindex[i]) {
|
||||||
|
fieldindex[i] = u_index;
|
||||||
|
xflag = NOSCALE_NOWRAP;
|
||||||
|
}
|
||||||
|
if (su_index >= 0 && su_index < fieldindex[i]) {
|
||||||
|
fieldindex[i] = su_index;
|
||||||
|
xflag = SCALE_NOWRAP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fieldindex[i] == nwords) fieldindex[i] = -1;
|
||||||
|
|
||||||
else if (fieldtype[i] == ID)
|
} else if (fieldtype[i] == Y) {
|
||||||
fieldindex[i] = find_label("id", labels);
|
fieldindex[i] = find_label("y", labels);
|
||||||
else if (fieldtype[i] == TYPE)
|
yflag = NOSCALE_WRAP;
|
||||||
fieldindex[i] = find_label("type", labels);
|
if (fieldindex[i] < 0) {
|
||||||
|
fieldindex[i] = nwords;
|
||||||
|
s_index = find_label("ys", labels);
|
||||||
|
u_index = find_label("yu", labels);
|
||||||
|
su_index = find_label("ysu", labels);
|
||||||
|
if (s_index >= 0 && s_index < fieldindex[i]) {
|
||||||
|
fieldindex[i] = s_index;
|
||||||
|
yflag = SCALE_WRAP;
|
||||||
|
}
|
||||||
|
if (u_index >= 0 && u_index < fieldindex[i]) {
|
||||||
|
fieldindex[i] = u_index;
|
||||||
|
yflag = NOSCALE_NOWRAP;
|
||||||
|
}
|
||||||
|
if (su_index >= 0 && su_index < fieldindex[i]) {
|
||||||
|
fieldindex[i] = su_index;
|
||||||
|
yflag = SCALE_NOWRAP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fieldindex[i] == nwords) fieldindex[i] = -1;
|
||||||
|
|
||||||
else if (fieldtype[i] == X) {
|
} else if (fieldtype[i] == Z) {
|
||||||
fieldindex[i] = find_label("x", labels);
|
fieldindex[i] = find_label("z", labels);
|
||||||
xflag = NOSCALE_WRAP;
|
zflag = NOSCALE_WRAP;
|
||||||
if (fieldindex[i] < 0) {
|
if (fieldindex[i] < 0) {
|
||||||
fieldindex[i] = nwords;
|
fieldindex[i] = nwords;
|
||||||
s_index = find_label("xs", labels);
|
s_index = find_label("zs", labels);
|
||||||
u_index = find_label("xu", labels);
|
u_index = find_label("zu", labels);
|
||||||
su_index = find_label("xsu", labels);
|
su_index = find_label("zsu", labels);
|
||||||
if (s_index >= 0 && s_index < fieldindex[i]) {
|
if (s_index >= 0 && s_index < fieldindex[i]) {
|
||||||
fieldindex[i] = s_index;
|
fieldindex[i] = s_index;
|
||||||
xflag = SCALE_WRAP;
|
zflag = SCALE_WRAP;
|
||||||
}
|
}
|
||||||
if (u_index >= 0 && u_index < fieldindex[i]) {
|
if (u_index >= 0 && u_index < fieldindex[i]) {
|
||||||
fieldindex[i] = u_index;
|
fieldindex[i] = u_index;
|
||||||
xflag = NOSCALE_NOWRAP;
|
zflag = NOSCALE_NOWRAP;
|
||||||
}
|
}
|
||||||
if (su_index >= 0 && su_index < fieldindex[i]) {
|
if (su_index >= 0 && su_index < fieldindex[i]) {
|
||||||
fieldindex[i] = su_index;
|
fieldindex[i] = su_index;
|
||||||
xflag = SCALE_NOWRAP;
|
zflag = SCALE_NOWRAP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fieldindex[i] == nwords)
|
if (fieldindex[i] == nwords) fieldindex[i] = -1;
|
||||||
fieldindex[i] = -1;
|
|
||||||
|
|
||||||
} else if (fieldtype[i] == Y) {
|
} else if (fieldtype[i] == VX)
|
||||||
fieldindex[i] = find_label("y", labels);
|
fieldindex[i] = find_label("vx", labels);
|
||||||
yflag = NOSCALE_WRAP;
|
else if (fieldtype[i] == VY)
|
||||||
if (fieldindex[i] < 0) {
|
fieldindex[i] = find_label("vy", labels);
|
||||||
fieldindex[i] = nwords;
|
else if (fieldtype[i] == VZ)
|
||||||
s_index = find_label("ys", labels);
|
fieldindex[i] = find_label("vz", labels);
|
||||||
u_index = find_label("yu", labels);
|
|
||||||
su_index = find_label("ysu", labels);
|
|
||||||
if (s_index >= 0 && s_index < fieldindex[i]) {
|
|
||||||
fieldindex[i] = s_index;
|
|
||||||
yflag = SCALE_WRAP;
|
|
||||||
}
|
|
||||||
if (u_index >= 0 && u_index < fieldindex[i]) {
|
|
||||||
fieldindex[i] = u_index;
|
|
||||||
yflag = NOSCALE_NOWRAP;
|
|
||||||
}
|
|
||||||
if (su_index >= 0 && su_index < fieldindex[i]) {
|
|
||||||
fieldindex[i] = su_index;
|
|
||||||
yflag = SCALE_NOWRAP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fieldindex[i] == nwords)
|
|
||||||
fieldindex[i] = -1;
|
|
||||||
|
|
||||||
} else if (fieldtype[i] == Z) {
|
else if (fieldtype[i] == FX)
|
||||||
fieldindex[i] = find_label("z", labels);
|
fieldindex[i] = find_label("fx", labels);
|
||||||
zflag = NOSCALE_WRAP;
|
else if (fieldtype[i] == FY)
|
||||||
if (fieldindex[i] < 0) {
|
fieldindex[i] = find_label("fy", labels);
|
||||||
fieldindex[i] = nwords;
|
else if (fieldtype[i] == FZ)
|
||||||
s_index = find_label("zs", labels);
|
fieldindex[i] = find_label("fz", labels);
|
||||||
u_index = find_label("zu", labels);
|
|
||||||
su_index = find_label("zsu", labels);
|
|
||||||
if (s_index >= 0 && s_index < fieldindex[i]) {
|
|
||||||
fieldindex[i] = s_index;
|
|
||||||
zflag = SCALE_WRAP;
|
|
||||||
}
|
|
||||||
if (u_index >= 0 && u_index < fieldindex[i]) {
|
|
||||||
fieldindex[i] = u_index;
|
|
||||||
zflag = NOSCALE_NOWRAP;
|
|
||||||
}
|
|
||||||
if (su_index >= 0 && su_index < fieldindex[i]) {
|
|
||||||
fieldindex[i] = su_index;
|
|
||||||
zflag = SCALE_NOWRAP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fieldindex[i] == nwords)
|
|
||||||
fieldindex[i] = -1;
|
|
||||||
|
|
||||||
} else if (fieldtype[i] == VX)
|
else if (fieldtype[i] == Q)
|
||||||
fieldindex[i] = find_label("vx", labels);
|
fieldindex[i] = find_label("q", labels);
|
||||||
else if (fieldtype[i] == VY)
|
|
||||||
fieldindex[i] = find_label("vy", labels);
|
|
||||||
else if (fieldtype[i] == VZ)
|
|
||||||
fieldindex[i] = find_label("vz", labels);
|
|
||||||
|
|
||||||
else if (fieldtype[i] == FX)
|
else if (fieldtype[i] == IX)
|
||||||
fieldindex[i] = find_label("fx", labels);
|
fieldindex[i] = find_label("ix", labels);
|
||||||
else if (fieldtype[i] == FY)
|
else if (fieldtype[i] == IY)
|
||||||
fieldindex[i] = find_label("fy", labels);
|
fieldindex[i] = find_label("iy", labels);
|
||||||
else if (fieldtype[i] == FZ)
|
else if (fieldtype[i] == IZ)
|
||||||
fieldindex[i] = find_label("fz", labels);
|
fieldindex[i] = find_label("iz", labels);
|
||||||
|
}
|
||||||
|
|
||||||
else if (fieldtype[i] == Q)
|
// set fieldflag = -1 if any unfound fields
|
||||||
fieldindex[i] = find_label("q", labels);
|
|
||||||
|
|
||||||
else if (fieldtype[i] == IX)
|
fieldflag = 0;
|
||||||
fieldindex[i] = find_label("ix", labels);
|
for (int i = 0; i < nfield; i++)
|
||||||
else if (fieldtype[i] == IY)
|
if (fieldindex[i] < 0) fieldflag = -1;
|
||||||
fieldindex[i] = find_label("iy", labels);
|
|
||||||
else if (fieldtype[i] == IZ)
|
|
||||||
fieldindex[i] = find_label("iz", labels);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set fieldflag = -1 if any unfound fields
|
return nAtoms;
|
||||||
|
|
||||||
fieldflag = 0;
|
|
||||||
for (int i = 0; i < nfield; i++)
|
|
||||||
if (fieldindex[i] < 0)
|
|
||||||
fieldflag = -1;
|
|
||||||
|
|
||||||
return nAtoms;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
@ -475,41 +414,33 @@ bigint ReaderADIOS::read_header(double box[3][3], int &boxinfo, int &triclinic,
|
|||||||
|
|
||||||
void ReaderADIOS::read_atoms(int n, int nfield, double **fields)
|
void ReaderADIOS::read_atoms(int n, int nfield, double **fields)
|
||||||
{
|
{
|
||||||
char str[1024];
|
/* Read Atoms */
|
||||||
|
/* This is the firsts (and last) read of array data, so we
|
||||||
|
* call EndStep() here instead of PerformGets()
|
||||||
|
*/
|
||||||
|
|
||||||
/* Read Atoms */
|
adios2::Variable<double> varAtoms = internal->io.InquireVariable<double>("atoms");
|
||||||
/* This is the firsts (and last) read of array data, so we
|
|
||||||
* call EndStep() here instead of PerformGets()
|
|
||||||
*/
|
|
||||||
|
|
||||||
adios2::Variable<double> varAtoms =
|
if ((uint64_t)n != nAtoms)
|
||||||
internal->io.InquireVariable<double>("atoms");
|
error->one(FLERR,
|
||||||
|
"ReaderADIOS::read_atoms() expects 'n={}' equal to the number of "
|
||||||
|
"atoms (={}) for process {} in ADIOS file {}.",
|
||||||
|
n, nAtoms, comm->me, internal->fh.Name());
|
||||||
|
|
||||||
if (n != nAtoms) {
|
size_t ncols = varAtoms.Count()[1];
|
||||||
snprintf(
|
varAtoms.SetSelection({{atomOffset, 0}, {nAtoms, ncols}});
|
||||||
str, sizeof(str),
|
|
||||||
"ReaderADIOS::read_atoms() expects 'n=%d' equal to the number of "
|
|
||||||
"atoms (=%" PRIu64 ") for process %d in ADIOS file %s.",
|
|
||||||
n, nAtoms, comm->me, internal->fh.Name().c_str());
|
|
||||||
error->one(FLERR, str);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ncols = varAtoms.Count()[1];
|
std::vector<double> table;
|
||||||
varAtoms.SetSelection({{atomOffset, 0}, {nAtoms, ncols}});
|
|
||||||
|
|
||||||
std::vector<double> table;
|
internal->fh.Get<double>(varAtoms, table);
|
||||||
|
// EndStep or PerformGets required to make the read happen
|
||||||
|
internal->fh.EndStep();
|
||||||
|
|
||||||
internal->fh.Get<double>(varAtoms, table);
|
size_t idx;
|
||||||
// EndStep or PerformGets required to make the read happen
|
for (uint64_t i = 0; i < nAtoms; i++) {
|
||||||
internal->fh.EndStep();
|
idx = i * ncols;
|
||||||
|
for (int m = 0; m < nfield; m++) { fields[i][m] = table[idx + fieldindex[m]]; }
|
||||||
size_t idx;
|
}
|
||||||
for (int i = 0; i < nAtoms; i++) {
|
|
||||||
idx = i * ncols;
|
|
||||||
for (int m = 0; m < nfield; m++) {
|
|
||||||
fields[i][m] = table[idx + fieldindex[m]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
@ -517,12 +448,9 @@ void ReaderADIOS::read_atoms(int n, int nfield, double **fields)
|
|||||||
return index of match or -1 if no match
|
return index of match or -1 if no match
|
||||||
------------------------------------------------------------------------- */
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
int ReaderADIOS::find_label(const std::string &label,
|
int ReaderADIOS::find_label(const std::string &label, const std::map<std::string, int> &labels)
|
||||||
const std::map<std::string, int> &labels)
|
|
||||||
{
|
{
|
||||||
std::map<std::string, int>::const_iterator it = labels.find(label);
|
std::map<std::string, int>::const_iterator it = labels.find(label);
|
||||||
if (it != labels.end()) {
|
if (it != labels.end()) { return it->second; }
|
||||||
return it->second;
|
return -1;
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,7 +44,7 @@ class ReaderADIOS : public Reader {
|
|||||||
int &, int &, int &) override;
|
int &, int &, int &) override;
|
||||||
void read_atoms(int, int, double **) override;
|
void read_atoms(int, int, double **) override;
|
||||||
|
|
||||||
void open_file(const char *) override;
|
void open_file(const std::string &) override;
|
||||||
void close_file() override;
|
void close_file() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
Reference in New Issue
Block a user