From bdf8dd4e5415ff0dcd8bcf7a704d64726ff860df Mon Sep 17 00:00:00 2001 From: Jacob Gissinger Date: Fri, 20 Jan 2023 00:32:31 -0500 Subject: [PATCH 1/9] serial version --- src/REAXFF/fix_reaxff_species.cpp | 53 +++++++++++++++++++++++++++++-- src/REAXFF/fix_reaxff_species.h | 1 + 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/REAXFF/fix_reaxff_species.cpp b/src/REAXFF/fix_reaxff_species.cpp index 65a2e6d8ce..ceaf983893 100644 --- a/src/REAXFF/fix_reaxff_species.cpp +++ b/src/REAXFF/fix_reaxff_species.cpp @@ -38,6 +38,7 @@ #include #include +#include using namespace LAMMPS_NS; using namespace FixConst; @@ -145,6 +146,7 @@ FixReaxFFSpecies::FixReaxFFSpecies(LAMMPS *lmp, int narg, char **arg) : ele = filepos = filedel = nullptr; eleflag = posflag = padflag = 0; delflag = specieslistflag = masslimitflag = 0; + delete_Nlimit = delete_Nsteps = 0; singlepos_opened = multipos_opened = del_opened = 0; multipos = 0; @@ -221,7 +223,12 @@ FixReaxFFSpecies::FixReaxFFSpecies(LAMMPS *lmp, int narg, char **arg) : } else error->all(FLERR, "Unknown fix reaxff/species delete option: {}", arg[iarg]); - + // rate limit when deleting molecules + } else if (strcmp(arg[iarg], "delete_rate_limit") == 0) { + if (iarg + 3 > narg) utils::missing_cmd_args(FLERR, "fix reaxff/species delete_rate_limit", error); + delete_Nlimit = utils::numeric(FLERR, arg[iarg+1], false, lmp); + delete_Nsteps = utils::numeric(FLERR, arg[iarg+2], false, lmp); + iarg += 3; // position of molecules } else if (strcmp(arg[iarg], "position") == 0) { if (iarg + 3 > narg) utils::missing_cmd_args(FLERR, "fix reaxff/species position", error); @@ -260,6 +267,14 @@ FixReaxFFSpecies::FixReaxFFSpecies(LAMMPS *lmp, int narg, char **arg) : if (delflag && specieslistflag && masslimitflag) error->all(FLERR, "Incompatible combination fix reaxff/species command options"); + if (delete_Nlimit > 0) { + memory->create(delete_Tcount,delete_Nsteps,"reaxff/species:delete_Tcount"); + + for (int i = 0; i < delete_Nsteps; i++) + delete_Tcount[i] = -1; + delete_Tcount[0] = 0; + } + vector_nmole = 0; vector_nspec = 0; } @@ -279,6 +294,7 @@ FixReaxFFSpecies::~FixReaxFFSpecies() memory->destroy(Mol2Spec); memory->destroy(MolType); memory->destroy(MolName); + memory->destroy(delete_Tcount); delete[] filepos; delete[] filedel; @@ -375,6 +391,11 @@ void FixReaxFFSpecies::Output_ReaxFF_Bonds(bigint ntimestep, FILE * /*fp*/) // point to fix_ave_atom f_SPECBOND->end_of_step(); + // push back delete_Tcount on every step + if (delete_Nlimit > 0) + for (int i = delete_Nsteps-1; i > 0; i--) + delete_Tcount[i] = delete_Tcount[i-1]; + if (ntimestep != nvalid) return; nlocal = atom->nlocal; @@ -826,6 +847,15 @@ void FixReaxFFSpecies::WritePos(int Nmole, int Nspec) void FixReaxFFSpecies::DeleteSpecies(int Nmole, int Nspec) { + int ndeletions; + int headroom = -1; + if (delete_Nlimit > 0) { + if (delete_Tcount[delete_Nsteps-1] == -1) return; + ndeletions = delete_Tcount[0] - delete_Tcount[delete_Nsteps-1]; + headroom = MAX(0, delete_Nlimit - ndeletions); + if (headroom == 0) return; + } + int i, j, m, n, itype, cid; int ndel, ndelone, count, count_tmp; int *Nameall; @@ -856,7 +886,20 @@ void FixReaxFFSpecies::DeleteSpecies(int Nmole, int Nspec) int *marklist; memory->create(marklist, nlocal, "reaxff/species:marklist"); - for (m = 1; m <= Nmole; m++) { + std::random_device rnd; + std::minstd_rand park_rng(rnd()); + int *molrange; + memory->create(molrange,Nmole,"reaxff/species:molrange"); + for (m = 0; m < Nmole; m++) + molrange[m] = m + 1; + // shuffle index when using rate_limit, in case order is biased + if (delete_Nlimit > 0) + std::shuffle(&molrange[0],&molrange[Nmole], park_rng); + + int this_delete_Tcount = 0; + for (int mm = 0; mm < Nmole; mm++) { + if (this_delete_Tcount == headroom) break; + m = molrange[mm]; localmass = totalmass = count = nmarklist = 0; for (n = 0; n < ntypes; n++) Name[n] = 0; @@ -896,6 +939,7 @@ void FixReaxFFSpecies::DeleteSpecies(int Nmole, int Nspec) // find corresponding moltype if (totalmass > massmin && totalmass < massmax) { + this_delete_Tcount++; for (j = 0; j < nmarklist; j++) { mark[marklist[j]] = 1; deletecount[Mol2Spec[m - 1]] += 1.0 / (double) count; @@ -905,6 +949,7 @@ void FixReaxFFSpecies::DeleteSpecies(int Nmole, int Nspec) if (count > 0) { for (i = 0; i < ndelspec; i++) { if (del_species[i] == species_str) { + this_delete_Tcount++; for (j = 0; j < nmarklist; j++) { mark[marklist[j]] = 1; deletecount[i] += 1.0 / (double) count; @@ -976,6 +1021,9 @@ void FixReaxFFSpecies::DeleteSpecies(int Nmole, int Nspec) } } + if (delete_Nlimit) + delete_Tcount[0] += this_delete_Tcount; + if (ndel && (atom->map_style != Atom::MAP_NONE)) { atom->nghost = 0; atom->map_init(); @@ -988,6 +1036,7 @@ void FixReaxFFSpecies::DeleteSpecies(int Nmole, int Nspec) memory->destroy(marklist); memory->destroy(mark); memory->destroy(deletecount); + memory->destroy(molrange); } /* ---------------------------------------------------------------------- */ diff --git a/src/REAXFF/fix_reaxff_species.h b/src/REAXFF/fix_reaxff_species.h index 65eeae4c60..329e17145b 100644 --- a/src/REAXFF/fix_reaxff_species.h +++ b/src/REAXFF/fix_reaxff_species.h @@ -60,6 +60,7 @@ class FixReaxFFSpecies : public Fix { FILE *fp, *pos, *fdel; int eleflag, posflag, multipos, padflag, setupflag; int delflag, specieslistflag, masslimitflag; + int delete_Nlimit, delete_Nsteps, *delete_Tcount; double massmin, massmax; int singlepos_opened, multipos_opened, del_opened; char *ele, **eletype, *filepos, *filedel; From 096e0a14f009fcfa05d777daabb66e2bd7b89d8f Mon Sep 17 00:00:00 2001 From: Jacob Gissinger Date: Fri, 20 Jan 2023 00:38:06 -0500 Subject: [PATCH 2/9] off-by-one fix --- src/REAXFF/fix_reaxff_species.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/REAXFF/fix_reaxff_species.cpp b/src/REAXFF/fix_reaxff_species.cpp index ceaf983893..6ad7b50226 100644 --- a/src/REAXFF/fix_reaxff_species.cpp +++ b/src/REAXFF/fix_reaxff_species.cpp @@ -391,12 +391,13 @@ void FixReaxFFSpecies::Output_ReaxFF_Bonds(bigint ntimestep, FILE * /*fp*/) // point to fix_ave_atom f_SPECBOND->end_of_step(); - // push back delete_Tcount on every step - if (delete_Nlimit > 0) - for (int i = delete_Nsteps-1; i > 0; i--) - delete_Tcount[i] = delete_Tcount[i-1]; - - if (ntimestep != nvalid) return; + if (ntimestep != nvalid) { + // push back delete_Tcount on every step + if (delete_Nlimit > 0) + for (int i = delete_Nsteps-1; i > 0; i--) + delete_Tcount[i] = delete_Tcount[i-1]; + return; + } nlocal = atom->nlocal; @@ -1021,8 +1022,13 @@ void FixReaxFFSpecies::DeleteSpecies(int Nmole, int Nspec) } } - if (delete_Nlimit) + + // push back delete_Tcount on every step + if (delete_Nlimit > 0) { + for (i = delete_Nsteps-1; i > 0; i--) + delete_Tcount[i] = delete_Tcount[i-1]; delete_Tcount[0] += this_delete_Tcount; + } if (ndel && (atom->map_style != Atom::MAP_NONE)) { atom->nghost = 0; From bebf79ec92251f04d36b40dfce0e7f627d74f50a Mon Sep 17 00:00:00 2001 From: Jacob Gissinger Date: Fri, 20 Jan 2023 00:41:56 -0500 Subject: [PATCH 3/9] reaxff species delete_rate_limit keyword docs --- doc/src/fix_reaxff_species.rst | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/src/fix_reaxff_species.rst b/doc/src/fix_reaxff_species.rst index 11f0e7b7e7..dcb9cfa3bc 100644 --- a/doc/src/fix_reaxff_species.rst +++ b/doc/src/fix_reaxff_species.rst @@ -39,6 +39,9 @@ Syntax *masslimit* value = massmin massmax massmin = minimum molecular weight of species to delete massmax = maximum molecular weight of species to delete + *delete_rate_limit* value = Nlimit Nsteps + Nlimit = maximum number of deletions allowed to occur within interval + Nsteps = the interval (number of timesteps) over which to count deletions Examples """""""" @@ -140,7 +143,13 @@ When using the *masslimit* keyword, each line of the *filedel* file contains the timestep on which deletions occurs, followed by how many of each species are deleted (with quantities preceding chemical formulae). The *specieslist* and *masslimit* keywords cannot both be -used in the same *reaxff/species* fix. +used in the same *reaxff/species* fix. The *delete_rate_limit* +keyword can enforce an upper limit on the overall rate of molecule +deletion. The number of deletion occurrences is limited to Nlimit +within an interval of Nsteps timesteps. When using the +*delete_rate_limit* keyword, no deletions are permitted to occur +within the first Nsteps timesteps of the first run (after reading a +either a data or restart file). ---------- From ff709f5897c38a8d5d685a9957865dc5ae0dc27a Mon Sep 17 00:00:00 2001 From: Jacob Gissinger Date: Fri, 20 Jan 2023 16:29:16 -0500 Subject: [PATCH 4/9] 'include' for std::shuffle --- src/REAXFF/fix_reaxff_species.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/REAXFF/fix_reaxff_species.cpp b/src/REAXFF/fix_reaxff_species.cpp index 6ad7b50226..caffcc08af 100644 --- a/src/REAXFF/fix_reaxff_species.cpp +++ b/src/REAXFF/fix_reaxff_species.cpp @@ -36,6 +36,7 @@ #include "pair_reaxff.h" #include "reaxff_defs.h" +#include #include #include #include From 846f00ce32d6e59cd7acd93b85a8d1eff4d2eea4 Mon Sep 17 00:00:00 2001 From: Jacob Gissinger Date: Fri, 20 Jan 2023 16:58:19 -0500 Subject: [PATCH 5/9] add citation --- src/REAXFF/fix_reaxff_species.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/REAXFF/fix_reaxff_species.cpp b/src/REAXFF/fix_reaxff_species.cpp index caffcc08af..9bc70e7617 100644 --- a/src/REAXFF/fix_reaxff_species.cpp +++ b/src/REAXFF/fix_reaxff_species.cpp @@ -21,6 +21,7 @@ #include "atom.h" #include "atom_vec.h" +#include "citeme.h" #include "comm.h" #include "domain.h" #include "error.h" @@ -44,6 +45,17 @@ using namespace LAMMPS_NS; using namespace FixConst; +static const char cite_reaxff_species_delete[] = + "fix reaxff/species, 'delete' keyword: https://doi.org/10.1016/j.carbon.2022.11.002\n\n" + "@Article{Gissinger23,\n" + " author = {J. R. Gissinger, S. R. Zavada, J. G. Smith, J. Kemppainen, I. Gallegos, G. M. Odegard, E. J. Siochi, K. E. Wise},\n" + " title = {Predicting char yield of high-temperature resins},\n" + " journal = {Carbon},\n" + " year = 2023,\n" + " volume = 202,\n" + " pages = {336-347}\n" + "}\n\n"; + /* ---------------------------------------------------------------------- */ FixReaxFFSpecies::FixReaxFFSpecies(LAMMPS *lmp, int narg, char **arg) : @@ -52,6 +64,8 @@ FixReaxFFSpecies::FixReaxFFSpecies(LAMMPS *lmp, int narg, char **arg) : x0(nullptr), BOCut(nullptr), fp(nullptr), pos(nullptr), fdel(nullptr), ele(nullptr), eletype(nullptr), filepos(nullptr), filedel(nullptr) { + if (lmp->citeme) lmp->citeme->add(cite_reaxff_species_delete); + if (narg < 7) utils::missing_cmd_args(FLERR, "fix reaxff/species", error); force_reneighbor = 1; From 375fad6d2a132ddac5827b6f3b4b6b387e659970 Mon Sep 17 00:00:00 2001 From: Jacob Gissinger Date: Fri, 20 Jan 2023 17:13:56 -0500 Subject: [PATCH 6/9] parallel version --- src/REAXFF/fix_reaxff_species.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/REAXFF/fix_reaxff_species.cpp b/src/REAXFF/fix_reaxff_species.cpp index 9bc70e7617..c3335a0397 100644 --- a/src/REAXFF/fix_reaxff_species.cpp +++ b/src/REAXFF/fix_reaxff_species.cpp @@ -906,11 +906,14 @@ void FixReaxFFSpecies::DeleteSpecies(int Nmole, int Nspec) std::minstd_rand park_rng(rnd()); int *molrange; memory->create(molrange,Nmole,"reaxff/species:molrange"); - for (m = 0; m < Nmole; m++) - molrange[m] = m + 1; - // shuffle index when using rate_limit, in case order is biased - if (delete_Nlimit > 0) - std::shuffle(&molrange[0],&molrange[Nmole], park_rng); + if (comm->me == 0) { + for (m = 0; m < Nmole; m++) + molrange[m] = m + 1; + // shuffle index when using rate_limit, in case order is biased + if (delete_Nlimit > 0) + std::shuffle(&molrange[0],&molrange[Nmole], park_rng); + } + MPI_Bcast(&molrange[0], Nmole, MPI_INT, 0, world); int this_delete_Tcount = 0; for (int mm = 0; mm < Nmole; mm++) { From f6ded5a7d742e600cab2c88878be137d65c68b94 Mon Sep 17 00:00:00 2001 From: Jacob Gissinger Date: Fri, 20 Jan 2023 17:36:46 -0500 Subject: [PATCH 7/9] reduce unnecessary communication --- src/REAXFF/fix_reaxff_species.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/REAXFF/fix_reaxff_species.cpp b/src/REAXFF/fix_reaxff_species.cpp index c3335a0397..a9bab28003 100644 --- a/src/REAXFF/fix_reaxff_species.cpp +++ b/src/REAXFF/fix_reaxff_species.cpp @@ -906,14 +906,14 @@ void FixReaxFFSpecies::DeleteSpecies(int Nmole, int Nspec) std::minstd_rand park_rng(rnd()); int *molrange; memory->create(molrange,Nmole,"reaxff/species:molrange"); - if (comm->me == 0) { - for (m = 0; m < Nmole; m++) - molrange[m] = m + 1; + for (m = 0; m < Nmole; m++) + molrange[m] = m + 1; + if (delete_Nlimit > 0) { // shuffle index when using rate_limit, in case order is biased - if (delete_Nlimit > 0) + if (comm->me == 0) std::shuffle(&molrange[0],&molrange[Nmole], park_rng); + MPI_Bcast(&molrange[0], Nmole, MPI_INT, 0, world); } - MPI_Bcast(&molrange[0], Nmole, MPI_INT, 0, world); int this_delete_Tcount = 0; for (int mm = 0; mm < Nmole; mm++) { From 8537ccb840e406b2049291c2ddfccbb05ce90063 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 21 Jan 2023 11:18:51 -0500 Subject: [PATCH 8/9] add CMake option to skip automatic download of large potential files --- cmake/CMakeLists.txt | 2 ++ cmake/Modules/LAMMPSUtils.cmake | 40 +++++++++++++++++---------------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 0223750ace..767bbbfe34 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -566,6 +566,8 @@ RegisterStyles(${LAMMPS_SOURCE_DIR}) ######################################################## # Fetch missing external files and archives for packages ######################################################## +option(DOWNLOAD_POTENTIALS "Automatically download large potential files" ON) +mark_as_advanced(DOWNLOAD_POTENTIALS) foreach(PKG ${STANDARD_PACKAGES} ${EXTRA_PACKAGES} ${SUFFIX_PACKAGES}) if(PKG_${PKG}) FetchPotentials(${LAMMPS_SOURCE_DIR}/${PKG} ${LAMMPS_POTENTIALS_DIR}) diff --git a/cmake/Modules/LAMMPSUtils.cmake b/cmake/Modules/LAMMPSUtils.cmake index 9602379403..d42f91f10e 100644 --- a/cmake/Modules/LAMMPSUtils.cmake +++ b/cmake/Modules/LAMMPSUtils.cmake @@ -118,25 +118,27 @@ endfunction(GenerateBinaryHeader) # fetch missing potential files function(FetchPotentials pkgfolder potfolder) - if(EXISTS "${pkgfolder}/potentials.txt") - file(STRINGS "${pkgfolder}/potentials.txt" linelist REGEX "^[^#].") - foreach(line ${linelist}) - string(FIND ${line} " " blank) - math(EXPR plusone "${blank}+1") - string(SUBSTRING ${line} 0 ${blank} pot) - string(SUBSTRING ${line} ${plusone} -1 sum) - if(EXISTS "${LAMMPS_POTENTIALS_DIR}/${pot}") - file(MD5 "${LAMMPS_POTENTIALS_DIR}/${pot}" oldsum) - endif() - if(NOT sum STREQUAL oldsum) - message(STATUS "Downloading external potential ${pot} from ${LAMMPS_POTENTIALS_URL}") - string(MD5 TMP_EXT "${CMAKE_BINARY_DIR}") - file(DOWNLOAD "${LAMMPS_POTENTIALS_URL}/${pot}.${sum}" "${CMAKE_BINARY_DIR}/${pot}.${TMP_EXT}" - EXPECTED_HASH MD5=${sum} SHOW_PROGRESS) - file(COPY "${CMAKE_BINARY_DIR}/${pot}.${TMP_EXT}" DESTINATION "${LAMMPS_POTENTIALS_DIR}") - file(RENAME "${LAMMPS_POTENTIALS_DIR}/${pot}.${TMP_EXT}" "${LAMMPS_POTENTIALS_DIR}/${pot}") - endif() - endforeach() + if(DOWNLOAD_POTENTIALS) + if(EXISTS "${pkgfolder}/potentials.txt") + file(STRINGS "${pkgfolder}/potentials.txt" linelist REGEX "^[^#].") + foreach(line ${linelist}) + string(FIND ${line} " " blank) + math(EXPR plusone "${blank}+1") + string(SUBSTRING ${line} 0 ${blank} pot) + string(SUBSTRING ${line} ${plusone} -1 sum) + if(EXISTS "${LAMMPS_POTENTIALS_DIR}/${pot}") + file(MD5 "${LAMMPS_POTENTIALS_DIR}/${pot}" oldsum) + endif() + if(NOT sum STREQUAL oldsum) + message(STATUS "Downloading external potential ${pot} from ${LAMMPS_POTENTIALS_URL}") + string(RANDOM LENGTH 10 TMP_EXT) + file(DOWNLOAD "${LAMMPS_POTENTIALS_URL}/${pot}.${sum}" "${CMAKE_BINARY_DIR}/${pot}.${TMP_EXT}" + EXPECTED_HASH MD5=${sum} SHOW_PROGRESS) + file(COPY "${CMAKE_BINARY_DIR}/${pot}.${TMP_EXT}" DESTINATION "${LAMMPS_POTENTIALS_DIR}") + file(RENAME "${LAMMPS_POTENTIALS_DIR}/${pot}.${TMP_EXT}" "${LAMMPS_POTENTIALS_DIR}/${pot}") + endif() + endforeach() + endif() endif() endfunction(FetchPotentials) From 917151f695a2ca3a6b1ee602fa32cb81953b541c Mon Sep 17 00:00:00 2001 From: Jacob Gissinger Date: Mon, 23 Jan 2023 17:30:35 -0500 Subject: [PATCH 9/9] Update fix_reaxff_species.cpp --- src/REAXFF/fix_reaxff_species.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/REAXFF/fix_reaxff_species.cpp b/src/REAXFF/fix_reaxff_species.cpp index a9bab28003..ce04be2cc8 100644 --- a/src/REAXFF/fix_reaxff_species.cpp +++ b/src/REAXFF/fix_reaxff_species.cpp @@ -64,8 +64,6 @@ FixReaxFFSpecies::FixReaxFFSpecies(LAMMPS *lmp, int narg, char **arg) : x0(nullptr), BOCut(nullptr), fp(nullptr), pos(nullptr), fdel(nullptr), ele(nullptr), eletype(nullptr), filepos(nullptr), filedel(nullptr) { - if (lmp->citeme) lmp->citeme->add(cite_reaxff_species_delete); - if (narg < 7) utils::missing_cmd_args(FLERR, "fix reaxff/species", error); force_reneighbor = 1; @@ -283,6 +281,7 @@ FixReaxFFSpecies::FixReaxFFSpecies(LAMMPS *lmp, int narg, char **arg) : error->all(FLERR, "Incompatible combination fix reaxff/species command options"); if (delete_Nlimit > 0) { + if (lmp->citeme) lmp->citeme->add(cite_reaxff_species_delete); memory->create(delete_Tcount,delete_Nsteps,"reaxff/species:delete_Tcount"); for (int i = 0; i < delete_Nsteps; i++)