diff --git a/src/dump.cpp b/src/dump.cpp index 21c1b16f75..df39f3738d 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -330,8 +330,6 @@ void Dump::write() if (delay_flag && update->ntimestep < delaystep) return; - printf("DUMP %ld\n",update->ntimestep); - // if file per timestep, open new file if (multifile) openfile(); diff --git a/src/integrate.cpp b/src/integrate.cpp index 52d34fb943..7a1dbfaf34 100644 --- a/src/integrate.cpp +++ b/src/integrate.cpp @@ -20,6 +20,7 @@ #include "kspace.h" #include "modify.h" #include "pair.h" +#include "output.h" #include "update.h" using namespace LAMMPS_NS; @@ -115,7 +116,13 @@ void Integrate::ev_setup() /* ---------------------------------------------------------------------- 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 eflag: set any or no bits ENERGY_GLOBAL bit for global energy @@ -133,6 +140,10 @@ void Integrate::ev_set(bigint ntimestep) { int i,flag; + int tdflag = 0; + if (output->any_time_dumps) + tdflag = output->check_time_dumps(ntimestep); + flag = 0; int eflag_global = 0; for (i = 0; i < nelist_global; i++) @@ -143,7 +154,7 @@ void Integrate::ev_set(bigint ntimestep) int eflag_atom = 0; for (i = 0; i < nelist_atom; i++) 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_atom) update->eflag_atom = ntimestep; @@ -159,13 +170,13 @@ void Integrate::ev_set(bigint ntimestep) int vflag_atom = 0; for (i = 0; i < nvlist_atom; i++) 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; int cvflag_atom = 0; for (i = 0; i < ncvlist_atom; i++) 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_atom || cvflag_atom) update->vflag_atom = ntimestep; diff --git a/src/output.cpp b/src/output.cpp index 30248e449d..94688cd74c 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -133,7 +133,9 @@ void Output::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) || (mode_dump[i] == 1 && every_time_dump[i] == 0.0)) { ivar_dump[i] = input->variable->find(var_dump[i]); @@ -142,6 +144,7 @@ void Output::init() if (!input->variable->equalstyle(ivar_dump[i])) error->all(FLERR,"Variable for dump every or delta is invalid style"); } + } if (restart_flag_single && restart_every_single == 0) { ivar_restart_single = input->variable->find(var_restart_single); @@ -176,9 +179,11 @@ void Output::setup(int memflag) 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 + // 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(); // 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() // 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]); else modify->addstep_compute_all(next_dump[idump]); } @@ -239,413 +245,435 @@ void Output::setup(int memflag) } else next_dump_any = update->laststep + 1; - // do not write restart files at start of run - // set next_restart values to multiple of every or variable value - // wrap variable eval with clear/add - // if no restarts, set next_restart to last+1 so will not influence next + // do not write restart files at start of run + // set next_restart values to multiple of every or variable value + // wrap variable eval with clear/add + // if no restarts, set next_restart to last+1 so will not influence next - if (restart_flag && update->restrict_output == 0) { - if (restart_flag_single) { - if (restart_every_single) - next_restart_single = - (ntimestep/restart_every_single)*restart_every_single + - restart_every_single; - else { - bigint nextrestart = static_cast - (input->variable->compute_equal(ivar_restart_single)); - if (nextrestart <= ntimestep) - error->all(FLERR,"Restart variable returned a bad timestep"); - next_restart_single = nextrestart; - } - } 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 + - restart_every_double; - else { - bigint nextrestart = static_cast - (input->variable->compute_equal(ivar_restart_double)); - if (nextrestart <= ntimestep) - error->all(FLERR,"Restart variable returned a bad timestep"); - next_restart_double = nextrestart; - } - } else next_restart_double = update->laststep + 1; - next_restart = MIN(next_restart_single,next_restart_double); - } else next_restart = update->laststep + 1; + if (restart_flag && update->restrict_output == 0) { + if (restart_flag_single) { + if (restart_every_single) + next_restart_single = + (ntimestep/restart_every_single)*restart_every_single + + restart_every_single; + else { + bigint nextrestart = static_cast + (input->variable->compute_equal(ivar_restart_single)); + if (nextrestart <= ntimestep) + error->all(FLERR,"Restart variable returned a bad timestep"); + next_restart_single = nextrestart; + } + } 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 + + restart_every_double; + else { + bigint nextrestart = static_cast + (input->variable->compute_equal(ivar_restart_double)); + if (nextrestart <= ntimestep) + error->all(FLERR,"Restart variable returned a bad timestep"); + next_restart_double = nextrestart; + } + } else next_restart_double = update->laststep + 1; + next_restart = MIN(next_restart_single,next_restart_double); + } 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 - // insure thermo output on last step of run - // thermo may invoke computes so wrap with clear/add + // set next_thermo to multiple of every or variable eval if var defined + // insure thermo output on last step of run + // thermo may invoke computes so wrap with clear/add - modify->clearstep_compute(); + modify->clearstep_compute(); - thermo->header(); - thermo->compute(0); - last_thermo = ntimestep; + thermo->header(); + thermo->compute(0); + last_thermo = ntimestep; - if (var_thermo) { - next_thermo = static_cast - (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 = (ntimestep/thermo_every)*thermo_every + thermo_every; - next_thermo = MIN(next_thermo,update->laststep); - } else next_thermo = update->laststep; + if (var_thermo) { + next_thermo = static_cast + (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 = (ntimestep/thermo_every)*thermo_every + thermo_every; + next_thermo = MIN(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,next_thermo); -} + next = MIN(next_dump_any,next_restart); + next = MIN(next,next_thermo); + } -/* ---------------------------------------------------------------------- - perform all output for this timestep - 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 -------------------------------------------------------------------------- */ + /* ---------------------------------------------------------------------- + perform all output for this timestep + 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 + ------------------------------------------------------------------------- */ -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 + (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 + (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 + (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 + (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 (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 ((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 + ((tnext - nexttime) / every_time_dump[idump]); + nexttime = nexttime + (multiple+1)*every_time_dump[idump]; + nextdump = ntimestep + + static_cast ((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 ((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 - // 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 dumps that invoke computes or do variable eval with clear/add + int nowflag = 0; + for (int i = 0; i < ndump; i++) + if (mode_dump[i] && next_dump[i] == ntimestep) nowflag = 1; - 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(); - - // 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 - (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 - (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 - (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); + return nowflag; } -/* ---------------------------------------------------------------------- - force a snapshot to be written for all dumps - called from PRD and TAD -------------------------------------------------------------------------- */ + /* ---------------------------------------------------------------------- + force restart file(s) to be written + 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; - } -} + 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 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 + (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 + (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 + (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 - 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 - (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 (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 ((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 - ((tnext - nexttime) / every_time_dump[idump]); - nexttime = nexttime + (multiple+1)*every_time_dump[idump]; - nextdump = ntimestep + - static_cast ((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 ((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 - (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 - (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 - (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) + timestep size is being changed 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() @@ -659,21 +687,10 @@ void Output::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 - // use compute_all() b/c don't know what computes will be needed + // since timestep change affects next step if (next_dump[idump] != 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); } + /* ---------------------------------------------------------------------- add a Dump to list of Dumps ------------------------------------------------------------------------- */ diff --git a/src/output.h b/src/output.h index c8d3f734e0..c7c4faf252 100644 --- a/src/output.h +++ b/src/output.h @@ -36,6 +36,7 @@ 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 + 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 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_dump(bigint); // force output of dump snapshots void write_restart(bigint); // force output of a restart file - void reset_timestep(bigint); // reset output which depeneds on timestep - void reset_dt(); // reset output which depends on dt + void reset_timestep(bigint); // reset output which depends on timestep + void reset_dt(); // reset output which depends on timestep size void add_dump(int, char **); // add a Dump to Dump list void modify_dump(int, char **); // modify a Dump void delete_dump(char *); // delete a Dump from Dump list 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 create_thermo(int, char **); // create a thermo style diff --git a/src/verlet.cpp b/src/verlet.cpp index 348639ef05..342dc3d951 100644 --- a/src/verlet.cpp +++ b/src/verlet.cpp @@ -252,8 +252,6 @@ void Verlet::run(int n) ntimestep = ++update->ntimestep; ev_set(ntimestep); - printf("VERLET %ld: %d %d\n",ntimestep,eflag,vflag); - // initial time integration timer->stamp();