diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 41229e9cd6..5a30cd5aa5 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -856,35 +856,6 @@ else() ${CMAKE_COMMAND} -E echo "Must build LAMMPS as a shared library to use the Python module") endif() -############################################################################### -# Add LAMMPS python module to "install" target. This is taylored for building -# LAMMPS for package managers and with different prefix settings. -# This requires either a shared library or that the PYTHON package is included. -############################################################################### -if(BUILD_SHARED_LIBS OR PKG_PYTHON) - if(CMAKE_VERSION VERSION_LESS 3.12) - # adjust so we find Python 3 versions before Python 2 on old systems with old CMake - set(Python_ADDITIONAL_VERSIONS 3.12 3.11 3.10 3.9 3.8 3.7 3.6) - find_package(PythonInterp) # Deprecated since version 3.12 - if(PYTHONINTERP_FOUND) - set(Python_EXECUTABLE ${PYTHON_EXECUTABLE}) - endif() - else() - # backward compatibility - if(PYTHON_EXECUTABLE) - set(Python_EXECUTABLE ${PYTHON_EXECUTABLE}) - endif() - find_package(Python COMPONENTS Interpreter) - endif() - if(Python_EXECUTABLE) - file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/python/lib) - file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/python/src) - file(COPY ${LAMMPS_SOURCE_DIR}/version.h DESTINATION ${CMAKE_BINARY_DIR}/python/src) - file(COPY ${LAMMPS_PYTHON_DIR}/README ${LAMMPS_PYTHON_DIR}/pyproject.toml ${LAMMPS_PYTHON_DIR}/setup.py ${LAMMPS_PYTHON_DIR}/lammps DESTINATION ${CMAKE_BINARY_DIR}/python/lib) - install(CODE "if(\"\$ENV{DESTDIR}\" STREQUAL \"\")\n execute_process(COMMAND ${Python_EXECUTABLE} -m pip install -v ${CMAKE_BINARY_DIR}/python/lib --prefix=${CMAKE_INSTALL_PREFIX})\n else()\n execute_process(COMMAND ${Python_EXECUTABLE} -m pip install -v ${CMAKE_BINARY_DIR}/python/lib --prefix=${CMAKE_INSTALL_PREFIX} --root=\$ENV{DESTDIR})\n endif()") - endif() -endif() - include(Testing) include(CodeCoverage) include(CodingStandard) diff --git a/doc/src/Commands_bond.rst b/doc/src/Commands_bond.rst index cfc896aa0e..aaf706b5df 100644 --- a/doc/src/Commands_bond.rst +++ b/doc/src/Commands_bond.rst @@ -42,6 +42,7 @@ OPT. * :doc:`gaussian ` * :doc:`gromos (o) ` * :doc:`harmonic (iko) ` + * :doc:`harmonic/restrain ` * :doc:`harmonic/shift (o) ` * :doc:`harmonic/shift/cut (o) ` * :doc:`lepton (o) ` diff --git a/doc/src/Developer_notes.rst b/doc/src/Developer_notes.rst index 92121cca15..07b289b583 100644 --- a/doc/src/Developer_notes.rst +++ b/doc/src/Developer_notes.rst @@ -11,6 +11,7 @@ Available topics are: - `Reading and parsing of text and text files`_ - `Requesting and accessing neighbor lists`_ +- `Choosing between a custom atom style, fix property/atom, and fix STORE/ATOM`_ - `Fix contributions to instantaneous energy, virial, and cumulative energy`_ - `KSpace PPPM FFT grids`_ @@ -216,6 +217,30 @@ command: neighbor->add_request(this, "delete_atoms", NeighConst::REQ_FULL); +Choosing between a custom atom style, fix property/atom, and fix STORE/ATOM +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There are multiple ways to manage per-atom data within LAMMPS. Often +the per-atom storage is only used locally and managed by the class that +uses it. If the data has to persist between multiple time steps and +migrate with atoms when they move from sub-domain to sub-domain or +across periodic boundaries, then using a custom atom style, or :doc:`fix +property/atom `, or the internal fix STORE/ATOM are +possible options. + +- Using the atom style is usually the most programming effort and mostly + needed when the per-atom data is an integral part of the model like a + per-atom charge or diameter and thus should be part of the Atoms + section of a :doc:`data file `. + +- Fix property/atom is useful if the data is optional or should be + entered by the user, or accessed as a (named) custom property. In this + case the fix should be entered as part of the input (and not + internally) which allows to enter and store its content with data files. + +- Fix STORE/ATOM should be used when the data should be accessed internally + only and thus the fix can be created internally. + Fix contributions to instantaneous energy, virial, and cumulative energy ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/src/Developer_updating.rst b/doc/src/Developer_updating.rst index 6089969c38..28b3712ae0 100644 --- a/doc/src/Developer_updating.rst +++ b/doc/src/Developer_updating.rst @@ -24,6 +24,7 @@ Available topics in mostly chronological order are: - `Use of "override" instead of "virtual"`_ - `Simplified and more compact neighbor list requests`_ - `Split of fix STORE into fix STORE/GLOBAL and fix STORE/PERATOM`_ +- `Rename of fix STORE/PERATOM to fix STORE/ATOM and change of arguments`_ - `Use Output::get_dump_by_id() instead of Output::find_dump()`_ - `Refactored grid communication using Grid3d/Grid2d classes instead of GridComm`_ @@ -385,6 +386,34 @@ New: This change is **required** or else the code will not compile. +Rename of fix STORE/PERATOM to fix STORE/ATOM and change of arguments +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. versionchanged:: TBD + +The available functionality of the internal fix to store per-atom +properties was expanded to enable storing data with ghost atoms and to +support binary restart files. With those changes, the fix was renamed +to fix STORE/ATOM and the number and order of (required) arguments has +changed. + +Old syntax: ``ID group-ID STORE/PERATOM rflag n1 n2 [n3]`` + +- *rflag* = 0/1, *no*/*yes* store per-atom values in restart file +- :math:`n1 = 1, n2 = 1, \mathrm{no}\;n3 \to` per-atom vector, single value per atom +- :math:`n1 = 1, n2 > 1, \mathrm{no}\;n3 \to` per-atom array, *n2* values per atom +- :math:`n1 = 1, n2 > 0, n3 > 0 \to` per-atom tensor, *n2* x *n3* values per atom + +New syntax: ``ID group-ID STORE/ATOM n1 n2 gflag rflag`` + +- :math:`n1 = 1, n2 = 0 \to` per-atom vector, single value per atom +- :math:`n1 > 1, n2 = 0 \to` per-atom array, *n1* values per atom +- :math:`n1 > 0, n2 > 0 \to` per-atom tensor, *n1* x *n2* values per atom +- *gflag* = 0/1, *no*/*yes* communicate per-atom values with ghost atoms +- *rflag* = 0/1, *no*/*yes* store per-atom values in restart file + +Since this is an internal fix, there is no user visible change. + Use Output::get_dump_by_id() instead of Output::find_dump() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/src/Python_install.rst b/doc/src/Python_install.rst index bc0406ee92..cc1e2cb5c9 100644 --- a/doc/src/Python_install.rst +++ b/doc/src/Python_install.rst @@ -27,124 +27,19 @@ interpreter can find it and installing the LAMMPS shared library 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 - headers, documentation (if enabled), and supporting files (only - available via CMake), which can also be either system-wide or into - user specific folders. - #. 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 package only or a full installation of LAMMPS. +#. Do an installation into a virtual environment. #. Leave the files where they are in the source/development tree and adjust some environment variables. .. tabs:: - .. tab:: Full install (CMake-only) - - :ref:`Build the LAMMPS executable and library ` with - ``-DBUILD_SHARED_LIBS=on``, ``-DLAMMPS_EXCEPTIONS=on`` and - ``-DPKG_PYTHON=on`` (The first option is required, the other two - are optional by recommended). The exact file name of the shared - library depends on the platform (Unix/Linux, macOS, Windows) and - the build configuration being used. The installation base folder - is already set by default to the ``$HOME/.local`` directory, but - it can be changed to a custom location defined by the - ``CMAKE_INSTALL_PREFIX`` CMake variable. This uses a folder - called ``build`` to store files generated during compilation. - - .. code-block:: bash - - # create build folder - mkdir build - cd build - - # configure LAMMPS compilation - cmake -C ../cmake/presets/basic.cmake -D BUILD_SHARED_LIBS=on \ - -D LAMMPS_EXCEPTIONS=on -D PKG_PYTHON=on ../cmake - - # compile LAMMPS - cmake --build . - - # install LAMMPS into $HOME/.local - cmake --install . - - - This leads to an installation to the following locations: - - +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ - | 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) | Set shared loader environment variable to this path | - | | * ``$HOME/.local/lib64/`` (64bit) | (see below for more info on this) | - +------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+ - | 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 - ``/usr/local``); the default is ``${HOME}/.local``. The - installation step for a system folder installation (**not** the - configuration/compilation) needs to be done with superuser - privilege, e.g. by using ``sudo cmake --install .``. The - installation folders will then be changed to (assuming ``/usr`` as - prefix): - - +------------------------+---------------------------------------------------------+-------------------------------------------------------------+ - | 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 - in a path searched by the shared linker (e.g. like - ``/usr/lib64/``) or part of the ``LD_LIBRARY_PATH`` environment - variable (or ``DYLD_LIBRARY_PATH`` on macOS). Otherwise you will - get an error when trying to create a LAMMPS object through the - Python module. - - .. code-block:: bash - - # Unix/Linux - export LD_LIBRARY_PATH=$HOME/.local/lib:$LD_LIBRARY_PATH - - # macOS - export DYLD_LIBRARY_PATH=$HOME/.local/lib:$DYLD_LIBRARY_PATH - - If you plan to use the LAMMPS executable (e.g., ``lmp``), you may - also need to adjust the ``PATH`` environment variable (but many - newer Linux distributions already have ``$HOME/.local/bin`` - included). Example: - - .. code-block:: bash - - export PATH=$HOME/.local/bin:$PATH - - To make those changes permanent, you can add the commands to your - ``$HOME/.bashrc`` file. For a system-wide installation is is not - necessary due to files installed in system folders that are loaded - automatically when a login shell is started. - - .. tab:: Python package only + .. tab:: Python package Compile LAMMPS with either :doc:`CMake ` or the :doc:`traditional make ` procedure in :ref:`shared @@ -272,38 +167,6 @@ folder that the dynamic loader searches or inside of the installed | LAMMPS shared library | * ``$VIRTUAL_ENV/lib/pythonX.Y/site-packages/lammps`` | ``X.Y`` depends on the installed Python version | +------------------------+--------------------------------------------------------+-------------------------------------------------------------+ - 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/lammps`` | ``X.Y`` depends on the installed Python version | - +------------------------+--------------------------------------------------------+-------------------------------------------------------------+ - | 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/`` | Set ``LAMMPS_POTENTIALS`` environment variable to this path | - +------------------------+--------------------------------------------------------+-------------------------------------------------------------+ - - In that case you need to modify the ``$HOME/myenv/bin/activate`` - script in a similar fashion you need to update your - ``$HOME/.bashrc`` file to include the shared library and - executable locations in ``LD_LIBRARY_PATH`` (or - ``DYLD_LIBRARY_PATH`` on macOS) and ``PATH``, respectively. - - For example with: - - .. code-block:: bash - - # Unix/Linux - echo 'export LD_LIBRARY_PATH=$VIRTUAL_ENV/lib:$LD_LIBRARY_PATH' >> $HOME/myenv/bin/activate - - # macOS - echo 'export DYLD_LIBRARY_PATH=$VIRTUAL_ENV/lib:$DYLD_LIBRARY_PATH' >> $HOME/myenv/bin/activate - .. tab:: In place usage You can also :doc:`compile LAMMPS ` as usual in diff --git a/doc/src/bond_harmonic_restrain.rst b/doc/src/bond_harmonic_restrain.rst new file mode 100644 index 0000000000..c9707f5546 --- /dev/null +++ b/doc/src/bond_harmonic_restrain.rst @@ -0,0 +1,90 @@ +.. index:: bond_style harmonic/restrain + +bond_style harmonic/restrain command +==================================== + +Syntax +"""""" + +.. code-block:: LAMMPS + + bond_style harmonic/restrain + +Examples +"""""""" + +.. code-block:: LAMMPS + + bond_style harmonic + bond_coeff 5 80.0 + +Description +""""""""""" + +.. versionadded:: TBD + +The *harmonic/restrain* bond style uses the potential + +.. math:: + + E = K (r - r_{t=0})^2 + +where :math:`r_{t=0}` is the distance between the bonded atoms at the +beginning of the first :doc:`run ` or :doc:`minimize ` +command after the bond style has been defined (*t=0*). Note that the +usual 1/2 factor is included in :math:`K`. This will effectively +restrain bonds to their initial length, whatever that is. This is where +this bond style differs from :doc:`bond style harmonic ` +where the bond length is set through the per bond type coefficients. + +The following coefficient must be defined for each bond type via the +:doc:`bond_coeff ` command as in the example above, or in +the data file or restart files read by the :doc:`read_data ` +or :doc:`read_restart ` commands + +* :math:`K` (energy/distance\^2) + +This bond style differs from other options to add harmonic restraints +like :doc:`fix restrain ` or :doc:`pair style list +` or :doc:`fix colvars ` in that it requires a +bond topology, and thus the defined bonds will trigger exclusion of +special neighbors from the neighbor list according to the +:doc:`special_bonds ` settings. + +Restart info +"""""""""""" + +This bond style supports the :doc:`write_restart ` and +:doc:`read_restart ` commands. The state of the initial +bond lengths is stored with restart files and read back. + +Restrictions +"""""""""""" + +This bond style can only be used if LAMMPS was built with the +EXTRA-MOLECULE package. See the :doc:`Build package ` +page for more info. + +This bond style maintains internal data to determine the original bond +lengths :math:`r_{t=0}`. This information will be written to +:doc:`binary restart files ` but **not** to :doc:`data +files `. Thus, continuing a simulation is *only* possible +with :doc:`read_restart `. When using the :doc:`read_data +command `, the reference bond lengths :math:`r_{t=0}` will be +re-initialized from the current geometry. + +This bond style cannot be used with :doc:`fix shake or fix rattle +`, with :doc:`fix filter/corotate `, or +any :doc:`tip4p pair style ` since there is no specific +equilibrium distance for a given bond type. + +Related commands +"""""""""""""""" + +:doc:`bond_coeff `, :doc:`bond_harmonic `, +:doc:`fix restrain `, :doc:`pair style list ` + +Default +""""""" + +none diff --git a/doc/src/bond_style.rst b/doc/src/bond_style.rst index 23b89d00a2..b33d0a9e9a 100644 --- a/doc/src/bond_style.rst +++ b/doc/src/bond_style.rst @@ -10,7 +10,7 @@ Syntax bond_style style args -* style = *none* or *zero* or *hybrid* or *bpm/rotational* or *bpm/spring* or *class2* or *fene* or *fene/expand* or *fene/nm* or *gaussian* or *gromos* or *harmonic* or *harmonic/shift* or *harmonic/shift/cut* or *lepton* or *morse* or *nonlinear* or *oxdna/fene* or *oxdena2/fene* or *oxrna2/fene* or *quartic* or *special* or *table* +* style = *none* or *zero* or *hybrid* or *bpm/rotational* or *bpm/spring* or *class2* or *fene* or *fene/expand* or *fene/nm* or *gaussian* or *gromos* or *harmonic* or *harmonic/restrain* *harmonic/shift* or *harmonic/shift/cut* or *lepton* or *morse* or *nonlinear* or *oxdna/fene* or *oxdena2/fene* or *oxrna2/fene* or *quartic* or *special* or *table* * args = none for any style except *hybrid* @@ -93,6 +93,7 @@ accelerated styles exist. * :doc:`gaussian ` - multicentered Gaussian-based bond potential * :doc:`gromos ` - GROMOS force field bond * :doc:`harmonic ` - harmonic bond +* :doc:`harmonic/restrain ` - harmonic bond to restrain to original bond distance * :doc:`harmonic/shift ` - shifted harmonic bond * :doc:`harmonic/shift/cut ` - shifted harmonic bond with a cutoff * :doc:`lepton ` - bond potential from evaluating a string diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index 0f18e6822f..1ea36a39c7 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -2469,6 +2469,7 @@ nodeless nodeset nodesets Noehring +nofix Noffset noforce noguess diff --git a/src/.gitignore b/src/.gitignore index df02ab3397..aa57927669 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -492,6 +492,8 @@ /bond_gromos.h /bond_harmonic.cpp /bond_harmonic.h +/bond_harmonic_restrain.cpp +/bond_harmonic_restrain.h /bond_harmonic_shift.cpp /bond_harmonic_shift.h /bond_harmonic_shift_cut.cpp diff --git a/src/AMOEBA/amoeba_induce.cpp b/src/AMOEBA/amoeba_induce.cpp index ecc20a198c..6017b775ca 100644 --- a/src/AMOEBA/amoeba_induce.cpp +++ b/src/AMOEBA/amoeba_induce.cpp @@ -19,7 +19,7 @@ #include "comm.h" #include "domain.h" #include "error.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "math_const.h" #include "math_special.h" #include "my_page.h" diff --git a/src/AMOEBA/amoeba_utils.cpp b/src/AMOEBA/amoeba_utils.cpp index 5a4057930c..8fb839b693 100644 --- a/src/AMOEBA/amoeba_utils.cpp +++ b/src/AMOEBA/amoeba_utils.cpp @@ -17,7 +17,7 @@ #include "atom.h" #include "domain.h" #include "error.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "neigh_list.h" #include diff --git a/src/AMOEBA/improper_amoeba.cpp b/src/AMOEBA/improper_amoeba.cpp index cb9db01b59..32c31b0af9 100644 --- a/src/AMOEBA/improper_amoeba.cpp +++ b/src/AMOEBA/improper_amoeba.cpp @@ -36,6 +36,10 @@ using namespace MathConst; ImproperAmoeba::ImproperAmoeba(LAMMPS *lmp) : Improper(lmp) { writedata = 1; + + // the second atom in the quadruplet is the atom of symmetry + + symmatoms[1] = 1; } /* ---------------------------------------------------------------------- */ diff --git a/src/AMOEBA/pair_amoeba.cpp b/src/AMOEBA/pair_amoeba.cpp index 0812fe43f0..72efa76523 100644 --- a/src/AMOEBA/pair_amoeba.cpp +++ b/src/AMOEBA/pair_amoeba.cpp @@ -20,7 +20,7 @@ #include "domain.h" #include "error.h" #include "fix.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "force.h" #include "group.h" #include "math_special.h" @@ -861,8 +861,8 @@ void PairAmoeba::init_style() Fix *myfix; if (first_flag) { id_pole = utils::strdup("AMOEBA_pole"); - myfix = modify->add_fix(fmt::format("{} {} STORE/PERATOM 1 13",id_pole,group->names[0])); - fixpole = dynamic_cast(myfix); + myfix = modify->add_fix(fmt::format("{} {} STORE/ATOM 13 0 0 1",id_pole,group->names[0])); + fixpole = dynamic_cast(myfix); } // creation of per-atom storage @@ -873,14 +873,14 @@ void PairAmoeba::init_style() if (first_flag && use_pred) { id_udalt = utils::strdup("AMOEBA_udalt"); - myfix = modify->add_fix(fmt::format("{} {} STORE/PERATOM 1 {} 3", + myfix = modify->add_fix(fmt::format("{} {} STORE/ATOM {} 3 0 1", id_udalt, group->names[0], maxualt)); - fixudalt = dynamic_cast(myfix); + fixudalt = dynamic_cast(myfix); id_upalt = utils::strdup("AMOEBA_upalt"); - myfix = modify->add_fix(fmt::format("{} {} STORE/PERATOM 1 {} 3", + myfix = modify->add_fix(fmt::format("{} {} STORE/ATOM {} 3 0 1", id_upalt, group->names[0], maxualt)); - fixupalt = dynamic_cast(myfix); + fixupalt = dynamic_cast(myfix); } // create pages for storing pairwise data: @@ -995,21 +995,21 @@ void PairAmoeba::init_style() if (id_pole) { myfix = modify->get_fix_by_id(id_pole); if (!myfix) - error->all(FLERR,"Could not find internal pair amoeba fix STORE/PERATOM id {}", id_pole); - fixpole = dynamic_cast(myfix); + error->all(FLERR,"Could not find internal pair amoeba fix STORE/ATOM id {}", id_pole); + fixpole = dynamic_cast(myfix); } if (id_udalt) { myfix = modify->get_fix_by_id(id_udalt); if (!myfix) - error->all(FLERR,"Could not find internal pair amoeba fix STORE/PERATOM id {}", id_udalt); - fixudalt = dynamic_cast(myfix); + error->all(FLERR,"Could not find internal pair amoeba fix STORE/ATOM id {}", id_udalt); + fixudalt = dynamic_cast(myfix); myfix = modify->get_fix_by_id(id_upalt); if (!myfix) - error->all(FLERR,"Could not find internal pair amoeba fix STORE/PERATOM id {}", id_upalt); - fixupalt = dynamic_cast(myfix); + error->all(FLERR,"Could not find internal pair amoeba fix STORE/ATOM id {}", id_upalt); + fixupalt = dynamic_cast(myfix); } // assign hydrogen neighbors (redID) to each owned atom diff --git a/src/AMOEBA/pair_amoeba.h b/src/AMOEBA/pair_amoeba.h index cdeee6c95f..1f3a4b799a 100644 --- a/src/AMOEBA/pair_amoeba.h +++ b/src/AMOEBA/pair_amoeba.h @@ -166,9 +166,9 @@ class PairAmoeba : public Pair { int *amgroup; // AMOEBA polarization group, 1 to Ngroup char *id_pole, *id_udalt, *id_upalt; - class FixStorePeratom *fixpole; // stores pole = multipole components - class FixStorePeratom *fixudalt; // stores udalt = induced dipole history - class FixStorePeratom *fixupalt; // stores upalt = induced dipole history + class FixStoreAtom *fixpole; // stores pole = multipole components + class FixStoreAtom *fixudalt; // stores udalt = induced dipole history + class FixStoreAtom *fixupalt; // stores upalt = induced dipole history // static per-type properties defined in force-field file diff --git a/src/CLASS2/improper_class2.cpp b/src/CLASS2/improper_class2.cpp index 6e6541919a..1e172757b0 100644 --- a/src/CLASS2/improper_class2.cpp +++ b/src/CLASS2/improper_class2.cpp @@ -39,6 +39,10 @@ using namespace MathConst; ImproperClass2::ImproperClass2(LAMMPS *lmp) : Improper(lmp) { writedata = 1; + + // the second atom in the quadruplet is the atom of symmetry + + symmatoms[1] = 1; } /* ---------------------------------------------------------------------- */ diff --git a/src/CORESHELL/compute_temp_cs.cpp b/src/CORESHELL/compute_temp_cs.cpp index c28d52e5b2..b66db30bc5 100644 --- a/src/CORESHELL/compute_temp_cs.cpp +++ b/src/CORESHELL/compute_temp_cs.cpp @@ -24,7 +24,7 @@ #include "comm.h" #include "domain.h" #include "error.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "force.h" #include "group.h" #include "memory.h" @@ -67,8 +67,8 @@ ComputeTempCS::ComputeTempCS(LAMMPS *lmp, int narg, char **arg) : // id = compute-ID + COMPUTE_STORE, fix group = compute group id_fix = utils::strdup(id + std::string("_COMPUTE_STORE")); - fix = dynamic_cast( - modify->add_fix(fmt::format("{} {} STORE/PERATOM 0 1", id_fix, group->names[igroup]))); + fix = dynamic_cast( + modify->add_fix(fmt::format("{} {} STORE/ATOM 1 0 0 0", id_fix, group->names[igroup]))); // set fix store values = 0 for now // fill them in via setup() once Comm::borders() has been called diff --git a/src/CORESHELL/compute_temp_cs.h b/src/CORESHELL/compute_temp_cs.h index 3fdf0f3711..1e7c537a83 100644 --- a/src/CORESHELL/compute_temp_cs.h +++ b/src/CORESHELL/compute_temp_cs.h @@ -54,7 +54,7 @@ class ComputeTempCS : public Compute { double **vint; char *id_fix; - class FixStorePeratom *fix; + class FixStoreAtom *fix; void dof_compute(); void vcm_pairs(); diff --git a/src/EXTRA-COMPUTE/compute_hma.cpp b/src/EXTRA-COMPUTE/compute_hma.cpp index 0f7279a5f5..4b949f6592 100644 --- a/src/EXTRA-COMPUTE/compute_hma.cpp +++ b/src/EXTRA-COMPUTE/compute_hma.cpp @@ -54,7 +54,7 @@ https://doi.org/10.1103/PhysRevE.92.043303 #include "domain.h" #include "error.h" #include "fix.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "force.h" #include "group.h" #include "improper.h" @@ -90,8 +90,8 @@ ComputeHMA::ComputeHMA(LAMMPS *lmp, int narg, char **arg) : // our new fix's group = same as compute group id_fix = utils::strdup(std::string(id)+"_COMPUTE_STORE"); - fix = dynamic_cast( - modify->add_fix(fmt::format("{} {} STORE/PERATOM 1 3", id_fix, group->names[igroup]))); + fix = dynamic_cast( + modify->add_fix(fmt::format("{} {} STORE/ATOM 3 0 0 1", id_fix, group->names[igroup]))); // calculate xu,yu,zu for fix store array // skip if reset from restart file @@ -196,7 +196,7 @@ void ComputeHMA::setup() // set fix which stores original atom coords - fix = dynamic_cast(modify->get_fix_by_id(id_fix)); + fix = dynamic_cast(modify->get_fix_by_id(id_fix)); if (!fix) error->all(FLERR,"Could not find hma per-atom store fix ID {}", id_fix); } diff --git a/src/EXTRA-COMPUTE/compute_hma.h b/src/EXTRA-COMPUTE/compute_hma.h index d8b8e55b96..8b5ea1a8dc 100644 --- a/src/EXTRA-COMPUTE/compute_hma.h +++ b/src/EXTRA-COMPUTE/compute_hma.h @@ -43,7 +43,7 @@ class ComputeHMA : public Compute { char *id_fix; char *id_temp; double finaltemp; - class FixStorePeratom *fix; + class FixStoreAtom *fix; double boltz, nktv2p, inv_volume; double deltaPcap; double virial_compute(int); diff --git a/src/EXTRA-COMPUTE/compute_msd_nongauss.cpp b/src/EXTRA-COMPUTE/compute_msd_nongauss.cpp index f75ab69a01..42af0f0b6e 100644 --- a/src/EXTRA-COMPUTE/compute_msd_nongauss.cpp +++ b/src/EXTRA-COMPUTE/compute_msd_nongauss.cpp @@ -19,7 +19,7 @@ #include "atom.h" #include "domain.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "group.h" #include "update.h" diff --git a/src/EXTRA-MOLECULE/bond_harmonic_restrain.cpp b/src/EXTRA-MOLECULE/bond_harmonic_restrain.cpp new file mode 100644 index 0000000000..87b6e5a80e --- /dev/null +++ b/src/EXTRA-MOLECULE/bond_harmonic_restrain.cpp @@ -0,0 +1,260 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + LAMMPS development team: developers@lammps.org + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#include "bond_harmonic_restrain.h" + +#include "atom.h" +#include "comm.h" +#include "domain.h" +#include "error.h" +#include "fix_store_atom.h" +#include "force.h" +#include "memory.h" +#include "modify.h" +#include "neighbor.h" + +#include +#include + +using namespace LAMMPS_NS; + +/* ---------------------------------------------------------------------- */ + +BondHarmonicRestrain::BondHarmonicRestrain(LAMMPS *_lmp) : Bond(_lmp), initial(nullptr) +{ + writedata = 0; + natoms = -1; +} + +/* ---------------------------------------------------------------------- */ + +BondHarmonicRestrain::~BondHarmonicRestrain() +{ + if (initial) modify->delete_fix("BOND_RESTRAIN_X0"); + if (allocated) { + memory->destroy(setflag); + memory->destroy(k); + } +} + +/* ---------------------------------------------------------------------- */ + +void BondHarmonicRestrain::compute(int eflag, int vflag) +{ + int i1, i2, n, type; + double delx, dely, delz, ebond, fbond; + double rsq, r, r0, dr, rk; + + ebond = 0.0; + ev_init(eflag, vflag); + + double **x = atom->x; + double **x0 = initial->astore; + double **f = atom->f; + int **bondlist = neighbor->bondlist; + int nbondlist = neighbor->nbondlist; + int nlocal = atom->nlocal; + int newton_bond = force->newton_bond; + + for (n = 0; n < nbondlist; n++) { + i1 = bondlist[n][0]; + i2 = bondlist[n][1]; + type = bondlist[n][2]; + + delx = x0[i1][0] - x0[i2][0]; + dely = x0[i1][1] - x0[i2][1]; + delz = x0[i1][2] - x0[i2][2]; + domain->minimum_image(delx, dely, delz); + rsq = delx * delx + dely * dely + delz * delz; + r0 = sqrt(rsq); + + delx = x[i1][0] - x[i2][0]; + dely = x[i1][1] - x[i2][1]; + delz = x[i1][2] - x[i2][2]; + + rsq = delx * delx + dely * dely + delz * delz; + r = sqrt(rsq); + dr = r - r0; + rk = k[type] * dr; + + // force & energy + + if (r > 0.0) + fbond = -2.0 * rk / r; + else + fbond = 0.0; + + if (eflag) ebond = rk * dr; + + // apply force to each of 2 atoms + + if (newton_bond || i1 < nlocal) { + f[i1][0] += delx * fbond; + f[i1][1] += dely * fbond; + f[i1][2] += delz * fbond; + } + + if (newton_bond || i2 < nlocal) { + f[i2][0] -= delx * fbond; + f[i2][1] -= dely * fbond; + f[i2][2] -= delz * fbond; + } + + if (evflag) ev_tally(i1, i2, nlocal, newton_bond, ebond, fbond, delx, dely, delz); + } +} + +/* ---------------------------------------------------------------------- */ + +void BondHarmonicRestrain::allocate() +{ + allocated = 1; + const int np1 = atom->nbondtypes + 1; + + memory->create(k, np1, "bond:k"); + + memory->create(setflag, np1, "bond:setflag"); + for (int i = 1; i < np1; i++) setflag[i] = 0; +} + +/* ---------------------------------------------------------------------- + set coeffs for one or more types +------------------------------------------------------------------------- */ + +void BondHarmonicRestrain::coeff(int narg, char **arg) +{ + if (narg != 2) error->all(FLERR, "Incorrect args for bond coefficients"); + if (!allocated) allocate(); + + int ilo, ihi; + utils::bounds(FLERR, arg[0], 1, atom->nbondtypes, ilo, ihi, error); + + double k_one = utils::numeric(FLERR, arg[1], false, lmp); + + int count = 0; + for (int i = ilo; i <= ihi; i++) { + k[i] = k_one; + setflag[i] = 1; + count++; + } + + if (count == 0) error->all(FLERR, "Incorrect args for bond coefficients"); +} + +/* ---------------------------------------------------------------------- + initialize custom data storage +------------------------------------------------------------------------- */ + +void BondHarmonicRestrain::init_style() +{ + // store initial positions + + if (natoms < 0) { + + // create internal fix to store initial positions + initial = dynamic_cast( + modify->add_fix("BOND_RESTRAIN_X0 all STORE/ATOM 3 0 1 1")); + if (!initial) error->all(FLERR, "Failure to create internal per-atom storage"); + + natoms = atom->natoms; + double **x0 = initial->astore; + const double *const *const x = atom->x; + for (int i = 0; i < atom->nlocal; ++i) + for (int j = 0; j < 3; ++j) x0[i][j] = x[i][j]; + + } else { + + // after a restart, natoms is set but initial is a null pointer. + // we add the fix, but do not initialize it. It will pull the data from the restart. + + if (!initial) { + initial = dynamic_cast( + modify->add_fix("BOND_RESTRAIN_X0 all STORE/ATOM 3 0 1 1")); + if (!initial) error->all(FLERR, "Failure to create internal per-atom storage"); + } + } + + // must not add atoms + if (natoms < atom->natoms) + error->all(FLERR, "Bond style harmonic/restrain does not support adding atoms"); +} + +/* ---------------------------------------------------------------------- + proc 0 writes out coeffs to restart file +------------------------------------------------------------------------- */ + +void BondHarmonicRestrain::write_restart(FILE *fp) +{ + fwrite(&natoms, sizeof(bigint), 1, fp); + fwrite(&k[1], sizeof(double), atom->nbondtypes, fp); +} + +/* ---------------------------------------------------------------------- + proc 0 reads coeffs from restart file, bcasts them +------------------------------------------------------------------------- */ + +void BondHarmonicRestrain::read_restart(FILE *fp) +{ + allocate(); + + if (comm->me == 0) { + utils::sfread(FLERR, &natoms, sizeof(bigint), 1, fp, nullptr, error); + utils::sfread(FLERR, &k[1], sizeof(double), atom->nbondtypes, fp, nullptr, error); + } + MPI_Bcast(&natoms, 1, MPI_LMP_BIGINT, 0, world); + MPI_Bcast(&k[1], atom->nbondtypes, MPI_DOUBLE, 0, world); + + for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1; +} + +/* ---------------------------------------------------------------------- + proc 0 writes to data file +------------------------------------------------------------------------- */ + +void BondHarmonicRestrain::write_data(FILE *fp) +{ + for (int i = 1; i <= atom->nbondtypes; i++) fprintf(fp, "%d %g\n", i, k[i]); +} + +/* ---------------------------------------------------------------------- */ + +double BondHarmonicRestrain::single(int type, double rsq, int i, int j, double &fforce) +{ + double **x0 = initial->astore; + + double delx = x0[i][0] - x0[j][0]; + double dely = x0[i][1] - x0[j][1]; + double delz = x0[i][2] - x0[j][2]; + domain->minimum_image(delx, dely, delz); + double r0 = sqrt(delx * delx + dely * dely + delz * delz); + + double r = sqrt(rsq); + double dr = r - r0; + double rk = k[type] * dr; + fforce = 0; + if (r > 0.0) fforce = -2.0 * rk / r; + return rk * dr; +} + +/* ---------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *BondHarmonicRestrain::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k; + return nullptr; +} diff --git a/src/EXTRA-MOLECULE/bond_harmonic_restrain.h b/src/EXTRA-MOLECULE/bond_harmonic_restrain.h new file mode 100644 index 0000000000..66ee1300c1 --- /dev/null +++ b/src/EXTRA-MOLECULE/bond_harmonic_restrain.h @@ -0,0 +1,52 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + LAMMPS development team: developers@lammps.org + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#ifdef BOND_CLASS +// clang-format off +BondStyle(harmonic/restrain,BondHarmonicRestrain); +// clang-format on +#else + +#ifndef LMP_BOND_HARMONIC_RESTRAIN_H +#define LMP_BOND_HARMONIC_RESTRAIN_H + +#include "bond.h" + +namespace LAMMPS_NS { + +class BondHarmonicRestrain : public Bond { + public: + BondHarmonicRestrain(class LAMMPS *); + ~BondHarmonicRestrain() override; + void compute(int, int) override; + void coeff(int, char **) override; + void init_style() override; + double equilibrium_distance(int) override { return -1.0; }; // return invalid value since not applicable + void write_restart(FILE *) override; + void read_restart(FILE *) override; + void write_data(FILE *) override; + double single(int, double, int, int, double &) override; + void *extract(const char *, int &) override; + + protected: + double *k; + bigint natoms; + class FixStoreAtom *initial; + + virtual void allocate(); +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/EXTRA-MOLECULE/improper_cossq.cpp b/src/EXTRA-MOLECULE/improper_cossq.cpp index d08c2afebe..bd21fa12e7 100644 --- a/src/EXTRA-MOLECULE/improper_cossq.cpp +++ b/src/EXTRA-MOLECULE/improper_cossq.cpp @@ -37,7 +37,12 @@ using namespace MathConst; /* ---------------------------------------------------------------------- */ -ImproperCossq::ImproperCossq(LAMMPS *lmp) : Improper(lmp) {} +ImproperCossq::ImproperCossq(LAMMPS *lmp) : Improper(lmp) +{ + // the first atom in the quadruplet is the atom of symmetry + + symmatoms[0] = 1; +} /* ---------------------------------------------------------------------- */ diff --git a/src/EXTRA-MOLECULE/improper_distance.cpp b/src/EXTRA-MOLECULE/improper_distance.cpp index b16e2cc674..18f6dd9a3f 100644 --- a/src/EXTRA-MOLECULE/improper_distance.cpp +++ b/src/EXTRA-MOLECULE/improper_distance.cpp @@ -35,7 +35,12 @@ using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ -ImproperDistance::ImproperDistance(LAMMPS *lmp) : Improper(lmp) {} +ImproperDistance::ImproperDistance(LAMMPS *lmp) : Improper(lmp) +{ + // the first atom in the quadruplet is the atom of symmetry + + symmatoms[0] = 1; +} /* ---------------------------------------------------------------------- */ diff --git a/src/EXTRA-MOLECULE/improper_fourier.cpp b/src/EXTRA-MOLECULE/improper_fourier.cpp index 58f8677fd6..295657b1b6 100644 --- a/src/EXTRA-MOLECULE/improper_fourier.cpp +++ b/src/EXTRA-MOLECULE/improper_fourier.cpp @@ -35,7 +35,13 @@ using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ -ImproperFourier::ImproperFourier(LAMMPS *lmp) : Improper(lmp) {} +ImproperFourier::ImproperFourier(LAMMPS *lmp) : Improper(lmp) +{ + // the first and fourth atoms in the quadruplet are the atoms of symmetry + + symmatoms[0] = 1; + symmatoms[3] = 2; +} /* ---------------------------------------------------------------------- */ diff --git a/src/EXTRA-MOLECULE/improper_ring.cpp b/src/EXTRA-MOLECULE/improper_ring.cpp index ce3f16a696..36d6277e46 100644 --- a/src/EXTRA-MOLECULE/improper_ring.cpp +++ b/src/EXTRA-MOLECULE/improper_ring.cpp @@ -59,7 +59,12 @@ using namespace MathSpecial; /* ---------------------------------------------------------------------- */ -ImproperRing::ImproperRing(LAMMPS *lmp) : Improper(lmp) {} +ImproperRing::ImproperRing(LAMMPS *lmp) : Improper(lmp) +{ + // the second atom in the quadruplet is the atom of symmetry + + symmatoms[1] = 1; +} /* ---------------------------------------------------------------------- */ diff --git a/src/FEP/fix_adapt_fep.cpp b/src/FEP/fix_adapt_fep.cpp index 2d2409d27f..6e38c90ef2 100644 --- a/src/FEP/fix_adapt_fep.cpp +++ b/src/FEP/fix_adapt_fep.cpp @@ -20,7 +20,7 @@ #include "atom.h" #include "error.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "force.h" #include "group.h" #include "input.h" @@ -211,8 +211,8 @@ void FixAdaptFEP::post_constructor() if (diamflag) { id_fix_diam = utils::strdup(id + std::string("_FIX_STORE_DIAM")); - fix_diam = dynamic_cast( - modify->add_fix(fmt::format("{} {} STORE/PERATOM 1 1", id_fix_diam,group->names[igroup]))); + fix_diam = dynamic_cast( + modify->add_fix(fmt::format("{} {} STORE/ATOM 1 0 0 1", id_fix_diam,group->names[igroup]))); if (fix_diam->restart_reset) fix_diam->restart_reset = 0; else { double *vec = fix_diam->vstore; @@ -229,8 +229,8 @@ void FixAdaptFEP::post_constructor() if (chgflag) { id_fix_chg = utils::strdup(id + std::string("_FIX_STORE_CHG")); - fix_chg = dynamic_cast( - modify->add_fix(fmt::format("{} {} STORE/PERATOM 1 1",id_fix_chg,group->names[igroup]))); + fix_chg = dynamic_cast( + modify->add_fix(fmt::format("{} {} STORE/ATOM 1 0 0 1",id_fix_chg,group->names[igroup]))); if (fix_chg->restart_reset) fix_chg->restart_reset = 0; else { double *vec = fix_chg->vstore; @@ -333,11 +333,11 @@ void FixAdaptFEP::init() // fixes that store initial per-atom values if (id_fix_diam) { - fix_diam = dynamic_cast(modify->get_fix_by_id(id_fix_diam)); + fix_diam = dynamic_cast(modify->get_fix_by_id(id_fix_diam)); if (!fix_diam) error->all(FLERR,"Could not find fix adapt/fep storage fix ID {}", id_fix_diam); } if (id_fix_chg) { - fix_chg = dynamic_cast(modify->get_fix_by_id(id_fix_chg)); + fix_chg = dynamic_cast(modify->get_fix_by_id(id_fix_chg)); if (!fix_chg) error->all(FLERR,"Could not find fix adapt/fep storage fix ID {}", id_fix_chg); } diff --git a/src/FEP/fix_adapt_fep.h b/src/FEP/fix_adapt_fep.h index a93349a780..370a34a0f3 100644 --- a/src/FEP/fix_adapt_fep.h +++ b/src/FEP/fix_adapt_fep.h @@ -46,7 +46,7 @@ class FixAdaptFEP : public Fix { int anypair; int nlevels_respa; char *id_fix_diam, *id_fix_chg; - class FixStorePeratom *fix_diam, *fix_chg; + class FixStoreAtom *fix_diam, *fix_chg; struct Adapt { int which, ivar; diff --git a/src/GPU/pair_amoeba_gpu.cpp b/src/GPU/pair_amoeba_gpu.cpp index 1221db66b1..b7e1f8e118 100644 --- a/src/GPU/pair_amoeba_gpu.cpp +++ b/src/GPU/pair_amoeba_gpu.cpp @@ -23,7 +23,7 @@ #include "comm.h" #include "domain.h" #include "error.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "force.h" #include "gpu_extra.h" #include "info.h" diff --git a/src/GPU/pair_hippo_gpu.cpp b/src/GPU/pair_hippo_gpu.cpp index eb835b5f27..f87676ec08 100644 --- a/src/GPU/pair_hippo_gpu.cpp +++ b/src/GPU/pair_hippo_gpu.cpp @@ -23,7 +23,7 @@ #include "comm.h" #include "domain.h" #include "error.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "force.h" #include "gpu_extra.h" #include "info.h" diff --git a/src/MOFFF/improper_inversion_harmonic.cpp b/src/MOFFF/improper_inversion_harmonic.cpp index 50ec3b0737..817b35332a 100644 --- a/src/MOFFF/improper_inversion_harmonic.cpp +++ b/src/MOFFF/improper_inversion_harmonic.cpp @@ -43,6 +43,10 @@ using namespace MathConst; ImproperInversionHarmonic::ImproperInversionHarmonic(LAMMPS *lmp) : Improper(lmp) { writedata = 1; + + // the first atom in the quadruplet is the atom of symmetry + + symmatoms[0] = 1; } /* ---------------------------------------------------------------------- */ diff --git a/src/MOLECULE/improper_cvff.cpp b/src/MOLECULE/improper_cvff.cpp index afe3bd9d73..ad8f709541 100644 --- a/src/MOLECULE/improper_cvff.cpp +++ b/src/MOLECULE/improper_cvff.cpp @@ -32,6 +32,10 @@ static constexpr double SMALL = 0.001; ImproperCvff::ImproperCvff(LAMMPS *_lmp) : Improper(_lmp) { writedata = 1; + + // the first atom in the quadruplet is the atom of symmetry + + symmatoms[0] = 1; } /* ---------------------------------------------------------------------- */ diff --git a/src/MOLECULE/improper_harmonic.cpp b/src/MOLECULE/improper_harmonic.cpp index d2cd505e68..06647fb93b 100644 --- a/src/MOLECULE/improper_harmonic.cpp +++ b/src/MOLECULE/improper_harmonic.cpp @@ -35,6 +35,10 @@ static constexpr double SMALL = 0.001; ImproperHarmonic::ImproperHarmonic(LAMMPS *_lmp) : Improper(_lmp) { writedata = 1; + + // the first atom in the quadruplet is the atom of symmetry + + symmatoms[0] = 1; } /* ---------------------------------------------------------------------- */ diff --git a/src/MOLECULE/improper_umbrella.cpp b/src/MOLECULE/improper_umbrella.cpp index fdf9870083..1558adc337 100644 --- a/src/MOLECULE/improper_umbrella.cpp +++ b/src/MOLECULE/improper_umbrella.cpp @@ -39,6 +39,11 @@ static constexpr double SMALL = 0.001; ImproperUmbrella::ImproperUmbrella(LAMMPS *_lmp) : Improper(_lmp) { writedata = 1; + + // the first and fourth atoms in the quadruplet are the atoms of symmetry + + symmatoms[0] = 1; + symmatoms[3] = 2; } /* ---------------------------------------------------------------------- */ diff --git a/src/REPLICA/tad.cpp b/src/REPLICA/tad.cpp index d89cbe80ba..b9b04a63d5 100644 --- a/src/REPLICA/tad.cpp +++ b/src/REPLICA/tad.cpp @@ -24,7 +24,7 @@ #include "error.h" #include "finish.h" #include "fix_event_tad.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "force.h" #include "integrate.h" #include "memory.h" @@ -133,9 +133,9 @@ void TAD::command(int narg, char **arg) fix_event = dynamic_cast(modify->add_fix("tad_event all EVENT/TAD")); - // create FixStorePeratom object to store revert state + // create FixStoreAtom object to store revert state - fix_revert = dynamic_cast(modify->add_fix("tad_revert all STORE/PERATOM 0 7")); + fix_revert = dynamic_cast(modify->add_fix("tad_revert all STORE/ATOM 7 0 0 0")); // create Finish for timing output diff --git a/src/REPLICA/tad.h b/src/REPLICA/tad.h index 8f51ca8c91..88379794cc 100644 --- a/src/REPLICA/tad.h +++ b/src/REPLICA/tad.h @@ -48,15 +48,15 @@ class TAD : public Command { double time_dynamics, time_quench, time_neb, time_comm, time_output; double time_start; - class NEB *neb; // NEB object - class Fix *fix_neb; // FixNEB object - class Compute *compute_event; // compute to detect event - class FixEventTAD *fix_event; // current event/state - class FixStorePeratom *fix_revert; // revert state - FixEventTAD **fix_event_list; // list of possible events - int n_event_list; // number of events - int nmax_event_list; // allocated events - int nmin_event_list; // minimum allocation + class NEB *neb; // NEB object + class Fix *fix_neb; // FixNEB object + class Compute *compute_event; // compute to detect event + class FixEventTAD *fix_event; // current event/state + class FixStoreAtom *fix_revert; // revert state + FixEventTAD **fix_event_list; // list of possible events + int n_event_list; // number of events + int nmax_event_list; // allocated events + int nmin_event_list; // minimum allocation char *neb_logfilename; // filename for ulogfile_neb FILE *uscreen_neb; // neb universe screen output diff --git a/src/VTK/dump_vtk.cpp b/src/VTK/dump_vtk.cpp index a188a1f060..75033684ae 100644 --- a/src/VTK/dump_vtk.cpp +++ b/src/VTK/dump_vtk.cpp @@ -31,7 +31,7 @@ #include "domain.h" #include "error.h" #include "fix.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "force.h" #include "group.h" #include "input.h" @@ -2357,16 +2357,16 @@ int DumpVTK::modify_param(int narg, char **arg) thresh_value[nthresh] = utils::numeric(FLERR,arg[3],false,lmp); thresh_last[nthresh] = -1; } else { - thresh_fix = (FixStorePeratom **) - memory->srealloc(thresh_fix,(nthreshlast+1)*sizeof(FixStorePeratom *),"dump:thresh_fix"); + thresh_fix = (FixStoreAtom **) + memory->srealloc(thresh_fix,(nthreshlast+1)*sizeof(FixStoreAtom *),"dump:thresh_fix"); thresh_fixID = (char **) memory->srealloc(thresh_fixID,(nthreshlast+1)*sizeof(char *),"dump:thresh_fixID"); memory->grow(thresh_first,(nthreshlast+1),"dump:thresh_first"); std::string threshid = fmt::format("{}{}_DUMP_STORE",id,nthreshlast); thresh_fixID[nthreshlast] = utils::strdup(threshid); - threshid += fmt::format(" {} STORE/PERATOM 1 1", group->names[igroup]); - thresh_fix[nthreshlast] = dynamic_cast(modify->add_fix(threshid)); + threshid += fmt::format(" {} STORE/ATOM 1 0 0 1", group->names[igroup]); + thresh_fix[nthreshlast] = dynamic_cast(modify->add_fix(threshid)); thresh_last[nthreshlast] = nthreshlast; thresh_first[nthreshlast] = 1; diff --git a/src/YAFF/improper_distharm.cpp b/src/YAFF/improper_distharm.cpp index 3e67b6a436..27516fa416 100644 --- a/src/YAFF/improper_distharm.cpp +++ b/src/YAFF/improper_distharm.cpp @@ -36,7 +36,12 @@ using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ -ImproperDistHarm::ImproperDistHarm(LAMMPS *lmp) : Improper(lmp) {} +ImproperDistHarm::ImproperDistHarm(LAMMPS *lmp) : Improper(lmp) +{ + // the fourth atom in the quadruplet is the atom of symmetry + + symmatoms[3] = 1; +} /* ---------------------------------------------------------------------- */ diff --git a/src/YAFF/improper_sqdistharm.cpp b/src/YAFF/improper_sqdistharm.cpp index 1b366c058f..1cd8515d9a 100644 --- a/src/YAFF/improper_sqdistharm.cpp +++ b/src/YAFF/improper_sqdistharm.cpp @@ -36,7 +36,12 @@ using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ -ImproperSQDistHarm::ImproperSQDistHarm(LAMMPS *lmp) : Improper(lmp) {} +ImproperSQDistHarm::ImproperSQDistHarm(LAMMPS *lmp) : Improper(lmp) +{ + // the fourth atom in the quadruplet is the atom of symmetry + + symmatoms[3] = 1; +} /* ---------------------------------------------------------------------- */ diff --git a/src/balance.cpp b/src/balance.cpp index 91b9d70378..3bd083e2b9 100644 --- a/src/balance.cpp +++ b/src/balance.cpp @@ -26,7 +26,7 @@ #include "neighbor.h" #include "comm.h" #include "domain.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "force.h" #include "imbalance.h" #include "imbalance_group.h" @@ -513,9 +513,9 @@ void Balance::weight_storage(char *prefix) if (prefix) cmd = prefix; cmd += "IMBALANCE_WEIGHTS"; - fixstore = dynamic_cast(modify->get_fix_by_id(cmd)); + fixstore = dynamic_cast(modify->get_fix_by_id(cmd)); if (!fixstore) - fixstore = dynamic_cast(modify->add_fix(cmd + " all STORE/PERATOM 0 1")); + fixstore = dynamic_cast(modify->add_fix(cmd + " all STORE/ATOM 1 0 0 0")); // do not carry weights with atoms during normal atom migration diff --git a/src/balance.h b/src/balance.h index 3a6e8bf457..669d21e2b5 100644 --- a/src/balance.h +++ b/src/balance.h @@ -27,11 +27,11 @@ namespace LAMMPS_NS { class Balance : public Command { public: class RCB *rcb; - class FixStorePeratom *fixstore; // per-atom weights stored in FixStorePeratom - int wtflag; // 1 if particle weighting is used - int varflag; // 1 if weight style var(iable) is used - int sortflag; // 1 if sorting of comm messages is done - int outflag; // 1 for output of balance results to file + class FixStoreAtom *fixstore; // per-atom weights stored in FixStorePeratom + int wtflag; // 1 if particle weighting is used + int varflag; // 1 if weight style var(iable) is used + int sortflag; // 1 if sorting of comm messages is done + int outflag; // 1 for output of balance results to file Balance(class LAMMPS *); ~Balance() override; diff --git a/src/compute_chunk_atom.cpp b/src/compute_chunk_atom.cpp index f9723497b1..f5c68c8f25 100644 --- a/src/compute_chunk_atom.cpp +++ b/src/compute_chunk_atom.cpp @@ -21,7 +21,7 @@ #include "domain.h" #include "error.h" #include "fix.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "group.h" #include "input.h" #include "lattice.h" @@ -571,8 +571,8 @@ void ComputeChunkAtom::init() if ((idsflag == ONCE || lockcount) && !fixstore) { id_fix = utils::strdup(id + std::string("_COMPUTE_STORE")); - fixstore = dynamic_cast( - modify->add_fix(fmt::format("{} {} STORE/PERATOM 1 1", id_fix, group->names[igroup]))); + fixstore = dynamic_cast( + modify->add_fix(fmt::format("{} {} STORE/ATOM 1 0 0 1", id_fix, group->names[igroup]))); } if ((idsflag != ONCE && !lockcount) && fixstore) { diff --git a/src/compute_chunk_atom.h b/src/compute_chunk_atom.h index 6850003b3e..943e36c985 100644 --- a/src/compute_chunk_atom.h +++ b/src/compute_chunk_atom.h @@ -93,7 +93,7 @@ class ComputeChunkAtom : public Compute { double *varatom; char *id_fix; - class FixStorePeratom *fixstore; + class FixStoreAtom *fixstore; class Fix *lockfix; // ptr to FixAveChunk that is locking out setups // null pointer if no lock currently in place diff --git a/src/compute_displace_atom.cpp b/src/compute_displace_atom.cpp index 0b1ffff687..9f37ff2a78 100644 --- a/src/compute_displace_atom.cpp +++ b/src/compute_displace_atom.cpp @@ -17,7 +17,7 @@ #include "atom.h" #include "domain.h" #include "error.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "group.h" #include "input.h" #include "memory.h" @@ -74,8 +74,8 @@ ComputeDisplaceAtom::ComputeDisplaceAtom(LAMMPS *lmp, int narg, char **arg) : // id = compute-ID + COMPUTE_STORE, fix group = compute group id_fix = utils::strdup(std::string(id) + "_COMPUTE_STORE"); - fix = dynamic_cast( - modify->add_fix(fmt::format("{} {} STORE/PERATOM 1 3", id_fix, group->names[igroup]))); + fix = dynamic_cast( + modify->add_fix(fmt::format("{} {} STORE/ATOM 3 0 0 1", id_fix, group->names[igroup]))); // calculate xu,yu,zu for fix store array // skip if reset from restart file @@ -120,7 +120,7 @@ void ComputeDisplaceAtom::init() { // set fix which stores original atom coords - fix = dynamic_cast(modify->get_fix_by_id(id_fix)); + fix = dynamic_cast(modify->get_fix_by_id(id_fix)); if (!fix) error->all(FLERR,"Could not find compute displace/atom fix with ID {}", id_fix); if (refreshflag) { diff --git a/src/compute_displace_atom.h b/src/compute_displace_atom.h index dc1be7434f..006928bd42 100644 --- a/src/compute_displace_atom.h +++ b/src/compute_displace_atom.h @@ -38,7 +38,7 @@ class ComputeDisplaceAtom : public Compute { int nmax; double **displace; char *id_fix; - class FixStorePeratom *fix; + class FixStoreAtom *fix; int refreshflag, ivar, nvmax; // refresh option is enabled char *rvar; // for incremental dumps diff --git a/src/compute_msd.cpp b/src/compute_msd.cpp index 8b7043e20d..e73dbd3d53 100644 --- a/src/compute_msd.cpp +++ b/src/compute_msd.cpp @@ -16,7 +16,7 @@ #include "atom.h" #include "domain.h" #include "error.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "group.h" #include "modify.h" #include "update.h" @@ -63,8 +63,8 @@ ComputeMSD::ComputeMSD(LAMMPS *lmp, int narg, char **arg) : Compute(lmp, narg, a // id = compute-ID + COMPUTE_STORE, fix group = compute group id_fix = utils::strdup(id + std::string("_COMPUTE_STORE")); - fix = dynamic_cast( - modify->add_fix(fmt::format("{} {} STORE/PERATOM 1 3", id_fix, group->names[igroup]))); + fix = dynamic_cast( + modify->add_fix(fmt::format("{} {} STORE/ATOM 3 0 0 1", id_fix, group->names[igroup]))); // calculate xu,yu,zu for fix store array // skip if reset from restart file @@ -127,7 +127,7 @@ void ComputeMSD::init() { // set fix which stores reference atom coords - fix = dynamic_cast(modify->get_fix_by_id(id_fix)); + fix = dynamic_cast(modify->get_fix_by_id(id_fix)); if (!fix) error->all(FLERR, "Could not find compute msd fix with ID {}", id_fix); // nmsd = # of atoms in group diff --git a/src/compute_msd.h b/src/compute_msd.h index a273e9cf58..ffb0c18c8c 100644 --- a/src/compute_msd.h +++ b/src/compute_msd.h @@ -39,7 +39,7 @@ class ComputeMSD : public Compute { bigint nmsd; double masstotal; char *id_fix; - class FixStorePeratom *fix; + class FixStoreAtom *fix; }; } // namespace LAMMPS_NS diff --git a/src/compute_vacf.cpp b/src/compute_vacf.cpp index 4e209f8612..acf1405092 100644 --- a/src/compute_vacf.cpp +++ b/src/compute_vacf.cpp @@ -18,7 +18,7 @@ #include "update.h" #include "group.h" #include "modify.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "error.h" using namespace LAMMPS_NS; @@ -39,8 +39,8 @@ ComputeVACF::ComputeVACF(LAMMPS *lmp, int narg, char **arg) : // id = compute-ID + COMPUTE_STORE, fix group = compute group id_fix = utils::strdup(id + std::string("_COMPUTE_STORE")); - fix = dynamic_cast( - modify->add_fix(fmt::format("{} {} STORE/PERATOM 1 3", id_fix, group->names[igroup]))); + fix = dynamic_cast( + modify->add_fix(fmt::format("{} {} STORE/ATOM 3 0 0 1", id_fix, group->names[igroup]))); // store current velocities in fix store array // skip if reset from restart file @@ -84,7 +84,7 @@ void ComputeVACF::init() { // set fix which stores original atom velocities - fix = dynamic_cast(modify->get_fix_by_id(id_fix)); + fix = dynamic_cast(modify->get_fix_by_id(id_fix)); if (!fix) error->all(FLERR,"Could not find compute vacf fix ID {}", id_fix); // nvacf = # of atoms in group diff --git a/src/compute_vacf.h b/src/compute_vacf.h index 42b3ed4adc..8e5e57ab65 100644 --- a/src/compute_vacf.h +++ b/src/compute_vacf.h @@ -35,7 +35,7 @@ class ComputeVACF : public Compute { protected: bigint nvacf; char *id_fix; - class FixStorePeratom *fix; + class FixStoreAtom *fix; }; } // namespace LAMMPS_NS diff --git a/src/dump_custom.cpp b/src/dump_custom.cpp index 8d64e532a4..8667c6af12 100644 --- a/src/dump_custom.cpp +++ b/src/dump_custom.cpp @@ -20,7 +20,7 @@ #include "domain.h" #include "error.h" #include "fix.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "group.h" #include "input.h" #include "memory.h" @@ -2005,16 +2005,16 @@ int DumpCustom::modify_param(int narg, char **arg) thresh_value[nthresh] = utils::numeric(FLERR,arg[3],false,lmp); thresh_last[nthresh] = -1; } else { - thresh_fix = (FixStorePeratom **) - memory->srealloc(thresh_fix,(nthreshlast+1)*sizeof(FixStorePeratom *),"dump:thresh_fix"); + thresh_fix = (FixStoreAtom **) + memory->srealloc(thresh_fix,(nthreshlast+1)*sizeof(FixStoreAtom *),"dump:thresh_fix"); thresh_fixID = (char **) memory->srealloc(thresh_fixID,(nthreshlast+1)*sizeof(char *),"dump:thresh_fixID"); memory->grow(thresh_first,(nthreshlast+1),"dump:thresh_first"); std::string threshid = fmt::format("{}{}_DUMP_STORE",id,nthreshlast); thresh_fixID[nthreshlast] = utils::strdup(threshid); - threshid += fmt::format(" {} STORE/PERATOM 1 1", group->names[igroup]); - thresh_fix[nthreshlast] = dynamic_cast(modify->add_fix(threshid)); + threshid += fmt::format(" {} STORE/ATOM 1 0 0 1", group->names[igroup]); + thresh_fix[nthreshlast] = dynamic_cast(modify->add_fix(threshid)); thresh_last[nthreshlast] = nthreshlast; thresh_first[nthreshlast] = 1; diff --git a/src/dump_custom.h b/src/dump_custom.h index da49ffdc22..b600bd60b8 100644 --- a/src/dump_custom.h +++ b/src/dump_custom.h @@ -37,19 +37,19 @@ class DumpCustom : public Dump { int nevery; // dump frequency for output char *idregion; // region ID, nullptr if no region - int nthresh; // # of defined thresholds - int nthreshlast; // # of defined thresholds with value = LAST - // - int *thresh_array; // array to threshold on for each nthresh - int *thresh_op; // threshold operation for each nthresh - double *thresh_value; // threshold value for each nthresh - int *thresh_last; // for threshold value = LAST, - // index into thresh_fix - // -1 if not LAST, value is numeric - // - class FixStorePeratom **thresh_fix; // stores values for each threshold LAST - char **thresh_fixID; // IDs of thresh_fixes - int *thresh_first; // 1 the first time a FixStore values accessed + int nthresh; // # of defined thresholds + int nthreshlast; // # of defined thresholds with value = LAST + // + int *thresh_array; // array to threshold on for each nthresh + int *thresh_op; // threshold operation for each nthresh + double *thresh_value; // threshold value for each nthresh + int *thresh_last; // for threshold value = LAST, + // index into thresh_fix + // -1 if not LAST, value is numeric + // + class FixStoreAtom **thresh_fix; // stores values for each threshold LAST + char **thresh_fixID; // IDs of thresh_fixes + int *thresh_first; // 1 the first time a FixStore values accessed int expand; // flag for whether field args were expanded char **earg; // field names with wildcard expansion diff --git a/src/fix_adapt.cpp b/src/fix_adapt.cpp index e0eaeb864e..8dd97250a3 100644 --- a/src/fix_adapt.cpp +++ b/src/fix_adapt.cpp @@ -19,7 +19,7 @@ #include "bond.h" #include "domain.h" #include "error.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "force.h" #include "group.h" #include "input.h" @@ -278,8 +278,8 @@ void FixAdapt::post_constructor() if (diamflag && atom->radius_flag) { id_fix_diam = utils::strdup(id + std::string("_FIX_STORE_DIAM")); - fix_diam = dynamic_cast( - modify->add_fix(fmt::format("{} {} STORE/PERATOM 1 1", id_fix_diam,group->names[igroup]))); + fix_diam = dynamic_cast( + modify->add_fix(fmt::format("{} {} STORE/ATOM 1 0 0 1", id_fix_diam,group->names[igroup]))); if (fix_diam->restart_reset) fix_diam->restart_reset = 0; else { double *vec = fix_diam->vstore; @@ -296,8 +296,8 @@ void FixAdapt::post_constructor() if (chgflag && atom->q_flag) { id_fix_chg = utils::strdup(id + std::string("_FIX_STORE_CHG")); - fix_chg = dynamic_cast( - modify->add_fix(fmt::format("{} {} STORE/PERATOM 1 1",id_fix_chg,group->names[igroup]))); + fix_chg = dynamic_cast( + modify->add_fix(fmt::format("{} {} STORE/ATOM 1 0 0 1",id_fix_chg,group->names[igroup]))); if (fix_chg->restart_reset) fix_chg->restart_reset = 0; else { double *vec = fix_chg->vstore; @@ -494,11 +494,11 @@ void FixAdapt::init() // fixes that store initial per-atom values if (id_fix_diam) { - fix_diam = dynamic_cast(modify->get_fix_by_id(id_fix_diam)); + fix_diam = dynamic_cast(modify->get_fix_by_id(id_fix_diam)); if (!fix_diam) error->all(FLERR,"Could not find fix adapt storage fix ID {}", id_fix_diam); } if (id_fix_chg) { - fix_chg = dynamic_cast(modify->get_fix_by_id(id_fix_chg)); + fix_chg = dynamic_cast(modify->get_fix_by_id(id_fix_chg)); if (!fix_chg) error->all(FLERR,"Could not find fix adapt storage fix ID {}", id_fix_chg); } diff --git a/src/fix_adapt.h b/src/fix_adapt.h index 82dc739c67..f8477f7259 100644 --- a/src/fix_adapt.h +++ b/src/fix_adapt.h @@ -48,7 +48,7 @@ class FixAdapt : public Fix { int anypair, anybond, anyangle; int nlevels_respa; char *id_fix_diam, *id_fix_chg; - class FixStorePeratom *fix_diam, *fix_chg; + class FixStoreAtom *fix_diam, *fix_chg; double previous_diam_scale, previous_chg_scale; int discflag; diff --git a/src/fix_balance.cpp b/src/fix_balance.cpp index 06274eea03..844ffe474e 100644 --- a/src/fix_balance.cpp +++ b/src/fix_balance.cpp @@ -19,7 +19,7 @@ #include "comm.h" #include "domain.h" #include "error.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "force.h" #include "irregular.h" #include "kspace.h" diff --git a/src/fix_store_peratom.cpp b/src/fix_store_atom.cpp similarity index 60% rename from src/fix_store_peratom.cpp rename to src/fix_store_atom.cpp index 6f5637e3f6..461959d264 100644 --- a/src/fix_store_peratom.cpp +++ b/src/fix_store_atom.cpp @@ -11,7 +11,7 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "atom.h" #include "error.h" @@ -22,50 +22,59 @@ using namespace LAMMPS_NS; using namespace FixConst; +// INTERNAL fix for storing/communicating per-atom values +// syntax: id group style n1 n2 gflag rflag +// N1 = 1, N2 = 0 is per-atom vector, single value per atom +// N1 > 1, N2 = 0 is per-atom array, N1 values per atom +// N1 > 0, N2 > 0 is per-atom tensor, N1xN2 array per atom +// gflag = 0/1, no/yes communicate per-atom values with ghost atoms +// rflag = 0/1, no/yes store per-atom values in restart file + /* ---------------------------------------------------------------------- */ -FixStorePeratom::FixStorePeratom(LAMMPS *lmp, int narg, char **arg) : +FixStoreAtom::FixStoreAtom(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg), vstore(nullptr), astore(nullptr) { - if (narg != 5 && narg != 6) - error->all(FLERR, "Illegal fix STORE/PERATOM command: number of args"); - - // syntax: id group style 0/1 n1 n2 (n3), last arg optional - // 0/1 flag = not-store or store peratom values in restart file - // N2 = 1 and no n3 is vector, N2 > 1 and no n3 is array, N3 = tensor - // nvalues = # of peratom values, N = 1 is vector, N > 1 is array + if (narg != 7) error->all(FLERR, "Illegal fix STORE/ATOM command: number of args"); disable = 0; - vecflag = arrayflag = tensorflag = 0; - restart_peratom = utils::inumeric(FLERR, arg[3], false, lmp); + n1 = utils::inumeric(FLERR, arg[3], false, lmp); n2 = utils::inumeric(FLERR, arg[4], false, lmp); - if (narg == 6) - n3 = utils::inumeric(FLERR, arg[5], false, lmp); - else - n3 = 1; - if (restart_peratom < 0 || restart_peratom > 1) - error->all(FLERR, "Illegal fix STORE/PERATOM restart flag: {}", restart_peratom); - if (n2 <= 0 || n3 <= 0) - error->all(FLERR, "Illegal fix STORE/PERATOM dimension args: must be >0: {} {}", n2, n3); - if (n2 == 1 && narg == 5) + ghostflag = utils::logical(FLERR, arg[5], false, lmp); + restartflag = utils::logical(FLERR, arg[6], false, lmp); + + vecflag = arrayflag = tensorflag = 0; + if (n1 == 1 && n2 == 0) vecflag = 1; - else if (narg == 5) + else if (n1 > 1 && n2 == 0) arrayflag = 1; - else + else if (n1 > 0 && n2 > 0) tensorflag = 1; - nvalues = n2 * n3; + else + error->all(FLERR, "Illegal fix STORE/ATOM dimension args: {} {}", n1, n2); + + if (vecflag || arrayflag) + nvalues = n1; + else + nvalues = n1 * n2; nbytes = nvalues * sizeof(double); + if (ghostflag) comm_border = nvalues; + maxexchange = nvalues; + + if (restartflag) restart_peratom = 1; + + // allocate data structs and register with Atom class + vstore = nullptr; astore = nullptr; tstore = nullptr; - // allocate data structs and register with Atom class - - FixStorePeratom::grow_arrays(atom->nmax); + FixStoreAtom::grow_arrays(atom->nmax); atom->add_callback(Atom::GROW); - if (restart_peratom) atom->add_callback(Atom::RESTART); + if (restartflag) atom->add_callback(Atom::RESTART); + if (ghostflag) atom->add_callback(Atom::BORDER); // zero the storage @@ -74,23 +83,23 @@ FixStorePeratom::FixStorePeratom(LAMMPS *lmp, int narg, char **arg) : for (int i = 0; i < nlocal; i++) vstore[i] = 0.0; } else if (arrayflag) { for (int i = 0; i < nlocal; i++) - for (int j = 0; j < n2; j++) astore[i][j] = 0.0; + for (int j = 0; j < n1; j++) astore[i][j] = 0.0; } else if (tensorflag) { for (int i = 0; i < nlocal; i++) - for (int j = 0; j < n2; j++) - for (int k = 0; k < n3; k++) tstore[i][j][k] = 0.0; + for (int j = 0; j < n1; j++) + for (int k = 0; k < n2; k++) tstore[i][j][k] = 0.0; } - maxexchange = nvalues; } /* ---------------------------------------------------------------------- */ -FixStorePeratom::~FixStorePeratom() +FixStoreAtom::~FixStoreAtom() { // unregister callbacks to this fix from Atom class atom->delete_callback(id, Atom::GROW); - if (restart_peratom) atom->delete_callback(id, Atom::RESTART); + if (restartflag) atom->delete_callback(id, Atom::RESTART); + if (ghostflag) atom->delete_callback(id, Atom::BORDER); memory->destroy(vstore); memory->destroy(astore); @@ -99,7 +108,7 @@ FixStorePeratom::~FixStorePeratom() /* ---------------------------------------------------------------------- */ -int FixStorePeratom::setmask() +int FixStoreAtom::setmask() { int mask = 0; return mask; @@ -109,21 +118,21 @@ int FixStorePeratom::setmask() allocate atom-based array ------------------------------------------------------------------------- */ -void FixStorePeratom::grow_arrays(int nmax) +void FixStoreAtom::grow_arrays(int nmax) { if (vecflag) memory->grow(vstore, nmax, "store:vstore"); else if (arrayflag) - memory->grow(astore, nmax, n2, "store:astore"); + memory->grow(astore, nmax, n1, "store:astore"); else if (tensorflag) - memory->grow(tstore, nmax, n2, n3, "store:tstore"); + memory->grow(tstore, nmax, n1, n2, "store:tstore"); } /* ---------------------------------------------------------------------- copy values within local atom-based array ------------------------------------------------------------------------- */ -void FixStorePeratom::copy_arrays(int i, int j, int /*delflag*/) +void FixStoreAtom::copy_arrays(int i, int j, int /*delflag*/) { if (disable) return; @@ -136,11 +145,65 @@ void FixStorePeratom::copy_arrays(int i, int j, int /*delflag*/) } } +/* ---------------------------------------------------------------------- + pack values for border communication at re-neighboring +------------------------------------------------------------------------- */ + +int FixStoreAtom::pack_border(int n, int *list, double *buf) +{ + int i, j, k; + + int m = 0; + if (vecflag) { + for (i = 0; i < n; i++) { + j = list[i]; + buf[m++] = vstore[j]; + } + } else if (arrayflag) { + for (i = 0; i < n; i++) { + j = list[i]; + for (k = 0; k < nvalues; k++) buf[m++] = astore[j][k]; + } + } else if (tensorflag) { + for (i = 0; i < n; i++) { + j = list[i]; + memcpy(&buf[m], &tstore[j][0][0], nbytes); + m += nvalues; + } + } + + return m; +} + +/* ---------------------------------------------------------------------- + unpack values for border communication at re-neighboring +------------------------------------------------------------------------- */ + +int FixStoreAtom::unpack_border(int n, int first, double *buf) +{ + int i, k, last; + + int m = 0; + last = first + n; + if (vecflag) { + for (i = first; i < last; i++) vstore[i] = buf[m++]; + } else if (arrayflag) { + for (i = first; i < last; i++) + for (k = 0; k < nvalues; k++) astore[i][k] = buf[m++]; + } else if (tensorflag) { + for (i = first; i < last; i++) { + memcpy(&tstore[i][0][0], &buf[m], nbytes); + m += nvalues; + } + } + return m; +} + /* ---------------------------------------------------------------------- pack values in local atom-based array for exchange with another proc ------------------------------------------------------------------------- */ -int FixStorePeratom::pack_exchange(int i, double *buf) +int FixStoreAtom::pack_exchange(int i, double *buf) { if (disable) return 0; @@ -159,7 +222,7 @@ int FixStorePeratom::pack_exchange(int i, double *buf) unpack values in local atom-based array from exchange with another proc ------------------------------------------------------------------------- */ -int FixStorePeratom::unpack_exchange(int nlocal, double *buf) +int FixStoreAtom::unpack_exchange(int nlocal, double *buf) { if (disable) return 0; @@ -178,7 +241,7 @@ int FixStorePeratom::unpack_exchange(int nlocal, double *buf) pack values in local atom-based arrays for restart file ------------------------------------------------------------------------- */ -int FixStorePeratom::pack_restart(int i, double *buf) +int FixStoreAtom::pack_restart(int i, double *buf) { if (disable) { buf[0] = 0; @@ -203,7 +266,7 @@ int FixStorePeratom::pack_restart(int i, double *buf) unpack values from atom->extra array to restart the fix ------------------------------------------------------------------------- */ -void FixStorePeratom::unpack_restart(int nlocal, int nth) +void FixStoreAtom::unpack_restart(int nlocal, int nth) { if (disable) return; @@ -229,7 +292,7 @@ void FixStorePeratom::unpack_restart(int nlocal, int nth) maxsize of any atom's restart data ------------------------------------------------------------------------- */ -int FixStorePeratom::maxsize_restart() +int FixStoreAtom::maxsize_restart() { if (disable) return 1; return nvalues + 1; @@ -239,17 +302,17 @@ int FixStorePeratom::maxsize_restart() size of atom nlocal's restart data ------------------------------------------------------------------------- */ -int FixStorePeratom::size_restart(int /*nlocal*/) +int FixStoreAtom::size_restart(int /*nlocal*/) { if (disable) return 1; return nvalues + 1; } /* ---------------------------------------------------------------------- - memory usage of global or peratom atom-based array + memory usage of per-atom atom-based array ------------------------------------------------------------------------- */ -double FixStorePeratom::memory_usage() +double FixStoreAtom::memory_usage() { - return (double) atom->nmax * n2 * n3 * sizeof(double); + return (double) atom->nmax * nvalues * sizeof(double); } diff --git a/src/fix_store_peratom.h b/src/fix_store_atom.h similarity index 77% rename from src/fix_store_peratom.h rename to src/fix_store_atom.h index d3efe4142b..e13b8aa37d 100644 --- a/src/fix_store_peratom.h +++ b/src/fix_store_atom.h @@ -13,30 +13,32 @@ #ifdef FIX_CLASS // clang-format off -FixStyle(STORE/PERATOM,FixStorePeratom); +FixStyle(STORE/ATOM,FixStoreAtom); // clang-format on #else -#ifndef LMP_FIX_STORE_PERATOM_H -#define LMP_FIX_STORE_PERATOM_H +#ifndef LMP_FIX_STORE_ATOM_H +#define LMP_FIX_STORE_ATOM_H #include "fix.h" namespace LAMMPS_NS { -class FixStorePeratom : public Fix { +class FixStoreAtom : public Fix { public: double *vstore; // vector storage double **astore; // array storage double ***tstore; // tensor (3d array) storage int disable; // 1 if operations (except grow) are currently disabled - FixStorePeratom(class LAMMPS *, int, char **); - ~FixStorePeratom() override; + FixStoreAtom(class LAMMPS *, int, char **); + ~FixStoreAtom() override; int setmask() override; void grow_arrays(int) override; void copy_arrays(int, int, int) override; + int pack_border(int, int *, double *) override; + int unpack_border(int, int, double *) override; int pack_exchange(int, double *) override; int unpack_exchange(int, double *) override; int pack_restart(int, double *) override; @@ -50,8 +52,10 @@ class FixStorePeratom : public Fix { int vecflag; // 1 if ncol=1 int arrayflag; // 1 if a 2d array (vector per atom) int tensorflag; // 1 if a 3d array (array per atom) + int ghostflag; // 0/1 to communicate values with ghost atoms + int restartflag; // 0/1 to store values in restart files - int n2, n3; // size of 3d dims of per-atom data struct + int n1, n2; // size of 3d dims of per-atom data struct int nvalues; // number of per-atom values int nbytes; // number of per-atom bytes }; diff --git a/src/fix_store_global.cpp b/src/fix_store_global.cpp index cebf4f7690..028d35810e 100644 --- a/src/fix_store_global.cpp +++ b/src/fix_store_global.cpp @@ -182,7 +182,7 @@ void FixStoreGlobal::restart(char *buf) } /* ---------------------------------------------------------------------- - memory usage of global or peratom atom-based array + memory usage of global data ------------------------------------------------------------------------- */ double FixStoreGlobal::memory_usage() diff --git a/src/improper.cpp b/src/improper.cpp index b135dfbac8..dd4b1b2b25 100644 --- a/src/improper.cpp +++ b/src/improper.cpp @@ -30,6 +30,7 @@ Improper::Improper(LAMMPS *_lmp) : Pointers(_lmp) { energy = 0.0; writedata = 0; + for (int i = 0; i < 4; i++) symmatoms[i] = 0; allocated = 0; suffix_flag = Suffix::NONE; diff --git a/src/improper.h b/src/improper.h index 59302485e2..fbe86dfcd1 100644 --- a/src/improper.h +++ b/src/improper.h @@ -36,6 +36,11 @@ class Improper : protected Pointers { // CENTROID_SAME = same as two-body stress // CENTROID_AVAIL = different and implemented // CENTROID_NOTAVAIL = different, not yet implemented + + int symmatoms[4]; // symmetry atom(s) of improper style + // value of 0: interchangable atoms + // value of 1: central atom + // values >1: additional atoms of symmetry // KOKKOS host/device flag and data masks diff --git a/src/variable.cpp b/src/variable.cpp index 2ac9bd0364..19aed73734 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -20,7 +20,7 @@ #include "domain.h" #include "error.h" #include "fix.h" -#include "fix_store_peratom.h" +#include "fix_store_atom.h" #include "group.h" #include "info.h" #include "input.h" @@ -5027,8 +5027,8 @@ VarReader::VarReader(LAMMPS *lmp, char *name, char *file, int flag) : error->all(FLERR,"Cannot use atomfile-style variable unless an atom map exists"); id_fix = utils::strdup(std::string(name) + "_VARIABLE_STORE"); - fixstore = dynamic_cast( - modify->add_fix(std::string(id_fix) + " all STORE/PERATOM 0 1")); + fixstore = dynamic_cast( + modify->add_fix(std::string(id_fix) + " all STORE/ATOM 1 0 0 0")); buffer = new char[CHUNK*MAXLINE]; } } diff --git a/src/variable.h b/src/variable.h index 6326c5cc78..825a207d78 100644 --- a/src/variable.h +++ b/src/variable.h @@ -152,7 +152,7 @@ class Variable : protected Pointers { class VarReader : protected Pointers { public: - class FixStorePeratom *fixstore; + class FixStoreAtom *fixstore; char *id_fix; VarReader(class LAMMPS *, char *, char *, int); diff --git a/unittest/force-styles/test_angle_style.cpp b/unittest/force-styles/test_angle_style.cpp index d9f541df96..e9f4a3f7fc 100644 --- a/unittest/force-styles/test_angle_style.cpp +++ b/unittest/force-styles/test_angle_style.cpp @@ -691,8 +691,8 @@ TEST(AngleStyle, extract) } auto angle = lmp->force->angle; - void *ptr = nullptr; - int dim = 0; + void *ptr = nullptr; + int dim = 0; for (auto extract : test_config.extract) { ptr = angle->extract(extract.first.c_str(), dim); EXPECT_NE(ptr, nullptr); diff --git a/unittest/force-styles/test_bond_style.cpp b/unittest/force-styles/test_bond_style.cpp index d056fdc876..c723541366 100644 --- a/unittest/force-styles/test_bond_style.cpp +++ b/unittest/force-styles/test_bond_style.cpp @@ -123,7 +123,7 @@ LAMMPS *init_lammps(int argc, char **argv, const TestConfig &cfg, const bool new command("run 0 post no"); command("write_restart " + cfg.basename + ".restart"); - command("write_data " + cfg.basename + ".data"); + command("write_data " + cfg.basename + ".data nofix"); command("write_coeff " + cfg.basename + "-coeffs.in"); return lmp; diff --git a/unittest/force-styles/tests/bond-harmonic_restrain.yaml b/unittest/force-styles/tests/bond-harmonic_restrain.yaml new file mode 100644 index 0000000000..07546775ab --- /dev/null +++ b/unittest/force-styles/tests/bond-harmonic_restrain.yaml @@ -0,0 +1,89 @@ +--- +lammps_version: 8 Feb 2023 +date_generated: Tue Mar 7 21:07:27 2023 +epsilon: 2.5e-13 +skip_tests: extract +prerequisites: ! | + atom full + bond harmonic/restrain +pre_commands: ! "" +post_commands: ! "" +input_file: in.fourmol +bond_style: harmonic/restrain +bond_coeff: ! | + 1 250.0 + 2 300.0 + 3 350.0 + 4 650.0 + 5 450.0 +equilibrium: 5 -1 -1 -1 -1 -1 +extract: ! | + k 1 +natoms: 29 +init_energy: 0 +init_stress: ! |2- + 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +init_forces: ! |2 + 1 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 2 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 3 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 4 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 5 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 6 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 7 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 8 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 9 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 10 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 11 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 12 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 13 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 14 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 15 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 16 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 17 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 18 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 19 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 20 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 21 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 22 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 23 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 24 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 25 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 26 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 27 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 28 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 + 29 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 +run_energy: 0.009384424442608962 +run_stress: ! |2- + 1.3334287184173488e+00 3.1110677999939773e-01 -1.4064657849540130e+00 2.6546279385354110e-01 1.5492956756466219e+00 7.2358876924785698e-01 +run_forces: ! |2 + 1 1.1485941046856593e-01 1.4088049450172524e-01 -8.5852076971833030e-02 + 2 -9.3217481807658653e-02 -7.6867386712704044e-02 1.0932532178570745e-01 + 3 -2.3741413942894266e-01 -8.5667734110971339e-02 -8.2143831089792743e-02 + 4 2.3324188168788909e-01 -6.5094431822773302e-02 1.6591701889629748e-01 + 5 2.6793200848186677e-02 4.1227376782380774e-02 -1.3685685314886964e-01 + 6 2.4862628338772436e-01 -3.6125357500552457e-01 -7.8230634578348013e-01 + 7 -3.8706943762359766e-02 1.9888379369193138e-01 9.8933719851963053e-01 + 8 -3.5267248957722913e-01 4.2911503092501313e-01 1.0190469073820968e-01 + 9 -5.1632048293607458e-02 -5.5343430872859360e-02 -2.2821606693951479e-01 + 10 1.2860877826855494e-01 -7.5971599169706849e-01 -5.5343112593256227e-01 + 11 1.6956002318038377e-01 4.2001247662003161e-01 6.8896503378985918e-01 + 12 3.4231534762621078e-02 -2.4857235824638585e-01 -6.3964642589377518e-01 + 13 -2.7815178906130594e-01 1.0946454990993748e-01 5.1669158882660616e-03 + 14 2.2738751895410908e-01 -4.5437525741145839e-02 5.8956676893113813e-01 + 15 -4.6207378210972273e-03 1.6438094307388113e-01 5.8917445017986604e-02 + 16 -1.1399994473799732e-02 1.1329499720204761e-01 -5.0720152745025260e-01 + 17 -1.1549300733203431e-01 8.0692771502484495e-02 3.0655385964298520e-01 + 18 1.9145703373728828e+00 1.8373130373081787e+00 -3.9519344330792983e-01 + 19 -4.7317441908503255e-01 -3.0353033418925196e-01 -5.7175303978447201e-01 + 20 -1.4413959182878502e+00 -1.5337827031189268e+00 9.6694648309240183e-01 + 21 -3.3244533656237202e-01 -3.0309080808086836e-01 6.5775553694406208e-01 + 22 -2.9549353211149859e-01 -7.2150425050573716e-02 -4.6194669575592789e-01 + 23 6.2793886867387061e-01 3.7524123313144209e-01 -1.9580884118813421e-01 + 24 8.2698432709098157e-01 -1.4448474780063469e+00 1.2133188519739595e+00 + 25 -1.5417378702379472e+00 2.4470962384652978e-01 -1.2964818258023694e+00 + 26 7.1475354314696560e-01 1.2001378541598171e+00 8.3162973828409884e-02 + 27 2.1885007758012770e-01 -5.7423924185981945e-01 2.7745249319135684e-01 + 28 -5.2036258696458004e-01 2.2330647386191435e-01 -3.5136945845348061e-01 + 29 3.0151250938445234e-01 3.5093276799790507e-01 7.3916965262123782e-02 +...