add new ReaderNativeBin class

This commit is contained in:
nw13slx
2021-12-11 11:54:21 -05:00
parent e1e46b5322
commit 7ab5d4edd4
7 changed files with 425 additions and 24 deletions

View File

@ -88,6 +88,7 @@ static const std::vector<compress_info> compress_styles = {
{"xz", "xz", " > ", " -cdf ", compress_info::XZ}, {"xz", "xz", " > ", " -cdf ", compress_info::XZ},
{"lzma", "xz", " --format=lzma > ", " --format=lzma -cdf ", compress_info::LZMA}, {"lzma", "xz", " --format=lzma > ", " --format=lzma -cdf ", compress_info::LZMA},
{"lz4", "lz4", " > ", " -cdf ", compress_info::LZ4}, {"lz4", "lz4", " > ", " -cdf ", compress_info::LZ4},
{"bin", "", "", "", compress_info::LZ4},
}; };
// clang-format on // clang-format on
@ -984,6 +985,8 @@ FILE *platform::compressed_read(const std::string &file)
if (find_exe_path(compress.command).size()) if (find_exe_path(compress.command).size())
// put quotes around file name so that they may contain blanks // put quotes around file name so that they may contain blanks
fp = popen((compress.command + compress.uncompressflags + "\"" + file + "\""), "r"); fp = popen((compress.command + compress.uncompressflags + "\"" + file + "\""), "r");
else
fp = popen("", "r");
#endif #endif
return fp; return fp;
} }

View File

@ -16,6 +16,8 @@
#include "error.h" #include "error.h"
#include <cstring>
using namespace LAMMPS_NS; using namespace LAMMPS_NS;
// only proc 0 calls methods of this class, except for constructor/destructor // only proc 0 calls methods of this class, except for constructor/destructor
@ -42,7 +44,18 @@ void Reader::open_file(const std::string &file)
if (!fp) error->one(FLERR,"Cannot open compressed file for reading"); if (!fp) error->one(FLERR,"Cannot open compressed file for reading");
} else { } else {
compressed = 0; compressed = 0;
fp = fopen(file.c_str(),"r");
// leleslx: if there is .bin ending
std::size_t dot = file.find_last_of('.');
char reading_mode[3] = "r";
if (dot != std::string::npos) {
const std::string ext = file.substr(dot + 1);
if ("bin" == ext){
sprintf(reading_mode, "rb");
}
}
fp = fopen(file.c_str(), reading_mode);
} }
if (!fp) error->one(FLERR,"Cannot open file {}: {}", file, utils::getsyserror()); if (!fp) error->one(FLERR,"Cannot open file {}: {}", file, utils::getsyserror());

View File

@ -174,6 +174,17 @@ bigint ReaderNative::read_header(double box[3][3], int &boxinfo, int &triclinic,
return 1; return 1;
} }
match_field(nfield, xflag, yflag, zflag, fieldtype, fieldlabel, scaleflag, wrapflag, fieldflag, labels);
return natoms;
}
void ReaderNative::match_field(int nfield,
int &xflag, int &yflag, int &zflag,
int *fieldtype, char **fieldlabel,
int scaleflag, int wrapflag, int &fieldflag,
std::map<std::string, int> labels)
{
// match each field with a column of per-atom data // match each field with a column of per-atom data
// if fieldlabel set, match with explicit column // if fieldlabel set, match with explicit column
// else infer one or more column matches from fieldtype // else infer one or more column matches from fieldtype
@ -299,7 +310,6 @@ bigint ReaderNative::read_header(double box[3][3], int &boxinfo, int &triclinic,
for (int i = 0; i < nfield; i++) for (int i = 0; i < nfield; i++)
if (fieldindex[i] < 0) fieldflag = -1; if (fieldindex[i] < 0) fieldflag = -1;
return natoms;
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------

View File

@ -37,6 +37,9 @@ class ReaderNative : public Reader {
void skip(); void skip();
bigint read_header(double[3][3], int &, int &, int, int, int *, char **, int, int, int &, int &, bigint read_header(double[3][3], int &, int &, int, int, int *, char **, int, int, int &, int &,
int &, int &); int &, int &);
void match_field(int nfield, int &xflag, int &yflag, int &zflag, int *fieldtype,
char **fieldlabel, int scaleflag, int wrapflag, int &fieldflag,
std::map<std::string, int> labels);
void read_atoms(int, int, double **); void read_atoms(int, int, double **);
private: private:

271
src/reader_native_bin.cpp Normal file
View File

@ -0,0 +1,271 @@
// clang-format off
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "reader_native_bin.h"
#include "error.h"
#include "memory.h"
#include "tokenizer.h"
#include <cstring>
#include <utility>
using namespace LAMMPS_NS;
#define MAXLINE 1024 // max line length in dump file
// also in read_dump.cpp
enum{ID,TYPE,X,Y,Z,VX,VY,VZ,Q,IX,IY,IZ,FX,FY,FZ};
enum{UNSET,NOSCALE_NOWRAP,NOSCALE_WRAP,SCALE_NOWRAP,SCALE_WRAP};
/* ---------------------------------------------------------------------- */
ReaderNativeBin::ReaderNativeBin(LAMMPS *lmp) : ReaderNative(lmp)
{
line = new char[MAXLINE];
fieldindex = nullptr;
}
/* ---------------------------------------------------------------------- */
ReaderNativeBin::~ReaderNativeBin()
{
delete [] line;
memory->destroy(fieldindex);
}
/* ----------------------------------------------------------------------
read and return time stamp from dump file
if first read reaches end-of-file, return 1 so caller can open next file
only called by proc 0
------------------------------------------------------------------------- */
int ReaderNativeBin::read_time(bigint &ntimestep)
{
endian = 0x0001;
revision = 0x0001;
magic_string = nullptr;
unit_style = nullptr;
fread(&ntimestep, sizeof(bigint), 1, fp);
// detect end-of-file
if (feof(fp)) return 1;
// detect newer format
if (ntimestep < 0) {
// first bigint encodes negative format name length
bigint magic_string_len = -ntimestep;
delete[] magic_string;
magic_string = new char[magic_string_len + 1];
fread(magic_string, sizeof(char), magic_string_len, fp);
magic_string[magic_string_len] = '\0';
// read endian flag
fread(&endian, sizeof(int), 1, fp);
// read revision number
fread(&revision, sizeof(int), 1, fp);
// read the real ntimestep
fread(&ntimestep, sizeof(bigint), 1, fp);
}
return 0;
}
/* ----------------------------------------------------------------------
skip snapshot from timestamp onward
only called by proc 0
------------------------------------------------------------------------- */
void ReaderNativeBin::skip()
{
int nchunk;
fread(&nchunk, sizeof(int), 1, fp);
if (feof(fp)) {
error->one(FLERR,"Unexpected end of dump file");
}
for (int i = 0; i < nchunk; i++) {
int n;
fread(&n, sizeof(int), 1, fp);
// extend buffer to fit chunk size
if (n > maxbuf) {
if (buf) delete[] buf;
buf = new double[n];
maxbuf = n;
}
// read chunk and write as size_one values per line
fread(buf, sizeof(double), n, fp);
if (feof(fp)) {
error->one(FLERR,"Unexpected end of dump file");
}
}
delete[] magic_string;
delete[] unit_style;
magic_string = nullptr;
unit_style = nullptr;
}
/* ----------------------------------------------------------------------
read remaining header info:
return natoms
box bounds, triclinic (inferred), fieldflag (1 if any fields not found),
xyz flags = UNSET (not a requested field), SCALE/WRAP as in enum
if fieldflag set:
match Nfield fields to per-atom column labels
allocate and set fieldindex = which column each field maps to
fieldtype = X,VX,IZ etc
fieldlabel = user-specified label or nullptr if use fieldtype default
xyz flags = scaleflag+wrapflag if has fieldlabel name,
else set by x,xs,xu,xsu
only called by proc 0
------------------------------------------------------------------------- */
bigint ReaderNativeBin::read_header(double box[3][3], int &boxinfo, int &triclinic,
int fieldinfo, int nfield,
int *fieldtype, char **fieldlabel,
int scaleflag, int wrapflag, int &fieldflag,
int &xflag, int &yflag, int &zflag)
{
bigint natoms;
fread(&natoms, sizeof(bigint), 1, fp);
boxinfo = 1;
triclinic = 0;
box[0][2] = box[1][2] = box[2][2] = 0.0;
int boundary[3][2];
fread(&triclinic, sizeof(int), 1, fp);
fread(&boundary[0][0], 6 * sizeof(int), 1, fp);
fread(&box[0][0], sizeof(double), 1, fp);
fread(&box[0][1], sizeof(double), 1, fp);
fread(&box[1][0], sizeof(double), 1, fp);
fread(&box[1][1], sizeof(double), 1, fp);
fread(&box[2][0], sizeof(double), 1, fp);
fread(&box[2][1], sizeof(double), 1, fp);
if (triclinic) {
fread(&box[0][2], sizeof(double), 1, fp);
fread(&box[1][2], sizeof(double), 1, fp);
fread(&box[2][2], sizeof(double), 1, fp);
}
if (!fieldinfo) return natoms;
// exatract column labels and match to requested fields
fread(&size_one, sizeof(int), 1, fp);
int len = 0;
char *labelline;
if (magic_string && revision > 0x0001) {
// newer format includes units string, columns string
// and time
fread(&len, sizeof(int), 1, fp);
labelline = new char[len + 1];
if (len > 0) {
// has units
delete[] unit_style;
unit_style = new char[len + 1];
fread(unit_style, sizeof(char), len, fp);
unit_style[len] = '\0';
}
char flag = 0;
fread(&flag, sizeof(char), 1, fp);
if (flag) {
double time;
fread(&time, sizeof(double), 1, fp);
}
fread(&len, sizeof(int), 1, fp);
fread(labelline, sizeof(char), len, fp);
labelline[len] = '\0';
}
std::map<std::string, int> labels;
Tokenizer tokens(labelline);
nwords = 0;
while (tokens.has_next()) {
labels[tokens.next()] = nwords++;
}
if (nwords == 0) {
return 1;
}
match_field(nfield, xflag, yflag, zflag, fieldtype, fieldlabel, scaleflag, wrapflag, fieldflag, labels);
return natoms;
}
/* ----------------------------------------------------------------------
read N atom lines from dump file
stores appropriate values in fields array
return 0 if success, 1 if error
only called by proc 0
------------------------------------------------------------------------- */
void ReaderNativeBin::read_atoms(int n, int nfield, double **fields)
{
if (feof(fp)) {
error->one(FLERR,"Unexpected end of dump file");
}
int i_atom = 0;
int nchunk;
fread(&nchunk, sizeof(int), 1, fp);
for (int i = 0; i < nchunk; i++) {
fread(&n, sizeof(int), 1, fp);
// extend buffer to fit chunk size
if (n > maxbuf) {
if (buf) delete[] buf;
buf = new double[n];
maxbuf = n;
}
// read chunk and write as size_one values per line
fread(buf, sizeof(double), n, fp);
n /= size_one;
int m = 0;
for (int j = 0; j < n; j++)
{
double *words = &buf[m];
for (int k = 0; k < nfield; k++)
fields[i_atom][k] = words[fieldindex[k]];
i_atom += 1;
m+=size_one;
}
}
delete[] magic_string;
delete[] unit_style;
magic_string = nullptr;
unit_style = nullptr;
}

75
src/reader_native_bin.h Normal file
View File

@ -0,0 +1,75 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
Contributed by Lixin Sun
------------------------------------------------------------------------- */
#ifdef READER_CLASS
// clang-format off
ReaderStyle(native_bin,ReaderNative);
// clang-format on
#else
#ifndef LMP_READER_NATIVE_BIN_H
#define LMP_READER_NATIVE_BIN_H
#include "reader_native.h"
#include <map>
namespace LAMMPS_NS {
class ReaderNativeBin : public ReaderNative {
public:
ReaderNativeBin(class LAMMPS *);
~ReaderNativeBin();
int read_time(bigint &);
void skip();
bigint read_header(double[3][3], int &, int &, int, int, int *, char **, int, int, int &, int &,
int &, int &);
void read_atoms(int, int, double **);
private:
char *line; // line read from dump file
int nwords; // # of per-atom columns in dump file
int *fieldindex; //
int endian;
int revision;
char *magic_string;
char *unit_style;
int size_one;
int maxbuf = 0;
double *buf = nullptr;
int find_label(const std::string &label, const std::map<std::string, int> &labels);
void read_lines(int);
};
} // namespace LAMMPS_NS
#endif
#endif
/* ERROR/WARNING messages:
E: Dump file is incorrectly formatted
Self-explanatory.
E: Unexpected end of dump file
A read operation from the file failed.
*/

View File

@ -67,18 +67,21 @@ int main(int narg, char **arg)
int maxbuf = 0; int maxbuf = 0;
double *buf = nullptr; double *buf = nullptr;
if (narg == 1) { if (narg == 1)
{
printf("Syntax: binary2txt file1 file2 ...\n"); printf("Syntax: binary2txt file1 file2 ...\n");
return 1; return 1;
} }
// loop over files // loop over files
for (int iarg = 1; iarg < narg; iarg++) { for (int iarg = 1; iarg < narg; iarg++)
{
printf("%s:", arg[iarg]); printf("%s:", arg[iarg]);
fflush(stdout); fflush(stdout);
FILE *fp = fopen(arg[iarg], "rb"); FILE *fp = fopen(arg[iarg], "rb");
if (!fp) { if (!fp)
{
printf("ERROR: Could not open %s\n", arg[iarg]); printf("ERROR: Could not open %s\n", arg[iarg]);
return 1; return 1;
} }
@ -97,7 +100,8 @@ int main(int narg, char **arg)
// loop over snapshots in file // loop over snapshots in file
while (true) { while (true)
{
int endian = 0x0001; int endian = 0x0001;
int revision = 0x0001; int revision = 0x0001;
@ -105,14 +109,16 @@ int main(int narg, char **arg)
// detect end-of-file // detect end-of-file
if (feof(fp)) { if (feof(fp))
{
fclose(fp); fclose(fp);
fclose(fptxt); fclose(fptxt);
break; break;
} }
// detect newer format // detect newer format
if (ntimestep < 0) { if (ntimestep < 0)
{
// first bigint encodes negative format name length // first bigint encodes negative format name length
bigint magic_string_len = -ntimestep; bigint magic_string_len = -ntimestep;
@ -140,20 +146,23 @@ int main(int narg, char **arg)
fread(&yhi, sizeof(double), 1, fp); fread(&yhi, sizeof(double), 1, fp);
fread(&zlo, sizeof(double), 1, fp); fread(&zlo, sizeof(double), 1, fp);
fread(&zhi, sizeof(double), 1, fp); fread(&zhi, sizeof(double), 1, fp);
if (triclinic) { if (triclinic)
{
fread(&xy, sizeof(double), 1, fp); fread(&xy, sizeof(double), 1, fp);
fread(&xz, sizeof(double), 1, fp); fread(&xz, sizeof(double), 1, fp);
fread(&yz, sizeof(double), 1, fp); fread(&yz, sizeof(double), 1, fp);
} }
fread(&size_one, sizeof(int), 1, fp); fread(&size_one, sizeof(int), 1, fp);
if (magic_string && revision > 0x0001) { if (magic_string && revision > 0x0001)
{
// newer format includes units string, columns string // newer format includes units string, columns string
// and time // and time
int len = 0; int len = 0;
fread(&len, sizeof(int), 1, fp); fread(&len, sizeof(int), 1, fp);
if (len > 0) { if (len > 0)
{
// has units // has units
delete[] unit_style; delete[] unit_style;
unit_style = new char[len + 1]; unit_style = new char[len + 1];
@ -166,7 +175,8 @@ int main(int narg, char **arg)
char flag = 0; char flag = 0;
fread(&flag, sizeof(char), 1, fp); fread(&flag, sizeof(char), 1, fp);
if (flag) { if (flag)
{
double time; double time;
fread(&time, sizeof(double), 1, fp); fread(&time, sizeof(double), 1, fp);
fprintf(fptxt, "ITEM: TIME\n%.16g\n", time); fprintf(fptxt, "ITEM: TIME\n%.16g\n", time);
@ -187,8 +197,10 @@ int main(int narg, char **arg)
fprintf(fptxt, BIGINT_FORMAT "\n", natoms); fprintf(fptxt, BIGINT_FORMAT "\n", natoms);
m = 0; m = 0;
for (int idim = 0; idim < 3; idim++) { for (int idim = 0; idim < 3; idim++)
for (int iside = 0; iside < 2; iside++) { {
for (int iside = 0; iside < 2; iside++)
{
if (boundary[idim][iside] == 0) if (boundary[idim][iside] == 0)
boundstr[m++] = 'p'; boundstr[m++] = 'p';
else if (boundary[idim][iside] == 1) else if (boundary[idim][iside] == 1)
@ -202,12 +214,15 @@ int main(int narg, char **arg)
} }
boundstr[8] = '\0'; boundstr[8] = '\0';
if (!triclinic) { if (!triclinic)
{
fprintf(fptxt, "ITEM: BOX BOUNDS %s\n", boundstr); fprintf(fptxt, "ITEM: BOX BOUNDS %s\n", boundstr);
fprintf(fptxt, "%-1.16e %-1.16e\n", xlo, xhi); fprintf(fptxt, "%-1.16e %-1.16e\n", xlo, xhi);
fprintf(fptxt, "%-1.16e %-1.16e\n", ylo, yhi); fprintf(fptxt, "%-1.16e %-1.16e\n", ylo, yhi);
fprintf(fptxt, "%-1.16e %-1.16e\n", zlo, zhi); fprintf(fptxt, "%-1.16e %-1.16e\n", zlo, zhi);
} else { }
else
{
fprintf(fptxt, "ITEM: BOX BOUNDS xy xz yz %s\n", boundstr); fprintf(fptxt, "ITEM: BOX BOUNDS xy xz yz %s\n", boundstr);
fprintf(fptxt, "%-1.16e %-1.16e %-1.16e\n", xlo, xhi, xy); fprintf(fptxt, "%-1.16e %-1.16e %-1.16e\n", xlo, xhi, xy);
fprintf(fptxt, "%-1.16e %-1.16e %-1.16e\n", ylo, yhi, xz); fprintf(fptxt, "%-1.16e %-1.16e %-1.16e\n", ylo, yhi, xz);
@ -221,13 +236,17 @@ int main(int narg, char **arg)
// loop over processor chunks in file // loop over processor chunks in file
for (i = 0; i < nchunk; i++) { for (i = 0; i < nchunk; i++)
{
fread(&n, sizeof(int), 1, fp); fread(&n, sizeof(int), 1, fp);
// extend buffer to fit chunk size // extend buffer to fit chunk size
if (n > maxbuf) { if (n > maxbuf)
if (buf) delete[] buf; {
if (buf)
delete[] buf;
buf = new double[n]; buf = new double[n];
maxbuf = n; maxbuf = n;
} }
@ -237,11 +256,17 @@ int main(int narg, char **arg)
fread(buf, sizeof(double), n, fp); fread(buf, sizeof(double), n, fp);
n /= size_one; n /= size_one;
m = 0; m = 0;
for (j = 0; j < n; j++) { std::string line = "";
for (k = 0; k < size_one; k++) { for (j = 0; j < n; j++)
if (k + 1 < size_one) { {
for (k = 0; k < size_one; k++)
{
if (k + 1 < size_one)
{
fprintf(fptxt, "%g ", buf[m++]); fprintf(fptxt, "%g ", buf[m++]);
} else { }
else
{
fprintf(fptxt, "%g", buf[m++]); fprintf(fptxt, "%g", buf[m++]);
} }
} }
@ -261,6 +286,7 @@ int main(int narg, char **arg)
unit_style = nullptr; unit_style = nullptr;
} }
if (buf) delete[] buf; if (buf)
delete[] buf;
return 0; return 0;
} }