diff --git a/doc/src/Intro_citing.rst b/doc/src/Intro_citing.rst index a74d3134f3..e758992e2b 100644 --- a/doc/src/Intro_citing.rst +++ b/doc/src/Intro_citing.rst @@ -38,17 +38,18 @@ In addition there are DOIs for individual stable releases. Currently there are: Home page ^^^^^^^^^ -The LAMMPS website at `https://lammps.sandia.gov/ `_ is the canonical -location for information about LAMMPS and more detailed lists of publications -using LAMMPS and contributing features. +The LAMMPS website at `https://lammps.sandia.gov/ +`_ is the canonical location for information +about LAMMPS and its features. Citing contributions ^^^^^^^^^^^^^^^^^^^^ -LAMMPS has many features and uses previously published methods and -algorithms or novel features. It also includes potential parameter -filed for specific models. You can look up relevant publications either -in the LAMMPS output to the screen, the ``log.cite`` file (which is -populated with references to relevant papers through embedding them into -the source code) and in the documentation of the :doc:`corresponding commands +LAMMPS has many features and that use either previously published +methods and algorithms or novel features. It also includes potential +parameter filed for specific models. Where available, a reminder about +references for optional features used in a specific run is printed to +the screen and log file. Style and output location can be selected with +the :ref:`-cite command-line switch `. Additional references are +given in the documentation of the :doc:`corresponding commands ` or in the :doc:`Howto tutorials `. diff --git a/doc/src/Modify_contribute.rst b/doc/src/Modify_contribute.rst index 27de36f30c..4998712a3d 100644 --- a/doc/src/Modify_contribute.rst +++ b/doc/src/Modify_contribute.rst @@ -206,16 +206,22 @@ packages in the src directory for examples. If you are uncertain, please ask. algorithm/science behind the feature itself, or its initial usage, or its implementation in LAMMPS), you can add the citation to the \*.cpp source file. See src/USER-EFF/atom_vec_electron.cpp for an example. - A LaTeX citation is stored in a variable at the top of the file and a - single line of code that references the variable is added to the - constructor of the class. Whenever a user invokes your feature from - their input script, this will cause LAMMPS to output the citation to a - log.cite file and prompt the user to examine the file. Note that you - should only use this for a paper you or your group authored. - E.g. adding a cite in the code for a paper by Nose and Hoover if you - write a fix that implements their integrator is not the intended - usage. That kind of citation should just be in the doc page you - provide. + A LaTeX citation is stored in a variable at the top of the file and + a single line of code registering this variable is added to the + constructor of the class. If there is additional functionality (which + may have been added later) described in a different publication, + additional citation descriptions may be added for as long as they + are only registered when the corresponding keyword activating this + functionality is used. With these options it is possible to have + LAMMPS output a specific citation reminder whenever a user invokes + your feature from their input script. Note that you should only use + this for the most relevant paper for a feature and a publication that + you or your group authored. E.g. adding a citation in the code for + a paper by Nose and Hoover if you write a fix that implements their + integrator is not the intended usage. That kind of citation should + just be included in the documentation page you provide describing + your contribution. If you are not sure what the best option would + be, please contact the LAMMPS developers for advice. Finally, as a general rule-of-thumb, the more clear and self-explanatory you make your documentation and README files, and the diff --git a/doc/src/Run_options.rst b/doc/src/Run_options.rst index 9c269e552f..25756d9be0 100644 --- a/doc/src/Run_options.rst +++ b/doc/src/Run_options.rst @@ -11,6 +11,7 @@ letter abbreviation can be used: * :ref:`-k or -kokkos ` * :ref:`-l or -log ` * :ref:`-m or -mpicolor ` +* :ref:`-c or -cite ` * :ref:`-nc or -nocite ` * :ref:`-pk or -package ` * :ref:`-p or -partition ` @@ -220,14 +221,31 @@ links with from the lib/message directory. See the ---------- +.. _cite: + +**-cite style or file name** + +Select how and where to output a reminder about citing contributions +to the LAMMPS code that were used during the run. Available styles are +"both", "none", "screen", or "log". Any flag will be considered a file +name to write the detailed citation info to. Default is the "log" style +where there is a short summary in the screen output and detailed citations +in BibTeX format in the logfile. The option "both" selects the detailed +output for both, "none", the short output for both, and "screen" will +write the detailed info to the screen and the short version to the log +file. If a dedicated citation info file is requested, the screen and +log file output will be in the short format (same as with "none"). + +See the :doc:`citation page ` for more details on +how to correctly reference and cite LAMMPS. + +---------- + .. _nocite: **-nocite** -Disable writing the log.cite file which is normally written to list -references for specific cite-able features used during a LAMMPS run. -See the `citation page `_ for more -details. +Disable generating a citation reminder (see above) at all. ---------- diff --git a/doc/src/fix_bond_react.rst b/doc/src/fix_bond_react.rst index b995239d08..5291aff81b 100644 --- a/doc/src/fix_bond_react.rst +++ b/doc/src/fix_bond_react.rst @@ -650,8 +650,8 @@ reset_mol_ids = yes, custom_charges = no, molecule = off, modify_create = no .. _Gissinger: -**(Gissinger)** Gissinger, Jensen and Wise, Polymer, 128, 211-217 (2017). +**(Gissinger2017)** Gissinger, Jensen and Wise, Polymer, 128, 211-217 (2017). .. _Gissinger2020: -**(Gissinger)** Gissinger, Jensen and Wise, Macromolecules, 53, 22, 9953-9961 (2020). +**(Gissinger2020)** Gissinger, Jensen and Wise, Macromolecules, 53, 22, 9953-9961 (2020). diff --git a/doc/src/kim_commands.rst b/doc/src/kim_commands.rst index 99f7efffd5..e9afa48fd5 100644 --- a/doc/src/kim_commands.rst +++ b/doc/src/kim_commands.rst @@ -1286,7 +1286,7 @@ to cite the OpenKIM project :ref:`(Tadmor) `, KIM API in addition to the relevant scientific references for the IM. The citation format for an IM is displayed on its page on `OpenKIM `_ along with the corresponding BibTex file, -and is automatically added to the LAMMPS *log.cite* file. +and is automatically added to the LAMMPS citation reminder. Citing the IM software (KIM infrastructure and specific PM or SM codes) used in the simulation gives credit to the researchers who developed them diff --git a/src/citeme.cpp b/src/citeme.cpp index 4b1b627298..fdd1ee867d 100644 --- a/src/citeme.cpp +++ b/src/citeme.cpp @@ -12,64 +12,118 @@ ------------------------------------------------------------------------- */ #include "citeme.h" +#include "comm.h" #include "universe.h" using namespace LAMMPS_NS; -static const char cite_header[] = - "This LAMMPS simulation made specific use of work described in the\n" - "following references. See https://lammps.sandia.gov/cite.html\n" - "for details.\n\n"; +static const char cite_separator[] = + "CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE\n\n"; -static const char cite_nagline[] = "\nPlease see the log.cite file " - "for references relevant to this simulation\n\n"; +static const char cite_nagline[] = + "Your simulation uses code contributions which should be cited:\n"; + +static const char cite_file[] = "The {} {} lists these citations in " + "BibTeX format.\n\n"; /* ---------------------------------------------------------------------- */ -CiteMe::CiteMe(LAMMPS *lmp) : Pointers(lmp) +CiteMe::CiteMe(LAMMPS *lmp, int _screen, int _logfile, const char *_file) + : Pointers(lmp) { fp = nullptr; cs = new citeset(); + + screen_flag = _screen; + scrbuffer.clear(); + logfile_flag = _logfile; + logbuffer.clear(); + + if (_file && universe->me == 0) { + citefile = _file; + fp = fopen(_file,"w"); + if (fp) { + fputs(cite_nagline,fp); + fflush(fp); + } else { + utils::logmesg(lmp, "Unable to open citation file '" + citefile + + "': " + utils::getsyserror() + "\n"); + } + } } /* ---------------------------------------------------------------------- - write out nag-line at the end of the regular output and clean up + write out remaining citations at end of the regular output and clean up ------------------------------------------------------------------------- */ CiteMe::~CiteMe() { - if (universe->me || cs->size() == 0) { - delete cs; - return; - } - + flush(); delete cs; - if (fp) { - if (screen) fprintf(screen,cite_nagline); - if (logfile) fprintf(logfile,cite_nagline); - - fclose(fp); - } + if (fp) fclose(fp); } /* ---------------------------------------------------------------------- - write out and register a citation so it will be written only once + process an added citation so it will be shown only once and as requested ------------------------------------------------------------------------- */ void CiteMe::add(const char *ref) { - if (universe->me) return; + if (comm->me != 0) return; if (cs->find(ref) != cs->end()) return; cs->insert(ref); - if (!fp) { - fp = fopen("log.cite","w"); - if (!fp) return; - fputs(cite_header,fp); + if (fp) { + fputs(ref,fp); fflush(fp); } - fputs(ref,fp); - fflush(fp); + if (scrbuffer.empty()) { + scrbuffer += "\n"; + scrbuffer += cite_separator; + scrbuffer += cite_nagline; + if (screen_flag == VERBOSE) scrbuffer += "\n"; + } + + if (logbuffer.empty()) { + logbuffer += "\n"; + logbuffer += cite_separator; + logbuffer += cite_nagline; + if (logfile_flag == VERBOSE) logbuffer += "\n"; + } + + std::string reference = ref; + std::size_t found = reference.find_first_of("\n"); + std::string header = reference.substr(0,found+1); + if (screen_flag == VERBOSE) scrbuffer += "- " + reference; + if (screen_flag == TERSE) scrbuffer += "- " + header; + if (logfile_flag == VERBOSE) logbuffer += "- " + reference; + if (logfile_flag == TERSE) logbuffer += "- " + header; } + +void CiteMe::flush() +{ + if (comm->me == 0) { + if (!scrbuffer.empty()) { + if (!citefile.empty()) + scrbuffer += fmt::format(cite_file,"file",citefile); + if (logfile_flag == VERBOSE) + scrbuffer += fmt::format(cite_file,"log","file"); + scrbuffer += cite_separator; + if (screen) fputs(scrbuffer.c_str(),screen); + scrbuffer.clear(); + } + if (!logbuffer.empty()) { + if (!citefile.empty()) + logbuffer += fmt::format(cite_file,"file",citefile); + if (screen_flag == VERBOSE) + scrbuffer += fmt::format(cite_file,"screen","output"); + logbuffer += cite_separator; + if (logfile) fputs(logbuffer.c_str(),logfile); + logbuffer.clear(); + } + } + return; +} + diff --git a/src/citeme.h b/src/citeme.h index c383ec2227..dd54268a3b 100644 --- a/src/citeme.h +++ b/src/citeme.h @@ -21,27 +21,33 @@ namespace LAMMPS_NS { class CiteMe : protected Pointers { public: - CiteMe(class LAMMPS *); + CiteMe(class LAMMPS *, int, int, const char *); virtual ~CiteMe(); - void add(const char *); // print out and register publication + void add(const char *); // register publication for output + void flush(); // flush buffers to screen and logfile + enum {VERBOSE, TERSE}; private: - FILE *fp; // opaque pointer to log.cite file object + FILE *fp; // explicit citation file pointer or NULL + std::string citefile; // name of the explicit citation file. + int screen_flag; // determine whether verbose or terse output + int logfile_flag; // determine whether verbose or terse output + std::string scrbuffer; // output buffer for screen + std::string logbuffer; // output buffer for logfile typedef std::set citeset; citeset *cs; // registered set of publications }; - } #endif /* ERROR/WARNING messages: -E: Cannot open log.cite file +E: Cannot open citation file This file is created when you use some LAMMPS features, to indicate what paper you should cite on behalf of those who implemented -the feature. Check that you have write privileges into the directory +the feature. Check that you have write privileges in the directory you are running in. */ diff --git a/src/integrate.cpp b/src/integrate.cpp index 5c700527a1..f866840f1c 100644 --- a/src/integrate.cpp +++ b/src/integrate.cpp @@ -12,12 +12,14 @@ ------------------------------------------------------------------------- */ #include "integrate.h" -#include "update.h" + +#include "citeme.h" +#include "compute.h" #include "force.h" -#include "pair.h" #include "kspace.h" #include "modify.h" -#include "compute.h" +#include "pair.h" +#include "update.h" using namespace LAMMPS_NS; @@ -45,6 +47,7 @@ Integrate::~Integrate() void Integrate::init() { + if (lmp->citeme) lmp->citeme->flush(); update->atimestep = update->ntimestep; // allow pair and Kspace compute() to be turned off via modify flags diff --git a/src/lammps.cpp b/src/lammps.cpp index 0b38f09ef5..6734fbd209 100644 --- a/src/lammps.cpp +++ b/src/lammps.cpp @@ -171,6 +171,9 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) : int restart2dump = 0; int restartremap = 0; int citeflag = 1; + int citescreen = CiteMe::TERSE; + int citelogfile = CiteMe::VERBOSE; + char *citefile = nullptr; int helpflag = 0; suffix = suffix2 = suffixp = nullptr; @@ -190,7 +193,35 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) : iarg = 1; while (iarg < narg) { - if (strcmp(arg[iarg],"-echo") == 0 || + if (strcmp(arg[iarg],"-cite") == 0 || + strcmp(arg[iarg],"-c") == 0) { + if (iarg+2 > narg) + error->universe_all(FLERR,"Invalid command-line argument"); + + if (strcmp(arg[iarg+1],"both") == 0) { + citescreen = CiteMe::VERBOSE; + citelogfile = CiteMe::VERBOSE; + citefile = nullptr; + } else if (strcmp(arg[iarg+1],"none") == 0) { + citescreen = CiteMe::TERSE; + citelogfile = CiteMe::TERSE; + citefile = nullptr; + } else if (strcmp(arg[iarg+1],"screen") == 0) { + citescreen = CiteMe::VERBOSE; + citelogfile = CiteMe::TERSE; + citefile = nullptr; + } else if (strcmp(arg[iarg+1],"log") == 0) { + citescreen = CiteMe::TERSE; + citelogfile = CiteMe::VERBOSE; + citefile = nullptr; + } else { + citescreen = CiteMe::TERSE; + citelogfile = CiteMe::TERSE; + citefile = arg[iarg+1]; + } + iarg += 2; + + } else if (strcmp(arg[iarg],"-echo") == 0 || strcmp(arg[iarg],"-e") == 0) { if (iarg+2 > narg) error->universe_all(FLERR,"Invalid command-line argument"); @@ -605,7 +636,7 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) : // allocate CiteMe class if enabled - if (citeflag) citeme = new CiteMe(this); + if (citeflag) citeme = new CiteMe(this,citescreen,citelogfile,citefile); else citeme = nullptr; // allocate input class now that MPI is fully setup @@ -669,8 +700,8 @@ LAMMPS::~LAMMPS() { const int me = comm->me; - destroy(); delete citeme; + destroy(); if (num_package) { for (int i = 0; i < num_package; i++) { @@ -1111,7 +1142,8 @@ void _noopt LAMMPS::help() "-kokkos on/off ... : turn KOKKOS mode on or off (-k)\n" "-log none/filename : where to send log output (-l)\n" "-mpicolor color : which exe in a multi-exe mpirun cmd (-m)\n" - "-nocite : disable writing log.cite file (-nc)\n" + "-cite : select citation reminder style (-c)\n" + "-nocite : disable citation reminder (-nc)\n" "-package style ... : invoke package command (-pk)\n" "-partition size1 size2 ... : assign partition sizes (-p)\n" "-plog basename : basename for partition logs (-pl)\n" diff --git a/src/lammps.h b/src/lammps.h index 49d55d4e37..553db6597e 100644 --- a/src/lammps.h +++ b/src/lammps.h @@ -56,7 +56,6 @@ class LAMMPS { char *exename; // pointer to argv[0] char ***packargs; // arguments for cmdline package commands int num_package; // number of cmdline package commands - int cite_enable; // 1 if generating log.cite, 0 if disabled int clientserver; // 0 = neither, 1 = client, 2 = server void *cslib; // client/server messaging via CSlib @@ -66,9 +65,9 @@ class LAMMPS { class AtomKokkos *atomKK; // KOKKOS version of Atom class class MemoryKokkos *memoryKK; // KOKKOS version of Memory class - class Python * python; // Python interface + class Python *python; // Python interface - class CiteMe *citeme; // citation info + class CiteMe *citeme; // handle citation info const char *match_style(const char *style, const char *name); static const char * installed_packages[]; diff --git a/src/minimize.cpp b/src/minimize.cpp index a909afdaa5..8e55d6e0ea 100644 --- a/src/minimize.cpp +++ b/src/minimize.cpp @@ -13,6 +13,7 @@ #include "minimize.h" +#include "citeme.h" #include "domain.h" #include "error.h" #include "finish.h" @@ -46,6 +47,7 @@ void Minimize::command(int narg, char **arg) if (update->etol < 0.0 || update->ftol < 0.0) error->all(FLERR,"Illegal minimize command"); + if (lmp->citeme) lmp->citeme->flush(); update->whichflag = 2; update->beginstep = update->firststep = update->ntimestep; update->endstep = update->laststep = update->firststep + update->nsteps;