more optimizations and extend to other dump styles

This commit is contained in:
Steve Plimpton
2021-12-21 10:57:42 -07:00
parent 4d31e300c6
commit ded48cc031
11 changed files with 106 additions and 61 deletions

View File

@ -200,15 +200,16 @@ will be accepted.
----------
The *every* keyword does two things. It specifies that the interval
between dump snapshots will be specified in timesteps, which is the
default if the *every* or *every/time* keywords are not used. See the
The *every* keyword can be used with any dump style except the *dcd*
and *xtc* styles. It does two things. It specifies that the interval
between dump snapshots will be set in timesteps, which is the default
if the *every* or *every/time* keywords are not used. See the
*every/time* keyword for how to specify the interval in simulation
time, i.e. in time units of the :doc:`units <units>` command. This
command also sets the interval value, which overrides the dump
time, i.e. in time units of the :doc:`units <units>` command. The
*every* keyword also sets the interval value, which overrides the dump
frequency originally specified by the :doc:`dump <dump>` command.
The every keyword can be specified in one of two ways. It can be a
The *every* keyword can be specified in one of two ways. It can be a
numeric value in which case it must be > 0. Or it can be an
:doc:`equal-style variable <variable>`, which should be specified as
v_name, where name is the variable name.
@ -266,13 +267,21 @@ in file tmp.times:
----------
The *every/time* keyword does two things. It specifies that the
interval between dump snapshots will be specified in simulation time,
The *every/time* keyword can be used with any dump style except the
*dcd* and *xtc* styles. It does two things. It specifies that the
interval between dump snapshots will be set in simulation time,
i.e. in time units of the :doc:`units <units>` command. This can be
useful when the timestep size varies during a simulation run, e.g. by
use of the :doc:`fix dt/reset <fix_dt_reset>` command. The default is
to specify the interval in timesteps; see the *every* keyword. This
command also sets the interval value.
to specify the interval in timesteps; see the *every* keyword. The
*every/time* command also sets the interval value.
.. note::
If you wish dump styles *atom*, *custom*, *local*, or *xyz* to
include the simulation time as a field in the header portion of
each snapshot, you also need to use the dump_modify *time* keyword
with a setting of *yes*. See its documentation below.
Note that since snapshots are output on simulation steps, each
snapshot will be written on the first timestep whose associated
@ -323,8 +332,8 @@ file tmp.times:
.. note::
When using a file-style variable with the *every* keyword, the file
of timesteps must list a first times that is beyond the time
When using a file-style variable with the *every/time* keyword, the
file of timesteps must list a first time that is beyond the time
associated with the current timestep (e.g. it cannot be 0.0). And
it must list one or more times beyond the length of the run you
perform. This is because the dump command will generate an error
@ -342,8 +351,8 @@ always occur if the current timestep is a multiple of $N$, the
frequency specified in the :doc:`dump <dump>` command or
:doc:`dump_modify every <dump_modify>` command, including timestep 0.
It will also always occur if the current simulation time is a multiple
of *Delta*, the time interval specified in the doc:`dump_modify every/time
<dump_modify>` command.
of *Delta*, the time interval specified in the doc:`dump_modify
every/time <dump_modify>` command.
But if this is not the case, a dump snapshot will only be written if
the setting of this keyword is *yes*\ . If it is *no*, which is the
@ -731,16 +740,20 @@ threshold criterion is met. Otherwise it is not met.
----------
The *time* keyword only applies to the dump *atom*, *custom*, and
*local* styles (and their COMPRESS package versions *atom/gz*,
*custom/gz* and *local/gz*\ ). If set to *yes*, each frame will will
contain two extra lines before the "ITEM: TIMESTEP" entry:
The *time* keyword only applies to the dump *atom*, *custom*, *local*,
and *xyz* styles (and their COMPRESS package versions *atom/gz*,
*custom/gz* and *local/gz*\ ). For the first 3 styles, if set to
*yes*, each frame will will contain two extra lines before the "ITEM:
TIMESTEP" entry:
.. parsed-literal::
ITEM: TIME
\<elapsed time\>
For the *xyz* style, the simulation time is included on the same line
as the timestep value.
This will output the current elapsed simulation time in current
time units equivalent to the :doc:`thermo keyword <thermo_style>` *time*\ .
This is to simplify post-processing of trajectories using a variable time

View File

@ -88,11 +88,17 @@ void DumpXYZGZ::openfile()
if (multifile) delete[] filecurrent;
}
/* ---------------------------------------------------------------------- */
void DumpXYZGZ::write_header(bigint ndump)
{
if (me == 0) {
std::string header = fmt::format("{}\n", ndump);
header += fmt::format("Atoms. Timestep: {}\n", update->ntimestep);
if (time_flag)
header += fmt::format("Atoms. Timestep: {} Time: {:.6f}\n",
update->ntimestep, update->atime);
else
header += fmt::format("Atoms. Timestep: {}\n", update->ntimestep);
writer.write(header.c_str(), header.length());
}
}

View File

@ -100,7 +100,11 @@ void DumpXYZZstd::write_header(bigint ndump)
{
if (me == 0) {
std::string header = fmt::format("{}\n", ndump);
header += fmt::format("Atoms. Timestep: {}\n", update->ntimestep);
if (time_flag)
header += fmt::format("Atoms. Timestep: {} Time: {:.6f}\n",
update->ntimestep, update->atime);
else
header += fmt::format("Atoms. Timestep: {}\n", update->ntimestep);
writer.write(header.c_str(), header.length());
}
}

View File

@ -100,13 +100,17 @@ void DumpDCD::init_style()
if (sort_flag == 0 || sortcol != 0)
error->all(FLERR,"Dump dcd requires sorting by atom ID");
// check that dump frequency has not changed and is not a variable
// but only when not being called from the "write_dump" command.
// check that dump modify settings are compatible with dcd
// but only when not being called from the "write_dump" command
if (strcmp(id,"WRITE_DUMP") != 0) {
int idump;
for (idump = 0; idump < output->ndump; idump++)
if (strcmp(id,output->dump[idump]->id) == 0) break;
if (output->mode_dump[idump] == 1)
error->all(FLERR,"Cannot use every/time setting for dump dcd");
if (output->every_dump[idump] == 0)
error->all(FLERR,"Cannot use variable every setting for dump dcd");

View File

@ -121,17 +121,24 @@ void DumpXTC::init_style()
if (flush_flag) error->all(FLERR,"Cannot set dump_modify flush for dump xtc");
// check that dump frequency has not changed and is not a variable
// check that dump modify settings are compatible with xtc
// but only when not being called from the "write_dump" command
int idump;
for (idump = 0; idump < output->ndump; idump++)
if (strcmp(id,output->dump[idump]->id) == 0) break;
if (output->every_dump[idump] == 0)
error->all(FLERR,"Cannot use variable every setting for dump xtc");
if (strcmp(id,"WRITE_DUMP") != 0) {
int idump;
for (idump = 0; idump < output->ndump; idump++)
if (strcmp(id,output->dump[idump]->id) == 0) break;
if (output->mode_dump[idump] == 1)
error->all(FLERR,"Cannot use every/time setting for dump xtc");
if (nevery_save == 0) nevery_save = output->every_dump[idump];
else if (nevery_save != output->every_dump[idump])
error->all(FLERR,"Cannot change dump_modify every for dump xtc");
if (output->every_dump[idump] == 0)
error->all(FLERR,"Cannot use every variable setting for dump xtc");
if (nevery_save == 0) nevery_save = output->every_dump[idump];
else if (nevery_save != output->every_dump[idump])
error->all(FLERR,"Cannot change dump_modify every for dump xtc");
}
}
/* ---------------------------------------------------------------------- */

View File

@ -26,7 +26,7 @@ class Dump : protected Pointers {
int igroup, groupbit; // group that Dump is performed on
int first_flag; // 0 if no initial dump, 1 if yes initial dump
int clearstep; // 1 if dump invokes computes, 0 if not
int clearstep; // 1 if dump can invoke computes, 0 if not
int comm_forward; // size of forward communication (0 if none)
int comm_reverse; // size of reverse communication (0 if none)
@ -75,7 +75,7 @@ class Dump : protected Pointers {
int sortcol; // 0 to sort on ID, 1-N on columns
int sortcolm1; // sortcol - 1
int sortorder; // ASCEND or DESCEND
int time_flag; // 1 if output accumulated time
int time_flag; // 1 if output simulation time
int unit_flag; // 1 if dump should contain unit information
int unit_count; // # of times the unit information was written
int delay_flag; // 1 if delay output until delaystep

View File

@ -131,7 +131,11 @@ void DumpXYZ::write_header(bigint n)
{
if (me == 0) {
fprintf(fp,BIGINT_FORMAT "\n",n);
fprintf(fp,"Atoms. Timestep: " BIGINT_FORMAT "\n",update->ntimestep);
if (time_flag)
fprintf(fp,"Atoms. Timestep: " BIGINT_FORMAT " Time: %f\n",
update->ntimestep, update->atime);
else
fprintf(fp,"Atoms. Timestep: " BIGINT_FORMAT "\n",update->ntimestep);
}
}
@ -159,7 +163,6 @@ void DumpXYZ::pack(tagint *ids)
}
}
/* ----------------------------------------------------------------------
convert mybuf of doubles to one big formatted string in sbuf
return -1 if strlen exceeds an int, since used as arg in MPI calls in Dump

View File

@ -121,14 +121,6 @@ void FixDtReset::init()
respaflag = 0;
if (utils::strmatch(update->integrate_style, "^respa")) respaflag = 1;
// check for DCD or XTC dumps
for (int i = 0; i < output->ndump; i++)
if ((strcmp(output->dump[i]->style, "dcd") == 0 ||
strcmp(output->dump[i]->style, "xtc") == 0) &&
comm->me == 0)
error->warning(FLERR, "Dump dcd/xtc timestamp may be wrong with fix dt/reset");
ftm2v = force->ftm2v;
mvv2e = force->mvv2e;
dt = update->dt;

View File

@ -118,11 +118,10 @@ void Integrate::ev_setup()
set eflag,vflag for current iteration
based on
(1) computes that need energy/virial info on this timestep
(2) time dumps that need unknown per-atom info on this timestep
NOTE: could not check time dumps if timestep size is not varying
(2) time dumps that may need per-atom compute info on this timestep
NOTE: inefficient to add all per-atom eng/virial computes
but don't know which ones the dump needs
see NOTE in output.cpp
also inefficient to add all per-atom eng/virial computes
but don't know which ones the dump needs
invoke matchstep() on all timestep-dependent computes to clear their arrays
eflag: set any or no bits
ENERGY_GLOBAL bit for global energy
@ -141,8 +140,8 @@ void Integrate::ev_set(bigint ntimestep)
int i,flag;
int tdflag = 0;
if (output->any_time_dumps)
tdflag = output->check_time_dumps(ntimestep);
if (output->any_time_dumps &&
output->next_time_dump_any == ntimestep) tdflag = 1;
flag = 0;
int eflag_global = 0;

View File

@ -12,6 +12,10 @@
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Michal Kanski (Jagiellonian U) for simulation time dumps
------------------------------------------------------------------------- */
#include "output.h"
#include "style_dump.h" // IWYU pragma: keep
@ -177,6 +181,8 @@ void Output::setup(int memflag)
// decide whether to write snapshot and/or calculate next step for dump
if (ndump && update->restrict_output == 0) {
next_time_dump_any = MAXBIGINT;
for (int idump = 0; idump < ndump; idump++) {
// wrap step dumps that invoke computes or do variable eval with clear/add
@ -237,6 +243,8 @@ void Output::setup(int memflag)
else modify->addstep_compute_all(next_dump[idump]);
}
if (mode_dump[idump] && (dump[idump]->clearstep || var_dump[idump]))
next_time_dump_any = MIN(next_time_dump_any,next_dump[idump]);
if (idump) next_dump_any = MIN(next_dump_any,next_dump[idump]);
else next_dump_any = next_dump[0];
}
@ -326,6 +334,9 @@ void Output::setup(int memflag)
// set next_dump_any to smallest next_dump
// wrap step dumps that invoke computes or do variable eval with clear/add
// NOTE:
// not wrapping time dumps means that Integrate::ev_set()
// needs to trigger all per-atom eng/virial computes
// on a timestep where any time dump will be output
// could wrap time dumps as well, if timestep size did not vary
// if wrap when timestep size varies frequently,
// then can do many unneeded addstep() --> inefficient
@ -336,7 +347,10 @@ void Output::setup(int memflag)
int writeflag;
if (next_dump_any == ntimestep) {
for (int idump = 0; idump < ndump; idump++) {
next_time_dump_any = MAXBIGINT;
if (next_dump[idump] == ntimestep) {
if (last_dump[idump] == ntimestep) continue;
@ -356,6 +370,8 @@ void Output::setup(int memflag)
modify->addstep_compute(next_dump[idump]);
}
if (mode_dump[idump] && (dump[idump]->clearstep || var_dump[idump]))
next_time_dump_any = MIN(next_time_dump_any,next_dump[idump]);
if (idump) next_dump_any = MIN(next_dump_any,next_dump[idump]);
else next_dump_any = next_dump[0];
}
@ -680,23 +696,23 @@ void Output::reset_dt()
{
bigint ntimestep = update->ntimestep;
next_dump_any = MAXBIGINT;
next_time_dump_any = MAXBIGINT;
for (int idump = 0; idump < ndump; idump++) {
if (mode_dump[idump] == 1) {
if (mode_dump[idump] == 0) continue;
// reset next_dump but do not change next_time_dump, 2 arg for reset_dt()
// do not invoke for a dump already scheduled for this step
// since timestep change affects next step
// reset next_dump but do not change next_time_dump, 2 arg for reset_dt()
// do not invoke for a dump already scheduled for this step
// since timestep change affects next step
if (next_dump[idump] != ntimestep)
calculate_next_dump(2,idump,update->ntimestep);
if (next_dump[idump] != ntimestep) {
calculate_next_dump(2,idump,update->ntimestep);
}
}
next_dump_any = MIN(next_dump_any,next_dump[idump]);
if (dump[idump]->clearstep || var_dump[idump])
next_time_dump_any = MIN(next_time_dump_any,next_dump[idump]);
}
next_dump_any = MIN(next_dump_any,next_time_dump_any);
next = MIN(next_dump_any,next_restart);
next = MIN(next,next_thermo);
}

View File

@ -35,7 +35,8 @@ class Output : protected Pointers {
int ndump; // # of Dumps defined
int max_dump; // max size of Dump list
bigint next_dump_any; // next timestep for any Dump
bigint next_dump_any; // next timestep for any dump
bigint next_time_dump_any; // next timestep for any time dump with computes
int any_time_dumps; // 1 if any time dump defined
int *mode_dump; // 0/1 if write every N timesteps or Delta in sim time
int *every_dump; // dump every N timesteps, 0 if variable