add diskfree check to fix halt

This commit is contained in:
Axel Kohlmeyer 2020-03-09 16:23:20 -04:00
parent 072ce8947b
commit 69a206f720
No known key found for this signature in database
GPG Key ID: D9B44E93BF0C375A
3 changed files with 118 additions and 45 deletions

View File

@ -14,23 +14,25 @@ Syntax
* ID, group-ID are documented in :doc:`fix <fix>` command * ID, group-ID are documented in :doc:`fix <fix>` command
* halt = style name of this fix command * halt = style name of this fix command
* N = check halt condition every N steps * N = check halt condition every N steps
* attribute = *bondmax* or *tlimit* or v\_name * attribute = *bondmax* or *tlimit* or *diskfree* or *v\_name*
.. parsed-literal:: .. parsed-literal::
bondmax = length of longest bond in the system bondmax = length of longest bond in the system (in length units)
tlimit = elapsed CPU time tlimit = elapsed CPU time (in seconds)
diskfree = free disk space (in megabytes)
v_name = name of :doc:`equal-style variable <variable>` v_name = name of :doc:`equal-style variable <variable>`
* operator = "<" or "<=" or ">" or ">=" or "==" or "!=" or "\|\^" * operator = "<" or "<=" or ">" or ">=" or "==" or "!=" or "\|\^"
* avalue = numeric value to compare attribute to * avalue = numeric value to compare attribute to
* zero or more keyword/value pairs may be appended * zero or more keyword/value pairs may be appended
* keyword = *error* or *message* * keyword = *error* or *message* or *path*
.. parsed-literal:: .. parsed-literal::
*error* value = *hard* or *soft* or *continue* *error* value = *hard* or *soft* or *continue*
*message* value = *yes* or *no* *message* value = *yes* or *no*
*path* value = path to check for free space (may be in quotes)
@ -38,25 +40,26 @@ Examples
"""""""" """"""""
.. parsed-literal:: .. code-block:: LAMMPS
fix 10 all halt 1 bondmax > 1.5 fix 10 all halt 1 bondmax > 1.5
fix 10 all print 10 v_myCheck != 0 error soft fix 10 all halt 10 v_myCheck != 0 error soft
fix 10 all halt 100 diskfree < 100000.0 path "dump storage/."
Description Description
""""""""""" """""""""""
Check a condition every N steps during a simulation run. N must be >= Check a condition every N steps during a simulation run. N must be >=1.
1. If the condition is met, exit the run immediately. In this If the condition is met, exit the run. In this context a "run" can be
context a "run" can be dynamics or minimization iterations, as dynamics or minimization iterations, as specified by the :doc:`run
specified by the :doc:`run <run>` or :doc:`minimize <minimize>` command. <run>` or :doc:`minimize <minimize>` command.
The specified group-ID is ignored by this fix. The specified group-ID is ignored by this fix.
The specified *attribute* can be one of the options listed above, The specified *attribute* can be one of the options listed above, namely
namely *bondmax* or *tlimit*\ , or an :doc:`equal-style variable <variable>` referenced as *v\_name*, where "name" is the *bondmax*, *tlimit*\ , *diskfree*\ , or an :doc:`equal-style variable
name of a variable that has been defined previously in the input <variable>` referenced as *v\_name*, where "name" is the name of a
script. variable that has been defined previously in the input script.
The *bondmax* attribute will loop over all bonds in the system, The *bondmax* attribute will loop over all bonds in the system,
compute their current lengths, and set *attribute* to the longest bond compute their current lengths, and set *attribute* to the longest bond
@ -80,6 +83,14 @@ a run is performing 1000s of timesteps/sec, the overhead for syncing
the timer frequently across a large number of processors may be the timer frequently across a large number of processors may be
non-negligible. non-negligible.
The *diskfree* attribute will check for available disk space (in
megabytes) on supported operating systems. By default it will
check the file system of the current working directory. This
can be changed with the optional *path* keyword, which will take
the path to a file or folder on the file system to be checked
as argument. This path must be given with single or double quotes,
if it contains blanks or other special characters (like \$).
Equal-style variables evaluate to a numeric value. See the Equal-style variables evaluate to a numeric value. See the
:doc:`variable <variable>` command for a description. They calculate :doc:`variable <variable>` command for a description. They calculate
formulas which can involve mathematical operations, atom properties, formulas which can involve mathematical operations, atom properties,
@ -91,7 +102,7 @@ following "bondmax" variable will calculate the same quantity as the
hstyle = bondmax option. hstyle = bondmax option.
.. parsed-literal:: .. code-block:: LAMMPS
compute bdist all bond/local dist compute bdist all bond/local dist
compute bmax all reduce max c_bdist compute bmax all reduce max c_bdist
@ -100,7 +111,7 @@ hstyle = bondmax option.
Thus these two versions of a fix halt command will do the same thing: Thus these two versions of a fix halt command will do the same thing:
.. parsed-literal:: .. code-block:: LAMMPS
fix 10 all halt 1 bondmax > 1.5 fix 10 all halt 1 bondmax > 1.5
fix 10 all halt 1 v_bondmax > 1.5 fix 10 all halt 1 v_bondmax > 1.5
@ -156,7 +167,7 @@ the :doc:`run <run>` command.
Restrictions Restrictions
"""""""""""" """"""""""""
none The *diskfree* attribute is currently only supported on Linux.
Related commands Related commands
"""""""""""""""" """"""""""""""""
@ -166,4 +177,4 @@ Related commands
Default Default
""""""" """""""
The option defaults are error = hard and message = yes. The option defaults are error = hard, message = yes, and path = ".".

View File

@ -29,7 +29,7 @@
using namespace LAMMPS_NS; using namespace LAMMPS_NS;
using namespace FixConst; using namespace FixConst;
enum{BONDMAX,TLIMIT,VARIABLE}; enum{BONDMAX,TLIMIT,DISKFREE,VARIABLE};
enum{LT,LE,GT,GE,EQ,NEQ,XOR}; enum{LT,LE,GT,GE,EQ,NEQ,XOR};
enum{HARD,SOFT,CONTINUE}; enum{HARD,SOFT,CONTINUE};
enum{NOMSG,YESMSG}; enum{NOMSG,YESMSG};
@ -37,7 +37,7 @@ enum{NOMSG,YESMSG};
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
FixHalt::FixHalt(LAMMPS *lmp, int narg, char **arg) : FixHalt::FixHalt(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg), idvar(NULL) Fix(lmp, narg, arg), idvar(NULL), dlimit_path(NULL)
{ {
if (narg < 7) error->all(FLERR,"Illegal fix halt command"); if (narg < 7) error->all(FLERR,"Illegal fix halt command");
nevery = force->inumeric(FLERR,arg[3]); nevery = force->inumeric(FLERR,arg[3]);
@ -46,37 +46,45 @@ FixHalt::FixHalt(LAMMPS *lmp, int narg, char **arg) :
// comparison args // comparison args
idvar = NULL; idvar = NULL;
int iarg = 4;
if (strcmp(arg[4],"tlimit") == 0) attribute = TLIMIT; if (strcmp(arg[iarg],"tlimit") == 0) {
else if (strcmp(arg[4],"bondmax") == 0) attribute = BONDMAX; attribute = TLIMIT;
else if (strncmp(arg[4],"v_",2) == 0) { } else if (strcmp(arg[iarg],"diskfree") == 0) {
attribute = DISKFREE;
dlimit_path = new char[2];
strcpy(dlimit_path,".");
} else if (strcmp(arg[iarg],"bondmax") == 0) {
attribute = BONDMAX;
} else if (strncmp(arg[iarg],"v_",2) == 0) {
attribute = VARIABLE; attribute = VARIABLE;
int n = strlen(arg[4]); int n = strlen(arg[iarg]);
idvar = new char[n]; idvar = new char[n];
strcpy(idvar,&arg[4][2]); strcpy(idvar,&arg[iarg][2]);
ivar = input->variable->find(idvar); ivar = input->variable->find(idvar);
if (ivar < 0) error->all(FLERR,"Could not find fix halt variable name"); if (ivar < 0) error->all(FLERR,"Could not find fix halt variable name");
if (input->variable->equalstyle(ivar) == 0) if (input->variable->equalstyle(ivar) == 0)
error->all(FLERR,"Fix halt variable is not equal-style variable"); error->all(FLERR,"Fix halt variable is not equal-style variable");
} else error->all(FLERR,"Invalid fix halt attribute"); } else error->all(FLERR,"Invalid fix halt attribute");
if (strcmp(arg[5],"<") == 0) operation = LT; ++iarg;
else if (strcmp(arg[5],"<=") == 0) operation = LE; if (strcmp(arg[iarg],"<") == 0) operation = LT;
else if (strcmp(arg[5],">") == 0) operation = GT; else if (strcmp(arg[iarg],"<=") == 0) operation = LE;
else if (strcmp(arg[5],">=") == 0) operation = GE; else if (strcmp(arg[iarg],">") == 0) operation = GT;
else if (strcmp(arg[5],"==") == 0) operation = EQ; else if (strcmp(arg[iarg],">=") == 0) operation = GE;
else if (strcmp(arg[5],"!=") == 0) operation = NEQ; else if (strcmp(arg[iarg],"==") == 0) operation = EQ;
else if (strcmp(arg[5],"|^") == 0) operation = XOR; else if (strcmp(arg[iarg],"!=") == 0) operation = NEQ;
else if (strcmp(arg[iarg],"|^") == 0) operation = XOR;
else error->all(FLERR,"Invalid fix halt operator"); else error->all(FLERR,"Invalid fix halt operator");
value = force->numeric(FLERR,arg[6]); ++iarg;
value = force->numeric(FLERR,arg[iarg]);
// parse optional args // parse optional args
eflag = SOFT; eflag = SOFT;
msgflag = YESMSG; msgflag = YESMSG;
++iarg;
int iarg = 7;
while (iarg < narg) { while (iarg < narg) {
if (strcmp(arg[iarg],"error") == 0) { if (strcmp(arg[iarg],"error") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix halt command"); if (iarg+2 > narg) error->all(FLERR,"Illegal fix halt command");
@ -91,6 +99,19 @@ FixHalt::FixHalt(LAMMPS *lmp, int narg, char **arg) :
else if (strcmp(arg[iarg+1],"yes") == 0) msgflag = YESMSG; else if (strcmp(arg[iarg+1],"yes") == 0) msgflag = YESMSG;
else error->all(FLERR,"Illegal fix halt command"); else error->all(FLERR,"Illegal fix halt command");
iarg += 2; iarg += 2;
} else if (strcmp(arg[iarg],"path") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix halt command");
++iarg;
int len = strlen(arg[iarg])+1;
delete[] dlimit_path;
dlimit_path = new char[len];
// strip off quotes, if present
if ( ((arg[iarg][0] == '"') || (arg[iarg][0] == '\''))
&& (arg[iarg][0] == arg[iarg][len-2]) ) {
strcpy(dlimit_path,&arg[iarg][1]);
dlimit_path[len-3] = '\0';
} else strcpy(dlimit_path,arg[iarg]);
++iarg;
} else error->all(FLERR,"Illegal fix halt command"); } else error->all(FLERR,"Illegal fix halt command");
} }
@ -109,6 +130,7 @@ FixHalt::FixHalt(LAMMPS *lmp, int narg, char **arg) :
FixHalt::~FixHalt() FixHalt::~FixHalt()
{ {
delete [] idvar; delete [] idvar;
delete [] dlimit_path;
} }
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
@ -140,6 +162,13 @@ void FixHalt::init()
nextstep = (update->ntimestep/nevery)*nevery + nevery; nextstep = (update->ntimestep/nevery)*nevery + nevery;
thisstep = -1; thisstep = -1;
tratio = 0.5; tratio = 0.5;
// check if disk limit is supported
if (attribute == DISKFREE) {
if (diskfree() < 0.0)
error->all(FLERR,"Disk limit not supported by OS or illegal path");
}
} }
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
@ -162,6 +191,8 @@ void FixHalt::end_of_step()
if (attribute == TLIMIT) { if (attribute == TLIMIT) {
if (update->ntimestep != nextstep) return; if (update->ntimestep != nextstep) return;
attvalue = tlimit(); attvalue = tlimit();
} else if (attribute == DISKFREE) {
attvalue = diskfree();
} else if (attribute == BONDMAX) { } else if (attribute == BONDMAX) {
attvalue = bondmax(); attvalue = bondmax();
} else { } else {
@ -194,7 +225,8 @@ void FixHalt::end_of_step()
// print message with ID of fix halt in case multiple instances // print message with ID of fix halt in case multiple instances
char str[128]; char str[128];
sprintf(str,"Fix halt %s condition met on step " BIGINT_FORMAT " with value %g", sprintf(str,"Fix halt condition for fix-id %s met on step "
BIGINT_FORMAT " with value %g",
id, update->ntimestep, attvalue); id, update->ntimestep, attvalue);
if (eflag == HARD) { if (eflag == HARD) {
@ -270,3 +302,31 @@ double FixHalt::tlimit()
return cpu; return cpu;
} }
/* ----------------------------------------------------------------------
determine available disk space, if supported. Return -1 if not.
------------------------------------------------------------------------- */
#if defined(__linux)
#include <sys/statvfs.h>
#endif
double FixHalt::diskfree()
{
#if defined(__linux)
struct statvfs fs;
double disk_free = -1.0;
if (dlimit_path) {
disk_free = 1.0e100;
int rv = statvfs(dlimit_path,&fs);
if (rv == 0)
disk_free = fs.f_bavail*fs.f_bsize/1048576.0;
else
disk_free = -1.0;
MPI_Bcast(&disk_free,1,MPI_DOUBLE,0,world);
}
return disk_free;
#else
return -1.0;
#endif
}

View File

@ -39,9 +39,11 @@ class FixHalt : public Fix {
bigint nextstep,thisstep; bigint nextstep,thisstep;
double value,tratio; double value,tratio;
char *idvar; char *idvar;
char *dlimit_path;
double bondmax(); double bondmax();
double tlimit(); double tlimit();
double diskfree();
}; };
} }
@ -59,26 +61,26 @@ command-line option when running LAMMPS to see the offending line.
E: Could not find fix halt variable name E: Could not find fix halt variable name
UNDOCUMENTED Self-explanatory.
E: Fix halt variable is not equal-style variable E: Fix halt variable is not equal-style variable
UNDOCUMENTED Self-explanatory.
E: Invalid fix halt attribute E: Invalid fix halt attribute
UNDOCUMENTED Self-explanatory.
E: Invalid fix halt operator E: Invalid fix halt operator
UNDOCUMENTED Self-explanatory.
E: Fix halt %s condition met on step %ld with value %g E: Disk limit not supported by OS or illegal path
UNDOCUMENTED Self-explanatory.
U: Cannot open fix print file %s W: Fix halt condition for fix-id %s met on step %ld with value %g
The output file generated by the fix print command cannot be opened Self explanatory.
*/ */