From 6ac481409a54d7d12853cda5eb0a471ec6b57488 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 1 Dec 2020 19:04:43 -0500 Subject: [PATCH 01/44] remove temporary flag for using the new pip resolver which is now the default --- doc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Makefile b/doc/Makefile index 59700f03aa..041c7a372a 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -229,7 +229,7 @@ $(VENV): $(VIRTUALENV) -p $(PYTHON) $(VENV); \ . $(VENV)/bin/activate; \ pip install --upgrade pip; \ - pip install --use-feature=2020-resolver -r $(BUILDDIR)/utils/requirements.txt; \ + pip install -r $(BUILDDIR)/utils/requirements.txt; \ deactivate;\ ) From 63d8182ff375ecfee448a7f68d5580445a669bbc Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 1 Dec 2020 19:06:09 -0500 Subject: [PATCH 02/44] fix spelling --- doc/src/balance.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/balance.rst b/doc/src/balance.rst index 7af8a86e9a..07ea82eeba 100644 --- a/doc/src/balance.rst +++ b/doc/src/balance.rst @@ -288,7 +288,7 @@ adjacent planes are closer together than the neighbor skin distance (as specified by the :doc`neigh_modify ` command), then the plane positions are shifted to separate them by at least this amount. This is to prevent particles being lost when dynamics are run -with processor subdomains that are too narrow in one or more +with processor sub-domains that are too narrow in one or more dimensions. Once the re-balancing is complete and final processor sub-domains From 71827f009950296ee56f9c0024de70eef6ddde31 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 1 Dec 2020 19:06:54 -0500 Subject: [PATCH 03/44] update pair meam/spline docs to reflect limitations of the implementation this closes #2500 --- doc/src/pair_meam_spline.rst | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/doc/src/pair_meam_spline.rst b/doc/src/pair_meam_spline.rst index b5c94385fa..6bedb9b4fb 100644 --- a/doc/src/pair_meam_spline.rst +++ b/doc/src/pair_meam_spline.rst @@ -20,7 +20,7 @@ Examples pair_style meam/spline pair_coeff * * Ti.meam.spline Ti - pair_coeff * * Ti.meam.spline Ti Ti Ti + pair_coeff * * Ti.meam.spline Ti O Description """"""""""" @@ -84,23 +84,22 @@ where N is the number of LAMMPS atom types: See the :doc:`pair_coeff ` doc page for alternate ways to specify the path for the potential file. -As an example, imagine the Ti.meam.spline file has values for Ti (old style). If -your LAMMPS simulation has 3 atoms types and they are all to be -treated with this potentials, you would use the following pair_coeff -command: +As an example, imagine the Ti.meam.spline file has values for Ti (old style). +In that case your LAMMPS simulation may only have one atom type which has +to be mapped to the Ti element as follows: .. code-block:: LAMMPS - pair_coeff * * Ti.meam.spline Ti Ti Ti + pair_coeff * * Ti.meam.spline Ti -The first 2 arguments must be \* \* so as to span all LAMMPS atom types. -The three Ti arguments map LAMMPS atom types 1,2,3 to the Ti element -in the potential file. If a mapping value is specified as NULL, the -mapping is not performed. This can be used when a *meam/spline* -potential is used as part of the *hybrid* pair style. The NULL values -are placeholders for atom types that will be used with other -potentials. The old-style potential maps any non-NULL species named -on the command line to that single type. +The first 2 arguments must be \* \* and there may be only one element +following or NULL. Systems where there would be multiple atom types +assigned to the same element are **not** supported by this pair style +due to limitations in its implementation. If a mapping value is +specified as NULL, the mapping is not performed. This can be used when +a *meam/spline* potential is used as part of the *hybrid* pair style. +The NULL values are placeholders for atom types that will be used with +other potentials. An example with a two component spline (new style) is TiO.meam.spline, where the command @@ -143,6 +142,8 @@ Restrictions This pair style requires the :doc:`newton ` setting to be "on" for pair interactions. +This pair style does not support mapping multiple atom types to the same element. + This pair style is only enabled if LAMMPS was built with the USER-MISC package. See the :doc:`Build package ` doc page for more info. From 90f00c01a4083254f1390568b2f3736eeb29adca Mon Sep 17 00:00:00 2001 From: Oliver Henrich Date: Thu, 3 Dec 2020 12:57:55 +0000 Subject: [PATCH 04/44] Introduced ellipsoid pointer in quaternion data access --- src/USER-CGDNA/bond_oxdna_fene.cpp | 5 +++-- src/USER-CGDNA/pair_oxdna2_coaxstk.cpp | 5 +++-- src/USER-CGDNA/pair_oxdna2_dh.cpp | 5 +++-- src/USER-CGDNA/pair_oxdna_coaxstk.cpp | 5 +++-- src/USER-CGDNA/pair_oxdna_excv.cpp | 5 +++-- src/USER-CGDNA/pair_oxdna_hbond.cpp | 5 +++-- src/USER-CGDNA/pair_oxdna_stk.cpp | 5 +++-- src/USER-CGDNA/pair_oxdna_xstk.cpp | 5 +++-- src/USER-CGDNA/pair_oxrna2_stk.cpp | 5 +++-- src/USER-CGDNA/pair_oxrna2_xstk.cpp | 5 +++-- 10 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/USER-CGDNA/bond_oxdna_fene.cpp b/src/USER-CGDNA/bond_oxdna_fene.cpp index 522ea2a745..abff3804b8 100644 --- a/src/USER-CGDNA/bond_oxdna_fene.cpp +++ b/src/USER-CGDNA/bond_oxdna_fene.cpp @@ -173,6 +173,7 @@ void BondOxdnaFene::compute(int eflag, int vflag) AtomVecEllipsoid *avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); AtomVecEllipsoid::Bonus *bonus = avec->bonus; + int *ellipsoid = atom->ellipsoid; int **bondlist = neighbor->bondlist; int nbondlist = neighbor->nbondlist; @@ -190,9 +191,9 @@ void BondOxdnaFene::compute(int eflag, int vflag) b = bondlist[in][0]; type = bondlist[in][2]; - qa=bonus[a].quat; + qa=bonus[ellipsoid[a]].quat; MathExtra::q_to_exyz(qa,ax,ay,az); - qb=bonus[b].quat; + qb=bonus[ellipsoid[b]].quat; MathExtra::q_to_exyz(qb,bx,by,bz); // vector COM-backbone site a and b diff --git a/src/USER-CGDNA/pair_oxdna2_coaxstk.cpp b/src/USER-CGDNA/pair_oxdna2_coaxstk.cpp index 273060612d..f0b3386478 100644 --- a/src/USER-CGDNA/pair_oxdna2_coaxstk.cpp +++ b/src/USER-CGDNA/pair_oxdna2_coaxstk.cpp @@ -133,6 +133,7 @@ void PairOxdna2Coaxstk::compute(int eflag, int vflag) AtomVecEllipsoid *avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); AtomVecEllipsoid::Bonus *bonus = avec->bonus; + int *ellipsoid = atom->ellipsoid; int a,b,ia,ib,anum,bnum,atype,btype; @@ -154,7 +155,7 @@ void PairOxdna2Coaxstk::compute(int eflag, int vflag) a = alist[ia]; atype = type[a]; - qa=bonus[a].quat; + qa=bonus[ellipsoid[a]].quat; MathExtra::q_to_exyz(qa,ax,ay,az); // vector COM a - stacking site a @@ -178,7 +179,7 @@ void PairOxdna2Coaxstk::compute(int eflag, int vflag) btype = type[b]; - qb=bonus[b].quat; + qb=bonus[ellipsoid[b]].quat; MathExtra::q_to_exyz(qb,bx,by,bz); // vector COM b - stacking site b diff --git a/src/USER-CGDNA/pair_oxdna2_dh.cpp b/src/USER-CGDNA/pair_oxdna2_dh.cpp index f210fe3b65..d877e0bf9a 100644 --- a/src/USER-CGDNA/pair_oxdna2_dh.cpp +++ b/src/USER-CGDNA/pair_oxdna2_dh.cpp @@ -102,6 +102,7 @@ void PairOxdna2Dh::compute(int eflag, int vflag) AtomVecEllipsoid *avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); AtomVecEllipsoid::Bonus *bonus = avec->bonus; + int *ellipsoid = atom->ellipsoid; int a,b,ia,ib,anum,bnum,atype,btype; @@ -120,7 +121,7 @@ void PairOxdna2Dh::compute(int eflag, int vflag) a = alist[ia]; atype = type[a]; - qa=bonus[a].quat; + qa=bonus[ellipsoid[a]].quat; MathExtra::q_to_exyz(qa,ax,ay,az); // vector COM-backbone site a @@ -140,7 +141,7 @@ void PairOxdna2Dh::compute(int eflag, int vflag) b &= NEIGHMASK; btype = type[b]; - qb=bonus[b].quat; + qb=bonus[ellipsoid[b]].quat; MathExtra::q_to_exyz(qb,bx,by,bz); // vector COM-backbone site b diff --git a/src/USER-CGDNA/pair_oxdna_coaxstk.cpp b/src/USER-CGDNA/pair_oxdna_coaxstk.cpp index 0a4a4f8ed8..c062bbfa99 100644 --- a/src/USER-CGDNA/pair_oxdna_coaxstk.cpp +++ b/src/USER-CGDNA/pair_oxdna_coaxstk.cpp @@ -145,6 +145,7 @@ void PairOxdnaCoaxstk::compute(int eflag, int vflag) AtomVecEllipsoid *avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); AtomVecEllipsoid::Bonus *bonus = avec->bonus; + int *ellipsoid = atom->ellipsoid; int a,b,ia,ib,anum,bnum,atype,btype; @@ -166,7 +167,7 @@ void PairOxdnaCoaxstk::compute(int eflag, int vflag) a = alist[ia]; atype = type[a]; - qa=bonus[a].quat; + qa=bonus[ellipsoid[a]].quat; MathExtra::q_to_exyz(qa,ax,ay,az); // vector COM a - stacking site a @@ -190,7 +191,7 @@ void PairOxdnaCoaxstk::compute(int eflag, int vflag) btype = type[b]; - qb=bonus[b].quat; + qb=bonus[ellipsoid[b]].quat; MathExtra::q_to_exyz(qb,bx,by,bz); // vector COM b - stacking site b diff --git a/src/USER-CGDNA/pair_oxdna_excv.cpp b/src/USER-CGDNA/pair_oxdna_excv.cpp index 0f5dc54354..e5f2a5cad5 100644 --- a/src/USER-CGDNA/pair_oxdna_excv.cpp +++ b/src/USER-CGDNA/pair_oxdna_excv.cpp @@ -134,6 +134,7 @@ void PairOxdnaExcv::compute(int eflag, int vflag) AtomVecEllipsoid *avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); AtomVecEllipsoid::Bonus *bonus = avec->bonus; + int *ellipsoid = atom->ellipsoid; int a,b,ia,ib,anum,bnum,atype,btype; @@ -152,7 +153,7 @@ void PairOxdnaExcv::compute(int eflag, int vflag) a = alist[ia]; atype = type[a]; - qa=bonus[a].quat; + qa=bonus[ellipsoid[a]].quat; MathExtra::q_to_exyz(qa,ax,ay,az); // vector COM - backbone and base site a @@ -177,7 +178,7 @@ void PairOxdnaExcv::compute(int eflag, int vflag) btype = type[b]; - qb=bonus[b].quat; + qb=bonus[ellipsoid[b]].quat; MathExtra::q_to_exyz(qb,bx,by,bz); // vector COM - backbone and base site b diff --git a/src/USER-CGDNA/pair_oxdna_hbond.cpp b/src/USER-CGDNA/pair_oxdna_hbond.cpp index 455c26f188..3e1d51ddf1 100644 --- a/src/USER-CGDNA/pair_oxdna_hbond.cpp +++ b/src/USER-CGDNA/pair_oxdna_hbond.cpp @@ -164,6 +164,7 @@ void PairOxdnaHbond::compute(int eflag, int vflag) AtomVecEllipsoid *avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); AtomVecEllipsoid::Bonus *bonus = avec->bonus; + int *ellipsoid = atom->ellipsoid; int a,b,ia,ib,anum,bnum,atype,btype; @@ -185,7 +186,7 @@ void PairOxdnaHbond::compute(int eflag, int vflag) a = alist[ia]; atype = type[a]; - qa=bonus[a].quat; + qa=bonus[ellipsoid[a]].quat; MathExtra::q_to_exyz(qa,ax,ay,az); ra_chb[0] = d_chb*ax[0]; @@ -203,7 +204,7 @@ void PairOxdnaHbond::compute(int eflag, int vflag) btype = type[b]; - qb=bonus[b].quat; + qb=bonus[ellipsoid[b]].quat; MathExtra::q_to_exyz(qb,bx,by,bz); rb_chb[0] = d_chb*bx[0]; diff --git a/src/USER-CGDNA/pair_oxdna_stk.cpp b/src/USER-CGDNA/pair_oxdna_stk.cpp index 1a84003493..6aed2d854c 100644 --- a/src/USER-CGDNA/pair_oxdna_stk.cpp +++ b/src/USER-CGDNA/pair_oxdna_stk.cpp @@ -245,6 +245,7 @@ void PairOxdnaStk::compute(int eflag, int vflag) AtomVecEllipsoid *avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); AtomVecEllipsoid::Bonus *bonus = avec->bonus; + int *ellipsoid = atom->ellipsoid; int a,b,in,atype,btype; @@ -262,9 +263,9 @@ void PairOxdnaStk::compute(int eflag, int vflag) a = bondlist[in][1]; b = bondlist[in][0]; - qa=bonus[a].quat; + qa=bonus[ellipsoid[a]].quat; MathExtra::q_to_exyz(qa,ax,ay,az); - qb=bonus[b].quat; + qb=bonus[ellipsoid[b]].quat; MathExtra::q_to_exyz(qb,bx,by,bz); // vector COM a - stacking site a diff --git a/src/USER-CGDNA/pair_oxdna_xstk.cpp b/src/USER-CGDNA/pair_oxdna_xstk.cpp index 76b67d0baa..c1b63ea2fa 100644 --- a/src/USER-CGDNA/pair_oxdna_xstk.cpp +++ b/src/USER-CGDNA/pair_oxdna_xstk.cpp @@ -142,6 +142,7 @@ void PairOxdnaXstk::compute(int eflag, int vflag) AtomVecEllipsoid *avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); AtomVecEllipsoid::Bonus *bonus = avec->bonus; + int *ellipsoid = atom->ellipsoid; int a,b,ia,ib,anum,bnum,atype,btype; @@ -163,7 +164,7 @@ void PairOxdnaXstk::compute(int eflag, int vflag) a = alist[ia]; atype = type[a]; - qa=bonus[a].quat; + qa=bonus[ellipsoid[a]].quat; MathExtra::q_to_exyz(qa,ax,ay,az); ra_chb[0] = d_chb*ax[0]; @@ -181,7 +182,7 @@ void PairOxdnaXstk::compute(int eflag, int vflag) btype = type[b]; - qb=bonus[b].quat; + qb=bonus[ellipsoid[b]].quat; MathExtra::q_to_exyz(qb,bx,by,bz); rb_chb[0] = d_chb*bx[0]; diff --git a/src/USER-CGDNA/pair_oxrna2_stk.cpp b/src/USER-CGDNA/pair_oxrna2_stk.cpp index fdd1f863f4..33480aa380 100644 --- a/src/USER-CGDNA/pair_oxrna2_stk.cpp +++ b/src/USER-CGDNA/pair_oxrna2_stk.cpp @@ -262,6 +262,7 @@ void PairOxrna2Stk::compute(int eflag, int vflag) AtomVecEllipsoid *avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); AtomVecEllipsoid::Bonus *bonus = avec->bonus; + int *ellipsoid = atom->ellipsoid; int a,b,in,atype,btype; @@ -279,9 +280,9 @@ void PairOxrna2Stk::compute(int eflag, int vflag) a = bondlist[in][1]; b = bondlist[in][0]; - qa=bonus[a].quat; + qa=bonus[ellipsoid[a]].quat; MathExtra::q_to_exyz(qa,ax,ay,az); - qb=bonus[b].quat; + qb=bonus[ellipsoid[b]].quat; MathExtra::q_to_exyz(qb,bx,by,bz); // vector COM a - 3'-stacking site a diff --git a/src/USER-CGDNA/pair_oxrna2_xstk.cpp b/src/USER-CGDNA/pair_oxrna2_xstk.cpp index 81b8c92780..c3b97bfa9c 100644 --- a/src/USER-CGDNA/pair_oxrna2_xstk.cpp +++ b/src/USER-CGDNA/pair_oxrna2_xstk.cpp @@ -135,6 +135,7 @@ void PairOxrna2Xstk::compute(int eflag, int vflag) AtomVecEllipsoid *avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); AtomVecEllipsoid::Bonus *bonus = avec->bonus; + int *ellipsoid = atom->ellipsoid; int a,b,ia,ib,anum,bnum,atype,btype; @@ -156,7 +157,7 @@ void PairOxrna2Xstk::compute(int eflag, int vflag) a = alist[ia]; atype = type[a]; - qa=bonus[a].quat; + qa=bonus[ellipsoid[a]].quat; MathExtra::q_to_exyz(qa,ax,ay,az); ra_chb[0] = d_chb*ax[0]; @@ -174,7 +175,7 @@ void PairOxrna2Xstk::compute(int eflag, int vflag) btype = type[b]; - qb=bonus[b].quat; + qb=bonus[ellipsoid[b]].quat; MathExtra::q_to_exyz(qb,bx,by,bz); rb_chb[0] = d_chb*bx[0]; From 36c2947de725d3e4fce6c961582010506959d445 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Dec 2020 00:31:50 -0500 Subject: [PATCH 05/44] silence compiler warnings --- src/COMPRESS/zstd_file_writer.cpp | 2 +- src/USER-MISC/angle_gaussian.cpp | 3 +-- src/USER-MISC/fix_electron_stopping_fit.cpp | 10 ++++----- src/USER-PLUMED/fix_plumed.cpp | 2 +- src/USER-REACTION/fix_bond_react.cpp | 24 +++++++++++---------- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/COMPRESS/zstd_file_writer.cpp b/src/COMPRESS/zstd_file_writer.cpp index e99dbf0181..2631faa4ad 100644 --- a/src/COMPRESS/zstd_file_writer.cpp +++ b/src/COMPRESS/zstd_file_writer.cpp @@ -79,7 +79,7 @@ size_t ZstdFileWriter::write(const void * buffer, size_t length) do { ZSTD_outBuffer output = { out_buffer, out_buffer_size, 0 }; - size_t const remaining = ZSTD_compressStream2(cctx, &output, &input, mode); + ZSTD_compressStream2(cctx, &output, &input, mode); fwrite(out_buffer, sizeof(char), output.pos, fp); } while(input.pos < input.size); diff --git a/src/USER-MISC/angle_gaussian.cpp b/src/USER-MISC/angle_gaussian.cpp index 640be38433..554b19cfb5 100644 --- a/src/USER-MISC/angle_gaussian.cpp +++ b/src/USER-MISC/angle_gaussian.cpp @@ -62,7 +62,7 @@ void AngleGaussian::compute(int eflag, int vflag) int i1,i2,i3,n,type; double delx1,dely1,delz1,delx2,dely2,delz2; double eangle,f1[3],f3[3]; - double dtheta,tk; + double dtheta; double rsq1,rsq2,r1,r2,c,s,a,a11,a12,a22; double prefactor, exponent, g_i, sum_g_i, sum_numerator; @@ -331,7 +331,6 @@ double AngleGaussian::single(int type, int i1, int i2, int i3) double theta = acos(c) ; double sum_g_i = 0.0; - double sum_numerator = 0.0; for (int i = 0; i < nterms[type]; i++) { double dtheta = theta - theta0[type][i]; double prefactor = (alpha[type][i]/(width[type][i]*sqrt(MY_PI2))); diff --git a/src/USER-MISC/fix_electron_stopping_fit.cpp b/src/USER-MISC/fix_electron_stopping_fit.cpp index e6fa0f2b9b..2d9034aaef 100644 --- a/src/USER-MISC/fix_electron_stopping_fit.cpp +++ b/src/USER-MISC/fix_electron_stopping_fit.cpp @@ -62,9 +62,9 @@ static const char cite_fix_electron_stopping_fit_c[] = // --------------------------------------------------------------------- FixElectronStoppingFit::FixElectronStoppingFit(LAMMPS *lmp, int narg, char **arg) : - Fix(lmp,narg,arg), energy_coh_in(nullptr), drag_fac_in_1(nullptr), - drag_fac_in_2(nullptr), drag_fac_1(nullptr), drag_fac_2(nullptr), - v_min_sq(nullptr), v_max_sq(nullptr) + Fix(lmp,narg,arg), energy_coh_in(nullptr), v_min_sq(nullptr), v_max_sq(nullptr), + drag_fac_in_1(nullptr), drag_fac_in_2(nullptr), + drag_fac_1(nullptr), drag_fac_2(nullptr) { if (lmp->citeme) lmp->citeme->add(cite_fix_electron_stopping_fit_c); @@ -151,7 +151,7 @@ void FixElectronStoppingFit::setup(int vflag) // --------------------------------------------------------------------- -void FixElectronStoppingFit::post_force(int vflag) +void FixElectronStoppingFit::post_force(int /*vflag*/) { double **v = atom->v; double **f = atom->f; @@ -192,7 +192,7 @@ void FixElectronStoppingFit::post_force(int vflag) // --------------------------------------------------------------------- -void FixElectronStoppingFit::post_force_respa(int vflag, int ilevel, int iloop) +void FixElectronStoppingFit::post_force_respa(int vflag, int ilevel, int /*iloop*/) { if (ilevel == nlevels_respa-1) post_force(vflag); }; diff --git a/src/USER-PLUMED/fix_plumed.cpp b/src/USER-PLUMED/fix_plumed.cpp index b1397b8eeb..ed7f05f2ae 100644 --- a/src/USER-PLUMED/fix_plumed.cpp +++ b/src/USER-PLUMED/fix_plumed.cpp @@ -76,7 +76,7 @@ FixPlumed::FixPlumed(LAMMPS *lmp, int narg, char **arg) : // Check API version - int api_version; + int api_version=0; p->cmd("getApiVersion",&api_version); if ((api_version < 5) || (api_version > 7)) error->all(FLERR,"Incompatible API version for PLUMED in fix plumed. " diff --git a/src/USER-REACTION/fix_bond_react.cpp b/src/USER-REACTION/fix_bond_react.cpp index 29a99db75f..efadec1b91 100644 --- a/src/USER-REACTION/fix_bond_react.cpp +++ b/src/USER-REACTION/fix_bond_react.cpp @@ -761,15 +761,15 @@ void FixBondReact::post_constructor() void FixBondReact::init() { - if (strstr(update->integrate_style,"respa")) + if (utils::strmatch(update->integrate_style,"^respa")) nlevels_respa = ((Respa *) update->integrate)->nlevels; - // check cutoff for iatomtype,jatomtype - for (int i = 0; i < nreacts; i++) { - if (closeneigh[i] == -1) // indicates will search for non-bonded bonding atoms - if (force->pair == nullptr || cutsq[i][1] > force->pair->cutsq[iatomtype[i]][jatomtype[i]]) - error->all(FLERR,"Bond/react: Fix bond/react cutoff is longer than pairwise cutoff"); - } + // check cutoff for iatomtype,jatomtype + for (int i = 0; i < nreacts; i++) { + if (closeneigh[i] == -1) // indicates will search for non-bonded bonding atoms + if (force->pair == nullptr || cutsq[i][1] > force->pair->cutsq[iatomtype[i]][jatomtype[i]]) + error->all(FLERR,"Bond/react: Fix bond/react cutoff is longer than pairwise cutoff"); + } // need a half neighbor list, built every Nevery steps int irequest = neighbor->request(this,instance_me); @@ -1068,10 +1068,11 @@ void FixBondReact::far_partner() continue; } - if (molecule_keyword[rxnID] == INTER) + if (molecule_keyword[rxnID] == INTER) { if (atom->molecule[i] == atom->molecule[j]) continue; - else if (molecule_keyword[rxnID] == INTRA) + } else if (molecule_keyword[rxnID] == INTRA) { if (atom->molecule[i] != atom->molecule[j]) continue; + } jtype = type[j]; possible = 0; @@ -1152,10 +1153,11 @@ void FixBondReact::close_partner() if (i_limit_tags[i2] != 0) continue; if (itype != iatomtype[rxnID] || jtype != jatomtype[rxnID]) continue; - if (molecule_keyword[rxnID] == INTER) + if (molecule_keyword[rxnID] == INTER) { if (atom->molecule[i1] == atom->molecule[i2]) continue; - else if (molecule_keyword[rxnID] == INTRA) + } else if (molecule_keyword[rxnID] == INTRA) { if (atom->molecule[i1] != atom->molecule[i2]) continue; + } delx = x[i1][0] - x[i2][0]; dely = x[i1][1] - x[i2][1]; From 1695bf3d67fe949ea0f2da900e242254f261a89e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Dec 2020 01:09:24 -0500 Subject: [PATCH 06/44] silence compiler warnings and correct issues with energy/virial accumulators - must not zero global accumulators from Pair class (already done by parent) - must add not set accumulated values --- src/USER-MESONT/pair_mesont_tpm.cpp | 37 ++++++++++++----------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/src/USER-MESONT/pair_mesont_tpm.cpp b/src/USER-MESONT/pair_mesont_tpm.cpp index 1271ebddb6..2a18bd64c9 100644 --- a/src/USER-MESONT/pair_mesont_tpm.cpp +++ b/src/USER-MESONT/pair_mesont_tpm.cpp @@ -510,33 +510,28 @@ void PairMESONTTPM::compute(int eflag, int vflag) { buckling[idx] = b_sort[i]; } if (eflag_global) { - eng_vdwl = 0.0; energy_s = 0.0; - energy_b = 0.0; energy_t = 0.0; + energy_s = energy_b = energy_t = 0.0; for (int i = 0; i < nall; i++) { - int idx = ntlist.get_idx(i); energy_s += u_ts_sort[i]; energy_b += u_tb_sort[i]; energy_t += u_tt_sort[i]; } - eng_vdwl = energy_s + energy_b + energy_t; + eng_vdwl += energy_s + energy_b + energy_t; } if (eflag_atom) { - for (int i = 0; i < ntot; i++) { - eatom[i] = 0.0; eatom_s[i] = 0.0; - eatom_b[i] = 0.0; eatom_t[i] = 0.0; - } + for (int i = 0; i < ntot; i++) + eatom_s[i] = eatom_b[i] = eatom_t[i] = 0.0; + for (int i = 0; i < nall; i++) { int idx = ntlist.get_idx(i); - eatom_s[idx] = u_ts_sort[i]; - eatom_b[idx] = u_tb_sort[i]; - eatom_t[idx] = u_tt_sort[i]; - eatom[idx] = u_ts_sort[i] + u_tb_sort[i] + u_tt_sort[i]; + eatom_s[idx] += u_ts_sort[i]; + eatom_b[idx] += u_tb_sort[i]; + eatom_t[idx] += u_tt_sort[i]; + eatom[idx] += u_ts_sort[i] + u_tb_sort[i] + u_tt_sort[i]; } } if (vflag_global) { - for (int i = 0; i < 6; i++) virial[i] = 0.0; for (int i = 0; i < nall; i++) { - int idx = ntlist.get_idx(i); virial[0] += s_sort[9*i+0]; //xx virial[1] += s_sort[9*i+4]; //yy virial[2] += s_sort[9*i+8]; //zz @@ -546,16 +541,14 @@ void PairMESONTTPM::compute(int eflag, int vflag) { } } if (vflag_atom) { - for (int i = 0; i < ntot; i++) - for (int j = 0; j < 6; j++) vatom[i][j] = 0.0; for (int i = 0; i < nall; i++) { int idx = ntlist.get_idx(i); - vatom[idx][0] = s_sort[9*i+0]; //xx - vatom[idx][1] = s_sort[9*i+4]; //yy - vatom[idx][2] = s_sort[9*i+8]; //zz - vatom[idx][3] = s_sort[9*i+1]; //xy - vatom[idx][4] = s_sort[9*i+2]; //xz - vatom[idx][5] = s_sort[9*i+5]; //yz + vatom[idx][0] += s_sort[9*i+0]; //xx + vatom[idx][1] += s_sort[9*i+4]; //yy + vatom[idx][2] += s_sort[9*i+8]; //zz + vatom[idx][3] += s_sort[9*i+1]; //xy + vatom[idx][4] += s_sort[9*i+2]; //xz + vatom[idx][5] += s_sort[9*i+5]; //yz } } From fd37abd6495952e3d71c3d9e2d046538db278fd8 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Dec 2020 01:45:27 -0500 Subject: [PATCH 07/44] fix typo flagged by compiler warning --- src/USER-MESONT/pair_mesocnt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/USER-MESONT/pair_mesocnt.cpp b/src/USER-MESONT/pair_mesocnt.cpp index 39a97321a7..f460e3aebb 100644 --- a/src/USER-MESONT/pair_mesocnt.cpp +++ b/src/USER-MESONT/pair_mesocnt.cpp @@ -546,7 +546,7 @@ void PairMesoCNT::bond_neigh() if (i2 > nlocal-1 && false) numneigh2 = 0; else numneigh2 = numneigh[i2]; - int numneigh_max_local = numneigh1 + numneigh1; + int numneigh_max_local = numneigh1 + numneigh2; if (numneigh_max_local > numneigh_max) numneigh_max = numneigh_max_local; } if (numneigh_max > reduced_neigh_size) { From dbdb1085129323f97729c57a94ac4327e1dcd892 Mon Sep 17 00:00:00 2001 From: Pablo Piaggi Date: Thu, 10 Dec 2020 15:18:48 -0500 Subject: [PATCH 08/44] update temp/csvr manual --- doc/src/fix_temp_csvr.rst | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/doc/src/fix_temp_csvr.rst b/doc/src/fix_temp_csvr.rst index 8faa6035cf..c5ca2ed5eb 100644 --- a/doc/src/fix_temp_csvr.rst +++ b/doc/src/fix_temp_csvr.rst @@ -124,6 +124,19 @@ temperature is calculated taking the bias into account, bias is removed from each atom, thermostatting is performed on the remaining thermal degrees of freedom, and the bias is added back in. +An important feature of these thermostats is that they have an +associated effective energy that is a contant of the motion. +The effective energy is the total energy (kinetic + potential) plus +the accumulated kinetic energy changes due to the thermostat. The +latter quantity is the global scalar computed by these fixes. This +feature is useful to check the integration of the equations of motion +against discretization errors. In other words, the conservation of +the effective energy can be used to choose an appropriate integration +:doc:`timestep `. This is similar to the usual paradigm of +checking the conservation of the total energy in the microcanonical +ensemble. + + ---------- Restart, fix_modify, output, run start/stop, minimize info @@ -153,7 +166,7 @@ These fixes are not invoked during :doc:`energy minimization `. These fixes compute a global scalar which can be accessed by various :doc:`output commands `. The scalar is the cumulative -energy change due to the fix. The scalar value calculated by this fix +kinetic energy change due to the fix. The scalar value calculated by this fix is "extensive". Restrictions From b53f37a9ac9a7fbdb6b707d43b6c7b490549d507 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 12 Dec 2020 23:43:11 -0500 Subject: [PATCH 09/44] fix typo --- src/universe.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/universe.cpp b/src/universe.cpp index 3f58c4a074..a7fa8fc2e2 100644 --- a/src/universe.cpp +++ b/src/universe.cpp @@ -185,7 +185,7 @@ void Universe::add_world(char *str) nper = atoi(part.c_str()); } else { n = atoi(part.substr(0,found).c_str()); - nper = atoi(part.substr(found-1).c_str());\ + nper = atoi(part.substr(found+1).c_str()); } } From acce3c265ae02c8ae4755d1617686f5c8053ec69 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 13 Dec 2020 00:00:15 -0500 Subject: [PATCH 10/44] use C++ string operations --- src/KIM/kim_interactions.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/KIM/kim_interactions.cpp b/src/KIM/kim_interactions.cpp index 5eb01d7ced..afb1391606 100644 --- a/src/KIM/kim_interactions.cpp +++ b/src/KIM/kim_interactions.cpp @@ -291,10 +291,10 @@ void KimInteractions::KIM_SET_TYPE_PARAMETERS(const std::string &input_line) con MPI_Bcast(&n,1,MPI_INT,0,world); MPI_Bcast(line,n,MPI_CHAR,0,world); - if (ptr = strchr(line,'#')) *ptr = '\0'; - if (strspn(line," \t\n\r") == strlen(line)) continue; + auto trimmed = utils::trim_comment(line); + if (trimmed.find_first_not_of(" \t\n\r") == std::string::npos) continue; - words = utils::split_words(line); + words = utils::split_words(trimmed); if (key == "pair") { for (int ia = 0; ia < atom->ntypes; ++ia) { for (int ib = ia; ib < atom->ntypes; ++ib) From 524302e6e688c23caad353cb380b964dba6026c5 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 13 Dec 2020 00:07:48 -0500 Subject: [PATCH 11/44] whitespace --- doc/src/lattice.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/src/lattice.rst b/doc/src/lattice.rst index e937541864..b87ddaaf70 100644 --- a/doc/src/lattice.rst +++ b/doc/src/lattice.rst @@ -254,9 +254,9 @@ in commands that use the spacings should be decipherable. Example commands for generating a Wurtzite crystal. The lattice constants approximate those of CdSe. The :math:`\sqrt{3}\times 1` orthorhombic supercell is used -with the x, y, and z directions oriented -along :math:`[\bar{1}\bar{2}30]`, -:math:`[10\bar{1}0]`, and :math:`[0001]`, respectively. +with the x, y, and z directions oriented +along :math:`[\bar{1}\bar{2}30]`, +:math:`[10\bar{1}0]`, and :math:`[0001]`, respectively. .. code-block:: LAMMPS From 7f29c56c8f20033385ddd92f0bd7d98dd0ecc1e5 Mon Sep 17 00:00:00 2001 From: "Ryan S. Elliott" Date: Mon, 14 Dec 2020 00:03:59 -0600 Subject: [PATCH 12/44] update for kim-api-2.2.1 --- cmake/Modules/Packages/KIM.cmake | 4 ++-- lib/kim/Install.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cmake/Modules/Packages/KIM.cmake b/cmake/Modules/Packages/KIM.cmake index 42b7bb884d..91a48eb3a7 100644 --- a/cmake/Modules/Packages/KIM.cmake +++ b/cmake/Modules/Packages/KIM.cmake @@ -34,8 +34,8 @@ if(DOWNLOAD_KIM) enable_language(C) enable_language(Fortran) ExternalProject_Add(kim_build - URL https://s3.openkim.org/kim-api/kim-api-2.2.0.txz - URL_MD5 e7f944e1593cffd7444679a660607f6c + URL https://s3.openkim.org/kim-api/kim-api-2.2.1.txz + URL_MD5 ae1ddda2ef7017ea07934e519d023dca BINARY_DIR build CMAKE_ARGS ${CMAKE_REQUEST_PIC} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} diff --git a/lib/kim/Install.py b/lib/kim/Install.py index 3ebcb8e237..ae4b356ba9 100644 --- a/lib/kim/Install.py +++ b/lib/kim/Install.py @@ -18,13 +18,14 @@ parser = ArgumentParser(prog='Install.py', # settings thisdir = fullpath('.') -version = "2.2.0" +version = "2.2.1" # known checksums for different KIM-API versions. used to validate the download. checksums = { \ '2.1.2' : '6ac52e14ef52967fc7858220b208cba5', \ '2.1.3' : '6ee829a1bbba5f8b9874c88c4c4ebff8', \ '2.2.0' : 'e7f944e1593cffd7444679a660607f6c', \ + '2.2.1' : 'ae1ddda2ef7017ea07934e519d023dca', \ } From 65d1594474fabfcbdf4fee7c297b9a9242e6a7a1 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 14 Dec 2020 08:39:27 -0500 Subject: [PATCH 13/44] Fix typo and adjust grammar --- doc/src/fix_temp_csvr.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/fix_temp_csvr.rst b/doc/src/fix_temp_csvr.rst index c5ca2ed5eb..ea023c4e24 100644 --- a/doc/src/fix_temp_csvr.rst +++ b/doc/src/fix_temp_csvr.rst @@ -125,7 +125,7 @@ removed from each atom, thermostatting is performed on the remaining thermal degrees of freedom, and the bias is added back in. An important feature of these thermostats is that they have an -associated effective energy that is a contant of the motion. +associated effective energy that is a constant of motion. The effective energy is the total energy (kinetic + potential) plus the accumulated kinetic energy changes due to the thermostat. The latter quantity is the global scalar computed by these fixes. This From 17f8aed268e24f5947c2164e050a6941c491cc72 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 14 Dec 2020 13:03:16 -0500 Subject: [PATCH 14/44] must not use MPI_COMM_WORLD inside of LAMMPS. value of "me" is already computed. --- src/USER-REAXC/reaxc_ffield.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/USER-REAXC/reaxc_ffield.cpp b/src/USER-REAXC/reaxc_ffield.cpp index e4826e78c3..5181415a9f 100644 --- a/src/USER-REAXC/reaxc_ffield.cpp +++ b/src/USER-REAXC/reaxc_ffield.cpp @@ -44,10 +44,7 @@ char Read_Force_Field( FILE *fp, reax_interaction *reax, int lgflag = control->lgflag; int errorflag = 1; double val; - MPI_Comm comm; - int me; - comm = MPI_COMM_WORLD; - MPI_Comm_rank(comm, &me); + int me = control->me; s = (char*) malloc(sizeof(char)*MAX_LINE); tmp = (char**) malloc(sizeof(char*)*MAX_TOKENS); From ac36fb8290fb5b12f7764527c694e69fcecf3e0c Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 14 Dec 2020 15:53:21 -0500 Subject: [PATCH 15/44] must not use MPI_COMM_WORLD to be compatible with multi-partition runs --- src/USER-NETCDF/dump_netcdf_mpiio.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/USER-NETCDF/dump_netcdf_mpiio.cpp b/src/USER-NETCDF/dump_netcdf_mpiio.cpp index 5b83ab58ee..2067e14c22 100644 --- a/src/USER-NETCDF/dump_netcdf_mpiio.cpp +++ b/src/USER-NETCDF/dump_netcdf_mpiio.cpp @@ -292,7 +292,7 @@ void DumpNetCDFMPIIO::openfile() if (singlefile_opened) return; singlefile_opened = 1; - NCERRX( ncmpi_open(MPI_COMM_WORLD, filecurrent, NC_WRITE, MPI_INFO_NULL, + NCERRX( ncmpi_open(world, filecurrent, NC_WRITE, MPI_INFO_NULL, &ncid), filecurrent ); // dimensions @@ -372,7 +372,7 @@ void DumpNetCDFMPIIO::openfile() if (singlefile_opened) return; singlefile_opened = 1; - NCERRX( ncmpi_create(MPI_COMM_WORLD, filecurrent, NC_64BIT_DATA, + NCERRX( ncmpi_create(world, filecurrent, NC_64BIT_DATA, MPI_INFO_NULL, &ncid), filecurrent ); // dimensions @@ -748,7 +748,7 @@ void DumpNetCDFMPIIO::write() nme = count(); int *block_sizes = new int[comm->nprocs]; - MPI_Allgather(&nme, 1, MPI_INT, block_sizes, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Allgather(&nme, 1, MPI_INT, block_sizes, 1, MPI_INT, world); blocki = 0; for (int i = 0; i < comm->me; i++) blocki += block_sizes[i]; delete [] block_sizes; From 231b40995fc5e637a525d7011c41ad021cf82f5d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 14 Dec 2020 17:49:12 -0500 Subject: [PATCH 16/44] work around dump output issues with TAD --- src/REPLICA/tad.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/REPLICA/tad.cpp b/src/REPLICA/tad.cpp index b2a4851d27..0fc611b307 100644 --- a/src/REPLICA/tad.cpp +++ b/src/REPLICA/tad.cpp @@ -554,7 +554,10 @@ void TAD::log_event(int ievent) timer->barrier_start(); modify->addstep_compute_all(update->ntimestep); update->integrate->setup_minimal(1); + // must reset whichflag so that computes won't fail. + update->whichflag = 1; output->write_dump(update->ntimestep); + update->whichflag = 0; timer->barrier_stop(); time_output += timer->get_wall(Timer::TOTAL); } From 4b69693b89a80f4849d565e12efbc07914ab078d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 14 Dec 2020 18:24:50 -0500 Subject: [PATCH 17/44] correct/improve warning messages related to per-atom properties --- src/atom_vec_hybrid.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/atom_vec_hybrid.cpp b/src/atom_vec_hybrid.cpp index 885299982b..8679b7383d 100644 --- a/src/atom_vec_hybrid.cpp +++ b/src/atom_vec_hybrid.cpp @@ -154,9 +154,9 @@ void AtomVecHybrid::process_args(int narg, char **arg) } if (mass_pertype && mass_peratom && comm->me == 0) - error->warning(FLERR, - "Atom_style hybrid defines both pertype and peratom masses " - "- both must be set, only peratom masses will be used"); + error->warning(FLERR, "Atom style hybrid defines both, per-type " + "and per-atom masses; both must be set, but only " + "per-atom masses will be used"); // free allstyles created by build_styles() @@ -216,8 +216,8 @@ void AtomVecHybrid::process_args(int narg, char **arg) char *dup = (char *) dupfield[idup]; ptr = strstr(concat_grow,dup); if ((ptr && strstr(ptr+1,dup)) && (comm->me == 0)) - error->warning(FLERR,fmt::format("Peratom {} is in multiple sub-styles " - "- must be used consistently",dup)); + error->warning(FLERR,fmt::format("Per-atom {} is used in multiple sub-" + "styles; must be used consistently",dup)); } delete [] concat_grow; From 40d260dcc6bbdbea23c9268065e3e5920d6d097e Mon Sep 17 00:00:00 2001 From: PabloPiaggi Date: Mon, 14 Dec 2020 18:45:46 -0500 Subject: [PATCH 18/44] Remove word kinetic --- doc/src/fix_temp_csvr.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/fix_temp_csvr.rst b/doc/src/fix_temp_csvr.rst index ea023c4e24..5e6074bc66 100644 --- a/doc/src/fix_temp_csvr.rst +++ b/doc/src/fix_temp_csvr.rst @@ -166,7 +166,7 @@ These fixes are not invoked during :doc:`energy minimization `. These fixes compute a global scalar which can be accessed by various :doc:`output commands `. The scalar is the cumulative -kinetic energy change due to the fix. The scalar value calculated by this fix +energy change due to the fix. The scalar value calculated by this fix is "extensive". Restrictions From f7dc7e3f3f383b7897682bec02a4fba2dfee9166 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 15 Dec 2020 14:31:40 -0500 Subject: [PATCH 19/44] add preset for use with PGI compilers (tested with version 20.11) --- cmake/presets/pgi.cmake | 16 ++++++++++++++++ doc/src/Build_basics.rst | 5 ++++- doc/src/Build_package.rst | 2 ++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 cmake/presets/pgi.cmake diff --git a/cmake/presets/pgi.cmake b/cmake/presets/pgi.cmake new file mode 100644 index 0000000000..b34cb05331 --- /dev/null +++ b/cmake/presets/pgi.cmake @@ -0,0 +1,16 @@ +# preset that will enable clang/clang++ with support for MPI and OpenMP (on Linux boxes) + +set(CMAKE_CXX_COMPILER "pgc++" CACHE STRING "" FORCE) +set(CMAKE_C_COMPILER "pgcc" CACHE STRING "" FORCE) +set(CMAKE_Fortran_COMPILER "pgfortran" CACHE STRING "" FORCE) +set(MPI_CXX "pgc++" CACHE STRING "" FORCE) +set(MPI_CXX_COMPILER "mpicxx" CACHE STRING "" FORCE) +unset(HAVE_OMP_H_INCLUDE CACHE) + +set(OpenMP_C "pgcc" CACHE STRING "" FORCE) +set(OpenMP_C_FLAGS "-mp" CACHE STRING "" FORCE) +set(OpenMP_C_LIB_NAMES "omp" CACHE STRING "" FORCE) +set(OpenMP_CXX "pgc++" CACHE STRING "" FORCE) +set(OpenMP_CXX_FLAGS "-mp" CACHE STRING "" FORCE) +set(OpenMP_CXX_LIB_NAMES "omp" CACHE STRING "" FORCE) +set(OpenMP_omp_LIBRARY "libomp.so" CACHE PATH "" FORCE) diff --git a/doc/src/Build_basics.rst b/doc/src/Build_basics.rst index 8f40d3e5ba..cb6bd9f6aa 100644 --- a/doc/src/Build_basics.rst +++ b/doc/src/Build_basics.rst @@ -236,12 +236,15 @@ LAMMPS. cmake ../cmake -DCMAKE_C_COMPILER=icc -DCMAKE_CXX_COMPILER=icpc -DCMAKE_Fortran_COMPILER=ifort # Building with LLVM/Clang Compilers: cmake ../cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_Fortran_COMPILER=flang + # Building with PGI/Nvidia Compilers: + cmake ../cmake -DCMAKE_C_COMPILER=pgcc -DCMAKE_CXX_COMPILER=pgc++ -DCMAKE_Fortran_COMPILER=pgfortran For compiling with the Clang/LLVM compilers a CMake preset is provided that can be loaded with `-C ../cmake/presets/clang.cmake`. Similarly, `-C ../cmake/presets/intel.cmake` should switch the compiler - toolchain to the Intel compilers. + toolchain to the Intel compilers and `-C ../cmake/presets/pgi.cmake` + should switch the compiler to the PGI compilers. In addition you can set ``CMAKE_TUNE_FLAGS`` to specifically add compiler flags to tune for optimal performance on given hosts. By diff --git a/doc/src/Build_package.rst b/doc/src/Build_package.rst index 18d9ab5f19..63312d7aa8 100644 --- a/doc/src/Build_package.rst +++ b/doc/src/Build_package.rst @@ -1,4 +1,5 @@ Include packages in build + ========================= In LAMMPS, a package is a group of files that enable a specific set of @@ -160,6 +161,7 @@ one of them as a starting point and customize it to your needs. cmake -C ../cmake/presets/clang.cmake [OPTIONS] ../cmake # change settings to use the Clang compilers by default cmake -C ../cmake/presets/gcc.cmake [OPTIONS] ../cmake # change settings to use the GNU compilers by default cmake -C ../cmake/presets/intel.cmake [OPTIONS] ../cmake # change settings to use the Intel compilers by default + cmake -C ../cmake/presets/pgi.cmake [OPTIONS] ../cmake # change settings to use the PGI compilers by default cmake -C ../cmake/presets/all_on.cmake [OPTIONS] ../cmake # enable all packages cmake -C ../cmake/presets/all_off.cmake [OPTIONS] ../cmake # disable all packages mingw64-cmake -C ../cmake/presets/mingw-cross.cmake [OPTIONS] ../cmake # compile with MinGW cross compilers From 65dc5c0351139ee381376feef7547e5cabb63829 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 15 Dec 2020 14:32:18 -0500 Subject: [PATCH 20/44] work around PGI compiler issues --- cmake/CMakeLists.txt | 1 + src/fmt/os.h | 4 ++++ src/lmptype.h | 2 ++ unittest/fortran/test_fortran_commands.f90 | 6 +++--- unittest/fortran/test_fortran_create.f90 | 8 +++----- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 42e6d12ffb..60b1bcfc0a 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -220,6 +220,7 @@ if(BUILD_OMP) endif() if (((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 9.0)) OR + (CMAKE_CXX_COMPILER_ID STREQUAL "PGI") OR ((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0)) OR ((CMAKE_CXX_COMPILER_ID STREQUAL "Intel") AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.0))) # GCC 9.x and later plus Clang 10.x and later implement strict OpenMP 4.0 semantics for consts. diff --git a/src/fmt/os.h b/src/fmt/os.h index d44ea0c904..823173c8e3 100644 --- a/src/fmt/os.h +++ b/src/fmt/os.h @@ -375,7 +375,11 @@ struct ostream_params { }; } // namespace detail +#if defined(__PGI) +static detail::buffer_size buffer_size; +#else static constexpr detail::buffer_size buffer_size; +#endif // A fast output stream which is not thread-safe. class ostream final : private detail::buffer { diff --git a/src/lmptype.h b/src/lmptype.h index e5dba94be0..264b93a329 100644 --- a/src/lmptype.h +++ b/src/lmptype.h @@ -268,6 +268,8 @@ The typecasts prevent compiler warnings about possible truncation issues. # define _noopt __attribute__((optnone)) #elif defined(__INTEL_COMPILER) # define _noopt +#elif defined(__PGI) +# define _noopt #elif defined(__GNUC__) # if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) # if defined(_FORTIFY_SOURCE) && (_FORTIFY_SOURCE > 0) diff --git a/unittest/fortran/test_fortran_commands.f90 b/unittest/fortran/test_fortran_commands.f90 index 748bc5774a..b5cffe698f 100644 --- a/unittest/fortran/test_fortran_commands.f90 +++ b/unittest/fortran/test_fortran_commands.f90 @@ -1,12 +1,12 @@ MODULE keepcmds USE liblammps TYPE(LAMMPS) :: lmp - CHARACTER(len=*), DIMENSION(*), PARAMETER :: demo_input = & + CHARACTER(len=40), DIMENSION(3), PARAMETER :: demo_input = & [ CHARACTER(len=40) :: & 'region box block 0 $x 0 2 0 2', & 'create_box 1 box', & 'create_atoms 1 single 1.0 1.0 ${zpos}' ] - CHARACTER(len=*), DIMENSION(*), PARAMETER :: cont_input = & + CHARACTER(len=40), DIMENSION(2), PARAMETER :: cont_input = & [ CHARACTER(len=40) :: & 'create_atoms 1 single &', & ' 0.2 0.1 0.1' ] @@ -19,7 +19,7 @@ FUNCTION f_lammps_with_args() BIND(C, name="f_lammps_with_args") IMPLICIT NONE TYPE(c_ptr) :: f_lammps_with_args - CHARACTER(len=*), DIMENSION(*), PARAMETER :: args = & + CHARACTER(len=12), DIMENSION(12), PARAMETER :: args = & [ CHARACTER(len=12) :: 'liblammps', '-log', 'none', & '-echo','screen','-nocite','-var','zpos','1.5','-var','x','2'] diff --git a/unittest/fortran/test_fortran_create.f90 b/unittest/fortran/test_fortran_create.f90 index 694646e9bd..e1df7502cb 100644 --- a/unittest/fortran/test_fortran_create.f90 +++ b/unittest/fortran/test_fortran_create.f90 @@ -22,7 +22,7 @@ FUNCTION f_lammps_no_mpi_with_args() BIND(C, name="f_lammps_no_mpi_with_args") IMPLICIT NONE TYPE(c_ptr) :: f_lammps_no_mpi_with_args - CHARACTER(len=*), DIMENSION(*), PARAMETER :: args = & + CHARACTER(len=12), DIMENSION(4), PARAMETER :: args = & [ CHARACTER(len=12) :: 'liblammps', '-log', 'none', '-nocite' ] lmp = lammps(args) @@ -54,7 +54,7 @@ FUNCTION f_lammps_open_with_args() BIND(C, name="f_lammps_open_with_args") TYPE(c_ptr) :: f_lammps_open_with_args INTEGER :: color, key, ierr - CHARACTER(len=*), DIMENSION(*), PARAMETER :: args = & + CHARACTER(len=12), DIMENSION(4), PARAMETER :: args = & [ CHARACTER(len=12) :: 'liblammps', '-log', 'none', '-nocite' ] color = 2 @@ -73,7 +73,7 @@ SUBROUTINE f_lammps_close() BIND(C, name="f_lammps_close") CALL lmp%close() lmp%handle = c_null_ptr END SUBROUTINE f_lammps_close - + FUNCTION f_lammps_get_comm() BIND(C, name="f_lammps_get_comm") USE liblammps USE keepcreate, ONLY: mycomm @@ -82,5 +82,3 @@ FUNCTION f_lammps_get_comm() BIND(C, name="f_lammps_get_comm") f_lammps_get_comm = mycomm END FUNCTION f_lammps_get_comm - - From 2a763d17132d40d227aacb07a1c44d3756865f0b Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 15 Dec 2020 15:00:31 -0500 Subject: [PATCH 21/44] PythonCommands test fails without exceptions enabled --- unittest/python/CMakeLists.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/unittest/python/CMakeLists.txt b/unittest/python/CMakeLists.txt index 47fdbbfb2d..575b64252b 100644 --- a/unittest/python/CMakeLists.txt +++ b/unittest/python/CMakeLists.txt @@ -57,10 +57,13 @@ if (Python_EXECUTABLE) WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) set_tests_properties(PythonOpen PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}") - add_test(NAME PythonCommands - COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-commands.py -v - WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) - set_tests_properties(PythonCommands PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}") + # some of the tests in this file will fail without exceptions enabled + if(LAMMPS_EXCEPTIONS) + add_test(NAME PythonCommands + COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-commands.py -v + WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) + set_tests_properties(PythonCommands PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}") + endif() add_test(NAME PythonNumpy COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-numpy.py -v From aca2eefce595a6366a4fdab7a2b0c26987adb39b Mon Sep 17 00:00:00 2001 From: Richard Berger Date: Tue, 15 Dec 2020 15:11:21 -0500 Subject: [PATCH 22/44] Transform LAMMPS Python module into package - Moves lammps.py into its own package - Imports entire module in __init__.py - Changes both how legacy and CMake build systems install - Added traditional setup.py for Python-only installation Note: the CMake install target runs setup.py build and install in a way that produces files in CMAKE_BINARY_DIR/python instead of python/build. This is to maintain out-of-source compilation support. --- cmake/CMakeLists.txt | 9 ++---- python/install.py | 54 +++++++++++++++++++---------------- python/lammps/__init__.py | 1 + python/{ => lammps}/lammps.py | 0 python/setup.py | 26 +++++++++++++++++ src/Makefile | 2 +- 6 files changed, 60 insertions(+), 32 deletions(-) create mode 100644 python/lammps/__init__.py rename python/{ => lammps}/lammps.py (100%) create mode 100644 python/setup.py diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 42e6d12ffb..854937dec8 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -661,7 +661,7 @@ if(BUILD_SHARED_LIBS) add_custom_target( install-python ${Python_EXECUTABLE} install.py -v ${LAMMPS_SOURCE_DIR}/version.h - -m ${LAMMPS_PYTHON_DIR}/lammps.py + -p ${LAMMPS_PYTHON_DIR}/lammps -l ${CMAKE_BINARY_DIR}/liblammps${CMAKE_SHARED_LIBRARY_SUFFIX} WORKING_DIRECTORY ${LAMMPS_PYTHON_DIR} COMMENT "Installing LAMMPS Python module") @@ -691,11 +691,8 @@ if(BUILD_SHARED_LIBS OR PKG_PYTHON) find_package(Python COMPONENTS Interpreter) endif() if (Python_EXECUTABLE) - execute_process(COMMAND ${Python_EXECUTABLE} - -c "import distutils.sysconfig as cg; print(cg.get_python_lib(1,0,prefix='${CMAKE_INSTALL_PREFIX}'))" - OUTPUT_VARIABLE PYTHON_DEFAULT_INSTDIR OUTPUT_STRIP_TRAILING_WHITESPACE) - set(PYTHON_INSTDIR ${PYTHON_DEFAULT_INSTDIR} CACHE PATH "Installation folder for LAMMPS Python module") - install(FILES ${LAMMPS_PYTHON_DIR}/lammps.py DESTINATION ${PYTHON_INSTDIR}) + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/python) + install(CODE "execute_process(COMMAND ${Python_EXECUTABLE} setup.py build -b ${CMAKE_BINARY_DIR}/python install --prefix=${CMAKE_INSTALL_PREFIX} WORKING_DIRECTORY ${LAMMPS_PYTHON_DIR})") endif() endif() diff --git a/python/install.py b/python/install.py index 7f7062103a..a6b69c1ee6 100644 --- a/python/install.py +++ b/python/install.py @@ -1,42 +1,42 @@ #!/usr/bin/env python """ -Installer script to install the LAMMPS python module and the corresponding +Installer script to install the LAMMPS python package and the corresponding shared library into either the system-wide site-packages tree, or - failing that - into the corresponding user tree. Called from the 'install-python' build target in the conventional and CMake based build systems """ -# copy LAMMPS shared library and lammps.py to system dirs +# copy LAMMPS shared library and lammps package to system dirs from __future__ import print_function import sys,os,shutil from argparse import ArgumentParser parser = ArgumentParser(prog='install.py', - description='LAMMPS python module installer script') + description='LAMMPS python package installer script') -parser.add_argument("-m", "--module", required=True, - help="path to the source of the LAMMPS Python module") +parser.add_argument("-p", "--package", required=True, + help="path to the LAMMPS Python package") parser.add_argument("-l", "--lib", required=True, help="path to the compiled LAMMPS shared library") parser.add_argument("-v", "--version", required=True, help="path to the LAMMPS version.h header file") parser.add_argument("-d","--dir", - help="Legacy custom installation folder selection for module and library") + help="Legacy custom installation folder selection for package and library") args = parser.parse_args() # validate arguments and make paths absolute -if args.module: - if not os.path.exists(args.module): - print( "ERROR: LAMMPS module file %s does not exist" % args.module) +if args.package: + if not os.path.exists(args.package): + print( "ERROR: LAMMPS package %s does not exist" % args.package) parser.print_help() sys.exit(1) else: - args.module = os.path.abspath(args.module) + args.package = os.path.abspath(args.package) if args.lib: if not os.path.exists(args.lib): @@ -66,9 +66,9 @@ if args.dir: # without any special processing or additional steps to that folder if args.dir: - print("Copying LAMMPS Python module to custom folder %s" % args.dir) + print("Copying LAMMPS Python package to custom folder %s" % args.dir) try: - shutil.copyfile(args.module, os.path.join(args.dir,'lammps.py')) + shutil.copytree(args.package, os.path.join(args.dir,'lammps')) except shutil.Error: pass # fail silently @@ -81,15 +81,19 @@ if args.dir: sys.exit() # extract version string from header -fp = open(args.version,'r') -txt=fp.read().split('"')[1].split() -verstr=txt[0]+txt[1]+txt[2] -fp.close() +def get_lammps_version(header): + with open(header, 'r') as f: + line = f.readline() + start_pos = line.find('"')+1 + end_pos = line.find('"', start_pos) + return "".join(line[start_pos:end_pos].split()) -print("Installing LAMMPS Python module version %s into site-packages folder" % verstr) +verstr = get_lammps_version(args.version) -# we need to switch to the folder of the python module -os.chdir(os.path.dirname(args.module)) +print("Installing LAMMPS Python package version %s into site-packages folder" % verstr) + +# we need to switch to the folder of the python package +os.chdir(os.path.dirname(args.package)) from distutils.core import setup from distutils.sysconfig import get_python_lib @@ -103,10 +107,10 @@ try: author = "Steve Plimpton", author_email = "sjplimp@sandia.gov", url = "https://lammps.sandia.gov", - description = "LAMMPS Molecular Dynamics Python module", + description = "LAMMPS Molecular Dynamics Python package", license = "GPL", - py_modules = ["lammps"], - data_files = [(get_python_lib(), [args.lib])]) + packages=['lammps'], + data_files = [(os.path.join(get_python_lib(), 'lammps'), [args.lib])]) except: tryuser=True print ("Installation into global site-packages folder failed.\nTrying user folder %s now." % site.USER_SITE) @@ -119,9 +123,9 @@ if tryuser: author = "Steve Plimpton", author_email = "sjplimp@sandia.gov", url = "https://lammps.sandia.gov", - description = "LAMMPS Molecular Dynamics Python module", + description = "LAMMPS Molecular Dynamics Python package", license = "GPL", - py_modules = ["lammps"], - data_files = [(site.USER_SITE, [args.lib])]) + packages=['lammps'], + data_files = [(os.path.join(site.USER_SITE, 'lammps'), [args.lib])]) except: print("Installation into user site package folder failed.") diff --git a/python/lammps/__init__.py b/python/lammps/__init__.py new file mode 100644 index 0000000000..2f29663b75 --- /dev/null +++ b/python/lammps/__init__.py @@ -0,0 +1 @@ +from .lammps import * diff --git a/python/lammps.py b/python/lammps/lammps.py similarity index 100% rename from python/lammps.py rename to python/lammps/lammps.py diff --git a/python/setup.py b/python/setup.py new file mode 100644 index 0000000000..9be04138d5 --- /dev/null +++ b/python/setup.py @@ -0,0 +1,26 @@ +# this only installs the LAMMPS python package +# it assumes the LAMMPS shared library is already installed +from distutils.core import setup +import os + +LAMMPS_PYTHON_DIR = os.path.dirname(os.path.realpath(__file__)) +LAMMPS_DIR = os.path.dirname(LAMMPS_PYTHON_DIR) +LAMMPS_SOURCE_DIR = os.path.join(LAMMPS_DIR, 'src') + +def get_lammps_version(): + with open(os.path.join(LAMMPS_SOURCE_DIR, 'version.h'), 'r') as f: + line = f.readline() + start_pos = line.find('"')+1 + end_pos = line.find('"', start_pos) + return "".join(line[start_pos:end_pos].split()) + +setup( + name = "lammps", + version = get_lammps_version(), + author = "Steve Plimpton", + author_email = "sjplimp@sandia.gov", + url = "https://lammps.sandia.gov", + description = "LAMMPS Molecular Dynamics Python package", + license = "GPL", + packages=["lammps"] +) diff --git a/src/Makefile b/src/Makefile index 149dedd35b..7a5e1aa728 100644 --- a/src/Makefile +++ b/src/Makefile @@ -278,7 +278,7 @@ mpi-stubs: sinclude ../lib/python/Makefile.lammps install-python: @$(PYTHON) ../python/install.py -v ../src/version.h \ - -m ../python/lammps.py -l ../src/liblammps.so + -p ../python/lammps -l ../src/liblammps.so # Create a tarball of src dir and packages From 588198c5dda256ce6b0cd72d7b1953e86b7fca92 Mon Sep 17 00:00:00 2001 From: Richard Berger Date: Tue, 15 Dec 2020 16:07:49 -0500 Subject: [PATCH 23/44] Add --embed to python-config for legacy build Newer versions of Python (v3.9) do not include the python library in their python-config --ldflags unless you also pass --embed. --- lib/python/Makefile.lammps | 2 +- lib/python/Makefile.lammps.python3 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/python/Makefile.lammps b/lib/python/Makefile.lammps index 4289674e99..e4afa70456 100644 --- a/lib/python/Makefile.lammps +++ b/lib/python/Makefile.lammps @@ -2,6 +2,6 @@ # See the README file for more explanation python_SYSINC = $(shell which python-config > /dev/null 2>&1 && python-config --includes || :) -python_SYSLIB = $(shell which python-config > /dev/null 2>&1 && python-config --ldflags || :) +python_SYSLIB = $(shell which python-config > /dev/null 2>&1 && python-config --ldflags --embed > /dev/null 2>&1 && python-config --ldflags --embed || (which python-config > /dev/null 2>&1 && python-config --ldflags || :) ) python_SYSPATH = PYTHON=python diff --git a/lib/python/Makefile.lammps.python3 b/lib/python/Makefile.lammps.python3 index 5c43b45ff6..d37e822327 100644 --- a/lib/python/Makefile.lammps.python3 +++ b/lib/python/Makefile.lammps.python3 @@ -2,6 +2,6 @@ # See the README file for more explanation python_SYSINC = $(shell which python3-config > /dev/null 2>&1 && python3-config --includes || (which python-config > /dev/null 2>&1 && python-config --includes || :)) -python_SYSLIB = $(shell which python3-config > /dev/null 2>&1 && python3-config --ldflags || (which python-config > /dev/null 2>&1 && python-config --ldflags || :)) +python_SYSLIB = $(shell which python3-config > /dev/null 2>&1 && python3-config --ldflags --embed > /dev/null 2>&1 && python3-config --ldflags --embed || (which python3-config > /dev/null 2>&1 && python3-config --ldflags || (which python-config > /dev/null 2>&1 && python-config --ldflags || :) ) ) python_SYSPATH = PYTHON=$(shell which python3 > /dev/null 2>&1 && echo python3 || echo python) From b390c1e3d34c599d77abe3fb418cb5a201c55491 Mon Sep 17 00:00:00 2001 From: Richard Berger Date: Tue, 15 Dec 2020 16:15:16 -0500 Subject: [PATCH 24/44] Split lammps.py into core.py and pylammps.py --- python/lammps/__init__.py | 3 +- python/lammps/{lammps.py => core.py} | 858 +------------------------- python/lammps/pylammps.py | 870 +++++++++++++++++++++++++++ 3 files changed, 877 insertions(+), 854 deletions(-) rename python/lammps/{lammps.py => core.py} (73%) create mode 100644 python/lammps/pylammps.py diff --git a/python/lammps/__init__.py b/python/lammps/__init__.py index 2f29663b75..37773d84a5 100644 --- a/python/lammps/__init__.py +++ b/python/lammps/__init__.py @@ -1 +1,2 @@ -from .lammps import * +from .core import * +from .pylammps import * diff --git a/python/lammps/lammps.py b/python/lammps/core.py similarity index 73% rename from python/lammps/lammps.py rename to python/lammps/core.py index b74e111dc6..14b727e59a 100644 --- a/python/lammps/lammps.py +++ b/python/lammps/core.py @@ -10,28 +10,21 @@ # # See the README file in the top-level LAMMPS directory. # ------------------------------------------------------------------------- -# Python wrappers for the LAMMPS library via ctypes +# Python wrapper for the LAMMPS library via ctypes # for python2/3 compatibility from __future__ import print_function -# imports for simple LAMMPS python wrapper module "lammps" - -import sys,traceback,types +import os +import sys +import traceback +import types import warnings from ctypes import * from os.path import dirname,abspath,join from inspect import getsourcefile -# imports for advanced LAMMPS python wrapper modules "PyLammps" and "IPyLammps" - -from collections import namedtuple -import os -import select -import re -import sys - # various symbolic constants to be used # in certain calls to select data formats LAMMPS_AUTODETECT = None @@ -2083,844 +2076,3 @@ class numpy_wrapper: a = np.frombuffer(ptr.contents) a.shape = (nelem, dim) return a - - -# ------------------------------------------------------------------------- -# ------------------------------------------------------------------------- -# ------------------------------------------------------------------------- - -################################################################################ -# Alternative Python Wrapper -# Written by Richard Berger -################################################################################ - -class OutputCapture(object): - """ Utility class to capture LAMMPS library output """ - - def __init__(self): - self.stdout_pipe_read, self.stdout_pipe_write = os.pipe() - self.stdout_fd = 1 - - def __enter__(self): - self.stdout = os.dup(self.stdout_fd) - os.dup2(self.stdout_pipe_write, self.stdout_fd) - return self - - def __exit__(self, type, value, tracebac): - os.dup2(self.stdout, self.stdout_fd) - os.close(self.stdout) - os.close(self.stdout_pipe_read) - os.close(self.stdout_pipe_write) - - # check if we have more to read from the pipe - def more_data(self, pipe): - r, _, _ = select.select([pipe], [], [], 0) - return bool(r) - - # read the whole pipe - def read_pipe(self, pipe): - out = "" - while self.more_data(pipe): - out += os.read(pipe, 1024).decode() - return out - - @property - def output(self): - return self.read_pipe(self.stdout_pipe_read) - -# ------------------------------------------------------------------------- - -class Variable(object): - def __init__(self, pylammps_instance, name, style, definition): - self._pylmp = pylammps_instance - self.name = name - self.style = style - self.definition = definition.split() - - @property - def value(self): - if self.style == 'atom': - return list(self._pylmp.lmp.extract_variable(self.name, "all", 1)) - else: - value = self._pylmp.lmp_print('"${%s}"' % self.name).strip() - try: - return float(value) - except ValueError: - return value - -# ------------------------------------------------------------------------- - -class AtomList(object): - """ - A dynamic list of atoms that returns either an :py:class:`Atom` or - :py:class:`Atom2D` instance for each atom. Instances are only allocated - when accessed. - - :ivar natoms: total number of atoms - :ivar dimensions: number of dimensions in system - """ - def __init__(self, pylammps_instance): - self._pylmp = pylammps_instance - self.natoms = self._pylmp.system.natoms - self.dimensions = self._pylmp.system.dimensions - self._loaded = {} - - def __getitem__(self, index): - """ - Return Atom with given local index - - :param index: Local index of atom - :type index: int - :rtype: Atom or Atom2D - """ - if index not in self._loaded: - if self.dimensions == 2: - atom = Atom2D(self._pylmp, index + 1) - else: - atom = Atom(self._pylmp, index + 1) - self._loaded[index] = atom - return self._loaded[index] - - def __len__(self): - return self.natoms - - -# ------------------------------------------------------------------------- - -class Atom(object): - """ - A wrapper class then represents a single atom inside of LAMMPS - - It provides access to properties of the atom and allows you to change some of them. - """ - def __init__(self, pylammps_instance, index): - self._pylmp = pylammps_instance - self.index = index - - @property - def id(self): - """ - Return the atom ID - - :type: int - """ - return int(self._pylmp.eval("id[%d]" % self.index)) - - @property - def type(self): - """ - Return the atom type - - :type: int - """ - return int(self._pylmp.eval("type[%d]" % self.index)) - - @property - def mol(self): - """ - Return the atom molecule index - - :type: int - """ - return self._pylmp.eval("mol[%d]" % self.index) - - @property - def mass(self): - """ - Return the atom mass - - :type: float - """ - return self._pylmp.eval("mass[%d]" % self.index) - - @property - def position(self): - """ - :getter: Return position of atom - :setter: Set position of atom - :type: tuple (float, float, float) - """ - return (self._pylmp.eval("x[%d]" % self.index), - self._pylmp.eval("y[%d]" % self.index), - self._pylmp.eval("z[%d]" % self.index)) - - @position.setter - def position(self, value): - """ - :getter: Return velocity of atom - :setter: Set velocity of atom - :type: tuple (float, float, float) - """ - self._pylmp.set("atom", self.index, "x", value[0]) - self._pylmp.set("atom", self.index, "y", value[1]) - self._pylmp.set("atom", self.index, "z", value[2]) - - @property - def velocity(self): - return (self._pylmp.eval("vx[%d]" % self.index), - self._pylmp.eval("vy[%d]" % self.index), - self._pylmp.eval("vz[%d]" % self.index)) - - @velocity.setter - def velocity(self, value): - self._pylmp.set("atom", self.index, "vx", value[0]) - self._pylmp.set("atom", self.index, "vy", value[1]) - self._pylmp.set("atom", self.index, "vz", value[2]) - - @property - def force(self): - """ - Return the total force acting on the atom - - :type: tuple (float, float, float) - """ - return (self._pylmp.eval("fx[%d]" % self.index), - self._pylmp.eval("fy[%d]" % self.index), - self._pylmp.eval("fz[%d]" % self.index)) - - @property - def charge(self): - """ - Return the atom charge - - :type: float - """ - return self._pylmp.eval("q[%d]" % self.index) - -# ------------------------------------------------------------------------- - -class Atom2D(Atom): - """ - A wrapper class then represents a single 2D atom inside of LAMMPS - - Inherits all properties from the :py:class:`Atom` class, but returns 2D versions - of position, velocity, and force. - - It provides access to properties of the atom and allows you to change some of them. - """ - def __init__(self, pylammps_instance, index): - super(Atom2D, self).__init__(pylammps_instance, index) - - @property - def position(self): - """ - :getter: Return position of atom - :setter: Set position of atom - :type: tuple (float, float) - """ - return (self._pylmp.eval("x[%d]" % self.index), - self._pylmp.eval("y[%d]" % self.index)) - - @position.setter - def position(self, value): - self._pylmp.set("atom", self.index, "x", value[0]) - self._pylmp.set("atom", self.index, "y", value[1]) - - @property - def velocity(self): - """ - :getter: Return velocity of atom - :setter: Set velocity of atom - :type: tuple (float, float) - """ - return (self._pylmp.eval("vx[%d]" % self.index), - self._pylmp.eval("vy[%d]" % self.index)) - - @velocity.setter - def velocity(self, value): - self._pylmp.set("atom", self.index, "vx", value[0]) - self._pylmp.set("atom", self.index, "vy", value[1]) - - @property - def force(self): - """ - Return the total force acting on the atom - - :type: tuple (float, float) - """ - return (self._pylmp.eval("fx[%d]" % self.index), - self._pylmp.eval("fy[%d]" % self.index)) - -# ------------------------------------------------------------------------- - -class variable_set: - def __init__(self, name, variable_dict): - self._name = name - array_pattern = re.compile(r"(?P.+)\[(?P[0-9]+)\]") - - for key, value in variable_dict.items(): - m = array_pattern.match(key) - if m: - g = m.groupdict() - varname = g['arr'] - idx = int(g['index']) - if varname not in self.__dict__: - self.__dict__[varname] = {} - self.__dict__[varname][idx] = value - else: - self.__dict__[key] = value - - def __str__(self): - return "{}({})".format(self._name, ','.join(["{}={}".format(k, self.__dict__[k]) for k in self.__dict__.keys() if not k.startswith('_')])) - - def __repr__(self): - return self.__str__() - -# ------------------------------------------------------------------------- - -def get_thermo_data(output): - """ traverse output of runs and extract thermo data columns """ - if isinstance(output, str): - lines = output.splitlines() - else: - lines = output - - runs = [] - columns = [] - in_run = False - current_run = {} - - for line in lines: - if line.startswith("Per MPI rank memory allocation"): - in_run = True - elif in_run and len(columns) == 0: - # first line after memory usage are column names - columns = line.split() - - current_run = {} - - for col in columns: - current_run[col] = [] - - elif line.startswith("Loop time of "): - in_run = False - columns = None - thermo_data = variable_set('ThermoData', current_run) - r = {'thermo' : thermo_data } - runs.append(namedtuple('Run', list(r.keys()))(*list(r.values()))) - elif in_run and len(columns) > 0: - items = line.split() - # Convert thermo output and store it. - # It must have the same number of columns and - # all of them must be convertible to floats. - # Otherwise we ignore the line - if len(items) == len(columns): - try: - values = [float(x) for x in items] - for i, col in enumerate(columns): - current_run[col].append(values[i]) - except ValueError: - pass - - return runs - -# ------------------------------------------------------------------------- -# ------------------------------------------------------------------------- - -class PyLammps(object): - """ - This is a Python wrapper class around the lower-level - :py:class:`lammps` class, exposing a more Python-like, - object-oriented interface for prototyping system inside of IPython and - Jupyter notebooks. - - It either creates its own instance of :py:class:`lammps` or can be - initialized with an existing instance. The arguments are the same of the - lower-level interface. The original interface can still be accessed via - :py:attr:`PyLammps.lmp`. - - :param name: "machine" name of the shared LAMMPS library ("mpi" loads ``liblammps_mpi.so``, "" loads ``liblammps.so``) - :type name: string - :param cmdargs: list of command line arguments to be passed to the :cpp:func:`lammps_open` function. The executable name is automatically added. - :type cmdargs: list - :param ptr: pointer to a LAMMPS C++ class instance when called from an embedded Python interpreter. None means load symbols from shared library. - :type ptr: pointer - :param comm: MPI communicator (as provided by `mpi4py `_). ``None`` means use ``MPI_COMM_WORLD`` implicitly. - :type comm: MPI_Comm - - :ivar lmp: instance of original LAMMPS Python interface - :vartype lmp: :py:class:`lammps` - - :ivar runs: list of completed runs, each storing the thermo output - :vartype run: list - """ - - def __init__(self, name="", cmdargs=None, ptr=None, comm=None): - self.has_echo = False - - if cmdargs: - if '-echo' in cmdargs: - idx = cmdargs.index('-echo') - # ensures that echo line is ignored during output capture - self.has_echo = idx+1 < len(cmdargs) and cmdargs[idx+1] in ('screen', 'both') - - if ptr: - if isinstance(ptr,PyLammps): - self.lmp = ptr.lmp - elif isinstance(ptr,lammps): - self.lmp = ptr - else: - self.lmp = lammps(name=name,cmdargs=cmdargs,ptr=ptr,comm=comm) - else: - self.lmp = lammps(name=name,cmdargs=cmdargs,ptr=None,comm=comm) - print("LAMMPS output is captured by PyLammps wrapper") - self._cmd_history = [] - self.runs = [] - - def __del__(self): - if self.lmp: self.lmp.close() - self.lmp = None - - def close(self): - """Explicitly delete a LAMMPS instance - - This is a wrapper around the :py:meth:`lammps.close` of the Python interface. - """ - if self.lmp: self.lmp.close() - self.lmp = None - - def version(self): - """Return a numerical representation of the LAMMPS version in use. - - This is a wrapper around the :py:meth:`lammps.version` function of the Python interface. - - :return: version number - :rtype: int - """ - return self.lmp.version() - - def file(self, file): - """Read LAMMPS commands from a file. - - This is a wrapper around the :py:meth:`lammps.file` function of the Python interface. - - :param path: Name of the file/path with LAMMPS commands - :type path: string - """ - self.lmp.file(file) - - def write_script(self, filepath): - """ - Write LAMMPS script file containing all commands executed up until now - - :param filepath: path to script file that should be written - :type filepath: string - """ - with open(filepath, "w") as f: - for cmd in self._cmd_history: - print(cmd, file=f) - - def command(self, cmd): - """ - Execute LAMMPS command - - All commands executed will be stored in a command history which can be - written to a file using :py:meth:`PyLammps.write_script()` - - :param cmd: command string that should be executed - :type: cmd: string - """ - self.lmp.command(cmd) - self._cmd_history.append(cmd) - - def run(self, *args, **kwargs): - """ - Execute LAMMPS run command with given arguments - - All thermo output during the run is captured and saved as new entry in - :py:attr:`PyLammps.runs`. The latest run can be retrieved by - :py:attr:`PyLammps.last_run`. - """ - output = self.__getattr__('run')(*args, **kwargs) - - comm = self.lmp.get_mpi_comm() - if comm: - output = self.lmp.comm.bcast(output, root=0) - - self.runs += get_thermo_data(output) - return output - - @property - def last_run(self): - """ - Return data produced of last completed run command - - :getter: Returns an object containing information about the last run command - :type: dict - """ - if len(self.runs) > 0: - return self.runs[-1] - return None - - @property - def atoms(self): - """ - All atoms of this LAMMPS instance - - :getter: Returns a list of atoms currently in the system - :type: AtomList - """ - return AtomList(self) - - @property - def system(self): - """ - The system state of this LAMMPS instance - - :getter: Returns an object with properties storing the current system state - :type: namedtuple - """ - output = self.info("system") - d = self._parse_info_system(output) - return namedtuple('System', d.keys())(*d.values()) - - @property - def communication(self): - """ - The communication state of this LAMMPS instance - - :getter: Returns an object with properties storing the current communication state - :type: namedtuple - """ - output = self.info("communication") - d = self._parse_info_communication(output) - return namedtuple('Communication', d.keys())(*d.values()) - - @property - def computes(self): - """ - The list of active computes of this LAMMPS instance - - :getter: Returns a list of computes that are currently active in this LAMMPS instance - :type: list - """ - output = self.info("computes") - return self._parse_element_list(output) - - @property - def dumps(self): - """ - The list of active dumps of this LAMMPS instance - - :getter: Returns a list of dumps that are currently active in this LAMMPS instance - :type: list - """ - output = self.info("dumps") - return self._parse_element_list(output) - - @property - def fixes(self): - """ - The list of active fixes of this LAMMPS instance - - :getter: Returns a list of fixes that are currently active in this LAMMPS instance - :type: list - """ - output = self.info("fixes") - return self._parse_element_list(output) - - @property - def groups(self): - """ - The list of active atom groups of this LAMMPS instance - - :getter: Returns a list of atom groups that are currently active in this LAMMPS instance - :type: list - """ - output = self.info("groups") - return self._parse_groups(output) - - @property - def variables(self): - """ - Returns a dictionary of all variables defined in the current LAMMPS instance - - :getter: Returns a dictionary of all variables that are defined in this LAMMPS instance - :type: dict - """ - output = self.info("variables") - vars = {} - for v in self._parse_element_list(output): - vars[v['name']] = Variable(self, v['name'], v['style'], v['def']) - return vars - - def eval(self, expr): - """ - Evaluate expression - - :param expr: the expression string that should be evaluated inside of LAMMPS - :type expr: string - - :return: the value of the evaluated expression - :rtype: float if numeric, string otherwise - """ - value = self.lmp_print('"$(%s)"' % expr).strip() - try: - return float(value) - except ValueError: - return value - - def _split_values(self, line): - return [x.strip() for x in line.split(',')] - - def _get_pair(self, value): - return [x.strip() for x in value.split('=')] - - def _parse_info_system(self, output): - lines = output[6:-2] - system = {} - - for line in lines: - if line.startswith("Units"): - system['units'] = self._get_pair(line)[1] - elif line.startswith("Atom style"): - system['atom_style'] = self._get_pair(line)[1] - elif line.startswith("Atom map"): - system['atom_map'] = self._get_pair(line)[1] - elif line.startswith("Atoms"): - parts = self._split_values(line) - system['natoms'] = int(self._get_pair(parts[0])[1]) - system['ntypes'] = int(self._get_pair(parts[1])[1]) - system['style'] = self._get_pair(parts[2])[1] - elif line.startswith("Kspace style"): - system['kspace_style'] = self._get_pair(line)[1] - elif line.startswith("Dimensions"): - system['dimensions'] = int(self._get_pair(line)[1]) - elif line.startswith("Orthogonal box"): - system['orthogonal_box'] = [float(x) for x in self._get_pair(line)[1].split('x')] - elif line.startswith("Boundaries"): - system['boundaries'] = self._get_pair(line)[1] - elif line.startswith("xlo"): - keys, values = [self._split_values(x) for x in self._get_pair(line)] - for key, value in zip(keys, values): - system[key] = float(value) - elif line.startswith("ylo"): - keys, values = [self._split_values(x) for x in self._get_pair(line)] - for key, value in zip(keys, values): - system[key] = float(value) - elif line.startswith("zlo"): - keys, values = [self._split_values(x) for x in self._get_pair(line)] - for key, value in zip(keys, values): - system[key] = float(value) - elif line.startswith("Molecule type"): - system['molecule_type'] = self._get_pair(line)[1] - elif line.startswith("Bonds"): - parts = self._split_values(line) - system['nbonds'] = int(self._get_pair(parts[0])[1]) - system['nbondtypes'] = int(self._get_pair(parts[1])[1]) - system['bond_style'] = self._get_pair(parts[2])[1] - elif line.startswith("Angles"): - parts = self._split_values(line) - system['nangles'] = int(self._get_pair(parts[0])[1]) - system['nangletypes'] = int(self._get_pair(parts[1])[1]) - system['angle_style'] = self._get_pair(parts[2])[1] - elif line.startswith("Dihedrals"): - parts = self._split_values(line) - system['ndihedrals'] = int(self._get_pair(parts[0])[1]) - system['ndihedraltypes'] = int(self._get_pair(parts[1])[1]) - system['dihedral_style'] = self._get_pair(parts[2])[1] - elif line.startswith("Impropers"): - parts = self._split_values(line) - system['nimpropers'] = int(self._get_pair(parts[0])[1]) - system['nimpropertypes'] = int(self._get_pair(parts[1])[1]) - system['improper_style'] = self._get_pair(parts[2])[1] - - return system - - def _parse_info_communication(self, output): - lines = output[6:-3] - comm = {} - - for line in lines: - if line.startswith("MPI library"): - comm['mpi_version'] = line.split(':')[1].strip() - elif line.startswith("Comm style"): - parts = self._split_values(line) - comm['comm_style'] = self._get_pair(parts[0])[1] - comm['comm_layout'] = self._get_pair(parts[1])[1] - elif line.startswith("Processor grid"): - comm['proc_grid'] = [int(x) for x in self._get_pair(line)[1].split('x')] - elif line.startswith("Communicate velocities for ghost atoms"): - comm['ghost_velocity'] = (self._get_pair(line)[1] == "yes") - elif line.startswith("Nprocs"): - parts = self._split_values(line) - comm['nprocs'] = int(self._get_pair(parts[0])[1]) - comm['nthreads'] = int(self._get_pair(parts[1])[1]) - return comm - - def _parse_element_list(self, output): - lines = output[6:-3] - elements = [] - - for line in lines: - element_info = self._split_values(line.split(':')[1].strip()) - element = {'name': element_info[0]} - for key, value in [self._get_pair(x) for x in element_info[1:]]: - element[key] = value - elements.append(element) - return elements - - def _parse_groups(self, output): - lines = output[6:-3] - groups = [] - group_pattern = re.compile(r"(?P.+) \((?P.+)\)") - - for line in lines: - m = group_pattern.match(line.split(':')[1].strip()) - group = {'name': m.group('name'), 'type': m.group('type')} - groups.append(group) - return groups - - def lmp_print(self, s): - """ needed for Python2 compatibility, since print is a reserved keyword """ - return self.__getattr__("print")(s) - - def __dir__(self): - return ['angle_coeff', 'angle_style', 'atom_modify', 'atom_style', 'atom_style', - 'bond_coeff', 'bond_style', 'boundary', 'change_box', 'communicate', 'compute', - 'create_atoms', 'create_box', 'delete_atoms', 'delete_bonds', 'dielectric', - 'dihedral_coeff', 'dihedral_style', 'dimension', 'dump', 'fix', 'fix_modify', - 'group', 'improper_coeff', 'improper_style', 'include', 'kspace_modify', - 'kspace_style', 'lattice', 'mass', 'minimize', 'min_style', 'neighbor', - 'neigh_modify', 'newton', 'nthreads', 'pair_coeff', 'pair_modify', - 'pair_style', 'processors', 'read', 'read_data', 'read_restart', 'region', - 'replicate', 'reset_timestep', 'restart', 'run', 'run_style', 'thermo', - 'thermo_modify', 'thermo_style', 'timestep', 'undump', 'unfix', 'units', - 'variable', 'velocity', 'write_restart'] - - def __getattr__(self, name): - """ - This method is where the Python 'magic' happens. If a method is not - defined by the class PyLammps, it assumes it is a LAMMPS command. It takes - all the arguments, concatinates them to a single string, and executes it using - :py:meth:`lammps.PyLammps.command()`. - - :param verbose: Print output of command - :type verbose: bool - :return: line or list of lines of output, None if no output - :rtype: list or string - """ - def handler(*args, **kwargs): - cmd_args = [name] + [str(x) for x in args] - - with OutputCapture() as capture: - cmd = ' '.join(cmd_args) - self.command(cmd) - output = capture.output - - if 'verbose' in kwargs and kwargs['verbose']: - print(output) - - lines = output.splitlines() - - if self.has_echo: - lines = lines[1:] - - if len(lines) > 1: - return lines - elif len(lines) == 1: - return lines[0] - return None - - return handler - - -class IPyLammps(PyLammps): - """ - IPython wrapper for LAMMPS which adds embedded graphics capabilities to PyLammmps interface - - It either creates its own instance of :py:class:`lammps` or can be - initialized with an existing instance. The arguments are the same of the - lower-level interface. The original interface can still be accessed via - :py:attr:`PyLammps.lmp`. - - :param name: "machine" name of the shared LAMMPS library ("mpi" loads ``liblammps_mpi.so``, "" loads ``liblammps.so``) - :type name: string - :param cmdargs: list of command line arguments to be passed to the :cpp:func:`lammps_open` function. The executable name is automatically added. - :type cmdargs: list - :param ptr: pointer to a LAMMPS C++ class instance when called from an embedded Python interpreter. None means load symbols from shared library. - :type ptr: pointer - :param comm: MPI communicator (as provided by `mpi4py `_). ``None`` means use ``MPI_COMM_WORLD`` implicitly. - :type comm: MPI_Comm - """ - - def __init__(self,name="",cmdargs=None,ptr=None,comm=None): - super(IPyLammps, self).__init__(name=name,cmdargs=cmdargs,ptr=ptr,comm=comm) - - def image(self, filename="snapshot.png", group="all", color="type", diameter="type", - size=None, view=None, center=None, up=None, zoom=1.0, background_color="white"): - """ Generate image using write_dump command and display it - - See :doc:`dump image ` for more information. - - :param filename: Name of the image file that should be generated. The extension determines whether it is PNG or JPEG - :type filename: string - :param group: the group of atoms write_image should use - :type group: string - :param color: name of property used to determine color - :type color: string - :param diameter: name of property used to determine atom diameter - :type diameter: string - :param size: dimensions of image - :type size: tuple (width, height) - :param view: view parameters - :type view: tuple (theta, phi) - :param center: center parameters - :type center: tuple (flag, center_x, center_y, center_z) - :param up: vector pointing to up direction - :type up: tuple (up_x, up_y, up_z) - :param zoom: zoom factor - :type zoom: float - :param background_color: background color of scene - :type background_color: string - - :return: Image instance used to display image in notebook - :rtype: :py:class:`IPython.core.display.Image` - """ - cmd_args = [group, "image", filename, color, diameter] - - if size: - width = size[0] - height = size[1] - cmd_args += ["size", width, height] - - if view: - theta = view[0] - phi = view[1] - cmd_args += ["view", theta, phi] - - if center: - flag = center[0] - Cx = center[1] - Cy = center[2] - Cz = center[3] - cmd_args += ["center", flag, Cx, Cy, Cz] - - if up: - Ux = up[0] - Uy = up[1] - Uz = up[2] - cmd_args += ["up", Ux, Uy, Uz] - - if zoom: - cmd_args += ["zoom", zoom] - - cmd_args.append("modify backcolor " + background_color) - - self.write_dump(*cmd_args) - from IPython.core.display import Image - return Image(filename) - - def video(self, filename): - """ - Load video from file - - Can be used to visualize videos from :doc:`dump movie `. - - :param filename: Path to video file - :type filename: string - :return: HTML Video Tag used by notebook to embed a video - :rtype: :py:class:`IPython.display.HTML` - """ - from IPython.display import HTML - return HTML("") diff --git a/python/lammps/pylammps.py b/python/lammps/pylammps.py new file mode 100644 index 0000000000..007c771308 --- /dev/null +++ b/python/lammps/pylammps.py @@ -0,0 +1,870 @@ +# ---------------------------------------------------------------------- +# LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator +# http://lammps.sandia.gov, Sandia National Laboratories +# Steve Plimpton, sjplimp@sandia.gov +# +# Copyright (2003) Sandia Corporation. Under the terms of Contract +# DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains +# certain rights in this software. This software is distributed under +# the GNU General Public License. +# +# See the README file in the top-level LAMMPS directory. +# ------------------------------------------------------------------------- + +################################################################################ +# Alternative Python Wrapper +# Written by Richard Berger +################################################################################ + +# for python2/3 compatibility + +from __future__ import print_function + +# imports for simple LAMMPS python wrapper module "lammps" + +import sys,traceback,types +import warnings +from ctypes import * +from os.path import dirname,abspath,join +from inspect import getsourcefile + +# imports for advanced LAMMPS python wrapper modules "PyLammps" and "IPyLammps" + +from collections import namedtuple +import os +import select +import re +import sys + +from .core import lammps + +class OutputCapture(object): + """ Utility class to capture LAMMPS library output """ + + def __init__(self): + self.stdout_pipe_read, self.stdout_pipe_write = os.pipe() + self.stdout_fd = 1 + + def __enter__(self): + self.stdout = os.dup(self.stdout_fd) + os.dup2(self.stdout_pipe_write, self.stdout_fd) + return self + + def __exit__(self, type, value, tracebac): + os.dup2(self.stdout, self.stdout_fd) + os.close(self.stdout) + os.close(self.stdout_pipe_read) + os.close(self.stdout_pipe_write) + + # check if we have more to read from the pipe + def more_data(self, pipe): + r, _, _ = select.select([pipe], [], [], 0) + return bool(r) + + # read the whole pipe + def read_pipe(self, pipe): + out = "" + while self.more_data(pipe): + out += os.read(pipe, 1024).decode() + return out + + @property + def output(self): + return self.read_pipe(self.stdout_pipe_read) + +# ------------------------------------------------------------------------- + +class Variable(object): + def __init__(self, pylammps_instance, name, style, definition): + self._pylmp = pylammps_instance + self.name = name + self.style = style + self.definition = definition.split() + + @property + def value(self): + if self.style == 'atom': + return list(self._pylmp.lmp.extract_variable(self.name, "all", 1)) + else: + value = self._pylmp.lmp_print('"${%s}"' % self.name).strip() + try: + return float(value) + except ValueError: + return value + +# ------------------------------------------------------------------------- + +class AtomList(object): + """ + A dynamic list of atoms that returns either an :py:class:`Atom` or + :py:class:`Atom2D` instance for each atom. Instances are only allocated + when accessed. + + :ivar natoms: total number of atoms + :ivar dimensions: number of dimensions in system + """ + def __init__(self, pylammps_instance): + self._pylmp = pylammps_instance + self.natoms = self._pylmp.system.natoms + self.dimensions = self._pylmp.system.dimensions + self._loaded = {} + + def __getitem__(self, index): + """ + Return Atom with given local index + + :param index: Local index of atom + :type index: int + :rtype: Atom or Atom2D + """ + if index not in self._loaded: + if self.dimensions == 2: + atom = Atom2D(self._pylmp, index + 1) + else: + atom = Atom(self._pylmp, index + 1) + self._loaded[index] = atom + return self._loaded[index] + + def __len__(self): + return self.natoms + + +# ------------------------------------------------------------------------- + +class Atom(object): + """ + A wrapper class then represents a single atom inside of LAMMPS + + It provides access to properties of the atom and allows you to change some of them. + """ + def __init__(self, pylammps_instance, index): + self._pylmp = pylammps_instance + self.index = index + + @property + def id(self): + """ + Return the atom ID + + :type: int + """ + return int(self._pylmp.eval("id[%d]" % self.index)) + + @property + def type(self): + """ + Return the atom type + + :type: int + """ + return int(self._pylmp.eval("type[%d]" % self.index)) + + @property + def mol(self): + """ + Return the atom molecule index + + :type: int + """ + return self._pylmp.eval("mol[%d]" % self.index) + + @property + def mass(self): + """ + Return the atom mass + + :type: float + """ + return self._pylmp.eval("mass[%d]" % self.index) + + @property + def position(self): + """ + :getter: Return position of atom + :setter: Set position of atom + :type: tuple (float, float, float) + """ + return (self._pylmp.eval("x[%d]" % self.index), + self._pylmp.eval("y[%d]" % self.index), + self._pylmp.eval("z[%d]" % self.index)) + + @position.setter + def position(self, value): + """ + :getter: Return velocity of atom + :setter: Set velocity of atom + :type: tuple (float, float, float) + """ + self._pylmp.set("atom", self.index, "x", value[0]) + self._pylmp.set("atom", self.index, "y", value[1]) + self._pylmp.set("atom", self.index, "z", value[2]) + + @property + def velocity(self): + return (self._pylmp.eval("vx[%d]" % self.index), + self._pylmp.eval("vy[%d]" % self.index), + self._pylmp.eval("vz[%d]" % self.index)) + + @velocity.setter + def velocity(self, value): + self._pylmp.set("atom", self.index, "vx", value[0]) + self._pylmp.set("atom", self.index, "vy", value[1]) + self._pylmp.set("atom", self.index, "vz", value[2]) + + @property + def force(self): + """ + Return the total force acting on the atom + + :type: tuple (float, float, float) + """ + return (self._pylmp.eval("fx[%d]" % self.index), + self._pylmp.eval("fy[%d]" % self.index), + self._pylmp.eval("fz[%d]" % self.index)) + + @property + def charge(self): + """ + Return the atom charge + + :type: float + """ + return self._pylmp.eval("q[%d]" % self.index) + +# ------------------------------------------------------------------------- + +class Atom2D(Atom): + """ + A wrapper class then represents a single 2D atom inside of LAMMPS + + Inherits all properties from the :py:class:`Atom` class, but returns 2D versions + of position, velocity, and force. + + It provides access to properties of the atom and allows you to change some of them. + """ + def __init__(self, pylammps_instance, index): + super(Atom2D, self).__init__(pylammps_instance, index) + + @property + def position(self): + """ + :getter: Return position of atom + :setter: Set position of atom + :type: tuple (float, float) + """ + return (self._pylmp.eval("x[%d]" % self.index), + self._pylmp.eval("y[%d]" % self.index)) + + @position.setter + def position(self, value): + self._pylmp.set("atom", self.index, "x", value[0]) + self._pylmp.set("atom", self.index, "y", value[1]) + + @property + def velocity(self): + """ + :getter: Return velocity of atom + :setter: Set velocity of atom + :type: tuple (float, float) + """ + return (self._pylmp.eval("vx[%d]" % self.index), + self._pylmp.eval("vy[%d]" % self.index)) + + @velocity.setter + def velocity(self, value): + self._pylmp.set("atom", self.index, "vx", value[0]) + self._pylmp.set("atom", self.index, "vy", value[1]) + + @property + def force(self): + """ + Return the total force acting on the atom + + :type: tuple (float, float) + """ + return (self._pylmp.eval("fx[%d]" % self.index), + self._pylmp.eval("fy[%d]" % self.index)) + +# ------------------------------------------------------------------------- + +class variable_set: + def __init__(self, name, variable_dict): + self._name = name + array_pattern = re.compile(r"(?P.+)\[(?P[0-9]+)\]") + + for key, value in variable_dict.items(): + m = array_pattern.match(key) + if m: + g = m.groupdict() + varname = g['arr'] + idx = int(g['index']) + if varname not in self.__dict__: + self.__dict__[varname] = {} + self.__dict__[varname][idx] = value + else: + self.__dict__[key] = value + + def __str__(self): + return "{}({})".format(self._name, ','.join(["{}={}".format(k, self.__dict__[k]) for k in self.__dict__.keys() if not k.startswith('_')])) + + def __repr__(self): + return self.__str__() + +# ------------------------------------------------------------------------- + +def get_thermo_data(output): + """ traverse output of runs and extract thermo data columns """ + if isinstance(output, str): + lines = output.splitlines() + else: + lines = output + + runs = [] + columns = [] + in_run = False + current_run = {} + + for line in lines: + if line.startswith("Per MPI rank memory allocation"): + in_run = True + elif in_run and len(columns) == 0: + # first line after memory usage are column names + columns = line.split() + + current_run = {} + + for col in columns: + current_run[col] = [] + + elif line.startswith("Loop time of "): + in_run = False + columns = None + thermo_data = variable_set('ThermoData', current_run) + r = {'thermo' : thermo_data } + runs.append(namedtuple('Run', list(r.keys()))(*list(r.values()))) + elif in_run and len(columns) > 0: + items = line.split() + # Convert thermo output and store it. + # It must have the same number of columns and + # all of them must be convertible to floats. + # Otherwise we ignore the line + if len(items) == len(columns): + try: + values = [float(x) for x in items] + for i, col in enumerate(columns): + current_run[col].append(values[i]) + except ValueError: + pass + + return runs + +# ------------------------------------------------------------------------- +# ------------------------------------------------------------------------- + +class PyLammps(object): + """ + This is a Python wrapper class around the lower-level + :py:class:`lammps` class, exposing a more Python-like, + object-oriented interface for prototyping system inside of IPython and + Jupyter notebooks. + + It either creates its own instance of :py:class:`lammps` or can be + initialized with an existing instance. The arguments are the same of the + lower-level interface. The original interface can still be accessed via + :py:attr:`PyLammps.lmp`. + + :param name: "machine" name of the shared LAMMPS library ("mpi" loads ``liblammps_mpi.so``, "" loads ``liblammps.so``) + :type name: string + :param cmdargs: list of command line arguments to be passed to the :cpp:func:`lammps_open` function. The executable name is automatically added. + :type cmdargs: list + :param ptr: pointer to a LAMMPS C++ class instance when called from an embedded Python interpreter. None means load symbols from shared library. + :type ptr: pointer + :param comm: MPI communicator (as provided by `mpi4py `_). ``None`` means use ``MPI_COMM_WORLD`` implicitly. + :type comm: MPI_Comm + + :ivar lmp: instance of original LAMMPS Python interface + :vartype lmp: :py:class:`lammps` + + :ivar runs: list of completed runs, each storing the thermo output + :vartype run: list + """ + + def __init__(self, name="", cmdargs=None, ptr=None, comm=None): + self.has_echo = False + + if cmdargs: + if '-echo' in cmdargs: + idx = cmdargs.index('-echo') + # ensures that echo line is ignored during output capture + self.has_echo = idx+1 < len(cmdargs) and cmdargs[idx+1] in ('screen', 'both') + + if ptr: + if isinstance(ptr,PyLammps): + self.lmp = ptr.lmp + elif isinstance(ptr,lammps): + self.lmp = ptr + else: + self.lmp = lammps(name=name,cmdargs=cmdargs,ptr=ptr,comm=comm) + else: + self.lmp = lammps(name=name,cmdargs=cmdargs,ptr=None,comm=comm) + print("LAMMPS output is captured by PyLammps wrapper") + self._cmd_history = [] + self.runs = [] + + def __del__(self): + if self.lmp: self.lmp.close() + self.lmp = None + + def close(self): + """Explicitly delete a LAMMPS instance + + This is a wrapper around the :py:meth:`lammps.close` of the Python interface. + """ + if self.lmp: self.lmp.close() + self.lmp = None + + def version(self): + """Return a numerical representation of the LAMMPS version in use. + + This is a wrapper around the :py:meth:`lammps.version` function of the Python interface. + + :return: version number + :rtype: int + """ + return self.lmp.version() + + def file(self, file): + """Read LAMMPS commands from a file. + + This is a wrapper around the :py:meth:`lammps.file` function of the Python interface. + + :param path: Name of the file/path with LAMMPS commands + :type path: string + """ + self.lmp.file(file) + + def write_script(self, filepath): + """ + Write LAMMPS script file containing all commands executed up until now + + :param filepath: path to script file that should be written + :type filepath: string + """ + with open(filepath, "w") as f: + for cmd in self._cmd_history: + print(cmd, file=f) + + def command(self, cmd): + """ + Execute LAMMPS command + + All commands executed will be stored in a command history which can be + written to a file using :py:meth:`PyLammps.write_script()` + + :param cmd: command string that should be executed + :type: cmd: string + """ + self.lmp.command(cmd) + self._cmd_history.append(cmd) + + def run(self, *args, **kwargs): + """ + Execute LAMMPS run command with given arguments + + All thermo output during the run is captured and saved as new entry in + :py:attr:`PyLammps.runs`. The latest run can be retrieved by + :py:attr:`PyLammps.last_run`. + """ + output = self.__getattr__('run')(*args, **kwargs) + + comm = self.lmp.get_mpi_comm() + if comm: + output = self.lmp.comm.bcast(output, root=0) + + self.runs += get_thermo_data(output) + return output + + @property + def last_run(self): + """ + Return data produced of last completed run command + + :getter: Returns an object containing information about the last run command + :type: dict + """ + if len(self.runs) > 0: + return self.runs[-1] + return None + + @property + def atoms(self): + """ + All atoms of this LAMMPS instance + + :getter: Returns a list of atoms currently in the system + :type: AtomList + """ + return AtomList(self) + + @property + def system(self): + """ + The system state of this LAMMPS instance + + :getter: Returns an object with properties storing the current system state + :type: namedtuple + """ + output = self.info("system") + d = self._parse_info_system(output) + return namedtuple('System', d.keys())(*d.values()) + + @property + def communication(self): + """ + The communication state of this LAMMPS instance + + :getter: Returns an object with properties storing the current communication state + :type: namedtuple + """ + output = self.info("communication") + d = self._parse_info_communication(output) + return namedtuple('Communication', d.keys())(*d.values()) + + @property + def computes(self): + """ + The list of active computes of this LAMMPS instance + + :getter: Returns a list of computes that are currently active in this LAMMPS instance + :type: list + """ + output = self.info("computes") + return self._parse_element_list(output) + + @property + def dumps(self): + """ + The list of active dumps of this LAMMPS instance + + :getter: Returns a list of dumps that are currently active in this LAMMPS instance + :type: list + """ + output = self.info("dumps") + return self._parse_element_list(output) + + @property + def fixes(self): + """ + The list of active fixes of this LAMMPS instance + + :getter: Returns a list of fixes that are currently active in this LAMMPS instance + :type: list + """ + output = self.info("fixes") + return self._parse_element_list(output) + + @property + def groups(self): + """ + The list of active atom groups of this LAMMPS instance + + :getter: Returns a list of atom groups that are currently active in this LAMMPS instance + :type: list + """ + output = self.info("groups") + return self._parse_groups(output) + + @property + def variables(self): + """ + Returns a dictionary of all variables defined in the current LAMMPS instance + + :getter: Returns a dictionary of all variables that are defined in this LAMMPS instance + :type: dict + """ + output = self.info("variables") + vars = {} + for v in self._parse_element_list(output): + vars[v['name']] = Variable(self, v['name'], v['style'], v['def']) + return vars + + def eval(self, expr): + """ + Evaluate expression + + :param expr: the expression string that should be evaluated inside of LAMMPS + :type expr: string + + :return: the value of the evaluated expression + :rtype: float if numeric, string otherwise + """ + value = self.lmp_print('"$(%s)"' % expr).strip() + try: + return float(value) + except ValueError: + return value + + def _split_values(self, line): + return [x.strip() for x in line.split(',')] + + def _get_pair(self, value): + return [x.strip() for x in value.split('=')] + + def _parse_info_system(self, output): + lines = output[6:-2] + system = {} + + for line in lines: + if line.startswith("Units"): + system['units'] = self._get_pair(line)[1] + elif line.startswith("Atom style"): + system['atom_style'] = self._get_pair(line)[1] + elif line.startswith("Atom map"): + system['atom_map'] = self._get_pair(line)[1] + elif line.startswith("Atoms"): + parts = self._split_values(line) + system['natoms'] = int(self._get_pair(parts[0])[1]) + system['ntypes'] = int(self._get_pair(parts[1])[1]) + system['style'] = self._get_pair(parts[2])[1] + elif line.startswith("Kspace style"): + system['kspace_style'] = self._get_pair(line)[1] + elif line.startswith("Dimensions"): + system['dimensions'] = int(self._get_pair(line)[1]) + elif line.startswith("Orthogonal box"): + system['orthogonal_box'] = [float(x) for x in self._get_pair(line)[1].split('x')] + elif line.startswith("Boundaries"): + system['boundaries'] = self._get_pair(line)[1] + elif line.startswith("xlo"): + keys, values = [self._split_values(x) for x in self._get_pair(line)] + for key, value in zip(keys, values): + system[key] = float(value) + elif line.startswith("ylo"): + keys, values = [self._split_values(x) for x in self._get_pair(line)] + for key, value in zip(keys, values): + system[key] = float(value) + elif line.startswith("zlo"): + keys, values = [self._split_values(x) for x in self._get_pair(line)] + for key, value in zip(keys, values): + system[key] = float(value) + elif line.startswith("Molecule type"): + system['molecule_type'] = self._get_pair(line)[1] + elif line.startswith("Bonds"): + parts = self._split_values(line) + system['nbonds'] = int(self._get_pair(parts[0])[1]) + system['nbondtypes'] = int(self._get_pair(parts[1])[1]) + system['bond_style'] = self._get_pair(parts[2])[1] + elif line.startswith("Angles"): + parts = self._split_values(line) + system['nangles'] = int(self._get_pair(parts[0])[1]) + system['nangletypes'] = int(self._get_pair(parts[1])[1]) + system['angle_style'] = self._get_pair(parts[2])[1] + elif line.startswith("Dihedrals"): + parts = self._split_values(line) + system['ndihedrals'] = int(self._get_pair(parts[0])[1]) + system['ndihedraltypes'] = int(self._get_pair(parts[1])[1]) + system['dihedral_style'] = self._get_pair(parts[2])[1] + elif line.startswith("Impropers"): + parts = self._split_values(line) + system['nimpropers'] = int(self._get_pair(parts[0])[1]) + system['nimpropertypes'] = int(self._get_pair(parts[1])[1]) + system['improper_style'] = self._get_pair(parts[2])[1] + + return system + + def _parse_info_communication(self, output): + lines = output[6:-3] + comm = {} + + for line in lines: + if line.startswith("MPI library"): + comm['mpi_version'] = line.split(':')[1].strip() + elif line.startswith("Comm style"): + parts = self._split_values(line) + comm['comm_style'] = self._get_pair(parts[0])[1] + comm['comm_layout'] = self._get_pair(parts[1])[1] + elif line.startswith("Processor grid"): + comm['proc_grid'] = [int(x) for x in self._get_pair(line)[1].split('x')] + elif line.startswith("Communicate velocities for ghost atoms"): + comm['ghost_velocity'] = (self._get_pair(line)[1] == "yes") + elif line.startswith("Nprocs"): + parts = self._split_values(line) + comm['nprocs'] = int(self._get_pair(parts[0])[1]) + comm['nthreads'] = int(self._get_pair(parts[1])[1]) + return comm + + def _parse_element_list(self, output): + lines = output[6:-3] + elements = [] + + for line in lines: + element_info = self._split_values(line.split(':')[1].strip()) + element = {'name': element_info[0]} + for key, value in [self._get_pair(x) for x in element_info[1:]]: + element[key] = value + elements.append(element) + return elements + + def _parse_groups(self, output): + lines = output[6:-3] + groups = [] + group_pattern = re.compile(r"(?P.+) \((?P.+)\)") + + for line in lines: + m = group_pattern.match(line.split(':')[1].strip()) + group = {'name': m.group('name'), 'type': m.group('type')} + groups.append(group) + return groups + + def lmp_print(self, s): + """ needed for Python2 compatibility, since print is a reserved keyword """ + return self.__getattr__("print")(s) + + def __dir__(self): + return ['angle_coeff', 'angle_style', 'atom_modify', 'atom_style', 'atom_style', + 'bond_coeff', 'bond_style', 'boundary', 'change_box', 'communicate', 'compute', + 'create_atoms', 'create_box', 'delete_atoms', 'delete_bonds', 'dielectric', + 'dihedral_coeff', 'dihedral_style', 'dimension', 'dump', 'fix', 'fix_modify', + 'group', 'improper_coeff', 'improper_style', 'include', 'kspace_modify', + 'kspace_style', 'lattice', 'mass', 'minimize', 'min_style', 'neighbor', + 'neigh_modify', 'newton', 'nthreads', 'pair_coeff', 'pair_modify', + 'pair_style', 'processors', 'read', 'read_data', 'read_restart', 'region', + 'replicate', 'reset_timestep', 'restart', 'run', 'run_style', 'thermo', + 'thermo_modify', 'thermo_style', 'timestep', 'undump', 'unfix', 'units', + 'variable', 'velocity', 'write_restart'] + + def __getattr__(self, name): + """ + This method is where the Python 'magic' happens. If a method is not + defined by the class PyLammps, it assumes it is a LAMMPS command. It takes + all the arguments, concatinates them to a single string, and executes it using + :py:meth:`lammps.PyLammps.command()`. + + :param verbose: Print output of command + :type verbose: bool + :return: line or list of lines of output, None if no output + :rtype: list or string + """ + def handler(*args, **kwargs): + cmd_args = [name] + [str(x) for x in args] + + with OutputCapture() as capture: + cmd = ' '.join(cmd_args) + self.command(cmd) + output = capture.output + + if 'verbose' in kwargs and kwargs['verbose']: + print(output) + + lines = output.splitlines() + + if self.has_echo: + lines = lines[1:] + + if len(lines) > 1: + return lines + elif len(lines) == 1: + return lines[0] + return None + + return handler + + +class IPyLammps(PyLammps): + """ + IPython wrapper for LAMMPS which adds embedded graphics capabilities to PyLammmps interface + + It either creates its own instance of :py:class:`lammps` or can be + initialized with an existing instance. The arguments are the same of the + lower-level interface. The original interface can still be accessed via + :py:attr:`PyLammps.lmp`. + + :param name: "machine" name of the shared LAMMPS library ("mpi" loads ``liblammps_mpi.so``, "" loads ``liblammps.so``) + :type name: string + :param cmdargs: list of command line arguments to be passed to the :cpp:func:`lammps_open` function. The executable name is automatically added. + :type cmdargs: list + :param ptr: pointer to a LAMMPS C++ class instance when called from an embedded Python interpreter. None means load symbols from shared library. + :type ptr: pointer + :param comm: MPI communicator (as provided by `mpi4py `_). ``None`` means use ``MPI_COMM_WORLD`` implicitly. + :type comm: MPI_Comm + """ + + def __init__(self,name="",cmdargs=None,ptr=None,comm=None): + super(IPyLammps, self).__init__(name=name,cmdargs=cmdargs,ptr=ptr,comm=comm) + + def image(self, filename="snapshot.png", group="all", color="type", diameter="type", + size=None, view=None, center=None, up=None, zoom=1.0, background_color="white"): + """ Generate image using write_dump command and display it + + See :doc:`dump image ` for more information. + + :param filename: Name of the image file that should be generated. The extension determines whether it is PNG or JPEG + :type filename: string + :param group: the group of atoms write_image should use + :type group: string + :param color: name of property used to determine color + :type color: string + :param diameter: name of property used to determine atom diameter + :type diameter: string + :param size: dimensions of image + :type size: tuple (width, height) + :param view: view parameters + :type view: tuple (theta, phi) + :param center: center parameters + :type center: tuple (flag, center_x, center_y, center_z) + :param up: vector pointing to up direction + :type up: tuple (up_x, up_y, up_z) + :param zoom: zoom factor + :type zoom: float + :param background_color: background color of scene + :type background_color: string + + :return: Image instance used to display image in notebook + :rtype: :py:class:`IPython.core.display.Image` + """ + cmd_args = [group, "image", filename, color, diameter] + + if size: + width = size[0] + height = size[1] + cmd_args += ["size", width, height] + + if view: + theta = view[0] + phi = view[1] + cmd_args += ["view", theta, phi] + + if center: + flag = center[0] + Cx = center[1] + Cy = center[2] + Cz = center[3] + cmd_args += ["center", flag, Cx, Cy, Cz] + + if up: + Ux = up[0] + Uy = up[1] + Uz = up[2] + cmd_args += ["up", Ux, Uy, Uz] + + if zoom: + cmd_args += ["zoom", zoom] + + cmd_args.append("modify backcolor " + background_color) + + self.write_dump(*cmd_args) + from IPython.core.display import Image + return Image(filename) + + def video(self, filename): + """ + Load video from file + + Can be used to visualize videos from :doc:`dump movie `. + + :param filename: Path to video file + :type filename: string + :return: HTML Video Tag used by notebook to embed a video + :rtype: :py:class:`IPython.display.HTML` + """ + from IPython.display import HTML + return HTML("") From 9e188a381867e915ddda5c78131d53064716656a Mon Sep 17 00:00:00 2001 From: Richard Berger Date: Tue, 15 Dec 2020 16:19:23 -0500 Subject: [PATCH 25/44] Clean up imports --- python/lammps/pylammps.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/python/lammps/pylammps.py b/python/lammps/pylammps.py index 007c771308..1ec45d43b5 100644 --- a/python/lammps/pylammps.py +++ b/python/lammps/pylammps.py @@ -20,24 +20,15 @@ from __future__ import print_function -# imports for simple LAMMPS python wrapper module "lammps" - -import sys,traceback,types -import warnings -from ctypes import * -from os.path import dirname,abspath,join -from inspect import getsourcefile - -# imports for advanced LAMMPS python wrapper modules "PyLammps" and "IPyLammps" - -from collections import namedtuple import os -import select import re +import select import sys +from collections import namedtuple from .core import lammps + class OutputCapture(object): """ Utility class to capture LAMMPS library output """ From df58a1fc5fccf5edb052d7a03029d581fb11259c Mon Sep 17 00:00:00 2001 From: Yaser Afshar Date: Tue, 15 Dec 2020 15:22:24 -0600 Subject: [PATCH 26/44] Update the eflag_global & eflag_atom Update the eflag_global & eflag_atom use based on the flag use in LAMMPS. --- src/KIM/pair_kim.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/KIM/pair_kim.cpp b/src/KIM/pair_kim.cpp index 7ff067dcac..ad671de5b3 100644 --- a/src/KIM/pair_kim.cpp +++ b/src/KIM/pair_kim.cpp @@ -890,7 +890,7 @@ void PairKIM::set_argument_pointers() KIM_SUPPORT_STATUS_notSupported)) { if (KIM_SupportStatus_Equal(kim_model_support_for_energy, KIM_SUPPORT_STATUS_required) - || (eflag_global == 1)) { + || (eflag_global != 0)) { kimerror = kimerror || KIM_ComputeArguments_SetArgumentPointerDouble( pargs,KIM_COMPUTE_ARGUMENT_NAME_partialEnergy,&(eng_vdwl)); @@ -905,7 +905,7 @@ void PairKIM::set_argument_pointers() // Set KIM pointer appropriately for particalEnergy if (KIM_SupportStatus_Equal(kim_model_support_for_particleEnergy, KIM_SUPPORT_STATUS_required) - && (eflag_atom != 1)) { + && (eflag_atom == 0)) { // reallocate per-atom energy array if necessary if (atom->nmax > maxeatom) { maxeatom = atom->nmax; @@ -916,13 +916,13 @@ void PairKIM::set_argument_pointers() if (KIM_SupportStatus_Equal(kim_model_support_for_particleEnergy, KIM_SUPPORT_STATUS_optional) - && (eflag_atom != 1)) { + && (eflag_atom == 0)) { kimerror = kimerror || KIM_ComputeArguments_SetArgumentPointerDouble( pargs, KIM_COMPUTE_ARGUMENT_NAME_partialParticleEnergy, static_cast(nullptr)); } else if (KIM_SupportStatus_NotEqual(kim_model_support_for_particleEnergy, - KIM_SUPPORT_STATUS_notSupported)) { + KIM_SUPPORT_STATUS_notSupported)) { kimerror = kimerror || KIM_ComputeArguments_SetArgumentPointerDouble( pargs, KIM_COMPUTE_ARGUMENT_NAME_partialParticleEnergy, eatom); } @@ -940,9 +940,9 @@ void PairKIM::set_argument_pointers() } // Set KIM pointer appropriately for particleVirial - if ((vflag_atom == 0) && - KIM_SupportStatus_Equal(kim_model_support_for_particleVirial, - KIM_SUPPORT_STATUS_required)) { + if (KIM_SupportStatus_Equal(kim_model_support_for_particleVirial, + KIM_SUPPORT_STATUS_required) + && (vflag_atom == 0)) { // reallocate per-atom virial array if necessary if (atom->nmax > maxvatom) { maxvatom = atom->nmax; @@ -951,9 +951,9 @@ void PairKIM::set_argument_pointers() } } - if ((vflag_atom == 0) && - KIM_SupportStatus_Equal(kim_model_support_for_particleVirial, - KIM_SUPPORT_STATUS_optional)) { + if (KIM_SupportStatus_Equal(kim_model_support_for_particleVirial, + KIM_SUPPORT_STATUS_optional) + && (vflag_atom == 0)) { kimerror = kimerror || KIM_ComputeArguments_SetArgumentPointerDouble( pargs, KIM_COMPUTE_ARGUMENT_NAME_partialParticleVirial, From 33f9a296399a45ac7c6d6ea74a7b18e58e3fdebc Mon Sep 17 00:00:00 2001 From: Richard Berger Date: Tue, 15 Dec 2020 16:33:21 -0500 Subject: [PATCH 27/44] Split core.py into more files --- python/lammps/__init__.py | 2 + python/lammps/constants.py | 49 +++++ python/lammps/core.py | 412 +------------------------------------ python/lammps/data.py | 73 +++++++ python/lammps/numpy.py | 335 ++++++++++++++++++++++++++++++ 5 files changed, 462 insertions(+), 409 deletions(-) create mode 100644 python/lammps/constants.py create mode 100644 python/lammps/data.py create mode 100644 python/lammps/numpy.py diff --git a/python/lammps/__init__.py b/python/lammps/__init__.py index 37773d84a5..b1c8306617 100644 --- a/python/lammps/__init__.py +++ b/python/lammps/__init__.py @@ -1,2 +1,4 @@ +from .constants import * from .core import * +from .data import * from .pylammps import * diff --git a/python/lammps/constants.py b/python/lammps/constants.py new file mode 100644 index 0000000000..e5504691fe --- /dev/null +++ b/python/lammps/constants.py @@ -0,0 +1,49 @@ +# ---------------------------------------------------------------------- +# LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator +# http://lammps.sandia.gov, Sandia National Laboratories +# Steve Plimpton, sjplimp@sandia.gov +# +# Copyright (2003) Sandia Corporation. Under the terms of Contract +# DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains +# certain rights in this software. This software is distributed under +# the GNU General Public License. +# +# See the README file in the top-level LAMMPS directory. +# ------------------------------------------------------------------------- + +from ctypes import c_int, c_int32, c_int64 + +# various symbolic constants to be used +# in certain calls to select data formats +LAMMPS_AUTODETECT = None +LAMMPS_INT = 0 +LAMMPS_INT_2D = 1 +LAMMPS_DOUBLE = 2 +LAMMPS_DOUBLE_2D = 3 +LAMMPS_INT64 = 4 +LAMMPS_INT64_2D = 5 +LAMMPS_STRING = 6 + +# these must be kept in sync with the enums in library.h +LMP_STYLE_GLOBAL = 0 +LMP_STYLE_ATOM = 1 +LMP_STYLE_LOCAL = 2 + +LMP_TYPE_SCALAR = 0 +LMP_TYPE_VECTOR = 1 +LMP_TYPE_ARRAY = 2 +LMP_SIZE_VECTOR = 3 +LMP_SIZE_ROWS = 4 +LMP_SIZE_COLS = 5 + +LMP_VAR_EQUAL = 0 +LMP_VAR_ATOM = 1 + +# ------------------------------------------------------------------------- + +def get_ctypes_int(size): + if size == 4: + return c_int32 + elif size == 8: + return c_int64 + return c_int diff --git a/python/lammps/core.py b/python/lammps/core.py index 14b727e59a..009409f48d 100644 --- a/python/lammps/core.py +++ b/python/lammps/core.py @@ -25,40 +25,8 @@ from ctypes import * from os.path import dirname,abspath,join from inspect import getsourcefile -# various symbolic constants to be used -# in certain calls to select data formats -LAMMPS_AUTODETECT = None -LAMMPS_INT = 0 -LAMMPS_INT_2D = 1 -LAMMPS_DOUBLE = 2 -LAMMPS_DOUBLE_2D = 3 -LAMMPS_INT64 = 4 -LAMMPS_INT64_2D = 5 -LAMMPS_STRING = 6 - -# these must be kept in sync with the enums in library.h -LMP_STYLE_GLOBAL = 0 -LMP_STYLE_ATOM = 1 -LMP_STYLE_LOCAL = 2 - -LMP_TYPE_SCALAR = 0 -LMP_TYPE_VECTOR = 1 -LMP_TYPE_ARRAY = 2 -LMP_SIZE_VECTOR = 3 -LMP_SIZE_ROWS = 4 -LMP_SIZE_COLS = 5 - -LMP_VAR_EQUAL = 0 -LMP_VAR_ATOM = 1 - -# ------------------------------------------------------------------------- - -def get_ctypes_int(size): - if size == 4: - return c_int32 - elif size == 8: - return c_int64 - return c_int +from .constants import * +from .data import * # ------------------------------------------------------------------------- @@ -71,94 +39,6 @@ class MPIAbortException(Exception): # ------------------------------------------------------------------------- -class NeighList: - """This is a wrapper class that exposes the contents of a neighbor list. - - It can be used like a regular Python list. Each element is a tuple of: - - * the atom local index - * its number of neighbors - * and a pointer to an c_int array containing local atom indices of its - neighbors - - Internally it uses the lower-level LAMMPS C-library interface. - - :param lmp: reference to instance of :py:class:`lammps` - :type lmp: lammps - :param idx: neighbor list index - :type idx: int - """ - def __init__(self, lmp, idx): - self.lmp = lmp - self.idx = idx - - def __str__(self): - return "Neighbor List ({} atoms)".format(self.size) - - def __repr__(self): - return self.__str__() - - @property - def size(self): - """ - :return: number of elements in neighbor list - """ - return self.lmp.get_neighlist_size(self.idx) - - def get(self, element): - """ - :return: tuple with atom local index, numpy array of neighbor local atom indices - :rtype: (int, int, ctypes.POINTER(c_int)) - """ - iatom, numneigh, neighbors = self.lmp.get_neighlist_element_neighbors(self.idx, element) - return iatom, numneigh, neighbors - - # the methods below implement the iterator interface, so NeighList can be used like a regular Python list - - def __getitem__(self, element): - return self.get(element) - - def __len__(self): - return self.size - - def __iter__(self): - inum = self.size - - for ii in range(inum): - yield self.get(ii) - -# ------------------------------------------------------------------------- - -class NumPyNeighList(NeighList): - """This is a wrapper class that exposes the contents of a neighbor list. - - It can be used like a regular Python list. Each element is a tuple of: - - * the atom local index - * a NumPy array containing the local atom indices of its neighbors - - Internally it uses the lower-level LAMMPS C-library interface. - - :param lmp: reference to instance of :py:class:`lammps` - :type lmp: lammps - :param idx: neighbor list index - :type idx: int - """ - def __init__(self, lmp, idx): - super(NumPyNeighList, self).__init__(lmp, idx) - - def get(self, element): - """ - :return: tuple with atom local index, numpy array of neighbor local atom indices - :rtype: (int, numpy.array) - """ - iatom, neighbors = self.lmp.numpy.get_neighlist_element_neighbors(self.idx, element) - return iatom, neighbors - - -# ------------------------------------------------------------------------- -# ------------------------------------------------------------------------- - class lammps(object): """Create an instance of the LAMMPS Python class. @@ -521,6 +401,7 @@ class lammps(object): :rtype: numpy_wrapper """ if not self._numpy: + from .numpy import numpy_wrapper self._numpy = numpy_wrapper(self) return self._numpy @@ -1789,290 +1670,3 @@ class lammps(object): computeid = computeid.encode() idx = self.lib.lammps_find_compute_neighlist(self.lmp, computeid, request) return idx - -# ------------------------------------------------------------------------- - -class numpy_wrapper: - """lammps API NumPy Wrapper - - This is a wrapper class that provides additional methods on top of an - existing :py:class:`lammps` instance. The methods transform raw ctypes - pointers into NumPy arrays, which give direct access to the - original data while protecting against out-of-bounds accesses. - - There is no need to explicitly instantiate this class. Each instance - of :py:class:`lammps` has a :py:attr:`numpy ` property - that returns an instance. - - :param lmp: instance of the :py:class:`lammps` class - :type lmp: lammps - """ - def __init__(self, lmp): - self.lmp = lmp - - # ------------------------------------------------------------------------- - - def _ctype_to_numpy_int(self, ctype_int): - import numpy as np - if ctype_int == c_int32: - return np.int32 - elif ctype_int == c_int64: - return np.int64 - return np.intc - - # ------------------------------------------------------------------------- - - def extract_atom(self, name, dtype=LAMMPS_AUTODETECT, nelem=LAMMPS_AUTODETECT, dim=LAMMPS_AUTODETECT): - """Retrieve per-atom properties from LAMMPS as NumPy arrays - - This is a wrapper around the :py:meth:`lammps.extract_atom()` method. - It behaves the same as the original method, but returns NumPy arrays - instead of ``ctypes`` pointers. - - .. note:: - - While the returned arrays of per-atom data are dimensioned - for the range [0:nmax] - as is the underlying storage - - the data is usually only valid for the range of [0:nlocal], - unless the property of interest is also updated for ghost - atoms. In some cases, this depends on a LAMMPS setting, see - for example :doc:`comm_modify vel yes `. - - :param name: name of the property - :type name: string - :param dtype: type of the returned data (see :ref:`py_datatype_constants`) - :type dtype: int, optional - :param nelem: number of elements in array - :type nelem: int, optional - :param dim: dimension of each element - :type dim: int, optional - :return: requested data as NumPy array with direct access to C data or None - :rtype: numpy.array or NoneType - """ - if dtype == LAMMPS_AUTODETECT: - dtype = self.lmp.extract_atom_datatype(name) - - if nelem == LAMMPS_AUTODETECT: - if name == "mass": - nelem = self.lmp.extract_global("ntypes") + 1 - else: - nelem = self.lmp.extract_global("nlocal") - if dim == LAMMPS_AUTODETECT: - if dtype in (LAMMPS_INT_2D, LAMMPS_DOUBLE_2D, LAMMPS_INT64_2D): - # TODO add other fields - if name in ("x", "v", "f", "angmom", "torque", "csforce", "vforce"): - dim = 3 - else: - dim = 2 - else: - dim = 1 - - raw_ptr = self.lmp.extract_atom(name, dtype) - - if dtype in (LAMMPS_DOUBLE, LAMMPS_DOUBLE_2D): - return self.darray(raw_ptr, nelem, dim) - elif dtype in (LAMMPS_INT, LAMMPS_INT_2D): - return self.iarray(c_int32, raw_ptr, nelem, dim) - elif dtype in (LAMMPS_INT64, LAMMPS_INT64_2D): - return self.iarray(c_int64, raw_ptr, nelem, dim) - return raw_ptr - - # ------------------------------------------------------------------------- - - def extract_atom_iarray(self, name, nelem, dim=1): - warnings.warn("deprecated, use extract_atom instead", DeprecationWarning) - - if name in ['id', 'molecule']: - c_int_type = self.lmp.c_tagint - elif name in ['image']: - c_int_type = self.lmp.c_imageint - else: - c_int_type = c_int - - if dim == 1: - raw_ptr = self.lmp.extract_atom(name, LAMMPS_INT) - else: - raw_ptr = self.lmp.extract_atom(name, LAMMPS_INT_2D) - - return self.iarray(c_int_type, raw_ptr, nelem, dim) - - # ------------------------------------------------------------------------- - - def extract_atom_darray(self, name, nelem, dim=1): - warnings.warn("deprecated, use extract_atom instead", DeprecationWarning) - - if dim == 1: - raw_ptr = self.lmp.extract_atom(name, LAMMPS_DOUBLE) - else: - raw_ptr = self.lmp.extract_atom(name, LAMMPS_DOUBLE_2D) - - return self.darray(raw_ptr, nelem, dim) - - # ------------------------------------------------------------------------- - - def extract_compute(self, cid, style, type): - """Retrieve data from a LAMMPS compute - - This is a wrapper around the - :py:meth:`lammps.extract_compute() ` method. - It behaves the same as the original method, but returns NumPy arrays - instead of ``ctypes`` pointers. - - :param id: compute ID - :type id: string - :param style: style of the data retrieve (global, atom, or local), see :ref:`py_style_constants` - :type style: int - :param type: type of the returned data (scalar, vector, or array), see :ref:`py_type_constants` - :type type: int - :return: requested data either as float, as NumPy array with direct access to C data, or None - :rtype: float, numpy.array, or NoneType - """ - value = self.lmp.extract_compute(cid, style, type) - - if style in (LMP_STYLE_GLOBAL, LMP_STYLE_LOCAL): - if type == LMP_TYPE_VECTOR: - nrows = self.lmp.extract_compute(cid, style, LMP_SIZE_VECTOR) - return self.darray(value, nrows) - elif type == LMP_TYPE_ARRAY: - nrows = self.lmp.extract_compute(cid, style, LMP_SIZE_ROWS) - ncols = self.lmp.extract_compute(cid, style, LMP_SIZE_COLS) - return self.darray(value, nrows, ncols) - elif style == LMP_STYLE_ATOM: - if type == LMP_TYPE_VECTOR: - nlocal = self.lmp.extract_global("nlocal") - return self.darray(value, nlocal) - elif type == LMP_TYPE_ARRAY: - nlocal = self.lmp.extract_global("nlocal") - ncols = self.lmp.extract_compute(cid, style, LMP_SIZE_COLS) - return self.darray(value, nlocal, ncols) - return value - - # ------------------------------------------------------------------------- - - def extract_fix(self, fid, style, type, nrow=0, ncol=0): - """Retrieve data from a LAMMPS fix - - This is a wrapper around the :py:meth:`lammps.extract_fix() ` method. - It behaves the same as the original method, but returns NumPy arrays - instead of ``ctypes`` pointers. - - :param id: fix ID - :type id: string - :param style: style of the data retrieve (global, atom, or local), see :ref:`py_style_constants` - :type style: int - :param type: type or size of the returned data (scalar, vector, or array), see :ref:`py_type_constants` - :type type: int - :param nrow: index of global vector element or row index of global array element - :type nrow: int - :param ncol: column index of global array element - :type ncol: int - :return: requested data - :rtype: integer or double value, pointer to 1d or 2d double array or None - - """ - value = self.lmp.extract_fix(fid, style, type, nrow, ncol) - if style == LMP_STYLE_ATOM: - if type == LMP_TYPE_VECTOR: - nlocal = self.lmp.extract_global("nlocal") - return self.darray(value, nlocal) - elif type == LMP_TYPE_ARRAY: - nlocal = self.lmp.extract_global("nlocal") - ncols = self.lmp.extract_fix(fid, style, LMP_SIZE_COLS, 0, 0) - return self.darray(value, nlocal, ncols) - elif style == LMP_STYLE_LOCAL: - if type == LMP_TYPE_VECTOR: - nrows = self.lmp.extract_fix(fid, style, LMP_SIZE_ROWS, 0, 0) - return self.darray(value, nrows) - elif type == LMP_TYPE_ARRAY: - nrows = self.lmp.extract_fix(fid, style, LMP_SIZE_ROWS, 0, 0) - ncols = self.lmp.extract_fix(fid, style, LMP_SIZE_COLS, 0, 0) - return self.darray(value, nrows, ncols) - return value - - # ------------------------------------------------------------------------- - - def extract_variable(self, name, group=None, vartype=LMP_VAR_EQUAL): - """ Evaluate a LAMMPS variable and return its data - - This function is a wrapper around the function - :py:meth:`lammps.extract_variable() ` - method. It behaves the same as the original method, but returns NumPy arrays - instead of ``ctypes`` pointers. - - :param name: name of the variable to execute - :type name: string - :param group: name of group for atom-style variable (ignored for equal-style variables) - :type group: string - :param vartype: type of variable, see :ref:`py_vartype_constants` - :type vartype: int - :return: the requested data or None - :rtype: c_double, numpy.array, or NoneType - """ - import numpy as np - value = self.lmp.extract_variable(name, group, vartype) - if vartype == LMP_VAR_ATOM: - return np.ctypeslib.as_array(value) - return value - - # ------------------------------------------------------------------------- - - def get_neighlist(self, idx): - """Returns an instance of :class:`NumPyNeighList` which wraps access to the neighbor list with the given index - - :param idx: index of neighbor list - :type idx: int - :return: an instance of :class:`NumPyNeighList` wrapping access to neighbor list data - :rtype: NumPyNeighList - """ - if idx < 0: - return None - return NumPyNeighList(self.lmp, idx) - - # ------------------------------------------------------------------------- - - def get_neighlist_element_neighbors(self, idx, element): - """Return data of neighbor list entry - - This function is a wrapper around the function - :py:meth:`lammps.get_neighlist_element_neighbors() ` - method. It behaves the same as the original method, but returns a NumPy array containing the neighbors - instead of a ``ctypes`` pointer. - - :param element: neighbor list index - :type element: int - :param element: neighbor list element index - :type element: int - :return: tuple with atom local index and numpy array of neighbor local atom indices - :rtype: (int, numpy.array) - """ - iatom, numneigh, c_neighbors = self.lmp.get_neighlist_element_neighbors(idx, element) - neighbors = self.iarray(c_int, c_neighbors, numneigh, 1) - return iatom, neighbors - - # ------------------------------------------------------------------------- - - def iarray(self, c_int_type, raw_ptr, nelem, dim=1): - import numpy as np - np_int_type = self._ctype_to_numpy_int(c_int_type) - - if dim == 1: - ptr = cast(raw_ptr, POINTER(c_int_type * nelem)) - else: - ptr = cast(raw_ptr[0], POINTER(c_int_type * nelem * dim)) - - a = np.frombuffer(ptr.contents, dtype=np_int_type) - a.shape = (nelem, dim) - return a - - # ------------------------------------------------------------------------- - - def darray(self, raw_ptr, nelem, dim=1): - import numpy as np - if dim == 1: - ptr = cast(raw_ptr, POINTER(c_double * nelem)) - else: - ptr = cast(raw_ptr[0], POINTER(c_double * nelem * dim)) - - a = np.frombuffer(ptr.contents) - a.shape = (nelem, dim) - return a diff --git a/python/lammps/data.py b/python/lammps/data.py new file mode 100644 index 0000000000..2cf100ed82 --- /dev/null +++ b/python/lammps/data.py @@ -0,0 +1,73 @@ +# ---------------------------------------------------------------------- +# LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator +# http://lammps.sandia.gov, Sandia National Laboratories +# Steve Plimpton, sjplimp@sandia.gov +# +# Copyright (2003) Sandia Corporation. Under the terms of Contract +# DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains +# certain rights in this software. This software is distributed under +# the GNU General Public License. +# +# See the README file in the top-level LAMMPS directory. +# ------------------------------------------------------------------------- + +################################################################################ +# LAMMPS data structures +# Written by Richard Berger +################################################################################ + +class NeighList: + """This is a wrapper class that exposes the contents of a neighbor list. + + It can be used like a regular Python list. Each element is a tuple of: + + * the atom local index + * its number of neighbors + * and a pointer to an c_int array containing local atom indices of its + neighbors + + Internally it uses the lower-level LAMMPS C-library interface. + + :param lmp: reference to instance of :py:class:`lammps` + :type lmp: lammps + :param idx: neighbor list index + :type idx: int + """ + def __init__(self, lmp, idx): + self.lmp = lmp + self.idx = idx + + def __str__(self): + return "Neighbor List ({} atoms)".format(self.size) + + def __repr__(self): + return self.__str__() + + @property + def size(self): + """ + :return: number of elements in neighbor list + """ + return self.lmp.get_neighlist_size(self.idx) + + def get(self, element): + """ + :return: tuple with atom local index, numpy array of neighbor local atom indices + :rtype: (int, int, ctypes.POINTER(c_int)) + """ + iatom, numneigh, neighbors = self.lmp.get_neighlist_element_neighbors(self.idx, element) + return iatom, numneigh, neighbors + + # the methods below implement the iterator interface, so NeighList can be used like a regular Python list + + def __getitem__(self, element): + return self.get(element) + + def __len__(self): + return self.size + + def __iter__(self): + inum = self.size + + for ii in range(inum): + yield self.get(ii) diff --git a/python/lammps/numpy.py b/python/lammps/numpy.py new file mode 100644 index 0000000000..e7b4ef9fcd --- /dev/null +++ b/python/lammps/numpy.py @@ -0,0 +1,335 @@ +# ---------------------------------------------------------------------- +# LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator +# http://lammps.sandia.gov, Sandia National Laboratories +# Steve Plimpton, sjplimp@sandia.gov +# +# Copyright (2003) Sandia Corporation. Under the terms of Contract +# DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains +# certain rights in this software. This software is distributed under +# the GNU General Public License. +# +# See the README file in the top-level LAMMPS directory. +# ------------------------------------------------------------------------- + +################################################################################ +# NumPy additions +# Written by Richard Berger +################################################################################ + +import warnings +from ctypes import POINTER, c_double, c_int, c_int32, c_int64, cast + +import numpy as np + +from .constants import * +from .data import NeighList + + +class numpy_wrapper: + """lammps API NumPy Wrapper + + This is a wrapper class that provides additional methods on top of an + existing :py:class:`lammps` instance. The methods transform raw ctypes + pointers into NumPy arrays, which give direct access to the + original data while protecting against out-of-bounds accesses. + + There is no need to explicitly instantiate this class. Each instance + of :py:class:`lammps` has a :py:attr:`numpy ` property + that returns an instance. + + :param lmp: instance of the :py:class:`lammps` class + :type lmp: lammps + """ + def __init__(self, lmp): + self.lmp = lmp + + # ------------------------------------------------------------------------- + + def _ctype_to_numpy_int(self, ctype_int): + if ctype_int == c_int32: + return np.int32 + elif ctype_int == c_int64: + return np.int64 + return np.intc + + # ------------------------------------------------------------------------- + + def extract_atom(self, name, dtype=LAMMPS_AUTODETECT, nelem=LAMMPS_AUTODETECT, dim=LAMMPS_AUTODETECT): + """Retrieve per-atom properties from LAMMPS as NumPy arrays + + This is a wrapper around the :py:meth:`lammps.extract_atom()` method. + It behaves the same as the original method, but returns NumPy arrays + instead of ``ctypes`` pointers. + + .. note:: + + While the returned arrays of per-atom data are dimensioned + for the range [0:nmax] - as is the underlying storage - + the data is usually only valid for the range of [0:nlocal], + unless the property of interest is also updated for ghost + atoms. In some cases, this depends on a LAMMPS setting, see + for example :doc:`comm_modify vel yes `. + + :param name: name of the property + :type name: string + :param dtype: type of the returned data (see :ref:`py_datatype_constants`) + :type dtype: int, optional + :param nelem: number of elements in array + :type nelem: int, optional + :param dim: dimension of each element + :type dim: int, optional + :return: requested data as NumPy array with direct access to C data or None + :rtype: numpy.array or NoneType + """ + if dtype == LAMMPS_AUTODETECT: + dtype = self.lmp.extract_atom_datatype(name) + + if nelem == LAMMPS_AUTODETECT: + if name == "mass": + nelem = self.lmp.extract_global("ntypes") + 1 + else: + nelem = self.lmp.extract_global("nlocal") + if dim == LAMMPS_AUTODETECT: + if dtype in (LAMMPS_INT_2D, LAMMPS_DOUBLE_2D, LAMMPS_INT64_2D): + # TODO add other fields + if name in ("x", "v", "f", "angmom", "torque", "csforce", "vforce"): + dim = 3 + else: + dim = 2 + else: + dim = 1 + + raw_ptr = self.lmp.extract_atom(name, dtype) + + if dtype in (LAMMPS_DOUBLE, LAMMPS_DOUBLE_2D): + return self.darray(raw_ptr, nelem, dim) + elif dtype in (LAMMPS_INT, LAMMPS_INT_2D): + return self.iarray(c_int32, raw_ptr, nelem, dim) + elif dtype in (LAMMPS_INT64, LAMMPS_INT64_2D): + return self.iarray(c_int64, raw_ptr, nelem, dim) + return raw_ptr + + # ------------------------------------------------------------------------- + + def extract_atom_iarray(self, name, nelem, dim=1): + warnings.warn("deprecated, use extract_atom instead", DeprecationWarning) + + if name in ['id', 'molecule']: + c_int_type = self.lmp.c_tagint + elif name in ['image']: + c_int_type = self.lmp.c_imageint + else: + c_int_type = c_int + + if dim == 1: + raw_ptr = self.lmp.extract_atom(name, LAMMPS_INT) + else: + raw_ptr = self.lmp.extract_atom(name, LAMMPS_INT_2D) + + return self.iarray(c_int_type, raw_ptr, nelem, dim) + + # ------------------------------------------------------------------------- + + def extract_atom_darray(self, name, nelem, dim=1): + warnings.warn("deprecated, use extract_atom instead", DeprecationWarning) + + if dim == 1: + raw_ptr = self.lmp.extract_atom(name, LAMMPS_DOUBLE) + else: + raw_ptr = self.lmp.extract_atom(name, LAMMPS_DOUBLE_2D) + + return self.darray(raw_ptr, nelem, dim) + + # ------------------------------------------------------------------------- + + def extract_compute(self, cid, style, type): + """Retrieve data from a LAMMPS compute + + This is a wrapper around the + :py:meth:`lammps.extract_compute() ` method. + It behaves the same as the original method, but returns NumPy arrays + instead of ``ctypes`` pointers. + + :param id: compute ID + :type id: string + :param style: style of the data retrieve (global, atom, or local), see :ref:`py_style_constants` + :type style: int + :param type: type of the returned data (scalar, vector, or array), see :ref:`py_type_constants` + :type type: int + :return: requested data either as float, as NumPy array with direct access to C data, or None + :rtype: float, numpy.array, or NoneType + """ + value = self.lmp.extract_compute(cid, style, type) + + if style in (LMP_STYLE_GLOBAL, LMP_STYLE_LOCAL): + if type == LMP_TYPE_VECTOR: + nrows = self.lmp.extract_compute(cid, style, LMP_SIZE_VECTOR) + return self.darray(value, nrows) + elif type == LMP_TYPE_ARRAY: + nrows = self.lmp.extract_compute(cid, style, LMP_SIZE_ROWS) + ncols = self.lmp.extract_compute(cid, style, LMP_SIZE_COLS) + return self.darray(value, nrows, ncols) + elif style == LMP_STYLE_ATOM: + if type == LMP_TYPE_VECTOR: + nlocal = self.lmp.extract_global("nlocal") + return self.darray(value, nlocal) + elif type == LMP_TYPE_ARRAY: + nlocal = self.lmp.extract_global("nlocal") + ncols = self.lmp.extract_compute(cid, style, LMP_SIZE_COLS) + return self.darray(value, nlocal, ncols) + return value + + # ------------------------------------------------------------------------- + + def extract_fix(self, fid, style, type, nrow=0, ncol=0): + """Retrieve data from a LAMMPS fix + + This is a wrapper around the :py:meth:`lammps.extract_fix() ` method. + It behaves the same as the original method, but returns NumPy arrays + instead of ``ctypes`` pointers. + + :param id: fix ID + :type id: string + :param style: style of the data retrieve (global, atom, or local), see :ref:`py_style_constants` + :type style: int + :param type: type or size of the returned data (scalar, vector, or array), see :ref:`py_type_constants` + :type type: int + :param nrow: index of global vector element or row index of global array element + :type nrow: int + :param ncol: column index of global array element + :type ncol: int + :return: requested data + :rtype: integer or double value, pointer to 1d or 2d double array or None + + """ + value = self.lmp.extract_fix(fid, style, type, nrow, ncol) + if style == LMP_STYLE_ATOM: + if type == LMP_TYPE_VECTOR: + nlocal = self.lmp.extract_global("nlocal") + return self.darray(value, nlocal) + elif type == LMP_TYPE_ARRAY: + nlocal = self.lmp.extract_global("nlocal") + ncols = self.lmp.extract_fix(fid, style, LMP_SIZE_COLS, 0, 0) + return self.darray(value, nlocal, ncols) + elif style == LMP_STYLE_LOCAL: + if type == LMP_TYPE_VECTOR: + nrows = self.lmp.extract_fix(fid, style, LMP_SIZE_ROWS, 0, 0) + return self.darray(value, nrows) + elif type == LMP_TYPE_ARRAY: + nrows = self.lmp.extract_fix(fid, style, LMP_SIZE_ROWS, 0, 0) + ncols = self.lmp.extract_fix(fid, style, LMP_SIZE_COLS, 0, 0) + return self.darray(value, nrows, ncols) + return value + + # ------------------------------------------------------------------------- + + def extract_variable(self, name, group=None, vartype=LMP_VAR_EQUAL): + """ Evaluate a LAMMPS variable and return its data + + This function is a wrapper around the function + :py:meth:`lammps.extract_variable() ` + method. It behaves the same as the original method, but returns NumPy arrays + instead of ``ctypes`` pointers. + + :param name: name of the variable to execute + :type name: string + :param group: name of group for atom-style variable (ignored for equal-style variables) + :type group: string + :param vartype: type of variable, see :ref:`py_vartype_constants` + :type vartype: int + :return: the requested data or None + :rtype: c_double, numpy.array, or NoneType + """ + value = self.lmp.extract_variable(name, group, vartype) + if vartype == LMP_VAR_ATOM: + return np.ctypeslib.as_array(value) + return value + + # ------------------------------------------------------------------------- + + def get_neighlist(self, idx): + """Returns an instance of :class:`NumPyNeighList` which wraps access to the neighbor list with the given index + + :param idx: index of neighbor list + :type idx: int + :return: an instance of :class:`NumPyNeighList` wrapping access to neighbor list data + :rtype: NumPyNeighList + """ + if idx < 0: + return None + return NumPyNeighList(self.lmp, idx) + + # ------------------------------------------------------------------------- + + def get_neighlist_element_neighbors(self, idx, element): + """Return data of neighbor list entry + + This function is a wrapper around the function + :py:meth:`lammps.get_neighlist_element_neighbors() ` + method. It behaves the same as the original method, but returns a NumPy array containing the neighbors + instead of a ``ctypes`` pointer. + + :param element: neighbor list index + :type element: int + :param element: neighbor list element index + :type element: int + :return: tuple with atom local index and numpy array of neighbor local atom indices + :rtype: (int, numpy.array) + """ + iatom, numneigh, c_neighbors = self.lmp.get_neighlist_element_neighbors(idx, element) + neighbors = self.iarray(c_int, c_neighbors, numneigh, 1) + return iatom, neighbors + + # ------------------------------------------------------------------------- + + def iarray(self, c_int_type, raw_ptr, nelem, dim=1): + np_int_type = self._ctype_to_numpy_int(c_int_type) + + if dim == 1: + ptr = cast(raw_ptr, POINTER(c_int_type * nelem)) + else: + ptr = cast(raw_ptr[0], POINTER(c_int_type * nelem * dim)) + + a = np.frombuffer(ptr.contents, dtype=np_int_type) + a.shape = (nelem, dim) + return a + + # ------------------------------------------------------------------------- + + def darray(self, raw_ptr, nelem, dim=1): + if dim == 1: + ptr = cast(raw_ptr, POINTER(c_double * nelem)) + else: + ptr = cast(raw_ptr[0], POINTER(c_double * nelem * dim)) + + a = np.frombuffer(ptr.contents) + a.shape = (nelem, dim) + return a + +# ------------------------------------------------------------------------- + +class NumPyNeighList(NeighList): + """This is a wrapper class that exposes the contents of a neighbor list. + + It can be used like a regular Python list. Each element is a tuple of: + + * the atom local index + * a NumPy array containing the local atom indices of its neighbors + + Internally it uses the lower-level LAMMPS C-library interface. + + :param lmp: reference to instance of :py:class:`lammps` + :type lmp: lammps + :param idx: neighbor list index + :type idx: int + """ + def __init__(self, lmp, idx): + super(NumPyNeighList, self).__init__(lmp, idx) + + def get(self, element): + """ + :return: tuple with atom local index, numpy array of neighbor local atom indices + :rtype: (int, numpy.array) + """ + iatom, neighbors = self.lmp.numpy.get_neighlist_element_neighbors(self.idx, element) + return iatom, neighbors From 47d18c9f903d8155c4bd8c9b066a34b72bcc1df7 Mon Sep 17 00:00:00 2001 From: Yaser Afshar Date: Tue, 15 Dec 2020 15:48:49 -0600 Subject: [PATCH 28/44] Add KIM_EXTRA_UNITTESTS option Add KIM_EXTRA_UNITTESTS option which defaults to OFF and can be enabled on request to add a corresponding pre-processor define to do extra tests. --- cmake/Modules/Packages/KIM.cmake | 2 ++ unittest/commands/CMakeLists.txt | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/cmake/Modules/Packages/KIM.cmake b/cmake/Modules/Packages/KIM.cmake index 91a48eb3a7..83a96d02b8 100644 --- a/cmake/Modules/Packages/KIM.cmake +++ b/cmake/Modules/Packages/KIM.cmake @@ -19,6 +19,8 @@ if(CURL_FOUND) target_compile_definitions(lammps PRIVATE -DLMP_NO_SSL_CHECK) endif() endif() +set(KIM_EXTRA_UNITTESTS OFF CACHE STRING "Set extra unit tests verbose mode on/off. If on, extra tests are included.") +mark_as_advanced(KIM_EXTRA_UNITTESTS) find_package(PkgConfig QUIET) set(DOWNLOAD_KIM_DEFAULT ON) if(PKG_CONFIG_FOUND) diff --git a/unittest/commands/CMakeLists.txt b/unittest/commands/CMakeLists.txt index e9cdf78ab7..218189721a 100644 --- a/unittest/commands/CMakeLists.txt +++ b/unittest/commands/CMakeLists.txt @@ -8,6 +8,13 @@ target_link_libraries(test_lattice_region PRIVATE lammps GTest::GMock GTest::GTe add_test(NAME LatticeRegion COMMAND test_lattice_region WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) add_executable(test_kim_commands test_kim_commands.cpp) +if(KIM_EXTRA_UNITTESTS) + if(CURL_FOUND) + target_compile_definitions(test_kim_commands PRIVATE -DKIM_EXTRA_UNITTESTS) + else() + message(STATUS "CURL not found. Enabling KIM extra unit tests requires to have libcurl installed.") + endif() +endif() target_link_libraries(test_kim_commands PRIVATE lammps GTest::GMock GTest::GTest) add_test(NAME KimCommands COMMAND test_kim_commands WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) From 94cbee7710091ccdca999c8adbb6c5180a0cbd4a Mon Sep 17 00:00:00 2001 From: Yaser Afshar Date: Tue, 15 Dec 2020 15:50:15 -0600 Subject: [PATCH 29/44] Document the cmake KIM_EXTRA_UNITTESTS option Document KIM_EXTRA_UNITTESTS option and it's pre-requisites. --- doc/src/Build_extras.rst | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/doc/src/Build_extras.rst b/doc/src/Build_extras.rst index 5ef29fbca1..6847b8c030 100644 --- a/doc/src/Build_extras.rst +++ b/doc/src/Build_extras.rst @@ -282,6 +282,7 @@ minutes to hours) to build. Of course you only need to do that once.) -D DOWNLOAD_KIM=value # download OpenKIM API v2 for build, value = no (default) or yes -D LMP_DEBUG_CURL=value # set libcurl verbose mode on/off, value = off (default) or on -D LMP_NO_SSL_CHECK=value # tell libcurl to not verify the peer, value = no (default) or yes + -D KIM_EXTRA_UNITTESTS=value # enables extra unit tests, value = no (default) or yes If ``DOWNLOAD_KIM`` is set to *yes* (or *on*), the KIM API library will be downloaded and built inside the CMake build directory. If @@ -290,6 +291,11 @@ minutes to hours) to build. Of course you only need to do that once.) ``PKG_CONFIG_PATH`` environment variable so that libkim-api can be found, or run the command ``source kim-api-activate``. + Extra unit tests can only be available if they are explicitly requested + (``KIM_EXTRA_UNITTESTS`` is set to *yes* (or *on*)) and the prerequisites + are met. See :ref:`KIM Extra unit tests ` for + more details on this. + .. tab:: Traditional make You can download and build the KIM library manually if you prefer; @@ -338,6 +344,38 @@ specify your own CA cert path by setting the environment variable ``CURL_CA_BUNDLE`` to the path of your choice. A call to the KIM web query would get this value from the environment variable. +.. _kim_extra_unittests: + +KIM Extra unit tests (CMake only) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +During development, testing, or debugging, if +:doc:`unit testing ` is enabled in LAMMPS, one can also +enable extra tests on :doc:`KIM commands ` by setting the +``KIM_EXTRA_UNITTESTS`` to *yes* (or *on*). + +Enabling the extra unit tests have some requirements, + +* It requires to have internet access. +* It requires to have libcurl installed with the matching development headers + and the curl-config tool. +* It requires to build LAMMPS with the PYTHON package installed and linked to + Python 3.6 or later. See the :ref:`PYTHON package build info ` for + more details on this. +* It requires to have ``kim-property`` Python package installed, which can be + easily done using *pip* as ``pip install kim-property``, or from the + *conda-forge* channel as ``conda install kim-property`` if LAMMPS is built in + Conda. More detailed information is available at: + `kim-property installation `_. +* It is also necessary to install + ``EAM_Dynamo_Mendelev_2007_Zr__MO_848899341753_000``, and + ``EAM_Dynamo_ErcolessiAdams_1994_Al__MO_123629422045_005`` KIM models. + See `Obtaining KIM Models `_ + to learn how to install a pre-build binary of the OpenKIM Repository of + Models or see + `Installing KIM Models `_ + to learn how to install the specific KIM models. + ---------- .. _kokkos: From 9f8b42acca448b042684c3ccda0fe074f1222832 Mon Sep 17 00:00:00 2001 From: Yaser Afshar Date: Tue, 15 Dec 2020 16:31:23 -0600 Subject: [PATCH 30/44] Add extra unit tests and uncomment the kim_query tests --- unittest/commands/test_kim_commands.cpp | 94 ++++++++++++++++--------- 1 file changed, 60 insertions(+), 34 deletions(-) diff --git a/unittest/commands/test_kim_commands.cpp b/unittest/commands/test_kim_commands.cpp index 42e8a441bd..4e16e28783 100644 --- a/unittest/commands/test_kim_commands.cpp +++ b/unittest/commands/test_kim_commands.cpp @@ -326,7 +326,8 @@ TEST_F(KimCommandsTest, kim_property) "3 >= 3.6 support.*", lmp->input->one("kim_property");); } else { - TEST_FAILURE(".*ERROR: Invalid kim_property command.*", lmp->input->one("kim_property");); + TEST_FAILURE(".*ERROR: Invalid kim_property command.*", + lmp->input->one("kim_property");); TEST_FAILURE(".*ERROR: Invalid kim_property command.*", lmp->input->one("kim_property create");); TEST_FAILURE(".*ERROR: Incorrect arguments in kim_property command.\n" @@ -334,6 +335,29 @@ TEST_F(KimCommandsTest, kim_property) "is mandatory.*", lmp->input->one("kim_property unknown 1 atomic-mass");); } +#if defined(KIM_EXTRA_UNITTESTS) + TEST_FAILURE(".*ERROR: Invalid 'kim_property create' command.*", + lmp->input->one("kim_property create 1");); + TEST_FAILURE(".*ERROR: Invalid 'kim_property destroy' command.*", + lmp->input->one("kim_property destroy 1 cohesive-potential-energy-cubic-crystal");); + TEST_FAILURE(".*ERROR: Invalid 'kim_property modify' command.*", + lmp->input->one("kim_property modify 1 key short-name");); + TEST_FAILURE(".*ERROR: There is no property instance to modify the content.*", + lmp->input->one("kim_property modify 1 key short-name source-value 1 fcc");); + TEST_FAILURE(".*ERROR: Invalid 'kim_property remove' command.*", + lmp->input->one("kim_property remove 1 key");); + TEST_FAILURE(".*ERROR: There is no property instance to remove the content.*", + lmp->input->one("kim_property remove 1 key short-name");); + TEST_FAILURE(".*ERROR: There is no property instance to dump the content.*", + lmp->input->one("kim_property dump results.edn");); + if (!verbose) ::testing::internal::CaptureStdout(); + lmp->input->one("clear"); + lmp->input->one("kim_init LennardJones612_UniversalShifted__MO_959249795837_003 real"); + lmp->input->one("kim_property create 1 cohesive-potential-energy-cubic-crystal"); + lmp->input->one("kim_property modify 1 key short-name source-value 1 fcc"); + lmp->input->one("kim_property destroy 1"); + if (!verbose) ::testing::internal::GetCapturedStdout(); +#endif } TEST_F(KimCommandsTest, kim_query) @@ -420,48 +444,50 @@ TEST_F(KimCommandsTest, kim_query) "units=[\"angstrom\"]"; TEST_FAILURE(".*ERROR: OpenKIM query failed:.*", lmp->input->one(squery);); - // if (!verbose) ::testing::internal::CaptureStdout(); - // lmp->input->one("clear"); - // lmp->input->one("kim_init EAM_Dynamo_Mendelev_2007_Zr__MO_848899341753_000 metal"); +#if defined(KIM_EXTRA_UNITTESTS) + if (!verbose) ::testing::internal::CaptureStdout(); + lmp->input->one("clear"); + lmp->input->one("kim_init EAM_Dynamo_Mendelev_2007_Zr__MO_848899341753_000 metal"); - // squery = "kim_query latconst split get_lattice_constant_hexagonal "; - // squery += "crystal=[\"hcp\"] species=[\"Zr\"] units=[\"angstrom\"]"; - // lmp->input->one(squery); - // if (!verbose) ::testing::internal::GetCapturedStdout(); + squery = "kim_query latconst split get_lattice_constant_hexagonal "; + squery += "crystal=[\"hcp\"] species=[\"Zr\"] units=[\"angstrom\"]"; + lmp->input->one(squery); + if (!verbose) ::testing::internal::GetCapturedStdout(); - // ASSERT_TRUE((std::string(lmp->input->variable->retrieve("latconst_1")) == - // std::string("3.234055244384789"))); - // ASSERT_TRUE((std::string(lmp->input->variable->retrieve("latconst_2")) == - // std::string("5.167650199630013"))); + ASSERT_TRUE((std::string(lmp->input->variable->retrieve("latconst_1")) == + std::string("3.234055244384789"))); + ASSERT_TRUE((std::string(lmp->input->variable->retrieve("latconst_2")) == + std::string("5.167650199630013"))); - // if (!verbose) ::testing::internal::CaptureStdout(); - // lmp->input->one("clear"); - // lmp->input->one("kim_init EAM_Dynamo_Mendelev_2007_Zr__MO_848899341753_000 metal"); + if (!verbose) ::testing::internal::CaptureStdout(); + lmp->input->one("clear"); + lmp->input->one("kim_init EAM_Dynamo_Mendelev_2007_Zr__MO_848899341753_000 metal"); - // squery = "kim_query latconst list get_lattice_constant_hexagonal "; - // squery += "crystal=[hcp] species=[Zr] units=[angstrom]"; - // lmp->input->one(squery); - // if (!verbose) ::testing::internal::GetCapturedStdout(); + squery = "kim_query latconst list get_lattice_constant_hexagonal "; + squery += "crystal=[hcp] species=[Zr] units=[angstrom]"; + lmp->input->one(squery); + if (!verbose) ::testing::internal::GetCapturedStdout(); - // ASSERT_TRUE((std::string(lmp->input->variable->retrieve("latconst")) == - // std::string("3.234055244384789 5.167650199630013"))); + ASSERT_TRUE((std::string(lmp->input->variable->retrieve("latconst")) == + std::string("3.234055244384789 5.167650199630013"))); - // squery = "kim_query latconst list get_lattice_constant_hexagonal "; - // squery += "crystal=[bcc] species=[Zr] units=[angstrom]"; - // TEST_FAILURE(".*ERROR: OpenKIM query failed:.*", lmp->input->one(squery);); + squery = "kim_query latconst list get_lattice_constant_hexagonal "; + squery += "crystal=[bcc] species=[Zr] units=[angstrom]"; + TEST_FAILURE(".*ERROR: OpenKIM query failed:.*", lmp->input->one(squery);); - // if (!verbose) ::testing::internal::CaptureStdout(); - // lmp->input->one("clear"); - // lmp->input->one("kim_init EAM_Dynamo_ErcolessiAdams_1994_Al__MO_123629422045_005 metal"); + if (!verbose) ::testing::internal::CaptureStdout(); + lmp->input->one("clear"); + lmp->input->one("kim_init EAM_Dynamo_ErcolessiAdams_1994_Al__MO_123629422045_005 metal"); - // squery = "kim_query alpha get_linear_thermal_expansion_coefficient_cubic "; - // squery += "crystal=[fcc] species=[Al] units=[1/K] temperature=[293.15] "; - // squery += "temperature_units=[K]"; - // lmp->input->one(squery); - // if (!verbose) ::testing::internal::GetCapturedStdout(); + squery = "kim_query alpha get_linear_thermal_expansion_coefficient_cubic "; + squery += "crystal=[fcc] species=[Al] units=[1/K] temperature=[293.15] "; + squery += "temperature_units=[K]"; + lmp->input->one(squery); + if (!verbose) ::testing::internal::GetCapturedStdout(); - // ASSERT_TRUE((std::string(lmp->input->variable->retrieve("alpha")) == - // std::string("1.654960564704273e-05"))); + ASSERT_TRUE((std::string(lmp->input->variable->retrieve("alpha")) == + std::string("1.654960564704273e-05"))); +#endif } } // namespace LAMMPS_NS From 162d34d16852cdc25f151bff39ee9756ae216a5c Mon Sep 17 00:00:00 2001 From: Richard Berger Date: Tue, 15 Dec 2020 17:58:41 -0500 Subject: [PATCH 31/44] Update Python coverage tests --- unittest/python/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittest/python/CMakeLists.txt b/unittest/python/CMakeLists.txt index 47fdbbfb2d..c344a51ce7 100644 --- a/unittest/python/CMakeLists.txt +++ b/unittest/python/CMakeLists.txt @@ -44,7 +44,7 @@ if (Python_EXECUTABLE) find_package_handle_standard_args(COVERAGE DEFAULT_MSG COVERAGE_BINARY) if(COVERAGE_FOUND) - set(PYTHON_TEST_RUNNER ${Python_EXECUTABLE} -u ${COVERAGE_BINARY} run --parallel-mode --include=${LAMMPS_PYTHON_DIR}/lammps.py --omit=${LAMMPS_PYTHON_DIR}/install.py) + set(PYTHON_TEST_RUNNER ${Python_EXECUTABLE} -u ${COVERAGE_BINARY} run --parallel-mode --include=${LAMMPS_PYTHON_DIR}/lammps/*.py --omit=${LAMMPS_PYTHON_DIR}/install.py) else() set(PYTHON_TEST_RUNNER ${Python_EXECUTABLE} -u) endif() From ccb304fa1360a198cc0246b2fcf203595793ccc5 Mon Sep 17 00:00:00 2001 From: Richard Berger Date: Tue, 15 Dec 2020 18:23:40 -0500 Subject: [PATCH 32/44] Remove deprecated PyEval_InitThreads() not needed by Python > 3.6 --- src/PYTHON/python_impl.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/PYTHON/python_impl.cpp b/src/PYTHON/python_impl.cpp index 22bf8e77fb..1b3fabfa62 100644 --- a/src/PYTHON/python_impl.cpp +++ b/src/PYTHON/python_impl.cpp @@ -53,7 +53,15 @@ PythonImpl::PythonImpl(LAMMPS *lmp) : Pointers(lmp) external_interpreter = Py_IsInitialized(); Py_Initialize(); - PyEval_InitThreads(); + + // only needed for Python 2.x and Python 3 < 3.7 + // With Python 3.7 this function is now called by Py_Initialize() + // Deprecated since version 3.9, will be removed in version 3.11 +#if PY_MAJOR_VERSION < 3 || PY_MINOR_VERSION < 7 + if(!PyEval_ThreadsInitialized()) { + PyEval_InitThreads(); + } +#endif PyGILState_STATE gstate = PyGILState_Ensure(); From ac203b36839675f5c7c9c972a8328f3df3aea300 Mon Sep 17 00:00:00 2001 From: Richard Berger Date: Tue, 15 Dec 2020 18:50:38 -0500 Subject: [PATCH 33/44] Keep numpy imports inside of functions --- python/lammps/numpy.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python/lammps/numpy.py b/python/lammps/numpy.py index e7b4ef9fcd..ce64d68c90 100644 --- a/python/lammps/numpy.py +++ b/python/lammps/numpy.py @@ -19,7 +19,6 @@ import warnings from ctypes import POINTER, c_double, c_int, c_int32, c_int64, cast -import numpy as np from .constants import * from .data import NeighList @@ -46,6 +45,7 @@ class numpy_wrapper: # ------------------------------------------------------------------------- def _ctype_to_numpy_int(self, ctype_int): + import numpy as np if ctype_int == c_int32: return np.int32 elif ctype_int == c_int64: @@ -240,6 +240,7 @@ class numpy_wrapper: :return: the requested data or None :rtype: c_double, numpy.array, or NoneType """ + import numpy as np value = self.lmp.extract_variable(name, group, vartype) if vartype == LMP_VAR_ATOM: return np.ctypeslib.as_array(value) @@ -283,6 +284,7 @@ class numpy_wrapper: # ------------------------------------------------------------------------- def iarray(self, c_int_type, raw_ptr, nelem, dim=1): + import numpy as np np_int_type = self._ctype_to_numpy_int(c_int_type) if dim == 1: @@ -297,6 +299,7 @@ class numpy_wrapper: # ------------------------------------------------------------------------- def darray(self, raw_ptr, nelem, dim=1): + import numpy as np if dim == 1: ptr = cast(raw_ptr, POINTER(c_double * nelem)) else: From 3103fe85f6c39672dae0d092c2ca5e9771810d6c Mon Sep 17 00:00:00 2001 From: Richard Berger Date: Tue, 15 Dec 2020 19:16:29 -0500 Subject: [PATCH 34/44] Update Python_module.rst --- doc/src/Python_module.rst | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/src/Python_module.rst b/doc/src/Python_module.rst index 04bc3f2c5b..8b4fbe1c2e 100644 --- a/doc/src/Python_module.rst +++ b/doc/src/Python_module.rst @@ -3,12 +3,12 @@ The ``lammps`` Python module .. py:module:: lammps -The LAMMPS Python interface is implemented as a module called -:py:mod:`lammps` in the ``lammps.py`` file in the ``python`` folder of -the LAMMPS source code distribution. After compilation of LAMMPS, the -module can be installed into a Python system folder or a user folder -with ``make install-python``. Components of the module can then loaded -into a Python session with the ``import`` command. +The LAMMPS Python interface is implemented as a module called :py:mod:`lammps` +which is defined in the ``lammps`` package in the ``python`` folder of the +LAMMPS source code distribution. After compilation of LAMMPS, the module can +be installed into a Python system folder or a user folder with ``make +install-python``. Components of the module can then loaded into a Python +session with the ``import`` command. There are multiple Python interface classes in the :py:mod:`lammps` module: @@ -44,7 +44,7 @@ functions. Below is a detailed documentation of the API. .. autoclass:: lammps.lammps :members: -.. autoclass:: lammps.numpy_wrapper +.. autoclass:: lammps.numpy::numpy_wrapper :members: ---------- @@ -117,8 +117,8 @@ Style Constants to request from computes or fixes. See :cpp:enum:`_LMP_STYLE_CONST` for the equivalent constants in the C library interface. Used in :py:func:`lammps.extract_compute`, :py:func:`lammps.extract_fix`, and their NumPy variants - :py:func:`lammps.numpy.extract_compute() ` and - :py:func:`lammps.numpy.extract_fix() `. + :py:func:`lammps.numpy.extract_compute() ` and + :py:func:`lammps.numpy.extract_fix() `. .. _py_type_constants: @@ -132,8 +132,8 @@ Type Constants to request from computes or fixes. See :cpp:enum:`_LMP_TYPE_CONST` for the equivalent constants in the C library interface. Used in :py:func:`lammps.extract_compute`, :py:func:`lammps.extract_fix`, and their NumPy variants - :py:func:`lammps.numpy.extract_compute() ` and - :py:func:`lammps.numpy.extract_fix() `. + :py:func:`lammps.numpy.extract_compute() ` and + :py:func:`lammps.numpy.extract_fix() `. .. _py_vartype_constants: @@ -153,6 +153,6 @@ Classes representing internal objects :members: :no-undoc-members: -.. autoclass:: lammps.NumPyNeighList +.. autoclass:: lammps.numpy::NumPyNeighList :members: :no-undoc-members: From 7a9d6611d9c574b122fdfa475c9b3b89e7300f9d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 15 Dec 2020 20:36:27 -0500 Subject: [PATCH 35/44] add false positive --- doc/utils/sphinx-config/false_positives.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index 3fd204ceb8..0563ac1499 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -3001,6 +3001,7 @@ Sukumaran Sulc sumsq Sunderland +supercell superset supersphere Supinski From 6671e7ba3c164df03735b8f21a5d2d1bc1bc7cf5 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 15 Dec 2020 20:37:14 -0500 Subject: [PATCH 36/44] relax some more unittest thresholds to reduce failures with crappy compilers --- unittest/force-styles/tests/angle-harmonic.yaml | 2 +- unittest/force-styles/tests/angle-table_linear.yaml | 2 +- unittest/force-styles/tests/angle-table_spline.yaml | 2 +- unittest/force-styles/tests/atomic-pair-hybrid-eam.yaml | 2 +- unittest/force-styles/tests/fix-timestep-addforce_const.yaml | 2 +- unittest/force-styles/tests/fix-timestep-addforce_variable.yaml | 2 +- unittest/force-styles/tests/fix-timestep-aveforce_const.yaml | 2 +- unittest/force-styles/tests/fix-timestep-aveforce_variable.yaml | 2 +- unittest/force-styles/tests/fix-timestep-drag.yaml | 2 +- unittest/force-styles/tests/fix-timestep-heat.yaml | 2 +- unittest/force-styles/tests/fix-timestep-momentum.yaml | 2 +- unittest/force-styles/tests/fix-timestep-npt_aniso.yaml | 2 +- unittest/force-styles/tests/fix-timestep-npt_iso.yaml | 2 +- unittest/force-styles/tests/fix-timestep-nve.yaml | 2 +- unittest/force-styles/tests/fix-timestep-nve_limit.yaml | 2 +- unittest/force-styles/tests/fix-timestep-nve_noforce.yaml | 2 +- unittest/force-styles/tests/fix-timestep-nvt.yaml | 2 +- .../force-styles/tests/fix-timestep-press_berendsen_iso.yaml | 2 +- unittest/force-styles/tests/fix-timestep-rattle_bond.yaml | 2 +- unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml | 2 +- unittest/force-styles/tests/fix-timestep-setforce_const.yaml | 2 +- unittest/force-styles/tests/fix-timestep-setforce_variable.yaml | 2 +- unittest/force-styles/tests/fix-timestep-shake_angle.yaml | 2 +- unittest/force-styles/tests/fix-timestep-shake_bond.yaml | 2 +- unittest/force-styles/tests/fix-timestep-spring_chunk.yaml | 2 +- unittest/force-styles/tests/fix-timestep-spring_self.yaml | 2 +- unittest/force-styles/tests/fix-timestep-temp_berendsen.yaml | 2 +- unittest/force-styles/tests/fix-timestep-temp_csld.yaml | 2 +- unittest/force-styles/tests/fix-timestep-temp_csvr.yaml | 2 +- .../force-styles/tests/fix-timestep-wall_harmonic_const.yaml | 2 +- unittest/force-styles/tests/fix-timestep-wall_lj1043_const.yaml | 2 +- unittest/force-styles/tests/fix-timestep-wall_lj126_const.yaml | 2 +- unittest/force-styles/tests/fix-timestep-wall_lj93_const.yaml | 2 +- unittest/force-styles/tests/fix-timestep-wall_morse_const.yaml | 2 +- unittest/force-styles/tests/kspace-pppm_tip4p_ad.yaml | 2 +- unittest/force-styles/tests/kspace-pppm_tip4p_slab.yaml | 2 +- unittest/force-styles/tests/manybody-pair-polymorphic_sw.yaml | 2 +- unittest/force-styles/tests/mol-pair-buck.yaml | 2 +- unittest/force-styles/tests/mol-pair-buck_coul_long.yaml | 2 +- unittest/force-styles/tests/mol-pair-buck_coul_msm.yaml | 2 +- unittest/force-styles/tests/mol-pair-buck_coul_msm_table.yaml | 2 +- unittest/force-styles/tests/mol-pair-lj_charmm_coul_charmm.yaml | 2 +- unittest/force-styles/tests/mol-pair-lj_cut_coul_cut.yaml | 2 +- unittest/force-styles/tests/mol-pair-lj_cut_coul_dsf.yaml | 2 +- unittest/force-styles/tests/mol-pair-lj_cut_coul_msm.yaml | 2 +- unittest/force-styles/tests/mol-pair-lj_expand.yaml | 2 +- unittest/force-styles/tests/mol-pair-tip4p_cut.yaml | 2 +- unittest/force-styles/tests/mol-pair-tip4p_long.yaml | 2 +- 48 files changed, 48 insertions(+), 48 deletions(-) diff --git a/unittest/force-styles/tests/angle-harmonic.yaml b/unittest/force-styles/tests/angle-harmonic.yaml index a419c131f1..6d9cf67210 100644 --- a/unittest/force-styles/tests/angle-harmonic.yaml +++ b/unittest/force-styles/tests/angle-harmonic.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:34 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full angle harmonic diff --git a/unittest/force-styles/tests/angle-table_linear.yaml b/unittest/force-styles/tests/angle-table_linear.yaml index 2c5410f646..7dc66d9edf 100644 --- a/unittest/force-styles/tests/angle-table_linear.yaml +++ b/unittest/force-styles/tests/angle-table_linear.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:35 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full angle table diff --git a/unittest/force-styles/tests/angle-table_spline.yaml b/unittest/force-styles/tests/angle-table_spline.yaml index 42d8f58900..10edec26fd 100644 --- a/unittest/force-styles/tests/angle-table_spline.yaml +++ b/unittest/force-styles/tests/angle-table_spline.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:35 202 -epsilon: 2.5e-13 +epsilon: 5e-13 prerequisites: ! | atom full angle table diff --git a/unittest/force-styles/tests/atomic-pair-hybrid-eam.yaml b/unittest/force-styles/tests/atomic-pair-hybrid-eam.yaml index 6647cc39a5..b3569a7e74 100644 --- a/unittest/force-styles/tests/atomic-pair-hybrid-eam.yaml +++ b/unittest/force-styles/tests/atomic-pair-hybrid-eam.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:23 202 -epsilon: 5e-12 +epsilon: 1e-11 prerequisites: ! | pair eam/fs pre_commands: ! "" diff --git a/unittest/force-styles/tests/fix-timestep-addforce_const.yaml b/unittest/force-styles/tests/fix-timestep-addforce_const.yaml index 13f4644815..39bbfcf280 100644 --- a/unittest/force-styles/tests/fix-timestep-addforce_const.yaml +++ b/unittest/force-styles/tests/fix-timestep-addforce_const.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:39 202 -epsilon: 5e-12 +epsilon: 9e-12 prerequisites: ! | atom full fix addforce diff --git a/unittest/force-styles/tests/fix-timestep-addforce_variable.yaml b/unittest/force-styles/tests/fix-timestep-addforce_variable.yaml index 112b6d89c1..421051601a 100644 --- a/unittest/force-styles/tests/fix-timestep-addforce_variable.yaml +++ b/unittest/force-styles/tests/fix-timestep-addforce_variable.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:39 202 -epsilon: 5e-12 +epsilon: 2e-11 prerequisites: ! | atom full fix addforce diff --git a/unittest/force-styles/tests/fix-timestep-aveforce_const.yaml b/unittest/force-styles/tests/fix-timestep-aveforce_const.yaml index bb8ec69e3e..18dd4cf4b2 100644 --- a/unittest/force-styles/tests/fix-timestep-aveforce_const.yaml +++ b/unittest/force-styles/tests/fix-timestep-aveforce_const.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:40 202 -epsilon: 5e-12 +epsilon: 2e-11 prerequisites: ! | atom full fix aveforce diff --git a/unittest/force-styles/tests/fix-timestep-aveforce_variable.yaml b/unittest/force-styles/tests/fix-timestep-aveforce_variable.yaml index 3f7832acfe..41299b2ec8 100644 --- a/unittest/force-styles/tests/fix-timestep-aveforce_variable.yaml +++ b/unittest/force-styles/tests/fix-timestep-aveforce_variable.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:40 202 -epsilon: 2e-11 +epsilon: 2.5e-11 prerequisites: ! | atom full fix aveforce diff --git a/unittest/force-styles/tests/fix-timestep-drag.yaml b/unittest/force-styles/tests/fix-timestep-drag.yaml index 9b5791f55b..bb4908f55e 100644 --- a/unittest/force-styles/tests/fix-timestep-drag.yaml +++ b/unittest/force-styles/tests/fix-timestep-drag.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:40 202 -epsilon: 1e-14 +epsilon: 5e-14 prerequisites: ! | atom full fix drag diff --git a/unittest/force-styles/tests/fix-timestep-heat.yaml b/unittest/force-styles/tests/fix-timestep-heat.yaml index bfd51fb2a9..a7197528f5 100644 --- a/unittest/force-styles/tests/fix-timestep-heat.yaml +++ b/unittest/force-styles/tests/fix-timestep-heat.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:40 202 -epsilon: 1e-14 +epsilon: 2e-14 prerequisites: ! | atom full fix heat diff --git a/unittest/force-styles/tests/fix-timestep-momentum.yaml b/unittest/force-styles/tests/fix-timestep-momentum.yaml index eb5f4e0235..884c71785d 100644 --- a/unittest/force-styles/tests/fix-timestep-momentum.yaml +++ b/unittest/force-styles/tests/fix-timestep-momentum.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:40 202 -epsilon: 2e-14 +epsilon: 4e-14 prerequisites: ! | atom full fix momentum diff --git a/unittest/force-styles/tests/fix-timestep-npt_aniso.yaml b/unittest/force-styles/tests/fix-timestep-npt_aniso.yaml index 3f71f8d87b..b086a1b95e 100644 --- a/unittest/force-styles/tests/fix-timestep-npt_aniso.yaml +++ b/unittest/force-styles/tests/fix-timestep-npt_aniso.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:40 202 -epsilon: 2e-12 +epsilon: 4e-11 prerequisites: ! | atom full fix npt diff --git a/unittest/force-styles/tests/fix-timestep-npt_iso.yaml b/unittest/force-styles/tests/fix-timestep-npt_iso.yaml index 365b01c29e..8dec2a1bec 100644 --- a/unittest/force-styles/tests/fix-timestep-npt_iso.yaml +++ b/unittest/force-styles/tests/fix-timestep-npt_iso.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:40 202 -epsilon: 5e-13 +epsilon: 2e-12 prerequisites: ! | atom full fix npt diff --git a/unittest/force-styles/tests/fix-timestep-nve.yaml b/unittest/force-styles/tests/fix-timestep-nve.yaml index 8626163bd3..5d2efa1373 100644 --- a/unittest/force-styles/tests/fix-timestep-nve.yaml +++ b/unittest/force-styles/tests/fix-timestep-nve.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:40 202 -epsilon: 1e-14 +epsilon: 2e-14 prerequisites: ! | atom full fix nve diff --git a/unittest/force-styles/tests/fix-timestep-nve_limit.yaml b/unittest/force-styles/tests/fix-timestep-nve_limit.yaml index 56f9873ddd..bc6a16704f 100644 --- a/unittest/force-styles/tests/fix-timestep-nve_limit.yaml +++ b/unittest/force-styles/tests/fix-timestep-nve_limit.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:41 202 -epsilon: 1e-14 +epsilon: 2e-14 prerequisites: ! | atom full fix nve/limit diff --git a/unittest/force-styles/tests/fix-timestep-nve_noforce.yaml b/unittest/force-styles/tests/fix-timestep-nve_noforce.yaml index 7bb02e7873..17e9923d45 100644 --- a/unittest/force-styles/tests/fix-timestep-nve_noforce.yaml +++ b/unittest/force-styles/tests/fix-timestep-nve_noforce.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:41 202 -epsilon: 1e-14 +epsilon: 2e-14 prerequisites: ! | atom full fix nve/noforce diff --git a/unittest/force-styles/tests/fix-timestep-nvt.yaml b/unittest/force-styles/tests/fix-timestep-nvt.yaml index 58eeee64d0..6a4ead99c1 100644 --- a/unittest/force-styles/tests/fix-timestep-nvt.yaml +++ b/unittest/force-styles/tests/fix-timestep-nvt.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:41 202 -epsilon: 5e-14 +epsilon: 2e-13 prerequisites: ! | atom full fix nvt diff --git a/unittest/force-styles/tests/fix-timestep-press_berendsen_iso.yaml b/unittest/force-styles/tests/fix-timestep-press_berendsen_iso.yaml index 975d31692e..5bbf178dc3 100644 --- a/unittest/force-styles/tests/fix-timestep-press_berendsen_iso.yaml +++ b/unittest/force-styles/tests/fix-timestep-press_berendsen_iso.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:41 202 -epsilon: 2e-13 +epsilon: 2e-12 prerequisites: ! | atom full fix press/berendsen diff --git a/unittest/force-styles/tests/fix-timestep-rattle_bond.yaml b/unittest/force-styles/tests/fix-timestep-rattle_bond.yaml index 8f771d84b3..cad83187c6 100644 --- a/unittest/force-styles/tests/fix-timestep-rattle_bond.yaml +++ b/unittest/force-styles/tests/fix-timestep-rattle_bond.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:41 202 -epsilon: 9e-12 +epsilon: 1e-10 prerequisites: ! | atom full fix rattle diff --git a/unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml b/unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml index 5019d8fbe5..11d6870a42 100644 --- a/unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml +++ b/unittest/force-styles/tests/fix-timestep-rigid_nph_small.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 22:36:55 202 -epsilon: 5e-13 +epsilon: 6.5e-13 prerequisites: ! | atom full fix rigid/nph/small diff --git a/unittest/force-styles/tests/fix-timestep-setforce_const.yaml b/unittest/force-styles/tests/fix-timestep-setforce_const.yaml index b932718f71..4ff222aff6 100644 --- a/unittest/force-styles/tests/fix-timestep-setforce_const.yaml +++ b/unittest/force-styles/tests/fix-timestep-setforce_const.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:42 202 -epsilon: 5e-12 +epsilon: 2e-11 prerequisites: ! | atom full fix setforce diff --git a/unittest/force-styles/tests/fix-timestep-setforce_variable.yaml b/unittest/force-styles/tests/fix-timestep-setforce_variable.yaml index 5c01ca714f..960368a081 100644 --- a/unittest/force-styles/tests/fix-timestep-setforce_variable.yaml +++ b/unittest/force-styles/tests/fix-timestep-setforce_variable.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:42 202 -epsilon: 5e-12 +epsilon: 1e-11 prerequisites: ! | atom full fix setforce diff --git a/unittest/force-styles/tests/fix-timestep-shake_angle.yaml b/unittest/force-styles/tests/fix-timestep-shake_angle.yaml index e2cc5cb36f..1cc3dfe429 100644 --- a/unittest/force-styles/tests/fix-timestep-shake_angle.yaml +++ b/unittest/force-styles/tests/fix-timestep-shake_angle.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:42 202 -epsilon: 2e-12 +epsilon: 3e-10 prerequisites: ! | atom full fix shake diff --git a/unittest/force-styles/tests/fix-timestep-shake_bond.yaml b/unittest/force-styles/tests/fix-timestep-shake_bond.yaml index 70e70215cc..afbba6c6d7 100644 --- a/unittest/force-styles/tests/fix-timestep-shake_bond.yaml +++ b/unittest/force-styles/tests/fix-timestep-shake_bond.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:42 202 -epsilon: 2e-12 +epsilon: 3.5e-11 prerequisites: ! | atom full fix shake diff --git a/unittest/force-styles/tests/fix-timestep-spring_chunk.yaml b/unittest/force-styles/tests/fix-timestep-spring_chunk.yaml index c151352548..66a9ff9449 100644 --- a/unittest/force-styles/tests/fix-timestep-spring_chunk.yaml +++ b/unittest/force-styles/tests/fix-timestep-spring_chunk.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:42 202 -epsilon: 2e-14 +epsilon: 1e-11 prerequisites: ! | atom full fix spring/chunk diff --git a/unittest/force-styles/tests/fix-timestep-spring_self.yaml b/unittest/force-styles/tests/fix-timestep-spring_self.yaml index 0e8e85516b..96755572bf 100644 --- a/unittest/force-styles/tests/fix-timestep-spring_self.yaml +++ b/unittest/force-styles/tests/fix-timestep-spring_self.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:43 202 -epsilon: 2e-14 +epsilon: 5e-14 prerequisites: ! | atom full fix spring/self diff --git a/unittest/force-styles/tests/fix-timestep-temp_berendsen.yaml b/unittest/force-styles/tests/fix-timestep-temp_berendsen.yaml index 8b05abe90f..7975b61a13 100644 --- a/unittest/force-styles/tests/fix-timestep-temp_berendsen.yaml +++ b/unittest/force-styles/tests/fix-timestep-temp_berendsen.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:43 202 -epsilon: 1e-14 +epsilon: 2e-14 prerequisites: ! | atom full fix temp/berendsen diff --git a/unittest/force-styles/tests/fix-timestep-temp_csld.yaml b/unittest/force-styles/tests/fix-timestep-temp_csld.yaml index 63940d626c..ef6535888d 100644 --- a/unittest/force-styles/tests/fix-timestep-temp_csld.yaml +++ b/unittest/force-styles/tests/fix-timestep-temp_csld.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:43 202 -epsilon: 1e-14 +epsilon: 2e-14 prerequisites: ! | atom full fix temp/csld diff --git a/unittest/force-styles/tests/fix-timestep-temp_csvr.yaml b/unittest/force-styles/tests/fix-timestep-temp_csvr.yaml index 02592f100c..d4f77f596c 100644 --- a/unittest/force-styles/tests/fix-timestep-temp_csvr.yaml +++ b/unittest/force-styles/tests/fix-timestep-temp_csvr.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:43 202 -epsilon: 1e-14 +epsilon: 2e-14 prerequisites: ! | atom full fix temp/csvr diff --git a/unittest/force-styles/tests/fix-timestep-wall_harmonic_const.yaml b/unittest/force-styles/tests/fix-timestep-wall_harmonic_const.yaml index 2cb8904632..e1de14d018 100644 --- a/unittest/force-styles/tests/fix-timestep-wall_harmonic_const.yaml +++ b/unittest/force-styles/tests/fix-timestep-wall_harmonic_const.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:43 202 -epsilon: 2e-14 +epsilon: 3e-14 prerequisites: ! | atom full fix wall/harmonic diff --git a/unittest/force-styles/tests/fix-timestep-wall_lj1043_const.yaml b/unittest/force-styles/tests/fix-timestep-wall_lj1043_const.yaml index db63a76786..e8be8b41a2 100644 --- a/unittest/force-styles/tests/fix-timestep-wall_lj1043_const.yaml +++ b/unittest/force-styles/tests/fix-timestep-wall_lj1043_const.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:43 202 -epsilon: 1e-14 +epsilon: 5e-14 prerequisites: ! | atom full fix wall/lj1043 diff --git a/unittest/force-styles/tests/fix-timestep-wall_lj126_const.yaml b/unittest/force-styles/tests/fix-timestep-wall_lj126_const.yaml index 71b1498ac5..e65b582c09 100644 --- a/unittest/force-styles/tests/fix-timestep-wall_lj126_const.yaml +++ b/unittest/force-styles/tests/fix-timestep-wall_lj126_const.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:43 202 -epsilon: 1e-14 +epsilon: 2e-14 prerequisites: ! | atom full fix wall/lj126 diff --git a/unittest/force-styles/tests/fix-timestep-wall_lj93_const.yaml b/unittest/force-styles/tests/fix-timestep-wall_lj93_const.yaml index 7fa620fae3..d1c27927a2 100644 --- a/unittest/force-styles/tests/fix-timestep-wall_lj93_const.yaml +++ b/unittest/force-styles/tests/fix-timestep-wall_lj93_const.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:43 202 -epsilon: 1e-14 +epsilon: 2e-14 prerequisites: ! | atom full fix wall/lj93 diff --git a/unittest/force-styles/tests/fix-timestep-wall_morse_const.yaml b/unittest/force-styles/tests/fix-timestep-wall_morse_const.yaml index 65f82f8a80..2b935dbf14 100644 --- a/unittest/force-styles/tests/fix-timestep-wall_morse_const.yaml +++ b/unittest/force-styles/tests/fix-timestep-wall_morse_const.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:43 202 -epsilon: 1e-14 +epsilon: 4e-14 prerequisites: ! | atom full fix wall/morse diff --git a/unittest/force-styles/tests/kspace-pppm_tip4p_ad.yaml b/unittest/force-styles/tests/kspace-pppm_tip4p_ad.yaml index 7aebfdd2fb..e2a644a7b2 100644 --- a/unittest/force-styles/tests/kspace-pppm_tip4p_ad.yaml +++ b/unittest/force-styles/tests/kspace-pppm_tip4p_ad.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:39 202 -epsilon: 2e-13 +epsilon: 3e-13 prerequisites: ! | atom full pair tip4p/long diff --git a/unittest/force-styles/tests/kspace-pppm_tip4p_slab.yaml b/unittest/force-styles/tests/kspace-pppm_tip4p_slab.yaml index 69dcdfaf32..b64d7db0f6 100644 --- a/unittest/force-styles/tests/kspace-pppm_tip4p_slab.yaml +++ b/unittest/force-styles/tests/kspace-pppm_tip4p_slab.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:39 202 -epsilon: 2e-13 +epsilon: 5e-13 prerequisites: ! | atom full pair tip4p/long diff --git a/unittest/force-styles/tests/manybody-pair-polymorphic_sw.yaml b/unittest/force-styles/tests/manybody-pair-polymorphic_sw.yaml index 02200151c9..18a2e85c7c 100644 --- a/unittest/force-styles/tests/manybody-pair-polymorphic_sw.yaml +++ b/unittest/force-styles/tests/manybody-pair-polymorphic_sw.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:31 202 -epsilon: 1e-12 +epsilon: 4e-12 prerequisites: ! | pair polymorphic pre_commands: ! | diff --git a/unittest/force-styles/tests/mol-pair-buck.yaml b/unittest/force-styles/tests/mol-pair-buck.yaml index 16866bba3e..6600c63b4f 100644 --- a/unittest/force-styles/tests/mol-pair-buck.yaml +++ b/unittest/force-styles/tests/mol-pair-buck.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:11 202 -epsilon: 5e-14 +epsilon: 6e-14 prerequisites: ! | atom full pair buck diff --git a/unittest/force-styles/tests/mol-pair-buck_coul_long.yaml b/unittest/force-styles/tests/mol-pair-buck_coul_long.yaml index 75b2c40fbd..07606715b8 100644 --- a/unittest/force-styles/tests/mol-pair-buck_coul_long.yaml +++ b/unittest/force-styles/tests/mol-pair-buck_coul_long.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:11 202 -epsilon: 5e-14 +epsilon: 4e-13 prerequisites: ! | atom full pair buck/coul/long diff --git a/unittest/force-styles/tests/mol-pair-buck_coul_msm.yaml b/unittest/force-styles/tests/mol-pair-buck_coul_msm.yaml index 70a34e3726..ca38b6369d 100644 --- a/unittest/force-styles/tests/mol-pair-buck_coul_msm.yaml +++ b/unittest/force-styles/tests/mol-pair-buck_coul_msm.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:11 202 -epsilon: 5e-14 +epsilon: 2e-13 prerequisites: ! | atom full pair buck/coul/msm diff --git a/unittest/force-styles/tests/mol-pair-buck_coul_msm_table.yaml b/unittest/force-styles/tests/mol-pair-buck_coul_msm_table.yaml index b78affb564..24a23bb444 100644 --- a/unittest/force-styles/tests/mol-pair-buck_coul_msm_table.yaml +++ b/unittest/force-styles/tests/mol-pair-buck_coul_msm_table.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:11 202 -epsilon: 5e-14 +epsilon: 2e-13 prerequisites: ! | atom full pair buck/coul/msm diff --git a/unittest/force-styles/tests/mol-pair-lj_charmm_coul_charmm.yaml b/unittest/force-styles/tests/mol-pair-lj_charmm_coul_charmm.yaml index 6c91f1a9a1..d20b8e2e87 100644 --- a/unittest/force-styles/tests/mol-pair-lj_charmm_coul_charmm.yaml +++ b/unittest/force-styles/tests/mol-pair-lj_charmm_coul_charmm.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:14 202 -epsilon: 5e-14 +epsilon: 7e-14 prerequisites: ! | atom full pair lj/charmm/coul/charmm diff --git a/unittest/force-styles/tests/mol-pair-lj_cut_coul_cut.yaml b/unittest/force-styles/tests/mol-pair-lj_cut_coul_cut.yaml index 9140d352d6..d34748446f 100644 --- a/unittest/force-styles/tests/mol-pair-lj_cut_coul_cut.yaml +++ b/unittest/force-styles/tests/mol-pair-lj_cut_coul_cut.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:15 202 -epsilon: 5e-14 +epsilon: 1e-13 prerequisites: ! | atom full pair lj/cut/coul/cut diff --git a/unittest/force-styles/tests/mol-pair-lj_cut_coul_dsf.yaml b/unittest/force-styles/tests/mol-pair-lj_cut_coul_dsf.yaml index 7560b3a2d0..e830d17236 100644 --- a/unittest/force-styles/tests/mol-pair-lj_cut_coul_dsf.yaml +++ b/unittest/force-styles/tests/mol-pair-lj_cut_coul_dsf.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:15 202 -epsilon: 5e-14 +epsilon: 8e-14 prerequisites: ! | atom full pair lj/cut/coul/dsf diff --git a/unittest/force-styles/tests/mol-pair-lj_cut_coul_msm.yaml b/unittest/force-styles/tests/mol-pair-lj_cut_coul_msm.yaml index d150f9ee7c..a861ce9a34 100644 --- a/unittest/force-styles/tests/mol-pair-lj_cut_coul_msm.yaml +++ b/unittest/force-styles/tests/mol-pair-lj_cut_coul_msm.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:16 202 -epsilon: 5e-14 +epsilon: 7e-14 prerequisites: ! | atom full pair lj/cut/coul/msm diff --git a/unittest/force-styles/tests/mol-pair-lj_expand.yaml b/unittest/force-styles/tests/mol-pair-lj_expand.yaml index 4732d26d9c..cc94bc7213 100644 --- a/unittest/force-styles/tests/mol-pair-lj_expand.yaml +++ b/unittest/force-styles/tests/mol-pair-lj_expand.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:16 202 -epsilon: 5e-14 +epsilon: 1e-13 prerequisites: ! | atom full pair lj/expand diff --git a/unittest/force-styles/tests/mol-pair-tip4p_cut.yaml b/unittest/force-styles/tests/mol-pair-tip4p_cut.yaml index f5e302e7ce..aeaa129089 100644 --- a/unittest/force-styles/tests/mol-pair-tip4p_cut.yaml +++ b/unittest/force-styles/tests/mol-pair-tip4p_cut.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:20 202 -epsilon: 1e-14 +epsilon: 5e-14 prerequisites: ! | atom full pair tip4p/cut diff --git a/unittest/force-styles/tests/mol-pair-tip4p_long.yaml b/unittest/force-styles/tests/mol-pair-tip4p_long.yaml index f80d4587b3..16e07643fb 100644 --- a/unittest/force-styles/tests/mol-pair-tip4p_long.yaml +++ b/unittest/force-styles/tests/mol-pair-tip4p_long.yaml @@ -1,7 +1,7 @@ --- lammps_version: 24 Aug 2020 date_generated: Tue Sep 15 09:44:20 202 -epsilon: 1e-13 +epsilon: 2.5e-13 prerequisites: ! | atom full pair tip4p/long From 8fc2c13f8d557ce1ad7985df56ce54bf94c8573d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 15 Dec 2020 20:47:20 -0500 Subject: [PATCH 37/44] add PGI compiler version detection --- src/info.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/info.cpp b/src/info.cpp index 63ea4dccce..085e4e65ea 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -1179,6 +1179,8 @@ std::string Info::get_compiler_info() std::string buf; #if __clang__ buf = fmt::format("Clang C++ {}", __VERSION__); +#elif __PGI + buf = fmt::format("PGI C++ {}.{}",__PGIC__,__PGIC_MINOR__); #elif __INTEL_COMPILER double version = static_cast(__INTEL_COMPILER)*0.01; buf = fmt::format("Intel C++ {:.2f}.{} / {}", version, From 21c3a5155738e2e96b31b6ed2048111a407c79d0 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 15 Dec 2020 20:47:40 -0500 Subject: [PATCH 38/44] skip unsupported GCC pragma --- unittest/formats/test_atom_styles.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittest/formats/test_atom_styles.cpp b/unittest/formats/test_atom_styles.cpp index cb3f7d79a4..b9957c6732 100644 --- a/unittest/formats/test_atom_styles.cpp +++ b/unittest/formats/test_atom_styles.cpp @@ -32,7 +32,7 @@ #include #if !defined(_FORTIFY_SOURCE) || (_FORTIFY_SOURCE == 0) -#if defined(__INTEL_COMPILER) +#if defined(__INTEL_COMPILER) || (__PGI) #define _do_nothing #elif defined(__clang__) #pragma clang optimize off From f614aa401e13ba4ce427a9d94683c7907c6b3ab1 Mon Sep 17 00:00:00 2001 From: Shern Tee Date: Wed, 16 Dec 2020 15:42:10 +1000 Subject: [PATCH 39/44] build_one() update parent skiplist if an occasional skip list has an occasional parent list, the parent list must be built when the skip list is built. This patch ensures that behavior. (Otherwise, build_one(foo) returns an empty skip list with no warnings or errors.) --- src/neighbor.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/neighbor.cpp b/src/neighbor.cpp index 949e0387ea..7761aae721 100644 --- a/src/neighbor.cpp +++ b/src/neighbor.cpp @@ -2162,12 +2162,15 @@ void Neighbor::build_one(class NeighList *mylist, int preflag) // if this is copy list and parent is occasional list, // or this is halffull and parent is occasional list, + // or this is skip list and parent is occasional list, // insure parent is current if (mylist->listcopy && mylist->listcopy->occasional) build_one(mylist->listcopy,preflag); if (mylist->listfull && mylist->listfull->occasional) build_one(mylist->listfull,preflag); + if (mylist->listskip && mylist->listskip->occasional) + build_one(mylist->listskip,preflag); // create stencil if hasn't been created since last setup_bins() call From 0e6e1b6de176a9b6994f2fcc2d05909334a98334 Mon Sep 17 00:00:00 2001 From: Yaser Afshar Date: Wed, 16 Dec 2020 07:53:37 -0600 Subject: [PATCH 40/44] Update the mode to FATAL_ERROR when CURL not found --- unittest/commands/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittest/commands/CMakeLists.txt b/unittest/commands/CMakeLists.txt index 218189721a..7a804820cb 100644 --- a/unittest/commands/CMakeLists.txt +++ b/unittest/commands/CMakeLists.txt @@ -12,7 +12,7 @@ if(KIM_EXTRA_UNITTESTS) if(CURL_FOUND) target_compile_definitions(test_kim_commands PRIVATE -DKIM_EXTRA_UNITTESTS) else() - message(STATUS "CURL not found. Enabling KIM extra unit tests requires to have libcurl installed.") + message(FATAL_ERROR "CURL not found. Enabling KIM extra unit tests requires to have libcurl installed.") endif() endif() target_link_libraries(test_kim_commands PRIVATE lammps GTest::GMock GTest::GTest) From f9f9c37bd2b67d99fe281b060fc09c4acf99ea2c Mon Sep 17 00:00:00 2001 From: Richard Berger Date: Thu, 17 Dec 2020 11:54:30 -0500 Subject: [PATCH 41/44] Update docs --- doc/src/Howto_pylammps.rst | 4 +- doc/src/Python_ext.rst | 2 +- doc/src/Python_install.rst | 176 ++++++++++++++++++------------------ doc/src/Python_overview.rst | 10 +- doc/src/Python_trouble.rst | 2 +- doc/src/python.rst | 26 +++--- 6 files changed, 111 insertions(+), 109 deletions(-) diff --git a/doc/src/Howto_pylammps.rst b/doc/src/Howto_pylammps.rst index 89119e89af..e6d3d7b91d 100644 --- a/doc/src/Howto_pylammps.rst +++ b/doc/src/Howto_pylammps.rst @@ -9,8 +9,8 @@ Overview ``PyLammps`` is a Python wrapper class for LAMMPS which can be created on its own or use an existing lammps Python object. It creates a simpler, more "pythonic" interface to common LAMMPS functionality, in contrast to -the ``lammps.py`` wrapper for the C-style LAMMPS library interface which -is written using `Python ctypes `_. The ``lammps.py`` wrapper +the ``lammps`` wrapper for the C-style LAMMPS library interface which +is written using `Python ctypes `_. The ``lammps`` wrapper is discussed on the :doc:`Python_head` doc page. Unlike the flat ``ctypes`` interface, PyLammps exposes a discoverable diff --git a/doc/src/Python_ext.rst b/doc/src/Python_ext.rst index 6b6d1ab715..8966ffcb2a 100644 --- a/doc/src/Python_ext.rst +++ b/doc/src/Python_ext.rst @@ -9,7 +9,7 @@ This means you can extend the Python wrapper by following these steps: * Add a new interface function to ``src/library.cpp`` and ``src/library.h``. * Rebuild LAMMPS as a shared library. -* Add a wrapper method to ``python/lammps.py`` for this interface +* Add a wrapper method to ``python/lammps/core.py`` for this interface function. * Define the corresponding ``argtypes`` list and ``restype`` in the ``lammps.__init__()`` function. diff --git a/doc/src/Python_install.rst b/doc/src/Python_install.rst index 88d32895a3..0ebc1c49c3 100644 --- a/doc/src/Python_install.rst +++ b/doc/src/Python_install.rst @@ -8,9 +8,9 @@ module. Because of the dynamic loading, it is required that LAMMPS is compiled in :ref:`"shared" mode `. It is also recommended to compile LAMMPS with :ref:`C++ exceptions ` enabled. -Two files are necessary for Python to be able to invoke LAMMPS code: +Two components are necessary for Python to be able to invoke LAMMPS code: -* The LAMMPS Python Module (``lammps.py``) from the ``python`` folder +* The LAMMPS Python Package (``lammps``) from the ``python`` folder * The LAMMPS Shared Library (``liblammps.so``, ``liblammps.dylib`` or ``liblammps.dll``) from the folder where you compiled LAMMPS. @@ -25,10 +25,10 @@ Installing the LAMMPS Python Module and Shared Library ====================================================== Making LAMMPS usable within Python and vice versa requires putting the -LAMMPS Python module file (``lammps.py``) into a location where the +LAMMPS Python package (``lammps``) into a location where the Python interpreter can find it and installing the LAMMPS shared library -into a folder that the dynamic loader searches or into the same folder -where the ``lammps.py`` file is. There are multiple ways to achieve +into a folder that the dynamic loader searches or inside of the installed +``lammps`` package folder. There are multiple ways to achieve this. #. Do a full LAMMPS installation of libraries, executables, selected @@ -36,13 +36,13 @@ this. available via CMake), which can also be either system-wide or into user specific folders. -#. Install both files into a Python ``site-packages`` folder, either +#. Install both components into a Python ``site-packages`` folder, either system-wide or in the corresponding user-specific folder. This way no additional environment variables need to be set, but the shared library is otherwise not accessible. -#. Do an installation into a virtual environment. This can either be - an installation of the python module only or a full installation. +#. Do an installation into a virtual environment. This can either be an + installation of the Python package only or a full installation of LAMMPS. #. Leave the files where they are in the source/development tree and adjust some environment variables. @@ -81,19 +81,19 @@ this. This leads to an installation to the following locations: - +------------------------+-----------------------------------------------------------+-------------------------------------------------------------+ - | File | Location | Notes | - +========================+===========================================================+=============================================================+ - | LAMMPS Python Module | * ``$HOME/.local/lib/pythonX.Y/site-packages/`` (32bit) | ``X.Y`` depends on the installed Python version | - | | * ``$HOME/.local/lib64/pythonX.Y/site-packages/`` (64bit) | | - +------------------------+-----------------------------------------------------------+-------------------------------------------------------------+ - | LAMMPS shared library | * ``$HOME/.local/lib/`` (32bit) | | - | | * ``$HOME/.local/lib64/`` (64bit) | | - +------------------------+-----------------------------------------------------------+-------------------------------------------------------------+ - | LAMMPS executable | * ``$HOME/.local/bin/`` | | - +------------------------+-----------------------------------------------------------+-------------------------------------------------------------+ - | LAMMPS potential files | * ``$HOME/.local/share/lammps/potentials/`` | Set ``LAMMPS_POTENTIALS`` environment variable to this path | - +------------------------+-----------------------------------------------------------+-------------------------------------------------------------+ + +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ + | File | Location | Notes | + +========================+=================================================================+=============================================================+ + | LAMMPS Python package | * ``$HOME/.local/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version | + | | * ``$HOME/.local/lib64/pythonX.Y/site-packages/lammps`` (64bit) | | + +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ + | LAMMPS shared library | * ``$HOME/.local/lib/`` (32bit) | | + | | * ``$HOME/.local/lib64/`` (64bit) | | + +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ + | LAMMPS executable | * ``$HOME/.local/bin/`` | | + +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ + | LAMMPS potential files | * ``$HOME/.local/share/lammps/potentials/`` | Set ``LAMMPS_POTENTIALS`` environment variable to this path | + +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ For a system-wide installation you need to set ``CMAKE_INSTALL_PREFIX`` to a system folder like ``/usr`` (or @@ -102,19 +102,19 @@ this. privilege, e.g. by using ``sudo cmake --install .``. The installation folders will then by changed to: - +------------------------+---------------------------------------------------+-------------------------------------------------------------+ - | File | Location | Notes | - +========================+===================================================+=============================================================+ - | LAMMPS Python Module | * ``/usr/lib/pythonX.Y/site-packages/`` (32bit) | ``X.Y`` depends on the installed Python version | - | | * ``/usr/lib64/pythonX.Y/site-packages/`` (64bit) | | - +------------------------+---------------------------------------------------+-------------------------------------------------------------+ - | LAMMPS shared library | * ``/usr/lib/`` (32bit) | | - | | * ``/usr/lib64/`` (64bit) | | - +------------------------+---------------------------------------------------+-------------------------------------------------------------+ - | LAMMPS executable | * ``/usr/bin/`` | | - +------------------------+---------------------------------------------------+-------------------------------------------------------------+ - | LAMMPS potential files | * ``/usr/share/lammps/potentials/`` | | - +------------------------+---------------------------------------------------+-------------------------------------------------------------+ + +------------------------+---------------------------------------------------------+-------------------------------------------------------------+ + | File | Location | Notes | + +========================+=========================================================+=============================================================+ + | LAMMPS Python package | * ``/usr/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version | + | | * ``/usr/lib64/pythonX.Y/site-packages/lammps`` (64bit) | | + +------------------------+---------------------------------------------------------+-------------------------------------------------------------+ + | LAMMPS shared library | * ``/usr/lib/`` (32bit) | | + | | * ``/usr/lib64/`` (64bit) | | + +------------------------+---------------------------------------------------------+-------------------------------------------------------------+ + | LAMMPS executable | * ``/usr/bin/`` | | + +------------------------+---------------------------------------------------------+-------------------------------------------------------------+ + | LAMMPS potential files | * ``/usr/share/lammps/potentials/`` | | + +------------------------+---------------------------------------------------------+-------------------------------------------------------------+ To be able to use the "user" installation you have to ensure that the folder containing the LAMMPS shared library is either included @@ -146,7 +146,7 @@ this. necessary due to files installed in system folders that are loaded automatically when a login shell is started. - .. tab:: Python module only + .. tab:: Python package only Compile LAMMPS with either :doc:`CMake ` or the :doc:`traditional make ` procedure in :ref:`shared @@ -157,37 +157,37 @@ this. make install-python - This will try to install (only) the shared library and the python - module into a system folder and if that fails (due to missing + This will try to install (only) the shared library and the Python + package into a system folder and if that fails (due to missing write permissions) will instead do the installation to a user folder under ``$HOME/.local``. For a system-wide installation you would have to gain superuser privilege, e.g. though ``sudo`` - +------------------------+-----------------------------------------------------------+-------------------------------------------------------------+ - | File | Location | Notes | - +========================+===========================================================+=============================================================+ - | LAMMPS Python Module | * ``$HOME/.local/lib/pythonX.Y/site-packages/`` (32bit) | ``X.Y`` depends on the installed Python version | - | | * ``$HOME/.local/lib64/pythonX.Y/site-packages/`` (64bit) | | - +------------------------+-----------------------------------------------------------+-------------------------------------------------------------+ - | LAMMPS shared library | * ``$HOME/.local/lib/pythonX.Y/site-packages/`` (32bit) | ``X.Y`` depends on the installed Python version | - | | * ``$HOME/.local/lib64/pythonX.Y/site-packages/`` (64bit) | | - +------------------------+-----------------------------------------------------------+-------------------------------------------------------------+ + +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ + | File | Location | Notes | + +========================+=================================================================+=============================================================+ + | LAMMPS Python package | * ``$HOME/.local/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version | + | | * ``$HOME/.local/lib64/pythonX.Y/site-packages/lammps`` (64bit) | | + +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ + | LAMMPS shared library | * ``$HOME/.local/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version | + | | * ``$HOME/.local/lib64/pythonX.Y/site-packages/lammps`` (64bit) | | + +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ For a system-wide installation those folders would then become. - +------------------------+---------------------------------------------------+-------------------------------------------------------------+ - | File | Location | Notes | - +========================+===================================================+=============================================================+ - | LAMMPS Python Module | * ``/usr/lib/pythonX.Y/site-packages/`` (32bit) | ``X.Y`` depends on the installed Python version | - | | * ``/usr/lib64/pythonX.Y/site-packages/`` (64bit) | | - +------------------------+---------------------------------------------------+-------------------------------------------------------------+ - | LAMMPS shared library | * ``/usr/lib/pythonX.Y/site-packages/`` (32bit) | ``X.Y`` depends on the installed Python version | - | | * ``/usr/lib64/pythonX.Y/site-packages/`` (64bit) | | - +------------------------+---------------------------------------------------+-------------------------------------------------------------+ + +------------------------+---------------------------------------------------------+-------------------------------------------------------------+ + | File | Location | Notes | + +========================+=========================================================+=============================================================+ + | LAMMPS Python package | * ``/usr/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version | + | | * ``/usr/lib64/pythonX.Y/site-packages/lammps`` (64bit) | | + +------------------------+---------------------------------------------------------+-------------------------------------------------------------+ + | LAMMPS shared library | * ``/usr/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version | + | | * ``/usr/lib64/pythonX.Y/site-packages/lammps`` (64bit) | | + +------------------------+---------------------------------------------------------+-------------------------------------------------------------+ No environment variables need to be set for those, as those folders are searched by default by Python or the LAMMPS Python - module. + package. For the traditional make process you can override the python version to version x.y when calling ``make`` with @@ -199,9 +199,9 @@ this. .. code-block:: bash - $ python install.py -m -l -v [-d ] + $ python install.py -p -l -v [-d ] - * The ``-m`` flag points to the ``lammps.py`` python module file to be installed, + * The ``-p`` flag points to the ``lammps`` Python package folder to be installed, * the ``-l`` flag points to the LAMMPS shared library file to be installed, * the ``-v`` flag points to the ``version.h`` file in the LAMMPS source * and the optional ``-d`` flag to a custom (legacy) installation folder @@ -249,38 +249,38 @@ this. When using CMake to build LAMMPS, you need to set ``CMAKE_INSTALL_PREFIX`` to the value of the ``$VIRTUAL_ENV`` environment variable during the configuration step. For the - traditional make procedure, not additional steps are needed. - After compiling LAMMPS you can do a "Python module only" + traditional make procedure, no additional steps are needed. + After compiling LAMMPS you can do a "Python package only" installation with ``make install-python`` and the LAMMPS Python - module and the shared library file are installed into the + package and the shared library file are installed into the following locations: - +------------------------+-----------------------------------------------------------+-------------------------------------------------------------+ - | File | Location | Notes | - +========================+===========================================================+=============================================================+ - | LAMMPS Python Module | * ``$VIRTUAL_ENV/lib/pythonX.Y/site-packages/`` (32bit) | ``X.Y`` depends on the installed Python version | - | | * ``$VIRTUAL_ENV/lib64/pythonX.Y/site-packages/`` (64bit) | | - +------------------------+-----------------------------------------------------------+-------------------------------------------------------------+ - | LAMMPS shared library | * ``$VIRTUAL_ENV/lib/pythonX.Y/site-packages/`` (32bit) | ``X.Y`` depends on the installed Python version | - | | * ``$VIRTUAL_ENV/lib64/pythonX.Y/site-packages/`` (64bit) | | - +------------------------+-----------------------------------------------------------+-------------------------------------------------------------+ + +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ + | File | Location | Notes | + +========================+=================================================================+=============================================================+ + | LAMMPS Python Module | * ``$VIRTUAL_ENV/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version | + | | * ``$VIRTUAL_ENV/lib64/pythonX.Y/site-packages/lammps`` (64bit) | | + +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ + | LAMMPS shared library | * ``$VIRTUAL_ENV/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version | + | | * ``$VIRTUAL_ENV/lib64/pythonX.Y/site-packages/lammps`` (64bit) | | + +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ If you do a full installation (CMake only) with "install", this leads to the following installation locations: - +------------------------+-----------------------------------------------------------+-------------------------------------------------------------+ - | File | Location | Notes | - +========================+===========================================================+=============================================================+ - | LAMMPS Python Module | * ``$VIRTUAL_ENV/lib/pythonX.Y/site-packages/`` (32bit) | ``X.Y`` depends on the installed Python version | - | | * ``$VIRTUAL_ENV/lib64/pythonX.Y/site-packages/`` (64bit) | | - +------------------------+-----------------------------------------------------------+-------------------------------------------------------------+ - | LAMMPS shared library | * ``$VIRTUAL_ENV/lib/`` (32bit) | | - | | * ``$VIRTUAL_ENV/lib64/`` (64bit) | | - +------------------------+-----------------------------------------------------------+-------------------------------------------------------------+ - | LAMMPS executable | * ``$VIRTUAL_ENV/bin/`` | | - +------------------------+-----------------------------------------------------------+-------------------------------------------------------------+ - | LAMMPS potential files | * ``$VIRTUAL_ENV/share/lammps/potentials/`` | | - +------------------------+-----------------------------------------------------------+-------------------------------------------------------------+ + +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ + | File | Location | Notes | + +========================+=================================================================+=============================================================+ + | LAMMPS Python Module | * ``$VIRTUAL_ENV/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version | + | | * ``$VIRTUAL_ENV/lib64/pythonX.Y/site-packages/lammps`` (64bit) | | + +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ + | LAMMPS shared library | * ``$VIRTUAL_ENV/lib/`` (32bit) | | + | | * ``$VIRTUAL_ENV/lib64/`` (64bit) | | + +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ + | LAMMPS executable | * ``$VIRTUAL_ENV/bin/`` | | + +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ + | LAMMPS potential files | * ``$VIRTUAL_ENV/share/lammps/potentials/`` | | + +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ In that case you need to modify the ``$HOME/myenv/bin/activate`` script in a similar fashion you need to update your @@ -302,9 +302,9 @@ this. You can also :doc:`compile LAMMPS ` as usual in :ref:`"shared" mode ` leave the shared library and Python - module files inside the source/compilation folders. Instead of + package inside the source/compilation folders. Instead of copying the files where they can be found, you need to set the environment - variables ``PYTHONPATH`` (for the Python module) and + variables ``PYTHONPATH`` (for the Python package) and ``LD_LIBRARY_PATH`` (or ``DYLD_LIBRARY_PATH`` on MacOS For Bourne shells (bash, ksh and similar) the commands are: @@ -325,6 +325,10 @@ this. You can make those changes permanent by editing your ``$HOME/.bashrc`` or ``$HOME/.login`` files, respectively. + .. note:: + + The ``PYTHONPATH`` needs to point to the parent folder that contains the ``lammps`` package! + To verify if LAMMPS can be successfully started from Python, start the Python interpreter, load the ``lammps`` Python module and create a @@ -346,7 +350,7 @@ output similar to the following: .. note:: Unless you opted for "In place use", you will have to rerun the installation - any time you recompile LAMMPS to ensure the latest Python module and shared + any time you recompile LAMMPS to ensure the latest Python package and shared library are installed and used. .. note:: diff --git a/doc/src/Python_overview.rst b/doc/src/Python_overview.rst index a90ea171d5..2dfc193f8d 100644 --- a/doc/src/Python_overview.rst +++ b/doc/src/Python_overview.rst @@ -2,9 +2,9 @@ Overview ======== The LAMMPS distribution includes a ``python`` directory with the Python -code needed to run LAMMPS from Python. The ``python/lammps.py`` -contains :doc:`the "lammps" Python ` that wraps the -LAMMPS C-library interface. This file makes it is possible to do the +code needed to run LAMMPS from Python. The ``python/lammps`` package +contains :doc:`the "lammps" Python module ` that wraps the +LAMMPS C-library interface. This module makes it is possible to do the following either from a Python script, or interactively from a Python prompt: @@ -20,8 +20,8 @@ have a version of Python that extends Python to enable multiple instances of Python to read what you type. To do all of this, you must build LAMMPS in :ref:`"shared" mode ` -and make certain that your Python interpreter can find the ``lammps.py`` -file and the LAMMPS shared library file. +and make certain that your Python interpreter can find the ``lammps`` +Python package and the LAMMPS shared library file. .. _ctypes: https://docs.python.org/3/library/ctypes.html diff --git a/doc/src/Python_trouble.rst b/doc/src/Python_trouble.rst index 3ef7dacf34..b94a043a6a 100644 --- a/doc/src/Python_trouble.rst +++ b/doc/src/Python_trouble.rst @@ -33,7 +33,7 @@ the constructor call as follows (see :ref:`python_create_lammps` for more detail >>> lmp = lammps(name='mpi') You can also test the load directly in Python as follows, without -first importing from the lammps.py file: +first importing from the ``lammps`` module: .. code-block:: python diff --git a/doc/src/python.rst b/doc/src/python.rst index f38e756232..a4c3d7097c 100644 --- a/doc/src/python.rst +++ b/doc/src/python.rst @@ -323,8 +323,8 @@ Python function is as follows: The function definition must include a variable (lmpptr in this case) which corresponds to SELF in the python command. The first line of the -function imports the Python module lammps.py in the python directory of -the distribution. The second line creates a Python object "lmp" which +function imports the :doc:`"lammps" Python module `. +The second line creates a Python object ``lmp`` which wraps the instance of LAMMPS that called the function. The "ptr=lmpptr" argument is what makes that happen. The third line invokes the command() function in the LAMMPS library interface. It takes a single @@ -502,18 +502,16 @@ Python library on your system. Settings to enable this are in the lib/python/Makefile.lammps file. See the lib/python/README file for information on those settings. -If you use Python code which calls back to LAMMPS, via the SELF input -argument explained above, there is an extra step required when -building LAMMPS. LAMMPS must also be built as a shared library and -your Python function must be able to load the Python module in -python/lammps.py that wraps the LAMMPS library interface. These are -the same steps required to use Python by itself to wrap LAMMPS. -Details on these steps are explained on the :doc:`Python ` -doc page. Note that it is important that the stand-alone LAMMPS -executable and the LAMMPS shared library be consistent (built from the -same source code files) in order for this to work. If the two have -been built at different times using different source files, problems -may occur. +If you use Python code which calls back to LAMMPS, via the SELF input argument +explained above, there is an extra step required when building LAMMPS. LAMMPS +must also be built as a shared library and your Python function must be able to +load the :doc:`"lammps" Python module ` that wraps the LAMMPS +library interface. These are the same steps required to use Python by itself +to wrap LAMMPS. Details on these steps are explained on the :doc:`Python +` doc page. Note that it is important that the stand-alone LAMMPS +executable and the LAMMPS shared library be consistent (built from the same +source code files) in order for this to work. If the two have been built at +different times using different source files, problems may occur. Related commands """""""""""""""" From bcb89a1d90f0eafd27bb149d189e150180c7edb3 Mon Sep 17 00:00:00 2001 From: Richard Berger Date: Wed, 16 Dec 2020 10:55:29 -0500 Subject: [PATCH 42/44] Honor DESTDIR for packaging --- cmake/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 854937dec8..e0d0cafb2a 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -692,7 +692,7 @@ if(BUILD_SHARED_LIBS OR PKG_PYTHON) endif() if (Python_EXECUTABLE) file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/python) - install(CODE "execute_process(COMMAND ${Python_EXECUTABLE} setup.py build -b ${CMAKE_BINARY_DIR}/python install --prefix=${CMAKE_INSTALL_PREFIX} WORKING_DIRECTORY ${LAMMPS_PYTHON_DIR})") + install(CODE "execute_process(COMMAND ${Python_EXECUTABLE} setup.py build -b ${CMAKE_BINARY_DIR}/python install --prefix=${CMAKE_INSTALL_PREFIX} --root=\$ENV{DESTDIR}/ WORKING_DIRECTORY ${LAMMPS_PYTHON_DIR})") endif() endif() From 511a1a539540cc7346161565316728d313a127b7 Mon Sep 17 00:00:00 2001 From: Richard Berger Date: Thu, 17 Dec 2020 12:12:04 -0500 Subject: [PATCH 43/44] Update comments mentioning lammps.py --- examples/COUPLE/python/example.py | 2 +- python/lammps/core.py | 6 +++--- src/library.h | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/COUPLE/python/example.py b/examples/COUPLE/python/example.py index ea268fe1ca..5ddb9fb587 100644 --- a/examples/COUPLE/python/example.py +++ b/examples/COUPLE/python/example.py @@ -1,4 +1,4 @@ -# this example requires the LAMMPS Python package (lammps.py) to be installed +# this example requires the LAMMPS Python package (python/lammps) to be installed # and LAMMPS to be loadable as shared library in LD_LIBRARY_PATH import lammps diff --git a/python/lammps/core.py b/python/lammps/core.py index 009409f48d..161583b78c 100644 --- a/python/lammps/core.py +++ b/python/lammps/core.py @@ -95,7 +95,7 @@ class lammps(object): # load liblammps.so unless name is given # if name = "g++", load liblammps_g++.so # try loading the LAMMPS shared object from the location - # of lammps.py with an absolute path, + # of the lammps package with an absolute path, # so that LD_LIBRARY_PATH does not need to be set for regular install # fall back to loading with a relative path, # typically requires LD_LIBRARY_PATH to be set appropriately @@ -319,7 +319,7 @@ class lammps(object): narg = 0 cargs = None if cmdargs: - cmdargs.insert(0,"lammps.py") + cmdargs.insert(0,"lammps") narg = len(cmdargs) for i in range(narg): if type(cmdargs[i]) is str: @@ -341,7 +341,7 @@ class lammps(object): self.comm = self.MPI.COMM_WORLD self.opened = 1 if cmdargs: - cmdargs.insert(0,"lammps.py") + cmdargs.insert(0,"lammps") narg = len(cmdargs) for i in range(narg): if type(cmdargs[i]) is str: diff --git a/src/library.h b/src/library.h index 7806903e49..14be4064ea 100644 --- a/src/library.h +++ b/src/library.h @@ -42,7 +42,7 @@ /** Data type constants for extracting data from atoms, computes and fixes * - * Must be kept in sync with the equivalent constants in lammps.py */ + * Must be kept in sync with the equivalent constants in lammps/constants.py */ enum _LMP_DATATYPE_CONST { LAMMPS_INT = 0, /*!< 32-bit integer (array) */ @@ -56,7 +56,7 @@ enum _LMP_DATATYPE_CONST { /** Style constants for extracting data from computes and fixes. * - * Must be kept in sync with the equivalent constants in lammps.py */ + * Must be kept in sync with the equivalent constants in lammps/constants.py */ enum _LMP_STYLE_CONST { LMP_STYLE_GLOBAL=0, /*!< return global data */ @@ -66,7 +66,7 @@ enum _LMP_STYLE_CONST { /** Type and size constants for extracting data from computes and fixes. * - * Must be kept in sync with the equivalent constants in lammps.py */ + * Must be kept in sync with the equivalent constants in lammps/constants.py */ enum _LMP_TYPE_CONST { LMP_TYPE_SCALAR=0, /*!< return scalar */ From 09023edc984405cf991d2e7bbf158ccab033553c Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 17 Dec 2020 16:41:18 -0500 Subject: [PATCH 44/44] small python installation docs update --- doc/src/Python_install.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/src/Python_install.rst b/doc/src/Python_install.rst index 0ebc1c49c3..c12644bf4a 100644 --- a/doc/src/Python_install.rst +++ b/doc/src/Python_install.rst @@ -87,8 +87,8 @@ this. | LAMMPS Python package | * ``$HOME/.local/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version | | | * ``$HOME/.local/lib64/pythonX.Y/site-packages/lammps`` (64bit) | | +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ - | LAMMPS shared library | * ``$HOME/.local/lib/`` (32bit) | | - | | * ``$HOME/.local/lib64/`` (64bit) | | + | LAMMPS shared library | * ``$HOME/.local/lib/`` (32bit) | Set shared loader environment variable to this path | + | | * ``$HOME/.local/lib64/`` (64bit) | (see below for more info on this) | +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ | LAMMPS executable | * ``$HOME/.local/bin/`` | | +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ @@ -274,12 +274,12 @@ this. | LAMMPS Python Module | * ``$VIRTUAL_ENV/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version | | | * ``$VIRTUAL_ENV/lib64/pythonX.Y/site-packages/lammps`` (64bit) | | +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ - | LAMMPS shared library | * ``$VIRTUAL_ENV/lib/`` (32bit) | | - | | * ``$VIRTUAL_ENV/lib64/`` (64bit) | | + | LAMMPS shared library | * ``$VIRTUAL_ENV/lib/`` (32bit) | Set shared loader environment variable to this path | + | | * ``$VIRTUAL_ENV/lib64/`` (64bit) | (see below for more info on this) | +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ | LAMMPS executable | * ``$VIRTUAL_ENV/bin/`` | | +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ - | LAMMPS potential files | * ``$VIRTUAL_ENV/share/lammps/potentials/`` | | + | LAMMPS potential files | * ``$VIRTUAL_ENV/share/lammps/potentials/`` | Set ``LAMMPS_POTENTIALS`` environment variable to this path | +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ In that case you need to modify the ``$HOME/myenv/bin/activate`` @@ -296,7 +296,7 @@ this. echo 'export LD_LIBRARY_PATH=$VIRTUAL_ENV/lib:$LD_LIBRARY_PATH' >> $HOME/myenv/bin/activate # MacOS - echo 'export DYLD_LIBRARY_PATH=$VIRTUAL_ENV/lib:$LD_LIBRARY_PATH' >> $HOME/myenv/bin/activate + echo 'export DYLD_LIBRARY_PATH=$VIRTUAL_ENV/lib:$DYLD_LIBRARY_PATH' >> $HOME/myenv/bin/activate .. tab:: In place usage