From 7780d92823364ef6013b00a0c44e5e9b3385a12d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 10 May 2018 23:25:26 -0400 Subject: [PATCH 1/5] implement 'dump_modify maxfiles' feature as discussed --- doc/src/dump_modify.txt | 14 ++++++++++++- src/dump.cpp | 46 +++++++++++++++++++++++++++++++++++++++++ src/dump.h | 5 +++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/doc/src/dump_modify.txt b/doc/src/dump_modify.txt index 6de6de545e..f4ce69af54 100644 --- a/doc/src/dump_modify.txt +++ b/doc/src/dump_modify.txt @@ -15,7 +15,7 @@ dump_modify dump-ID keyword values ... :pre dump-ID = ID of dump to modify :ulb,l one or more keyword/value pairs may be appended :l these keywords apply to various dump styles :l -keyword = {append} or {at} or {buffer} or {delay} or {element} or {every} or {fileper} or {first} or {flush} or {format} or {image} or {label} or {nfile} or {pad} or {precision} or {region} or {scale} or {sort} or {thresh} or {unwrap} :l +keyword = {append} or {at} or {buffer} or {delay} or {element} or {every} or {fileper} or {first} or {flush} or {format} or {image} or {label} or {maxfiles} or {nfile} or {pad} or {precision} or {region} or {scale} or {sort} or {thresh} or {unwrap} :l {append} arg = {yes} or {no} {at} arg = N N = index of frame written upon first dump @@ -37,6 +37,8 @@ keyword = {append} or {at} or {buffer} or {delay} or {element} or {every} or {fi {image} arg = {yes} or {no} {label} arg = string string = character string (e.g. BONDS) to use in header of dump local file + {maxfiles} arg = maxf + maxf = retain at most {maxf} files when writing one file per timestepq {nfile} arg = Nf Nf = write this many files, one from each of Nf processors {pad} arg = Nchar = # of characters to convert timestep to @@ -364,6 +366,15 @@ e.g. BONDS or ANGLES. :line +The {maxfiles} keyword applies only to dumps with a '*' wildcard included +in the dump file name, i.e. when writing one file per frame. The number +following the keyword determines the maximum number of files being written. +If this number is reached, the olders dump file from the current sequence +is deleted before a new dump file is written. A {maxfiles} value of -1 +or 0 indicates that all files are retained. + +:line + The {nfile} or {fileper} keywords can be used in conjunction with the "%" wildcard character in the specified dump file name, for all dump styles except the {dcd}, {image}, {movie}, {xtc}, and {xyz} styles @@ -901,6 +912,7 @@ flush = yes format = %d and %g for each integer or floating point value image = no label = ENTRIES +maxifiles = -1 nfile = 1 pad = 0 pbc = no diff --git a/src/dump.cpp b/src/dump.cpp index 46e556600a..ce9fc9a0a9 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -91,6 +91,11 @@ Dump::Dump(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp) pbcflag = 0; delay_flag = 0; + maxfiles = -1; + numfiles = 0; + fileidx = 0; + nameslist = NULL; + maxbuf = maxids = maxsort = maxproc = 0; buf = bufsort = NULL; ids = idsort = NULL; @@ -187,6 +192,13 @@ Dump::~Dump() if (multiproc) MPI_Comm_free(&clustercomm); + // delete storage for caching file names + if (maxfiles > 0) { + for (int idx=0; idx < numfiles; ++idx) + delete[] nameslist[idx]; + delete[] nameslist; + } + // XTC style sets fp to NULL since it closes file in its destructor if (multifile == 0 && fp != NULL) { @@ -549,6 +561,19 @@ void Dump::openfile() sprintf(filecurrent,pad,filestar,update->ntimestep,ptr+1); } *ptr = '*'; + if (maxfiles > 0) { + if (numfiles < maxfiles) { + nameslist[numfiles] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[numfiles],filecurrent); + ++numfiles; + } else { + remove(nameslist[fileidx]); + delete[] nameslist[fileidx]; + nameslist[fileidx] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[fileidx],filecurrent); + fileidx = (fileidx + 1) % maxfiles; + } + } } // each proc with filewriter = 1 opens a file @@ -1003,6 +1028,27 @@ void Dump::modify_params(int narg, char **arg) iarg += n; } + } else if (strcmp(arg[iarg],"maxfiles") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); + if (!multifile) + error->all(FLERR,"Cannot use dump_modify maxfiles " + "without * in dump file name"); + // wipe out existing storage + if (maxfiles > 0) { + for (int idx=0; idx < numfiles; ++idx) + delete[] nameslist[idx]; + delete[] nameslist; + } + maxfiles = force->inumeric(FLERR,arg[iarg+1]); + if (maxfiles == 0) error->all(FLERR,"Illegal dump_modify command"); + if (maxfiles > 0) { + nameslist = new char*[maxfiles]; + numfiles = 0; + for (int idx=0; idx < maxfiles; ++idx) + nameslist[idx] = NULL; + fileidx = 0; + } + iarg += 2; } else if (strcmp(arg[iarg],"nfile") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); if (!multiproc) diff --git a/src/dump.h b/src/dump.h index b726b9c3e7..90c10f1ebb 100644 --- a/src/dump.h +++ b/src/dump.h @@ -105,6 +105,11 @@ class Dump : protected Pointers { double boxzlo,boxzhi; double boxxy,boxxz,boxyz; + int maxfiles; // max number of files created, -1 == infinite + int numfiles; // number of files in names list + int fileidx; // index of file in names list + char **nameslist; // list of history file names + bigint ntotal; // total # of per-atom lines in snapshot int reorderflag; // 1 if OK to reorder instead of sort int ntotal_reorder; // # of atoms that must be in snapshot From 075598b405c5acd8afed76a9c380a16c50fbdf21 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 10 May 2018 23:44:27 -0400 Subject: [PATCH 2/5] port dump_modify maxfiles option to COMPRESS and MPIIO package --- src/COMPRESS/dump_atom_gz.cpp | 13 +++++++++++++ src/COMPRESS/dump_cfg_gz.cpp | 13 +++++++++++++ src/COMPRESS/dump_custom_gz.cpp | 13 +++++++++++++ src/COMPRESS/dump_xyz_gz.cpp | 13 +++++++++++++ src/MPIIO/dump_atom_mpiio.cpp | 13 +++++++++++++ src/MPIIO/dump_cfg_mpiio.cpp | 13 +++++++++++++ src/MPIIO/dump_custom_mpiio.cpp | 13 +++++++++++++ src/MPIIO/dump_xyz_mpiio.cpp | 13 +++++++++++++ src/dump.cpp | 2 +- src/dump_custom.cpp | 4 ++-- 10 files changed, 107 insertions(+), 3 deletions(-) diff --git a/src/COMPRESS/dump_atom_gz.cpp b/src/COMPRESS/dump_atom_gz.cpp index fb605b74ce..ef7e6583be 100644 --- a/src/COMPRESS/dump_atom_gz.cpp +++ b/src/COMPRESS/dump_atom_gz.cpp @@ -71,6 +71,19 @@ void DumpAtomGZ::openfile() sprintf(filecurrent,pad,filestar,update->ntimestep,ptr+1); } *ptr = '*'; + if (maxfiles > 0) { + if (numfiles < maxfiles) { + nameslist[numfiles] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[numfiles],filecurrent); + ++numfiles; + } else { + remove(nameslist[fileidx]); + delete[] nameslist[fileidx]; + nameslist[fileidx] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[fileidx],filecurrent); + fileidx = (fileidx + 1) % maxfiles; + } + } } // each proc with filewriter = 1 opens a file diff --git a/src/COMPRESS/dump_cfg_gz.cpp b/src/COMPRESS/dump_cfg_gz.cpp index a1ffa92ec8..aaeb878584 100644 --- a/src/COMPRESS/dump_cfg_gz.cpp +++ b/src/COMPRESS/dump_cfg_gz.cpp @@ -75,6 +75,19 @@ void DumpCFGGZ::openfile() sprintf(filecurrent,pad,filestar,update->ntimestep,ptr+1); } *ptr = '*'; + if (maxfiles > 0) { + if (numfiles < maxfiles) { + nameslist[numfiles] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[numfiles],filecurrent); + ++numfiles; + } else { + remove(nameslist[fileidx]); + delete[] nameslist[fileidx]; + nameslist[fileidx] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[fileidx],filecurrent); + fileidx = (fileidx + 1) % maxfiles; + } + } } // each proc with filewriter = 1 opens a file diff --git a/src/COMPRESS/dump_custom_gz.cpp b/src/COMPRESS/dump_custom_gz.cpp index 52d67445be..9c30f4742f 100644 --- a/src/COMPRESS/dump_custom_gz.cpp +++ b/src/COMPRESS/dump_custom_gz.cpp @@ -73,6 +73,19 @@ void DumpCustomGZ::openfile() sprintf(filecurrent,pad,filestar,update->ntimestep,ptr+1); } *ptr = '*'; + if (maxfiles > 0) { + if (numfiles < maxfiles) { + nameslist[numfiles] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[numfiles],filecurrent); + ++numfiles; + } else { + remove(nameslist[fileidx]); + delete[] nameslist[fileidx]; + nameslist[fileidx] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[fileidx],filecurrent); + fileidx = (fileidx + 1) % maxfiles; + } + } } // each proc with filewriter = 1 opens a file diff --git a/src/COMPRESS/dump_xyz_gz.cpp b/src/COMPRESS/dump_xyz_gz.cpp index 047ad8652f..7be1a10fe2 100644 --- a/src/COMPRESS/dump_xyz_gz.cpp +++ b/src/COMPRESS/dump_xyz_gz.cpp @@ -73,6 +73,19 @@ void DumpXYZGZ::openfile() sprintf(filecurrent,pad,filestar,update->ntimestep,ptr+1); } *ptr = '*'; + if (maxfiles > 0) { + if (numfiles < maxfiles) { + nameslist[numfiles] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[numfiles],filecurrent); + ++numfiles; + } else { + remove(nameslist[fileidx]); + delete[] nameslist[fileidx]; + nameslist[fileidx] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[fileidx],filecurrent); + fileidx = (fileidx + 1) % maxfiles; + } + } } // each proc with filewriter = 1 opens a file diff --git a/src/MPIIO/dump_atom_mpiio.cpp b/src/MPIIO/dump_atom_mpiio.cpp index 4422ef1cdf..f2f2991442 100644 --- a/src/MPIIO/dump_atom_mpiio.cpp +++ b/src/MPIIO/dump_atom_mpiio.cpp @@ -77,6 +77,19 @@ void DumpAtomMPIIO::openfile() sprintf(filecurrent,pad,filestar,update->ntimestep,ptr+1); } *ptr = '*'; + if (maxfiles > 0) { + if (numfiles < maxfiles) { + nameslist[numfiles] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[numfiles],filecurrent); + ++numfiles; + } else { + remove(nameslist[fileidx]); + delete[] nameslist[fileidx]; + nameslist[fileidx] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[fileidx],filecurrent); + fileidx = (fileidx + 1) % maxfiles; + } + } } if (append_flag) { // append open diff --git a/src/MPIIO/dump_cfg_mpiio.cpp b/src/MPIIO/dump_cfg_mpiio.cpp index 5086d1dc6c..09fd63bca5 100644 --- a/src/MPIIO/dump_cfg_mpiio.cpp +++ b/src/MPIIO/dump_cfg_mpiio.cpp @@ -96,6 +96,19 @@ void DumpCFGMPIIO::openfile() sprintf(filecurrent,pad,filestar,update->ntimestep,ptr+1); } *ptr = '*'; + if (maxfiles > 0) { + if (numfiles < maxfiles) { + nameslist[numfiles] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[numfiles],filecurrent); + ++numfiles; + } else { + remove(nameslist[fileidx]); + delete[] nameslist[fileidx]; + nameslist[fileidx] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[fileidx],filecurrent); + fileidx = (fileidx + 1) % maxfiles; + } + } } if (append_flag) { // append open diff --git a/src/MPIIO/dump_custom_mpiio.cpp b/src/MPIIO/dump_custom_mpiio.cpp index 2da6dd700d..ce981a7d1f 100644 --- a/src/MPIIO/dump_custom_mpiio.cpp +++ b/src/MPIIO/dump_custom_mpiio.cpp @@ -98,6 +98,19 @@ void DumpCustomMPIIO::openfile() sprintf(filecurrent,pad,filestar,update->ntimestep,ptr+1); } *ptr = '*'; + if (maxfiles > 0) { + if (numfiles < maxfiles) { + nameslist[numfiles] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[numfiles],filecurrent); + ++numfiles; + } else { + remove(nameslist[fileidx]); + delete[] nameslist[fileidx]; + nameslist[fileidx] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[fileidx],filecurrent); + fileidx = (fileidx + 1) % maxfiles; + } + } } if (append_flag) { // append open diff --git a/src/MPIIO/dump_xyz_mpiio.cpp b/src/MPIIO/dump_xyz_mpiio.cpp index 4725efccd1..804832ec1e 100644 --- a/src/MPIIO/dump_xyz_mpiio.cpp +++ b/src/MPIIO/dump_xyz_mpiio.cpp @@ -98,6 +98,19 @@ void DumpXYZMPIIO::openfile() sprintf(filecurrent,pad,filestar,update->ntimestep,ptr+1); } *ptr = '*'; + if (maxfiles > 0) { + if (numfiles < maxfiles) { + nameslist[numfiles] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[numfiles],filecurrent); + ++numfiles; + } else { + remove(nameslist[fileidx]); + delete[] nameslist[fileidx]; + nameslist[fileidx] = new char[strlen(filecurrent)+1]; + strcpy(nameslist[fileidx],filecurrent); + fileidx = (fileidx + 1) % maxfiles; + } + } } if (append_flag) { // append open diff --git a/src/dump.cpp b/src/dump.cpp index ce9fc9a0a9..12b35c3395 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -573,7 +573,7 @@ void Dump::openfile() strcpy(nameslist[fileidx],filecurrent); fileidx = (fileidx + 1) % maxfiles; } - } + } } // each proc with filewriter = 1 opens a file diff --git a/src/dump_custom.cpp b/src/dump_custom.cpp index 174fcd73c8..47108e309e 100644 --- a/src/dump_custom.cpp +++ b/src/dump_custom.cpp @@ -60,7 +60,7 @@ DumpCustom::DumpCustom(LAMMPS *lmp, int narg, char **arg) : earg(NULL), vtype(NULL), vformat(NULL), columns(NULL), choose(NULL), dchoose(NULL), clist(NULL), field2index(NULL), argindex(NULL), id_compute(NULL), compute(NULL), id_fix(NULL), fix(NULL), id_variable(NULL), variable(NULL), - vbuf(NULL), id_custom(NULL), flag_custom(NULL), typenames(NULL), + vbuf(NULL), id_custom(NULL), flag_custom(NULL), typenames(NULL), pack_choice(NULL) { if (narg == 5) error->all(FLERR,"No dump custom arguments specified"); @@ -1676,7 +1676,7 @@ int DumpCustom::modify_param(int narg, char **arg) if (strcmp(arg[0],"refresh") == 0) { if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); - if (strncmp(arg[1],"c_",2) != 0) + if (strncmp(arg[1],"c_",2) != 0) error->all(FLERR,"Illegal dump_modify command"); if (refreshflag) error->all(FLERR,"Dump modify can only have one refresh"); From 0f32d603b5472500454925917f3b995f761ca898 Mon Sep 17 00:00:00 2001 From: "Steven J. Plimpton" Date: Fri, 11 May 2018 15:52:18 -0600 Subject: [PATCH 3/5] tweaks to dump_modify maxfiles doc page --- doc/src/dump_modify.txt | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/doc/src/dump_modify.txt b/doc/src/dump_modify.txt index f4ce69af54..3230507dc3 100644 --- a/doc/src/dump_modify.txt +++ b/doc/src/dump_modify.txt @@ -37,8 +37,8 @@ keyword = {append} or {at} or {buffer} or {delay} or {element} or {every} or {fi {image} arg = {yes} or {no} {label} arg = string string = character string (e.g. BONDS) to use in header of dump local file - {maxfiles} arg = maxf - maxf = retain at most {maxf} files when writing one file per timestepq + {maxfiles} arg = Fmax + Fmax = keep only the most recent {Fmax} snapshots (one snapshot per file) {nfile} arg = Nf Nf = write this many files, one from each of Nf processors {pad} arg = Nchar = # of characters to convert timestep to @@ -366,12 +366,17 @@ e.g. BONDS or ANGLES. :line -The {maxfiles} keyword applies only to dumps with a '*' wildcard included -in the dump file name, i.e. when writing one file per frame. The number -following the keyword determines the maximum number of files being written. -If this number is reached, the olders dump file from the current sequence -is deleted before a new dump file is written. A {maxfiles} value of -1 -or 0 indicates that all files are retained. +The {maxfiles} keyword can only be used when a '*' wildcard is +included in the dump file name, i.e. when writing a new file(s) for +each snapshot. The specified {Fmax} is how many snapshots will be +kept. Once this number is reached, the file(s) containing the oldest +snapshot is deleted before a new dump file is written. If the +specified {Fmax} <= 0, then all files are retained. + +This can be useful for debugging, especially if you don't know on what +timestep something bad will happen, e.g. when LAMMPS will exit with an +error. You can dump every timestep, and limit the number of dump +files produced, even if you run for 1000s of steps. :line From f65b06de0e4dbcccab301ac11f0ea8db2513f149 Mon Sep 17 00:00:00 2001 From: "Steven J. Plimpton" Date: Fri, 11 May 2018 15:54:16 -0600 Subject: [PATCH 4/5] dump_modify maxfiles tweak --- src/dump.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dump.cpp b/src/dump.cpp index 12b35c3395..7c171015bb 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -193,6 +193,7 @@ Dump::~Dump() if (multiproc) MPI_Comm_free(&clustercomm); // delete storage for caching file names + if (maxfiles > 0) { for (int idx=0; idx < numfiles; ++idx) delete[] nameslist[idx]; From 233f03ea8ecbb54db17d872e81b6064fa3d60fb6 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 11 May 2018 18:03:49 -0400 Subject: [PATCH 5/5] windows portability bugfix --- lib/atc/Function.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/atc/Function.cpp b/lib/atc/Function.cpp index fb615e7bef..6004937a01 100644 --- a/lib/atc/Function.cpp +++ b/lib/atc/Function.cpp @@ -1,4 +1,6 @@ +#ifndef _WIN32 #include +#endif #include "Function.h" #include "ATC_Error.h" #include "LammpsInterface.h" @@ -59,7 +61,11 @@ namespace ATC { { string type = args[0]; int narg = nargs -1; +#ifdef _WIN32 + double *dargs = (double *) _alloca(sizeof(double) * narg); +#endif double *dargs = (double *) alloca(sizeof(double) * narg); +#endif for (int i = 0; i < narg; ++i) dargs[i] = atof(args[i+1]); return function(type, narg, dargs); @@ -193,7 +199,11 @@ XT_Function_Mgr * XT_Function_Mgr::myInstance_ = NULL; { string type = args[0]; int narg = nargs -1; +#ifdef _WIN32 + double *dargs = (double *) _alloca(sizeof(double) * narg); +#else double *dargs = (double *) alloca(sizeof(double) * narg); +#endif for (int i = 0; i < narg; ++i) dargs[i] = atof(args[i+1]); return function(type, narg, dargs);