Merge pull request #2906 from jtclemm/BPM

Adding package for bonded particle models
This commit is contained in:
Axel Kohlmeyer
2022-04-14 15:43:14 -04:00
committed by GitHub
124 changed files with 12509 additions and 1356 deletions

View File

@ -172,6 +172,7 @@ set(STANDARD_PACKAGES
AWPMD
BOCS
BODY
BPM
BROWNIAN
CG-DNA
CG-SDK

View File

@ -8,6 +8,7 @@ set(ALL_PACKAGES
AWPMD
BOCS
BODY
BPM
BROWNIAN
CG-DNA
CG-SDK

View File

@ -10,6 +10,7 @@ set(ALL_PACKAGES
AWPMD
BOCS
BODY
BPM
BROWNIAN
CG-DNA
CG-SDK

View File

@ -4,6 +4,7 @@ set(WIN_PACKAGES
AWPMD
BOCS
BODY
BPM
BROWNIAN
CG-DNA
CG-SDK

View File

@ -6,6 +6,7 @@ set(ALL_PACKAGES
ASPHERE
BOCS
BODY
BPM
BROWNIAN
CG-DNA
CG-SDK

View File

@ -2,6 +2,7 @@ set(WIN_PACKAGES
ASPHERE
BOCS
BODY
BPM
BROWNIAN
CG-DNA
CG-SDK

View File

@ -32,6 +32,8 @@ OPT.
*
*
*
* :doc:`bpm/rotational <bond_bpm_rotational>`
* :doc:`bpm/spring <bond_bpm_spring>`
* :doc:`class2 (ko) <bond_class2>`
* :doc:`fene (iko) <bond_fene>`
* :doc:`fene/expand (o) <bond_fene_expand>`

View File

@ -91,6 +91,7 @@ KOKKOS, o = OPENMP, t = OPT.
* :doc:`msd <compute_msd>`
* :doc:`msd/chunk <compute_msd_chunk>`
* :doc:`msd/nongauss <compute_msd_nongauss>`
* :doc:`nbond/atom <compute_nbond_atom>`
* :doc:`omega/chunk <compute_omega_chunk>`
* :doc:`orientorder/atom (k) <compute_orientorder_atom>`
* :doc:`pair <compute_pair>`

View File

@ -141,6 +141,7 @@ OPT.
* :doc:`nve/manifold/rattle <fix_nve_manifold_rattle>`
* :doc:`nve/noforce <fix_nve_noforce>`
* :doc:`nve/sphere (ko) <fix_nve_sphere>`
* :doc:`nve/bpm/sphere <fix_nve_bpm_sphere>`
* :doc:`nve/spin <fix_nve_spin>`
* :doc:`nve/tri <fix_nve_tri>`
* :doc:`nvk <fix_nvk>`
@ -158,7 +159,6 @@ OPT.
* :doc:`orient/fcc <fix_orient>`
* :doc:`orient/eco <fix_orient_eco>`
* :doc:`pafi <fix_pafi>`
* :doc:`pair/tracker <fix_pair_tracker>`
* :doc:`phonon <fix_phonon>`
* :doc:`pimd <fix_pimd>`
* :doc:`planeforce <fix_planeforce>`

View File

@ -53,6 +53,7 @@ OPT.
* :doc:`born/coul/msm (o) <pair_born>`
* :doc:`born/coul/wolf (go) <pair_born>`
* :doc:`born/coul/wolf/cs (g) <pair_cs>`
* :doc:`bpm/spring <pair_bpm_spring>`
* :doc:`brownian (o) <pair_brownian>`
* :doc:`brownian/poly (o) <pair_brownian>`
* :doc:`buck (giko) <pair_buck>`

View File

@ -54,6 +54,8 @@ Lowercase directories
+-------------+------------------------------------------------------------------+
| body | body particles, 2d system |
+-------------+------------------------------------------------------------------+
| bpm | BPM simulations of pouring elastic grains and plate impact |
+-------------+------------------------------------------------------------------+
| cmap | CMAP 5-body contributions to CHARMM force field |
+-------------+------------------------------------------------------------------+
| colloid | big colloid particles in a small particle solvent, 2d system |

View File

@ -23,6 +23,8 @@ General howto
Howto_library
Howto_couple
Howto_mdi
Howto_bpm
Howto_broken_bonds
Settings howto
==============

124
doc/src/Howto_bpm.rst Normal file
View File

@ -0,0 +1,124 @@
Bonded particle models
======================
The BPM package implements bonded particle models which can be used to
simulate mesoscale solids. Solids are constructed as a collection of
particles which each represent a coarse-grained region of space much
larger than the atomistic scale. Particles within a solid region are
then connected by a network of bonds to provide solid elasticity.
Unlike traditional bonds in molecular dynamics, the equilibrium bond
length can vary between bonds. Bonds store the reference state. This
includes setting the equilibrium length equal to the initial distance
between the two particles but can also include data on the bond
orientation for rotational models. This produces a stress free initial
state. Furthermore, bonds are allowed to break under large strains
producing fracture. The examples/bpm directory has sample input scripts
for simulations of the fragmentation of an impacted plate and the
pouring of extended, elastic bodies.
----------
Bonds can be created using a :doc:`read data <read_data>` or
:doc:`create bonds <create_bonds>` command. Alternatively, a
:doc:`molecule <molecule>` template with bonds can be used with
:doc:`fix deposit <fix_deposit>` or :doc:`fix pour <fix_pour>` to
create solid grains.
In this implementation, bonds store their reference state when they are
first computed in the setup of the first simulation run. Data is then
preserved across run commands and is written to :doc:`binary restart
files <restart>` such that restarting the system will not reset the
reference state of a bond. Bonds that are created midway into a run,
such as those created by pouring grains using :doc:`fix pour
<fix_pour>`, are initialized on that timestep.
As bonds can be broken between neighbor list builds, the
:doc:`special_bonds <special_bonds>` command works differently for BPM
bond styles. There are two possible settings which determine how pair
interactions work between bonded particles. First, one can turn off
all pair interactions between bonded particles. Unlike :doc:`bond
quartic <bond_quartic>`, this is not done by subtracting pair forces
during the bond computation but rather by dynamically updating the
special bond list. This is the default behavior of BPM bond styles and
is done by updating the 1-2 special bond list as bonds break. To do
this, LAMMPS requires :doc:`newton <newton>` bond off such that all
processors containing an atom know when a bond breaks. Additionally,
one must do either (A) or (B).
(A)
Use the following special bond settings
.. code-block:: LAMMPS
special_bonds lj 0 1 1 coul 1 1 1
These settings accomplish two goals. First, they turn off 1-3 and 1-4
special bond lists, which are not currently supported for BPMs. As
BPMs often have dense bond networks, generating 1-3 and 1-4 special
bond lists is expensive. By setting the lj weight for 1-2 bonds to
zero, this turns off pairwise interactions. Even though there are no
charges in BPM models, setting a nonzero coul weight for 1-2 bonds
ensures all bonded neighbors are still included in the neighbor list
in case bonds break between neighbor list builds.
(B)
Alternatively, one can simply overlay pair interactions such that all
bonded particles also feel pair interactions. This can be accomplished
by using the *overlay/pair* keyword present in all bpm bond styles and
by using the following special bond settings
.. code-block:: LAMMPS
special_bonds lj/coul 1 1 1
See the :doc:`Howto <Howto_broken_bonds>` page on broken bonds for
more information.
----------
Currently there are two types of bonds included in the BPM
package. The first bond style, :doc:`bond bpm/spring
<bond_bpm_spring>`, only applies pairwise, central body forces. Point
particles must have :doc:`bond atom style <atom_style>` and may be
thought of as nodes in a spring network. Alternatively, the second
bond style, :doc:`bond bpm/rotational <bond_bpm_rotational>`, resolves
tangential forces and torques arising with the shearing, bending, and
twisting of the bond due to rotation or displacement of particles.
Particles are similar to those used in the :doc:`granular package
<Howto_granular>`, :doc:`atom style sphere <atom_style>`. However,
they must also track the current orientation of particles and store bonds
and therefore use a :doc:`bpm/sphere atom style <atom_style>`.
This also requires a unique integrator :doc:`fix nve/bpm/sphere
<fix_nve_bpm_sphere>` which numerically integrates orientation similar
to :doc:`fix nve/asphere <fix_nve_asphere>`.
To monitor the fracture of bonds in the system, all BPM bond styles
have the ability to record instances of bond breakage to output using
the :doc:`dump local <dump>` command. Additionally, one can use
:doc:`compute nbond/atom <compute_nbond_atom>` to tally the current
number of bonds per atom.
In addition to bond styles, a new pair style :doc:`pair bpm/spring
<pair_bpm_spring>` was added to accompany the bpm/spring bond
style. This pair style is simply a hookean repulsion with similar
velocity damping as its sister bond style.
----------
While LAMMPS has many utilities to create and delete bonds, *only*
the following are currently compatible with BPM bond styles:
* :doc:`create_bonds <create_bonds>`
* :doc:`delete_bonds <delete_bonds>`
* :doc:`fix bond/create <fix_bond_create>`
* :doc:`fix bond/break <fix_bond_break>`
* :doc:`fix bond/swap <fix_bond_swap>`
Note :doc:`create_bonds <create_bonds>` requires certain special_bonds settings.
To subtract pair interactions, one will need to switch between different
special_bonds settings in the input script. An example is found in
examples/bpm/impact.

View File

@ -0,0 +1,48 @@
Broken Bonds
============
Typically, bond interactions persist for the duration of a simulation
in LAMMPS. However, there are some exceptions that allow for bonds to
break including the :doc:`quartic bond style <bond_quartic>` and the
bond styles in the :doc:`BPM package <Howto_bpm>` which contains the
:doc:`bpm/spring <bond_bpm_spring>` and
:doc:`bpm/rotational <bond_bpm_rotational>` bond styles. In these cases,
a bond can be broken if it is stretched beyond a user-defined threshold.
LAMMPS accomplishes this by setting the bond type to zero such that the
bond force is no longer computed.
Users are normally able to weight the contribution of pair forces to atoms
that are bonded using the :doc:`special_bonds command <special_bonds>`.
When bonds break, this is not always the case. For the quartic bond style,
pair forces are always turned off between bonded particles. LAMMPS does
this via a computational sleight-of-hand. It subtracts the pairwise
interaction as part of the bond computation. When the bond breaks, the
subtraction stops. For this to work, the pairwise interaction must always
be computed by the :doc:`pair_style <pair_style>` command, whether the bond
is broken or not. This means that :doc:`special_bonds <special_bonds>` must
be set to 1,1,1. After the bond breaks, the pairwise interaction between the
two atoms is turned on, since they are no longer bonded.
In the BPM package, one can either turn off all pair interactions between
bonded particles or leave them on, overlaying pair forces on top of bond
forces. To remove pair forces, the special bond list is dynamically
updated. More details can be found on the :doc:`Howto BPM <Howto_bpm>`
page.
Bonds can also be broken by fixes which change bond topology, including
:doc:`fix bond/break <fix_bond_break>` and
:doc:`fix bond/react <fix_bond_react>`. These fixes will automatically
trigger a rebuild of the neighbor list and update special bond data structures
when bonds are broken.
Note that when bonds are dumped to a file via the :doc:`dump local <dump>` command, bonds with type 0 are not included. The
:doc:`delete_bonds <delete_bonds>` command can also be used to query the
status of broken bonds or permanently delete them, e.g.:
.. code-block:: LAMMPS
delete_bonds all stats
delete_bonds all bond 0 remove
The compute :doc:`nbond/atom <compute_nbond_atom>` can also be used
to tally the current number of bonds per atom, excluding broken bonds.

View File

@ -32,6 +32,7 @@ page gives those details.
* :ref:`AWPMD <PKG-AWPMD>`
* :ref:`BOCS <PKG-BOCS>`
* :ref:`BODY <PKG-BODY>`
* :ref:`BPM <PKG-BPM>`
* :ref:`BROWNIAN <PKG-BROWNIAN>`
* :ref:`CG-DNA <PKG-CG-DNA>`
* :ref:`CG-SDK <PKG-CG-SDK>`
@ -283,6 +284,33 @@ overview.
----------
.. _PKG-BPM:
BPM package
------------
**Contents:**
Pair styles, bond styles, fixes, and computes for bonded particle
models for mesoscale simulations of solids and fracture. See the
:doc:`Howto bpm <Howto_bpm>` page for an overview.
**Authors:** Joel T. Clemmer (Sandia National Labs)
**Supporting info:**
* src/BPM filenames -> commands
* :doc:`Howto_bpm <Howto_bpm>`
* :doc:`atom_style bpm/sphere <atom_style>`
* :doc:`bond_style bpm/rotational <bond_bpm_rotational>`
* :doc:`bond_style bpm/spring <bond_bpm_spring>`
* :doc:`compute nbond/atom <compute_nbond_atom>`
* :doc:`fix nve/bpm/sphere <fix_nve_bpm_sphere>`
* :doc:`pair_style bpm/spring <pair_bpm_spring>`
* examples/bpm
----------
.. _PKG-BROWNIAN:
BROWNIAN package
@ -1545,7 +1573,6 @@ listing, "ls src/MISC", to see the list of commands.
* :doc:`pair_style list <pair_list>`
* :doc:`pair_style srp <pair_srp>`
* :doc:`pair_style tracker <pair_tracker>`
* :doc:`fix pair/tracker <fix_pair_tracker>`
----------

View File

@ -58,6 +58,11 @@ whether an extra library is needed to build and use the package:
- :doc:`Howto body <Howto_body>`
- body
- no
* - :ref:`BPM <PKG-BPM>`
- bonded particle models
- :doc:`Howto bpm <Howto_bpm>`
- bpm
- no
* - :ref:`BROWNIAN <PKG-BROWNIAN>`
- Brownian dynamics, self-propelled particles
- :doc:`fix brownian <fix_brownian>`, :doc:`fix propel/self <fix_propel_self>`

View File

@ -10,7 +10,7 @@ Syntax
atom_style style args
* style = *angle* or *atomic* or *body* or *bond* or *charge* or *dipole* or *dpd* or *edpd* or *electron* or *ellipsoid* or *full* or *line* or *mdpd* or *molecular* or *oxdna* or *peri* or *smd* or *sph* or *sphere* or *spin* or *tdpd* or *tri* or *template* or *hybrid*
* style = *angle* or *atomic* or *body* or *bond* or *charge* or *dipole* or *dpd* or *edpd* or *electron* or *ellipsoid* or *full* or *line* or *mdpd* or *molecular* or *oxdna* or *peri* or *smd* or *sph* or *sphere* or *bpm/sphere* or *spin* or *tdpd* or *tri* or *template* or *hybrid*
.. parsed-literal::
@ -21,6 +21,7 @@ Syntax
see the :doc:`Howto body <Howto_body>` doc
page for details
*sphere* arg = 0/1 (optional) for static/dynamic particle radii
*bpm/sphere* arg = 0/1 (optional) for static/dynamic particle radii
*tdpd* arg = Nspecies
Nspecies = # of chemical species
*template* arg = template-ID
@ -120,6 +121,8 @@ quantities.
+--------------+-----------------------------------------------------+--------------------------------------+
| *sphere* | diameter, mass, angular velocity | granular models |
+--------------+-----------------------------------------------------+--------------------------------------+
| *bpm/sphere* | diameter, mass, angular velocity, quaternion | granular bonded particle models (BPM)|
+--------------+-----------------------------------------------------+--------------------------------------+
| *spin* | magnetic moment | system with magnetic particles |
+--------------+-----------------------------------------------------+--------------------------------------+
| *tdpd* | chemical concentration | tDPD particles |
@ -141,8 +144,9 @@ quantities.
output the custom values.
All of the above styles define point particles, except the *sphere*,
*ellipsoid*, *electron*, *peri*, *wavepacket*, *line*, *tri*, and
*body* styles, which define finite-size particles. See the :doc:`Howto spherical <Howto_spherical>` page for an overview of using
*bpm/sphere*, *ellipsoid*, *electron*, *peri*, *wavepacket*, *line*,
*tri*, and *body* styles, which define finite-size particles. See the
:doc:`Howto spherical <Howto_spherical>` page for an overview of using
finite-size particle models with LAMMPS.
All of the point-particle styles assign mass to particles on a
@ -150,15 +154,15 @@ per-type basis, using the :doc:`mass <mass>` command, The finite-size
particle styles assign mass to individual particles on a per-particle
basis.
For the *sphere* style, the particles are spheres and each stores a
For the *sphere* and *bpm/sphere* styles, the particles are spheres and each stores a
per-particle diameter and mass. If the diameter > 0.0, the particle
is a finite-size sphere. If the diameter = 0.0, it is a point
particle. Note that by use of the *disc* keyword with the :doc:`fix
nve/sphere <fix_nve_sphere>`, :doc:`fix nvt/sphere <fix_nvt_sphere>`,
:doc:`fix nph/sphere <fix_nph_sphere>`, :doc:`fix npt/sphere
<fix_npt_sphere>` commands, spheres can be effectively treated as 2d
<fix_npt_sphere>` commands for the *sphere* style, spheres can be effectively treated as 2d
discs for a 2d simulation if desired. See also the :doc:`set
density/disc <set>` command. The *sphere* style takes an optional 0
density/disc <set>` command. The *sphere* and *bpm/sphere* styles take an optional 0
or 1 argument. A value of 0 means the radius of each sphere is
constant for the duration of the simulation. A value of 1 means the
radii may vary dynamically during the simulation, e.g. due to use of
@ -195,6 +199,8 @@ position, which is represented by the eradius = electron size.
For the *peri* style, the particles are spherical and each stores a
per-particle mass and volume.
The *bpm/sphere* style is part of the BPM package.
The *oxdna* style is for coarse-grained nucleotides and stores the
3'-to-5' polarity of the nucleotide strand, which is set through
the bond topology in the data file. The first (second) atom in a

View File

@ -0,0 +1,258 @@
.. index:: bond_style bpm/rotational
bond_style bpm/rotational command
=================================
Syntax
""""""
.. code-block:: LAMMPS
bond_style bpm/rotational keyword value attribute1 attribute2 ...
* optional keyword = *overlay/pair* or *store/local* or *smooth*
.. parsed-literal::
*store/local* values = fix_ID N attributes ...
* fix_ID = ID of associated internal fix to store data
* N = prepare data for output every this many timesteps
* attributes = zero or more of the below attributes may be appended
*id1, id2* = IDs of 2 atoms in the bond
*time* = the timestep the bond broke
*x, y, z* = the center of mass position of the 2 atoms when the bond broke (distance units)
*x/ref, y/ref, z/ref* = the initial center of mass position of the 2 atoms (distance units)
*overlay/pair* value = none
bonded particles will still interact with pair forces
*smooth* value = *yes* or *no*
smooths bond forces near the breaking point
Examples
""""""""
.. code-block:: LAMMPS
bond_style bpm/rotational
bond_coeff 1 1.0 0.2 0.02 0.02 0.20 0.04 0.04 0.04 0.1 0.02 0.002 0.002
bond_style bpm/rotational myfix 1000 time id1 id2
fix myfix all store/local 1000 3
dump 1 all local 1000 dump.broken f_myfix[1] f_myfix[2] f_myfix[3]
dump_modify 1 write_header no
Description
"""""""""""
The *bpm/rotational* bond style computes forces and torques based on
deviations from the initial reference state of the two atoms. The
reference state is stored by each bond when it is first computed in
the setup of a run. Data is then preserved across run commands and is
written to :doc:`binary restart files <restart>` such that restarting
the system will not reset the reference state of a bond.
Forces include a normal and tangential component. The base normal force
has a magnitude of
.. math::
f_r = k_r (r - r_0)
where :math:`k_r` is a stiffness and :math:`r` is the current distance and
:math:`r_0` is the initial distance between the two particles.
A tangential force is applied perpendicular to the normal direction
which is proportional to the tangential shear displacement with a
stiffness of :math:`k_s`. This tangential force also induces a torque.
In addition, bending and twisting torques are also applied to
particles which are proportional to angular bending and twisting
displacements with stiffnesses of :math`k_b` and :math:`k_t',
respectively. Details on the calculations of shear displacements and
angular displacements can be found in :ref:`(Wang) <Wang2009>` and
:ref:`(Wang and Mora) <Wang2009b>`.
Bonds will break under sufficient stress. A breaking criteria is calculated
.. math::
B = \mathrm{max}\{0, \frac{f_r}{f_{r,c}} + \frac{|f_s|}{f_{s,c}} +
\frac{|\tau_b|}{\tau_{b,c}} + \frac{|\tau_t|}{\tau_{t,c}} \}
where :math:`|f_s|` is the magnitude of the shear force and
:math:`|\tau_b|` and :math:`|\tau_t|` are the magnitudes of the
bending and twisting forces, respectively. The corresponding variables
:math:`f_{r,c}` :math:`f_{s,c}`, :math:`\tau_{b,c}`, and
:math:`\tau_{t,c}` are critical limits to each force or torque. If
:math:`B` is ever equal to or exceeds one, the bond will break. This
is done by setting by setting its type to 0 such that forces and
torques are no longer computed.
After computing the base magnitudes of the forces and torques, they
can be optionally multiplied by an extra factor :math:`w` to smoothly
interpolate forces and torques to zero as the bond breaks. This term
is calculated as :math:`w = (1.0 - B^4)`. This smoothing factor can be
added or removed using the *smooth* keyword.
Finally, additional damping forces and torques are applied to the two
particles. A force is applied proportional to the difference in the
normal velocity of particles using a similar construction as
dissipative particle dynamics (:ref:`(Groot) <Groot3>`):
.. math::
F_D = - \gamma_n w (\hat{r} \bullet \vec{v})
where :math:`\gamma_n` is the damping strength, :math:`\hat{r}` is the
radial normal vector, and :math:`\vec{v}` is the velocity difference
between the two particles. Similarly, tangential forces are applied to
each atom proportional to the relative differences in sliding
velocities with a constant prefactor :math:`\gamma_s` (:ref:`(Wang et
al.) <Wang20152>`) along with their associated torques. The rolling and
twisting components of the relative angular velocities of the two
atoms are also damped by applying torques with prefactors of
:math:`\gamma_r` and :math:`\gamma_t`, respectively.
The following coefficients must be defined for each bond type via the
:doc:`bond_coeff <bond_coeff>` command as in the example above, or in
the data file or restart files read by the :doc:`read_data <read_data>`
or :doc:`read_restart <read_restart>` commands:
* :math:`k_r` (force/distance units)
* :math:`k_s` (force/distance units)
* :math:`k_t` (force*distance/radians units)
* :math:`k_b` (force*distance/radians units)
* :math:`f_{r,c}` (force units)
* :math:`f_{s,c}` (force units)
* :math:`\tau_{b,c}` (force*distance units)
* :math:`\tau_{t,c}` (force*distance units)
* :math:`\gamma_n` (force/velocity units)
* :math:`\gamma_s` (force/velocity units)
* :math:`\gamma_r` (force*distance/velocity units)
* :math:`\gamma_t` (force*distance/velocity units)
By default, pair forces are not calculated between bonded particles.
Pair forces can alternatively be overlaid on top of bond forces using
the *overlay/pair* keyword. These settings require specific
:doc:`special_bonds <special_bonds>` settings described in the
restrictions. Further details can be found in the `:doc: how to
<Howto_BPM>` page on BPMs.
If the *store/local* keyword is used, this fix will track bonds that
break during the simulation. Whenever a bond breaks, data is processed
and transferred to an internal fix labeled *fix_ID*. This allows the
local data to be accessed by other LAMMPS commands.
Following any optional keyword/value arguments, a list of one or more
attributes is specified. These include the IDs of the two atoms in
the bond. The other attributes for the two atoms include the timestep
during which the bond broke and the current/initial center of mass
position of the two atoms.
Data is continuously accumulated over intervals of *N*
timesteps. At the end of each interval, all of the saved accumulated
data is deleted to make room for new data. Individual datum may
therefore persist anywhere between *1* to *N* timesteps depending on
when they are saved. This data can be accessed using the *fix_ID* and a
:doc:`dump local <dump>` command. To ensure all data is output,
the dump frequency should correspond to the same interval of *N*
timesteps. A dump frequency of an integer multiple of *N* can be used
to regularly output a sample of the accumulated data.
Note that when unbroken bonds are dumped to a file via the
:doc:`dump local <dump>` command, bonds with type 0 (broken bonds)
are not included.
The :doc:`delete_bonds <delete_bonds>` command can also be used to
query the status of broken bonds or permanently delete them, e.g.:
.. code-block:: LAMMPS
delete_bonds all stats
delete_bonds all bond 0 remove
----------
Restart and other info
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
This bond style writes the reference state of each bond to
:doc:`binary restart files <restart>`. Loading a restart file will
properly resume bonds.
The single() function of these pair styles returns 0.0 for the energy
of a pairwise interaction, since energy is not conserved in these
dissipative potentials. It also returns only the normal component of
the pairwise interaction force.
The accumulated data is not written to restart files and should be
output before a restart file is written to avoid missing data.
The internal fix calculates a local vector or local array depending on the
number of input values. The length of the vector or number of rows in
the array is the number of recorded, lost interactions. If a single
input is specified, a local vector is produced. If two or more inputs
are specified, a local array is produced where the number of columns =
the number of inputs. The vector or array can be accessed by any
command that uses local values from a compute as input. See the
:doc:`Howto output <Howto_output>` page for an overview of LAMMPS
output options.
The vector or array will be floating point values that correspond to
the specified attribute.
Restrictions
""""""""""""
This bond style can only be used if LAMMPS was built with the BPM
package. See the :doc:`Build package <Build_package>` doc page for
more info.
By default if pair interactions are to be disabled, this bond style
requires setting
.. code-block:: LAMMPS
special_bonds lj 0 1 1 coul 1 1 1
and :doc:`newton <newton>` must be set to bond off. If the
*overlay/pair* option is used, this bond style alternatively requires
setting
.. code-block:: LAMMPS
special_bonds lj/coul 1 1 1
The *bpm/rotational* style requires :doc:`atom style bpm/sphere <atom_style>`.
Related commands
""""""""""""""""
:doc:`bond_coeff <bond_coeff>`, :doc:`fix nve/bpm/sphere <fix_nve_bpm_sphere>`
Default
"""""""
The option defaults are *smooth* = *yes*
----------
.. _Wang2009:
**(Wang)** Wang, Acta Geotechnica, 4,
p 117-127 (2009).
.. _Wang2009b:
**(Wang and Mora)** Wang, Mora, Advances in Geocomputing,
119, p 183-228 (2009).
.. _Groot3:
**(Groot)** Groot and Warren, J Chem Phys, 107, 4423-35 (1997).
.. _Wang20152:
**(Wang et al, 2015)** Wang, Y., Alonso-Marroquin, F., & Guo,
W. W. (2015). Rolling and sliding in 3-D discrete element
models. Particuology, 23, 49-55.

202
doc/src/bond_bpm_spring.rst Normal file
View File

@ -0,0 +1,202 @@
.. index:: bond_style bpm/spring
bond_style bpm/spring command
=============================
Syntax
""""""
.. code-block:: LAMMPS
bond_style bpm/spring keyword value attribute1 attribute2 ...
* optional keyword = *overlay/pair* or *store/local* or *smooth*
.. parsed-literal::
*store/local* values = fix_ID N attributes ...
* fix_ID = ID of associated internal fix to store data
* N = prepare data for output every this many timesteps
* attributes = zero or more of the below attributes may be appended
*id1, id2* = IDs of 2 atoms in the bond
*time* = the timestep the bond broke
*x, y, z* = the center of mass position of the 2 atoms when the bond broke (distance units)
*x/ref, y/ref, z/ref* = the initial center of mass position of the 2 atoms (distance units)
*overlay/pair* value = none
bonded particles will still interact with pair forces
*smooth* value = *yes* or *no*
smooths bond forces near the breaking point
Examples
""""""""
.. code-block:: LAMMPS
bond_style bpm/spring
bond_coeff 1 1.0 0.05 0.1
bond_style bpm/spring myfix 1000 time id1 id2
dump 1 all local 1000 dump.broken f_myfix[1] f_myfix[2] f_myfix[3]
dump_modify 1 write_header no
Description
"""""""""""
The *bpm/spring* bond style computes forces and torques based on
deviations from the initial reference state of the two atoms. The
reference state is stored by each bond when it is first computed in
the setup of a run. Data is then preserved across run commands and is
written to :doc:`binary restart files <restart>` such that restarting
the system will not reset the reference state of a bond.
This bond style only applies central-body forces which conserve the
translational and rotational degrees of freedom of a bonded set of
particles. The force has a magnitude of
.. math::
F = k (r - r_0) w
where :math:`k_r` is a stiffness, :math:`r` is the current distance
and :math:`r_0` is the initial distance between the two particles, and
:math:`w` is an optional smoothing factor discussed below. Bonds will
break at a strain of :math:`\epsilon_c`. This is done by setting by
setting its type to 0 such that forces are no longer computed.
An additional damping force is applied to the bonded
particles. This forces is proportional to the difference in the
normal velocity of particles using a similar construction as
dissipative particle dynamics (:ref:`(Groot) <Groot4>`):
.. math::
F_D = - \gamma w (\hat{r} \bullet \vec{v})
where :math:`\gamma` is the damping strength, :math:`\hat{r}` is the
radial normal vector, and :math:`\vec{v}` is the velocity difference
between the two particles.
The smoothing factor :math:`w` can be added or removed using the
*smooth* keyword. It is constructed such that forces smoothly go
to zero, avoiding discontinuities, as bonds approach the critical strain
.. math::
w = 1.0 - \left( \frac{r - r_0}{r_0 \epsilon_c} \right)^8 .
The following coefficients must be defined for each bond type via the
:doc:`bond_coeff <bond_coeff>` command as in the example above, or in
the data file or restart files read by the :doc:`read_data
<read_data>` or :doc:`read_restart <read_restart>` commands:
* :math:`k` (force/distance units)
* :math:`\epsilon_c` (unit less)
* :math:`\gamma` (force/velocity units)
By default, pair forces are not calculated between bonded particles.
Pair forces can alternatively be overlaid on top of bond forces using
the *overlay/pair* keyword. These settings require specific
:doc:`special_bonds <special_bonds>` settings described in the
restrictions. Further details can be found in the `:doc: how to
<Howto_BPM>` page on BPMs.
If the *store/local* keyword is used, this fix will track bonds that
break during the simulation. Whenever a bond breaks, data is processed
and transferred to an internal fix labeled *fix_ID*. This allows the
local data to be accessed by other LAMMPS commands.
Following any optional keyword/value arguments, a list of one or more
attributes is specified. These include the IDs of the two atoms in
the bond. The other attributes for the two atoms include the timestep
during which the bond broke and the current/initial center of mass
position of the two atoms.
Data is continuously accumulated over intervals of *N*
timesteps. At the end of each interval, all of the saved accumulated
data is deleted to make room for new data. Individual datum may
therefore persist anywhere between *1* to *N* timesteps depending on
when they are saved. This data can be accessed using the *fix_ID* and a
:doc:`dump local <dump>` command. To ensure all data is output,
the dump frequency should correspond to the same interval of *N*
timesteps. A dump frequency of an integer multiple of *N* can be used
to regularly output a sample of the accumulated data.
Note that when unbroken bonds are dumped to a file via the
:doc:`dump local <dump>` command, bonds with type 0 (broken bonds)
are not included.
The :doc:`delete_bonds <delete_bonds>` command can also be used to
query the status of broken bonds or permanently delete them, e.g.:
.. code-block:: LAMMPS
delete_bonds all stats
delete_bonds all bond 0 remove
----------
Restart and other info
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
This bond style writes the reference state of each bond to
:doc:`binary restart files <restart>`. Loading a restart
file will properly resume bonds.
The single() function of these pair styles returns 0.0 for the energy
of a pairwise interaction, since energy is not conserved in these
dissipative potentials.
The accumulated data is not written to restart files and should be
output before a restart file is written to avoid missing data.
The internal fix calculates a local vector or local array depending on the
number of input values. The length of the vector or number of rows in
the array is the number of recorded, lost interactions. If a single
input is specified, a local vector is produced. If two or more inputs
are specified, a local array is produced where the number of columns =
the number of inputs. The vector or array can be accessed by any
command that uses local values from a compute as input. See the
:doc:`Howto output <Howto_output>` page for an overview of LAMMPS
output options.
The vector or array will be floating point values that correspond to
the specified attribute.
Restrictions
""""""""""""
This bond style can only be used if LAMMPS was built with the BPM
package. See the :doc:`Build package <Build_package>` doc page for
more info.
By default if pair interactions are to be disabled, this bond style
requires setting
.. code-block:: LAMMPS
special_bonds lj 0 1 1 coul 1 1 1
and :doc:`newton <newton>` must be set to bond off. If the
*overlay/pair* option is used, this bond style alternatively requires
setting
.. code-block:: LAMMPS
special_bonds lj/coul 1 1 1
Related commands
""""""""""""""""
:doc:`bond_coeff <bond_coeff>`, :doc:`pair bpm/spring <pair_bpm_spring>`
Default
"""""""
The option defaults are *smooth* = *yes*
----------
.. _Groot4:
**(Groot)** Groot and Warren, J Chem Phys, 107, 4423-35 (1997).

View File

@ -67,7 +67,8 @@ local maximum. If a bond length ever becomes :math:`> R_c`, LAMMPS "breaks"
the bond, which means two things. First, the bond potential is turned
off by setting its type to 0, and is no longer computed. Second, a
pairwise interaction between the two atoms is turned on, since they
are no longer bonded.
are no longer bonded. See the :doc:`Howto <Howto_broken_bonds>` page
on broken bonds for more information.
LAMMPS does the second task via a computational sleight-of-hand. It
subtracts the pairwise interaction as part of the bond computation.

View File

@ -84,6 +84,8 @@ accelerated styles exist.
* :doc:`zero <bond_zero>` - topology but no interactions
* :doc:`hybrid <bond_hybrid>` - define multiple styles of bond interactions
* :doc:`bpm/rotational <bond_bpm_rotational>` - breakable bond with forces and torques based on deviation from reference state
* :doc:`bpm/spring <bond_bpm_spring>` - breakable bond with forces based on deviation from reference length
* :doc:`class2 <bond_class2>` - COMPASS (class 2) bond
* :doc:`fene <bond_fene>` - FENE (finite-extensible non-linear elastic) bond
* :doc:`fene/expand <bond_fene_expand>` - FENE bonds with variable size particles

View File

@ -236,6 +236,7 @@ The individual style names on the :doc:`Commands compute <Commands_compute>` pag
* :doc:`msd <compute_msd>` - mean-squared displacement of group of atoms
* :doc:`msd/chunk <compute_msd_chunk>` - mean-squared displacement for each chunk
* :doc:`msd/nongauss <compute_msd_nongauss>` - MSD and non-Gaussian parameter of group of atoms
* :doc:`nbond/atom <compute_nbond_atom>` - calculates number of bonds per atom
* :doc:`omega/chunk <compute_omega_chunk>` - angular velocity for each chunk
* :doc:`orientorder/atom <compute_orientorder_atom>` - Steinhardt bond orientational order parameters Ql
* :doc:`pair <compute_pair>` - values computed by a pair style

View File

@ -0,0 +1,52 @@
.. index:: compute nbond/atom
compute nbond/atom command
==========================
Syntax
""""""
.. parsed-literal::
compute ID group-ID nbond/atom
* ID, group-ID are documented in :doc:`compute <compute>` command
* nbond/atom = style name of this compute command
Examples
""""""""
.. code-block:: LAMMPS
compute 1 all nbond/atom
Description
"""""""""""
Define a computation that computes the number of bonds each atom is
part of. Bonds which are broken are not counted in the tally. See
the :doc:`Howto broken bonds <Howto_bpm>` page for more information.
The number of bonds will be zero for atoms not in the specified
compute group. This compute does not depend on Newton bond settings.
Output info
"""""""""""
This compute calculates a per-atom vector, which can be accessed by
any command that uses per-atom values from a compute as input. See
the :doc:`Howto output <Howto_output>` doc page for an overview of
LAMMPS output options.
Restrictions
""""""""""""
This fix can only be used if LAMMPS was built with the BPM package.
See the :doc:`Build package <Build_package>` doc page for more info.
Related commands
""""""""""""""""
Default
"""""""
none

View File

@ -474,8 +474,9 @@ The *fileper* keyword is documented below with the *nfile* keyword.
The *header* keyword toggles whether the dump file will include a
header. Excluding a header will reduce the size of the dump file for
fixes such as :doc:`fix pair/tracker <fix_pair_tracker>` which do not
require the information typically written to the header.
data produced by :doc:`pair tracker <pair_tracker>` or
:doc:`bpm bond styles <Howto_bpm>` which may not require the
information typically written to the header.
----------

View File

@ -284,6 +284,7 @@ accelerated styles exist.
* :doc:`nve/manifold/rattle <fix_nve_manifold_rattle>` -
* :doc:`nve/noforce <fix_nve_noforce>` - NVE without forces (v only)
* :doc:`nve/sphere <fix_nve_sphere>` - NVE for spherical particles
* :doc:`nve/bpm/sphere <fix_nve_bpm_sphere>` - NVE for spherical particles used in the BPM package
* :doc:`nve/spin <fix_nve_spin>` - NVE for a spin or spin-lattice system
* :doc:`nve/tri <fix_nve_tri>` - NVE for triangles
* :doc:`nvk <fix_nvk>` - constant kinetic energy time integration
@ -301,7 +302,6 @@ accelerated styles exist.
* :doc:`orient/fcc <fix_orient>` - add grain boundary migration force for FCC
* :doc:`orient/eco <fix_orient_eco>` - add generalized grain boundary migration force
* :doc:`pafi <fix_pafi>` - constrained force averages on hyper-planes to compute free energies (PAFI)
* :doc:`pair/tracker <fix_pair_tracker>` - track properties of pairwise interactions
* :doc:`phonon <fix_phonon>` - calculate dynamical matrix from MD simulations
* :doc:`pimd <fix_pimd>` - Feynman path integral molecular dynamics
* :doc:`planeforce <fix_planeforce>` - constrain atoms to move in a plane

View File

@ -113,6 +113,9 @@ You can dump out snapshots of the current bond topology via the :doc:`dump local
may need to thermostat your system to compensate for energy changes
resulting from broken bonds (and angles, dihedrals, impropers).
See the :doc:`Howto <Howto_broken_bonds>` page on broken bonds for more
information on related features in LAMMPS.
----------
Restart, fix_modify, output, run start/stop, minimize info

View File

@ -0,0 +1,87 @@
.. index:: fix nve/bpm/sphere
fix nve/bpm/sphere command
==========================
Syntax
""""""
.. parsed-literal::
fix ID group-ID nve/bpm/sphere
* ID, group-ID are documented in :doc:`fix <fix>` command
* nve/bpm/sphere = style name of this fix command
* zero or more keyword/value pairs may be appended
* keyword = *disc*
.. parsed-literal::
*disc* value = none = treat particles as 2d discs, not spheres
Examples
""""""""
.. code-block:: LAMMPS
fix 1 all nve/bpm/sphere
fix 1 all nve/bpm/sphere disc
Description
"""""""""""
Perform constant NVE integration to update position, velocity, angular
velocity, and quaternion orientation for finite-size spherical
particles in the group each timestep. V is volume; E is energy. This
creates a system trajectory consistent with the microcanonical
ensemble.
This fix differs from the :doc:`fix nve <fix_nve>` command, which
assumes point particles and only updates their position and velocity.
It also differs from the :doc:`fix nve/sphere <fix_nve_sphere>`
command which assumes finite-size spheroid particles which do not
store a quaternion. It thus does not update a particle's orientation
or quaternion.
If the *disc* keyword is used, then each particle is treated as a 2d
disc (circle) instead of as a sphere. This is only possible for 2d
simulations, as defined by the :doc:`dimension <dimension>` keyword.
The only difference between discs and spheres in this context is their
moment of inertia, as used in the time integration.
----------
Restart, fix_modify, output, run start/stop, minimize info
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
No information about this fix is written to :doc:`binary restart files
<restart>`. None of the :doc:`fix_modify <fix_modify>` options are
relevant to this fix. No global or per-atom quantities are stored by
this fix for access by various :doc:`output commands <Howto_output>`.
No parameter of this fix can be used with the *start/stop* keywords of
the :doc:`run <run>` command. This fix is not invoked during
:doc:`energy minimization <minimize>`.
Restrictions
""""""""""""
This fix requires that atoms store torque, angular velocity (omega), a
radius, and a quaternion as defined by the :doc:`atom_style bpm/sphere
<atom_style>` command.
All particles in the group must be finite-size spheres with
quaternions. They cannot be point particles.
Use of the *disc* keyword is only allowed for 2d simulations, as
defined by the :doc:`dimension <dimension>` keyword.
Related commands
""""""""""""""""
:doc:`fix nve <fix_nve>`, :doc:`fix nve/sphere <fix_nve_sphere>`
Default
"""""""
none

View File

@ -1,124 +0,0 @@
.. index:: fix pair/tracker
fix pair/tracker command
========================
Syntax
""""""
.. parsed-literal::
fix ID group-ID pair/tracker N attribute1 attribute2 ... keyword values ...
* ID, group-ID are documented in :doc:`fix <fix>` command
* pair/tracker = style name of this fix command
* N = prepare data for output every this many timesteps
* one or more attributes may be appended
.. parsed-literal::
possible attributes = id1 id2 time/created time/broken time/total
rmin rave x y z
.. parsed-literal::
id1, id2 = IDs of the 2 atoms in each pair interaction
time/created = the time that the 2 atoms began interacting
time/broken = the time that the 2 atoms stopped interacting
time/total = the total time the 2 atoms interacted
r/min = the minimum radial distance between the 2 atoms during the interaction
r/ave = the average radial distance between the 2 atoms during the interaction
x, y, z = the center of mass position of the 2 atoms when they stopped interacting
* zero or more keyword/value pairs may be appended
* keyword = *time/min* or *type/include*
.. parsed-literal::
*time/min* value = T
T = minimum interaction time
*type/include* value = arg1 arg2
arg = separate lists of types (see below)
Examples
""""""""
.. code-block:: LAMMPS
fix 1 all pair/tracker 1000 id1 id2 time/min 100
fix 1 all pair/tracker 1000 time/created time/broken type/include 1 * type/include 2 3,4
Description
"""""""""""
Tracks properties of pairwise interactions between two atoms and records data
whenever the atoms move beyond the interaction cutoff.
Must be used in conjunction with :doc:`pair tracker <pair_tracker>`.
Data is accumulated over a span of *N* timesteps before being deleted.
The number of datums generated, aggregated across all processors, equals
the number of broken interactions. Interactions are only included if both
atoms are included in the specified fix group. Additional filters can be
applied using the *time/min* or *type/include* keywords described below.
.. note::
For extremely long-lived interactions, the calculation of *r/ave* may not be
correct due to double overflow.
The *time/min* keyword sets a minimum amount of time that an interaction must
persist to be included. This setting can be used to censor short-lived interactions.
The *type/include* keyword filters interactions based on the types of the two atoms.
Data is only saved for interactions between atoms with types in the two lists.
Each list consists of a series of type
ranges separated by commas. The range can be specified as a
single numeric value, or a wildcard asterisk can be used to specify a range
of values. This takes the form "\*" or "\*n" or "n\*" or "m\*n". For
example, if M = the number of atom types, then an asterisk with no numeric
values means all types from 1 to M. A leading asterisk means all types
from 1 to n (inclusive). A trailing asterisk means all types from n to M
(inclusive). A middle asterisk means all types from m to n (inclusive).
Multiple *type/include* keywords may be added.
----------
Restart, fix_modify, run start/stop, minimize info
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
No information about this fix is written to :doc:`binary restart files <restart>`.
None of the :doc:`fix_modify <fix_modify>` options are
relevant to this fix.
No parameter of this fix can be used with the *start/stop* keywords of
the :doc:`run <run>` command.
Output info
"""""""""""
This compute calculates a local vector or local array depending on the
number of input values. The length of the vector or number of rows in
the array is the number of recorded, lost interactions. If a single input is
specified, a local vector is produced. If two or more inputs are
specified, a local array is produced where the number of columns = the
number of inputs. The vector or array can be accessed by any command
that uses local values from a compute as input. See the :doc:`Howto output <Howto_output>` page for an overview of LAMMPS output
options.
The vector or array values will be doubles that correspond to the
specified attribute.
Restrictions
""""""""""""
Must be used in conjunction with :doc:`pair style tracker <pair_tracker>`.
This fix is part of the MISC package. It is only enabled if LAMMPS
was built with that package. See the :doc:`Build package <Build_package>` page for more info.
Related commands
""""""""""""""""
:doc:`pair tracker <pair_tracker>`
Default
"""""""
none

114
doc/src/pair_bpm_spring.rst Normal file
View File

@ -0,0 +1,114 @@
.. index:: pair_style bpm/spring
pair_style bpm/spring command
=============================
Syntax
""""""
.. code-block:: LAMMPS
pair_style bpm/spring
Examples
""""""""
.. code-block:: LAMMPS
pair_style bpm/spring
pair_coeff * * 1.0 1.0 1.0
pair_coeff 1 1 1.0 1.0 1.0
Description
"""""""""""
Style *bpm/spring* computes pairwise forces with the formula
.. math::
F = k (r - r_c)
where :math:`k` is a stiffness and :math:`r_c` is the cutoff length.
An additional damping force is also applied to interacting
particles. The force is proportional to the difference in the
normal velocity of particles
.. math::
F_D = - \gamma w (\hat{r} \bullet \vec{v})
where :math:`\gamma` is the damping strength, :math:`\hat{r}` is the
radial normal vector, :math:`\vec{v}` is the velocity difference
between the two particles, and :math:`w` is a smoothing factor.
This smoothing factor is constructed such that damping forces go to zero
as particles come out of contact to avoid discontinuities. It is
given by
.. math::
w = 1.0 - \left( \frac{r}{r_c} \right)^8 .
This pair style is designed for use in a spring-based bonded particle
model. It mirrors the construction of the :doc:`bpm/spring
<bond_bpm_spring>` bond style.
This pair interaction is always applied to pairs of non-bonded particles
that are within the interaction distance. For pairs of bonded particles
that are within the interaction distance, there is the option to either
include this pair interaction and overlay the pair force over the bond
force or to exclude this pair interaction such that the two particles
only interact via the bond force. See discussion of the *overlay/pair*
option for BPM bond styles and the :doc:`special_bonds <special_bonds>`
command in the `:doc: how to <Howto_BPM>` page on BPMs for more details.
The following coefficients must be defined for each pair of atom types
via the :doc:`pair_coeff <pair_coeff>` command as in the examples
above, or in the data file or restart files read by the
:doc:`read_data <read_data>` or :doc:`read_restart <read_restart>`
commands, or by mixing as described below:
* :math:`k` (force/distance units)
* :math:`r_c` (distance units)
* :math:`\gamma` (force/velocity units)
----------
Mixing, shift, table, tail correction, restart, rRESPA info
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
For atom type pairs I,J and I != J, the A coefficient and cutoff
distance for this pair style can be mixed. A is always mixed via a
*geometric* rule. The cutoff is mixed according to the pair_modify
mix value. The default mix value is *geometric*\ . See the
"pair_modify" command for details.
This pair style does not support the :doc:`pair_modify <pair_modify>`
shift option, since the pair interaction goes to 0.0 at the cutoff.
The :doc:`pair_modify <pair_modify>` table and tail options are not
relevant for this pair style.
This pair style writes its information to :doc:`binary restart files
<restart>`, so pair_style and pair_coeff commands do not need to be
specified in an input script that reads a restart file.
This pair style can only be used via the *pair* keyword of the
:doc:`run_style respa <run_style>` command. It does not support the
*inner*, *middle*, *outer* keywords.
----------
Restrictions
""""""""""""
none
Related commands
""""""""""""""""
:doc:`pair_coeff <pair_coeff>`, :doc:`bond bpm/spring <bond_bpm_spring>`
Default
"""""""
none

View File

@ -131,6 +131,7 @@ accelerated styles exist.
* :doc:`born/coul/msm <pair_born>` - Born with long-range MSM Coulomb
* :doc:`born/coul/wolf <pair_born>` - Born with Wolf potential for Coulomb
* :doc:`born/coul/wolf/cs <pair_cs>` - Born with Wolf potential for Coulomb and core/shell model
* :doc:`bpm/spring <pair_bpm_spring>` - repulsive harmonic force with damping
* :doc:`brownian <pair_brownian>` - Brownian potential for Fast Lubrication Dynamics
* :doc:`brownian/poly <pair_brownian>` - Brownian potential for Fast Lubrication Dynamics with polydispersity
* :doc:`buck <pair_buck>` - Buckingham potential

View File

@ -8,89 +8,182 @@ Syntax
.. code-block:: LAMMPS
pair_style tracker keyword
pair_style tracker fix_ID N keyword values attribute1 attribute2 ...
* zero or more keyword/arg pairs may be appended
* keyword = *finite*
* fix_ID = ID of associated internal fix to store data
* N = prepare data for output every this many timesteps
* zero or more keywords may be appended
* keyword = *finite* or *time/min* or *type/include*
.. parsed-literal::
*finite* value = none
pair style uses atomic diameters to identify contacts
*time/min* value = T
T = minimum number of timesteps of interaction
*type/include* value = list1 list2
list1,list2 = separate lists of types (see below)
* one or more attributes may be appended
.. parsed-literal::
possible attributes = id1 id2 time/created time/broken time/total
r/min r/ave x y z
.. parsed-literal::
id1, id2 = IDs of the 2 atoms in each pair interaction
time/created = the timestep that the 2 atoms began interacting
time/broken = the timestep that the 2 atoms stopped interacting
time/total = the total number of timesteps the 2 atoms interacted
r/min = the minimum radial distance between the 2 atoms during the interaction (distance units)
r/ave = the average radial distance between the 2 atoms during the interaction (distance units)
x, y, z = the center of mass position of the 2 atoms when they stopped interacting (distance units)
Examples
""""""""
.. code-block:: LAMMPS
pair_style hybrid/overlay tracker ...
pair_style hybrid/overlay tracker myfix 1000 id1 id2 type/include 1 * type/include 2 3,4 lj/cut 2.5
pair_coeff 1 1 tracker 2.0
pair_style hybrid/overlay tracker finite ...
pair_style hybrid/overlay tracker myfix 1000 finite x y z time/min 100 granular
pair_coeff * * tracker
fix 1 all pair/tracker 1000 time/created time/broken
dump 1 all local 1000 dump.local f_1[1] f_1[2]
dump 1 all local 1000 dump.local f_myfix[1] f_myfix[2] f_myfix[3]
dump_modify 1 write_header no
Description
"""""""""""
Style *tracker* monitors information about pairwise interactions.
It does not calculate any forces on atoms.
:doc:`Pair hybrid/overlay <pair_hybrid>` can be used to combine this pair
style with another pair style. Style *tracker* must be used in conjunction
with about :doc:`fix pair_tracker <fix_pair_tracker>` which contains
information on what data can be output.
Style *tracker* monitors information about pairwise interactions. It
does not calculate any forces on atoms. :doc:`Pair hybrid/overlay
<pair_hybrid>` can be used to combine this pair style with any other
pair style, as shown in the examples above.
If the *finite* keyword is not defined, the following coefficients must be
defined for each pair of atom types via the :doc:`pair_coeff <pair_coeff>`
command as in the examples above, or in the data file or restart files
read by the :doc:`read_data <read_data>` or :doc:`read_restart <read_restart>`
commands, or by mixing as described below:
At each timestep, if two neighboring atoms move beyond the interaction
cutoff, pairwise data is processed and transferred to an internal fix
labeled *fix_ID*. This allows the local data to be accessed by other
LAMMPS commands. Additional
filters can be applied using the *time/min* or *type/include* keywords
described below. Note that this is the interaction cutoff defined by
this pair style, not the short-range cutoff defined by the pair style
that is calculating forces on atoms.
Following any optional keyword/value arguments, a list of one or more
attributes is specified. These include the IDs of the two atoms in
the pair. The other attributes for the pair of atoms are the
duration of time they were "interacting" or at the point in time they
started or stopped interacting. In this context, "interacting" means
the time window during which the two atoms were closer than the
interaction cutoff distance. The attributes for time/* refer to
timesteps.
Data is continuously accumulated by the internal fix over intervals of *N*
timesteps. At the end of each interval, all of the saved accumulated
data is deleted to make room for new data. Individual datum may
therefore persist anywhere between *1* to *N* timesteps depending on
when they are saved. This data can be accessed using the *fix_ID* and a
:doc:`dump local <dump>` command. To ensure all data is output,
the dump frequency should correspond to the same interval of *N*
timesteps. A dump frequency of an integer multiple of *N* can be used
to regularly output a sample of the accumulated data.
----------
The following optional keywords may be used.
If the *finite* keyword is not used, the following coefficients must
be defined for each pair of atom types via the :doc:`pair_coeff
<pair_coeff>` command as in the examples above, or in the data file or
restart files read by the :doc:`read_data <read_data>` or
:doc:`read_restart <read_restart>` commands, or by mixing as described
below:
* cutoff (distance units)
If the *finite* keyword is defined, no coefficients may be defined.
Interaction cutoffs are alternatively calculated based on the
diameter of finite particles.
If the *finite* keyword is used, there are no additional coefficients
to set for each pair of atom types via the
:doc:`pair_coeff <pair_coeff>` command. Interaction cutoffs are
instead calculated based on the diameter of finite particles. However
you must still use the :doc:`pair_coeff <pair_coeff>` for all atom
types. For example the command
.. code-block:: LAMMPS
pair_coeff * *
should be used.
The *time/min* keyword sets a minimum amount of time that an
interaction must persist to be included. This setting can be used to
censor short-lived interactions.
The *type/include* keyword filters interactions based on the types of
the two atoms. Data is only saved for interactions between atoms
whose two atom types appear in *list1* and *list2*. Atom type 1 must
be in list1 and atom type 2 in list2. Or vice versa.
Each type list consists of a series of type ranges separated by
commas. Each range can be specified as a single numeric value, or a
wildcard asterisk can be used to specify a range of values. This
takes the form "\*" or "\*n" or "n\*" or "m\*n". For example, if M =
the number of atom types, then an asterisk with no numeric values
means all types from 1 to M. A leading asterisk means all types from
1 to n (inclusive). A trailing asterisk means all types from n to M
(inclusive). A middle asterisk means all types from m to n
(inclusive). Note that the *type/include* keyword can be specified
multiple times.
Mixing, shift, table, tail correction, restart, rRESPA info
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
For atom type pairs I,J and I != J, the cutoff coefficient and cutoff
distance for this pair style can be mixed. The cutoff is always mixed via a
*geometric* rule. The cutoff is mixed according to the pair_modify
mix value. The default mix value is *geometric*\ . See the
"pair_modify" command for details.
distance for this pair style can be mixed. The cutoff is always mixed
via a *geometric* rule. The cutoff is mixed according to the
pair_modify mix value. The default mix value is *geometric*\ . See
the "pair_modify" command for details.
This pair style writes its information to :doc:`binary restart files <restart>`, so
pair_style and pair_coeff commands do not need
to be specified in an input script that reads a restart file.
This pair style writes its information to :doc:`binary restart files
<restart>`, so pair_style and pair_coeff commands do not need to be
specified in an input script that reads a restart file.
The :doc:`pair_modify <pair_modify>` shift, table, and tail options
are not relevant for this pair style.
The accumulated data is not written to restart files and should be
output before a restart file is written to avoid missing data.
The internal fix calculates a local vector or local array depending on the
number of input values. The length of the vector or number of rows in
the array is the number of recorded, lost interactions. If a single
input is specified, a local vector is produced. If two or more inputs
are specified, a local array is produced where the number of columns =
the number of inputs. The vector or array can be accessed by any
command that uses local values from a compute as input. See the
:doc:`Howto output <Howto_output>` page for an overview of LAMMPS
output options.
The vector or array will be floating point values that correspond to
the specified attribute.
----------
Restrictions
""""""""""""
A corresponding :doc:`fix pair_tracker <fix_pair_tracker>` must be defined
to use this pair style.
This pair style is currently incompatible with granular pair styles that extend
beyond the contact (e.g. JKR and DMT).
This fix is part of the MISC package. It is only enabled if LAMMPS
was built with that package. See the :doc:`Build package <Build_package>` page for more info.
was built with that package. See the :doc:`Build package
<Build_package>` page for more info.
This pair style is currently incompatible with granular pair styles
that extend beyond the contact (e.g. JKR and DMT).
Related commands
""""""""""""""""
:doc:`fix pair_tracker <fix_pair_tracker>`
Default
"""""""

View File

@ -650,6 +650,8 @@ of analysis.
- atom-ID atom-type rho esph cv x y z
* - sphere
- atom-ID atom-type diameter density x y z
* - bpm/sphere
- atom-ID molecule-ID atom-type diameter density x y z
* - spin
- atom-ID atom-type x y z spx spy spz sp
* - tdpd

View File

@ -328,6 +328,8 @@ boxzlo
bp
bpclermont
bpls
bpm
BPM
br
Branduardi
Branicio
@ -1149,8 +1151,10 @@ gdot
GeC
Geier
gencode
Geocomputing
georg
Georg
Geotechnica
germain
Germann
Germano
@ -1320,6 +1324,7 @@ Holm
holonomic
Homebrew
hooke
hookean
Hookean
hostname
hotpink
@ -2074,6 +2079,7 @@ monopole
monovalent
Montalenti
Montero
Mora
Morefoo
Morfill
Mori
@ -2203,6 +2209,7 @@ Nbin
Nbins
nbody
Nbody
nbond
nbonds
nbondtype
Nbondtype
@ -3174,6 +3181,7 @@ Steinhauser
Stepaniants
stepwise
Stesmans
stiffnesses
Stillinger
stk
stochastically

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@
units lj
dimension 3
boundary f f f
atom_style bpm/sphere
special_bonds lj 0.0 1.0 1.0 coul 0.0 1.0 1.0
newton on off
comm_modify vel yes cutoff 2.6
lattice fcc 1.0
region box block -25 15 -22 22 -22 22
create_box 1 box bond/types 2 extra/bond/per/atom 20 extra/special/per/atom 50
region disk cylinder x 0.0 0.0 20.0 -0.5 0.5
create_atoms 1 region disk
group plate region disk
region ball sphere 8.0 0.0 0.0 6.0
create_atoms 1 region ball
group projectile region ball
displace_atoms all random 0.1 0.1 0.1 134598738
neighbor 1.0 bin
pair_style gran/hooke/history 1.0 NULL 0.5 NULL 0.1 1
pair_coeff 1 1
fix 1 all nve/bpm/sphere
create_bonds many plate plate 1 0.0 1.5
create_bonds many projectile projectile 2 0.0 1.5
neighbor 0.3 bin
special_bonds lj 0.0 1.0 1.0 coul 1.0 1.0 1.0
bond_style bpm/rotational store/local brkbond 100 time id1 id2
bond_coeff 1 1.0 0.2 0.02 0.02 0.05 0.01 0.01 0.01 0.1 0.2 0.002 0.002
bond_coeff 2 1.0 0.2 0.02 0.02 0.20 0.04 0.04 0.04 0.1 0.2 0.002 0.002
velocity projectile set -0.05 0.0 0.0
compute nbond all nbond/atom
compute tbond all reduce sum c_nbond
timestep 0.05
thermo_style custom step ke pe pxx pyy pzz c_tbond
thermo 100
thermo_modify lost ignore lost/bond ignore
#dump 1 all custom 100 atomDump id radius x y z c_nbond
dump 2 all local 100 brokenDump f_brkbond[1] f_brkbond[2] f_brkbond[3]
dump_modify 2 header no
run 7500

View File

@ -0,0 +1,53 @@
units lj
dimension 3
boundary f f f
atom_style bond
special_bonds lj 0.0 1.0 1.0 coul 0.0 1.0 1.0
newton on off
comm_modify vel yes cutoff 2.6
lattice fcc 1.0
region box block -25 15 -22 22 -22 22
create_box 1 box bond/types 2 extra/bond/per/atom 20 extra/special/per/atom 50
region disk cylinder x 0.0 0.0 20.0 -0.5 0.5
create_atoms 1 region disk
group plate region disk
region ball sphere 8.0 0.0 0.0 6.0
create_atoms 1 region ball
group projectile region ball
displace_atoms all random 0.1 0.1 0.1 134598738
mass 1 1.0
neighbor 1.0 bin
pair_style bpm/spring
pair_coeff 1 1 1.0 1.0 1.0
fix 1 all nve
create_bonds many plate plate 1 0.0 1.5
create_bonds many projectile projectile 2 0.0 1.5
neighbor 0.3 bin
special_bonds lj 0.0 1.0 1.0 coul 1.0 1.0 1.0
bond_style bpm/spring store/local brkbond 100 time id1 id2
bond_coeff 1 1.0 0.04 1.0
bond_coeff 2 1.0 0.20 1.0
velocity projectile set -0.05 0.0 0.0
compute nbond all nbond/atom
compute tbond all reduce sum c_nbond
timestep 0.1
thermo_style custom step ke pe pxx pyy pzz c_tbond
thermo 100
thermo_modify lost ignore lost/bond ignore
#dump 1 all custom 100 atomDump id x y z c_nbond
dump 2 all local 100 brokenDump f_brkbond[1] f_brkbond[2] f_brkbond[3]
dump_modify 2 header no
run 7500

View File

@ -0,0 +1,219 @@
LAMMPS (17 Feb 2022)
units lj
dimension 3
boundary f f f
atom_style bpm/sphere
special_bonds lj 0.0 1.0 1.0 coul 0.0 1.0 1.0
newton on off
comm_modify vel yes cutoff 2.6
lattice fcc 1.0
Lattice spacing in x,y,z = 1.5874011 1.5874011 1.5874011
region box block -25 15 -22 22 -22 22
create_box 1 box bond/types 2 extra/bond/per/atom 20 extra/special/per/atom 50
Created orthogonal box = (-39.685026 -34.922823 -34.922823) to (23.811016 34.922823 34.922823)
1 by 2 by 2 MPI processor grid
region disk cylinder x 0.0 0.0 20.0 -0.5 0.5
create_atoms 1 region disk
Created 7529 atoms
using lattice units in orthogonal box = (-39.685026 -34.922823 -34.922823) to (23.811016 34.922823 34.922823)
create_atoms CPU = 0.002 seconds
group plate region disk
7529 atoms in group plate
region ball sphere 8.0 0.0 0.0 6.0
create_atoms 1 region ball
Created 3589 atoms
using lattice units in orthogonal box = (-39.685026 -34.922823 -34.922823) to (23.811016 34.922823 34.922823)
create_atoms CPU = 0.001 seconds
group projectile region ball
3589 atoms in group projectile
displace_atoms all random 0.1 0.1 0.1 134598738
Displacing atoms ...
neighbor 1.0 bin
pair_style gran/hooke/history 1.0 NULL 0.5 NULL 0.1 1
pair_coeff 1 1
fix 1 all nve/bpm/sphere
create_bonds many plate plate 1 0.0 1.5
generated 0 of 0 mixed pair_coeff terms from geometric mixing rule
Neighbor list info ...
update every 1 steps, delay 10 steps, check yes
max neighbors/atom: 2000, page size: 100000
master list distance cutoff = 2
ghost atom cutoff = 2.6
binsize = 1, bins = 64 70 70
2 neighbor lists, perpetual/occasional/extra = 1 1 0
(1) command create_bonds, occasional
attributes: full, newton on
pair build: full/bin
stencil: full/bin/3d
bin: standard
(2) pair gran/hooke/history, perpetual
attributes: half, newton on, size, history
pair build: half/size/bin/newton
stencil: half/bin/3d
bin: standard
Added 38559 bonds, new total = 38559
Finding 1-2 1-3 1-4 neighbors ...
special bond factors lj: 0 1 1
special bond factors coul: 0 1 1
15 = max # of 1-2 neighbors
101 = max # of special neighbors
special bonds CPU = 0.001 seconds
create_bonds many projectile projectile 2 0.0 1.5
generated 0 of 0 mixed pair_coeff terms from geometric mixing rule
WARNING: Bonds are defined but no bond style is set (../force.cpp:192)
WARNING: Likewise 1-2 special neighbor interactions != 1.0 (../force.cpp:194)
Added 21869 bonds, new total = 60428
Finding 1-2 1-3 1-4 neighbors ...
special bond factors lj: 0 1 1
special bond factors coul: 0 1 1
16 = max # of 1-2 neighbors
101 = max # of special neighbors
special bonds CPU = 0.001 seconds
neighbor 0.3 bin
special_bonds lj 0.0 1.0 1.0 coul 1.0 1.0 1.0
bond_style bpm/rotational store/local brkbond 100 time id1 id2
bond_coeff 1 1.0 0.2 0.02 0.02 0.05 0.01 0.01 0.01 0.1 0.2 0.002 0.002
bond_coeff 2 1.0 0.2 0.02 0.02 0.20 0.04 0.04 0.04 0.1 0.2 0.002 0.002
velocity projectile set -0.05 0.0 0.0
compute nbond all nbond/atom
compute tbond all reduce sum c_nbond
timestep 0.05
thermo_style custom step ke pe pxx pyy pzz c_tbond
thermo 100
thermo_modify lost ignore lost/bond ignore
#dump 1 all custom 100 atomDump id radius x y z c_nbond
dump 2 all local 100 brokenDump f_brkbond[1] f_brkbond[2] f_brkbond[3]
dump_modify 2 header no
run 7500
generated 0 of 0 mixed pair_coeff terms from geometric mixing rule
Neighbor list info ...
update every 1 steps, delay 10 steps, check yes
max neighbors/atom: 2000, page size: 100000
master list distance cutoff = 1.3
ghost atom cutoff = 2.6
binsize = 0.65, bins = 98 108 108
1 neighbor lists, perpetual/occasional/extra = 1 0 0
(1) pair gran/hooke/history, perpetual
attributes: half, newton on, size, history
pair build: half/size/bin/newton
stencil: half/bin/3d
bin: standard
Per MPI rank memory allocation (min/avg/max) = 33.34 | 33.34 | 33.35 Mbytes
Step KinEng PotEng Pxx Pyy Pzz c_tbond
0 0.00053238861 0 3.8217307e-05 0 0 10.8703
100 0.00053238861 0 3.8217307e-05 1.2166373e-20 1.2308212e-20 10.8703
200 0.00053238861 0 3.8217307e-05 1.2454467e-20 1.2479589e-20 10.8703
300 0.00053238861 0 3.8217307e-05 1.2256702e-20 1.2621091e-20 10.8703
400 0.00053238861 0 3.8217307e-05 1.2170534e-20 1.2751666e-20 10.8703
500 0.00053093549 0 3.8484194e-05 7.645531e-08 1.4861825e-07 10.8703
600 0.00051485902 0 4.0340751e-05 3.8615876e-07 4.8663463e-07 10.869221
700 0.00049942978 0 3.8684008e-05 4.5363318e-07 4.4560229e-07 10.85501
800 0.00049465262 0 3.6604612e-05 1.4755468e-07 2.0062093e-07 10.820651
900 0.00048784775 0 3.5333139e-05 3.5118328e-07 6.6697625e-07 10.769563
1000 0.00048345699 0 3.4702137e-05 7.0312998e-07 4.0218318e-07 10.730347
1100 0.00047945073 0 3.5065961e-05 6.2813891e-07 7.4640359e-07 10.703184
1200 0.00047512604 0 3.4833144e-05 8.5208604e-07 8.7277583e-07 10.686634
1300 0.00047401428 0 3.4236869e-05 1.0321827e-06 7.4545242e-07 10.678
1400 0.00047619121 0 3.4416549e-05 8.7518021e-07 7.3979503e-07 10.671704
1500 0.0004668728 0 3.4495751e-05 1.4077823e-06 1.517373e-06 10.666127
1600 0.00045088371 0 3.3264301e-05 1.8499661e-06 1.9842415e-06 10.66073
1700 0.00044275099 0 3.2471064e-05 1.9028747e-06 2.2248947e-06 10.6458
1800 0.0004424362 0 3.1846336e-05 1.6208492e-06 1.9291602e-06 10.620615
1900 0.00043678957 0 3.1260936e-05 1.4673956e-06 1.6120523e-06 10.603166
2000 0.00042747562 0 3.0652107e-05 1.6455486e-06 1.53127e-06 10.576003
2100 0.0004214344 0 3.0240727e-05 1.8873967e-06 1.5258622e-06 10.539845
2200 0.00041712779 0 3.0329566e-05 1.8846152e-06 1.4971471e-06 10.49937
2300 0.00041095769 0 3.0000572e-05 2.3585924e-06 1.6773177e-06 10.471668
2400 0.00040883568 0 2.9625158e-05 1.9105554e-06 1.8720763e-06 10.45116
2500 0.00040762685 0 2.9441541e-05 1.6848938e-06 1.8877532e-06 10.437309
2600 0.00040579873 0 2.9255988e-05 1.7523874e-06 1.636423e-06 10.422378
2700 0.00040340975 0 2.9035693e-05 1.673158e-06 1.9038932e-06 10.410505
2800 0.00040170914 0 2.8829361e-05 1.6711978e-06 1.9776001e-06 10.400792
2900 0.00040015113 0 2.8614186e-05 1.5982427e-06 1.7994733e-06 10.393416
3000 0.00040029253 0 2.8470718e-05 1.5589166e-06 1.6682302e-06 10.385321
3100 0.00040037329 0 2.8483376e-05 1.2831526e-06 1.4788005e-06 10.378485
3200 0.00040142612 0 2.8481287e-05 1.1577988e-06 1.3495778e-06 10.373988
3300 0.00040105092 0 2.8547009e-05 1.2155138e-06 1.2633439e-06 10.370031
3400 0.00039950673 0 2.8340939e-05 1.1182251e-06 1.1624668e-06 10.364274
3500 0.00039715236 0 2.824813e-05 1.3086462e-06 1.2029185e-06 10.360496
3600 0.00039446552 0 2.8112283e-05 1.1232321e-06 1.0077217e-06 10.353121
3700 0.00039263296 0 2.7927975e-05 1.1083636e-06 1.2091857e-06 10.346645
3800 0.00039061341 0 2.7819957e-05 1.1836841e-06 1.3566272e-06 10.341069
3900 0.00038985051 0 2.7681947e-05 1.3588359e-06 1.4099727e-06 10.329196
4000 0.00038815347 0 2.7492102e-05 1.1111719e-06 1.1700718e-06 10.318043
4100 0.00038651302 0 2.7444105e-05 9.9563429e-07 1.4085969e-06 10.311027
4200 0.00038565809 0 2.7177341e-05 9.5736307e-07 1.0404482e-06 10.299155
4300 0.0003847255 0 2.7029216e-05 9.6204756e-07 1.140804e-06 10.292319
4400 0.0003844421 0 2.6841047e-05 9.6570404e-07 1.2319818e-06 10.286203
4500 0.0003842788 0 2.6633558e-05 9.6452478e-07 1.1954945e-06 10.278287
4600 0.00038365139 0 2.6514403e-05 9.6185846e-07 1.2002452e-06 10.270732
4700 0.00038271503 0 2.6374349e-05 9.4061833e-07 1.1774211e-06 10.264796
4800 0.00038233688 0 2.638398e-05 1.1644119e-06 1.3746239e-06 10.25742
4900 0.00038223496 0 2.6279821e-05 1.1345508e-06 1.4709213e-06 10.246987
5000 0.00038219402 0 2.6188871e-05 1.0115151e-06 1.2024203e-06 10.240511
5100 0.00038195153 0 2.6137945e-05 1.009856e-06 1.1961088e-06 10.236014
5200 0.00038170903 0 2.6103563e-05 1.0046761e-06 1.1881008e-06 10.232236
5300 0.00038194303 0 2.6111938e-05 1.0533375e-06 1.2621634e-06 10.230617
5400 0.00038147407 0 2.6078641e-05 1.082228e-06 1.2915223e-06 10.230098
5500 0.00038156894 0 2.6084488e-05 1.1395485e-06 1.3592644e-06 10.227759
5600 0.00038169434 0 2.6085704e-05 1.1173618e-06 1.3003599e-06 10.2256
5700 0.00038219734 0 2.6095279e-05 1.1026614e-06 1.280455e-06 10.223621
5800 0.00038268758 0 2.6113437e-05 1.1096198e-06 1.2565503e-06 10.222902
5900 0.00038300658 0 2.6131709e-05 1.1123595e-06 1.235992e-06 10.222182
6000 0.00038250316 0 2.606995e-05 1.1590744e-06 1.2888416e-06 10.221123
6100 0.0003821526 0 2.6025605e-05 1.1434025e-06 1.3141861e-06 10.219503
6200 0.00038185711 0 2.5991255e-05 1.1471391e-06 1.3427373e-06 10.219503
6300 0.00038197679 0 2.5996965e-05 1.1338082e-06 1.3315258e-06 10.218604
6400 0.00038232311 0 2.6035805e-05 1.1353407e-06 1.3306683e-06 10.217884
6500 0.00038255543 0 2.6091572e-05 1.1768703e-06 1.3629611e-06 10.217704
6600 0.00038251887 0 2.6068968e-05 1.1808094e-06 1.3969697e-06 10.217344
6700 0.00038177389 0 2.6004288e-05 1.1659866e-06 1.423638e-06 10.218084
6800 0.00038096291 0 2.5969494e-05 1.1377343e-06 1.4348787e-06 10.218103
6900 0.00038090601 0 2.5951546e-05 1.1327767e-06 1.4311663e-06 10.217024
7000 0.00038088094 0 2.5946255e-05 1.1652568e-06 1.4567559e-06 10.215944
7100 0.00038094624 0 2.5972593e-05 1.1558871e-06 1.4692935e-06 10.214684
7200 0.00038168738 0 2.6002e-05 1.1562707e-06 1.4881081e-06 10.212705
7300 0.00038200854 0 2.6038768e-05 1.1339903e-06 1.4808455e-06 10.212345
7400 0.00038187543 0 2.6044759e-05 1.101743e-06 1.4758679e-06 10.213084
7500 0.00038165297 0 2.6004536e-05 1.0892731e-06 1.4872621e-06 10.214742
Loop time of 28.804 on 4 procs for 7500 steps with 11111 atoms
Performance: 1124843.305 tau/day, 260.380 timesteps/s
97.5% CPU use with 4 MPI tasks x no OpenMP threads
MPI task timing breakdown:
Section | min time | avg time | max time |%varavg| %total
---------------------------------------------------------------
Pair | 0.26977 | 0.28058 | 0.2866 | 1.3 | 0.97
Bond | 22.742 | 23.598 | 24.671 | 16.6 | 81.92
Neigh | 0.54555 | 0.5728 | 0.60272 | 3.2 | 1.99
Comm | 1.4024 | 2.5619 | 3.5079 | 54.8 | 8.89
Output | 0.025307 | 0.025833 | 0.027022 | 0.4 | 0.09
Modify | 1.592 | 1.6506 | 1.7059 | 4.0 | 5.73
Other | | 0.1147 | | | 0.40
Nlocal: 2777.75 ave 2887 max 2682 min
Histogram: 1 0 0 0 2 0 0 0 0 1
Nghost: 1152.5 ave 1189 max 1125 min
Histogram: 1 0 1 0 0 1 0 0 0 1
Neighs: 11515.5 ave 12520 max 10831 min
Histogram: 1 1 0 0 1 0 0 0 0 1
Total # of neighbors = 46062
Ave neighs/atom = 4.1456215
Ave special neighs/atom = 10.214742
Neighbor list builds = 408
Dangerous builds = 0
Total wall time: 0:00:28

View File

@ -0,0 +1,221 @@
LAMMPS (17 Feb 2022)
units lj
dimension 3
boundary f f f
atom_style bond
special_bonds lj 0.0 1.0 1.0 coul 0.0 1.0 1.0
newton on off
comm_modify vel yes cutoff 2.6
lattice fcc 1.0
Lattice spacing in x,y,z = 1.5874011 1.5874011 1.5874011
region box block -25 15 -22 22 -22 22
create_box 1 box bond/types 2 extra/bond/per/atom 20 extra/special/per/atom 50
Created orthogonal box = (-39.685026 -34.922823 -34.922823) to (23.811016 34.922823 34.922823)
1 by 2 by 2 MPI processor grid
region disk cylinder x 0.0 0.0 20.0 -0.5 0.5
create_atoms 1 region disk
Created 7529 atoms
using lattice units in orthogonal box = (-39.685026 -34.922823 -34.922823) to (23.811016 34.922823 34.922823)
create_atoms CPU = 0.001 seconds
group plate region disk
7529 atoms in group plate
region ball sphere 8.0 0.0 0.0 6.0
create_atoms 1 region ball
Created 3589 atoms
using lattice units in orthogonal box = (-39.685026 -34.922823 -34.922823) to (23.811016 34.922823 34.922823)
create_atoms CPU = 0.000 seconds
group projectile region ball
3589 atoms in group projectile
displace_atoms all random 0.1 0.1 0.1 134598738
Displacing atoms ...
mass 1 1.0
neighbor 1.0 bin
pair_style bpm/spring
pair_coeff 1 1 1.0 1.0 1.0
fix 1 all nve
create_bonds many plate plate 1 0.0 1.5
generated 0 of 0 mixed pair_coeff terms from geometric mixing rule
Neighbor list info ...
update every 1 steps, delay 10 steps, check yes
max neighbors/atom: 2000, page size: 100000
master list distance cutoff = 2
ghost atom cutoff = 2.6
binsize = 1, bins = 64 70 70
2 neighbor lists, perpetual/occasional/extra = 1 1 0
(1) command create_bonds, occasional
attributes: full, newton on
pair build: full/bin
stencil: full/bin/3d
bin: standard
(2) pair bpm/spring, perpetual
attributes: half, newton on
pair build: half/bin/newton
stencil: half/bin/3d
bin: standard
Added 38559 bonds, new total = 38559
Finding 1-2 1-3 1-4 neighbors ...
special bond factors lj: 0 1 1
special bond factors coul: 0 1 1
15 = max # of 1-2 neighbors
101 = max # of special neighbors
special bonds CPU = 0.001 seconds
create_bonds many projectile projectile 2 0.0 1.5
generated 0 of 0 mixed pair_coeff terms from geometric mixing rule
WARNING: Bonds are defined but no bond style is set (../force.cpp:192)
WARNING: Likewise 1-2 special neighbor interactions != 1.0 (../force.cpp:194)
Added 21869 bonds, new total = 60428
Finding 1-2 1-3 1-4 neighbors ...
special bond factors lj: 0 1 1
special bond factors coul: 0 1 1
16 = max # of 1-2 neighbors
101 = max # of special neighbors
special bonds CPU = 0.001 seconds
neighbor 0.3 bin
special_bonds lj 0.0 1.0 1.0 coul 1.0 1.0 1.0
bond_style bpm/spring store/local brkbond 100 time id1 id2
bond_coeff 1 1.0 0.04 1.0
bond_coeff 2 1.0 0.20 1.0
velocity projectile set -0.05 0.0 0.0
compute nbond all nbond/atom
compute tbond all reduce sum c_nbond
timestep 0.1
thermo_style custom step ke pe pxx pyy pzz c_tbond
thermo 100
thermo_modify lost ignore lost/bond ignore
#dump 1 all custom 100 atomDump id x y z c_nbond
dump 2 all local 100 brokenDump f_brkbond[1] f_brkbond[2] f_brkbond[3]
dump_modify 2 header no
run 7500
generated 0 of 0 mixed pair_coeff terms from geometric mixing rule
Neighbor list info ...
update every 1 steps, delay 10 steps, check yes
max neighbors/atom: 2000, page size: 100000
master list distance cutoff = 1.3
ghost atom cutoff = 2.6
binsize = 0.65, bins = 98 108 108
1 neighbor lists, perpetual/occasional/extra = 1 0 0
(1) pair bpm/spring, perpetual
attributes: half, newton on
pair build: half/bin/newton
stencil: half/bin/3d
bin: standard
Per MPI rank memory allocation (min/avg/max) = 17.74 | 17.74 | 17.74 Mbytes
Step KinEng PotEng Pxx Pyy Pzz c_tbond
0 0.0010167873 0 7.298968e-05 0 0 10.8703
100 0.0010167873 0 7.298968e-05 -8.7429897e-20 -8.8470837e-20 10.8703
200 0.0010167873 0 7.298968e-05 -7.2809565e-20 -8.0915788e-20 10.8703
300 0.0009951439 0 9.9273671e-05 8.1569216e-06 8.0922512e-06 10.868142
400 0.00095142792 0 0.00012669557 -1.3413721e-05 -1.4800745e-05 10.849793
500 0.00092272662 0 8.1708784e-05 -9.7488701e-06 -1.3603634e-05 10.819752
600 0.00088967612 0 6.2587266e-05 -5.1954127e-06 -6.781587e-06 10.797985
700 0.00086070919 0 8.8529902e-05 -9.9431205e-06 -7.9905211e-06 10.776579
800 0.00083543943 0 7.5920357e-05 3.6381024e-07 3.7747551e-06 10.759309
900 0.00081190799 0 6.3678219e-05 5.4158243e-06 1.2751247e-05 10.744199
1000 0.00078828988 0 7.3079869e-05 -6.6410613e-06 -1.198683e-06 10.728368
1100 0.00075664718 0 6.2976995e-05 -4.7863299e-06 -3.9814556e-06 10.711819
1200 0.00072472205 0 4.9680233e-05 9.3093553e-06 4.4426393e-06 10.69401
1300 0.00070176532 0 5.4048176e-05 1.3051954e-05 7.5448558e-06 10.671164
1400 0.00068599319 0 5.4062404e-05 9.9930199e-06 1.0353154e-05 10.650117
1500 0.0006786164 0 4.5038593e-05 8.067571e-06 9.8825461e-06 10.636266
1600 0.00067466823 0 4.6733251e-05 9.8595584e-06 1.1551081e-05 10.621335
1700 0.00066847126 0 5.1472453e-05 2.1569974e-07 6.0070599e-06 10.6127
1800 0.00065711827 0 5.0355189e-05 -8.030203e-06 -3.1395588e-06 10.599568
1900 0.00063882539 0 4.7146888e-05 -2.0596242e-05 -1.6494542e-05 10.581939
2000 0.00061717894 0 4.6698781e-05 -2.5473048e-05 -2.7703615e-05 10.567188
2100 0.00059261327 0 3.7701055e-05 -2.4637803e-05 -3.3919162e-05 10.552617
2200 0.00056527158 0 3.2239421e-05 -1.8786685e-05 -2.4202734e-05 10.538406
2300 0.00054054919 0 2.7410334e-05 -6.701111e-06 -7.4354974e-06 10.520777
2400 0.00051820065 0 2.2997206e-05 1.5623767e-05 1.8687824e-05 10.501889
2500 0.00049647925 0 1.746693e-05 2.8814144e-05 3.5569425e-05 10.487498
2600 0.00047837258 0 1.4127067e-05 3.4245611e-05 4.0208577e-05 10.472387
2700 0.00046626924 0 1.3714876e-05 3.7922196e-05 4.1550346e-05 10.456377
2800 0.0004560167 0 1.5260976e-05 3.5632577e-05 3.7885738e-05 10.440007
2900 0.00045331059 0 1.5194832e-05 3.1036124e-05 2.8633755e-05 10.427955
3000 0.00045227799 0 1.4877378e-05 1.9327028e-05 2.1189487e-05 10.414283
3100 0.00044866178 0 2.0424612e-05 -2.7242288e-06 7.7121438e-06 10.40349
3200 0.00044336453 0 2.3276121e-05 -1.979069e-05 -4.2311089e-06 10.395575
3300 0.00043526526 0 2.3338132e-05 -2.834945e-05 -1.7302033e-05 10.389998
3400 0.00042817758 0 2.4374527e-05 -2.9870076e-05 -3.0623264e-05 10.382803
3500 0.00042182658 0 2.6120627e-05 -2.9449521e-05 -3.787776e-05 10.378126
3600 0.00041794291 0 2.4736957e-05 -2.4098172e-05 -3.0529166e-05 10.373628
3700 0.0004156005 0 2.7543305e-05 -1.2431749e-05 -1.8626096e-05 10.37075
3800 0.0004141461 0 2.4630482e-05 -6.345489e-06 -1.7375803e-05 10.368771
3900 0.00041328832 0 2.2220142e-05 4.1471034e-07 -1.3339476e-05 10.366972
4000 0.00041121725 0 2.3491321e-05 1.1284551e-05 -5.8651834e-06 10.364634
4100 0.00040761876 0 2.6688248e-05 1.9721625e-05 3.7536871e-06 10.362655
4200 0.00040301362 0 2.7601916e-05 1.9212118e-05 9.7175996e-06 10.359417
4300 0.00040001545 0 2.7243769e-05 1.6889359e-05 1.1857147e-05 10.3551
4400 0.00039654521 0 2.561083e-05 1.3863551e-05 1.0593597e-05 10.351142
4500 0.00039435924 0 2.4366458e-05 1.2545563e-05 1.1323962e-05 10.348804
4600 0.00039250006 0 2.3719127e-05 1.1015167e-05 8.5964046e-06 10.348444
4700 0.00039145496 0 2.2943915e-05 8.7824224e-06 5.0397129e-06 10.346825
4800 0.00039105331 0 2.4005757e-05 7.5899773e-06 9.033741e-07 10.344846
4900 0.0003898798 0 2.3819433e-05 4.9673894e-06 -2.3466459e-06 10.343587
5000 0.00038747508 0 2.3605028e-05 -1.1717437e-06 -6.1096657e-06 10.343047
5100 0.00038549022 0 2.3453798e-05 -9.9256693e-06 -9.3584148e-06 10.341788
5200 0.00038283936 0 2.5243567e-05 -1.5877598e-05 -9.9474447e-06 10.340169
5300 0.00038140888 0 2.5522223e-05 -1.9331435e-05 -1.1067039e-05 10.33873
5400 0.00037916674 0 2.5181488e-05 -2.1581255e-05 -1.1252641e-05 10.336931
5500 0.00037782932 0 2.691805e-05 -1.5768241e-05 -5.6704695e-06 10.334952
5600 0.00037628832 0 2.5851445e-05 -1.4239811e-05 -1.9122536e-06 10.333153
5700 0.00037451913 0 2.4758416e-05 -1.3252284e-05 -1.9222041e-06 10.331714
5800 0.00037328662 0 2.2507032e-05 -9.6704092e-06 -7.5470215e-06 10.330095
5900 0.00037253111 0 2.3303086e-05 -4.2828034e-06 -7.888056e-06 10.328476
6000 0.00037171133 0 2.4042456e-05 -4.7684985e-06 -6.5164336e-06 10.327397
6100 0.00036986726 0 2.4938695e-05 -4.8738316e-06 -4.5380007e-06 10.327037
6200 0.0003675822 0 2.3322229e-05 -4.6333093e-06 -5.7086464e-06 10.327037
6300 0.00036552389 0 2.1435354e-05 -4.8971566e-06 -3.5935426e-06 10.327037
6400 0.00036488091 0 2.0813994e-05 -3.8333319e-06 -3.6595059e-06 10.327037
6500 0.00036447973 0 2.2241876e-05 8.7797361e-08 -4.141203e-06 10.327037
6600 0.00036383343 0 2.269485e-05 4.9364593e-06 1.3062133e-06 10.326677
6700 0.00036305076 0 2.1838759e-05 6.4587048e-06 4.7758772e-06 10.326318
6800 0.00036226601 0 2.2916622e-05 6.044926e-06 5.0291597e-06 10.325598
6900 0.00036175279 0 2.2691667e-05 6.9998847e-06 5.8988637e-06 10.324699
7000 0.00036143633 0 2.1725813e-05 8.1268152e-06 5.0390503e-06 10.324519
7100 0.0003610248 0 2.1799675e-05 8.65795e-06 3.1360368e-06 10.323439
7200 0.00036086259 0 2.2198029e-05 5.1764734e-06 5.4798783e-07 10.32308
7300 0.00036099757 0 2.4160496e-05 1.0310325e-06 -5.115075e-07 10.32254
7400 0.00036129334 0 2.5325018e-05 -9.4918158e-07 -1.7064957e-06 10.32218
7500 0.00036136655 0 2.3513198e-05 -3.8618451e-06 -4.4344772e-06 10.321281
Loop time of 4.51074 on 4 procs for 7500 steps with 11118 atoms
Performance: 14365719.597 tau/day, 1662.699 timesteps/s
93.8% CPU use with 4 MPI tasks x no OpenMP threads
MPI task timing breakdown:
Section | min time | avg time | max time |%varavg| %total
---------------------------------------------------------------
Pair | 0.25733 | 0.26952 | 0.28068 | 1.6 | 5.98
Bond | 1.9391 | 2.0128 | 2.0851 | 3.7 | 44.62
Neigh | 0.56308 | 0.5941 | 0.62077 | 2.8 | 13.17
Comm | 0.68282 | 0.80856 | 0.94406 | 10.7 | 17.93
Output | 0.19287 | 0.1933 | 0.19426 | 0.1 | 4.29
Modify | 0.53239 | 0.55343 | 0.57349 | 2.0 | 12.27
Other | | 0.07902 | | | 1.75
Nlocal: 2779.5 ave 2862 max 2686 min
Histogram: 1 0 0 0 0 1 1 0 0 1
Nghost: 1183.25 ave 1220 max 1134 min
Histogram: 1 0 0 0 1 0 0 0 1 1
Neighs: 11828.8 ave 12387 max 11053 min
Histogram: 1 0 0 0 1 0 0 0 1 1
Total # of neighbors = 47315
Ave neighs/atom = 4.2557115
Ave special neighs/atom = 10.321461
Neighbor list builds = 421
Dangerous builds = 11
Total wall time: 0:00:04

View File

@ -0,0 +1,35 @@
units lj
dimension 3
boundary m m m
atom_style bpm/sphere
special_bonds lj 0.0 1.0 1.0 coul 1.0 1.0 1.0
newton on off
comm_modify vel yes cutoff 3.3
region box block -15 15 -15 15 0 60.0
create_box 1 box bond/types 1 extra/bond/per/atom 15 extra/special/per/atom 50
molecule my_mol "rect.mol"
region wall_cyl cylinder z 0.0 0.0 10.0 EDGE EDGE side in
region dropzone cylinder z 0.0 0.0 10.0 40.0 50.0 side in
pair_style gran/hertz/history 1.0 NULL 0.5 NULL 0.1 1
bond_style bpm/rotational
pair_coeff 1 1
bond_coeff 1 1.0 0.2 0.01 0.01 2.0 0.4 0.02 0.02 0.2 0.04 0.002 0.002
compute nbond all nbond/atom
compute tbond all reduce sum c_nbond
compute_modify thermo_temp dynamic/dof yes
fix 1 all wall/gran hertz/history 1.0 NULL 0.5 NULL 0.1 1 zplane 0.0 NULL
fix 2 all wall/gran/region hertz/history 1.0 NULL 0.5 NULL 0.1 1 region wall_cyl
fix 3 all gravity 1e-4 vector 0 0 -1
fix 4 all deposit 40 0 1500 712511343 mol my_mol region dropzone near 2.0 vz -0.05 -0.05
fix 5 all nve/bpm/sphere
timestep 0.05
thermo_style custom step ke pe pxx pyy pzz c_tbond
thermo 100
#dump 1 all custom 500 atomDump id radius x y z c_nbond mol
run 100000

File diff suppressed because it is too large Load Diff

568
examples/bpm/pour/rect.mol Normal file
View File

@ -0,0 +1,568 @@
#Made with create_mol.py
63 atoms
297 bonds
Coords
#ID x y z
1 0.0 0.0 0.0
2 0.7348518971806154 0.7348518971806154 0.0
3 0.7348518971806154 0.0 0.7348518971806154
4 0.0 0.7348518971806154 0.7348518971806154
5 1.4697037943612308 0.0 0.0
6 1.4697037943612308 0.7348518971806154 0.7348518971806154
7 0.0 1.4697037943612308 0.0
8 0.7348518971806154 1.4697037943612308 0.7348518971806154
9 1.4697037943612308 1.4697037943612308 0.0
10 0.0 0.0 1.4697037943612308
11 0.7348518971806154 0.7348518971806154 1.4697037943612308
12 0.7348518971806154 0.0 2.204555691541846
13 0.0 0.7348518971806154 2.204555691541846
14 1.4697037943612308 0.0 1.4697037943612308
15 1.4697037943612308 0.7348518971806154 2.204555691541846
16 0.0 1.4697037943612308 1.4697037943612308
17 0.7348518971806154 1.4697037943612308 2.204555691541846
18 1.4697037943612308 1.4697037943612308 1.4697037943612308
19 0.0 0.0 2.9394075887224616
20 0.7348518971806154 0.7348518971806154 2.9394075887224616
21 0.7348518971806154 0.0 3.674259485903077
22 0.0 0.7348518971806154 3.674259485903077
23 1.4697037943612308 0.0 2.9394075887224616
24 1.4697037943612308 0.7348518971806154 3.674259485903077
25 0.0 1.4697037943612308 2.9394075887224616
26 0.7348518971806154 1.4697037943612308 3.674259485903077
27 1.4697037943612308 1.4697037943612308 2.9394075887224616
28 0.0 0.0 4.409111383083692
29 0.7348518971806154 0.7348518971806154 4.409111383083692
30 0.7348518971806154 0.0 5.143963280264308
31 0.0 0.7348518971806154 5.143963280264308
32 1.4697037943612308 0.0 4.409111383083692
33 1.4697037943612308 0.7348518971806154 5.143963280264308
34 0.0 1.4697037943612308 4.409111383083692
35 0.7348518971806154 1.4697037943612308 5.143963280264308
36 1.4697037943612308 1.4697037943612308 4.409111383083692
37 0.0 0.0 5.878815177444923
38 0.7348518971806154 0.7348518971806154 5.878815177444923
39 0.7348518971806154 0.0 6.613667074625538
40 0.0 0.7348518971806154 6.613667074625538
41 1.4697037943612308 0.0 5.878815177444923
42 1.4697037943612308 0.7348518971806154 6.613667074625538
43 0.0 1.4697037943612308 5.878815177444923
44 0.7348518971806154 1.4697037943612308 6.613667074625538
45 1.4697037943612308 1.4697037943612308 5.878815177444923
46 0.0 0.0 7.348518971806154
47 0.7348518971806154 0.7348518971806154 7.348518971806154
48 0.7348518971806154 0.0 8.08337086898677
49 0.0 0.7348518971806154 8.08337086898677
50 1.4697037943612308 0.0 7.348518971806154
51 1.4697037943612308 0.7348518971806154 8.08337086898677
52 0.0 1.4697037943612308 7.348518971806154
53 0.7348518971806154 1.4697037943612308 8.08337086898677
54 1.4697037943612308 1.4697037943612308 7.348518971806154
55 0.0 0.0 8.818222766167384
56 0.7348518971806154 0.7348518971806154 8.818222766167384
57 0.7348518971806154 0.0 9.553074663348
58 0.0 0.7348518971806154 9.553074663348
59 1.4697037943612308 0.0 8.818222766167384
60 1.4697037943612308 0.7348518971806154 9.553074663348
61 0.0 1.4697037943612308 8.818222766167384
62 0.7348518971806154 1.4697037943612308 9.553074663348
63 1.4697037943612308 1.4697037943612308 8.818222766167384
Types
#ID type
1 1
2 1
3 1
4 1
5 1
6 1
7 1
8 1
9 1
10 1
11 1
12 1
13 1
14 1
15 1
16 1
17 1
18 1
19 1
20 1
21 1
22 1
23 1
24 1
25 1
26 1
27 1
28 1
29 1
30 1
31 1
32 1
33 1
34 1
35 1
36 1
37 1
38 1
39 1
40 1
41 1
42 1
43 1
44 1
45 1
46 1
47 1
48 1
49 1
50 1
51 1
52 1
53 1
54 1
55 1
56 1
57 1
58 1
59 1
60 1
61 1
62 1
63 1
Diameters
#ID diameter
1 1
2 1
3 1
4 1
5 1
6 1
7 1
8 1
9 1
10 1
11 1
12 1
13 1
14 1
15 1
16 1
17 1
18 1
19 1
20 1
21 1
22 1
23 1
24 1
25 1
26 1
27 1
28 1
29 1
30 1
31 1
32 1
33 1
34 1
35 1
36 1
37 1
38 1
39 1
40 1
41 1
42 1
43 1
44 1
45 1
46 1
47 1
48 1
49 1
50 1
51 1
52 1
53 1
54 1
55 1
56 1
57 1
58 1
59 1
60 1
61 1
62 1
63 1
Masses
#ID mass
1 1
2 1
3 1
4 1
5 1
6 1
7 1
8 1
9 1
10 1
11 1
12 1
13 1
14 1
15 1
16 1
17 1
18 1
19 1
20 1
21 1
22 1
23 1
24 1
25 1
26 1
27 1
28 1
29 1
30 1
31 1
32 1
33 1
34 1
35 1
36 1
37 1
38 1
39 1
40 1
41 1
42 1
43 1
44 1
45 1
46 1
47 1
48 1
49 1
50 1
51 1
52 1
53 1
54 1
55 1
56 1
57 1
58 1
59 1
60 1
61 1
62 1
63 1
Bonds
#ID type atom1 atom2
1 1 1 2
2 1 1 3
3 1 1 4
4 1 1 5
5 1 1 7
6 1 1 10
7 1 2 3
8 1 2 4
9 1 2 5
10 1 2 6
11 1 2 7
12 1 2 8
13 1 2 9
14 1 2 11
15 1 3 4
16 1 3 5
17 1 3 6
18 1 3 8
19 1 3 10
20 1 3 11
21 1 3 12
22 1 3 14
23 1 4 6
24 1 4 7
25 1 4 8
26 1 4 10
27 1 4 11
28 1 4 13
29 1 4 16
30 1 5 6
31 1 5 9
32 1 5 14
33 1 6 8
34 1 6 9
35 1 6 11
36 1 6 14
37 1 6 18
38 1 7 8
39 1 7 9
40 1 7 16
41 1 8 9
42 1 8 11
43 1 8 16
44 1 8 17
45 1 8 18
46 1 9 18
47 1 10 11
48 1 10 12
49 1 10 13
50 1 10 14
51 1 10 16
52 1 10 19
53 1 11 12
54 1 11 13
55 1 11 14
56 1 11 15
57 1 11 16
58 1 11 17
59 1 11 18
60 1 12 13
61 1 12 14
62 1 12 15
63 1 12 17
64 1 12 19
65 1 12 20
66 1 12 21
67 1 12 23
68 1 13 15
69 1 13 16
70 1 13 17
71 1 13 19
72 1 13 20
73 1 13 22
74 1 13 25
75 1 14 15
76 1 14 18
77 1 14 23
78 1 15 17
79 1 15 18
80 1 15 20
81 1 15 23
82 1 15 27
83 1 16 17
84 1 16 18
85 1 16 25
86 1 17 18
87 1 17 20
88 1 17 25
89 1 17 27
90 1 18 27
91 1 19 20
92 1 19 21
93 1 19 22
94 1 19 23
95 1 19 25
96 1 19 28
97 1 20 21
98 1 20 22
99 1 20 23
100 1 20 24
101 1 20 25
102 1 20 26
103 1 20 27
104 1 20 29
105 1 21 22
106 1 21 23
107 1 21 24
108 1 21 26
109 1 21 28
110 1 21 29
111 1 21 30
112 1 21 32
113 1 22 24
114 1 22 25
115 1 22 26
116 1 22 28
117 1 22 29
118 1 22 34
119 1 23 24
120 1 23 27
121 1 23 32
122 1 24 26
123 1 24 27
124 1 24 29
125 1 24 32
126 1 24 36
127 1 25 26
128 1 25 27
129 1 25 34
130 1 26 27
131 1 26 29
132 1 26 34
133 1 26 35
134 1 26 36
135 1 27 36
136 1 28 29
137 1 28 30
138 1 28 31
139 1 28 32
140 1 28 34
141 1 28 37
142 1 29 30
143 1 29 31
144 1 29 32
145 1 29 33
146 1 29 34
147 1 29 35
148 1 29 36
149 1 29 38
150 1 30 31
151 1 30 32
152 1 30 33
153 1 30 35
154 1 30 37
155 1 30 38
156 1 30 41
157 1 31 33
158 1 31 34
159 1 31 35
160 1 31 37
161 1 31 38
162 1 31 40
163 1 31 43
164 1 32 33
165 1 32 36
166 1 32 41
167 1 33 35
168 1 33 36
169 1 33 38
170 1 33 41
171 1 33 42
172 1 33 45
173 1 34 35
174 1 34 36
175 1 34 43
176 1 35 36
177 1 35 38
178 1 35 43
179 1 35 45
180 1 36 45
181 1 37 38
182 1 37 39
183 1 37 40
184 1 37 41
185 1 37 43
186 1 37 46
187 1 38 39
188 1 38 40
189 1 38 41
190 1 38 42
191 1 38 43
192 1 38 44
193 1 38 45
194 1 38 47
195 1 39 40
196 1 39 41
197 1 39 42
198 1 39 44
199 1 39 46
200 1 39 47
201 1 39 50
202 1 40 42
203 1 40 43
204 1 40 44
205 1 40 46
206 1 40 47
207 1 40 52
208 1 41 42
209 1 41 45
210 1 41 50
211 1 42 44
212 1 42 45
213 1 42 47
214 1 42 50
215 1 42 51
216 1 42 54
217 1 43 44
218 1 43 45
219 1 43 52
220 1 44 45
221 1 44 47
222 1 44 52
223 1 44 53
224 1 44 54
225 1 45 54
226 1 46 47
227 1 46 48
228 1 46 49
229 1 46 50
230 1 46 52
231 1 46 55
232 1 47 48
233 1 47 49
234 1 47 50
235 1 47 51
236 1 47 52
237 1 47 53
238 1 47 54
239 1 47 56
240 1 48 49
241 1 48 50
242 1 48 51
243 1 48 53
244 1 48 55
245 1 48 56
246 1 48 57
247 1 48 59
248 1 49 51
249 1 49 52
250 1 49 53
251 1 49 55
252 1 49 56
253 1 49 58
254 1 49 61
255 1 50 51
256 1 50 54
257 1 50 59
258 1 51 53
259 1 51 54
260 1 51 56
261 1 51 59
262 1 51 63
263 1 52 53
264 1 52 54
265 1 52 61
266 1 53 54
267 1 53 56
268 1 53 61
269 1 53 62
270 1 53 63
271 1 54 63
272 1 55 56
273 1 55 57
274 1 55 58
275 1 55 59
276 1 55 61
277 1 56 57
278 1 56 58
279 1 56 59
280 1 56 60
281 1 56 61
282 1 56 62
283 1 56 63
284 1 57 58
285 1 57 59
286 1 57 60
287 1 57 62
288 1 58 60
289 1 58 61
290 1 58 62
291 1 59 60
292 1 59 63
293 1 60 62
294 1 60 63
295 1 61 62
296 1 61 63
297 1 62 63

18
src/.gitignore vendored
View File

@ -254,6 +254,21 @@
/pair_mesont_tpm.cpp
/pair_mesont_tpm.h
/atom_vec_bpm_sphere.cpp
/atom_vec_bpm_sphere.h
/bond_bpm.cpp
/bond_bpm.h
/bond_bpm_rotational.cpp
/bond_bpm_rotational.h
/bond_bpm_spring.cpp
/bond_bpm_spring.h
/compute_nbond_atom.cpp
/compute_nbond_atom.h
/fix_nve_bpm_sphere.cpp
/fix_nve_bpm_sphere.h
/pair_bpm_spring.cpp
/pair_bpm_spring.h
/compute_adf.cpp
/compute_adf.h
/compute_contact_atom.cpp
@ -792,8 +807,6 @@
/fix_orient_eco.h
/fix_orient_fcc.cpp
/fix_orient_fcc.h
/fix_pair_tracker.cpp
/fix_pair_tracker.h
/fix_peri_neigh.cpp
/fix_peri_neigh.h
/fix_phonon.cpp
@ -1524,3 +1537,4 @@
/pair_smtbq.h
/pair_vashishta*.cpp
/pair_vashishta*.h

View File

@ -0,0 +1,245 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, 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.
------------------------------------------------------------------------- */
#include "atom_vec_bpm_sphere.h"
#include "atom.h"
#include "error.h"
#include "fix.h"
#include "fix_adapt.h"
#include "math_const.h"
#include "modify.h"
#include "utils.h"
#include <cstring>
using namespace LAMMPS_NS;
using MathConst::MY_PI;
/* ---------------------------------------------------------------------- */
AtomVecBPMSphere::AtomVecBPMSphere(LAMMPS *_lmp) : AtomVec(_lmp)
{
mass_type = PER_ATOM;
molecular = Atom::MOLECULAR;
bonds_allow = 1;
atom->molecule_flag = 1;
atom->sphere_flag = 1;
atom->radius_flag = atom->rmass_flag = atom->omega_flag = atom->torque_flag = atom->quat_flag = 1;
// strings with peratom variables to include in each AtomVec method
// strings cannot contain fields in corresponding AtomVec default strings
// order of fields in a string does not matter
// except: fields_data_atom & fields_data_vel must match data file
// clang-format off
fields_grow = (char *) "molecule num_bond bond_type bond_atom nspecial special radius rmass "
"omega torque quat";
fields_copy = (char *) "molecule num_bond bond_type bond_atom nspecial special radius rmass "
"omega quat";
fields_comm = (char *) "";
fields_comm_vel = (char *) "omega quat";
fields_reverse = (char *) "torque";
fields_border = (char *) "molecule radius rmass";
fields_border_vel = (char *) "molecule radius rmass omega quat";
fields_exchange = (char *) "molecule num_bond bond_type bond_atom nspecial special radius rmass "
"omega quat";
fields_restart = (char *) "molecule num_bond bond_type bond_atom radius rmass omega quat";
fields_create = (char *) "molecule num_bond nspecial radius rmass omega quat";
fields_data_atom = (char *) "id molecule type radius rmass x";
fields_data_vel = (char *) "id v omega";
// clang-format on
bond_per_atom = 0;
bond_negative = NULL;
}
/* ----------------------------------------------------------------------
process sub-style args
optional arg = 0/1 for static/dynamic particle radii
------------------------------------------------------------------------- */
void AtomVecBPMSphere::process_args(int narg, char **arg)
{
if (narg != 0 && narg != 1) error->all(FLERR, "Illegal atom_style bpm/sphere command");
radvary = 0;
if (narg == 1) {
radvary = utils::numeric(FLERR, arg[0], true, lmp);
if (radvary < 0 || radvary > 1) error->all(FLERR, "Illegal atom_style bpm/sphere command");
}
// dynamic particle radius and mass must be communicated every step
if (radvary) {
fields_comm = (char *) "radius rmass";
fields_comm_vel = (char *) "radius rmass omega";
}
// delay setting up of fields until now
setup_fields();
}
/* ---------------------------------------------------------------------- */
void AtomVecBPMSphere::init()
{
AtomVec::init();
// check if optional radvary setting should have been set to 1
for (int i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style, "adapt") == 0) {
FixAdapt *fix = (FixAdapt *) modify->fix[i];
if (fix->diamflag && radvary == 0)
error->all(FLERR, "Fix adapt changes atom radii but atom_style bpm/sphere is not dynamic");
}
}
/* ----------------------------------------------------------------------
set local copies of all grow ptrs used by this class, except defaults
needed in replicate when 2 atom classes exist and it calls pack_restart()
------------------------------------------------------------------------- */
void AtomVecBPMSphere::grow_pointers()
{
radius = atom->radius;
rmass = atom->rmass;
omega = atom->omega;
quat = atom->quat;
num_bond = atom->num_bond;
bond_type = atom->bond_type;
nspecial = atom->nspecial;
}
/* ----------------------------------------------------------------------
initialize non-zero atom quantities
------------------------------------------------------------------------- */
void AtomVecBPMSphere::create_atom_post(int ilocal)
{
radius[ilocal] = 0.5;
rmass[ilocal] = 4.0 * MY_PI / 3.0 * 0.5 * 0.5 * 0.5;
quat[ilocal][0] = 1.0;
quat[ilocal][1] = 0.0;
quat[ilocal][2] = 0.0;
quat[ilocal][3] = 0.0;
}
/* ----------------------------------------------------------------------
modify values for AtomVec::pack_restart() to pack
------------------------------------------------------------------------- */
void AtomVecBPMSphere::pack_restart_pre(int ilocal)
{
// insure bond_negative vector is needed length
if (bond_per_atom < atom->bond_per_atom) {
delete[] bond_negative;
bond_per_atom = atom->bond_per_atom;
bond_negative = new int[bond_per_atom];
}
// flip any negative types to positive and flag which ones
any_bond_negative = 0;
for (int m = 0; m < num_bond[ilocal]; m++) {
if (bond_type[ilocal][m] < 0) {
bond_negative[m] = 1;
bond_type[ilocal][m] = -bond_type[ilocal][m];
any_bond_negative = 1;
} else
bond_negative[m] = 0;
}
}
/* ----------------------------------------------------------------------
unmodify values packed by AtomVec::pack_restart()
------------------------------------------------------------------------- */
void AtomVecBPMSphere::pack_restart_post(int ilocal)
{
// restore the flagged types to their negative values
if (any_bond_negative) {
for (int m = 0; m < num_bond[ilocal]; m++)
if (bond_negative[m]) bond_type[ilocal][m] = -bond_type[ilocal][m];
}
}
/* ----------------------------------------------------------------------
initialize other atom quantities after AtomVec::unpack_restart()
------------------------------------------------------------------------- */
void AtomVecBPMSphere::unpack_restart_init(int ilocal)
{
nspecial[ilocal][0] = 0;
nspecial[ilocal][1] = 0;
nspecial[ilocal][2] = 0;
}
/* ----------------------------------------------------------------------
modify what AtomVec::data_atom() just unpacked
or initialize other atom quantities
------------------------------------------------------------------------- */
void AtomVecBPMSphere::data_atom_post(int ilocal)
{
radius_one = 0.5 * atom->radius[ilocal];
radius[ilocal] = radius_one;
if (radius_one > 0.0) rmass[ilocal] *= 4.0 * MY_PI / 3.0 * radius_one * radius_one * radius_one;
if (rmass[ilocal] <= 0.0) error->one(FLERR, "Invalid density in Atoms section of data file");
omega[ilocal][0] = 0.0;
omega[ilocal][1] = 0.0;
omega[ilocal][2] = 0.0;
quat[ilocal][0] = 1.0;
quat[ilocal][1] = 0.0;
quat[ilocal][2] = 0.0;
quat[ilocal][3] = 0.0;
num_bond[ilocal] = 0;
nspecial[ilocal][0] = 0;
nspecial[ilocal][1] = 0;
nspecial[ilocal][2] = 0;
}
/* ----------------------------------------------------------------------
modify values for AtomVec::pack_data() to pack
------------------------------------------------------------------------- */
void AtomVecBPMSphere::pack_data_pre(int ilocal)
{
radius_one = radius[ilocal];
rmass_one = rmass[ilocal];
radius[ilocal] *= 2.0;
if (radius_one != 0.0)
rmass[ilocal] = rmass_one / (4.0 * MY_PI / 3.0 * radius_one * radius_one * radius_one);
}
/* ----------------------------------------------------------------------
unmodify values packed by AtomVec::pack_data()
------------------------------------------------------------------------- */
void AtomVecBPMSphere::pack_data_post(int ilocal)
{
radius[ilocal] = radius_one;
rmass[ilocal] = rmass_one;
}

View File

@ -0,0 +1,82 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, 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.
------------------------------------------------------------------------- */
#ifdef ATOM_CLASS
// clang-format off
AtomStyle(bpm/sphere,AtomVecBPMSphere);
// clang-format on
#else
#ifndef LMP_ATOM_VEC_BPM_SPHERE_H
#define LMP_ATOM_VEC_BPM_SPHERE_H
#include "atom_vec.h"
namespace LAMMPS_NS {
class AtomVecBPMSphere : public AtomVec {
public:
AtomVecBPMSphere(class LAMMPS *);
void process_args(int, char **) override;
void init() override;
void grow_pointers() override;
void create_atom_post(int) override;
void pack_restart_pre(int) override;
void pack_restart_post(int) override;
void unpack_restart_init(int) override;
void data_atom_post(int) override;
void pack_data_pre(int) override;
void pack_data_post(int) override;
private:
int *num_bond;
int **bond_type;
int **nspecial;
double *radius, *rmass;
double **omega, **torque, **quat;
int any_bond_negative;
int bond_per_atom;
int *bond_negative;
int radvary;
double radius_one, rmass_one;
};
} // namespace LAMMPS_NS
#endif
#endif
/* ERROR/WARNING messages:
E: Per-processor system is too big
The number of owned atoms plus ghost atoms on a single
processor must fit in 32-bit integer.
E: Invalid atom type in Atoms section of data file
Atom types must range from 1 to specified # of types.
E: Invalid radius in Atoms section of data file
Radius must be >= 0.0.
E: Invalid density in Atoms section of data file
Density value cannot be <= 0.0.
*/

415
src/BPM/bond_bpm.cpp Normal file
View File

@ -0,0 +1,415 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, 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.
------------------------------------------------------------------------- */
#include "bond_bpm.h"
#include "atom.h"
#include "domain.h"
#include "error.h"
#include "fix_bond_history.h"
#include "fix_store_local.h"
#include "fix_update_special_bonds.h"
#include "force.h"
#include "memory.h"
#include "modify.h"
#include "update.h"
#include <vector>
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
BondBPM::BondBPM(LAMMPS *_lmp) :
Bond(_lmp), id_fix_dummy(nullptr), id_fix_dummy2(nullptr), id_fix_update(nullptr),
id_fix_bond_history(nullptr), id_fix_store_local(nullptr), id_fix_prop_atom(nullptr),
fix_store_local(nullptr), fix_bond_history(nullptr), fix_update_special_bonds(nullptr),
pack_choice(nullptr), output_data(nullptr)
{
overlay_flag = 0;
prop_atom_flag = 0;
nvalues = 0;
r0_max_estimate = 0.0;
max_stretch = 1.0;
// create dummy fix as placeholder for FixUpdateSpecialBonds & BondHistory
// this is so final order of Modify:fix will conform to input script
// BondHistory technically only needs this if updateflag = 1
id_fix_dummy = utils::strdup("BPM_DUMMY");
modify->add_fix(fmt::format("{} all DUMMY ", id_fix_dummy));
id_fix_dummy2 = utils::strdup("BPM_DUMMY2");
modify->add_fix(fmt::format("{} all DUMMY ", id_fix_dummy2));
}
/* ---------------------------------------------------------------------- */
BondBPM::~BondBPM()
{
delete[] pack_choice;
if (id_fix_dummy) modify->delete_fix(id_fix_dummy);
if (id_fix_dummy2) modify->delete_fix(id_fix_dummy2);
if (id_fix_update) modify->delete_fix(id_fix_update);
if (id_fix_bond_history) modify->delete_fix(id_fix_bond_history);
if (id_fix_store_local) modify->delete_fix(id_fix_store_local);
if (id_fix_prop_atom) modify->delete_fix(id_fix_prop_atom);
delete[] id_fix_dummy;
delete[] id_fix_dummy2;
delete[] id_fix_update;
delete[] id_fix_bond_history;
delete[] id_fix_store_local;
delete[] id_fix_prop_atom;
memory->destroy(output_data);
}
/* ---------------------------------------------------------------------- */
void BondBPM::init_style()
{
if (id_fix_store_local) {
auto ifix = modify->get_fix_by_id(id_fix_store_local);
if (!ifix) error->all(FLERR, "Cannot find fix store/local");
if (strcmp(ifix->style, "STORE_LOCAL") != 0)
error->all(FLERR, "Incorrect fix style matched, not store/local");
fix_store_local = dynamic_cast<FixStoreLocal *>(ifix);
fix_store_local->nvalues = nvalues;
}
if (overlay_flag) {
if (force->special_lj[1] != 1.0)
error->all(FLERR,
"With overlay/pair, BPM bond styles require special_bonds weight of 1.0 for "
"first neighbors");
if (id_fix_update) {
modify->delete_fix(id_fix_update);
delete[] id_fix_update;
id_fix_update = nullptr;
}
} else {
// Require atoms know about all of their bonds and if they break
if (force->newton_bond)
error->all(FLERR, "Without overlay/pair, BPM bond styles require Newton bond off");
// special lj must be 0 1 1 to censor pair forces between bonded particles
// special coulomb must be 1 1 1 to ensure all pairs are included in the
// neighbor list and 1-3 and 1-4 special bond lists are skipped
if (force->special_lj[1] != 0.0 || force->special_lj[2] != 1.0 || force->special_lj[3] != 1.0)
error->all(FLERR,
"Without overlay/pair, BPM bond sytles requires special LJ weights = 0,1,1");
if (force->special_coul[1] != 1.0 || force->special_coul[2] != 1.0 ||
force->special_coul[3] != 1.0)
error->all(FLERR,
"Without overlay/pair, BPM bond sytles requires special Coulomb weights = 1,1,1");
if (id_fix_dummy) {
id_fix_update = utils::strdup("BPM_UPDATE_SPECIAL_BONDS");
fix_update_special_bonds = dynamic_cast<FixUpdateSpecialBonds *>(modify->replace_fix(
id_fix_dummy, fmt::format("{} all UPDATE_SPECIAL_BONDS", id_fix_update), 1));
delete[] id_fix_dummy;
id_fix_dummy = nullptr;
}
}
if (force->angle || force->dihedral || force->improper)
error->all(FLERR, "Bond style bpm cannot be used with 3,4-body interactions");
if (atom->molecular == 2)
error->all(FLERR, "Bond style bpm cannot be used with atom style template");
// special 1-3 and 1-4 weights must be 1 to prevent building 1-3 and 1-4 special bond lists
if (force->special_lj[2] != 1.0 || force->special_lj[3] != 1.0 || force->special_coul[2] != 1.0 ||
force->special_coul[3] != 1.0)
error->all(FLERR, "Bond style bpm requires 1-3 and 1-4 special weights of 1.0");
}
/* ----------------------------------------------------------------------
global settings
All args before store/local command are saved for potential args
for specific bond BPM substyles
All args after optional store/local command are variables stored
in the compute store/local
------------------------------------------------------------------------- */
void BondBPM::settings(int narg, char **arg)
{
leftover_iarg.clear();
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg], "store/local") == 0) {
nvalues = 0;
id_fix_store_local = utils::strdup(arg[iarg + 1]);
store_local_freq = utils::inumeric(FLERR, arg[iarg + 2], false, lmp);
pack_choice = new FnPtrPack[narg - iarg - 1];
iarg += 3;
while (iarg < narg) {
if (strcmp(arg[iarg], "id1") == 0) {
pack_choice[nvalues++] = &BondBPM::pack_id1;
} else if (strcmp(arg[iarg], "id2") == 0) {
pack_choice[nvalues++] = &BondBPM::pack_id2;
} else if (strcmp(arg[iarg], "time") == 0) {
pack_choice[nvalues++] = &BondBPM::pack_time;
} else if (strcmp(arg[iarg], "x") == 0) {
pack_choice[nvalues++] = &BondBPM::pack_x;
} else if (strcmp(arg[iarg], "y") == 0) {
pack_choice[nvalues++] = &BondBPM::pack_y;
} else if (strcmp(arg[iarg], "z") == 0) {
pack_choice[nvalues++] = &BondBPM::pack_z;
} else if (strcmp(arg[iarg], "x/ref") == 0) {
pack_choice[nvalues++] = &BondBPM::pack_x_ref;
prop_atom_flag = 1;
} else if (strcmp(arg[iarg], "y/ref") == 0) {
pack_choice[nvalues++] = &BondBPM::pack_y_ref;
prop_atom_flag = 1;
} else if (strcmp(arg[iarg], "z/ref") == 0) {
pack_choice[nvalues++] = &BondBPM::pack_z_ref;
prop_atom_flag = 1;
} else {
break;
}
iarg++;
}
} else if (strcmp(arg[iarg], "overlay/pair") == 0) {
overlay_flag = 1;
iarg++;
} else {
leftover_iarg.push_back(iarg);
iarg++;
}
}
if (id_fix_store_local) {
if (nvalues == 0)
error->all(FLERR, "Storing local data must include at least one value to output");
memory->create(output_data, nvalues, "bond/bpm:output_data");
auto ifix = modify->get_fix_by_id(id_fix_store_local);
if (!ifix)
ifix = modify->add_fix(
fmt::format("{} all STORE_LOCAL {} {}", id_fix_store_local, store_local_freq, nvalues));
fix_store_local = dynamic_cast<FixStoreLocal *>(ifix);
// Use property/atom to save reference positions as it can transfer to ghost atoms
// This won't work for instances where bonds are added (e.g. fix pour) but in those cases
// a reference state isn't well defined
if (prop_atom_flag == 1) {
id_fix_prop_atom = utils::strdup("BPM_property_atom");
char *x_ref_id = utils::strdup("BPM_X_REF");
char *y_ref_id = utils::strdup("BPM_Y_REF");
char *z_ref_id = utils::strdup("BPM_Z_REF");
ifix = modify->get_fix_by_id(id_fix_prop_atom);
if (!ifix)
ifix = modify->add_fix(fmt::format("{} all property/atom {} {} {} ghost yes",
id_fix_prop_atom, x_ref_id, y_ref_id, z_ref_id));
int type_flag;
int col_flag;
index_x_ref = atom->find_custom(x_ref_id, type_flag, col_flag);
index_y_ref = atom->find_custom(y_ref_id, type_flag, col_flag);
index_z_ref = atom->find_custom(z_ref_id, type_flag, col_flag);
delete[] x_ref_id;
delete[] y_ref_id;
delete[] z_ref_id;
if (ifix->restart_reset) {
ifix->restart_reset = 0;
} else {
double *x_ref = atom->dvector[index_x_ref];
double *y_ref = atom->dvector[index_y_ref];
double *z_ref = atom->dvector[index_z_ref];
double **x = atom->x;
for (int i = 0; i < atom->nlocal; i++) {
x_ref[i] = x[i][0];
y_ref[i] = x[i][1];
z_ref[i] = x[i][2];
}
}
}
}
}
/* ----------------------------------------------------------------------
used to check bond communiction cutoff - not perfect, estimates based on local-local only
------------------------------------------------------------------------- */
double BondBPM::equilibrium_distance(int /*i*/)
{
// Ghost atoms may not yet be communicated, this may only be an estimate
if (r0_max_estimate == 0) {
int type, j;
double delx, dely, delz, r;
double **x = atom->x;
for (int i = 0; i < atom->nlocal; i++) {
for (int m = 0; m < atom->num_bond[i]; m++) {
type = atom->bond_type[i][m];
if (type == 0) continue;
j = atom->map(atom->bond_atom[i][m]);
if (j == -1) continue;
delx = x[i][0] - x[j][0];
dely = x[i][1] - x[j][1];
delz = x[i][2] - x[j][2];
domain->minimum_image(delx, dely, delz);
r = sqrt(delx * delx + dely * dely + delz * delz);
if (r > r0_max_estimate) r0_max_estimate = r;
}
}
double temp;
MPI_Allreduce(&r0_max_estimate, &temp, 1, MPI_DOUBLE, MPI_MAX, world);
r0_max_estimate = temp;
}
// Divide out heuristic prefactor added in comm class
return max_stretch * r0_max_estimate / 1.5;
}
/* ---------------------------------------------------------------------- */
void BondBPM::process_broken(int i, int j)
{
if (fix_store_local) {
for (int n = 0; n < nvalues; n++) (this->*pack_choice[n])(n, i, j);
fix_store_local->add_data(output_data, i, j);
}
if (fix_update_special_bonds) fix_update_special_bonds->add_broken_bond(i, j);
// Manually search and remove from atom arrays
// need to remove in case special bonds arrays rebuilt
int m, n;
int nlocal = atom->nlocal;
tagint *tag = atom->tag;
tagint **bond_atom = atom->bond_atom;
int **bond_type = atom->bond_type;
int *num_bond = atom->num_bond;
if (i < nlocal) {
for (m = 0; m < num_bond[i]; m++) {
if (bond_atom[i][m] == tag[j]) {
bond_type[i][m] = 0;
n = num_bond[i];
bond_type[i][m] = bond_type[i][n - 1];
bond_atom[i][m] = bond_atom[i][n - 1];
fix_bond_history->shift_history(i, m, n - 1);
fix_bond_history->delete_history(i, n - 1);
num_bond[i]--;
break;
}
}
}
if (j < nlocal) {
for (m = 0; m < num_bond[j]; m++) {
if (bond_atom[j][m] == tag[i]) {
bond_type[j][m] = 0;
n = num_bond[j];
bond_type[j][m] = bond_type[j][n - 1];
bond_atom[j][m] = bond_atom[j][n - 1];
fix_bond_history->shift_history(j, m, n - 1);
fix_bond_history->delete_history(j, n - 1);
num_bond[j]--;
break;
}
}
}
}
/* ----------------------------------------------------------------------
one method for every keyword bond bpm can output
the atom property is packed into array or vector
------------------------------------------------------------------------- */
void BondBPM::pack_id1(int n, int i, int /*j*/)
{
tagint *tag = atom->tag;
output_data[n] = tag[i];
}
/* ---------------------------------------------------------------------- */
void BondBPM::pack_id2(int n, int /*i*/, int j)
{
tagint *tag = atom->tag;
output_data[n] = tag[j];
}
/* ---------------------------------------------------------------------- */
void BondBPM::pack_time(int n, int /*i*/, int /*j*/)
{
bigint time = update->ntimestep;
output_data[n] = time;
}
/* ---------------------------------------------------------------------- */
void BondBPM::pack_x(int n, int i, int j)
{
double **x = atom->x;
output_data[n] = (x[i][0] + x[j][0]) * 0.5;
}
/* ---------------------------------------------------------------------- */
void BondBPM::pack_y(int n, int i, int j)
{
double **x = atom->x;
output_data[n] = (x[i][1] + x[j][1]) * 0.5;
}
/* ---------------------------------------------------------------------- */
void BondBPM::pack_z(int n, int i, int j)
{
double **x = atom->x;
output_data[n] = (x[i][2] + x[j][2]) * 0.5;
}
/* ---------------------------------------------------------------------- */
void BondBPM::pack_x_ref(int n, int i, int j)
{
double *x = atom->dvector[index_x_ref];
output_data[n] = (x[i] + x[j]) * 0.5;
}
/* ---------------------------------------------------------------------- */
void BondBPM::pack_y_ref(int n, int i, int j)
{
double *y = atom->dvector[index_y_ref];
output_data[n] = (y[i] + y[j]) * 0.5;
}
/* ---------------------------------------------------------------------- */
void BondBPM::pack_z_ref(int n, int i, int j)
{
double *z = atom->dvector[index_z_ref];
output_data[n] = (z[i] + z[j]) * 0.5;
}

98
src/BPM/bond_bpm.h Normal file
View File

@ -0,0 +1,98 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, 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.
------------------------------------------------------------------------- */
#ifndef LMP_BOND_BPM_H
#define LMP_BOND_BPM_H
#include "bond.h"
#include <vector>
namespace LAMMPS_NS {
class BondBPM : public Bond {
public:
BondBPM(class LAMMPS *);
~BondBPM() override;
void compute(int, int) override = 0;
void coeff(int, char **) override = 0;
void init_style() override;
void settings(int, char **) override;
double equilibrium_distance(int) override;
void write_restart(FILE *) override{};
void read_restart(FILE *) override{};
void write_data(FILE *) override{};
double single(int, double, int, int, double &) override = 0;
protected:
double r0_max_estimate;
double max_stretch;
int store_local_freq;
std::vector<int> leftover_iarg;
char *id_fix_dummy, *id_fix_dummy2;
char *id_fix_update, *id_fix_bond_history;
char *id_fix_store_local, *id_fix_prop_atom;
class FixStoreLocal *fix_store_local;
class FixBondHistory *fix_bond_history;
class FixUpdateSpecialBonds *fix_update_special_bonds;
void process_broken(int, int);
typedef void (BondBPM::*FnPtrPack)(int, int, int);
FnPtrPack *pack_choice; // ptrs to pack functions
double *output_data;
int prop_atom_flag, nvalues, overlay_flag;
int index_x_ref, index_y_ref, index_z_ref;
void pack_id1(int, int, int);
void pack_id2(int, int, int);
void pack_time(int, int, int);
void pack_x(int, int, int);
void pack_y(int, int, int);
void pack_z(int, int, int);
void pack_x_ref(int, int, int);
void pack_y_ref(int, int, int);
void pack_z_ref(int, int, int);
};
} // namespace LAMMPS_NS
#endif
/* ERROR/WARNING messages:
E: Cannot find fix store/local
Fix id cannot be found.
E: Illegal bond_style command
Self-explanatory.
E: Bond style bpm must include at least one value to output
Must include at least one bond property to store in fix store/local
E: Bond style bpm cannot be used with 3,4-body interactions
No angle, dihedral, or improper styles can be defined when using
bond style bpm.
E: Bond style bpm cannot be used with atom style template
This bond style can change the bond topology which is not
allowed with this atom style.
*/

View File

@ -0,0 +1,796 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, 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.
------------------------------------------------------------------------- */
#include "bond_bpm_rotational.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "error.h"
#include "fix_bond_history.h"
#include "force.h"
#include "math_const.h"
#include "math_extra.h"
#include "memory.h"
#include "modify.h"
#include "neighbor.h"
#include <cmath>
#define EPSILON 1e-10
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
BondBPMRotational::BondBPMRotational(LAMMPS *_lmp) : BondBPM(_lmp)
{
Kr = nullptr;
Ks = nullptr;
Kt = nullptr;
Kb = nullptr;
Fcr = nullptr;
Fcs = nullptr;
Tct = nullptr;
Tcb = nullptr;
gnorm = nullptr;
gslide = nullptr;
groll = nullptr;
gtwist = nullptr;
partial_flag = 1;
smooth_flag = 1;
}
/* ---------------------------------------------------------------------- */
BondBPMRotational::~BondBPMRotational()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(Kr);
memory->destroy(Ks);
memory->destroy(Kt);
memory->destroy(Kb);
memory->destroy(Fcr);
memory->destroy(Fcs);
memory->destroy(Tct);
memory->destroy(Tcb);
memory->destroy(gnorm);
memory->destroy(gslide);
memory->destroy(groll);
memory->destroy(gtwist);
}
}
/* ---------------------------------------------------------------------- */
double BondBPMRotational::acos_limit(double c)
{
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
return acos(c);
}
/* ----------------------------------------------------------------------
Store data for a single bond - if bond added after LAMMPS init (e.g. pour)
------------------------------------------------------------------------- */
double BondBPMRotational::store_bond(int n, int i, int j)
{
double delx, dely, delz, r, rinv;
double **x = atom->x;
tagint *tag = atom->tag;
double **bondstore = fix_bond_history->bondstore;
if (tag[i] < tag[j]) {
delx = x[i][0] - x[j][0];
dely = x[i][1] - x[j][1];
delz = x[i][2] - x[j][2];
} else {
delx = x[j][0] - x[i][0];
dely = x[j][1] - x[i][1];
delz = x[j][2] - x[i][2];
}
r = sqrt(delx * delx + dely * dely + delz * delz);
rinv = 1.0 / r;
bondstore[n][0] = r;
bondstore[n][1] = delx * rinv;
bondstore[n][2] = dely * rinv;
bondstore[n][3] = delz * rinv;
if (i < atom->nlocal) {
for (int m = 0; m < atom->num_bond[i]; m++) {
if (atom->bond_atom[i][m] == tag[j]) {
fix_bond_history->update_atom_value(i, m, 0, r);
fix_bond_history->update_atom_value(i, m, 1, delx * rinv);
fix_bond_history->update_atom_value(i, m, 2, dely * rinv);
fix_bond_history->update_atom_value(i, m, 3, delz * rinv);
}
}
}
if (j < atom->nlocal) {
for (int m = 0; m < atom->num_bond[j]; m++) {
if (atom->bond_atom[j][m] == tag[i]) {
fix_bond_history->update_atom_value(j, m, 0, r);
fix_bond_history->update_atom_value(j, m, 1, delx * rinv);
fix_bond_history->update_atom_value(j, m, 2, dely * rinv);
fix_bond_history->update_atom_value(j, m, 3, delz * rinv);
}
}
}
return r;
}
/* ----------------------------------------------------------------------
Store data for all bonds called once
------------------------------------------------------------------------- */
void BondBPMRotational::store_data()
{
int i, j, m, type;
double delx, dely, delz, r, rinv;
double **x = atom->x;
int **bond_type = atom->bond_type;
tagint *tag = atom->tag;
for (i = 0; i < atom->nlocal; i++) {
for (m = 0; m < atom->num_bond[i]; m++) {
type = bond_type[i][m];
//Skip if bond was turned off
if (type < 0) continue;
// map to find index n for tag
j = atom->map(atom->bond_atom[i][m]);
if (j == -1) error->one(FLERR, "Atom missing in BPM bond");
// Save orientation as pointing towards small tag
if (tag[i] < tag[j]) {
delx = x[i][0] - x[j][0];
dely = x[i][1] - x[j][1];
delz = x[i][2] - x[j][2];
} else {
delx = x[j][0] - x[i][0];
dely = x[j][1] - x[i][1];
delz = x[j][2] - x[i][2];
}
// Get closest image in case bonded with ghost
domain->minimum_image(delx, dely, delz);
r = sqrt(delx * delx + dely * dely + delz * delz);
rinv = 1.0 / r;
fix_bond_history->update_atom_value(i, m, 0, r);
fix_bond_history->update_atom_value(i, m, 1, delx * rinv);
fix_bond_history->update_atom_value(i, m, 2, dely * rinv);
fix_bond_history->update_atom_value(i, m, 3, delz * rinv);
}
}
fix_bond_history->post_neighbor();
}
/* ----------------------------------------------------------------------
Calculate forces using formulation in:
1) Y. Wang Acta Geotechnica 2009
2) P. Mora & Y. Wang Advances in Geomcomputing 2009
---------------------------------------------------------------------- */
double BondBPMRotational::elastic_forces(int i1, int i2, int type, double &Fr, double r_mag,
double r0_mag, double r_mag_inv, double * /*rhat*/,
double *r, double *r0, double *force1on2,
double *torque1on2, double *torque2on1)
{
double breaking, temp, r0_dot_rb, c, gamma;
double psi, theta, cos_phi, sin_phi;
double mag_in_plane, mag_out_plane;
double Fs_mag, Tt_mag, Tb_mag;
double q1[4], q2[4];
double q2inv[4], mq[4], mqinv[4], qp21[4], q21[4], qtmp[4];
double rb[3], rb_x_r0[3], s[3], t[3];
double Fs[3], Fsp[3], F_rot[3], Ftmp[3];
double Ts[3], Tb[3], Tt[3], Tbp[3], Ttp[3], Tsp[3], T_rot[3], Ttmp[3];
double **quat = atom->quat;
q1[0] = quat[i1][0];
q1[1] = quat[i1][1];
q1[2] = quat[i1][2];
q1[3] = quat[i1][3];
q2[0] = quat[i2][0];
q2[1] = quat[i2][1];
q2[2] = quat[i2][2];
q2[3] = quat[i2][3];
// Calculate normal forces, rb = bond vector in particle 1's frame
MathExtra::qconjugate(q2, q2inv);
MathExtra::quatrotvec(q2inv, r, rb);
Fr = Kr[type] * (r_mag - r0_mag);
MathExtra::scale3(Fr * r_mag_inv, rb, F_rot);
// Calculate forces due to tangential displacements (no rotation)
r0_dot_rb = MathExtra::dot3(r0, rb);
c = r0_dot_rb * r_mag_inv / r0_mag;
gamma = acos_limit(c);
MathExtra::cross3(rb, r0, rb_x_r0);
MathExtra::cross3(rb, rb_x_r0, s);
MathExtra::norm3(s);
MathExtra::scale3(Ks[type] * r_mag * gamma, s, Fs);
// Calculate torque due to tangential displacements
MathExtra::cross3(r0, rb, t);
MathExtra::norm3(t);
MathExtra::scale3(0.5 * r_mag * Ks[type] * r_mag * gamma, t, Ts);
// Relative rotation force/torque
// Use representation of X'Y'Z' rotations from Wang, Mora 2009
temp = r_mag + rb[2];
if (temp < 0.0) temp = 0.0;
mq[0] = sqrt(2) * 0.5 * sqrt(temp * r_mag_inv);
temp = sqrt(rb[0] * rb[0] + rb[1] * rb[1]);
if (temp != 0.0) {
mq[1] = -sqrt(2) * 0.5 / temp;
temp = r_mag - rb[2];
if (temp < 0.0) temp = 0.0;
mq[1] *= sqrt(temp * r_mag_inv);
mq[2] = -mq[1];
mq[1] *= rb[1];
mq[2] *= rb[0];
} else {
// If aligned along z axis, x,y terms zero (r_mag-rb[2] = 0)
mq[1] = 0.0;
mq[2] = 0.0;
}
mq[3] = 0.0;
// qp21 = opposite of r^\circ_21 in Wang
// q21 = opposite of r_21 in Wang
MathExtra::quatquat(q2inv, q1, qp21);
MathExtra::qconjugate(mq, mqinv);
MathExtra::quatquat(mqinv, qp21, qtmp);
MathExtra::quatquat(qtmp, mq, q21);
temp = sqrt(q21[0] * q21[0] + q21[3] * q21[3]);
if (temp != 0.0) {
c = q21[0] / temp;
psi = 2.0 * acos_limit(c);
} else {
c = 0.0;
psi = 0.0;
}
// Map negative rotations
if (q21[3] < 0.0) // sin = q21[3]/temp
psi = -psi;
if (q21[3] == 0.0) psi = 0.0;
c = q21[0] * q21[0] - q21[1] * q21[1] - q21[2] * q21[2] + q21[3] * q21[3];
theta = acos_limit(c);
// Separately calculte magnitude of quaternion in x-y and out of x-y planes
// to avoid dividing by zero
mag_out_plane = (q21[0] * q21[0] + q21[3] * q21[3]);
mag_in_plane = (q21[1] * q21[1] + q21[2] * q21[2]);
if (mag_in_plane == 0.0) {
// No rotation => no bending/shear torque or extra shear force
// achieve by setting cos/sin = 0
cos_phi = 0.0;
sin_phi = 0.0;
} else if (mag_out_plane == 0.0) {
// Calculate angle in plane
cos_phi = q21[2] / sqrt(mag_in_plane);
sin_phi = -q21[1] / sqrt(mag_in_plane);
} else {
// Default equations in Mora, Wang 2009
cos_phi = q21[1] * q21[3] + q21[0] * q21[2];
sin_phi = q21[2] * q21[3] - q21[0] * q21[1];
cos_phi /= sqrt(mag_out_plane * mag_in_plane);
sin_phi /= sqrt(mag_out_plane * mag_in_plane);
}
Tbp[0] = -Kb[type] * theta * sin_phi;
Tbp[1] = Kb[type] * theta * cos_phi;
Tbp[2] = 0.0;
Ttp[0] = 0.0;
Ttp[1] = 0.0;
Ttp[2] = Kt[type] * psi;
Fsp[0] = -0.5 * Ks[type] * r_mag * theta * cos_phi;
Fsp[1] = -0.5 * Ks[type] * r_mag * theta * sin_phi;
Fsp[2] = 0.0;
Tsp[0] = 0.25 * Ks[type] * r_mag * r_mag * theta * sin_phi;
Tsp[1] = -0.25 * Ks[type] * r_mag * r_mag * theta * cos_phi;
Tsp[2] = 0.0;
// Rotate forces/torques back to 1st particle's frame
MathExtra::quatrotvec(mq, Fsp, Ftmp);
MathExtra::quatrotvec(mq, Tsp, Ttmp);
for (int m = 0; m < 3; m++) {
Fs[m] += Ftmp[m];
Ts[m] += Ttmp[m];
}
MathExtra::quatrotvec(mq, Tbp, Tb);
MathExtra::quatrotvec(mq, Ttp, Tt);
// Sum forces and calculate magnitudes
F_rot[0] += Fs[0];
F_rot[1] += Fs[1];
F_rot[2] += Fs[2];
MathExtra::quatrotvec(q2, F_rot, force1on2);
T_rot[0] = Ts[0] + Tt[0] + Tb[0];
T_rot[1] = Ts[1] + Tt[1] + Tb[1];
T_rot[2] = Ts[2] + Tt[2] + Tb[2];
MathExtra::quatrotvec(q2, T_rot, torque1on2);
T_rot[0] = Ts[0] - Tt[0] - Tb[0];
T_rot[1] = Ts[1] - Tt[1] - Tb[1];
T_rot[2] = Ts[2] - Tt[2] - Tb[2];
MathExtra::quatrotvec(q2, T_rot, torque2on1);
Fs_mag = MathExtra::len3(Fs);
Tt_mag = MathExtra::len3(Tt);
Tb_mag = MathExtra::len3(Tb);
breaking = Fr / Fcr[type] + Fs_mag / Fcs[type] + Tb_mag / Tcb[type] + Tt_mag / Tct[type];
if (breaking < 0.0) breaking = 0.0;
return breaking;
}
/* ----------------------------------------------------------------------
Calculate damping using formulation in
Y. Wang, F. Alonso-Marroquin, W. Guo 2015
Note: n points towards 1 vs pointing towards 2
---------------------------------------------------------------------- */
void BondBPMRotational::damping_forces(int i1, int i2, int type, double &Fr, double *rhat,
double *r, double *force1on2, double *torque1on2,
double *torque2on1)
{
double v1dotr, v2dotr, w1dotr, w2dotr;
double s1[3], s2[3], tdamp[3], tmp[3];
double vn1[3], vn2[3], vt1[3], vt2[3], vroll[3];
double wxn1[3], wxn2[3], wn1[3], wn2[3];
double **v = atom->v;
double **omega = atom->omega;
// Damp normal velocity difference
v1dotr = MathExtra::dot3(v[i1], rhat);
v2dotr = MathExtra::dot3(v[i2], rhat);
MathExtra::scale3(v1dotr, rhat, vn1);
MathExtra::scale3(v2dotr, rhat, vn2);
MathExtra::sub3(vn1, vn2, tmp);
MathExtra::scale3(gnorm[type], tmp);
Fr = MathExtra::lensq3(tmp);
MathExtra::add3(force1on2, tmp, force1on2);
// Damp tangential objective velocities
MathExtra::sub3(v[i1], vn1, vt1);
MathExtra::sub3(v[i2], vn2, vt2);
MathExtra::sub3(vt2, vt1, tmp);
MathExtra::scale3(0.5, tmp);
MathExtra::cross3(omega[i1], r, s1);
MathExtra::scale3(-0.5, s1);
MathExtra::sub3(s1, tmp, s1); // Eq 12
MathExtra::cross3(omega[i2], r, s2);
MathExtra::scale3(0.5, s2);
MathExtra::add3(s2, tmp, s2); // Eq 13
MathExtra::sub3(s1, s2, tmp);
MathExtra::scale3(gslide[type], tmp);
MathExtra::add3(force1on2, tmp, force1on2);
// Apply corresponding torque
MathExtra::cross3(r, tmp, tdamp);
MathExtra::scale3(0.5, tdamp);
MathExtra::add3(torque1on2, tdamp, torque1on2);
MathExtra::add3(torque2on1, tdamp, torque2on1);
// Damp rolling
MathExtra::cross3(omega[i1], rhat, wxn1);
MathExtra::cross3(omega[i2], rhat, wxn2);
MathExtra::sub3(wxn1, wxn2, vroll); // Eq. 31
MathExtra::cross3(r, vroll, tdamp);
MathExtra::scale3(0.5 * groll[type], tdamp);
MathExtra::add3(torque1on2, tdamp, torque1on2);
MathExtra::scale3(-1.0, tdamp);
MathExtra::add3(torque2on1, tdamp, torque2on1);
// Damp twist
w1dotr = MathExtra::dot3(omega[i1], rhat);
w2dotr = MathExtra::dot3(omega[i2], rhat);
MathExtra::scale3(w1dotr, rhat, wn1);
MathExtra::scale3(w2dotr, rhat, wn2);
MathExtra::sub3(wn1, wn2, tdamp); // Eq. 38
MathExtra::scale3(0.5 * gtwist[type], tdamp);
MathExtra::add3(torque1on2, tdamp, torque1on2);
MathExtra::scale3(-1.0, tdamp);
MathExtra::add3(torque2on1, tdamp, torque2on1);
}
/* ---------------------------------------------------------------------- */
void BondBPMRotational::compute(int eflag, int vflag)
{
if (!fix_bond_history->stored_flag) {
fix_bond_history->stored_flag = true;
store_data();
}
int i1, i2, itmp, n, type;
double r[3], r0[3], rhat[3];
double rsq, r0_mag, r_mag, r_mag_inv;
double Fr, breaking, smooth;
double force1on2[3], torque1on2[3], torque2on1[3];
ev_init(eflag, vflag);
double **x = atom->x;
double **f = atom->f;
double **torque = atom->torque;
tagint *tag = atom->tag;
int **bondlist = neighbor->bondlist;
int nbondlist = neighbor->nbondlist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
double **bondstore = fix_bond_history->bondstore;
for (n = 0; n < nbondlist; n++) {
// skip bond if already broken
if (bondlist[n][2] <= 0) continue;
i1 = bondlist[n][0];
i2 = bondlist[n][1];
type = bondlist[n][2];
r0_mag = bondstore[n][0];
// Ensure pair is always ordered such that r0 points in
// a consistent direction and to ensure numerical operations
// are identical to minimize the possibility that a bond straddling
// an mpi grid (newton off) doesn't break on one proc but not the other
if (tag[i2] < tag[i1]) {
itmp = i1;
i1 = i2;
i2 = itmp;
}
// If bond hasn't been set - should be initialized to zero
if (r0_mag < EPSILON || std::isnan(r0_mag)) r0_mag = store_bond(n, i1, i2);
r0[0] = bondstore[n][1];
r0[1] = bondstore[n][2];
r0[2] = bondstore[n][3];
MathExtra::scale3(r0_mag, r0);
// Note this is the reverse of Mora & Wang
MathExtra::sub3(x[i1], x[i2], r);
rsq = MathExtra::lensq3(r);
r_mag = sqrt(rsq);
r_mag_inv = 1.0 / r_mag;
MathExtra::scale3(r_mag_inv, r, rhat);
// ------------------------------------------------------//
// Calculate forces, check if bond breaks
// ------------------------------------------------------//
breaking = elastic_forces(i1, i2, type, Fr, r_mag, r0_mag, r_mag_inv, rhat, r, r0, force1on2,
torque1on2, torque2on1);
if (breaking >= 1.0) {
bondlist[n][2] = 0;
process_broken(i1, i2);
continue;
}
damping_forces(i1, i2, type, Fr, rhat, r, force1on2, torque1on2, torque2on1);
if (smooth_flag) {
smooth = breaking * breaking;
smooth = 1.0 - smooth * smooth;
} else {
smooth = 1.0;
}
// ------------------------------------------------------//
// Apply forces and torques to particles
// ------------------------------------------------------//
if (newton_bond || i1 < nlocal) {
f[i1][0] -= force1on2[0] * smooth;
f[i1][1] -= force1on2[1] * smooth;
f[i1][2] -= force1on2[2] * smooth;
torque[i1][0] += torque2on1[0] * smooth;
torque[i1][1] += torque2on1[1] * smooth;
torque[i1][2] += torque2on1[2] * smooth;
}
if (newton_bond || i2 < nlocal) {
f[i2][0] += force1on2[0] * smooth;
f[i2][1] += force1on2[1] * smooth;
f[i2][2] += force1on2[2] * smooth;
torque[i2][0] += torque1on2[0] * smooth;
torque[i2][1] += torque1on2[1] * smooth;
torque[i2][2] += torque1on2[2] * smooth;
}
if (evflag) ev_tally(i1, i2, nlocal, newton_bond, 0.0, Fr * smooth, r[0], r[1], r[2]);
}
}
/* ---------------------------------------------------------------------- */
void BondBPMRotational::allocate()
{
allocated = 1;
const int np1 = atom->nbondtypes + 1;
memory->create(Kr, np1, "bond:Kr");
memory->create(Ks, np1, "bond:Ks");
memory->create(Kt, np1, "bond:Kt");
memory->create(Kb, np1, "bond:Kb");
memory->create(Fcr, np1, "bond:Fcr");
memory->create(Fcs, np1, "bond:Fcs");
memory->create(Tct, np1, "bond:Tct");
memory->create(Tcb, np1, "bond:Tcb");
memory->create(gnorm, np1, "bond:gnorm");
memory->create(gslide, np1, "bond:gslide");
memory->create(groll, np1, "bond:groll");
memory->create(gtwist, np1, "bond:gtwist");
memory->create(setflag, np1, "bond:setflag");
for (int i = 1; i < np1; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more types
------------------------------------------------------------------------- */
void BondBPMRotational::coeff(int narg, char **arg)
{
if (narg != 13) 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 Kr_one = utils::numeric(FLERR, arg[1], false, lmp);
double Ks_one = utils::numeric(FLERR, arg[2], false, lmp);
double Kt_one = utils::numeric(FLERR, arg[3], false, lmp);
double Kb_one = utils::numeric(FLERR, arg[4], false, lmp);
double Fcr_one = utils::numeric(FLERR, arg[5], false, lmp);
double Fcs_one = utils::numeric(FLERR, arg[6], false, lmp);
double Tct_one = utils::numeric(FLERR, arg[7], false, lmp);
double Tcb_one = utils::numeric(FLERR, arg[8], false, lmp);
double gnorm_one = utils::numeric(FLERR, arg[9], false, lmp);
double gslide_one = utils::numeric(FLERR, arg[10], false, lmp);
double groll_one = utils::numeric(FLERR, arg[11], false, lmp);
double gtwist_one = utils::numeric(FLERR, arg[12], false, lmp);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
Kr[i] = Kr_one;
Ks[i] = Ks_one;
Kt[i] = Kt_one;
Kb[i] = Kb_one;
Fcr[i] = Fcr_one;
Fcs[i] = Fcs_one;
Tct[i] = Tct_one;
Tcb[i] = Tcb_one;
gnorm[i] = gnorm_one;
gslide[i] = gslide_one;
groll[i] = groll_one;
gtwist[i] = gtwist_one;
setflag[i] = 1;
count++;
if (Fcr[i] / Kr[i] > max_stretch) max_stretch = Fcr[i] / Kr[i];
}
if (count == 0) error->all(FLERR, "Incorrect args for bond coefficients");
}
/* ----------------------------------------------------------------------
check for correct settings and create fix
------------------------------------------------------------------------- */
void BondBPMRotational::init_style()
{
BondBPM::init_style();
if (!atom->quat_flag || !atom->sphere_flag)
error->all(FLERR, "Bond bpm/rotational requires atom style bpm/sphere");
if (comm->ghost_velocity == 0)
error->all(FLERR, "Bond bpm/rotational requires ghost atoms store velocity");
if (domain->dimension == 2)
error->warning(FLERR, "Bond style bpm/rotational not intended for 2d use");
if (!id_fix_bond_history) {
id_fix_bond_history = utils::strdup("HISTORY_BPM_ROTATIONAL");
fix_bond_history = dynamic_cast<FixBondHistory *>(modify->replace_fix(
id_fix_dummy2, fmt::format("{} all BOND_HISTORY 0 4", id_fix_bond_history), 1));
delete[] id_fix_dummy2;
id_fix_dummy2 = nullptr;
}
}
/* ---------------------------------------------------------------------- */
void BondBPMRotational::settings(int narg, char **arg)
{
BondBPM::settings(narg, arg);
int iarg;
for (std::size_t i = 0; i < leftover_iarg.size(); i++) {
iarg = leftover_iarg[i];
if (strcmp(arg[iarg], "smooth") == 0) {
if (iarg + 1 > narg) error->all(FLERR, "Illegal bond bpm command");
smooth_flag = utils::logical(FLERR, arg[iarg + 1], false, lmp);
i += 1;
} else {
error->all(FLERR, "Illegal bond_style command");
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void BondBPMRotational::write_restart(FILE *fp)
{
fwrite(&Kr[1], sizeof(double), atom->nbondtypes, fp);
fwrite(&Ks[1], sizeof(double), atom->nbondtypes, fp);
fwrite(&Kt[1], sizeof(double), atom->nbondtypes, fp);
fwrite(&Kb[1], sizeof(double), atom->nbondtypes, fp);
fwrite(&Fcr[1], sizeof(double), atom->nbondtypes, fp);
fwrite(&Fcs[1], sizeof(double), atom->nbondtypes, fp);
fwrite(&Tct[1], sizeof(double), atom->nbondtypes, fp);
fwrite(&Tcb[1], sizeof(double), atom->nbondtypes, fp);
fwrite(&gnorm[1], sizeof(double), atom->nbondtypes, fp);
fwrite(&gslide[1], sizeof(double), atom->nbondtypes, fp);
fwrite(&groll[1], sizeof(double), atom->nbondtypes, fp);
fwrite(&gtwist[1], sizeof(double), atom->nbondtypes, fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void BondBPMRotational::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
utils::sfread(FLERR, &Kr[1], sizeof(double), atom->nbondtypes, fp, nullptr, error);
utils::sfread(FLERR, &Ks[1], sizeof(double), atom->nbondtypes, fp, nullptr, error);
utils::sfread(FLERR, &Kt[1], sizeof(double), atom->nbondtypes, fp, nullptr, error);
utils::sfread(FLERR, &Kb[1], sizeof(double), atom->nbondtypes, fp, nullptr, error);
utils::sfread(FLERR, &Fcr[1], sizeof(double), atom->nbondtypes, fp, nullptr, error);
utils::sfread(FLERR, &Fcs[1], sizeof(double), atom->nbondtypes, fp, nullptr, error);
utils::sfread(FLERR, &Tct[1], sizeof(double), atom->nbondtypes, fp, nullptr, error);
utils::sfread(FLERR, &Tcb[1], sizeof(double), atom->nbondtypes, fp, nullptr, error);
utils::sfread(FLERR, &gnorm[1], sizeof(double), atom->nbondtypes, fp, nullptr, error);
utils::sfread(FLERR, &gslide[1], sizeof(double), atom->nbondtypes, fp, nullptr, error);
utils::sfread(FLERR, &groll[1], sizeof(double), atom->nbondtypes, fp, nullptr, error);
utils::sfread(FLERR, &gtwist[1], sizeof(double), atom->nbondtypes, fp, nullptr, error);
}
MPI_Bcast(&Kr[1], atom->nbondtypes, MPI_DOUBLE, 0, world);
MPI_Bcast(&Ks[1], atom->nbondtypes, MPI_DOUBLE, 0, world);
MPI_Bcast(&Kt[1], atom->nbondtypes, MPI_DOUBLE, 0, world);
MPI_Bcast(&Kb[1], atom->nbondtypes, MPI_DOUBLE, 0, world);
MPI_Bcast(&Fcr[1], atom->nbondtypes, MPI_DOUBLE, 0, world);
MPI_Bcast(&Fcs[1], atom->nbondtypes, MPI_DOUBLE, 0, world);
MPI_Bcast(&Tct[1], atom->nbondtypes, MPI_DOUBLE, 0, world);
MPI_Bcast(&Tcb[1], atom->nbondtypes, MPI_DOUBLE, 0, world);
MPI_Bcast(&gnorm[1], atom->nbondtypes, MPI_DOUBLE, 0, world);
MPI_Bcast(&gslide[1], atom->nbondtypes, MPI_DOUBLE, 0, world);
MPI_Bcast(&groll[1], atom->nbondtypes, MPI_DOUBLE, 0, world);
MPI_Bcast(&gtwist[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 BondBPMRotational::write_data(FILE *fp)
{
for (int i = 1; i <= atom->nbondtypes; i++)
fprintf(fp, "%d %g %g %g %g %g %g %g %g %g %g %g %g\n", i, Kr[i], Ks[i], Kt[i], Kb[i], Fcr[i],
Fcs[i], Tct[i], Tcb[i], gnorm[i], gslide[i], groll[i], gtwist[i]);
}
/* ---------------------------------------------------------------------- */
double BondBPMRotational::single(int type, double rsq, int i, int j, double &fforce)
{
// Not yet enabled
if (type <= 0) return 0.0;
int itmp;
if (atom->tag[j] < atom->tag[i]) {
itmp = i;
i = j;
j = itmp;
}
double r0_mag, r_mag, r_mag_inv;
double r0[3], r[3], rhat[3];
for (int n = 0; n < atom->num_bond[i]; n++) {
if (atom->bond_atom[i][n] == atom->tag[j]) {
r0_mag = fix_bond_history->get_atom_value(i, n, 0);
r0[0] = fix_bond_history->get_atom_value(i, n, 1);
r0[1] = fix_bond_history->get_atom_value(i, n, 2);
r0[2] = fix_bond_history->get_atom_value(i, n, 3);
}
}
double **x = atom->x;
MathExtra::scale3(r0_mag, r0);
MathExtra::sub3(x[i], x[j], r);
r_mag = sqrt(rsq);
r_mag_inv = 1.0 / r_mag;
MathExtra::scale3(r_mag_inv, r, rhat);
double breaking, smooth, Fr;
double force1on2[3], torque1on2[3], torque2on1[3];
breaking = elastic_forces(i, j, type, Fr, r_mag, r0_mag, r_mag_inv, rhat, r, r0, force1on2,
torque1on2, torque2on1);
fforce = Fr;
damping_forces(i, j, type, Fr, rhat, r, force1on2, torque1on2, torque2on1);
fforce += Fr;
if (smooth_flag) {
smooth = breaking * breaking;
smooth = 1.0 - smooth * smooth;
fforce *= smooth;
}
return 0.0;
}

View File

@ -0,0 +1,83 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, 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.
------------------------------------------------------------------------- */
#ifdef BOND_CLASS
// clang-format off
BondStyle(bpm/rotational,BondBPMRotational);
// clang-format on
#else
#ifndef LMP_BOND_BPM_ROTATIONAL_H
#define LMP_BOND_BPM_ROTATIONAL_H
#include "bond_bpm.h"
namespace LAMMPS_NS {
class BondBPMRotational : public BondBPM {
public:
BondBPMRotational(class LAMMPS *);
~BondBPMRotational() override;
void compute(int, int) override;
void coeff(int, char **) override;
void init_style() override;
void settings(int, char **) override;
void write_restart(FILE *) override;
void read_restart(FILE *) override;
void write_data(FILE *) override;
double single(int, double, int, int, double &) override;
protected:
double *Kr, *Ks, *Kt, *Kb, *gnorm, *gslide, *groll, *gtwist;
double *Fcr, *Fcs, *Tct, *Tcb;
int smooth_flag;
double acos_limit(double);
double elastic_forces(int, int, int, double &, double, double, double, double *, double *,
double *, double *, double *, double *);
void damping_forces(int, int, int, double &, double *, double *, double *, double *, double *);
void allocate();
void store_data();
double store_bond(int, int, int);
};
} // namespace LAMMPS_NS
#endif
#endif
/* ERROR/WARNING messages:
E: Atom missing in BPM bond
Bonded atom cannot be found
E: Incorrect args for bond coefficients
Self-explanatory. Check the input script or data file.
E: Bond bpm/rotational requires atom style bpm/sphere
Self-explanatory.
E: Bond style bpm requires 1-3 and 1-4 special weights of 1.0
Self-explanatory.
W: Bond style bpm/rotational not intended for 2d use, may be inefficient
This bond style will perform a lot of unnecessary calculations in 2d
*/

380
src/BPM/bond_bpm_spring.cpp Normal file
View File

@ -0,0 +1,380 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, 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.
------------------------------------------------------------------------- */
#include "bond_bpm_spring.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "error.h"
#include "fix_bond_history.h"
#include "force.h"
#include "memory.h"
#include "modify.h"
#include "neighbor.h"
#define EPSILON 1e-10
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
BondBPMSpring::BondBPMSpring(LAMMPS *_lmp) : BondBPM(_lmp), k(nullptr), ecrit(nullptr), gamma(nullptr)
{
partial_flag = 1;
smooth_flag = 1;
}
/* ---------------------------------------------------------------------- */
BondBPMSpring::~BondBPMSpring()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
memory->destroy(ecrit);
memory->destroy(gamma);
}
}
/* ----------------------------------------------------------------------
Store data for a single bond - if bond added after LAMMPS init (e.g. pour)
------------------------------------------------------------------------- */
double BondBPMSpring::store_bond(int n, int i, int j)
{
double delx, dely, delz, r;
double **x = atom->x;
double **bondstore = fix_bond_history->bondstore;
tagint *tag = atom->tag;
delx = x[i][0] - x[j][0];
dely = x[i][1] - x[j][1];
delz = x[i][2] - x[j][2];
r = sqrt(delx * delx + dely * dely + delz * delz);
bondstore[n][0] = r;
if (i < atom->nlocal) {
for (int m = 0; m < atom->num_bond[i]; m++) {
if (atom->bond_atom[i][m] == tag[j]) { fix_bond_history->update_atom_value(i, m, 0, r); }
}
}
if (j < atom->nlocal) {
for (int m = 0; m < atom->num_bond[j]; m++) {
if (atom->bond_atom[j][m] == tag[i]) { fix_bond_history->update_atom_value(j, m, 0, r); }
}
}
return r;
}
/* ----------------------------------------------------------------------
Store data for all bonds called once
------------------------------------------------------------------------- */
void BondBPMSpring::store_data()
{
int i, j, m, type;
double delx, dely, delz, r;
double **x = atom->x;
int **bond_type = atom->bond_type;
for (i = 0; i < atom->nlocal; i++) {
for (m = 0; m < atom->num_bond[i]; m++) {
type = bond_type[i][m];
//Skip if bond was turned off
if (type < 0) continue;
// map to find index n
j = atom->map(atom->bond_atom[i][m]);
if (j == -1) error->one(FLERR, "Atom missing in BPM bond");
delx = x[i][0] - x[j][0];
dely = x[i][1] - x[j][1];
delz = x[i][2] - x[j][2];
// Get closest image in case bonded with ghost
domain->minimum_image(delx, dely, delz);
r = sqrt(delx * delx + dely * dely + delz * delz);
fix_bond_history->update_atom_value(i, m, 0, r);
}
}
fix_bond_history->post_neighbor();
}
/* ---------------------------------------------------------------------- */
void BondBPMSpring::compute(int eflag, int vflag)
{
if (!fix_bond_history->stored_flag) {
fix_bond_history->stored_flag = true;
store_data();
}
int i1, i2, itmp, n, type;
double delx, dely, delz, delvx, delvy, delvz;
double e, rsq, r, r0, rinv, smooth, fbond, dot;
ev_init(eflag, vflag);
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
tagint *tag = atom->tag;
int **bondlist = neighbor->bondlist;
int nbondlist = neighbor->nbondlist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
double **bondstore = fix_bond_history->bondstore;
for (n = 0; n < nbondlist; n++) {
// skip bond if already broken
if (bondlist[n][2] <= 0) continue;
i1 = bondlist[n][0];
i2 = bondlist[n][1];
type = bondlist[n][2];
r0 = bondstore[n][0];
// Ensure pair is always ordered to ensure numerical operations
// are identical to minimize the possibility that a bond straddling
// an mpi grid (newton off) doesn't break on one proc but not the other
if (tag[i2] < tag[i1]) {
itmp = i1;
i1 = i2;
i2 = itmp;
}
// If bond hasn't been set - should be initialized to zero
if (r0 < EPSILON || std::isnan(r0)) r0 = store_bond(n, i1, i2);
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);
e = (r - r0) / r0;
if (fabs(e) > ecrit[type]) {
bondlist[n][2] = 0;
process_broken(i1, i2);
continue;
}
rinv = 1.0 / r;
fbond = k[type] * (r0 - r);
delvx = v[i1][0] - v[i2][0];
delvy = v[i1][1] - v[i2][1];
delvz = v[i1][2] - v[i2][2];
dot = delx * delvx + dely * delvy + delz * delvz;
fbond -= gamma[type] * dot * rinv;
fbond *= rinv;
if (smooth_flag) {
smooth = (r - r0) / (r0 * ecrit[type]);
smooth *= smooth;
smooth *= smooth;
smooth *= smooth;
smooth = 1 - smooth;
fbond *= smooth;
}
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, 0.0, fbond, delx, dely, delz);
}
}
/* ---------------------------------------------------------------------- */
void BondBPMSpring::allocate()
{
allocated = 1;
const int np1 = atom->nbondtypes + 1;
memory->create(k, np1, "bond:k");
memory->create(ecrit, np1, "bond:ecrit");
memory->create(gamma, np1, "bond:gamma");
memory->create(setflag, np1, "bond:setflag");
for (int i = 1; i < np1; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more types
------------------------------------------------------------------------- */
void BondBPMSpring::coeff(int narg, char **arg)
{
if (narg != 4) 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);
double ecrit_one = utils::numeric(FLERR, arg[2], false, lmp);
double gamma_one = utils::numeric(FLERR, arg[3], false, lmp);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = k_one;
ecrit[i] = ecrit_one;
gamma[i] = gamma_one;
setflag[i] = 1;
count++;
if (1.0 + ecrit[i] > max_stretch) max_stretch = 1.0 + ecrit[i];
}
if (count == 0) error->all(FLERR, "Incorrect args for bond coefficients");
}
/* ----------------------------------------------------------------------
check for correct settings and create fix
------------------------------------------------------------------------- */
void BondBPMSpring::init_style()
{
BondBPM::init_style();
if (comm->ghost_velocity == 0)
error->all(FLERR, "Bond bpm/spring requires ghost atoms store velocity");
if (!id_fix_bond_history) {
id_fix_bond_history = utils::strdup("HISTORY_BPM_SPRING");
fix_bond_history = dynamic_cast<FixBondHistory *>(modify->replace_fix(
id_fix_dummy2, fmt::format("{} all BOND_HISTORY 0 1", id_fix_bond_history), 1));
delete[] id_fix_dummy2;
id_fix_dummy2 = nullptr;
}
}
/* ---------------------------------------------------------------------- */
void BondBPMSpring::settings(int narg, char **arg)
{
BondBPM::settings(narg, arg);
int iarg;
for (std::size_t i = 0; i < leftover_iarg.size(); i++) {
iarg = leftover_iarg[i];
if (strcmp(arg[iarg], "smooth") == 0) {
if (iarg + 1 > narg) error->all(FLERR, "Illegal bond bpm command");
smooth_flag = utils::logical(FLERR, arg[iarg + 1], false, lmp);
i += 1;
} else {
error->all(FLERR, "Illegal bond_style command");
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void BondBPMSpring::write_restart(FILE *fp)
{
fwrite(&k[1], sizeof(double), atom->nbondtypes, fp);
fwrite(&ecrit[1], sizeof(double), atom->nbondtypes, fp);
fwrite(&gamma[1], sizeof(double), atom->nbondtypes, fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void BondBPMSpring::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
utils::sfread(FLERR, &k[1], sizeof(double), atom->nbondtypes, fp, nullptr, error);
utils::sfread(FLERR, &ecrit[1], sizeof(double), atom->nbondtypes, fp, nullptr, error);
utils::sfread(FLERR, &gamma[1], sizeof(double), atom->nbondtypes, fp, nullptr, error);
}
MPI_Bcast(&k[1], atom->nbondtypes, MPI_DOUBLE, 0, world);
MPI_Bcast(&ecrit[1], atom->nbondtypes, MPI_DOUBLE, 0, world);
MPI_Bcast(&gamma[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 BondBPMSpring::write_data(FILE *fp)
{
for (int i = 1; i <= atom->nbondtypes; i++)
fprintf(fp, "%d %g %g %g\n", i, k[i], ecrit[i], gamma[i]);
}
/* ---------------------------------------------------------------------- */
double BondBPMSpring::single(int type, double rsq, int i, int j, double &fforce)
{
if (type <= 0) return 0.0;
double r0;
for (int n = 0; n < atom->num_bond[i]; n++) {
if (atom->bond_atom[i][n] == atom->tag[j]) r0 = fix_bond_history->get_atom_value(i, n, 0);
}
double r = sqrt(rsq);
double rinv = 1.0 / r;
fforce = k[type] * (r0 - r);
double **x = atom->x;
double **v = atom->v;
double delx = x[i][0] - x[j][0];
double dely = x[i][1] - x[j][1];
double delz = x[i][2] - x[j][2];
double delvx = v[i][0] - v[j][0];
double delvy = v[i][1] - v[j][1];
double delvz = v[i][2] - v[j][2];
double dot = delx * delvx + dely * delvy + delz * delvz;
fforce -= gamma[type] * dot * rinv;
fforce *= rinv;
if (smooth_flag) {
double smooth = (r - r0) / (r0 * ecrit[type]);
smooth *= smooth;
smooth *= smooth;
smooth *= smooth;
smooth = 1 - smooth;
fforce *= smooth;
}
return 0.0;
}

68
src/BPM/bond_bpm_spring.h Normal file
View File

@ -0,0 +1,68 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, 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.
------------------------------------------------------------------------- */
#ifdef BOND_CLASS
// clang-format off
BondStyle(bpm/spring,BondBPMSpring);
// clang-format on
#else
#ifndef LMP_BOND_BPM_SPRING_H
#define LMP_BOND_BPM_SPRING_H
#include "bond_bpm.h"
namespace LAMMPS_NS {
class BondBPMSpring : public BondBPM {
public:
BondBPMSpring(class LAMMPS *);
~BondBPMSpring() override;
void compute(int, int) override;
void coeff(int, char **) override;
void init_style() override;
void settings(int, char **) override;
void write_restart(FILE *) override;
void read_restart(FILE *) override;
void write_data(FILE *) override;
double single(int, double, int, int, double &) override;
protected:
double *k, *ecrit, *gamma;
int smooth_flag;
void allocate();
void store_data();
double store_bond(int, int, int);
};
} // namespace LAMMPS_NS
#endif
#endif
/* ERROR/WARNING messages:
E: Atom missing in BPM bond
Bonded atom cannot be found
E: Incorrect args for bond coefficients
Self-explanatory. Check the input script or data file.
E: Bond style bpm requires 1-3 and 1-4 special weights of 1.0
Self-explanatory.
*/

View File

@ -0,0 +1,145 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, 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.
------------------------------------------------------------------------- */
#include "compute_nbond_atom.h"
#include "atom.h"
#include "comm.h"
#include "error.h"
#include "force.h"
#include "memory.h"
#include "update.h"
#include <string.h>
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeNBondAtom::ComputeNBondAtom(LAMMPS *_lmp, int narg, char **arg) :
Compute(_lmp, narg, arg), nbond(nullptr)
{
if (narg < 3) error->all(FLERR, "Illegal compute nbond/atom command");
peratom_flag = 1;
size_peratom_cols = 0;
peatomflag = 1;
timeflag = 1;
comm_reverse = 1;
nmax = 0;
}
/* ---------------------------------------------------------------------- */
ComputeNBondAtom::~ComputeNBondAtom()
{
memory->destroy(nbond);
}
/* ---------------------------------------------------------------------- */
void ComputeNBondAtom::compute_peratom()
{
invoked_peratom = update->ntimestep;
if (update->eflag_atom != invoked_peratom)
error->all(FLERR, "Per-atom nbond was not tallied on needed timestep");
// grow local nbond array if necessary
// needs to be atom->nmax in length
if (atom->nmax > nmax) {
memory->destroy(nbond);
nmax = atom->nmax;
memory->create(nbond, nmax, "nbond/atom:nbond");
vector_atom = nbond;
}
// npair includes ghosts if either newton flag is set
// b/c some bonds/dihedrals call pair::ev_tally with pairwise info
// nbond includes ghosts if newton_bond is set
// ntotal includes ghosts if either newton flag is set
// KSpace includes ghosts if tip4pflag is set
int nlocal = atom->nlocal;
tagint **bond_atom = atom->bond_atom;
int **bond_type = atom->bond_type;
int ntotal = nlocal;
if (force->newton) ntotal += atom->nghost;
// set local nbond array
int i, j, k;
int *num_bond = atom->num_bond;
int newton_bond = force->newton_bond;
for (i = 0; i < ntotal; i++) nbond[i] = 0;
for (i = 0; i < nlocal; i++) {
for (j = 0; j < num_bond[i]; j++) {
if (bond_type[i][j] <= 0) continue;
k = atom->map(bond_atom[i][j]);
if (k < 0) continue;
nbond[i] += 1;
if (newton_bond) nbond[k] += 1;
}
}
// communicate ghost nbond between neighbor procs
if (force->newton) comm->reverse_comm(this);
// zero nbond of atoms not in group
// only do this after comm since ghost contributions must be included
int *mask = atom->mask;
for (i = 0; i < nlocal; i++)
if (!(mask[i] & groupbit)) nbond[i] = 0.0;
}
/* ---------------------------------------------------------------------- */
int ComputeNBondAtom::pack_reverse_comm(int n, int first, double *buf)
{
int i, m, last;
m = 0;
last = first + n;
for (i = first; i < last; i++) buf[m++] = nbond[i];
return m;
}
/* ---------------------------------------------------------------------- */
void ComputeNBondAtom::unpack_reverse_comm(int n, int *list, double *buf)
{
int i, j, m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
nbond[j] += buf[m++];
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double ComputeNBondAtom::memory_usage()
{
double bytes = nmax * sizeof(double);
return bytes;
}

View File

@ -0,0 +1,61 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, 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.
------------------------------------------------------------------------- */
#ifdef COMPUTE_CLASS
// clang-format off
ComputeStyle(nbond/atom,ComputeNBondAtom);
// clang-format on
#else
#ifndef LMP_COMPUTE_NBOND_ATOM_H
#define LMP_COMPUTE_NBOND_ATOM_H
#include "compute.h"
namespace LAMMPS_NS {
class ComputeNBondAtom : public Compute {
public:
ComputeNBondAtom(class LAMMPS *, int, char **);
~ComputeNBondAtom() override;
void init() override {}
void compute_peratom() override;
int pack_reverse_comm(int, int, double *) override;
void unpack_reverse_comm(int, int *, double *) override;
double memory_usage() override;
private:
int nmax;
double *nbond;
};
} // namespace LAMMPS_NS
#endif
#endif
/* ERROR/WARNING messages:
E: Illegal ... command
Self-explanatory. Check the input script syntax and compare to the
documentation for the command. You can use -echo screen as a
command-line option when running LAMMPS to see the offending line.
E: Per-atom energy was not tallied on needed timestep
You are using a thermo keyword that requires potentials to
have tallied energy, but they didn't on this timestep. See the
variable doc page for ideas on how to make this work.
*/

View File

@ -0,0 +1,157 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, 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.
------------------------------------------------------------------------- */
#include "fix_nve_bpm_sphere.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "error.h"
#include "force.h"
#include "math_extra.h"
#include <cmath>
#include <cstring>
using namespace LAMMPS_NS;
using namespace FixConst;
using namespace MathExtra;
/* ---------------------------------------------------------------------- */
FixNVEBPMSphere::FixNVEBPMSphere(LAMMPS *_lmp, int narg, char **arg) : FixNVE(_lmp, narg, arg)
{
if (narg < 3) error->all(FLERR, "Illegal fix nve/bpm/sphere command");
time_integrate = 1;
// process extra keywords
// inertia = moment of inertia prefactor for sphere or disc
inertia = 0.4;
int iarg = 3;
while (iarg < narg) {
if (strcmp(arg[iarg], "disc") == 0) {
inertia = 0.5;
if (domain->dimension != 2)
error->all(FLERR, "Fix nve/bpm/sphere disc requires 2d simulation");
iarg++;
} else
error->all(FLERR, "Illegal fix nve/bpm/sphere command");
}
inv_inertia = 1.0 / inertia;
// error checks
if (!atom->quat_flag || !atom->sphere_flag)
error->all(FLERR, "Fix nve/bpm/sphere requires atom style bpm/sphere");
}
/* ---------------------------------------------------------------------- */
void FixNVEBPMSphere::init()
{
FixNVE::init();
// check that all particles are finite-size spheres
// no point particles allowed
double *radius = atom->radius;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (radius[i] == 0.0) error->one(FLERR, "Fix nve/bpm/sphere requires extended particles");
}
/* ---------------------------------------------------------------------- */
void FixNVEBPMSphere::initial_integrate(int /*vflag*/)
{
double dtq, dtfm, dtirotate, particle_inertia;
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double **omega = atom->omega;
double **torque = atom->torque;
double **quat = atom->quat;
double *radius = atom->radius;
double *rmass = atom->rmass;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
// set timestep here since dt may have changed or come via rRESPA
dtq = 0.5 * dtv;
// update v,x,omega,quat for all particles
// d_omega/dt = torque / inertia
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
particle_inertia = inertia * (radius[i] * radius[i] * rmass[i]);
dtirotate = dtf / particle_inertia;
omega[i][0] += dtirotate * torque[i][0];
omega[i][1] += dtirotate * torque[i][1];
omega[i][2] += dtirotate * torque[i][2];
MathExtra::richardson_sphere(quat[i], omega[i], dtq);
}
}
}
/* ---------------------------------------------------------------------- */
void FixNVEBPMSphere::final_integrate()
{
double dtfm, dtirotate, particle_inertia;
double **v = atom->v;
double **f = atom->f;
double **omega = atom->omega;
double **torque = atom->torque;
double *rmass = atom->rmass;
double *radius = atom->radius;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
// update v,omega for all particles
// d_omega/dt = torque / inertia
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
particle_inertia = inertia * (radius[i] * radius[i] * rmass[i]);
dtirotate = dtf / particle_inertia;
omega[i][0] += dtirotate * torque[i][0];
omega[i][1] += dtirotate * torque[i][1];
omega[i][2] += dtirotate * torque[i][2];
}
}

View File

@ -0,0 +1,71 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, 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.
------------------------------------------------------------------------- */
#ifdef FIX_CLASS
// clang-format off
FixStyle(nve/bpm/sphere,FixNVEBPMSphere);
// clang-format on
#else
#ifndef LMP_FIX_NVE_BPM_SPHERE_H
#define LMP_FIX_NVE_BPM_SPHERE_H
#include "fix_nve.h"
namespace LAMMPS_NS {
class FixNVEBPMSphere : public FixNVE {
public:
FixNVEBPMSphere(class LAMMPS *, int, char **);
void init() override;
void initial_integrate(int) override;
void final_integrate() override;
protected:
double inertia, inv_inertia;
int extra;
int dlm;
};
} // namespace LAMMPS_NS
#endif
#endif
/* ERROR/WARNING messages:
E: Illegal ... command
Self-explanatory. Check the input script syntax and compare to the
documentation for the command. You can use -echo screen as a
command-line option when running LAMMPS to see the offending line.
E: Fix nve/bpm/sphere disc requires 2d simulation
UNDOCUMENTED
E: Fix nve/bpm/sphere requires atom style bpm/sphere
Self-explanatory.
E: Fix nve/bpm/sphere update dipole requires atom attribute mu
An atom style with this attribute is needed.
E: Fix nve/bpm/sphere requires extended particles
This fix can only be used for particles of a finite size.
*/

326
src/BPM/pair_bpm_spring.cpp Normal file
View File

@ -0,0 +1,326 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, 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.
------------------------------------------------------------------------- */
#include "pair_bpm_spring.h"
#include "atom.h"
#include "comm.h"
#include "error.h"
#include "force.h"
#include "memory.h"
#include "neigh_list.h"
#include "neighbor.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairBPMSpring::PairBPMSpring(LAMMPS *_lmp) : Pair(_lmp)
{
writedata = 1;
}
/* ---------------------------------------------------------------------- */
PairBPMSpring::~PairBPMSpring()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(k);
memory->destroy(cut);
memory->destroy(gamma);
}
}
/* ---------------------------------------------------------------------- */
void PairBPMSpring::compute(int eflag, int vflag)
{
int i, j, ii, jj, inum, jnum, itype, jtype;
double xtmp, ytmp, ztmp, delx, dely, delz, evdwl, fpair;
double r, rsq, rinv, factor_lj;
int *ilist, *jlist, *numneigh, **firstneigh;
double vxtmp, vytmp, vztmp, delvx, delvy, delvz, dot, smooth;
evdwl = 0.0;
if (eflag || vflag)
ev_setup(eflag, vflag);
else
evflag = vflag_fdotr = 0;
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
double *special_lj = force->special_lj;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
vxtmp = v[i][0];
vytmp = v[i][1];
vztmp = v[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
if (factor_lj == 0) continue;
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx * delx + dely * dely + delz * delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r = sqrt(rsq);
rinv = 1.0 / r;
fpair = k[itype][jtype] * (cut[itype][jtype] - r);
smooth = rsq / cutsq[itype][jtype];
smooth *= smooth;
smooth *= smooth;
smooth = 1.0 - smooth;
delvx = vxtmp - v[j][0];
delvy = vytmp - v[j][1];
delvz = vztmp - v[j][2];
dot = delx * delvx + dely * delvy + delz * delvz;
fpair -= gamma[itype][jtype] * dot * smooth * rinv;
fpair *= factor_lj * rinv;
if (eflag) evdwl = 0.0;
f[i][0] += delx * fpair;
f[i][1] += dely * fpair;
f[i][2] += delz * fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx * fpair;
f[j][1] -= dely * fpair;
f[j][2] -= delz * fpair;
}
if (evflag) ev_tally(i, j, nlocal, newton_pair, evdwl, 0.0, fpair, delx, dely, delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairBPMSpring::allocate()
{
allocated = 1;
const int np1 = atom->ntypes + 1;
memory->create(setflag, np1, np1, "pair:setflag");
for (int i = 1; i < np1; i++)
for (int j = i; j < np1; j++) setflag[i][j] = 0;
memory->create(cutsq, np1, np1, "pair:cutsq");
memory->create(k, np1, np1, "pair:k");
memory->create(cut, np1, np1, "pair:cut");
memory->create(gamma, np1, np1, "pair:gamma");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairBPMSpring::settings(int narg, char ** /*arg*/)
{
if (narg != 0) error->all(FLERR, "Illegal pair_style command");
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairBPMSpring::coeff(int narg, char **arg)
{
if (narg != 5) error->all(FLERR, "Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo, ihi, jlo, jhi;
utils::bounds(FLERR, arg[0], 1, atom->ntypes, ilo, ihi, error);
utils::bounds(FLERR, arg[1], 1, atom->ntypes, jlo, jhi, error);
double k_one = utils::numeric(FLERR, arg[2], false, lmp);
double cut_one = utils::numeric(FLERR, arg[3], false, lmp);
double gamma_one = utils::numeric(FLERR, arg[4], false, lmp);
if (cut_one <= 0.0) error->all(FLERR, "Incorrect args for pair coefficients");
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo, i); j <= jhi; j++) {
k[i][j] = k_one;
cut[i][j] = cut_one;
gamma[i][j] = gamma_one;
setflag[i][j] = 1;
count++;
}
}
if (count == 0) error->all(FLERR, "Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairBPMSpring::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
cut[i][j] = mix_distance(cut[i][i], cut[j][j]);
k[i][j] = mix_energy(k[i][i], k[j][j], cut[i][i], cut[j][j]);
gamma[i][j] = mix_energy(gamma[i][i], gamma[j][j], cut[i][i], cut[j][j]);
}
cut[j][i] = cut[i][j];
k[j][i] = k[i][j];
gamma[j][i] = gamma[i][j];
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairBPMSpring::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i, j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j], sizeof(int), 1, fp);
if (setflag[i][j]) {
fwrite(&k[i][j], sizeof(double), 1, fp);
fwrite(&cut[i][j], sizeof(double), 1, fp);
fwrite(&gamma[i][j], sizeof(double), 1, fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairBPMSpring::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i, j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j], sizeof(int), 1, fp);
MPI_Bcast(&setflag[i][j], 1, MPI_INT, 0, world);
if (setflag[i][j]) {
if (me == 0) {
fread(&k[i][j], sizeof(double), 1, fp);
fread(&cut[i][j], sizeof(double), 1, fp);
fread(&gamma[i][j], sizeof(double), 1, fp);
}
MPI_Bcast(&k[i][j], 1, MPI_DOUBLE, 0, world);
MPI_Bcast(&cut[i][j], 1, MPI_DOUBLE, 0, world);
MPI_Bcast(&gamma[i][j], 1, MPI_DOUBLE, 0, world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to data file
------------------------------------------------------------------------- */
void PairBPMSpring::write_data(FILE *fp)
{
for (int i = 1; i <= atom->ntypes; i++)
fprintf(fp, "%d %g %g %g\n", i, k[i][i], cut[i][i], gamma[i][i]);
}
/* ----------------------------------------------------------------------
proc 0 writes all pairs to data file
------------------------------------------------------------------------- */
void PairBPMSpring::write_data_all(FILE *fp)
{
for (int i = 1; i <= atom->ntypes; i++)
for (int j = i; j <= atom->ntypes; j++)
fprintf(fp, "%d %d %g %g %g\n", i, j, k[i][j], cut[i][j], gamma[i][j]);
}
/* ---------------------------------------------------------------------- */
double PairBPMSpring::single(int i, int j, int itype, int jtype, double rsq, double /*factor_coul*/,
double factor_lj, double &fforce)
{
double fpair, r, rinv;
double delx, dely, delz, delvx, delvy, delvz, dot, smooth;
if (rsq > cutsq[itype][jtype]) return 0.0;
double **x = atom->x;
double **v = atom->v;
r = sqrt(rsq);
rinv = 1.0 / r;
fpair = k[itype][jtype] * (cut[itype][jtype] - r);
smooth = rsq / cutsq[itype][jtype];
smooth *= smooth;
smooth = 1.0 - smooth;
delx = x[i][0] - x[j][0];
dely = x[i][1] - x[j][1];
delz = x[i][2] - x[j][2];
delvx = v[i][0] - v[j][0];
delvy = v[i][1] - v[j][1];
delvz = v[i][2] - v[j][2];
dot = delx * delvx + dely * delvy + delz * delvz;
fpair -= gamma[itype][jtype] * dot * rinv * smooth;
fpair *= factor_lj;
fforce = fpair;
return 0.0;
}

64
src/BPM/pair_bpm_spring.h Normal file
View File

@ -0,0 +1,64 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, 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.
------------------------------------------------------------------------- */
#ifdef PAIR_CLASS
// clang-format off
PairStyle(bpm/spring,PairBPMSpring);
// clang-format on
#else
#ifndef LMP_PAIR_BPM_SPRING_H
#define LMP_PAIR_BPM_SPRING_H
#include "pair.h"
namespace LAMMPS_NS {
class PairBPMSpring : public Pair {
public:
PairBPMSpring(class LAMMPS *);
~PairBPMSpring() override;
void compute(int, int) override;
void settings(int, char **) override;
void coeff(int, char **) override;
double init_one(int, int) override;
void write_restart(FILE *) override;
void read_restart(FILE *) override;
void write_data(FILE *) override;
void write_data_all(FILE *) override;
double single(int, int, int, int, double, double, double, double &) override;
protected:
double **k, **cut, **gamma;
void allocate();
};
} // namespace LAMMPS_NS
#endif
#endif
/* ERROR/WARNING messages:
E: Illegal ... command
Self-explanatory. Check the input script syntax and compare to the
documentation for the command. You can use -echo screen as a
command-line option when running LAMMPS to see the offending line.
E: Incorrect args for pair coefficients
Self-explanatory. Check the input script or data file.
*/

View File

@ -136,8 +136,7 @@ FixPour::FixPour(LAMMPS *lmp, int narg, char **arg) :
error->all(FLERR,"Invalid atom type in fix pour mol command");
if (atom->molecular == Atom::TEMPLATE && onemols != atom->avec->onemols)
error->all(FLERR,"Fix pour molecule template ID must be same "
"as atom style template ID");
error->all(FLERR,"Fix pour molecule template ID must be same as atom style template ID");
onemols[i]->check_attributes(0);
// fix pour uses geoemetric center of molecule for insertion

View File

@ -45,7 +45,7 @@ void PairGranHertzHistory::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum;
double xtmp,ytmp,ztmp,delx,dely,delz,fx,fy,fz;
double radi,radj,radsum,rsq,r,rinv,rsqinv;
double radi,radj,radsum,rsq,r,rinv,rsqinv,factor_lj;
double vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3;
double wr1,wr2,wr3;
double vtr1,vtr2,vtr3,vrel;
@ -91,6 +91,7 @@ void PairGranHertzHistory::compute(int eflag, int vflag)
int *mask = atom->mask;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
double *special_lj = force->special_lj;
inum = list->inum;
ilist = list->ilist;
@ -114,8 +115,11 @@ void PairGranHertzHistory::compute(int eflag, int vflag)
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
if (factor_lj == 0) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
@ -247,6 +251,9 @@ void PairGranHertzHistory::compute(int eflag, int vflag)
fx = delx*ccel + fs1;
fy = dely*ccel + fs2;
fz = delz*ccel + fs3;
fx *= factor_lj;
fy *= factor_lj;
fz *= factor_lj;
f[i][0] += fx;
f[i][1] += fy;
f[i][2] += fz;
@ -254,6 +261,9 @@ void PairGranHertzHistory::compute(int eflag, int vflag)
tor1 = rinv * (dely*fs3 - delz*fs2);
tor2 = rinv * (delz*fs1 - delx*fs3);
tor3 = rinv * (delx*fs2 - dely*fs1);
tor1 *= factor_lj;
tor2 *= factor_lj;
tor3 *= factor_lj;
torque[i][0] -= radi*tor1;
torque[i][1] -= radi*tor2;
torque[i][2] -= radi*tor3;

View File

@ -42,7 +42,7 @@ void PairGranHooke::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum;
double xtmp,ytmp,ztmp,delx,dely,delz,fx,fy,fz;
double radi,radj,radsum,rsq,r,rinv,rsqinv;
double radi,radj,radsum,rsq,r,rinv,rsqinv,factor_lj;
double vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3;
double wr1,wr2,wr3;
double vtr1,vtr2,vtr3,vrel;
@ -82,6 +82,7 @@ void PairGranHooke::compute(int eflag, int vflag)
int *mask = atom->mask;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
double *special_lj = force->special_lj;
inum = list->inum;
ilist = list->ilist;
@ -101,8 +102,11 @@ void PairGranHooke::compute(int eflag, int vflag)
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
if (factor_lj == 0) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
@ -187,6 +191,9 @@ void PairGranHooke::compute(int eflag, int vflag)
fx = delx*ccel + fs1;
fy = dely*ccel + fs2;
fz = delz*ccel + fs3;
fx *= factor_lj;
fy *= factor_lj;
fz *= factor_lj;
f[i][0] += fx;
f[i][1] += fy;
f[i][2] += fz;
@ -194,6 +201,9 @@ void PairGranHooke::compute(int eflag, int vflag)
tor1 = rinv * (dely*fs3 - delz*fs2);
tor2 = rinv * (delz*fs1 - delx*fs3);
tor3 = rinv * (delx*fs2 - dely*fs1);
tor1 *= factor_lj;
tor2 *= factor_lj;
tor3 *= factor_lj;
torque[i][0] -= radi*tor1;
torque[i][1] -= radi*tor2;
torque[i][2] -= radi*tor3;

View File

@ -103,7 +103,7 @@ void PairGranHookeHistory::compute(int eflag, int vflag)
{
int i, j, ii, jj, inum, jnum;
double xtmp, ytmp, ztmp, delx, dely, delz, fx, fy, fz;
double radi, radj, radsum, rsq, r, rinv, rsqinv;
double radi, radj, radsum, rsq, r, rinv, rsqinv, factor_lj;
double vr1, vr2, vr3, vnnr, vn1, vn2, vn3, vt1, vt2, vt3;
double wr1, wr2, wr3;
double vtr1, vtr2, vtr3, vrel;
@ -151,6 +151,7 @@ void PairGranHookeHistory::compute(int eflag, int vflag)
int *mask = atom->mask;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
double *special_lj = force->special_lj;
inum = list->inum;
ilist = list->ilist;
@ -174,8 +175,11 @@ void PairGranHookeHistory::compute(int eflag, int vflag)
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
if (factor_lj == 0) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
@ -306,6 +310,9 @@ void PairGranHookeHistory::compute(int eflag, int vflag)
fx = delx * ccel + fs1;
fy = dely * ccel + fs2;
fz = delz * ccel + fs3;
fx *= factor_lj;
fy *= factor_lj;
fz *= factor_lj;
f[i][0] += fx;
f[i][1] += fy;
f[i][2] += fz;
@ -313,6 +320,9 @@ void PairGranHookeHistory::compute(int eflag, int vflag)
tor1 = rinv * (dely * fs3 - delz * fs2);
tor2 = rinv * (delz * fs1 - delx * fs3);
tor3 = rinv * (delx * fs2 - dely * fs1);
tor1 *= factor_lj;
tor2 *= factor_lj;
tor3 *= factor_lj;
torque[i][0] -= radi * tor1;
torque[i][1] -= radi * tor2;
torque[i][2] -= radi * tor3;

View File

@ -150,7 +150,7 @@ void PairGranular::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,fx,fy,fz,nx,ny,nz;
double radi,radj,radsum,rsq,r,rinv;
double radi,radj,radsum,rsq,r,rinv,factor_lj;
double Reff, delta, dR, dR2, dist_to_contact;
double vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3;
@ -222,6 +222,7 @@ void PairGranular::compute(int eflag, int vflag)
double *rmass = atom->rmass;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
inum = list->inum;
ilist = list->ilist;
@ -249,8 +250,11 @@ void PairGranular::compute(int eflag, int vflag)
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
if (factor_lj == 0) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
@ -651,6 +655,9 @@ void PairGranular::compute(int eflag, int vflag)
fx = nx*Fntot + fs1;
fy = ny*Fntot + fs2;
fz = nz*Fntot + fs3;
fx *= factor_lj;
fy *= factor_lj;
fz *= factor_lj;
f[i][0] += fx;
f[i][1] += fy;
@ -659,6 +666,9 @@ void PairGranular::compute(int eflag, int vflag)
tor1 = ny*fs3 - nz*fs2;
tor2 = nz*fs1 - nx*fs3;
tor3 = nx*fs2 - ny*fs1;
tor1 *= factor_lj;
tor2 *= factor_lj;
tor3 *= factor_lj;
dist_to_contact = radi-0.5*delta;
torque[i][0] -= dist_to_contact*tor1;
@ -666,9 +676,9 @@ void PairGranular::compute(int eflag, int vflag)
torque[i][2] -= dist_to_contact*tor3;
if (twist_model[itype][jtype] != TWIST_NONE) {
tortwist1 = magtortwist * nx;
tortwist2 = magtortwist * ny;
tortwist3 = magtortwist * nz;
tortwist1 = magtortwist * nx * factor_lj;
tortwist2 = magtortwist * ny * factor_lj;
tortwist3 = magtortwist * nz * factor_lj;
torque[i][0] += tortwist1;
torque[i][1] += tortwist2;
@ -676,9 +686,9 @@ void PairGranular::compute(int eflag, int vflag)
}
if (roll_model[itype][jtype] != ROLL_NONE) {
torroll1 = Reff*(ny*fr3 - nz*fr2); // n cross fr
torroll2 = Reff*(nz*fr1 - nx*fr3);
torroll3 = Reff*(nx*fr2 - ny*fr1);
torroll1 = Reff*(ny*fr3 - nz*fr2) * factor_lj; // n cross fr
torroll2 = Reff*(nz*fr1 - nx*fr3) * factor_lj;
torroll3 = Reff*(nx*fr2 - ny*fr1) * factor_lj;
torque[i][0] += torroll1;
torque[i][1] += torroll2;

View File

@ -19,11 +19,14 @@
#include "error.h"
#include "force.h"
#include "memory.h"
#include "modify.h"
#include "neighbor.h"
#include "random_mars.h"
#include "respa.h"
#include "update.h"
#include "fix_bond_history.h"
#include <cstring>
using namespace LAMMPS_NS;
@ -258,6 +261,10 @@ void FixBondBreak::post_integrate()
commflag = 1;
comm->forward_comm(this,2);
// find instances of bond history to delete data
auto histories = modify->get_fix_by_style("BOND_HISTORY");
int n_histories = histories.size();
// break bonds
// if both atoms list each other as winning bond partner
// and probability constraint is satisfied
@ -292,7 +299,13 @@ void FixBondBreak::post_integrate()
for (k = m; k < num_bond[i]-1; k++) {
bond_atom[i][k] = bond_atom[i][k+1];
bond_type[i][k] = bond_type[i][k+1];
if (n_histories > 0)
for (auto &ihistory: histories)
dynamic_cast<FixBondHistory *>(ihistory)->shift_history(i,k,k+1);
}
if (n_histories > 0)
for (auto &ihistory: histories)
dynamic_cast<FixBondHistory *>(ihistory)->delete_history(i,num_bond[i]-1);
num_bond[i]--;
break;
}

View File

@ -17,21 +17,15 @@
------------------------------------------------------------------------- */
#include "fix_bond_create_angle.h"
#include "atom.h"
#include <cmath>
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixBondCreateAngle::FixBondCreateAngle(LAMMPS *lmp, int narg, char **arg) :
FixBondCreate(lmp, narg, arg)
{
}
/* ---------------------------------------------------------------------- */
int FixBondCreateAngle::constrain(int i, int j, double amin, double amax)
{
double **x = atom->x;

View File

@ -26,7 +26,7 @@ namespace LAMMPS_NS {
class FixBondCreateAngle : public FixBondCreate {
public:
FixBondCreateAngle(class LAMMPS *, int, char **);
FixBondCreateAngle(LAMMPS *_lmp, int narg, char **arg) : FixBondCreate(_lmp, narg, arg) {}
private:
int constrain(int, int, double, double) override;

View File

@ -22,6 +22,7 @@
#include "compute.h"
#include "domain.h"
#include "error.h"
#include "fix_bond_history.h"
#include "force.h"
#include "memory.h"
#include "modify.h"
@ -446,6 +447,10 @@ void FixBondSwap::post_integrate()
if (!accept) return;
naccept++;
// find instances of bond/history to reset history
auto histories = modify->get_fix_by_style("BOND_HISTORY");
int n_histories = histories.size();
// change bond partners of affected atoms
// on atom i: bond i-inext changes to i-jnext
// on atom j: bond j-jnext changes to j-inext
@ -453,13 +458,33 @@ void FixBondSwap::post_integrate()
// on atom jnext: bond jnext-j changes to jnext-i
for (ibond = 0; ibond < num_bond[i]; ibond++)
if (bond_atom[i][ibond] == tag[inext]) bond_atom[i][ibond] = tag[jnext];
if (bond_atom[i][ibond] == tag[inext]) {
if (n_histories > 0)
for (auto &ihistory: histories)
dynamic_cast<FixBondHistory *>(ihistory)->delete_history(i,ibond);
bond_atom[i][ibond] = tag[jnext];
}
for (jbond = 0; jbond < num_bond[j]; jbond++)
if (bond_atom[j][jbond] == tag[jnext]) bond_atom[j][jbond] = tag[inext];
if (bond_atom[j][jbond] == tag[jnext]) {
if (n_histories > 0)
for (auto &ihistory: histories)
dynamic_cast<FixBondHistory *>(ihistory)->delete_history(j,jbond);
bond_atom[j][jbond] = tag[inext];
}
for (ibond = 0; ibond < num_bond[inext]; ibond++)
if (bond_atom[inext][ibond] == tag[i]) bond_atom[inext][ibond] = tag[j];
if (bond_atom[inext][ibond] == tag[i]) {
if (n_histories > 0)
for (auto &ihistory: histories)
dynamic_cast<FixBondHistory *>(ihistory)->delete_history(inext,ibond);
bond_atom[inext][ibond] = tag[j];
}
for (jbond = 0; jbond < num_bond[jnext]; jbond++)
if (bond_atom[jnext][jbond] == tag[j]) bond_atom[jnext][jbond] = tag[i];
if (bond_atom[jnext][jbond] == tag[j]) {
if (n_histories > 0)
for (auto &ihistory: histories)
dynamic_cast<FixBondHistory *>(ihistory)->delete_history(jnext,jbond);
bond_atom[jnext][jbond] = tag[i];
}
// set global tags of 4 atoms in bonds

View File

@ -1,350 +0,0 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/ 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.
------------------------------------------------------------------------- */
#include "fix_pair_tracker.h"
#include "atom.h"
#include "error.h"
#include "memory.h"
#include "tokenizer.h"
#include "update.h"
#include <cstring>
using namespace LAMMPS_NS;
using namespace FixConst;
#define DELTA 1000
/* ---------------------------------------------------------------------- */
FixPairTracker::FixPairTracker(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg), nvalues(0), vector(nullptr), array(nullptr), pack_choice(nullptr)
{
if (narg < 3) error->all(FLERR, "Illegal fix pair/tracker command");
local_flag = 1;
nevery = utils::inumeric(FLERR, arg[3], false, lmp);
if (nevery <= 0) error->all(FLERR, "Illegal fix pair/tracker command");
local_freq = nevery;
// If optional arguments included, this will be oversized
nvalues = narg - 4;
pack_choice = new FnPtrPack[nvalues];
tmin = -1;
type_filter = nullptr;
int iarg = 4;
nvalues = 0;
while (iarg < narg) {
if (strcmp(arg[iarg], "id1") == 0) {
pack_choice[nvalues++] = &FixPairTracker::pack_id1;
} else if (strcmp(arg[iarg], "id2") == 0) {
pack_choice[nvalues++] = &FixPairTracker::pack_id2;
} else if (strcmp(arg[iarg], "time/created") == 0) {
pack_choice[nvalues++] = &FixPairTracker::pack_time_created;
} else if (strcmp(arg[iarg], "time/broken") == 0) {
pack_choice[nvalues++] = &FixPairTracker::pack_time_broken;
} else if (strcmp(arg[iarg], "time/total") == 0) {
pack_choice[nvalues++] = &FixPairTracker::pack_time_total;
} else if (strcmp(arg[iarg], "x") == 0) {
pack_choice[nvalues++] = &FixPairTracker::pack_x;
} else if (strcmp(arg[iarg], "y") == 0) {
pack_choice[nvalues++] = &FixPairTracker::pack_y;
} else if (strcmp(arg[iarg], "z") == 0) {
pack_choice[nvalues++] = &FixPairTracker::pack_z;
} else if (strcmp(arg[iarg], "r/min") == 0) {
pack_choice[nvalues++] = &FixPairTracker::pack_rmin;
} else if (strcmp(arg[iarg], "r/ave") == 0) {
pack_choice[nvalues++] = &FixPairTracker::pack_rave;
} else if (strcmp(arg[iarg], "time/min") == 0) {
if (iarg + 1 >= narg) error->all(FLERR, "Invalid keyword in fix pair/tracker command");
tmin = utils::numeric(FLERR, arg[iarg + 1], false, lmp);
iarg++;
} else if (strcmp(arg[iarg], "type/include") == 0) {
if (iarg + 1 >= narg) error->all(FLERR, "Invalid keyword in fix pair/tracker command");
int ntypes = atom->ntypes;
int i, j, itype, jtype;
int inlo, inhi, jnlo, jnhi;
if (!type_filter) {
memory->create(type_filter, ntypes + 1, ntypes + 1, "fix/pair/tracker:type_filter");
for (i = 0; i <= ntypes; i++) {
for (j = 0; j <= ntypes; j++) type_filter[i][j] = 0;
}
}
auto iwords = Tokenizer(arg[iarg + 1], ",").as_vector();
auto jwords = Tokenizer(arg[iarg + 2], ",").as_vector();
for (const auto &ifield : iwords) {
utils::bounds(FLERR, ifield, 1, ntypes, inlo, inhi, error);
for (const auto &jfield : jwords) {
utils::bounds(FLERR, jfield, 1, ntypes, jnlo, jnhi, error);
for (itype = inlo; itype <= inhi; itype++) {
for (jtype = jnlo; jtype <= jnhi; jtype++) {
type_filter[itype][jtype] = 1;
type_filter[jtype][itype] = 1;
}
}
}
}
iarg += 2;
} else
error->all(FLERR, "Invalid keyword in fix pair/tracker command");
iarg++;
}
if (nvalues == 1)
size_local_cols = 0;
else
size_local_cols = nvalues;
nmax = 0;
ncount = 0;
vector = nullptr;
array = nullptr;
}
/* ---------------------------------------------------------------------- */
FixPairTracker::~FixPairTracker()
{
delete[] pack_choice;
memory->destroy(vector);
memory->destroy(array);
memory->destroy(type_filter);
}
/* ---------------------------------------------------------------------- */
int FixPairTracker::setmask()
{
int mask = 0;
mask |= POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixPairTracker::init()
{
// Set size of array/vector
ncount = 0;
if (ncount > nmax) reallocate(ncount);
size_local_rows = ncount;
}
/* ---------------------------------------------------------------------- */
void FixPairTracker::lost_contact(int i, int j, double time_tmp, double nstep_tmp, double rsum_tmp,
double rmin_tmp)
{
double time = update->atime + (update->ntimestep - update->atimestep) * update->dt;
if ((time - time_tmp) < tmin) return;
if (type_filter) {
int *type = atom->type;
if (type_filter[type[i]][type[j]] == 0) return;
}
int *mask = atom->mask;
if (!(mask[i] & groupbit)) return;
if (!(mask[j] & groupbit)) return;
if (ncount == nmax) reallocate(ncount);
index_i = i;
index_j = j;
rmin = rmin_tmp;
rsum = rsum_tmp;
time_initial = time_tmp;
nstep_initial = nstep_tmp;
// fill vector or array with local values
if (nvalues == 1) {
(this->*pack_choice[0])(0);
} else {
for (int k = 0; k < nvalues; k++) { (this->*pack_choice[k])(k); }
}
ncount += 1;
}
/* ---------------------------------------------------------------------- */
void FixPairTracker::post_force(int /*vflag*/)
{
if (update->ntimestep % nevery == 0) {
size_local_rows = ncount;
ncount = 0;
}
}
/* ---------------------------------------------------------------------- */
void FixPairTracker::reallocate(int n)
{
// grow vector or array
while (nmax <= n) nmax += DELTA;
if (nvalues == 1) {
memory->grow(vector, nmax, "fix_pair_tracker:vector");
vector_local = vector;
} else {
memory->grow(array, nmax, nvalues, "fix_pair_tracker:array");
array_local = array;
}
}
/* ----------------------------------------------------------------------
memory usage of local data
------------------------------------------------------------------------- */
double FixPairTracker::memory_usage()
{
double bytes = nmax * (double) nvalues * sizeof(double);
bytes += nmax * 2 * sizeof(int);
return bytes;
}
/* ----------------------------------------------------------------------
one method for every keyword fix pair/tracker can output
the atom property is packed into a local vector or array
------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
void FixPairTracker::pack_time_created(int n)
{
if (nvalues == 1)
vector[ncount] = time_initial;
else
array[ncount][n] = time_initial;
}
/* ---------------------------------------------------------------------- */
void FixPairTracker::pack_time_broken(int n)
{
double time = update->atime + (update->ntimestep - update->atimestep) * update->dt;
if (nvalues == 1)
vector[ncount] = time;
else
array[ncount][n] = time;
}
/* ---------------------------------------------------------------------- */
void FixPairTracker::pack_time_total(int n)
{
double time = update->atime + (update->ntimestep - update->atimestep) * update->dt;
if (nvalues == 1)
vector[ncount] = time - time_initial;
else
array[ncount][n] = time - time_initial;
}
/* ---------------------------------------------------------------------- */
void FixPairTracker::pack_id1(int n)
{
tagint *tag = atom->tag;
if (nvalues == 1)
vector[ncount] = tag[index_i];
else
array[ncount][n] = tag[index_i];
}
/* ---------------------------------------------------------------------- */
void FixPairTracker::pack_id2(int n)
{
tagint *tag = atom->tag;
if (nvalues == 1)
vector[ncount] = tag[index_j];
else
array[ncount][n] = tag[index_j];
}
/* ---------------------------------------------------------------------- */
void FixPairTracker::pack_x(int n)
{
double **x = atom->x;
if (nvalues == 1)
vector[ncount] = (x[index_i][0] + x[index_j][0]) / 2;
else
array[ncount][n] = (x[index_i][0] + x[index_j][0]) / 2;
}
/* ---------------------------------------------------------------------- */
void FixPairTracker::pack_y(int n)
{
double **x = atom->x;
if (nvalues == 1)
vector[ncount] = (x[index_i][1] + x[index_j][1]) / 2;
else
array[ncount][n] = (x[index_i][1] + x[index_j][1]) / 2;
}
/* ---------------------------------------------------------------------- */
void FixPairTracker::pack_z(int n)
{
double **x = atom->x;
if (nvalues == 1)
vector[ncount] = (x[index_i][2] + x[index_j][2]) / 2;
else
array[ncount][n] = (x[index_i][2] + x[index_j][2]) / 2;
}
/* ---------------------------------------------------------------------- */
void FixPairTracker::pack_rmin(int n)
{
if (nvalues == 1)
vector[ncount] = rmin;
else
array[ncount][n] = rmin;
}
/* ---------------------------------------------------------------------- */
void FixPairTracker::pack_rave(int n)
{
if (nvalues == 1)
vector[ncount] = rsum / (update->ntimestep - nstep_initial);
else
array[ncount][n] = rsum / (update->ntimestep - nstep_initial);
}

View File

@ -19,39 +19,41 @@
#include "fix.h"
#include "fix_dummy.h"
#include "fix_neigh_history.h"
#include "fix_pair_tracker.h"
#include "fix_store_local.h"
#include "force.h"
#include "memory.h"
#include "modify.h"
#include "neigh_list.h"
#include "neighbor.h"
#include "tokenizer.h"
#include "update.h"
#include "utils.h"
#include <cmath>
#include <cstring>
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairTracker::PairTracker(LAMMPS *lmp) : Pair(lmp)
PairTracker::PairTracker(LAMMPS *lmp) :
Pair(lmp), onerad_dynamic(nullptr), onerad_frozen(nullptr), maxrad_dynamic(nullptr),
maxrad_frozen(nullptr), id_fix_store_local(nullptr), fix_dummy(nullptr), fix_history(nullptr),
fix_store_local(nullptr), type_filter(nullptr), output_data(nullptr), pack_choice(nullptr)
{
single_enable = 1;
no_virial_fdotr_compute = 1;
neighprev = 0;
history = 1;
size_history = 4;
size_history = 3;
nondefault_history_transfer = 1;
finitecutflag = 0;
tmin = -1;
// create dummy fix as placeholder for FixNeighHistory
// this is so final order of Modify:fix will conform to input script
fix_history = nullptr;
modify->add_fix("NEIGH_HISTORY_TRACK_DUMMY all DUMMY");
fix_dummy = dynamic_cast<FixDummy *>( modify->fix[modify->nfix - 1]);
fix_dummy = dynamic_cast<FixDummy *>(modify->add_fix("NEIGH_HISTORY_TRACK_DUMMY all DUMMY"));
}
/* ---------------------------------------------------------------------- */
@ -62,6 +64,7 @@ PairTracker::~PairTracker()
modify->delete_fix("NEIGH_HISTORY_TRACK_DUMMY");
else
modify->delete_fix("NEIGH_HISTORY_TRACK");
if (id_fix_store_local) modify->delete_fix(id_fix_store_local);
if (allocated) {
memory->destroy(setflag);
@ -73,6 +76,12 @@ PairTracker::~PairTracker()
delete[] maxrad_dynamic;
delete[] maxrad_frozen;
}
delete[] pack_choice;
delete[] id_fix_store_local;
memory->destroy(output_data);
memory->destroy(type_filter);
}
/* ---------------------------------------------------------------------- */
@ -80,7 +89,7 @@ PairTracker::~PairTracker()
void PairTracker::compute(int eflag, int vflag)
{
int i, j, ii, jj, inum, jnum, itype, jtype;
double xtmp, ytmp, ztmp, delx, dely, delz, time;
double xtmp, ytmp, ztmp, delx, dely, delz;
double radi, radj, radsum, rsq, r;
int *ilist, *jlist, *numneigh, **firstneigh;
int *touch, **firsttouch;
@ -131,27 +140,23 @@ void PairTracker::compute(int eflag, int vflag)
if (rsq >= radsum * radsum) {
data = &alldata[size_history * jj];
if (touch[jj] == 1) {
fix_pair_tracker->lost_contact(i, j, data[0], data[1], data[2], data[3]);
}
if (touch[jj] == 1) process_data(i, j, data);
touch[jj] = 0;
data[0] = 0.0; // initial time
data[1] = 0.0; // initial timestep
data[2] = 0.0; // sum of r, may overflow
data[3] = 0.0; // min of r
data[0] = 0.0; // initial timestep
data[1] = 0.0; // sum of r, may be inaccurate over long times
data[2] = 0.0; // min of r
} else {
data = &alldata[size_history * jj];
if (touch[jj] == 0) {
time = update->atime + (update->ntimestep - update->atimestep) * update->dt;
data[0] = time;
data[1] = (double) update->ntimestep;
data[0] = (double) update->ntimestep;
data[1] = r;
data[2] = r;
data[3] = r;
} else if (updateflag) {
data[2] += r;
if (data[3] > r) data[3] = r;
data[1] += r;
if (data[2] > r) data[2] = r;
}
touch[jj] = 1;
}
@ -160,28 +165,23 @@ void PairTracker::compute(int eflag, int vflag)
if (rsq >= cutsq[itype][jtype]) {
data = &alldata[size_history * jj];
if (touch[jj] == 1) {
fix_pair_tracker->lost_contact(i, j, data[0], data[1], data[2], data[3]);
}
if (touch[jj] == 1) process_data(i, j, data);
touch[jj] = 0;
data[0] = 0.0; // initial time
data[1] = 0.0; // initial timestep
data[2] = 0.0; // sum of r, may overflow
data[3] = 0.0; // min of r
data[0] = 0.0; // initial timestep
data[1] = 0.0; // sum of r, may be inaccurate over long times
data[2] = 0.0; // min of r
} else {
data = &alldata[size_history * jj];
if (touch[jj] == 0) {
time = update->atime + (update->ntimestep - update->atimestep) * update->dt;
data[0] = time;
data[1] = (double) update->ntimestep;
data[0] = (double) update->ntimestep;
data[1] = r;
data[2] = r;
data[3] = r;
} else if (updateflag) {
data[2] += r;
if (data[3] > r) data[3] = r;
data[1] += r;
if (data[2] > r) data[2] = r;
}
touch[jj] = 1;
}
@ -218,14 +218,89 @@ void PairTracker::allocate()
void PairTracker::settings(int narg, char **arg)
{
if (narg != 0 && narg != 1) error->all(FLERR, "Illegal pair_style command");
if (narg < 2) error->all(FLERR, "Illegal pair_style command");
if (narg == 1) {
if (strcmp(arg[0], "finite") == 0)
id_fix_store_local = utils::strdup(arg[0]);
store_local_freq = utils::inumeric(FLERR, arg[1], false, lmp);
// If optional arguments included, this will be oversized
pack_choice = new FnPtrPack[narg - 1];
nvalues = 0;
int iarg = 2;
while (iarg < narg) {
if (strcmp(arg[iarg], "finite") == 0) {
finitecutflag = 1;
else
} else if (strcmp(arg[iarg], "id1") == 0) {
pack_choice[nvalues++] = &PairTracker::pack_id1;
} else if (strcmp(arg[iarg], "id2") == 0) {
pack_choice[nvalues++] = &PairTracker::pack_id2;
} else if (strcmp(arg[iarg], "time/created") == 0) {
pack_choice[nvalues++] = &PairTracker::pack_time_created;
} else if (strcmp(arg[iarg], "time/broken") == 0) {
pack_choice[nvalues++] = &PairTracker::pack_time_broken;
} else if (strcmp(arg[iarg], "time/total") == 0) {
pack_choice[nvalues++] = &PairTracker::pack_time_total;
} else if (strcmp(arg[iarg], "x") == 0) {
pack_choice[nvalues++] = &PairTracker::pack_x;
} else if (strcmp(arg[iarg], "y") == 0) {
pack_choice[nvalues++] = &PairTracker::pack_y;
} else if (strcmp(arg[iarg], "z") == 0) {
pack_choice[nvalues++] = &PairTracker::pack_z;
} else if (strcmp(arg[iarg], "r/min") == 0) {
pack_choice[nvalues++] = &PairTracker::pack_rmin;
} else if (strcmp(arg[iarg], "r/ave") == 0) {
pack_choice[nvalues++] = &PairTracker::pack_rave;
} else if (strcmp(arg[iarg], "time/min") == 0) {
if (iarg + 1 >= narg) error->all(FLERR, "Invalid keyword in pair tracker command");
tmin = utils::numeric(FLERR, arg[iarg + 1], false, lmp);
iarg++;
} else if (strcmp(arg[iarg], "type/include") == 0) {
if (iarg + 1 >= narg) error->all(FLERR, "Invalid keyword in pair tracker command");
int ntypes = atom->ntypes;
int i, j, itype, jtype;
int inlo, inhi, jnlo, jnhi;
if (!type_filter) {
memory->create(type_filter, ntypes + 1, ntypes + 1, "pair/tracker:type_filter");
for (i = 0; i <= ntypes; i++) {
for (j = 0; j <= ntypes; j++) type_filter[i][j] = 0;
}
}
auto iwords = Tokenizer(arg[iarg + 1], ",").as_vector();
auto jwords = Tokenizer(arg[iarg + 2], ",").as_vector();
for (const auto &ifield : iwords) {
utils::bounds(FLERR, ifield, 1, ntypes, inlo, inhi, error);
for (const auto &jfield : jwords) {
utils::bounds(FLERR, jfield, 1, ntypes, jnlo, jnhi, error);
for (itype = inlo; itype <= inhi; itype++) {
for (jtype = jnlo; jtype <= jnhi; jtype++) {
type_filter[itype][jtype] = 1;
type_filter[jtype][itype] = 1;
}
}
}
}
iarg += 2;
} else {
error->all(FLERR, "Illegal pair_style command");
}
iarg++;
}
if (nvalues == 0) error->all(FLERR, "Must request at least one value to output");
memory->create(output_data, nvalues, "pair/tracker:output_data");
fix_store_local = dynamic_cast<FixStoreLocal *>(modify->get_fix_by_id(id_fix_store_local));
if (!fix_store_local)
fix_store_local = dynamic_cast<FixStoreLocal *>(modify->add_fix(
fmt::format("{} all STORE_LOCAL {} {}", id_fix_store_local, store_local_freq, nvalues)));
}
/* ----------------------------------------------------------------------
@ -263,8 +338,6 @@ void PairTracker::coeff(int narg, char **arg)
void PairTracker::init_style()
{
int i;
// error and warning checks
if (!atom->radius_flag && finitecutflag)
@ -283,44 +356,49 @@ void PairTracker::init_style()
if (fix_history == nullptr) {
modify->replace_fix("NEIGH_HISTORY_TRACK_DUMMY",
fmt::format("NEIGH_HISTORY_TRACK all NEIGH_HISTORY {}", size_history), 1);
fix_history = dynamic_cast<FixNeighHistory *>( modify->get_fix_by_id("NEIGH_HISTORY_TRACK"));
fix_history = dynamic_cast<FixNeighHistory *>(modify->get_fix_by_id("NEIGH_HISTORY_TRACK"));
fix_history->pair = this;
fix_history->use_bit_flag = 0;
} else {
fix_history = dynamic_cast<FixNeighHistory *>( modify->get_fix_by_id("NEIGH_HISTORY_TRACK"));
fix_history = dynamic_cast<FixNeighHistory *>(modify->get_fix_by_id("NEIGH_HISTORY_TRACK"));
if (!fix_history) error->all(FLERR, "Could not find pair fix neigh history ID");
}
if (finitecutflag) {
if (force->pair->beyond_contact)
error->all(FLERR,
"Pair tracker incompatible with granular pairstyles that extend beyond contact");
// check for FixFreeze and set freeze_group_bit
auto fixlist = modify->get_fix_by_style("^freeze");
if (fixlist.size() == 0)
freeze_group_bit = 0;
else if (fixlist.size() > 1)
error->all(FLERR, "Only one fix freeze command at a time allowed");
else
freeze_group_bit = fixlist.front()->groupbit;
// check for FixPour and FixDeposit so can extract particle radii
int ipour;
for (ipour = 0; ipour < modify->nfix; ipour++)
if (strcmp(modify->fix[ipour]->style, "pour") == 0) break;
if (ipour == modify->nfix) ipour = -1;
int idep;
for (idep = 0; idep < modify->nfix; idep++)
if (strcmp(modify->fix[idep]->style, "deposit") == 0) break;
if (idep == modify->nfix) idep = -1;
auto pours = modify->get_fix_by_style("^pour");
auto deps = modify->get_fix_by_style("^deposit");
// set maxrad_dynamic and maxrad_frozen for each type
// include future FixPour and FixDeposit particles as dynamic
int itype;
for (i = 1; i <= atom->ntypes; i++) {
int itype = 0;
for (int i = 1; i <= atom->ntypes; i++) {
onerad_dynamic[i] = onerad_frozen[i] = 0.0;
if (ipour >= 0) {
for (auto &ipour : pours) {
itype = i;
onerad_dynamic[i] = *((double *) modify->fix[ipour]->extract("radius", itype));
double maxrad = *((double *) ipour->extract("radius", itype));
if (maxrad > 0.0) onerad_dynamic[i] = maxrad;
}
if (idep >= 0) {
for (auto &idep : deps) {
itype = i;
onerad_dynamic[i] = *((double *) modify->fix[idep]->extract("radius", itype));
double maxrad = *((double *) idep->extract("radius", itype));
if (maxrad > 0.0) onerad_dynamic[i] = maxrad;
}
}
@ -329,7 +407,7 @@ void PairTracker::init_style()
int *type = atom->type;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++)
for (int i = 0; i < nlocal; i++)
if (mask[i] & freeze_group_bit)
onerad_frozen[type[i]] = MAX(onerad_frozen[type[i]], radius[i]);
else
@ -338,11 +416,6 @@ void PairTracker::init_style()
MPI_Allreduce(&onerad_dynamic[1], &maxrad_dynamic[1], atom->ntypes, MPI_DOUBLE, MPI_MAX, world);
MPI_Allreduce(&onerad_frozen[1], &maxrad_frozen[1], atom->ntypes, MPI_DOUBLE, MPI_MAX, world);
}
auto trackfixes = modify->get_fix_by_style("pair/tracker");
if (trackfixes.size() != 1)
error->all(FLERR, "Must use exactly one fix pair/tracker command with pair style tracker");
fix_pair_tracker = dynamic_cast<FixPairTracker *>( trackfixes.front());
}
/* ----------------------------------------------------------------------
@ -354,8 +427,7 @@ double PairTracker::init_one(int i, int j)
if (!allocated) allocate();
// always mix prefactors geometrically
if (setflag[i][j] == 0) { cut[i][j] = mix_distance(cut[i][i], cut[j][j]); }
if (setflag[i][j] == 0) cut[i][j] = mix_distance(cut[i][i], cut[j][j]);
cut[j][i] = cut[i][j];
@ -384,7 +456,7 @@ void PairTracker::write_restart(FILE *fp)
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j], sizeof(int), 1, fp);
if (setflag[i][j]) { fwrite(&cut[i][j], sizeof(double), 1, fp); }
if (setflag[i][j]) fwrite(&cut[i][j], sizeof(double), 1, fp);
}
}
@ -404,7 +476,7 @@ void PairTracker::read_restart(FILE *fp)
if (me == 0) utils::sfread(FLERR, &setflag[i][j], sizeof(int), 1, fp, nullptr, error);
MPI_Bcast(&setflag[i][j], 1, MPI_INT, 0, world);
if (setflag[i][j]) {
if (me == 0) { utils::sfread(FLERR, &cut[i][j], sizeof(double), 1, fp, nullptr, error); }
if (me == 0) utils::sfread(FLERR, &cut[i][j], sizeof(double), 1, fp, nullptr, error);
MPI_Bcast(&cut[i][j], 1, MPI_DOUBLE, 0, world);
}
}
@ -466,3 +538,91 @@ double PairTracker::radii2cut(double r1, double r2)
double cut = r1 + r2;
return cut;
}
/* ---------------------------------------------------------------------- */
void PairTracker::process_data(int i, int j, double *input_data)
{
if ((update->ntimestep - input_data[0]) < tmin) return;
if (type_filter) {
int *type = atom->type;
if (type_filter[type[i]][type[j]] == 0) return;
}
for (int k = 0; k < nvalues; k++) (this->*pack_choice[k])(k, i, j, input_data);
fix_store_local->add_data(output_data, i, j);
}
/* ----------------------------------------------------------------------
one method for every keyword fix pair/tracker can output
the atom property is packed into a local vector or array
------------------------------------------------------------------------- */
void PairTracker::pack_time_created(int n, int /*i*/, int /*j*/, double *data)
{
output_data[n] = data[0];
}
/* ---------------------------------------------------------------------- */
void PairTracker::pack_time_broken(int n, int /*i*/, int /*j*/, double * /*data*/)
{
output_data[n] = update->ntimestep;
}
/* ---------------------------------------------------------------------- */
void PairTracker::pack_time_total(int n, int /*i*/, int /*j*/, double *data)
{
output_data[n] = update->ntimestep - data[0];
}
/* ---------------------------------------------------------------------- */
void PairTracker::pack_id1(int n, int i, int /*j*/, double * /*data*/)
{
output_data[n] = atom->tag[i];
}
/* ---------------------------------------------------------------------- */
void PairTracker::pack_id2(int n, int /*i*/, int j, double * /*data*/)
{
output_data[n] = atom->tag[j];
}
/* ---------------------------------------------------------------------- */
void PairTracker::pack_x(int n, int i, int j, double * /*data*/)
{
output_data[n] = (atom->x[i][0] + atom->x[j][0]) * 0.5;
}
/* ---------------------------------------------------------------------- */
void PairTracker::pack_y(int n, int i, int j, double * /*data*/)
{
output_data[n] = (atom->x[i][1] + atom->x[j][1]) * 0.5;
}
/* ---------------------------------------------------------------------- */
void PairTracker::pack_z(int n, int i, int j, double * /*data*/)
{
output_data[n] = (atom->x[i][2] + atom->x[j][2]) * 0.5;
}
/* ---------------------------------------------------------------------- */
void PairTracker::pack_rmin(int n, int /*i*/, int /*j*/, double *data)
{
output_data[n] = data[2];
}
/* ---------------------------------------------------------------------- */
void PairTracker::pack_rave(int n, int /*i*/, int /*j*/, double *data)
{
output_data[n] = data[1] / (update->ntimestep - data[0]);
}

View File

@ -40,6 +40,7 @@ class PairTracker : public Pair {
double single(int, int, int, int, double, double, double, double &) override;
double atom2cut(int) override;
double radii2cut(double, double) override;
void transfer_history(double *, double *) override;
protected:
int sizeflag;
@ -50,12 +51,33 @@ class PairTracker : public Pair {
double *onerad_dynamic, *onerad_frozen;
double *maxrad_dynamic, *maxrad_frozen;
int freeze_group_bit;
int store_local_freq;
char *id_fix_store_local;
class FixDummy *fix_dummy;
class FixNeighHistory *fix_history;
class FixPairTracker *fix_pair_tracker;
class FixStoreLocal *fix_store_local;
void transfer_history(double *, double *) override;
int **type_filter;
double tmin;
int nvalues, ncount;
double *output_data;
typedef void (PairTracker::*FnPtrPack)(int, int, int, double *);
FnPtrPack *pack_choice; // ptrs to pack functions
void pack_id1(int, int, int, double *);
void pack_id2(int, int, int, double *);
void pack_time_created(int, int, int, double *);
void pack_time_broken(int, int, int, double *);
void pack_time_total(int, int, int, double *);
void pack_x(int, int, int, double *);
void pack_y(int, int, int, double *);
void pack_z(int, int, int, double *);
void pack_rmin(int, int, int, double *);
void pack_rave(int, int, int, double *);
void process_data(int, int, double *);
void allocate();
};
@ -72,20 +94,37 @@ Self-explanatory. Check the input script syntax and compare to the
documentation for the command. You can use -echo screen as a
command-line option when running LAMMPS to see the offending line.
E: Invalid keyword in pair tracker command
Self-explanatory.
E: Incorrect args for pair coefficients
Self-explanatory. Check the input script or data file.
E: Must request at least one value to output
Must include at least one bond property to store in fix store/local
E: Pair tracker requires atom attribute radius for finite cutoffs
The atom style defined does not have these attributes.
E: Pair tracker incompatible with granular pairstyles that extend beyond contact
Self-explanatory.
E: Could not find pair fix neigh history ID
The associated fix neigh/history is missing
E: Cannot use pair tracker without fix pair/tracker
E: Cannot use pair tracker without fix store/local
This pairstyle requires one to define a pair/tracker fix
The associated fix store/local does not exist
E: Inconsistent number of output variables in fix store/local
The number of values specified in fix store/local disagrees with
the number of values requested in pair tracker
*/

View File

@ -36,6 +36,7 @@ using MathConst::MY_CUBEROOT2;
BondQuartic::BondQuartic(LAMMPS *_lmp) :
Bond(_lmp), k(nullptr), b1(nullptr), b2(nullptr), rc(nullptr), u0(nullptr)
{
partial_flag = 1;
}
/* ---------------------------------------------------------------------- */

View File

@ -54,6 +54,7 @@ PACKAGE = \
awpmd \
bocs \
body \
bpm \
brownian \
cg-dna \
cg-sdk \
@ -147,6 +148,7 @@ PACKMOST = \
asphere \
bocs \
body \
bpm \
brownian \
cg-dna \
cg-sdk \

View File

@ -578,7 +578,7 @@ void FixNeighHistoryOMP::post_neighbor()
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
rflag = sbmask(j);
rflag = histmask(j);
j &= NEIGHMASK;
jlist[jj] = j;

View File

@ -15,7 +15,10 @@
#include "npair_half_size_bin_newtoff_omp.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "error.h"
#include "molecule.h"
#include "my_page.h"
#include "neigh_list.h"
#include "npair_omp.h"
@ -40,8 +43,10 @@ NPairHalfSizeBinNewtoffOmp::NPairHalfSizeBinNewtoffOmp(LAMMPS *lmp) :
void NPairHalfSizeBinNewtoffOmp::build(NeighList *list)
{
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
const int molecular = atom->molecular;
const int moltemplate = (molecular == Atom::TEMPLATE) ? 1 : 0;
const int history = list->history;
const int mask_history = 3 << SBBITS;
const int mask_history = 1 << HISTBITS;
NPAIR_OMP_INIT;
@ -50,7 +55,8 @@ void NPairHalfSizeBinNewtoffOmp::build(NeighList *list)
#endif
NPAIR_OMP_SETUP(nlocal);
int i,j,k,n,ibin;
int i,j,jh,k,n,ibin,which,imol,iatom;
tagint tagprev;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
double radi,radsum,cutsq;
int *neighptr;
@ -61,7 +67,14 @@ void NPairHalfSizeBinNewtoffOmp::build(NeighList *list)
double *radius = atom->radius;
int *type = atom->type;
int *mask = atom->mask;
tagint *tag = atom->tag;
tagint *molecule = atom->molecule;
tagint **special = atom->special;
int **nspecial = atom->nspecial;
int *molindex = atom->molindex;
int *molatom = atom->molatom;
Molecule **onemols = atom->avec->onemols;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
@ -81,6 +94,11 @@ void NPairHalfSizeBinNewtoffOmp::build(NeighList *list)
ztmp = x[i][2];
radi = radius[i];
ibin = atom2bin[i];
if (moltemplate) {
imol = molindex[i];
iatom = molatom[i];
tagprev = tag[i] - iatom - 1;
}
// loop over all atoms in surrounding bins in stencil including self
// only store pair if i < j
@ -100,10 +118,23 @@ void NPairHalfSizeBinNewtoffOmp::build(NeighList *list)
cutsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutsq) {
jh = j;
if (history && rsq < radsum*radsum)
neighptr[n++] = j ^ mask_history;
else
neighptr[n++] = j;
jh = jh ^ mask_history;
if (molecular != Atom::ATOMIC) {
if (!moltemplate)
which = find_special(special[i],nspecial[i],tag[j]);
else if (imol >=0)
which = find_special(onemols[imol]->special[iatom],
onemols[imol]->nspecial[iatom],
tag[j]-tagprev);
else which = 0;
if (which == 0) neighptr[n++] = jh;
else if (domain->minimum_image_check(delx,dely,delz))
neighptr[n++] = jh;
else if (which > 0) neighptr[n++] = jh ^ (which << SBBITS);
} else neighptr[n++] = jh;
}
}
}

View File

@ -15,7 +15,10 @@
#include "npair_half_size_bin_newton_omp.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "error.h"
#include "molecule.h"
#include "my_page.h"
#include "neigh_list.h"
#include "npair_omp.h"
@ -39,8 +42,10 @@ NPairHalfSizeBinNewtonOmp::NPairHalfSizeBinNewtonOmp(LAMMPS *lmp) :
void NPairHalfSizeBinNewtonOmp::build(NeighList *list)
{
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
const int molecular = atom->molecular;
const int moltemplate = (molecular == Atom::TEMPLATE) ? 1 : 0;
const int history = list->history;
const int mask_history = 3 << SBBITS;
const int mask_history = 1 << HISTBITS;
NPAIR_OMP_INIT;
@ -49,7 +54,8 @@ void NPairHalfSizeBinNewtonOmp::build(NeighList *list)
#endif
NPAIR_OMP_SETUP(nlocal);
int i,j,k,n,ibin;
int i,j,jh,k,n,ibin,which,imol,iatom;
tagint tagprev;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
double radi,radsum,cutsq;
int *neighptr;
@ -58,7 +64,14 @@ void NPairHalfSizeBinNewtonOmp::build(NeighList *list)
double *radius = atom->radius;
int *type = atom->type;
int *mask = atom->mask;
tagint *tag = atom->tag;
tagint *molecule = atom->molecule;
tagint **special = atom->special;
int **nspecial = atom->nspecial;
int *molindex = atom->molindex;
int *molatom = atom->molatom;
Molecule **onemols = atom->avec->onemols;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
@ -77,6 +90,11 @@ void NPairHalfSizeBinNewtonOmp::build(NeighList *list)
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
if (moltemplate) {
imol = molindex[i];
iatom = molatom[i];
tagprev = tag[i] - iatom - 1;
}
// loop over rest of atoms in i's bin, ghosts are at end of linked list
// if j is owned atom, store it, since j is beyond i in linked list
@ -101,10 +119,23 @@ void NPairHalfSizeBinNewtonOmp::build(NeighList *list)
cutsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutsq) {
jh = j;
if (history && rsq < radsum*radsum)
neighptr[n++] = j ^ mask_history;
else
neighptr[n++] = j;
jh = jh ^ mask_history;
if (molecular != Atom::ATOMIC) {
if (!moltemplate)
which = find_special(special[i],nspecial[i],tag[j]);
else if (imol >=0)
which = find_special(onemols[imol]->special[iatom],
onemols[imol]->nspecial[iatom],
tag[j]-tagprev);
else which = 0;
if (which == 0) neighptr[n++] = jh;
else if (domain->minimum_image_check(delx,dely,delz))
neighptr[n++] = jh;
else if (which > 0) neighptr[n++] = jh ^ (which << SBBITS);
} else neighptr[n++] = jh;
}
}
@ -123,10 +154,23 @@ void NPairHalfSizeBinNewtonOmp::build(NeighList *list)
cutsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutsq) {
jh = j;
if (history && rsq < radsum*radsum)
neighptr[n++] = j ^ mask_history;
else
neighptr[n++] = j;
jh = jh ^ mask_history;
if (molecular != Atom::ATOMIC) {
if (!moltemplate)
which = find_special(special[i],nspecial[i],tag[j]);
else if (imol >=0)
which = find_special(onemols[imol]->special[iatom],
onemols[imol]->nspecial[iatom],
tag[j]-tagprev);
else which = 0;
if (which == 0) neighptr[n++] = jh;
else if (domain->minimum_image_check(delx,dely,delz))
neighptr[n++] = jh;
else if (which > 0) neighptr[n++] = jh ^ (which << SBBITS);
} else neighptr[n++] = jh;
}
}
}

View File

@ -15,7 +15,10 @@
#include "npair_half_size_bin_newton_tri_omp.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "error.h"
#include "molecule.h"
#include "my_page.h"
#include "neigh_list.h"
#include "npair_omp.h"
@ -39,8 +42,10 @@ NPairHalfSizeBinNewtonTriOmp::NPairHalfSizeBinNewtonTriOmp(LAMMPS *lmp) :
void NPairHalfSizeBinNewtonTriOmp::build(NeighList *list)
{
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
const int molecular = atom->molecular;
const int moltemplate = (molecular == Atom::TEMPLATE) ? 1 : 0;
const int history = list->history;
const int mask_history = 3 << SBBITS;
const int mask_history = 1 << HISTBITS;
NPAIR_OMP_INIT;
#if defined(_OPENMP)
@ -48,7 +53,8 @@ void NPairHalfSizeBinNewtonTriOmp::build(NeighList *list)
#endif
NPAIR_OMP_SETUP(nlocal);
int i,j,k,n,ibin;
int i,j,jh,k,n,ibin,which,imol,iatom;
tagint tagprev;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
double radi,radsum,cutsq;
int *neighptr;
@ -59,7 +65,14 @@ void NPairHalfSizeBinNewtonTriOmp::build(NeighList *list)
double *radius = atom->radius;
int *type = atom->type;
int *mask = atom->mask;
tagint *tag = atom->tag;
tagint *molecule = atom->molecule;
tagint **special = atom->special;
int **nspecial = atom->nspecial;
int *molindex = atom->molindex;
int *molatom = atom->molatom;
Molecule **onemols = atom->avec->onemols;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
@ -78,6 +91,11 @@ void NPairHalfSizeBinNewtonTriOmp::build(NeighList *list)
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
if (moltemplate) {
imol = molindex[i];
iatom = molatom[i];
tagprev = tag[i] - iatom - 1;
}
// loop over all atoms in bins in stencil
// pairs for atoms j "below" i are excluded
@ -107,10 +125,23 @@ void NPairHalfSizeBinNewtonTriOmp::build(NeighList *list)
cutsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutsq) {
jh = j;
if (history && rsq < radsum*radsum)
neighptr[n++] = j ^ mask_history;
else
neighptr[n++] = j;
jh = jh ^ mask_history;
if (molecular != Atom::ATOMIC) {
if (!moltemplate)
which = find_special(special[i],nspecial[i],tag[j]);
else if (imol >=0)
which = find_special(onemols[imol]->special[iatom],
onemols[imol]->nspecial[iatom],
tag[j]-tagprev);
else which = 0;
if (which == 0) neighptr[n++] = jh;
else if (domain->minimum_image_check(delx,dely,delz))
neighptr[n++] = jh;
else if (which > 0) neighptr[n++] = jh ^ (which << SBBITS);
} else neighptr[n++] = jh;
}
}
}

View File

@ -15,7 +15,10 @@
#include "npair_half_size_multi_newtoff_omp.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "error.h"
#include "molecule.h"
#include "my_page.h"
#include "neighbor.h"
#include "neigh_list.h"
@ -41,8 +44,10 @@ NPairHalfSizeMultiNewtoffOmp::NPairHalfSizeMultiNewtoffOmp(LAMMPS *lmp) : NPair(
void NPairHalfSizeMultiNewtoffOmp::build(NeighList *list)
{
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
const int molecular = atom->molecular;
const int moltemplate = (molecular == Atom::TEMPLATE) ? 1 : 0;
const int history = list->history;
const int mask_history = 3 << SBBITS;
const int mask_history = 1 << HISTBITS;
NPAIR_OMP_INIT;
#if defined(_OPENMP)
@ -50,7 +55,9 @@ void NPairHalfSizeMultiNewtoffOmp::build(NeighList *list)
#endif
NPAIR_OMP_SETUP(nlocal);
int i,j,k,n,itype,jtype,icollection,jcollection,ibin,jbin,ns;
int i,j,jh,k,n,itype,jtype,icollection,jcollection,ibin,jbin,ns;
int which,imol,iatom;
tagint tagprev;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
double radi,radsum,cutdistsq;
int *neighptr,*s;
@ -63,7 +70,14 @@ void NPairHalfSizeMultiNewtoffOmp::build(NeighList *list)
double *radius = atom->radius;
int *type = atom->type;
int *mask = atom->mask;
tagint *tag = atom->tag;
tagint *molecule = atom->molecule;
tagint **special = atom->special;
int **nspecial = atom->nspecial;
int *molindex = atom->molindex;
int *molatom = atom->molatom;
Molecule **onemols = atom->avec->onemols;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
@ -84,6 +98,11 @@ void NPairHalfSizeMultiNewtoffOmp::build(NeighList *list)
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
if (moltemplate) {
imol = molindex[i];
iatom = molatom[i];
tagprev = tag[i] - iatom - 1;
}
ibin = atom2bin[i];
@ -119,10 +138,23 @@ void NPairHalfSizeMultiNewtoffOmp::build(NeighList *list)
cutdistsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutdistsq) {
jh = j;
if (history && rsq < radsum*radsum)
neighptr[n++] = j ^ mask_history;
else
neighptr[n++] = j;
jh = jh ^ mask_history;
if (molecular != Atom::ATOMIC) {
if (!moltemplate)
which = find_special(special[i],nspecial[i],tag[j]);
else if (imol >=0)
which = find_special(onemols[imol]->special[iatom],
onemols[imol]->nspecial[iatom],
tag[j]-tagprev);
else which = 0;
if (which == 0) neighptr[n++] = jh;
else if (domain->minimum_image_check(delx,dely,delz))
neighptr[n++] = jh;
else if (which > 0) neighptr[n++] = jh ^ (which << SBBITS);
} else neighptr[n++] = jh;
}
}
}

View File

@ -15,7 +15,10 @@
#include "npair_half_size_multi_newton_omp.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "error.h"
#include "molecule.h"
#include "my_page.h"
#include "neighbor.h"
#include "neigh_list.h"
@ -40,8 +43,10 @@ NPairHalfSizeMultiNewtonOmp::NPairHalfSizeMultiNewtonOmp(LAMMPS *lmp) : NPair(lm
void NPairHalfSizeMultiNewtonOmp::build(NeighList *list)
{
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
const int molecular = atom->molecular;
const int moltemplate = (molecular == Atom::TEMPLATE) ? 1 : 0;
const int history = list->history;
const int mask_history = 3 << SBBITS;
const int mask_history = 1 << HISTBITS;
NPAIR_OMP_INIT;
#if defined(_OPENMP)
@ -49,7 +54,9 @@ void NPairHalfSizeMultiNewtonOmp::build(NeighList *list)
#endif
NPAIR_OMP_SETUP(nlocal);
int i,j,k,n,itype,jtype,icollection,jcollection,ibin,jbin,ns;
int i,j,jh,k,n,itype,jtype,icollection,jcollection,ibin,jbin,ns;
int which,imol,iatom;
tagint tagprev;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
double radi,radsum,cutdistsq;
int *neighptr,*s;
@ -62,7 +69,14 @@ void NPairHalfSizeMultiNewtonOmp::build(NeighList *list)
double *radius = atom->radius;
int *type = atom->type;
int *mask = atom->mask;
tagint *tag = atom->tag;
tagint *molecule = atom->molecule;
tagint **special = atom->special;
int **nspecial = atom->nspecial;
int *molindex = atom->molindex;
int *molatom = atom->molatom;
Molecule **onemols = atom->avec->onemols;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
@ -83,6 +97,11 @@ void NPairHalfSizeMultiNewtonOmp::build(NeighList *list)
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
if (moltemplate) {
imol = molindex[i];
iatom = molatom[i];
tagprev = tag[i] - iatom - 1;
}
ibin = atom2bin[i];
@ -129,10 +148,23 @@ void NPairHalfSizeMultiNewtonOmp::build(NeighList *list)
cutdistsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutdistsq) {
jh = j;
if (history && rsq < radsum*radsum)
neighptr[n++] = j ^ mask_history;
else
neighptr[n++] = j;
jh = jh ^ mask_history;
if (molecular != Atom::ATOMIC) {
if (!moltemplate)
which = find_special(special[i],nspecial[i],tag[j]);
else if (imol >=0)
which = find_special(onemols[imol]->special[iatom],
onemols[imol]->nspecial[iatom],
tag[j]-tagprev);
else which = 0;
if (which == 0) neighptr[n++] = jh;
else if (domain->minimum_image_check(delx,dely,delz))
neighptr[n++] = jh;
else if (which > 0) neighptr[n++] = jh ^ (which << SBBITS);
} else neighptr[n++] = jh;
}
}
}
@ -161,9 +193,21 @@ void NPairHalfSizeMultiNewtonOmp::build(NeighList *list)
if (rsq <= cutdistsq) {
if (history && rsq < radsum*radsum)
neighptr[n++] = j ^ mask_history;
else
j = j ^ mask_history;
if (molecular != Atom::ATOMIC) {
if (!moltemplate)
which = find_special(special[i],nspecial[i],tag[j]);
else if (imol >=0)
which = find_special(onemols[imol]->special[iatom],
onemols[imol]->nspecial[iatom],
tag[j]-tagprev);
else which = 0;
if (which == 0) neighptr[n++] = j;
else if (domain->minimum_image_check(delx,dely,delz))
neighptr[n++] = j;
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
}

View File

@ -15,7 +15,10 @@
#include "npair_half_size_multi_newton_tri_omp.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "error.h"
#include "molecule.h"
#include "my_page.h"
#include "neighbor.h"
#include "neigh_list.h"
@ -41,8 +44,10 @@ NPairHalfSizeMultiNewtonTriOmp::NPairHalfSizeMultiNewtonTriOmp(LAMMPS *lmp) :
void NPairHalfSizeMultiNewtonTriOmp::build(NeighList *list)
{
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
const int molecular = atom->molecular;
const int moltemplate = (molecular == Atom::TEMPLATE) ? 1 : 0;
const int history = list->history;
const int mask_history = 3 << SBBITS;
const int mask_history = 1 << HISTBITS;
NPAIR_OMP_INIT;
#if defined(_OPENMP)
@ -50,7 +55,9 @@ void NPairHalfSizeMultiNewtonTriOmp::build(NeighList *list)
#endif
NPAIR_OMP_SETUP(nlocal);
int i,j,k,n,itype,jtype,icollection,jcollection,ibin,jbin,ns;
int i,j,jh,k,n,itype,jtype,icollection,jcollection,ibin,jbin,ns;
int which,imol,iatom;
tagint tagprev;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
double radi,radsum,cutdistsq;
int *neighptr,*s;
@ -63,7 +70,14 @@ void NPairHalfSizeMultiNewtonTriOmp::build(NeighList *list)
double *radius = atom->radius;
int *type = atom->type;
int *mask = atom->mask;
tagint *tag = atom->tag;
tagint *molecule = atom->molecule;
tagint **special = atom->special;
int **nspecial = atom->nspecial;
int *molindex = atom->molindex;
int *molatom = atom->molatom;
Molecule **onemols = atom->avec->onemols;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
@ -84,6 +98,11 @@ void NPairHalfSizeMultiNewtonTriOmp::build(NeighList *list)
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
if (moltemplate) {
imol = molindex[i];
iatom = molatom[i];
tagprev = tag[i] - iatom - 1;
}
ibin = atom2bin[i];
@ -134,10 +153,23 @@ void NPairHalfSizeMultiNewtonTriOmp::build(NeighList *list)
cutdistsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutdistsq) {
jh = j;
if (history && rsq < radsum*radsum)
neighptr[n++] = j ^ mask_history;
else
neighptr[n++] = j;
jh = jh ^ mask_history;
if (molecular != Atom::ATOMIC) {
if (!moltemplate)
which = find_special(special[i],nspecial[i],tag[j]);
else if (imol >=0)
which = find_special(onemols[imol]->special[iatom],
onemols[imol]->nspecial[iatom],
tag[j]-tagprev);
else which = 0;
if (which == 0) neighptr[n++] = jh;
else if (domain->minimum_image_check(delx,dely,delz))
neighptr[n++] = jh;
else if (which > 0) neighptr[n++] = jh ^ (which << SBBITS);
} else neighptr[n++] = jh;
}
}
}

View File

@ -13,8 +13,12 @@
------------------------------------------------------------------------- */
#include "npair_half_size_multi_old_newtoff_omp.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "error.h"
#include "molecule.h"
#include "my_page.h"
#include "neigh_list.h"
#include "npair_omp.h"
@ -39,8 +43,10 @@ NPairHalfSizeMultiOldNewtoffOmp::NPairHalfSizeMultiOldNewtoffOmp(LAMMPS *lmp) :
void NPairHalfSizeMultiOldNewtoffOmp::build(NeighList *list)
{
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
const int molecular = atom->molecular;
const int moltemplate = (molecular == Atom::TEMPLATE) ? 1 : 0;
const int history = list->history;
const int mask_history = 3 << SBBITS;
const int mask_history = 1 << HISTBITS;
NPAIR_OMP_INIT;
#if defined(_OPENMP)
@ -48,7 +54,8 @@ void NPairHalfSizeMultiOldNewtoffOmp::build(NeighList *list)
#endif
NPAIR_OMP_SETUP(nlocal);
int i,j,k,n,itype,jtype,ibin,ns;
int i,j,jh,k,n,itype,jtype,ibin,ns,which,imol,iatom;
tagint tagprev;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
double radi,radsum,cutdistsq;
int *neighptr,*s;
@ -58,7 +65,14 @@ void NPairHalfSizeMultiOldNewtoffOmp::build(NeighList *list)
double *radius = atom->radius;
int *type = atom->type;
int *mask = atom->mask;
tagint *tag = atom->tag;
tagint *molecule = atom->molecule;
tagint **special = atom->special;
int **nspecial = atom->nspecial;
int *molindex = atom->molindex;
int *molatom = atom->molatom;
Molecule **onemols = atom->avec->onemols;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
@ -78,6 +92,11 @@ void NPairHalfSizeMultiOldNewtoffOmp::build(NeighList *list)
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
if (moltemplate) {
imol = molindex[i];
iatom = molatom[i];
tagprev = tag[i] - iatom - 1;
}
// loop over all atoms in other bins in stencil including self
// only store pair if i < j
@ -106,10 +125,23 @@ void NPairHalfSizeMultiOldNewtoffOmp::build(NeighList *list)
cutdistsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutdistsq) {
jh = j;
if (history && rsq < radsum*radsum)
neighptr[n++] = j ^ mask_history;
else
neighptr[n++] = j;
jh = jh ^ mask_history;
if (molecular != Atom::ATOMIC) {
if (!moltemplate)
which = find_special(special[i],nspecial[i],tag[j]);
else if (imol >=0)
which = find_special(onemols[imol]->special[iatom],
onemols[imol]->nspecial[iatom],
tag[j]-tagprev);
else which = 0;
if (which == 0) neighptr[n++] = jh;
else if (domain->minimum_image_check(delx,dely,delz))
neighptr[n++] = jh;
else if (which > 0) neighptr[n++] = jh ^ (which << SBBITS);
} else neighptr[n++] = jh;
}
}
}

View File

@ -15,7 +15,10 @@
#include "npair_half_size_multi_old_newton_omp.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "error.h"
#include "molecule.h"
#include "my_page.h"
#include "neigh_list.h"
#include "npair_omp.h"
@ -39,8 +42,10 @@ NPairHalfSizeMultiOldNewtonOmp::NPairHalfSizeMultiOldNewtonOmp(LAMMPS *lmp) :
void NPairHalfSizeMultiOldNewtonOmp::build(NeighList *list)
{
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
const int molecular = atom->molecular;
const int moltemplate = (molecular == Atom::TEMPLATE) ? 1 : 0;
const int history = list->history;
const int mask_history = 3 << SBBITS;
const int mask_history = 1 << HISTBITS;
NPAIR_OMP_INIT;
#if defined(_OPENMP)
@ -48,7 +53,8 @@ void NPairHalfSizeMultiOldNewtonOmp::build(NeighList *list)
#endif
NPAIR_OMP_SETUP(nlocal);
int i,j,k,n,itype,jtype,ibin,ns;
int i,j,jh,k,n,itype,jtype,ibin,ns,which,imol,iatom;
tagint tagprev;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
double radi,radsum,cutdistsq;
int *neighptr,*s;
@ -58,7 +64,14 @@ void NPairHalfSizeMultiOldNewtonOmp::build(NeighList *list)
double *radius = atom->radius;
int *type = atom->type;
int *mask = atom->mask;
tagint *tag = atom->tag;
tagint *molecule = atom->molecule;
tagint **special = atom->special;
int **nspecial = atom->nspecial;
int *molindex = atom->molindex;
int *molatom = atom->molatom;
Molecule **onemols = atom->avec->onemols;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
@ -78,6 +91,11 @@ void NPairHalfSizeMultiOldNewtonOmp::build(NeighList *list)
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
if (moltemplate) {
imol = molindex[i];
iatom = molatom[i];
tagprev = tag[i] - iatom - 1;
}
// loop over rest of atoms in i's bin, ghosts are at end of linked list
// if j is owned atom, store it, since j is beyond i in linked list
@ -102,10 +120,23 @@ void NPairHalfSizeMultiOldNewtonOmp::build(NeighList *list)
cutdistsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutdistsq) {
jh = j;
if (history && rsq < radsum*radsum)
neighptr[n++] = j ^ mask_history;
else
neighptr[n++] = j;
jh = jh ^ mask_history;
if (molecular != Atom::ATOMIC) {
if (!moltemplate)
which = find_special(special[i],nspecial[i],tag[j]);
else if (imol >=0)
which = find_special(onemols[imol]->special[iatom],
onemols[imol]->nspecial[iatom],
tag[j]-tagprev);
else which = 0;
if (which == 0) neighptr[n++] = jh;
else if (domain->minimum_image_check(delx,dely,delz))
neighptr[n++] = jh;
else if (which > 0) neighptr[n++] = jh ^ (which << SBBITS);
} else neighptr[n++] = jh;
}
}
@ -132,10 +163,23 @@ void NPairHalfSizeMultiOldNewtonOmp::build(NeighList *list)
cutdistsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutdistsq) {
jh = j;
if (history && rsq < radsum*radsum)
neighptr[n++] = j ^ mask_history;
else
neighptr[n++] = j;
jh = jh ^ mask_history;
if (molecular != Atom::ATOMIC) {
if (!moltemplate)
which = find_special(special[i],nspecial[i],tag[j]);
else if (imol >=0)
which = find_special(onemols[imol]->special[iatom],
onemols[imol]->nspecial[iatom],
tag[j]-tagprev);
else which = 0;
if (which == 0) neighptr[n++] = jh;
else if (domain->minimum_image_check(delx,dely,delz))
neighptr[n++] = jh;
else if (which > 0) neighptr[n++] = jh ^ (which << SBBITS);
} else neighptr[n++] = jh;
}
}
}

View File

@ -15,7 +15,10 @@
#include "npair_half_size_multi_old_newton_tri_omp.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "error.h"
#include "molecule.h"
#include "my_page.h"
#include "neigh_list.h"
#include "npair_omp.h"
@ -39,8 +42,10 @@ NPairHalfSizeMultiOldNewtonTriOmp::NPairHalfSizeMultiOldNewtonTriOmp(LAMMPS *lmp
void NPairHalfSizeMultiOldNewtonTriOmp::build(NeighList *list)
{
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
const int molecular = atom->molecular;
const int moltemplate = (molecular == Atom::TEMPLATE) ? 1 : 0;
const int history = list->history;
const int mask_history = 3 << SBBITS;
const int mask_history = 1 << HISTBITS;
NPAIR_OMP_INIT;
#if defined(_OPENMP)
@ -48,7 +53,8 @@ void NPairHalfSizeMultiOldNewtonTriOmp::build(NeighList *list)
#endif
NPAIR_OMP_SETUP(nlocal);
int i,j,k,n,itype,jtype,ibin,ns;
int i,j,jh,k,n,itype,jtype,ibin,ns,which,imol,iatom;
tagint tagprev;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
double radi,radsum,cutdistsq;
int *neighptr,*s;
@ -58,7 +64,14 @@ void NPairHalfSizeMultiOldNewtonTriOmp::build(NeighList *list)
double *radius = atom->radius;
int *type = atom->type;
int *mask = atom->mask;
tagint *tag = atom->tag;
tagint *molecule = atom->molecule;
tagint **special = atom->special;
int **nspecial = atom->nspecial;
int *molindex = atom->molindex;
int *molatom = atom->molatom;
Molecule **onemols = atom->avec->onemols;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
@ -78,6 +91,11 @@ void NPairHalfSizeMultiOldNewtonTriOmp::build(NeighList *list)
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
if (moltemplate) {
imol = molindex[i];
iatom = molatom[i];
tagprev = tag[i] - iatom - 1;
}
// loop over all atoms in bins, including self, in stencil
// skip if i,j neighbor cutoff is less than bin distance
@ -115,10 +133,23 @@ void NPairHalfSizeMultiOldNewtonTriOmp::build(NeighList *list)
cutdistsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutdistsq) {
jh = j;
if (history && rsq < radsum*radsum)
neighptr[n++] = j ^ mask_history;
else
neighptr[n++] = j;
jh = jh ^ mask_history;
if (molecular != Atom::ATOMIC) {
if (!moltemplate)
which = find_special(special[i],nspecial[i],tag[j]);
else if (imol >=0)
which = find_special(onemols[imol]->special[iatom],
onemols[imol]->nspecial[iatom],
tag[j]-tagprev);
else which = 0;
if (which == 0) neighptr[n++] = jh;
else if (domain->minimum_image_check(delx,dely,delz))
neighptr[n++] = jh;
else if (which > 0) neighptr[n++] = jh ^ (which << SBBITS);
} else neighptr[n++] = jh;
}
}
}

View File

@ -15,7 +15,10 @@
#include "npair_half_size_nsq_newtoff_omp.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "error.h"
#include "molecule.h"
#include "group.h"
#include "my_page.h"
#include "neigh_list.h"
@ -42,8 +45,10 @@ void NPairHalfSizeNsqNewtoffOmp::build(NeighList *list)
{
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
const int bitmask = (includegroup) ? group->bitmask[includegroup] : 0;
const int molecular = atom->molecular;
const int moltemplate = (molecular == Atom::TEMPLATE) ? 1 : 0;
const int history = list->history;
const int mask_history = 3 << SBBITS;
const int mask_history = 1 << HISTBITS;
NPAIR_OMP_INIT;
@ -52,7 +57,8 @@ void NPairHalfSizeNsqNewtoffOmp::build(NeighList *list)
#endif
NPAIR_OMP_SETUP(nlocal);
int i,j,n;
int i,j,jh,n,which,imol,iatom;
tagint tagprev;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
double radi,radsum,cutsq;
int *neighptr;
@ -61,9 +67,17 @@ void NPairHalfSizeNsqNewtoffOmp::build(NeighList *list)
double *radius = atom->radius;
int *type = atom->type;
int *mask = atom->mask;
tagint *tag = atom->tag;
tagint *molecule = atom->molecule;
tagint **special = atom->special;
int **nspecial = atom->nspecial;
int nall = atom->nlocal + atom->nghost;
int *molindex = atom->molindex;
int *molatom = atom->molatom;
Molecule **onemols = atom->avec->onemols;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
@ -81,6 +95,11 @@ void NPairHalfSizeNsqNewtoffOmp::build(NeighList *list)
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
if (moltemplate) {
imol = molindex[i];
iatom = molatom[i];
tagprev = tag[i] - iatom - 1;
}
// loop over remaining atoms, owned and ghost
@ -96,10 +115,23 @@ void NPairHalfSizeNsqNewtoffOmp::build(NeighList *list)
cutsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutsq) {
jh = j;
if (history && rsq < radsum*radsum)
neighptr[n++] = j ^ mask_history;
else
neighptr[n++] = j;
jh = jh ^ mask_history;
if (molecular != Atom::ATOMIC) {
if (!moltemplate)
which = find_special(special[i],nspecial[i],tag[j]);
else if (imol >=0)
which = find_special(onemols[imol]->special[iatom],
onemols[imol]->nspecial[iatom],
tag[j]-tagprev);
else which = 0;
if (which == 0) neighptr[n++] = jh;
else if (domain->minimum_image_check(delx,dely,delz))
neighptr[n++] = jh;
else if (which > 0) neighptr[n++] = jh ^ (which << SBBITS);
} else neighptr[n++] = jh;
}
}

View File

@ -15,7 +15,10 @@
#include "npair_half_size_nsq_newton_omp.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "error.h"
#include "molecule.h"
#include "group.h"
#include "my_page.h"
#include "neigh_list.h"
@ -42,9 +45,11 @@ NPairHalfSizeNsqNewtonOmp::NPairHalfSizeNsqNewtonOmp(LAMMPS *lmp) :
void NPairHalfSizeNsqNewtonOmp::build(NeighList *list)
{
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
const int bitmask = (includegroup) ? group->bitmask[includegroup] : 0;;
const int bitmask = (includegroup) ? group->bitmask[includegroup] : 0;
const int molecular = atom->molecular;
const int moltemplate = (molecular == Atom::TEMPLATE) ? 1 : 0;
const int history = list->history;
const int mask_history = 3 << SBBITS;
const int mask_history = 1 << HISTBITS;
NPAIR_OMP_INIT;
@ -53,7 +58,8 @@ void NPairHalfSizeNsqNewtonOmp::build(NeighList *list)
#endif
NPAIR_OMP_SETUP(nlocal);
int i,j,n,itag,jtag;
int i,j,jh,n,itag,jtag,which,imol,iatom;
tagint tagprev;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
double radi,radsum,cutsq;
int *neighptr;
@ -64,6 +70,13 @@ void NPairHalfSizeNsqNewtonOmp::build(NeighList *list)
int *type = atom->type;
int *mask = atom->mask;
tagint *molecule = atom->molecule;
tagint **special = atom->special;
int **nspecial = atom->nspecial;
int *molindex = atom->molindex;
int *molatom = atom->molatom;
Molecule **onemols = atom->avec->onemols;
int nall = atom->nlocal + atom->nghost;
int *ilist = list->ilist;
@ -84,6 +97,11 @@ void NPairHalfSizeNsqNewtonOmp::build(NeighList *list)
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
if (moltemplate) {
imol = molindex[i];
iatom = molatom[i];
tagprev = tag[i] - iatom - 1;
}
// loop over remaining atoms, owned and ghost
@ -115,10 +133,23 @@ void NPairHalfSizeNsqNewtonOmp::build(NeighList *list)
cutsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutsq) {
jh = j;
if (history && rsq < radsum*radsum)
neighptr[n++] = j ^ mask_history;
else
neighptr[n++] = j;
jh = jh ^ mask_history;
if (molecular != Atom::ATOMIC) {
if (!moltemplate)
which = find_special(special[i],nspecial[i],tag[j]);
else if (imol >=0)
which = find_special(onemols[imol]->special[iatom],
onemols[imol]->nspecial[iatom],
tag[j]-tagprev);
else which = 0;
if (which == 0) neighptr[n++] = jh;
else if (domain->minimum_image_check(delx,dely,delz))
neighptr[n++] = jh;
else if (which > 0) neighptr[n++] = jh ^ (which << SBBITS);
} else neighptr[n++] = jh;
}
}

View File

@ -24,6 +24,7 @@ Contributing Author: Jacob Gissinger (jacob.r.gissinger@gmail.com)
#include "comm.h"
#include "domain.h"
#include "error.h"
#include "fix_bond_history.h"
#include "force.h"
#include "group.h"
#include "input.h"
@ -3093,6 +3094,10 @@ void FixBondReact::update_everything()
// next let's update bond info
// cool thing is, newton_bond issues are already taken care of in templates
// same with class2 improper issues, which is why this fix started in the first place
// also need to find any instances of bond history to update histories
auto histories = modify->get_fix_by_style("BOND_HISTORY");
int n_histories = histories.size();
for (int i = 0; i < update_num_mega; i++) {
rxnID = update_mega_glove[0][i];
twomol = atom->molecules[reacted_mol[rxnID]];
@ -3102,6 +3107,14 @@ void FixBondReact::update_everything()
if (atom->map(update_mega_glove[jj+1][i]) < nlocal && atom->map(update_mega_glove[jj+1][i]) >= 0) {
if (landlocked_atoms[j][rxnID] == 1) {
delta_bonds -= num_bond[atom->map(update_mega_glove[jj+1][i])];
// If deleting all bonds, first cache then remove all histories
if (n_histories > 0)
for (auto &ihistory: histories) {
for (int n = 0; n < num_bond[atom->map(update_mega_glove[jj+1][i])]; n++)
dynamic_cast<FixBondHistory *>(ihistory)->cache_history(atom->map(update_mega_glove[jj+1][i]), n);
for (int n = 0; n < num_bond[atom->map(update_mega_glove[jj+1][i])]; n++)
dynamic_cast<FixBondHistory *>(ihistory)->delete_history(atom->map(update_mega_glove[jj+1][i]), 0);
}
num_bond[atom->map(update_mega_glove[jj+1][i])] = 0;
}
if (landlocked_atoms[j][rxnID] == 0) {
@ -3109,10 +3122,21 @@ void FixBondReact::update_everything()
for (int n = 0; n < twomol->natoms; n++) {
int nn = equivalences[n][1][rxnID]-1;
if (n!=j && bond_atom[atom->map(update_mega_glove[jj+1][i])][p] == update_mega_glove[nn+1][i] && landlocked_atoms[n][rxnID] == 1) {
// Cache history information, shift history, then delete final element
if (n_histories > 0)
for (auto &ihistory: histories)
dynamic_cast<FixBondHistory *>(ihistory)->cache_history(atom->map(update_mega_glove[jj+1][i]), p);
for (int m = p; m < num_bond[atom->map(update_mega_glove[jj+1][i])]-1; m++) {
bond_type[atom->map(update_mega_glove[jj+1][i])][m] = bond_type[atom->map(update_mega_glove[jj+1][i])][m+1];
bond_atom[atom->map(update_mega_glove[jj+1][i])][m] = bond_atom[atom->map(update_mega_glove[jj+1][i])][m+1];
if (n_histories > 0)
for (auto &ihistory: histories)
dynamic_cast<FixBondHistory *>(ihistory)->shift_history(atom->map(update_mega_glove[jj+1][i]),m,m+1);
}
if (n_histories > 0)
for (auto &ihistory: histories)
dynamic_cast<FixBondHistory *>(ihistory)->delete_history(atom->map(update_mega_glove[jj+1][i]),
num_bond[atom->map(update_mega_glove[jj+1][i])]-1);
num_bond[atom->map(update_mega_glove[jj+1][i])]--;
delta_bonds--;
}
@ -3131,6 +3155,10 @@ void FixBondReact::update_everything()
for (int p = 0; p < twomol->num_bond[j]; p++) {
bond_type[atom->map(update_mega_glove[jj+1][i])][p] = twomol->bond_type[j][p];
bond_atom[atom->map(update_mega_glove[jj+1][i])][p] = update_mega_glove[equivalences[twomol->bond_atom[j][p]-1][1][rxnID]][i];
// Check cached history data to see if bond regenerated
if (n_histories > 0)
for (auto &ihistory: histories)
dynamic_cast<FixBondHistory *>(ihistory)->check_cache(atom->map(update_mega_glove[jj+1][i]), p);
}
}
if (landlocked_atoms[j][rxnID] == 0) {
@ -3139,6 +3167,10 @@ void FixBondReact::update_everything()
insert_num = num_bond[atom->map(update_mega_glove[jj+1][i])];
bond_type[atom->map(update_mega_glove[jj+1][i])][insert_num] = twomol->bond_type[j][p];
bond_atom[atom->map(update_mega_glove[jj+1][i])][insert_num] = update_mega_glove[equivalences[twomol->bond_atom[j][p]-1][1][rxnID]][i];
// Check cached history data to see if bond regenerated
if (n_histories > 0)
for (auto &ihistory: histories)
dynamic_cast<FixBondHistory *>(ihistory)->check_cache(atom->map(update_mega_glove[jj+1][i]), insert_num);
num_bond[atom->map(update_mega_glove[jj+1][i])]++;
if (num_bond[atom->map(update_mega_glove[jj+1][i])] > atom->bond_per_atom)
error->one(FLERR,"Bond/react topology/atom exceed system topology/atom");
@ -3150,6 +3182,10 @@ void FixBondReact::update_everything()
}
}
if (n_histories > 0)
for (auto &ihistory: histories)
dynamic_cast<FixBondHistory *>(ihistory)->clear_cache();
// Angles! First let's delete all angle info:
if (force->angle && twomol->angleflag) {
int *num_angle = atom->num_angle;

View File

@ -128,6 +128,7 @@ Atom::Atom(LAMMPS *lmp) : Pointers(lmp)
omega = angmom = torque = nullptr;
radius = rmass = nullptr;
ellipsoid = line = tri = body = nullptr;
quat = nullptr;
// molecular systems
@ -426,6 +427,10 @@ void Atom::peratom_create()
add_peratom("tri",&tri,INT,0);
add_peratom("body",&body,INT,0);
// BPM package
add_peratom("quat",&quat,DOUBLE,4);
// MOLECULE package
add_peratom("molecule",&molecule,tagintsize,0);
@ -646,6 +651,7 @@ void Atom::set_atomflag_defaults()
// identical list as 2nd customization in atom.h
sphere_flag = ellipsoid_flag = line_flag = tri_flag = body_flag = 0;
quat_flag = 0;
peri_flag = electron_flag = 0;
wavepacket_flag = sph_flag = 0;
molecule_flag = molindex_flag = molatom_flag = 0;
@ -1889,8 +1895,7 @@ void Atom::add_molecule(int narg, char **arg)
int index = 1;
while (true) {
molecules = (Molecule **)
memory->srealloc(molecules,(nmolecule+1)*sizeof(Molecule *),
"atom::molecules");
memory->srealloc(molecules,(nmolecule+1)*sizeof(Molecule *), "atom::molecules");
molecules[nmolecule] = new Molecule(lmp,narg,arg,index);
molecules[nmolecule]->nset = 0;
molecules[nmolecule-ifile+1]->nset++;
@ -1920,8 +1925,7 @@ int Atom::find_molecule(char *id)
called by fixes and commands that add molecules
------------------------------------------------------------------------- */
void Atom::add_molecule_atom(Molecule *onemol, int iatom,
int ilocal, tagint offset)
void Atom::add_molecule_atom(Molecule *onemol, int iatom, int ilocal, tagint offset)
{
if (onemol->qflag && q_flag) q[ilocal] = onemol->q[iatom];
if (onemol->radiusflag && radius_flag) radius[ilocal] = onemol->radius[iatom];
@ -1936,6 +1940,19 @@ void Atom::add_molecule_atom(Molecule *onemol, int iatom,
onemol->avec_body->set_quat(ilocal,onemol->quat_external);
}
// initialize custom per-atom properties to zero if present
for (int i = 0; i < nivector; ++i)
ivector[i][ilocal] = 0;
for (int i = 0; i < ndvector; ++i)
dvector[i][ilocal] = 0.0;
for (int i = 0; i < niarray; ++i)
for (int j = 0; j < icols[i]; ++j)
iarray[i][ilocal][j] = 0;
for (int i = 0; i < ndarray; ++i)
for (int j = 0; j < dcols[i]; ++j)
darray[i][ilocal][j] = 0.0;
if (molecular != Atom::MOLECULAR) return;
// add bond topology info
@ -2614,6 +2631,10 @@ length of the data area, and a short description.
- int
- 1
- 1 if the particle is a body particle, 0 if not
* - quat
- double
- 4
- four quaternion components of the particles
* - i_name
- int
- 1
@ -2669,6 +2690,7 @@ void *Atom::extract(const char *name)
if (strcmp(name,"line") == 0) return (void *) line;
if (strcmp(name,"tri") == 0) return (void *) tri;
if (strcmp(name,"body") == 0) return (void *) body;
if (strcmp(name,"quat") == 0) return (void *) quat;
if (strcmp(name,"vfrac") == 0) return (void *) vfrac;
if (strcmp(name,"s0") == 0) return (void *) s0;
@ -2791,6 +2813,7 @@ int Atom::extract_datatype(const char *name)
if (strcmp(name,"line") == 0) return LAMMPS_INT;
if (strcmp(name,"tri") == 0) return LAMMPS_INT;
if (strcmp(name,"body") == 0) return LAMMPS_INT;
if (strcmp(name,"quat") == 0) return LAMMPS_DOUBLE_2D;
if (strcmp(name,"vfrac") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"s0") == 0) return LAMMPS_DOUBLE;

View File

@ -79,6 +79,7 @@ class Atom : protected Pointers {
double *radius;
double **omega, **angmom, **torque;
int *ellipsoid, *line, *tri, *body;
double **quat;
// molecular systems
@ -180,7 +181,7 @@ class Atom : protected Pointers {
int molecule_flag, molindex_flag, molatom_flag;
int q_flag, mu_flag;
int rmass_flag, radius_flag, omega_flag, torque_flag, angmom_flag;
int rmass_flag, radius_flag, omega_flag, torque_flag, angmom_flag, quat_flag;
int vfrac_flag, spin_flag, eradius_flag, ervel_flag, erforce_flag;
int cs_flag, csforce_flag, vforce_flag, ervelforce_flag, etag_flag;
int rho_flag, esph_flag, cv_flag, vest_flag;

View File

@ -6,7 +6,7 @@
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 distributead under
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.

View File

@ -27,6 +27,10 @@ using namespace LAMMPS_NS;
enum { NONE, LINEAR, SPLINE };
// allocate space for static class instance variable and initialize it
int Bond::instance_total = 0;
/* -----------------------------------------------------------------------
set bond contribution to Vdwl energy to 0.0
a particular bond style can override this
@ -34,12 +38,17 @@ enum { NONE, LINEAR, SPLINE };
Bond::Bond(LAMMPS *_lmp) : Pointers(_lmp)
{
instance_me = instance_total++;
energy = 0.0;
virial[0] = virial[1] = virial[2] = virial[3] = virial[4] = virial[5] = 0.0;
writedata = 1;
comm_forward = comm_reverse = comm_reverse_off = 0;
allocated = 0;
suffix_flag = Suffix::NONE;
partial_flag = 0;
maxeatom = maxvatom = 0;
eatom = nullptr;

View File

@ -23,13 +23,20 @@ class Bond : protected Pointers {
friend class FixOMP;
public:
static int instance_total; // # of Bond classes ever instantiated
int allocated;
int *setflag;
int partial_flag; // 1 if bond type can be set to 0 and deleted
int writedata; // 1 if writes coeffs to data file
double energy; // accumulated energies
double virial[6]; // accumulated virial: xx,yy,zz,xy,xz,yz
double *eatom, **vatom; // accumulated per-atom energy/virial
int comm_forward; // size of forward communication (0 if none)
int comm_reverse; // size of reverse communication (0 if none)
int comm_reverse_off; // size of reverse comm even if newton off
int reinitflag; // 1 if compatible with fix adapt and alike
// KOKKOS host/device flag and data masks
@ -55,10 +62,15 @@ class Bond : protected Pointers {
virtual double memory_usage();
virtual void *extract(const char *, int &) { return nullptr; }
virtual void reinit();
virtual int pack_forward_comm(int, int *, double *, int, int *) {return 0;}
virtual void unpack_forward_comm(int, int, double *) {}
virtual int pack_reverse_comm(int, int, double *) {return 0;}
virtual void unpack_reverse_comm(int, int *, double *) {}
void write_file(int, char **);
protected:
int instance_me; // which Bond class instantiation I am
int suffix_flag; // suffix compatibility flag
int evflag;

View File

@ -218,6 +218,9 @@ void Comm::init()
if (force->pair) maxforward = MAX(maxforward,force->pair->comm_forward);
if (force->pair) maxreverse = MAX(maxreverse,force->pair->comm_reverse);
if (force->bond) maxforward = MAX(maxforward,force->bond->comm_forward);
if (force->bond) maxreverse = MAX(maxreverse,force->bond->comm_reverse);
for (const auto &fix : fix_list) {
maxforward = MAX(maxforward,fix->comm_forward);
maxreverse = MAX(maxreverse,fix->comm_reverse);
@ -235,6 +238,7 @@ void Comm::init()
if (force->newton == 0) maxreverse = 0;
if (force->pair) maxreverse = MAX(maxreverse,force->pair->comm_reverse_off);
if (force->bond) maxreverse = MAX(maxreverse,force->bond->comm_reverse_off);
// maxexchange_atom = size of an exchanged atom, set by AtomVec
// only needs to be set if size > BUFEXTRA

View File

@ -80,10 +80,12 @@ class Comm : protected Pointers {
virtual void exchange() = 0; // move atoms to new procs
virtual void borders() = 0; // setup list of atoms to comm
// forward/reverse comm from a Pair, Fix, Compute, Dump
// forward/reverse comm from a Pair, Bond, Fix, Compute, Dump
virtual void forward_comm(class Pair *) = 0;
virtual void reverse_comm(class Pair *) = 0;
virtual void forward_comm(class Bond *) = 0;
virtual void reverse_comm(class Bond *) = 0;
virtual void forward_comm(class Fix *, int size = 0) = 0;
virtual void reverse_comm(class Fix *, int size = 0) = 0;
virtual void reverse_comm_variable(class Fix *) = 0;

View File

@ -20,6 +20,7 @@
#include "atom.h"
#include "atom_vec.h"
#include "bond.h"
#include "compute.h"
#include "domain.h"
#include "dump.h"
@ -490,8 +491,7 @@ void CommBrick::setup()
return how many procs away are needed to encompass cutghost away from loc
------------------------------------------------------------------------- */
int CommBrick::updown(int dim, int dir, int loc,
double prd, int periodicity, double *split)
int CommBrick::updown(int dim, int dir, int loc, double prd, int periodicity, double *split)
{
int index,count;
double frac,delta;
@ -552,19 +552,15 @@ void CommBrick::forward_comm(int /*dummy*/)
if (comm_x_only) {
if (size_forward_recv[iswap]) {
buf = x[firstrecv[iswap]];
MPI_Irecv(buf,size_forward_recv[iswap],MPI_DOUBLE,
recvproc[iswap],0,world,&request);
MPI_Irecv(buf,size_forward_recv[iswap],MPI_DOUBLE,recvproc[iswap],0,world,&request);
}
n = avec->pack_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
n = avec->pack_comm(sendnum[iswap],sendlist[iswap],buf_send,pbc_flag[iswap],pbc[iswap]);
if (n) MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
if (size_forward_recv[iswap]) MPI_Wait(&request,MPI_STATUS_IGNORE);
} else if (ghost_velocity) {
if (size_forward_recv[iswap])
MPI_Irecv(buf_recv,size_forward_recv[iswap],MPI_DOUBLE,
recvproc[iswap],0,world,&request);
n = avec->pack_comm_vel(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
MPI_Irecv(buf_recv,size_forward_recv[iswap],MPI_DOUBLE,recvproc[iswap],0,world,&request);
n = avec->pack_comm_vel(sendnum[iswap],sendlist[iswap],buf_send,pbc_flag[iswap],pbc[iswap]);
if (n) MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
if (size_forward_recv[iswap]) MPI_Wait(&request,MPI_STATUS_IGNORE);
avec->unpack_comm_vel(recvnum[iswap],firstrecv[iswap],buf_recv);
@ -572,8 +568,7 @@ void CommBrick::forward_comm(int /*dummy*/)
if (size_forward_recv[iswap])
MPI_Irecv(buf_recv,size_forward_recv[iswap],MPI_DOUBLE,
recvproc[iswap],0,world,&request);
n = avec->pack_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
n = avec->pack_comm(sendnum[iswap],sendlist[iswap],buf_send,pbc_flag[iswap],pbc[iswap]);
if (n) MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
if (size_forward_recv[iswap]) MPI_Wait(&request,MPI_STATUS_IGNORE);
avec->unpack_comm(recvnum[iswap],firstrecv[iswap],buf_recv);
@ -585,12 +580,10 @@ void CommBrick::forward_comm(int /*dummy*/)
avec->pack_comm(sendnum[iswap],sendlist[iswap],
x[firstrecv[iswap]],pbc_flag[iswap],pbc[iswap]);
} else if (ghost_velocity) {
avec->pack_comm_vel(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
avec->pack_comm_vel(sendnum[iswap],sendlist[iswap],buf_send,pbc_flag[iswap],pbc[iswap]);
avec->unpack_comm_vel(recvnum[iswap],firstrecv[iswap],buf_send);
} else {
avec->pack_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
avec->pack_comm(sendnum[iswap],sendlist[iswap],buf_send,pbc_flag[iswap],pbc[iswap]);
avec->unpack_comm(recvnum[iswap],firstrecv[iswap],buf_send);
}
}
@ -618,18 +611,15 @@ void CommBrick::reverse_comm()
if (sendproc[iswap] != me) {
if (comm_f_only) {
if (size_reverse_recv[iswap])
MPI_Irecv(buf_recv,size_reverse_recv[iswap],MPI_DOUBLE,
sendproc[iswap],0,world,&request);
MPI_Irecv(buf_recv,size_reverse_recv[iswap],MPI_DOUBLE,sendproc[iswap],0,world,&request);
if (size_reverse_send[iswap]) {
buf = f[firstrecv[iswap]];
MPI_Send(buf,size_reverse_send[iswap],MPI_DOUBLE,
recvproc[iswap],0,world);
MPI_Send(buf,size_reverse_send[iswap],MPI_DOUBLE,recvproc[iswap],0,world);
}
if (size_reverse_recv[iswap]) MPI_Wait(&request,MPI_STATUS_IGNORE);
} else {
if (size_reverse_recv[iswap])
MPI_Irecv(buf_recv,size_reverse_recv[iswap],MPI_DOUBLE,
sendproc[iswap],0,world,&request);
MPI_Irecv(buf_recv,size_reverse_recv[iswap],MPI_DOUBLE,sendproc[iswap],0,world,&request);
n = avec->pack_reverse(recvnum[iswap],firstrecv[iswap],buf_send);
if (n) MPI_Send(buf_send,n,MPI_DOUBLE,recvproc[iswap],0,world);
if (size_reverse_recv[iswap]) MPI_Wait(&request,MPI_STATUS_IGNORE);
@ -639,8 +629,7 @@ void CommBrick::reverse_comm()
} else {
if (comm_f_only) {
if (sendnum[iswap])
avec->unpack_reverse(sendnum[iswap],sendlist[iswap],
f[firstrecv[iswap]]);
avec->unpack_reverse(sendnum[iswap],sendlist[iswap],f[firstrecv[iswap]]);
} else {
avec->pack_reverse(recvnum[iswap],firstrecv[iswap],buf_send);
avec->unpack_reverse(sendnum[iswap],sendlist[iswap],buf_send);
@ -733,25 +722,21 @@ void CommBrick::exchange()
if (procgrid[dim] == 1) nrecv = 0;
else {
MPI_Sendrecv(&nsend,1,MPI_INT,procneigh[dim][0],0,
&nrecv1,1,MPI_INT,procneigh[dim][1],0,world,
MPI_STATUS_IGNORE);
&nrecv1,1,MPI_INT,procneigh[dim][1],0,world,MPI_STATUS_IGNORE);
nrecv = nrecv1;
if (procgrid[dim] > 2) {
MPI_Sendrecv(&nsend,1,MPI_INT,procneigh[dim][1],0,
&nrecv2,1,MPI_INT,procneigh[dim][0],0,world,
MPI_STATUS_IGNORE);
&nrecv2,1,MPI_INT,procneigh[dim][0],0,world,MPI_STATUS_IGNORE);
nrecv += nrecv2;
}
if (nrecv > maxrecv) grow_recv(nrecv);
MPI_Irecv(buf_recv,nrecv1,MPI_DOUBLE,procneigh[dim][1],0,
world,&request);
MPI_Irecv(buf_recv,nrecv1,MPI_DOUBLE,procneigh[dim][1],0,world,&request);
MPI_Send(buf_send,nsend,MPI_DOUBLE,procneigh[dim][0],0,world);
MPI_Wait(&request,MPI_STATUS_IGNORE);
if (procgrid[dim] > 2) {
MPI_Irecv(&buf_recv[nrecv1],nrecv2,MPI_DOUBLE,procneigh[dim][0],0,
world,&request);
MPI_Irecv(&buf_recv[nrecv1],nrecv2,MPI_DOUBLE,procneigh[dim][0],0,world,&request);
MPI_Send(buf_send,nsend,MPI_DOUBLE,procneigh[dim][1],0,world);
MPI_Wait(&request,MPI_STATUS_IGNORE);
}
@ -925,11 +910,9 @@ void CommBrick::borders()
if (nsend*size_border > maxsend) grow_send(nsend*size_border,0);
if (ghost_velocity)
n = avec->pack_border_vel(nsend,sendlist[iswap],buf_send,
pbc_flag[iswap],pbc[iswap]);
n = avec->pack_border_vel(nsend,sendlist[iswap],buf_send,pbc_flag[iswap],pbc[iswap]);
else
n = avec->pack_border(nsend,sendlist[iswap],buf_send,
pbc_flag[iswap],pbc[iswap]);
n = avec->pack_border(nsend,sendlist[iswap],buf_send,pbc_flag[iswap],pbc[iswap]);
// swap atoms with other proc
// no MPI calls except SendRecv if nsend/nrecv = 0
@ -938,8 +921,7 @@ void CommBrick::borders()
if (sendproc[iswap] != me) {
MPI_Sendrecv(&nsend,1,MPI_INT,sendproc[iswap],0,
&nrecv,1,MPI_INT,recvproc[iswap],0,world,
MPI_STATUS_IGNORE);
&nrecv,1,MPI_INT,recvproc[iswap],0,world,MPI_STATUS_IGNORE);
if (nrecv*size_border > maxrecv) grow_recv(nrecv*size_border);
if (nrecv) MPI_Irecv(buf_recv,nrecv*size_border,MPI_DOUBLE,
recvproc[iswap],0,world,&request);
@ -1013,16 +995,14 @@ void CommBrick::forward_comm(Pair *pair)
// pack buffer
n = pair->pack_forward_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
n = pair->pack_forward_comm(sendnum[iswap],sendlist[iswap],buf_send,pbc_flag[iswap],pbc[iswap]);
// exchange with another proc
// if self, set recv buffer to send buffer
if (sendproc[iswap] != me) {
if (recvnum[iswap])
MPI_Irecv(buf_recv,nsize*recvnum[iswap],MPI_DOUBLE,
recvproc[iswap],0,world,&request);
MPI_Irecv(buf_recv,nsize*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,world,&request);
if (sendnum[iswap])
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
if (recvnum[iswap]) MPI_Wait(&request,MPI_STATUS_IGNORE);
@ -1059,8 +1039,7 @@ void CommBrick::reverse_comm(Pair *pair)
if (sendproc[iswap] != me) {
if (sendnum[iswap])
MPI_Irecv(buf_recv,nsize*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,
world,&request);
MPI_Irecv(buf_recv,nsize*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,world,&request);
if (recvnum[iswap])
MPI_Send(buf_send,n,MPI_DOUBLE,recvproc[iswap],0,world);
if (sendnum[iswap]) MPI_Wait(&request,MPI_STATUS_IGNORE);
@ -1073,6 +1052,80 @@ void CommBrick::reverse_comm(Pair *pair)
}
}
/* ----------------------------------------------------------------------
forward communication invoked by a Bond
nsize used only to set recv buffer limit
------------------------------------------------------------------------- */
void CommBrick::forward_comm(Bond *bond)
{
int iswap,n;
double *buf;
MPI_Request request;
int nsize = bond->comm_forward;
for (iswap = 0; iswap < nswap; iswap++) {
// pack buffer
n = bond->pack_forward_comm(sendnum[iswap],sendlist[iswap],buf_send,pbc_flag[iswap],pbc[iswap]);
// exchange with another proc
// if self, set recv buffer to send buffer
if (sendproc[iswap] != me) {
if (recvnum[iswap])
MPI_Irecv(buf_recv,nsize*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,world,&request);
if (sendnum[iswap])
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
if (recvnum[iswap]) MPI_Wait(&request,MPI_STATUS_IGNORE);
buf = buf_recv;
} else buf = buf_send;
// unpack buffer
bond->unpack_forward_comm(recvnum[iswap],firstrecv[iswap],buf);
}
}
/* ----------------------------------------------------------------------
reverse communication invoked by a Bond
nsize used only to set recv buffer limit
------------------------------------------------------------------------- */
void CommBrick::reverse_comm(Bond *bond)
{
int iswap,n;
double *buf;
MPI_Request request;
int nsize = MAX(bond->comm_reverse,bond->comm_reverse_off);
for (iswap = nswap-1; iswap >= 0; iswap--) {
// pack buffer
n = bond->pack_reverse_comm(recvnum[iswap],firstrecv[iswap],buf_send);
// exchange with another proc
// if self, set recv buffer to send buffer
if (sendproc[iswap] != me) {
if (sendnum[iswap])
MPI_Irecv(buf_recv,nsize*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,world,&request);
if (recvnum[iswap])
MPI_Send(buf_send,n,MPI_DOUBLE,recvproc[iswap],0,world);
if (sendnum[iswap]) MPI_Wait(&request,MPI_STATUS_IGNORE);
buf = buf_recv;
} else buf = buf_send;
// unpack buffer
bond->unpack_reverse_comm(sendnum[iswap],sendlist[iswap],buf);
}
}
/* ----------------------------------------------------------------------
forward communication invoked by a Fix
size/nsize used only to set recv buffer limit
@ -1095,16 +1148,14 @@ void CommBrick::forward_comm(Fix *fix, int size)
// pack buffer
n = fix->pack_forward_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
n = fix->pack_forward_comm(sendnum[iswap],sendlist[iswap],buf_send,pbc_flag[iswap],pbc[iswap]);
// exchange with another proc
// if self, set recv buffer to send buffer
if (sendproc[iswap] != me) {
if (recvnum[iswap])
MPI_Irecv(buf_recv,nsize*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,
world,&request);
MPI_Irecv(buf_recv,nsize*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,world,&request);
if (sendnum[iswap])
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
if (recvnum[iswap]) MPI_Wait(&request,MPI_STATUS_IGNORE);
@ -1146,8 +1197,7 @@ void CommBrick::reverse_comm(Fix *fix, int size)
if (sendproc[iswap] != me) {
if (sendnum[iswap])
MPI_Irecv(buf_recv,nsize*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,
world,&request);
MPI_Irecv(buf_recv,nsize*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,world,&request);
if (recvnum[iswap])
MPI_Send(buf_send,n,MPI_DOUBLE,recvproc[iswap],0,world);
if (sendnum[iswap]) MPI_Wait(&request,MPI_STATUS_IGNORE);
@ -1185,13 +1235,11 @@ void CommBrick::reverse_comm_variable(Fix *fix)
if (sendproc[iswap] != me) {
MPI_Sendrecv(&nsend,1,MPI_INT,recvproc[iswap],0,
&nrecv,1,MPI_INT,sendproc[iswap],0,world,
MPI_STATUS_IGNORE);
&nrecv,1,MPI_INT,sendproc[iswap],0,world,MPI_STATUS_IGNORE);
if (sendnum[iswap]) {
if (nrecv > maxrecv) grow_recv(nrecv);
MPI_Irecv(buf_recv,maxrecv,MPI_DOUBLE,sendproc[iswap],0,
world,&request);
MPI_Irecv(buf_recv,maxrecv,MPI_DOUBLE,sendproc[iswap],0,world,&request);
}
if (recvnum[iswap])
MPI_Send(buf_send,nsend,MPI_DOUBLE,recvproc[iswap],0,world);
@ -1230,8 +1278,7 @@ void CommBrick::forward_comm(Compute *compute)
if (sendproc[iswap] != me) {
if (recvnum[iswap])
MPI_Irecv(buf_recv,nsize*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,
world,&request);
MPI_Irecv(buf_recv,nsize*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,world,&request);
if (sendnum[iswap])
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
if (recvnum[iswap]) MPI_Wait(&request,MPI_STATUS_IGNORE);
@ -1268,8 +1315,7 @@ void CommBrick::reverse_comm(Compute *compute)
if (sendproc[iswap] != me) {
if (sendnum[iswap])
MPI_Irecv(buf_recv,nsize*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,
world,&request);
MPI_Irecv(buf_recv,nsize*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,world,&request);
if (recvnum[iswap])
MPI_Send(buf_send,n,MPI_DOUBLE,recvproc[iswap],0,world);
if (sendnum[iswap]) MPI_Wait(&request,MPI_STATUS_IGNORE);
@ -1307,8 +1353,7 @@ void CommBrick::forward_comm(Dump *dump)
if (sendproc[iswap] != me) {
if (recvnum[iswap])
MPI_Irecv(buf_recv,nsize*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,
world,&request);
MPI_Irecv(buf_recv,nsize*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,world,&request);
if (sendnum[iswap])
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
if (recvnum[iswap]) MPI_Wait(&request,MPI_STATUS_IGNORE);
@ -1345,8 +1390,7 @@ void CommBrick::reverse_comm(Dump *dump)
if (sendproc[iswap] != me) {
if (sendnum[iswap])
MPI_Irecv(buf_recv,nsize*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,
world,&request);
MPI_Irecv(buf_recv,nsize*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,world,&request);
if (recvnum[iswap])
MPI_Send(buf_send,n,MPI_DOUBLE,recvproc[iswap],0,world);
if (sendnum[iswap]) MPI_Wait(&request,MPI_STATUS_IGNORE);
@ -1394,11 +1438,9 @@ void CommBrick::forward_comm_array(int nsize, double **array)
if (sendproc[iswap] != me) {
if (recvnum[iswap])
MPI_Irecv(buf_recv,nsize*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,
world,&request);
MPI_Irecv(buf_recv,nsize*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,world,&request);
if (sendnum[iswap])
MPI_Send(buf_send,nsize*sendnum[iswap],MPI_DOUBLE,
sendproc[iswap],0,world);
MPI_Send(buf_send,nsize*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,world);
if (recvnum[iswap]) MPI_Wait(&request,MPI_STATUS_IGNORE);
buf = buf_recv;
} else buf = buf_send;
@ -1444,21 +1486,18 @@ int CommBrick::exchange_variable(int n, double *inbuf, double *&outbuf)
nrecv += nrecv1;
if (procgrid[dim] > 2) {
MPI_Sendrecv(&nsend,1,MPI_INT,procneigh[dim][1],0,
&nrecv2,1,MPI_INT,procneigh[dim][0],0,world,
MPI_STATUS_IGNORE);
&nrecv2,1,MPI_INT,procneigh[dim][0],0,world,MPI_STATUS_IGNORE);
nrecv += nrecv2;
} else nrecv2 = 0;
if (nrecv > maxrecv) grow_recv(nrecv);
MPI_Irecv(&buf_recv[nsend],nrecv1,MPI_DOUBLE,procneigh[dim][1],0,
world,&request);
MPI_Irecv(&buf_recv[nsend],nrecv1,MPI_DOUBLE,procneigh[dim][1],0,world,&request);
MPI_Send(buf_recv,nsend,MPI_DOUBLE,procneigh[dim][0],0,world);
MPI_Wait(&request,MPI_STATUS_IGNORE);
if (procgrid[dim] > 2) {
MPI_Irecv(&buf_recv[nsend+nrecv1],nrecv2,MPI_DOUBLE,procneigh[dim][0],0,
world,&request);
MPI_Irecv(&buf_recv[nsend+nrecv1],nrecv2,MPI_DOUBLE,procneigh[dim][0],0,world,&request);
MPI_Send(buf_recv,nsend,MPI_DOUBLE,procneigh[dim][1],0,world);
MPI_Wait(&request,MPI_STATUS_IGNORE);
}

View File

@ -22,6 +22,7 @@ class CommBrick : public Comm {
public:
CommBrick(class LAMMPS *);
CommBrick(class LAMMPS *, class Comm *);
~CommBrick() override;
void init() override;
@ -33,6 +34,8 @@ class CommBrick : public Comm {
void forward_comm(class Pair *) override; // forward comm from a Pair
void reverse_comm(class Pair *) override; // reverse comm from a Pair
void forward_comm(class Bond *) override; // forward comm from a Bond
void reverse_comm(class Bond *) override; // reverse comm from a Bond
void forward_comm(class Fix *, int size = 0) override; // forward comm from a Fix
void reverse_comm(class Fix *, int size = 0) override; // reverse comm from a Fix
void reverse_comm_variable(class Fix *) override; // variable size reverse comm from a Fix

View File

@ -21,6 +21,7 @@
#include "atom.h"
#include "atom_vec.h"
#include "bond.h"
#include "compute.h"
#include "domain.h"
#include "dump.h"
@ -512,16 +513,14 @@ void CommTiled::setup()
MIN(sbox_multi[3+idim]+cutghostmulti[icollection][idim],subhi[idim]);
else
sbox_multi[3+idim] =
MIN(sbox_multi[3+idim]-prd[idim]+cutghostmulti[icollection][idim],
subhi[idim]);
MIN(sbox_multi[3+idim]-prd[idim]+cutghostmulti[icollection][idim],subhi[idim]);
} else {
if (i < noverlap1)
sbox_multi[idim] =
MAX(sbox_multi[idim]-cutghostmulti[icollection][idim],sublo[idim]);
else
sbox_multi[idim] =
MAX(sbox_multi[idim]+prd[idim]-cutghostmulti[icollection][idim],
sublo[idim]);
MAX(sbox_multi[idim]+prd[idim]-cutghostmulti[icollection][idim],sublo[idim]);
sbox_multi[3+idim] = subhi[idim];
}
@ -588,16 +587,14 @@ void CommTiled::setup()
MIN(sbox_multiold[3+idim]+cutghostmultiold[itype][idim],subhi[idim]);
else
sbox_multiold[3+idim] =
MIN(sbox_multiold[3+idim]-prd[idim]+cutghostmultiold[itype][idim],
subhi[idim]);
MIN(sbox_multiold[3+idim]-prd[idim]+cutghostmultiold[itype][idim],subhi[idim]);
} else {
if (i < noverlap1)
sbox_multiold[idim] =
MAX(sbox_multiold[idim]-cutghostmultiold[itype][idim],sublo[idim]);
else
sbox_multiold[idim] =
MAX(sbox_multiold[idim]+prd[idim]-cutghostmultiold[itype][idim],
sublo[idim]);
MAX(sbox_multiold[idim]+prd[idim]-cutghostmultiold[itype][idim],sublo[idim]);
sbox_multiold[3+idim] = subhi[idim];
}
@ -747,8 +744,7 @@ void CommTiled::forward_comm(int /*dummy*/)
}
if (sendself[iswap]) {
avec->pack_comm(sendnum[iswap][nsend],sendlist[iswap][nsend],
x[firstrecv[iswap][nrecv]],pbc_flag[iswap][nsend],
pbc[iswap][nsend]);
x[firstrecv[iswap][nrecv]],pbc_flag[iswap][nsend],pbc[iswap][nsend]);
}
if (recvother[iswap]) MPI_Waitall(nrecv,requests,MPI_STATUS_IGNORE);
@ -756,8 +752,7 @@ void CommTiled::forward_comm(int /*dummy*/)
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++)
MPI_Irecv(&buf_recv[size_forward*forward_recv_offset[iswap][i]],
size_forward_recv[iswap][i],
MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
size_forward_recv[iswap][i],MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
}
if (sendother[iswap]) {
for (i = 0; i < nsend; i++) {
@ -769,15 +764,13 @@ void CommTiled::forward_comm(int /*dummy*/)
if (sendself[iswap]) {
avec->pack_comm_vel(sendnum[iswap][nsend],sendlist[iswap][nsend],
buf_send,pbc_flag[iswap][nsend],pbc[iswap][nsend]);
avec->unpack_comm_vel(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],
buf_send);
avec->unpack_comm_vel(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],buf_send);
}
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++) {
MPI_Waitany(nrecv,requests,&irecv,MPI_STATUS_IGNORE);
avec->unpack_comm_vel(recvnum[iswap][irecv],firstrecv[iswap][irecv],
&buf_recv[size_forward*
forward_recv_offset[iswap][irecv]]);
&buf_recv[size_forward*forward_recv_offset[iswap][irecv]]);
}
}
@ -785,8 +778,7 @@ void CommTiled::forward_comm(int /*dummy*/)
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++)
MPI_Irecv(&buf_recv[size_forward*forward_recv_offset[iswap][i]],
size_forward_recv[iswap][i],
MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
size_forward_recv[iswap][i],MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
}
if (sendother[iswap]) {
for (i = 0; i < nsend; i++) {
@ -798,15 +790,13 @@ void CommTiled::forward_comm(int /*dummy*/)
if (sendself[iswap]) {
avec->pack_comm(sendnum[iswap][nsend],sendlist[iswap][nsend],
buf_send,pbc_flag[iswap][nsend],pbc[iswap][nsend]);
avec->unpack_comm(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],
buf_send);
avec->unpack_comm(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],buf_send);
}
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++) {
MPI_Waitany(nrecv,requests,&irecv,MPI_STATUS_IGNORE);
avec->unpack_comm(recvnum[iswap][irecv],firstrecv[iswap][irecv],
&buf_recv[size_forward*
forward_recv_offset[iswap][irecv]]);
&buf_recv[size_forward*forward_recv_offset[iswap][irecv]]);
}
}
}
@ -839,8 +829,7 @@ void CommTiled::reverse_comm()
if (sendother[iswap]) {
for (i = 0; i < nsend; i++) {
MPI_Irecv(&buf_recv[size_reverse*reverse_recv_offset[iswap][i]],
size_reverse_recv[iswap][i],MPI_DOUBLE,
sendproc[iswap][i],0,world,&requests[i]);
size_reverse_recv[iswap][i],MPI_DOUBLE,sendproc[iswap][i],0,world,&requests[i]);
}
}
if (recvother[iswap]) {
@ -856,8 +845,7 @@ void CommTiled::reverse_comm()
for (i = 0; i < nsend; i++) {
MPI_Waitany(nsend,requests,&irecv,MPI_STATUS_IGNORE);
avec->unpack_reverse(sendnum[iswap][irecv],sendlist[iswap][irecv],
&buf_recv[size_reverse*
reverse_recv_offset[iswap][irecv]]);
&buf_recv[size_reverse*reverse_recv_offset[iswap][irecv]]);
}
}
@ -865,28 +853,23 @@ void CommTiled::reverse_comm()
if (sendother[iswap]) {
for (i = 0; i < nsend; i++)
MPI_Irecv(&buf_recv[size_reverse*reverse_recv_offset[iswap][i]],
size_reverse_recv[iswap][i],MPI_DOUBLE,
sendproc[iswap][i],0,world,&requests[i]);
size_reverse_recv[iswap][i],MPI_DOUBLE,sendproc[iswap][i],0,world,&requests[i]);
}
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++) {
n = avec->pack_reverse(recvnum[iswap][i],firstrecv[iswap][i],
buf_send);
n = avec->pack_reverse(recvnum[iswap][i],firstrecv[iswap][i],buf_send);
MPI_Send(buf_send,n,MPI_DOUBLE,recvproc[iswap][i],0,world);
}
}
if (sendself[iswap]) {
avec->pack_reverse(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],
buf_send);
avec->unpack_reverse(sendnum[iswap][nsend],sendlist[iswap][nsend],
buf_send);
avec->pack_reverse(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],buf_send);
avec->unpack_reverse(sendnum[iswap][nsend],sendlist[iswap][nsend],buf_send);
}
if (sendother[iswap]) {
for (i = 0; i < nsend; i++) {
MPI_Waitany(nsend,requests,&irecv,MPI_STATUS_IGNORE);
avec->unpack_reverse(sendnum[iswap][irecv],sendlist[iswap][irecv],
&buf_recv[size_reverse*
reverse_recv_offset[iswap][irecv]]);
&buf_recv[size_reverse*reverse_recv_offset[iswap][irecv]]);
}
}
}
@ -989,8 +972,7 @@ void CommTiled::exchange()
if (!nexch) continue;
for (m = 0; m < nexch; m++)
MPI_Irecv(&exchnum[dim][m],1,MPI_INT,
exchproc[dim][m],0,world,&requests[m]);
MPI_Irecv(&exchnum[dim][m],1,MPI_INT,exchproc[dim][m],0,world,&requests[m]);
for (m = 0; m < nexch; m++)
MPI_Send(&nsend,1,MPI_INT,exchproc[dim][m],0,world);
MPI_Waitall(nexch,requests,MPI_STATUS_IGNORE);
@ -1001,8 +983,7 @@ void CommTiled::exchange()
offset = 0;
for (m = 0; m < nexch; m++) {
MPI_Irecv(&buf_recv[offset],exchnum[dim][m],
MPI_DOUBLE,exchproc[dim][m],0,world,&requests[m]);
MPI_Irecv(&buf_recv[offset],exchnum[dim][m],MPI_DOUBLE,exchproc[dim][m],0,world,&requests[m]);
offset += exchnum[dim][m];
}
for (m = 0; m < nexch; m++)
@ -1233,8 +1214,7 @@ void CommTiled::borders()
if (recvother[iswap])
for (m = 0; m < nrecv; m++)
MPI_Irecv(&recvnum[iswap][m],1,MPI_INT,
recvproc[iswap][m],0,world,&requests[m]);
MPI_Irecv(&recvnum[iswap][m],1,MPI_INT,recvproc[iswap][m],0,world,&requests[m]);
if (sendother[iswap])
for (m = 0; m < nsend; m++)
MPI_Send(&sendnum[iswap][m],1,MPI_INT,sendproc[iswap][m],0,world);
@ -1294,17 +1274,14 @@ void CommTiled::borders()
}
if (sendself[iswap]) {
avec->pack_border_vel(sendnum[iswap][nsend],sendlist[iswap][nsend],
buf_send,pbc_flag[iswap][nsend],
pbc[iswap][nsend]);
avec->unpack_border_vel(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],
buf_send);
buf_send,pbc_flag[iswap][nsend],pbc[iswap][nsend]);
avec->unpack_border_vel(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],buf_send);
}
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++) {
MPI_Waitany(nrecv,requests,&m,MPI_STATUS_IGNORE);
avec->unpack_border_vel(recvnum[iswap][m],firstrecv[iswap][m],
&buf_recv[size_border*
forward_recv_offset[iswap][m]]);
&buf_recv[size_border*forward_recv_offset[iswap][m]]);
}
}
@ -1325,15 +1302,13 @@ void CommTiled::borders()
if (sendself[iswap]) {
avec->pack_border(sendnum[iswap][nsend],sendlist[iswap][nsend],
buf_send,pbc_flag[iswap][nsend],pbc[iswap][nsend]);
avec->unpack_border(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],
buf_send);
avec->unpack_border(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],buf_send);
}
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++) {
MPI_Waitany(nrecv,requests,&m,MPI_STATUS_IGNORE);
avec->unpack_border(recvnum[iswap][m],firstrecv[iswap][m],
&buf_recv[size_border*
forward_recv_offset[iswap][m]]);
&buf_recv[size_border*forward_recv_offset[iswap][m]]);
}
}
}
@ -1351,10 +1326,8 @@ void CommTiled::borders()
// For molecular systems we lose some bits for local atom indices due
// to encoding of special pairs in neighbor lists. Check for overflows.
if ((atom->molecular != Atom::ATOMIC)
&& ((atom->nlocal + atom->nghost) > NEIGHMASK))
error->one(FLERR,"Per-processor number of atoms is too large for "
"molecular neighbor lists");
if ((atom->molecular != Atom::ATOMIC) && ((atom->nlocal + atom->nghost) > NEIGHMASK))
error->one(FLERR,"Per-processor number of atoms is too large for molecular neighbor lists");
// insure send/recv buffers are long enough for all forward & reverse comm
// send buf is for one forward or reverse sends to one proc
@ -1388,8 +1361,7 @@ void CommTiled::forward_comm(Pair *pair)
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++)
MPI_Irecv(&buf_recv[nsize*forward_recv_offset[iswap][i]],
nsize*recvnum[iswap][i],
MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
nsize*recvnum[iswap][i],MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
}
if (sendother[iswap]) {
@ -1402,17 +1374,14 @@ void CommTiled::forward_comm(Pair *pair)
if (sendself[iswap]) {
pair->pack_forward_comm(sendnum[iswap][nsend],sendlist[iswap][nsend],
buf_send,pbc_flag[iswap][nsend],
pbc[iswap][nsend]);
pair->unpack_forward_comm(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],
buf_send);
buf_send,pbc_flag[iswap][nsend],pbc[iswap][nsend]);
pair->unpack_forward_comm(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],buf_send);
}
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++) {
MPI_Waitany(nrecv,requests,&irecv,MPI_STATUS_IGNORE);
pair->unpack_forward_comm(recvnum[iswap][irecv],firstrecv[iswap][irecv],
&buf_recv[nsize*
forward_recv_offset[iswap][irecv]]);
&buf_recv[nsize*forward_recv_offset[iswap][irecv]]);
}
}
}
@ -1436,28 +1405,107 @@ void CommTiled::reverse_comm(Pair *pair)
if (sendother[iswap]) {
for (i = 0; i < nsend; i++)
MPI_Irecv(&buf_recv[nsize*reverse_recv_offset[iswap][i]],
nsize*sendnum[iswap][i],MPI_DOUBLE,
sendproc[iswap][i],0,world,&requests[i]);
nsize*sendnum[iswap][i],MPI_DOUBLE,sendproc[iswap][i],0,world,&requests[i]);
}
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++) {
n = pair->pack_reverse_comm(recvnum[iswap][i],firstrecv[iswap][i],
buf_send);
n = pair->pack_reverse_comm(recvnum[iswap][i],firstrecv[iswap][i],buf_send);
MPI_Send(buf_send,n,MPI_DOUBLE,recvproc[iswap][i],0,world);
}
}
if (sendself[iswap]) {
pair->pack_reverse_comm(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],
buf_send);
pair->unpack_reverse_comm(sendnum[iswap][nsend],sendlist[iswap][nsend],
buf_send);
pair->pack_reverse_comm(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],buf_send);
pair->unpack_reverse_comm(sendnum[iswap][nsend],sendlist[iswap][nsend],buf_send);
}
if (sendother[iswap]) {
for (i = 0; i < nsend; i++) {
MPI_Waitany(nsend,requests,&irecv,MPI_STATUS_IGNORE);
pair->unpack_reverse_comm(sendnum[iswap][irecv],sendlist[iswap][irecv],
&buf_recv[nsize*
reverse_recv_offset[iswap][irecv]]);
&buf_recv[nsize*reverse_recv_offset[iswap][irecv]]);
}
}
}
}
/* ----------------------------------------------------------------------
forward communication invoked by a Bond
nsize used only to set recv buffer limit
------------------------------------------------------------------------- */
void CommTiled::forward_comm(Bond *bond)
{
int i,irecv,n,nsend,nrecv;
int nsize = bond->comm_forward;
for (int iswap = 0; iswap < nswap; iswap++) {
nsend = nsendproc[iswap] - sendself[iswap];
nrecv = nrecvproc[iswap] - sendself[iswap];
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++)
MPI_Irecv(&buf_recv[nsize*forward_recv_offset[iswap][i]],
nsize*recvnum[iswap][i],MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
}
if (sendother[iswap]) {
for (i = 0; i < nsend; i++) {
n = bond->pack_forward_comm(sendnum[iswap][i],sendlist[iswap][i],
buf_send,pbc_flag[iswap][i],pbc[iswap][i]);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap][i],0,world);
}
}
if (sendself[iswap]) {
bond->pack_forward_comm(sendnum[iswap][nsend],sendlist[iswap][nsend],
buf_send,pbc_flag[iswap][nsend],pbc[iswap][nsend]);
bond->unpack_forward_comm(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],buf_send);
}
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++) {
MPI_Waitany(nrecv,requests,&irecv,MPI_STATUS_IGNORE);
bond->unpack_forward_comm(recvnum[iswap][irecv],firstrecv[iswap][irecv],
&buf_recv[nsize*forward_recv_offset[iswap][irecv]]);
}
}
}
}
/* ----------------------------------------------------------------------
reverse communication invoked by a Bond
nsize used only to set recv buffer limit
------------------------------------------------------------------------- */
void CommTiled::reverse_comm(Bond *bond)
{
int i,irecv,n,nsend,nrecv;
int nsize = MAX(bond->comm_reverse,bond->comm_reverse_off);
for (int iswap = nswap-1; iswap >= 0; iswap--) {
nsend = nsendproc[iswap] - sendself[iswap];
nrecv = nrecvproc[iswap] - sendself[iswap];
if (sendother[iswap]) {
for (i = 0; i < nsend; i++)
MPI_Irecv(&buf_recv[nsize*reverse_recv_offset[iswap][i]],
nsize*sendnum[iswap][i],MPI_DOUBLE,sendproc[iswap][i],0,world,&requests[i]);
}
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++) {
n = bond->pack_reverse_comm(recvnum[iswap][i],firstrecv[iswap][i],buf_send);
MPI_Send(buf_send,n,MPI_DOUBLE,recvproc[iswap][i],0,world);
}
}
if (sendself[iswap]) {
bond->pack_reverse_comm(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],buf_send);
bond->unpack_reverse_comm(sendnum[iswap][nsend],sendlist[iswap][nsend],buf_send);
}
if (sendother[iswap]) {
for (i = 0; i < nsend; i++) {
MPI_Waitany(nsend,requests,&irecv,MPI_STATUS_IGNORE);
bond->unpack_reverse_comm(sendnum[iswap][irecv],sendlist[iswap][irecv],
&buf_recv[nsize*reverse_recv_offset[iswap][irecv]]);
}
}
}
@ -1486,8 +1534,7 @@ void CommTiled::forward_comm(Fix *fix, int size)
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++)
MPI_Irecv(&buf_recv[nsize*forward_recv_offset[iswap][i]],
nsize*recvnum[iswap][i],
MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
nsize*recvnum[iswap][i],MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
}
if (sendother[iswap]) {
for (i = 0; i < nsend; i++) {
@ -1498,17 +1545,14 @@ void CommTiled::forward_comm(Fix *fix, int size)
}
if (sendself[iswap]) {
fix->pack_forward_comm(sendnum[iswap][nsend],sendlist[iswap][nsend],
buf_send,pbc_flag[iswap][nsend],
pbc[iswap][nsend]);
fix->unpack_forward_comm(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],
buf_send);
buf_send,pbc_flag[iswap][nsend],pbc[iswap][nsend]);
fix->unpack_forward_comm(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],buf_send);
}
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++) {
MPI_Waitany(nrecv,requests,&irecv,MPI_STATUS_IGNORE);
fix->unpack_forward_comm(recvnum[iswap][irecv],firstrecv[iswap][irecv],
&buf_recv[nsize*
forward_recv_offset[iswap][irecv]]);
&buf_recv[nsize*forward_recv_offset[iswap][irecv]]);
}
}
}
@ -1537,28 +1581,23 @@ void CommTiled::reverse_comm(Fix *fix, int size)
if (sendother[iswap]) {
for (i = 0; i < nsend; i++)
MPI_Irecv(&buf_recv[nsize*reverse_recv_offset[iswap][i]],
nsize*sendnum[iswap][i],MPI_DOUBLE,
sendproc[iswap][i],0,world,&requests[i]);
nsize*sendnum[iswap][i],MPI_DOUBLE,sendproc[iswap][i],0,world,&requests[i]);
}
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++) {
n = fix->pack_reverse_comm(recvnum[iswap][i],firstrecv[iswap][i],
buf_send);
n = fix->pack_reverse_comm(recvnum[iswap][i],firstrecv[iswap][i],buf_send);
MPI_Send(buf_send,n,MPI_DOUBLE,recvproc[iswap][i],0,world);
}
}
if (sendself[iswap]) {
fix->pack_reverse_comm(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],
buf_send);
fix->unpack_reverse_comm(sendnum[iswap][nsend],sendlist[iswap][nsend],
buf_send);
fix->pack_reverse_comm(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],buf_send);
fix->unpack_reverse_comm(sendnum[iswap][nsend],sendlist[iswap][nsend],buf_send);
}
if (sendother[iswap]) {
for (i = 0; i < nsend; i++) {
MPI_Waitany(nsend,requests,&irecv,MPI_STATUS_IGNORE);
fix->unpack_reverse_comm(sendnum[iswap][irecv],sendlist[iswap][irecv],
&buf_recv[nsize*
reverse_recv_offset[iswap][irecv]]);
&buf_recv[nsize*reverse_recv_offset[iswap][irecv]]);
}
}
}
@ -1594,31 +1633,26 @@ void CommTiled::forward_comm(Compute *compute)
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++)
MPI_Irecv(&buf_recv[nsize*forward_recv_offset[iswap][i]],
nsize*recvnum[iswap][i],
MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
nsize*recvnum[iswap][i],MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
}
if (sendother[iswap]) {
for (i = 0; i < nsend; i++) {
n = compute->pack_forward_comm(sendnum[iswap][i],sendlist[iswap][i],
buf_send,pbc_flag[iswap][i],
pbc[iswap][i]);
buf_send,pbc_flag[iswap][i],pbc[iswap][i]);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap][i],0,world);
}
}
if (sendself[iswap]) {
compute->pack_forward_comm(sendnum[iswap][nsend],sendlist[iswap][nsend],
buf_send,pbc_flag[iswap][nsend],
pbc[iswap][nsend]);
compute->unpack_forward_comm(recvnum[iswap][nrecv],
firstrecv[iswap][nrecv],buf_send);
buf_send,pbc_flag[iswap][nsend],pbc[iswap][nsend]);
compute->unpack_forward_comm(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],buf_send);
}
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++) {
MPI_Waitany(nrecv,requests,&irecv,MPI_STATUS_IGNORE);
compute->
unpack_forward_comm(recvnum[iswap][irecv],firstrecv[iswap][irecv],
&buf_recv[nsize*
forward_recv_offset[iswap][irecv]]);
&buf_recv[nsize*forward_recv_offset[iswap][irecv]]);
}
}
}
@ -1642,29 +1676,24 @@ void CommTiled::reverse_comm(Compute *compute)
if (sendother[iswap]) {
for (i = 0; i < nsend; i++)
MPI_Irecv(&buf_recv[nsize*reverse_recv_offset[iswap][i]],
nsize*sendnum[iswap][i],MPI_DOUBLE,
sendproc[iswap][i],0,world,&requests[i]);
nsize*sendnum[iswap][i],MPI_DOUBLE,sendproc[iswap][i],0,world,&requests[i]);
}
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++) {
n = compute->pack_reverse_comm(recvnum[iswap][i],firstrecv[iswap][i],
buf_send);
n = compute->pack_reverse_comm(recvnum[iswap][i],firstrecv[iswap][i],buf_send);
MPI_Send(buf_send,n,MPI_DOUBLE,recvproc[iswap][i],0,world);
}
}
if (sendself[iswap]) {
compute->pack_reverse_comm(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],
buf_send);
compute->unpack_reverse_comm(sendnum[iswap][nsend],sendlist[iswap][nsend],
buf_send);
compute->pack_reverse_comm(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],buf_send);
compute->unpack_reverse_comm(sendnum[iswap][nsend],sendlist[iswap][nsend],buf_send);
}
if (sendother[iswap]) {
for (i = 0; i < nsend; i++) {
MPI_Waitany(nsend,requests,&irecv,MPI_STATUS_IGNORE);
compute->
unpack_reverse_comm(sendnum[iswap][irecv],sendlist[iswap][irecv],
&buf_recv[nsize*
reverse_recv_offset[iswap][irecv]]);
&buf_recv[nsize*reverse_recv_offset[iswap][irecv]]);
}
}
}
@ -1688,21 +1717,18 @@ void CommTiled::forward_comm(Dump *dump)
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++)
MPI_Irecv(&buf_recv[nsize*forward_recv_offset[iswap][i]],
nsize*recvnum[iswap][i],
MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
nsize*recvnum[iswap][i],MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
}
if (sendother[iswap]) {
for (i = 0; i < nsend; i++) {
n = dump->pack_forward_comm(sendnum[iswap][i],sendlist[iswap][i],
buf_send,pbc_flag[iswap][i],
pbc[iswap][i]);
buf_send,pbc_flag[iswap][i],pbc[iswap][i]);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap][i],0,world);
}
}
if (sendself[iswap]) {
dump->pack_forward_comm(sendnum[iswap][nsend],sendlist[iswap][nsend],
buf_send,pbc_flag[iswap][nsend],
pbc[iswap][nsend]);
buf_send,pbc_flag[iswap][nsend],pbc[iswap][nsend]);
dump->unpack_forward_comm(recvnum[iswap][nrecv],
firstrecv[iswap][nrecv],buf_send);
}
@ -1710,8 +1736,7 @@ void CommTiled::forward_comm(Dump *dump)
for (i = 0; i < nrecv; i++) {
MPI_Waitany(nrecv,requests,&irecv,MPI_STATUS_IGNORE);
dump->unpack_forward_comm(recvnum[iswap][irecv],firstrecv[iswap][irecv],
&buf_recv[nsize*
forward_recv_offset[iswap][irecv]]);
&buf_recv[nsize*forward_recv_offset[iswap][irecv]]);
}
}
}
@ -1735,28 +1760,23 @@ void CommTiled::reverse_comm(Dump *dump)
if (sendother[iswap]) {
for (i = 0; i < nsend; i++)
MPI_Irecv(&buf_recv[nsize*reverse_recv_offset[iswap][i]],
nsize*sendnum[iswap][i],MPI_DOUBLE,
sendproc[iswap][i],0,world,&requests[i]);
nsize*sendnum[iswap][i],MPI_DOUBLE,sendproc[iswap][i],0,world,&requests[i]);
}
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++) {
n = dump->pack_reverse_comm(recvnum[iswap][i],firstrecv[iswap][i],
buf_send);
n = dump->pack_reverse_comm(recvnum[iswap][i],firstrecv[iswap][i],buf_send);
MPI_Send(buf_send,n,MPI_DOUBLE,recvproc[iswap][i],0,world);
}
}
if (sendself[iswap]) {
dump->pack_reverse_comm(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],
buf_send);
dump->unpack_reverse_comm(sendnum[iswap][nsend],sendlist[iswap][nsend],
buf_send);
dump->pack_reverse_comm(recvnum[iswap][nrecv],firstrecv[iswap][nrecv],buf_send);
dump->unpack_reverse_comm(sendnum[iswap][nsend],sendlist[iswap][nsend],buf_send);
}
if (sendother[iswap]) {
for (i = 0; i < nsend; i++) {
MPI_Waitany(nsend,requests,&irecv,MPI_STATUS_IGNORE);
dump->unpack_reverse_comm(sendnum[iswap][irecv],sendlist[iswap][irecv],
&buf_recv[nsize*
reverse_recv_offset[iswap][irecv]]);
&buf_recv[nsize*reverse_recv_offset[iswap][irecv]]);
}
}
}
@ -1788,8 +1808,7 @@ void CommTiled::forward_comm_array(int nsize, double **array)
if (recvother[iswap]) {
for (i = 0; i < nrecv; i++)
MPI_Irecv(&buf_recv[nsize*forward_recv_offset[iswap][i]],
nsize*recvnum[iswap][i],
MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
nsize*recvnum[iswap][i],MPI_DOUBLE,recvproc[iswap][i],0,world,&requests[i]);
}
if (sendother[iswap]) {
for (i = 0; i < nsend; i++) {
@ -1799,8 +1818,7 @@ void CommTiled::forward_comm_array(int nsize, double **array)
for (k = 0; k < nsize; k++)
buf_send[m++] = array[j][k];
}
MPI_Send(buf_send,nsize*sendnum[iswap][i],
MPI_DOUBLE,sendproc[iswap][i],0,world);
MPI_Send(buf_send,nsize*sendnum[iswap][i],MPI_DOUBLE,sendproc[iswap][i],0,world);
}
}
if (sendself[iswap]) {
@ -1919,8 +1937,7 @@ void CommTiled::box_drop_tiled(int /*idim*/, double *lo, double *hi, int &indexm
box_drop_tiled_recurse(lo,hi,0,nprocs-1,indexme);
}
void CommTiled::box_drop_tiled_recurse(double *lo, double *hi,
int proclower, int procupper,
void CommTiled::box_drop_tiled_recurse(double *lo, double *hi, int proclower, int procupper,
int &indexme)
{
// end recursion when partition is a single proc
@ -1958,8 +1975,7 @@ void CommTiled::box_drop_tiled_recurse(double *lo, double *hi,
return other box owned by proc as lo/hi corner pts
------------------------------------------------------------------------- */
void CommTiled::box_other_brick(int idim, int idir,
int proc, double *lo, double *hi)
void CommTiled::box_other_brick(int idim, int idir, int proc, double *lo, double *hi)
{
lo[0] = sublo[0]; lo[1] = sublo[1]; lo[2] = sublo[2];
hi[0] = subhi[0]; hi[1] = subhi[1]; hi[2] = subhi[2];
@ -2006,8 +2022,7 @@ void CommTiled::box_other_brick(int idim, int idir,
return other box owned by proc as lo/hi corner pts
------------------------------------------------------------------------- */
void CommTiled::box_other_tiled(int /*idim*/, int /*idir*/,
int proc, double *lo, double *hi)
void CommTiled::box_other_tiled(int /*idim*/, int /*idir*/, int proc, double *lo, double *hi)
{
double (*split)[2] = rcbinfo[proc].mysplit;
@ -2136,8 +2151,7 @@ int CommTiled::point_drop_tiled(int idim, double *x)
recursive point drop thru RCB tree
------------------------------------------------------------------------- */
int CommTiled::point_drop_tiled_recurse(double *x,
int proclower, int procupper)
int CommTiled::point_drop_tiled_recurse(double *x, int proclower, int procupper)
{
// end recursion when partition is a single proc
// return proc
@ -2195,8 +2209,7 @@ void CommTiled::coord2proc_setup()
memcpy(&rcbone.mysplit[0][0],&mysplit[0][0],6*sizeof(double));
rcbone.cutfrac = rcbcutfrac;
rcbone.dim = rcbcutdim;
MPI_Allgather(&rcbone,sizeof(RCBinfo),MPI_CHAR,
rcbinfo,sizeof(RCBinfo),MPI_CHAR,world);
MPI_Allgather(&rcbone,sizeof(RCBinfo),MPI_CHAR,rcbinfo,sizeof(RCBinfo),MPI_CHAR,world);
}
/* ----------------------------------------------------------------------

View File

@ -22,6 +22,7 @@ class CommTiled : public Comm {
public:
CommTiled(class LAMMPS *);
CommTiled(class LAMMPS *, class Comm *);
~CommTiled() override;
void init() override;
@ -33,6 +34,8 @@ class CommTiled : public Comm {
void forward_comm(class Pair *) override; // forward comm from a Pair
void reverse_comm(class Pair *) override; // reverse comm from a Pair
void forward_comm(class Bond *) override; // forward comm from a Bond
void reverse_comm(class Bond *) override; // reverse comm from a Bond
void forward_comm(class Fix *, int size = 0) override; // forward comm from a Fix
void reverse_comm(class Fix *, int size = 0) override; // reverse comm from a Fix
void reverse_comm_variable(class Fix *) override; // variable size reverse comm from a Fix

View File

@ -231,25 +231,25 @@ ComputePropertyAtom::ComputePropertyAtom(LAMMPS *lmp, int narg, char **arg) :
} else if (strcmp(arg[iarg],"quatw") == 0) {
avec_ellipsoid = dynamic_cast<AtomVecEllipsoid *>( atom->style_match("ellipsoid"));
avec_body = dynamic_cast<AtomVecBody *>( atom->style_match("body"));
if (!avec_ellipsoid && !avec_body)
if (!avec_ellipsoid && !avec_body && !atom->quat_flag)
error->all(FLERR,"Compute property/atom for atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_quatw;
} else if (strcmp(arg[iarg],"quati") == 0) {
avec_ellipsoid = dynamic_cast<AtomVecEllipsoid *>( atom->style_match("ellipsoid"));
avec_body = dynamic_cast<AtomVecBody *>( atom->style_match("body"));
if (!avec_ellipsoid && !avec_body)
if (!avec_ellipsoid && !avec_body && !atom->quat_flag)
error->all(FLERR,"Compute property/atom for atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_quati;
} else if (strcmp(arg[iarg],"quatj") == 0) {
avec_ellipsoid = dynamic_cast<AtomVecEllipsoid *>( atom->style_match("ellipsoid"));
avec_body = dynamic_cast<AtomVecBody *>( atom->style_match("body"));
if (!avec_ellipsoid && !avec_body)
if (!avec_ellipsoid && !avec_body && !atom->quat_flag)
error->all(FLERR,"Compute property/atom for atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_quatj;
} else if (strcmp(arg[iarg],"quatk") == 0) {
avec_ellipsoid = dynamic_cast<AtomVecEllipsoid *>( atom->style_match("ellipsoid"));
avec_body = dynamic_cast<AtomVecBody *>( atom->style_match("body"));
if (!avec_ellipsoid && !avec_body)
if (!avec_ellipsoid && !avec_body && !atom->quat_flag)
error->all(FLERR,"Compute property/atom for atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_quatk;
@ -1334,7 +1334,7 @@ void ComputePropertyAtom::pack_quatw(int n)
n += nvalues;
}
} else {
} else if (avec_body) {
AtomVecBody::Bonus *bonus = avec_body->bonus;
int *body = atom->body;
int *mask = atom->mask;
@ -1346,6 +1346,17 @@ void ComputePropertyAtom::pack_quatw(int n)
else buf[n] = 0.0;
n += nvalues;
}
} else {
double **quat = atom->quat;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit)
buf[n] = quat[i][0];
else buf[n] = 0.0;
n += nvalues;
}
}
}
@ -1366,7 +1377,7 @@ void ComputePropertyAtom::pack_quati(int n)
n += nvalues;
}
} else {
} else if (avec_body) {
AtomVecBody::Bonus *bonus = avec_body->bonus;
int *body = atom->body;
int *mask = atom->mask;
@ -1378,6 +1389,17 @@ void ComputePropertyAtom::pack_quati(int n)
else buf[n] = 0.0;
n += nvalues;
}
} else {
double **quat = atom->quat;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit)
buf[n] = quat[i][1];
else buf[n] = 0.0;
n += nvalues;
}
}
}
@ -1398,7 +1420,7 @@ void ComputePropertyAtom::pack_quatj(int n)
n += nvalues;
}
} else {
} else if (avec_body) {
AtomVecBody::Bonus *bonus = avec_body->bonus;
int *body = atom->body;
int *mask = atom->mask;
@ -1410,6 +1432,17 @@ void ComputePropertyAtom::pack_quatj(int n)
else buf[n] = 0.0;
n += nvalues;
}
} else {
double **quat = atom->quat;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit)
buf[n] = quat[i][2];
else buf[n] = 0.0;
n += nvalues;
}
}
}
@ -1430,7 +1463,7 @@ void ComputePropertyAtom::pack_quatk(int n)
n += nvalues;
}
} else {
} else if (avec_body) {
AtomVecBody::Bonus *bonus = avec_body->bonus;
int *body = atom->body;
int *mask = atom->mask;
@ -1442,6 +1475,17 @@ void ComputePropertyAtom::pack_quatk(int n)
else buf[n] = 0.0;
n += nvalues;
}
} else {
double **quat = atom->quat;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit)
buf[n] = quat[i][3];
else buf[n] = 0.0;
n += nvalues;
}
}
}

View File

@ -19,8 +19,10 @@
#include "comm.h"
#include "domain.h"
#include "error.h"
#include "fix_bond_history.h"
#include "force.h"
#include "group.h"
#include "modify.h"
#include "special.h"
#include <cstring>
@ -116,6 +118,10 @@ void DeleteBonds::command(int narg, char **arg)
iarg++;
}
// find instances of bond history to delete data
auto histories = modify->get_fix_by_style("BOND_HISTORY");
int n_histories = histories.size();
// border swap to insure type and mask is current for off-proc atoms
// enforce PBC before in case atoms are outside box
@ -331,6 +337,11 @@ void DeleteBonds::command(int narg, char **arg)
n = atom->num_bond[i];
atom->bond_type[i][m] = atom->bond_type[i][n-1];
atom->bond_atom[i][m] = atom->bond_atom[i][n-1];
if (n_histories > 0)
for (auto &ihistory: histories) {
dynamic_cast<FixBondHistory *>(ihistory)->shift_history(i,m,n-1);
dynamic_cast<FixBondHistory *>(ihistory)->delete_history(i,n-1);
}
atom->num_bond[i]--;
} else m++;
} else m++;
@ -431,32 +442,28 @@ void DeleteBonds::command(int narg, char **arg)
if (atom->avec->bonds_allow) {
bigint nbonds = 0;
for (i = 0; i < nlocal; i++) nbonds += atom->num_bond[i];
MPI_Allreduce(&nbonds,&atom->nbonds,1,MPI_LMP_BIGINT,
MPI_SUM,world);
MPI_Allreduce(&nbonds,&atom->nbonds,1,MPI_LMP_BIGINT,MPI_SUM,world);
if (force->newton_bond == 0) atom->nbonds /= 2;
}
if (atom->avec->angles_allow) {
bigint nangles = 0;
for (i = 0; i < nlocal; i++) nangles += atom->num_angle[i];
MPI_Allreduce(&nangles,&atom->nangles,1,MPI_LMP_BIGINT,
MPI_SUM,world);
MPI_Allreduce(&nangles,&atom->nangles,1,MPI_LMP_BIGINT,MPI_SUM,world);
if (force->newton_bond == 0) atom->nangles /= 3;
}
if (atom->avec->dihedrals_allow) {
bigint ndihedrals = 0;
for (i = 0; i < nlocal; i++) ndihedrals += atom->num_dihedral[i];
MPI_Allreduce(&ndihedrals,&atom->ndihedrals,
1,MPI_LMP_BIGINT,MPI_SUM,world);
MPI_Allreduce(&ndihedrals,&atom->ndihedrals,1,MPI_LMP_BIGINT,MPI_SUM,world);
if (force->newton_bond == 0) atom->ndihedrals /= 4;
}
if (atom->avec->impropers_allow) {
bigint nimpropers = 0;
for (i = 0; i < nlocal; i++) nimpropers += atom->num_improper[i];
MPI_Allreduce(&nimpropers,&atom->nimpropers,
1,MPI_LMP_BIGINT,MPI_SUM,world);
MPI_Allreduce(&nimpropers,&atom->nimpropers,1,MPI_LMP_BIGINT,MPI_SUM,world);
if (force->newton_bond == 0) atom->nimpropers /= 4;
}
@ -535,21 +542,18 @@ void DeleteBonds::command(int narg, char **arg)
}
if (comm->me == 0) {
constexpr auto fmtstr = " {} total {}, {} turned on, {} turned off\n";
if (atom->avec->bonds_allow)
utils::logmesg(lmp," {} total bonds, {} turned on, {} turned off\n",
atom->nbonds,bond_on,bond_off);
utils::logmesg(lmp,fmtstr,atom->nbonds,"bonds",bond_on,bond_off);
if (atom->avec->angles_allow)
utils::logmesg(lmp," {} total angles, {} turned on, {} turned off\n",
atom->nangles,angle_on,angle_off);
utils::logmesg(lmp,fmtstr,atom->nangles,"angles",angle_on,angle_off);
if (atom->avec->dihedrals_allow)
utils::logmesg(lmp," {} total dihedrals, {} turned on, {} turned off\n",
atom->ndihedrals,dihedral_on,dihedral_off);
utils::logmesg(lmp,fmtstr,atom->ndihedrals,"dihedrals",dihedral_on,dihedral_off);
if (atom->avec->impropers_allow)
utils::logmesg(lmp," {} total impropers, {} turned on, {} turned off\n",
atom->nimpropers,improper_on,improper_off);
utils::logmesg(lmp,fmtstr,atom->nimpropers,"impropers",improper_on,improper_off);
}
// re-compute special list if requested

View File

@ -1181,7 +1181,7 @@ void Dump::modify_params(int narg, char **arg)
} else if (strcmp(arg[iarg],"header") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command");
header_flag = utils::logical(FLERR,arg[iarg+1],false,lmp);
write_header_flag = utils::logical(FLERR,arg[iarg+1],false,lmp);
iarg += 2;
} else if (strcmp(arg[iarg],"maxfiles") == 0) {

View File

@ -66,7 +66,6 @@ class Dump : protected Pointers {
char *multiname; // filename with % converted to cluster ID
MPI_Comm clustercomm; // MPI communicator within my cluster of procs
int header_flag; // 0 = item, 2 = xyz
int flush_flag; // 0 if no flush, 1 if flush every dump
int sort_flag; // 1 if sorted output
int balance_flag; // 1 if load balanced output

365
src/fix_bond_history.cpp Normal file
View File

@ -0,0 +1,365 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, 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.
------------------------------------------------------------------------- */
#include "fix_bond_history.h"
#include "atom.h"
#include "comm.h"
#include "error.h"
#include "group.h"
#include "memory.h"
#include "modify.h"
#include "neighbor.h"
#include <map>
#include <utility>
using namespace LAMMPS_NS;
using namespace FixConst;
#define LB_FACTOR 1.5
#define DELTA 8192
/* ---------------------------------------------------------------------- */
FixBondHistory::FixBondHistory(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg), bondstore(nullptr), id_fix(nullptr), id_array(nullptr)
{
if (narg != 5) error->all(FLERR, "Illegal fix bond/history command");
update_flag = utils::inumeric(FLERR, arg[3], false, lmp);
ndata = utils::inumeric(FLERR, arg[4], false, lmp);
nbond = atom->bond_per_atom;
if (nbond == 0) error->all(FLERR, "Cannot store bond variables without any bonds");
stored_flag = false;
restart_global = 1;
create_attribute = 1;
// Flag whether bond arrays are updated such that data may need to be
// copied to atom arrays before exchanging atoms
// Prevents sequential calls to pre_exchange() without post_neighbor()
updated_bond_flag = 0;
maxbond = 0;
allocate();
}
/* ---------------------------------------------------------------------- */
FixBondHistory::~FixBondHistory()
{
if (id_fix && modify->nfix) modify->delete_fix(id_fix);
delete[] id_fix;
delete[] id_array;
memory->destroy(bondstore);
}
/* ---------------------------------------------------------------------- */
int FixBondHistory::setmask()
{
int mask = 0;
mask |= PRE_EXCHANGE;
mask |= POST_NEIGHBOR;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixBondHistory::post_constructor()
{
// Store saved bond quantities for each atom using fix property atom
id_fix = utils::strdup(id + std::string("_FIX_PROP_ATOM"));
id_array = utils::strdup(std::string("d2_") + id);
modify->add_fix(fmt::format("{} {} property/atom {} {}", id_fix, group->names[igroup], id_array,
nbond * ndata));
int tmp1, tmp2;
index = atom->find_custom(&id_array[3], tmp1, tmp2);
}
/* ---------------------------------------------------------------------- */
void FixBondHistory::update_atom_value(int i, int m, int idata, double value)
{
if (idata >= ndata || m > nbond) error->all(FLERR, "Index exceeded in fix bond history");
atom->darray[index][i][m * ndata + idata] = value;
}
/* ---------------------------------------------------------------------- */
double FixBondHistory::get_atom_value(int i, int m, int idata)
{
if (idata >= ndata || m > nbond) error->all(FLERR, "Index exceeded in fix bond history");
return atom->darray[index][i][m * ndata + idata];
}
/* ---------------------------------------------------------------------- */
void FixBondHistory::setup_pre_exchange()
{
pre_exchange();
}
/* ----------------------------------------------------------------------
If stored values are updated, need to copy to atom arrays before exchanging
If bondstore array has been allocated, call before nlist rebuild
Also call prior to irregular communication in other fixes (e.g. deform)
------------------------------------------------------------------------- */
void FixBondHistory::pre_exchange()
{
if (!update_flag) return;
if (!stored_flag) return;
if (!updated_bond_flag) return;
int i1, i2, n, m, idata;
int **bondlist = neighbor->bondlist;
int nbondlist = neighbor->nbondlist;
double **stored = atom->darray[index];
int nlocal = atom->nlocal;
tagint **bond_atom = atom->bond_atom;
int *num_bond = atom->num_bond;
tagint *tag = atom->tag;
for (n = 0; n < nbondlist; n++) {
i1 = bondlist[n][0];
i2 = bondlist[n][1];
// skip bond if already broken
if (bondlist[n][2] <= 0) { continue; }
if (i1 < nlocal) {
for (m = 0; m < num_bond[i1]; m++) {
if (bond_atom[i1][m] == tag[i2]) {
for (idata = 0; idata < ndata; idata++) {
stored[i1][m * ndata + idata] = bondstore[n][idata];
}
}
}
}
if (i2 < nlocal) {
for (m = 0; m < num_bond[i2]; m++) {
if (bond_atom[i2][m] == tag[i1]) {
for (idata = 0; idata < ndata; idata++) {
stored[i2][m * ndata + idata] = bondstore[n][idata];
}
}
}
}
}
updated_bond_flag = 0;
}
/* ---------------------------------------------------------------------- */
void FixBondHistory::allocate()
{
//Ideally would just ask ntopo for maxbond, but protected
if (comm->nprocs == 1)
maxbond = atom->nbonds;
else
maxbond = static_cast<int>(LB_FACTOR * atom->nbonds / comm->nprocs);
memory->create(bondstore, maxbond, ndata, "fix_bond_store:bondstore");
}
/* ---------------------------------------------------------------------- */
void FixBondHistory::setup_post_neighbor()
{
//Grow array if number of bonds has increased
while (neighbor->nbondlist >= maxbond) {
maxbond += DELTA;
memory->grow(bondstore, maxbond, ndata, "fix_bond_store:bondstore");
}
pre_exchange();
post_neighbor();
}
/* ----------------------------------------------------------------------
called after neighbor list is build
build array of stored bond quantities from fix property atom
------------------------------------------------------------------------- */
void FixBondHistory::post_neighbor()
{
//Grow array if number of bonds has increased
while (neighbor->nbondlist >= maxbond) {
maxbond += DELTA;
memory->grow(bondstore, maxbond, ndata, "fix_bond_store:bondstore");
}
int i1, i2, n, m, idata;
int **bondlist = neighbor->bondlist;
int nbondlist = neighbor->nbondlist;
double **stored = atom->darray[index];
int nlocal = atom->nlocal;
tagint **bond_atom = atom->bond_atom;
int *num_bond = atom->num_bond;
tagint *tag = atom->tag;
for (n = 0; n < nbondlist; n++) {
i1 = bondlist[n][0];
i2 = bondlist[n][1];
// skip bond if already broken
if (bondlist[n][2] <= 0) { continue; }
if (i1 < nlocal) {
for (m = 0; m < num_bond[i1]; m++) {
if (bond_atom[i1][m] == tag[i2]) {
for (idata = 0; idata < ndata; idata++) {
bondstore[n][idata] = stored[i1][m * ndata + idata];
}
}
}
}
if (i2 < nlocal) {
for (m = 0; m < num_bond[i2]; m++) {
if (bond_atom[i2][m] == tag[i1]) {
for (idata = 0; idata < ndata; idata++) {
bondstore[n][idata] = stored[i2][m * ndata + idata];
}
}
}
}
}
updated_bond_flag = 1;
}
/* ---------------------------------------------------------------------- */
double FixBondHistory::memory_usage()
{
return maxbond * ndata * sizeof(double);
}
/* ---------------------------------------------------------------------- */
void FixBondHistory::write_restart(FILE *fp)
{
int n = 0;
double list[1];
list[n++] = stored_flag;
if (comm->me == 0) {
int size = n * sizeof(double);
fwrite(&size, sizeof(int), 1, fp);
fwrite(list, sizeof(double), n, fp);
}
}
/* ---------------------------------------------------------------------- */
void FixBondHistory::restart(char *buf)
{
int n = 0;
double *list = (double *) buf;
stored_flag = static_cast<int>(list[n++]);
}
/* ----------------------------------------------------------------------
initialize bond values to zero, called when atom is created
------------------------------------------------------------------------- */
void FixBondHistory::set_arrays(int i)
{
double **stored = atom->darray[index];
for (int m = 0; m < nbond; m++)
for (int idata = 0; idata < ndata; idata++) stored[i][m * ndata + idata] = 0.0;
}
/* ----------------------------------------------------------------------
Delete bond by zeroing data
------------------------------------------------------------------------- */
void FixBondHistory::delete_history(int i, int m)
{
double **stored = atom->darray[index];
for (int idata = 0; idata < ndata; idata++) stored[i][m * ndata + idata] = 0.0;
}
/* ----------------------------------------------------------------------
Shift bond data to a new location
------------------------------------------------------------------------- */
void FixBondHistory::shift_history(int i, int m, int k)
{
if (m == k) return;
double **stored = atom->darray[index];
for (int idata = 0; idata < ndata; idata++)
stored[i][m * ndata + idata] = stored[i][k * ndata + idata];
}
/* ----------------------------------------------------------------------
Temporarily caches history for a deleted bond which
could be recreated before the cache is emptied
NOTE: the cache methods still need to be tested, need an example first
------------------------------------------------------------------------- */
void FixBondHistory::cache_history(int i, int m)
{
// Order tags to create a unique key pair
tagint max_tag = MAX(atom->tag[i], atom->bond_atom[i][m]);
tagint min_tag = MIN(atom->tag[i], atom->bond_atom[i][m]);
auto key = std::make_pair(min_tag, max_tag);
// Copy data to vector
double **stored = atom->darray[index];
std::vector<double> data;
for (int idata = 0; idata < ndata; idata++) data.push_back(stored[i][m * ndata + idata]);
// Add data to cache
cached_histories.insert(std::make_pair(key, data));
}
/* ----------------------------------------------------------------------
Checks to see if a newly created bond has cached history
------------------------------------------------------------------------- */
void FixBondHistory::check_cache(int i, int m)
{
// Order tags to create a unique key pair
tagint max_tag = MAX(atom->tag[i], atom->bond_atom[i][m]);
tagint min_tag = MIN(atom->tag[i], atom->bond_atom[i][m]);
auto key = std::make_pair(min_tag, max_tag);
// Check if it exists, if so, copy data
double **stored = atom->darray[index];
std::vector<double> data;
auto pos = cached_histories.find(key);
if (pos != cached_histories.end()) {
data = pos->second;
for (int idata = 0; idata < ndata; idata++) stored[i][m * ndata + idata] = data[idata];
}
}
/* ----------------------------------------------------------------------
Delete saved memory
------------------------------------------------------------------------- */
void FixBondHistory::clear_cache()
{
cached_histories.clear();
}

94
src/fix_bond_history.h Normal file
View File

@ -0,0 +1,94 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, 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.
------------------------------------------------------------------------- */
#ifdef FIX_CLASS
// clang-format off
FixStyle(BOND_HISTORY,FixBondHistory);
// clang-format on
#else
#ifndef LMP_FIX_BOND_HISTORY_H
#define LMP_FIX_BOND_HISTORY_H
#include "fix.h"
#include <map>
#include <utility>
#include <vector>
namespace LAMMPS_NS {
class FixBondHistory : public Fix {
public:
FixBondHistory(class LAMMPS *, int, char **);
~FixBondHistory() override;
int setmask() override;
void post_constructor() override;
void setup_post_neighbor() override;
void setup_pre_exchange() override;
void post_neighbor() override;
void pre_exchange() override;
double memory_usage() override;
void write_restart(FILE *fp) override;
void restart(char *buf) override;
void set_arrays(int);
void update_atom_value(int, int, int, double);
double get_atom_value(int, int, int);
// methods to reorder/delete elements of atom->bond_atom
void delete_history(int, int);
void shift_history(int, int, int);
void cache_history(int, int);
void check_cache(int, int);
void clear_cache();
// if data is temporarily stored while the bond_atom array
// is being reordered, use map of vectors with pairs for keys
// to enable quick look up
std::map<std::pair<tagint, tagint>, std::vector<double>> cached_histories;
double **bondstore;
int stored_flag;
protected:
void allocate();
int update_flag; //Flag whether history values can evolve
int updated_bond_flag;
int nbond, maxbond, ndata;
int index;
char *id_fix;
char *id_array;
};
} // namespace LAMMPS_NS
#endif
#endif
/* ERROR/WARNING messages:
E: Illegal ... command
UNDOCUMENTED
E: Index exceeded in fix bond history
Bond requested non-existant data
E: Cannot store bond variables without any bonds
Atoms must have a nonzero number of bonds to store data
*/

Some files were not shown because too many files have changed in this diff Show More