From 2ae07ec1cb2aa36e7a477422c7a947e645bee0a7 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 4 Feb 2025 17:00:12 -0500 Subject: [PATCH 01/30] sync C++ standard selection with main CMakeLists.txt file --- cmake/Modules/LAMMPSInterfacePlugin.cmake | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/cmake/Modules/LAMMPSInterfacePlugin.cmake b/cmake/Modules/LAMMPSInterfacePlugin.cmake index 151e0a04f7..fcaf604778 100644 --- a/cmake/Modules/LAMMPSInterfacePlugin.cmake +++ b/cmake/Modules/LAMMPSInterfacePlugin.cmake @@ -34,8 +34,26 @@ if(MSVC) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) endif() -# C++11 is required -set(CMAKE_CXX_STANDARD 11) +if(NOT CMAKE_CXX_STANDARD) + if(cxx_std_17 IN_LIST CMAKE_CXX_COMPILE_FEATURES) + set(CMAKE_CXX_STANDARD 17) + else() + set(CMAKE_CXX_STANDARD 11) + endif() +endif() +if(CMAKE_CXX_STANDARD LESS 11) + message(FATAL_ERROR "C++ standard must be set to at least 11") +endif() +if(CMAKE_CXX_STANDARD LESS 17) + message(WARNING "Selecting C++17 standard is preferred over C++${CMAKE_CXX_STANDARD}") +endif() +if(PKG_KOKKOS AND (CMAKE_CXX_STANDARD LESS 17)) + set(CMAKE_CXX_STANDARD 17) +endif() +# turn off C++17 check in lmptype.h +if(LAMMPS_CXX11) + add_compile_definitions(LAMMPS_CXX11) +endif() set(CMAKE_CXX_STANDARD_REQUIRED ON) # Need -restrict with Intel compilers From 97e7baf33f0dddbea9c5dabe8d960eacdb4ea3c2 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 5 Feb 2025 23:39:13 -0500 Subject: [PATCH 02/30] get rid of non-standard variable-length arrays in ML-RANN package --- src/ML-RANN/rann_fingerprint_bond.cpp | 54 ++++++++------- src/ML-RANN/rann_fingerprint_bondscreened.cpp | 67 ++++++++++--------- .../rann_fingerprint_bondscreenedspin.cpp | 60 +++++++++-------- src/ML-RANN/rann_fingerprint_bondspin.cpp | 57 ++++++++-------- 4 files changed, 123 insertions(+), 115 deletions(-) diff --git a/src/ML-RANN/rann_fingerprint_bond.cpp b/src/ML-RANN/rann_fingerprint_bond.cpp index acc3318ba0..536859dc8f 100644 --- a/src/ML-RANN/rann_fingerprint_bond.cpp +++ b/src/ML-RANN/rann_fingerprint_bond.cpp @@ -36,6 +36,8 @@ DISTRIBUTION A. Approved for public release; distribution unlimited. OPSEC#4918 using namespace LAMMPS_NS::RANN; +static constexpr double SMALL = 1.0e-12; + Fingerprint_bond::Fingerprint_bond(PairRANN *_pair) : Fingerprint(_pair) { n_body_type = 3; @@ -317,7 +319,8 @@ void Fingerprint_bond::do3bodyfeatureset_singleneighborloop(double * features,do i = ilist[ii]; itype = pair->map[type[i]]; int f = pair->net[itype].dimensions[0]; - double expr[jnum][kmax+12]; + std::vector row(kmax+12, 0.0); + std::vector> expr(jnum, row); int p = kmax; int countmb=((mlength)*(mlength+1))>>1; // calculate interpolation expr, rinvs and dfc, for each neighbor @@ -354,13 +357,13 @@ void Fingerprint_bond::do3bodyfeatureset_singleneighborloop(double * features,do expr[jj][p+1]=dely*rinvs; expr[jj][p+2]=delz*rinvs; //Hack to avoid nan when x y or z component of radial vector is exactly 0. Shouldn't affect accuracy. - if (expr[jj][p]*expr[jj][p]<0.000000000001) { + if (expr[jj][p]*expr[jj][p] < SMALL) { expr[jj][p] = 0.000001; } - if (expr[jj][p+1]*expr[jj][p+1]<0.000000000001) { + if (expr[jj][p+1]*expr[jj][p+1] < SMALL) { expr[jj][p+1] = 0.000001; } - if (expr[jj][p+2]*expr[jj][p+2]<0.000000000001) { + if (expr[jj][p+2]*expr[jj][p+2] < SMALL) { expr[jj][p+2] = 0.000001; } expr[jj][p+3] = -dfc*expr[jj][p]; @@ -377,7 +380,7 @@ void Fingerprint_bond::do3bodyfeatureset_singleneighborloop(double * features,do int kb = kmax; int mb = mlength; count = startingneuron; - double Bb[mb]; + std::vector Bb(mb, 0.0); double dBbx; double dBby; double dBbz; @@ -397,7 +400,7 @@ void Fingerprint_bond::do3bodyfeatureset_singleneighborloop(double * features,do } for (n=0;n Bg(mb, 0.0); ai = n; double y1 = alpha_k[ai]/re; //loop over ktype to get Bg @@ -433,7 +433,7 @@ void Fingerprint_bond::do3bodyfeatureset_singleneighborloop(double * features,do continue; } double yprod = expr[jj][ai]; - double *y4 = &expr[jj][p]; + double *y4 = expr[jj].data() + p; for (a2=0;a2map[type[i]]; int f = pair->net[itype].dimensions[0]; - double expr[jnum][kmax]; - double y[jnum][3]; - double ri[jnum]; - double dfc[jnum]; + std::vector row(kmax, 0.0); + std::vector> expr(jnum, row); + std::vector yrow(3, 0.0); + std::vector> y(jnum, yrow); + std::vector ri(jnum, 0.0); + std::vector dfc(jnum, 0.0); int kb = kmax; int mb = mlength; - double c41[kmax]; - double c51[kmax]; - double c61[kmax]; - double ct[kmax]; + std::vector c41(kmax, 0.0); + std::vector c51(kmax, 0.0); + std::vector c61(kmax, 0.0); + std::vector ct(kmax, 0.0); for (jj = 0; jj < jnum; jj++) { jtype = tn[jj]; if (jtypes != nelements && jtypes != jtype && ktypes != nelements && ktypes != jtype) { diff --git a/src/ML-RANN/rann_fingerprint_bondscreened.cpp b/src/ML-RANN/rann_fingerprint_bondscreened.cpp index 8dcc2e4389..018bbc6df1 100644 --- a/src/ML-RANN/rann_fingerprint_bondscreened.cpp +++ b/src/ML-RANN/rann_fingerprint_bondscreened.cpp @@ -36,6 +36,8 @@ DISTRIBUTION A. Approved for public release; distribution unlimited. OPSEC#4918 using namespace LAMMPS_NS::RANN; +static constexpr double SMALL = 1.0e-12; + Fingerprint_bondscreened::Fingerprint_bondscreened(PairRANN *_pair) : Fingerprint(_pair) { n_body_type = 3; @@ -319,7 +321,8 @@ void Fingerprint_bondscreened::do3bodyfeatureset_singleneighborloop(double * fea i = ilist[ii]; itype = pair->map[type[i]]; int f = pair->net[itype].dimensions[0]; - double expr[jnum][kmax+12]; + std::vector row(kmax+12, 0.0); + std::vector> expr(jnum, row); int p = kmax; int countmb=((mlength)*(mlength+1))>>1; // calculate interpolation expr, rinvs and dfc, for each neighbor @@ -358,13 +361,13 @@ void Fingerprint_bondscreened::do3bodyfeatureset_singleneighborloop(double * fea expr[jj][p+1]=dely*rinvs; expr[jj][p+2]=delz*rinvs; //Hack to avoid nan when x y or z component of radial vector is exactly 0. Shouldn't affect accuracy. - if (expr[jj][p]*expr[jj][p]<0.000000000001) { + if (expr[jj][p]*expr[jj][p] < SMALL) { expr[jj][p] = 0.000001; } - if (expr[jj][p+1]*expr[jj][p+1]<0.000000000001) { + if (expr[jj][p+1]*expr[jj][p+1] < SMALL) { expr[jj][p+1] = 0.000001; } - if (expr[jj][p+2]*expr[jj][p+2]<0.000000000001) { + if (expr[jj][p+2]*expr[jj][p+2] < SMALL) { expr[jj][p+2] = 0.000001; } expr[jj][p+3] = -dfc*expr[jj][p]-dSikx[jj]; @@ -381,20 +384,20 @@ void Fingerprint_bondscreened::do3bodyfeatureset_singleneighborloop(double * fea int kb = kmax; int mb = mlength; count = startingneuron; - double Bb[mb]; + std::vector Bb(mb, 0.0); double dBbx; double dBby; double dBbz; - double dBbx1[mb]; - double dBby1[mb]; - double dBbz1[mb]; + std::vector dBbx1(mb, 0.0); + std::vector dBby1(mb, 0.0); + std::vector dBbz1(mb, 0.0); double yprod; for (mcount=0;mcount Bg(mb, 0.0); ai = n; double y1 = alpha_k[ai]/re; //loop over ktype to get Bg @@ -445,7 +445,7 @@ void Fingerprint_bondscreened::do3bodyfeatureset_singleneighborloop(double * fea continue; } double yprod = expr[jj][ai]; - double *y4 = &expr[jj][p]; + double *y4 = expr[jj].data() + p; for (a2=0;a2map[type[i]]; int f = pair->net[itype].dimensions[0]; - double expr[jnum][kmax]; - double y[jnum][3]; - double ri[jnum]; - double dfc[jnum]; + std::vector row(kmax, 0.0); + std::vector> expr(jnum, row); + std::vector yrow(3, 0.0); + std::vector> y(jnum, yrow); + std::vector ri(jnum, 0.0); + std::vector dfc(jnum, 0.0); int kb = kmax; int mb = mlength; - double Bijk[kb][mb]; - double c41[kmax]; - double c51[kmax]; - double c61[kmax]; - double ct[kmax]; + std::vector brow(mb, 0.0); + std::vector> Bijk(kb, brow); + std::vector c41(kmax, 0.0); + std::vector c51(kmax, 0.0); + std::vector c61(kmax, 0.0); + std::vector ct(kmax, 0.0); for (jj = 0; jj < jnum; jj++) { if (Bij[jj]==false) {continue;} jtype = tn[jj]; diff --git a/src/ML-RANN/rann_fingerprint_bondscreenedspin.cpp b/src/ML-RANN/rann_fingerprint_bondscreenedspin.cpp index cbd3b2a6dc..26fa46b4eb 100644 --- a/src/ML-RANN/rann_fingerprint_bondscreenedspin.cpp +++ b/src/ML-RANN/rann_fingerprint_bondscreenedspin.cpp @@ -35,6 +35,8 @@ DISTRIBUTION A. Approved for public release; distribution unlimited. OPSEC#4918 using namespace LAMMPS_NS::RANN; +static constexpr double SMALL = 1.0e-12; + Fingerprint_bondscreenedspin::Fingerprint_bondscreenedspin(PairRANN *_pair) : Fingerprint(_pair) { n_body_type = 3; @@ -320,7 +322,8 @@ void Fingerprint_bondscreenedspin::do3bodyfeatureset_singleneighborloop(double * i = ilist[ii]; itype = pair->map[type[i]]; int f = pair->net[itype].dimensions[0]; - double expr[jnum][kmax+12]; + std::vector row(kmax+12, 0.0); + std::vector> expr(jnum, row); int p = kmax; int countmb=((mlength)*(mlength+1))>>1; double *si = sim->s[i]; @@ -360,13 +363,13 @@ void Fingerprint_bondscreenedspin::do3bodyfeatureset_singleneighborloop(double * expr[jj][p+1]=dely*rinvs; expr[jj][p+2]=delz*rinvs; //Hack to avoid nan when x y or z component of radial vector is exactly 0. Shouldn't affect accuracy. - if (expr[jj][p]*expr[jj][p]<0.000000000001) { + if (expr[jj][p]*expr[jj][p] < SMALL) { expr[jj][p] = 0.000001; } - if (expr[jj][p+1]*expr[jj][p+1]<0.000000000001) { + if (expr[jj][p+1]*expr[jj][p+1] < SMALL) { expr[jj][p+1] = 0.000001; } - if (expr[jj][p+2]*expr[jj][p+2]<0.000000000001) { + if (expr[jj][p+2]*expr[jj][p+2] < SMALL) { expr[jj][p+2] = 0.000001; } expr[jj][p+3] = -dfc*expr[jj][p]-dSikx[jj]; @@ -383,8 +386,8 @@ void Fingerprint_bondscreenedspin::do3bodyfeatureset_singleneighborloop(double * int kb = kmax; int mb = mlength; count = startingneuron; - double Bb[mb]; - double Bbs[mb]; + std::vector Bb(mb, 0.0); + std::vector Bbs(mb, 0.0); double dBbx; double dBby; double dBbz; @@ -421,7 +424,7 @@ void Fingerprint_bondscreenedspin::do3bodyfeatureset_singleneighborloop(double * double *sj = sim->s[j]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; double yprod = expr[jj][ai]; - double *y4 = &expr[jj][p]; + double *y4 = expr[jj].data() + p; for (a2=0;a2 Bg(mb, 0.0); + std::vector Bgs(mb, 0.0); ai = n; double y1 = alpha_k[ai]/re; //loop over ktype to get Bg @@ -452,7 +451,7 @@ void Fingerprint_bondscreenedspin::do3bodyfeatureset_singleneighborloop(double * double *sj = sim->s[j]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; double yprod = expr[jj][ai]; - double *y4 = &expr[jj][p]; + double *y4 = expr[jj].data() + p; for (a2=0;a2s[j]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; - double *y3 = &expr[jj][p+3]; - double *y4 = &expr[jj][p]; + double *y3 = expr[jj].data() + p + 3; + double *y4 = expr[jj].data() + p; ai = n; yprod = expr[jj][ai]; for (a2=0;a2s[j]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; - double *y3 = &expr[jj][p+3]; - double *y4 = &expr[jj][p]; + double *y3 = expr[jj].data() + p + 3; + double *y4 = expr[jj].data() + p; ai = n; yprod = expr[jj][ai]; for (a2=0;a2s[j]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; - double *y3 = &expr[jj][p+3]; - double *y4 = &expr[jj][p]; + double *y3 = expr[jj].data() + p + 3; + double *y4 = expr[jj].data() + p; ai = n; yprod = expr[jj][ai]; for (a2=0;a2map[type[i]]; int f = pair->net[itype].dimensions[0]; - double expr[jnum][kmax]; - double y[jnum][3]; - double ri[jnum]; - double dfc[jnum]; + std::vector row(kmax, 0.0); + std::vector> expr(jnum, row); + std::vector yrow(3, 0.0); + std::vector> y(jnum, yrow); + std::vector ri(jnum, 0.0); + std::vector dfc(jnum, 0.0); int kb = kmax; int mb = mlength; - double Bijk[kb][mb]; - double c41[kmax]; - double c51[kmax]; - double c61[kmax]; - double ct[kmax]; double *si = sim->s[i]; + std::vector brow(mb, 0.0); + std::vector> Bijk(kb, brow); + std::vector c41(kmax, 0.0); + std::vector c51(kmax, 0.0); + std::vector c61(kmax, 0.0); + std::vector ct(kmax, 0.0); for (jj = 0; jj < jnum; jj++) { if (Bij[jj]==false) {continue;} jtype = tn[jj]; diff --git a/src/ML-RANN/rann_fingerprint_bondspin.cpp b/src/ML-RANN/rann_fingerprint_bondspin.cpp index 1ccdf8ff62..5ecd37b89c 100644 --- a/src/ML-RANN/rann_fingerprint_bondspin.cpp +++ b/src/ML-RANN/rann_fingerprint_bondspin.cpp @@ -35,6 +35,8 @@ DISTRIBUTION A. Approved for public release; distribution unlimited. OPSEC#4918 using namespace LAMMPS_NS::RANN; +static constexpr double SMALL = 1.0e-12; + Fingerprint_bondspin::Fingerprint_bondspin(PairRANN *_pair) : Fingerprint(_pair) { n_body_type = 3; @@ -317,7 +319,8 @@ void Fingerprint_bondspin::do3bodyfeatureset_singleneighborloop(double * feature i = ilist[ii]; itype = pair->map[type[i]]; int f = pair->net[itype].dimensions[0]; - double expr[jnum][kmax+12]; + std::vector row(kmax+12, 0.0); + std::vector> expr(jnum, row); int p = kmax; int countmb=((mlength)*(mlength+1))>>1; double *si = sim->s[i]; @@ -355,13 +358,13 @@ void Fingerprint_bondspin::do3bodyfeatureset_singleneighborloop(double * feature expr[jj][p+1]=dely*rinvs; expr[jj][p+2]=delz*rinvs; //Hack to avoid nan when x y or z component of radial vector is exactly 0. Shouldn't affect accuracy. - if (expr[jj][p]*expr[jj][p]<0.000000000001) { + if (expr[jj][p]*expr[jj][p] < SMALL) { expr[jj][p] = 0.000001; } - if (expr[jj][p+1]*expr[jj][p+1]<0.000000000001) { + if (expr[jj][p+1]*expr[jj][p+1] < SMALL) { expr[jj][p+1] = 0.000001; } - if (expr[jj][p+2]*expr[jj][p+2]<0.000000000001) { + if (expr[jj][p+2]*expr[jj][p+2] < SMALL) { expr[jj][p+2] = 0.000001; } expr[jj][p+3] = -dfc*expr[jj][p]; @@ -378,8 +381,8 @@ void Fingerprint_bondspin::do3bodyfeatureset_singleneighborloop(double * feature int kb = kmax; int mb = mlength; count = startingneuron; - double Bb[mb]; - double Bbs[mb]; + std::vector Bb(mb, 0.0); + std::vector Bbs(mb, 0.0); double dBbx; double dBby; double dBbz; @@ -415,7 +418,7 @@ void Fingerprint_bondspin::do3bodyfeatureset_singleneighborloop(double * feature double *sj = sim->s[j]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; double yprod = expr[jj][ai]; - double *y4 = &expr[jj][p]; + double *y4 = expr[jj].data() + p; for (a2=0;a2 Bg(mb, 0.0); + std::vector Bgs(mb, 0.0); ai = n; double y1 = alpha_k[ai]/re; //loop over ktype to get Bg @@ -445,7 +444,7 @@ void Fingerprint_bondspin::do3bodyfeatureset_singleneighborloop(double * feature double *sj = sim->s[j]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; double yprod = expr[jj][ai]; - double *y4 = &expr[jj][p]; + double *y4 = expr[jj].data() + p; for (a2=0;a2s[j]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; - double *y3 = &expr[jj][p+3]; - double *y4 = &expr[jj][p]; + double *y3 = expr[jj].data() + p + 3; + double *y4 = expr[jj].data() + p; ai = n; yprod = expr[jj][ai]; for (a2=0;a2s[j]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; - double *y3 = &expr[jj][p+3]; - double *y4 = &expr[jj][p]; + double *y3 = expr[jj].data() + p + 3; + double *y4 = expr[jj].data() + p; ai = n; yprod = expr[jj][ai]; for (a2=0;a2s[j]; double sp = si[0]*sj[0]+si[1]*sj[1]+si[2]*sj[2]; - double *y3 = &expr[jj][p+3]; - double *y4 = &expr[jj][p]; + double *y3 = expr[jj].data() + p + 3; + double *y4 = expr[jj].data() + p; ai = n; yprod = expr[jj][ai]; for (a2=0;a2map[type[i]]; int f = pair->net[itype].dimensions[0]; - double expr[jnum][kmax]; - double y[jnum][3]; - double ri[jnum]; - double dfc[jnum]; + std::vector row(kmax, 0.0); + std::vector> expr(jnum, row); + std::vector yrow(3, 0.0); + std::vector> y(jnum, yrow); + std::vector ri(jnum, 0.0); + std::vector dfc(jnum, 0.0); int kb = kmax; int mb = mlength; - double c41[kmax]; - double c51[kmax]; - double c61[kmax]; - double ct[kmax]; + std::vector c41(kmax, 0.0); + std::vector c51(kmax, 0.0); + std::vector c61(kmax, 0.0); + std::vector ct(kmax, 0.0); double *si = sim->s[i]; for (jj = 0; jj < jnum; jj++) { jtype = tn[jj]; From 04cad88b551e7f9ffedcfa272b749f8b9945ee39 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 6 Feb 2025 00:10:17 -0500 Subject: [PATCH 03/30] we can include ML-RANN package now in VLA check --- .github/workflows/check-vla.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-vla.yml b/.github/workflows/check-vla.yml index ab89018a3d..94e367be33 100644 --- a/.github/workflows/check-vla.yml +++ b/.github/workflows/check-vla.yml @@ -77,7 +77,7 @@ jobs: -D PKG_MDI=on \ -D PKG_MANIFOLD=on \ -D PKG_ML-PACE=on \ - -D PKG_ML-RANN=off \ + -D PKG_ML-RANN=on \ -D PKG_MOLFILE=on \ -D PKG_RHEO=on \ -D PKG_PTM=on \ From a547b9a4171da2f1052d9e510c7b61a03c93d3df Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 6 Feb 2025 15:00:54 -0500 Subject: [PATCH 04/30] do not mention rebasing --- .github/release_steps.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/release_steps.md b/.github/release_steps.md index 71388e115a..01b9224114 100644 --- a/.github/release_steps.md +++ b/.github/release_steps.md @@ -28,9 +28,9 @@ Create a 'next\_release' branch off 'develop' and make the following changes: ..versionadded:: or ..versionchanged:: are missing and need to be added -Submit this pull request, rebase if needed. This is the last pull -request merged for the release and should not contain any other -changes. (Exceptions: this document, last minute trivial(!) changes). +Submit this pull request. This is the last pull request merged for the +release and should not contain any other changes. (Exceptions: this +document, last minute trivial(!) changes). This PR shall not be merged before **all** pending tests have completed and cleared. We currently use a mix of automated tests running on From c9f41f9d90ab3cc2d2f5aa1a453450ecf3e77ed9 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 6 Feb 2025 17:32:39 -0500 Subject: [PATCH 05/30] explain more steps of the release process related to building packages --- .github/release_steps.md | 178 +++++++++++++++++++--- tools/singularity/README.md | 2 +- tools/singularity/fedora41_musl_mingw.def | 109 +++++++++++++ 3 files changed, 264 insertions(+), 25 deletions(-) create mode 100644 tools/singularity/fedora41_musl_mingw.def diff --git a/.github/release_steps.md b/.github/release_steps.md index 01b9224114..857acfdb85 100644 --- a/.github/release_steps.md +++ b/.github/release_steps.md @@ -35,7 +35,7 @@ document, last minute trivial(!) changes). This PR shall not be merged before **all** pending tests have completed and cleared. We currently use a mix of automated tests running on either Temple's Jenkins cluster or GitHub workflows. Those include time -consuming tests not run on pull requests. If needed, a bugfix pull +consuming tests not run on pull requests. If needed, a bug-fix pull request should be created and merged to clear all tests. ### Create release on GitHub @@ -56,7 +56,7 @@ git pull git checkout release git pull git merge --ff-only develop -git tag -s -m "LAMMPS feature release 19 November 2024" patch_19Nov2024 +git tag -s -m "LAMMPS feature release 4 February 2025" patch_4Feb2025 git push git@github.com:lammps/lammps.git --tags develop release ``` @@ -77,7 +77,7 @@ release page with a summary of all the changes included and references to the pull requests they were merged from or check the existing draft for any necessary changes from pull requests that were merged but are not listed. Then select the applied tag for the release in the "Choose -a tag" dropdown list. Go to the bottom of the list and select the "Set +a tag" drop-down list. Go to the bottom of the list and select the "Set as pre-release" checkbox. The "Set as the latest release" button is reserved for stable releases and updates to them. @@ -87,12 +87,18 @@ you can return to edit the release page and publish it. ### Prepare pre-compiled packages, update packages to GitHub -Build a fully static LAMMPS installation using a musl-libc -cross-compiler, install into a lammps-static folder, and create a -tarball called lammps-linux-x86_64-19Nov2024.tar.gz (or using a -corresponding date with a future release) from the lammps-static folder. A suitable build environment is provided with the -https://download.lammps.org/static/fedora37_musl.sif container image. +https://download.lammps.org/static/fedora41_musl_mingw.sif container +image. The corresponding container build definition file is maintained +in the tools/singularity folder of the LAMMPS source distribution. + +#### Fully portable static Linux x86_64 non-MPI binaries + +The following commands use the Fedora container to build a fully static +LAMMPS installation using a musl-libc cross-compiler, install it into a +`lammps-static` folder, and create a tarball called +`lammps-linux-x86_64-4Feb2025.tar.gz` (or using a corresponding date +with a future release) from the `lammps-static` folder. ``` sh rm -rf release-packages @@ -105,49 +111,173 @@ cmake -S lammps-release/cmake -B build-release -G Ninja -D CMAKE_INSTALL_PREFIX= cmake --build build-release --target all cmake --build build-release --target install /usr/musl/bin/x86_64-linux-musl-strip lammps-static/bin/* -tar -czvvf lammps-linux-x86_64-19Nov2024.tar.gz lammps-static +tar -czvvf ../lammps-linux-x86_64-4Feb2025.tar.gz lammps-static exit # fedora 41 container +cd .. ``` The resulting tar archive can be uploaded to the GitHub release page with: -``` -gh release upload patch_19Nov2024 lammps-linux-x86_64-19Nov2024.tar.gz +``` sh +gh release upload patch_4Feb2025 lammps-linux-x86_64-4Feb2025.tar.gz ``` +#### Linux x86_64 Flatpak bundle with GUI included + Make sure you have the `flatpak` and `flatpak-builder` packages -installed locally (they cannot be used from the container) and build a +installed locally (they require binaries that run with elevated +privileges and thus cannot be used from the container) and build a LAMMPS and LAMMPS-GUI flatpak bundle in the `release-packages` folder with: ``` sh +cd release-packages flatpak --user remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo flatpak-builder --force-clean --verbose --repo=$PWD/flatpak-repo --install-deps-from=flathub --state-dir=$PWD --user --ccache --default-branch=release flatpak-build lammps-release/tools/lammps-gui/org.lammps.lammps-gui.yml -flatpak build-bundle --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo --verbose $PWD/flatpak-repo LAMMPS-Linux-x86_64-GUI-19Nov2024.flatpak org.lammps.lammps-gui release +flatpak build-bundle --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo --verbose $PWD/flatpak-repo ../LAMMPS-Linux-x86_64-GUI-4Feb2025.flatpak org.lammps.lammps-gui release +cd .. ``` The resulting flatpak bundle file can be uploaded to the GitHub release page with: -``` -gh release upload patch_19Nov2024 LAMMPS-Linux-x86_64-GUI-19Nov2024.flatpak +``` sh +gh release upload patch_4Feb2025 LAMMPS-Linux-x86_64-GUI-4Feb2025.flatpak ``` -Also build serial executable packages that also include LAMMPS-GUI for -Linux, macOS, and Windows, and upload them to the GitHub release. +#### LAMMPS Source tarball -Clean up: +The container for the static binary can also be used to prepare the source +tarball including the HTML and PDF manual (this is currently done automatically +when the releases is created and the tarball uploaded to https://download.lammps.org/tars/). +The steps are as follows: + +``` sh +cd release-packages +apptainer shell fedora41_musl_mingw.sif +cd lammps-release +rm -f ../release.tar* +git archive --output=../release.tar --prefix=lammps-4Feb2025/ HEAD +cd doc +make clean-all +make html pdf +tar -rf ../../release.tar --transform 's,^,lammps-4Feb2025/doc/,' html Manual.pdf +gzip -9v ../../release.tar +mv ../../release.tar.gz ../../lammps-src-4Feb2025.tar.gz +exit # fedora41 container +cd .. +``` + +The resulting source tarball can be uploaded to the GitHub release page with: + +``` sh +gh release upload patch_4Feb2025 lammps-src-4Feb2025.tar.gz +``` + +#### Build Windows Installer Packages with MinGW Linux-to-Windows Cross-compiler + +The various Windows installer packages can also be built with +apptainer container image. + +``` sh +cd release-packages +apptainer shell fedora41_musl_mingw.sif +git clone --depth 10 https://github.com/lammps/lammps-packages.git lammps-packages +cd lammps-packages/mingw-cross +ln -sf ../../lammps-release lammps +./buildall.sh release >& mk.log & less +F mk.log +``` + +The installer with the GUI included can be uploaded to the GitHub release page with: + +``` sh +ln -sf LAMMPS-64bit-GUI-4Feb2025.exe LAMMPS-Win10-64bit-GUI-4Feb2025.exe +gh release upload patch_4Feb2025 LAMMPS-Win10-64bit-GUI-4Feb2025.exe +``` + +The symbolic link is used to have a consistent naming scheme for the packages +attached to the GitHub release page. + +#### Clean up: ``` sh cd .. rm -r release-packages ``` -TODO: -- add detailed commands for building GUI packages on Ubuntu 20.04LTS (move to 22.04LTS?), - macOS, and Windows cross-compiler and upload to GitHub -- build all Windows cross-compiled installer packages using lammps-packages repo +#### Build Multi-arch App-bundle for macOS -### Update download website +Building app-bundles for macOS is not as easily automated and portable +as some of the other steps. It requires a machine actually running +macOS. In that machine the Xcode compiler package needs to be +installed. This also includes tools for building and manipulating disk +images. This compiler supports building executables for both, the +x86_64 and the arm64 architectures. This requires building with CMake +and using the CMake settings: + +``` sh +-D CMAKE_OSX_ARCHITECTURES=arm64;x86_64 +-D CMAKE_OSX_DEPLOYMENT_TARGER=11.0 +``` + +This will add the compiler flags `-arch arm64 -arch x86_64 +-mmacosx-version-min=11.0` and thus produce object for both +architectures and support for macOS versions back to version 11 (aka Big +Sur). With these settings the following libraries should be compiled +and installed (e.g. to `$HOME/.local`) as static libraries only: +- libomp taken from the LLVM/Clang source distribution (to support OpenMP) +- jpeg +- zlib +- png +- Qt (for LAMMPS-GUI) + +When configuring LAMMPS the `cmake/presets/clang.cmake` should be used +and as many packages as possible enabled. For LAMMPS-GUI, MPI should be +disabled with `-D BUILD_MPI=OFF` and LAMMPS-GUI enabled with +`-D BUILD_LAMMPS_GUI=ON`. If the CMake configuration is successful, +settings for building a macOS app-bundle are enabled and with `cmake +--build build --target dmg` extra steps will be executed that will build +a macOS application installer image under the name +`LAMMPS_GUI-macOS-multiarch-4Feb2025.dmg` + +The application image can be uploaded to the GitHub release page with: + +``` sh +ln -sf LAMMPS_GUI-macOS-multiarch-4Feb2025.dmg LAMMPS-macOS-multiarch-GUI-4Feb2025.dmg +gh release upload patch_4Feb2025 LAMMPS-macOS-multiarch-GUI-4Feb2025.dmg +``` + +The symbolic link is used to have a consistent naming scheme for the packages +attached to the GitHub release page. + +We are currently building the application images on macOS 12 (aka Monterey). + +#### Build Linux x86_64 binary tarball on Ubuntu 20.04LTS + +While the flatpak Linux version uses portable runtime libraries provided +by the flatpak environment, we also build regular Linux executables that +use a wrapper script and matching shared libraries in a tarball. To be +compatible with many Linux distributions, one has to build this on a +very old Linux distribution, since most Linux system libraries are +usually backward compatible but not forward compatible. This is +currently done on an Ubuntu 20.04LTS system. Once LAMMPS moves to +require CMake 3.20 and C++17, we will have to move to Ubuntu 22.04LTS. +This installation (either on a real or a virtual machine) should have +the packages installed that are indicated in +`tools/singularity/ubuntu20.04.def` plus Qt version 5.x with development +headers, so that LAMMPS-GUI can be compiled. + +Also the building of the binary tarball and setup of the bundled +libraries and wrapper scripts is automated and can executed with `cmake +--build build --target tgz`. This should produce a file +`LAMMPS_GUI-Linux-amd64-4Feb2025.tar.gz` which can be uploaded to the +GitHub release page with: + +``` sh +ln -sf LAMMPS_GUI-Linux-amd64-4Feb2025.tar.gz LAMMPS-Linux-x86_64-GUI-4Feb2025.tar.gz +gh release upload patch_4Feb2025 LAMMPS-Linux-x86_64-GUI-4Feb2025.tar.gz +``` + +### Update download page on LAMMPS website Check out the LAMMPS website repo https://github.com/lammps/lammps-website.git and edit the file @@ -156,7 +286,7 @@ html` and review `html/download.html` Then add and commit to git and push the changes to GitHub. The Temple Jenkis cluster will automatically update https://www.lammps.org/download.html accordingly. -Notify Steve of the release so he can update `src/bug.txt` on the +Also notify Steve of the release so he can update `src/bug.txt` on the website from the available release notes. ## LAMMPS Stable Release diff --git a/tools/singularity/README.md b/tools/singularity/README.md index 4700dac6ec..8f0508b9f0 100644 --- a/tools/singularity/README.md +++ b/tools/singularity/README.md @@ -1,6 +1,6 @@ # Apptainer (aka Singularity) container definitions for compiling/testing LAMMPS -The *.def files in this folder can be used to build container images +The \*.def files in this folder can be used to build container images for [Apptainer](https://apptainer.org) (previously called [Singularity](https://sylabs.io)), suitable for compiling and testing LAMMPS on a variety of OS variants with support for most standard diff --git a/tools/singularity/fedora41_musl_mingw.def b/tools/singularity/fedora41_musl_mingw.def new file mode 100644 index 0000000000..7e15f6590b --- /dev/null +++ b/tools/singularity/fedora41_musl_mingw.def @@ -0,0 +1,109 @@ +BootStrap: docker +From: fedora:41 + +%setup + curl -L -o musl-gcc-f37.tar.gz https://download.lammps.org/static/musl-gcc-f37.tar.gz + cp musl-gcc-f37.tar.gz ${APPTAINER_ROOTFS} + +%post + dnf -y update + dnf -y install vim-enhanced git file make cmake patch which file \ + ninja-build libomp-devel diffutils dos2unix findutils rsync \ + ccache gcc-c++ gcc-gfortran gdb valgrind python3-pyyaml \ + enchant enchant2 python3-enchant python3-virtualenv doxygen latexmk \ + texlive-latex-fonts texlive-pslatex texlive-collection-latexrecommended \ + texlive-latex texlive-latexconfig doxygen-latex texlive-collection-latex \ + texlive-latex-bin texlive-lualatex-math texlive-fncychap texlive-tabulary \ + texlive-framed texlive-wrapfig texlive-upquote texlive-capt-of texlive-pict2e \ + texlive-needspace texlive-titlesec texlive-anysize texlive-dvipng texlive-xindy \ + texlive-fontawesome texlive-ellipse texlive-tex-gyre \ + mingw-filesystem-base mingw32-nsis mingw-binutils-generic \ + mingw64-filesystem mingw64-pkg-config \ + mingw64-crt mingw64-headers mingw64-binutils \ + mingw64-cpp mingw64-gcc mingw64-gcc-gfortran mingw64-gcc-c++ \ + mingw64-curl \ + mingw64-libgomp \ + mingw64-winpthreads \ + mingw64-eigen3 \ + mingw64-fftw \ + mingw64-libjpeg-turbo \ + mingw64-libpng \ + mingw64-python3 \ + mingw64-python3-numpy \ + mingw64-python3-pyyaml \ + mingw64-python3-setuptools \ + mingw64-readline \ + mingw64-termcap \ + mingw64-tcl \ + mingw64-tk \ + mingw64-zlib \ + mingw64-zstd \ + mingw64-qt5-qtdeclarative \ + mingw64-qt5-qmldevtools \ + mingw64-qt5-qmldevtools-devel \ + mingw64-qt5-qttools-tools \ + mingw64-qt5-qtcharts \ + mingw64-qt5-qttools \ + mingw64-qt5-qmake \ + mingw64-qt5-qtbase \ + mingw64-qt5-qtbase-devel \ + mingw64-qt5-qtbase-static \ + + dnf clean all + + # install musl-libc Linux-2-Linux cross-compiler + tar -C /usr/ -xvf /musl-gcc-f37.tar.gz + rm -f /musl-gcc-f37.tar.gz + + # install NSIS EnVar plugin + curl -L -o EnVar_plugin.zip https://nsis.sourceforge.io/mediawiki/images/7/7f/EnVar_plugin.zip + unzip -d /usr/share/nsis EnVar_plugin.zip + rm EnVar_plugin.zip + + # create missing termcap pkgconfig file + cat > /usr/x86_64-w64-mingw32/sys-root/mingw/lib/pkgconfig/termcap.pc <$CUSTOM_PROMPT_ENV < Date: Thu, 6 Feb 2025 20:55:23 -0500 Subject: [PATCH 06/30] update copyright year --- tools/lammps-gui/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/lammps-gui/CMakeLists.txt b/tools/lammps-gui/CMakeLists.txt index aee806c81a..b09c6c26d9 100644 --- a/tools/lammps-gui/CMakeLists.txt +++ b/tools/lammps-gui/CMakeLists.txt @@ -279,7 +279,7 @@ if(APPLE) MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} MACOSX_BUNDLE_ICON_FILE lammps.icns - MACOSX_BUNDLE_COPYRIGHT "(c) 2003 - 2024, The LAMMPS Developers" + MACOSX_BUNDLE_COPYRIGHT "(c) 2003 - 2025, The LAMMPS Developers" MACOSX_BUNDLE TRUE ) # additional targets to populate the bundle tree and create the .dmg image file From ab6668031fe47090c50ea6608a65c414f4ec8c62 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 6 Feb 2025 20:55:40 -0500 Subject: [PATCH 07/30] explain some more about transition to C++17 --- doc/src/Build_settings.rst | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/doc/src/Build_settings.rst b/doc/src/Build_settings.rst index e4a53ddee7..53a7a3b761 100644 --- a/doc/src/Build_settings.rst +++ b/doc/src/Build_settings.rst @@ -23,14 +23,15 @@ explains how to do this for building both with CMake and make. .. _cxx11: -C++11 standard compliance -------------------------- +C++11 and C++17 standard compliance +----------------------------------- -A C++11 standard compatible compiler is a requirement for compiling LAMMPS. -LAMMPS version 3 March 2020 is the last version compatible with the previous -C++98 standard for the core code and most packages. Most currently used -C++ compilers are compatible with C++11, but some older ones may need extra -flags to enable C++11 compliance. Example for GNU c++ 4.8.x: +A C++11 standard compatible compiler is currently the minimum +requirement for compiling LAMMPS. LAMMPS version 3 March 2020 is the +last version compatible with the previous C++98 standard for the core +code and most packages. Most currently used C++ compilers are compatible +with C++11, but some older ones may need extra flags to enable C++11 +compliance. Example for GNU c++ 4.8.x: .. code-block:: make @@ -40,6 +41,17 @@ Individual packages may require compliance with a later C++ standard like C++14 or C++17. These requirements will be documented with the :doc:`individual packages `. +.. versionchanged:: 4Feb2025 + +Starting with LAMMPS version 4 February 2025 we are starting a +transition to require the C++17 standard. Most current compilers are +compatible and if the C++17 standard is available by default, LAMMPS +will enable C++17 and will compile normally. If the chosen compiler is +not compatible with C++17, but only supports C++11, then the define +-DLAMMPS_CXX11 is required to fall back to compiling with a C++11 +compiler. After the next stable release of LAMMPS in summer 2025, the +LAMMPS development branch and future releases will require C++17. + ---------- .. _fft: From 1a636acf81a8fcd3cd49f7b5127426045c3b6cd3 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 7 Feb 2025 07:34:32 -0500 Subject: [PATCH 08/30] simplify / optimize --- src/REAXFF/fix_reaxff_species.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/REAXFF/fix_reaxff_species.cpp b/src/REAXFF/fix_reaxff_species.cpp index 09c3884c34..5b32ca0528 100644 --- a/src/REAXFF/fix_reaxff_species.cpp +++ b/src/REAXFF/fix_reaxff_species.cpp @@ -965,6 +965,7 @@ void FixReaxFFSpecies::DeleteSpecies(int Nmole, int Nspec) int *mask = atom->mask; double *mass = atom->mass; double *rmass = atom->rmass; + int *type = atom->type; double localmass, totalmass; std::string species_str; @@ -1013,12 +1014,12 @@ void FixReaxFFSpecies::DeleteSpecies(int Nmole, int Nspec) if (!(mask[i] & groupbit)) continue; cid = nint(clusterID[i]); if (cid == m) { - itype = ele2uele[atom->type[i] - 1]; + itype = ele2uele[type[i] - 1]; Name[itype]++; count++; marklist[nmarklist++] = i; if (rmass) localmass += rmass[i]; - else localmass += atom->mass[atom->type[i]]; + else localmass += mass[type[i]]; } } From 61a2db47152aed59cd75cc568e173213446394f7 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 7 Feb 2025 19:47:05 -0500 Subject: [PATCH 09/30] revise and expand global README file --- README | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/README b/README index c25506e2c0..6477eb41d3 100644 --- a/README +++ b/README @@ -23,17 +23,20 @@ more information about the code and its uses. The LAMMPS distribution includes the following files and directories: README this file -LICENSE the GNU General Public License (GPL) -bench benchmark problems +LICENSE the GNU General Public License (GPLv2) +CITATION.cff Citation information for LAMMPS in CFF format +bench benchmark inputs cmake CMake build files doc documentation -examples simple test problems -fortran Fortran wrapper for LAMMPS +examples example inputs for many LAMMPS commands +fortran Fortran 2003 module for LAMMPS lib additional provided or external libraries potentials interatomic potential files -python Python wrappers for LAMMPS +python Python module for LAMMPS src source files tools pre- and post-processing tools +unittest test programs for use with CTest +.github Git and GitHub related files and tools Point your browser at any of these files to get started: @@ -42,6 +45,8 @@ https://docs.lammps.org/Intro.html hi-level introduction https://docs.lammps.org/Build.html how to build LAMMPS https://docs.lammps.org/Run_head.html how to run LAMMPS https://docs.lammps.org/Commands_all.html Table of available commands +https://docs.lammps.org/Howto.html Short tutorials and HowTo discussions +https://docs.lammps.org/Errors.html How to interpret and debug errors https://docs.lammps.org/Library.html LAMMPS library interfaces https://docs.lammps.org/Modify.html how to modify and extend LAMMPS https://docs.lammps.org/Developer.html LAMMPS developer info From 6eddb3a33f410d1e8a386e27c83799f1341d541b Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 7 Feb 2025 20:50:14 -0500 Subject: [PATCH 10/30] various minor tweaks and reformatting for CMake scripts --- cmake/CMakeLists.txt | 4 +- cmake/Modules/CodeCoverage.cmake | 120 +++++++++++++-------------- cmake/Modules/Documentation.cmake | 6 +- cmake/Modules/Packages/ML-QUIP.cmake | 2 +- cmake/Modules/Packages/PLUMED.cmake | 11 ++- cmake/Modules/Packages/PYTHON.cmake | 2 +- doc/src/Build_settings.rst | 2 +- 7 files changed, 77 insertions(+), 70 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index ff0d69e316..591958f996 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -209,7 +209,7 @@ endif() ######################################################################## # User input options # ######################################################################## -# backward compatibility with CMake before 3.12 and older LAMMPS documentation +# backward compatibility with older LAMMPS documentation if (PYTHON_EXECUTABLE) set(Python_EXECUTABLE "${PYTHON_EXECUTABLE}") endif() @@ -930,7 +930,7 @@ endif() include(Testing) include(CodeCoverage) include(CodingStandard) -find_package(ClangFormat 11.0) +find_package(ClangFormat 11.0 QUIET) if(ClangFormat_FOUND) add_custom_target(format-src diff --git a/cmake/Modules/CodeCoverage.cmake b/cmake/Modules/CodeCoverage.cmake index 21a651e519..885b5cba6d 100644 --- a/cmake/Modules/CodeCoverage.cmake +++ b/cmake/Modules/CodeCoverage.cmake @@ -7,76 +7,76 @@ # For Python coverage the coverage package needs to be installed ############################################################################### if(ENABLE_COVERAGE) - find_program(GCOVR_BINARY gcovr) - find_package_handle_standard_args(GCOVR DEFAULT_MSG GCOVR_BINARY) + find_program(GCOVR_BINARY gcovr) + find_package_handle_standard_args(GCOVR DEFAULT_MSG GCOVR_BINARY) - find_program(COVERAGE_BINARY coverage) - find_package_handle_standard_args(COVERAGE DEFAULT_MSG COVERAGE_BINARY) + find_program(COVERAGE_BINARY coverage) + find_package_handle_standard_args(COVERAGE DEFAULT_MSG COVERAGE_BINARY) - if(GCOVR_FOUND) - get_filename_component(ABSOLUTE_LAMMPS_SOURCE_DIR ${LAMMPS_SOURCE_DIR} ABSOLUTE) + if(GCOVR_FOUND) + get_filename_component(ABSOLUTE_LAMMPS_SOURCE_DIR ${LAMMPS_SOURCE_DIR} ABSOLUTE) - add_custom_target( - gen_coverage_xml - COMMAND ${GCOVR_BINARY} -s -x -r ${ABSOLUTE_LAMMPS_SOURCE_DIR} --object-directory=${CMAKE_BINARY_DIR} -o coverage.xml - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMENT "Generating XML coverage report..." - ) + add_custom_target( + gen_coverage_xml + COMMAND ${GCOVR_BINARY} -s -x -r ${ABSOLUTE_LAMMPS_SOURCE_DIR} --object-directory=${CMAKE_BINARY_DIR} -o coverage.xml + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Generating XML coverage report..." + ) - set(COVERAGE_HTML_DIR ${CMAKE_BINARY_DIR}/coverage_html) + set(COVERAGE_HTML_DIR ${CMAKE_BINARY_DIR}/coverage_html) - add_custom_target(coverage_html_folder - COMMAND ${CMAKE_COMMAND} -E make_directory ${COVERAGE_HTML_DIR}) + add_custom_target(coverage_html_folder + COMMAND ${CMAKE_COMMAND} -E make_directory ${COVERAGE_HTML_DIR}) - add_custom_target( - gen_coverage_html - COMMAND ${GCOVR_BINARY} -s --html --html-details -r ${ABSOLUTE_LAMMPS_SOURCE_DIR} --object-directory=${CMAKE_BINARY_DIR} -o ${COVERAGE_HTML_DIR}/index.html - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMENT "Generating HTML coverage report..." - ) - add_dependencies(gen_coverage_html coverage_html_folder) + add_custom_target( + gen_coverage_html + COMMAND ${GCOVR_BINARY} -s --html --html-details -r ${ABSOLUTE_LAMMPS_SOURCE_DIR} --object-directory=${CMAKE_BINARY_DIR} -o ${COVERAGE_HTML_DIR}/index.html + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Generating HTML coverage report..." + ) + add_dependencies(gen_coverage_html coverage_html_folder) - add_custom_target(clean_coverage_html - ${CMAKE_COMMAND} -E remove_directory ${COVERAGE_HTML_DIR} - COMMENT "Deleting HTML coverage report..." - ) + add_custom_target(clean_coverage_html + ${CMAKE_COMMAND} -E remove_directory ${COVERAGE_HTML_DIR} + COMMENT "Deleting HTML coverage report..." + ) - add_custom_target(reset_coverage - ${CMAKE_COMMAND} -E remove -f */*.gcda */*/*.gcda */*/*/*.gcda - */*/*/*/*.gcda */*/*/*/*/*.gcda */*/*/*/*/*/*.gcda - */*/*/*/*/*/*/*.gcda */*/*/*/*/*/*/*/*.gcda - */*/*/*/*/*/*/*/*/*.gcda */*/*/*/*/*/*/*/*/*/*.gcda - WORKIND_DIRECTORY ${CMAKE_BINARY_DIR} - COMMENT "Deleting coverage data files..." - ) - add_dependencies(reset_coverage clean_coverage_html) - endif() + add_custom_target(reset_coverage + ${CMAKE_COMMAND} -E remove -f */*.gcda */*/*.gcda */*/*/*.gcda + */*/*/*/*.gcda */*/*/*/*/*.gcda */*/*/*/*/*/*.gcda + */*/*/*/*/*/*/*.gcda */*/*/*/*/*/*/*/*.gcda + */*/*/*/*/*/*/*/*/*.gcda */*/*/*/*/*/*/*/*/*/*.gcda + WORKIND_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Deleting coverage data files..." + ) + add_dependencies(reset_coverage clean_coverage_html) + endif() - if(COVERAGE_FOUND) - set(PYTHON_COVERAGE_HTML_DIR ${CMAKE_BINARY_DIR}/python_coverage_html) - configure_file(.coveragerc.in ${CMAKE_BINARY_DIR}/.coveragerc @ONLY) + if(COVERAGE_FOUND) + set(PYTHON_COVERAGE_HTML_DIR ${CMAKE_BINARY_DIR}/python_coverage_html) + configure_file(.coveragerc.in ${CMAKE_BINARY_DIR}/.coveragerc @ONLY) - add_custom_command( - OUTPUT ${CMAKE_BINARY_DIR}/unittest/python/.coverage - COMMAND ${COVERAGE_BINARY} combine - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittest/python - COMMENT "Combine Python coverage files..." - ) + add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/unittest/python/.coverage + COMMAND ${COVERAGE_BINARY} combine + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittest/python + COMMENT "Combine Python coverage files..." + ) - add_custom_target( - gen_python_coverage_html - COMMAND ${COVERAGE_BINARY} html --rcfile=${CMAKE_BINARY_DIR}/.coveragerc -d ${PYTHON_COVERAGE_HTML_DIR} - DEPENDS ${CMAKE_BINARY_DIR}/unittest/python/.coverage ${CMAKE_BINARY_DIR}/.coveragerc - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittest/python - COMMENT "Generating HTML Python coverage report..." - ) + add_custom_target( + gen_python_coverage_html + COMMAND ${COVERAGE_BINARY} html --rcfile=${CMAKE_BINARY_DIR}/.coveragerc -d ${PYTHON_COVERAGE_HTML_DIR} + DEPENDS ${CMAKE_BINARY_DIR}/unittest/python/.coverage ${CMAKE_BINARY_DIR}/.coveragerc + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittest/python + COMMENT "Generating HTML Python coverage report..." + ) - add_custom_target( - gen_python_coverage_xml - COMMAND ${COVERAGE_BINARY} xml --rcfile=${CMAKE_BINARY_DIR}/.coveragerc -o ${CMAKE_BINARY_DIR}/python_coverage.xml - DEPENDS ${CMAKE_BINARY_DIR}/unittest/python/.coverage ${CMAKE_BINARY_DIR}/.coveragerc - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittest/python - COMMENT "Generating XML Python coverage report..." - ) - endif() + add_custom_target( + gen_python_coverage_xml + COMMAND ${COVERAGE_BINARY} xml --rcfile=${CMAKE_BINARY_DIR}/.coveragerc -o ${CMAKE_BINARY_DIR}/python_coverage.xml + DEPENDS ${CMAKE_BINARY_DIR}/unittest/python/.coverage ${CMAKE_BINARY_DIR}/.coveragerc + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittest/python + COMMENT "Generating XML Python coverage report..." + ) + endif() endif() diff --git a/cmake/Modules/Documentation.cmake b/cmake/Modules/Documentation.cmake index dfaf7bdb39..511d54114c 100644 --- a/cmake/Modules/Documentation.cmake +++ b/cmake/Modules/Documentation.cmake @@ -13,7 +13,7 @@ if(BUILD_DOC) endif() find_package(Python3 REQUIRED COMPONENTS Interpreter) if(Python3_VERSION VERSION_LESS 3.8) - message(FATAL_ERROR "Python 3.8 and up is required to build the HTML documentation") + message(FATAL_ERROR "Python 3.8 and up is required to build the LAMMPS HTML documentation") endif() set(VIRTUALENV ${Python3_EXECUTABLE} -m venv) @@ -65,8 +65,8 @@ if(BUILD_DOC) find_package(Sphinx) endif() - set(MATHJAX_URL "https://github.com/mathjax/MathJax/archive/3.1.3.tar.gz" CACHE STRING "URL for MathJax tarball") - set(MATHJAX_MD5 "b81661c6e6ba06278e6ae37b30b0c492" CACHE STRING "MD5 checksum of MathJax tarball") + set(MATHJAX_URL "https://github.com/mathjax/MathJax/archive/3.2.2.tar.gz" CACHE STRING "URL for MathJax tarball") + set(MATHJAX_MD5 "08dd6ef33ca08870220d9aade2a62845" CACHE STRING "MD5 checksum of MathJax tarball") mark_as_advanced(MATHJAX_URL) GetFallbackURL(MATHJAX_URL MATHJAX_FALLBACK) diff --git a/cmake/Modules/Packages/ML-QUIP.cmake b/cmake/Modules/Packages/ML-QUIP.cmake index 9106ff54ef..aad6ee5e34 100644 --- a/cmake/Modules/Packages/ML-QUIP.cmake +++ b/cmake/Modules/Packages/ML-QUIP.cmake @@ -37,7 +37,7 @@ if(DOWNLOAD_QUIP) endforeach() # Fix cmake crashing when MATH_LINKOPTS not set, required for e.g. recent Cray Programming Environment set(temp "${temp} -L/_DUMMY_PATH_\n") - set(temp "${temp}PYTHON=python\nPIP=pip\nEXTRA_LINKOPTS=\n") + set(temp "${temp}PYTHON=${Python_EXECUTABLE}\nPIP=pip\nEXTRA_LINKOPTS=\n") set(temp "${temp}HAVE_CP2K=0\nHAVE_VASP=0\nHAVE_TB=0\nHAVE_PRECON=1\nHAVE_LOTF=0\nHAVE_ONIOM=0\n") set(temp "${temp}HAVE_LOCAL_E_MIX=0\nHAVE_QC=0\nHAVE_GAP=1\nHAVE_DESCRIPTORS_NONCOMMERCIAL=1\n") set(temp "${temp}HAVE_TURBOGAP=0\nHAVE_QR=1\nHAVE_THIRDPARTY=0\nHAVE_FX=0\nHAVE_SCME=0\nHAVE_MTP=0\n") diff --git a/cmake/Modules/Packages/PLUMED.cmake b/cmake/Modules/Packages/PLUMED.cmake index 5e5d110626..1b4845d259 100644 --- a/cmake/Modules/Packages/PLUMED.cmake +++ b/cmake/Modules/Packages/PLUMED.cmake @@ -40,6 +40,13 @@ mark_as_advanced(PLUMED_URL) mark_as_advanced(PLUMED_MD5) GetFallbackURL(PLUMED_URL PLUMED_FALLBACK) +# adjust C++ standard support for self-compiled Plumed2 +if(CMAKE_CXX_STANDARD GREATER 11) + set(PLUMED_CXX_STANDARD 14) +else() + set(PLUMED_CXX_STANDARD 11) +endif() + if((CMAKE_SYSTEM_NAME STREQUAL "Windows") AND (CMAKE_CROSSCOMPILING)) if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") set(CROSS_CONFIGURE mingw64-configure) @@ -55,7 +62,7 @@ if((CMAKE_SYSTEM_NAME STREQUAL "Windows") AND (CMAKE_CROSSCOMPILING)) URL_MD5 ${PLUMED_MD5} BUILD_IN_SOURCE 1 CONFIGURE_COMMAND ${CROSS_CONFIGURE} --disable-shared --disable-bsymbolic - --disable-python --enable-cxx=11 + --disable-python --enable-cxx=${PLUMED_CXX_STANDARD} --enable-modules=-adjmat:+crystallization:-dimred:+drr:+eds:-fisst:+funnel:+logmfd:+manyrestraints:+maze:+opes:+multicolvar:-pamm:-piv:+s2cm:-sasa:-ves ${PLUMED_CONFIG_OMP} ${PLUMED_CONFIG_MPI} @@ -142,7 +149,7 @@ else() CONFIGURE_COMMAND /configure --prefix= ${CONFIGURE_REQUEST_PIC} --enable-modules=all - --enable-cxx=11 + --enable-cxx=${PLUMED_CXX_STANDARD} --disable-python ${PLUMED_CONFIG_MPI} ${PLUMED_CONFIG_OMP} diff --git a/cmake/Modules/Packages/PYTHON.cmake b/cmake/Modules/Packages/PYTHON.cmake index e05edadbf3..0879382ed7 100644 --- a/cmake/Modules/Packages/PYTHON.cmake +++ b/cmake/Modules/Packages/PYTHON.cmake @@ -1,6 +1,6 @@ if(NOT Python_INTERPRETER) - # backward compatibility with CMake before 3.12 and older LAMMPS documentation + # backward compatibility with older LAMMPS documentation if(PYTHON_EXECUTABLE) set(Python_EXECUTABLE ${PYTHON_EXECUTABLE}) endif() diff --git a/doc/src/Build_settings.rst b/doc/src/Build_settings.rst index 53a7a3b761..fb3ebf4b48 100644 --- a/doc/src/Build_settings.rst +++ b/doc/src/Build_settings.rst @@ -8,7 +8,7 @@ Optional build settings LAMMPS can be built with several optional settings. Each subsection explains how to do this for building both with CMake and make. -* `C++11 standard compliance`_ when building all of LAMMPS +* `C++11 and C++17 standard compliance`_ when building all of LAMMPS * `FFT library`_ for use with the :doc:`kspace_style pppm ` command * `Size of LAMMPS integer types and size limits`_ * `Read or write compressed files`_ From 8a1744c038072e0b7c39bd8eeb5496a0abaaf77c Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 7 Feb 2025 21:51:37 -0500 Subject: [PATCH 11/30] Updates to the instructions for building the manual. --- doc/README | 20 ++++++++++++------ doc/src/Build_manual.rst | 45 ++++++++++++++++++++++++++++++---------- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/doc/README b/doc/README index de956a96bb..f96e0b14da 100644 --- a/doc/README +++ b/doc/README @@ -22,12 +22,12 @@ doxygen-warn.log logfile with warnings from running doxygen and: github-development-workflow.md notes on the LAMMPS development workflow -include-file-conventions.md notes on LAMMPS' include file conventions documentation_conventions.md notes on writing documentation for LAMMPS If you downloaded a LAMMPS tarball from www.lammps.org, then the html folder and the PDF manual should be included. If you downloaded LAMMPS -from GitHub then you either need to build them. +using GitHub then you either need to build them yourself or read the +online version at https://docs.lammps.org/ You can build the HTML and PDF files yourself, by typing "make html" or by "make pdf", respectively. This requires various tools and files. @@ -39,10 +39,10 @@ environment and local folders. Installing prerequisites for the documentation build -To run the HTML documention build toolchain, python 3.x, doxygen, git, -and the venv python module have to be installed if not already available. -Also internet access is initially required to download external files -and tools. +To run the HTML documention build toolchain, python 3.8 or later, +doxygen 1.8.10 or later, git, and the venv python module have to be +installed if not already available. Also internet access is initially +required to download external files and tools. Building the PDF format manual requires in addition a compatible LaTeX installation with support for PDFLaTeX and several add-on LaTeX packages @@ -52,16 +52,24 @@ installed. This includes: - babel - capt-of - cmap +- dvipng +- ellipse - fncychap +- fontawesom - framed - geometry +- gyre - hyperref - hypcap - needspace +- pict2e - times - tabulary +- titlesec - upquote - wrapfig +- xindy + Also the latexmk script is required to run PDFLaTeX and related tools. the required number of times to have self-consistent output and include updated bibliography and indices. diff --git a/doc/src/Build_manual.rst b/doc/src/Build_manual.rst index 4b4bfa5a45..490594af02 100644 --- a/doc/src/Build_manual.rst +++ b/doc/src/Build_manual.rst @@ -116,9 +116,9 @@ environment variable. Prerequisites for HTML ---------------------- -To run the HTML documentation build toolchain, python 3, git, doxygen, -and virtualenv have to be installed locally. Here are instructions for -common setups: +To run the HTML documentation build toolchain, Python 3.8 or later, git, +doxygen, and virtualenv have to be installed locally. Here are +instructions for common setups: .. tabs:: @@ -128,13 +128,7 @@ common setups: sudo apt-get install git doxygen - .. tab:: RHEL or CentOS (Version 7.x) - - .. code-block:: bash - - sudo yum install git doxygen - - .. tab:: Fedora or RHEL/CentOS (8.x or later) + .. tab:: Fedora or RHEL/AlmaLinux/RockyLinux (8.x or later) .. code-block:: bash @@ -154,7 +148,36 @@ Prerequisites for PDF In addition to the tools needed for building the HTML format manual, a working LaTeX installation with support for PDFLaTeX and a selection -of LaTeX styles/packages are required. To run the PDFLaTeX translation +of LaTeX styles/packages are required. Apart from LaTeX packages that +are usually installed by default, the following packages are required: + +.. table_from_list:: + :columns: 11 + + - amsmath + - anysize + - babel + - capt-of + - cmap + - dvipng + - ellipse + - fncychap + - fontawesom + - framed + - geometry + - gyre + - hyperref + - hypcap + - needspace + - pict2e + - times + - tabulary + - titlesec + - upquote + - wrapfig + - xindy + +To run the PDFLaTeX translation the ``latexmk`` script needs to be installed as well. Prerequisites for ePUB and MOBI From 098bb4b3c8715a013e24904f6936cfb714631944 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 8 Feb 2025 08:55:32 -0500 Subject: [PATCH 12/30] flag development version --- src/version.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/version.h b/src/version.h index d24e7ed8f1..d28810b466 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1,2 @@ #define LAMMPS_VERSION "4 Feb 2025" +#define LAMMPS_UPDATE "Development" From 31697bac8d41566005609c4ba6cb84c625e11010 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 9 Feb 2025 10:22:55 -0500 Subject: [PATCH 13/30] correct copy-n-modify omission --- src/fix_adapt.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fix_adapt.cpp b/src/fix_adapt.cpp index 9144ecde71..dfb27e48e7 100644 --- a/src/fix_adapt.cpp +++ b/src/fix_adapt.cpp @@ -428,7 +428,7 @@ void FixAdapt::init() for (i = ad->ilo; i <= ad->ihi; i++) { if (!bond->check_itype(i,bstyle)) error->all(FLERR,"Fix adapt type bond range is not valid " - "for pair hybrid sub-style {}", bstyle); + "for bond hybrid sub-style {}", bstyle); } } } @@ -462,7 +462,7 @@ void FixAdapt::init() for (i = ad->ilo; i <= ad->ihi; i++) { if (!angle->check_itype(i,astyle)) error->all(FLERR,"Fix adapt type angle range is not valid " - "for pair hybrid sub-style {}", astyle); + "for angle hybrid sub-style {}", astyle); } } } From 6bd2e0e4966e245d06625a937378b208126963ec Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 9 Feb 2025 10:53:03 -0500 Subject: [PATCH 14/30] update error messages to use new Error class APIs --- src/fix_adapt.cpp | 70 ++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/src/fix_adapt.cpp b/src/fix_adapt.cpp index dfb27e48e7..418e2e4a80 100644 --- a/src/fix_adapt.cpp +++ b/src/fix_adapt.cpp @@ -52,7 +52,7 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : { if (narg < 5) utils::missing_cmd_args(FLERR,"fix adapt", error); nevery = utils::inumeric(FLERR,arg[3],false,lmp); - if (nevery < 0) error->all(FLERR,"Illegal fix adapt every value {}", nevery); + if (nevery < 0) error->all(FLERR, 3, "Illegal fix adapt every value {}", nevery); dynamic_group_allow = 1; create_attribute = 1; @@ -86,7 +86,7 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : } else break; } - if (nadapt == 0) error->all(FLERR,"Nothing to adapt in fix adapt command"); + if (nadapt == 0) error->all(FLERR, 3, "Nothing to adapt in fix adapt command"); adapt = new Adapt[nadapt]; // parse keywords @@ -119,7 +119,7 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : if (utils::strmatch(arg[iarg+5],"^v_")) { adapt[nadapt].var = utils::strdup(arg[iarg+5]+2); - } else error->all(FLERR,"Argument #{} must be variable not {}", iarg+6, arg[iarg+5]); + } else error->all(FLERR, iarg+5, "Argument must be variable not {}", arg[iarg+5]); nadapt++; iarg += 6; @@ -132,7 +132,7 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : adapt[nadapt].ilo, adapt[nadapt].ihi, lmp, Atom::BOND); if (utils::strmatch(arg[iarg+4],"^v_")) { adapt[nadapt].var = utils::strdup(arg[iarg+4]+2); - } else error->all(FLERR,"Argument #{} must be variable not {}", iarg+5, arg[iarg+4]); + } else error->all(FLERR, iarg+4, "Argument must be variable not {}", arg[iarg+4]); nadapt++; iarg += 5; @@ -145,7 +145,7 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : adapt[nadapt].ilo, adapt[nadapt].ihi, lmp, Atom::ANGLE); if (utils::strmatch(arg[iarg+4],"^v_")) { adapt[nadapt].var = utils::strdup(arg[iarg+4]+2); - } else error->all(FLERR,"Argument #{} must be variable not {}", iarg+5, arg[iarg+4]); + } else error->all(FLERR,iarg+4, "Argument must be variable not {}", arg[iarg+4]); nadapt++; iarg += 5; @@ -153,7 +153,7 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : adapt[nadapt].which = KSPACE; if (utils::strmatch(arg[iarg+1],"^v_")) { adapt[nadapt].var = utils::strdup(arg[iarg+1]+2); - } else error->all(FLERR,"Argument #{} must be variable not {}", iarg+2, arg[iarg+1]); + } else error->all(FLERR, iarg+1, "Argument must be variable not {}", arg[iarg+1]); nadapt++; iarg += 2; @@ -168,10 +168,11 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : } else if (strcmp(arg[iarg+1],"charge") == 0) { adapt[nadapt].atomparam = CHARGE; chgflag = 1; - } else error->all(FLERR,"Unsupported per-atom property {} for fix adapt", arg[iarg+1]); + } else error->all(FLERR, iarg+1, "Unsupported per-atom property {} for fix adapt", + arg[iarg+1]); if (utils::strmatch(arg[iarg+2],"^v_")) { adapt[nadapt].var = utils::strdup(arg[iarg+2]+2); - } else error->all(FLERR,"Argument #{} must be variable not {}", iarg+3, arg[iarg+2]); + } else error->all(FLERR, iarg+2, "Argument must be variable not {}", arg[iarg+2]); nadapt++; iarg += 3; } else break; @@ -329,7 +330,8 @@ void FixAdapt::init() if (group->dynamic[igroup]) for (i = 0; i < nadapt; i++) if (adapt[i].which == ATOM) - error->all(FLERR,"Cannot use dynamic group {} with fix adapt atom", group->names[igroup]); + error->all(FLERR, Error::NOLASTLINE, + "Cannot use dynamic group {} with fix adapt atom", group->names[igroup]); // setup and error checks @@ -342,9 +344,11 @@ void FixAdapt::init() ad->ivar = input->variable->find(ad->var); if (ad->ivar < 0) - error->all(FLERR,"Variable name {} for fix adapt does not exist", ad->var); + error->all(FLERR, Error::NOLASTLINE, + "Variable name {} for fix adapt does not exist", ad->var); if (!input->variable->equalstyle(ad->ivar)) - error->all(FLERR,"Variable {} for fix adapt is invalid style", ad->var); + error->all(FLERR, Error::NOLASTLINE, + "Variable {} for fix adapt is invalid style", ad->var); if (ad->which == PAIR) { anypair = 1; @@ -369,17 +373,20 @@ void FixAdapt::init() ad->pair = force->pair_match(fmt::format("{}/{}",pstyle,lmp->suffix2),1,nsub); } if (ad->pair == nullptr) ad->pair = force->pair_match(pstyle,1,nsub); - if (ad->pair == nullptr) error->all(FLERR,"Fix adapt pair style {} not found", pstyle); + if (ad->pair == nullptr) + error->all(FLERR, Error::NOLASTLINE, "Fix adapt pair style {} not found", pstyle); void *ptr = ad->pair->extract(ad->pparam,ad->pdim); if (ptr == nullptr) - error->all(FLERR,"Fix adapt pair style {} param {} not supported", ad->pstyle, ad->pparam); + error->all(FLERR, Error::NOLASTLINE, + "Fix adapt pair style {} param {} not supported", ad->pstyle, ad->pparam); // for pair styles only parameters that are 2-d arrays in atom types or // scalars are supported if (ad->pdim != 2 && ad->pdim != 0) - error->all(FLERR,"Pair style parameter {} is not compatible with fix adapt", ad->pparam); + error->all(FLERR, Error::NOLASTLINE, + "Pair style parameter {} is not compatible with fix adapt", ad->pparam); if (ad->pdim == 2) ad->array = (double **) ptr; if (ad->pdim == 0) ad->scalar = (double *) ptr; @@ -392,7 +399,7 @@ void FixAdapt::init() for (i = ad->ilo; i <= ad->ihi; i++) { for (j = MAX(ad->jlo,i); j <= ad->jhi; j++) { if (!pair->check_ijtype(i,j,pstyle)) - error->all(FLERR,"Fix adapt type pair range is not valid " + error->all(FLERR, Error::NOLASTLINE, "Fix adapt type pair range is not valid " "for pair hybrid sub-style {}", pstyle); } } @@ -411,12 +418,13 @@ void FixAdapt::init() if (ad->bond == nullptr) ad->bond = force->bond_match(bstyle); if (ad->bond == nullptr ) - error->all(FLERR,"Fix adapt bond style {} does not exist", bstyle); + error->all(FLERR, Error::NOLASTLINE,"Fix adapt bond style {} does not exist", bstyle); void *ptr = ad->bond->extract(ad->bparam,ad->bdim); if (ptr == nullptr) - error->all(FLERR,"Fix adapt bond style parameter {} not supported", ad->bparam); + error->all(FLERR, Error::NOLASTLINE, + "Fix adapt bond style parameter {} not supported", ad->bparam); // for bond styles, use a vector @@ -427,7 +435,7 @@ void FixAdapt::init() if (bond) { for (i = ad->ilo; i <= ad->ihi; i++) { if (!bond->check_itype(i,bstyle)) - error->all(FLERR,"Fix adapt type bond range is not valid " + error->all(FLERR, Error::NOLASTLINE, "Fix adapt type bond range is not valid " "for bond hybrid sub-style {}", bstyle); } } @@ -445,12 +453,13 @@ void FixAdapt::init() if (ad->angle == nullptr) ad->angle = force->angle_match(astyle); if (ad->angle == nullptr ) - error->all(FLERR,"Fix adapt angle style {} does not exist", astyle); + error->all(FLERR, Error::NOLASTLINE, "Fix adapt angle style {} does not exist", astyle); void *ptr = ad->angle->extract(ad->aparam,ad->adim); if (ptr == nullptr) - error->all(FLERR,"Fix adapt angle style parameter {} not supported", ad->aparam); + error->all(FLERR, Error::NOLASTLINE, + "Fix adapt angle style parameter {} not supported", ad->aparam); // for angle styles, use a vector @@ -461,7 +470,7 @@ void FixAdapt::init() if (angle) { for (i = ad->ilo; i <= ad->ihi; i++) { if (!angle->check_itype(i,astyle)) - error->all(FLERR,"Fix adapt type angle range is not valid " + error->all(FLERR, Error::NOLASTLINE, "Fix adapt type angle range is not valid " "for angle hybrid sub-style {}", astyle); } } @@ -471,22 +480,23 @@ void FixAdapt::init() } else if (ad->which == KSPACE) { if (force->kspace == nullptr) - error->all(FLERR,"Fix adapt expected a kspace style but none was defined"); + error->all(FLERR, Error::NOLASTLINE, + "Fix adapt expected a kspace style but none was defined"); kspace_scale = (double *) force->kspace->extract("scale"); } else if (ad->which == ATOM) { if (ad->atomparam == DIAMETER) { if (!atom->radius_flag) - error->all(FLERR,"Fix adapt requires atom attribute diameter"); + error->all(FLERR, Error::NOLASTLINE, "Fix adapt requires atom attribute diameter"); if (!atom->rmass_flag) - error->all(FLERR,"Fix adapt requires atom attribute mass"); + error->all(FLERR, Error::NOLASTLINE, "Fix adapt requires atom attribute mass"); if (discflag && domain->dimension != 2) - error->all(FLERR,"Fix adapt requires 2d simulation"); + error->all(FLERR, Error::NOLASTLINE, "Fix adapt requires 2d simulation"); if (!restart_reset) previous_diam_scale = 1.0; } if (ad->atomparam == CHARGE) { if (!atom->q_flag) - error->all(FLERR,"Fix adapt requires atom attribute charge"); + error->all(FLERR, Error::NOLASTLINE, "Fix adapt requires atom attribute charge"); if (!restart_reset) previous_chg_scale = 1.0; } } @@ -520,11 +530,15 @@ void FixAdapt::init() if (id_fix_diam) { fix_diam = dynamic_cast(modify->get_fix_by_id(id_fix_diam)); - if (!fix_diam) error->all(FLERR,"Could not find fix adapt storage fix ID {}", id_fix_diam); + if (!fix_diam) + error->all(FLERR, Error::NOLASTLINE, + "Could not find fix adapt storage fix ID {}", id_fix_diam); } if (id_fix_chg) { fix_chg = dynamic_cast(modify->get_fix_by_id(id_fix_chg)); - if (!fix_chg) error->all(FLERR,"Could not find fix adapt storage fix ID {}", id_fix_chg); + if (!fix_chg) + error->all(FLERR, Error::NOLASTLINE, + "Could not find fix adapt storage fix ID {}", id_fix_chg); } if (utils::strmatch(update->integrate_style,"^respa")) From c42650257f6fe53978afb161a9000e60a502d548 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 10 Feb 2025 22:27:09 -0500 Subject: [PATCH 15/30] move AutoClose class to separate header and rename to SafeFilePtr --- src/EXTRA-COMMAND/region2vmd.cpp | 22 ++---------- src/safe_pointers.h | 57 ++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 19 deletions(-) create mode 100644 src/safe_pointers.h diff --git a/src/EXTRA-COMMAND/region2vmd.cpp b/src/EXTRA-COMMAND/region2vmd.cpp index 3a0570ac79..f244fc8121 100644 --- a/src/EXTRA-COMMAND/region2vmd.cpp +++ b/src/EXTRA-COMMAND/region2vmd.cpp @@ -21,6 +21,7 @@ #include "domain.h" #include "error.h" #include "region.h" +#include "safe_pointers.h" #include "region_block.h" #include "region_cone.h" @@ -158,30 +159,14 @@ static constexpr char draw_ellipsoid_function[] = " return $gid\n" "}\n\n"; -// class that "owns" the file pointer and closes it when going out of scope. -// this avoids a lot of redundant checks and calls. -class AutoClose { - public: - AutoClose() = delete; - AutoClose(const AutoClose &) = delete; - AutoClose(const AutoClose &&) = delete; - explicit AutoClose(FILE *_fp) : fp(_fp) {}; - ~AutoClose() - { - if (fp) fclose(fp); - } - - private: - FILE *fp; -}; - /* ---------------------------------------------------------------------- */ void Region2VMD::command(int narg, char **arg) { if (narg < 3) utils::missing_cmd_args(FLERR, "region2vmd", error); - FILE *fp = nullptr; + // automatically close file when it goes out of scope + SafeFilePtr fp; if (comm->me == 0) { fp = fopen(arg[0], "w"); if (fp == nullptr) { @@ -194,7 +179,6 @@ void Region2VMD::command(int narg, char **arg) } // automatically close fp when fpowner goes out of scope - AutoClose fpowner(fp); // defaults std::string color = "silver"; diff --git a/src/safe_pointers.h b/src/safe_pointers.h new file mode 100644 index 0000000000..8ae6ab74e4 --- /dev/null +++ b/src/safe_pointers.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + LAMMPS development team: developers@lammps.org + + 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. +------------------------------------------------------------------------- */ + +#ifndef LMP_SAFE_POINTERS_H +#define LMP_SAFE_POINTERS_H + +// collection of smart pointers for specific purposes + +#include + +namespace LAMMPS_NS { + +/** Class to automatically close a FILE pointer when a class instance goes out of scope. + +\verbatim embed:rst + +Drop in replacement for ``FILE *``. Use as ``SafeFilePtr fp;`` instead of +``FILE *fp = nullptr;`` and there is no more need to explicitly call +``fclose(fp)``. + +\endverbatim +*/ +class SafeFilePtr { + public: + SafeFilePtr() : fp(nullptr) {}; + SafeFilePtr(const SafeFilePtr &) = delete; + SafeFilePtr(const SafeFilePtr &&) = delete; + SafeFilePtr &operator=(const SafeFilePtr &) = delete; + + ~SafeFilePtr() + { + if (fp) fclose(fp); + } + + SafeFilePtr &operator=(FILE *_fp) + { + fp = _fp; + return *this; + } + operator FILE *() const { return fp; } + + private: + FILE *fp; +}; +} // namespace LAMMPS_NS + +#endif From 08553a7272041b2f0246d4647c2cdfaf778e902a Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 10 Feb 2025 22:48:55 -0500 Subject: [PATCH 16/30] apply safe file pointer --- src/angle_write.cpp | 10 +++++----- src/bond.cpp | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/angle_write.cpp b/src/angle_write.cpp index 863183995b..9a33722250 100644 --- a/src/angle_write.cpp +++ b/src/angle_write.cpp @@ -26,6 +26,7 @@ #include "force.h" #include "input.h" #include "math_const.h" +#include "safe_pointers.h" #include "update.h" #include @@ -79,13 +80,13 @@ void AngleWrite::command(int narg, char **arg) // otherwise make certain that units are consistent // print header in format used by angle_style table - FILE *fp = nullptr; + SafeFilePtr fp; std::string coeffs_file = table_file + ".tmp.coeffs"; if (comm->me == 0) { - fp = fopen(coeffs_file.c_str(), "w"); - force->angle->write_data(fp); - fclose(fp); + FILE *coeffs = fopen(coeffs_file.c_str(), "w"); + force->angle->write_data(coeffs); + fclose(coeffs); // units sanity check: // - if this is the first time we write to this potential file, @@ -221,7 +222,6 @@ void AngleWrite::command(int narg, char **arg) // clean up delete writer; - fclose(fp); } MPI_Comm_free(&singlecomm); } diff --git a/src/bond.cpp b/src/bond.cpp index f5af30062e..d42dd6fd24 100644 --- a/src/bond.cpp +++ b/src/bond.cpp @@ -20,6 +20,7 @@ #include "force.h" #include "memory.h" #include "neighbor.h" +#include "safe_pointers.h" #include "suffix.h" #include "update.h" @@ -365,7 +366,7 @@ void Bond::write_file(int narg, char **arg) // add line with DATE: and UNITS: tag when creating new file // print header in format used by bond_style table - FILE *fp = nullptr; + SafeFilePtr fp; if (comm->me == 0) { std::string table_file = arg[4]; @@ -419,7 +420,6 @@ void Bond::write_file(int narg, char **arg) e = single(btype, r * r, itype, jtype, f); fprintf(fp, "%8d %- 22.15g %- 22.15g %- 22.15g\n", i + 1, r, e, f * r); } - fclose(fp); } } From 252bd9aa9d31c9d6e514c77fe08ce4807eb413aa Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 11 Feb 2025 05:13:07 -0500 Subject: [PATCH 17/30] must close "owned" file pointer if a different one is is assigned --- src/safe_pointers.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/safe_pointers.h b/src/safe_pointers.h index 8ae6ab74e4..af6e51d64b 100644 --- a/src/safe_pointers.h +++ b/src/safe_pointers.h @@ -44,6 +44,7 @@ class SafeFilePtr { SafeFilePtr &operator=(FILE *_fp) { + if (fp && (fp != _fp)) fclose(fp); fp = _fp; return *this; } From 1d3ad36e85ae70180a36991085732468bff0b983 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 11 Feb 2025 07:40:42 -0500 Subject: [PATCH 18/30] add support for visualization plane regions --- src/EXTRA-COMMAND/region2vmd.cpp | 81 ++++++++++++++++++++++++++++++++ src/region_plane.h | 2 + 2 files changed, 83 insertions(+) diff --git a/src/EXTRA-COMMAND/region2vmd.cpp b/src/EXTRA-COMMAND/region2vmd.cpp index f244fc8121..3175c54408 100644 --- a/src/EXTRA-COMMAND/region2vmd.cpp +++ b/src/EXTRA-COMMAND/region2vmd.cpp @@ -20,6 +20,7 @@ #include "comm.h" #include "domain.h" #include "error.h" +#include "math_extra.h" #include "region.h" #include "safe_pointers.h" @@ -27,6 +28,7 @@ #include "region_cone.h" #include "region_cylinder.h" #include "region_ellipsoid.h" +#include "region_plane.h" #include "region_prism.h" #include "region_sphere.h" @@ -452,6 +454,85 @@ void Region2VMD::write_region(FILE *fp, Region *region) ellipsoid->c); } + } else if (regstyle == "plane") { + const auto plane = dynamic_cast(region); + if (!plane) { + error->one(FLERR, Error::NOLASTLINE, "Region {} is not of style 'plane'", region->id); + } else { + double v1[3], v2[3], v3[3], v4[3], v5[3], v6[3]; + MathExtra::copy3(plane->normal, v1); + MathExtra::norm3(v1); + v2[0] = plane->xp + dx; + v2[1] = plane->yp + dy; + v2[2] = plane->zp + dz; + // determine the largest component of the plane normal and use that to determine the triangle edges + int dim1, dim2, dim3; + if (fabs(v1[0]) > fabs(v1[1])) { // x > y + if (fabs(v1[0]) > fabs(v1[2])) { // x > z => x is largest + dim3 = 0; + dim1 = 1; + dim2 = 2; + } else { // z is largest + dim3 = 2; + dim1 = 0; + dim2 = 1; + } + } else { // x < y + if (fabs(v1[1]) > fabs(v1[2])) { // y > z => y is largest + dim3 = 1; + dim1 = 0; + dim2 = 2; + } else { // z is largest + dim3 = 2; + dim1 = 0; + dim2 = 1; + } + } + + MathExtra::scale3(2.0, domain->boxlo, v3); + v3[dim3] = 0.0; + MathExtra::cross3(v1, v3, v4); + MathExtra::add3(v4, v2, v5); + v3[dim1] = domain->boxhi[dim1]; + v3[dim2] = domain->boxlo[dim2]; + v3[dim3] = 0.0; + MathExtra::scale3(2.0, v3); + MathExtra::cross3(v1, v3, v4); + MathExtra::add3(v4, v2, v6); + utils::print(fp, "draw triangle {{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", v2[dim1], v2[dim2], + v2[dim3], v5[dim1], v5[dim2], v5[dim3], v6[dim1], v6[dim2], v6[dim3]); + v3[dim1] = domain->boxlo[dim1]; + v3[dim2] = domain->boxhi[dim2]; + v3[dim3] = 0.0; + MathExtra::scale3(2.0, v3); + MathExtra::cross3(v1, v3, v4); + MathExtra::add3(v4, v2, v6); + utils::print(fp, "draw triangle {{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", v2[dim1], v2[dim2], + v2[dim3], v5[dim1], v5[dim2], v5[dim3], v6[dim1], v6[dim2], v6[dim3]); + v3[dim1] = domain->boxhi[dim1]; + v3[dim2] = domain->boxhi[dim2]; + v3[dim3] = 0.0; + MathExtra::scale3(2.0, v3); + MathExtra::cross3(v1, v3, v4); + MathExtra::add3(v4, v2, v5); + v3[dim1] = domain->boxhi[dim1]; + v3[dim2] = domain->boxlo[dim2]; + v3[dim3] = 0.0; + MathExtra::scale3(2.0, v3); + MathExtra::cross3(v1, v3, v4); + MathExtra::add3(v4, v2, v6); + utils::print(fp, "draw triangle {{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", v2[dim1], v2[dim2], + v2[dim3], v5[dim1], v5[dim2], v5[dim3], v6[dim1], v6[dim2], v6[dim3]); + v3[dim1] = domain->boxlo[dim1]; + v3[dim2] = domain->boxhi[dim2]; + v3[dim3] = 0.0; + MathExtra::scale3(2.0, v3); + MathExtra::cross3(v1, v3, v4); + MathExtra::add3(v4, v2, v6); + utils::print(fp, "draw triangle {{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", v2[dim1], v2[dim2], + v2[dim3], v5[dim1], v5[dim2], v5[dim3], v6[dim1], v6[dim2], v6[dim3]); + } + } else if (regstyle == "prism") { const auto prism = dynamic_cast(region); if (!prism) { diff --git a/src/region_plane.h b/src/region_plane.h index 790564e176..0988fda812 100644 --- a/src/region_plane.h +++ b/src/region_plane.h @@ -25,6 +25,8 @@ RegionStyle(plane,RegPlane); namespace LAMMPS_NS { class RegPlane : public Region { + friend class Region2VMD; + public: RegPlane(class LAMMPS *, int, char **); ~RegPlane() override; From 5b7bf1951e41393262fd064e8786ffa13bb1a714 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 12 Feb 2025 05:42:51 -0500 Subject: [PATCH 19/30] simplify logic for drawing a cylinder region --- src/EXTRA-COMMAND/region2vmd.cpp | 142 +++++++++++++------------------ 1 file changed, 59 insertions(+), 83 deletions(-) diff --git a/src/EXTRA-COMMAND/region2vmd.cpp b/src/EXTRA-COMMAND/region2vmd.cpp index 3175c54408..5f48b1f9b3 100644 --- a/src/EXTRA-COMMAND/region2vmd.cpp +++ b/src/EXTRA-COMMAND/region2vmd.cpp @@ -336,6 +336,7 @@ void Region2VMD::write_region(FILE *fp, Region *region) utils::print(fp, "draw cone {{{2} {3} {0}}} {{{2} {3} {1}}} radius {4} resolution 20\n", cone->lo + dz, cone->hi + dz, cone->c1 + dx, cone->c2 + dy, cone->radiuslo); } + } else { utils::logmesg(lmp, "Cannot (yet) translate a truncated cone to VMD graphics. Skipping...\n"); @@ -343,102 +344,77 @@ void Region2VMD::write_region(FILE *fp, Region *region) } } else if (regstyle == "cylinder") { - const auto cylinder = dynamic_cast(region); - if (!cylinder) { + const auto cyl = dynamic_cast(region); + if (!cyl) { error->one(FLERR, Error::NOLASTLINE, "Region {} is not of style 'cylinder'", region->id); } else { - std::string filled = "yes"; - if (cylinder->open_faces[0] && cylinder->open_faces[1]) { - filled = "no"; - } else if (cylinder->open_faces[0] != cylinder->open_faces[1]) { - filled = "no"; - // we put a single "lid" on an open cylinder by adding a filled cylinder of zero height - double lid = cylinder->lo; - if (cylinder->open_faces[0]) lid = cylinder->hi; - if (cylinder->axis == 'x') { + // first draw the cylinder. filled only when *all* faces are closed. + // with any open face we draw each part separately + std::string filled = "filled no"; + if (!cyl->open_faces[0] && !cyl->open_faces[1] && !cyl->open_faces[2]) { + filled = "filled yes"; + } + + // the cylinder uses a single cylinder primitive + if (!cyl->open_faces[2]) { + if (cyl->axis == 'x') { + utils::print( + fp, "draw cylinder {{{0} {2} {3}}} {{{1} {2} {3}}} radius {4} resolution 20 {5}\n", + cyl->lo + dx, cyl->hi + dx, cyl->c1 + dy, cyl->c2 + dz, cyl->radius, filled); + } else if (cyl->axis == 'y') { + utils::print( + fp, "draw cylinder {{{2} {0} {3}}} {{{2} {1} {3}}} radius {4} resolution 20 {5}\n", + cyl->lo + dy, cyl->hi + dy, cyl->c1 + dx, cyl->c2 + dz, cyl->radius, filled); + } else if (cyl->axis == 'z') { + utils::print( + fp, "draw cylinder {{{2} {3} {0}}} {{{2} {3} {1}}} radius {4} resolution 20 {5}\n", + cyl->lo + dz, cyl->hi + dz, cyl->c1 + dx, cyl->c2 + dy, cyl->radius, filled); + } + } + + // draw lids + if ((filled == "filled no") && !cyl->open_faces[0]) { + double lid = cyl->lo; + if (cyl->axis == 'x') { + lid += dx; utils::print(fp, "draw cylinder {{{0} {2} {3}}} {{{1:.15} {2} {3}}} radius {4} resolution 20 " "filled yes\n", - lid + dx, lid + dx + DELTA, cylinder->c1 + dy, cylinder->c2 + dz, - cylinder->radius); - } else if (cylinder->axis == 'y') { + lid, lid + DELTA, cyl->c1 + dy, cyl->c2 + dz, cyl->radius); + } else if (cyl->axis == 'y') { + lid += dy; utils::print(fp, "draw cylinder {{{2} {0} {3}}} {{{2} {1:.15} {3}}} radius {4} resolution 20 " "filled yes\n", - lid + dy, lid + dy + DELTA, cylinder->c1 + dx, cylinder->c2 + dz, - cylinder->radius); - } else if (cylinder->axis == 'z') { + lid, lid + DELTA, cyl->c1 + dx, cyl->c2 + dz, cyl->radius); + } else if (cyl->axis == 'z') { + lid += dz; utils::print(fp, "draw cylinder {{{2} {3} {0}}} {{{2} {3} {1:.15}}} radius {4} resolution 20 " "filled yes\n", - lid + dz, lid + dz + DELTA, cylinder->c1 + dx, cylinder->c2 + dy, - cylinder->radius); + lid + dz, lid + dz + DELTA, cyl->c1 + dx, cyl->c2 + dy, cyl->radius); } } - if (cylinder->open_faces[2]) { - // need to handle two lids case only. Single lid is already done - if (!cylinder->open_faces[0] && !cylinder->open_faces[1]) { - if (cylinder->axis == 'x') { - utils::print( - fp, - "draw cylinder {{{0} {2} {3}}} {{{1:.15} {2} {3}}} radius {4} resolution 20 " - "filled yes\n", - cylinder->lo + dx, cylinder->lo + dx + DELTA, cylinder->c1 + dy, cylinder->c2 + dz, - cylinder->radius); - utils::print( - fp, - "draw cylinder {{{0} {2} {3}}} {{{1:.15} {2} {3}}} radius {4} resolution 20 " - "filled yes\n", - cylinder->hi + dx, cylinder->hi + dx + DELTA, cylinder->c1 + dy, cylinder->c2 + dz, - cylinder->radius); - } else if (cylinder->axis == 'y') { - utils::print( - fp, - "draw cylinder {{{2} {0} {3}}} {{{2} {1:.15} {3}}} radius {4} resolution 20 " - "filled yes\n", - cylinder->lo + dy, cylinder->lo + dy + DELTA, cylinder->c1 + dx, cylinder->c2 + dz, - cylinder->radius); - utils::print( - fp, - "draw cylinder {{{2} {0} {3}}} {{{2} {1:.15} {3}}} radius {4} resolution 20 " - "filled yes\n", - cylinder->hi + dy, cylinder->hi + dy + DELTA, cylinder->c1 + dx, cylinder->c2 + dz, - cylinder->radius); - } else if (cylinder->axis == 'z') { - utils::print( - fp, - "draw cylinder {{{2} {3} {0}}} {{{2} {3} {1:.15}}} radius {4} resolution 20 " - "filled yes\n", - cylinder->lo + dz, cylinder->lo + dz + DELTA, cylinder->c1 + dx, cylinder->c2 + dy, - cylinder->radius); - utils::print( - fp, - "draw cylinder {{{2} {3} {0}}} {{{2} {3} {1:.15}}} radius {4} resolution 20 " - "filled yes\n", - cylinder->hi + dz, cylinder->hi + dz + DELTA, cylinder->c1 + dx, cylinder->c2 + dy, - cylinder->radius); - } - } - } else { - // a cylinder uses a single cylinder primitive and possibly a single "lid" - if (cylinder->axis == 'x') { - utils::print( - fp, - "draw cylinder {{{0} {2} {3}}} {{{1} {2} {3}}} radius {4} resolution 20 filled {5}\n", - cylinder->lo + dx, cylinder->hi + dx, cylinder->c1 + dy, cylinder->c2 + dz, - cylinder->radius, filled); - } else if (cylinder->axis == 'y') { - utils::print( - fp, - "draw cylinder {{{2} {0} {3}}} {{{2} {1} {3}}} radius {4} resolution 20 filled {5}\n", - cylinder->lo + dy, cylinder->hi + dy, cylinder->c1 + dx, cylinder->c2 + dz, - cylinder->radius, filled); - } else if (cylinder->axis == 'z') { - utils::print( - fp, - "draw cylinder {{{2} {3} {0}}} {{{2} {3} {1}}} radius {4} resolution 20 filled {5}\n", - cylinder->lo + dz, cylinder->hi + dz, cylinder->c1 + dx, cylinder->c2 + dy, - cylinder->radius, filled); + if ((filled == "filled no") && !cyl->open_faces[1]) { + double lid = cyl->hi; + if (cyl->axis == 'x') { + lid += dx; + utils::print(fp, + "draw cylinder {{{0} {2} {3}}} {{{1:.15} {2} {3}}} radius {4} resolution 20 " + "filled yes\n", + lid, lid + DELTA, cyl->c1 + dy, cyl->c2 + dz, cyl->radius); + } else if (cyl->axis == 'y') { + lid += dy; + utils::print(fp, + "draw cylinder {{{2} {0} {3}}} {{{2} {1:.15} {3}}} radius {4} resolution 20 " + "filled yes\n", + lid, lid + DELTA, cyl->c1 + dx, cyl->c2 + dz, cyl->radius); + } else if (cyl->axis == 'z') { + lid += dz; + utils::print(fp, + "draw cylinder {{{2} {3} {0}}} {{{2} {3} {1:.15}}} radius {4} resolution 20 " + "filled yes\n", + lid, lid + DELTA, cyl->c1 + dx, cyl->c2 + dy, cyl->radius); } } } From 944e50b06a9a3da5752c6869a66e942ea201f722 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 12 Feb 2025 10:34:21 -0500 Subject: [PATCH 20/30] need to define another constructor to make the SafeFilePtr class work for more cases --- src/safe_pointers.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/safe_pointers.h b/src/safe_pointers.h index af6e51d64b..22b2969ced 100644 --- a/src/safe_pointers.h +++ b/src/safe_pointers.h @@ -33,6 +33,8 @@ Drop in replacement for ``FILE *``. Use as ``SafeFilePtr fp;`` instead of class SafeFilePtr { public: SafeFilePtr() : fp(nullptr) {}; + SafeFilePtr(FILE *_fp) : fp(_fp) {}; + SafeFilePtr(const SafeFilePtr &) = delete; SafeFilePtr(const SafeFilePtr &&) = delete; SafeFilePtr &operator=(const SafeFilePtr &) = delete; From 7af11fe60471903171d90ee6acb97b8106217d90 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 12 Feb 2025 10:35:02 -0500 Subject: [PATCH 21/30] make more use of SafeFilePtr class. --- src/angle_write.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/angle_write.cpp b/src/angle_write.cpp index 9a33722250..1c1601d002 100644 --- a/src/angle_write.cpp +++ b/src/angle_write.cpp @@ -84,9 +84,8 @@ void AngleWrite::command(int narg, char **arg) std::string coeffs_file = table_file + ".tmp.coeffs"; if (comm->me == 0) { - FILE *coeffs = fopen(coeffs_file.c_str(), "w"); + SafeFilePtr coeffs = fopen(coeffs_file.c_str(), "w"); force->angle->write_data(coeffs); - fclose(coeffs); // units sanity check: // - if this is the first time we write to this potential file, @@ -146,16 +145,14 @@ void AngleWrite::command(int narg, char **arg) writer->input->one("pair_coeff * *"); writer->input->one("mass * 1.0"); writer->input->one(fmt::format("angle_style {}", force->angle_style)); - FILE *coeffs; char line[MAXLINE] = {'\0'}; - coeffs = fopen(coeffs_file.c_str(), "r"); + SafeFilePtr coeffs = fopen(coeffs_file.c_str(), "r"); if (!coeffs) error->one(FLERR, "Unable to open temporary file {}: {}", coeffs_file, utils::getsyserror()); for (int i = 0; i < atom->nangletypes; ++i) { utils::sfgets(FLERR, line, MAXLINE, coeffs, coeffs_file.c_str(), error); writer->input->one(fmt::format("angle_coeff {}", line)); } - fclose(coeffs); platform::unlink(coeffs_file); // initialize system From 66ec1ff360b4e980920ff466682c081b07926a3e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 12 Feb 2025 12:09:29 -0500 Subject: [PATCH 22/30] make resolution of VMD graphics primitives a compile time constant. --- src/EXTRA-COMMAND/region2vmd.cpp | 56 +++++++++++++++++--------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/EXTRA-COMMAND/region2vmd.cpp b/src/EXTRA-COMMAND/region2vmd.cpp index 5f48b1f9b3..c90f96a56c 100644 --- a/src/EXTRA-COMMAND/region2vmd.cpp +++ b/src/EXTRA-COMMAND/region2vmd.cpp @@ -39,6 +39,7 @@ using namespace LAMMPS_NS; static constexpr double SMALL = 1.0e-10; static constexpr double DELTA = 1.0e-5; +static constexpr int RESOLUTION = 20; static const std::unordered_set vmdcolors{ "blue", "red", "gray", "orange", "yellow", "tan", "silver", "green", "white", @@ -359,16 +360,19 @@ void Region2VMD::write_region(FILE *fp, Region *region) if (!cyl->open_faces[2]) { if (cyl->axis == 'x') { utils::print( - fp, "draw cylinder {{{0} {2} {3}}} {{{1} {2} {3}}} radius {4} resolution 20 {5}\n", - cyl->lo + dx, cyl->hi + dx, cyl->c1 + dy, cyl->c2 + dz, cyl->radius, filled); + fp, "draw cylinder {{{0} {2} {3}}} {{{1} {2} {3}}} radius {4} resolution {5} {6}\n", + cyl->lo + dx, cyl->hi + dx, cyl->c1 + dy, cyl->c2 + dz, cyl->radius, RESOLUTION, + filled); } else if (cyl->axis == 'y') { utils::print( - fp, "draw cylinder {{{2} {0} {3}}} {{{2} {1} {3}}} radius {4} resolution 20 {5}\n", - cyl->lo + dy, cyl->hi + dy, cyl->c1 + dx, cyl->c2 + dz, cyl->radius, filled); + fp, "draw cylinder {{{2} {0} {3}}} {{{2} {1} {3}}} radius {4} resolution {5} {6}\n", + cyl->lo + dy, cyl->hi + dy, cyl->c1 + dx, cyl->c2 + dz, cyl->radius, RESOLUTION, + filled); } else if (cyl->axis == 'z') { utils::print( - fp, "draw cylinder {{{2} {3} {0}}} {{{2} {3} {1}}} radius {4} resolution 20 {5}\n", - cyl->lo + dz, cyl->hi + dz, cyl->c1 + dx, cyl->c2 + dy, cyl->radius, filled); + fp, "draw cylinder {{{2} {3} {0}}} {{{2} {3} {1}}} radius {4} resolution {5} {6}\n", + cyl->lo + dz, cyl->hi + dz, cyl->c1 + dx, cyl->c2 + dy, cyl->radius, RESOLUTION, + filled); } } @@ -378,21 +382,21 @@ void Region2VMD::write_region(FILE *fp, Region *region) if (cyl->axis == 'x') { lid += dx; utils::print(fp, - "draw cylinder {{{0} {2} {3}}} {{{1:.15} {2} {3}}} radius {4} resolution 20 " - "filled yes\n", - lid, lid + DELTA, cyl->c1 + dy, cyl->c2 + dz, cyl->radius); + "draw cylinder {{{0} {2} {3}}} {{{1:.15} {2} {3}}} radius {4} " + "resolution {5} filled yes\n", + lid, lid + DELTA, cyl->c1 + dy, cyl->c2 + dz, cyl->radius, RESOLUTION); } else if (cyl->axis == 'y') { lid += dy; utils::print(fp, - "draw cylinder {{{2} {0} {3}}} {{{2} {1:.15} {3}}} radius {4} resolution 20 " - "filled yes\n", - lid, lid + DELTA, cyl->c1 + dx, cyl->c2 + dz, cyl->radius); + "draw cylinder {{{2} {0} {3}}} {{{2} {1:.15} {3}}} radius {4} " + "resolution {5} filled yes\n", + lid, lid + DELTA, cyl->c1 + dx, cyl->c2 + dz, cyl->radius, RESOLUTION); } else if (cyl->axis == 'z') { lid += dz; utils::print(fp, - "draw cylinder {{{2} {3} {0}}} {{{2} {3} {1:.15}}} radius {4} resolution 20 " - "filled yes\n", - lid + dz, lid + dz + DELTA, cyl->c1 + dx, cyl->c2 + dy, cyl->radius); + "draw cylinder {{{2} {3} {0}}} {{{2} {3} {1:.15}}} radius {4} " + "resolution {5} filled yes\n", + lid, lid + DELTA, cyl->c1 + dx, cyl->c2 + dy, cyl->radius, RESOLUTION); } } if ((filled == "filled no") && !cyl->open_faces[1]) { @@ -400,21 +404,21 @@ void Region2VMD::write_region(FILE *fp, Region *region) if (cyl->axis == 'x') { lid += dx; utils::print(fp, - "draw cylinder {{{0} {2} {3}}} {{{1:.15} {2} {3}}} radius {4} resolution 20 " - "filled yes\n", - lid, lid + DELTA, cyl->c1 + dy, cyl->c2 + dz, cyl->radius); + "draw cylinder {{{0} {2} {3}}} {{{1:.15} {2} {3}}} radius {4} " + "resolution {5} filled yes\n", + lid, lid + DELTA, cyl->c1 + dy, cyl->c2 + dz, cyl->radius, RESOLUTION); } else if (cyl->axis == 'y') { lid += dy; utils::print(fp, - "draw cylinder {{{2} {0} {3}}} {{{2} {1:.15} {3}}} radius {4} resolution 20 " - "filled yes\n", - lid, lid + DELTA, cyl->c1 + dx, cyl->c2 + dz, cyl->radius); + "draw cylinder {{{2} {0} {3}}} {{{2} {1:.15} {3}}} radius {4} " + "resolution {5} filled yes\n", + lid, lid + DELTA, cyl->c1 + dx, cyl->c2 + dz, cyl->radius, RESOLUTION); } else if (cyl->axis == 'z') { lid += dz; utils::print(fp, - "draw cylinder {{{2} {3} {0}}} {{{2} {3} {1:.15}}} radius {4} resolution 20 " - "filled yes\n", - lid, lid + DELTA, cyl->c1 + dx, cyl->c2 + dy, cyl->radius); + "draw cylinder {{{2} {3} {0}}} {{{2} {3} {1:.15}}} radius {4} " + "resolution {5} filled yes\n", + lid, lid + DELTA, cyl->c1 + dx, cyl->c2 + dy, cyl->radius, RESOLUTION); } } } @@ -545,8 +549,8 @@ void Region2VMD::write_region(FILE *fp, Region *region) error->one(FLERR, Error::NOLASTLINE, "Region {} is not of style 'sphere'", region->id); } else { // a sphere uses a single sphere primitive - utils::print(fp, "draw sphere {{{} {} {}}} radius {} resolution 20\n", sphere->xc, sphere->yc, - sphere->zc, sphere->radius); + utils::print(fp, "draw sphere {{{} {} {}}} radius {} resolution {}\n", sphere->xc, sphere->yc, + sphere->zc, sphere->radius, RESOLUTION); } } else { From 98f3a0a1ba05f3a22a3ff5f3a98889b9fb85983c Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 12 Feb 2025 15:28:13 -0500 Subject: [PATCH 23/30] refactor cone visualization to match what LAMMPS is showing --- src/EXTRA-COMMAND/region2vmd.cpp | 392 ++++++++++++++++++++++++++++--- 1 file changed, 360 insertions(+), 32 deletions(-) diff --git a/src/EXTRA-COMMAND/region2vmd.cpp b/src/EXTRA-COMMAND/region2vmd.cpp index c90f96a56c..3e845651af 100644 --- a/src/EXTRA-COMMAND/region2vmd.cpp +++ b/src/EXTRA-COMMAND/region2vmd.cpp @@ -20,6 +20,7 @@ #include "comm.h" #include "domain.h" #include "error.h" +#include "math_const.h" #include "math_extra.h" #include "region.h" #include "safe_pointers.h" @@ -32,14 +33,17 @@ #include "region_prism.h" #include "region_sphere.h" +#include #include #include using namespace LAMMPS_NS; +using MathConst::MY_2PI; static constexpr double SMALL = 1.0e-10; static constexpr double DELTA = 1.0e-5; static constexpr int RESOLUTION = 20; +static constexpr double RADINC = MY_2PI / RESOLUTION; static const std::unordered_set vmdcolors{ "blue", "red", "gray", "orange", "yellow", "tan", "silver", "green", "white", @@ -181,8 +185,6 @@ void Region2VMD::command(int narg, char **arg) } } - // automatically close fp when fpowner goes out of scope - // defaults std::string color = "silver"; std::string material = "Transparent"; @@ -310,37 +312,363 @@ void Region2VMD::write_region(FILE *fp, Region *region) if (!cone) { error->one(FLERR, Error::NOLASTLINE, "Region {} is not of style 'cone'", region->id); } else { - if (cone->open_faces[0] || cone->open_faces[1]) - error->warning(FLERR, "Drawing open-faced cones is not supported"); - // The VMD cone primitive requires one radius set to zero - if (cone->radiuslo < SMALL) { - // a VMD cone uses a single cone primitive - if (cone->axis == 'x') { - utils::print(fp, "draw cone {{{1} {2} {3}}} {{{0} {2} {3}}} radius {4} resolution 20\n", - cone->lo + dx, cone->hi + dx, cone->c1 + dy, cone->c2 + dz, cone->radiushi); - } else if (cone->axis == 'y') { - utils::print(fp, "draw cone {{{2} {1} {3}}} {{{2} {0} {3}}} radius {4} resolution 20\n", - cone->lo + dy, cone->hi + dy, cone->c1 + dx, cone->c2 + dz, cone->radiushi); - } else if (cone->axis == 'z') { - utils::print(fp, "draw cone {{{2} {3} {1}}} {{{2} {3} {0}}} radius {4} resolution 20\n", - cone->lo + dz, cone->hi + dz, cone->c1 + dx, cone->c2 + dy, cone->radiushi); - } - } else if (cone->radiushi < SMALL) { - // a VMD cone uses a single cone primitive - if (cone->axis == 'x') { - utils::print(fp, "draw cone {{{0} {2} {3}}} {{{1} {2} {3}}} radius {4} resolution 20\n", - cone->lo + dx, cone->hi + dx, cone->c1 + dy, cone->c2 + dz, cone->radiuslo); - } else if (cone->axis == 'y') { - utils::print(fp, "draw cone {{{2} {0} {3}}} {{{2} {1} {3}}} radius {4} resolution 20\n", - cone->lo + dy, cone->hi + dy, cone->c1 + dx, cone->c2 + dz, cone->radiuslo); - } else if (cone->axis == 'z') { - utils::print(fp, "draw cone {{{2} {3} {0}}} {{{2} {3} {1}}} radius {4} resolution 20\n", - cone->lo + dz, cone->hi + dz, cone->c1 + dx, cone->c2 + dy, cone->radiuslo); - } + // draw cone + if (!cone->open_faces[2]) { - } else { - utils::logmesg(lmp, - "Cannot (yet) translate a truncated cone to VMD graphics. Skipping...\n"); + // both radii too small + if ((cone->radiuslo < SMALL) && (cone->radiushi < SMALL)) { + ; // nothing to draw + + // lo end has a tip + } else if (cone->radiuslo < SMALL) { + double v1[3], v2[3], v3[0], v4[3], v5[3]; + + if (cone->axis == 'x') { + // set tip coordinate + v1[0] = cone->lo + dx; + v1[1] = cone->c1 + dy; + v1[2] = cone->c2 + dz; + + // loop around radius + for (int i = 0; i < RESOLUTION; ++i) { + v2[0] = cone->hi + dx; + v2[1] = cone->c1 + cone->radiushi * sin(RADINC * i) + dy; + v2[2] = cone->c2 + cone->radiushi * cos(RADINC * i) + dz; + v3[0] = cone->hi + dx; + v3[1] = cone->c1 + cone->radiushi * sin(RADINC * (i + 1.0)) + dy; + v3[2] = cone->c2 + cone->radiushi * cos(RADINC * (i + 1.0)) + dz; + v4[0] = 0.0; + v4[1] = sin(RADINC * i); + v4[2] = cos(RADINC * i); + v5[0] = 0.0; + v5[1] = sin(RADINC * (i + 1.0)); + v5[2] = cos(RADINC * (i + 1.0)); + + utils::print(fp, + "draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} " + "{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", + v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], 1.0, 0.0, + 0.0, v4[0], v4[1], v4[2], v5[0], v5[1], v5[2]); + } + + } else if (cone->axis == 'y') { + // set tip coordinate + v1[0] = cone->c1 + dx; + v1[1] = cone->lo + dy; + v1[2] = cone->c2 + dz; + + // loop around radius + for (int i = 0; i < RESOLUTION; ++i) { + v2[0] = cone->c1 + cone->radiushi * sin(RADINC * i) + dx; + v2[1] = cone->hi + dy; + v2[2] = cone->c2 + cone->radiushi * cos(RADINC * i) + dz; + v3[0] = cone->c1 + cone->radiushi * sin(RADINC * (i + 1.0)) + dx; + v3[1] = cone->hi + dy; + v3[2] = cone->c2 + cone->radiushi * cos(RADINC * (i + 1.0)) + dz; + v4[0] = sin(RADINC * i); + v4[1] = 0.0; + v4[2] = cos(RADINC * i); + v5[0] = sin(RADINC * (i + 1.0)); + v5[1] = 0.0; + v5[2] = cos(RADINC * (i + 1.0)); + + utils::print(fp, + "draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} " + "{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", + v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], 0.0, 1.0, + 0.0, v4[0], v4[1], v4[2], v5[0], v5[1], v5[2]); + } + + } else if (cone->axis == 'z') { + // set tip coordinate + v1[0] = cone->c1 + dx; + v1[1] = cone->c2 + dy; + v1[2] = cone->lo + dz; + + // loop around radius + for (int i = 0; i < RESOLUTION; ++i) { + v2[0] = cone->c1 + cone->radiushi * sin(RADINC * i) + dx; + v2[1] = cone->c2 + cone->radiushi * cos(RADINC * i) + dy; + v2[2] = cone->hi + dz; + v3[0] = cone->c1 + cone->radiushi * sin(RADINC * (i + 1.0)) + dx; + v3[1] = cone->c2 + cone->radiushi * cos(RADINC * (i + 1.0)) + dy; + v3[2] = cone->hi + dz; + v4[0] = sin(RADINC * i); + v4[1] = cos(RADINC * i); + v4[2] = 0.0; + v5[0] = sin(RADINC * (i + 1.0)); + v5[1] = cos(RADINC * (i + 1.0)); + v5[2] = 0.0; + utils::print(fp, + "draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} " + "{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", + v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], 0.0, 0.0, + 1.0, v4[0], v4[1], v4[2], v5[0], v5[1], v5[2]); + } + } + + // hi end has a tip + } else if (cone->radiushi < SMALL) { + double v1[3], v2[3], v3[0], v4[3], v5[3]; + + if (cone->axis == 'x') { + // set tip coordinate + v1[0] = cone->hi + dx; + v1[1] = cone->c1 + dy; + v1[2] = cone->c2 + dz; + + // loop around radius + for (int i = 0; i < RESOLUTION; ++i) { + v2[0] = cone->lo + dx; + v2[1] = cone->c1 + cone->radiuslo * sin(RADINC * i) + dy; + v2[2] = cone->c2 + cone->radiuslo * cos(RADINC * i) + dz; + v3[0] = cone->lo + dx; + v3[1] = cone->c1 + cone->radiuslo * sin(RADINC * (i + 1.0)) + dy; + v3[2] = cone->c2 + cone->radiuslo * cos(RADINC * (i + 1.0)) + dz; + v4[0] = 0.0; + v4[1] = sin(RADINC * i); + v4[2] = cos(RADINC * i); + v5[0] = 0.0; + v5[1] = sin(RADINC * (i + 1.0)); + v5[2] = cos(RADINC * (i + 1.0)); + + utils::print(fp, + "draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} " + "{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", + v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], 1.0, 0.0, + 0.0, v4[0], v4[1], v4[2], v5[0], v5[1], v5[2]); + } + + } else if (cone->axis == 'y') { + // set tip coordinate + v1[0] = cone->c1 + dx; + v1[1] = cone->hi + dy; + v1[2] = cone->c2 + dz; + + // loop around radius + for (int i = 0; i < RESOLUTION; ++i) { + v2[0] = cone->c1 + cone->radiuslo * sin(RADINC * i) + dx; + v2[1] = cone->lo + dy; + v2[2] = cone->c2 + cone->radiuslo * cos(RADINC * i) + dz; + v3[0] = cone->c1 + cone->radiuslo * sin(RADINC * (i + 1.0)) + dx; + v3[1] = cone->lo + dy; + v3[2] = cone->c2 + cone->radiuslo * cos(RADINC * (i + 1.0)) + dz; + v4[0] = sin(RADINC * i); + v4[1] = 0.0; + v4[2] = cos(RADINC * i); + v5[0] = sin(RADINC * (i + 1.0)); + v5[1] = 0.0; + v5[2] = cos(RADINC * (i + 1.0)); + + utils::print(fp, + "draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} " + "{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", + v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], 0.0, 1.0, + 0.0, v4[0], v4[1], v4[2], v5[0], v5[1], v5[2]); + } + + } else if (cone->axis == 'z') { + // set tip coordinate + v1[0] = cone->c1 + dx; + v1[1] = cone->c2 + dy; + v1[2] = cone->hi + dz; + + // loop around radius + for (int i = 0; i < RESOLUTION; ++i) { + v2[0] = cone->c1 + cone->radiuslo * sin(RADINC * i) + dx; + v2[1] = cone->c2 + cone->radiuslo * cos(RADINC * i) + dy; + v2[2] = cone->lo + dz; + v3[0] = cone->c1 + cone->radiuslo * sin(RADINC * (i + 1.0)) + dx; + v3[1] = cone->c2 + cone->radiuslo * cos(RADINC * (i + 1.0)) + dy; + v3[2] = cone->lo + dz; + v4[0] = sin(RADINC * i); + v4[1] = cos(RADINC * i); + v4[2] = 0.0; + v5[0] = sin(RADINC * (i + 1.0)); + v5[1] = cos(RADINC * (i + 1.0)); + v5[2] = 0.0; + utils::print(fp, + "draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} " + "{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", + v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], 0.0, 0.0, + 1.0, v4[0], v4[1], v4[2], v5[0], v5[1], v5[2]); + } + } + + // truncated cone + } else if (!cone->open_faces[2]) { + double v1[3], v2[3], v3[0], v4[3], v5[3], v6[3], v7[3], v8[3]; + + if (cone->axis == 'x') { + + // loop around radii + for (int i = 0; i < RESOLUTION; ++i) { + v1[0] = cone->hi + dx; + v1[1] = cone->c1 + cone->radiushi * sin(RADINC * (i - 0.5)) + dy; + v1[2] = cone->c2 + cone->radiushi * cos(RADINC * (i - 0.5)) + dz; + v2[0] = cone->lo + dx; + v2[1] = cone->c1 + cone->radiuslo * sin(RADINC * i) + dy; + v2[2] = cone->c2 + cone->radiuslo * cos(RADINC * i) + dz; + v3[0] = cone->hi + dx; + v3[1] = cone->c1 + cone->radiushi * sin(RADINC * (i + 0.5)) + dy; + v3[2] = cone->c2 + cone->radiushi * cos(RADINC * (i + 0.5)) + dz; + v4[0] = cone->lo + dx; + v4[1] = cone->c1 + cone->radiuslo * sin(RADINC * (i + 1.0)) + dy; + v4[2] = cone->c2 + cone->radiuslo * cos(RADINC * (i + 1.0)) + dz; + v5[0] = 0.0; + v5[1] = sin(RADINC * (i - 0.5)); + v5[2] = cos(RADINC * (i - 0.5)); + v6[0] = 0.0; + v6[1] = sin(RADINC * i); + v6[2] = cos(RADINC * i); + v7[0] = 0.0; + v7[1] = sin(RADINC * (i + 0.5)); + v7[2] = cos(RADINC * (i + 0.5)); + v8[0] = 0.0; + v8[1] = sin(RADINC * (i + 1.0)); + v8[2] = cos(RADINC * (i + 1.0)); + + utils::print(fp, + "draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} " + "{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", + v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], v5[0], + v5[1], v5[2], v6[0], v6[1], v6[2], v7[0], v7[1], v7[2]); + utils::print(fp, + "draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} " + "{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", + v2[0], v2[1], v2[2], v4[0], v4[1], v4[2], v3[0], v3[1], v3[2], v6[0], + v6[1], v6[2], v8[0], v8[1], v8[2], v7[0], v7[1], v7[2]); + } + + } else if (cone->axis == 'y') { + + // loop around radii + for (int i = 0; i < RESOLUTION; ++i) { + v1[0] = cone->c1 + cone->radiushi * sin(RADINC * (i - 0.5)) + dx; + v1[1] = cone->hi + dy; + v1[2] = cone->c2 + cone->radiushi * cos(RADINC * (i - 0.5)) + dz; + v2[0] = cone->c1 + cone->radiuslo * sin(RADINC * i) + dx; + v2[1] = cone->lo + dy; + v2[2] = cone->c2 + cone->radiuslo * cos(RADINC * i) + dz; + v3[0] = cone->c1 + cone->radiushi * sin(RADINC * (i + 0.5)) + dx; + v3[1] = cone->hi + dy; + v3[2] = cone->c2 + cone->radiushi * cos(RADINC * (i + 0.5)) + dz; + v4[0] = cone->c1 + cone->radiuslo * sin(RADINC * (i + 1.0)) + dx; + v4[1] = cone->lo + dy; + v4[2] = cone->c2 + cone->radiuslo * cos(RADINC * (i + 1.0)) + dz; + v5[0] = sin(RADINC * (i - 0.5)); + v5[1] = 0.0; + v5[2] = cos(RADINC * (i - 0.5)); + v6[0] = sin(RADINC * i); + v6[1] = 0.0; + v6[2] = cos(RADINC * i); + v7[0] = sin(RADINC * (i + 0.5)); + v7[1] = 0.0; + v7[2] = cos(RADINC * (i + 0.5)); + v8[0] = sin(RADINC * (i + 1.0)); + v8[1] = 0.0; + v8[2] = cos(RADINC * (i + 1.0)); + + utils::print(fp, + "draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} " + "{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", + v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], v5[0], + v5[1], v5[2], v6[0], v6[1], v6[2], v7[0], v7[1], v7[2]); + utils::print(fp, + "draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} " + "{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", + v2[0], v2[1], v2[2], v4[0], v4[1], v4[2], v3[0], v3[1], v3[2], v6[0], + v6[1], v6[2], v8[0], v8[1], v8[2], v7[0], v7[1], v7[2]); + } + + } else if (cone->axis == 'z') { + + // loop around radii + for (int i = 0; i < RESOLUTION; ++i) { + v1[0] = cone->c1 + cone->radiushi * sin(RADINC * (i - 0.5)) + dx; + v1[1] = cone->c2 + cone->radiushi * cos(RADINC * (i - 0.5)) + dy; + v1[2] = cone->hi + dz; + v2[0] = cone->c1 + cone->radiuslo * sin(RADINC * i) + dx; + v2[1] = cone->c2 + cone->radiuslo * cos(RADINC * i) + dy; + v2[2] = cone->lo + dz; + v3[0] = cone->c1 + cone->radiushi * sin(RADINC * (i + 0.5)) + dx; + v3[1] = cone->c2 + cone->radiushi * cos(RADINC * (i + 0.5)) + dy; + v3[2] = cone->hi + dz; + v4[0] = cone->c1 + cone->radiuslo * sin(RADINC * (i + 1.0)) + dx; + v4[1] = cone->c2 + cone->radiuslo * cos(RADINC * (i + 1.0)) + dy; + v4[2] = cone->lo + dz; + v5[0] = sin(RADINC * (i - 0.5)); + v5[1] = cos(RADINC * (i - 0.5)); + v5[2] = 0.0; + v6[0] = sin(RADINC * i); + v6[1] = cos(RADINC * i); + v6[2] = 0.0; + v7[0] = sin(RADINC * (i + 0.5)); + v7[1] = cos(RADINC * (i + 0.5)); + v7[2] = 0.0; + v8[0] = sin(RADINC * (i + 1.0)); + v8[1] = cos(RADINC * (i + 1.0)); + v8[2] = 0.0; + + utils::print(fp, + "draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} " + "{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", + v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], v5[0], + v5[1], v5[2], v6[0], v6[1], v6[2], v7[0], v7[1], v7[2]); + utils::print(fp, + "draw trinorm {{{} {} {}}} {{{} {} {}}} {{{} {} {}}} " + "{{{} {} {}}} {{{} {} {}}} {{{} {} {}}}\n", + v2[0], v2[1], v2[2], v4[0], v4[1], v4[2], v3[0], v3[1], v3[2], v6[0], + v6[1], v6[2], v8[0], v8[1], v8[2], v7[0], v7[1], v7[2]); + } + } + } + } + + // draw lids + if ((cone->radiuslo > SMALL) && !cone->open_faces[0]) { + double lid = cone->lo; + if (cone->axis == 'x') { + lid += dx; + utils::print(fp, + "draw cylinder {{{0} {2} {3}}} {{{1:.15} {2} {3}}} radius {4} " + "resolution {5} filled yes\n", + lid, lid + DELTA, cone->c1 + dy, cone->c2 + dz, cone->radiuslo, RESOLUTION); + } else if (cone->axis == 'y') { + lid += dy; + utils::print(fp, + "draw cylinder {{{2} {0} {3}}} {{{2} {1:.15} {3}}} radius {4} " + "resolution {5} filled yes\n", + lid, lid + DELTA, cone->c1 + dx, cone->c2 + dz, cone->radiuslo, RESOLUTION); + } else if (cone->axis == 'z') { + lid += dz; + utils::print(fp, + "draw cylinder {{{2} {3} {0}}} {{{2} {3} {1:.15}}} radius {4} " + "resolution {5} filled yes\n", + lid, lid + DELTA, cone->c1 + dx, cone->c2 + dy, cone->radiuslo, RESOLUTION); + } + } + if ((cone->radiushi > SMALL) && !cone->open_faces[1]) { + double lid = cone->hi; + if (cone->axis == 'x') { + lid += dx; + utils::print(fp, + "draw cylinder {{{0} {2} {3}}} {{{1:.15} {2} {3}}} radius {4} " + "resolution {5} filled yes\n", + lid, lid + DELTA, cone->c1 + dy, cone->c2 + dz, cone->radiushi, RESOLUTION); + } else if (cone->axis == 'y') { + lid += dy; + utils::print(fp, + "draw cylinder {{{2} {0} {3}}} {{{2} {1:.15} {3}}} radius {4} " + "resolution {5} filled yes\n", + lid, lid + DELTA, cone->c1 + dx, cone->c2 + dz, cone->radiushi, RESOLUTION); + } else if (cone->axis == 'z') { + lid += dz; + utils::print(fp, + "draw cylinder {{{2} {3} {0}}} {{{2} {3} {1:.15}}} radius {4} " + "resolution {5} filled yes\n", + lid, lid + DELTA, cone->c1 + dx, cone->c2 + dy, cone->radiushi, RESOLUTION); + } } } From 1d362a762729b52a18b1324ab72172620700f410 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 12 Feb 2025 16:31:14 -0500 Subject: [PATCH 24/30] must call region->prematch() before creating graphics to update variables --- src/EXTRA-COMMAND/region2vmd.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/EXTRA-COMMAND/region2vmd.cpp b/src/EXTRA-COMMAND/region2vmd.cpp index 3e845651af..469c01da97 100644 --- a/src/EXTRA-COMMAND/region2vmd.cpp +++ b/src/EXTRA-COMMAND/region2vmd.cpp @@ -266,6 +266,9 @@ void Region2VMD::write_region(FILE *fp, Region *region) return; } + // update internal variables + region->prematch(); + // compute position offset for moving regions double dx = 0.0; From 2e398bd17cbf1658a6652d6f9bfc02776f02a94c Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 12 Feb 2025 16:31:51 -0500 Subject: [PATCH 25/30] improve error messages --- src/region.cpp | 60 ++++++++++++++++++++++++++++++++------------- src/region_cone.cpp | 9 ++++--- 2 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/region.cpp b/src/region.cpp index 2d2c6513c9..1615ad5952 100644 --- a/src/region.cpp +++ b/src/region.cpp @@ -65,27 +65,39 @@ void Region::init() { if (xstr) { xvar = input->variable->find(xstr); - if (xvar < 0) error->all(FLERR, "Variable {} for region does not exist", xstr); + if (xvar < 0) + error->all(FLERR, Error::NOLASTLINE, "Variable {} for region {} {} does not exist", xstr, + style, id); if (!input->variable->equalstyle(xvar)) - error->all(FLERR, "Variable {} for region is invalid style", xstr); + error->all(FLERR, Error::NOLASTLINE, "Variable {} for region {} {} is invalid style", xstr, + style, id); } if (ystr) { yvar = input->variable->find(ystr); - if (yvar < 0) error->all(FLERR, "Variable {} for region does not exist", ystr); + if (yvar < 0) + error->all(FLERR, Error::NOLASTLINE, "Variable {} for region {} {} does not exist", ystr, + style, id); if (!input->variable->equalstyle(yvar)) - error->all(FLERR, "Variable {} for region is not equal style", ystr); + error->all(FLERR, Error::NOLASTLINE, "Variable {} for region {} {} is not equal style", ystr, + style, id); } if (zstr) { zvar = input->variable->find(zstr); - if (zvar < 0) error->all(FLERR, "Variable {} for region does not exist", zstr); + if (zvar < 0) + error->all(FLERR, Error::NOLASTLINE, "Variable {} for region {} {} does not exist", zstr, + style, id); if (!input->variable->equalstyle(zvar)) - error->all(FLERR, "Variable {} for region is not equal style", zstr); + error->all(FLERR, Error::NOLASTLINE, "Variable {} for region {} {} is not equal style", zstr, + style, id); } if (tstr) { tvar = input->variable->find(tstr); - if (tvar < 0) error->all(FLERR, "Variable {} for region does not exist", tstr); + if (tvar < 0) + error->all(FLERR, Error::NOLASTLINE, "Variable {} for region {} {} does not exist", tstr, + style, id); if (!input->variable->equalstyle(tvar)) - error->all(FLERR, "Variable {} for region is not equal style", tstr); + error->all(FLERR, Error::NOLASTLINE, "Variable {} for region {} {} is not equal style", tstr, + style, id); } vel_timestep = -1; } @@ -303,6 +315,16 @@ void Region::options(int narg, char **arg) { if (narg < 0) utils::missing_cmd_args(FLERR, "region", error); + int offset = -20; + if (input && input->arg && arg) { + for (int i = 0; i < input->narg; ++i) { + if (arg[0] == input->arg[i]) { + offset = i; + break; + } + } + } + // option defaults interior = 1; @@ -321,7 +343,7 @@ void Region::options(int narg, char **arg) else if (strcmp(arg[iarg + 1], "lattice") == 0) scaleflag = 1; else - error->all(FLERR, "Illegal region units: {}", arg[iarg + 1]); + error->all(FLERR, iarg + 1 + offset, "Unknown region units: {}", arg[iarg + 1]); iarg += 2; } else if (strcmp(arg[iarg], "side") == 0) { if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "region side", error); @@ -330,24 +352,27 @@ void Region::options(int narg, char **arg) else if (strcmp(arg[iarg + 1], "out") == 0) interior = 0; else - error->all(FLERR, "Illegal region side: {}", arg[iarg + 1]); + error->all(FLERR, iarg + 1 + offset, "Unknown region side setting: {}", arg[iarg + 1]); iarg += 2; } else if (strcmp(arg[iarg], "move") == 0) { if (iarg + 4 > narg) utils::missing_cmd_args(FLERR, "region move", error); if (strcmp(arg[iarg + 1], "NULL") != 0) { if (strstr(arg[iarg + 1], "v_") != arg[iarg + 1]) - error->all(FLERR, "Illegal region move x displacement variable: {}", arg[iarg + 1]); + error->all(FLERR, iarg + 1 + offset, "Illegal region move x displacement variable: {}", + arg[iarg + 1]); xstr = utils::strdup(&arg[iarg + 1][2]); } if (strcmp(arg[iarg + 2], "NULL") != 0) { if (strstr(arg[iarg + 2], "v_") != arg[iarg + 2]) - error->all(FLERR, "Illegal region move y displacement variable: {}", arg[iarg + 2]); + error->all(FLERR, iarg + 2 + offset, "Illegal region move y displacement variable: {}", + arg[iarg + 2]); ystr = utils::strdup(&arg[iarg + 2][2]); } if (strcmp(arg[iarg + 3], "NULL") != 0) { if (strstr(arg[iarg + 3], "v_") != arg[iarg + 3]) - error->all(FLERR, "Illegal region move z displacement variable: {}", arg[iarg + 3]); + error->all(FLERR, iarg + 3 + offset, "Illegal region move z displacement variable: {}", + arg[iarg + 3]); zstr = utils::strdup(&arg[iarg + 3][2]); } moveflag = 1; @@ -369,19 +394,20 @@ void Region::options(int narg, char **arg) } else if (strcmp(arg[iarg], "open") == 0) { if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "region open", error); int iface = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); - if (iface < 1 || iface > 6) error->all(FLERR, "Illegal region open face index: {}", iface); + if (iface < 1 || iface > 6) + error->all(FLERR, iarg + 1 + offset, "Illegal region open face index: {}", iface); // additional checks on valid face index are done by region classes open_faces[iface - 1] = 1; openflag = 1; iarg += 2; } else - error->all(FLERR, iarg, "Unknown region command argument: {}", arg[iarg]); + error->all(FLERR, iarg + offset, "Unknown region command argument: {}", arg[iarg]); } // error check if ((moveflag || rotateflag) && (strcmp(style, "union") == 0 || strcmp(style, "intersect") == 0)) - error->all(FLERR, "Region union or intersect cannot be dynamic"); + error->all(FLERR, 1, "Region union or intersect cannot be dynamic"); // setup scaling @@ -402,7 +428,7 @@ void Region::options(int narg, char **arg) if (rotateflag) { double len = sqrt(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]); - if (len == 0.0) error->all(FLERR, "Region cannot have 0 length rotation vector"); + if (len == 0.0) error->all(FLERR, Error::NOPOINTER, "Region cannot have 0 length rotation vector"); runit[0] = axis[0] / len; runit[1] = axis[1] / len; runit[2] = axis[2] / len; diff --git a/src/region_cone.cpp b/src/region_cone.cpp index 401ed53735..30f29e3934 100644 --- a/src/region_cone.cpp +++ b/src/region_cone.cpp @@ -41,10 +41,11 @@ RegCone::RegCone(LAMMPS *lmp, int narg, char **arg) : if (openflag) for (int i = 3; i < 6; i++) - if (open_faces[i]) error->all(FLERR, "Illegal region cone open face: {}", i + 1); + if (open_faces[i]) + error->all(FLERR, Error::NOPOINTER, "Illegal region cone open face: {}", i + 1); if (strcmp(arg[2], "x") != 0 && strcmp(arg[2], "y") != 0 && strcmp(arg[2], "z") != 0) - error->all(FLERR, "Illegal region cone axis: {}", arg[2]); + error->all(FLERR, 2, "Illegal region cone axis: {}", arg[2]); axis = arg[2][0]; if (axis == 'x') { @@ -256,8 +257,8 @@ RegCone::RegCone(LAMMPS *lmp, int narg, char **arg) : // error check - if (radiuslo < 0.0) error->all(FLERR, "Illegal radius in region cone command"); - if (radiushi < 0.0) error->all(FLERR, "Illegal radius in region cone command"); + if (radiuslo < 0.0) error->all(FLERR, 5, "Illegal lower radius in region cone command"); + if (radiushi < 0.0) error->all(FLERR, 6, "Illegal upper radius in region cone command"); if (radiuslo == 0.0 && radiushi == 0.0) error->all(FLERR, "Illegal radius in region cone command"); if (hi <= lo) error->all(FLERR, "Illegal cone length in region cone command"); From adfe84913f3b0e4826a280b9401d86b486d8aa7e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 12 Feb 2025 17:58:34 -0500 Subject: [PATCH 26/30] fix bogus array size bug --- src/EXTRA-COMMAND/region2vmd.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/EXTRA-COMMAND/region2vmd.cpp b/src/EXTRA-COMMAND/region2vmd.cpp index 469c01da97..3c357b68f6 100644 --- a/src/EXTRA-COMMAND/region2vmd.cpp +++ b/src/EXTRA-COMMAND/region2vmd.cpp @@ -324,7 +324,7 @@ void Region2VMD::write_region(FILE *fp, Region *region) // lo end has a tip } else if (cone->radiuslo < SMALL) { - double v1[3], v2[3], v3[0], v4[3], v5[3]; + double v1[3], v2[3], v3[3], v4[3], v5[3]; if (cone->axis == 'x') { // set tip coordinate @@ -412,7 +412,7 @@ void Region2VMD::write_region(FILE *fp, Region *region) // hi end has a tip } else if (cone->radiushi < SMALL) { - double v1[3], v2[3], v3[0], v4[3], v5[3]; + double v1[3], v2[3], v3[3], v4[3], v5[3]; if (cone->axis == 'x') { // set tip coordinate @@ -500,7 +500,7 @@ void Region2VMD::write_region(FILE *fp, Region *region) // truncated cone } else if (!cone->open_faces[2]) { - double v1[3], v2[3], v3[0], v4[3], v5[3], v6[3], v7[3], v8[3]; + double v1[3], v2[3], v3[3], v4[3], v5[3], v6[3], v7[3], v8[3]; if (cone->axis == 'x') { From 926f336962bfdad1364aac43e0e2dc133382db37 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 12 Feb 2025 21:46:37 -0500 Subject: [PATCH 27/30] add some note about build prerequisites --- doc/src/Build.rst | 23 +++++++++++++++++++++++ doc/src/Build_cmake.rst | 6 +++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/doc/src/Build.rst b/doc/src/Build.rst index 7ca8cd428e..ff09ee5678 100644 --- a/doc/src/Build.rst +++ b/doc/src/Build.rst @@ -14,6 +14,29 @@ As an alternative, you can download a package with pre-built executables or automated build trees, as described in the :doc:`Install ` section of the manual. +Prerequisites +------------- + +Which software you need to compile and use LAMMPS strongly depends on +which :doc:`features and settings ` and which +:doc:`optional packages ` you are trying to include. +Common to all is that you need a C++ and C compiler, where the C++ +compiler has to support at least the C++11 standard (note that some +compilers require command-line flag to activate C++11 support). +Furthermore, if you are building with CMake, you need at least CMake +version 3.20 and a compatible build tool (make or ninja-build); if you +are building the the legacy GNU make based build system you need GNU +make (other make variants are not going to work since the build system +uses features unique to GNU make) and a Unix-like build environment with +a Bourne shell, and shell tools like "sed", "grep", "touch", "test", +"tr", "cp", "mv", "rm", "ln", "diff" and so on. Parts of LAMMPS +interface with or use Python version 3.6 or later. + +The LAMMPS developers aim to keep LAMMPS very portable and usable - +at least in parts - on most operating systems commonly used for +running MD simulations. Please see the :doc:`section on portablility +` for more details. + .. toctree:: :maxdepth: 1 diff --git a/doc/src/Build_cmake.rst b/doc/src/Build_cmake.rst index 56b8e450f3..a38b42b4f4 100644 --- a/doc/src/Build_cmake.rst +++ b/doc/src/Build_cmake.rst @@ -52,9 +52,9 @@ software or for people that want to modify or extend LAMMPS. compilers can be configured and built concurrently from the same source tree. - Simplified packaging of LAMMPS for Linux distributions, environment - modules, or automated build tools like `Homebrew `_. -- Integration of automated unit and regression testing (the LAMMPS side - of this is still under active development). + modules, or automated build tools like `Spack `_ + or `Homebrew `_. +- Integration of automated unit and regression testing. .. _cmake_build: From 63d89155623f5752347ac1271b58b897bad3fe28 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 12 Feb 2025 21:47:02 -0500 Subject: [PATCH 28/30] make use of SafeFilePtr --- src/create_atoms.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/create_atoms.cpp b/src/create_atoms.cpp index 1a8318e315..dc00e2e1d1 100644 --- a/src/create_atoms.cpp +++ b/src/create_atoms.cpp @@ -34,6 +34,7 @@ #include "random_mars.h" #include "random_park.h" #include "region.h" +#include "safe_pointers.h" #include "special.h" #include "text_file_reader.h" #include "variable.h" @@ -1082,8 +1083,9 @@ void CreateAtoms::add_mesh(const char *filename) molid = maxmol + 1; } - FILE *fp = fopen(filename, "rb"); - if (fp == nullptr) error->one(FLERR, "Cannot open file {}: {}", filename, utils::getsyserror()); + SafeFilePtr fp = fopen(filename, "rb"); + if (fp == nullptr) + error->one(FLERR, "Cannot open STL mesh file {}: {}", filename, utils::getsyserror()); // first try reading the file in ASCII format @@ -1184,7 +1186,7 @@ void CreateAtoms::add_mesh(const char *filename) } } } else { - error->all(FLERR, "Error reading triangles from file {}: {}", filename, e.what()); + error->all(FLERR, "Error reading triangles from STL mesh file {}: {}", filename, e.what()); } } @@ -1195,7 +1197,6 @@ void CreateAtoms::add_mesh(const char *filename) utils::logmesg(lmp, " read {} triangles with {:.2f} atoms per triangle added in {} mode\n", ntriangle, ratio, mesh_name[mesh_style]); } - if (fp) fclose(fp); } /* ---------------------------------------------------------------------- From ea2eb930c5d9e75c90f25417a74d8801748dbe02 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 12 Feb 2025 21:47:11 -0500 Subject: [PATCH 29/30] clarify --- src/text_file_reader.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/text_file_reader.h b/src/text_file_reader.h index cc62471f66..f22885963c 100644 --- a/src/text_file_reader.h +++ b/src/text_file_reader.h @@ -26,6 +26,7 @@ namespace LAMMPS_NS { class TextFileReader { + private: std::string filetype; bool closefp; int bufsize; From 583f7b70b44c7c716caac4e415206e226933abd3 Mon Sep 17 00:00:00 2001 From: Stan Moore Date: Thu, 13 Feb 2025 12:41:16 -0700 Subject: [PATCH 30/30] Fix rare bug in KOKKOS, manifest when load balancing on GPUs and exchange comm is on host --- src/KOKKOS/comm_kokkos.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/KOKKOS/comm_kokkos.cpp b/src/KOKKOS/comm_kokkos.cpp index 5bf7464ac0..22800a1376 100644 --- a/src/KOKKOS/comm_kokkos.cpp +++ b/src/KOKKOS/comm_kokkos.cpp @@ -793,7 +793,10 @@ void CommKokkos::exchange() } atomKK->sync(Host,ALL_MASK); + int prev_auto_sync = lmp->kokkos->auto_sync; + lmp->kokkos->auto_sync = 1; CommBrick::exchange(); + lmp->kokkos->auto_sync = prev_auto_sync; atomKK->modified(Host,ALL_MASK); }