Final tidying up

This commit is contained in:
Aidan Thompson
2022-06-27 17:03:02 -06:00
parent 4881b232d3
commit b1b580cc04
7 changed files with 3 additions and 230 deletions

View File

@ -467,235 +467,6 @@ number of columns in the global array generated by *snap* are 31, and
931, respectively, while the number of rows is 1+3\*\ *N*\ +6, where *N*
is the total number of atoms.
If the *quadratic* keyword value is set to 1, then additional columns
are generated, corresponding to the products of all distinct pairs of
bispectrum components. If the number of bispectrum components is *K*,
then the number of distinct pairs is *K*\ (\ *K*\ +1)/2. For compute
*sna/atom* these columns are appended to existing *K* columns. The
ordering of quadratic terms is upper-triangular, (1,1),(1,2)...(1,\ *K*\
),(2,1)...(\ *K*\ -1,\ *K*\ -1),(\ *K*\ -1,\ *K*\ ),(\ *K*,\ *K*\ ).
For computes *snad/atom* and *snav/atom* each set of *K*\ (\ *K*\ +1)/2
additional columns is inserted directly after each of sub-block of
linear terms i.e. linear and quadratic terms are contiguous. So the
nesting order from inside to outside is bispectrum component, linear
then quadratic, vector/tensor component, type.
If the *chem* keyword is used, then the data is arranged into
:math:`N_{elem}^3` sub-blocks, each sub-block corresponding to a
particular chemical labeling :math:`\kappa\lambda\mu` with the last
label changing fastest. Each sub-block contains *K* bispectrum
components. For the purposes of handling contributions to force, virial,
and quadratic combinations, these :math:`N_{elem}^3` sub-blocks are
treated as a single block of :math:`K N_{elem}^3` columns.
These values 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. To see how this command
can be used within a Python workflow to train SNAP potentials, see the
examples in `FitSNAP <https://github.com/FitSNAP/FitSNAP>`_.
The value of all bispectrum components will be zero for atoms not in
the group. Neighbor atoms not in the group do not contribute to the
bispectrum of atoms in the group.
The neighbor list needed to compute this quantity is constructed each
time the calculation is performed (i.e. each time a snapshot of atoms
is dumped). Thus it can be inefficient to compute/dump this quantity
too frequently.
The argument *rcutfac* is a scale factor that controls the ratio of
atomic radius to radial cutoff distance.
The argument *rfac0* and the optional keyword *rmin0* define the
linear mapping from radial distance to polar angle :math:`theta_0` on the
3-sphere, given above.
The argument *twojmax* defines which
bispectrum components are generated. See section below on output for a
detailed explanation of the number of bispectrum components and the
ordered in which they are listed.
The keyword *switchflag* can be used to turn off the switching
function :math:`f_c(r)`.
The keyword *bzeroflag* determines whether or not *B0*, the bispectrum
components of an atom with no neighbors, are subtracted from the
calculated bispectrum components. This optional keyword normally only
affects compute *sna/atom*\ . However, when *quadraticflag* is on, it
also affects *snad/atom* and *snav/atom*\ .
The keyword *quadraticflag* determines whether or not the quadratic
combinations of bispectrum quantities are generated. These are formed
by taking the outer product of the vector of bispectrum components with
itself. See section below on output for a detailed explanation of the
number of quadratic terms and the ordered in which they are listed.
The keyword *chem* activates the explicit multi-element variant of the
SNAP bispectrum components. The argument *nelements* specifies the
number of SNAP elements that will be handled. This is followed by
*elementlist*, a list of integers of length *ntypes*, with values in the
range [0, *nelements* ), which maps each LAMMPS type to one of the SNAP
elements. Note that multiple LAMMPS types can be mapped to the same
element, and some elements may be mapped by no LAMMPS type. However, in
typical use cases (training SNAP potentials) the mapping from LAMMPS
types to elements is one-to-one.
The explicit multi-element variant invoked by the *chem* keyword
partitions the density of neighbors into partial densities for each
chemical element. This is described in detail in the paper by
:ref:`Cusentino et al. <Cusentino2020>` The bispectrum components are
indexed on ordered triplets of elements:
.. math::
B_{j_1,j_2,j}^{\kappa\lambda\mu} =
\sum_{m_1,m'_1=-j_1}^{j_1}\sum_{m_2,m'_2=-j_2}^{j_2}\sum_{m,m'=-j}^{j} (u^{\mu}_{j,m,m'})^*
H {\scriptscriptstyle \begin{array}{l} {j} {m} {m'} \\
{j_1} {m_1} {m'_1} \\
{j_2} {m_2} {m'_2} \end{array}}
u^{\kappa}_{j_1,m_1,m'_1} u^{\lambda}_{j_2,m_2,m'_2}
where :math:`u^{\mu}_{j,m,m'}` is an expansion coefficient for the partial density of neighbors
of element :math:`\mu`
.. math::
u^{\mu}_{j,m,m'} = w^{self}_{\mu_{i}\mu} U^{j,m,m'}(0,0,0) + \sum_{r_{ii'} < R_{ii'}}{\delta_{\mu\mu_{i'}}f_c(r_{ii'}) w_{\mu_{i'}} U^{j,m,m'}(\theta_0,\theta,\phi)}
where :math:`w^{self}_{\mu_{i}\mu}` is the self-contribution, which is
either 1 or 0 (see keyword *wselfallflag* below),
:math:`\delta_{\mu\mu_{i'}}` indicates that the sum is only over
neighbor atoms of element :math:`\mu`, and all other quantities are the
same as those appearing in the original equation for :math:`u^j_{m,m'}`
given above.
The keyword *wselfallflag* defines the rule used for the
self-contribution. If *wselfallflag* is on, then
:math:`w^{self}_{\mu_{i}\mu}` = 1. If it is off then
:math:`w^{self}_{\mu_{i}\mu}` = 0, except in the case of
:math:`{\mu_{i}=\mu}`, when :math:`w^{self}_{\mu_{i}\mu}` = 1. When the
*chem* keyword is not used, this keyword has no effect.
The keyword *bnormflag* determines whether or not the bispectrum
component :math:`B_{j_1,j_2,j}` is divided by a factor of :math:`2j+1`.
This normalization simplifies force calculations because of the
following symmetry relation
.. math::
\frac{B_{j_1,j_2,j}}{2j+1} = \frac{B_{j,j_2,j_1}}{2j_1+1} = \frac{B_{j_1,j,j_2}}{2j_2+1}
This option is typically used in conjunction with the *chem* keyword,
and LAMMPS will generate a warning if both *chem* and *bnormflag*
are not both set or not both unset.
The keyword *bikflag* determines whether or not to expand the bispectrum
rows of the global array returned by compute snap. If *bikflag* is set
to *1* then the bispectrum row, which is typically the per-atom bispectrum
descriptors :math:`B_{i,k}` summed over all atoms *i* to produce
:math:`B_k`, becomes bispectrum rows equal to the number of atoms. Thus,
the resulting bispectrum rows are :math:`B_{i,k}` instead of just
:math:`B_k`. In this case, the entries in the final column for these rows
are set to zero.
The keyword *switchinnerflag* with value 1
activates an additional radial switching
function similar to :math:`f_c(r)` above, but acting to switch off
smoothly contributions from neighbor atoms at short separation distances.
This is useful when SNAP is used in combination with a simple
repulsive potential. For a neighbor atom at
distance :math:`r`, its contribution is scaled by a multiplicative
factor :math:`f_{inner}(r)` defined as follows:
.. math::
= & 0, r \leq S_{inner} - D_{inner} \\
f_{inner}(r) = & \frac{1}{2}(1 - \cos(\frac{\pi}{2} (1 + \frac{r-S_{inner}}{D_{inner}})), S_{inner} - D_{inner} < r \leq S_{inner} + D_{inner} \\
= & 1, r > S_{inner} + D_{inner}
where the switching region is centered at :math:`S_{inner}` and it extends a distance :math:`D_{inner}`
to the left and to the right of this.
With this option, additional keywords *sinner* and *dinner* must be used,
each followed by *ntypes*
values for :math:`S_{inner}` and :math:`D_{inner}`, respectively.
When the central atom and the neighbor atom have different types,
the values of :math:`S_{inner}` and :math:`D_{inner}` are
the arithmetic means of the values for both types.
.. note::
If you have a bonded system, then the settings of :doc:`special_bonds
<special_bonds>` command can remove pairwise interactions between
atoms in the same bond, angle, or dihedral. This is the default
setting for the :doc:`special_bonds <special_bonds>` command, and
means those pairwise interactions do not appear in the neighbor list.
Because this fix uses the neighbor list, it also means those pairs
will not be included in the calculation. One way to get around this,
is to write a dump file, and use the :doc:`rerun <rerun>` command to
compute the bispectrum components for snapshots in the dump file.
The rerun script can use a :doc:`special_bonds <special_bonds>`
command that includes all pairs in the neighbor list.
----------
Output info
"""""""""""
Compute *sna/atom* calculates a per-atom array, each column
corresponding to a particular bispectrum component. The total number of
columns and the identity of the bispectrum component contained in each
column depend of the value of *twojmax*, as described by the following
piece of python code:
.. parsed-literal::
for j1 in range(0,twojmax+1):
for j2 in range(0,j1+1):
for j in range(j1-j2,min(twojmax,j1+j2)+1,2):
if (j>=j1): print j1/2.,j2/2.,j/2.
For even twojmax = 2(*m*\ -1), :math:`K = m(m+1)(2m+1)/6`, the *m*\ -th pyramidal number. For odd twojmax = 2 *m*\ -1, :math:`K = m(m+1)(m+2)/3`, twice the *m*\ -th tetrahedral number.
.. note::
the *diagonal* keyword allowing other possible choices
for the number of bispectrum components was removed in 2019,
since all potentials use the value of 3, corresponding to the
above set of bispectrum components.
Compute *snad/atom* evaluates a per-atom array. The columns are arranged
into *ntypes* blocks, listed in order of atom type *I*\ . Each block
contains three sub-blocks corresponding to the *x*, *y*, and *z*
components of the atom position. Each of these sub-blocks contains *K*
columns for the *K* bispectrum components, the same as for compute
*sna/atom*
Compute *snav/atom* evaluates a per-atom array. The columns are arranged
into *ntypes* blocks, listed in order of atom type *I*\ . Each block
contains six sub-blocks corresponding to the *xx*, *yy*, *zz*,
*yz*, *xz*, and *xy* components of the virial tensor in Voigt
notation. Each of these sub-blocks contains *K* columns for the *K*
bispectrum components, the same as for compute *sna/atom*
Compute *snap* evaluates a global array. The columns are arranged into
*ntypes* blocks, listed in order of atom type *I*\ . Each block contains
one column for each bispectrum component, the same as for compute
*sna/atom*\ . A final column contains the corresponding energy, force
component on an atom, or virial stress component. The rows of the array
appear in the following order:
* 1 row: *sna/atom* quantities summed for all atoms of type *I*
* 3\*\ *N* rows: *snad/atom* quantities, with derivatives w.r.t. x, y, and z coordinate of atom *i* appearing in consecutive rows. The atoms are sorted based on atom ID.
* 6 rows: *snav/atom* quantities summed for all atoms of type *I*
For example, if *K* =30 and ntypes=1, the number of columns in the
per-atom arrays generated by *sna/atom*, *snad/atom*, and
*snav/atom* are 30, 90, and 180, respectively. With *quadratic* value=1,
the numbers of columns are 930, 2790, and 5580, respectively. The
number of columns in the global array generated by *snap* are 31, and
931, respectively, while the number of rows is 1+3\*\ *N*\ +6, where *N*
is the total number of atoms.
Compute *sna/grid* evaluates a global array.
The array contains one row for each of the
:math:`nx \times ny \times nz` grid points, looping over the index for *ix* fastest,

View File

@ -228,6 +228,7 @@ void ComputeSNAGrid::compute_array()
const double ztmp = xgrid[2];
// currently, all grid points are type 1
// not clear what a better choice would be
const int itype = 1;
int ielem = 0;

View File

@ -227,6 +227,7 @@ void ComputeSNAGridLocal::compute_local()
const double ztmp = xgrid[2];
// currently, all grid points are type 1
// not clear what a better choice would be
const int itype = 1;
int ielem = 0;