Added initial untested ADIOS 2.x code with cmake building problems

This commit is contained in:
Norbert Podhorszki 2019-01-24 13:48:08 -05:00
parent 12bec9cbad
commit 8db88b1c02
8 changed files with 1005 additions and 2 deletions

View File

@ -2,7 +2,22 @@
# CMake build system
# This file is part of LAMMPS
# Created by Christoph Junghans and Richard Berger
cmake_minimum_required(VERSION 2.8.12)
if(PKG_USER-ADIOS)
message(STATUS "Force newer standards because 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()
project(lammps CXX)
set(SOVERSION 0)
@ -178,7 +193,7 @@ set(DEFAULT_PACKAGES ASPHERE BODY CLASS2 COLLOID COMPRESS DIPOLE GRANULAR
USER-MEAMC USER-MGPT USER-MISC USER-MOFFF USER-MOLFILE USER-NETCDF
USER-PHONON USER-PLUMED USER-PTM USER-QTB USER-REAXC USER-SCAFACOS
USER-SDPD USER-SMD USER-SMTBQ USER-SPH USER-TALLY USER-UEF USER-VTK
USER-QUIP USER-QMMM USER-YAFF)
USER-QUIP USER-QMMM USER-YAFF USER-ADIOS)
set(ACCEL_PACKAGES USER-OMP KOKKOS OPT USER-INTEL GPU)
set(OTHER_PACKAGES CORESHELL QEQ)
foreach(PKG ${DEFAULT_PACKAGES})
@ -613,6 +628,7 @@ if(PKG_USER-NETCDF)
add_definitions(-DLMP_HAS_NETCDF -DNC_64BIT_DATA=0x0020)
endif()
if(PKG_USER-SMD)
option(DOWNLOAD_EIGEN3 "Download Eigen3 instead of using an already installed one)" OFF)
if(DOWNLOAD_EIGEN3)
@ -1354,6 +1370,34 @@ if(BUILD_EXE)
endif()
endif()
#if(PKG_USER-ADIOS)
# cmake_minimum_required(VERSION 3.6)
# enable_language(C)
#
# find_package(ADIOS2 REQUIRED)
## find_package(MPI REQUIRED)
# include_directories(${ADIOS2_INCLUDE_DIRS})
## include_directories(/opt/adios2/include)
## list(APPEND LAMMPS_LINK_LIBS ${ADIOS2_LIBRARIES})
# list(APPEND LAMMPS_LINK_LIBS ${MPI_C_LIBRARIES})
# if(BUILD_LIB)
## target_link_libraries(lammps adios2::adios2 MPI::MPI_C)
## #target_include_directories(lammps PRIVATE ${ADIOS_INCLUDE_DIRS})
# elseif(BUILD_EXE)
## target_link_libraries(lmp adios2::adios2 MPI::MPI_C)
# endif()
#endif(PKG_USER-ADIOS)
if(PKG_USER-ADIOS)
enable_language(C)
find_package(ADIOS2 REQUIRED)
if(BUILD_LIB)
target_link_libraries(lammps adios2::adios2)
elseif(BUILD_EXE)
target_link_libraries(lmp adios2::adios2)
endif()
endif()
###############################################################################
# Build documentation
###############################################################################

22
runconf Normal file
View File

@ -0,0 +1,22 @@
# -D LAMMPS_SIZES=value # smallbig (default) or bigbig or smallsmall
export HDF5_ROOT=/opt/hdf5-serial
export ADIOS2_DIR=/opt/adios2
cmake -D CMAKE_INSTALL_PREFIX=/opt/lammps \
-D CMAKE_BUILD_TYPE=Debug \
-D BUILD_MPI=yes \
-D LAMMPS_MACHINE=adiosvm \
-D BUILD_EXE=yes \
-D BUILD_LIB=no \
-D BUILD_SHARED_LIBS=no \
-D BUILD_DOC=no \
-D LAMMPS_SIZES=smallbig \
-D PKG_USER-H5MD=yes \
-D PKG_USER-ADIOS=yes \
../cmake

89
src/USER-ADIOS/Install.sh Normal file
View File

@ -0,0 +1,89 @@
# Install/unInstall package files in LAMMPS
# mode = 0/1/2 for uninstall/install/update
mode=$1
# arg1 = file, arg2 = file it depends on
action () {
if (test $mode = 0) then
rm -f ../$1
elif (! cmp -s $1 ../$1) then
if (test -z "$2" || test -e ../$2) then
cp $1 ..
if (test $mode = 2) then
echo " updating src/$1"
fi
fi
elif (test -n "$2") then
if (test ! -e ../$2) then
rm -f ../$1
fi
fi
}
for file in *.cpp *.h; do
action $file
done
# edit 2 Makefile.package files to include/exclude package info
if (test $1 = 1) then
# if (test -z "$ADIOS_DIR") then
# if command -v adios_config; then
# ADIOS_DIR=`adios_config -d`
# else
# echo "ERROR: ADIOS_DIR environment variable needs to point to ADIOS" \
# " installation directory or adios_config should be in PATH"
# fi
# fi
# ADIOS_INC=-I${ADIOS_DIR}/include
# ADIOS_LIB=`${ADIOS_DIR}/bin/adios_config -l`
#
# echo "adios_SYSINC=${ADIOS_INC}
#adios_SYSLIB=${ADIOS_LIB}
#adios_SYSPATH=${ADIOS_DIR}
#" > ../Makefile.adios
if (test -e ../Makefile.package) then
sed -i -e 's/[^ \t]*adios[^ \t]* //g' ../Makefile.package
sed -i -e 's/-DLMP_ADIOS //g' ../Makefile.package
sed -i -e '/^adios_SYS.*$/d' ../Makefile.package
# sed -i -e '4 i \
#adios_SYSINC='"${ADIOS_INC}"'
#' ../Makefile.package
# sed -i -e '5 i \
#adios_SYSLIB='"${ADIOS_LIB}"'
#' ../Makefile.package
# sed -i -e '6 i \
#adios_SYSPATH='"${ADIOS_DIR}"'
#' ../Makefile.package
sed -i -e 's|^PKG_INC =[ \t]*|&-DLMP_ADIOS |' ../Makefile.package
sed -i -e 's|^PKG_SYSINC =[ \t]*|&$(adios_SYSINC) |' ../Makefile.package
sed -i -e 's|^PKG_SYSLIB =[ \t]*|&$(adios_SYSLIB) |' ../Makefile.package
sed -i -e 's|^PKG_SYSPATH =[ \t]*|&$(adios_SYSPATH) |' ../Makefile.package
fi
if (test -e ../Makefile.package.settings) then
sed -i -e '/^include.*adios.*$/d' ../Makefile.package.settings
# multiline form needed for BSD sed on Macs
sed -i -e '4 i \
include ..\/..\/lib\/adios\/Makefile.lammps
' ../Makefile.package.settings
fi
elif (test $1 = 0) then
if (test -e ../Makefile.package) then
sed -i -e 's/[^ \t]*adios[^ \t]* //g' ../Makefile.package
sed -i -e 's/-DLMP_ADIOS //g' ../Makefile.package
sed -i -e '/^adios_SYS.*$/d' ../Makefile.package
fi
if (test -e ../Makefile.package.settings) then
sed -i -e '/^include.*adios.*$/d' ../Makefile.package.settings
fi
fi

16
src/USER-ADIOS/README Normal file
View File

@ -0,0 +1,16 @@
This package provides the adios dump and restart styles.
See the doc page for the "dump adios" and "restart adios" commands.
These styles require having ADIOS 2.x itself installed on your system.
Configure LAMMPS with CMake
a. set the environment variable
ADIOS2_DIR
to the ADIOS 2.x installation path
b. use the cmake option
-D PKG_USER-ADIOS=yes
The person who created this package is Norbert Podhorszki (Oak Ridge National Laboratory);
If you need help, please submit a ticket at the OLCF ticket user support mentioning his name in the ticket.
https://www.olcf.ornl.gov/support/submit-ticket

View File

@ -0,0 +1,314 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, 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.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Norbert Podhorszki (ORNL)
------------------------------------------------------------------------- */
#include <string.h>
#include "dump_atom_adios.h"
#include "domain.h"
#include "atom.h"
#include "update.h"
#include "group.h"
#include "memory.h"
#include "universe.h"
#include "error.h"
using namespace LAMMPS_NS;
#define MAX_TEXT_HEADER_SIZE 4096
#define DUMP_BUF_CHUNK_SIZE 16384
#define DUMP_BUF_INCREMENT_SIZE 4096
/* ---------------------------------------------------------------------- */
DumpAtomADIOS::DumpAtomADIOS(LAMMPS *lmp, int narg, char **arg) :
DumpAtom(lmp, narg, arg)
{
ad = new adios2::ADIOS("adios2_config.xml", world, adios2::DebugON);
groupSize = 0;
}
/* ---------------------------------------------------------------------- */
DumpAtomADIOS::~DumpAtomADIOS()
{
if (fh)
{
fh.Close();
}
}
/* ---------------------------------------------------------------------- */
void DumpAtomADIOS::openfile()
{
if (multifile) {
// if one file per timestep, replace '*' with current timestep
char *filestar = strdup(filename);
char *filecurrent = new char[strlen(filestar) + 16];
char *ptr = strchr(filestar,'*');
*ptr = '\0';
if (padflag == 0)
sprintf(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);
}
fh = io.Open(filecurrent, adios2::Mode::Write, world);
if (!fh) {
char str[128];
sprintf(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) {
char str[128];
sprintf(str,"Cannot open dump file %s",filename);
error->one(FLERR,str);
}
singlefile_opened = 1;
}
}
}
/* ---------------------------------------------------------------------- */
void DumpAtomADIOS::write()
{
if (domain->triclinic == 0) {
boxxlo = domain->boxlo[0];
boxxhi = domain->boxhi[0];
boxylo = domain->boxlo[1];
boxyhi = domain->boxhi[1];
boxzlo = domain->boxlo[2];
boxzhi = domain->boxhi[2];
} else {
boxxlo = domain->boxlo_bound[0];
boxxhi = domain->boxhi_bound[0];
boxylo = domain->boxlo_bound[1];
boxyhi = domain->boxhi_bound[1];
boxzlo = domain->boxlo_bound[2];
boxzhi = domain->boxhi_bound[2];
boxxy = domain->xy;
boxxz = domain->xz;
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);
varAtoms.SetShape({nAtomsGlobal,nColumns});
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(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
}
}
openfile();
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);
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);
if (domain->triclinic) {
fh.Put<double>("boxxy", boxxy);
fh.Put<double>("boxxz", boxxz);
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);
// now write the atoms
fh.Put<double>("atoms", buf);
fh.EndStep();// I/O will happen now...
if (multifile)
{
fh.Close();
}
}
/* ---------------------------------------------------------------------- */
void DumpAtomADIOS::init_style()
{
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
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);
strncpy(filename,s,len);
}
// setup column string
if (scale_flag == 0 && image_flag == 0)
columns = (char *) "id type x y z";
else if (scale_flag == 0 && image_flag == 1)
columns = (char *) "id type x y z ix iy iz";
else if (scale_flag == 1 && image_flag == 0)
columns = (char *) "id type xs ys zs";
else if (scale_flag == 1 && image_flag == 1)
columns = (char *) "id type xs ys zs ix iy iz";
// setup function ptrs
if (scale_flag == 1 && image_flag == 0 && domain->triclinic == 0)
pack_choice = &DumpAtomADIOS::pack_scale_noimage;
else if (scale_flag == 1 && image_flag == 1 && domain->triclinic == 0)
pack_choice = &DumpAtomADIOS::pack_scale_image;
else if (scale_flag == 1 && image_flag == 0 && domain->triclinic == 1)
pack_choice = &DumpAtomADIOS::pack_scale_noimage_triclinic;
else if (scale_flag == 1 && image_flag == 1 && domain->triclinic == 1)
pack_choice = &DumpAtomADIOS::pack_scale_image_triclinic;
else if (scale_flag == 0 && image_flag == 0)
pack_choice = &DumpAtomADIOS::pack_noscale_noimage;
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 */
adios2::IO io = ad->DeclareIO(ioName);
if (!io.InConfigFile())
{
// if not defined by user, we can change the default settings
// BPFile is the default writer
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);
}
io.DefineVariable<uint64_t>("ntimestep");
io.DefineVariable<uint64_t>("natoms");
io.DefineVariable<int>("nprocs");
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");
io.DefineVariable<double>("boxxy");
io.DefineVariable<double>("boxxz");
io.DefineVariable<double>("boxyz");
io.DefineAttribute<int>("triclinic", domain->triclinic);
io.DefineAttribute<int>("scaled", scale_flag);
io.DefineAttribute<int>("image", image_flag);
int *boundaryptr = reinterpret_cast<int*>(domain->boundary);
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);
io.DefineVariable<uint64_t>("nme", {adios2::LocalValueDim}); // local dimension variable
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},
{UnknownSizeYet,nColumns});
}

View File

@ -0,0 +1,70 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, 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.
------------------------------------------------------------------------- */
#ifdef DUMP_CLASS
DumpStyle(atom/adios,DumpAtomADIOS)
#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 {
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();
};
}
#endif
#endif
/* ERROR/WARNING messages:
E: Cannot open dump file %s
The output file for the dump command cannot be opened. Check that the
path and name are correct.
E: Too much per-proc info for dump
Number of local atoms times number of columns must fit in a 32-bit
integer for dump.
*/

View File

@ -0,0 +1,354 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, 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.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Coffman (IBM)
------------------------------------------------------------------------- */
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "dump_custom_adios.h"
#include "atom.h"
#include "force.h"
#include "domain.h"
#include "region.h"
#include "group.h"
#include "input.h"
#include "variable.h"
#include "update.h"
#include "modify.h"
#include "compute.h"
#include "fix.h"
#include "universe.h"
#include "memory.h"
#include "error.h"
#include <stdlib.h>
using namespace LAMMPS_NS;
#define MAX_TEXT_HEADER_SIZE 4096
#define DUMP_BUF_CHUNK_SIZE 16384
#define DUMP_BUF_INCREMENT_SIZE 4096
enum{ID,MOL,TYPE,ELEMENT,MASS,
X,Y,Z,XS,YS,ZS,XSTRI,YSTRI,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};
enum{INT,DOUBLE,STRING,BIGINT}; // same as in DumpCustom
/* ---------------------------------------------------------------------- */
DumpCustomADIOS::DumpCustomADIOS(LAMMPS *lmp, int narg, char **arg) :
DumpCustom(lmp, narg, arg)
{
ad = new adios2::ADIOS("adios2_config.xml", world, adios2::DebugON);
groupsize = 0;
//if (screen) fprintf(screen, "DumpCustomADIOS constructor: nvariable=%d id_variable=%p, variables=%p, nfield=%d, earg=%p\n", nvariable, id_variable, variable, nfield, earg);
columnNames.reserve(nfield);
for (int i = 0; i < nfield; ++i) {
columnNames[i]=std::string(earg[i]);
//if (screen) fprintf(screen, "earg[%d] = '%s'\n", i, earg[i]);
}
}
/* ---------------------------------------------------------------------- */
DumpCustomADIOS::~DumpCustomADIOS()
{
columnNames.clear();
if (fh)
{
fh.Close();
}
}
/* ---------------------------------------------------------------------- */
void DumpCustomADIOS::openfile()
{
if (multifile) {
// if one file per timestep, replace '*' with current timestep
char *filestar = strdup(filename);
char *filecurrent = new char[strlen(filestar) + 16];
char *ptr = strchr(filestar,'*');
*ptr = '\0';
if (padflag == 0)
sprintf(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);
}
fh = io.Open(filecurrent, adios2::Mode::Write, world);
if (!fh) {
char str[128];
sprintf(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) {
char str[128];
sprintf(str,"Cannot open dump file %s",filename);
error->one(FLERR,str);
}
singlefile_opened = 1;
}
}
}
/* ---------------------------------------------------------------------- */
void DumpCustomADIOS::write()
{
if (domain->triclinic == 0) {
boxxlo = domain->boxlo[0];
boxxhi = domain->boxhi[0];
boxylo = domain->boxlo[1];
boxyhi = domain->boxhi[1];
boxzlo = domain->boxlo[2];
boxzhi = domain->boxhi[2];
} else {
boxxlo = domain->boxlo_bound[0];
boxxhi = domain->boxhi_bound[0];
boxylo = domain->boxlo_bound[1];
boxyhi = domain->boxhi_bound[1];
boxzlo = domain->boxlo_bound[2];
boxzhi = domain->boxhi_bound[2];
boxxy = domain->xy;
boxxz = domain->xz;
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);
varAtoms.SetShape({nAtomsGlobal,nColumns});
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(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
}
}
openfile();
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);
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);
if (domain->triclinic) {
fh.Put<double>("boxxy", boxxy);
fh.Put<double>("boxxz", boxxz);
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);
// now write the atoms
fh.Put<double>("atoms", buf);
fh.EndStep();// I/O will happen now...
if (multifile)
{
fh.Close();
}
}
/* ---------------------------------------------------------------------- */
void DumpCustomADIOS::init_style()
{
// setup boundary string
domain->boundary_string(boundstr);
// 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);
strncpy(filename,s,len);
}
/* The next four loops are copied from dump_custom_mpiio, but nothing is done with them.
* It is unclear why we need them here.
* For metadata, variable[] will be written out as an ADIOS attribute if nvariable>0
*/
// find current ptr for each compute,fix,variable
// check that fix frequency is acceptable
int icompute;
for (int i = 0; i < ncompute; i++) {
icompute = modify->find_compute(id_compute[i]);
if (icompute < 0) error->all(FLERR,"Could not find dump custom compute ID");
compute[i] = modify->compute[icompute];
}
int ifix;
for (int i = 0; i < nfix; i++) {
ifix = modify->find_fix(id_fix[i]);
if (ifix < 0) error->all(FLERR,"Could not find dump custom fix ID");
fix[i] = modify->fix[ifix];
if (nevery % modify->fix[ifix]->peratom_freq)
error->all(FLERR,"Dump custom and fix not computed at compatible times");
}
int ivariable;
for (int i = 0; i < nvariable; i++) {
ivariable = input->variable->find(id_variable[i]);
if (ivariable < 0)
error->all(FLERR,"Could not find dump custom variable name");
variable[i] = ivariable;
}
// set index and check validity of region
if (iregion >= 0) {
iregion = domain->find_region(idregion);
if (iregion == -1)
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 set */
adios2::IO io = ad->DeclareIO(ioName);
if (!io.InConfigFile())
{
// if not defined by user, we can change the default settings
// BPFile is the default writer
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);
}
io.DefineVariable<uint64_t>("ntimestep");
io.DefineVariable<uint64_t>("natoms");
io.DefineVariable<int>("nprocs");
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");
io.DefineVariable<double>("boxxy");
io.DefineVariable<double>("boxxz");
io.DefineVariable<double>("boxyz");
io.DefineAttribute<int>("triclinic", domain->triclinic);
int *boundaryptr = reinterpret_cast<int*>(domain->boundary);
io.DefineAttribute<int>("boundary", boundaryptr, 6);
size_t nColumns = static_cast<size_t>(size_one);
io.DefineAttribute<std::string>("columns", columnNames.data(), nColumns);
io.DefineAttribute<std::string>("columnstr", 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);
io.DefineVariable<uint64_t>("nme", {adios2::LocalValueDim}); // local dimension variable
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;
varAtoms = io.DefineVariable<double>("atoms",
{UnknownSizeYet,nColumns},
{UnknownSizeYet, 0},
{UnknownSizeYet,nColumns});
}

View File

@ -0,0 +1,94 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, 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.
------------------------------------------------------------------------- */
#ifdef DUMP_CLASS
DumpStyle(custom/adios,DumpCustomADIOS)
#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 {
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();
};
}
#endif
#endif
/* ERROR/WARNING messages:
E: Cannot open dump file %s
The output file for the dump command cannot be opened. Check that the
path and name are correct.
E: Too much per-proc info for dump
Number of local atoms times number of columns must fit in a 32-bit
integer for dump.
E: Dump_modify format string is too short
There are more fields to be dumped in a line of output than your
format string specifies.
E: Could not find dump custom compute ID
Self-explanatory.
E: Could not find dump custom fix ID
Self-explanatory.
E: Dump custom and fix not computed at compatible times
The fix must produce per-atom quantities on timesteps that dump custom
needs them.
E: Could not find dump custom variable name
Self-explanatory.
E: Region ID for dump custom does not exist
Self-explanatory.
*/