bug fixes to make a series of test inputs run correctly

This commit is contained in:
Steve Plimpton
2021-12-08 16:44:51 -07:00
parent 26492b13d5
commit d4149e9139
8 changed files with 342 additions and 160 deletions

View File

@ -169,11 +169,12 @@ or multiple smaller files).
.. note::
Because periodic boundary conditions are enforced only on
timesteps when neighbor lists are rebuilt, the coordinates of an atom
written to a dump file may be slightly outside the simulation box.
Re-neighbor timesteps will not typically coincide with the timesteps
dump snapshots are written. See the :doc:`dump_modify pbc <dump_modify>` command if you with to force coordinates to be
Because periodic boundary conditions are enforced only on timesteps
when neighbor lists are rebuilt, the coordinates of an atom written
to a dump file may be slightly outside the simulation box.
Re-neighbor timesteps will not typically coincide with the
timesteps dump snapshots are written. See the :doc:`dump_modify
pbc <dump_modify>` command if you with to force coordinates to be
strictly inside the simulation box.
.. note::
@ -189,20 +190,21 @@ or multiple smaller files).
multiple processors, each of which owns a subset of the atoms.
For the *atom*, *custom*, *cfg*, and *local* styles, sorting is off by
default. For the *dcd*, *xtc*, *xyz*, and *molfile* styles, sorting by
atom ID is on by default. See the :doc:`dump_modify <dump_modify>` doc
page for details.
default. For the *dcd*, *xtc*, *xyz*, and *molfile* styles, sorting
by atom ID is on by default. See the :doc:`dump_modify <dump_modify>`
doc page for details.
The *atom/gz*, *cfg/gz*, *custom/gz*, *local/gz*, and *xyz/gz* styles are identical
in command syntax to the corresponding styles without "gz", however,
they generate compressed files using the zlib library. Thus the filename
suffix ".gz" is mandatory. This is an alternative approach to writing
compressed files via a pipe, as done by the regular dump styles, which
may be required on clusters where the interface to the high-speed network
disallows using the fork() library call (which is needed for a pipe).
For the remainder of this doc page, you should thus consider the *atom*
and *atom/gz* styles (etc) to be inter-changeable, with the exception
of the required filename suffix.
The *atom/gz*, *cfg/gz*, *custom/gz*, *local/gz*, and *xyz/gz* styles
are identical in command syntax to the corresponding styles without
"gz", however, they generate compressed files using the zlib
library. Thus the filename suffix ".gz" is mandatory. This is an
alternative approach to writing compressed files via a pipe, as done
by the regular dump styles, which may be required on clusters where
the interface to the high-speed network disallows using the fork()
library call (which is needed for a pipe). For the remainder of this
doc page, you should thus consider the *atom* and *atom/gz* styles
(etc) to be inter-changeable, with the exception of the required
filename suffix.
Similarly, the *atom/zstd*, *cfg/zstd*, *custom/zstd*, *local/zstd*,
and *xyz/zstd* styles are identical to the gz styles, but use the Zstd
@ -275,10 +277,11 @@ This bounding box is convenient for many visualization programs. The
meaning of the 6 character flags for "xx yy zz" is the same as above.
Note that the first two numbers on each line are now xlo_bound instead
of xlo, etc, since they represent a bounding box. See the :doc:`Howto triclinic <Howto_triclinic>` page for a geometric description
of triclinic boxes, as defined by LAMMPS, simple formulas for how the
6 bounding box extents (xlo_bound,xhi_bound,etc) are calculated from
the triclinic parameters, and how to transform those parameters to and
of xlo, etc, since they represent a bounding box. See the :doc:`Howto
triclinic <Howto_triclinic>` page for a geometric description of
triclinic boxes, as defined by LAMMPS, simple formulas for how the 6
bounding box extents (xlo_bound,xhi_bound,etc) are calculated from the
triclinic parameters, and how to transform those parameters to and
from other commonly used triclinic representations.
The "ITEM: ATOMS" line in each snapshot lists column descriptors for
@ -310,23 +313,24 @@ written to the dump file. This local data is typically calculated by
each processor based on the atoms it owns, but there may be zero or
more entities per atom, e.g. a list of bond distances. An explanation
of the possible dump local attributes is given below. Note that by
using input from the :doc:`compute property/local <compute_property_local>` command with dump local,
it is possible to generate information on bonds, angles, etc that can
be cut and pasted directly into a data file read by the
:doc:`read_data <read_data>` command.
using input from the :doc:`compute property/local
<compute_property_local>` command with dump local, it is possible to
generate information on bonds, angles, etc that can be cut and pasted
directly into a data file read by the :doc:`read_data <read_data>`
command.
Style *cfg* has the same command syntax as style *custom* and writes
extended CFG format files, as used by the
`AtomEye <http://li.mit.edu/Archive/Graphics/A/>`_ visualization
package. Since the extended CFG format uses a single snapshot of the
system per file, a wildcard "\*" must be included in the filename, as
discussed below. The list of atom attributes for style *cfg* must
begin with either "mass type xs ys zs" or "mass type xsu ysu zsu"
since these quantities are needed to write the CFG files in the
appropriate format (though the "mass" and "type" fields do not appear
explicitly in the file). Any remaining attributes will be stored as
"auxiliary properties" in the CFG files. Note that you will typically
want to use the :doc:`dump_modify element <dump_modify>` command with
extended CFG format files, as used by the `AtomEye
<http://li.mit.edu/Archive/Graphics/A/>`_ visualization package.
Since the extended CFG format uses a single snapshot of the system per
file, a wildcard "\*" must be included in the filename, as discussed
below. The list of atom attributes for style *cfg* must begin with
either "mass type xs ys zs" or "mass type xsu ysu zsu" since these
quantities are needed to write the CFG files in the appropriate format
(though the "mass" and "type" fields do not appear explicitly in the
file). Any remaining attributes will be stored as "auxiliary
properties" in the CFG files. Note that you will typically want to
use the :doc:`dump_modify element <dump_modify>` command with
CFG-formatted files, to associate element names with atom types, so
that AtomEye can render atoms appropriately. When unwrapped
coordinates *xsu*, *ysu*, and *zsu* are requested, the nominal AtomEye

View File

@ -17,7 +17,7 @@ Syntax
* one or more keyword/value pairs may be appended
* these keywords apply to various dump styles
* keyword = *append* or *at* or *buffer* or *delay* or *element* or *every* or *fileper* or *first* or *flush* or *format* or *header* or *image* or *label* or *maxfiles* or *nfile* or *pad* or *pbc* or *precision* or *region* or *refresh* or *scale* or *sfactor* or *sort* or *tfactor* or *thermo* or *thresh* or *time* or *units* or *unwrap*
* keyword = *append* or *at* or *buffer* or *delay* or *element* or *every* or *every/time* or *fileper* or *first* or *flush* or *format* or *header* or *image* or *label* or *maxfiles* or *nfile* or *pad* or *pbc* or *precision* or *region* or *refresh* or *scale* or *sfactor* or *sort* or *tfactor* or *thermo* or *thresh* or *time* or *units* or *unwrap*
.. parsed-literal::
@ -32,6 +32,9 @@ Syntax
*every* arg = N
N = dump every this many timesteps
N can be a variable (see below)
*every/time* arg = Delta
Delta = dump every this interval in simulation time (time units)
Delta can be a variable (see below)
*fileper* arg = Np
Np = write one file for every this many processors
*first* arg = *yes* or *no*
@ -197,11 +200,18 @@ will be accepted.
----------
The *every* keyword changes the dump frequency originally specified by
the :doc:`dump <dump>` command to a new value. 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.
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
*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
frequency originally specified by the :doc:`dump <dump>` command.
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.
In this case, the variable is evaluated at the beginning of a run to
determine the next timestep at which a dump snapshot will be written
@ -210,11 +220,12 @@ determine the next timestep, etc. Thus the variable should return
timestep values. See the stagger() and logfreq() and stride() math
functions for :doc:`equal-style variables <variable>`, as examples of
useful functions to use in this context. Other similar math functions
could easily be added as options for :doc:`equal-style variables <variable>`. Also see the next() function, which allows
use of a file-style variable which reads successive values from a
file, each time the variable is evaluated. Used with the *every*
keyword, if the file contains a list of ascending timesteps, you can
output snapshots whenever you wish.
could easily be added as options for :doc:`equal-style variables
<variable>`. Also see the next() function, which allows use of a
file-style variable which reads successive values from a file, each
time the variable is evaluated. Used with the *every* keyword, if the
file contains a list of ascending timesteps, you can output snapshots
whenever you wish.
Note that when using the variable option with the *every* keyword, you
need to use the *first* option if you want an initial snapshot written
@ -255,14 +266,95 @@ 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,
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.
Note that since snapshots are output on simulation steps, each
snapshot will be written on the first timestep whose associated
simulation time is >= the exact snapshot time value.
As with the *every* option, the *Delta* value can be specified in one
of two ways. It can be a numeric value in which case it must be >
0.0. Or it can be an :doc:`equal-style variable <variable>`, which
should be specified as v_name, where name is the variable name.
In this case, the variable is evaluated at the beginning of a run to
determine the next simulation time at which a dump snapshot will be
written out. On that timestep the variable will be evaluated again to
determine the next simulation time, etc. Thus the variable should
return values in time units. Note the current timestep or simulation
time can be used in an :doc:`equal-style variables <variable>` since
they are both thermodynamic keywords. Also see the next() function,
which allows use of a file-style variable which reads successive
values from a file, each time the variable is evaluated. Used with
the *every/time* keyword, if the file contains a list of ascending
simulation times, you can output snapshots whenever you wish.
Note that when using the variable option with the *every/time*
keyword, you need to use the *first* option if you want an initial
snapshot written to the dump file. The *every/time* keyword cannot be
used with the dump *dcd* style.
For example, the following commands will write snapshots at successive
simulation times which grow by a factor of 1.5 with each interval.
The dt value used in the variable is to avoid a zero result when the
initial simulation time is 0.0.
.. code-block:: LAMMPS
variable increase equal 1.5*(time+dt)
dump 1 all atom 100 tmp.dump
dump_modify 1 every/time v_increase first yes
The following commands would write snapshots at the times listed in
file tmp.times:
.. code-block:: LAMMPS
variable f file tmp.times
variable s equal next(f)
dump 1 all atom 100 tmp.dump
dump_modify 1 every/time v_s
.. 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
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
if the next time it reads from the file is not a value greater than
the current time. Thus if you wanted output at times 0,15,100 of a
run of length 100 in simulation time, the file should contain the
values 15,100,101 and you should also use the dump_modify first
command. Any final value > 100 could be used in place of 101.
----------
The *first* keyword determines whether a dump snapshot is written on
the very first timestep after the dump command is invoked. This will
always occur if the current timestep is a multiple of N, the frequency
specified in the :doc:`dump <dump>` command, including timestep 0. 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
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.
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
default, then it will not be written.
Note that if the argument to the :doc:`dump_modify every
<dump_modify>` doc:`dump_modify every/time <dump_modify>` commands is
a variable and not a numeric value, then specifying *first yes* is the
only way to write a dump snapshot on the first timestep after the dump
command is invoked.
----------
The *flush* keyword determines whether a flush operation is invoked
@ -342,10 +434,10 @@ The *fileper* keyword is documented below with the *nfile* keyword.
----------
The *header* keyword toggles whether the dump file will include a header.
Excluding a header will reduce the size of the dump file for fixes such as
:doc:`fix pair/tracker <fix_pair_tracker>` which do not require the information
typically written to the header.
The *header* keyword toggles whether the dump file will include a
header. Excluding a header will reduce the size of the dump file for
fixes such as :doc:`fix pair/tracker <fix_pair_tracker>` which do not
require the information typically written to the header.
----------

View File

@ -78,13 +78,20 @@ outer loop (largest) timestep, which is the same timestep that the
Note that the cumulative simulation time (in time units), which
accounts for changes in the timestep size as a simulation proceeds,
can be accessed by the :doc:`thermo_style time <thermo_style>` keyword.
can be accessed by the :doc:`thermo_style time <thermo_style>`
keyword.
Also note that the :doc:`dump_modify every/time <dump_modify>` option
allows dump files to be written at intervals specified by simulation
time, rather than by timesteps. Simulation time is in time units;
see the :doc:`units <units>` doc page for details.
Restart, fix_modify, output, run start/stop, minimize info
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
No information about this fix is written to :doc:`binary restart files <restart>`. None of the :doc:`fix_modify <fix_modify>` options
are relevant to this fix.
No information about this fix is written to :doc:`binary restart files
<restart>`. None of the :doc:`fix_modify <fix_modify>` options are
relevant to this fix.
This fix computes a global scalar which can be accessed by various
:doc:`output commands <Howto_output>`. The scalar stores the last
@ -93,7 +100,8 @@ timestep on which the timestep was reset to a new value.
The scalar value calculated by this fix is "intensive".
No parameter of this fix can be used with the *start/stop* keywords of
the :doc:`run <run>` command. This fix is not invoked during :doc:`energy minimization <minimize>`.
the :doc:`run <run>` command. This fix is not invoked during
:doc:`energy minimization <minimize>`.
Restrictions
""""""""""""
@ -102,7 +110,7 @@ Restrictions
Related commands
""""""""""""""""
:doc:`timestep <timestep>`
:doc:`timestep <timestep>`, :doc:`dump_modify every/time <dump_modify>`
Default
"""""""

View File

@ -918,24 +918,6 @@ void Dump::modify_params(int narg, char **arg)
else delay_flag = 0;
iarg += 2;
} else if (strcmp(arg[iarg],"delta") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command");
int idump;
for (idump = 0; idump < output->ndump; idump++)
if (strcmp(id,output->dump[idump]->id) == 0) break;
double delta;
if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) {
delete [] output->var_dump[idump];
output->var_dump[idump] = utils::strdup(&arg[iarg+1][2]);
delta = 0.0;
} else {
delta = utils::numeric(FLERR,arg[iarg+1],false,lmp);
if (delta <= 0.0) error->all(FLERR,"Illegal dump_modify command");
}
output->mode_dump[idump] = 1;
output->delta_dump[idump] = delta;
iarg += 2;
} else if (strcmp(arg[iarg],"every") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command");
int idump;
@ -954,6 +936,24 @@ void Dump::modify_params(int narg, char **arg)
output->every_dump[idump] = n;
iarg += 2;
} else if (strcmp(arg[iarg],"every/time") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command");
int idump;
for (idump = 0; idump < output->ndump; idump++)
if (strcmp(id,output->dump[idump]->id) == 0) break;
double delta;
if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) {
delete [] output->var_dump[idump];
output->var_dump[idump] = utils::strdup(&arg[iarg+1][2]);
delta = 0.0;
} else {
delta = utils::numeric(FLERR,arg[iarg+1],false,lmp);
if (delta <= 0.0) error->all(FLERR,"Illegal dump_modify command");
}
output->mode_dump[idump] = 1;
output->every_time_dump[idump] = delta;
iarg += 2;
} else if (strcmp(arg[iarg],"fileper") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command");
if (!multiproc)

View File

@ -197,12 +197,15 @@ void FixDtReset::end_of_step()
laststep = update->ntimestep;
// calls to other classes that need to know timestep size changed
update->update_time();
update->dt = dt;
update->dt_default = 0;
if (respaflag) update->integrate->reset_dt();
if (force->pair) force->pair->reset_dt();
for (int i = 0; i < modify->nfix; i++) modify->fix[i]->reset_dt();
output->reset_dt();
}
/* ---------------------------------------------------------------------- */

View File

@ -29,6 +29,7 @@
#include "variable.h"
#include "write_restart.h"
#include <cmath>
#include <cstring>
using namespace LAMMPS_NS;
@ -62,7 +63,7 @@ Output::Output(LAMMPS *lmp) : Pointers(lmp)
max_dump = 0;
mode_dump = nullptr;
every_dump = nullptr;
delta_dump = nullptr;
every_time_dump = nullptr;
next_dump = nullptr;
next_time_dump = nullptr;
last_dump = nullptr;
@ -98,7 +99,7 @@ Output::~Output()
memory->destroy(mode_dump);
memory->destroy(every_dump);
memory->destroy(delta_dump);
memory->destroy(every_time_dump);
memory->destroy(next_dump);
memory->destroy(next_time_dump);
memory->destroy(last_dump);
@ -134,7 +135,7 @@ void Output::init()
for (int i = 0; i < ndump; i++) dump[i]->init();
for (int i = 0; i < ndump; i++)
if ((mode_dump[i] == 0 && every_dump[i] == 0) ||
(mode_dump[i] == 1 && delta_dump[i] == 0.0)) {
(mode_dump[i] == 1 && every_time_dump[i] == 0.0)) {
ivar_dump[i] = input->variable->find(var_dump[i]);
if (ivar_dump[i] < 0)
error->all(FLERR,"Variable name for dump every or delta does not exist");
@ -169,42 +170,61 @@ void Output::setup(int memflag)
{
bigint ntimestep = update->ntimestep;
// perform dump at start of run only if:
// current timestep is multiple of every and last dump not >= this step
// this is first run after dump created and firstflag is set
// note that variable freq will not write unless triggered by firstflag
// set next_dump, and also next_time_dump for mode_dump = 1
// set next_dump_any to smallest next_dump
// wrap dumps that invoke computes or do variable eval with clear/add
// if dump not written now, use addstep_compute_all() since don't know
// what computes the dump write would invoke
// if no dumps, set next_dump_any to last+1 so will not influence next
int writeflag;
// consider all dumps
// decide whether to write snapshot and/or calculate next step for dump
if (ndump && update->restrict_output == 0) {
for (int idump = 0; idump < ndump; idump++) {
// wrap dumps that invoke computes or do variable eval with clear/add
if (dump[idump]->clearstep || var_dump[idump])
modify->clearstep_compute();
writeflag = 0;
if (mode_dump[idump] == 0) {
if (every_dump[idump] && (ntimestep % every_dump[idump] == 0) &&
last_dump[idump] != ntimestep) writeflag = 1;
} else {
if (delta_dump[idump] >= 0.0 && last_dump[idump] != ntimestep)
writeflag = 1;
}
// write a snapshot at setup only if any of these 3 conditions hold
// (1) this is first run since dump was created and its first_flag = 0
// (2) mode_dump = 0 and timestep is multiple of every_dump
// (3) mode_dump = 1 and time is multiple of every_time_dump (within EPSDT)
// (2) and (3) only apply for non-variable dump intervals
// finally, do not write if same snapshot written previously,
// i.e. on last timestep of previous run
int writeflag = 0;
if (last_dump[idump] < 0 && dump[idump]->first_flag == 1) writeflag = 1;
if (mode_dump[idump] == 0) {
if (every_dump[idump] && (ntimestep % every_dump[idump] == 0))
writeflag = 1;
} else {
if (every_time_dump[idump] > 0.0) {
double tcurrent = update->atime +
(ntimestep - update->atimestep) * update->dt;
double remainder = fmod(tcurrent,every_time_dump[idump]);
if ((remainder < EPSDT*update->dt) ||
(every_time_dump[idump] - remainder < EPSDT*update->dt))
writeflag = 1;
}
}
if (last_dump[idump] == ntimestep) writeflag = 0;
// perform dump
if (writeflag) {
dump[idump]->write();
last_dump[idump] = ntimestep;
}
// calculate timestep and/or time for next dump
// set next_dump and next_time_dump, 0 arg for setup()
// only do this if dump written or dump has not been written yet
calculate_next_dump(0,idump,ntimestep);
if (writeflag || last_dump[idump] < 0)
calculate_next_dump(0,idump,ntimestep);
// if dump not written now, use addstep_compute_all()
// since don't know what computes the dump will invoke
if (dump[idump]->clearstep || var_dump[idump]) {
if (writeflag) modify->addstep_compute(next_dump[idump]);
@ -214,6 +234,9 @@ void Output::setup(int memflag)
if (idump) next_dump_any = MIN(next_dump_any,next_dump[idump]);
else next_dump_any = next_dump[0];
}
// if no dumps, set next_dump_any to last+1 so will not influence next
} else next_dump_any = update->laststep + 1;
// do not write restart files at start of run
@ -296,33 +319,26 @@ void Output::write(bigint ntimestep)
// set next_dump and also next_time_dump for mode_dump = 1
// set next_dump_any to smallest next_dump
// wrap dumps that invoke computes or do variable eval with clear/add
// if dump not written now, use addstep_compute_all() since don't know
// what computes the dump write would invoke
int writeflag;
if (next_dump_any == ntimestep) {
for (int idump = 0; idump < ndump; idump++) {
if (next_dump[idump] == ntimestep) {
if (last_dump[idump] == ntimestep) continue;
if (dump[idump]->clearstep || var_dump[idump])
modify->clearstep_compute();
writeflag = 0;
if (last_dump[idump] != ntimestep) writeflag = 1;
// perform dump
// reset next_dump and next_time_dump, 1 arg for write()
if (writeflag) {
dump[idump]->write();
last_dump[idump] = ntimestep;
}
// set next_dump and next_time_dump, 1 arg for write()
dump[idump]->write();
last_dump[idump] = ntimestep;
calculate_next_dump(1,idump,ntimestep);
if (dump[idump]->clearstep || var_dump[idump]) {
if (writeflag) modify->addstep_compute(next_dump[idump]);
else modify->addstep_compute_all(next_dump[idump]);
}
if (dump[idump]->clearstep || var_dump[idump])
modify->addstep_compute(next_dump[idump]);
}
if (idump) next_dump_any = MIN(next_dump_any,next_dump[idump]);
@ -422,6 +438,10 @@ void Output::write_dump(bigint ntimestep)
operates in one of two modes, based on mode_dump flag
for timestep mode, set next_dump
for simulation time mode, set next_time_dump and next_dump
which flag depends on caller
0 = from setup() at start of run
1 = from write() during run each time a dump file is written
2 = from reset_dt() called from fix dt/reset when it changes timestep size
------------------------------------------------------------------------- */
void Output::calculate_next_dump(int which, int idump, bigint ntimestep)
@ -431,13 +451,17 @@ void Output::write_dump(bigint ntimestep)
if (mode_dump[idump] == 0) {
// for setup, make next_dump a multiple of every_dump
if (every_dump[idump]) {
if (which == 1) next_dump[idump] += every_dump[idump];
else
// which = 0: nextdump = next multiple of every_dump
// which = 1: increment nextdump by every_dump
if (which == 0)
next_dump[idump] =
(ntimestep/every_dump[idump])*every_dump[idump] + every_dump[idump];
else if (which == 1)
next_dump[idump] += every_dump[idump];
} else {
next_dump[idump] = static_cast<bigint>
(input->variable->compute_equal(ivar_dump[idump]));
@ -449,22 +473,29 @@ void Output::write_dump(bigint ntimestep)
// set next_time_dump and next_dump
} else {
bigint nextdump;
double nexttime;
double tcurrent = update->atime +
(ntimestep - update->atimestep) * update->dt;
// for setup, make nexttime a multiple of delta_dump
if (every_time_dump[idump] > 0.0) {
if (delta_dump[idump] > 0.0) {
if (which == 1) nexttime = next_time_dump[idump] + delta_dump[idump];
else
nexttime = static_cast<bigint> (tcurrent/delta_dump[idump]) *
delta_dump[idump] + delta_dump[idump];
// which = 0: nexttime = next multiple of every_time_dump
// which = 1: increment nexttime by every_time_dump
// which = 2: no change to previous nexttime (only timestep has changed)
if (which == 0)
nexttime = static_cast<bigint> (tcurrent/every_time_dump[idump]) *
every_time_dump[idump] + every_time_dump[idump];
else if (which == 1)
nexttime = next_time_dump[idump] + every_time_dump[idump];
else if (which == 2)
nexttime = next_time_dump[idump];
nextdump = ntimestep +
static_cast<bigint> ((nexttime - tcurrent + EPSDT*update->dt) /
update->dt);
static_cast<bigint> ((nexttime - tcurrent - EPSDT*update->dt) /
update->dt) + 1;
// if delta is too small to reach next timestep, use multiple of delta
@ -472,30 +503,35 @@ void Output::write_dump(bigint ntimestep)
double tnext = update->atime +
(ntimestep+1 - update->atimestep) * update->dt;
int multiple = static_cast<int>
((tnext - nexttime) / delta_dump[idump]);
nexttime = nexttime + (multiple+1)*delta_dump[idump];
((tnext - nexttime) / every_time_dump[idump]);
nexttime = nexttime + (multiple+1)*every_time_dump[idump];
nextdump = ntimestep +
static_cast<bigint> ((nexttime - tcurrent + EPSDT*update->dt) /
update->dt);
static_cast<bigint> ((nexttime - tcurrent - EPSDT*update->dt) /
update->dt) + 1;
}
} else {
nexttime = input->variable->compute_equal(ivar_dump[idump]);
// do not re-evaulate variable for which = 2, leave nexttime as-is
// unless next_time_dump < 0.0, which means variable never yet evaluated
if (which < 2 || next_time_dump[idump] < 0.0)
nexttime = input->variable->compute_equal(ivar_dump[idump]);
else
nexttime = next_time_dump[idump];
if (nexttime <= tcurrent)
error->all(FLERR,"Dump delta variable returned a bad time");
error->all(FLERR,"Dump every/time variable returned a bad time");
nextdump = ntimestep +
static_cast<bigint> ((nexttime - tcurrent + EPSDT*update->dt) /
update->dt);
static_cast<bigint> ((nexttime - tcurrent - EPSDT*update->dt) /
update->dt) + 1;
if (nextdump <= ntimestep)
error->all(FLERR,"Dump delta variable too small for next timestep");
error->all(FLERR,"Dump every/time variable too small for next timestep");
}
next_time_dump[idump] = nexttime;
next_dump[idump] = nextdump;
//printf("END time %20.16g step %ld ratio %g\n",
// next_time_dump[idump],next_dump[idump],
// next_time_dump[idump]/update->dt/(next_dump[idump]+1));
}
}
@ -529,7 +565,7 @@ void Output::write_restart(bigint ntimestep)
/* ----------------------------------------------------------------------
timestep is being changed, called by update->reset_timestep()
reset next timestep values for dumps, restart, thermo output
reset next output values for dumps, restart, thermo output
reset to smallest value >= new timestep
if next timestep set by variable evaluation,
eval for ntimestep-1, so current ntimestep can be returned if needed
@ -626,6 +662,35 @@ void Output::reset_timestep(bigint ntimestep)
next = MIN(next,next_thermo);
}
/* ----------------------------------------------------------------------
timestep size is being changed, called by fix dt/reset (at end of step)
reset next output values for dumps which have mode_dump=1
------------------------------------------------------------------------- */
void Output::reset_dt()
{
next_dump_any = MAXBIGINT;
for (int idump = 0; idump < ndump; idump++) {
if (mode_dump[idump] == 1) {
// reset next_dump for unchanged next_time_dump, 2 arg for reset_dt()
calculate_next_dump(2,idump,update->ntimestep);
// use compute_all() b/c don't know what computes will be needed
if (dump[idump]->clearstep || var_dump[idump])
modify->addstep_compute_all(next_dump[idump]);
}
next_dump_any = MIN(next_dump_any,next_dump[idump]);
}
next = MIN(next_dump_any,next_restart);
next = MIN(next,next_thermo);
}
/* ----------------------------------------------------------------------
add a Dump to list of Dumps
------------------------------------------------------------------------- */
@ -652,7 +717,7 @@ void Output::add_dump(int narg, char **arg)
memory->srealloc(dump,max_dump*sizeof(Dump *),"output:dump");
memory->grow(mode_dump,max_dump,"output:mode_dump");
memory->grow(every_dump,max_dump,"output:every_dump");
memory->grow(delta_dump,max_dump,"output:delta_dump");
memory->grow(every_time_dump,max_dump,"output:every_time_dump");
memory->grow(next_dump,max_dump,"output:next_dump");
memory->grow(next_time_dump,max_dump,"output:next_time_dump");
memory->grow(last_dump,max_dump,"output:last_dump");
@ -673,7 +738,8 @@ void Output::add_dump(int narg, char **arg)
mode_dump[ndump] = 0;
every_dump[ndump] = utils::inumeric(FLERR,arg[3],false,lmp);
if (every_dump[ndump] <= 0) error->all(FLERR,"Illegal dump command");
delta_dump[ndump] = 0.0;
every_time_dump[ndump] = 0.0;
next_time_dump[ndump] = -1.0;
last_dump[ndump] = -1;
var_dump[ndump] = nullptr;
ivar_dump[ndump] = -1;
@ -731,7 +797,7 @@ void Output::delete_dump(char *id)
dump[i-1] = dump[i];
mode_dump[i-1] = mode_dump[i];
every_dump[i-1] = every_dump[i];
delta_dump[i-1] = delta_dump[i];
every_time_dump[i-1] = every_time_dump[i];
next_dump[i-1] = next_dump[i];
next_time_dump[i-1] = next_time_dump[i];
last_dump[i-1] = last_dump[i];

View File

@ -37,8 +37,8 @@ class Output : protected Pointers {
int max_dump; // max size of Dump list
bigint next_dump_any; // next timestep for any Dump
int *mode_dump; // 0/1 if write every N timesteps or Delta in sim time
int *every_dump; // dump every this many timesteps, 0 if variable
double *delta_dump; // dump every this delta sim time, 0.0 if variable
int *every_dump; // dump every N timesteps, 0 if variable
double *every_time_dump; // dump every Delta of sim time, 0.0 if variable
bigint *next_dump; // next timestep to perform dump
double *next_time_dump; // next simulation time to perform dump (mode = 1)
bigint *last_dump; // last timestep each snapshot was output
@ -75,7 +75,8 @@ class Output : protected Pointers {
void write(bigint); // output for current timestep
void write_dump(bigint); // force output of dump snapshots
void write_restart(bigint); // force output of a restart file
void reset_timestep(bigint); // reset next timestep for all output
void reset_timestep(bigint); // reset output which depeneds on timestep
void reset_dt(); // reset output which depends on dt
void add_dump(int, char **); // add a Dump to Dump list
void modify_dump(int, char **); // modify a Dump

View File

@ -458,7 +458,7 @@ Min *Update::minimize_creator(LAMMPS *lmp)
}
/* ----------------------------------------------------------------------
reset timestep as called from input script
reset timestep called from input script
------------------------------------------------------------------------- */
void Update::reset_timestep(int narg, char **arg)
@ -470,24 +470,32 @@ void Update::reset_timestep(int narg, char **arg)
/* ----------------------------------------------------------------------
reset timestep
called from rerun command and input script (indirectly)
called from input script (indirectly) or rerun command
------------------------------------------------------------------------- */
void Update::reset_timestep(bigint newstep)
{
if (newstep < 0) error->all(FLERR,"Timestep must be >= 0");
bigint oldstep = ntimestep;
ntimestep = newstep;
if (ntimestep < 0) error->all(FLERR,"Timestep must be >= 0");
// set atimestep to new timestep
// so future update_time() calls will be correct
// if newstep >= oldstep, update simulation time accordingly
// if newstep < oldstep, zero simulation time
atimestep = ntimestep;
if (newstep >= oldstep) update_time();
// trigger reset of timestep for output
// do not allow any timestep-dependent fixes to be already defined
if (newstep < oldstep) {
atime = 0.0;
atimestep = newstep;
}
// changes to output that depend on timestep
output->reset_timestep(ntimestep);
// do not allow timestep-dependent fixes to be defined
for (const auto &ifix : modify->get_fix_list())
if (ifix->time_depend)
error->all(FLERR, "Cannot reset timestep with time-dependent fix {} defined",ifix->style);
@ -508,7 +516,7 @@ void Update::reset_timestep(bigint newstep)
if (icompute->timeflag) icompute->clearstep();
}
// Neighbor Bin/Stencil/Pair classes store timestamps that need to be cleared
// neighbor Bin/Stencil/Pair classes store timestamps that need to be cleared
neighbor->reset_timestep(ntimestep);
}