From c021a2d185755b079cadb48a3b812a29961512ca Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 31 Jan 2020 10:49:59 -0500 Subject: [PATCH] multiple consistency improvements for restart files - make defines and enumerators automatically consistent by moving them to a shared header file - change VERSION_NUMERIC to FORMAT_REVISION (and corresponding function names) - new class member revision in ReadRestart class to allow backward compatibility - step current FORMAT_REVISION to 1 - write the magic string a the end of each restart - add a check, that skips to the end of a file and checks for the magic string and then returns but do this only if FORMAT_REVISION is 1 or larger for backward compatibility --- src/read_restart.cpp | 85 ++++++++++++++++++++++++------------------- src/read_restart.h | 6 ++- src/write_restart.cpp | 33 +++-------------- 3 files changed, 57 insertions(+), 67 deletions(-) diff --git a/src/read_restart.cpp b/src/read_restart.cpp index 6469a5ec76..537193c4a4 100644 --- a/src/read_restart.cpp +++ b/src/read_restart.cpp @@ -37,36 +37,10 @@ #include "error.h" #include "utils.h" +#include "lmp_restart.h" + using namespace LAMMPS_NS; -// same as write_restart.cpp - -#define MAGIC_STRING "LammpS RestartT" -#define ENDIAN 0x0001 -#define ENDIANSWAP 0x1000 -#define VERSION_NUMERIC 0 - -enum{VERSION,SMALLINT,TAGINT,BIGINT, - UNITS,NTIMESTEP,DIMENSION,NPROCS,PROCGRID, - NEWTON_PAIR,NEWTON_BOND, - XPERIODIC,YPERIODIC,ZPERIODIC,BOUNDARY, - ATOM_STYLE,NATOMS,NTYPES, - NBONDS,NBONDTYPES,BOND_PER_ATOM, - NANGLES,NANGLETYPES,ANGLE_PER_ATOM, - NDIHEDRALS,NDIHEDRALTYPES,DIHEDRAL_PER_ATOM, - NIMPROPERS,NIMPROPERTYPES,IMPROPER_PER_ATOM, - TRICLINIC,BOXLO,BOXHI,XY,XZ,YZ, - SPECIAL_LJ,SPECIAL_COUL, - MASS,PAIR,BOND,ANGLE,DIHEDRAL,IMPROPER, - MULTIPROC,MPIIO,PROCSPERFILE,PERPROC, - IMAGEINT,BOUNDMIN,TIMESTEP, - ATOM_ID,ATOM_MAP_STYLE,ATOM_MAP_USER,ATOM_SORTFREQ,ATOM_SORTBIN, - COMM_MODE,COMM_CUTOFF,COMM_VEL,NO_PAIR, - EXTRA_BOND_PER_ATOM,EXTRA_ANGLE_PER_ATOM,EXTRA_DIHEDRAL_PER_ATOM, - EXTRA_IMPROPER_PER_ATOM,EXTRA_SPECIAL_PER_ATOM,ATOM_MAXSPECIAL}; - -#define LB_FACTOR 1.1 - /* ---------------------------------------------------------------------- */ ReadRestart::ReadRestart(LAMMPS *lmp) : Pointers(lmp) {} @@ -146,15 +120,15 @@ void ReadRestart::command(int narg, char **arg) if (multiproc) delete [] hfile; } - // read magic string, endian flag, numeric version + // read magic string, endian flag, format revision magic_string(); endian(); - int incompatible = version_numeric(); + format_revision(); // read header info which creates simulation box - header(incompatible); + header(); domain->box_exist = 1; // problem setup using info from header @@ -681,7 +655,7 @@ void ReadRestart::file_search(char *inpfile, char *outfile) read header of restart file ------------------------------------------------------------------------- */ -void ReadRestart::header(int incompatible) +void ReadRestart::header() { int xperiodic(-1),yperiodic(-1),zperiodic(-1); @@ -698,10 +672,20 @@ void ReadRestart::header(int incompatible) if (screen) fprintf(screen," restart file = %s, LAMMPS = %s\n", version,universe->version); } - if (incompatible) - error->all(FLERR,"Restart file incompatible with current version"); delete [] version; + // we have no forward compatibility, thus exit with error + + if (revision > FORMAT_REVISION) + error->all(FLERR,"Restart file format revision incompatible " + "with current LAMMPS version"); + + // warn when attempting to read older format revision + + if ((me == 0) && (revision < FORMAT_REVISION)) + error->warning(FLERR,"Old restart file format revision. " + "Switching to compatibility mode."); + // check lmptype.h sizes, error if different } else if (flag == SMALLINT) { @@ -1242,11 +1226,36 @@ void ReadRestart::endian() /* ---------------------------------------------------------------------- ------------------------------------------------------------------------- */ -int ReadRestart::version_numeric() +void ReadRestart::format_revision() { - int vn = read_int(); - if (vn != VERSION_NUMERIC) return 1; - return 0; + revision = read_int(); +} + +/* ---------------------------------------------------------------------- +------------------------------------------------------------------------- */ + +void ReadRestart::check_eof_magic() +{ + // no check for revision 0 restart files + if (revision < 1) return; + + int n = strlen(MAGIC_STRING) + 1; + char *str = new char[n]; + + // read magic string at end of file and restore file pointer + + if (me == 0) { + long curpos = ftell(fp); + fseek(fp,(long)-n,SEEK_END); + fread(str,sizeof(char),n,fp); + fseek(fp,curpos,SEEK_SET); + } + + MPI_Bcast(str,n,MPI_CHAR,0,world); + if (strcmp(str,MAGIC_STRING) != 0) + error->all(FLERR,"Incomplete or corrupted LAMMPS restart file"); + + delete [] str; } /* ---------------------------------------------------------------------- diff --git a/src/read_restart.h b/src/read_restart.h index 63adf37b22..99b37cfa45 100644 --- a/src/read_restart.h +++ b/src/read_restart.h @@ -37,6 +37,7 @@ class ReadRestart : protected Pointers { // 1 = restart file is parallel (multiple files) int multiproc_file; // # of parallel files in restart int nprocs_file; // total # of procs that wrote restart file + int revision; // revision number of the restart file format // MPI-IO values @@ -46,13 +47,14 @@ class ReadRestart : protected Pointers { MPI_Offset assignedChunkOffset,headerOffset; void file_search(char *, char *); - void header(int); + void header(); void type_arrays(); void force_fields(); void magic_string(); void endian(); - int version_numeric(); + void format_revision(); + void check_eof_magic(); void file_layout(); int read_int(); diff --git a/src/write_restart.cpp b/src/write_restart.cpp index 4b84e790b8..f94b660bfa 100644 --- a/src/write_restart.cpp +++ b/src/write_restart.cpp @@ -36,34 +36,10 @@ #include "memory.h" #include "error.h" +#include "lmp_restart.h" + using namespace LAMMPS_NS; -// same as read_restart.cpp - -#define MAGIC_STRING "LammpS RestartT" -#define ENDIAN 0x0001 -#define ENDIANSWAP 0x1000 -#define VERSION_NUMERIC 0 - -enum{VERSION,SMALLINT,TAGINT,BIGINT, - UNITS,NTIMESTEP,DIMENSION,NPROCS,PROCGRID, - NEWTON_PAIR,NEWTON_BOND, - XPERIODIC,YPERIODIC,ZPERIODIC,BOUNDARY, - ATOM_STYLE,NATOMS,NTYPES, - NBONDS,NBONDTYPES,BOND_PER_ATOM, - NANGLES,NANGLETYPES,ANGLE_PER_ATOM, - NDIHEDRALS,NDIHEDRALTYPES,DIHEDRAL_PER_ATOM, - NIMPROPERS,NIMPROPERTYPES,IMPROPER_PER_ATOM, - TRICLINIC,BOXLO,BOXHI,XY,XZ,YZ, - SPECIAL_LJ,SPECIAL_COUL, - MASS,PAIR,BOND,ANGLE,DIHEDRAL,IMPROPER, - MULTIPROC,MPIIO,PROCSPERFILE,PERPROC, - IMAGEINT,BOUNDMIN,TIMESTEP, - ATOM_ID,ATOM_MAP_STYLE,ATOM_MAP_USER,ATOM_SORTFREQ,ATOM_SORTBIN, - COMM_MODE,COMM_CUTOFF,COMM_VEL,NO_PAIR, - EXTRA_BOND_PER_ATOM,EXTRA_ANGLE_PER_ATOM,EXTRA_DIHEDRAL_PER_ATOM, - EXTRA_IMPROPER_PER_ATOM,EXTRA_SPECIAL_PER_ATOM,ATOM_MAXSPECIAL}; - /* ---------------------------------------------------------------------- */ WriteRestart::WriteRestart(LAMMPS *lmp) : Pointers(lmp) @@ -319,6 +295,7 @@ void WriteRestart::write(char *file) if (multiproc) { if (me == 0 && fp) { + magic_string(); fclose(fp); fp = NULL; } @@ -401,6 +378,7 @@ void WriteRestart::write(char *file) if (mpiioflag) { if (me == 0 && fp) { + magic_string(); fclose(fp); fp = NULL; } @@ -430,6 +408,7 @@ void WriteRestart::write(char *file) write_double_vec(PERPROC,recv_size,buf); } + magic_string(); fclose(fp); fp = NULL; @@ -656,7 +635,7 @@ void WriteRestart::endian() void WriteRestart::version_numeric() { - int vn = VERSION_NUMERIC; + int vn = FORMAT_REVISION; fwrite(&vn,sizeof(int),1,fp); }