fold native binary reader class in to native reader class

This commit is contained in:
Axel Kohlmeyer
2021-12-11 20:31:44 -05:00
parent 8884acef24
commit 56fd07d88e
6 changed files with 300 additions and 473 deletions

View File

@ -25,11 +25,13 @@ using namespace LAMMPS_NS;
Reader::Reader(LAMMPS *lmp) : Pointers(lmp) Reader::Reader(LAMMPS *lmp) : Pointers(lmp)
{ {
fp = nullptr; fp = nullptr;
binary = false;
compressed = false;
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
try to open given file try to open given file
generic version for ASCII files that may be compressed generic version for ASCII files that may be compressed or native binary dumps
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void Reader::open_file(const std::string &file) void Reader::open_file(const std::string &file)
@ -37,12 +39,18 @@ void Reader::open_file(const std::string &file)
if (fp != nullptr) close_file(); if (fp != nullptr) close_file();
if (platform::has_compress_extension(file)) { if (platform::has_compress_extension(file)) {
compressed = 1; compressed = true;
fp = platform::compressed_read(file); fp = platform::compressed_read(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 = false;
if (utils::strmatch(file, "\\.bin$")) {
binary = true;
fp = fopen(file.c_str(),"rb");
} else {
fp = fopen(file.c_str(),"r"); fp = fopen(file.c_str(),"r");
binary = false;
}
} }
if (!fp) error->one(FLERR,"Cannot open file {}: {}", file, utils::getsyserror()); if (!fp) error->one(FLERR,"Cannot open file {}: {}", file, utils::getsyserror());

View File

@ -38,7 +38,8 @@ class Reader : protected Pointers {
protected: protected:
FILE *fp; // pointer to opened file or pipe FILE *fp; // pointer to opened file or pipe
int compressed; // flag for dump file compression bool compressed; // flag for dump file compression
bool binary; // flag for (native) binary files
}; };
} // namespace LAMMPS_NS } // namespace LAMMPS_NS

View File

@ -36,6 +36,8 @@ ReaderNative::ReaderNative(LAMMPS *lmp) : Reader(lmp)
{ {
line = new char[MAXLINE]; line = new char[MAXLINE];
fieldindex = nullptr; fieldindex = nullptr;
maxbuf = 0;
databuf = nullptr;
} }
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
@ -44,6 +46,7 @@ ReaderNative::~ReaderNative()
{ {
delete[] line; delete[] line;
memory->destroy(fieldindex); memory->destroy(fieldindex);
memory->destroy(databuf);
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
@ -54,6 +57,37 @@ ReaderNative::~ReaderNative()
int ReaderNative::read_time(bigint &ntimestep) int ReaderNative::read_time(bigint &ntimestep)
{ {
if (binary) {
int 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];
read_buf(magic_string, sizeof(char), magic_string_len);
magic_string[magic_string_len] = '\0';
// read endian flag
read_buf(&endian, sizeof(int), 1);
// read revision number
read_buf(&revision, sizeof(int), 1);
// read the real ntimestep
read_buf(&ntimestep, sizeof(bigint), 1);
}
} else {
char *eof = fgets(line,MAXLINE,fp); char *eof = fgets(line,MAXLINE,fp);
if (eof == nullptr) return 1; if (eof == nullptr) return 1;
@ -72,7 +106,7 @@ int ReaderNative::read_time(bigint &ntimestep)
int rv = sscanf(line,BIGINT_FORMAT,&ntimestep); int rv = sscanf(line,BIGINT_FORMAT,&ntimestep);
if (rv != 1) if (rv != 1)
error->one(FLERR,"Dump file is incorrectly formatted"); error->one(FLERR,"Dump file is incorrectly formatted");
}
return 0; return 0;
} }
@ -83,6 +117,33 @@ int ReaderNative::read_time(bigint &ntimestep)
void ReaderNative::skip() void ReaderNative::skip()
{ {
if (binary) {
bigint natoms;
int triclinic;
skip_buf(sizeof(bigint));
read_buf(&triclinic, sizeof(int), 1);
skip_buf((sizeof(int)+sizeof(double))*6);
if (triclinic) {
skip_buf(sizeof(double)*3);
}
skip_buf(sizeof(int));
skip_reading_magic_str();
// read chunk and skip them
int nchunk;
read_buf(&nchunk, sizeof(int), 1);
int n;
for (int i = 0; i < nchunk; i++) {
read_buf(&n, sizeof(int), 1);
read_double_chunk(n);
}
delete[] magic_string;
delete[] unit_style;
} else {
read_lines(2); read_lines(2);
bigint natoms; bigint natoms;
int rv = sscanf(line,BIGINT_FORMAT,&natoms); int rv = sscanf(line,BIGINT_FORMAT,&natoms);
@ -101,6 +162,30 @@ void ReaderNative::skip()
nremain -= nchunk; nremain -= nchunk;
} }
} }
}
void ReaderNative::skip_reading_magic_str()
{
if (magic_string && revision > 0x0001) {
int len;
read_buf(&len, sizeof(int), 1);
if (len > 0) {
// has units
skip_buf(sizeof(char)*len);
}
char flag = 0;
read_buf(&flag, sizeof(char), 1);
if (flag) {
skip_buf(sizeof(double));
}
read_buf(&len, sizeof(int), 1);
skip_buf(sizeof(char)*len);
}
}
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
read remaining header info: read remaining header info:
@ -123,7 +208,64 @@ bigint ReaderNative::read_header(double box[3][3], int &boxinfo, int &triclinic,
int scaleflag, int wrapflag, int &fieldflag, int scaleflag, int wrapflag, int &fieldflag,
int &xflag, int &yflag, int &zflag) int &xflag, int &yflag, int &zflag)
{ {
bigint natoms; bigint natoms = 0;
int len = 0;
char *labelline;
if (binary) {
read_buf(&natoms, sizeof(bigint), 1);
boxinfo = 1;
triclinic = 0;
box[0][2] = box[1][2] = box[2][2] = 0.0;
int boundary[3][2];
read_buf(&triclinic, sizeof(int), 1);
read_buf(&boundary[0][0], sizeof(int), 6);
read_buf(box[0], sizeof(double), 2);
read_buf(box[1], sizeof(double), 2);
read_buf(box[2], sizeof(double), 2);
if (triclinic) {
read_buf(&box[0][2], sizeof(double), 1);
read_buf(&box[1][2], sizeof(double), 1);
read_buf(&box[2][2], sizeof(double), 1);
}
// extract column labels and match to requested fields
read_buf(&size_one, sizeof(int), 1);
if (!fieldinfo) {
skip_reading_magic_str();
return natoms;
}
if (magic_string && revision > 0x0001) {
// newer format includes units string, columns string
// and time
read_buf(&len, sizeof(int), 1);
labelline = new char[len + 1];
if (len > 0) {
// has units
delete[] unit_style;
unit_style = new char[len + 1];
read_buf(unit_style, sizeof(char), len);
unit_style[len] = '\0';
}
char flag = 0;
read_buf(&flag, sizeof(char), 1);
if (flag) {
double time;
read_buf(&time, sizeof(double), 1);
}
read_buf(&len, sizeof(int), 1);
read_buf(labelline, sizeof(char), len);
labelline[len] = '\0';
}
} else {
int rv; int rv;
read_lines(2); read_lines(2);
@ -158,9 +300,10 @@ bigint ReaderNative::read_header(double box[3][3], int &boxinfo, int &triclinic,
if (!fieldinfo) return natoms; if (!fieldinfo) return natoms;
// exatract column labels and match to requested fields // extract column labels and match to requested fields
char *labelline = &line[strlen("ITEM: ATOMS ")]; labelline = &line[strlen("ITEM: ATOMS ")];
}
std::map<std::string, int> labels; std::map<std::string, int> labels;
Tokenizer tokens(labelline); Tokenizer tokens(labelline);
@ -174,7 +317,8 @@ bigint ReaderNative::read_header(double box[3][3], int &boxinfo, int &triclinic,
return 1; return 1;
} }
match_fields(nfield, xflag, yflag, zflag, fieldtype, fieldlabel, scaleflag, wrapflag, fieldflag, labels); match_fields(nfield, xflag, yflag, zflag, fieldtype, fieldlabel,
scaleflag, wrapflag, fieldflag, labels);
return natoms; return natoms;
} }
@ -323,6 +467,35 @@ void ReaderNative::match_fields(int nfield,
void ReaderNative::read_atoms(int n, int nfield, double **fields) void ReaderNative::read_atoms(int n, int nfield, double **fields)
{ {
if (binary) {
if (feof(fp)) {
error->one(FLERR,"Unexpected end of dump file");
}
int i_atom = 0;
int nchunk;
read_buf(&nchunk, sizeof(int), 1);
for (int i = 0; i < nchunk; i++) {
read_buf(&n, sizeof(int), 1);
// read chunk and write as size_one values per line
read_double_chunk(n);
n /= size_one;
int m = 0;
for (int j = 0; j < n; j++)
{
double *words = &databuf[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;
} else {
int i,m; int i,m;
char *eof; char *eof;
@ -341,6 +514,7 @@ void ReaderNative::read_atoms(int n, int nfield, double **fields)
fields[i][m] = atof(words[fieldindex[m]].c_str()); fields[i][m] = atof(words[fieldindex[m]].c_str());
} }
} }
}
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
match label to any of N labels match label to any of N labels
@ -369,3 +543,28 @@ void ReaderNative::read_lines(int n)
for (int i = 0; i < n; i++) eof = fgets(line,MAXLINE,fp); for (int i = 0; i < n; i++) eof = fgets(line,MAXLINE,fp);
if (eof == nullptr) error->one(FLERR,"Unexpected end of dump file"); if (eof == nullptr) error->one(FLERR,"Unexpected end of dump file");
} }
void ReaderNative::read_buf(void * ptr, size_t size, size_t count)
{
fread(ptr, size, count, fp);
// detect end-of-file
if (feof(fp)) error->one(FLERR,"Unexpected end of dump file");
}
void ReaderNative::read_double_chunk(size_t count)
{
// extend buffer to fit chunk size
if (count > maxbuf) {
memory->grow(databuf,count,"reader:databuf");
maxbuf = count;
}
read_buf(databuf, sizeof(double), count);
}
void ReaderNative::skip_buf(size_t size)
{
bigint pos = platform::ftell(fp);
pos += size;
platform::fseek(fp,pos);
}

View File

@ -39,18 +39,30 @@ class ReaderNative : public Reader {
int &, int &); int &, int &);
void read_atoms(int, int, double **); void read_atoms(int, int, double **);
protected: private:
int *fieldindex; // int revision;
char *magic_string;
char *unit_style;
int *fieldindex;
char *line; // line read from dump file
double *databuf; // buffer for binary data
int nwords; // # of per-atom columns in dump file
int size_one; // number of double for one atom
int maxbuf; // maximum buffer size
void match_fields(int, int &, int &, int &, int *, char **, int, int, int &, void match_fields(int, int &, int &, int &, int *, char **, int, int, int &,
std::map<std::string, int>); std::map<std::string, int>);
private:
char *line; // line read from dump file
int nwords; // # of per-atom columns in dump file
int find_label(const std::string &label, const std::map<std::string, int> &labels); int find_label(const std::string &label, const std::map<std::string, int> &labels);
void read_lines(int); void read_lines(int);
void read_buf(void *, size_t, size_t);
void read_double_chunk(size_t);
void skip_buf(size_t);
void skip_reading_magic_str();
}; };
} // namespace LAMMPS_NS } // namespace LAMMPS_NS

View File

@ -1,320 +0,0 @@
// 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>
#include <iostream>
using namespace LAMMPS_NS;
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)
{
fieldindex = nullptr;
buf = new double[maxbuf];
}
/* ---------------------------------------------------------------------- */
ReaderNativeBin::~ReaderNativeBin()
{
delete [] buf;
memory->destroy(fieldindex);
}
/* ----------------------------------------------------------------------
overload the open_file function to open the binary file
------------------------------------------------------------------------- */
void ReaderNativeBin::open_file(const std::string &file)
{
if (fp != nullptr) close_file();
if (platform::has_compress_extension(file)) {
error->one(FLERR,"Compressed binary files are not supported");
} else {
compressed = 0;
fp = fopen(file.c_str(), "rb");
}
if (!fp) error->one(FLERR,"Cannot open file {}: {}", file, utils::getsyserror());
}
/* ----------------------------------------------------------------------
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)
{
int 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];
read_buf(magic_string, sizeof(char), magic_string_len);
magic_string[magic_string_len] = '\0';
// read endian flag
read_buf(&endian, sizeof(int), 1);
// read revision number
read_buf(&revision, sizeof(int), 1);
// read the real ntimestep
read_buf(&ntimestep, sizeof(bigint), 1);
}
return 0;
}
/* ----------------------------------------------------------------------
skip snapshot from timestamp onward
only called by proc 0
------------------------------------------------------------------------- */
void ReaderNativeBin::skip()
{
bigint natoms;
int triclinic;
skip_buf(sizeof(bigint));
read_buf(&triclinic, sizeof(int), 1);
skip_buf((sizeof(int)+sizeof(double))*6);
if (triclinic) {
skip_buf(sizeof(double)*3);
}
skip_buf(sizeof(int));
skip_reading_magic_str();
// read chunk and skip them
int nchunk;
read_buf(&nchunk, sizeof(int), 1);
int n;
for (int i = 0; i < nchunk; i++) {
read_buf(&n, sizeof(int), 1);
read_double_chunk(n);
}
delete[] magic_string;
delete[] unit_style;
}
void ReaderNativeBin::skip_reading_magic_str()
{
if (magic_string && revision > 0x0001) {
int len;
read_buf(&len, sizeof(int), 1);
if (len > 0) {
// has units
skip_buf(sizeof(char)*len);
}
char flag = 0;
read_buf(&flag, sizeof(char), 1);
if (flag) {
skip_buf(sizeof(double));
}
read_buf(&len, sizeof(int), 1);
skip_buf(sizeof(char)*len);
}
}
/* ----------------------------------------------------------------------
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;
read_buf(&natoms, sizeof(bigint), 1);
boxinfo = 1;
triclinic = 0;
box[0][2] = box[1][2] = box[2][2] = 0.0;
int boundary[3][2];
read_buf(&triclinic, sizeof(int), 1);
read_buf(&boundary[0][0], sizeof(int), 6);
read_buf(box[0], sizeof(double), 2);
read_buf(box[1], sizeof(double), 2);
read_buf(box[2], sizeof(double), 2);
if (triclinic) {
read_buf(&box[0][2], sizeof(double), 1);
read_buf(&box[1][2], sizeof(double), 1);
read_buf(&box[2][2], sizeof(double), 1);
}
// exatract column labels and match to requested fields
read_buf(&size_one, sizeof(int), 1);
if (!fieldinfo) {
skip_reading_magic_str();
return natoms;
}
int len = 0;
char *labelline;
if (magic_string && revision > 0x0001) {
// newer format includes units string, columns string
// and time
read_buf(&len, sizeof(int), 1);
labelline = new char[len + 1];
if (len > 0) {
// has units
delete[] unit_style;
unit_style = new char[len + 1];
read_buf(unit_style, sizeof(char), len);
unit_style[len] = '\0';
}
char flag = 0;
read_buf(&flag, sizeof(char), 1);
if (flag) {
double time;
read_buf(&time, sizeof(double), 1);
}
read_buf(&len, sizeof(int), 1);
read_buf(labelline, sizeof(char), len);
labelline[len] = '\0';
}
std::map<std::string, int> labels;
Tokenizer tokens(labelline);
int nwords = 0;
while (tokens.has_next()) {
labels[tokens.next()] = nwords++;
}
if (nwords == 0) {
return 1;
}
match_fields(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;
read_buf(&nchunk, sizeof(int), 1);
for (int i = 0; i < nchunk; i++) {
read_buf(&n, sizeof(int), 1);
// read chunk and write as size_one values per line
read_double_chunk(n);
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;
}
void ReaderNativeBin::read_buf(void * ptr, size_t size, size_t count)
{
fread(ptr, size, count, fp);
// detect end-of-file
if (feof(fp)) error->one(FLERR,"Unexpected end of dump file");
}
void ReaderNativeBin::read_double_chunk(size_t count)
{
// extend buffer to fit chunk size
if (count > maxbuf) {
if (buf) delete[] buf;
buf = new double[count];
maxbuf = count;
}
read_buf(buf, sizeof(double), count);
}
void ReaderNativeBin::skip_buf(size_t size)
{
char tmp[size];
read_buf(tmp, 1, size);
}

View File

@ -1,73 +0,0 @@
/* -*- 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,ReaderNativeBin);
// 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 **);
void open_file(const std::string &);
private:
int revision;
char *magic_string;
char *unit_style;
int size_one; // number of double for one atom
double *buf;
int maxbuf = 1; // maximum buffer size
void read_buf(void *, size_t, size_t);
void read_double_chunk(size_t);
void skip_buf(size_t);
void skip_reading_magic_str();
};
} // 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.
*/