diff --git a/src/read_dump.cpp b/src/read_dump.cpp index 6f1db5f225..c0f79e8889 100644 --- a/src/read_dump.cpp +++ b/src/read_dump.cpp @@ -49,7 +49,7 @@ ReadDump::ReadDump(LAMMPS *lmp) : Pointers(lmp) dimension = domain->dimension; triclinic = domain->triclinic; - nfiles = 0; + nfile = 0; files = NULL; nfield = 0; @@ -59,13 +59,14 @@ ReadDump::ReadDump(LAMMPS *lmp) : Pointers(lmp) uflag = ucflag = ucflag_all = NULL; reader = NULL; + fp = NULL; } /* ---------------------------------------------------------------------- */ ReadDump::~ReadDump() { - for (int i = 0; i < nfiles; i++) delete [] files[i]; + for (int i = 0; i < nfile; i++) delete [] files[i]; delete [] files; for (int i = 0; i < nfield; i++) delete [] fieldlabel[i]; delete [] fieldlabel; @@ -113,7 +114,6 @@ void ReadDump::command(int narg, char **arg) bigint natoms_prev = atom->natoms; atoms(); - // NOTE: this logic is not yet right if (me == 0) close(); // print out stats @@ -158,10 +158,10 @@ void ReadDump::command(int narg, char **arg) void ReadDump::store_files(int nstr, char **str) { - nfiles = nstr; - files = new char*[nfiles]; + nfile = nstr; + files = new char*[nfile]; - for (int i = 0; i < nfiles; i++) { + for (int i = 0; i < nfile; i++) { int n = strlen(str[i]) + 1; files[i] = new char[n]; strcpy(files[i],str[i]); @@ -184,7 +184,6 @@ void ReadDump::setup_reader() /* ---------------------------------------------------------------------- seek Nrequest timestep in one or more dump files - Nrequest can be a timestamp or -1 to match first step with exact = 0 if exact = 1, must find exactly Nrequest if exact = 0, find first step >= Nrequest return matching ntimestep or -1 if did not find a match @@ -196,7 +195,11 @@ bigint ReadDump::seek(bigint nrequest, int exact) bigint ntimestep; if (me == 0) { - for (ifile = 0; ifile < nfiles; ifile++) { + + // exit file loop when dump timestep >= nrequest + // or files exhausted + + for (ifile = 0; ifile < nfile; ifile++) { ntimestep = -1; open(files[ifile]); reader->file(fp); @@ -211,9 +214,9 @@ bigint ReadDump::seek(bigint nrequest, int exact) } currentfile = ifile; - if (ntimestep < nrequest) close(); if (ntimestep < nrequest) ntimestep = -1; if (exact && ntimestep != nrequest) ntimestep = -1; + if (ntimestep < 0) close(); } MPI_Bcast(&ntimestep,1,MPI_LMP_BIGINT,0,world); @@ -223,34 +226,48 @@ bigint ReadDump::seek(bigint nrequest, int exact) /* ---------------------------------------------------------------------- find next matching snapshot in one or more dump files Ncurrent = current timestep from last snapshot - Nstop = match no timestep bigger than Nstop + Nlast = match no timestep bigger than Nlast Nevery = only match timesteps that are a multiple of Nevery Nskip = skip every this many timesteps return matching ntimestep or -1 if did not find a match ------------------------------------------------------------------------- */ -bigint ReadDump::next(bigint ncurrent, bigint nstop, int nevery, int nskip) +bigint ReadDump::next(bigint ncurrent, bigint nlast, int nevery, int nskip) { int ifile,eofflag; bigint ntimestep; - // NOTE: this logic is not yet right - if (me == 0) { - for (ifile = currentfile; ifile < nfiles; ifile++) { + + // exit file loop when dump timestep matches all criteria + // or files exhausted + + int iskip = 0; + + for (ifile = currentfile; ifile < nfile; ifile++) { ntimestep = -1; if (ifile != currentfile) open(files[ifile]); reader->file(fp); while (1) { eofflag = reader->read_time(ntimestep); - if (eofflag) ntimestep = -1; - break; + if (iskip == nskip) iskip = 0; + iskip++; + if (eofflag) break; + if (ntimestep <= ncurrent) break; + if (ntimestep > nlast) break; + if (nevery && ntimestep % nevery) reader->skip(); + else if (iskip < nskip) reader->skip(); + else break; } - if (ntimestep > ncurrent) break; - close(); + if (eofflag) close(); + else break; } currentfile = ifile; + if (eofflag) ntimestep = -1; + if (ntimestep <= ncurrent) ntimestep = -1; + if (ntimestep > nlast) ntimestep = -1; + if (ntimestep < 0) close(); } MPI_Bcast(&ntimestep,1,MPI_LMP_BIGINT,0,world); @@ -860,6 +877,8 @@ void ReadDump::open(char *file) void ReadDump::close() { + if (fp == NULL) return; if (compressed) pclose(fp); else fclose(fp); + fp = NULL; } diff --git a/src/read_dump.h b/src/read_dump.h index 19e2323e76..05ea5a0dc6 100644 --- a/src/read_dump.h +++ b/src/read_dump.h @@ -48,7 +48,7 @@ private: int dimension; int triclinic; - int nfiles; // # of dump files to process + int nfile; // # of dump files to process char **files; // list of file names int currentfile; // currently open file diff --git a/src/rerun.cpp b/src/rerun.cpp new file mode 100644 index 0000000000..015972bcc4 --- /dev/null +++ b/src/rerun.cpp @@ -0,0 +1,177 @@ +/* ---------------------------------------------------------------------- + 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 "lmptype.h" +#include "stdlib.h" +#include "string.h" +#include "rerun.h" +#include "read_dump.h" +#include "domain.h" +#include "update.h" +#include "integrate.h" +#include "modify.h" +#include "output.h" +#include "finish.h" +#include "timer.h" +#include "error.h" + +using namespace LAMMPS_NS; + +/* ---------------------------------------------------------------------- */ + +Rerun::Rerun(LAMMPS *lmp) : Pointers(lmp) {} + +/* ---------------------------------------------------------------------- */ + +void Rerun::command(int narg, char **arg) +{ + if (narg < 2) error->all(FLERR,"Illegal rerun command"); + + if (domain->box_exist == 0) + error->all(FLERR,"Rerun command before simulation box is defined"); + + // list of dump files = args until a keyword + + int iarg = 0; + while (iarg < narg) { + if (strcmp(arg[iarg],"first") == 0) break; + if (strcmp(arg[iarg],"last") == 0) break; + if (strcmp(arg[iarg],"every") == 0) break; + if (strcmp(arg[iarg],"skip") == 0) break; + if (strcmp(arg[iarg],"start") == 0) break; + if (strcmp(arg[iarg],"stop") == 0) break; + if (strcmp(arg[iarg],"dump") == 0) break; + iarg++; + } + int nfile = iarg; + if (nfile == 0 || nfile == narg) error->all(FLERR,"Illegal rerun command"); + + // parse optional args up until "dump" + + bigint first = 0; + bigint last = MAXBIGINT; + int nevery = 0; + int nskip = 1; + int startflag = 0; + int stopflag = 0; + bigint start,stop; + + while (iarg < narg) { + if (strcmp(arg[iarg],"first") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal rerun command"); + first = ATOBIGINT(arg[iarg+1]); + if (first < 0) error->all(FLERR,"Illegal rerun command"); + iarg += 2; + } else if (strcmp(arg[iarg],"last") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal rerun command"); + last = ATOBIGINT(arg[iarg+1]); + if (last < 0) error->all(FLERR,"Illegal rerun command"); + iarg += 2; + } else if (strcmp(arg[iarg],"every") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal rerun command"); + nevery = atoi(arg[iarg+1]); + if (nevery < 0) error->all(FLERR,"Illegal rerun command"); + iarg += 2; + } else if (strcmp(arg[iarg],"skip") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal rerun command"); + nskip = atoi(arg[iarg+1]); + if (nskip <= 0) error->all(FLERR,"Illegal rerun command"); + iarg += 2; + } else if (strcmp(arg[iarg],"start") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal rerun command"); + startflag = 1; + start = ATOBIGINT(arg[iarg+1]); + if (start < 0) error->all(FLERR,"Illegal rerun command"); + iarg += 2; + } else if (strcmp(arg[iarg],"stop") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal rerun command"); + stopflag = 1; + stop = ATOBIGINT(arg[iarg+1]); + if (stop < 0) error->all(FLERR,"Illegal rerun command"); + iarg += 2; + } else if (strcmp(arg[iarg],"dump") == 0) { + break; + } else error->all(FLERR,"Illegal rerun command"); + } + + if (strcmp(arg[iarg],"dump") != 0) error->all(FLERR,"Illegal rerun command"); + if (first > last) error->all(FLERR,"Illegal rerun command"); + if (startflag && stopflag && start > stop) + error->all(FLERR,"Illegal rerun command"); + + // pass list of filenames to ReadDump, along with post-"dump" args + + ReadDump *rd = new ReadDump(lmp); + + rd->store_files(nfile,arg); + rd->fields_and_keywords(narg-iarg-1,&arg[iarg+1]); + rd->setup_reader(); + + // perform the psuedo run + // invoke lmp->init() only once + // read all relevant snapshots + // uset setup_minimal() since atoms are already owned by correct procs + // addstep_compute_all() insures energy/virial computed on every snapshot + // set update->nsteps to ndump for Finish stats to print + + update->whichflag = 1; + + if (startflag) update->beginstep = update->firststep = start; + else update->beginstep = update->firststep = first; + if (stopflag) update->endstep = update->laststep = stop; + else update->endstep = update->laststep = last; + + int firstflag = 1; + int ndump = 0; + + lmp->init(); + + timer->init(); + timer->barrier_start(TIME_LOOP); + + bigint ntimestep = rd->seek(first,0); + if (ntimestep < 0) + error->all(FLERR,"Rerun dump file does not contain requested snapshot"); + + while (1) { + ndump++; + rd->header(firstflag); + update->reset_timestep(ntimestep); + rd->atoms(); + + modify->addstep_compute_all(ntimestep); + update->integrate->setup_minimal(1); + output->setup(firstflag,firstflag); + firstflag = 0; + + ntimestep = rd->next(ntimestep,last,nevery,nskip); + if (ntimestep < 0) break; + } + + timer->barrier_stop(TIME_LOOP); + + update->integrate->cleanup(); + + update->nsteps = ndump; + + Finish finish(lmp); + finish.end(1); + + update->whichflag = 0; + update->firststep = update->laststep = 0; + update->beginstep = update->endstep = 0; + + // clean-up + + delete rd; +} diff --git a/src/rerun.h b/src/rerun.h new file mode 100644 index 0000000000..2cca80824f --- /dev/null +++ b/src/rerun.h @@ -0,0 +1,36 @@ +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +#ifdef COMMAND_CLASS + +CommandStyle(rerun,Rerun) + +#else + +#ifndef LMP_RERUN_H +#define LMP_RERUN_H + +#include "pointers.h" + +namespace LAMMPS_NS { + +class Rerun : protected Pointers { + public: + Rerun(class LAMMPS *); + void command(int, char **); +}; + +} + +#endif +#endif