change to checking timestep for time dumps at start of each step

This commit is contained in:
Steve Plimpton
2021-12-20 16:39:17 -07:00
parent 06c45fbe68
commit 4d31e300c6
5 changed files with 440 additions and 413 deletions

View File

@ -330,8 +330,6 @@ void Dump::write()
if (delay_flag && update->ntimestep < delaystep) return; if (delay_flag && update->ntimestep < delaystep) return;
printf("DUMP %ld\n",update->ntimestep);
// if file per timestep, open new file // if file per timestep, open new file
if (multifile) openfile(); if (multifile) openfile();

View File

@ -20,6 +20,7 @@
#include "kspace.h" #include "kspace.h"
#include "modify.h" #include "modify.h"
#include "pair.h" #include "pair.h"
#include "output.h"
#include "update.h" #include "update.h"
using namespace LAMMPS_NS; using namespace LAMMPS_NS;
@ -115,7 +116,13 @@ void Integrate::ev_setup()
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
set eflag,vflag for current iteration set eflag,vflag for current iteration
based on computes that need energy/virial info on this timestep 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
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 invoke matchstep() on all timestep-dependent computes to clear their arrays
eflag: set any or no bits eflag: set any or no bits
ENERGY_GLOBAL bit for global energy ENERGY_GLOBAL bit for global energy
@ -133,6 +140,10 @@ void Integrate::ev_set(bigint ntimestep)
{ {
int i,flag; int i,flag;
int tdflag = 0;
if (output->any_time_dumps)
tdflag = output->check_time_dumps(ntimestep);
flag = 0; flag = 0;
int eflag_global = 0; int eflag_global = 0;
for (i = 0; i < nelist_global; i++) for (i = 0; i < nelist_global; i++)
@ -143,7 +154,7 @@ void Integrate::ev_set(bigint ntimestep)
int eflag_atom = 0; int eflag_atom = 0;
for (i = 0; i < nelist_atom; i++) for (i = 0; i < nelist_atom; i++)
if (elist_atom[i]->matchstep(ntimestep)) flag = 1; if (elist_atom[i]->matchstep(ntimestep)) flag = 1;
if (flag) eflag_atom = ENERGY_ATOM; if (flag || (tdflag && nelist_atom)) eflag_atom = ENERGY_ATOM;
if (eflag_global) update->eflag_global = ntimestep; if (eflag_global) update->eflag_global = ntimestep;
if (eflag_atom) update->eflag_atom = ntimestep; if (eflag_atom) update->eflag_atom = ntimestep;
@ -159,13 +170,13 @@ void Integrate::ev_set(bigint ntimestep)
int vflag_atom = 0; int vflag_atom = 0;
for (i = 0; i < nvlist_atom; i++) for (i = 0; i < nvlist_atom; i++)
if (vlist_atom[i]->matchstep(ntimestep)) flag = 1; if (vlist_atom[i]->matchstep(ntimestep)) flag = 1;
if (flag) vflag_atom = VIRIAL_ATOM; if (flag || (tdflag && nvlist_atom)) vflag_atom = VIRIAL_ATOM;
flag = 0; flag = 0;
int cvflag_atom = 0; int cvflag_atom = 0;
for (i = 0; i < ncvlist_atom; i++) for (i = 0; i < ncvlist_atom; i++)
if (cvlist_atom[i]->matchstep(ntimestep)) flag = 1; if (cvlist_atom[i]->matchstep(ntimestep)) flag = 1;
if (flag) cvflag_atom = VIRIAL_CENTROID; if (flag || (tdflag && ncvlist_atom)) cvflag_atom = VIRIAL_CENTROID;
if (vflag_global) update->vflag_global = ntimestep; if (vflag_global) update->vflag_global = ntimestep;
if (vflag_atom || cvflag_atom) update->vflag_atom = ntimestep; if (vflag_atom || cvflag_atom) update->vflag_atom = ntimestep;

View File

@ -133,7 +133,9 @@ void Output::init()
} }
for (int i = 0; i < ndump; i++) dump[i]->init(); for (int i = 0; i < ndump; i++) dump[i]->init();
for (int i = 0; i < ndump; i++) any_time_dumps = 0;
for (int i = 0; i < ndump; i++) {
if (mode_dump[i]) any_time_dumps = 1;
if ((mode_dump[i] == 0 && every_dump[i] == 0) || if ((mode_dump[i] == 0 && every_dump[i] == 0) ||
(mode_dump[i] == 1 && every_time_dump[i] == 0.0)) { (mode_dump[i] == 1 && every_time_dump[i] == 0.0)) {
ivar_dump[i] = input->variable->find(var_dump[i]); ivar_dump[i] = input->variable->find(var_dump[i]);
@ -142,6 +144,7 @@ void Output::init()
if (!input->variable->equalstyle(ivar_dump[i])) if (!input->variable->equalstyle(ivar_dump[i]))
error->all(FLERR,"Variable for dump every or delta is invalid style"); error->all(FLERR,"Variable for dump every or delta is invalid style");
} }
}
if (restart_flag_single && restart_every_single == 0) { if (restart_flag_single && restart_every_single == 0) {
ivar_restart_single = input->variable->find(var_restart_single); ivar_restart_single = input->variable->find(var_restart_single);
@ -176,9 +179,11 @@ void Output::setup(int memflag)
if (ndump && update->restrict_output == 0) { if (ndump && update->restrict_output == 0) {
for (int idump = 0; idump < ndump; idump++) { for (int idump = 0; idump < ndump; idump++) {
// wrap dumps that invoke computes or do variable eval with clear/add // wrap step dumps that invoke computes or do variable eval with clear/add
// see NOTE in write() about also wrapping time dumps
if (dump[idump]->clearstep || var_dump[idump]) if (mode_dump[idump] == 0 &&
(dump[idump]->clearstep || var_dump[idump]))
modify->clearstep_compute(); modify->clearstep_compute();
// write a snapshot at setup only if any of these 3 conditions hold // write a snapshot at setup only if any of these 3 conditions hold
@ -226,7 +231,8 @@ void Output::setup(int memflag)
// if dump not written now, use addstep_compute_all() // if dump not written now, use addstep_compute_all()
// since don't know what computes the dump will invoke // since don't know what computes the dump will invoke
if (dump[idump]->clearstep || var_dump[idump]) { if (mode_dump[idump] == 0 &&
(dump[idump]->clearstep || var_dump[idump])) {
if (writeflag) modify->addstep_compute(next_dump[idump]); if (writeflag) modify->addstep_compute(next_dump[idump]);
else modify->addstep_compute_all(next_dump[idump]); else modify->addstep_compute_all(next_dump[idump]);
} }
@ -239,413 +245,435 @@ void Output::setup(int memflag)
} else next_dump_any = update->laststep + 1; } else next_dump_any = update->laststep + 1;
// do not write restart files at start of run // do not write restart files at start of run
// set next_restart values to multiple of every or variable value // set next_restart values to multiple of every or variable value
// wrap variable eval with clear/add // wrap variable eval with clear/add
// if no restarts, set next_restart to last+1 so will not influence next // if no restarts, set next_restart to last+1 so will not influence next
if (restart_flag && update->restrict_output == 0) { if (restart_flag && update->restrict_output == 0) {
if (restart_flag_single) { if (restart_flag_single) {
if (restart_every_single) if (restart_every_single)
next_restart_single = next_restart_single =
(ntimestep/restart_every_single)*restart_every_single + (ntimestep/restart_every_single)*restart_every_single +
restart_every_single; restart_every_single;
else { else {
bigint nextrestart = static_cast<bigint> bigint nextrestart = static_cast<bigint>
(input->variable->compute_equal(ivar_restart_single)); (input->variable->compute_equal(ivar_restart_single));
if (nextrestart <= ntimestep) if (nextrestart <= ntimestep)
error->all(FLERR,"Restart variable returned a bad timestep"); error->all(FLERR,"Restart variable returned a bad timestep");
next_restart_single = nextrestart; next_restart_single = nextrestart;
} }
} else next_restart_single = update->laststep + 1; } else next_restart_single = update->laststep + 1;
if (restart_flag_double) { if (restart_flag_double) {
if (restart_every_double) if (restart_every_double)
next_restart_double = next_restart_double =
(ntimestep/restart_every_double)*restart_every_double + (ntimestep/restart_every_double)*restart_every_double +
restart_every_double; restart_every_double;
else { else {
bigint nextrestart = static_cast<bigint> bigint nextrestart = static_cast<bigint>
(input->variable->compute_equal(ivar_restart_double)); (input->variable->compute_equal(ivar_restart_double));
if (nextrestart <= ntimestep) if (nextrestart <= ntimestep)
error->all(FLERR,"Restart variable returned a bad timestep"); error->all(FLERR,"Restart variable returned a bad timestep");
next_restart_double = nextrestart; next_restart_double = nextrestart;
} }
} else next_restart_double = update->laststep + 1; } else next_restart_double = update->laststep + 1;
next_restart = MIN(next_restart_single,next_restart_double); next_restart = MIN(next_restart_single,next_restart_double);
} else next_restart = update->laststep + 1; } else next_restart = update->laststep + 1;
// print memory usage unless being called between multiple runs // print memory usage unless being called between multiple runs
if (memflag) memory_usage(); if (memflag) memory_usage();
// set next_thermo to multiple of every or variable eval if var defined // set next_thermo to multiple of every or variable eval if var defined
// insure thermo output on last step of run // insure thermo output on last step of run
// thermo may invoke computes so wrap with clear/add // thermo may invoke computes so wrap with clear/add
modify->clearstep_compute(); modify->clearstep_compute();
thermo->header(); thermo->header();
thermo->compute(0); thermo->compute(0);
last_thermo = ntimestep; last_thermo = ntimestep;
if (var_thermo) { if (var_thermo) {
next_thermo = static_cast<bigint> next_thermo = static_cast<bigint>
(input->variable->compute_equal(ivar_thermo)); (input->variable->compute_equal(ivar_thermo));
if (next_thermo <= ntimestep) if (next_thermo <= ntimestep)
error->all(FLERR,"Thermo every variable returned a bad timestep"); error->all(FLERR,"Thermo every variable returned a bad timestep");
} else if (thermo_every) { } else if (thermo_every) {
next_thermo = (ntimestep/thermo_every)*thermo_every + thermo_every; next_thermo = (ntimestep/thermo_every)*thermo_every + thermo_every;
next_thermo = MIN(next_thermo,update->laststep); next_thermo = MIN(next_thermo,update->laststep);
} else next_thermo = update->laststep; } else next_thermo = update->laststep;
modify->addstep_compute(next_thermo); modify->addstep_compute(next_thermo);
// next = next timestep any output will be done // next = next timestep any output will be done
next = MIN(next_dump_any,next_restart); next = MIN(next_dump_any,next_restart);
next = MIN(next,next_thermo); next = MIN(next,next_thermo);
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
perform all output for this timestep perform all output for this timestep
only perform output if next matches current step and last output doesn't only perform output if next matches current step and last output doesn't
do dump/restart before thermo so thermo CPU time will include them do dump/restart before thermo so thermo CPU time will include them
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void Output::write(bigint ntimestep) void Output::write(bigint ntimestep)
{
// perform dump if its next_dump = current ntimestep
// but not if it was already written on this step
// set next_dump and also next_time_dump for mode_dump = 1
// set next_dump_any to smallest next_dump
// wrap step dumps that invoke computes or do variable eval with clear/add
// NOTE:
// 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
// hard to know if timestep varies, since run every could change it
// can't remove an uneeded addstep from a compute, b/c don't know
// what other command may have added it
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 (mode_dump[idump] == 0 &&
(dump[idump]->clearstep || var_dump[idump]))
modify->clearstep_compute();
// perform dump
// reset next_dump and next_time_dump, 1 arg for write()
dump[idump]->write();
last_dump[idump] = ntimestep;
calculate_next_dump(1,idump,ntimestep);
if (mode_dump[idump] == 0 &&
(dump[idump]->clearstep || var_dump[idump]))
modify->addstep_compute(next_dump[idump]);
}
if (idump) next_dump_any = MIN(next_dump_any,next_dump[idump]);
else next_dump_any = next_dump[0];
}
}
// next_restart does not force output on last step of run
// for toggle = 0, replace "*" with current timestep in restart filename
// next restart variable may invoke computes so wrap with clear/add
if (next_restart == ntimestep) {
if (next_restart_single == ntimestep) {
std::string file = restart1;
std::size_t found = file.find('*');
if (found != std::string::npos)
file.replace(found,1,fmt::format("{}",update->ntimestep));
if (last_restart != ntimestep) restart->write(file);
if (restart_every_single) next_restart_single += restart_every_single;
else {
modify->clearstep_compute();
bigint nextrestart = static_cast<bigint>
(input->variable->compute_equal(ivar_restart_single));
if (nextrestart <= ntimestep)
error->all(FLERR,"Restart variable returned a bad timestep");
next_restart_single = nextrestart;
modify->addstep_compute(next_restart_single);
}
}
if (next_restart_double == ntimestep) {
if (last_restart != ntimestep) {
if (restart_toggle == 0) {
restart->write(restart2a);
restart_toggle = 1;
} else {
restart->write(restart2b);
restart_toggle = 0;
}
}
if (restart_every_double) next_restart_double += restart_every_double;
else {
modify->clearstep_compute();
bigint nextrestart = static_cast<bigint>
(input->variable->compute_equal(ivar_restart_double));
if (nextrestart <= ntimestep)
error->all(FLERR,"Restart variable returned a bad timestep");
next_restart_double = nextrestart;
modify->addstep_compute(next_restart_double);
}
}
last_restart = ntimestep;
next_restart = MIN(next_restart_single,next_restart_double);
}
// insure next_thermo forces output on last step of run
// thermo may invoke computes so wrap with clear/add
if (next_thermo == ntimestep) {
modify->clearstep_compute();
if (last_thermo != ntimestep) thermo->compute(1);
last_thermo = ntimestep;
if (var_thermo) {
next_thermo = static_cast<bigint>
(input->variable->compute_equal(ivar_thermo));
if (next_thermo <= ntimestep)
error->all(FLERR,"Thermo every variable returned a bad timestep");
} else if (thermo_every) next_thermo += thermo_every;
else next_thermo = update->laststep;
next_thermo = MIN(next_thermo,update->laststep);
modify->addstep_compute(next_thermo);
}
// next = next timestep any output will be done
next = MIN(next_dump_any,next_restart);
next = MIN(next,next_thermo);
}
/* ----------------------------------------------------------------------
force a snapshot to be written for all dumps
called from PRD and TAD
------------------------------------------------------------------------- */
void Output::write_dump(bigint ntimestep)
{
for (int idump = 0; idump < ndump; idump++) {
dump[idump]->write();
last_dump[idump] = ntimestep;
}
}
/* ----------------------------------------------------------------------
calculate when next dump occurs for Dump instance idump
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)
{
// dump mode is by timestep
// just set next_dump
if (mode_dump[idump] == 0) {
if (every_dump[idump]) {
// 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]));
if (next_dump[idump] <= ntimestep)
error->all(FLERR,"Dump every variable returned a bad timestep");
}
// dump mode is by simulation time
// set next_time_dump and next_dump
} else {
bigint nextdump;
double nexttime;
double tcurrent = update->atime +
(ntimestep - update->atimestep) * update->dt;
if (every_time_dump[idump] > 0.0) {
// 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) + 1;
// if delta is too small to reach next timestep, use multiple of delta
if (nextdump == ntimestep) {
double tnext = update->atime +
(ntimestep+1 - update->atimestep) * update->dt;
int multiple = static_cast<int>
((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) + 1;
}
} else {
// 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 every/time variable returned a bad time");
nextdump = ntimestep +
static_cast<bigint> ((nexttime - tcurrent - EPSDT*update->dt) /
update->dt) + 1;
if (nextdump <= ntimestep)
error->all(FLERR,"Dump every/time variable too small for next timestep");
}
next_time_dump[idump] = nexttime;
next_dump[idump] = nextdump;
}
}
/* ---------------------------------------------------------------------- */
int Output::check_time_dumps(bigint ntimestep)
{ {
// perform dump if its next_dump = current ntimestep int nowflag = 0;
// but not if it was already written on this step for (int i = 0; i < ndump; i++)
// set next_dump and also next_time_dump for mode_dump = 1 if (mode_dump[i] && next_dump[i] == ntimestep) nowflag = 1;
// set next_dump_any to smallest next_dump
// wrap dumps that invoke computes or do variable eval with clear/add
int writeflag; return nowflag;
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();
// perform dump
// reset 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])
modify->addstep_compute(next_dump[idump]);
}
if (idump) next_dump_any = MIN(next_dump_any,next_dump[idump]);
else next_dump_any = next_dump[0];
}
}
// next_restart does not force output on last step of run
// for toggle = 0, replace "*" with current timestep in restart filename
// next restart variable may invoke computes so wrap with clear/add
if (next_restart == ntimestep) {
if (next_restart_single == ntimestep) {
std::string file = restart1;
std::size_t found = file.find('*');
if (found != std::string::npos)
file.replace(found,1,fmt::format("{}",update->ntimestep));
if (last_restart != ntimestep) restart->write(file);
if (restart_every_single) next_restart_single += restart_every_single;
else {
modify->clearstep_compute();
bigint nextrestart = static_cast<bigint>
(input->variable->compute_equal(ivar_restart_single));
if (nextrestart <= ntimestep)
error->all(FLERR,"Restart variable returned a bad timestep");
next_restart_single = nextrestart;
modify->addstep_compute(next_restart_single);
}
}
if (next_restart_double == ntimestep) {
if (last_restart != ntimestep) {
if (restart_toggle == 0) {
restart->write(restart2a);
restart_toggle = 1;
} else {
restart->write(restart2b);
restart_toggle = 0;
}
}
if (restart_every_double) next_restart_double += restart_every_double;
else {
modify->clearstep_compute();
bigint nextrestart = static_cast<bigint>
(input->variable->compute_equal(ivar_restart_double));
if (nextrestart <= ntimestep)
error->all(FLERR,"Restart variable returned a bad timestep");
next_restart_double = nextrestart;
modify->addstep_compute(next_restart_double);
}
}
last_restart = ntimestep;
next_restart = MIN(next_restart_single,next_restart_double);
}
// insure next_thermo forces output on last step of run
// thermo may invoke computes so wrap with clear/add
if (next_thermo == ntimestep) {
modify->clearstep_compute();
if (last_thermo != ntimestep) thermo->compute(1);
last_thermo = ntimestep;
if (var_thermo) {
next_thermo = static_cast<bigint>
(input->variable->compute_equal(ivar_thermo));
if (next_thermo <= ntimestep)
error->all(FLERR,"Thermo every variable returned a bad timestep");
} else if (thermo_every) next_thermo += thermo_every;
else next_thermo = update->laststep;
next_thermo = MIN(next_thermo,update->laststep);
modify->addstep_compute(next_thermo);
}
// next = next timestep any output will be done
next = MIN(next_dump_any,next_restart);
next = MIN(next,next_thermo);
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
force a snapshot to be written for all dumps force restart file(s) to be written
called from PRD and TAD called from PRD and TAD
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void Output::write_dump(bigint ntimestep) void Output::write_restart(bigint ntimestep)
{ {
for (int idump = 0; idump < ndump; idump++) { if (restart_flag_single) {
dump[idump]->write(); std::string file = restart1;
last_dump[idump] = ntimestep; std::size_t found = file.find('*');
} if (found != std::string::npos)
} file.replace(found,1,fmt::format("{}",update->ntimestep));
restart->write(file);
}
if (restart_flag_double) {
if (restart_toggle == 0) {
restart->write(restart2a);
restart_toggle = 1;
} else {
restart->write(restart2b);
restart_toggle = 0;
}
}
last_restart = ntimestep;
}
/* ----------------------------------------------------------------------
timestep is being changed, called by update->reset_timestep()
for dumps, require that no dump is "active"
meaning that a snapshot has already been output
reset next output values for restart and thermo
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
no guarantee that variable can be evaluated for ntimestep-1
e.g. if it depends on computes, but live with that rare case for now
------------------------------------------------------------------------- */
void Output::reset_timestep(bigint ntimestep)
{
next_dump_any = MAXBIGINT;
for (int idump = 0; idump < ndump; idump++)
if (last_dump[idump] >= 0)
error->all(FLERR,
"Cannot reset timestep with active dump - must undump first");
if (restart_flag_single) {
if (restart_every_single) {
next_restart_single =
(ntimestep/restart_every_single)*restart_every_single;
if (next_restart_single < ntimestep)
next_restart_single += restart_every_single;
} else {
modify->clearstep_compute();
update->ntimestep--;
bigint nextrestart = static_cast<bigint>
(input->variable->compute_equal(ivar_restart_single));
if (nextrestart < ntimestep)
error->all(FLERR,"Restart variable returned a bad timestep");
update->ntimestep++;
next_restart_single = nextrestart;
modify->addstep_compute(next_restart_single);
}
} else next_restart_single = update->laststep + 1;
if (restart_flag_double) {
if (restart_every_double) {
next_restart_double =
(ntimestep/restart_every_double)*restart_every_double;
if (next_restart_double < ntimestep)
next_restart_double += restart_every_double;
} else {
modify->clearstep_compute();
update->ntimestep--;
bigint nextrestart = static_cast<bigint>
(input->variable->compute_equal(ivar_restart_double));
if (nextrestart < ntimestep)
error->all(FLERR,"Restart variable returned a bad timestep");
update->ntimestep++;
next_restart_double = nextrestart;
modify->addstep_compute(next_restart_double);
}
} else next_restart_double = update->laststep + 1;
next_restart = MIN(next_restart_single,next_restart_double);
if (var_thermo) {
modify->clearstep_compute();
update->ntimestep--;
next_thermo = static_cast<bigint>
(input->variable->compute_equal(ivar_thermo));
if (next_thermo < ntimestep)
error->all(FLERR,"Thermo_modify every variable returned a bad timestep");
update->ntimestep++;
next_thermo = MIN(next_thermo,update->laststep);
modify->addstep_compute(next_thermo);
} else if (thermo_every) {
next_thermo = (ntimestep/thermo_every)*thermo_every;
if (next_thermo < ntimestep) next_thermo += thermo_every;
next_thermo = MIN(next_thermo,update->laststep);
} else next_thermo = update->laststep;
next = MIN(next_dump_any,next_restart);
next = MIN(next,next_thermo);
}
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
calculate when next dump occurs for Dump instance idump timestep size is being changed
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)
{
// dump mode is by timestep
// just set next_dump
if (mode_dump[idump] == 0) {
if (every_dump[idump]) {
// 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]));
if (next_dump[idump] <= ntimestep)
error->all(FLERR,"Dump every variable returned a bad timestep");
}
// dump mode is by simulation time
// set next_time_dump and next_dump
} else {
bigint nextdump;
double nexttime;
double tcurrent = update->atime +
(ntimestep - update->atimestep) * update->dt;
if (every_time_dump[idump] > 0.0) {
// 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) + 1;
// if delta is too small to reach next timestep, use multiple of delta
if (nextdump == ntimestep) {
double tnext = update->atime +
(ntimestep+1 - update->atimestep) * update->dt;
int multiple = static_cast<int>
((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) + 1;
}
} else {
// 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 every/time variable returned a bad time");
nextdump = ntimestep +
static_cast<bigint> ((nexttime - tcurrent - EPSDT*update->dt) /
update->dt) + 1;
if (nextdump <= ntimestep)
error->all(FLERR,"Dump every/time variable too small for next timestep");
}
next_time_dump[idump] = nexttime;
next_dump[idump] = nextdump;
}
}
/* ----------------------------------------------------------------------
force restart file(s) to be written
called from PRD and TAD
------------------------------------------------------------------------- */
void Output::write_restart(bigint ntimestep)
{
if (restart_flag_single) {
std::string file = restart1;
std::size_t found = file.find('*');
if (found != std::string::npos)
file.replace(found,1,fmt::format("{}",update->ntimestep));
restart->write(file);
}
if (restart_flag_double) {
if (restart_toggle == 0) {
restart->write(restart2a);
restart_toggle = 1;
} else {
restart->write(restart2b);
restart_toggle = 0;
}
}
last_restart = ntimestep;
}
/* ----------------------------------------------------------------------
timestep is being changed, called by update->reset_timestep()
for dumps, require that no dump is "active"
meaning that a snapshot has already been output
reset next output values restart and 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
no guarantee that variable can be evaluated for ntimestep-1
e.g. if it depends on computes, but live with that rare case for now
------------------------------------------------------------------------- */
void Output::reset_timestep(bigint ntimestep)
{
next_dump_any = MAXBIGINT;
for (int idump = 0; idump < ndump; idump++)
if (last_dump[idump] >= 0)
error->all(FLERR,
"Cannot reset timestep with active dump - must undump first");
if (restart_flag_single) {
if (restart_every_single) {
next_restart_single =
(ntimestep/restart_every_single)*restart_every_single;
if (next_restart_single < ntimestep)
next_restart_single += restart_every_single;
} else {
modify->clearstep_compute();
update->ntimestep--;
bigint nextrestart = static_cast<bigint>
(input->variable->compute_equal(ivar_restart_single));
if (nextrestart < ntimestep)
error->all(FLERR,"Restart variable returned a bad timestep");
update->ntimestep++;
next_restart_single = nextrestart;
modify->addstep_compute(next_restart_single);
}
} else next_restart_single = update->laststep + 1;
if (restart_flag_double) {
if (restart_every_double) {
next_restart_double =
(ntimestep/restart_every_double)*restart_every_double;
if (next_restart_double < ntimestep)
next_restart_double += restart_every_double;
} else {
modify->clearstep_compute();
update->ntimestep--;
bigint nextrestart = static_cast<bigint>
(input->variable->compute_equal(ivar_restart_double));
if (nextrestart < ntimestep)
error->all(FLERR,"Restart variable returned a bad timestep");
update->ntimestep++;
next_restart_double = nextrestart;
modify->addstep_compute(next_restart_double);
}
} else next_restart_double = update->laststep + 1;
next_restart = MIN(next_restart_single,next_restart_double);
if (var_thermo) {
modify->clearstep_compute();
update->ntimestep--;
next_thermo = static_cast<bigint>
(input->variable->compute_equal(ivar_thermo));
if (next_thermo < ntimestep)
error->all(FLERR,"Thermo_modify every variable returned a bad timestep");
update->ntimestep++;
next_thermo = MIN(next_thermo,update->laststep);
modify->addstep_compute(next_thermo);
} else if (thermo_every) {
next_thermo = (ntimestep/thermo_every)*thermo_every;
if (next_thermo < ntimestep) next_thermo += thermo_every;
next_thermo = MIN(next_thermo,update->laststep);
} else next_thermo = update->laststep;
next = MIN(next_dump_any,next_restart);
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 reset next output values for dumps which have mode_dump=1
called by fix dt/reset (at end of step)
or called by timestep command via run every (also at end of step)
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void Output::reset_dt() void Output::reset_dt()
@ -659,21 +687,10 @@ void Output::reset_dt()
// reset next_dump but do not change next_time_dump, 2 arg for reset_dt() // 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 // do not invoke for a dump already scheduled for this step
// use compute_all() b/c don't know what computes will be needed // since timestep change affects next step
if (next_dump[idump] != ntimestep) { if (next_dump[idump] != ntimestep) {
calculate_next_dump(2,idump,update->ntimestep); calculate_next_dump(2,idump,update->ntimestep);
// NOTE: think I should not do this here
// for time dumps, calc_next_dump should calc the next timestep
// as one less and not add it to computes
// then on that step, write() should not actually write the dump
// but trigger it on next step and addstep_compute_all for that step
// b/c when write() is called, the next-step timestep is set
// unless run every timestep is invoked in-between!
//if (dump[idump]->clearstep || var_dump[idump])
// modify->addstep_compute_all(next_dump[idump]);
} }
} }
@ -684,6 +701,7 @@ void Output::reset_dt()
next = MIN(next,next_thermo); next = MIN(next,next_thermo);
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
add a Dump to list of Dumps add a Dump to list of Dumps
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */

View File

@ -36,6 +36,7 @@ class Output : protected Pointers {
int ndump; // # of Dumps defined int ndump; // # of Dumps defined
int max_dump; // max size of Dump list 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
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 *mode_dump; // 0/1 if write every N timesteps or Delta in sim time
int *every_dump; // dump every N timesteps, 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 double *every_time_dump; // dump every Delta of sim time, 0.0 if variable
@ -75,13 +76,14 @@ class Output : protected Pointers {
void write(bigint); // output for current timestep void write(bigint); // output for current timestep
void write_dump(bigint); // force output of dump snapshots void write_dump(bigint); // force output of dump snapshots
void write_restart(bigint); // force output of a restart file void write_restart(bigint); // force output of a restart file
void reset_timestep(bigint); // reset output which depeneds on timestep void reset_timestep(bigint); // reset output which depends on timestep
void reset_dt(); // reset output which depends on dt void reset_dt(); // reset output which depends on timestep size
void add_dump(int, char **); // add a Dump to Dump list void add_dump(int, char **); // add a Dump to Dump list
void modify_dump(int, char **); // modify a Dump void modify_dump(int, char **); // modify a Dump
void delete_dump(char *); // delete a Dump from Dump list void delete_dump(char *); // delete a Dump from Dump list
int find_dump(const char *); // find a Dump ID int find_dump(const char *); // find a Dump ID
int check_time_dumps(bigint); // check if any time dump is output now
void set_thermo(int, char **); // set thermo output freqquency void set_thermo(int, char **); // set thermo output freqquency
void create_thermo(int, char **); // create a thermo style void create_thermo(int, char **); // create a thermo style

View File

@ -252,8 +252,6 @@ void Verlet::run(int n)
ntimestep = ++update->ntimestep; ntimestep = ++update->ntimestep;
ev_set(ntimestep); ev_set(ntimestep);
printf("VERLET %ld: %d %d\n",ntimestep,eflag,vflag);
// initial time integration // initial time integration
timer->stamp(); timer->stamp();