forked from lijiext/lammps
Merge pull request #2136 from rbberger/refactor-reading
Refactor value parsing code segments and add dump tests
This commit is contained in:
commit
43f6fa4b29
|
@ -166,8 +166,83 @@ void DumpAtom::write_data(int n, double *mybuf)
|
|||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpAtom::format_magic_string_binary()
|
||||
{
|
||||
// use negative ntimestep as marker for new format
|
||||
bigint fmtlen = strlen(MAGIC_STRING);
|
||||
bigint marker = -fmtlen;
|
||||
fwrite(&marker, sizeof(bigint), 1, fp);
|
||||
fwrite(MAGIC_STRING, sizeof(char), fmtlen, fp);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpAtom::format_endian_binary()
|
||||
{
|
||||
int endian = ENDIAN;
|
||||
fwrite(&endian, sizeof(int), 1, fp);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpAtom::format_revision_binary()
|
||||
{
|
||||
int revision = FORMAT_REVISION;
|
||||
fwrite(&revision, sizeof(int), 1, fp);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpAtom::header_unit_style_binary()
|
||||
{
|
||||
int len = 0;
|
||||
if (unit_flag && !unit_count) {
|
||||
++unit_count;
|
||||
len = strlen(update->unit_style);
|
||||
fwrite(&len, sizeof(int), 1, fp);
|
||||
fwrite(update->unit_style, sizeof(char), len, fp);
|
||||
} else {
|
||||
fwrite(&len, sizeof(int), 1, fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpAtom::header_columns_binary()
|
||||
{
|
||||
int len = strlen(columns);
|
||||
fwrite(&len, sizeof(int), 1, fp);
|
||||
fwrite(columns, sizeof(char), len, fp);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpAtom::header_time_binary()
|
||||
{
|
||||
char flag = time_flag ? 1 : 0;
|
||||
fwrite(&flag, sizeof(char), 1, fp);
|
||||
|
||||
if (time_flag) {
|
||||
double t = compute_time();
|
||||
fwrite(&t, sizeof(double), 1, fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpAtom::header_format_binary()
|
||||
{
|
||||
format_magic_string_binary();
|
||||
format_endian_binary();
|
||||
format_revision_binary();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpAtom::header_binary(bigint ndump)
|
||||
{
|
||||
header_format_binary();
|
||||
|
||||
fwrite(&update->ntimestep,sizeof(bigint),1,fp);
|
||||
fwrite(&ndump,sizeof(bigint),1,fp);
|
||||
fwrite(&domain->triclinic,sizeof(int),1,fp);
|
||||
|
@ -179,6 +254,11 @@ void DumpAtom::header_binary(bigint ndump)
|
|||
fwrite(&boxzlo,sizeof(double),1,fp);
|
||||
fwrite(&boxzhi,sizeof(double),1,fp);
|
||||
fwrite(&size_one,sizeof(int),1,fp);
|
||||
|
||||
header_unit_style_binary();
|
||||
header_time_binary();
|
||||
header_columns_binary();
|
||||
|
||||
if (multiproc) fwrite(&nclusterprocs,sizeof(int),1,fp);
|
||||
else fwrite(&nprocs,sizeof(int),1,fp);
|
||||
}
|
||||
|
@ -187,6 +267,8 @@ void DumpAtom::header_binary(bigint ndump)
|
|||
|
||||
void DumpAtom::header_binary_triclinic(bigint ndump)
|
||||
{
|
||||
header_format_binary();
|
||||
|
||||
fwrite(&update->ntimestep,sizeof(bigint),1,fp);
|
||||
fwrite(&ndump,sizeof(bigint),1,fp);
|
||||
fwrite(&domain->triclinic,sizeof(int),1,fp);
|
||||
|
@ -201,6 +283,11 @@ void DumpAtom::header_binary_triclinic(bigint ndump)
|
|||
fwrite(&boxxz,sizeof(double),1,fp);
|
||||
fwrite(&boxyz,sizeof(double),1,fp);
|
||||
fwrite(&size_one,sizeof(int),1,fp);
|
||||
|
||||
header_unit_style_binary();
|
||||
header_time_binary();
|
||||
header_columns_binary();
|
||||
|
||||
if (multiproc) fwrite(&nclusterprocs,sizeof(int),1,fp);
|
||||
else fwrite(&nprocs,sizeof(int),1,fp);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,10 @@ class DumpAtom : public Dump {
|
|||
public:
|
||||
DumpAtom(LAMMPS *, int, char**);
|
||||
|
||||
const char * MAGIC_STRING = "DUMPATOM";
|
||||
const int FORMAT_REVISION = 0x0002;
|
||||
const int ENDIAN = 0x0001;
|
||||
|
||||
protected:
|
||||
int scale_flag; // 1 if atom coords are scaled, 0 if no
|
||||
int image_flag; // 1 if append box count to atom coords, 0 if no
|
||||
|
@ -41,6 +45,14 @@ class DumpAtom : public Dump {
|
|||
int convert_string(int, double *);
|
||||
void write_data(int, double *);
|
||||
|
||||
void header_format_binary();
|
||||
void header_unit_style_binary();
|
||||
void header_time_binary();
|
||||
void header_columns_binary();
|
||||
void format_magic_string_binary();
|
||||
void format_endian_binary();
|
||||
void format_revision_binary();
|
||||
|
||||
typedef void (DumpAtom::*FnPtrHeader)(bigint);
|
||||
FnPtrHeader header_choice; // ptr to write header functions
|
||||
void header_binary(bigint);
|
||||
|
|
|
@ -183,7 +183,7 @@ DumpCustom::DumpCustom(LAMMPS *lmp, int narg, char **arg) :
|
|||
columns[0] = '\0';
|
||||
for (int iarg = 0; iarg < nfield; iarg++) {
|
||||
strcat(columns,earg[iarg]);
|
||||
strcat(columns," ");
|
||||
if (iarg+1 < nfield) strcat(columns," ");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,7 +302,7 @@ void DumpCustom::init_style()
|
|||
strcpy(vformat[i],ptr);
|
||||
}
|
||||
|
||||
vformat[i] = strcat(vformat[i]," ");
|
||||
if (i+1 < size_one) vformat[i] = strcat(vformat[i]," ");
|
||||
}
|
||||
|
||||
// setup boundary string
|
||||
|
@ -381,8 +381,83 @@ void DumpCustom::write_header(bigint ndump)
|
|||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpCustom::format_magic_string_binary()
|
||||
{
|
||||
// use negative ntimestep as marker for new format
|
||||
bigint fmtlen = strlen(MAGIC_STRING);
|
||||
bigint marker = -fmtlen;
|
||||
fwrite(&marker, sizeof(bigint), 1, fp);
|
||||
fwrite(MAGIC_STRING, sizeof(char), fmtlen, fp);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpCustom::format_endian_binary()
|
||||
{
|
||||
int endian = ENDIAN;
|
||||
fwrite(&endian, sizeof(int), 1, fp);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpCustom::format_revision_binary()
|
||||
{
|
||||
int revision = FORMAT_REVISION;
|
||||
fwrite(&revision, sizeof(int), 1, fp);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpCustom::header_unit_style_binary()
|
||||
{
|
||||
int len = 0;
|
||||
if (unit_flag && !unit_count) {
|
||||
++unit_count;
|
||||
len = strlen(update->unit_style);
|
||||
fwrite(&len, sizeof(int), 1, fp);
|
||||
fwrite(update->unit_style, sizeof(char), len, fp);
|
||||
} else {
|
||||
fwrite(&len, sizeof(int), 1, fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpCustom::header_columns_binary()
|
||||
{
|
||||
int len = strlen(columns);
|
||||
fwrite(&len, sizeof(int), 1, fp);
|
||||
fwrite(columns, sizeof(char), len, fp);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpCustom::header_time_binary()
|
||||
{
|
||||
char flag = time_flag ? 1 : 0;
|
||||
fwrite(&flag, sizeof(char), 1, fp);
|
||||
|
||||
if (time_flag) {
|
||||
double t = compute_time();
|
||||
fwrite(&t, sizeof(double), 1, fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpCustom::header_format_binary()
|
||||
{
|
||||
format_magic_string_binary();
|
||||
format_endian_binary();
|
||||
format_revision_binary();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpCustom::header_binary(bigint ndump)
|
||||
{
|
||||
header_format_binary();
|
||||
|
||||
fwrite(&update->ntimestep,sizeof(bigint),1,fp);
|
||||
fwrite(&ndump,sizeof(bigint),1,fp);
|
||||
fwrite(&domain->triclinic,sizeof(int),1,fp);
|
||||
|
@ -394,6 +469,11 @@ void DumpCustom::header_binary(bigint ndump)
|
|||
fwrite(&boxzlo,sizeof(double),1,fp);
|
||||
fwrite(&boxzhi,sizeof(double),1,fp);
|
||||
fwrite(&size_one,sizeof(int),1,fp);
|
||||
|
||||
header_unit_style_binary();
|
||||
header_time_binary();
|
||||
header_columns_binary();
|
||||
|
||||
if (multiproc) fwrite(&nclusterprocs,sizeof(int),1,fp);
|
||||
else fwrite(&nprocs,sizeof(int),1,fp);
|
||||
}
|
||||
|
@ -402,6 +482,8 @@ void DumpCustom::header_binary(bigint ndump)
|
|||
|
||||
void DumpCustom::header_binary_triclinic(bigint ndump)
|
||||
{
|
||||
header_format_binary();
|
||||
|
||||
fwrite(&update->ntimestep,sizeof(bigint),1,fp);
|
||||
fwrite(&ndump,sizeof(bigint),1,fp);
|
||||
fwrite(&domain->triclinic,sizeof(int),1,fp);
|
||||
|
@ -416,6 +498,11 @@ void DumpCustom::header_binary_triclinic(bigint ndump)
|
|||
fwrite(&boxxz,sizeof(double),1,fp);
|
||||
fwrite(&boxyz,sizeof(double),1,fp);
|
||||
fwrite(&size_one,sizeof(int),1,fp);
|
||||
|
||||
header_unit_style_binary();
|
||||
header_time_binary();
|
||||
header_columns_binary();
|
||||
|
||||
if (multiproc) fwrite(&nclusterprocs,sizeof(int),1,fp);
|
||||
else fwrite(&nprocs,sizeof(int),1,fp);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,10 @@ class DumpCustom : public Dump {
|
|||
DumpCustom(class LAMMPS *, int, char **);
|
||||
virtual ~DumpCustom();
|
||||
|
||||
const char * MAGIC_STRING = "DUMPCUSTOM";
|
||||
const int FORMAT_REVISION = 0x0002;
|
||||
const int ENDIAN = 0x0001;
|
||||
|
||||
protected:
|
||||
int nevery; // dump frequency for output
|
||||
int iregion; // -1 if no region, else which region
|
||||
|
@ -107,6 +111,14 @@ class DumpCustom : public Dump {
|
|||
int add_custom(char *, int);
|
||||
virtual int modify_param(int, char **);
|
||||
|
||||
void header_format_binary();
|
||||
void header_unit_style_binary();
|
||||
void header_time_binary();
|
||||
void header_columns_binary();
|
||||
void format_magic_string_binary();
|
||||
void format_endian_binary();
|
||||
void format_revision_binary();
|
||||
|
||||
typedef void (DumpCustom::*FnPtrHeader)(bigint);
|
||||
FnPtrHeader header_choice; // ptr to write header functions
|
||||
void header_binary(bigint);
|
||||
|
|
20
src/info.cpp
20
src/info.cpp
|
@ -1243,6 +1243,26 @@ string Info::get_openmp_info()
|
|||
#endif
|
||||
}
|
||||
|
||||
string Info::get_mpi_vendor() {
|
||||
#if defined(MPI_STUBS)
|
||||
return "MPI STUBS";
|
||||
#elif defined(OPEN_MPI)
|
||||
return "Open MPI";
|
||||
#elif defined(MPICH_NAME)
|
||||
return "MPICH";
|
||||
#elif defined(I_MPI_VERSION)
|
||||
return "Intel MPI";
|
||||
#elif defined(PLATFORM_MPI)
|
||||
return "Platform MPI";
|
||||
#elif defined(HP_MPI)
|
||||
return "HP MPI";
|
||||
#elif defined(MSMPI_VER)
|
||||
return "Microsoft MPI";
|
||||
#else
|
||||
return "Unknown";
|
||||
#endif
|
||||
}
|
||||
|
||||
string Info::get_mpi_info(int &major, int &minor)
|
||||
{
|
||||
int len;
|
||||
|
|
|
@ -48,6 +48,7 @@ class Info : protected Pointers {
|
|||
static std::string get_os_info();
|
||||
static std::string get_compiler_info();
|
||||
static std::string get_openmp_info();
|
||||
static std::string get_mpi_vendor();
|
||||
static std::string get_mpi_info(int &, int &);
|
||||
static std::string get_cxx_info();
|
||||
|
||||
|
|
|
@ -91,33 +91,6 @@ using namespace LAMMPS_NS;
|
|||
#define END_CAPTURE
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// helper functions, not in library API
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
concatenate one or more LAMMPS input lines starting at ptr
|
||||
removes NULL terminator when last printable char of line = '&'
|
||||
by replacing both NULL and '&' with space character
|
||||
repeat as many times as needed
|
||||
on return, ptr now points to longer line
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void concatenate_lines(char *ptr)
|
||||
{
|
||||
int nend = strlen(ptr);
|
||||
int n = nend-1;
|
||||
while (n && isspace(ptr[n])) n--;
|
||||
while (ptr[n] == '&') {
|
||||
ptr[nend] = ' ';
|
||||
ptr[n] = ' ';
|
||||
strtok(ptr,"\n");
|
||||
nend = strlen(ptr);
|
||||
n = nend-1;
|
||||
while (n && isspace(ptr[n])) n--;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// library API functions to create/destroy an instance of LAMMPS
|
||||
// and communicate commands to it
|
||||
|
|
666
src/molecule.cpp
666
src/molecule.cpp
|
@ -27,6 +27,7 @@
|
|||
#include "error.h"
|
||||
#include "utils.h"
|
||||
#include "fmt/format.h"
|
||||
#include "tokenizer.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
|
@ -47,7 +48,7 @@ Molecule::Molecule(LAMMPS *lmp, int narg, char **arg, int &index) :
|
|||
improper_type(NULL), improper_atom1(NULL), improper_atom2(NULL),
|
||||
improper_atom3(NULL), improper_atom4(NULL), nspecial(NULL), special(NULL),
|
||||
shake_flag(NULL), shake_atom(NULL), shake_type(NULL), avec_body(NULL), ibodyparams(NULL),
|
||||
dbodyparams(NULL), fragmentmask(NULL), fragmentnames(NULL),
|
||||
dbodyparams(NULL), fragmentmask(NULL),
|
||||
dx(NULL), dxcom(NULL), dxbody(NULL), quat_external(NULL), fp(NULL), count(NULL)
|
||||
{
|
||||
me = comm->me;
|
||||
|
@ -424,65 +425,77 @@ void Molecule::read(int flag)
|
|||
if (strspn(line," \t\n\r") == strlen(line)) continue;
|
||||
|
||||
// search line for header keywords and set corresponding variable
|
||||
try {
|
||||
ValueTokenizer values(line);
|
||||
|
||||
int nmatch = 0;
|
||||
int nwant = 0;
|
||||
if (strstr(line,"atoms")) {
|
||||
nmatch = sscanf(line,"%d",&natoms);
|
||||
nwant = 1;
|
||||
} else if (strstr(line,"bonds")) {
|
||||
nmatch = sscanf(line,"%d",&nbonds);
|
||||
nwant = 1;
|
||||
} else if (strstr(line,"angles")) {
|
||||
nmatch = sscanf(line,"%d",&nangles);
|
||||
nwant = 1;
|
||||
} else if (strstr(line,"dihedrals")) {
|
||||
nmatch = sscanf(line,"%d",&ndihedrals);
|
||||
nwant = 1;
|
||||
} else if (strstr(line,"impropers")) {
|
||||
nmatch = sscanf(line,"%d",&nimpropers);
|
||||
nwant = 1;
|
||||
} else if (strstr(line,"fragments")) {
|
||||
nmatch = sscanf(line,"%d",&nfragments);
|
||||
nwant = 1;
|
||||
} else if (strstr(line,"mass")) {
|
||||
massflag = 1;
|
||||
nmatch = sscanf(line,"%lg",&masstotal);
|
||||
nwant = 1;
|
||||
masstotal *= sizescale*sizescale*sizescale;
|
||||
} else if (strstr(line,"com")) {
|
||||
comflag = 1;
|
||||
nmatch = sscanf(line,"%lg %lg %lg",&com[0],&com[1],&com[2]);
|
||||
nwant = 3;
|
||||
com[0] *= sizescale;
|
||||
com[1] *= sizescale;
|
||||
com[2] *= sizescale;
|
||||
if (domain->dimension == 2 && com[2] != 0.0)
|
||||
error->all(FLERR,"Molecule file z center-of-mass must be 0.0 for 2d");
|
||||
} else if (strstr(line,"inertia")) {
|
||||
inertiaflag = 1;
|
||||
nmatch = sscanf(line,"%lg %lg %lg %lg %lg %lg",
|
||||
&itensor[0],&itensor[1],&itensor[2],
|
||||
&itensor[3],&itensor[4],&itensor[5]);
|
||||
nwant = 6;
|
||||
const double scale5 = sizescale*sizescale*sizescale*sizescale*sizescale;
|
||||
itensor[0] *= scale5;
|
||||
itensor[1] *= scale5;
|
||||
itensor[2] *= scale5;
|
||||
itensor[3] *= scale5;
|
||||
itensor[4] *= scale5;
|
||||
itensor[5] *= scale5;
|
||||
} else if (strstr(line,"body")) {
|
||||
bodyflag = 1;
|
||||
avec_body = (AtomVecBody *) atom->style_match("body");
|
||||
if (!avec_body)
|
||||
error->all(FLERR,"Molecule file requires atom style body");
|
||||
nmatch = sscanf(line,"%d %d",&nibody,&ndbody);
|
||||
nwant = 2;
|
||||
} else break;
|
||||
int nmatch = values.count();
|
||||
int nwant = 0;
|
||||
if (values.contains("atoms")) {
|
||||
natoms = values.next_int();
|
||||
nwant = 2;
|
||||
} else if (values.contains("bonds")) {
|
||||
nbonds = values.next_int();
|
||||
nwant = 2;
|
||||
} else if (values.contains("angles")) {
|
||||
nangles = values.next_int();
|
||||
nwant = 2;
|
||||
} else if (values.contains("dihedrals")) {
|
||||
ndihedrals = values.next_int();
|
||||
nwant = 2;
|
||||
} else if (values.contains("impropers")) {
|
||||
nimpropers = values.next_int();
|
||||
nwant = 2;
|
||||
} else if (values.contains("fragments")) {
|
||||
nfragments = values.next_int();
|
||||
nwant = 2;
|
||||
} else if (values.contains("mass")) {
|
||||
massflag = 1;
|
||||
masstotal = values.next_double();
|
||||
nwant = 2;
|
||||
masstotal *= sizescale*sizescale*sizescale;
|
||||
} else if (values.contains("com")) {
|
||||
comflag = 1;
|
||||
com[0] = values.next_double();
|
||||
com[1] = values.next_double();
|
||||
com[2] = values.next_double();
|
||||
nwant = 4;
|
||||
com[0] *= sizescale;
|
||||
com[1] *= sizescale;
|
||||
com[2] *= sizescale;
|
||||
if (domain->dimension == 2 && com[2] != 0.0)
|
||||
error->all(FLERR,"Molecule file z center-of-mass must be 0.0 for 2d");
|
||||
} else if (values.contains("inertia")) {
|
||||
inertiaflag = 1;
|
||||
itensor[0] = values.next_double();
|
||||
itensor[1] = values.next_double();
|
||||
itensor[2] = values.next_double();
|
||||
itensor[3] = values.next_double();
|
||||
itensor[4] = values.next_double();
|
||||
itensor[5] = values.next_double();
|
||||
nwant = 7;
|
||||
const double scale5 = sizescale*sizescale*sizescale*sizescale*sizescale;
|
||||
itensor[0] *= scale5;
|
||||
itensor[1] *= scale5;
|
||||
itensor[2] *= scale5;
|
||||
itensor[3] *= scale5;
|
||||
itensor[4] *= scale5;
|
||||
itensor[5] *= scale5;
|
||||
} else if (values.contains("body")) {
|
||||
bodyflag = 1;
|
||||
avec_body = (AtomVecBody *) atom->style_match("body");
|
||||
if (!avec_body)
|
||||
error->all(FLERR,"Molecule file requires atom style body");
|
||||
nibody = values.next_int();
|
||||
ndbody = values.next_int();
|
||||
nwant = 3;
|
||||
} else break;
|
||||
|
||||
if (nmatch != nwant)
|
||||
error->all(FLERR,"Invalid header in molecule file");
|
||||
if (nmatch != nwant)
|
||||
error->one(FLERR,"Invalid header in molecule file");
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, fmt::format("Invalid header in molecule file\n"
|
||||
"{}", e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
// error checks
|
||||
|
@ -659,15 +672,25 @@ void Molecule::read(int flag)
|
|||
|
||||
void Molecule::coords(char *line)
|
||||
{
|
||||
int tmp;
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
if (4 != sscanf(line,"%d %lg %lg %lg",&tmp,&x[i][0],&x[i][1],&x[i][2]))
|
||||
error->all(FLERR,"Invalid Coords section in molecule file");
|
||||
try {
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
|
||||
x[i][0] *= sizescale;
|
||||
x[i][1] *= sizescale;
|
||||
x[i][2] *= sizescale;
|
||||
ValueTokenizer values(line);
|
||||
if (values.count() != 4) error->one(FLERR,"Invalid Coords section in molecule file");
|
||||
|
||||
values.next_int();
|
||||
x[i][0] = values.next_double();
|
||||
x[i][1] = values.next_double();
|
||||
x[i][2] = values.next_double();
|
||||
|
||||
x[i][0] *= sizescale;
|
||||
x[i][1] *= sizescale;
|
||||
x[i][2] *= sizescale;
|
||||
}
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, fmt::format("Invalid Coords section in molecule file\n"
|
||||
"{}", e.what()));
|
||||
}
|
||||
|
||||
if (domain->dimension == 2) {
|
||||
|
@ -684,12 +707,20 @@ void Molecule::coords(char *line)
|
|||
|
||||
void Molecule::types(char *line)
|
||||
{
|
||||
int tmp;
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
if (2 != sscanf(line,"%d %d",&tmp,&type[i]))
|
||||
error->all(FLERR,"Invalid Types section in molecule file");
|
||||
type[i] += toffset;
|
||||
try {
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
|
||||
ValueTokenizer values(line);
|
||||
if (values.count() != 2) error->one(FLERR,"Invalid Types section in molecule file");
|
||||
|
||||
values.next_int();
|
||||
type[i] = values.next_int();
|
||||
type[i] += toffset;
|
||||
}
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, fmt::format("Invalid Types section in molecule file\n"
|
||||
"{}", e.what()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < natoms; i++)
|
||||
|
@ -707,12 +738,19 @@ void Molecule::types(char *line)
|
|||
|
||||
void Molecule::molecules(char *line)
|
||||
{
|
||||
int tmp;
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
if (2 != sscanf(line,"%d %d",&tmp,&molecule[i]))
|
||||
error->all(FLERR,"Invalid Molecules section in molecule file");
|
||||
// molecule[i] += moffset; // placeholder for possible molecule offset
|
||||
try {
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
ValueTokenizer values(line);
|
||||
if (values.count() != 2) error->one(FLERR,"Invalid Molecules section in molecule file");
|
||||
|
||||
values.next_int();
|
||||
molecule[i] = values.next_int();
|
||||
// molecule[i] += moffset; // placeholder for possible molecule offset
|
||||
}
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, fmt::format("Invalid Molecules section in molecule file\n"
|
||||
"{}", e.what()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < natoms; i++)
|
||||
|
@ -729,27 +767,28 @@ void Molecule::molecules(char *line)
|
|||
|
||||
void Molecule::fragments(char *line)
|
||||
{
|
||||
int n,m,atomID,nwords;
|
||||
char **words = new char*[natoms+1];
|
||||
try {
|
||||
for (int i = 0; i < nfragments; i++) {
|
||||
readline(line);
|
||||
|
||||
for (int i = 0; i < nfragments; i++) {
|
||||
readline(line);
|
||||
nwords = parse(line,words,natoms+1);
|
||||
if (nwords > natoms+1)
|
||||
error->all(FLERR,"Invalid atom ID in Fragments section of molecule file");
|
||||
n = strlen(words[0]) + 1;
|
||||
fragmentnames[i] = new char[n];
|
||||
strcpy(fragmentnames[i],words[0]);
|
||||
ValueTokenizer values(line);
|
||||
|
||||
for (m = 1; m < nwords; m++) {
|
||||
atomID = atoi(words[m]);
|
||||
if (atomID <= 0 || atomID > natoms)
|
||||
error->all(FLERR,"Invalid atom ID in Fragments section of molecule file");
|
||||
fragmentmask[i][atomID-1] = 1;
|
||||
if (values.count() > natoms+1)
|
||||
error->one(FLERR,"Invalid atom ID in Fragments section of molecule file");
|
||||
|
||||
fragmentnames[i] = values.next_string();
|
||||
|
||||
while(values.has_next()) {
|
||||
int atomID = values.next_int();
|
||||
if (atomID <= 0 || atomID > natoms)
|
||||
error->one(FLERR,"Invalid atom ID in Fragments section of molecule file");
|
||||
fragmentmask[i][atomID-1] = 1;
|
||||
}
|
||||
}
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, fmt::format("Invalid atom ID in Fragments section of molecule file\n"
|
||||
"{}", e.what()));
|
||||
}
|
||||
|
||||
delete [] words;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
|
@ -758,11 +797,19 @@ void Molecule::fragments(char *line)
|
|||
|
||||
void Molecule::charges(char *line)
|
||||
{
|
||||
int tmp;
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
if (2 != sscanf(line,"%d %lg",&tmp,&q[i]))
|
||||
error->all(FLERR,"Invalid Charges section in molecule file");
|
||||
try {
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
|
||||
ValueTokenizer values(line);
|
||||
if (values.count() != 2) error->one(FLERR,"Invalid Charges section in molecule file");
|
||||
|
||||
values.next_int();
|
||||
q[i] = values.next_double();
|
||||
}
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, fmt::format("Invalid Charges section in molecule file\n"
|
||||
"{}", e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -772,15 +819,23 @@ void Molecule::charges(char *line)
|
|||
|
||||
void Molecule::diameters(char *line)
|
||||
{
|
||||
int tmp;
|
||||
maxradius = 0.0;
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
if (2 != sscanf(line,"%d %lg",&tmp,&radius[i]))
|
||||
error->all(FLERR,"Invalid Diameters section in molecule file");
|
||||
radius[i] *= sizescale;
|
||||
radius[i] *= 0.5;
|
||||
maxradius = MAX(maxradius,radius[i]);
|
||||
try {
|
||||
maxradius = 0.0;
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
|
||||
ValueTokenizer values(line);
|
||||
if (values.count() != 2) error->one(FLERR,"Invalid Diameters section in molecule file");
|
||||
|
||||
values.next_int();
|
||||
radius[i] = values.next_double();
|
||||
radius[i] *= sizescale;
|
||||
radius[i] *= 0.5;
|
||||
maxradius = MAX(maxradius,radius[i]);
|
||||
}
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, fmt::format("Invalid Diameters section in molecule file\n"
|
||||
"{}", e.what()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < natoms; i++)
|
||||
|
@ -794,12 +849,20 @@ void Molecule::diameters(char *line)
|
|||
|
||||
void Molecule::masses(char *line)
|
||||
{
|
||||
int tmp;
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
if (2 != sscanf(line,"%d %lg",&tmp,&rmass[i]))
|
||||
error->all(FLERR,"Invalid Masses section in molecule file");
|
||||
rmass[i] *= sizescale*sizescale*sizescale;
|
||||
try {
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
|
||||
ValueTokenizer values(line);
|
||||
if (values.count() != 2) error->one(FLERR,"Invalid Masses section in molecule file");
|
||||
|
||||
values.next_int();
|
||||
rmass[i] = values.next_double();
|
||||
rmass[i] *= sizescale*sizescale*sizescale;
|
||||
}
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, fmt::format("Invalid Masses section in molecule file\n"
|
||||
"{}", e.what()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < natoms; i++)
|
||||
|
@ -827,9 +890,19 @@ void Molecule::bonds(int flag, char *line)
|
|||
|
||||
for (int i = 0; i < nbonds; i++) {
|
||||
readline(line);
|
||||
if (4 != sscanf(line,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT,
|
||||
&tmp,&itype,&atom1,&atom2))
|
||||
error->all(FLERR,"Invalid Bonds section in molecule file");
|
||||
|
||||
try {
|
||||
ValueTokenizer values(line);
|
||||
if (values.count() != 4) error->one(FLERR,"Invalid Bonds section in molecule file");
|
||||
values.next_int();
|
||||
itype = values.next_int();
|
||||
atom1 = values.next_tagint();
|
||||
atom2 = values.next_tagint();
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, fmt::format("Invalid Bonds section in molecule file\n"
|
||||
"{}", e.what()));
|
||||
}
|
||||
|
||||
itype += boffset;
|
||||
|
||||
if ((atom1 <= 0) || (atom1 > natoms) ||
|
||||
|
@ -885,9 +958,20 @@ void Molecule::angles(int flag, char *line)
|
|||
|
||||
for (int i = 0; i < nangles; i++) {
|
||||
readline(line);
|
||||
if (5 != sscanf(line,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT,
|
||||
&tmp,&itype,&atom1,&atom2,&atom3))
|
||||
error->all(FLERR,"Invalid Angles section in molecule file");
|
||||
|
||||
try {
|
||||
ValueTokenizer values(line);
|
||||
if (values.count() != 5) error->one(FLERR,"Invalid Angles section in molecule file");
|
||||
values.next_int();
|
||||
itype = values.next_int();
|
||||
atom1 = values.next_tagint();
|
||||
atom2 = values.next_tagint();
|
||||
atom3 = values.next_tagint();
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, fmt::format("Invalid Angles section in molecule file\n"
|
||||
"{}", e.what()));
|
||||
}
|
||||
|
||||
itype += aoffset;
|
||||
|
||||
if ((atom1 <= 0) || (atom1 > natoms) ||
|
||||
|
@ -958,10 +1042,21 @@ void Molecule::dihedrals(int flag, char *line)
|
|||
|
||||
for (int i = 0; i < ndihedrals; i++) {
|
||||
readline(line);
|
||||
if (6 != sscanf(line,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT " "
|
||||
TAGINT_FORMAT " " TAGINT_FORMAT " ",
|
||||
&tmp,&itype,&atom1,&atom2,&atom3,&atom4))
|
||||
error->all(FLERR,"Invalid Dihedrals section in molecule file");
|
||||
|
||||
try {
|
||||
ValueTokenizer values(line);
|
||||
if (values.count() != 6) error->one(FLERR,"Invalid Dihedrals section in molecule file");
|
||||
values.next_int();
|
||||
itype = values.next_int();
|
||||
atom1 = values.next_tagint();
|
||||
atom2 = values.next_tagint();
|
||||
atom3 = values.next_tagint();
|
||||
atom4 = values.next_tagint();
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, fmt::format("Invalid Dihedrals section in molecule file\n"
|
||||
"{}", e.what()));
|
||||
}
|
||||
|
||||
itype += doffset;
|
||||
|
||||
if ((atom1 <= 0) || (atom1 > natoms) ||
|
||||
|
@ -1047,10 +1142,21 @@ void Molecule::impropers(int flag, char *line)
|
|||
|
||||
for (int i = 0; i < nimpropers; i++) {
|
||||
readline(line);
|
||||
if (6 != sscanf(line,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT " "
|
||||
TAGINT_FORMAT " " TAGINT_FORMAT " ",
|
||||
&tmp,&itype,&atom1,&atom2,&atom3,&atom4))
|
||||
error->all(FLERR,"Invalid Impropers section in molecule file");
|
||||
|
||||
try {
|
||||
ValueTokenizer values(line);
|
||||
if (values.count() != 6) error->one(FLERR,"Invalid Impropers section in molecule file");
|
||||
values.next_int();
|
||||
itype = values.next_int();
|
||||
atom1 = values.next_tagint();
|
||||
atom2 = values.next_tagint();
|
||||
atom3 = values.next_tagint();
|
||||
atom4 = values.next_tagint();
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, fmt::format("Invalid Impropers section in molecule file\n"
|
||||
"{}", e.what()));
|
||||
}
|
||||
|
||||
itype += ioffset;
|
||||
|
||||
if ((atom1 <= 0) || (atom1 > natoms) ||
|
||||
|
@ -1124,15 +1230,24 @@ void Molecule::impropers(int flag, char *line)
|
|||
|
||||
void Molecule::nspecial_read(int flag, char *line)
|
||||
{
|
||||
int tmp,c1,c2,c3;
|
||||
|
||||
if (flag == 0) maxspecial = 0;
|
||||
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
if (4 != sscanf(line,"%d %d %d %d",&tmp,&c1,&c2,&c3))
|
||||
error->all(FLERR,"Invalid Special Bond Counts section in "
|
||||
"molecule file");
|
||||
|
||||
int c1, c2, c3;
|
||||
|
||||
try {
|
||||
ValueTokenizer values(line);
|
||||
if (values.count() != 4) error->one(FLERR,"Invalid Special Bond Counts section in molecule file");
|
||||
values.next_int();
|
||||
c1 = values.next_tagint();
|
||||
c2 = values.next_tagint();
|
||||
c3 = values.next_tagint();
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, fmt::format("Invalid Special Bond Counts section in molecule file\n"
|
||||
"{}", e.what()));
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
nspecial[i][0] = c1;
|
||||
|
@ -1148,25 +1263,30 @@ void Molecule::nspecial_read(int flag, char *line)
|
|||
|
||||
void Molecule::special_read(char *line)
|
||||
{
|
||||
int m,nwords;
|
||||
char **words = new char*[maxspecial+1];
|
||||
try {
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
nwords = parse(line,words,maxspecial+1);
|
||||
if (nwords != nspecial[i][2]+1)
|
||||
error->all(FLERR,"Molecule file special list "
|
||||
"does not match special count");
|
||||
ValueTokenizer values(line);
|
||||
int nwords = values.count();
|
||||
|
||||
for (m = 1; m < nwords; m++) {
|
||||
special[i][m-1] = ATOTAGINT(words[m]);
|
||||
if (special[i][m-1] <= 0 || special[i][m-1] > natoms ||
|
||||
special[i][m-1] == i+1)
|
||||
error->all(FLERR,"Invalid special atom index in molecule file");
|
||||
if (nwords != nspecial[i][2]+1)
|
||||
error->one(FLERR,"Molecule file special list "
|
||||
"does not match special count");
|
||||
|
||||
values.next_int(); // ignore
|
||||
|
||||
for (int m = 1; m < nwords; m++) {
|
||||
special[i][m-1] = values.next_tagint();
|
||||
if (special[i][m-1] <= 0 || special[i][m-1] > natoms ||
|
||||
special[i][m-1] == i+1)
|
||||
error->one(FLERR,"Invalid special atom index in molecule file");
|
||||
}
|
||||
}
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, fmt::format("Invalid Molecule file special list\n"
|
||||
"{}", e.what()));
|
||||
}
|
||||
|
||||
delete [] words;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
|
@ -1283,16 +1403,26 @@ void Molecule::special_generate()
|
|||
|
||||
void Molecule::shakeflag_read(char *line)
|
||||
{
|
||||
int tmp;
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
if (2 != sscanf(line,"%d %d",&tmp,&shake_flag[i]))
|
||||
error->all(FLERR,"Invalid Shake Flags section in molecule file");
|
||||
try {
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
|
||||
ValueTokenizer values(line);
|
||||
|
||||
if (values.count() != 2)
|
||||
error->one(FLERR,"Invalid Shake Flags section in molecule file");
|
||||
|
||||
values.next_int();
|
||||
shake_flag[i] = values.next_int();
|
||||
}
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, fmt::format("Invalid Shake Flags section in molecule file\n"
|
||||
"{}", e.what()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < natoms; i++)
|
||||
if (shake_flag[i] < 0 || shake_flag[i] > 4)
|
||||
error->all(FLERR,"Invalid shake flag in molecule file");
|
||||
error->one(FLERR,"Invalid shake flag in molecule file");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
|
@ -1301,32 +1431,58 @@ void Molecule::shakeflag_read(char *line)
|
|||
|
||||
void Molecule::shakeatom_read(char *line)
|
||||
{
|
||||
int tmp, nmatch=0, nwant=0;
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
if (shake_flag[i] == 1) {
|
||||
nmatch = sscanf(line,"%d " TAGINT_FORMAT " " TAGINT_FORMAT
|
||||
" " TAGINT_FORMAT,&tmp,&shake_atom[i][0],
|
||||
&shake_atom[i][1],&shake_atom[i][2]);
|
||||
nwant = 4;
|
||||
} else if (shake_flag[i] == 2) {
|
||||
nmatch = sscanf(line,"%d " TAGINT_FORMAT " " TAGINT_FORMAT,
|
||||
&tmp,&shake_atom[i][0],&shake_atom[i][1]);
|
||||
nwant = 3;
|
||||
} else if (shake_flag[i] == 3) {
|
||||
nmatch = sscanf(line,"%d " TAGINT_FORMAT " " TAGINT_FORMAT
|
||||
" " TAGINT_FORMAT,&tmp,&shake_atom[i][0],
|
||||
&shake_atom[i][1],&shake_atom[i][2]);
|
||||
nwant = 4;
|
||||
} else if (shake_flag[i] == 4) {
|
||||
nmatch = sscanf(line,"%d " TAGINT_FORMAT " " TAGINT_FORMAT " "
|
||||
TAGINT_FORMAT " " TAGINT_FORMAT,
|
||||
&tmp,&shake_atom[i][0],&shake_atom[i][1],
|
||||
&shake_atom[i][2],&shake_atom[i][3]);
|
||||
nwant = 5;
|
||||
int nmatch=0, nwant=0;
|
||||
try {
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
|
||||
ValueTokenizer values(line);
|
||||
nmatch = values.count();
|
||||
|
||||
switch (shake_flag[i]) {
|
||||
case 1:
|
||||
values.next_int();
|
||||
shake_atom[i][0] = values.next_tagint();
|
||||
shake_atom[i][1] = values.next_tagint();
|
||||
shake_atom[i][2] = values.next_tagint();
|
||||
nwant = 4;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
values.next_int();
|
||||
shake_atom[i][0] = values.next_tagint();
|
||||
shake_atom[i][1] = values.next_tagint();
|
||||
nwant = 3;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
values.next_int();
|
||||
shake_atom[i][0] = values.next_tagint();
|
||||
shake_atom[i][1] = values.next_tagint();
|
||||
shake_atom[i][2] = values.next_tagint();
|
||||
nwant = 4;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
values.next_int();
|
||||
shake_atom[i][0] = values.next_tagint();
|
||||
shake_atom[i][1] = values.next_tagint();
|
||||
shake_atom[i][2] = values.next_tagint();
|
||||
shake_atom[i][3] = values.next_tagint();
|
||||
nwant = 5;
|
||||
break;
|
||||
|
||||
default:
|
||||
error->one(FLERR,"Invalid shake atom in molecule file");
|
||||
}
|
||||
|
||||
if (nmatch != nwant)
|
||||
error->one(FLERR,"Invalid shake atom in molecule file");
|
||||
}
|
||||
if (nmatch != nwant)
|
||||
error->all(FLERR,"Invalid shake atom in molecule file");
|
||||
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR,fmt::format("Invalid shake atom in molecule file\n"
|
||||
"{}", e.what()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
|
@ -1334,7 +1490,7 @@ void Molecule::shakeatom_read(char *line)
|
|||
if (m == 1) m = 3;
|
||||
for (int j = 0; j < m; j++)
|
||||
if (shake_atom[i][j] <= 0 || shake_atom[i][j] > natoms)
|
||||
error->all(FLERR,"Invalid shake atom in molecule file");
|
||||
error->one(FLERR,"Invalid shake atom in molecule file");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1344,27 +1500,54 @@ void Molecule::shakeatom_read(char *line)
|
|||
|
||||
void Molecule::shaketype_read(char *line)
|
||||
{
|
||||
int tmp, nmatch=0, nwant=0;
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
if (shake_flag[i] == 1) {
|
||||
nmatch = sscanf(line,"%d %d %d %d",&tmp,&shake_type[i][0],
|
||||
&shake_type[i][1],&shake_type[i][2]);
|
||||
nwant = 4;
|
||||
} else if (shake_flag[i] == 2) {
|
||||
nmatch = sscanf(line,"%d %d",&tmp,&shake_type[i][0]);
|
||||
nwant = 2;
|
||||
} else if (shake_flag[i] == 3) {
|
||||
nmatch = sscanf(line,"%d %d %d",&tmp,&shake_type[i][0],
|
||||
&shake_type[i][1]);
|
||||
nwant = 3;
|
||||
} else if (shake_flag[i] == 4) {
|
||||
nmatch = sscanf(line,"%d %d %d %d",&tmp,&shake_type[i][0],
|
||||
&shake_type[i][1],&shake_type[i][2]);
|
||||
nwant = 4;
|
||||
try {
|
||||
int nmatch=0, nwant=0;
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
readline(line);
|
||||
|
||||
ValueTokenizer values(line);
|
||||
nmatch = values.count();
|
||||
|
||||
switch (shake_flag[i]) {
|
||||
case 1:
|
||||
values.next_int();
|
||||
shake_type[i][0] = values.next_int();
|
||||
shake_type[i][1] = values.next_int();
|
||||
shake_type[i][2] = values.next_int();
|
||||
nwant = 4;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
values.next_int();
|
||||
shake_type[i][0] = values.next_int();
|
||||
nwant = 2;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
values.next_int();
|
||||
shake_type[i][0] = values.next_int();
|
||||
shake_type[i][1] = values.next_int();
|
||||
nwant = 3;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
values.next_int();
|
||||
shake_type[i][0] = values.next_int();
|
||||
shake_type[i][1] = values.next_int();
|
||||
shake_type[i][2] = values.next_int();
|
||||
nwant = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
error->one(FLERR,"Invalid shake type data in molecule file");
|
||||
}
|
||||
|
||||
if (nmatch != nwant)
|
||||
error->one(FLERR,"Invalid shake type data in molecule file");
|
||||
}
|
||||
if (nmatch != nwant)
|
||||
error->all(FLERR,"Invalid shake type data in molecule file");
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, fmt::format("Invalid shake type data in molecule file\n",
|
||||
"{}", e.what()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < natoms; i++) {
|
||||
|
@ -1372,10 +1555,10 @@ void Molecule::shaketype_read(char *line)
|
|||
if (m == 1) m = 3;
|
||||
for (int j = 0; j < m-1; j++)
|
||||
if (shake_type[i][j] <= 0)
|
||||
error->all(FLERR,"Invalid shake bond type in molecule file");
|
||||
error->one(FLERR,"Invalid shake bond type in molecule file");
|
||||
if (shake_flag[i] == 1)
|
||||
if (shake_type[i][2] <= 0)
|
||||
error->all(FLERR,"Invalid shake angle type in molecule file");
|
||||
error->one(FLERR,"Invalid shake angle type in molecule file");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1386,34 +1569,38 @@ void Molecule::shaketype_read(char *line)
|
|||
|
||||
void Molecule::body(int flag, int pflag, char *line)
|
||||
{
|
||||
int i,ncount;
|
||||
|
||||
int nparam = nibody;
|
||||
if (pflag) nparam = ndbody;
|
||||
|
||||
int nword = 0;
|
||||
while (nword < nparam) {
|
||||
readline(line);
|
||||
|
||||
ncount = utils::trim_and_count_words(line);
|
||||
if (ncount == 0)
|
||||
error->one(FLERR,"Too few values in body section of molecule file");
|
||||
if (nword+ncount > nparam)
|
||||
error->all(FLERR,"Too many values in body section of molecule file");
|
||||
try {
|
||||
while (nword < nparam) {
|
||||
readline(line);
|
||||
|
||||
if (flag) {
|
||||
if (pflag == 0) {
|
||||
ibodyparams[nword++] = force->inumeric(FLERR,strtok(line," \t\n\r\f"));
|
||||
for (i = 1; i < ncount; i++)
|
||||
ibodyparams[nword++] =
|
||||
force->inumeric(FLERR,strtok(NULL," \t\n\r\f"));
|
||||
} else {
|
||||
dbodyparams[nword++] = force->numeric(FLERR,strtok(line," \t\n\r\f"));
|
||||
for (i = 1; i < ncount; i++)
|
||||
dbodyparams[nword++] =
|
||||
force->numeric(FLERR,strtok(NULL," \t\n\r\f"));
|
||||
}
|
||||
} else nword += ncount;
|
||||
ValueTokenizer values(line);
|
||||
int ncount = values.count();
|
||||
|
||||
if (ncount == 0)
|
||||
error->one(FLERR,"Too few values in body section of molecule file");
|
||||
if (nword+ncount > nparam)
|
||||
error->one(FLERR,"Too many values in body section of molecule file");
|
||||
|
||||
if (flag) {
|
||||
if (pflag == 0) {
|
||||
while(values.has_next()) {
|
||||
ibodyparams[nword++] = values.next_int();
|
||||
}
|
||||
} else {
|
||||
while(values.has_next()) {
|
||||
dbodyparams[nword++] = values.next_double();
|
||||
}
|
||||
}
|
||||
} else nword += ncount;
|
||||
}
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, fmt::format("Invalid body params in molecule file\n",
|
||||
"{}", e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1424,7 +1611,7 @@ void Molecule::body(int flag, int pflag, char *line)
|
|||
int Molecule::findfragment(const char *name)
|
||||
{
|
||||
for (int i = 0; i < nfragments; i++)
|
||||
if (fragmentnames[i] && strcmp(name,fragmentnames[i]) == 0) return i;
|
||||
if (fragmentnames[i] == name) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1565,7 +1752,7 @@ void Molecule::allocate()
|
|||
if (typeflag) memory->create(type,natoms,"molecule:type");
|
||||
if (moleculeflag) memory->create(molecule,natoms,"molecule:molecule");
|
||||
if (fragmentflag) {
|
||||
fragmentnames = new char*[nfragments];
|
||||
fragmentnames.resize(nfragments);
|
||||
memory->create(fragmentmask,nfragments,natoms,"molecule:fragmentmask");
|
||||
for (int i = 0; i < nfragments; i++)
|
||||
for (int j = 0; j < natoms; j++) fragmentmask[i][j] = 0;
|
||||
|
@ -1664,9 +1851,9 @@ void Molecule::deallocate()
|
|||
|
||||
memory->destroy(molecule);
|
||||
memory->destroy(fragmentmask);
|
||||
|
||||
if (fragmentflag) {
|
||||
for (int i = 0; i < nfragments; i++) delete [] fragmentnames[i];
|
||||
delete [] fragmentnames;
|
||||
fragmentnames.clear();
|
||||
}
|
||||
|
||||
memory->destroy(num_bond);
|
||||
|
@ -1793,27 +1980,6 @@ void Molecule::skip_lines(int n, char *line)
|
|||
for (int i = 0; i < n; i++) readline(line);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
parse line into words separated by whitespace
|
||||
return # of words
|
||||
max = max pointers storable in words
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int Molecule::parse(char *line, char **words, int max)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
int nwords = 0;
|
||||
words[nwords++] = strtok(line," \t\n\r\f");
|
||||
|
||||
while ((ptr = strtok(NULL," \t\n\r\f"))) {
|
||||
if (nwords < max) words[nwords] = ptr;
|
||||
nwords++;
|
||||
}
|
||||
|
||||
return nwords;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 prints molecule params
|
||||
------------------------------------------------------------------------- */
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#define LMP_ONE_MOLECULE_H
|
||||
|
||||
#include "pointers.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
|
@ -94,7 +96,7 @@ class Molecule : protected Pointers {
|
|||
// fragment info
|
||||
|
||||
int **fragmentmask; // nfragments by natoms
|
||||
char **fragmentnames;
|
||||
std::vector<std::string> fragmentnames;
|
||||
|
||||
double center[3]; // geometric center of molecule
|
||||
double masstotal; // total mass of molecule
|
||||
|
@ -163,7 +165,6 @@ class Molecule : protected Pointers {
|
|||
void readline(char *);
|
||||
void parse_keyword(int, char *, char *);
|
||||
void skip_lines(int, char *);
|
||||
int parse(char *, char **, int);
|
||||
|
||||
// void print();
|
||||
};
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "error.h"
|
||||
#include "utils.h"
|
||||
#include "fmt/format.h"
|
||||
#include "potential_file_reader.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
@ -237,109 +238,71 @@ double PairCoulStreitz::init_one(int i, int j)
|
|||
|
||||
void PairCoulStreitz::read_file(char *file)
|
||||
{
|
||||
int params_per_line = 6;
|
||||
char **words = new char*[params_per_line+1];
|
||||
|
||||
memory->sfree(params);
|
||||
params = NULL;
|
||||
params = nullptr;
|
||||
nparams = 0;
|
||||
maxparam = 0;
|
||||
|
||||
// open file on proc 0
|
||||
|
||||
FILE *fp;
|
||||
if (comm->me == 0) {
|
||||
fp = force->open_potential(file);
|
||||
if (fp == NULL)
|
||||
error->one(FLERR,fmt::format("Cannot open coul/streitz potential "
|
||||
"file {}",file));
|
||||
}
|
||||
PotentialFileReader reader(lmp, file, "coul/streitz");
|
||||
char * line;
|
||||
|
||||
// read each line out of file, skipping blank lines or leading '#'
|
||||
// store line of params if all 3 element tags are in element list
|
||||
while((line = reader.next_line(NPARAMS_PER_LINE))) {
|
||||
try {
|
||||
ValueTokenizer values(line);
|
||||
|
||||
int n,nwords,ielement;
|
||||
char line[MAXLINE],*ptr;
|
||||
int eof = 0;
|
||||
std::string iname = values.next_string();
|
||||
|
||||
while (1) {
|
||||
if (comm->me == 0) {
|
||||
ptr = fgets(line,MAXLINE,fp);
|
||||
if (ptr == NULL) {
|
||||
eof = 1;
|
||||
fclose(fp);
|
||||
} else n = strlen(line) + 1;
|
||||
}
|
||||
MPI_Bcast(&eof,1,MPI_INT,0,world);
|
||||
if (eof) break;
|
||||
MPI_Bcast(&n,1,MPI_INT,0,world);
|
||||
MPI_Bcast(line,n,MPI_CHAR,0,world);
|
||||
// ielement = 1st args
|
||||
int ielement;
|
||||
|
||||
// strip comment, skip line if blank
|
||||
for (ielement = 0; ielement < nelements; ielement++)
|
||||
if (iname == elements[ielement]) break;
|
||||
|
||||
if ((ptr = strchr(line,'#'))) *ptr = '\0';
|
||||
nwords = utils::count_words(line);
|
||||
if (nwords == 0) continue;
|
||||
// load up parameter settings and error check their values
|
||||
|
||||
// concatenate additional lines until have params_per_line words
|
||||
if (nparams == maxparam) {
|
||||
maxparam += DELTA;
|
||||
params = (Param *) memory->srealloc(params,maxparam*sizeof(Param),
|
||||
"pair:params");
|
||||
|
||||
while (nwords < params_per_line) {
|
||||
n = strlen(line);
|
||||
if (comm->me == 0) {
|
||||
ptr = fgets(&line[n],MAXLINE-n,fp);
|
||||
if (ptr == NULL) {
|
||||
eof = 1;
|
||||
fclose(fp);
|
||||
} else n = strlen(line) + 1;
|
||||
// make certain all addional allocated storage is initialized
|
||||
// to avoid false positives when checking with valgrind
|
||||
|
||||
memset(params + nparams, 0, DELTA*sizeof(Param));
|
||||
}
|
||||
|
||||
|
||||
params[nparams].ielement = ielement;
|
||||
params[nparams].chi = values.next_double();
|
||||
params[nparams].eta = values.next_double();
|
||||
params[nparams].gamma = values.next_double();
|
||||
params[nparams].zeta = values.next_double();
|
||||
params[nparams].zcore = values.next_double();
|
||||
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, e.what());
|
||||
}
|
||||
MPI_Bcast(&eof,1,MPI_INT,0,world);
|
||||
if (eof) break;
|
||||
MPI_Bcast(&n,1,MPI_INT,0,world);
|
||||
MPI_Bcast(line,n,MPI_CHAR,0,world);
|
||||
if ((ptr = strchr(line,'#'))) *ptr = '\0';
|
||||
nwords = utils::count_words(line);
|
||||
|
||||
// parameter sanity check
|
||||
|
||||
if (params[nparams].eta < 0.0 || params[nparams].zeta < 0.0 ||
|
||||
params[nparams].zcore < 0.0 || params[nparams].gamma != 0.0 )
|
||||
error->one(FLERR,"Illegal coul/streitz parameter");
|
||||
|
||||
nparams++;
|
||||
}
|
||||
|
||||
if (nwords != params_per_line)
|
||||
error->all(FLERR,"Incorrect format in coul/streitz potential file");
|
||||
|
||||
// words = ptrs to all words in line
|
||||
|
||||
nwords = 0;
|
||||
words[nwords++] = strtok(line," \t\n\r\f");
|
||||
while ((words[nwords++] = strtok(NULL," \t\n\r\f"))) continue;
|
||||
|
||||
// ielement = 1st args
|
||||
|
||||
for (ielement = 0; ielement < nelements; ielement++)
|
||||
if (strcmp(words[0],elements[ielement]) == 0) break;
|
||||
if (ielement == nelements) continue;
|
||||
|
||||
// load up parameter settings and error check their values
|
||||
|
||||
if (nparams == maxparam) {
|
||||
maxparam += DELTA;
|
||||
params = (Param *) memory->srealloc(params,maxparam*sizeof(Param),
|
||||
"pair:params");
|
||||
}
|
||||
|
||||
params[nparams].ielement = ielement;
|
||||
params[nparams].chi = atof(words[1]);
|
||||
params[nparams].eta = atof(words[2]);
|
||||
params[nparams].gamma = atof(words[3]);
|
||||
params[nparams].zeta = atof(words[4]);
|
||||
params[nparams].zcore = atof(words[5]);
|
||||
|
||||
// parameter sanity check
|
||||
|
||||
if (params[nparams].eta < 0.0 || params[nparams].zeta < 0.0 ||
|
||||
params[nparams].zcore < 0.0 || params[nparams].gamma != 0.0 )
|
||||
error->all(FLERR,"Illegal coul/streitz parameter");
|
||||
|
||||
nparams++;
|
||||
}
|
||||
|
||||
delete [] words;
|
||||
MPI_Bcast(&nparams, 1, MPI_INT, 0, world);
|
||||
MPI_Bcast(&maxparam, 1, MPI_INT, 0, world);
|
||||
|
||||
if(comm->me != 0) {
|
||||
params = (Param *) memory->srealloc(params,maxparam*sizeof(Param), "pair:params");
|
||||
}
|
||||
|
||||
MPI_Bcast(params, maxparam*sizeof(Param), MPI_BYTE, 0, world);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
|
|
@ -36,6 +36,8 @@ class PairCoulStreitz : public Pair {
|
|||
double memory_usage();
|
||||
virtual void *extract(const char *, int &);
|
||||
|
||||
static const int NPARAMS_PER_LINE = 6;
|
||||
|
||||
protected:
|
||||
struct Param {
|
||||
double chi, eta, gamma, zeta, zcore;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "memory.h"
|
||||
#include "error.h"
|
||||
#include "utils.h"
|
||||
#include "tokenizer.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
|
@ -33,7 +34,6 @@ enum{UNSET,NOSCALE_NOWRAP,NOSCALE_WRAP,SCALE_NOWRAP,SCALE_WRAP};
|
|||
ReaderNative::ReaderNative(LAMMPS *lmp) : Reader(lmp)
|
||||
{
|
||||
line = new char[MAXLINE];
|
||||
words = NULL;
|
||||
fieldindex = NULL;
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,6 @@ ReaderNative::ReaderNative(LAMMPS *lmp) : Reader(lmp)
|
|||
ReaderNative::~ReaderNative()
|
||||
{
|
||||
delete [] line;
|
||||
delete [] words;
|
||||
memory->destroy(fieldindex);
|
||||
}
|
||||
|
||||
|
@ -162,19 +161,16 @@ bigint ReaderNative::read_header(double box[3][3], int &boxinfo, int &triclinic,
|
|||
|
||||
char *labelline = &line[strlen("ITEM: ATOMS ")];
|
||||
|
||||
nwords = utils::trim_and_count_words(labelline);
|
||||
char **labels = new char*[nwords];
|
||||
labels[0] = strtok(labelline," \t\n\r\f");
|
||||
if (labels[0] == NULL) {
|
||||
delete[] labels;
|
||||
return 1;
|
||||
std::map<std::string, int> labels;
|
||||
Tokenizer tokens(labelline);
|
||||
nwords = 0;
|
||||
|
||||
while(tokens.has_next()) {
|
||||
labels[tokens.next()] = nwords++;
|
||||
}
|
||||
for (int m = 1; m < nwords; m++) {
|
||||
labels[m] = strtok(NULL," \t\n\r\f");
|
||||
if (labels[m] == NULL) {
|
||||
delete[] labels;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(nwords == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// match each field with a column of per-atom data
|
||||
|
@ -191,25 +187,25 @@ bigint ReaderNative::read_header(double box[3][3], int &boxinfo, int &triclinic,
|
|||
|
||||
for (int i = 0; i < nfield; i++) {
|
||||
if (fieldlabel[i]) {
|
||||
fieldindex[i] = find_label(fieldlabel[i],nwords,labels);
|
||||
fieldindex[i] = find_label(fieldlabel[i], labels);
|
||||
if (fieldtype[i] == X) xflag = 2*scaleflag + wrapflag + 1;
|
||||
else if (fieldtype[i] == Y) yflag = 2*scaleflag + wrapflag + 1;
|
||||
else if (fieldtype[i] == Z) zflag = 2*scaleflag + wrapflag + 1;
|
||||
}
|
||||
|
||||
else if (fieldtype[i] == ID)
|
||||
fieldindex[i] = find_label("id",nwords,labels);
|
||||
fieldindex[i] = find_label("id", labels);
|
||||
else if (fieldtype[i] == TYPE)
|
||||
fieldindex[i] = find_label("type",nwords,labels);
|
||||
fieldindex[i] = find_label("type", labels);
|
||||
|
||||
else if (fieldtype[i] == X) {
|
||||
fieldindex[i] = find_label("x",nwords,labels);
|
||||
fieldindex[i] = find_label("x", labels);
|
||||
xflag = NOSCALE_WRAP;
|
||||
if (fieldindex[i] < 0) {
|
||||
fieldindex[i] = nwords;
|
||||
s_index = find_label("xs",nwords,labels);
|
||||
u_index = find_label("xu",nwords,labels);
|
||||
su_index = find_label("xsu",nwords,labels);
|
||||
s_index = find_label("xs", labels);
|
||||
u_index = find_label("xu", labels);
|
||||
su_index = find_label("xsu", labels);
|
||||
if (s_index >= 0 && s_index < fieldindex[i]) {
|
||||
fieldindex[i] = s_index;
|
||||
xflag = SCALE_WRAP;
|
||||
|
@ -226,13 +222,13 @@ bigint ReaderNative::read_header(double box[3][3], int &boxinfo, int &triclinic,
|
|||
if (fieldindex[i] == nwords) fieldindex[i] = -1;
|
||||
|
||||
} else if (fieldtype[i] == Y) {
|
||||
fieldindex[i] = find_label("y",nwords,labels);
|
||||
fieldindex[i] = find_label("y", labels);
|
||||
yflag = NOSCALE_WRAP;
|
||||
if (fieldindex[i] < 0) {
|
||||
fieldindex[i] = nwords;
|
||||
s_index = find_label("ys",nwords,labels);
|
||||
u_index = find_label("yu",nwords,labels);
|
||||
su_index = find_label("ysu",nwords,labels);
|
||||
s_index = find_label("ys", labels);
|
||||
u_index = find_label("yu", labels);
|
||||
su_index = find_label("ysu", labels);
|
||||
if (s_index >= 0 && s_index < fieldindex[i]) {
|
||||
fieldindex[i] = s_index;
|
||||
yflag = SCALE_WRAP;
|
||||
|
@ -249,13 +245,13 @@ bigint ReaderNative::read_header(double box[3][3], int &boxinfo, int &triclinic,
|
|||
if (fieldindex[i] == nwords) fieldindex[i] = -1;
|
||||
|
||||
} else if (fieldtype[i] == Z) {
|
||||
fieldindex[i] = find_label("z",nwords,labels);
|
||||
fieldindex[i] = find_label("z", labels);
|
||||
zflag = NOSCALE_WRAP;
|
||||
if (fieldindex[i] < 0) {
|
||||
fieldindex[i] = nwords;
|
||||
s_index = find_label("zs",nwords,labels);
|
||||
u_index = find_label("zu",nwords,labels);
|
||||
su_index = find_label("zsu",nwords,labels);
|
||||
s_index = find_label("zs", labels);
|
||||
u_index = find_label("zu", labels);
|
||||
su_index = find_label("zsu", labels);
|
||||
if (s_index >= 0 && s_index < fieldindex[i]) {
|
||||
fieldindex[i] = s_index;
|
||||
zflag = SCALE_WRAP;
|
||||
|
@ -272,42 +268,36 @@ bigint ReaderNative::read_header(double box[3][3], int &boxinfo, int &triclinic,
|
|||
if (fieldindex[i] == nwords) fieldindex[i] = -1;
|
||||
|
||||
} else if (fieldtype[i] == VX)
|
||||
fieldindex[i] = find_label("vx",nwords,labels);
|
||||
fieldindex[i] = find_label("vx", labels);
|
||||
else if (fieldtype[i] == VY)
|
||||
fieldindex[i] = find_label("vy",nwords,labels);
|
||||
fieldindex[i] = find_label("vy", labels);
|
||||
else if (fieldtype[i] == VZ)
|
||||
fieldindex[i] = find_label("vz",nwords,labels);
|
||||
fieldindex[i] = find_label("vz", labels);
|
||||
|
||||
else if (fieldtype[i] == FX)
|
||||
fieldindex[i] = find_label("fx",nwords,labels);
|
||||
fieldindex[i] = find_label("fx", labels);
|
||||
else if (fieldtype[i] == FY)
|
||||
fieldindex[i] = find_label("fy",nwords,labels);
|
||||
fieldindex[i] = find_label("fy", labels);
|
||||
else if (fieldtype[i] == FZ)
|
||||
fieldindex[i] = find_label("fz",nwords,labels);
|
||||
fieldindex[i] = find_label("fz", labels);
|
||||
|
||||
else if (fieldtype[i] == Q)
|
||||
fieldindex[i] = find_label("q",nwords,labels);
|
||||
fieldindex[i] = find_label("q", labels);
|
||||
|
||||
else if (fieldtype[i] == IX)
|
||||
fieldindex[i] = find_label("ix",nwords,labels);
|
||||
fieldindex[i] = find_label("ix", labels);
|
||||
else if (fieldtype[i] == IY)
|
||||
fieldindex[i] = find_label("iy",nwords,labels);
|
||||
fieldindex[i] = find_label("iy", labels);
|
||||
else if (fieldtype[i] == IZ)
|
||||
fieldindex[i] = find_label("iz",nwords,labels);
|
||||
fieldindex[i] = find_label("iz", labels);
|
||||
}
|
||||
|
||||
delete [] labels;
|
||||
|
||||
// set fieldflag = -1 if any unfound fields
|
||||
|
||||
fieldflag = 0;
|
||||
for (int i = 0; i < nfield; i++)
|
||||
if (fieldindex[i] < 0) fieldflag = -1;
|
||||
|
||||
// create internal vector of word ptrs for future parsing of per-atom lines
|
||||
|
||||
words = new char*[nwords];
|
||||
|
||||
return natoms;
|
||||
}
|
||||
|
||||
|
@ -328,15 +318,14 @@ void ReaderNative::read_atoms(int n, int nfield, double **fields)
|
|||
if (eof == NULL) error->one(FLERR,"Unexpected end of dump file");
|
||||
|
||||
// tokenize the line
|
||||
std::vector<std::string> words = Tokenizer(line).as_vector();
|
||||
|
||||
words[0] = strtok(line," \t\n\r\f");
|
||||
for (m = 1; m < nwords; m++)
|
||||
words[m] = strtok(NULL," \t\n\r\f");
|
||||
if (words.size() < nwords) error->one(FLERR,"Insufficient columns in dump file");
|
||||
|
||||
// convert selected fields to floats
|
||||
|
||||
for (m = 0; m < nfield; m++)
|
||||
fields[i][m] = atof(words[fieldindex[m]]);
|
||||
fields[i][m] = atof(words[fieldindex[m]].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -345,10 +334,12 @@ void ReaderNative::read_atoms(int n, int nfield, double **fields)
|
|||
return index of match or -1 if no match
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int ReaderNative::find_label(const char *label, int n, char **labels)
|
||||
int ReaderNative::find_label(const std::string & label, const std::map<std::string, int> & labels)
|
||||
{
|
||||
for (int i = 0; i < n; i++)
|
||||
if (strcmp(label,labels[i]) == 0) return i;
|
||||
auto it = labels.find(label);
|
||||
if (it != labels.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,9 @@ ReaderStyle(native,ReaderNative)
|
|||
#define LMP_READER_NATIVE_H
|
||||
|
||||
#include "reader.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
|
@ -41,10 +44,9 @@ private:
|
|||
char *line; // line read from dump file
|
||||
|
||||
int nwords; // # of per-atom columns in dump file
|
||||
char **words; // ptrs to values in parsed per-atom line
|
||||
int *fieldindex; //
|
||||
|
||||
int find_label(const char *, int, char **);
|
||||
int find_label(const std::string & label, const std::map<std::string, int> & labels);
|
||||
void read_lines(int);
|
||||
};
|
||||
|
||||
|
|
180
src/thermo.cpp
180
src/thermo.cpp
|
@ -46,6 +46,7 @@
|
|||
#include "math_const.h"
|
||||
#include "utils.h"
|
||||
#include "fmt/format.h"
|
||||
#include "tokenizer.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
@ -226,37 +227,36 @@ void Thermo::init()
|
|||
// add '/n' every 3 values if lineflag = MULTILINE
|
||||
// add trailing '/n' to last value
|
||||
|
||||
char *format_line = NULL;
|
||||
ValueTokenizer * format_line = nullptr;
|
||||
if (format_line_user) {
|
||||
int n = strlen(format_line_user) + 1;
|
||||
format_line = new char[n];
|
||||
strcpy(format_line,format_line_user);
|
||||
format_line = new ValueTokenizer(format_line_user);
|
||||
}
|
||||
|
||||
char *ptr,*format_line_ptr;
|
||||
const char *ptr = nullptr;
|
||||
std::string format_line_user_def;
|
||||
for (i = 0; i < nfield; i++) {
|
||||
|
||||
format[i][0] = '\0';
|
||||
if (lineflag == MULTILINE && i % 3 == 0) strcat(format[i],"\n");
|
||||
|
||||
if (format_line) {
|
||||
if (i == 0) format_line_ptr = strtok(format_line," \0");
|
||||
else format_line_ptr = strtok(NULL," \0");
|
||||
if (format_line_user) {
|
||||
format_line_user_def = format_line->next_string();
|
||||
}
|
||||
|
||||
if (format_column_user[i]) ptr = format_column_user[i];
|
||||
else if (vtype[i] == FLOAT) {
|
||||
if (format_float_user) ptr = format_float_user;
|
||||
else if (format_line_user) ptr = format_line_ptr;
|
||||
else if (format_line_user) ptr = format_line_user_def.c_str();
|
||||
else if (lineflag == ONELINE) ptr = format_float_one_def;
|
||||
else if (lineflag == MULTILINE) ptr = format_float_multi_def;
|
||||
} else if (vtype[i] == INT) {
|
||||
if (format_int_user) ptr = format_int_user;
|
||||
else if (format_line_user) ptr = format_line_ptr;
|
||||
else if (format_line_user) ptr = format_line_user_def.c_str();
|
||||
else if (lineflag == ONELINE) ptr = format_int_one_def;
|
||||
else if (lineflag == MULTILINE) ptr = format_int_multi_def;
|
||||
} else if (vtype[i] == BIGINT) {
|
||||
if (format_bigint_user) ptr = format_bigint_user;
|
||||
else if (format_line_user) ptr = format_line_ptr;
|
||||
else if (format_line_user) ptr = format_line_user_def.c_str();
|
||||
else if (lineflag == ONELINE) ptr = format_bigint_one_def;
|
||||
else if (lineflag == MULTILINE) ptr = format_bigint_multi_def;
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ void Thermo::init()
|
|||
}
|
||||
strcat(format[nfield-1],"\n");
|
||||
|
||||
delete [] format_line;
|
||||
delete format_line;
|
||||
|
||||
// find current ptr for each Compute ID
|
||||
|
||||
|
@ -709,185 +709,186 @@ void Thermo::parse_fields(char *str)
|
|||
|
||||
// customize a new keyword by adding to if statement
|
||||
|
||||
char *word = strtok(str," \0");
|
||||
while (word) {
|
||||
ValueTokenizer keywords(str);
|
||||
while (keywords.has_next()) {
|
||||
std::string word = keywords.next_string();
|
||||
|
||||
if (strcmp(word,"step") == 0) {
|
||||
if (word == "step") {
|
||||
addfield("Step",&Thermo::compute_step,BIGINT);
|
||||
} else if (strcmp(word,"elapsed") == 0) {
|
||||
} else if (word == "elapsed") {
|
||||
addfield("Elapsed",&Thermo::compute_elapsed,BIGINT);
|
||||
} else if (strcmp(word,"elaplong") == 0) {
|
||||
} else if (word == "elaplong") {
|
||||
addfield("Elaplong",&Thermo::compute_elapsed_long,BIGINT);
|
||||
} else if (strcmp(word,"dt") == 0) {
|
||||
} else if (word == "dt") {
|
||||
addfield("Dt",&Thermo::compute_dt,FLOAT);
|
||||
} else if (strcmp(word,"time") == 0) {
|
||||
} else if (word == "time") {
|
||||
addfield("Time",&Thermo::compute_time,FLOAT);
|
||||
} else if (strcmp(word,"cpu") == 0) {
|
||||
} else if (word == "cpu") {
|
||||
addfield("CPU",&Thermo::compute_cpu,FLOAT);
|
||||
} else if (strcmp(word,"tpcpu") == 0) {
|
||||
} else if (word == "tpcpu") {
|
||||
addfield("T/CPU",&Thermo::compute_tpcpu,FLOAT);
|
||||
} else if (strcmp(word,"spcpu") == 0) {
|
||||
} else if (word == "spcpu") {
|
||||
addfield("S/CPU",&Thermo::compute_spcpu,FLOAT);
|
||||
} else if (strcmp(word,"cpuremain") == 0) {
|
||||
} else if (word == "cpuremain") {
|
||||
addfield("CPULeft",&Thermo::compute_cpuremain,FLOAT);
|
||||
} else if (strcmp(word,"part") == 0) {
|
||||
} else if (word == "part") {
|
||||
addfield("Part",&Thermo::compute_part,INT);
|
||||
} else if (strcmp(word,"timeremain") == 0) {
|
||||
} else if (word == "timeremain") {
|
||||
addfield("TimeoutLeft",&Thermo::compute_timeremain,FLOAT);
|
||||
|
||||
} else if (strcmp(word,"atoms") == 0) {
|
||||
} else if (word == "atoms") {
|
||||
addfield("Atoms",&Thermo::compute_atoms,BIGINT);
|
||||
} else if (strcmp(word,"temp") == 0) {
|
||||
} else if (word == "temp") {
|
||||
addfield("Temp",&Thermo::compute_temp,FLOAT);
|
||||
index_temp = add_compute(id_temp,SCALAR);
|
||||
} else if (strcmp(word,"press") == 0) {
|
||||
} else if (word == "press") {
|
||||
addfield("Press",&Thermo::compute_press,FLOAT);
|
||||
index_press_scalar = add_compute(id_press,SCALAR);
|
||||
} else if (strcmp(word,"pe") == 0) {
|
||||
} else if (word == "pe") {
|
||||
addfield("PotEng",&Thermo::compute_pe,FLOAT);
|
||||
index_pe = add_compute(id_pe,SCALAR);
|
||||
} else if (strcmp(word,"ke") == 0) {
|
||||
} else if (word == "ke") {
|
||||
addfield("KinEng",&Thermo::compute_ke,FLOAT);
|
||||
index_temp = add_compute(id_temp,SCALAR);
|
||||
} else if (strcmp(word,"etotal") == 0) {
|
||||
} else if (word == "etotal") {
|
||||
addfield("TotEng",&Thermo::compute_etotal,FLOAT);
|
||||
index_temp = add_compute(id_temp,SCALAR);
|
||||
index_pe = add_compute(id_pe,SCALAR);
|
||||
} else if (strcmp(word,"enthalpy") == 0) {
|
||||
} else if (word == "enthalpy") {
|
||||
addfield("Enthalpy",&Thermo::compute_enthalpy,FLOAT);
|
||||
index_temp = add_compute(id_temp,SCALAR);
|
||||
index_press_scalar = add_compute(id_press,SCALAR);
|
||||
index_pe = add_compute(id_pe,SCALAR);
|
||||
|
||||
} else if (strcmp(word,"evdwl") == 0) {
|
||||
} else if (word == "evdwl") {
|
||||
addfield("E_vdwl",&Thermo::compute_evdwl,FLOAT);
|
||||
index_pe = add_compute(id_pe,SCALAR);
|
||||
} else if (strcmp(word,"ecoul") == 0) {
|
||||
} else if (word == "ecoul") {
|
||||
addfield("E_coul",&Thermo::compute_ecoul,FLOAT);
|
||||
index_pe = add_compute(id_pe,SCALAR);
|
||||
} else if (strcmp(word,"epair") == 0) {
|
||||
} else if (word == "epair") {
|
||||
addfield("E_pair",&Thermo::compute_epair,FLOAT);
|
||||
index_pe = add_compute(id_pe,SCALAR);
|
||||
} else if (strcmp(word,"ebond") == 0) {
|
||||
} else if (word == "ebond") {
|
||||
addfield("E_bond",&Thermo::compute_ebond,FLOAT);
|
||||
index_pe = add_compute(id_pe,SCALAR);
|
||||
} else if (strcmp(word,"eangle") == 0) {
|
||||
} else if (word == "eangle") {
|
||||
addfield("E_angle",&Thermo::compute_eangle,FLOAT);
|
||||
index_pe = add_compute(id_pe,SCALAR);
|
||||
} else if (strcmp(word,"edihed") == 0) {
|
||||
} else if (word == "edihed") {
|
||||
addfield("E_dihed",&Thermo::compute_edihed,FLOAT);
|
||||
index_pe = add_compute(id_pe,SCALAR);
|
||||
} else if (strcmp(word,"eimp") == 0) {
|
||||
} else if (word == "eimp") {
|
||||
addfield("E_impro",&Thermo::compute_eimp,FLOAT);
|
||||
index_pe = add_compute(id_pe,SCALAR);
|
||||
} else if (strcmp(word,"emol") == 0) {
|
||||
} else if (word == "emol") {
|
||||
addfield("E_mol",&Thermo::compute_emol,FLOAT);
|
||||
index_pe = add_compute(id_pe,SCALAR);
|
||||
} else if (strcmp(word,"elong") == 0) {
|
||||
} else if (word == "elong") {
|
||||
addfield("E_long",&Thermo::compute_elong,FLOAT);
|
||||
index_pe = add_compute(id_pe,SCALAR);
|
||||
} else if (strcmp(word,"etail") == 0) {
|
||||
} else if (word == "etail") {
|
||||
addfield("E_tail",&Thermo::compute_etail,FLOAT);
|
||||
index_pe = add_compute(id_pe,SCALAR);
|
||||
|
||||
} else if (strcmp(word,"vol") == 0) {
|
||||
} else if (word == "vol") {
|
||||
addfield("Volume",&Thermo::compute_vol,FLOAT);
|
||||
} else if (strcmp(word,"density") == 0) {
|
||||
} else if (word == "density") {
|
||||
addfield("Density",&Thermo::compute_density,FLOAT);
|
||||
} else if (strcmp(word,"lx") == 0) {
|
||||
} else if (word == "lx") {
|
||||
addfield("Lx",&Thermo::compute_lx,FLOAT);
|
||||
} else if (strcmp(word,"ly") == 0) {
|
||||
} else if (word == "ly") {
|
||||
addfield("Ly",&Thermo::compute_ly,FLOAT);
|
||||
} else if (strcmp(word,"lz") == 0) {
|
||||
} else if (word == "lz") {
|
||||
addfield("Lz",&Thermo::compute_lz,FLOAT);
|
||||
|
||||
} else if (strcmp(word,"xlo") == 0) {
|
||||
} else if (word == "xlo") {
|
||||
addfield("Xlo",&Thermo::compute_xlo,FLOAT);
|
||||
} else if (strcmp(word,"xhi") == 0) {
|
||||
} else if (word == "xhi") {
|
||||
addfield("Xhi",&Thermo::compute_xhi,FLOAT);
|
||||
} else if (strcmp(word,"ylo") == 0) {
|
||||
} else if (word == "ylo") {
|
||||
addfield("Ylo",&Thermo::compute_ylo,FLOAT);
|
||||
} else if (strcmp(word,"yhi") == 0) {
|
||||
} else if (word == "yhi") {
|
||||
addfield("Yhi",&Thermo::compute_yhi,FLOAT);
|
||||
} else if (strcmp(word,"zlo") == 0) {
|
||||
} else if (word == "zlo") {
|
||||
addfield("Zlo",&Thermo::compute_zlo,FLOAT);
|
||||
} else if (strcmp(word,"zhi") == 0) {
|
||||
} else if (word == "zhi") {
|
||||
addfield("Zhi",&Thermo::compute_zhi,FLOAT);
|
||||
|
||||
} else if (strcmp(word,"xy") == 0) {
|
||||
} else if (word == "xy") {
|
||||
addfield("Xy",&Thermo::compute_xy,FLOAT);
|
||||
} else if (strcmp(word,"xz") == 0) {
|
||||
} else if (word == "xz") {
|
||||
addfield("Xz",&Thermo::compute_xz,FLOAT);
|
||||
} else if (strcmp(word,"yz") == 0) {
|
||||
} else if (word == "yz") {
|
||||
addfield("Yz",&Thermo::compute_yz,FLOAT);
|
||||
|
||||
} else if (strcmp(word,"xlat") == 0) {
|
||||
} else if (word == "xlat") {
|
||||
addfield("Xlat",&Thermo::compute_xlat,FLOAT);
|
||||
} else if (strcmp(word,"ylat") == 0) {
|
||||
} else if (word == "ylat") {
|
||||
addfield("Ylat",&Thermo::compute_ylat,FLOAT);
|
||||
} else if (strcmp(word,"zlat") == 0) {
|
||||
} else if (word == "zlat") {
|
||||
addfield("Zlat",&Thermo::compute_zlat,FLOAT);
|
||||
|
||||
} else if (strcmp(word,"bonds") == 0) {
|
||||
} else if (word == "bonds") {
|
||||
addfield("Bonds",&Thermo::compute_bonds,BIGINT);
|
||||
} else if (strcmp(word,"angles") == 0) {
|
||||
} else if (word == "angles") {
|
||||
addfield("Angles",&Thermo::compute_angles,BIGINT);
|
||||
} else if (strcmp(word,"dihedrals") == 0) {
|
||||
} else if (word == "dihedrals") {
|
||||
addfield("Diheds",&Thermo::compute_dihedrals,BIGINT);
|
||||
} else if (strcmp(word,"impropers") == 0) {
|
||||
} else if (word == "impropers") {
|
||||
addfield("Impros",&Thermo::compute_impropers,BIGINT);
|
||||
|
||||
} else if (strcmp(word,"pxx") == 0) {
|
||||
} else if (word == "pxx") {
|
||||
addfield("Pxx",&Thermo::compute_pxx,FLOAT);
|
||||
index_press_vector = add_compute(id_press,VECTOR);
|
||||
} else if (strcmp(word,"pyy") == 0) {
|
||||
} else if (word == "pyy") {
|
||||
addfield("Pyy",&Thermo::compute_pyy,FLOAT);
|
||||
index_press_vector = add_compute(id_press,VECTOR);
|
||||
} else if (strcmp(word,"pzz") == 0) {
|
||||
} else if (word == "pzz") {
|
||||
addfield("Pzz",&Thermo::compute_pzz,FLOAT);
|
||||
index_press_vector = add_compute(id_press,VECTOR);
|
||||
} else if (strcmp(word,"pxy") == 0) {
|
||||
} else if (word == "pxy") {
|
||||
addfield("Pxy",&Thermo::compute_pxy,FLOAT);
|
||||
index_press_vector = add_compute(id_press,VECTOR);
|
||||
} else if (strcmp(word,"pxz") == 0) {
|
||||
} else if (word == "pxz") {
|
||||
addfield("Pxz",&Thermo::compute_pxz,FLOAT);
|
||||
index_press_vector = add_compute(id_press,VECTOR);
|
||||
} else if (strcmp(word,"pyz") == 0) {
|
||||
} else if (word == "pyz") {
|
||||
addfield("Pyz",&Thermo::compute_pyz,FLOAT);
|
||||
index_press_vector = add_compute(id_press,VECTOR);
|
||||
|
||||
} else if (strcmp(word,"fmax") == 0) {
|
||||
} else if (word == "fmax") {
|
||||
addfield("Fmax",&Thermo::compute_fmax,FLOAT);
|
||||
} else if (strcmp(word,"fnorm") == 0) {
|
||||
} else if (word == "fnorm") {
|
||||
addfield("Fnorm",&Thermo::compute_fnorm,FLOAT);
|
||||
|
||||
} else if (strcmp(word,"nbuild") == 0) {
|
||||
} else if (word == "nbuild") {
|
||||
addfield("Nbuild",&Thermo::compute_nbuild,BIGINT);
|
||||
} else if (strcmp(word,"ndanger") == 0) {
|
||||
} else if (word == "ndanger") {
|
||||
addfield("Ndanger",&Thermo::compute_ndanger,BIGINT);
|
||||
|
||||
} else if (strcmp(word,"cella") == 0) {
|
||||
} else if (word == "cella") {
|
||||
addfield("Cella",&Thermo::compute_cella,FLOAT);
|
||||
} else if (strcmp(word,"cellb") == 0) {
|
||||
} else if (word == "cellb") {
|
||||
addfield("Cellb",&Thermo::compute_cellb,FLOAT);
|
||||
} else if (strcmp(word,"cellc") == 0) {
|
||||
} else if (word == "cellc") {
|
||||
addfield("Cellc",&Thermo::compute_cellc,FLOAT);
|
||||
} else if (strcmp(word,"cellalpha") == 0) {
|
||||
} else if (word == "cellalpha") {
|
||||
addfield("CellAlpha",&Thermo::compute_cellalpha,FLOAT);
|
||||
} else if (strcmp(word,"cellbeta") == 0) {
|
||||
} else if (word == "cellbeta") {
|
||||
addfield("CellBeta",&Thermo::compute_cellbeta,FLOAT);
|
||||
} else if (strcmp(word,"cellgamma") == 0) {
|
||||
} else if (word == "cellgamma") {
|
||||
addfield("CellGamma",&Thermo::compute_cellgamma,FLOAT);
|
||||
|
||||
// compute value = c_ID, fix value = f_ID, variable value = v_ID
|
||||
// count trailing [] and store int arguments
|
||||
|
||||
} else if ((strncmp(word,"c_",2) == 0) || (strncmp(word,"f_",2) == 0) ||
|
||||
(strncmp(word,"v_",2) == 0)) {
|
||||
} else if ((word.substr(0, 2) == "c_") || (word.substr(0, 2) == "f_") ||
|
||||
(word.substr(0, 2) == "v_")) {
|
||||
|
||||
int n = strlen(word);
|
||||
int n = word.length() - 1;
|
||||
char *id = new char[n];
|
||||
strcpy(id,&word[2]);
|
||||
strcpy(id, &word.c_str()[2]);
|
||||
|
||||
// parse zero or one or two trailing brackets from ID
|
||||
// argindex1,argindex2 = int inside each bracket pair, 0 if no bracket
|
||||
|
@ -929,12 +930,12 @@ void Thermo::parse_fields(char *str)
|
|||
}
|
||||
|
||||
if (argindex1[nfield] == 0)
|
||||
field2index[nfield] = add_compute(id,SCALAR);
|
||||
field2index[nfield] = add_compute(id, SCALAR);
|
||||
else if (argindex2[nfield] == 0)
|
||||
field2index[nfield] = add_compute(id,VECTOR);
|
||||
field2index[nfield] = add_compute(id, VECTOR);
|
||||
else
|
||||
field2index[nfield] = add_compute(id,ARRAY);
|
||||
addfield(word,&Thermo::compute_compute,FLOAT);
|
||||
field2index[nfield] = add_compute(id, ARRAY);
|
||||
addfield(word.c_str(), &Thermo::compute_compute, FLOAT);
|
||||
|
||||
} else if (word[0] == 'f') {
|
||||
n = modify->find_fix(id);
|
||||
|
@ -959,7 +960,7 @@ void Thermo::parse_fields(char *str)
|
|||
}
|
||||
|
||||
field2index[nfield] = add_fix(id);
|
||||
addfield(word,&Thermo::compute_fix,FLOAT);
|
||||
addfield(word.c_str(), &Thermo::compute_fix, FLOAT);
|
||||
|
||||
} else if (word[0] == 'v') {
|
||||
n = input->variable->find(id);
|
||||
|
@ -975,14 +976,13 @@ void Thermo::parse_fields(char *str)
|
|||
error->all(FLERR,"Thermo custom variable cannot have two indices");
|
||||
|
||||
field2index[nfield] = add_variable(id);
|
||||
addfield(word,&Thermo::compute_variable,FLOAT);
|
||||
addfield(word.c_str(), &Thermo::compute_variable, FLOAT);
|
||||
}
|
||||
|
||||
delete [] id;
|
||||
|
||||
} else error->all(FLERR,"Unknown keyword in thermo_style custom command");
|
||||
|
||||
word = strtok(NULL," \0");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "comm.h"
|
||||
#include "error.h"
|
||||
#include "force.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
|
@ -31,32 +32,6 @@
|
|||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
// convert a timespec ([[HH:]MM:]SS) to seconds
|
||||
// the strings "off" and "unlimited" result in -1;
|
||||
|
||||
static double timespec2seconds(char *timespec)
|
||||
{
|
||||
double vals[3];
|
||||
char *num;
|
||||
int i = 0;
|
||||
|
||||
// first handle allowed textual inputs
|
||||
if (strcmp(timespec,"off") == 0) return -1;
|
||||
if (strcmp(timespec,"unlimited") == 0) return -1;
|
||||
|
||||
vals[0] = vals[1] = vals[2] = 0;
|
||||
|
||||
num = strtok(timespec,":");
|
||||
while ((num != NULL) && (i < 3)) {
|
||||
vals[i] = atoi(num);
|
||||
++i;
|
||||
num = strtok(NULL,":");
|
||||
}
|
||||
|
||||
if (i == 3) return (vals[0]*60 + vals[1])*60 + vals[2];
|
||||
else if (i == 2) return vals[0]*60 + vals[1];
|
||||
else return vals[0];
|
||||
}
|
||||
|
||||
// Return the CPU time for the current process in seconds very
|
||||
// much in the same way as MPI_Wtime() returns the wall time.
|
||||
|
@ -297,7 +272,7 @@ void Timer::modify_params(int narg, char **arg)
|
|||
} else if (strcmp(arg[iarg],"timeout") == 0) {
|
||||
++iarg;
|
||||
if (iarg < narg) {
|
||||
_timeout = timespec2seconds(arg[iarg]);
|
||||
_timeout = utils::timespec2seconds(arg[iarg]);
|
||||
} else error->all(FLERR,"Illegal timers command");
|
||||
} else if (strcmp(arg[iarg],"every") == 0) {
|
||||
++iarg;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "tokenizer.h"
|
||||
#include "utils.h"
|
||||
#include <algorithm>
|
||||
#include "fmt/format.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
@ -51,6 +52,10 @@ void Tokenizer::reset() {
|
|||
start = text.find_first_not_of(separators);
|
||||
}
|
||||
|
||||
bool Tokenizer::contains(const std::string & str) const {
|
||||
return text.find(str) != std::string::npos;
|
||||
}
|
||||
|
||||
void Tokenizer::skip(int n) {
|
||||
for(int i = 0; i < n; ++i) {
|
||||
if(!has_next()) throw TokenizerException("No more tokens", "");
|
||||
|
@ -126,6 +131,10 @@ bool ValueTokenizer::has_next() const {
|
|||
return tokens.has_next();
|
||||
}
|
||||
|
||||
bool ValueTokenizer::contains(const std::string & value) const {
|
||||
return tokens.contains(value);
|
||||
}
|
||||
|
||||
std::string ValueTokenizer::next_string() {
|
||||
if (has_next()) {
|
||||
std::string value = tokens.next();
|
||||
|
|
|
@ -42,6 +42,7 @@ public:
|
|||
void reset();
|
||||
void skip(int n);
|
||||
bool has_next() const;
|
||||
bool contains(const std::string & str) const;
|
||||
std::string next();
|
||||
|
||||
size_t count();
|
||||
|
@ -89,7 +90,8 @@ public:
|
|||
double next_double();
|
||||
|
||||
bool has_next() const;
|
||||
void skip(int n);
|
||||
bool contains(const std::string & value) const;
|
||||
void skip(int ntokens);
|
||||
|
||||
size_t count();
|
||||
};
|
||||
|
|
|
@ -705,6 +705,38 @@ double utils::get_conversion_factor(const int property, const int conversion)
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
convert a timespec ([[HH:]MM:]SS) to seconds
|
||||
the strings "off" and "unlimited" result in -1.0;
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double utils::timespec2seconds(const std::string & timespec)
|
||||
{
|
||||
double vals[3];
|
||||
int i = 0;
|
||||
|
||||
// first handle allowed textual inputs
|
||||
if (timespec == "off") return -1.0;
|
||||
if (timespec == "unlimited") return -1.0;
|
||||
|
||||
vals[0] = vals[1] = vals[2] = 0;
|
||||
|
||||
ValueTokenizer values(timespec, ":");
|
||||
|
||||
try {
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (!values.has_next()) break;
|
||||
vals[i] = values.next_int();
|
||||
}
|
||||
} catch (TokenizerException & e) {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
if (i == 3) return (vals[0]*60 + vals[1])*60 + vals[2];
|
||||
else if (i == 2) return vals[0]*60 + vals[1];
|
||||
return vals[0];
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
extern "C" {
|
||||
|
|
|
@ -291,6 +291,14 @@ namespace LAMMPS_NS {
|
|||
* \return conversion factor
|
||||
*/
|
||||
double get_conversion_factor(const int property, const int conversion);
|
||||
|
||||
/**
|
||||
* \brief Convert a time string to seconds
|
||||
* The strings "off" and "unlimited" result in -1
|
||||
* \param timespec a string in the following format: ([[HH:]MM:]SS)
|
||||
* \return total in seconds
|
||||
*/
|
||||
double timespec2seconds(const std::string & timespec);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -90,9 +90,16 @@ int main(int narg, char **arg)
|
|||
FILE *fptxt = fopen(filetxt,"w");
|
||||
delete [] filetxt;
|
||||
|
||||
// detect newer format
|
||||
char * magic_string = nullptr;
|
||||
char * columns = nullptr;
|
||||
char * unit_style = nullptr;
|
||||
|
||||
// loop over snapshots in file
|
||||
|
||||
while (1) {
|
||||
int endian = 0x0001;
|
||||
int revision = 0x0001;
|
||||
|
||||
fread(&ntimestep,sizeof(bigint),1,fp);
|
||||
|
||||
|
@ -104,6 +111,26 @@ int main(int narg, char **arg)
|
|||
break;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
fread(&natoms,sizeof(bigint),1,fp);
|
||||
fread(&triclinic,sizeof(int),1,fp);
|
||||
fread(&boundary[0][0],6*sizeof(int),1,fp);
|
||||
|
@ -119,6 +146,39 @@ int main(int narg, char **arg)
|
|||
fread(&yz,sizeof(double),1,fp);
|
||||
}
|
||||
fread(&size_one,sizeof(int),1,fp);
|
||||
|
||||
if (magic_string && revision > 0x0001) {
|
||||
// newer format includes units string, columns string
|
||||
// and time
|
||||
int len = 0;
|
||||
fread(&len, sizeof(int), 1, fp);
|
||||
|
||||
if (len > 0) {
|
||||
// has units
|
||||
delete [] unit_style;
|
||||
unit_style = new char[len+1];
|
||||
fread(unit_style, sizeof(char), len, fp);
|
||||
unit_style[len+1] = '\0';
|
||||
fprintf(fptxt, "ITEM: UNITS\n");
|
||||
fprintf(fptxt, "%s\n", unit_style);
|
||||
}
|
||||
|
||||
char flag = 0;
|
||||
fread(&flag, sizeof(char), 1, fp);
|
||||
|
||||
if (flag) {
|
||||
double time;
|
||||
fread(&time, sizeof(double), 1, fp);
|
||||
fprintf(fptxt, "ITEM: TIME\n%.16g\n", time);
|
||||
}
|
||||
|
||||
fread(&len, sizeof(int), 1, fp);
|
||||
delete [] columns;
|
||||
columns = new char[len+1];
|
||||
fread(columns, sizeof(char), len, fp);
|
||||
columns[len+1] = '\0';
|
||||
}
|
||||
|
||||
fread(&nchunk,sizeof(int),1,fp);
|
||||
|
||||
fprintf(fptxt,"ITEM: TIMESTEP\n");
|
||||
|
@ -140,18 +200,20 @@ int main(int narg, char **arg)
|
|||
|
||||
if (!triclinic) {
|
||||
fprintf(fptxt,"ITEM: BOX BOUNDS %s\n",boundstr);
|
||||
fprintf(fptxt,"%g %g\n",xlo,xhi);
|
||||
fprintf(fptxt,"%g %g\n",ylo,yhi);
|
||||
fprintf(fptxt,"%g %g\n",zlo,zhi);
|
||||
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",zlo,zhi);
|
||||
} else {
|
||||
fprintf(fptxt,"ITEM: BOX BOUNDS %s xy xz yz\n",boundstr);
|
||||
fprintf(fptxt,"%g %g %g\n",xlo,xhi,xy);
|
||||
fprintf(fptxt,"%g %g %g\n",ylo,yhi,xz);
|
||||
fprintf(fptxt,"%g %g %g\n",zlo,zhi,yz);
|
||||
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",ylo,yhi,xz);
|
||||
fprintf(fptxt,"%-1.16e %-1.16e %-1.16e\n",zlo,zhi,yz);
|
||||
}
|
||||
fprintf(fptxt,"ITEM: ATOMS\n");
|
||||
|
||||
|
||||
if (columns)
|
||||
fprintf(fptxt,"ITEM: ATOMS %s\n", columns);
|
||||
else
|
||||
fprintf(fptxt,"ITEM: ATOMS\n");
|
||||
|
||||
// loop over processor chunks in file
|
||||
|
||||
|
@ -172,7 +234,13 @@ int main(int narg, char **arg)
|
|||
n /= size_one;
|
||||
m = 0;
|
||||
for (j = 0; j < n; j++) {
|
||||
for (k = 0; k < size_one; k++) fprintf(fptxt,"%g ",buf[m++]);
|
||||
for (k = 0; k < size_one; k++) {
|
||||
if(k+1 < size_one) {
|
||||
fprintf(fptxt,"%g ",buf[m++]);
|
||||
} else {
|
||||
fprintf(fptxt,"%g",buf[m++]);
|
||||
}
|
||||
}
|
||||
fprintf(fptxt,"\n");
|
||||
}
|
||||
}
|
||||
|
@ -181,6 +249,12 @@ int main(int narg, char **arg)
|
|||
fflush(stdout);
|
||||
}
|
||||
printf("\n");
|
||||
delete [] columns;
|
||||
delete [] magic_string;
|
||||
delete [] unit_style;
|
||||
columns = nullptr;
|
||||
magic_string = nullptr;
|
||||
unit_style = nullptr;
|
||||
}
|
||||
|
||||
if (buf) delete [] buf;
|
||||
|
|
|
@ -23,3 +23,23 @@ endif()
|
|||
add_executable(test_file_operations test_file_operations.cpp)
|
||||
target_link_libraries(test_file_operations PRIVATE lammps GTest::GMock GTest::GTest)
|
||||
add_test(NAME FileOperations COMMAND test_file_operations WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_executable(test_dump_atom test_dump_atom.cpp)
|
||||
target_link_libraries(test_dump_atom PRIVATE lammps GTest::GMock GTest::GTest)
|
||||
add_test(NAME DumpAtom COMMAND test_dump_atom WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set_tests_properties(DumpAtom PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}")
|
||||
|
||||
add_executable(test_dump_custom test_dump_custom.cpp)
|
||||
target_link_libraries(test_dump_custom PRIVATE lammps GTest::GMock GTest::GTest)
|
||||
add_test(NAME DumpCustom COMMAND test_dump_custom WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set_tests_properties(DumpCustom PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}")
|
||||
|
||||
add_executable(test_dump_cfg test_dump_cfg.cpp)
|
||||
target_link_libraries(test_dump_cfg PRIVATE lammps GTest::GMock GTest::GTest)
|
||||
add_test(NAME DumpCfg COMMAND test_dump_cfg WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set_tests_properties(DumpCfg PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}")
|
||||
|
||||
if (BUILD_TOOLS)
|
||||
set_tests_properties(DumpAtom PROPERTIES ENVIRONMENT "BINARY2TXT_BINARY=$<TARGET_FILE:binary2txt>")
|
||||
set_tests_properties(DumpCustom PROPERTIES ENVIRONMENT "BINARY2TXT_BINARY=$<TARGET_FILE:binary2txt>")
|
||||
endif()
|
||||
|
|
|
@ -0,0 +1,600 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "fmt/format.h"
|
||||
#include "utils.h"
|
||||
#include "../testing/core.h"
|
||||
#include "../testing/systems/melt.h"
|
||||
#include "../testing/utils.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
using ::testing::Eq;
|
||||
|
||||
char * BINARY2TXT_BINARY = nullptr;
|
||||
|
||||
class DumpAtomTest : public MeltTest {
|
||||
std::string dump_style = "atom";
|
||||
public:
|
||||
void enable_triclinic() {
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
command("change_box all triclinic");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
}
|
||||
|
||||
void generate_dump(std::string dump_file, std::string dump_modify_options, int ntimesteps) {
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
command(fmt::format("dump id all {} 1 {}", dump_style, dump_file));
|
||||
|
||||
if (!dump_modify_options.empty()) {
|
||||
command(fmt::format("dump_modify id {}", dump_modify_options));
|
||||
}
|
||||
|
||||
command(fmt::format("run {}", ntimesteps));
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
}
|
||||
|
||||
void generate_text_and_binary_dump(std::string text_file, std::string binary_file, std::string dump_modify_options, int ntimesteps) {
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
command(fmt::format("dump id0 all {} 1 {}", dump_style, text_file));
|
||||
command(fmt::format("dump id1 all {} 1 {}", dump_style, binary_file));
|
||||
|
||||
if (!dump_modify_options.empty()) {
|
||||
command(fmt::format("dump_modify id0 {}", dump_modify_options));
|
||||
command(fmt::format("dump_modify id1 {}", dump_modify_options));
|
||||
}
|
||||
|
||||
command(fmt::format("run {}", ntimesteps));
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
}
|
||||
|
||||
std::string convert_binary_to_text(std::string binary_file) {
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
std::string cmdline = fmt::format("{} {}", BINARY2TXT_BINARY, binary_file);
|
||||
system(cmdline.c_str());
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
return fmt::format("{}.txt", binary_file);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(DumpAtomTest, run0)
|
||||
{
|
||||
auto dump_file = "dump_run0.melt";
|
||||
generate_dump(dump_file, "scale yes image no", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 41);
|
||||
ASSERT_THAT(lines[4], Eq("ITEM: BOX BOUNDS pp pp pp"));
|
||||
ASSERT_EQ(utils::split_words(lines[5]).size(), 2);
|
||||
ASSERT_THAT(lines[8], Eq("ITEM: ATOMS id type xs ys zs"));
|
||||
ASSERT_EQ(utils::split_words(lines[9]).size(), 5);
|
||||
ASSERT_THAT(lines[9], Eq("1 1 0 0 0"));
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, format_line_run0)
|
||||
{
|
||||
auto dump_file = "dump_format_line_run0.melt";
|
||||
generate_dump(dump_file, "format line \"%d %d %20.15g %g %g\" scale yes image no", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 41);
|
||||
ASSERT_THAT(lines[4], Eq("ITEM: BOX BOUNDS pp pp pp"));
|
||||
ASSERT_EQ(utils::split_words(lines[5]).size(), 2);
|
||||
ASSERT_THAT(lines[8], Eq("ITEM: ATOMS id type xs ys zs"));
|
||||
ASSERT_EQ(utils::split_words(lines[9]).size(), 5);
|
||||
ASSERT_THAT(lines[9], Eq("1 1 0 0 0"));
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, no_scale_run0)
|
||||
{
|
||||
auto dump_file = "dump_no_scale_run0.melt";
|
||||
generate_dump(dump_file, "scale no", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 41);
|
||||
ASSERT_THAT(lines[4], Eq("ITEM: BOX BOUNDS pp pp pp"));
|
||||
ASSERT_EQ(utils::split_words(lines[5]).size(), 2);
|
||||
ASSERT_THAT(lines[8], Eq("ITEM: ATOMS id type x y z"));
|
||||
ASSERT_EQ(utils::split_words(lines[9]).size(), 5);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, no_buffer_no_scale_run0)
|
||||
{
|
||||
auto dump_file = "dump_no_buffer_no_scale_run0.melt";
|
||||
generate_dump(dump_file, "scale no", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 41);
|
||||
ASSERT_THAT(lines[4], Eq("ITEM: BOX BOUNDS pp pp pp"));
|
||||
ASSERT_EQ(utils::split_words(lines[5]).size(), 2);
|
||||
ASSERT_THAT(lines[8], Eq("ITEM: ATOMS id type x y z"));
|
||||
ASSERT_EQ(utils::split_words(lines[9]).size(), 5);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, no_buffer_with_scale_run0)
|
||||
{
|
||||
auto dump_file = "dump_no_buffer_with_scale_run0.melt";
|
||||
generate_dump(dump_file, "buffer no scale yes", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 41);
|
||||
ASSERT_THAT(lines[4], Eq("ITEM: BOX BOUNDS pp pp pp"));
|
||||
ASSERT_EQ(utils::split_words(lines[5]).size(), 2);
|
||||
ASSERT_THAT(lines[8], Eq("ITEM: ATOMS id type xs ys zs"));
|
||||
ASSERT_EQ(utils::split_words(lines[9]).size(), 5);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, with_image_run0)
|
||||
{
|
||||
auto dump_file = "dump_with_image_run0.melt";
|
||||
generate_dump(dump_file, "scale no image yes", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 41);
|
||||
ASSERT_THAT(lines[8], Eq("ITEM: ATOMS id type x y z ix iy iz"));
|
||||
ASSERT_EQ(utils::split_words(lines[9]).size(), 8);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, with_units_run0)
|
||||
{
|
||||
auto dump_file = "dump_with_units_run0.melt";
|
||||
generate_dump(dump_file, "scale no units yes", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 43);
|
||||
ASSERT_THAT(lines[0], Eq("ITEM: UNITS"));
|
||||
ASSERT_THAT(lines[1], Eq("lj"));
|
||||
ASSERT_THAT(lines[10], Eq("ITEM: ATOMS id type x y z"));
|
||||
ASSERT_EQ(utils::split_words(lines[11]).size(), 5);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, with_time_run0)
|
||||
{
|
||||
auto dump_file = "dump_with_time_run0.melt";
|
||||
generate_dump(dump_file, "scale no time yes", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 43);
|
||||
ASSERT_THAT(lines[0], Eq("ITEM: TIME"));
|
||||
ASSERT_THAT(lines[10], Eq("ITEM: ATOMS id type x y z"));
|
||||
ASSERT_EQ(utils::split_words(lines[11]).size(), 5);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, with_units_run1)
|
||||
{
|
||||
auto dump_file = "dump_with_units_run1.melt";
|
||||
generate_dump(dump_file, "scale no units yes", 1);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 84);
|
||||
ASSERT_THAT(lines[0], Eq("ITEM: UNITS"));
|
||||
ASSERT_THAT(lines[1], Eq("lj"));
|
||||
ASSERT_THAT(lines[10], Eq("ITEM: ATOMS id type x y z"));
|
||||
ASSERT_EQ(utils::split_words(lines[11]).size(), 5);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, no_buffer_with_scale_and_image_run0)
|
||||
{
|
||||
auto dump_file = "dump_no_buffer_with_scale_and_image_run0.melt";
|
||||
generate_dump(dump_file, "buffer no scale yes image yes", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 41);
|
||||
ASSERT_THAT(lines[4], Eq("ITEM: BOX BOUNDS pp pp pp"));
|
||||
ASSERT_EQ(utils::split_words(lines[5]).size(), 2);
|
||||
ASSERT_THAT(lines[8], Eq("ITEM: ATOMS id type xs ys zs ix iy iz"));
|
||||
ASSERT_EQ(utils::split_words(lines[9]).size(), 8);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
TEST_F(DumpAtomTest, triclinic_run0)
|
||||
{
|
||||
auto dump_file = "dump_triclinic_run0.melt";
|
||||
enable_triclinic();
|
||||
generate_dump(dump_file, "", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 41);
|
||||
ASSERT_THAT(lines[4], Eq("ITEM: BOX BOUNDS xy xz yz pp pp pp"));
|
||||
ASSERT_EQ(utils::split_words(lines[5]).size(), 3);
|
||||
ASSERT_THAT(lines[8], Eq("ITEM: ATOMS id type xs ys zs"));
|
||||
ASSERT_EQ(utils::split_words(lines[9]).size(), 5);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, triclinic_with_units_run0)
|
||||
{
|
||||
auto dump_file = "dump_triclinic_with_units_run0.melt";
|
||||
enable_triclinic();
|
||||
generate_dump(dump_file, "units yes", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 43);
|
||||
ASSERT_THAT(lines[0], Eq("ITEM: UNITS"));
|
||||
ASSERT_THAT(lines[1], Eq("lj"));
|
||||
ASSERT_THAT(lines[6], Eq("ITEM: BOX BOUNDS xy xz yz pp pp pp"));
|
||||
ASSERT_EQ(utils::split_words(lines[7]).size(), 3);
|
||||
ASSERT_THAT(lines[10], Eq("ITEM: ATOMS id type xs ys zs"));
|
||||
ASSERT_EQ(utils::split_words(lines[11]).size(), 5);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, triclinic_with_time_run0)
|
||||
{
|
||||
auto dump_file = "dump_triclinic_with_time_run0.melt";
|
||||
enable_triclinic();
|
||||
generate_dump(dump_file, "time yes", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 43);
|
||||
ASSERT_THAT(lines[0], Eq("ITEM: TIME"));
|
||||
ASSERT_THAT(lines[6], Eq("ITEM: BOX BOUNDS xy xz yz pp pp pp"));
|
||||
ASSERT_EQ(utils::split_words(lines[7]).size(), 3);
|
||||
ASSERT_THAT(lines[10], Eq("ITEM: ATOMS id type xs ys zs"));
|
||||
ASSERT_EQ(utils::split_words(lines[11]).size(), 5);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, triclinic_with_image_run0)
|
||||
{
|
||||
auto dump_file = "dump_triclinic_with_image_run0.melt";
|
||||
enable_triclinic();
|
||||
generate_dump(dump_file, "image yes", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 41);
|
||||
ASSERT_THAT(lines[4], Eq("ITEM: BOX BOUNDS xy xz yz pp pp pp"));
|
||||
ASSERT_EQ(utils::split_words(lines[5]).size(), 3);
|
||||
ASSERT_THAT(lines[8], Eq("ITEM: ATOMS id type xs ys zs ix iy iz"));
|
||||
ASSERT_EQ(utils::split_words(lines[9]).size(), 8);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// binary formats
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
TEST_F(DumpAtomTest, binary_run0)
|
||||
{
|
||||
if(!BINARY2TXT_BINARY) GTEST_SKIP();
|
||||
|
||||
auto text_file = "dump_text_run0.melt";
|
||||
auto binary_file = "dump_binary_run0.melt.bin";
|
||||
|
||||
generate_text_and_binary_dump(text_file, binary_file, "", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(text_file);
|
||||
ASSERT_FILE_EXISTS(binary_file);
|
||||
|
||||
auto converted_file = convert_binary_to_text(binary_file);
|
||||
|
||||
ASSERT_FILE_EXISTS(converted_file);
|
||||
ASSERT_FILE_EQUAL(text_file, converted_file);
|
||||
delete_file(text_file);
|
||||
delete_file(binary_file);
|
||||
delete_file(converted_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, binary_with_units_run0)
|
||||
{
|
||||
if(!BINARY2TXT_BINARY) GTEST_SKIP();
|
||||
|
||||
auto text_file = "dump_text_with_units_run0.melt";
|
||||
auto binary_file = "dump_binary_with_units_run0.melt.bin";
|
||||
|
||||
generate_text_and_binary_dump(text_file, binary_file, "scale no units yes", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(text_file);
|
||||
ASSERT_FILE_EXISTS(binary_file);
|
||||
|
||||
auto converted_file = convert_binary_to_text(binary_file);
|
||||
|
||||
ASSERT_FILE_EXISTS(converted_file);
|
||||
ASSERT_FILE_EQUAL(text_file, converted_file);
|
||||
delete_file(text_file);
|
||||
delete_file(binary_file);
|
||||
delete_file(converted_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, binary_with_time_run0)
|
||||
{
|
||||
if(!BINARY2TXT_BINARY) GTEST_SKIP();
|
||||
|
||||
auto text_file = "dump_text_with_time_run0.melt";
|
||||
auto binary_file = "dump_binary_with_time_run0.melt.bin";
|
||||
|
||||
generate_text_and_binary_dump(text_file, binary_file, "scale no time yes", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(text_file);
|
||||
ASSERT_FILE_EXISTS(binary_file);
|
||||
|
||||
auto converted_file = convert_binary_to_text(binary_file);
|
||||
|
||||
ASSERT_FILE_EXISTS(converted_file);
|
||||
ASSERT_FILE_EQUAL(text_file, converted_file);
|
||||
delete_file(text_file);
|
||||
delete_file(binary_file);
|
||||
delete_file(converted_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, binary_triclinic_run0)
|
||||
{
|
||||
if(!BINARY2TXT_BINARY) GTEST_SKIP();
|
||||
|
||||
auto text_file = "dump_text_tri_run0.melt";
|
||||
auto binary_file = "dump_binary_tri_run0.melt.bin";
|
||||
|
||||
enable_triclinic();
|
||||
generate_text_and_binary_dump(text_file, binary_file, "", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(text_file);
|
||||
ASSERT_FILE_EXISTS(binary_file);
|
||||
|
||||
auto converted_file = convert_binary_to_text(binary_file);
|
||||
|
||||
ASSERT_FILE_EXISTS(converted_file);
|
||||
ASSERT_FILE_EQUAL(text_file, converted_file);
|
||||
delete_file(text_file);
|
||||
delete_file(binary_file);
|
||||
delete_file(converted_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, binary_triclinic_with_units_run0)
|
||||
{
|
||||
if(!BINARY2TXT_BINARY) GTEST_SKIP();
|
||||
|
||||
auto text_file = "dump_text_tri_with_units_run0.melt";
|
||||
auto binary_file = "dump_binary_tri_with_units_run0.melt.bin";
|
||||
|
||||
enable_triclinic();
|
||||
generate_text_and_binary_dump(text_file, binary_file, "scale no units yes", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(text_file);
|
||||
ASSERT_FILE_EXISTS(binary_file);
|
||||
|
||||
auto converted_file = convert_binary_to_text(binary_file);
|
||||
|
||||
ASSERT_FILE_EXISTS(converted_file);
|
||||
ASSERT_FILE_EQUAL(text_file, converted_file);
|
||||
delete_file(text_file);
|
||||
delete_file(binary_file);
|
||||
delete_file(converted_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, binary_triclinic_with_time_run0)
|
||||
{
|
||||
if(!BINARY2TXT_BINARY) GTEST_SKIP();
|
||||
|
||||
auto text_file = "dump_text_tri_with_time_run0.melt";
|
||||
auto binary_file = "dump_binary_tri_with_time_run0.melt.bin";
|
||||
|
||||
enable_triclinic();
|
||||
generate_text_and_binary_dump(text_file, binary_file, "scale no time yes", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(text_file);
|
||||
ASSERT_FILE_EXISTS(binary_file);
|
||||
|
||||
auto converted_file = convert_binary_to_text(binary_file);
|
||||
|
||||
ASSERT_FILE_EXISTS(converted_file);
|
||||
ASSERT_FILE_EQUAL(text_file, converted_file);
|
||||
delete_file(text_file);
|
||||
delete_file(binary_file);
|
||||
delete_file(converted_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, binary_triclinic_with_image_run0)
|
||||
{
|
||||
if(!BINARY2TXT_BINARY) GTEST_SKIP();
|
||||
|
||||
auto text_file = "dump_text_tri_with_image_run0.melt";
|
||||
auto binary_file = "dump_binary_tri_with_image_run0.melt.bin";
|
||||
|
||||
enable_triclinic();
|
||||
generate_text_and_binary_dump(text_file, binary_file, "image yes", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(text_file);
|
||||
ASSERT_FILE_EXISTS(binary_file);
|
||||
|
||||
auto converted_file = convert_binary_to_text(binary_file);
|
||||
|
||||
ASSERT_FILE_EXISTS(converted_file);
|
||||
ASSERT_FILE_EQUAL(text_file, converted_file);
|
||||
delete_file(text_file);
|
||||
delete_file(binary_file);
|
||||
delete_file(converted_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, run1)
|
||||
{
|
||||
auto dump_file = "dump_run1.melt";
|
||||
generate_dump(dump_file, "", 1);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
ASSERT_EQ(count_lines(dump_file), 82);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, run2)
|
||||
{
|
||||
auto dump_file = "dump_run2.melt";
|
||||
generate_dump(dump_file, "", 2);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
ASSERT_EQ(count_lines(dump_file), 123);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, multi_file_run1)
|
||||
{
|
||||
auto dump_file = "dump_run1_*.melt";
|
||||
generate_dump(dump_file, "", 1);
|
||||
|
||||
ASSERT_FILE_EXISTS("dump_run1_0.melt");
|
||||
ASSERT_FILE_EXISTS("dump_run1_1.melt");
|
||||
ASSERT_EQ(count_lines("dump_run1_0.melt"), 41);
|
||||
ASSERT_EQ(count_lines("dump_run1_1.melt"), 41);
|
||||
delete_file("dump_run1_0.melt");
|
||||
delete_file("dump_run1_1.melt");
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, per_processor_file_run1)
|
||||
{
|
||||
auto dump_file = "dump_run1_p%.melt";
|
||||
generate_dump(dump_file, "", 1);
|
||||
|
||||
ASSERT_FILE_EXISTS("dump_run1_p0.melt");
|
||||
ASSERT_EQ(count_lines("dump_run1_p0.melt"), 82);
|
||||
delete_file("dump_run1_p0.melt");
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, per_processor_multi_file_run1)
|
||||
{
|
||||
auto dump_file = "dump_run1_p%_*.melt";
|
||||
generate_dump(dump_file, "", 1);
|
||||
|
||||
ASSERT_FILE_EXISTS("dump_run1_p0_0.melt");
|
||||
ASSERT_FILE_EXISTS("dump_run1_p0_1.melt");
|
||||
ASSERT_EQ(count_lines("dump_run1_p0_0.melt"), 41);
|
||||
ASSERT_EQ(count_lines("dump_run1_p0_1.melt"), 41);
|
||||
delete_file("dump_run1_p0_0.melt");
|
||||
delete_file("dump_run1_p0_1.melt");
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, dump_modify_scale_invalid)
|
||||
{
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
command("dump id all atom 1 dump.txt");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
TEST_FAILURE(".*Illegal dump_modify command.*",
|
||||
command("dump_modify id scale true"););
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, dump_modify_image_invalid)
|
||||
{
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
command("dump id all atom 1 dump.txt");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
TEST_FAILURE(".*Illegal dump_modify command.*",
|
||||
command("dump_modify id image true"););
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, dump_modify_invalid)
|
||||
{
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
command("dump id all atom 1 dump.txt");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
TEST_FAILURE(".*Illegal dump_modify command.*",
|
||||
command("dump_modify id true"););
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, write_dump)
|
||||
{
|
||||
auto reference = "dump_ref_run0.melt";
|
||||
auto dump_file = "write_dump_atom_run0.melt";
|
||||
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
command(fmt::format("dump id all atom 1 {}", reference));
|
||||
command("dump_modify id scale no units yes");
|
||||
command("run 0");
|
||||
command("write_dump all atom write_dump_atom_run*.melt modify scale no units yes");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
ASSERT_FILE_EXISTS(reference);
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
|
||||
ASSERT_FILE_EQUAL(reference, dump_file);
|
||||
delete_file(reference);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpAtomTest, binary_write_dump)
|
||||
{
|
||||
if(!BINARY2TXT_BINARY) GTEST_SKIP();
|
||||
|
||||
auto reference = "dump_run0.melt.bin";
|
||||
auto dump_file = "write_dump_atom_run0_p0.melt.bin";
|
||||
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
command(fmt::format("dump id all atom 1 {}", reference));
|
||||
command("dump_modify id scale no units yes");
|
||||
command("run 0");
|
||||
command("write_dump all atom write_dump_atom_run*_p%.melt.bin modify scale no units yes");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
ASSERT_FILE_EXISTS(reference);
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
|
||||
auto reference_txt = convert_binary_to_text(reference);
|
||||
auto dump_file_txt = convert_binary_to_text(dump_file);
|
||||
|
||||
ASSERT_FILE_EXISTS(reference_txt);
|
||||
ASSERT_FILE_EXISTS(dump_file_txt);
|
||||
|
||||
ASSERT_FILE_EQUAL(reference_txt, dump_file_txt);
|
||||
delete_file(reference_txt);
|
||||
delete_file(dump_file_txt);
|
||||
delete_file(reference);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
MPI_Init(&argc, &argv);
|
||||
::testing::InitGoogleMock(&argc, argv);
|
||||
|
||||
// handle arguments passed via environment variable
|
||||
if (const char *var = getenv("TEST_ARGS")) {
|
||||
std::vector<std::string> env = utils::split_words(var);
|
||||
for (auto arg : env) {
|
||||
if (arg == "-v") {
|
||||
verbose = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BINARY2TXT_BINARY = getenv("BINARY2TXT_BINARY");
|
||||
|
||||
if ((argc > 1) && (strcmp(argv[1], "-v") == 0)) verbose = true;
|
||||
|
||||
int rv = RUN_ALL_TESTS();
|
||||
MPI_Finalize();
|
||||
return rv;
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "fmt/format.h"
|
||||
#include "utils.h"
|
||||
#include "../testing/core.h"
|
||||
#include "../testing/systems/melt.h"
|
||||
#include "../testing/utils.h"
|
||||
|
||||
using ::testing::Eq;
|
||||
|
||||
class DumpCfgTest : public MeltTest {
|
||||
std::string dump_style = "cfg";
|
||||
public:
|
||||
void generate_dump(std::string dump_file, std::string fields, std::string dump_modify_options, int ntimesteps) {
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
command(fmt::format("dump id all {} 1 {} {}", dump_style, dump_file, fields));
|
||||
|
||||
if (!dump_modify_options.empty()) {
|
||||
command(fmt::format("dump_modify id {}", dump_modify_options));
|
||||
}
|
||||
|
||||
command(fmt::format("run {}", ntimesteps));
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(DumpCfgTest, invalid_options)
|
||||
{
|
||||
TEST_FAILURE(".*Dump cfg arguments must start with 'mass type xs ys zs'.*",
|
||||
command("dump id all cfg 1 dump.cfg id type proc procp1 mass x y z");
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(DumpCfgTest, require_multifile)
|
||||
{
|
||||
auto dump_file = "dump_melt_run.cfg";
|
||||
auto fields = "mass type xs ys zs id proc procp1 x y z ix iy iz xu yu zu xsu ysu zsu vx vy vz fx fy fz";
|
||||
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
command(fmt::format("dump id all cfg 1 {} {}", dump_file, fields));
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
TEST_FAILURE(".*Dump cfg requires one snapshot per file.*",
|
||||
command("run 0");
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(DumpCfgTest, run0)
|
||||
{
|
||||
auto dump_file = "dump_cfg_run*.melt";
|
||||
auto fields = "mass type xs ys zs id proc procp1 x y z ix iy iz vx vy vz fx fy fz";
|
||||
|
||||
generate_dump(dump_file, fields, "", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS("dump_cfg_run0.melt");
|
||||
auto lines = read_lines("dump_cfg_run0.melt");
|
||||
ASSERT_EQ(lines.size(), 124);
|
||||
ASSERT_THAT(lines[0], Eq("Number of particles = 32"));
|
||||
delete_file("dump_cfg_run0.melt");
|
||||
}
|
||||
|
||||
TEST_F(DumpCfgTest, unwrap_run0)
|
||||
{
|
||||
auto dump_file = "dump_cfg_unwrap_run*.melt";
|
||||
auto fields = "mass type xsu ysu zsu id proc procp1 x y z ix iy iz vx vy vz fx fy fz";
|
||||
|
||||
generate_dump(dump_file, fields, "", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS("dump_cfg_unwrap_run0.melt");
|
||||
auto lines = read_lines("dump_cfg_unwrap_run0.melt");
|
||||
ASSERT_EQ(lines.size(), 124);
|
||||
ASSERT_THAT(lines[0], Eq("Number of particles = 32"));
|
||||
delete_file("dump_cfg_unwrap_run0.melt");
|
||||
}
|
||||
|
||||
TEST_F(DumpCfgTest, no_buffer_run0)
|
||||
{
|
||||
auto dump_file = "dump_cfg_no_buffer_run*.melt";
|
||||
auto fields = "mass type xsu ysu zsu id proc procp1 x y z ix iy iz vx vy vz fx fy fz";
|
||||
|
||||
generate_dump(dump_file, fields, "buffer no", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS("dump_cfg_no_buffer_run0.melt");
|
||||
auto lines = read_lines("dump_cfg_no_buffer_run0.melt");
|
||||
ASSERT_EQ(lines.size(), 124);
|
||||
ASSERT_THAT(lines[0], Eq("Number of particles = 32"));
|
||||
delete_file("dump_cfg_no_buffer_run0.melt");
|
||||
}
|
||||
|
||||
TEST_F(DumpCfgTest, no_unwrap_no_buffer_run0)
|
||||
{
|
||||
auto dump_file = "dump_cfg_no_unwrap_no_buffer_run*.melt";
|
||||
auto fields = "mass type xs ys zs id proc procp1 x y z ix iy iz vx vy vz fx fy fz";
|
||||
|
||||
generate_dump(dump_file, fields, "buffer no", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS("dump_cfg_no_unwrap_no_buffer_run0.melt");
|
||||
auto lines = read_lines("dump_cfg_no_unwrap_no_buffer_run0.melt");
|
||||
ASSERT_EQ(lines.size(), 124);
|
||||
ASSERT_THAT(lines[0], Eq("Number of particles = 32"));
|
||||
delete_file("dump_cfg_no_unwrap_no_buffer_run0.melt");
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
MPI_Init(&argc, &argv);
|
||||
::testing::InitGoogleMock(&argc, argv);
|
||||
|
||||
// handle arguments passed via environment variable
|
||||
if (const char *var = getenv("TEST_ARGS")) {
|
||||
std::vector<std::string> env = utils::split_words(var);
|
||||
for (auto arg : env) {
|
||||
if (arg == "-v") {
|
||||
verbose = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((argc > 1) && (strcmp(argv[1], "-v") == 0)) verbose = true;
|
||||
|
||||
int rv = RUN_ALL_TESTS();
|
||||
MPI_Finalize();
|
||||
return rv;
|
||||
}
|
|
@ -0,0 +1,279 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "fmt/format.h"
|
||||
#include "utils.h"
|
||||
#include "../testing/core.h"
|
||||
#include "../testing/systems/melt.h"
|
||||
#include "../testing/utils.h"
|
||||
|
||||
using ::testing::Eq;
|
||||
|
||||
char * BINARY2TXT_BINARY = nullptr;
|
||||
|
||||
class DumpCustomTest : public MeltTest {
|
||||
std::string dump_style = "custom";
|
||||
public:
|
||||
void enable_triclinic() {
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
command("change_box all triclinic");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
}
|
||||
|
||||
void generate_dump(std::string dump_file, std::string fields, std::string dump_modify_options, int ntimesteps) {
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
command(fmt::format("dump id all {} 1 {} {}", dump_style, dump_file, fields));
|
||||
|
||||
if (!dump_modify_options.empty()) {
|
||||
command(fmt::format("dump_modify id {}", dump_modify_options));
|
||||
}
|
||||
|
||||
command(fmt::format("run {}", ntimesteps));
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
}
|
||||
|
||||
void generate_text_and_binary_dump(std::string text_file, std::string binary_file, std::string fields,
|
||||
std::string dump_modify_options, int ntimesteps) {
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
command(fmt::format("dump id0 all {} 1 {} {}", dump_style, text_file, fields));
|
||||
command(fmt::format("dump id1 all {} 1 {} {}", dump_style, binary_file, fields));
|
||||
|
||||
if (!dump_modify_options.empty()) {
|
||||
command(fmt::format("dump_modify id0 {}", dump_modify_options));
|
||||
command(fmt::format("dump_modify id1 {}", dump_modify_options));
|
||||
}
|
||||
|
||||
command(fmt::format("run {}", ntimesteps));
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
}
|
||||
|
||||
std::string convert_binary_to_text(std::string binary_file) {
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
std::string cmdline = fmt::format("{} {}", BINARY2TXT_BINARY, binary_file);
|
||||
system(cmdline.c_str());
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
return fmt::format("{}.txt", binary_file);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(DumpCustomTest, run1)
|
||||
{
|
||||
auto dump_file = "dump_custom_run1.melt";
|
||||
auto fields = "id type proc procp1 mass x y z ix iy iz xs ys zs xu yu zu xsu ysu zsu vx vy vz fx fy fz";
|
||||
|
||||
generate_dump(dump_file, fields, "units yes", 1);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 84);
|
||||
ASSERT_THAT(lines[6], Eq("ITEM: BOX BOUNDS pp pp pp"));
|
||||
ASSERT_EQ(utils::split_words(lines[7]).size(), 2);
|
||||
ASSERT_THAT(lines[10], Eq(fmt::format("ITEM: ATOMS {}", fields)));
|
||||
ASSERT_EQ(utils::split_words(lines[11]).size(), 26);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpCustomTest, thresh_run0)
|
||||
{
|
||||
auto dump_file = "dump_custom_thresh_run0.melt";
|
||||
auto fields = "id type x y z";
|
||||
|
||||
generate_dump(dump_file, fields, "units yes thresh x < 1 thresh y < 1 thresh z < 1", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 15);
|
||||
ASSERT_THAT(lines[6], Eq("ITEM: BOX BOUNDS pp pp pp"));
|
||||
ASSERT_EQ(utils::split_words(lines[7]).size(), 2);
|
||||
ASSERT_THAT(lines[10], Eq(fmt::format("ITEM: ATOMS {}", fields)));
|
||||
ASSERT_EQ(utils::split_words(lines[11]).size(), 5);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpCustomTest, compute_run0)
|
||||
{
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
command("compute comp all property/atom x y z");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
auto dump_file = "dump_custom_compute_run0.melt";
|
||||
auto fields = "id type x y z c_comp[1] c_comp[2] c_comp[3]";
|
||||
|
||||
generate_dump(dump_file, fields, "units yes", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 43);
|
||||
ASSERT_THAT(lines[6], Eq("ITEM: BOX BOUNDS pp pp pp"));
|
||||
ASSERT_EQ(utils::split_words(lines[7]).size(), 2);
|
||||
ASSERT_THAT(lines[10], Eq(fmt::format("ITEM: ATOMS {}", fields)));
|
||||
ASSERT_EQ(utils::split_words(lines[11]).size(), 8);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpCustomTest, fix_run0)
|
||||
{
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
command("fix numdiff all numdiff 1 0.0001");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
auto dump_file = "dump_custom_compute_run0.melt";
|
||||
auto fields = "id x y z f_numdiff[1] f_numdiff[2] f_numdiff[3]";
|
||||
|
||||
generate_dump(dump_file, fields, "units yes", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 43);
|
||||
ASSERT_THAT(lines[6], Eq("ITEM: BOX BOUNDS pp pp pp"));
|
||||
ASSERT_EQ(utils::split_words(lines[7]).size(), 2);
|
||||
ASSERT_THAT(lines[10], Eq(fmt::format("ITEM: ATOMS {}", fields)));
|
||||
ASSERT_EQ(utils::split_words(lines[11]).size(), 7);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpCustomTest, custom_run0)
|
||||
{
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
command("fix prop all property/atom i_flag1 d_flag2");
|
||||
command("compute 1 all property/atom i_flag1 d_flag2");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
auto dump_file = "dump_custom_custom_run0.melt";
|
||||
auto fields = "id x y z i_flag1 d_flag2";
|
||||
|
||||
generate_dump(dump_file, fields, "units yes", 0);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 43);
|
||||
ASSERT_THAT(lines[6], Eq("ITEM: BOX BOUNDS pp pp pp"));
|
||||
ASSERT_EQ(utils::split_words(lines[7]).size(), 2);
|
||||
ASSERT_THAT(lines[10], Eq(fmt::format("ITEM: ATOMS {}", fields)));
|
||||
ASSERT_EQ(utils::split_words(lines[11]).size(), 6);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpCustomTest, binary_run1)
|
||||
{
|
||||
if(!BINARY2TXT_BINARY) GTEST_SKIP();
|
||||
|
||||
auto text_file = "dump_custom_text_run1.melt";
|
||||
auto binary_file = "dump_custom_binary_run1.melt.bin";
|
||||
auto fields = "id type proc x y z ix iy iz xs ys zs xu yu zu xsu ysu zsu vx vy vz fx fy fz";
|
||||
|
||||
generate_text_and_binary_dump(text_file, binary_file, fields, "units yes", 1);
|
||||
|
||||
ASSERT_FILE_EXISTS(text_file);
|
||||
ASSERT_FILE_EXISTS(binary_file);
|
||||
|
||||
auto converted_file = convert_binary_to_text(binary_file);
|
||||
|
||||
ASSERT_FILE_EXISTS(converted_file);
|
||||
ASSERT_FILE_EQUAL(text_file, converted_file);
|
||||
delete_file(text_file);
|
||||
delete_file(binary_file);
|
||||
delete_file(converted_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpCustomTest, triclinic_run1)
|
||||
{
|
||||
auto dump_file = "dump_custom_tri_run1.melt";
|
||||
auto fields = "id type proc x y z ix iy iz xs ys zs xu yu zu xsu ysu zsu vx vy vz fx fy fz";
|
||||
|
||||
enable_triclinic();
|
||||
|
||||
generate_dump(dump_file, fields, "units yes", 1);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_THAT(lines[6], Eq("ITEM: BOX BOUNDS xy xz yz pp pp pp"));
|
||||
ASSERT_EQ(utils::split_words(lines[7]).size(), 3);
|
||||
|
||||
ASSERT_EQ(lines.size(), 84);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpCustomTest, binary_triclinic_run1)
|
||||
{
|
||||
if(!BINARY2TXT_BINARY) GTEST_SKIP();
|
||||
|
||||
auto text_file = "dump_custom_tri_text_run1.melt";
|
||||
auto binary_file = "dump_custom_tri_binary_run1.melt.bin";
|
||||
auto fields = "id type proc x y z xs ys zs xsu ysu zsu vx vy vz fx fy fz";
|
||||
|
||||
enable_triclinic();
|
||||
|
||||
generate_text_and_binary_dump(text_file, binary_file, fields, "units yes", 1);
|
||||
|
||||
ASSERT_FILE_EXISTS(text_file);
|
||||
ASSERT_FILE_EXISTS(binary_file);
|
||||
|
||||
auto converted_file = convert_binary_to_text(binary_file);
|
||||
|
||||
ASSERT_FILE_EXISTS(converted_file);
|
||||
ASSERT_FILE_EQUAL(text_file, converted_file);
|
||||
delete_file(text_file);
|
||||
delete_file(binary_file);
|
||||
delete_file(converted_file);
|
||||
}
|
||||
|
||||
TEST_F(DumpCustomTest, with_variable_run1)
|
||||
{
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
command("compute 1 all property/atom proc");
|
||||
command("variable p atom (c_1%10)+1");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
auto dump_file = "dump_custom_with_variable_run1.melt";
|
||||
auto fields = "id type x y z v_p";
|
||||
|
||||
generate_dump(dump_file, fields, "units yes", 1);
|
||||
|
||||
ASSERT_FILE_EXISTS(dump_file);
|
||||
auto lines = read_lines(dump_file);
|
||||
ASSERT_EQ(lines.size(), 84);
|
||||
ASSERT_THAT(lines[6], Eq("ITEM: BOX BOUNDS pp pp pp"));
|
||||
ASSERT_EQ(utils::split_words(lines[7]).size(), 2);
|
||||
ASSERT_THAT(lines[10], Eq("ITEM: ATOMS id type x y z v_p"));
|
||||
ASSERT_EQ(utils::split_words(lines[11]).size(), 6);
|
||||
delete_file(dump_file);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
MPI_Init(&argc, &argv);
|
||||
::testing::InitGoogleMock(&argc, argv);
|
||||
|
||||
// handle arguments passed via environment variable
|
||||
if (const char *var = getenv("TEST_ARGS")) {
|
||||
std::vector<std::string> env = utils::split_words(var);
|
||||
for (auto arg : env) {
|
||||
if (arg == "-v") {
|
||||
verbose = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BINARY2TXT_BINARY = getenv("BINARY2TXT_BINARY");
|
||||
|
||||
if ((argc > 1) && (strcmp(argv[1], "-v") == 0)) verbose = true;
|
||||
|
||||
int rv = RUN_ALL_TESTS();
|
||||
MPI_Finalize();
|
||||
return rv;
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
#ifndef TESTING_CORE__H
|
||||
#define TESTING_CORE__H
|
||||
|
||||
#include "info.h"
|
||||
#include "input.h"
|
||||
#include "lammps.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
using ::testing::MatchesRegex;
|
||||
|
||||
#define TEST_FAILURE(errmsg, ...) \
|
||||
if (Info::has_exceptions()) { \
|
||||
::testing::internal::CaptureStdout(); \
|
||||
ASSERT_ANY_THROW({__VA_ARGS__}); \
|
||||
auto mesg = ::testing::internal::GetCapturedStdout(); \
|
||||
ASSERT_THAT(mesg, MatchesRegex(errmsg)); \
|
||||
} else { \
|
||||
if (Info::get_mpi_vendor() != "Open MPI") { \
|
||||
::testing::internal::CaptureStdout(); \
|
||||
ASSERT_DEATH({__VA_ARGS__}, ""); \
|
||||
auto mesg = ::testing::internal::GetCapturedStdout(); \
|
||||
ASSERT_THAT(mesg, MatchesRegex(errmsg)); \
|
||||
} \
|
||||
}
|
||||
|
||||
// whether to print verbose output (i.e. not capturing LAMMPS screen output).
|
||||
bool verbose = false;
|
||||
|
||||
|
||||
class LAMMPSTest : public ::testing::Test {
|
||||
public:
|
||||
void command(const std::string &line) {
|
||||
lmp->input->one(line.c_str());
|
||||
}
|
||||
|
||||
protected:
|
||||
const char * testbinary = "LAMMPSTest";
|
||||
LAMMPS *lmp;
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
const char *args[] = { testbinary, "-log", "none", "-echo", "screen", "-nocite"};
|
||||
char **argv = (char **)args;
|
||||
int argc = sizeof(args) / sizeof(char *);
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lmp = new LAMMPS(argc, argv, MPI_COMM_WORLD);
|
||||
InitSystem();
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
}
|
||||
|
||||
|
||||
virtual void InitSystem() {
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
delete lmp;
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
#ifndef TEST_EXAMPLE_MELT__H
|
||||
#define TEST_EXAMPLE_MELT__H
|
||||
|
||||
#include "../core.h"
|
||||
|
||||
class MeltTest : public LAMMPSTest {
|
||||
protected:
|
||||
virtual void InitSystem() override {
|
||||
command("units lj");
|
||||
command("atom_style atomic");
|
||||
command("atom_modify map yes");
|
||||
|
||||
command("lattice fcc 0.8442");
|
||||
command("region box block 0 2 0 2 0 2");
|
||||
command("create_box 1 box");
|
||||
command("create_atoms 1 box");
|
||||
command("mass 1 1.0");
|
||||
|
||||
command("velocity all create 3.0 87287");
|
||||
|
||||
command("pair_style lj/cut 2.5");
|
||||
command("pair_coeff 1 1 1.0 1.0 2.5");
|
||||
|
||||
command("neighbor 0.3 bin");
|
||||
command("neigh_modify every 20 delay 0 check no");
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,73 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
#ifndef TEST_EXTENSIONS__H
|
||||
#define TEST_EXTENSIONS__H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
static void delete_file(const std::string &filename)
|
||||
{
|
||||
remove(filename.c_str());
|
||||
}
|
||||
|
||||
static size_t count_lines(const std::string &filename)
|
||||
{
|
||||
std::ifstream infile(filename);
|
||||
std::string line;
|
||||
size_t nlines = 0;
|
||||
|
||||
while (std::getline(infile, line))
|
||||
++nlines;
|
||||
|
||||
return nlines;
|
||||
}
|
||||
|
||||
static bool equal_lines(const std::string &fileA, const std::string &fileB)
|
||||
{
|
||||
std::ifstream afile(fileA);
|
||||
std::ifstream bfile(fileB);
|
||||
std::string lineA, lineB;
|
||||
|
||||
while (std::getline(afile, lineA)) {
|
||||
if(!std::getline(bfile, lineB)) return false;
|
||||
if(lineA != lineB) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::vector<std::string> read_lines(const std::string &filename) {
|
||||
std::vector<std::string> lines;
|
||||
std::ifstream infile(filename);
|
||||
std::string line;
|
||||
|
||||
while (std::getline(infile, line))
|
||||
lines.push_back(line);
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
static bool file_exists(const std::string &filename) {
|
||||
struct stat result;
|
||||
return stat(filename.c_str(), &result) == 0;
|
||||
}
|
||||
|
||||
#define ASSERT_FILE_EXISTS(NAME) ASSERT_TRUE(file_exists(NAME))
|
||||
#define ASSERT_FILE_EQUAL(FILE_A, FILE_B) ASSERT_TRUE(equal_lines(FILE_A, FILE_B))
|
||||
|
||||
#endif
|
|
@ -125,3 +125,14 @@ TEST(ValueTokenizer, valid_double_with_exponential)
|
|||
ValueTokenizer values("3.14e22");
|
||||
ASSERT_DOUBLE_EQ(values.next_double(), 3.14e22);
|
||||
}
|
||||
|
||||
TEST(ValueTokenizer, contains) {
|
||||
ValueTokenizer values("test word");
|
||||
ASSERT_TRUE(values.contains("test"));
|
||||
ASSERT_TRUE(values.contains("word"));
|
||||
}
|
||||
|
||||
TEST(ValueTokenizer, not_contains) {
|
||||
ValueTokenizer values("test word");
|
||||
ASSERT_FALSE(values.contains("test2"));
|
||||
}
|
||||
|
|
|
@ -462,3 +462,18 @@ TEST(Utils, unit_conversion)
|
|||
factor = utils::get_conversion_factor(utils::ENERGY, utils::REAL2METAL);
|
||||
ASSERT_DOUBLE_EQ(factor, 1.0 / 23.060549);
|
||||
}
|
||||
|
||||
TEST(Utils, timespec2seconds_ss)
|
||||
{
|
||||
ASSERT_DOUBLE_EQ(utils::timespec2seconds("45"), 45.0);
|
||||
}
|
||||
|
||||
TEST(Utils, timespec2seconds_mmss)
|
||||
{
|
||||
ASSERT_DOUBLE_EQ(utils::timespec2seconds("10:45"), 645.0);
|
||||
}
|
||||
|
||||
TEST(Utils, timespec2seconds_hhmmss)
|
||||
{
|
||||
ASSERT_DOUBLE_EQ(utils::timespec2seconds("2:10:45"), 7845.0);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue