Merge pull request #3248 from akohlmey/add_set_time
Add time option to the "reset_timestep" command and make the "time" property restartable
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 24 KiB |
@ -8,9 +8,16 @@ Syntax
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
reset_timestep N
|
||||
reset_timestep N keyword values ...
|
||||
|
||||
* N = timestep number
|
||||
* zero or more keyword/value pairs may be appended
|
||||
* keyword = *time*
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
*time* value = atime
|
||||
atime = accumulated simulation time
|
||||
|
||||
Examples
|
||||
""""""""
|
||||
@ -19,48 +26,56 @@ Examples
|
||||
|
||||
reset_timestep 0
|
||||
reset_timestep 4000000
|
||||
reset_timestep 1000 time 100.0
|
||||
|
||||
Description
|
||||
"""""""""""
|
||||
|
||||
Set the timestep counter to the specified value. This command
|
||||
normally comes after the timestep has been set by reading a restart
|
||||
usually comes after the timestep has been set by reading a restart
|
||||
file via the :doc:`read_restart <read_restart>` command, or a previous
|
||||
simulation advanced the timestep.
|
||||
simulation run or minimization advanced the timestep.
|
||||
|
||||
The optional *time* keyword allows to also set the accumulated
|
||||
simulation time. This is usually the number of timesteps times
|
||||
the size of the timestep, but when using variable size timesteps
|
||||
with :doc:`fix dt/reset <fix_dt_reset>` it can differ.
|
||||
|
||||
The :doc:`read_data <read_data>` and :doc:`create_box <create_box>`
|
||||
commands set the timestep to 0; the :doc:`read_restart <read_restart>`
|
||||
command sets the timestep to the value it had when the restart file
|
||||
was written.
|
||||
was written. The same applies to the accumulated simulation time.
|
||||
|
||||
|
||||
Restrictions
|
||||
""""""""""""
|
||||
none
|
||||
|
||||
This command cannot be used when any fixes are defined that keep track
|
||||
of elapsed time to perform certain kinds of time-dependent operations.
|
||||
Examples are the :doc:`fix deposit <fix_deposit>` and :doc:`fix dt/reset <fix_dt_reset>` commands. The former adds atoms on
|
||||
specific timesteps. The latter keeps track of accumulated time.
|
||||
Examples are the :doc:`fix deposit <fix_deposit>` and :doc:`fix dt/reset
|
||||
<fix_dt_reset>` commands. The former adds atoms on specific timesteps.
|
||||
The latter keeps track of accumulated time.
|
||||
|
||||
Various fixes use the current timestep to calculate related
|
||||
quantities. If the timestep is reset, this may produce unexpected
|
||||
behavior, but LAMMPS allows the fixes to be defined even if the
|
||||
timestep is reset. For example, commands which thermostat the system,
|
||||
e.g. :doc:`fix nvt <fix_nh>`, allow you to specify a target temperature
|
||||
which ramps from Tstart to Tstop which may persist over several runs.
|
||||
If you change the timestep, you may induce an instantaneous change in
|
||||
the target temperature.
|
||||
Various fixes use the current timestep to calculate related quantities.
|
||||
If the timestep is reset, this may produce unexpected behavior, but
|
||||
LAMMPS allows the fixes to be defined even if the timestep is reset.
|
||||
For example, commands which thermostat the system, e.g. :doc:`fix nvt
|
||||
<fix_nh>`, allow you to specify a target temperature which ramps from
|
||||
Tstart to Tstop which may persist over several runs. If you change the
|
||||
timestep, you may induce an instantaneous change in the target
|
||||
temperature.
|
||||
|
||||
Resetting the timestep clears flags for :doc:`computes <compute>` that
|
||||
may have calculated some quantity from a previous run. This means
|
||||
these quantity cannot be accessed by a variable in between runs until
|
||||
a new run is performed. See the :doc:`variable <variable>` command for
|
||||
more details.
|
||||
may have calculated some quantity from a previous run. This means these
|
||||
quantity cannot be accessed by a variable in between runs until a new
|
||||
run is performed. See the :doc:`variable <variable>` command for more
|
||||
details.
|
||||
|
||||
Related commands
|
||||
""""""""""""""""
|
||||
|
||||
:doc:`rerun <rerun>`
|
||||
:doc:`rerun <rerun>`, :doc:`timestep <timestep>`,
|
||||
:doc:`fix dt/reset <fix_dt_reset>`
|
||||
|
||||
Default
|
||||
"""""""
|
||||
|
||||
@ -39,8 +39,9 @@ Description
|
||||
|
||||
Calculate the third order force constant tensor by finite difference of the selected group,
|
||||
|
||||
.. image:: JPG/third_order_force_constant.png
|
||||
:align: center
|
||||
.. math::
|
||||
|
||||
\Phi^{\alpha\beta\gamma}_{ijk} = \frac{\partial^3 U}{\partial x_{i,\alpha} \partial x_{j,\beta} \partial x_{k, \gamma}}
|
||||
|
||||
where Phi is the third order force constant tensor.
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
#define MAGIC_STRING "LammpS RestartT"
|
||||
#define ENDIAN 0x0001
|
||||
#define ENDIANSWAP 0x1000
|
||||
#define FORMAT_REVISION 2
|
||||
#define FORMAT_REVISION 3
|
||||
|
||||
enum{VERSION,SMALLINT,TAGINT,BIGINT,
|
||||
UNITS,NTIMESTEP,DIMENSION,NPROCS,PROCGRID,
|
||||
@ -37,7 +37,8 @@ enum{VERSION,SMALLINT,TAGINT,BIGINT,
|
||||
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,
|
||||
NELLIPSOIDS,NLINES,NTRIS,NBODIES};
|
||||
NELLIPSOIDS,NLINES,NTRIS,NBODIES,
|
||||
ATIME,ATIMESTEP};
|
||||
|
||||
#define LB_FACTOR 1.1
|
||||
|
||||
|
||||
@ -744,11 +744,11 @@ void Output::add_dump(int narg, char **arg)
|
||||
|
||||
for (int idump = 0; idump < ndump; idump++)
|
||||
if (strcmp(arg[0],dump[idump]->id) == 0)
|
||||
error->all(FLERR,"Reuse of dump ID");
|
||||
error->all(FLERR,"Reuse of dump ID: {}", arg[0]);
|
||||
int igroup = group->find(arg[1]);
|
||||
if (igroup == -1) error->all(FLERR,"Could not find dump group ID");
|
||||
if (igroup == -1) error->all(FLERR,"Could not find dump group ID: {}", arg[1]);
|
||||
if (utils::inumeric(FLERR,arg[3],false,lmp) <= 0)
|
||||
error->all(FLERR,"Invalid dump frequency");
|
||||
error->all(FLERR,"Invalid dump frequency {}", arg[3]);
|
||||
|
||||
// extend Dump list if necessary
|
||||
|
||||
@ -794,14 +794,14 @@ void Output::add_dump(int narg, char **arg)
|
||||
|
||||
void Output::modify_dump(int narg, char **arg)
|
||||
{
|
||||
if (narg < 1) error->all(FLERR,"Illegal dump_modify command");
|
||||
if (narg < 1) utils::missing_cmd_args(FLERR, "dump_modify",error);
|
||||
|
||||
// find which dump it is
|
||||
|
||||
int idump;
|
||||
for (idump = 0; idump < ndump; idump++)
|
||||
if (strcmp(arg[0],dump[idump]->id) == 0) break;
|
||||
if (idump == ndump) error->all(FLERR,"Cound not find dump_modify ID");
|
||||
if (idump == ndump) error->all(FLERR,"Could not find dump_modify ID: {}", arg[0]);
|
||||
|
||||
dump[idump]->modify_params(narg-1,&arg[1]);
|
||||
}
|
||||
@ -817,7 +817,7 @@ void Output::delete_dump(char *id)
|
||||
int idump;
|
||||
for (idump = 0; idump < ndump; idump++)
|
||||
if (strcmp(id,dump[idump]->id) == 0) break;
|
||||
if (idump == ndump) error->all(FLERR,"Could not find undump ID");
|
||||
if (idump == ndump) error->all(FLERR,"Could not find undump ID: {}", id);
|
||||
|
||||
delete dump[idump];
|
||||
delete[] var_dump[idump];
|
||||
@ -871,7 +871,7 @@ void Output::set_thermo(int narg, char **arg)
|
||||
var_thermo = utils::strdup(arg[0]+2);
|
||||
} else {
|
||||
thermo_every = utils::inumeric(FLERR,arg[0],false,lmp);
|
||||
if (thermo_every < 0) error->all(FLERR,"Illegal thermo command");
|
||||
if (thermo_every < 0) error->all(FLERR,"Illegal thermo output frequency {}", thermo_every);
|
||||
}
|
||||
}
|
||||
|
||||
@ -881,7 +881,7 @@ void Output::set_thermo(int narg, char **arg)
|
||||
|
||||
void Output::create_thermo(int narg, char **arg)
|
||||
{
|
||||
if (narg < 1) error->all(FLERR,"Illegal thermo_style command");
|
||||
if (narg < 1) utils::missing_cmd_args(FLERR, "thermo_style", error);
|
||||
|
||||
// don't allow this so that dipole style can safely allocate inertia vector
|
||||
|
||||
@ -891,8 +891,7 @@ void Output::create_thermo(int narg, char **arg)
|
||||
// warn if previous thermo had been modified via thermo_modify command
|
||||
|
||||
if (thermo->modified && comm->me == 0)
|
||||
error->warning(FLERR,"New thermo_style command, "
|
||||
"previous thermo_modify settings will be lost");
|
||||
error->warning(FLERR,"New thermo_style command, previous thermo_modify settings will be lost");
|
||||
|
||||
// set thermo = nullptr in case new Thermo throws an error
|
||||
|
||||
@ -908,7 +907,7 @@ void Output::create_thermo(int narg, char **arg)
|
||||
|
||||
void Output::create_restart(int narg, char **arg)
|
||||
{
|
||||
if (narg < 1) error->all(FLERR,"Illegal restart command");
|
||||
if (narg < 1) utils::missing_cmd_args(FLERR, "restart", error);
|
||||
|
||||
int every = 0;
|
||||
int varflag = 0;
|
||||
|
||||
@ -284,7 +284,7 @@ void Pair::init()
|
||||
|
||||
if (!manybody_flag && (comm->me == 0)) {
|
||||
const int num_mixed_pairs = atom->ntypes * (atom->ntypes - 1) / 2;
|
||||
utils::logmesg(lmp," generated {} of {} mixed pair_coeff terms from {} mixing rule\n",
|
||||
utils::logmesg(lmp,"Generated {} of {} mixed pair_coeff terms from {} mixing rule\n",
|
||||
mixed_count, num_mixed_pairs, mixing_rule_names[mix_flag]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -594,21 +594,18 @@ void ReadRestart::header()
|
||||
if (flag == VERSION) {
|
||||
char *version = read_string();
|
||||
if (me == 0)
|
||||
utils::logmesg(lmp," restart file = {}, LAMMPS = {}\n",
|
||||
version,lmp->version);
|
||||
utils::logmesg(lmp," restart file = {}, LAMMPS = {}\n", version, lmp->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");
|
||||
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.");
|
||||
error->warning(FLERR,"Old restart file format revision. Switching to compatibility mode.");
|
||||
|
||||
// check lmptype.h sizes, error if different
|
||||
|
||||
@ -654,8 +651,8 @@ void ReadRestart::header()
|
||||
} else if (flag == NPROCS) {
|
||||
nprocs_file = read_int();
|
||||
if (nprocs_file != comm->nprocs && me == 0)
|
||||
error->warning(FLERR,"Restart file used different # of processors: "
|
||||
"{} vs. {}",nprocs_file,comm->nprocs);
|
||||
error->warning(FLERR,"Restart file used different # of processors: {} vs. {}",
|
||||
nprocs_file,comm->nprocs);
|
||||
|
||||
// don't set procgrid, warn if different
|
||||
|
||||
@ -681,16 +678,14 @@ void ReadRestart::header()
|
||||
int newton_pair_file = read_int();
|
||||
if (force->newton_pair != 1) {
|
||||
if (newton_pair_file != force->newton_pair && me == 0)
|
||||
error->warning(FLERR,
|
||||
"Restart file used different newton pair setting, "
|
||||
error->warning(FLERR, "Restart file used different newton pair setting, "
|
||||
"using input script value");
|
||||
}
|
||||
} else if (flag == NEWTON_BOND) {
|
||||
int newton_bond_file = read_int();
|
||||
if (force->newton_bond != 1) {
|
||||
if (newton_bond_file != force->newton_bond && me == 0)
|
||||
error->warning(FLERR,
|
||||
"Restart file used different newton bond setting, "
|
||||
error->warning(FLERR, "Restart file used different newton bond setting, "
|
||||
"using restart file value");
|
||||
}
|
||||
force->newton_bond = newton_bond_file;
|
||||
@ -721,8 +716,7 @@ void ReadRestart::header()
|
||||
boundary[2][0] != domain->boundary[2][0] ||
|
||||
boundary[2][1] != domain->boundary[2][1]) {
|
||||
if (me == 0)
|
||||
error->warning(FLERR,
|
||||
"Restart file used different boundary settings, "
|
||||
error->warning(FLERR, "Restart file used different boundary settings, "
|
||||
"using restart file values");
|
||||
}
|
||||
}
|
||||
@ -864,6 +858,13 @@ void ReadRestart::header()
|
||||
} else if (flag == NBODIES) {
|
||||
atom->nbodies = read_bigint();
|
||||
|
||||
} else if (flag == ATIMESTEP) {
|
||||
update->atimestep = read_bigint();
|
||||
} else if (flag == ATIME) {
|
||||
update->atime = read_double();
|
||||
|
||||
// set dimension from restart file
|
||||
|
||||
// for backward compatibility
|
||||
} else if (flag == EXTRA_SPECIAL_PER_ATOM) {
|
||||
force->special_extra = read_int();
|
||||
|
||||
@ -457,9 +457,18 @@ void Update::new_minimize(char *style, int /* narg */, char ** /* arg */, int tr
|
||||
|
||||
void Update::reset_timestep(int narg, char **arg)
|
||||
{
|
||||
if (narg != 1) error->all(FLERR, "Illegal reset_timestep command");
|
||||
bigint newstep = utils::bnumeric(FLERR, arg[0], false, lmp);
|
||||
reset_timestep(newstep, true);
|
||||
if (narg < 1) utils::missing_cmd_args(FLERR, "reset_timestep", error);
|
||||
|
||||
reset_timestep(utils::bnumeric(FLERR, arg[0], false, lmp), true);
|
||||
|
||||
if (narg > 1) {
|
||||
if (strcmp(arg[1], "time") == 0) {
|
||||
if (narg < 3) utils::missing_cmd_args(FLERR, "reset_timestep time", error);
|
||||
atimestep = ntimestep;
|
||||
atime = utils::numeric(FLERR, arg[2], false, lmp);
|
||||
} else
|
||||
error->all(FLERR, "Unknown reset_timestep option {}", arg[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
|
||||
@ -27,7 +27,7 @@ class Update : protected Pointers {
|
||||
bigint ntimestep; // current step (dynamics or min iterations)
|
||||
int nsteps; // # of steps to run (dynamics or min iter)
|
||||
int whichflag; // 0 for unset, 1 for dynamics, 2 for min
|
||||
double atime; // simulation time at atime_step
|
||||
double atime; // simulation time at atimestep
|
||||
bigint atimestep; // last timestep atime was updated
|
||||
bigint firststep, laststep; // 1st & last step of this run
|
||||
bigint beginstep, endstep; // 1st and last step of multiple runs
|
||||
|
||||
@ -118,8 +118,7 @@ void WriteRestart::command(int narg, char **arg)
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void WriteRestart::multiproc_options(int multiproc_caller, int mpiioflag_caller,
|
||||
int narg, char **arg)
|
||||
void WriteRestart::multiproc_options(int multiproc_caller, int mpiioflag_caller, int narg, char **arg)
|
||||
{
|
||||
multiproc = multiproc_caller;
|
||||
mpiioflag = mpiioflag_caller;
|
||||
@ -127,14 +126,12 @@ void WriteRestart::multiproc_options(int multiproc_caller, int mpiioflag_caller,
|
||||
// error checks
|
||||
|
||||
if (multiproc && mpiioflag)
|
||||
error->all(FLERR,
|
||||
"Restart file MPI-IO output not allowed with % in filename");
|
||||
error->all(FLERR,"Restart file MPI-IO output not allowed with % in filename");
|
||||
|
||||
if (mpiioflag) {
|
||||
mpiio = new RestartMPIIO(lmp);
|
||||
if (!mpiio->mpiio_exists)
|
||||
error->all(FLERR,"Writing to MPI-IO filename when "
|
||||
"MPIIO package is not installed");
|
||||
error->all(FLERR,"Writing to MPI-IO filename when MPIIO package is not installed");
|
||||
}
|
||||
|
||||
// defaults for multiproc file writing
|
||||
@ -158,8 +155,7 @@ void WriteRestart::multiproc_options(int multiproc_caller, int mpiioflag_caller,
|
||||
if (strcmp(arg[iarg],"fileper") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal write_restart command");
|
||||
if (!multiproc)
|
||||
error->all(FLERR,"Cannot use write_restart fileper "
|
||||
"without % in restart file name");
|
||||
error->all(FLERR,"Cannot use write_restart fileper without % in restart file name");
|
||||
int nper = utils::inumeric(FLERR,arg[iarg+1],false,lmp);
|
||||
if (nper <= 0) error->all(FLERR,"Illegal write_restart command");
|
||||
|
||||
@ -176,8 +172,7 @@ void WriteRestart::multiproc_options(int multiproc_caller, int mpiioflag_caller,
|
||||
} else if (strcmp(arg[iarg],"nfile") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal write_restart command");
|
||||
if (!multiproc)
|
||||
error->all(FLERR,"Cannot use write_restart nfile "
|
||||
"without % in restart file name");
|
||||
error->all(FLERR,"Cannot use write_restart nfile without % in restart file name");
|
||||
int nfile = utils::inumeric(FLERR,arg[iarg+1],false,lmp);
|
||||
if (nfile <= 0) error->all(FLERR,"Illegal write_restart command");
|
||||
nfile = MIN(nfile,nprocs);
|
||||
@ -510,6 +505,11 @@ void WriteRestart::header()
|
||||
write_bigint(NTRIS,atom->ntris);
|
||||
write_bigint(NBODIES,atom->nbodies);
|
||||
|
||||
// write out current simulation time. added 3 May 2022
|
||||
|
||||
write_bigint(ATIMESTEP,update->atimestep);
|
||||
write_double(ATIME,update->atime);
|
||||
|
||||
// -1 flag signals end of header
|
||||
|
||||
int flag = -1;
|
||||
|
||||
@ -224,20 +224,35 @@ TEST_F(SimpleCommandsTest, Quit)
|
||||
TEST_F(SimpleCommandsTest, ResetTimestep)
|
||||
{
|
||||
ASSERT_EQ(lmp->update->ntimestep, 0);
|
||||
ASSERT_EQ(lmp->update->atimestep, 0);
|
||||
ASSERT_DOUBLE_EQ(lmp->update->atime, 0.0);
|
||||
|
||||
BEGIN_HIDE_OUTPUT();
|
||||
command("reset_timestep 10");
|
||||
END_HIDE_OUTPUT();
|
||||
ASSERT_EQ(lmp->update->ntimestep, 10);
|
||||
ASSERT_EQ(lmp->update->atimestep, 10);
|
||||
ASSERT_DOUBLE_EQ(lmp->update->atime, lmp->update->dt * 10);
|
||||
|
||||
BEGIN_HIDE_OUTPUT();
|
||||
command("reset_timestep 0");
|
||||
END_HIDE_OUTPUT();
|
||||
ASSERT_EQ(lmp->update->ntimestep, 0);
|
||||
ASSERT_EQ(lmp->update->atimestep, 0);
|
||||
ASSERT_DOUBLE_EQ(lmp->update->atime, 0.0);
|
||||
|
||||
BEGIN_HIDE_OUTPUT();
|
||||
command("reset_timestep 10 time 100.0");
|
||||
END_HIDE_OUTPUT();
|
||||
ASSERT_EQ(lmp->update->ntimestep, 10);
|
||||
ASSERT_EQ(lmp->update->atimestep, 10);
|
||||
ASSERT_DOUBLE_EQ(lmp->update->atime, 100.0);
|
||||
|
||||
TEST_FAILURE(".*ERROR: Timestep must be >= 0.*", command("reset_timestep -10"););
|
||||
TEST_FAILURE(".*ERROR: Illegal reset_timestep .*", command("reset_timestep"););
|
||||
TEST_FAILURE(".*ERROR: Illegal reset_timestep .*", command("reset_timestep 10 10"););
|
||||
TEST_FAILURE(".*ERROR: Unknown reset_timestep option 10.*", command("reset_timestep 10 10"););
|
||||
TEST_FAILURE(".*ERROR: Illegal reset_timestep .*", command("reset_timestep 10 time"););
|
||||
TEST_FAILURE(".*ERROR: Expected floating .**", command("reset_timestep 10 time xxx"););
|
||||
TEST_FAILURE(".*ERROR: Expected integer .*", command("reset_timestep xxx"););
|
||||
}
|
||||
|
||||
@ -325,7 +340,7 @@ TEST_F(SimpleCommandsTest, Thermo)
|
||||
ASSERT_EQ(lmp->output->var_thermo, nullptr);
|
||||
|
||||
TEST_FAILURE(".*ERROR: Illegal thermo command.*", command("thermo"););
|
||||
TEST_FAILURE(".*ERROR: Illegal thermo command.*", command("thermo -1"););
|
||||
TEST_FAILURE(".*ERROR: Illegal thermo output frequency.*", command("thermo -1"););
|
||||
TEST_FAILURE(".*ERROR: Expected integer.*", command("thermo xxx"););
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user