Merge branch 'master' into package-reorganization-step1
# Conflicts: # doc/src/Packages_details.rst
This commit is contained in:
@ -60,6 +60,7 @@ KOKKOS, o = OPENMP, t = OPT.
|
|||||||
* :doc:`erotate/sphere <compute_erotate_sphere>`
|
* :doc:`erotate/sphere <compute_erotate_sphere>`
|
||||||
* :doc:`erotate/sphere/atom <compute_erotate_sphere_atom>`
|
* :doc:`erotate/sphere/atom <compute_erotate_sphere_atom>`
|
||||||
* :doc:`event/displace <compute_event_displace>`
|
* :doc:`event/displace <compute_event_displace>`
|
||||||
|
* :doc:`fabric <compute_fabric>`
|
||||||
* :doc:`fep <compute_fep>`
|
* :doc:`fep <compute_fep>`
|
||||||
* :doc:`force/tally <compute_tally>`
|
* :doc:`force/tally <compute_tally>`
|
||||||
* :doc:`fragment/atom <compute_cluster_atom>`
|
* :doc:`fragment/atom <compute_cluster_atom>`
|
||||||
|
|||||||
@ -17,6 +17,11 @@ This compute
|
|||||||
* :doc:`compute erotate/sphere <compute_erotate_sphere>`
|
* :doc:`compute erotate/sphere <compute_erotate_sphere>`
|
||||||
|
|
||||||
calculates rotational kinetic energy which can be :doc:`output with thermodynamic info <Howto_output>`.
|
calculates rotational kinetic energy which can be :doc:`output with thermodynamic info <Howto_output>`.
|
||||||
|
The compute
|
||||||
|
|
||||||
|
* :doc:`compute fabric <compute_fabric>`
|
||||||
|
|
||||||
|
calculates various versions of the fabric tensor for granular and non-granular pair styles.
|
||||||
|
|
||||||
Use one of these 4 pair potentials, which compute forces and torques
|
Use one of these 4 pair potentials, which compute forces and torques
|
||||||
between interacting pairs of particles:
|
between interacting pairs of particles:
|
||||||
|
|||||||
@ -9,6 +9,7 @@ This section documents the following functions:
|
|||||||
- :cpp:func:`lammps_close`
|
- :cpp:func:`lammps_close`
|
||||||
- :cpp:func:`lammps_mpi_init`
|
- :cpp:func:`lammps_mpi_init`
|
||||||
- :cpp:func:`lammps_mpi_finalize`
|
- :cpp:func:`lammps_mpi_finalize`
|
||||||
|
- :cpp:func:`lammps_kokkos_finalize`
|
||||||
|
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
|||||||
@ -134,7 +134,10 @@ compiled with.
|
|||||||
The :py:func:`lmp.close() <lammps.lammps.close()>` call is
|
The :py:func:`lmp.close() <lammps.lammps.close()>` call is
|
||||||
optional since the LAMMPS class instance will also be deleted
|
optional since the LAMMPS class instance will also be deleted
|
||||||
automatically during the :py:class:`lammps <lammps.lammps>` class
|
automatically during the :py:class:`lammps <lammps.lammps>` class
|
||||||
destructor.
|
destructor. Instead of :py:func:`lmp.close() <lammps.lammps.close()>`
|
||||||
|
it is also possible to call :py:func:`lmp.finalize() <lammps.lammps.finalize()>`;
|
||||||
|
this will destruct the LAMMPS instance, but also finalized and release
|
||||||
|
the MPI and/or Kokkos environment if enabled and active.
|
||||||
|
|
||||||
Note that you can create multiple LAMMPS objects in your Python
|
Note that you can create multiple LAMMPS objects in your Python
|
||||||
script, and coordinate and run multiple simulations, e.g.
|
script, and coordinate and run multiple simulations, e.g.
|
||||||
|
|||||||
@ -206,6 +206,7 @@ The individual style names on the :doc:`Commands compute <Commands_compute>` doc
|
|||||||
* :doc:`erotate/sphere <compute_erotate_sphere>` - rotational energy of spherical particles
|
* :doc:`erotate/sphere <compute_erotate_sphere>` - rotational energy of spherical particles
|
||||||
* :doc:`erotate/sphere/atom <compute_erotate_sphere_atom>` - rotational energy for each spherical particle
|
* :doc:`erotate/sphere/atom <compute_erotate_sphere_atom>` - rotational energy for each spherical particle
|
||||||
* :doc:`event/displace <compute_event_displace>` - detect event on atom displacement
|
* :doc:`event/displace <compute_event_displace>` - detect event on atom displacement
|
||||||
|
* :doc:`fabric <compute_fabric>` - calculates fabric tensors from pair interactions
|
||||||
* :doc:`fep <compute_fep>` -
|
* :doc:`fep <compute_fep>` -
|
||||||
* :doc:`force/tally <compute_tally>` -
|
* :doc:`force/tally <compute_tally>` -
|
||||||
* :doc:`fragment/atom <compute_cluster_atom>` - fragment ID for each atom
|
* :doc:`fragment/atom <compute_cluster_atom>` - fragment ID for each atom
|
||||||
|
|||||||
185
doc/src/compute_fabric.rst
Normal file
185
doc/src/compute_fabric.rst
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
.. index:: compute fabric
|
||||||
|
|
||||||
|
compute fabric command
|
||||||
|
======================
|
||||||
|
|
||||||
|
Syntax
|
||||||
|
""""""
|
||||||
|
|
||||||
|
.. parsed-literal::
|
||||||
|
|
||||||
|
compute ID group-ID fabric cutoff attribute1 attribute2 ... keyword values ...
|
||||||
|
|
||||||
|
* ID, group-ID are documented in :doc:`compute <compute>` command
|
||||||
|
* fabric = style name of this compute command
|
||||||
|
* cutoff = *type* or *radius*
|
||||||
|
|
||||||
|
.. parsed-literal::
|
||||||
|
|
||||||
|
*type* = cutoffs determined based on atom types
|
||||||
|
*radius* = cutoffs determined based on atom diameters (atom style sphere)
|
||||||
|
|
||||||
|
* one or more attributes may be appended
|
||||||
|
|
||||||
|
.. parsed-literal::
|
||||||
|
|
||||||
|
*contact* = contact tensor
|
||||||
|
*branch* = branch tensor
|
||||||
|
*force/normal* = normal force tensor
|
||||||
|
*force/tangential* = tangential force tensor
|
||||||
|
|
||||||
|
* zero or more keyword/value pairs may be appended
|
||||||
|
* keyword = *type/include*
|
||||||
|
|
||||||
|
.. parsed-literal::
|
||||||
|
|
||||||
|
*type/include* value = arg1 arg2
|
||||||
|
arg = separate lists of types (see below)
|
||||||
|
|
||||||
|
Examples
|
||||||
|
""""""""
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
compute 1 all fabric type contact force/normal type/include 1,2 3*4
|
||||||
|
compute 1 all fabric radius force/normal force/tangential
|
||||||
|
|
||||||
|
Description
|
||||||
|
"""""""""""
|
||||||
|
|
||||||
|
Define a compute that calculates various fabric tensors for pairwise
|
||||||
|
interaction :ref:`(Ouadfel) <Ouadfel>`. Fabric tensors are commonly used
|
||||||
|
to quantify the anisotropy or orientation of granular contacts but can also
|
||||||
|
be used to characterize the direction of pairwise interactions in general
|
||||||
|
systems. The *type* and *radius* settings are used to select whether interactions
|
||||||
|
cutoffs are determined by atom types or by the sum of atomic radii (atom
|
||||||
|
style sphere), respectively. Calling this compute is roughly the cost of a
|
||||||
|
pair style invocation as it involves a loop over the neighbor list. If the
|
||||||
|
normal or tangential force tensors are requested, it will be more expensive
|
||||||
|
than a pair style invocation as it will also recalculate all pair forces.
|
||||||
|
|
||||||
|
Four fabric tensors are available: the contact, branch, normal force, or
|
||||||
|
tangential force tensor. The contact tensor is calculated as
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
|
||||||
|
C_{ab} = \frac{15}{2} (\phi_{ab} - \mathrm{tr}(\phi) \delta_{ab})
|
||||||
|
|
||||||
|
where :math:`a` and :math:`b` are the :math:`x`, :math:`y`, :math:`z`
|
||||||
|
directions, :math:`\delta_{ab}` is the Kronecker delta function, and
|
||||||
|
the tensor :math:`\phi` is defined as
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
|
||||||
|
\phi_{ab} = \sum_{n = 1}^{N_p} \frac{r_{a} r_{b}}{r^2}
|
||||||
|
|
||||||
|
where :math:`n` loops over the :math:`N_p` pair interactions in the simulation,
|
||||||
|
:math:`r_{a}` is the :math:`a` component of the radial vector between the
|
||||||
|
two pairwise interacting particles, and :math:`r` is the magnitude of the radial vector.
|
||||||
|
|
||||||
|
The branch tensor is calculated as
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
|
||||||
|
B_{ab} = \frac{15}{6 \mathrm{tr}(D)} (D_{ab} - \mathrm{tr}(D) \delta_{ab})
|
||||||
|
|
||||||
|
where the tensor :math:`D` is defined as
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
|
||||||
|
D_{ab} = \sum_{n = 1}^{N_p}
|
||||||
|
\frac{1}{N_c (r^2 + C_{cd} r_c r_d)}
|
||||||
|
\frac{r_{a} r_{b}}{r}
|
||||||
|
|
||||||
|
where :math:`N_c` is the total number of contacts in the system and the subscripts
|
||||||
|
:math:`c` and :math:`d` indices are summed according to Einstein notation.
|
||||||
|
|
||||||
|
The normal force fabric tensor is calculated as
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
|
||||||
|
F^n_{ab} = \frac{15}{6 \mathrm{tr}(N)} (N_{ab} - \mathrm{tr}(N) \delta_{ab})
|
||||||
|
|
||||||
|
where the tensor :math:`N` is defined as
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
|
||||||
|
N_{ab} = \sum_{n = 1}^{N_p}
|
||||||
|
\frac{1}{N_c (r^2 + C_{cd} r_c r_d)}
|
||||||
|
\frac{r_{a} r_{b}}{r^2} f_n
|
||||||
|
|
||||||
|
and :math:`f_n` is the magnitude of the normal, central-body force between the two atoms.
|
||||||
|
|
||||||
|
Finally, the tangential force fabric tensor is only defined for pair styles that
|
||||||
|
apply tangential forces to particles, namely granular pair styles. It is calculated
|
||||||
|
as
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
|
||||||
|
F^t_{ab} = \frac{15}{9 \mathrm{tr}(N)} (T_{ab} - \mathrm{tr}(T) \delta_{ab})
|
||||||
|
|
||||||
|
where the tensor :math:`T` is defined as
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
|
||||||
|
T_{ab} = \sum_{n = 1}^{N_p}
|
||||||
|
\frac{1}{N_c (r^2 + C_{cd} r_c r_d)}
|
||||||
|
\frac{r_{a} r_{b}}{r^2} f_t
|
||||||
|
|
||||||
|
and :math:`f_t` is the magnitude of the tangential force between the two atoms.
|
||||||
|
|
||||||
|
The *type/include* keyword filters interactions based on the types of the two atoms.
|
||||||
|
Interactions between two atoms are only included in calculations if the atom types
|
||||||
|
are 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.
|
||||||
|
|
||||||
|
Output info
|
||||||
|
"""""""""""
|
||||||
|
|
||||||
|
This compute calculates a local vector of doubles and a scalar. The vector stores the
|
||||||
|
unique components of the first requested tensor in the order xx, yy, zz, xy, xz, yz
|
||||||
|
followed by the same components for all subsequent tensors. The length of the vector
|
||||||
|
is therefore six times the number of requested tensors. The scalar output is the
|
||||||
|
number of pairwise interactions included in the calculation of the fabric tensor.
|
||||||
|
|
||||||
|
Restrictions
|
||||||
|
""""""""""""
|
||||||
|
|
||||||
|
This fix is part of the GRANULAR package. It is only enabled if LAMMPS
|
||||||
|
was built with that package. See the :doc:`Build package <Build_package>`
|
||||||
|
doc page for more info.
|
||||||
|
|
||||||
|
Currently, compute *fabric* does not support pair styles
|
||||||
|
with many-body interactions. It also does not
|
||||||
|
support models with long-range Coulombic or dispersion forces,
|
||||||
|
i.e. the kspace_style command in LAMMPS. It also does not support the
|
||||||
|
following fixes which add rigid-body constraints: :doc:`fix shake
|
||||||
|
<fix_shake>`, :doc:`fix rattle <fix_shake>`, :doc:`fix rigid
|
||||||
|
<fix_rigid>`, :doc:`fix rigid/small <fix_rigid>`. It does not support
|
||||||
|
granular pair styles that extend beyond the contact of atomic radii
|
||||||
|
(e.g. JKR and DMT).
|
||||||
|
|
||||||
|
Related commands
|
||||||
|
""""""""""""""""
|
||||||
|
|
||||||
|
none
|
||||||
|
|
||||||
|
Default
|
||||||
|
"""""""
|
||||||
|
|
||||||
|
none
|
||||||
|
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. _Ouadfel:
|
||||||
|
|
||||||
|
**(Ouadfel)** Ouadfel and Rothenburg
|
||||||
|
"Stress-force-fabric relationship for assemblies of ellipsoids",
|
||||||
|
Mechanics of Materials (2001). (`link to paper <https://doi.org/10.1016/S0167-6636(00)00057-0>`_)
|
||||||
@ -2680,6 +2680,7 @@ qoverride
|
|||||||
qqr
|
qqr
|
||||||
qqrd
|
qqrd
|
||||||
qtb
|
qtb
|
||||||
|
Quadfel
|
||||||
quadratically
|
quadratically
|
||||||
quadrupolar
|
quadrupolar
|
||||||
Quant
|
Quant
|
||||||
@ -2861,6 +2862,7 @@ Rossky
|
|||||||
rosybrown
|
rosybrown
|
||||||
rotationally
|
rotationally
|
||||||
Rotenberg
|
Rotenberg
|
||||||
|
Rothenburg
|
||||||
Rovigatti
|
Rovigatti
|
||||||
royalblue
|
royalblue
|
||||||
rozero
|
rozero
|
||||||
|
|||||||
@ -76,17 +76,15 @@ MODULE LIBLAMMPS
|
|||||||
TYPE(c_ptr), VALUE :: handle
|
TYPE(c_ptr), VALUE :: handle
|
||||||
END SUBROUTINE lammps_close
|
END SUBROUTINE lammps_close
|
||||||
|
|
||||||
SUBROUTINE lammps_mpi_init(handle) BIND(C, name='lammps_mpi_init')
|
SUBROUTINE lammps_mpi_init() BIND(C, name='lammps_mpi_init')
|
||||||
IMPORT :: c_ptr
|
|
||||||
TYPE(c_ptr), VALUE :: handle
|
|
||||||
END SUBROUTINE lammps_mpi_init
|
END SUBROUTINE lammps_mpi_init
|
||||||
|
|
||||||
SUBROUTINE lammps_mpi_finalize(handle) &
|
SUBROUTINE lammps_mpi_finalize() BIND(C, name='lammps_mpi_finalize')
|
||||||
BIND(C, name='lammps_mpi_finalize')
|
|
||||||
IMPORT :: c_ptr
|
|
||||||
TYPE(c_ptr), VALUE :: handle
|
|
||||||
END SUBROUTINE lammps_mpi_finalize
|
END SUBROUTINE lammps_mpi_finalize
|
||||||
|
|
||||||
|
SUBROUTINE lammps_kokkos_finalize() BIND(C, name='lammps_kokkos_finalize')
|
||||||
|
END SUBROUTINE lammps_kokkos_finalize
|
||||||
|
|
||||||
SUBROUTINE lammps_file(handle,filename) BIND(C, name='lammps_file')
|
SUBROUTINE lammps_file(handle,filename) BIND(C, name='lammps_file')
|
||||||
IMPORT :: c_ptr
|
IMPORT :: c_ptr
|
||||||
TYPE(c_ptr), VALUE :: handle
|
TYPE(c_ptr), VALUE :: handle
|
||||||
@ -188,7 +186,8 @@ CONTAINS
|
|||||||
|
|
||||||
IF (PRESENT(finalize)) THEN
|
IF (PRESENT(finalize)) THEN
|
||||||
IF (finalize) THEN
|
IF (finalize) THEN
|
||||||
CALL lammps_mpi_finalize(self%handle)
|
CALL lammps_kokkos_finalize()
|
||||||
|
CALL lammps_mpi_finalize()
|
||||||
END IF
|
END IF
|
||||||
END IF
|
END IF
|
||||||
END SUBROUTINE lmp_close
|
END SUBROUTINE lmp_close
|
||||||
|
|||||||
@ -460,10 +460,16 @@ class lammps(object):
|
|||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
"""Shut down the MPI communication through the library interface by calling :cpp:func:`lammps_finalize`.
|
"""Shut down the MPI communication and Kokkos environment (if active) through the
|
||||||
|
library interface by calling :cpp:func:`lammps_mpi_finalize` and
|
||||||
|
:cpp:func:`lammps_kokkos_finalize`.
|
||||||
|
|
||||||
|
You cannot create or use any LAMMPS instances after this function is called
|
||||||
|
unless LAMMPS was compiled without MPI and without Kokkos support.
|
||||||
"""
|
"""
|
||||||
self.close()
|
self.close()
|
||||||
self.lib.lammps_finalize()
|
self.lib.lammps_kokkos_finalize()
|
||||||
|
self.lib.lammps_mpi_finalize()
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
2
src/.gitignore
vendored
2
src/.gitignore
vendored
@ -386,6 +386,8 @@
|
|||||||
/compute_erotate_rigid.h
|
/compute_erotate_rigid.h
|
||||||
/compute_event_displace.cpp
|
/compute_event_displace.cpp
|
||||||
/compute_event_displace.h
|
/compute_event_displace.h
|
||||||
|
/compute_fabric.cpp
|
||||||
|
/compute_fabric.h
|
||||||
/compute_fep.cpp
|
/compute_fep.cpp
|
||||||
/compute_fep.h
|
/compute_fep.h
|
||||||
/compute_force_tally.cpp
|
/compute_force_tally.cpp
|
||||||
|
|||||||
595
src/GRANULAR/compute_fabric.cpp
Normal file
595
src/GRANULAR/compute_fabric.cpp
Normal file
@ -0,0 +1,595 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
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_fabric.h"
|
||||||
|
|
||||||
|
#include "atom.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "force.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "modify.h"
|
||||||
|
#include "neigh_list.h"
|
||||||
|
#include "neigh_request.h"
|
||||||
|
#include "neighbor.h"
|
||||||
|
#include "pair.h"
|
||||||
|
#include "tokenizer.h"
|
||||||
|
#include "update.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
using namespace LAMMPS_NS;
|
||||||
|
|
||||||
|
enum { OTHER, GRANULAR };
|
||||||
|
enum { TYPE, RADIUS };
|
||||||
|
enum { CN, BR, FN, FT };
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ComputeFabric::ComputeFabric(LAMMPS *lmp, int narg, char **arg) :
|
||||||
|
Compute(lmp, narg, arg), tensor_style(NULL)
|
||||||
|
{
|
||||||
|
if (narg < 3) error->all(FLERR, "Illegal compute fabric command");
|
||||||
|
|
||||||
|
if (strcmp(arg[3], "type") == 0)
|
||||||
|
cutstyle = TYPE;
|
||||||
|
else if (strcmp(arg[3], "radius") == 0)
|
||||||
|
cutstyle = RADIUS;
|
||||||
|
else
|
||||||
|
error->all(FLERR, "Illegal compute fabric command");
|
||||||
|
|
||||||
|
if (cutstyle == RADIUS && !atom->radius_flag)
|
||||||
|
error->all(FLERR, "Compute fabric radius style requires atom attribute radius");
|
||||||
|
|
||||||
|
// If optional arguments included, this will be oversized
|
||||||
|
ntensors = narg - 4;
|
||||||
|
tensor_style = new int[ntensors];
|
||||||
|
|
||||||
|
cn_flag = 0;
|
||||||
|
br_flag = 0;
|
||||||
|
fn_flag = 0;
|
||||||
|
ft_flag = 0;
|
||||||
|
type_filter = nullptr;
|
||||||
|
|
||||||
|
ntensors = 0;
|
||||||
|
int iarg = 4;
|
||||||
|
while (iarg < narg) {
|
||||||
|
if (strcmp(arg[iarg], "contact") == 0) {
|
||||||
|
cn_flag = 1;
|
||||||
|
tensor_style[ntensors++] = CN;
|
||||||
|
} else if (strcmp(arg[iarg], "branch") == 0) {
|
||||||
|
br_flag = 1;
|
||||||
|
tensor_style[ntensors++] = BR;
|
||||||
|
} else if (strcmp(arg[iarg], "force/normal") == 0) {
|
||||||
|
fn_flag = 1;
|
||||||
|
tensor_style[ntensors++] = FN;
|
||||||
|
} else if (strcmp(arg[iarg], "force/tangential") == 0) {
|
||||||
|
ft_flag = 1;
|
||||||
|
tensor_style[ntensors++] = FT;
|
||||||
|
} else if (strcmp(arg[iarg], "type/include") == 0) {
|
||||||
|
if (iarg + 1 >= narg) error->all(FLERR, "Invalid keyword in compute fabric command");
|
||||||
|
int ntypes = atom->ntypes;
|
||||||
|
|
||||||
|
int i, j, itype, jtype, in, jn, infield, jnfield;
|
||||||
|
int inlo, inhi, jnlo, jnhi;
|
||||||
|
char *istr, *jstr;
|
||||||
|
if (!type_filter) {
|
||||||
|
memory->create(type_filter, ntypes + 1, ntypes + 1, "compute/fabric:type_filter");
|
||||||
|
|
||||||
|
for (i = 0; i <= ntypes; i++) {
|
||||||
|
for (j = 0; j <= ntypes; j++) { type_filter[i][j] = 0; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
in = strlen(arg[iarg + 1]) + 1;
|
||||||
|
istr = new char[in];
|
||||||
|
strcpy(istr, arg[iarg + 1]);
|
||||||
|
std::vector<std::string> iwords = Tokenizer(istr, ",").as_vector();
|
||||||
|
infield = iwords.size();
|
||||||
|
|
||||||
|
jn = strlen(arg[iarg + 2]) + 1;
|
||||||
|
jstr = new char[jn];
|
||||||
|
strcpy(jstr, arg[iarg + 2]);
|
||||||
|
std::vector<std::string> jwords = Tokenizer(jstr, ",").as_vector();
|
||||||
|
jnfield = jwords.size();
|
||||||
|
|
||||||
|
for (i = 0; i < infield; i++) {
|
||||||
|
const char *ifield = iwords[i].c_str();
|
||||||
|
utils::bounds(FLERR, ifield, 1, ntypes, inlo, inhi, error);
|
||||||
|
|
||||||
|
for (j = 0; j < jnfield; j++) {
|
||||||
|
const char *jfield = jwords[j].c_str();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] istr;
|
||||||
|
delete[] jstr;
|
||||||
|
|
||||||
|
iarg += 2;
|
||||||
|
} else
|
||||||
|
error->all(FLERR, "Illegal compute fabric command");
|
||||||
|
iarg++;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector_flag = 1;
|
||||||
|
size_vector = ntensors * 6;
|
||||||
|
extvector = 0;
|
||||||
|
|
||||||
|
scalar_flag = 1;
|
||||||
|
extscalar = 1;
|
||||||
|
|
||||||
|
vector = new double[size_vector];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ComputeFabric::~ComputeFabric()
|
||||||
|
{
|
||||||
|
delete[] vector;
|
||||||
|
delete[] tensor_style;
|
||||||
|
memory->destroy(type_filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void ComputeFabric::init()
|
||||||
|
{
|
||||||
|
if (force->pair == NULL) error->all(FLERR, "No pair style is defined for compute fabric");
|
||||||
|
if (force->pair->single_enable == 0 && (fn_flag || ft_flag))
|
||||||
|
error->all(FLERR, "Pair style does not support compute fabric normal or tangential force");
|
||||||
|
|
||||||
|
// Find if granular or gran
|
||||||
|
pstyle = OTHER;
|
||||||
|
if (force->pair_match("^granular", 0) || force->pair_match("^gran/", 0)) pstyle = GRANULAR;
|
||||||
|
|
||||||
|
if (pstyle != GRANULAR && ft_flag)
|
||||||
|
error->all(FLERR, "Pair style does not calculate tangential forces for compute fabric");
|
||||||
|
|
||||||
|
if (force->pair->beyond_contact)
|
||||||
|
error->all(FLERR, "Compute fabric does not support pair styles that extend beyond contact");
|
||||||
|
|
||||||
|
// need an occasional half neighbor list
|
||||||
|
// set size to same value as request made by force->pair
|
||||||
|
// this should enable it to always be a copy list (e.g. for granular pstyle)
|
||||||
|
|
||||||
|
int irequest = neighbor->request(this, instance_me);
|
||||||
|
neighbor->requests[irequest]->pair = 0;
|
||||||
|
neighbor->requests[irequest]->compute = 1;
|
||||||
|
neighbor->requests[irequest]->occasional = 1;
|
||||||
|
NeighRequest *pairrequest = neighbor->find_request((void *) force->pair);
|
||||||
|
if (pairrequest) neighbor->requests[irequest]->size = pairrequest->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void ComputeFabric::init_list(int /*id*/, NeighList *ptr)
|
||||||
|
{
|
||||||
|
list = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void ComputeFabric::compute_vector()
|
||||||
|
{
|
||||||
|
invoked_vector = update->ntimestep;
|
||||||
|
|
||||||
|
int i, j, ii, jj, inum, jnum, itype, jtype;
|
||||||
|
tagint itag, jtag;
|
||||||
|
double xtmp, ytmp, ztmp, delx, dely, delz;
|
||||||
|
double r, rinv, rsq, radsum, eng, fpair;
|
||||||
|
|
||||||
|
double nx, ny, nz;
|
||||||
|
double ncinv, denom, fn, ft, prefactor;
|
||||||
|
double br_tensor[6], ft_tensor[6], fn_tensor[6];
|
||||||
|
double trace_phi, trace_D, trace_Xfn, trace_Xft;
|
||||||
|
double phi_ij[6] = {0.0};
|
||||||
|
double Ac_ij[6] = {0.0};
|
||||||
|
double D_ij[6] = {0.0};
|
||||||
|
double Xfn_ij[6] = {0.0};
|
||||||
|
double Xft_ij[6] = {0.0};
|
||||||
|
double temp_dbl[6];
|
||||||
|
|
||||||
|
int *ilist, *jlist, *numneigh, **firstneigh;
|
||||||
|
|
||||||
|
double **x = atom->x;
|
||||||
|
double *radius = atom->radius;
|
||||||
|
tagint *tag = atom->tag;
|
||||||
|
int *type = atom->type;
|
||||||
|
int *mask = atom->mask;
|
||||||
|
int nlocal = atom->nlocal;
|
||||||
|
int newton_pair = force->newton_pair;
|
||||||
|
|
||||||
|
// invoke half neighbor list (will copy or build if necessary)
|
||||||
|
neighbor->build_one(list);
|
||||||
|
|
||||||
|
inum = list->inum;
|
||||||
|
ilist = list->ilist;
|
||||||
|
numneigh = list->numneigh;
|
||||||
|
firstneigh = list->firstneigh;
|
||||||
|
|
||||||
|
Pair *pair = force->pair;
|
||||||
|
double **cutsq = force->pair->cutsq;
|
||||||
|
|
||||||
|
// invoke compute_scalar() to update the number of contacts, if needed
|
||||||
|
nc = compute_scalar();
|
||||||
|
|
||||||
|
// If no contacts, everything will be zero
|
||||||
|
if (nc == 0) {
|
||||||
|
for (i = 0; i < size_vector; i++) vector[i] = 0.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ncinv = 1.0 / nc;
|
||||||
|
|
||||||
|
// First loop through and calculate contact fabric tensor
|
||||||
|
for (ii = 0; ii < inum; ii++) {
|
||||||
|
i = ilist[ii];
|
||||||
|
if (!(mask[i] & groupbit)) continue;
|
||||||
|
|
||||||
|
xtmp = x[i][0];
|
||||||
|
ytmp = x[i][1];
|
||||||
|
ztmp = x[i][2];
|
||||||
|
itag = tag[i];
|
||||||
|
itype = type[i];
|
||||||
|
jlist = firstneigh[i];
|
||||||
|
jnum = numneigh[i];
|
||||||
|
|
||||||
|
for (jj = 0; jj < jnum; jj++) {
|
||||||
|
j = jlist[jj];
|
||||||
|
j &= NEIGHMASK;
|
||||||
|
|
||||||
|
if (!(mask[j] & groupbit)) continue;
|
||||||
|
|
||||||
|
// itag = jtag is possible for long cutoffs that include images of self
|
||||||
|
|
||||||
|
if (newton_pair == 0 && j >= nlocal) {
|
||||||
|
jtag = tag[j];
|
||||||
|
if (itag > jtag) {
|
||||||
|
if ((itag + jtag) % 2 == 0) continue;
|
||||||
|
} else if (itag < jtag) {
|
||||||
|
if ((itag + jtag) % 2 == 1) continue;
|
||||||
|
} else {
|
||||||
|
if (x[j][2] < ztmp) continue;
|
||||||
|
if (x[j][2] == ztmp) {
|
||||||
|
if (x[j][1] < ytmp) continue;
|
||||||
|
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jtype = type[j];
|
||||||
|
|
||||||
|
if (type_filter)
|
||||||
|
if (type_filter[itype][jtype] == 0) continue;
|
||||||
|
|
||||||
|
delx = xtmp - x[j][0];
|
||||||
|
dely = ytmp - x[j][1];
|
||||||
|
delz = ztmp - x[j][2];
|
||||||
|
rsq = delx * delx + dely * dely + delz * delz;
|
||||||
|
|
||||||
|
if (cutstyle == TYPE) {
|
||||||
|
if (rsq >= cutsq[itype][jtype]) continue;
|
||||||
|
} else {
|
||||||
|
radsum = radius[i] + radius[j];
|
||||||
|
if (rsq >= radsum * radsum) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sqrt(rsq);
|
||||||
|
rinv = 1.0 / r;
|
||||||
|
nx = delx * rinv;
|
||||||
|
ny = dely * rinv;
|
||||||
|
nz = delz * rinv;
|
||||||
|
|
||||||
|
phi_ij[0] += nx * nx;
|
||||||
|
phi_ij[1] += ny * ny;
|
||||||
|
phi_ij[2] += nz * nz;
|
||||||
|
phi_ij[3] += nx * ny;
|
||||||
|
phi_ij[4] += nx * nz;
|
||||||
|
phi_ij[5] += ny * nz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Sum phi across processors
|
||||||
|
MPI_Allreduce(phi_ij, temp_dbl, 6, MPI_DOUBLE, MPI_SUM, world);
|
||||||
|
for (i = 0; i < 6; i++) phi_ij[i] = temp_dbl[i] * ncinv;
|
||||||
|
|
||||||
|
trace_phi = (1.0 / 3.0) * (phi_ij[0] + phi_ij[1] + phi_ij[2]);
|
||||||
|
|
||||||
|
Ac_ij[0] = (15.0 / 2.0) * (phi_ij[0] - trace_phi);
|
||||||
|
Ac_ij[1] = (15.0 / 2.0) * (phi_ij[1] - trace_phi);
|
||||||
|
Ac_ij[2] = (15.0 / 2.0) * (phi_ij[2] - trace_phi);
|
||||||
|
Ac_ij[3] = (15.0 / 2.0) * (phi_ij[3]);
|
||||||
|
Ac_ij[4] = (15.0 / 2.0) * (phi_ij[4]);
|
||||||
|
Ac_ij[5] = (15.0 / 2.0) * (phi_ij[5]);
|
||||||
|
|
||||||
|
// If needed, loop through and calculate other fabric tensors
|
||||||
|
if (br_flag || fn_flag || ft_flag) {
|
||||||
|
|
||||||
|
for (ii = 0; ii < inum; ii++) {
|
||||||
|
i = ilist[ii];
|
||||||
|
if (!(mask[i] & groupbit)) continue;
|
||||||
|
|
||||||
|
xtmp = x[i][0];
|
||||||
|
ytmp = x[i][1];
|
||||||
|
ztmp = x[i][2];
|
||||||
|
itag = tag[i];
|
||||||
|
itype = type[i];
|
||||||
|
jlist = firstneigh[i];
|
||||||
|
jnum = numneigh[i];
|
||||||
|
|
||||||
|
for (jj = 0; jj < jnum; jj++) {
|
||||||
|
j = jlist[jj];
|
||||||
|
j &= NEIGHMASK;
|
||||||
|
|
||||||
|
if (!(mask[j] & groupbit)) continue;
|
||||||
|
|
||||||
|
// itag = jtag is possible for long cutoffs that include images of self
|
||||||
|
|
||||||
|
if (newton_pair == 0 && j >= nlocal) {
|
||||||
|
jtag = tag[j];
|
||||||
|
if (itag > jtag) {
|
||||||
|
if ((itag + jtag) % 2 == 0) continue;
|
||||||
|
} else if (itag < jtag) {
|
||||||
|
if ((itag + jtag) % 2 == 1) continue;
|
||||||
|
} else {
|
||||||
|
if (x[j][2] < ztmp) continue;
|
||||||
|
if (x[j][2] == ztmp) {
|
||||||
|
if (x[j][1] < ytmp) continue;
|
||||||
|
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jtype = type[j];
|
||||||
|
|
||||||
|
if (type_filter)
|
||||||
|
if (type_filter[itype][jtype] == 0) continue;
|
||||||
|
|
||||||
|
delx = xtmp - x[j][0];
|
||||||
|
dely = ytmp - x[j][1];
|
||||||
|
delz = ztmp - x[j][2];
|
||||||
|
rsq = delx * delx + dely * dely + delz * delz;
|
||||||
|
|
||||||
|
if (cutstyle == TYPE) {
|
||||||
|
if (rsq >= cutsq[itype][jtype]) continue;
|
||||||
|
} else {
|
||||||
|
radsum = radius[i] + radius[j];
|
||||||
|
if (rsq >= radsum * radsum) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fn_flag || ft_flag) eng = pair->single(i, j, itype, jtype, rsq, 1.0, 1.0, fpair);
|
||||||
|
|
||||||
|
r = sqrt(rsq);
|
||||||
|
rinv = 1.0 / r;
|
||||||
|
nx = delx * rinv;
|
||||||
|
ny = dely * rinv;
|
||||||
|
nz = delz * rinv;
|
||||||
|
|
||||||
|
denom = 1 + Ac_ij[0] * nx * nx + Ac_ij[1] * ny * ny + Ac_ij[2] * nz * nz;
|
||||||
|
denom += 2 * Ac_ij[3] * nx * ny + 2 * Ac_ij[4] * nx * nz + 2 * Ac_ij[5] * ny * nz;
|
||||||
|
prefactor = ncinv / denom;
|
||||||
|
|
||||||
|
if (br_flag) {
|
||||||
|
D_ij[0] += prefactor * nx * nx * r;
|
||||||
|
D_ij[1] += prefactor * ny * ny * r;
|
||||||
|
D_ij[2] += prefactor * nz * nz * r;
|
||||||
|
D_ij[3] += prefactor * nx * ny * r;
|
||||||
|
D_ij[4] += prefactor * nx * nz * r;
|
||||||
|
D_ij[5] += prefactor * ny * nz * r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fn_flag || ft_flag) {
|
||||||
|
fn = r * fpair;
|
||||||
|
|
||||||
|
Xfn_ij[0] += prefactor * nx * nx * fn;
|
||||||
|
Xfn_ij[1] += prefactor * ny * ny * fn;
|
||||||
|
Xfn_ij[2] += prefactor * nz * nz * fn;
|
||||||
|
Xfn_ij[3] += prefactor * nx * ny * fn;
|
||||||
|
Xfn_ij[4] += prefactor * nx * nz * fn;
|
||||||
|
Xfn_ij[5] += prefactor * ny * nz * fn;
|
||||||
|
|
||||||
|
if (ft_flag) {
|
||||||
|
ft = force->pair->svector[3];
|
||||||
|
|
||||||
|
Xft_ij[0] += prefactor * nx * nx * ft;
|
||||||
|
Xft_ij[1] += prefactor * ny * ny * ft;
|
||||||
|
Xft_ij[2] += prefactor * nz * nz * ft;
|
||||||
|
Xft_ij[3] += prefactor * nx * ny * ft;
|
||||||
|
Xft_ij[4] += prefactor * nx * nz * ft;
|
||||||
|
Xft_ij[5] += prefactor * ny * nz * ft;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output results
|
||||||
|
|
||||||
|
if (cn_flag) {
|
||||||
|
for (i = 0; i < ntensors; i++) {
|
||||||
|
if (tensor_style[i] == CN) {
|
||||||
|
for (j = 0; j < 6; j++) vector[6 * i + j] = Ac_ij[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (br_flag) {
|
||||||
|
MPI_Allreduce(D_ij, temp_dbl, 6, MPI_DOUBLE, MPI_SUM, world);
|
||||||
|
for (i = 0; i < 6; i++) D_ij[i] = temp_dbl[i];
|
||||||
|
|
||||||
|
trace_D = (1.0 / 3.0) * (D_ij[0] + D_ij[1] + D_ij[2]);
|
||||||
|
|
||||||
|
br_tensor[0] = (15.0 / (6.0 * trace_D)) * (D_ij[0] - trace_D);
|
||||||
|
br_tensor[1] = (15.0 / (6.0 * trace_D)) * (D_ij[1] - trace_D);
|
||||||
|
br_tensor[2] = (15.0 / (6.0 * trace_D)) * (D_ij[2] - trace_D);
|
||||||
|
br_tensor[3] = (15.0 / (6.0 * trace_D)) * (D_ij[3]);
|
||||||
|
br_tensor[4] = (15.0 / (6.0 * trace_D)) * (D_ij[4]);
|
||||||
|
br_tensor[5] = (15.0 / (6.0 * trace_D)) * (D_ij[5]);
|
||||||
|
|
||||||
|
for (i = 0; i < ntensors; i++) {
|
||||||
|
if (tensor_style[i] == BR) {
|
||||||
|
for (j = 0; j < 6; j++) vector[6 * i + j] = br_tensor[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fn_flag || ft_flag) {
|
||||||
|
MPI_Allreduce(Xfn_ij, temp_dbl, 6, MPI_DOUBLE, MPI_SUM, world);
|
||||||
|
for (i = 0; i < 6; i++) Xfn_ij[i] = temp_dbl[i];
|
||||||
|
|
||||||
|
trace_Xfn = (1.0 / 3.0) * (Xfn_ij[0] + Xfn_ij[1] + Xfn_ij[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fn_flag) {
|
||||||
|
|
||||||
|
fn_tensor[0] = (15.0 / (6.0 * trace_Xfn)) * (Xfn_ij[0] - trace_Xfn);
|
||||||
|
fn_tensor[1] = (15.0 / (6.0 * trace_Xfn)) * (Xfn_ij[1] - trace_Xfn);
|
||||||
|
fn_tensor[2] = (15.0 / (6.0 * trace_Xfn)) * (Xfn_ij[2] - trace_Xfn);
|
||||||
|
fn_tensor[3] = (15.0 / (6.0 * trace_Xfn)) * (Xfn_ij[3]);
|
||||||
|
fn_tensor[4] = (15.0 / (6.0 * trace_Xfn)) * (Xfn_ij[4]);
|
||||||
|
fn_tensor[5] = (15.0 / (6.0 * trace_Xfn)) * (Xfn_ij[5]);
|
||||||
|
|
||||||
|
for (i = 0; i < ntensors; i++) {
|
||||||
|
if (tensor_style[i] == FN) {
|
||||||
|
for (j = 0; j < 6; j++) vector[6 * i + j] = fn_tensor[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ft_flag) {
|
||||||
|
MPI_Allreduce(Xft_ij, temp_dbl, 6, MPI_DOUBLE, MPI_SUM, world);
|
||||||
|
for (i = 0; i < 6; i++) Xft_ij[i] = temp_dbl[i];
|
||||||
|
|
||||||
|
trace_Xft = (1.0 / 3.0) * (Xft_ij[0] + Xft_ij[1] + Xft_ij[2]);
|
||||||
|
|
||||||
|
ft_tensor[0] = (15.0 / (9.0 * trace_Xfn)) * (Xft_ij[0] - trace_Xft);
|
||||||
|
ft_tensor[1] = (15.0 / (9.0 * trace_Xfn)) * (Xft_ij[1] - trace_Xft);
|
||||||
|
ft_tensor[2] = (15.0 / (9.0 * trace_Xfn)) * (Xft_ij[2] - trace_Xft);
|
||||||
|
ft_tensor[3] = (15.0 / (9.0 * trace_Xfn)) * (Xft_ij[3]);
|
||||||
|
ft_tensor[4] = (15.0 / (9.0 * trace_Xfn)) * (Xft_ij[4]);
|
||||||
|
ft_tensor[5] = (15.0 / (9.0 * trace_Xfn)) * (Xft_ij[5]);
|
||||||
|
|
||||||
|
for (i = 0; i < ntensors; i++) {
|
||||||
|
if (tensor_style[i] == FT) {
|
||||||
|
for (j = 0; j < 6; j++) vector[6 * i + j] = ft_tensor[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
double ComputeFabric::compute_scalar()
|
||||||
|
{
|
||||||
|
// Skip if already calculated on this timestep
|
||||||
|
if (invoked_scalar == update->ntimestep) return nc;
|
||||||
|
|
||||||
|
invoked_scalar = update->ntimestep;
|
||||||
|
|
||||||
|
int i, j, ii, jj, inum, jnum, itype, jtype;
|
||||||
|
tagint itag, jtag;
|
||||||
|
double xtmp, ytmp, ztmp, delx, dely, delz;
|
||||||
|
double rsq, radsum, temp_dbl;
|
||||||
|
|
||||||
|
int *ilist, *jlist, *numneigh, **firstneigh;
|
||||||
|
|
||||||
|
double **x = atom->x;
|
||||||
|
double *radius = atom->radius;
|
||||||
|
tagint *tag = atom->tag;
|
||||||
|
int *type = atom->type;
|
||||||
|
int *mask = atom->mask;
|
||||||
|
int nlocal = atom->nlocal;
|
||||||
|
int newton_pair = force->newton_pair;
|
||||||
|
|
||||||
|
// invoke half neighbor list (will copy or build if necessary)
|
||||||
|
neighbor->build_one(list);
|
||||||
|
|
||||||
|
inum = list->inum;
|
||||||
|
ilist = list->ilist;
|
||||||
|
numneigh = list->numneigh;
|
||||||
|
firstneigh = list->firstneigh;
|
||||||
|
|
||||||
|
double **cutsq = force->pair->cutsq;
|
||||||
|
|
||||||
|
// First loop through and calculate contact fabric tensor
|
||||||
|
nc = 0;
|
||||||
|
for (ii = 0; ii < inum; ii++) {
|
||||||
|
i = ilist[ii];
|
||||||
|
if (!(mask[i] & groupbit)) continue;
|
||||||
|
|
||||||
|
xtmp = x[i][0];
|
||||||
|
ytmp = x[i][1];
|
||||||
|
ztmp = x[i][2];
|
||||||
|
itag = tag[i];
|
||||||
|
itype = type[i];
|
||||||
|
jlist = firstneigh[i];
|
||||||
|
jnum = numneigh[i];
|
||||||
|
|
||||||
|
for (jj = 0; jj < jnum; jj++) {
|
||||||
|
j = jlist[jj];
|
||||||
|
j &= NEIGHMASK;
|
||||||
|
|
||||||
|
if (!(mask[j] & groupbit)) continue;
|
||||||
|
|
||||||
|
// itag = jtag is possible for long cutoffs that include images of self
|
||||||
|
|
||||||
|
if (newton_pair == 0 && j >= nlocal) {
|
||||||
|
jtag = tag[j];
|
||||||
|
if (itag > jtag) {
|
||||||
|
if ((itag + jtag) % 2 == 0) continue;
|
||||||
|
} else if (itag < jtag) {
|
||||||
|
if ((itag + jtag) % 2 == 1) continue;
|
||||||
|
} else {
|
||||||
|
if (x[j][2] < ztmp) continue;
|
||||||
|
if (x[j][2] == ztmp) {
|
||||||
|
if (x[j][1] < ytmp) continue;
|
||||||
|
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jtype = type[j];
|
||||||
|
|
||||||
|
if (type_filter)
|
||||||
|
if (type_filter[itype][jtype] == 0) continue;
|
||||||
|
|
||||||
|
delx = xtmp - x[j][0];
|
||||||
|
dely = ytmp - x[j][1];
|
||||||
|
delz = ztmp - x[j][2];
|
||||||
|
rsq = delx * delx + dely * dely + delz * delz;
|
||||||
|
|
||||||
|
if (cutstyle == TYPE) {
|
||||||
|
if (rsq >= cutsq[itype][jtype]) continue;
|
||||||
|
} else {
|
||||||
|
radsum = radius[i] + radius[j];
|
||||||
|
if (rsq >= radsum * radsum) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nc += 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Count total contacts across processors
|
||||||
|
MPI_Allreduce(&nc, &temp_dbl, 1, MPI_DOUBLE, MPI_SUM, world);
|
||||||
|
nc = temp_dbl;
|
||||||
|
|
||||||
|
scalar = nc;
|
||||||
|
return nc;
|
||||||
|
}
|
||||||
|
|
||||||
79
src/GRANULAR/compute_fabric.h
Normal file
79
src/GRANULAR/compute_fabric.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/* -*- 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(fabric,ComputeFabric);
|
||||||
|
// clang-format on
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef LMP_COMPUTE_FABRIC_H
|
||||||
|
#define LMP_COMPUTE_FABRIC_H
|
||||||
|
|
||||||
|
#include "compute.h"
|
||||||
|
|
||||||
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class ComputeFabric : public Compute {
|
||||||
|
public:
|
||||||
|
ComputeFabric(class LAMMPS *, int, char **);
|
||||||
|
~ComputeFabric();
|
||||||
|
void init();
|
||||||
|
void init_list(int, class NeighList *);
|
||||||
|
void compute_vector();
|
||||||
|
double compute_scalar();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int ntensors, pstyle, cutstyle;
|
||||||
|
double nc;
|
||||||
|
int *tensor_style;
|
||||||
|
int **type_filter;
|
||||||
|
class NeighList *list;
|
||||||
|
|
||||||
|
int cn_flag, br_flag, fn_flag, ft_flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // 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: Compute fabric radius style requires atom attribute radius
|
||||||
|
|
||||||
|
Self-explanatory.
|
||||||
|
|
||||||
|
E: No pair style is defined for compute fabric
|
||||||
|
|
||||||
|
Self-explanatory.
|
||||||
|
|
||||||
|
E: Pair style does not support compute fabric normal or tangential force
|
||||||
|
|
||||||
|
Pair style must be single enabled to calculate the normal or tangential force tensors
|
||||||
|
|
||||||
|
E: Pair style does not calculate tangential forces for compute fabric
|
||||||
|
|
||||||
|
The tangential force tensor can only be calculated for granular pair styles with tangential forces
|
||||||
|
|
||||||
|
E: Compute fabric does not support pair styles that extend beyond contact
|
||||||
|
|
||||||
|
Granular pair styles that extend beyond contact such as JKR or DMT are not supported
|
||||||
|
|
||||||
|
*/
|
||||||
@ -69,6 +69,10 @@ GPU_AWARE_UNKNOWN
|
|||||||
|
|
||||||
using namespace LAMMPS_NS;
|
using namespace LAMMPS_NS;
|
||||||
|
|
||||||
|
Kokkos::InitArguments KokkosLMP::args{-1, -1, -1, false};
|
||||||
|
int KokkosLMP::is_finalized = 0;
|
||||||
|
int KokkosLMP::init_ngpus = 0;
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
KokkosLMP::KokkosLMP(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
|
KokkosLMP::KokkosLMP(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
|
||||||
@ -155,6 +159,10 @@ KokkosLMP::KokkosLMP(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
|
|||||||
} else if (strcmp(arg[iarg],"t") == 0 ||
|
} else if (strcmp(arg[iarg],"t") == 0 ||
|
||||||
strcmp(arg[iarg],"threads") == 0) {
|
strcmp(arg[iarg],"threads") == 0) {
|
||||||
nthreads = atoi(arg[iarg+1]);
|
nthreads = atoi(arg[iarg+1]);
|
||||||
|
|
||||||
|
if (nthreads <= 0)
|
||||||
|
error->all(FLERR,"Invalid number of threads requested for Kokkos: must be 1 or greater");
|
||||||
|
|
||||||
iarg += 2;
|
iarg += 2;
|
||||||
|
|
||||||
} else if (strcmp(arg[iarg],"n") == 0 ||
|
} else if (strcmp(arg[iarg],"n") == 0 ||
|
||||||
@ -165,13 +173,27 @@ KokkosLMP::KokkosLMP(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
|
|||||||
} else error->all(FLERR,"Invalid Kokkos command-line args");
|
} else error->all(FLERR,"Invalid Kokkos command-line args");
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize Kokkos
|
// Initialize Kokkos. However, we cannot change any
|
||||||
|
// Kokkos library parameters after the first initalization
|
||||||
|
|
||||||
if (me == 0) {
|
if (args.num_threads != -1) {
|
||||||
if (screen) fprintf(screen," will use up to %d GPU(s) per node\n",ngpus);
|
if (args.num_threads != nthreads || args.num_numa != numa || args.device_id != device)
|
||||||
if (logfile) fprintf(logfile," will use up to %d GPU(s) per node\n",ngpus);
|
if (me == 0)
|
||||||
|
error->warning(FLERR,"Kokkos package already initalized, cannot reinitialize with different parameters");
|
||||||
|
nthreads = args.num_threads;
|
||||||
|
numa = args.num_numa;
|
||||||
|
device = args.device_id;
|
||||||
|
ngpus = init_ngpus;
|
||||||
|
} else {
|
||||||
|
args.num_threads = nthreads;
|
||||||
|
args.num_numa = numa;
|
||||||
|
args.device_id = device;
|
||||||
|
init_ngpus = ngpus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (me == 0)
|
||||||
|
utils::logmesg(lmp, " will use up to {} GPU(s) per node\n",ngpus);
|
||||||
|
|
||||||
#ifdef LMP_KOKKOS_GPU
|
#ifdef LMP_KOKKOS_GPU
|
||||||
if (ngpus <= 0)
|
if (ngpus <= 0)
|
||||||
error->all(FLERR,"Kokkos has been compiled for CUDA, HIP, or SYCL but no GPUs are requested");
|
error->all(FLERR,"Kokkos has been compiled for CUDA, HIP, or SYCL but no GPUs are requested");
|
||||||
@ -184,12 +206,7 @@ KokkosLMP::KokkosLMP(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
|
|||||||
"than the OpenMP backend");
|
"than the OpenMP backend");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Kokkos::InitArguments args;
|
KokkosLMP::initialize(args,error);
|
||||||
args.num_threads = nthreads;
|
|
||||||
args.num_numa = numa;
|
|
||||||
args.device_id = device;
|
|
||||||
|
|
||||||
Kokkos::initialize(args);
|
|
||||||
|
|
||||||
// default settings for package kokkos command
|
// default settings for package kokkos command
|
||||||
|
|
||||||
@ -299,9 +316,27 @@ KokkosLMP::KokkosLMP(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
|
|||||||
|
|
||||||
KokkosLMP::~KokkosLMP()
|
KokkosLMP::~KokkosLMP()
|
||||||
{
|
{
|
||||||
// finalize Kokkos
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void KokkosLMP::initialize(Kokkos::InitArguments args, Error *error)
|
||||||
|
{
|
||||||
|
if (!Kokkos::is_initialized()) {
|
||||||
|
if (is_finalized)
|
||||||
|
error->all(FLERR,"Kokkos package already finalized, cannot re-initialize");
|
||||||
|
Kokkos::initialize(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void KokkosLMP::finalize()
|
||||||
|
{
|
||||||
|
if (Kokkos::is_initialized() && !is_finalized)
|
||||||
Kokkos::finalize();
|
Kokkos::finalize();
|
||||||
|
is_finalized = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
|
|||||||
@ -49,8 +49,14 @@ class KokkosLMP : protected Pointers {
|
|||||||
int newtonflag;
|
int newtonflag;
|
||||||
double binsize;
|
double binsize;
|
||||||
|
|
||||||
|
static int is_finalized;
|
||||||
|
static Kokkos::InitArguments args;
|
||||||
|
static int init_ngpus;
|
||||||
|
|
||||||
KokkosLMP(class LAMMPS *, int, char **);
|
KokkosLMP(class LAMMPS *, int, char **);
|
||||||
~KokkosLMP();
|
~KokkosLMP();
|
||||||
|
static void initialize(Kokkos::InitArguments, Error *);
|
||||||
|
static void finalize();
|
||||||
void accelerator(int, char **);
|
void accelerator(int, char **);
|
||||||
int neigh_count(int);
|
int neigh_count(int);
|
||||||
|
|
||||||
@ -84,13 +90,21 @@ because MPI library not recognized
|
|||||||
|
|
||||||
The local MPI rank was not found in one of four supported environment variables.
|
The local MPI rank was not found in one of four supported environment variables.
|
||||||
|
|
||||||
|
E: Invalid number of threads requested for Kokkos: must be 1 or greater
|
||||||
|
|
||||||
|
Self-explanatory.
|
||||||
|
|
||||||
E: GPUs are requested but Kokkos has not been compiled for CUDA
|
E: GPUs are requested but Kokkos has not been compiled for CUDA
|
||||||
|
|
||||||
Recompile Kokkos with CUDA support to use GPUs.
|
Recompile Kokkos with CUDA support to use GPUs.
|
||||||
|
|
||||||
E: Kokkos has been compiled for CUDA but no GPUs are requested
|
E: Kokkos has been compiled for CUDA, HIP, or SYCL but no GPUs are requested
|
||||||
|
|
||||||
One or more GPUs must be used when Kokkos is compiled for CUDA.
|
One or more GPUs must be used when Kokkos is compiled for CUDA/HIP/SYCL.
|
||||||
|
|
||||||
|
W: Kokkos package already initalized, cannot reinitialize with different parameters
|
||||||
|
|
||||||
|
Self-explanatory.
|
||||||
|
|
||||||
E: Illegal ... command
|
E: Illegal ... command
|
||||||
|
|
||||||
|
|||||||
@ -176,6 +176,7 @@ void FixNVESpin::init()
|
|||||||
|
|
||||||
// loop 1: obtain # of Pairs, and # of Pair/Spin styles
|
// loop 1: obtain # of Pairs, and # of Pair/Spin styles
|
||||||
|
|
||||||
|
npairspin = 0;
|
||||||
PairHybrid *hybrid = (PairHybrid *)force->pair_match("^hybrid",0);
|
PairHybrid *hybrid = (PairHybrid *)force->pair_match("^hybrid",0);
|
||||||
if (force->pair_match("^spin",0,0)) { // only one Pair/Spin style
|
if (force->pair_match("^spin",0,0)) { // only one Pair/Spin style
|
||||||
pair = force->pair_match("^spin",0,0);
|
pair = force->pair_match("^spin",0,0);
|
||||||
@ -232,6 +233,7 @@ void FixNVESpin::init()
|
|||||||
// loop 1: obtain # of fix precession/spin styles
|
// loop 1: obtain # of fix precession/spin styles
|
||||||
|
|
||||||
int iforce;
|
int iforce;
|
||||||
|
nprecspin = 0;
|
||||||
for (iforce = 0; iforce < modify->nfix; iforce++) {
|
for (iforce = 0; iforce < modify->nfix; iforce++) {
|
||||||
if (utils::strmatch(modify->fix[iforce]->style,"^precession/spin")) {
|
if (utils::strmatch(modify->fix[iforce]->style,"^precession/spin")) {
|
||||||
nprecspin++;
|
nprecspin++;
|
||||||
@ -264,6 +266,7 @@ void FixNVESpin::init()
|
|||||||
|
|
||||||
// loop 1: obtain # of fix langevin/spin styles
|
// loop 1: obtain # of fix langevin/spin styles
|
||||||
|
|
||||||
|
nlangspin = 0;
|
||||||
for (iforce = 0; iforce < modify->nfix; iforce++) {
|
for (iforce = 0; iforce < modify->nfix; iforce++) {
|
||||||
if (utils::strmatch(modify->fix[iforce]->style,"^langevin/spin")) {
|
if (utils::strmatch(modify->fix[iforce]->style,"^langevin/spin")) {
|
||||||
nlangspin++;
|
nlangspin++;
|
||||||
|
|||||||
@ -56,16 +56,12 @@ class KokkosLMP {
|
|||||||
|
|
||||||
KokkosLMP(class LAMMPS *, int, char **) { kokkos_exists = 0; }
|
KokkosLMP(class LAMMPS *, int, char **) { kokkos_exists = 0; }
|
||||||
~KokkosLMP() {}
|
~KokkosLMP() {}
|
||||||
|
static void finalize() {}
|
||||||
void accelerator(int, char **) {}
|
void accelerator(int, char **) {}
|
||||||
int neigh_list_kokkos(int) { return 0; }
|
int neigh_list_kokkos(int) { return 0; }
|
||||||
int neigh_count(int) { return 0; }
|
int neigh_count(int) { return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Kokkos {
|
|
||||||
public:
|
|
||||||
static void finalize() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class AtomKokkos : public Atom {
|
class AtomKokkos : public Atom {
|
||||||
public:
|
public:
|
||||||
tagint **k_special;
|
tagint **k_special;
|
||||||
|
|||||||
@ -81,7 +81,7 @@ void Error::universe_all(const std::string &file, int line, const std::string &s
|
|||||||
|
|
||||||
throw LAMMPSException(mesg);
|
throw LAMMPSException(mesg);
|
||||||
#else
|
#else
|
||||||
if (lmp->kokkos) Kokkos::finalize();
|
KokkosLMP::finalize();
|
||||||
MPI_Finalize();
|
MPI_Finalize();
|
||||||
exit(1);
|
exit(1);
|
||||||
#endif
|
#endif
|
||||||
@ -107,6 +107,7 @@ void Error::universe_one(const std::string &file, int line, const std::string &s
|
|||||||
|
|
||||||
throw LAMMPSAbortException(mesg, universe->uworld);
|
throw LAMMPSAbortException(mesg, universe->uworld);
|
||||||
#else
|
#else
|
||||||
|
KokkosLMP::finalize();
|
||||||
MPI_Abort(universe->uworld,1);
|
MPI_Abort(universe->uworld,1);
|
||||||
exit(1); // to trick "smart" compilers into believing this does not return
|
exit(1); // to trick "smart" compilers into believing this does not return
|
||||||
#endif
|
#endif
|
||||||
@ -173,8 +174,8 @@ void Error::all(const std::string &file, int line, const std::string &str)
|
|||||||
if (screen && screen != stdout) fclose(screen);
|
if (screen && screen != stdout) fclose(screen);
|
||||||
if (logfile) fclose(logfile);
|
if (logfile) fclose(logfile);
|
||||||
|
|
||||||
|
KokkosLMP::finalize();
|
||||||
if (universe->nworlds > 1) MPI_Abort(universe->uworld,1);
|
if (universe->nworlds > 1) MPI_Abort(universe->uworld,1);
|
||||||
if (lmp->kokkos) Kokkos::finalize();
|
|
||||||
MPI_Finalize();
|
MPI_Finalize();
|
||||||
exit(1);
|
exit(1);
|
||||||
#endif
|
#endif
|
||||||
@ -213,6 +214,7 @@ void Error::one(const std::string &file, int line, const std::string &str)
|
|||||||
#else
|
#else
|
||||||
if (screen) fflush(screen);
|
if (screen) fflush(screen);
|
||||||
if (logfile) fflush(logfile);
|
if (logfile) fflush(logfile);
|
||||||
|
KokkosLMP::finalize();
|
||||||
MPI_Abort(world,1);
|
MPI_Abort(world,1);
|
||||||
exit(1); // to trick "smart" compilers into believing this does not return
|
exit(1); // to trick "smart" compilers into believing this does not return
|
||||||
#endif
|
#endif
|
||||||
@ -315,7 +317,7 @@ void Error::done(int status)
|
|||||||
if (screen && screen != stdout) fclose(screen);
|
if (screen && screen != stdout) fclose(screen);
|
||||||
if (logfile) fclose(logfile);
|
if (logfile) fclose(logfile);
|
||||||
|
|
||||||
if (lmp->kokkos) Kokkos::finalize();
|
KokkosLMP::finalize();
|
||||||
MPI_Finalize();
|
MPI_Finalize();
|
||||||
exit(status);
|
exit(status);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
#include "library.h"
|
#include "library.h"
|
||||||
#include <mpi.h>
|
#include <mpi.h>
|
||||||
|
|
||||||
|
#include "accelerator_kokkos.h"
|
||||||
#include "atom.h"
|
#include "atom.h"
|
||||||
#include "atom_vec.h"
|
#include "atom_vec.h"
|
||||||
#include "comm.h"
|
#include "comm.h"
|
||||||
@ -333,8 +334,8 @@ The MPI standard requires that any MPI application calls
|
|||||||
do any MPI calls, MPI is still initialized internally to avoid errors
|
do any MPI calls, MPI is still initialized internally to avoid errors
|
||||||
accessing any MPI functions. This function should then be called right
|
accessing any MPI functions. This function should then be called right
|
||||||
before exiting the program to wait until all (parallel) tasks are
|
before exiting the program to wait until all (parallel) tasks are
|
||||||
completed and then MPI is cleanly shut down. After this function no
|
completed and then MPI is cleanly shut down. After calling this
|
||||||
more MPI calls may be made.
|
function no more MPI calls may be made.
|
||||||
|
|
||||||
.. versionadded:: 18Sep2020
|
.. versionadded:: 18Sep2020
|
||||||
|
|
||||||
@ -353,6 +354,28 @@ void lammps_mpi_finalize()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/** Shut down the Kokkos library environment.
|
||||||
|
*
|
||||||
|
\verbatim embed:rst
|
||||||
|
|
||||||
|
The Kokkos library may only be initialized once during the execution of
|
||||||
|
a process. This is done automatically the first time Kokkos
|
||||||
|
functionality is used. This requires that the Kokkos environment
|
||||||
|
must be explicitly shut down after any LAMMPS instance using it is
|
||||||
|
closed (to release associated resources).
|
||||||
|
After calling this function no Kokkos functionality may be used.
|
||||||
|
|
||||||
|
.. versionadded:: TBD
|
||||||
|
|
||||||
|
\endverbatim */
|
||||||
|
|
||||||
|
void lammps_kokkos_finalize()
|
||||||
|
{
|
||||||
|
KokkosLMP::finalize();
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
// Library functions to process commands
|
// Library functions to process commands
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|||||||
@ -94,6 +94,7 @@ void lammps_close(void *handle);
|
|||||||
|
|
||||||
void lammps_mpi_init();
|
void lammps_mpi_init();
|
||||||
void lammps_mpi_finalize();
|
void lammps_mpi_finalize();
|
||||||
|
void lammps_kokkos_finalize();
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
* Library functions to process commands
|
* Library functions to process commands
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
#include "lammps.h"
|
#include "lammps.h"
|
||||||
|
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
#include "accelerator_kokkos.h"
|
||||||
#if defined(LAMMPS_EXCEPTIONS)
|
#if defined(LAMMPS_EXCEPTIONS)
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#endif
|
#endif
|
||||||
@ -77,13 +78,16 @@ int main(int argc, char **argv)
|
|||||||
lammps->input->file();
|
lammps->input->file();
|
||||||
delete lammps;
|
delete lammps;
|
||||||
} catch (LAMMPSAbortException &ae) {
|
} catch (LAMMPSAbortException &ae) {
|
||||||
|
KokkosLMP::finalize();
|
||||||
MPI_Abort(ae.universe, 1);
|
MPI_Abort(ae.universe, 1);
|
||||||
} catch (LAMMPSException &e) {
|
} catch (LAMMPSException &e) {
|
||||||
|
KokkosLMP::finalize();
|
||||||
MPI_Barrier(lammps_comm);
|
MPI_Barrier(lammps_comm);
|
||||||
MPI_Finalize();
|
MPI_Finalize();
|
||||||
exit(1);
|
exit(1);
|
||||||
} catch (fmt::format_error &fe) {
|
} catch (fmt::format_error &fe) {
|
||||||
fprintf(stderr, "fmt::format_error: %s\n", fe.what());
|
fprintf(stderr, "fmt::format_error: %s\n", fe.what());
|
||||||
|
KokkosLMP::finalize();
|
||||||
MPI_Abort(MPI_COMM_WORLD, 1);
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -94,10 +98,12 @@ int main(int argc, char **argv)
|
|||||||
delete lammps;
|
delete lammps;
|
||||||
} catch (fmt::format_error &fe) {
|
} catch (fmt::format_error &fe) {
|
||||||
fprintf(stderr, "fmt::format_error: %s\n", fe.what());
|
fprintf(stderr, "fmt::format_error: %s\n", fe.what());
|
||||||
|
KokkosLMP::finalize();
|
||||||
MPI_Abort(MPI_COMM_WORLD, 1);
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
KokkosLMP::finalize();
|
||||||
MPI_Barrier(lammps_comm);
|
MPI_Barrier(lammps_comm);
|
||||||
MPI_Finalize();
|
MPI_Finalize();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,6 +63,7 @@ extern void *lammps_open_fortran(int argc, char **argv, int f_comm);
|
|||||||
extern void lammps_close(void *handle);
|
extern void lammps_close(void *handle);
|
||||||
extern void lammps_mpi_init();
|
extern void lammps_mpi_init();
|
||||||
extern void lammps_mpi_finalize();
|
extern void lammps_mpi_finalize();
|
||||||
|
extern void lammps_kokkos_finalize();
|
||||||
extern void lammps_file(void *handle, const char *file);
|
extern void lammps_file(void *handle, const char *file);
|
||||||
extern char *lammps_command(void *handle, const char *cmd);
|
extern char *lammps_command(void *handle, const char *cmd);
|
||||||
extern void lammps_commands_list(void *handle, int ncmd, const char **cmds);
|
extern void lammps_commands_list(void *handle, int ncmd, const char **cmds);
|
||||||
@ -185,6 +186,7 @@ extern void *lammps_open_fortran(int argc, char **argv, int f_comm);
|
|||||||
extern void lammps_close(void *handle);
|
extern void lammps_close(void *handle);
|
||||||
extern void lammps_mpi_init();
|
extern void lammps_mpi_init();
|
||||||
extern void lammps_mpi_finalize();
|
extern void lammps_mpi_finalize();
|
||||||
|
extern void lammps_kokkos_finalize();
|
||||||
extern void lammps_file(void *handle, const char *file);
|
extern void lammps_file(void *handle, const char *file);
|
||||||
extern char *lammps_command(void *handle, const char *cmd);
|
extern char *lammps_command(void *handle, const char *cmd);
|
||||||
extern void lammps_commands_list(void *handle, int ncmd, const char **cmds);
|
extern void lammps_commands_list(void *handle, int ncmd, const char **cmds);
|
||||||
|
|||||||
@ -165,6 +165,13 @@ class PythonCapabilities(unittest.TestCase):
|
|||||||
if self.cmake_cache['GPU_PREC'].lower() == 'single':
|
if self.cmake_cache['GPU_PREC'].lower() == 'single':
|
||||||
self.assertIn('single',settings['GPU']['precision'])
|
self.assertIn('single',settings['GPU']['precision'])
|
||||||
|
|
||||||
|
if self.cmake_cache['PKG_KOKKOS']:
|
||||||
|
if self.cmake_cache['Kokkos_ENABLE_OPENMP']:
|
||||||
|
self.assertIn('openmp',settings['KOKKOS']['api'])
|
||||||
|
if self.cmake_cache['Kokkos_ENABLE_SERIAL']:
|
||||||
|
self.assertIn('serial',settings['KOKKOS']['api'])
|
||||||
|
self.assertIn('double',settings['KOKKOS']['precision'])
|
||||||
|
|
||||||
def test_gpu_device(self):
|
def test_gpu_device(self):
|
||||||
|
|
||||||
info = self.lmp.get_gpu_device_info()
|
info = self.lmp.get_gpu_device_info()
|
||||||
|
|||||||
Reference in New Issue
Block a user