// clang-format off /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator https://www.lammps.org/, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #include "update.h" #include "style_integrate.h" // IWYU pragma: keep #include "style_minimize.h" // IWYU pragma: keep #include "comm.h" #include "compute.h" #include "integrate.h" #include "error.h" #include "fix.h" #include "force.h" #include "min.h" #include "modify.h" #include "neighbor.h" #include "output.h" #include using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ Update::Update(LAMMPS *lmp) : Pointers(lmp) { char *str; ntimestep = 0; atime = 0.0; atimestep = 0; first_update = 0; whichflag = 0; firststep = laststep = 0; beginstep = endstep = 0; restrict_output = 0; setupflag = 0; post_integrate = 0; multireplica = 0; eflag_global = vflag_global = -1; eflag_atom = vflag_atom = 0; dt_default = 1; dt = 0.0; unit_style = nullptr; set_units("lj"); integrate_style = nullptr; integrate = nullptr; minimize_style = nullptr; minimize = nullptr; integrate_map = new IntegrateCreatorMap(); #define INTEGRATE_CLASS #define IntegrateStyle(key,Class) \ (*integrate_map)[#key] = &integrate_creator; #include "style_integrate.h" // IWYU pragma: keep #undef IntegrateStyle #undef INTEGRATE_CLASS minimize_map = new MinimizeCreatorMap(); #define MINIMIZE_CLASS #define MinimizeStyle(key,Class) \ (*minimize_map)[#key] = &minimize_creator; #include "style_minimize.h" // IWYU pragma: keep #undef MinimizeStyle #undef MINIMIZE_CLASS str = (char *) "verlet"; create_integrate(1,&str,1); str = (char *) "cg"; create_minimize(1,&str,1); } /* ---------------------------------------------------------------------- */ Update::~Update() { delete [] unit_style; delete [] integrate_style; delete integrate; delete [] minimize_style; delete minimize; delete integrate_map; delete minimize_map; } /* ---------------------------------------------------------------------- */ void Update::init() { // init the appropriate integrate and/or minimize class // if neither (e.g. from write_restart) then just return if (whichflag == 0) return; if (whichflag == 1) integrate->init(); else if (whichflag == 2) minimize->init(); // only set first_update if a run or minimize is being performed first_update = 1; } /* ---------------------------------------------------------------------- */ void Update::set_units(const char *style) { // physical constants from: // https://physics.nist.gov/cuu/Constants/Table/allascii.txt // using thermochemical calorie = 4.184 J double dt_old = dt; if (strcmp(style,"lj") == 0) { force->boltz = 1.0; force->hplanck = 1.0; force->mvv2e = 1.0; force->ftm2v = 1.0; force->mv2d = 1.0; force->nktv2p = 1.0; force->qqr2e = 1.0; force->qe2f = 1.0; force->vxmu2f = 1.0; force->xxt2kmu = 1.0; force->e_mass = 0.0; // not yet set force->hhmrr2e = 0.0; force->mvh2r = 0.0; force->angstrom = 1.0; force->femtosecond = 1.0; force->qelectron = 1.0; dt = 0.005; neighbor->skin = 0.3; } else if (strcmp(style,"real") == 0) { force->boltz = 0.0019872067; force->hplanck = 95.306976368; force->mvv2e = 48.88821291 * 48.88821291; force->ftm2v = 1.0 / 48.88821291 / 48.88821291; force->mv2d = 1.0 / 0.602214129; force->nktv2p = 68568.415; force->qqr2e = 332.06371; // see also force->qqr2d_lammps_real force->qe2f = 23.060549; force->vxmu2f = 1.4393264316e4; force->xxt2kmu = 0.1; force->e_mass = 1.0/1836.1527556560675; force->hhmrr2e = 0.0957018663603261; force->mvh2r = 1.5339009481951; force->angstrom = 1.0; force->femtosecond = 1.0; force->qelectron = 1.0; dt = 1.0; neighbor->skin = 2.0; } else if (strcmp(style,"metal") == 0) { force->boltz = 8.617343e-5; force->hplanck = 4.135667403e-3; force->mvv2e = 1.0364269e-4; force->ftm2v = 1.0 / 1.0364269e-4; force->mv2d = 1.0 / 0.602214129; force->nktv2p = 1.6021765e6; force->qqr2e = 14.399645; force->qe2f = 1.0; force->vxmu2f = 0.6241509647; force->xxt2kmu = 1.0e-4; force->e_mass = 0.0; // not yet set force->hhmrr2e = 0.0; force->mvh2r = 0.0; force->angstrom = 1.0; force->femtosecond = 1.0e-3; force->qelectron = 1.0; dt = 0.001; neighbor->skin = 2.0; } else if (strcmp(style,"si") == 0) { force->boltz = 1.3806504e-23; force->hplanck = 6.62606896e-34; force->mvv2e = 1.0; force->ftm2v = 1.0; force->mv2d = 1.0; force->nktv2p = 1.0; force->qqr2e = 8.9876e9; force->qe2f = 1.0; force->vxmu2f = 1.0; force->xxt2kmu = 1.0; force->e_mass = 0.0; // not yet set force->hhmrr2e = 0.0; force->mvh2r = 0.0; force->angstrom = 1.0e-10; force->femtosecond = 1.0e-15; force->qelectron = 1.6021765e-19; dt = 1.0e-8; neighbor->skin = 0.001; } else if (strcmp(style,"cgs") == 0) { force->boltz = 1.3806504e-16; force->hplanck = 6.62606896e-27; force->mvv2e = 1.0; force->ftm2v = 1.0; force->mv2d = 1.0; force->nktv2p = 1.0; force->qqr2e = 1.0; force->qe2f = 1.0; force->vxmu2f = 1.0; force->xxt2kmu = 1.0; force->e_mass = 0.0; // not yet set force->hhmrr2e = 0.0; force->mvh2r = 0.0; force->angstrom = 1.0e-8; force->femtosecond = 1.0e-15; force->qelectron = 4.8032044e-10; dt = 1.0e-8; neighbor->skin = 0.1; } else if (strcmp(style,"electron") == 0) { force->boltz = 3.16681534e-6; force->hplanck = 0.1519829846; force->mvv2e = 1.06657236; force->ftm2v = 0.937582899; force->mv2d = 1.0; force->nktv2p = 2.94210108e13; force->qqr2e = 1.0; force->qe2f = 1.94469051e-10; force->vxmu2f = 3.39893149e1; force->xxt2kmu = 3.13796367e-2; force->e_mass = 0.0; // not yet set force->hhmrr2e = 0.0; force->mvh2r = 0.0; force->angstrom = 1.88972612; force->femtosecond = 1.0; force->qelectron = 1.0; dt = 0.001; neighbor->skin = 2.0; } else if (strcmp(style,"micro") == 0) { force->boltz = 1.3806504e-8; force->hplanck = 6.62606896e-13; force->mvv2e = 1.0; force->ftm2v = 1.0; force->mv2d = 1.0; force->nktv2p = 1.0; force->qqr2e = 8.987556e6; force->qe2f = 1.0; force->vxmu2f = 1.0; force->xxt2kmu = 1.0; force->e_mass = 0.0; // not yet set force->hhmrr2e = 0.0; force->mvh2r = 0.0; force->angstrom = 1.0e-4; force->femtosecond = 1.0e-9; force->qelectron = 1.6021765e-7; dt = 2.0; neighbor->skin = 0.1; } else if (strcmp(style,"nano") == 0) { force->boltz = 0.013806504; force->hplanck = 6.62606896e-4; force->mvv2e = 1.0; force->ftm2v = 1.0; force->mv2d = 1.0; force->nktv2p = 1.0; force->qqr2e = 230.7078669; force->qe2f = 1.0; force->vxmu2f = 1.0; force->xxt2kmu = 1.0; force->e_mass = 0.0; // not yet set force->hhmrr2e = 0.0; force->mvh2r = 0.0; force->angstrom = 1.0e-1; force->femtosecond = 1.0e-6; force->qelectron = 1.0; dt = 0.00045; neighbor->skin = 0.1; } else error->all(FLERR,"Illegal units command"); delete [] unit_style; unit_style = utils::strdup(style); // check if timestep was changed from default value if (!dt_default && (comm->me == 0)) { error->warning(FLERR,"Changing timestep from {:.6} to {:.6} due to " "changing units to {}", dt_old, dt, unit_style); } dt_default = 1; } /* ---------------------------------------------------------------------- */ void Update::create_integrate(int narg, char **arg, int trysuffix) { if (narg < 1) error->all(FLERR,"Illegal run_style command"); delete [] integrate_style; delete integrate; int sflag; if (narg-1 > 0) { new_integrate(arg[0],narg-1,&arg[1],trysuffix,sflag); } else { new_integrate(arg[0],0,nullptr,trysuffix,sflag); } std::string estyle = arg[0]; if (sflag) { estyle += "/"; if (sflag == 1) estyle += lmp->suffix; else estyle += lmp->suffix2; } integrate_style = new char[estyle.size()+1]; strcpy(integrate_style,estyle.c_str()); } /* ---------------------------------------------------------------------- create the Integrate style, first with suffix appended ------------------------------------------------------------------------- */ void Update::new_integrate(char *style, int narg, char **arg, int trysuffix, int &sflag) { if (trysuffix && lmp->suffix_enable) { if (lmp->suffix) { sflag = 1; std::string estyle = style + std::string("/") + lmp->suffix; if (integrate_map->find(estyle) != integrate_map->end()) { IntegrateCreator &integrate_creator = (*integrate_map)[estyle]; integrate = integrate_creator(lmp, narg, arg); return; } } if (lmp->suffix2) { sflag = 2; std::string estyle = style + std::string("/") + lmp->suffix2; if (integrate_map->find(estyle) != integrate_map->end()) { IntegrateCreator &integrate_creator = (*integrate_map)[estyle]; integrate = integrate_creator(lmp, narg, arg); return; } } } sflag = 0; if (integrate_map->find(style) != integrate_map->end()) { IntegrateCreator &integrate_creator = (*integrate_map)[style]; integrate = integrate_creator(lmp, narg, arg); return; } error->all(FLERR,"Illegal integrate style"); } /* ---------------------------------------------------------------------- one instance per integrate style in style_integrate.h ------------------------------------------------------------------------- */ template Integrate *Update::integrate_creator(LAMMPS *lmp, int narg, char ** arg) { return new T(lmp, narg, arg); } /* ---------------------------------------------------------------------- */ void Update::create_minimize(int narg, char **arg, int trysuffix) { if (narg < 1) error->all(FLERR,"Illegal run_style command"); delete [] minimize_style; delete minimize; int sflag; new_minimize(arg[0],narg-1,&arg[1],trysuffix,sflag); std::string estyle = arg[0]; if (sflag) { estyle += "/"; if (sflag == 1) estyle += lmp->suffix; else estyle += lmp->suffix2; } minimize_style = new char[estyle.size()+1]; strcpy(minimize_style,estyle.c_str()); } /* ---------------------------------------------------------------------- create the Minimize style, first with suffix appended ------------------------------------------------------------------------- */ void Update::new_minimize(char *style, int /* narg */, char ** /* arg */, int trysuffix, int &sflag) { if (trysuffix && lmp->suffix_enable) { if (lmp->suffix) { sflag = 1; std::string estyle = style + std::string("/") + lmp->suffix; if (minimize_map->find(estyle) != minimize_map->end()) { MinimizeCreator &minimize_creator = (*minimize_map)[estyle]; minimize = minimize_creator(lmp); return; } } if (lmp->suffix2) { sflag = 2; std::string estyle = style + std::string("/") + lmp->suffix2; if (minimize_map->find(estyle) != minimize_map->end()) { MinimizeCreator &minimize_creator = (*minimize_map)[estyle]; minimize = minimize_creator(lmp); return; } } } sflag = 0; if (minimize_map->find(style) != minimize_map->end()) { MinimizeCreator &minimize_creator = (*minimize_map)[style]; minimize = minimize_creator(lmp); return; } error->all(FLERR,"Illegal minimize style"); } /* ---------------------------------------------------------------------- one instance per minimize style in style_minimize.h ------------------------------------------------------------------------- */ template Min *Update::minimize_creator(LAMMPS *lmp) { return new T(lmp); } /* ---------------------------------------------------------------------- reset timestep as called from input script ------------------------------------------------------------------------- */ void Update::reset_timestep(int narg, char **arg) { if (narg != 1) error->all(FLERR,"Illegal reset_timestep command"); bigint newstep = utils::bnumeric(FLERR,arg[0],false,lmp); reset_timestep(newstep); } /* ---------------------------------------------------------------------- reset timestep called from rerun command and input script (indirectly) ------------------------------------------------------------------------- */ void Update::reset_timestep(bigint newstep) { 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 atimestep = ntimestep; // trigger reset of timestep for output // do not allow any timestep-dependent fixes to be already defined output->reset_timestep(ntimestep); for (int i = 0; i < modify->nfix; i++) { if (modify->fix[i]->time_depend) error->all(FLERR, "Cannot reset timestep with a time-dependent fix defined"); } // reset eflag/vflag global so no commands will think eng/virial are current eflag_global = vflag_global = -1; // reset invoked flags of computes, // so no commands will think they are current between runs for (int i = 0; i < modify->ncompute; i++) { modify->compute[i]->invoked_scalar = -1; modify->compute[i]->invoked_vector = -1; modify->compute[i]->invoked_array = -1; modify->compute[i]->invoked_peratom = -1; modify->compute[i]->invoked_local = -1; } // clear timestep list of computes that store future invocation times for (int i = 0; i < modify->ncompute; i++) if (modify->compute[i]->timeflag) modify->compute[i]->clearstep(); // Neighbor Bin/Stencil/Pair classes store timestamps that need to be cleared neighbor->reset_timestep(ntimestep); // NOTE: 7Jun12, adding rerun command, don't think this is required //for (int i = 0; i < domain->nregion; i++) // if (domain->regions[i]->dynamic_check()) // error->all(FLERR,"Cannot reset timestep with a dynamic region defined"); } /* ---------------------------------------------------------------------- update elapsed simulation time called at end of runs or when timestep size changes ------------------------------------------------------------------------- */ void Update::update_time() { atime += (ntimestep-atimestep) * dt; atimestep = ntimestep; } /* ---------------------------------------------------------------------- memory usage of update and integrate/minimize ------------------------------------------------------------------------- */ double Update::memory_usage() { double bytes = 0; if (whichflag == 1) bytes += integrate->memory_usage(); else if (whichflag == 2) bytes += minimize->memory_usage(); return bytes; }