remove MPIIO sources and references to them. update Purge.list and build systems
This commit is contained in:
@ -268,7 +268,6 @@ set(STANDARD_PACKAGES
|
|||||||
MOFFF
|
MOFFF
|
||||||
MOLECULE
|
MOLECULE
|
||||||
MOLFILE
|
MOLFILE
|
||||||
MPIIO
|
|
||||||
NETCDF
|
NETCDF
|
||||||
ORIENT
|
ORIENT
|
||||||
PERI
|
PERI
|
||||||
@ -377,7 +376,6 @@ endif()
|
|||||||
# "hard" dependencies between packages resulting
|
# "hard" dependencies between packages resulting
|
||||||
# in an error instead of skipping over files
|
# in an error instead of skipping over files
|
||||||
pkg_depends(ML-IAP ML-SNAP)
|
pkg_depends(ML-IAP ML-SNAP)
|
||||||
pkg_depends(MPIIO MPI)
|
|
||||||
pkg_depends(ATC MANYBODY)
|
pkg_depends(ATC MANYBODY)
|
||||||
pkg_depends(LATBOLTZ MPI)
|
pkg_depends(LATBOLTZ MPI)
|
||||||
pkg_depends(SCAFACOS MPI)
|
pkg_depends(SCAFACOS MPI)
|
||||||
@ -579,13 +577,6 @@ foreach(PKG ${STANDARD_PACKAGES})
|
|||||||
RegisterPackages(${${PKG}_SOURCES_DIR})
|
RegisterPackages(${${PKG}_SOURCES_DIR})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# packages that need defines set
|
|
||||||
foreach(PKG MPIIO)
|
|
||||||
if(PKG_${PKG})
|
|
||||||
target_compile_definitions(lammps PRIVATE -DLMP_${PKG})
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# dedicated check for entire contents of accelerator packages
|
# dedicated check for entire contents of accelerator packages
|
||||||
foreach(PKG ${SUFFIX_PACKAGES})
|
foreach(PKG ${SUFFIX_PACKAGES})
|
||||||
set(${PKG}_SOURCES_DIR ${LAMMPS_SOURCE_DIR}/${PKG})
|
set(${PKG}_SOURCES_DIR ${LAMMPS_SOURCE_DIR}/${PKG})
|
||||||
|
|||||||
@ -63,7 +63,6 @@ set(ALL_PACKAGES
|
|||||||
MOFFF
|
MOFFF
|
||||||
MOLECULE
|
MOLECULE
|
||||||
MOLFILE
|
MOLFILE
|
||||||
MPIIO
|
|
||||||
NETCDF
|
NETCDF
|
||||||
OPENMP
|
OPENMP
|
||||||
OPT
|
OPT
|
||||||
|
|||||||
@ -65,7 +65,6 @@ set(ALL_PACKAGES
|
|||||||
MOFFF
|
MOFFF
|
||||||
MOLECULE
|
MOLECULE
|
||||||
MOLFILE
|
MOLFILE
|
||||||
MPIIO
|
|
||||||
NETCDF
|
NETCDF
|
||||||
OPENMP
|
OPENMP
|
||||||
OPT
|
OPT
|
||||||
|
|||||||
@ -83,7 +83,6 @@ endforeach()
|
|||||||
|
|
||||||
# these two packages require a full MPI implementation
|
# these two packages require a full MPI implementation
|
||||||
if(BUILD_MPI)
|
if(BUILD_MPI)
|
||||||
set(PKG_MPIIO ON CACHE BOOL "" FORCE)
|
|
||||||
set(PKG_LATBOLTZ ON CACHE BOOL "" FORCE)
|
set(PKG_LATBOLTZ ON CACHE BOOL "" FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,6 @@ set(PACKAGES_WITH_LIB
|
|||||||
ML-PACE
|
ML-PACE
|
||||||
ML-QUIP
|
ML-QUIP
|
||||||
MOLFILE
|
MOLFILE
|
||||||
MPIIO
|
|
||||||
NETCDF
|
NETCDF
|
||||||
PLUMED
|
PLUMED
|
||||||
PYTHON
|
PYTHON
|
||||||
|
|||||||
10
src/.gitignore
vendored
10
src/.gitignore
vendored
@ -671,20 +671,14 @@
|
|||||||
/dump_atom_gz.h
|
/dump_atom_gz.h
|
||||||
/dump_atom_zstd.cpp
|
/dump_atom_zstd.cpp
|
||||||
/dump_atom_zstd.h
|
/dump_atom_zstd.h
|
||||||
/dump_atom_mpiio.cpp
|
|
||||||
/dump_atom_mpiio.h
|
|
||||||
/dump_cfg_gz.cpp
|
/dump_cfg_gz.cpp
|
||||||
/dump_cfg_gz.h
|
/dump_cfg_gz.h
|
||||||
/dump_cfg_mpiio.cpp
|
|
||||||
/dump_cfg_mpiio.h
|
|
||||||
/dump_cfg_zstd.cpp
|
/dump_cfg_zstd.cpp
|
||||||
/dump_cfg_zstd.h
|
/dump_cfg_zstd.h
|
||||||
/dump_custom_adios.cpp
|
/dump_custom_adios.cpp
|
||||||
/dump_custom_adios.h
|
/dump_custom_adios.h
|
||||||
/dump_custom_gz.cpp
|
/dump_custom_gz.cpp
|
||||||
/dump_custom_gz.h
|
/dump_custom_gz.h
|
||||||
/dump_custom_mpiio.cpp
|
|
||||||
/dump_custom_mpiio.h
|
|
||||||
/dump_custom_zstd.cpp
|
/dump_custom_zstd.cpp
|
||||||
/dump_custom_zstd.h
|
/dump_custom_zstd.h
|
||||||
/dump_h5md.cpp
|
/dump_h5md.cpp
|
||||||
@ -703,8 +697,6 @@
|
|||||||
/dump_xtc.h
|
/dump_xtc.h
|
||||||
/dump_xyz_gz.cpp
|
/dump_xyz_gz.cpp
|
||||||
/dump_xyz_gz.h
|
/dump_xyz_gz.h
|
||||||
/dump_xyz_mpiio.cpp
|
|
||||||
/dump_xyz_mpiio.h
|
|
||||||
/dump_xyz_zstd.cpp
|
/dump_xyz_zstd.cpp
|
||||||
/dump_xyz_zstd.h
|
/dump_xyz_zstd.h
|
||||||
/dump_yaml.cpp
|
/dump_yaml.cpp
|
||||||
@ -1455,8 +1447,6 @@
|
|||||||
/remap.h
|
/remap.h
|
||||||
/remap_wrap.cpp
|
/remap_wrap.cpp
|
||||||
/remap_wrap.h
|
/remap_wrap.h
|
||||||
/restart_mpiio.cpp
|
|
||||||
/restart_mpiio.h
|
|
||||||
/rigid_const.h
|
/rigid_const.h
|
||||||
/scafacos.cpp
|
/scafacos.cpp
|
||||||
/scafacos.h
|
/scafacos.h
|
||||||
|
|||||||
@ -1,58 +0,0 @@
|
|||||||
# Install/unInstall package files in LAMMPS
|
|
||||||
# mode = 0/1/2 for uninstall/install/update
|
|
||||||
|
|
||||||
mode=$1
|
|
||||||
|
|
||||||
# enforce using portable C locale
|
|
||||||
LC_ALL=C
|
|
||||||
export LC_ALL
|
|
||||||
|
|
||||||
# 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
|
|
||||||
}
|
|
||||||
|
|
||||||
# force rebuild of files with LMP_MPIIO switch
|
|
||||||
# also read/write restart so their dependence on changed mpiio.h is rebuilt
|
|
||||||
|
|
||||||
touch ../mpiio.h
|
|
||||||
touch ../read_restart.cpp
|
|
||||||
touch ../write_restart.cpp
|
|
||||||
|
|
||||||
# all package files with no dependencies
|
|
||||||
|
|
||||||
for file in *.cpp *.h; do
|
|
||||||
test -f ${file} && action $file
|
|
||||||
done
|
|
||||||
|
|
||||||
# edit 2 Makefile.package to include/exclude LMP_MPIIO setting
|
|
||||||
|
|
||||||
if (test $1 = 1) then
|
|
||||||
|
|
||||||
if (test -e ../Makefile.package) then
|
|
||||||
sed -i -e 's/[^ \t]*MPIIO[^ \t]* //' ../Makefile.package
|
|
||||||
sed -i -e 's|^PKG_INC =[ \t]*|&-DLMP_MPIIO |' ../Makefile.package
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
elif (test $1 = 0) then
|
|
||||||
|
|
||||||
if (test -e ../Makefile.package) then
|
|
||||||
sed -i -e 's/[^ \t]*MPIIO[^ \t]* //' ../Makefile.package
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
@ -1,728 +0,0 @@
|
|||||||
/* ----------------------------------------------------------------------
|
|
||||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
||||||
https://www.lammps.org/, Sandia National Laboratories
|
|
||||||
LAMMPS development team: developers@lammps.org
|
|
||||||
|
|
||||||
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 "dump_atom_mpiio.h"
|
|
||||||
|
|
||||||
#include "domain.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "update.h"
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include "omp_compat.h"
|
|
||||||
#if defined(_OPENMP)
|
|
||||||
#include <omp.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace LAMMPS_NS;
|
|
||||||
|
|
||||||
#define MAX_TEXT_HEADER_SIZE 4096
|
|
||||||
#define DUMP_BUF_CHUNK_SIZE 16384
|
|
||||||
#define DUMP_BUF_INCREMENT_SIZE 4096
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
DumpAtomMPIIO::DumpAtomMPIIO(LAMMPS *lmp, int narg, char **arg) : DumpAtom(lmp, narg, arg)
|
|
||||||
{
|
|
||||||
if (me == 0)
|
|
||||||
error->warning(FLERR, "MPI-IO output is unmaintained and unreliable. Use with caution.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
DumpAtomMPIIO::~DumpAtomMPIIO()
|
|
||||||
{
|
|
||||||
if (multifile == 0) MPI_File_close(&mpifh);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpAtomMPIIO::openfile()
|
|
||||||
{
|
|
||||||
if (singlefile_opened) { // single file already opened, so just return after resetting filesize
|
|
||||||
mpifo = currentFileSize;
|
|
||||||
MPI_File_set_size(mpifh, mpifo + headerSize + sumFileSize);
|
|
||||||
currentFileSize = mpifo + headerSize + sumFileSize;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (multifile == 0) singlefile_opened = 1;
|
|
||||||
|
|
||||||
// if one file per timestep, replace '*' with current timestep
|
|
||||||
|
|
||||||
filecurrent = filename;
|
|
||||||
|
|
||||||
if (multifile) {
|
|
||||||
filecurrent = utils::strdup(utils::star_subst(filecurrent, update->ntimestep, padflag));
|
|
||||||
if (maxfiles > 0) {
|
|
||||||
if (numfiles < maxfiles) {
|
|
||||||
nameslist[numfiles] = utils::strdup(filecurrent);
|
|
||||||
++numfiles;
|
|
||||||
} else {
|
|
||||||
remove(nameslist[fileidx]);
|
|
||||||
delete[] nameslist[fileidx];
|
|
||||||
nameslist[fileidx] = utils::strdup(filecurrent);
|
|
||||||
fileidx = (fileidx + 1) % maxfiles;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (append_flag) { // append open
|
|
||||||
int err = MPI_File_open(world, filecurrent, MPI_MODE_CREATE | MPI_MODE_APPEND | MPI_MODE_WRONLY,
|
|
||||||
MPI_INFO_NULL, &mpifh);
|
|
||||||
if (err != MPI_SUCCESS)
|
|
||||||
error->one(FLERR, "Cannot open dump file {}: {}", filecurrent, utils::getsyserror());
|
|
||||||
|
|
||||||
int myrank;
|
|
||||||
MPI_Comm_rank(world, &myrank);
|
|
||||||
if (myrank == 0) MPI_File_get_size(mpifh, &mpifo);
|
|
||||||
MPI_Bcast(&mpifo, 1, MPI_LMP_BIGINT, 0, world);
|
|
||||||
MPI_File_set_size(mpifh, mpifo + headerSize + sumFileSize);
|
|
||||||
currentFileSize = mpifo + headerSize + sumFileSize;
|
|
||||||
|
|
||||||
} else { // replace open
|
|
||||||
|
|
||||||
int err =
|
|
||||||
MPI_File_open(world, filecurrent, MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &mpifh);
|
|
||||||
if (err != MPI_SUCCESS)
|
|
||||||
error->one(FLERR, "Cannot open dump file {}: {}", filecurrent, utils::getsyserror());
|
|
||||||
|
|
||||||
mpifo = 0;
|
|
||||||
|
|
||||||
MPI_File_set_size(mpifh, (MPI_Offset) (headerSize + sumFileSize));
|
|
||||||
currentFileSize = (headerSize + sumFileSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpAtomMPIIO::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 dump lines in snapshot
|
|
||||||
// nmax = max # of dump lines on any proc
|
|
||||||
|
|
||||||
bigint bnme = nme;
|
|
||||||
MPI_Allreduce(&bnme, &ntotal, 1, MPI_LMP_BIGINT, MPI_SUM, world);
|
|
||||||
|
|
||||||
int nmax;
|
|
||||||
MPI_Allreduce(&nme, &nmax, 1, MPI_INT, MPI_MAX, world);
|
|
||||||
|
|
||||||
// write timestep header
|
|
||||||
// for multiproc,
|
|
||||||
// nheader = # of lines in this file via Allreduce on clustercomm
|
|
||||||
|
|
||||||
bigint nheader = ntotal;
|
|
||||||
|
|
||||||
// ensure 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 (nmax > maxbuf) {
|
|
||||||
if ((bigint) nmax * size_one > MAXSMALLINT)
|
|
||||||
error->all(FLERR, "Too much per-proc info for dump");
|
|
||||||
maxbuf = nmax;
|
|
||||||
memory->destroy(buf);
|
|
||||||
memory->create(buf, (maxbuf * size_one), "dump:buf");
|
|
||||||
}
|
|
||||||
if (sort_flag && sortcol == 0 && nmax > maxids) {
|
|
||||||
maxids = nmax;
|
|
||||||
memory->destroy(ids);
|
|
||||||
memory->create(ids, maxids, "dump:ids");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sort_flag && sortcol == 0)
|
|
||||||
pack(ids);
|
|
||||||
else
|
|
||||||
pack(nullptr);
|
|
||||||
if (sort_flag) sort();
|
|
||||||
|
|
||||||
// determine how much data needs to be written for setting the file size and prepocess it prior to writing
|
|
||||||
performEstimate = 1;
|
|
||||||
write_header(nheader);
|
|
||||||
write_data(nme, buf);
|
|
||||||
MPI_Bcast(&sumFileSize, 1, MPI_LMP_BIGINT, (nprocs - 1), world);
|
|
||||||
|
|
||||||
openfile();
|
|
||||||
|
|
||||||
performEstimate = 0;
|
|
||||||
write_header(nheader); // mpifo now points to end of header info
|
|
||||||
|
|
||||||
// now actually write the data
|
|
||||||
performEstimate = 0;
|
|
||||||
write_data(nme, buf);
|
|
||||||
|
|
||||||
if (multifile) MPI_File_close(&mpifh);
|
|
||||||
if (multifile) delete[] filecurrent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpAtomMPIIO::init_style()
|
|
||||||
{
|
|
||||||
if (image_flag == 0)
|
|
||||||
size_one = 5;
|
|
||||||
else
|
|
||||||
size_one = 8;
|
|
||||||
|
|
||||||
// format = copy of default or user-specified line format
|
|
||||||
// default depends on image flags
|
|
||||||
|
|
||||||
delete[] format;
|
|
||||||
if (format_line_user) {
|
|
||||||
format = utils::strdup(std::string(format_line_user) + "\n");
|
|
||||||
} else {
|
|
||||||
if (image_flag == 0)
|
|
||||||
format = utils::strdup(TAGINT_FORMAT " %d %g %g %g\n");
|
|
||||||
else
|
|
||||||
format = utils::strdup(TAGINT_FORMAT " %d %g %g %g %d %d %d\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup boundary string
|
|
||||||
|
|
||||||
domain->boundary_string(boundstr);
|
|
||||||
|
|
||||||
// setup column string
|
|
||||||
|
|
||||||
std::string default_columns;
|
|
||||||
|
|
||||||
if (scale_flag == 0 && image_flag == 0)
|
|
||||||
default_columns = "id type x y z";
|
|
||||||
else if (scale_flag == 0 && image_flag == 1)
|
|
||||||
default_columns = "id type x y z ix iy iz";
|
|
||||||
else if (scale_flag == 1 && image_flag == 0)
|
|
||||||
default_columns = "id type xs ys zs";
|
|
||||||
else if (scale_flag == 1 && image_flag == 1)
|
|
||||||
default_columns = "id type xs ys zs ix iy iz";
|
|
||||||
|
|
||||||
int icol = 0;
|
|
||||||
columns.clear();
|
|
||||||
for (const auto &item : utils::split_words(default_columns)) {
|
|
||||||
if (columns.size()) columns += " ";
|
|
||||||
if (keyword_user[icol].size())
|
|
||||||
columns += keyword_user[icol];
|
|
||||||
else
|
|
||||||
columns += item;
|
|
||||||
++icol;
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup function ptrs
|
|
||||||
|
|
||||||
if (binary && domain->triclinic == 0)
|
|
||||||
header_choice = &DumpAtomMPIIO::header_binary;
|
|
||||||
else if (binary && domain->triclinic == 1)
|
|
||||||
header_choice = &DumpAtomMPIIO::header_binary_triclinic;
|
|
||||||
else if (!binary && domain->triclinic == 0)
|
|
||||||
header_choice = &DumpAtomMPIIO::header_item;
|
|
||||||
else if (!binary && domain->triclinic == 1)
|
|
||||||
header_choice = &DumpAtomMPIIO::header_item_triclinic;
|
|
||||||
|
|
||||||
if (scale_flag == 1 && image_flag == 0 && domain->triclinic == 0)
|
|
||||||
pack_choice = &DumpAtomMPIIO::pack_scale_noimage;
|
|
||||||
else if (scale_flag == 1 && image_flag == 1 && domain->triclinic == 0)
|
|
||||||
pack_choice = &DumpAtomMPIIO::pack_scale_image;
|
|
||||||
else if (scale_flag == 1 && image_flag == 0 && domain->triclinic == 1)
|
|
||||||
pack_choice = &DumpAtomMPIIO::pack_scale_noimage_triclinic;
|
|
||||||
else if (scale_flag == 1 && image_flag == 1 && domain->triclinic == 1)
|
|
||||||
pack_choice = &DumpAtomMPIIO::pack_scale_image_triclinic;
|
|
||||||
else if (scale_flag == 0 && image_flag == 0)
|
|
||||||
pack_choice = &DumpAtomMPIIO::pack_noscale_noimage;
|
|
||||||
else if (scale_flag == 0 && image_flag == 1)
|
|
||||||
pack_choice = &DumpAtomMPIIO::pack_noscale_image;
|
|
||||||
|
|
||||||
if (binary)
|
|
||||||
write_choice = &DumpAtomMPIIO::write_binary;
|
|
||||||
else if (buffer_flag == 1)
|
|
||||||
write_choice = &DumpAtomMPIIO::write_string;
|
|
||||||
else if (image_flag == 0)
|
|
||||||
write_choice = &DumpAtomMPIIO::write_lines_noimage;
|
|
||||||
else if (image_flag == 1)
|
|
||||||
write_choice = &DumpAtomMPIIO::write_lines_image;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpAtomMPIIO::write_header(bigint ndump)
|
|
||||||
{
|
|
||||||
if (!header_choice) error->all(FLERR, "Must not use 'run pre no' after creating a new dump");
|
|
||||||
|
|
||||||
(this->*header_choice)(ndump);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpAtomMPIIO::header_binary(bigint ndump)
|
|
||||||
{
|
|
||||||
if (performEstimate) {
|
|
||||||
|
|
||||||
headerBuffer = (char *) malloc((2 * sizeof(bigint)) + (9 * sizeof(int)) + (6 * sizeof(double)));
|
|
||||||
|
|
||||||
headerSize = 0;
|
|
||||||
memcpy(headerBuffer + headerSize, &update->ntimestep, sizeof(bigint));
|
|
||||||
headerSize += sizeof(bigint);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &ndump, sizeof(bigint));
|
|
||||||
headerSize += sizeof(bigint);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &domain->triclinic, sizeof(int));
|
|
||||||
headerSize += sizeof(int);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &domain->boundary[0][0], 6 * sizeof(int));
|
|
||||||
headerSize += 6 * sizeof(int);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxxlo, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxxhi, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxylo, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxyhi, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxzlo, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxzhi, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &size_one, sizeof(int));
|
|
||||||
headerSize += sizeof(int);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &nprocs, sizeof(int));
|
|
||||||
headerSize += sizeof(int);
|
|
||||||
} else { // write data
|
|
||||||
if (me == 0)
|
|
||||||
MPI_File_write_at(mpifh, mpifo, headerBuffer, headerSize, MPI_BYTE, MPI_STATUS_IGNORE);
|
|
||||||
mpifo += headerSize;
|
|
||||||
free(headerBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpAtomMPIIO::header_binary_triclinic(bigint ndump)
|
|
||||||
{
|
|
||||||
if (performEstimate) {
|
|
||||||
|
|
||||||
headerBuffer = (char *) malloc((2 * sizeof(bigint)) + (9 * sizeof(int)) + (9 * sizeof(double)));
|
|
||||||
|
|
||||||
headerSize = 0;
|
|
||||||
memcpy(headerBuffer + headerSize, &update->ntimestep, sizeof(bigint));
|
|
||||||
headerSize += sizeof(bigint);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &ndump, sizeof(bigint));
|
|
||||||
headerSize += sizeof(bigint);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &domain->triclinic, sizeof(int));
|
|
||||||
headerSize += sizeof(int);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &domain->boundary[0][0], 6 * sizeof(int));
|
|
||||||
headerSize += 6 * sizeof(int);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxxlo, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxxhi, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxylo, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxyhi, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxzlo, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxzhi, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxxy, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxxz, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxyz, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &size_one, sizeof(int));
|
|
||||||
headerSize += sizeof(int);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &nprocs, sizeof(int));
|
|
||||||
headerSize += sizeof(int);
|
|
||||||
|
|
||||||
} else { // write data
|
|
||||||
|
|
||||||
if (me == 0)
|
|
||||||
MPI_File_write_at(mpifh, mpifo, headerBuffer, headerSize, MPI_BYTE, MPI_STATUS_IGNORE);
|
|
||||||
mpifo += headerSize;
|
|
||||||
free(headerBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpAtomMPIIO::header_item(bigint ndump)
|
|
||||||
{
|
|
||||||
if (performEstimate) {
|
|
||||||
|
|
||||||
auto itemtxt = fmt::format("ITEM: TIMESTEP\n{}\n", update->ntimestep);
|
|
||||||
itemtxt += fmt::format("ITEM: NUMBER OF ATOMS\n{}\n", ndump);
|
|
||||||
itemtxt += fmt::format("ITEM: BOX BOUNDS {}\n", boundstr);
|
|
||||||
itemtxt += fmt::format("{} {}\n{} {}\n{} {}\n", boxxlo, boxxhi, boxylo, boxyhi, boxzlo, boxzhi);
|
|
||||||
itemtxt += fmt::format("ITEM: ATOMS {}\n", columns);
|
|
||||||
|
|
||||||
headerSize = itemtxt.size();
|
|
||||||
headerBuffer = utils::strdup(itemtxt);
|
|
||||||
|
|
||||||
} else { // write data
|
|
||||||
|
|
||||||
if (me == 0)
|
|
||||||
MPI_File_write_at(mpifh, mpifo, headerBuffer, headerSize, MPI_CHAR, MPI_STATUS_IGNORE);
|
|
||||||
mpifo += headerSize;
|
|
||||||
delete[] headerBuffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpAtomMPIIO::header_item_triclinic(bigint ndump)
|
|
||||||
{
|
|
||||||
if (performEstimate) {
|
|
||||||
|
|
||||||
auto itemtxt = fmt::format("ITEM: TIMESTEP\n{}\n", update->ntimestep);
|
|
||||||
itemtxt += fmt::format("ITEM: NUMBER OF ATOMS\n{}\n", ndump);
|
|
||||||
itemtxt += fmt::format("ITEM: BOX BOUNDS xy xz yz {}\n", boundstr);
|
|
||||||
itemtxt += fmt::format("{} {} {}\n{} {} {}\n{} {} {}\n", boxxlo, boxxhi, boxxy, boxylo, boxyhi,
|
|
||||||
boxxz, boxzlo, boxzhi, boxyz);
|
|
||||||
itemtxt += fmt::format("ITEM: ATOMS {}\n", columns);
|
|
||||||
|
|
||||||
headerSize = itemtxt.size();
|
|
||||||
headerBuffer = utils::strdup(itemtxt);
|
|
||||||
|
|
||||||
} else { // write data
|
|
||||||
|
|
||||||
if (me == 0)
|
|
||||||
MPI_File_write_at(mpifh, mpifo, headerBuffer, headerSize, MPI_CHAR, MPI_STATUS_IGNORE);
|
|
||||||
mpifo += headerSize;
|
|
||||||
delete[] headerBuffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpAtomMPIIO::write_data(int n, double *mybuf)
|
|
||||||
{
|
|
||||||
(this->*write_choice)(n, mybuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpAtomMPIIO::write_binary(int n, double *mybuf)
|
|
||||||
{
|
|
||||||
n *= size_one;
|
|
||||||
|
|
||||||
if (performEstimate) {
|
|
||||||
|
|
||||||
bigint incPrefix = 0;
|
|
||||||
bigint bigintNme = (bigint) nme;
|
|
||||||
MPI_Scan(&bigintNme, &incPrefix, 1, MPI_LMP_BIGINT, MPI_SUM, world);
|
|
||||||
sumFileSize = (incPrefix * size_one * sizeof(double)) + (nprocs * sizeof(int));
|
|
||||||
offsetFromHeader = ((incPrefix - bigintNme) * size_one * sizeof(double)) + (me * sizeof(int));
|
|
||||||
} else {
|
|
||||||
int byteBufSize = (n * sizeof(double)) + sizeof(int);
|
|
||||||
|
|
||||||
char *bufWithSize;
|
|
||||||
memory->create(bufWithSize, byteBufSize, "dump:bufWithSize");
|
|
||||||
memcpy(bufWithSize, (char *) (&n), sizeof(int));
|
|
||||||
memcpy(&((char *) bufWithSize)[sizeof(int)], mybuf, (n * sizeof(double)));
|
|
||||||
MPI_File_write_at_all(mpifh, mpifo + offsetFromHeader, bufWithSize, byteBufSize, MPI_BYTE,
|
|
||||||
MPI_STATUS_IGNORE);
|
|
||||||
memory->destroy(bufWithSize);
|
|
||||||
|
|
||||||
if (flush_flag) MPI_File_sync(mpifh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpAtomMPIIO::write_string(int n, double *mybuf)
|
|
||||||
{
|
|
||||||
if (performEstimate) {
|
|
||||||
|
|
||||||
#if defined(_OPENMP)
|
|
||||||
int nthreads = omp_get_max_threads();
|
|
||||||
if (nthreads > 1)
|
|
||||||
nsme = convert_string_omp(n, mybuf);
|
|
||||||
else {
|
|
||||||
nsme = convert_string(n, mybuf);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
nsme = convert_string(n, mybuf);
|
|
||||||
#endif
|
|
||||||
bigint incPrefix = 0;
|
|
||||||
bigint bigintNsme = (bigint) nsme;
|
|
||||||
MPI_Scan(&bigintNsme, &incPrefix, 1, MPI_LMP_BIGINT, MPI_SUM, world);
|
|
||||||
sumFileSize = (incPrefix * sizeof(char));
|
|
||||||
offsetFromHeader = ((incPrefix - bigintNsme) * sizeof(char));
|
|
||||||
} else {
|
|
||||||
MPI_File_write_at_all(mpifh, mpifo + offsetFromHeader, sbuf, nsme, MPI_CHAR, MPI_STATUS_IGNORE);
|
|
||||||
if (flush_flag) MPI_File_sync(mpifh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
int DumpAtomMPIIO::convert_string(int n, double *mybuf)
|
|
||||||
{
|
|
||||||
if (image_flag == 0)
|
|
||||||
return convert_noimage(n, mybuf);
|
|
||||||
else
|
|
||||||
return convert_image(n, mybuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#if defined(_OPENMP)
|
|
||||||
|
|
||||||
int DumpAtomMPIIO::convert_string_omp(int n, double *mybuf)
|
|
||||||
{
|
|
||||||
if (image_flag == 0)
|
|
||||||
return convert_noimage_omp(n, mybuf);
|
|
||||||
else
|
|
||||||
return convert_image_omp(n, mybuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
|
||||||
multithreaded version - convert mybuf of doubles to one big formatted string in sbuf
|
|
||||||
return -1 if strlen exceeds an int, since used as arg in MPI calls in Dump
|
|
||||||
------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
int DumpAtomMPIIO::convert_image_omp(int n, double *mybuf)
|
|
||||||
{
|
|
||||||
char **mpifh_buffer_line_per_thread;
|
|
||||||
int mpifhStringCount;
|
|
||||||
int *mpifhStringCountPerThread, *bufOffset, *bufRange, *bufLength;
|
|
||||||
|
|
||||||
mpifhStringCount = 0;
|
|
||||||
|
|
||||||
int nthreads = omp_get_max_threads();
|
|
||||||
if (nthreads > n) { // call serial version
|
|
||||||
convert_string(n, mybuf);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
memory->create(mpifhStringCountPerThread, nthreads, "dump:mpifhStringCountPerThread");
|
|
||||||
mpifh_buffer_line_per_thread = (char **) malloc(nthreads * sizeof(char *));
|
|
||||||
memory->create(bufOffset, nthreads, "dump:bufOffset");
|
|
||||||
memory->create(bufRange, nthreads, "dump:bufRange");
|
|
||||||
memory->create(bufLength, nthreads, "dump:bufLength");
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (i = 0; i < (nthreads - 1); i++) {
|
|
||||||
mpifhStringCountPerThread[i] = 0;
|
|
||||||
bufOffset[i] = (int) (i * (int) (floor((double) n / (double) nthreads)) * size_one);
|
|
||||||
bufRange[i] = (int) (floor((double) n / (double) nthreads));
|
|
||||||
bufLength[i] = DUMP_BUF_CHUNK_SIZE;
|
|
||||||
mpifh_buffer_line_per_thread[i] = (char *) malloc(DUMP_BUF_CHUNK_SIZE * sizeof(char));
|
|
||||||
mpifh_buffer_line_per_thread[i][0] = '\0';
|
|
||||||
}
|
|
||||||
mpifhStringCountPerThread[i] = 0;
|
|
||||||
bufOffset[i] = (int) (i * (int) (floor((double) n / (double) nthreads)) * size_one);
|
|
||||||
bufRange[i] = n - (i * (int) (floor((double) n / (double) nthreads)));
|
|
||||||
bufLength[i] = DUMP_BUF_CHUNK_SIZE;
|
|
||||||
mpifh_buffer_line_per_thread[i] = (char *) malloc(DUMP_BUF_CHUNK_SIZE * sizeof(char));
|
|
||||||
mpifh_buffer_line_per_thread[i][0] = '\0';
|
|
||||||
|
|
||||||
#pragma omp parallel LMP_DEFAULT_NONE LMP_SHARED(bufOffset, bufRange, bufLength, \
|
|
||||||
mpifhStringCountPerThread, \
|
|
||||||
mpifh_buffer_line_per_thread, mybuf)
|
|
||||||
{
|
|
||||||
int tid = omp_get_thread_num();
|
|
||||||
int m = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < bufRange[tid]; i++) {
|
|
||||||
|
|
||||||
if ((bufLength[tid] - mpifhStringCountPerThread[tid]) < DUMP_BUF_INCREMENT_SIZE) {
|
|
||||||
mpifh_buffer_line_per_thread[tid] = (char *) realloc(
|
|
||||||
mpifh_buffer_line_per_thread[tid],
|
|
||||||
(mpifhStringCountPerThread[tid] + DUMP_BUF_CHUNK_SIZE) * sizeof(char));
|
|
||||||
bufLength[tid] = (mpifhStringCountPerThread[tid] + DUMP_BUF_CHUNK_SIZE) * sizeof(char);
|
|
||||||
}
|
|
||||||
|
|
||||||
mpifhStringCountPerThread[tid] +=
|
|
||||||
sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]), format,
|
|
||||||
static_cast<int>(mybuf[bufOffset[tid] + m]),
|
|
||||||
static_cast<int>(mybuf[bufOffset[tid] + m + 1]), mybuf[bufOffset[tid] + m + 2],
|
|
||||||
mybuf[bufOffset[tid] + m + 3], mybuf[bufOffset[tid] + m + 4],
|
|
||||||
static_cast<int>(mybuf[bufOffset[tid] + m + 5]),
|
|
||||||
static_cast<int>(mybuf[bufOffset[tid] + m + 6]),
|
|
||||||
static_cast<int>(mybuf[bufOffset[tid] + m + 7]));
|
|
||||||
m += size_one;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma omp barrier
|
|
||||||
mpifhStringCount = 0;
|
|
||||||
for (i = 0; i < nthreads; i++) { mpifhStringCount += mpifhStringCountPerThread[i]; }
|
|
||||||
|
|
||||||
memory->destroy(bufOffset);
|
|
||||||
memory->destroy(bufRange);
|
|
||||||
memory->destroy(bufLength);
|
|
||||||
|
|
||||||
if (mpifhStringCount > 0) {
|
|
||||||
if (mpifhStringCount > maxsbuf) {
|
|
||||||
if (mpifhStringCount > MAXSMALLINT) return -1;
|
|
||||||
maxsbuf = mpifhStringCount + 1;
|
|
||||||
memory->grow(sbuf, maxsbuf, "dump:sbuf");
|
|
||||||
}
|
|
||||||
sbuf[0] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < nthreads; i++) {
|
|
||||||
strcat(sbuf, mpifh_buffer_line_per_thread[i]);
|
|
||||||
free(mpifh_buffer_line_per_thread[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
memory->destroy(mpifhStringCountPerThread);
|
|
||||||
free(mpifh_buffer_line_per_thread);
|
|
||||||
}
|
|
||||||
return mpifhStringCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
|
||||||
multithreaded version - convert mybuf of doubles to one big formatted string in sbuf
|
|
||||||
return -1 if strlen exceeds an int, since used as arg in MPI calls in Dump
|
|
||||||
------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
int DumpAtomMPIIO::convert_noimage_omp(int n, double *mybuf)
|
|
||||||
{
|
|
||||||
char **mpifh_buffer_line_per_thread;
|
|
||||||
int mpifhStringCount;
|
|
||||||
int *mpifhStringCountPerThread, *bufOffset, *bufRange, *bufLength;
|
|
||||||
|
|
||||||
mpifhStringCount = 0;
|
|
||||||
|
|
||||||
int nthreads = omp_get_max_threads();
|
|
||||||
if (nthreads > n) { // call serial version
|
|
||||||
convert_string(n, mybuf);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
memory->create(mpifhStringCountPerThread, nthreads, "dump:mpifhStringCountPerThread");
|
|
||||||
mpifh_buffer_line_per_thread = (char **) malloc(nthreads * sizeof(char *));
|
|
||||||
memory->create(bufOffset, nthreads, "dump:bufOffset");
|
|
||||||
memory->create(bufRange, nthreads, "dump:bufRange");
|
|
||||||
memory->create(bufLength, nthreads, "dump:bufLength");
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (i = 0; i < (nthreads - 1); i++) {
|
|
||||||
mpifhStringCountPerThread[i] = 0;
|
|
||||||
bufOffset[i] = (int) (i * (int) (floor((double) n / (double) nthreads)) * size_one);
|
|
||||||
bufRange[i] = (int) (floor((double) n / (double) nthreads));
|
|
||||||
bufLength[i] = DUMP_BUF_CHUNK_SIZE;
|
|
||||||
mpifh_buffer_line_per_thread[i] = (char *) malloc(DUMP_BUF_CHUNK_SIZE * sizeof(char));
|
|
||||||
mpifh_buffer_line_per_thread[i][0] = '\0';
|
|
||||||
}
|
|
||||||
mpifhStringCountPerThread[i] = 0;
|
|
||||||
bufOffset[i] = (int) (i * (int) (floor((double) n / (double) nthreads)) * size_one);
|
|
||||||
bufRange[i] = n - (i * (int) (floor((double) n / (double) nthreads)));
|
|
||||||
bufLength[i] = DUMP_BUF_CHUNK_SIZE;
|
|
||||||
mpifh_buffer_line_per_thread[i] = (char *) malloc(DUMP_BUF_CHUNK_SIZE * sizeof(char));
|
|
||||||
mpifh_buffer_line_per_thread[i][0] = '\0';
|
|
||||||
|
|
||||||
#pragma omp parallel LMP_DEFAULT_NONE LMP_SHARED(bufOffset, bufRange, bufLength, \
|
|
||||||
mpifhStringCountPerThread, \
|
|
||||||
mpifh_buffer_line_per_thread, mybuf)
|
|
||||||
{
|
|
||||||
int tid = omp_get_thread_num();
|
|
||||||
int m = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < bufRange[tid]; i++) {
|
|
||||||
|
|
||||||
if ((bufLength[tid] - mpifhStringCountPerThread[tid]) < DUMP_BUF_INCREMENT_SIZE) {
|
|
||||||
mpifh_buffer_line_per_thread[tid] = (char *) realloc(
|
|
||||||
mpifh_buffer_line_per_thread[tid],
|
|
||||||
(mpifhStringCountPerThread[tid] + DUMP_BUF_CHUNK_SIZE) * sizeof(char));
|
|
||||||
bufLength[tid] = (mpifhStringCountPerThread[tid] + DUMP_BUF_CHUNK_SIZE) * sizeof(char);
|
|
||||||
}
|
|
||||||
|
|
||||||
mpifhStringCountPerThread[tid] +=
|
|
||||||
sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]), format,
|
|
||||||
static_cast<int>(mybuf[bufOffset[tid] + m]),
|
|
||||||
static_cast<int>(mybuf[bufOffset[tid] + m + 1]), mybuf[bufOffset[tid] + m + 2],
|
|
||||||
mybuf[bufOffset[tid] + m + 3], mybuf[bufOffset[tid] + m + 4]);
|
|
||||||
m += size_one;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma omp barrier
|
|
||||||
mpifhStringCount = 0;
|
|
||||||
for (i = 0; i < nthreads; i++) { mpifhStringCount += mpifhStringCountPerThread[i]; }
|
|
||||||
|
|
||||||
memory->destroy(bufOffset);
|
|
||||||
memory->destroy(bufRange);
|
|
||||||
memory->destroy(bufLength);
|
|
||||||
|
|
||||||
if (mpifhStringCount > 0) {
|
|
||||||
if (mpifhStringCount > maxsbuf) {
|
|
||||||
if (mpifhStringCount > MAXSMALLINT) return -1;
|
|
||||||
maxsbuf = mpifhStringCount + 1;
|
|
||||||
memory->grow(sbuf, maxsbuf, "dump:sbuf");
|
|
||||||
}
|
|
||||||
sbuf[0] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < nthreads; i++) {
|
|
||||||
strcat(sbuf, mpifh_buffer_line_per_thread[i]);
|
|
||||||
free(mpifh_buffer_line_per_thread[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
memory->destroy(mpifhStringCountPerThread);
|
|
||||||
free(mpifh_buffer_line_per_thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mpifhStringCount;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -1,72 +0,0 @@
|
|||||||
/* -*- c++ -*- ----------------------------------------------------------
|
|
||||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
||||||
https://www.lammps.org/, Sandia National Laboratories
|
|
||||||
LAMMPS development team: developers@lammps.org
|
|
||||||
|
|
||||||
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
|
|
||||||
// clang-format off
|
|
||||||
DumpStyle(atom/mpiio,DumpAtomMPIIO);
|
|
||||||
// clang-format on
|
|
||||||
#else
|
|
||||||
|
|
||||||
#ifndef LMP_DUMP_ATOM_MPIIO_H
|
|
||||||
#define LMP_DUMP_ATOM_MPIIO_H
|
|
||||||
|
|
||||||
#include "dump_atom.h"
|
|
||||||
|
|
||||||
namespace LAMMPS_NS {
|
|
||||||
|
|
||||||
class DumpAtomMPIIO : public DumpAtom {
|
|
||||||
|
|
||||||
public:
|
|
||||||
DumpAtomMPIIO(class LAMMPS *, int, char **);
|
|
||||||
~DumpAtomMPIIO() override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bigint
|
|
||||||
sumFileSize; // size in bytes of the file up through this rank offset from the end of the header data
|
|
||||||
char *headerBuffer; // buffer for holding header data
|
|
||||||
|
|
||||||
MPI_File mpifh;
|
|
||||||
MPI_Offset mpifo, offsetFromHeader, headerSize, currentFileSize;
|
|
||||||
int performEstimate; // switch for write_data and write_header methods to use for gathering data and detemining filesize for preallocation vs actually writing the data
|
|
||||||
char *filecurrent; // name of file for this round (with % and * replaced)
|
|
||||||
|
|
||||||
void openfile() override;
|
|
||||||
void write_header(bigint) override;
|
|
||||||
void write() override;
|
|
||||||
void write_data(int, double *) override;
|
|
||||||
|
|
||||||
void init_style() override;
|
|
||||||
typedef void (DumpAtomMPIIO::*FnPtrHeader)(bigint);
|
|
||||||
FnPtrHeader header_choice; // ptr to write header functions
|
|
||||||
void header_binary(bigint);
|
|
||||||
void header_binary_triclinic(bigint);
|
|
||||||
void header_item(bigint);
|
|
||||||
void header_item_triclinic(bigint);
|
|
||||||
|
|
||||||
#if defined(_OPENMP)
|
|
||||||
int convert_string_omp(int, double *); // multithreaded version of convert_string
|
|
||||||
int convert_image_omp(int, double *); // multithreaded version of convert_image
|
|
||||||
int convert_noimage_omp(int, double *); // multithreaded version of convert_noimage
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int convert_string(int, double *) override;
|
|
||||||
typedef void (DumpAtomMPIIO::*FnPtrData)(int, double *);
|
|
||||||
FnPtrData write_choice; // ptr to write data functions
|
|
||||||
void write_binary(int, double *);
|
|
||||||
void write_string(int, double *);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace LAMMPS_NS
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@ -1,488 +0,0 @@
|
|||||||
// clang-format off
|
|
||||||
/* ----------------------------------------------------------------------
|
|
||||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
||||||
https://www.lammps.org/, Sandia National Laboratories
|
|
||||||
LAMMPS development team: developers@lammps.org
|
|
||||||
|
|
||||||
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 "omp_compat.h"
|
|
||||||
#include "dump_cfg_mpiio.h"
|
|
||||||
|
|
||||||
#include "atom.h"
|
|
||||||
#include "domain.h"
|
|
||||||
#include "update.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#ifdef LMP_USER_IO_TIMER
|
|
||||||
#include <sys/times.h>
|
|
||||||
#include <hwi/include/bqc/A2_inlines.h>
|
|
||||||
long dumpCFGTimestamps[10];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_OPENMP)
|
|
||||||
#include <omp.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace LAMMPS_NS;
|
|
||||||
|
|
||||||
#define MAX_TEXT_HEADER_SIZE 4096
|
|
||||||
#define DUMP_BUF_CHUNK_SIZE 16384
|
|
||||||
#define DUMP_BUF_INCREMENT_SIZE 4096
|
|
||||||
|
|
||||||
#define UNWRAPEXPAND 10.0
|
|
||||||
#define ONEFIELD 32
|
|
||||||
#define DELTA 1048576
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
DumpCFGMPIIO::DumpCFGMPIIO(LAMMPS *lmp, int narg, char **arg) :
|
|
||||||
DumpCFG(lmp, narg, arg)
|
|
||||||
{
|
|
||||||
if (me == 0)
|
|
||||||
error->warning(FLERR,"MPI-IO output is unmaintained and unreliable. Use with caution.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
DumpCFGMPIIO::~DumpCFGMPIIO()
|
|
||||||
{
|
|
||||||
if (multifile == 0) MPI_File_close(&mpifh);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpCFGMPIIO::openfile()
|
|
||||||
{
|
|
||||||
if (singlefile_opened) { // single file already opened, so just return after resetting filesize
|
|
||||||
mpifo = currentFileSize;
|
|
||||||
MPI_File_set_size(mpifh,mpifo+headerSize+sumFileSize);
|
|
||||||
currentFileSize = mpifo+headerSize+sumFileSize;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (multifile == 0) singlefile_opened = 1;
|
|
||||||
|
|
||||||
// if one file per timestep, replace '*' with current timestep
|
|
||||||
|
|
||||||
filecurrent = filename;
|
|
||||||
|
|
||||||
if (multifile) {
|
|
||||||
filecurrent = utils::strdup(utils::star_subst(filecurrent, update->ntimestep, padflag));
|
|
||||||
if (maxfiles > 0) {
|
|
||||||
if (numfiles < maxfiles) {
|
|
||||||
nameslist[numfiles] = utils::strdup(filecurrent);
|
|
||||||
++numfiles;
|
|
||||||
} else {
|
|
||||||
remove(nameslist[fileidx]);
|
|
||||||
delete[] nameslist[fileidx];
|
|
||||||
nameslist[fileidx] = utils::strdup(filecurrent);
|
|
||||||
fileidx = (fileidx + 1) % maxfiles;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (append_flag) { // append open
|
|
||||||
int err = MPI_File_open( world, filecurrent, MPI_MODE_CREATE | MPI_MODE_APPEND |
|
|
||||||
MPI_MODE_WRONLY, MPI_INFO_NULL, &mpifh);
|
|
||||||
if (err != MPI_SUCCESS) error->one(FLERR, "Cannot open dump file {}", filecurrent);
|
|
||||||
|
|
||||||
int myrank;
|
|
||||||
MPI_Comm_rank(world,&myrank);
|
|
||||||
if (myrank == 0)
|
|
||||||
MPI_File_get_size(mpifh,&mpifo);
|
|
||||||
MPI_Bcast(&mpifo, 1, MPI_LMP_BIGINT, 0, world);
|
|
||||||
MPI_File_set_size(mpifh,mpifo+headerSize+sumFileSize);
|
|
||||||
currentFileSize = mpifo+headerSize+sumFileSize;
|
|
||||||
|
|
||||||
} else { // replace open
|
|
||||||
|
|
||||||
int err = MPI_File_open( world, filecurrent, MPI_MODE_CREATE | MPI_MODE_WRONLY,
|
|
||||||
MPI_INFO_NULL, &mpifh);
|
|
||||||
if (err != MPI_SUCCESS) error->one(FLERR, "Cannot open dump file {}", filecurrent);
|
|
||||||
mpifo = 0;
|
|
||||||
|
|
||||||
MPI_File_set_size(mpifh,(MPI_Offset) (headerSize+sumFileSize));
|
|
||||||
currentFileSize = (headerSize+sumFileSize);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpCFGMPIIO::write()
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef LMP_USER_IO_TIMER
|
|
||||||
long startTimeBase, endTimeBase;
|
|
||||||
MPI_Barrier(world); // timestamp barrier
|
|
||||||
if (me == 0)
|
|
||||||
startTimeBase = GetTimeBase();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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 dump lines in snapshot
|
|
||||||
// nmax = max # of dump lines on any proc
|
|
||||||
|
|
||||||
bigint bnme = nme;
|
|
||||||
MPI_Allreduce(&bnme,&ntotal,1,MPI_LMP_BIGINT,MPI_SUM,world);
|
|
||||||
|
|
||||||
int nmax;
|
|
||||||
MPI_Allreduce(&nme,&nmax,1,MPI_INT,MPI_MAX,world);
|
|
||||||
|
|
||||||
// write timestep header
|
|
||||||
// for multiproc,
|
|
||||||
// nheader = # of lines in this file via Allreduce on clustercomm
|
|
||||||
|
|
||||||
bigint nheader = ntotal;
|
|
||||||
|
|
||||||
// ensure 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 (nmax > maxbuf) {
|
|
||||||
if ((bigint) nmax * size_one > MAXSMALLINT)
|
|
||||||
error->all(FLERR,"Too much per-proc info for dump");
|
|
||||||
maxbuf = nmax;
|
|
||||||
memory->destroy(buf);
|
|
||||||
memory->create(buf,(maxbuf*size_one),"dump:buf");
|
|
||||||
}
|
|
||||||
if (sort_flag && sortcol == 0 && nmax > maxids) {
|
|
||||||
maxids = nmax;
|
|
||||||
memory->destroy(ids);
|
|
||||||
memory->create(ids,maxids,"dump:ids");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sort_flag && sortcol == 0) pack(ids);
|
|
||||||
else pack(nullptr);
|
|
||||||
if (sort_flag) sort();
|
|
||||||
|
|
||||||
// determine how much data needs to be written for setting the file size and prepocess it prior to writing
|
|
||||||
performEstimate = 1;
|
|
||||||
write_header(nheader);
|
|
||||||
write_data(nme,buf);
|
|
||||||
MPI_Bcast(&sumFileSize, 1, MPI_LMP_BIGINT, (nprocs-1), world);
|
|
||||||
|
|
||||||
#ifdef LMP_USER_IO_TIMER
|
|
||||||
MPI_Barrier(world); // timestamp barrier
|
|
||||||
dumpCFGTimestamps[0] = GetTimeBase();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
openfile();
|
|
||||||
|
|
||||||
#ifdef LMP_USER_IO_TIMER
|
|
||||||
MPI_Barrier(world); // timestamp barrier
|
|
||||||
dumpCFGTimestamps[1] = GetTimeBase();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
performEstimate = 0;
|
|
||||||
write_header(nheader); // mpifo now points to end of header info
|
|
||||||
|
|
||||||
#ifdef LMP_USER_IO_TIMER
|
|
||||||
MPI_Barrier(world); // timestamp barrier
|
|
||||||
dumpCFGTimestamps[2] = GetTimeBase();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// now actually write the data
|
|
||||||
performEstimate = 0;
|
|
||||||
write_data(nme,buf);
|
|
||||||
|
|
||||||
#ifdef LMP_USER_IO_TIMER
|
|
||||||
MPI_Barrier(world); // timestamp barrier
|
|
||||||
dumpCFGTimestamps[3] = GetTimeBase();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (multifile) MPI_File_close(&mpifh);
|
|
||||||
if (multifile) delete [] filecurrent;
|
|
||||||
|
|
||||||
#ifdef LMP_USER_IO_TIMER
|
|
||||||
MPI_Barrier(world); // timestamp barrier
|
|
||||||
dumpCFGTimestamps[4] = GetTimeBase();
|
|
||||||
if (me == 0) {
|
|
||||||
endTimeBase = GetTimeBase();
|
|
||||||
printf("total dump cycles: %ld - estimates and setup: %ld openfile: %ld write header: %ld write data: %ld close file: %ld\n",(long) (endTimeBase-startTimeBase),(long) (dumpCFGTimestamps[0]-startTimeBase),(long) (dumpCFGTimestamps[1]-dumpCFGTimestamps[0]),(long) (dumpCFGTimestamps[2]-dumpCFGTimestamps[1]),(long) (dumpCFGTimestamps[3]-dumpCFGTimestamps[2]),(long) (dumpCFGTimestamps[4]-dumpCFGTimestamps[3]));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpCFGMPIIO::init_style()
|
|
||||||
{
|
|
||||||
if (multifile == 0 && !multifile_override)
|
|
||||||
error->all(FLERR,"Dump cfg requires one snapshot per file");
|
|
||||||
|
|
||||||
DumpCFG::init_style();
|
|
||||||
|
|
||||||
// setup function ptrs
|
|
||||||
|
|
||||||
write_choice = &DumpCFGMPIIO::write_string;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpCFGMPIIO::write_header(bigint n)
|
|
||||||
{
|
|
||||||
// set scale factor used by AtomEye for CFG viz
|
|
||||||
// default = 1.0
|
|
||||||
// for peridynamics, set to pre-computed PD scale factor
|
|
||||||
// so PD particles mimic C atoms
|
|
||||||
// for unwrapped coords, set to UNWRAPEXPAND (10.0)
|
|
||||||
// so molecules are not split across periodic box boundaries
|
|
||||||
|
|
||||||
double scale = 1.0;
|
|
||||||
if (atom->peri_flag) scale = atom->pdscale;
|
|
||||||
else if (unwrapflag == 1) scale = UNWRAPEXPAND;
|
|
||||||
|
|
||||||
auto header = fmt::format("Number of particles = {}\n",n);
|
|
||||||
header += fmt::format("A = {} Angstrom (basic length-scale)\n",scale);
|
|
||||||
header += fmt::format("H0(1,1) = {} A\n",domain->xprd);
|
|
||||||
header += fmt::format("H0(1,2) = 0 A\n");
|
|
||||||
header += fmt::format("H0(1,3) = 0 A\n");
|
|
||||||
header += fmt::format("H0(2,1) = {} A\n",domain->xy);
|
|
||||||
header += fmt::format("H0(2,2) = {} A\n",domain->yprd);
|
|
||||||
header += fmt::format("H0(2,3) = 0 A\n");
|
|
||||||
header += fmt::format("H0(3,1) = {} A\n",domain->xz);
|
|
||||||
header += fmt::format("H0(3,2) = {} A\n",domain->yz);
|
|
||||||
header += fmt::format("H0(3,3) = {} A\n",domain->zprd);
|
|
||||||
header += fmt::format(".NO_VELOCITY.\n");
|
|
||||||
header += fmt::format("entry_count = {}\n",nfield-2);
|
|
||||||
for (int i = 0; i < nfield-5; i++)
|
|
||||||
header += fmt::format("auxiliary[{}] = {}\n",i,auxname[i]);
|
|
||||||
|
|
||||||
if (performEstimate) {
|
|
||||||
headerSize = header.size();
|
|
||||||
} else { // write data
|
|
||||||
if (me == 0)
|
|
||||||
MPI_File_write_at(mpifh,mpifo,(void *)header.c_str(),header.size(),MPI_CHAR,MPI_STATUS_IGNORE);
|
|
||||||
mpifo += header.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_OPENMP)
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
|
||||||
convert mybuf of doubles to one big formatted string in sbuf
|
|
||||||
return -1 if strlen exceeds an int, since used as arg in MPI calls in Dump
|
|
||||||
------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
int DumpCFGMPIIO::convert_string_omp(int n, double *mybuf)
|
|
||||||
{
|
|
||||||
|
|
||||||
char **mpifh_buffer_line_per_thread;
|
|
||||||
int mpifhStringCount;
|
|
||||||
int *mpifhStringCountPerThread, *bufOffset, *bufRange, *bufLength;
|
|
||||||
|
|
||||||
mpifhStringCount = 0;
|
|
||||||
|
|
||||||
int nthreads = omp_get_max_threads();
|
|
||||||
if (nthreads > n) { // call serial version
|
|
||||||
convert_string(n,mybuf);
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
memory->create(mpifhStringCountPerThread,nthreads,"dump:mpifhStringCountPerThread");
|
|
||||||
mpifh_buffer_line_per_thread = (char **) malloc(nthreads*sizeof(char*));
|
|
||||||
memory->create(bufOffset,nthreads,"dump:bufOffset");
|
|
||||||
memory->create(bufRange,nthreads,"dump:bufRange");
|
|
||||||
memory->create(bufLength,nthreads,"dump:bufLength");
|
|
||||||
|
|
||||||
int i=0;
|
|
||||||
for (i=0;i<(nthreads-1);i++) {
|
|
||||||
mpifhStringCountPerThread[i] = 0;
|
|
||||||
bufOffset[i] = (int) (i*(int)(floor((double)n/(double)nthreads))*size_one);
|
|
||||||
bufRange[i] = (int)(floor((double)n/(double)nthreads));
|
|
||||||
bufLength[i] = DUMP_BUF_CHUNK_SIZE;
|
|
||||||
mpifh_buffer_line_per_thread[i] = (char *) malloc(DUMP_BUF_CHUNK_SIZE * sizeof(char));
|
|
||||||
mpifh_buffer_line_per_thread[i][0] = '\0';
|
|
||||||
}
|
|
||||||
mpifhStringCountPerThread[i] = 0;
|
|
||||||
bufOffset[i] = (int) (i*(int)(floor((double)n/(double)nthreads))*size_one);
|
|
||||||
bufRange[i] = n-(i*(int)(floor((double)n/(double)nthreads)));
|
|
||||||
bufLength[i] = DUMP_BUF_CHUNK_SIZE;
|
|
||||||
mpifh_buffer_line_per_thread[i] = (char *) malloc(DUMP_BUF_CHUNK_SIZE * sizeof(char));
|
|
||||||
mpifh_buffer_line_per_thread[i][0] = '\0';
|
|
||||||
|
|
||||||
#pragma omp parallel LMP_DEFAULT_NONE LMP_SHARED(bufOffset, bufRange, bufLength, mpifhStringCountPerThread, mpifh_buffer_line_per_thread, mybuf)
|
|
||||||
{
|
|
||||||
int tid = omp_get_thread_num();
|
|
||||||
int m=0;
|
|
||||||
|
|
||||||
if (unwrapflag == 0) {
|
|
||||||
for (int i = 0; i < bufRange[tid]; i++) {
|
|
||||||
if ((bufLength[tid] - mpifhStringCountPerThread[tid]) < DUMP_BUF_INCREMENT_SIZE) {
|
|
||||||
mpifh_buffer_line_per_thread[tid] = (char *) realloc(mpifh_buffer_line_per_thread[tid],(mpifhStringCountPerThread[tid]+DUMP_BUF_CHUNK_SIZE) * sizeof(char));
|
|
||||||
bufLength[tid] = (mpifhStringCountPerThread[tid]+DUMP_BUF_CHUNK_SIZE) * sizeof(char);
|
|
||||||
}
|
|
||||||
for (int j = 0; j < size_one; j++) {
|
|
||||||
if (j == 0) {
|
|
||||||
mpifhStringCountPerThread[tid] += sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),"%f \n",(mybuf[bufOffset[tid]+m]));
|
|
||||||
} else if (j == 1) {
|
|
||||||
mpifhStringCountPerThread[tid] += sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),"%s \n",typenames[(int) mybuf[bufOffset[tid]+m]]);
|
|
||||||
} else if (j >= 2) {
|
|
||||||
if (vtype[j] == Dump::INT)
|
|
||||||
mpifhStringCountPerThread[tid] += sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),vformat[j],static_cast<int> (mybuf[bufOffset[tid]+m]));
|
|
||||||
else if (vtype[j] == Dump::DOUBLE)
|
|
||||||
mpifhStringCountPerThread[tid] += sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),vformat[j],mybuf[bufOffset[tid]+m]);
|
|
||||||
else if (vtype[j] == Dump::STRING)
|
|
||||||
mpifhStringCountPerThread[tid] += sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),vformat[j],typenames[(int) mybuf[bufOffset[tid]+m]]);
|
|
||||||
else if (vtype[j] == Dump::BIGINT)
|
|
||||||
mpifhStringCountPerThread[tid] += sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),vformat[j],static_cast<bigint> (mybuf[bufOffset[tid]+m]));
|
|
||||||
}
|
|
||||||
m++;
|
|
||||||
} // for j
|
|
||||||
mpifhStringCountPerThread[tid] += sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),"\n");
|
|
||||||
} // for i
|
|
||||||
} // wrap flag
|
|
||||||
else if (unwrapflag == 1) {
|
|
||||||
for (int i = 0; i < bufRange[tid]; i++) {
|
|
||||||
if ((bufLength[tid] - mpifhStringCountPerThread[tid]) < DUMP_BUF_INCREMENT_SIZE) {
|
|
||||||
mpifh_buffer_line_per_thread[tid] = (char *) realloc(mpifh_buffer_line_per_thread[tid],(mpifhStringCountPerThread[tid]+DUMP_BUF_CHUNK_SIZE) * sizeof(char));
|
|
||||||
bufLength[tid] = (mpifhStringCountPerThread[tid]+DUMP_BUF_CHUNK_SIZE) * sizeof(char);
|
|
||||||
}
|
|
||||||
for (int j = 0; j < size_one; j++) {
|
|
||||||
double unwrap_coord;
|
|
||||||
if (j == 0) {
|
|
||||||
//offset += sprintf(&sbuf[offset],"%f \n",mybuf[m]);
|
|
||||||
mpifhStringCountPerThread[tid] += sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),"%f \n",mybuf[bufOffset[tid]+m]);
|
|
||||||
} else if (j == 1) {
|
|
||||||
// offset += sprintf(&sbuf[offset],"%s \n",typenames[(int) mybuf[m]]);
|
|
||||||
mpifhStringCountPerThread[tid] += sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),"%s \n",typenames[(int) mybuf[bufOffset[tid]+m]]);
|
|
||||||
} else if (j >= 2 && j <= 4) {
|
|
||||||
unwrap_coord = (mybuf[bufOffset[tid]+m] - 0.5)/UNWRAPEXPAND + 0.5;
|
|
||||||
//offset += sprintf(&sbuf[offset],vformat[j],unwrap_coord);
|
|
||||||
mpifhStringCountPerThread[tid] += sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),vformat[j],unwrap_coord);
|
|
||||||
} else if (j >= 5) {
|
|
||||||
if (vtype[j] == Dump::INT)
|
|
||||||
//offset +=
|
|
||||||
// sprintf(&sbuf[offset],vformat[j],static_cast<int> (mybuf[m]));
|
|
||||||
mpifhStringCountPerThread[tid] += sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),vformat[j],static_cast<int> (mybuf[bufOffset[tid]+m]));
|
|
||||||
else if (vtype[j] == Dump::DOUBLE)
|
|
||||||
// offset += sprintf(&sbuf[offset],vformat[j],mybuf[m]);
|
|
||||||
mpifhStringCountPerThread[tid] += sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),vformat[j],mybuf[bufOffset[tid]+m]);
|
|
||||||
else if (vtype[j] == Dump::STRING)
|
|
||||||
// offset +=
|
|
||||||
// sprintf(&sbuf[offset],vformat[j],typenames[(int) mybuf[m]]);
|
|
||||||
mpifhStringCountPerThread[tid] += sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),vformat[j],typenames[(int) mybuf[bufOffset[tid]+m]]);
|
|
||||||
else if (vtype[j] == Dump::BIGINT)
|
|
||||||
// offset +=
|
|
||||||
// sprintf(&sbuf[offset],vformat[j],static_cast<bigint> (mybuf[m]));
|
|
||||||
mpifhStringCountPerThread[tid] += sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),vformat[j],static_cast<bigint> (mybuf[bufOffset[tid]+m]));
|
|
||||||
}
|
|
||||||
m++;
|
|
||||||
} // for j
|
|
||||||
mpifhStringCountPerThread[tid] += sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),"\n");
|
|
||||||
} // for i
|
|
||||||
} // unwrap flag
|
|
||||||
} // pragma omp parallel
|
|
||||||
|
|
||||||
#pragma omp barrier
|
|
||||||
mpifhStringCount = 0;
|
|
||||||
for (i=0;i<nthreads;i++) {
|
|
||||||
mpifhStringCount += mpifhStringCountPerThread[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
memory->destroy(bufOffset);
|
|
||||||
memory->destroy(bufRange);
|
|
||||||
memory->destroy(bufLength);
|
|
||||||
|
|
||||||
if (mpifhStringCount > 0) {
|
|
||||||
if (mpifhStringCount > maxsbuf) {
|
|
||||||
if (mpifhStringCount > MAXSMALLINT) return -1;
|
|
||||||
maxsbuf = mpifhStringCount+1;
|
|
||||||
memory->grow(sbuf,maxsbuf,"dump:sbuf");
|
|
||||||
}
|
|
||||||
sbuf[0] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=0;i<nthreads;i++) {
|
|
||||||
strcat(sbuf,mpifh_buffer_line_per_thread[i]);
|
|
||||||
free(mpifh_buffer_line_per_thread[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
memory->destroy(mpifhStringCountPerThread);
|
|
||||||
free(mpifh_buffer_line_per_thread);
|
|
||||||
|
|
||||||
} // else omp
|
|
||||||
|
|
||||||
return mpifhStringCount;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpCFGMPIIO::write_data(int n, double *mybuf)
|
|
||||||
{
|
|
||||||
(this->*write_choice)(n,mybuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpCFGMPIIO::write_string(int n, double *mybuf)
|
|
||||||
{
|
|
||||||
if (performEstimate) {
|
|
||||||
|
|
||||||
#if defined(_OPENMP)
|
|
||||||
int nthreads = omp_get_max_threads();
|
|
||||||
if (nthreads > 1)
|
|
||||||
nsme = convert_string_omp(n,mybuf);
|
|
||||||
else
|
|
||||||
nsme = convert_string(n,mybuf);
|
|
||||||
#else
|
|
||||||
|
|
||||||
nsme = convert_string(n,mybuf);
|
|
||||||
#endif
|
|
||||||
bigint incPrefix = 0;
|
|
||||||
bigint bigintNsme = (bigint) nsme;
|
|
||||||
MPI_Scan(&bigintNsme,&incPrefix,1,MPI_LMP_BIGINT,MPI_SUM,world);
|
|
||||||
sumFileSize = (incPrefix*sizeof(char));
|
|
||||||
offsetFromHeader = ((incPrefix-bigintNsme)*sizeof(char));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
MPI_File_write_at_all(mpifh,mpifo+offsetFromHeader,sbuf,nsme,MPI_CHAR,MPI_STATUS_IGNORE);
|
|
||||||
if (flush_flag)
|
|
||||||
MPI_File_sync(mpifh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
/* -*- c++ -*- ----------------------------------------------------------
|
|
||||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
||||||
https://www.lammps.org/, Sandia National Laboratories
|
|
||||||
LAMMPS development team: developers@lammps.org
|
|
||||||
|
|
||||||
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
|
|
||||||
// clang-format off
|
|
||||||
DumpStyle(cfg/mpiio,DumpCFGMPIIO);
|
|
||||||
// clang-format on
|
|
||||||
#else
|
|
||||||
|
|
||||||
#ifndef LMP_DUMP_CFG_MPIIO_H
|
|
||||||
#define LMP_DUMP_CFG_MPIIO_H
|
|
||||||
|
|
||||||
#include "dump_cfg.h"
|
|
||||||
|
|
||||||
namespace LAMMPS_NS {
|
|
||||||
|
|
||||||
class DumpCFGMPIIO : public DumpCFG {
|
|
||||||
public:
|
|
||||||
DumpCFGMPIIO(class LAMMPS *, int, char **);
|
|
||||||
~DumpCFGMPIIO() override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bigint
|
|
||||||
sumFileSize; // size in bytes of the file up through this rank offset from the end of the header data
|
|
||||||
char *headerBuffer; // buffer for holding header data
|
|
||||||
|
|
||||||
MPI_File mpifh;
|
|
||||||
MPI_Offset mpifo, offsetFromHeader, headerSize, currentFileSize;
|
|
||||||
int performEstimate; // switch for write_data and write_header methods to use for gathering data and detemining filesize for preallocation vs actually writing the data
|
|
||||||
char *filecurrent; // name of file for this round (with % and * replaced)
|
|
||||||
|
|
||||||
#if defined(_OPENMP)
|
|
||||||
int convert_string_omp(int, double *); // multithreaded version of convert_string
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void openfile() override;
|
|
||||||
void init_style() override;
|
|
||||||
void write_header(bigint) override;
|
|
||||||
void write() override;
|
|
||||||
void write_data(int, double *) override;
|
|
||||||
|
|
||||||
typedef void (DumpCFGMPIIO::*FnPtrData)(int, double *);
|
|
||||||
FnPtrData write_choice; // ptr to write data functions
|
|
||||||
void write_string(int, double *);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace LAMMPS_NS
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@ -1,648 +0,0 @@
|
|||||||
/* ----------------------------------------------------------------------
|
|
||||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
||||||
https://www.lammps.org/, Sandia National Laboratories
|
|
||||||
LAMMPS development team: developers@lammps.org
|
|
||||||
|
|
||||||
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 "dump_custom_mpiio.h"
|
|
||||||
|
|
||||||
#include "domain.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "fix.h"
|
|
||||||
#include "input.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "modify.h"
|
|
||||||
#include "update.h"
|
|
||||||
#include "variable.h"
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include "omp_compat.h"
|
|
||||||
#if defined(_OPENMP)
|
|
||||||
#include <omp.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace LAMMPS_NS;
|
|
||||||
|
|
||||||
#define DUMP_BUF_CHUNK_SIZE 16384
|
|
||||||
#define DUMP_BUF_INCREMENT_SIZE 4096
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
DumpCustomMPIIO::DumpCustomMPIIO(LAMMPS *lmp, int narg, char **arg) : DumpCustom(lmp, narg, arg)
|
|
||||||
{
|
|
||||||
if (me == 0)
|
|
||||||
error->warning(FLERR, "MPI-IO output is unmaintained and unreliable. Use with caution.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
DumpCustomMPIIO::~DumpCustomMPIIO()
|
|
||||||
{
|
|
||||||
if (multifile == 0) MPI_File_close(&mpifh);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpCustomMPIIO::openfile()
|
|
||||||
{
|
|
||||||
if (singlefile_opened) { // single file already opened, so just return after resetting filesize
|
|
||||||
mpifo = currentFileSize;
|
|
||||||
MPI_File_set_size(mpifh, mpifo + headerSize + sumFileSize);
|
|
||||||
currentFileSize = mpifo + headerSize + sumFileSize;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (multifile == 0) singlefile_opened = 1;
|
|
||||||
|
|
||||||
// if one file per timestep, replace '*' with current timestep
|
|
||||||
|
|
||||||
filecurrent = filename;
|
|
||||||
|
|
||||||
if (multifile) {
|
|
||||||
filecurrent = utils::strdup(utils::star_subst(filecurrent, update->ntimestep, padflag));
|
|
||||||
if (maxfiles > 0) {
|
|
||||||
if (numfiles < maxfiles) {
|
|
||||||
nameslist[numfiles] = utils::strdup(filecurrent);
|
|
||||||
++numfiles;
|
|
||||||
} else {
|
|
||||||
remove(nameslist[fileidx]);
|
|
||||||
delete[] nameslist[fileidx];
|
|
||||||
nameslist[fileidx] = utils::strdup(filecurrent);
|
|
||||||
fileidx = (fileidx + 1) % maxfiles;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (append_flag) { // append open
|
|
||||||
int err = MPI_File_open(world, filecurrent, MPI_MODE_CREATE | MPI_MODE_APPEND | MPI_MODE_WRONLY,
|
|
||||||
MPI_INFO_NULL, &mpifh);
|
|
||||||
if (err != MPI_SUCCESS)
|
|
||||||
error->one(FLERR, "Cannot open dump file {}: {}", filecurrent, utils::getsyserror());
|
|
||||||
|
|
||||||
int myrank;
|
|
||||||
MPI_Comm_rank(world, &myrank);
|
|
||||||
if (myrank == 0) MPI_File_get_size(mpifh, &mpifo);
|
|
||||||
MPI_Bcast(&mpifo, 1, MPI_LMP_BIGINT, 0, world);
|
|
||||||
MPI_File_set_size(mpifh, mpifo + headerSize + sumFileSize);
|
|
||||||
currentFileSize = mpifo + headerSize + sumFileSize;
|
|
||||||
|
|
||||||
} else { // replace open
|
|
||||||
|
|
||||||
int err =
|
|
||||||
MPI_File_open(world, filecurrent, MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &mpifh);
|
|
||||||
if (err != MPI_SUCCESS)
|
|
||||||
error->one(FLERR, "Cannot open dump file {}: {}", filecurrent, utils::getsyserror());
|
|
||||||
|
|
||||||
mpifo = 0;
|
|
||||||
|
|
||||||
MPI_File_set_size(mpifh, (MPI_Offset) (headerSize + sumFileSize));
|
|
||||||
currentFileSize = (headerSize + sumFileSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpCustomMPIIO::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 dump lines in snapshot
|
|
||||||
// nmax = max # of dump lines on any proc
|
|
||||||
|
|
||||||
bigint bnme = nme;
|
|
||||||
MPI_Allreduce(&bnme, &ntotal, 1, MPI_LMP_BIGINT, MPI_SUM, world);
|
|
||||||
|
|
||||||
int nmax;
|
|
||||||
MPI_Allreduce(&nme, &nmax, 1, MPI_INT, MPI_MAX, world);
|
|
||||||
|
|
||||||
// write timestep header
|
|
||||||
// for multiproc,
|
|
||||||
// nheader = # of lines in this file via Allreduce on clustercomm
|
|
||||||
|
|
||||||
bigint nheader = ntotal;
|
|
||||||
|
|
||||||
// ensure 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 (nmax > maxbuf) {
|
|
||||||
if ((bigint) nmax * size_one > MAXSMALLINT)
|
|
||||||
error->all(FLERR, "Too much per-proc info for dump");
|
|
||||||
maxbuf = nmax;
|
|
||||||
memory->destroy(buf);
|
|
||||||
memory->create(buf, (maxbuf * size_one), "dump:buf");
|
|
||||||
}
|
|
||||||
if (sort_flag && sortcol == 0 && nmax > maxids) {
|
|
||||||
maxids = nmax;
|
|
||||||
memory->destroy(ids);
|
|
||||||
memory->create(ids, maxids, "dump:ids");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sort_flag && sortcol == 0)
|
|
||||||
pack(ids);
|
|
||||||
else
|
|
||||||
pack(nullptr);
|
|
||||||
if (sort_flag) sort();
|
|
||||||
|
|
||||||
// determine how much data needs to be written for setting the file size and prepocess it prior to writing
|
|
||||||
performEstimate = 1;
|
|
||||||
write_header(nheader);
|
|
||||||
write_data(nme, buf);
|
|
||||||
MPI_Bcast(&sumFileSize, 1, MPI_LMP_BIGINT, (nprocs - 1), world);
|
|
||||||
|
|
||||||
openfile();
|
|
||||||
|
|
||||||
performEstimate = 0;
|
|
||||||
write_header(nheader); // mpifo now points to end of header info
|
|
||||||
|
|
||||||
// now actually write the data
|
|
||||||
performEstimate = 0;
|
|
||||||
write_data(nme, buf);
|
|
||||||
|
|
||||||
if (multifile) MPI_File_close(&mpifh);
|
|
||||||
if (multifile) delete[] filecurrent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpCustomMPIIO::init_style()
|
|
||||||
{
|
|
||||||
// assemble ITEMS: column string from defaults and user values
|
|
||||||
|
|
||||||
delete[] columns;
|
|
||||||
std::string combined;
|
|
||||||
int icol = 0;
|
|
||||||
for (const auto &item : utils::split_words(columns_default)) {
|
|
||||||
if (combined.size()) combined += " ";
|
|
||||||
if (keyword_user[icol].size())
|
|
||||||
combined += keyword_user[icol];
|
|
||||||
else
|
|
||||||
combined += item;
|
|
||||||
++icol;
|
|
||||||
}
|
|
||||||
columns = utils::strdup(combined);
|
|
||||||
|
|
||||||
// format = copy of default or user-specified line format
|
|
||||||
|
|
||||||
delete[] format;
|
|
||||||
if (format_line_user)
|
|
||||||
format = utils::strdup(format_line_user);
|
|
||||||
else
|
|
||||||
format = utils::strdup(format_default);
|
|
||||||
|
|
||||||
// tokenize the format string and add space at end of each format element
|
|
||||||
// if user-specified int/float format exists, use it instead
|
|
||||||
// if user-specified column format exists, use it instead
|
|
||||||
// lo priority = line, medium priority = int/float, hi priority = column
|
|
||||||
|
|
||||||
auto words = utils::split_words(format);
|
|
||||||
if ((int) words.size() < nfield)
|
|
||||||
error->all(FLERR, "Dump_modify format line is too short: {}", format);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (const auto &word : words) {
|
|
||||||
if (i >= nfield) break;
|
|
||||||
delete[] vformat[i];
|
|
||||||
|
|
||||||
if (format_column_user[i])
|
|
||||||
vformat[i] = utils::strdup(std::string(format_column_user[i]) + " ");
|
|
||||||
else if (vtype[i] == Dump::INT && format_int_user)
|
|
||||||
vformat[i] = utils::strdup(std::string(format_int_user) + " ");
|
|
||||||
else if (vtype[i] == Dump::DOUBLE && format_float_user)
|
|
||||||
vformat[i] = utils::strdup(std::string(format_float_user) + " ");
|
|
||||||
else if (vtype[i] == Dump::BIGINT && format_bigint_user)
|
|
||||||
vformat[i] = utils::strdup(std::string(format_bigint_user) + " ");
|
|
||||||
else
|
|
||||||
vformat[i] = utils::strdup(word + " ");
|
|
||||||
|
|
||||||
// remove trailing blank on last column's format
|
|
||||||
if (i == nfield - 1) vformat[i][strlen(vformat[i]) - 1] = '\0';
|
|
||||||
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup boundary string
|
|
||||||
|
|
||||||
domain->boundary_string(boundstr);
|
|
||||||
|
|
||||||
// setup function ptrs
|
|
||||||
|
|
||||||
if (binary && domain->triclinic == 0)
|
|
||||||
header_choice = &DumpCustomMPIIO::header_binary;
|
|
||||||
else if (binary && domain->triclinic == 1)
|
|
||||||
header_choice = &DumpCustomMPIIO::header_binary_triclinic;
|
|
||||||
else if (!binary && domain->triclinic == 0)
|
|
||||||
header_choice = &DumpCustomMPIIO::header_item;
|
|
||||||
else if (!binary && domain->triclinic == 1)
|
|
||||||
header_choice = &DumpCustomMPIIO::header_item_triclinic;
|
|
||||||
|
|
||||||
if (binary)
|
|
||||||
write_choice = &DumpCustomMPIIO::write_binary;
|
|
||||||
else
|
|
||||||
write_choice = &DumpCustomMPIIO::write_string;
|
|
||||||
|
|
||||||
// find current ptr for each compute,fix,variable
|
|
||||||
// check that fix frequency is acceptable
|
|
||||||
|
|
||||||
for (i = 0; i < ncompute; i++) {
|
|
||||||
compute[i] = modify->get_compute_by_id(id_compute[i]);
|
|
||||||
if (!compute[i])
|
|
||||||
error->all(FLERR, "Could not find dump custom/mpiio compute ID {}", id_compute[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < nfix; i++) {
|
|
||||||
fix[i] = modify->get_fix_by_id(id_fix[i]);
|
|
||||||
if (!fix[i]) error->all(FLERR, "Could not find dump custom/mpiio fix ID {}", id_fix[i]);
|
|
||||||
if (nevery % fix[i]->peratom_freq)
|
|
||||||
error->all(FLERR, "dump custom/mpiio and fix not computed at compatible times");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < nvariable; i++) {
|
|
||||||
int ivariable = input->variable->find(id_variable[i]);
|
|
||||||
if (ivariable < 0)
|
|
||||||
error->all(FLERR, "Could not find dump custom/mpiio variable name {}", id_variable[i]);
|
|
||||||
variable[i] = ivariable;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set index and check validity of region
|
|
||||||
|
|
||||||
if (idregion && !domain->get_region_by_id(idregion))
|
|
||||||
error->all(FLERR, "Region {} for dump custom/mpiio does not exist", idregion);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpCustomMPIIO::write_header(bigint ndump)
|
|
||||||
{
|
|
||||||
if (!header_choice) error->all(FLERR, "Must not use 'run pre no' after creating a new dump");
|
|
||||||
|
|
||||||
(this->*header_choice)(ndump);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpCustomMPIIO::header_binary(bigint ndump)
|
|
||||||
{
|
|
||||||
if (performEstimate) {
|
|
||||||
|
|
||||||
headerBuffer = (char *) malloc((2 * sizeof(bigint)) + (9 * sizeof(int)) + (6 * sizeof(double)));
|
|
||||||
|
|
||||||
headerSize = 0;
|
|
||||||
memcpy(headerBuffer + headerSize, &update->ntimestep, sizeof(bigint));
|
|
||||||
headerSize += sizeof(bigint);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &ndump, sizeof(bigint));
|
|
||||||
headerSize += sizeof(bigint);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &domain->triclinic, sizeof(int));
|
|
||||||
headerSize += sizeof(int);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &domain->boundary[0][0], 6 * sizeof(int));
|
|
||||||
headerSize += 6 * sizeof(int);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxxlo, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxxhi, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxylo, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxyhi, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxzlo, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxzhi, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &size_one, sizeof(int));
|
|
||||||
headerSize += sizeof(int);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &nprocs, sizeof(int));
|
|
||||||
headerSize += sizeof(int);
|
|
||||||
} else { // write data
|
|
||||||
if (me == 0)
|
|
||||||
MPI_File_write_at(mpifh, mpifo, headerBuffer, headerSize, MPI_BYTE, MPI_STATUS_IGNORE);
|
|
||||||
mpifo += headerSize;
|
|
||||||
free(headerBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpCustomMPIIO::header_binary_triclinic(bigint ndump)
|
|
||||||
{
|
|
||||||
if (performEstimate) {
|
|
||||||
|
|
||||||
headerBuffer = (char *) malloc((2 * sizeof(bigint)) + (9 * sizeof(int)) + (9 * sizeof(double)));
|
|
||||||
|
|
||||||
headerSize = 0;
|
|
||||||
memcpy(headerBuffer + headerSize, &update->ntimestep, sizeof(bigint));
|
|
||||||
headerSize += sizeof(bigint);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &ndump, sizeof(bigint));
|
|
||||||
headerSize += sizeof(bigint);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &domain->triclinic, sizeof(int));
|
|
||||||
headerSize += sizeof(int);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &domain->boundary[0][0], 6 * sizeof(int));
|
|
||||||
headerSize += 6 * sizeof(int);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxxlo, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxxhi, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxylo, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxyhi, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxzlo, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxzhi, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxxy, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxxz, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &boxyz, sizeof(double));
|
|
||||||
headerSize += sizeof(double);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &size_one, sizeof(int));
|
|
||||||
headerSize += sizeof(int);
|
|
||||||
|
|
||||||
memcpy(headerBuffer + headerSize, &nprocs, sizeof(int));
|
|
||||||
headerSize += sizeof(int);
|
|
||||||
|
|
||||||
} else { // write data
|
|
||||||
|
|
||||||
if (me == 0)
|
|
||||||
MPI_File_write_at(mpifh, mpifo, headerBuffer, headerSize, MPI_BYTE, MPI_STATUS_IGNORE);
|
|
||||||
mpifo += headerSize;
|
|
||||||
free(headerBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpCustomMPIIO::header_item(bigint ndump)
|
|
||||||
{
|
|
||||||
if (performEstimate) {
|
|
||||||
|
|
||||||
auto itemtxt = fmt::format("ITEM: TIMESTEP\n{}\n", update->ntimestep);
|
|
||||||
itemtxt += fmt::format("ITEM: NUMBER OF ATOMS\n{}\n", ndump);
|
|
||||||
itemtxt += fmt::format("ITEM: BOX BOUNDS {}\n", boundstr);
|
|
||||||
itemtxt += fmt::format("{} {}\n{} {}\n{} {}\n", boxxlo, boxxhi, boxylo, boxyhi, boxzlo, boxzhi);
|
|
||||||
itemtxt += fmt::format("ITEM: ATOMS {}\n", columns);
|
|
||||||
|
|
||||||
headerSize = itemtxt.size();
|
|
||||||
headerBuffer = utils::strdup(itemtxt);
|
|
||||||
|
|
||||||
} else { // write data
|
|
||||||
|
|
||||||
if (me == 0)
|
|
||||||
MPI_File_write_at(mpifh, mpifo, headerBuffer, headerSize, MPI_CHAR, MPI_STATUS_IGNORE);
|
|
||||||
mpifo += headerSize;
|
|
||||||
delete[] headerBuffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpCustomMPIIO::header_item_triclinic(bigint ndump)
|
|
||||||
{
|
|
||||||
if (performEstimate) {
|
|
||||||
|
|
||||||
auto itemtxt = fmt::format("ITEM: TIMESTEP\n{}\n", update->ntimestep);
|
|
||||||
itemtxt += fmt::format("ITEM: NUMBER OF ATOMS\n{}\n", ndump);
|
|
||||||
itemtxt += fmt::format("ITEM: BOX BOUNDS xy xz yz {}\n", boundstr);
|
|
||||||
itemtxt += fmt::format("{} {} {}\n{} {} {}\n{} {} {}\n", boxxlo, boxxhi, boxxy, boxylo, boxyhi,
|
|
||||||
boxxz, boxzlo, boxzhi, boxyz);
|
|
||||||
itemtxt += fmt::format("ITEM: ATOMS {}\n", columns);
|
|
||||||
|
|
||||||
headerSize = itemtxt.size();
|
|
||||||
headerBuffer = utils::strdup(itemtxt);
|
|
||||||
|
|
||||||
} else { // write data
|
|
||||||
|
|
||||||
if (me == 0)
|
|
||||||
MPI_File_write_at(mpifh, mpifo, headerBuffer, headerSize, MPI_CHAR, MPI_STATUS_IGNORE);
|
|
||||||
mpifo += headerSize;
|
|
||||||
delete[] headerBuffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpCustomMPIIO::write_data(int n, double *mybuf)
|
|
||||||
{
|
|
||||||
(this->*write_choice)(n, mybuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpCustomMPIIO::write_binary(int n, double *mybuf)
|
|
||||||
{
|
|
||||||
n *= size_one;
|
|
||||||
|
|
||||||
if (performEstimate) {
|
|
||||||
|
|
||||||
bigint incPrefix = 0;
|
|
||||||
bigint bigintNme = (bigint) nme;
|
|
||||||
MPI_Scan(&bigintNme, &incPrefix, 1, MPI_LMP_BIGINT, MPI_SUM, world);
|
|
||||||
sumFileSize = (incPrefix * size_one * sizeof(double)) + (nprocs * sizeof(int));
|
|
||||||
offsetFromHeader = ((incPrefix - bigintNme) * size_one * sizeof(double)) + (me * sizeof(int));
|
|
||||||
} else {
|
|
||||||
int byteBufSize = (n * sizeof(double)) + sizeof(int);
|
|
||||||
|
|
||||||
char *bufWithSize;
|
|
||||||
memory->create(bufWithSize, byteBufSize, "dump:bufWithSize");
|
|
||||||
memcpy(bufWithSize, (char *) (&n), sizeof(int));
|
|
||||||
memcpy(&((char *) bufWithSize)[sizeof(int)], mybuf, (n * sizeof(double)));
|
|
||||||
MPI_File_write_at_all(mpifh, mpifo + offsetFromHeader, bufWithSize, byteBufSize, MPI_BYTE,
|
|
||||||
MPI_STATUS_IGNORE);
|
|
||||||
memory->destroy(bufWithSize);
|
|
||||||
|
|
||||||
if (flush_flag) MPI_File_sync(mpifh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpCustomMPIIO::write_string(int n, double *mybuf)
|
|
||||||
{
|
|
||||||
if (performEstimate) {
|
|
||||||
|
|
||||||
#if defined(_OPENMP)
|
|
||||||
int nthreads = omp_get_max_threads();
|
|
||||||
if ((nthreads > 1) && !(lmp->kokkos))
|
|
||||||
nsme = convert_string_omp(n, mybuf); // not (yet) compatible with Kokkos
|
|
||||||
else
|
|
||||||
nsme = convert_string(n, mybuf);
|
|
||||||
#else
|
|
||||||
nsme = convert_string(n, mybuf);
|
|
||||||
#endif
|
|
||||||
bigint incPrefix = 0;
|
|
||||||
bigint bigintNsme = (bigint) nsme;
|
|
||||||
MPI_Scan(&bigintNsme, &incPrefix, 1, MPI_LMP_BIGINT, MPI_SUM, world);
|
|
||||||
sumFileSize = (incPrefix * sizeof(char));
|
|
||||||
offsetFromHeader = ((incPrefix - bigintNsme) * sizeof(char));
|
|
||||||
} else {
|
|
||||||
MPI_File_write_at_all(mpifh, mpifo + offsetFromHeader, sbuf, nsme, MPI_CHAR, MPI_STATUS_IGNORE);
|
|
||||||
if (flush_flag) MPI_File_sync(mpifh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_OPENMP)
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
|
||||||
multithreaded version - convert mybuf of doubles to one big formatted string in sbuf
|
|
||||||
return -1 if strlen exceeds an int, since used as arg in MPI calls in Dump
|
|
||||||
------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
int DumpCustomMPIIO::convert_string_omp(int n, double *mybuf)
|
|
||||||
{
|
|
||||||
char **mpifh_buffer_line_per_thread;
|
|
||||||
int mpifhStringCount;
|
|
||||||
int *mpifhStringCountPerThread, *bufOffset, *bufRange, *bufLength;
|
|
||||||
|
|
||||||
mpifhStringCount = 0;
|
|
||||||
|
|
||||||
int nthreads = omp_get_max_threads();
|
|
||||||
if (nthreads > n) { // call serial version
|
|
||||||
convert_string(n, mybuf);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
memory->create(mpifhStringCountPerThread, nthreads, "dump:mpifhStringCountPerThread");
|
|
||||||
mpifh_buffer_line_per_thread = (char **) malloc(nthreads * sizeof(char *));
|
|
||||||
memory->create(bufOffset, nthreads, "dump:bufOffset");
|
|
||||||
memory->create(bufRange, nthreads, "dump:bufRange");
|
|
||||||
memory->create(bufLength, nthreads, "dump:bufLength");
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (i = 0; i < (nthreads - 1); i++) {
|
|
||||||
mpifhStringCountPerThread[i] = 0;
|
|
||||||
bufOffset[i] = (int) (i * (int) (floor((double) n / (double) nthreads)) * size_one);
|
|
||||||
bufRange[i] = (int) (floor((double) n / (double) nthreads));
|
|
||||||
bufLength[i] = DUMP_BUF_CHUNK_SIZE;
|
|
||||||
mpifh_buffer_line_per_thread[i] = (char *) malloc(DUMP_BUF_CHUNK_SIZE * sizeof(char));
|
|
||||||
mpifh_buffer_line_per_thread[i][0] = '\0';
|
|
||||||
}
|
|
||||||
mpifhStringCountPerThread[i] = 0;
|
|
||||||
bufOffset[i] = (int) (i * (int) (floor((double) n / (double) nthreads)) * size_one);
|
|
||||||
bufRange[i] = n - (i * (int) (floor((double) n / (double) nthreads)));
|
|
||||||
bufLength[i] = DUMP_BUF_CHUNK_SIZE;
|
|
||||||
mpifh_buffer_line_per_thread[i] = (char *) malloc(DUMP_BUF_CHUNK_SIZE * sizeof(char));
|
|
||||||
mpifh_buffer_line_per_thread[i][0] = '\0';
|
|
||||||
|
|
||||||
#pragma omp parallel LMP_DEFAULT_NONE LMP_SHARED(bufOffset, bufRange, bufLength, \
|
|
||||||
mpifhStringCountPerThread, \
|
|
||||||
mpifh_buffer_line_per_thread, mybuf)
|
|
||||||
{
|
|
||||||
int tid = omp_get_thread_num();
|
|
||||||
int m = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < bufRange[tid]; i++) {
|
|
||||||
|
|
||||||
if ((bufLength[tid] - mpifhStringCountPerThread[tid]) < DUMP_BUF_INCREMENT_SIZE) {
|
|
||||||
mpifh_buffer_line_per_thread[tid] = (char *) realloc(
|
|
||||||
mpifh_buffer_line_per_thread[tid],
|
|
||||||
(mpifhStringCountPerThread[tid] + DUMP_BUF_CHUNK_SIZE) * sizeof(char));
|
|
||||||
bufLength[tid] = (mpifhStringCountPerThread[tid] + DUMP_BUF_CHUNK_SIZE) * sizeof(char);
|
|
||||||
}
|
|
||||||
for (int j = 0; j < size_one; j++) {
|
|
||||||
|
|
||||||
if (vtype[j] == Dump::INT)
|
|
||||||
mpifhStringCountPerThread[tid] +=
|
|
||||||
sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),
|
|
||||||
vformat[j], static_cast<int>(mybuf[bufOffset[tid] + m]));
|
|
||||||
else if (vtype[j] == Dump::DOUBLE)
|
|
||||||
mpifhStringCountPerThread[tid] +=
|
|
||||||
sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),
|
|
||||||
vformat[j], mybuf[bufOffset[tid] + m]);
|
|
||||||
else if (vtype[j] == Dump::STRING)
|
|
||||||
mpifhStringCountPerThread[tid] +=
|
|
||||||
sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),
|
|
||||||
vformat[j], typenames[(int) mybuf[bufOffset[tid] + m]]);
|
|
||||||
m++;
|
|
||||||
}
|
|
||||||
mpifhStringCountPerThread[tid] +=
|
|
||||||
sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]), "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma omp barrier
|
|
||||||
mpifhStringCount = 0;
|
|
||||||
for (i = 0; i < nthreads; i++) { mpifhStringCount += mpifhStringCountPerThread[i]; }
|
|
||||||
|
|
||||||
memory->destroy(bufOffset);
|
|
||||||
memory->destroy(bufRange);
|
|
||||||
memory->destroy(bufLength);
|
|
||||||
|
|
||||||
if (mpifhStringCount > 0) {
|
|
||||||
if (mpifhStringCount > maxsbuf) {
|
|
||||||
if (mpifhStringCount > MAXSMALLINT) return -1;
|
|
||||||
maxsbuf = mpifhStringCount + 1;
|
|
||||||
memory->grow(sbuf, maxsbuf, "dump:sbuf");
|
|
||||||
}
|
|
||||||
sbuf[0] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < nthreads; i++) {
|
|
||||||
strcat(sbuf, mpifh_buffer_line_per_thread[i]);
|
|
||||||
free(mpifh_buffer_line_per_thread[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
memory->destroy(mpifhStringCountPerThread);
|
|
||||||
free(mpifh_buffer_line_per_thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mpifhStringCount;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
/* -*- c++ -*- ----------------------------------------------------------
|
|
||||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
||||||
https://www.lammps.org/, Sandia National Laboratories
|
|
||||||
LAMMPS development team: developers@lammps.org
|
|
||||||
|
|
||||||
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
|
|
||||||
// clang-format off
|
|
||||||
DumpStyle(custom/mpiio,DumpCustomMPIIO);
|
|
||||||
// clang-format on
|
|
||||||
#else
|
|
||||||
|
|
||||||
#ifndef LMP_DUMP_CUSTOM_MPIIO_H
|
|
||||||
#define LMP_DUMP_CUSTOM_MPIIO_H
|
|
||||||
|
|
||||||
#include "dump_custom.h"
|
|
||||||
|
|
||||||
namespace LAMMPS_NS {
|
|
||||||
|
|
||||||
class DumpCustomMPIIO : public DumpCustom {
|
|
||||||
public:
|
|
||||||
DumpCustomMPIIO(class LAMMPS *, int, char **);
|
|
||||||
~DumpCustomMPIIO() override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bigint
|
|
||||||
sumFileSize; // size in bytes of the file up through this rank offset from the end of the header data
|
|
||||||
char *headerBuffer; // buffer for holding header data
|
|
||||||
|
|
||||||
MPI_File mpifh;
|
|
||||||
MPI_Offset mpifo, offsetFromHeader, headerSize, currentFileSize;
|
|
||||||
int performEstimate; // switch for write_data and write_header methods to use for gathering data and detemining filesize for preallocation vs actually writing the data
|
|
||||||
char *filecurrent; // name of file for this round (with % and * replaced)
|
|
||||||
|
|
||||||
#if defined(_OPENMP)
|
|
||||||
int convert_string_omp(int, double *); // multithreaded version of convert_string
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void openfile() override;
|
|
||||||
void write_header(bigint) override;
|
|
||||||
void write() override;
|
|
||||||
void write_data(int, double *) override;
|
|
||||||
|
|
||||||
void init_style() override;
|
|
||||||
typedef void (DumpCustomMPIIO::*FnPtrHeader)(bigint);
|
|
||||||
FnPtrHeader header_choice; // ptr to write header functions
|
|
||||||
void header_binary(bigint);
|
|
||||||
void header_binary_triclinic(bigint);
|
|
||||||
void header_item(bigint);
|
|
||||||
void header_item_triclinic(bigint);
|
|
||||||
|
|
||||||
typedef void (DumpCustomMPIIO::*FnPtrData)(int, double *);
|
|
||||||
FnPtrData write_choice; // ptr to write data functions
|
|
||||||
void write_binary(int, double *);
|
|
||||||
void write_string(int, double *);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace LAMMPS_NS
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@ -1,369 +0,0 @@
|
|||||||
// clang-format off
|
|
||||||
/* ----------------------------------------------------------------------
|
|
||||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
||||||
https://www.lammps.org/, Sandia National Laboratories
|
|
||||||
LAMMPS development team: developers@lammps.org
|
|
||||||
|
|
||||||
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 "dump_xyz_mpiio.h"
|
|
||||||
|
|
||||||
#include "compute.h"
|
|
||||||
#include "domain.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "update.h"
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include "omp_compat.h"
|
|
||||||
#if defined(_OPENMP)
|
|
||||||
#include <omp.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace LAMMPS_NS;
|
|
||||||
|
|
||||||
#define MAX_TEXT_HEADER_SIZE 4096
|
|
||||||
#define DUMP_BUF_CHUNK_SIZE 16384
|
|
||||||
#define DUMP_BUF_INCREMENT_SIZE 4096
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
DumpXYZMPIIO::DumpXYZMPIIO(LAMMPS *lmp, int narg, char **arg) :
|
|
||||||
DumpXYZ(lmp, narg, arg) {
|
|
||||||
if (me == 0)
|
|
||||||
error->warning(FLERR,"MPI-IO output is unmaintained and unreliable. Use with caution.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
DumpXYZMPIIO::~DumpXYZMPIIO()
|
|
||||||
{
|
|
||||||
if (multifile == 0) MPI_File_close(&mpifh);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpXYZMPIIO::openfile()
|
|
||||||
{
|
|
||||||
if (singlefile_opened) { // single file already opened, so just return after resetting filesize
|
|
||||||
mpifo = currentFileSize;
|
|
||||||
MPI_File_set_size(mpifh,mpifo+headerSize+sumFileSize);
|
|
||||||
currentFileSize = mpifo+headerSize+sumFileSize;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (multifile == 0) singlefile_opened = 1;
|
|
||||||
|
|
||||||
// if one file per timestep, replace '*' with current timestep
|
|
||||||
|
|
||||||
filecurrent = filename;
|
|
||||||
|
|
||||||
if (multifile) {
|
|
||||||
filecurrent = utils::strdup(utils::star_subst(filecurrent, update->ntimestep, padflag));
|
|
||||||
if (maxfiles > 0) {
|
|
||||||
if (numfiles < maxfiles) {
|
|
||||||
nameslist[numfiles] = utils::strdup(filecurrent);
|
|
||||||
++numfiles;
|
|
||||||
} else {
|
|
||||||
remove(nameslist[fileidx]);
|
|
||||||
delete[] nameslist[fileidx];
|
|
||||||
nameslist[fileidx] = utils::strdup(filecurrent);
|
|
||||||
fileidx = (fileidx + 1) % maxfiles;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (append_flag) { // append open
|
|
||||||
int err = MPI_File_open( world, filecurrent, MPI_MODE_CREATE | MPI_MODE_APPEND |
|
|
||||||
MPI_MODE_WRONLY , MPI_INFO_NULL, &mpifh);
|
|
||||||
if (err != MPI_SUCCESS) error->one(FLERR, "Cannot open dump file {}", filecurrent);
|
|
||||||
|
|
||||||
int myrank;
|
|
||||||
MPI_Comm_rank(world,&myrank);
|
|
||||||
if (myrank == 0) MPI_File_get_size(mpifh,&mpifo);
|
|
||||||
MPI_Bcast(&mpifo, 1, MPI_LMP_BIGINT, 0, world);
|
|
||||||
MPI_File_set_size(mpifh,mpifo+headerSize+sumFileSize);
|
|
||||||
currentFileSize = mpifo+headerSize+sumFileSize;
|
|
||||||
} else { // replace open
|
|
||||||
|
|
||||||
int err = MPI_File_open( world, filecurrent, MPI_MODE_CREATE | MPI_MODE_WRONLY,
|
|
||||||
MPI_INFO_NULL, &mpifh);
|
|
||||||
if (err != MPI_SUCCESS) error->one(FLERR, "Cannot open dump file {}",filecurrent);
|
|
||||||
mpifo = 0;
|
|
||||||
|
|
||||||
MPI_File_set_size(mpifh,(MPI_Offset) (headerSize+sumFileSize));
|
|
||||||
currentFileSize = (headerSize+sumFileSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpXYZMPIIO::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 dump lines in snapshot
|
|
||||||
// nmax = max # of dump lines on any proc
|
|
||||||
|
|
||||||
bigint bnme = nme;
|
|
||||||
MPI_Allreduce(&bnme,&ntotal,1,MPI_LMP_BIGINT,MPI_SUM,world);
|
|
||||||
|
|
||||||
int nmax;
|
|
||||||
MPI_Allreduce(&nme,&nmax,1,MPI_INT,MPI_MAX,world);
|
|
||||||
|
|
||||||
// write timestep header
|
|
||||||
// for multiproc,
|
|
||||||
// nheader = # of lines in this file via Allreduce on clustercomm
|
|
||||||
|
|
||||||
bigint nheader = ntotal;
|
|
||||||
|
|
||||||
// ensure 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 (nmax > maxbuf) {
|
|
||||||
if ((bigint) nmax * size_one > MAXSMALLINT)
|
|
||||||
error->all(FLERR,"Too much per-proc info for dump");
|
|
||||||
maxbuf = nmax;
|
|
||||||
memory->destroy(buf);
|
|
||||||
memory->create(buf,(maxbuf*size_one),"dump:buf");
|
|
||||||
}
|
|
||||||
if (sort_flag && sortcol == 0 && nmax > maxids) {
|
|
||||||
maxids = nmax;
|
|
||||||
memory->destroy(ids);
|
|
||||||
memory->create(ids,maxids,"dump:ids");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sort_flag && sortcol == 0) pack(ids);
|
|
||||||
else pack(nullptr);
|
|
||||||
if (sort_flag) sort();
|
|
||||||
|
|
||||||
// determine how much data needs to be written for setting the file size and prepocess it prior to writing
|
|
||||||
performEstimate = 1;
|
|
||||||
write_header(nheader);
|
|
||||||
write_data(nme,buf);
|
|
||||||
MPI_Bcast(&sumFileSize, 1, MPI_LMP_BIGINT, (nprocs-1), world);
|
|
||||||
|
|
||||||
openfile();
|
|
||||||
|
|
||||||
performEstimate = 0;
|
|
||||||
write_header(nheader); // actually write the header - mpifo now points to end of header info
|
|
||||||
|
|
||||||
// now actually write the data
|
|
||||||
performEstimate = 0;
|
|
||||||
write_data(nme,buf);
|
|
||||||
|
|
||||||
if (multifile) MPI_File_close(&mpifh);
|
|
||||||
if (multifile) delete[] filecurrent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpXYZMPIIO::init_style()
|
|
||||||
{
|
|
||||||
// format = copy of default or user-specified line format
|
|
||||||
|
|
||||||
delete[] format;
|
|
||||||
char *str;
|
|
||||||
if (format_line_user) str = format_line_user;
|
|
||||||
else str = format_default;
|
|
||||||
|
|
||||||
int n = strlen(str) + 2;
|
|
||||||
format = new char[n];
|
|
||||||
strcpy(format,str);
|
|
||||||
strcat(format,"\n");
|
|
||||||
|
|
||||||
// initialize typenames array to be backward compatible by default
|
|
||||||
// a 32-bit int can be maximally 10 digits plus sign
|
|
||||||
|
|
||||||
if (typenames == nullptr) {
|
|
||||||
typenames = new char*[ntypes+1];
|
|
||||||
for (int itype = 1; itype <= ntypes; itype++)
|
|
||||||
typenames[itype] = utils::strdup(std::to_string(itype));
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup function ptr
|
|
||||||
write_choice = &DumpXYZMPIIO::write_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpXYZMPIIO::write_header(bigint n)
|
|
||||||
{
|
|
||||||
auto header = fmt::format("{}\n Atoms. Timestep: {}", n, update->ntimestep);
|
|
||||||
if (time_flag) header += fmt::format(" Time: {:.6f}", compute_time());
|
|
||||||
header += "\n";
|
|
||||||
|
|
||||||
if (performEstimate) {
|
|
||||||
headerSize = header.size();
|
|
||||||
} else { // write data
|
|
||||||
if (me == 0)
|
|
||||||
MPI_File_write_at(mpifh,mpifo,(void *)header.c_str(),header.size(),MPI_CHAR,MPI_STATUS_IGNORE);
|
|
||||||
mpifo += header.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpXYZMPIIO::write_data(int n, double *mybuf)
|
|
||||||
{
|
|
||||||
(this->*write_choice)(n,mybuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void DumpXYZMPIIO::write_string(int n, double *mybuf)
|
|
||||||
{
|
|
||||||
if (performEstimate) {
|
|
||||||
|
|
||||||
#if defined(_OPENMP)
|
|
||||||
int nthreads = omp_get_max_threads();
|
|
||||||
if (nthreads > 1)
|
|
||||||
nsme = convert_string_omp(n,mybuf);
|
|
||||||
else
|
|
||||||
nsme = convert_string(n,mybuf);
|
|
||||||
#else
|
|
||||||
|
|
||||||
nsme = convert_string(n,mybuf);
|
|
||||||
#endif
|
|
||||||
bigint incPrefix = 0;
|
|
||||||
bigint bigintNsme = (bigint) nsme;
|
|
||||||
MPI_Scan(&bigintNsme,&incPrefix,1,MPI_LMP_BIGINT,MPI_SUM,world);
|
|
||||||
sumFileSize = (incPrefix*sizeof(char));
|
|
||||||
offsetFromHeader = ((incPrefix-bigintNsme)*sizeof(char));
|
|
||||||
}
|
|
||||||
else { // write data
|
|
||||||
MPI_File_write_at_all(mpifh,mpifo+offsetFromHeader,sbuf,nsme,MPI_CHAR,MPI_STATUS_IGNORE);
|
|
||||||
if (flush_flag)
|
|
||||||
MPI_File_sync(mpifh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_OPENMP)
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
|
||||||
multithreaded version - convert mybuf of doubles to one big formatted string in sbuf
|
|
||||||
return -1 if strlen exceeds an int, since used as arg in MPI calls in Dump
|
|
||||||
------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
int DumpXYZMPIIO::convert_string_omp(int n, double *mybuf)
|
|
||||||
{
|
|
||||||
char **mpifh_buffer_line_per_thread;
|
|
||||||
int mpifhStringCount;
|
|
||||||
int *mpifhStringCountPerThread, *bufOffset, *bufRange, *bufLength;
|
|
||||||
|
|
||||||
mpifhStringCount = 0;
|
|
||||||
|
|
||||||
int nthreads = omp_get_max_threads();
|
|
||||||
if (nthreads > n) { // call serial version
|
|
||||||
convert_string(n,mybuf);
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
memory->create(mpifhStringCountPerThread,nthreads,"dump:mpifhStringCountPerThread");
|
|
||||||
mpifh_buffer_line_per_thread = (char **) malloc(nthreads*sizeof(char*));
|
|
||||||
memory->create(bufOffset,nthreads,"dump:bufOffset");
|
|
||||||
memory->create(bufRange,nthreads,"dump:bufRange");
|
|
||||||
memory->create(bufLength,nthreads,"dump:bufLength");
|
|
||||||
|
|
||||||
int i=0;
|
|
||||||
for (i=0;i<(nthreads-1);i++) {
|
|
||||||
mpifhStringCountPerThread[i] = 0;
|
|
||||||
bufOffset[i] = (int) (i*(int)(floor((double)n/(double)nthreads))*size_one);
|
|
||||||
bufRange[i] = (int)(floor((double)n/(double)nthreads));
|
|
||||||
bufLength[i] = DUMP_BUF_CHUNK_SIZE;
|
|
||||||
mpifh_buffer_line_per_thread[i] = (char *) malloc(DUMP_BUF_CHUNK_SIZE * sizeof(char));
|
|
||||||
mpifh_buffer_line_per_thread[i][0] = '\0';
|
|
||||||
}
|
|
||||||
mpifhStringCountPerThread[i] = 0;
|
|
||||||
bufOffset[i] = (int) (i*(int)(floor((double)n/(double)nthreads))*size_one);
|
|
||||||
bufRange[i] = n-(i*(int)(floor((double)n/(double)nthreads)));
|
|
||||||
bufLength[i] = DUMP_BUF_CHUNK_SIZE;
|
|
||||||
mpifh_buffer_line_per_thread[i] = (char *) malloc(DUMP_BUF_CHUNK_SIZE * sizeof(char));
|
|
||||||
mpifh_buffer_line_per_thread[i][0] = '\0';
|
|
||||||
|
|
||||||
#pragma omp parallel LMP_DEFAULT_NONE LMP_SHARED(bufOffset, bufRange, bufLength, mpifhStringCountPerThread, mpifh_buffer_line_per_thread, mybuf)
|
|
||||||
{
|
|
||||||
int tid = omp_get_thread_num();
|
|
||||||
int m=0;
|
|
||||||
|
|
||||||
for (int i = 0; i < bufRange[tid]; i++) {
|
|
||||||
|
|
||||||
if ((bufLength[tid] - mpifhStringCountPerThread[tid]) < DUMP_BUF_INCREMENT_SIZE) {
|
|
||||||
mpifh_buffer_line_per_thread[tid] = (char *) realloc(mpifh_buffer_line_per_thread[tid],(mpifhStringCountPerThread[tid]+DUMP_BUF_CHUNK_SIZE) * sizeof(char));
|
|
||||||
bufLength[tid] = (mpifhStringCountPerThread[tid]+DUMP_BUF_CHUNK_SIZE) * sizeof(char);
|
|
||||||
}
|
|
||||||
|
|
||||||
mpifhStringCountPerThread[tid] += sprintf(&(mpifh_buffer_line_per_thread[tid][mpifhStringCountPerThread[tid]]),format,typenames[static_cast<int> (mybuf[bufOffset[tid]+m+1])],mybuf[bufOffset[tid]+m+2],mybuf[bufOffset[tid]+m+3],mybuf[bufOffset[tid]+m+4]);
|
|
||||||
m += size_one;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma omp barrier
|
|
||||||
mpifhStringCount = 0;
|
|
||||||
for (i=0;i<nthreads;i++) {
|
|
||||||
mpifhStringCount += mpifhStringCountPerThread[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
memory->destroy(bufOffset);
|
|
||||||
memory->destroy(bufRange);
|
|
||||||
memory->destroy(bufLength);
|
|
||||||
|
|
||||||
if (mpifhStringCount > 0) {
|
|
||||||
if (mpifhStringCount > maxsbuf) {
|
|
||||||
if (mpifhStringCount > MAXSMALLINT) return -1;
|
|
||||||
maxsbuf = mpifhStringCount+1;
|
|
||||||
memory->grow(sbuf,maxsbuf,"dump:sbuf");
|
|
||||||
}
|
|
||||||
sbuf[0] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (int i=0;i<nthreads;i++) {
|
|
||||||
strcat(sbuf,mpifh_buffer_line_per_thread[i]);
|
|
||||||
free(mpifh_buffer_line_per_thread[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
memory->destroy(mpifhStringCountPerThread);
|
|
||||||
free(mpifh_buffer_line_per_thread);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return mpifhStringCount;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
/* -*- c++ -*- ---------------------------------------------------------
|
|
||||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
||||||
https://www.lammps.org/, Sandia National Laboratories
|
|
||||||
LAMMPS development team: developers@lammps.org
|
|
||||||
|
|
||||||
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
|
|
||||||
// clang-format off
|
|
||||||
DumpStyle(xyz/mpiio,DumpXYZMPIIO);
|
|
||||||
// clang-format on
|
|
||||||
#else
|
|
||||||
|
|
||||||
#ifndef LMP_DUMP_XYZ_MPIIO_H
|
|
||||||
#define LMP_DUMP_XYZ_MPIIO_H
|
|
||||||
|
|
||||||
#include "dump_xyz.h"
|
|
||||||
|
|
||||||
namespace LAMMPS_NS {
|
|
||||||
|
|
||||||
class DumpXYZMPIIO : public DumpXYZ {
|
|
||||||
public:
|
|
||||||
DumpXYZMPIIO(class LAMMPS *, int, char **);
|
|
||||||
~DumpXYZMPIIO() override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bigint
|
|
||||||
sumFileSize; // size in bytes of the file up through this rank offset from the end of the header data
|
|
||||||
char *headerBuffer; // buffer for holding header data
|
|
||||||
|
|
||||||
MPI_File mpifh;
|
|
||||||
MPI_Offset mpifo, offsetFromHeader, headerSize, currentFileSize;
|
|
||||||
int performEstimate; // switch for write_data and write_header methods to use for gathering data and detemining filesize for preallocation vs actually writing the data
|
|
||||||
char *filecurrent; // name of file for this round (with % and * replaced)
|
|
||||||
|
|
||||||
#if defined(_OPENMP)
|
|
||||||
int convert_string_omp(int, double *); // multithreaded version of convert_string
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void openfile() override;
|
|
||||||
void write_header(bigint) override;
|
|
||||||
void write() override;
|
|
||||||
void write_data(int, double *) override;
|
|
||||||
|
|
||||||
void init_style() override;
|
|
||||||
|
|
||||||
typedef void (DumpXYZMPIIO::*FnPtrData)(int, double *);
|
|
||||||
FnPtrData write_choice; // ptr to write data functions
|
|
||||||
void write_string(int, double *);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace LAMMPS_NS
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@ -1,199 +0,0 @@
|
|||||||
// clang-format off
|
|
||||||
/* ----------------------------------------------------------------------
|
|
||||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
||||||
https://www.lammps.org/, Sandia National Laboratories
|
|
||||||
LAMMPS development team: developers@lammps.org
|
|
||||||
|
|
||||||
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 "restart_mpiio.h"
|
|
||||||
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
using namespace LAMMPS_NS;
|
|
||||||
|
|
||||||
// the (rather old) version of ROMIO in MPICH for Windows
|
|
||||||
// uses "char *" instead of "const char *". This works around it.
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#define ROMIO_COMPAT_CAST (char *)
|
|
||||||
#else
|
|
||||||
#define ROMIO_COMPAT_CAST
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
RestartMPIIO::RestartMPIIO(LAMMPS *lmp) : Pointers(lmp)
|
|
||||||
{
|
|
||||||
mpiio_exists = 1;
|
|
||||||
MPI_Comm_size(world,&nprocs);
|
|
||||||
MPI_Comm_rank(world,&myrank);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
|
||||||
calls MPI_File_open in read-only mode, read_restart should call this
|
|
||||||
for some file servers it is most efficient to only read or only write
|
|
||||||
------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void RestartMPIIO::openForRead(const char *filename)
|
|
||||||
{
|
|
||||||
int err = MPI_File_open(world, ROMIO_COMPAT_CAST filename, MPI_MODE_RDONLY,
|
|
||||||
MPI_INFO_NULL, &mpifh);
|
|
||||||
if (err != MPI_SUCCESS) {
|
|
||||||
char str[MPI_MAX_ERROR_STRING+128];
|
|
||||||
char mpiErrorString[MPI_MAX_ERROR_STRING];
|
|
||||||
int mpiErrorStringLength;
|
|
||||||
MPI_Error_string(err, mpiErrorString, &mpiErrorStringLength);
|
|
||||||
sprintf(str,"Cannot open restart file for reading - MPI error: %s",
|
|
||||||
mpiErrorString);
|
|
||||||
error->one(FLERR,str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
|
||||||
calls MPI_File_open in write-only mode, write_restart should call this
|
|
||||||
for some file servers it is most efficient to only read or only write
|
|
||||||
------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void RestartMPIIO::openForWrite(const char *filename)
|
|
||||||
{
|
|
||||||
int err = MPI_File_open(world, ROMIO_COMPAT_CAST filename, MPI_MODE_WRONLY,
|
|
||||||
MPI_INFO_NULL, &mpifh);
|
|
||||||
if (err != MPI_SUCCESS) {
|
|
||||||
char str[MPI_MAX_ERROR_STRING+128];
|
|
||||||
char mpiErrorString[MPI_MAX_ERROR_STRING];
|
|
||||||
int mpiErrorStringLength;
|
|
||||||
MPI_Error_string(err, mpiErrorString, &mpiErrorStringLength);
|
|
||||||
sprintf(str,"Cannot open restart file for writing - MPI error: %s",
|
|
||||||
mpiErrorString);
|
|
||||||
error->one(FLERR,str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
|
||||||
determine the absolute offset for the data to be written with
|
|
||||||
MPI_Scan of the send sizes
|
|
||||||
compute the file size based off the MPI_Scan send size value on the last rank
|
|
||||||
set the filesize with ftruncate via MPI_File_set_size
|
|
||||||
write the data via collective MPI-IO by calling MPI_File_write_at_all
|
|
||||||
------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void RestartMPIIO::write(MPI_Offset headerOffset, int send_size, double *buf)
|
|
||||||
{
|
|
||||||
bigint incPrefix = 0;
|
|
||||||
bigint bigintSendSize = (bigint) send_size;
|
|
||||||
MPI_Scan(&bigintSendSize,&incPrefix,1,MPI_LMP_BIGINT,MPI_SUM,world);
|
|
||||||
|
|
||||||
bigint largestIncPrefix = incPrefix;
|
|
||||||
MPI_Bcast(&largestIncPrefix, 1, MPI_LMP_BIGINT, (nprocs-1), world);
|
|
||||||
|
|
||||||
int err = MPI_File_set_size(mpifh,
|
|
||||||
(headerOffset+(largestIncPrefix*sizeof(double))));
|
|
||||||
if (err != MPI_SUCCESS) {
|
|
||||||
char str[MPI_MAX_ERROR_STRING+128];
|
|
||||||
char mpiErrorString[MPI_MAX_ERROR_STRING];
|
|
||||||
int mpiErrorStringLength;
|
|
||||||
MPI_Error_string(err, mpiErrorString, &mpiErrorStringLength);
|
|
||||||
sprintf(str,"Cannot set restart file size - MPI error: %s",
|
|
||||||
mpiErrorString);
|
|
||||||
error->one(FLERR,str);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = MPI_File_write_at_all(mpifh,headerOffset +
|
|
||||||
((incPrefix-bigintSendSize)*sizeof(double)),
|
|
||||||
buf,send_size,MPI_DOUBLE,MPI_STATUS_IGNORE);
|
|
||||||
if (err != MPI_SUCCESS) {
|
|
||||||
char str[MPI_MAX_ERROR_STRING+128];
|
|
||||||
char mpiErrorString[MPI_MAX_ERROR_STRING];
|
|
||||||
int mpiErrorStringLength;
|
|
||||||
MPI_Error_string(err, mpiErrorString, &mpiErrorStringLength);
|
|
||||||
sprintf(str,"Cannot write to restart file - MPI error: %s",
|
|
||||||
mpiErrorString);
|
|
||||||
error->one(FLERR,str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
|
||||||
read the data into buf via collective MPI-IO by calling MPI_File_read_at_all
|
|
||||||
with the chunkOffset and chunkSize provided
|
|
||||||
if the consolidated chunksize is greater than INT_MAX
|
|
||||||
can only happen in extreme situation of reading restart file on
|
|
||||||
much fewer ranks than written and with relatively large data sizes
|
|
||||||
follow the collective IO call with rank independent IO to read remaining data
|
|
||||||
------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void RestartMPIIO::read(MPI_Offset chunkOffset, bigint chunkSize, double *buf)
|
|
||||||
{
|
|
||||||
int intChunkSize;
|
|
||||||
bigint remainingSize = 0;
|
|
||||||
if (chunkSize > INT_MAX) {
|
|
||||||
intChunkSize = INT_MAX;
|
|
||||||
remainingSize = chunkSize - INT_MAX;
|
|
||||||
}
|
|
||||||
else intChunkSize = (int) chunkSize;
|
|
||||||
|
|
||||||
int err = MPI_File_read_at_all(mpifh,chunkOffset,buf,intChunkSize,
|
|
||||||
MPI_DOUBLE,MPI_STATUS_IGNORE);
|
|
||||||
if (err != MPI_SUCCESS) {
|
|
||||||
char str[MPI_MAX_ERROR_STRING+128];
|
|
||||||
char mpiErrorString[MPI_MAX_ERROR_STRING];
|
|
||||||
int mpiErrorStringLength;
|
|
||||||
MPI_Error_string(err, mpiErrorString, &mpiErrorStringLength);
|
|
||||||
sprintf(str,"Cannot read from restart file - MPI error: %s",
|
|
||||||
mpiErrorString);
|
|
||||||
error->one(FLERR,str);
|
|
||||||
}
|
|
||||||
|
|
||||||
MPI_Offset currentOffset = chunkOffset+intChunkSize;
|
|
||||||
MPI_Offset bufOffset = intChunkSize;
|
|
||||||
while (remainingSize > 0) {
|
|
||||||
int currentChunkSize;
|
|
||||||
if (remainingSize > INT_MAX) {
|
|
||||||
currentChunkSize = INT_MAX;
|
|
||||||
remainingSize -= INT_MAX;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
currentChunkSize = remainingSize;
|
|
||||||
remainingSize = 0;
|
|
||||||
}
|
|
||||||
int err = MPI_File_read_at(mpifh,currentOffset,&buf[bufOffset],
|
|
||||||
currentChunkSize,MPI_DOUBLE,MPI_STATUS_IGNORE);
|
|
||||||
if (err != MPI_SUCCESS) {
|
|
||||||
char str[MPI_MAX_ERROR_STRING+128];
|
|
||||||
char mpiErrorString[MPI_MAX_ERROR_STRING];
|
|
||||||
int mpiErrorStringLength;
|
|
||||||
MPI_Error_string(err, mpiErrorString, &mpiErrorStringLength);
|
|
||||||
sprintf(str,"Cannot read from restart file - MPI error: %s",
|
|
||||||
mpiErrorString);
|
|
||||||
error->one(FLERR,str);
|
|
||||||
}
|
|
||||||
currentOffset += currentChunkSize;
|
|
||||||
bufOffset += currentChunkSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
|
||||||
calls MPI_File_close
|
|
||||||
------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void RestartMPIIO::close()
|
|
||||||
{
|
|
||||||
int err = MPI_File_close(&mpifh);
|
|
||||||
if (err != MPI_SUCCESS) {
|
|
||||||
char str[MPI_MAX_ERROR_STRING+128];
|
|
||||||
char mpiErrorString[MPI_MAX_ERROR_STRING];
|
|
||||||
int mpiErrorStringLength;
|
|
||||||
MPI_Error_string(err, mpiErrorString, &mpiErrorStringLength);
|
|
||||||
sprintf(str,"Cannot close restart file - MPI error: %s",mpiErrorString);
|
|
||||||
error->one(FLERR,str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
/* -*- c++ -*- ----------------------------------------------------------
|
|
||||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
||||||
https://www.lammps.org/, Sandia National Laboratories
|
|
||||||
LAMMPS development team: developers@lammps.org
|
|
||||||
|
|
||||||
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.
|
|
||||||
------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#ifndef LMP_RESTART_MPIIO_H
|
|
||||||
#define LMP_RESTART_MPIIO_H
|
|
||||||
|
|
||||||
#include "pointers.h"
|
|
||||||
|
|
||||||
namespace LAMMPS_NS {
|
|
||||||
|
|
||||||
class RestartMPIIO : protected Pointers {
|
|
||||||
private:
|
|
||||||
MPI_File mpifh;
|
|
||||||
int nprocs, myrank;
|
|
||||||
|
|
||||||
public:
|
|
||||||
int mpiio_exists;
|
|
||||||
|
|
||||||
RestartMPIIO(class LAMMPS *);
|
|
||||||
|
|
||||||
void openForRead(const char *);
|
|
||||||
void openForWrite(const char *);
|
|
||||||
void write(MPI_Offset, int, double *);
|
|
||||||
void read(MPI_Offset, bigint, double *);
|
|
||||||
void close();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace LAMMPS_NS
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -44,7 +44,7 @@ endif
|
|||||||
# PACKLIB = all packages that require an additional lib
|
# PACKLIB = all packages that require an additional lib
|
||||||
# should be PACKSYS + PACKINT + PACKEXT
|
# should be PACKSYS + PACKINT + PACKEXT
|
||||||
# PACKSYS = subset that reqiure a common system library
|
# PACKSYS = subset that reqiure a common system library
|
||||||
# include MPIIO and LB b/c require full MPI, not just STUBS
|
# include LATBOLTZ b/c it requires a full MPI, not just STUBS
|
||||||
# PACKINT = subset that require an internal (provided) library
|
# PACKINT = subset that require an internal (provided) library
|
||||||
# PACKEXT = subset that require an external (downloaded) library
|
# PACKEXT = subset that require an external (downloaded) library
|
||||||
|
|
||||||
@ -106,7 +106,6 @@ PACKAGE = \
|
|||||||
mofff \
|
mofff \
|
||||||
molecule \
|
molecule \
|
||||||
molfile \
|
molfile \
|
||||||
mpiio \
|
|
||||||
netcdf \
|
netcdf \
|
||||||
openmp \
|
openmp \
|
||||||
opt \
|
opt \
|
||||||
@ -212,7 +211,6 @@ PACKLIB = \
|
|||||||
kim \
|
kim \
|
||||||
kokkos \
|
kokkos \
|
||||||
lepton \
|
lepton \
|
||||||
mpiio \
|
|
||||||
poems \
|
poems \
|
||||||
python \
|
python \
|
||||||
voronoi \
|
voronoi \
|
||||||
@ -237,7 +235,7 @@ PACKLIB = \
|
|||||||
vtk \
|
vtk \
|
||||||
electrode
|
electrode
|
||||||
|
|
||||||
PACKSYS = compress latboltz mpiio python
|
PACKSYS = compress latboltz python
|
||||||
|
|
||||||
PACKINT = atc awpmd colvars electrode gpu kokkos lepton ml-pod poems
|
PACKINT = atc awpmd colvars electrode gpu kokkos lepton ml-pod poems
|
||||||
|
|
||||||
|
|||||||
@ -52,6 +52,17 @@ lmpgitversion.h
|
|||||||
mliap_model_python_couple.cpp
|
mliap_model_python_couple.cpp
|
||||||
mliap_model_python_couple.h
|
mliap_model_python_couple.h
|
||||||
# removed in August 2023
|
# removed in August 2023
|
||||||
|
dump_atom_mpiio.cpp
|
||||||
|
dump_atom_mpiio.h
|
||||||
|
dump_cfg_mpiio.cpp
|
||||||
|
dump_cfg_mpiio.h
|
||||||
|
dump_custom_mpiio.cpp
|
||||||
|
dump_custom_mpiio.h
|
||||||
|
dump_xyz_mpiio.cpp
|
||||||
|
dump_xyz_mpiio.h
|
||||||
|
restart_mpiio.cpp
|
||||||
|
restart_mpiio.h
|
||||||
|
# removed on 3 August 2023
|
||||||
fix_mscg.cpp
|
fix_mscg.cpp
|
||||||
fix_mscg.h
|
fix_mscg.h
|
||||||
# removed on 29 March 2023
|
# removed on 29 March 2023
|
||||||
|
|||||||
@ -120,8 +120,6 @@ Dump::Dump(LAMMPS *lmp, int /*narg*/, char **arg) :
|
|||||||
|
|
||||||
char *ptr;
|
char *ptr;
|
||||||
if ((ptr = strchr(filename,'%'))) {
|
if ((ptr = strchr(filename,'%'))) {
|
||||||
if (strstr(style,"mpiio"))
|
|
||||||
error->all(FLERR,"Dump file MPI-IO output not allowed with % in filename");
|
|
||||||
multiproc = 1;
|
multiproc = 1;
|
||||||
nclusterprocs = 1;
|
nclusterprocs = 1;
|
||||||
filewriter = 1;
|
filewriter = 1;
|
||||||
|
|||||||
51
src/mpiio.h
51
src/mpiio.h
@ -1,51 +0,0 @@
|
|||||||
/* -*- c++ -*- ----------------------------------------------------------
|
|
||||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
||||||
https://www.lammps.org/, Sandia National Laboratories
|
|
||||||
LAMMPS development team: developers@lammps.org
|
|
||||||
|
|
||||||
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.
|
|
||||||
------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#ifndef LMP_MPIIO_H
|
|
||||||
#define LMP_MPIIO_H
|
|
||||||
|
|
||||||
// true interface to MPIIO package
|
|
||||||
// used when MPIIO package is installed
|
|
||||||
|
|
||||||
#ifdef LMP_MPIIO
|
|
||||||
|
|
||||||
#if defined(MPI_STUBS)
|
|
||||||
#error "The MPIIO package cannot be compiled in serial with MPI STUBS"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "restart_mpiio.h" // IWYU pragma: export
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
// dummy interface to MPIIO package
|
|
||||||
// needed for compiling when MPIIO package is not installed
|
|
||||||
|
|
||||||
namespace LAMMPS_NS {
|
|
||||||
|
|
||||||
class RestartMPIIO {
|
|
||||||
public:
|
|
||||||
int mpiio_exists;
|
|
||||||
|
|
||||||
RestartMPIIO(class LAMMPS *) { mpiio_exists = 0; }
|
|
||||||
~RestartMPIIO() {}
|
|
||||||
void openForRead(const char *) {}
|
|
||||||
void openForWrite(const char *) {}
|
|
||||||
void write(MPI_Offset, int, double *) {}
|
|
||||||
void read(MPI_Offset, long, double *) {}
|
|
||||||
void close() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace LAMMPS_NS
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@ -994,22 +994,12 @@ void Output::create_restart(int narg, char **arg)
|
|||||||
error->all(FLERR,"Both restart files must use % or neither");
|
error->all(FLERR,"Both restart files must use % or neither");
|
||||||
}
|
}
|
||||||
|
|
||||||
int mpiioflag;
|
|
||||||
if (utils::strmatch(arg[1],"\\.mpiio$")) mpiioflag = 1;
|
|
||||||
else mpiioflag = 0;
|
|
||||||
if (nfile == 2) {
|
|
||||||
if (mpiioflag && !utils::strmatch(arg[2],"\\.mpiio$"))
|
|
||||||
error->all(FLERR,"Both restart files must use MPI-IO or neither");
|
|
||||||
if (!mpiioflag && utils::strmatch(arg[2],"\\.mpiio$"))
|
|
||||||
error->all(FLERR,"Both restart files must use MPI-IO or neither");
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup output style and process optional args
|
// setup output style and process optional args
|
||||||
|
|
||||||
delete restart;
|
delete restart;
|
||||||
restart = new WriteRestart(lmp);
|
restart = new WriteRestart(lmp);
|
||||||
int iarg = nfile+1;
|
int iarg = nfile+1;
|
||||||
restart->multiproc_options(multiproc,mpiioflag,narg-iarg,&arg[iarg]);
|
restart->multiproc_options(multiproc,narg-iarg,&arg[iarg]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
|
|||||||
@ -30,7 +30,6 @@
|
|||||||
#include "label_map.h"
|
#include "label_map.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "modify.h"
|
#include "modify.h"
|
||||||
#include "mpiio.h"
|
|
||||||
#include "pair.h"
|
#include "pair.h"
|
||||||
#include "special.h"
|
#include "special.h"
|
||||||
#include "update.h"
|
#include "update.h"
|
||||||
@ -43,7 +42,7 @@ using namespace LAMMPS_NS;
|
|||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
ReadRestart::ReadRestart(LAMMPS *lmp) : Command(lmp), mpiio(nullptr) {}
|
ReadRestart::ReadRestart(LAMMPS *lmp) : Command(lmp) {}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
@ -88,17 +87,8 @@ void ReadRestart::command(int narg, char **arg)
|
|||||||
|
|
||||||
if (strchr(arg[0],'%')) multiproc = 1;
|
if (strchr(arg[0],'%')) multiproc = 1;
|
||||||
else multiproc = 0;
|
else multiproc = 0;
|
||||||
if (strstr(arg[0],".mpiio")) mpiioflag = 1;
|
if (utils::strmatch(arg[0],"\\.mpiio"))
|
||||||
else mpiioflag = 0;
|
error->all(FLERR,"MPI-IO files are no longer supported by LAMMPS");
|
||||||
|
|
||||||
if (multiproc && mpiioflag)
|
|
||||||
error->all(FLERR,"Read restart MPI-IO input not allowed with % in filename");
|
|
||||||
|
|
||||||
if (mpiioflag) {
|
|
||||||
mpiio = new RestartMPIIO(lmp);
|
|
||||||
if (!mpiio->mpiio_exists)
|
|
||||||
error->all(FLERR,"Reading from MPI-IO filename when MPIIO package is not installed");
|
|
||||||
}
|
|
||||||
|
|
||||||
// open single restart file or base file for multiproc case
|
// open single restart file or base file for multiproc case
|
||||||
|
|
||||||
@ -182,28 +172,6 @@ void ReadRestart::command(int narg, char **arg)
|
|||||||
double *buf = nullptr;
|
double *buf = nullptr;
|
||||||
int m,flag;
|
int m,flag;
|
||||||
|
|
||||||
// MPI-IO input from single file
|
|
||||||
|
|
||||||
if (mpiioflag) {
|
|
||||||
mpiio->openForRead(file);
|
|
||||||
memory->create(buf,assignedChunkSize,"read_restart:buf");
|
|
||||||
mpiio->read((headerOffset+assignedChunkOffset),assignedChunkSize,buf);
|
|
||||||
mpiio->close();
|
|
||||||
|
|
||||||
// can calculate number of atoms from assignedChunkSize
|
|
||||||
|
|
||||||
if (!nextra) {
|
|
||||||
atom->nlocal = 1; // temporarily claim there is one atom...
|
|
||||||
int perAtomSize = avec->size_restart(); // ...so we can get its size
|
|
||||||
atom->nlocal = 0; // restore nlocal to zero atoms
|
|
||||||
int atomCt = (int) (assignedChunkSize / perAtomSize);
|
|
||||||
if (atomCt > atom->nmax) avec->grow(atomCt);
|
|
||||||
}
|
|
||||||
|
|
||||||
m = 0;
|
|
||||||
while (m < assignedChunkSize) m += avec->unpack_restart(&buf[m]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// input of single native file
|
// input of single native file
|
||||||
// nprocs_file = # of chunks in file
|
// nprocs_file = # of chunks in file
|
||||||
// proc 0 reads a chunk and bcasts it to other procs
|
// proc 0 reads a chunk and bcasts it to other procs
|
||||||
@ -211,7 +179,7 @@ void ReadRestart::command(int narg, char **arg)
|
|||||||
// if remapflag set, remap the atom to box before checking sub-domain
|
// if remapflag set, remap the atom to box before checking sub-domain
|
||||||
// check for atom in sub-domain differs for orthogonal vs triclinic box
|
// check for atom in sub-domain differs for orthogonal vs triclinic box
|
||||||
|
|
||||||
else if (multiproc == 0) {
|
if (multiproc == 0) {
|
||||||
|
|
||||||
int triclinic = domain->triclinic;
|
int triclinic = domain->triclinic;
|
||||||
imageint *iptr;
|
imageint *iptr;
|
||||||
@ -410,7 +378,7 @@ void ReadRestart::command(int narg, char **arg)
|
|||||||
// for multiproc or MPI-IO files:
|
// for multiproc or MPI-IO files:
|
||||||
// perform irregular comm to migrate atoms to correct procs
|
// perform irregular comm to migrate atoms to correct procs
|
||||||
|
|
||||||
if (multiproc || mpiioflag) {
|
if (multiproc) {
|
||||||
|
|
||||||
// if remapflag set, remap all atoms I read back to box before migrating
|
// if remapflag set, remap all atoms I read back to box before migrating
|
||||||
|
|
||||||
@ -419,8 +387,7 @@ void ReadRestart::command(int narg, char **arg)
|
|||||||
imageint *image = atom->image;
|
imageint *image = atom->image;
|
||||||
int nlocal = atom->nlocal;
|
int nlocal = atom->nlocal;
|
||||||
|
|
||||||
for (int i = 0; i < nlocal; i++)
|
for (int i = 0; i < nlocal; i++) domain->remap(x[i],image[i]);
|
||||||
domain->remap(x[i],image[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a temporary fix to hold and migrate extra atom info
|
// create a temporary fix to hold and migrate extra atom info
|
||||||
@ -528,8 +495,6 @@ void ReadRestart::command(int narg, char **arg)
|
|||||||
|
|
||||||
if (comm->me == 0)
|
if (comm->me == 0)
|
||||||
utils::logmesg(lmp," read_restart CPU = {:.3f} seconds\n",platform::walltime()-time1);
|
utils::logmesg(lmp," read_restart CPU = {:.3f} seconds\n",platform::walltime()-time1);
|
||||||
|
|
||||||
delete mpiio;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
@ -989,120 +954,9 @@ void ReadRestart::file_layout()
|
|||||||
error->all(FLERR,"Restart file is not a multi-proc file");
|
error->all(FLERR,"Restart file is not a multi-proc file");
|
||||||
if (multiproc && multiproc_file == 0)
|
if (multiproc && multiproc_file == 0)
|
||||||
error->all(FLERR,"Restart file is a multi-proc file");
|
error->all(FLERR,"Restart file is a multi-proc file");
|
||||||
|
|
||||||
} else if (flag == MPIIO) {
|
|
||||||
int mpiioflag_file = read_int();
|
|
||||||
if (mpiioflag == 0 && mpiioflag_file)
|
|
||||||
error->all(FLERR,"Restart file is a MPI-IO file");
|
|
||||||
if (mpiioflag && mpiioflag_file == 0)
|
|
||||||
error->all(FLERR,"Restart file is not a MPI-IO file");
|
|
||||||
|
|
||||||
if (mpiioflag) {
|
|
||||||
bigint *nproc_chunk_offsets;
|
|
||||||
memory->create(nproc_chunk_offsets,nprocs,
|
|
||||||
"write_restart:nproc_chunk_offsets");
|
|
||||||
bigint *nproc_chunk_sizes;
|
|
||||||
memory->create(nproc_chunk_sizes,nprocs,
|
|
||||||
"write_restart:nproc_chunk_sizes");
|
|
||||||
|
|
||||||
// on rank 0 read in the chunk sizes that were written out
|
|
||||||
// then consolidate them and compute offsets relative to the
|
|
||||||
// end of the header info to fit the current partition size
|
|
||||||
// if the number of ranks that did the writing is different
|
|
||||||
|
|
||||||
if (me == 0) {
|
|
||||||
int ndx;
|
|
||||||
int *all_written_send_sizes;
|
|
||||||
memory->create(all_written_send_sizes,nprocs_file,
|
|
||||||
"write_restart:all_written_send_sizes");
|
|
||||||
int *nproc_chunk_number;
|
|
||||||
memory->create(nproc_chunk_number,nprocs,
|
|
||||||
"write_restart:nproc_chunk_number");
|
|
||||||
|
|
||||||
utils::sfread(FLERR,all_written_send_sizes,sizeof(int),nprocs_file,fp,nullptr,error);
|
|
||||||
|
|
||||||
if ((nprocs != nprocs_file) && !(atom->nextra_store)) {
|
|
||||||
// nprocs differ, but atom sizes are fixed length, yeah!
|
|
||||||
atom->nlocal = 1; // temporarily claim there is one atom...
|
|
||||||
int perAtomSize = atom->avec->size_restart(); // ...so we can get its size
|
|
||||||
atom->nlocal = 0; // restore nlocal to zero atoms
|
|
||||||
|
|
||||||
bigint total_size = 0;
|
|
||||||
for (int i = 0; i < nprocs_file; ++i) {
|
|
||||||
total_size += all_written_send_sizes[i];
|
|
||||||
}
|
}
|
||||||
bigint total_ct = total_size / perAtomSize;
|
|
||||||
|
|
||||||
bigint base_ct = total_ct / nprocs;
|
|
||||||
bigint leftover_ct = total_ct - (base_ct * nprocs);
|
|
||||||
bigint current_ByteOffset = 0;
|
|
||||||
base_ct += 1;
|
|
||||||
bigint base_ByteOffset = base_ct * (perAtomSize * sizeof(double));
|
|
||||||
for (ndx = 0; ndx < leftover_ct; ++ndx) {
|
|
||||||
nproc_chunk_offsets[ndx] = current_ByteOffset;
|
|
||||||
nproc_chunk_sizes[ndx] = base_ct * perAtomSize;
|
|
||||||
current_ByteOffset += base_ByteOffset;
|
|
||||||
}
|
|
||||||
base_ct -= 1;
|
|
||||||
base_ByteOffset -= (perAtomSize * sizeof(double));
|
|
||||||
for (; ndx < nprocs; ++ndx) {
|
|
||||||
nproc_chunk_offsets[ndx] = current_ByteOffset;
|
|
||||||
nproc_chunk_sizes[ndx] = base_ct * perAtomSize;
|
|
||||||
current_ByteOffset += base_ByteOffset;
|
|
||||||
}
|
|
||||||
} else { // we have to read in based on how it was written
|
|
||||||
int init_chunk_number = nprocs_file/nprocs;
|
|
||||||
int num_extra_chunks = nprocs_file - (nprocs*init_chunk_number);
|
|
||||||
|
|
||||||
for (int i = 0; i < nprocs; i++) {
|
|
||||||
if (i < num_extra_chunks)
|
|
||||||
nproc_chunk_number[i] = init_chunk_number+1;
|
|
||||||
else
|
|
||||||
nproc_chunk_number[i] = init_chunk_number;
|
|
||||||
}
|
|
||||||
|
|
||||||
int all_written_send_sizes_index = 0;
|
|
||||||
bigint current_offset = 0;
|
|
||||||
for (int i=0;i<nprocs;i++) {
|
|
||||||
nproc_chunk_offsets[i] = current_offset;
|
|
||||||
nproc_chunk_sizes[i] = 0;
|
|
||||||
for (int j=0;j<nproc_chunk_number[i];j++) {
|
|
||||||
nproc_chunk_sizes[i] +=
|
|
||||||
all_written_send_sizes[all_written_send_sizes_index];
|
|
||||||
current_offset +=
|
|
||||||
(all_written_send_sizes[all_written_send_sizes_index] *
|
|
||||||
sizeof(double));
|
|
||||||
all_written_send_sizes_index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memory->destroy(all_written_send_sizes);
|
|
||||||
memory->destroy(nproc_chunk_number);
|
|
||||||
}
|
|
||||||
|
|
||||||
// scatter chunk sizes and offsets to all procs
|
|
||||||
|
|
||||||
MPI_Scatter(nproc_chunk_sizes, 1, MPI_LMP_BIGINT,
|
|
||||||
&assignedChunkSize , 1, MPI_LMP_BIGINT, 0,world);
|
|
||||||
MPI_Scatter(nproc_chunk_offsets, 1, MPI_LMP_BIGINT,
|
|
||||||
&assignedChunkOffset , 1, MPI_LMP_BIGINT, 0,world);
|
|
||||||
|
|
||||||
memory->destroy(nproc_chunk_sizes);
|
|
||||||
memory->destroy(nproc_chunk_offsets);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
flag = read_int();
|
flag = read_int();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if MPI-IO file, broadcast the end of the header offset
|
|
||||||
// this allows all ranks to compute offset to their data
|
|
||||||
|
|
||||||
if (mpiioflag) {
|
|
||||||
if (me == 0) headerOffset = platform::ftell(fp);
|
|
||||||
MPI_Bcast(&headerOffset,1,MPI_LMP_BIGINT,0,world);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|||||||
@ -39,13 +39,6 @@ class ReadRestart : public Command {
|
|||||||
int nprocs_file; // total # of procs that wrote restart file
|
int nprocs_file; // total # of procs that wrote restart file
|
||||||
int revision; // revision number of the restart file format
|
int revision; // revision number of the restart file format
|
||||||
|
|
||||||
// MPI-IO values
|
|
||||||
|
|
||||||
int mpiioflag; // 1 for MPIIO output, else 0
|
|
||||||
class RestartMPIIO *mpiio; // MPIIO for restart file input
|
|
||||||
bigint assignedChunkSize;
|
|
||||||
MPI_Offset assignedChunkOffset, headerOffset;
|
|
||||||
|
|
||||||
std::string file_search(const std::string &);
|
std::string file_search(const std::string &);
|
||||||
void header();
|
void header();
|
||||||
void type_arrays();
|
void type_arrays();
|
||||||
|
|||||||
@ -29,7 +29,6 @@
|
|||||||
#include "label_map.h"
|
#include "label_map.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "modify.h"
|
#include "modify.h"
|
||||||
#include "mpiio.h"
|
|
||||||
#include "neighbor.h"
|
#include "neighbor.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "pair.h"
|
#include "pair.h"
|
||||||
@ -74,16 +73,13 @@ void WriteRestart::command(int narg, char **arg)
|
|||||||
|
|
||||||
if (strchr(arg[0],'%')) multiproc = nprocs;
|
if (strchr(arg[0],'%')) multiproc = nprocs;
|
||||||
else multiproc = 0;
|
else multiproc = 0;
|
||||||
if (utils::strmatch(arg[0],"\\.mpiio$")) mpiioflag = 1;
|
if (utils::strmatch(arg[0],"\\.mpiio$"))
|
||||||
else mpiioflag = 0;
|
error->all(FLERR,"MPI-IO files are no longer supported by LAMMPS");
|
||||||
|
|
||||||
if ((comm->me == 0) && mpiioflag)
|
|
||||||
error->warning(FLERR,"MPI-IO output is unmaintained and unreliable. Use with caution.");
|
|
||||||
|
|
||||||
// setup output style and process optional args
|
// setup output style and process optional args
|
||||||
// also called by Output class for periodic restart files
|
// also called by Output class for periodic restart files
|
||||||
|
|
||||||
multiproc_options(multiproc,mpiioflag,narg-1,&arg[1]);
|
multiproc_options(multiproc,narg-1,&arg[1]);
|
||||||
|
|
||||||
// init entire system since comm->exchange is done
|
// init entire system since comm->exchange is done
|
||||||
// comm::init needs neighbor::init needs pair::init needs kspace::init, etc
|
// comm::init needs neighbor::init needs pair::init needs kspace::init, etc
|
||||||
@ -119,21 +115,9 @@ void WriteRestart::command(int narg, char **arg)
|
|||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
void WriteRestart::multiproc_options(int multiproc_caller, int mpiioflag_caller, int narg, char **arg)
|
void WriteRestart::multiproc_options(int multiproc_caller, int narg, char **arg)
|
||||||
{
|
{
|
||||||
multiproc = multiproc_caller;
|
multiproc = multiproc_caller;
|
||||||
mpiioflag = mpiioflag_caller;
|
|
||||||
|
|
||||||
// error checks
|
|
||||||
|
|
||||||
if (multiproc && mpiioflag)
|
|
||||||
error->all(FLERR,"Restart file MPI-IO output not allowed with % in filename");
|
|
||||||
|
|
||||||
if (mpiioflag) {
|
|
||||||
mpiio = new RestartMPIIO(lmp);
|
|
||||||
if (!mpiio->mpiio_exists)
|
|
||||||
error->all(FLERR,"Writing to MPI-IO filename when MPIIO package is not installed");
|
|
||||||
}
|
|
||||||
|
|
||||||
// defaults for multiproc file writing
|
// defaults for multiproc file writing
|
||||||
|
|
||||||
@ -354,20 +338,6 @@ void WriteRestart::write(const std::string &file)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MPI-IO output to single file
|
|
||||||
|
|
||||||
if (mpiioflag) {
|
|
||||||
if (me == 0 && fp) {
|
|
||||||
magic_string();
|
|
||||||
if (ferror(fp)) io_error = 1;
|
|
||||||
fclose(fp);
|
|
||||||
fp = nullptr;
|
|
||||||
}
|
|
||||||
mpiio->openForWrite(file.c_str());
|
|
||||||
mpiio->write(headerOffset,send_size,buf);
|
|
||||||
mpiio->close();
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// output of one or more native files
|
// output of one or more native files
|
||||||
// filewriter = 1 = this proc writes to file
|
// filewriter = 1 = this proc writes to file
|
||||||
// ping each proc in my cluster, receive its data, write data to file
|
// ping each proc in my cluster, receive its data, write data to file
|
||||||
@ -397,7 +367,6 @@ void WriteRestart::write(const std::string &file)
|
|||||||
MPI_Recv(&tmp,0,MPI_INT,fileproc,0,world,MPI_STATUS_IGNORE);
|
MPI_Recv(&tmp,0,MPI_INT,fileproc,0,world,MPI_STATUS_IGNORE);
|
||||||
MPI_Rsend(buf,send_size,MPI_DOUBLE,fileproc,0,world);
|
MPI_Rsend(buf,send_size,MPI_DOUBLE,fileproc,0,world);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// check for I/O error status
|
// check for I/O error status
|
||||||
|
|
||||||
@ -578,18 +547,7 @@ void WriteRestart::force_fields()
|
|||||||
|
|
||||||
void WriteRestart::file_layout(int send_size)
|
void WriteRestart::file_layout(int send_size)
|
||||||
{
|
{
|
||||||
if (me == 0) {
|
if (me == 0) write_int(MULTIPROC,multiproc);
|
||||||
write_int(MULTIPROC,multiproc);
|
|
||||||
write_int(MPIIO,mpiioflag);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mpiioflag) {
|
|
||||||
int *all_send_sizes;
|
|
||||||
memory->create(all_send_sizes,nprocs,"write_restart:all_send_sizes");
|
|
||||||
MPI_Gather(&send_size, 1, MPI_INT, all_send_sizes, 1, MPI_INT, 0,world);
|
|
||||||
if (me == 0) fwrite(all_send_sizes,sizeof(int),nprocs,fp);
|
|
||||||
memory->destroy(all_send_sizes);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -1 flag signals end of file layout info
|
// -1 flag signals end of file layout info
|
||||||
|
|
||||||
@ -597,14 +555,6 @@ void WriteRestart::file_layout(int send_size)
|
|||||||
int flag = -1;
|
int flag = -1;
|
||||||
fwrite(&flag,sizeof(int),1,fp);
|
fwrite(&flag,sizeof(int),1,fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if MPI-IO file, broadcast the end of the header offste
|
|
||||||
// this allows all ranks to compute offset to their data
|
|
||||||
|
|
||||||
if (mpiioflag) {
|
|
||||||
if (me == 0) headerOffset = platform::ftell(fp);
|
|
||||||
MPI_Bcast(&headerOffset,1,MPI_LMP_BIGINT,0,world);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|||||||
@ -28,7 +28,7 @@ class WriteRestart : public Command {
|
|||||||
public:
|
public:
|
||||||
WriteRestart(class LAMMPS *);
|
WriteRestart(class LAMMPS *);
|
||||||
void command(int, char **) override;
|
void command(int, char **) override;
|
||||||
void multiproc_options(int, int, int, char **);
|
void multiproc_options(int, int, char **);
|
||||||
void write(const std::string &);
|
void write(const std::string &);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -44,12 +44,6 @@ class WriteRestart : public Command {
|
|||||||
int fileproc; // ID of proc in my cluster who writes to file
|
int fileproc; // ID of proc in my cluster who writes to file
|
||||||
int icluster; // which cluster I am in
|
int icluster; // which cluster I am in
|
||||||
|
|
||||||
// MPI-IO values
|
|
||||||
|
|
||||||
int mpiioflag; // 1 for MPIIO output, else 0
|
|
||||||
class RestartMPIIO *mpiio; // MPIIO for restart file output
|
|
||||||
MPI_Offset headerOffset;
|
|
||||||
|
|
||||||
void header();
|
void header();
|
||||||
void type_arrays();
|
void type_arrays();
|
||||||
void force_fields();
|
void force_fields();
|
||||||
@ -66,8 +60,6 @@ class WriteRestart : public Command {
|
|||||||
void write_int_vec(int, int, int *);
|
void write_int_vec(int, int, int *);
|
||||||
void write_double_vec(int, int, double *);
|
void write_double_vec(int, int, double *);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace LAMMPS_NS
|
} // namespace LAMMPS_NS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -324,7 +324,6 @@ TEST_F(FileOperationsTest, write_restart)
|
|||||||
command("write_restart multi-%.restart");
|
command("write_restart multi-%.restart");
|
||||||
command("write_restart multi2-%.restart fileper 2");
|
command("write_restart multi2-%.restart fileper 2");
|
||||||
command("write_restart multi3-%.restart nfile 1");
|
command("write_restart multi3-%.restart nfile 1");
|
||||||
// if (Info::has_package("MPIIO")) command("write_restart test.restart.mpiio");
|
|
||||||
END_HIDE_OUTPUT();
|
END_HIDE_OUTPUT();
|
||||||
|
|
||||||
ASSERT_FILE_EXISTS("noinit.restart");
|
ASSERT_FILE_EXISTS("noinit.restart");
|
||||||
@ -336,19 +335,6 @@ TEST_F(FileOperationsTest, write_restart)
|
|||||||
ASSERT_FILE_EXISTS("multi2-0.restart");
|
ASSERT_FILE_EXISTS("multi2-0.restart");
|
||||||
ASSERT_FILE_EXISTS("multi3-base.restart");
|
ASSERT_FILE_EXISTS("multi3-base.restart");
|
||||||
ASSERT_FILE_EXISTS("multi3-0.restart");
|
ASSERT_FILE_EXISTS("multi3-0.restart");
|
||||||
#if 0
|
|
||||||
if (Info::has_package("MPIIO")) {
|
|
||||||
ASSERT_FILE_EXISTS("test.restart.mpiio");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Info::has_package("MPIIO")) {
|
|
||||||
TEST_FAILURE(".*ERROR: Writing to MPI-IO filename when MPIIO package is not inst.*",
|
|
||||||
command("write_restart test.restart.mpiio"););
|
|
||||||
} else {
|
|
||||||
TEST_FAILURE(".*ERROR: Restart file MPI-IO output not allowed with % in filename.*",
|
|
||||||
command("write_restart test.restart-%.mpiio"););
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
TEST_FAILURE(".*ERROR: Illegal write_restart command.*", command("write_restart"););
|
TEST_FAILURE(".*ERROR: Illegal write_restart command.*", command("write_restart"););
|
||||||
TEST_FAILURE(".*ERROR: Unknown write_restart keyword: xxxx.*",
|
TEST_FAILURE(".*ERROR: Unknown write_restart keyword: xxxx.*",
|
||||||
command("write_restart test.restart xxxx"););
|
command("write_restart test.restart xxxx"););
|
||||||
@ -402,7 +388,6 @@ TEST_F(FileOperationsTest, write_restart)
|
|||||||
delete_file("multi3-base.restart");
|
delete_file("multi3-base.restart");
|
||||||
delete_file("multi3-0.restart");
|
delete_file("multi3-0.restart");
|
||||||
delete_file("triclinic.restart");
|
delete_file("triclinic.restart");
|
||||||
//if (Info::has_package("MPIIO")) delete_file("test.restart.mpiio");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FileOperationsTest, write_data)
|
TEST_F(FileOperationsTest, write_data)
|
||||||
|
|||||||
Reference in New Issue
Block a user