Merge remote-tracking branch 'github/develop' into add-error-explanations
This commit is contained in:
1
.github/workflows/style-check.yml
vendored
1
.github/workflows/style-check.yml
vendored
@ -35,3 +35,4 @@ jobs:
|
||||
make check-permissions
|
||||
make check-homepage
|
||||
make check-errordocs
|
||||
make check-fmtlib
|
||||
|
||||
@ -98,23 +98,26 @@ check_for_autogen_files(${LAMMPS_SOURCE_DIR})
|
||||
#####################################################################
|
||||
include(CheckIncludeFileCXX)
|
||||
|
||||
# set required compiler flags, apply checks, and compiler/CPU arch specific optimizations
|
||||
# set required compiler flags and compiler/CPU arch specific optimizations
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
||||
# Intel classic compilers version 19 are broken and fail to compile the embedded fmtlib
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 20.0)
|
||||
message(ERROR "Intel classic compiler version ${CMAKE_CXX_COMPILER_VERSION} is too old")
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Qrestrict")
|
||||
endif()
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.3 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.4)
|
||||
set(CMAKE_TUNE_DEFAULT "/QxCOMMON-AVX512")
|
||||
else()
|
||||
set(CMAKE_TUNE_DEFAULT "/QxHost")
|
||||
endif()
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -restrict")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.3 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.4)
|
||||
set(CMAKE_TUNE_DEFAULT "-xCOMMON-AVX512")
|
||||
else()
|
||||
set(CMAKE_TUNE_DEFAULT "-xHost -fp-model fast=2 -no-prec-div -qoverride-limits -diag-disable=10441 -diag-disable=11074 -diag-disable=11076 -diag-disable=2196")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# silence excessive warnings for new Intel Compilers
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")
|
||||
|
||||
@ -32,9 +32,9 @@ endif()
|
||||
|
||||
# Note: must also adjust check for supported API versions in
|
||||
# fix_plumed.cpp when version changes from v2.n.x to v2.n+1.y
|
||||
set(PLUMED_URL "https://github.com/plumed/plumed2/releases/download/v2.9.2/plumed-src-2.9.2.tgz"
|
||||
set(PLUMED_URL "https://github.com/plumed/plumed2/releases/download/v2.9.3/plumed-src-2.9.3.tgz"
|
||||
CACHE STRING "URL for PLUMED tarball")
|
||||
set(PLUMED_MD5 "04862602a372c1013bdfee2d6d03bace" CACHE STRING "MD5 checksum of PLUMED tarball")
|
||||
set(PLUMED_MD5 "ee1249805fe94bccee17d10610d3f6f1" CACHE STRING "MD5 checksum of PLUMED tarball")
|
||||
|
||||
mark_as_advanced(PLUMED_URL)
|
||||
mark_as_advanced(PLUMED_MD5)
|
||||
|
||||
@ -196,13 +196,18 @@ LAMMPS.
|
||||
|
||||
.. tab:: CMake build
|
||||
|
||||
By default CMake will use the compiler it finds according to
|
||||
By default CMake will use the compiler it finds according to its
|
||||
internal preferences, and it will add optimization flags
|
||||
appropriate to that compiler and any :doc:`accelerator packages
|
||||
<Speed_packages>` you have included in the build. CMake will
|
||||
check if the detected or selected compiler is compatible with the
|
||||
C++ support requirements of LAMMPS and stop with an error, if this
|
||||
is not the case.
|
||||
is not the case. A C++11 compatible compiler is currently
|
||||
required, but a transition to require C++17 is in progress and
|
||||
planned to be completed in Summer 2025. Currently, setting
|
||||
``-DLAMMPS_CXX11=yes`` is required when configuring with CMake while
|
||||
using a C++11 compatible compiler that does not support C++17,
|
||||
otherwise setting ``-DCMAKE_CXX_STANDARD=17`` is preferred.
|
||||
|
||||
You can tell CMake to look for a specific compiler with setting
|
||||
CMake variables (listed below) during configuration. For a few
|
||||
@ -223,6 +228,8 @@ LAMMPS.
|
||||
-D CMAKE_C_COMPILER=name # name of C compiler
|
||||
-D CMAKE_Fortran_COMPILER=name # name of Fortran compiler
|
||||
|
||||
-D CMAKE_CXX_STANDARD=17 # put compiler in C++17 mode
|
||||
-D LAMMPS_CXX11=yes # enforce compilation in C++11 mode
|
||||
-D CMAKE_CXX_FLAGS=string # flags to use with C++ compiler
|
||||
-D CMAKE_C_FLAGS=string # flags to use with C compiler
|
||||
-D CMAKE_Fortran_FLAGS=string # flags to use with Fortran compiler
|
||||
@ -321,6 +328,14 @@ LAMMPS.
|
||||
you would have to install a newer compiler that supports C++11;
|
||||
either as a binary package or through compiling from source.
|
||||
|
||||
While a C++11 compatible compiler is currently sufficient to compile
|
||||
LAMMPS, a transition to require C++17 is in progress and planned to
|
||||
be completed in Summer 2025. Currently, setting ``-DLAMMPS_CXX11``
|
||||
in the ``LMP_INC =`` line in the machine makefile is required when
|
||||
using a C++11 compatible compiler that does not support C++17.
|
||||
Otherwise, to enable C++17 support (if not enabled by default) using
|
||||
a compiler flag like ``-std=c++17`` in CCFLAGS may needed.
|
||||
|
||||
If you build LAMMPS with any :doc:`Speed_packages` included,
|
||||
there may be specific compiler or linker flags that are either
|
||||
required or recommended to enable required features and to
|
||||
|
||||
@ -58,6 +58,7 @@ KOKKOS, o = OPENMP, t = OPT.
|
||||
* :doc:`fep/ta <compute_fep_ta>`
|
||||
* :doc:`force/tally <compute_tally>`
|
||||
* :doc:`fragment/atom <compute_cluster_atom>`
|
||||
* :doc:`gaussian/grid/local (k) <compute_gaussian_grid_local>`
|
||||
* :doc:`global/atom <compute_global_atom>`
|
||||
* :doc:`group/group <compute_group_group>`
|
||||
* :doc:`gyration <compute_gyration>`
|
||||
@ -140,8 +141,8 @@ KOKKOS, o = OPENMP, t = OPT.
|
||||
* :doc:`smd/vol <compute_smd_vol>`
|
||||
* :doc:`snap <compute_sna_atom>`
|
||||
* :doc:`sna/atom <compute_sna_atom>`
|
||||
* :doc:`sna/grid <compute_sna_atom>`
|
||||
* :doc:`sna/grid/local <compute_sna_atom>`
|
||||
* :doc:`sna/grid (k) <compute_sna_atom>`
|
||||
* :doc:`sna/grid/local (k) <compute_sna_atom>`
|
||||
* :doc:`snad/atom <compute_sna_atom>`
|
||||
* :doc:`snav/atom <compute_sna_atom>`
|
||||
* :doc:`sph/e/atom <compute_sph_e_atom>`
|
||||
|
||||
@ -115,7 +115,9 @@ OPT.
|
||||
* :doc:`gw/zbl <pair_gw>`
|
||||
* :doc:`harmonic/cut (o) <pair_harmonic_cut>`
|
||||
* :doc:`hbond/dreiding/lj (o) <pair_hbond_dreiding>`
|
||||
* :doc:`hbond/dreiding/lj/angleoffset (o) <pair_hbond_dreiding>`
|
||||
* :doc:`hbond/dreiding/morse (o) <pair_hbond_dreiding>`
|
||||
* :doc:`hbond/dreiding/morse/angleoffset (o) <pair_hbond_dreiding>`
|
||||
* :doc:`hdnnp <pair_hdnnp>`
|
||||
* :doc:`hippo (g) <pair_amoeba>`
|
||||
* :doc:`ilp/graphene/hbn (t) <pair_ilp_graphene_hbn>`
|
||||
|
||||
@ -203,6 +203,7 @@ processed in the expected order before types are removed from dynamic
|
||||
dispatch.
|
||||
|
||||
.. admonition:: Important Notes
|
||||
:class: note
|
||||
|
||||
In order to be able to detect incompatibilities at compile time and
|
||||
to avoid unexpected behavior, it is crucial that all member functions
|
||||
@ -300,18 +301,24 @@ Formatting with the {fmt} library
|
||||
|
||||
The LAMMPS source code includes a copy of the `{fmt} library
|
||||
<https://fmt.dev>`_, which is preferred over formatting with the
|
||||
"printf()" family of functions. The primary reason is that it allows
|
||||
a typesafe default format for any type of supported data. This is
|
||||
"printf()" family of functions. The primary reason is that it allows a
|
||||
typesafe default format for any type of supported data. This is
|
||||
particularly useful for formatting integers of a given size (32-bit or
|
||||
64-bit) which may require different format strings depending on
|
||||
compile time settings or compilers/operating systems. Furthermore,
|
||||
{fmt} gives better performance, has more functionality, a familiar
|
||||
formatting syntax that has similarities to ``format()`` in Python, and
|
||||
provides a facility that can be used to integrate format strings and a
|
||||
variable number of arguments into custom functions in a much simpler
|
||||
way than the varargs mechanism of the C library. Finally, {fmt} has
|
||||
been included into the C++20 language standard, so changes to adopt it
|
||||
are future-proof.
|
||||
64-bit) which may require different format strings depending on compile
|
||||
time settings or compilers/operating systems. Furthermore, {fmt} gives
|
||||
better performance, has more functionality, a familiar formatting syntax
|
||||
that has similarities to ``format()`` in Python, and provides a facility
|
||||
that can be used to integrate format strings and a variable number of
|
||||
arguments into custom functions in a much simpler way than the varargs
|
||||
mechanism of the C library. Finally, {fmt} has been included into the
|
||||
C++20 language standard as ``std::format()``, so changes to adopt it are
|
||||
future-proof, for as long as they are not using any extensions that are
|
||||
not (yet) included into C++.
|
||||
|
||||
The long-term plan is to switch to using ``std::format()`` instead of
|
||||
``fmt::format()`` when the minimum C++ standard required for LAMMPS will
|
||||
be set to C++20. See the :ref:`basic build instructions <compile>` for
|
||||
more details.
|
||||
|
||||
Formatted strings are frequently created by calling the
|
||||
``fmt::format()`` function, which will return a string as a
|
||||
@ -319,11 +326,13 @@ Formatted strings are frequently created by calling the
|
||||
``printf()``, the {fmt} library uses ``{}`` to embed format descriptors.
|
||||
In the simplest case, no additional characters are needed, as {fmt} will
|
||||
choose the default format based on the data type of the argument.
|
||||
Otherwise, the ``fmt::print()`` function may be used instead of
|
||||
``printf()`` or ``fprintf()``. In addition, several LAMMPS output
|
||||
functions, that originally accepted a single string as argument have
|
||||
been overloaded to accept a format string with optional arguments as
|
||||
well (e.g., ``Error::all()``, ``Error::one()``, ``utils::logmesg()``).
|
||||
Otherwise, the :cpp:func:`utils::print() <LAMMPS_NS::utils::print>`
|
||||
function may be used instead of ``printf()`` or ``fprintf()``. In
|
||||
addition, several LAMMPS output functions, that originally accepted a
|
||||
single string as argument have been overloaded to accept a format string
|
||||
with optional arguments as well (e.g., ``Error::all()``,
|
||||
``Error::one()``, :cpp:func:`utils::logmesg()
|
||||
<LAMMPS_NS::utils::logmesg>`).
|
||||
|
||||
Summary of the {fmt} format syntax
|
||||
==================================
|
||||
|
||||
@ -209,7 +209,7 @@ nve, nvt, npt.
|
||||
|
||||
At the end of the timestep, fixes that contain an ``end_of_step()``
|
||||
method are invoked. These typically perform a diagnostic calculation,
|
||||
e.g. the ave/time and ave/spatial fixes. The final operation of the
|
||||
e.g. the ave/time and ave/chunk fixes. The final operation of the
|
||||
timestep is to perform any requested output, via the ``write()`` method
|
||||
of the Output class. There are 3 kinds of LAMMPS output: thermodynamic
|
||||
output to the screen and log file, snapshots of atom data to a dump
|
||||
|
||||
@ -238,6 +238,12 @@ Convenience functions
|
||||
.. doxygenfunction:: logmesg(LAMMPS *lmp, const std::string &mesg)
|
||||
:project: progguide
|
||||
|
||||
.. doxygenfunction:: print(FILE *fp, const std::string &format, Args&&... args)
|
||||
:project: progguide
|
||||
|
||||
.. doxygenfunction:: print(FILE *fp, const std::string &mesg)
|
||||
:project: progguide
|
||||
|
||||
.. doxygenfunction:: errorurl
|
||||
:project: progguide
|
||||
|
||||
|
||||
@ -96,7 +96,7 @@ Here the we specify which methods of the fix should be called during
|
||||
MPI_Allreduce(localAvgVel, globalAvgVel, 4, MPI_DOUBLE, MPI_SUM, world);
|
||||
scale3(1.0 / globalAvgVel[3], globalAvgVel);
|
||||
if ((comm->me == 0) && screen) {
|
||||
fmt::print(screen,"{}, {}, {}\n",
|
||||
utils::print(screen, "{}, {}, {}\n",
|
||||
globalAvgVel[0], globalAvgVel[1], globalAvgVel[2]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -323,6 +323,12 @@ of the contents of the :f:mod:`LIBLAMMPS` Fortran interface to LAMMPS.
|
||||
:ftype set_internal_variable: subroutine
|
||||
:f eval: :f:func:`eval`
|
||||
:ftype eval: function
|
||||
:f clearstep_compute: :f:subr:`clearstep_compute`
|
||||
:ftype clearstep_compute: subroutine
|
||||
:f addstep_compute: :f:subr:`addstep_compute`
|
||||
:ftype addstep_compute: subroutine
|
||||
:f addstep_compute_all: :f:subr:`addstep_compute_all`
|
||||
:ftype addstep_compute_all: subroutine
|
||||
:f gather_atoms: :f:subr:`gather_atoms`
|
||||
:ftype gather_atoms: subroutine
|
||||
:f gather_atoms_concat: :f:subr:`gather_atoms_concat`
|
||||
@ -956,6 +962,7 @@ Procedures Bound to the :f:type:`lammps` Derived Type
|
||||
:f:func:`extract_atom` between runs.
|
||||
|
||||
.. admonition:: Array index order
|
||||
:class: tip
|
||||
|
||||
Two-dimensional arrays returned from :f:func:`extract_atom` will be
|
||||
**transposed** from equivalent arrays in C, and they will be indexed
|
||||
@ -1068,6 +1075,7 @@ Procedures Bound to the :f:type:`lammps` Derived Type
|
||||
you based on data from the :cpp:class:`Compute` class.
|
||||
|
||||
.. admonition:: Array index order
|
||||
:class: tip
|
||||
|
||||
Two-dimensional arrays returned from :f:func:`extract_compute` will be
|
||||
**transposed** from equivalent arrays in C, and they will be indexed
|
||||
@ -1326,6 +1334,7 @@ Procedures Bound to the :f:type:`lammps` Derived Type
|
||||
:rtype data: polymorphic
|
||||
|
||||
.. admonition:: Array index order
|
||||
:class: tip
|
||||
|
||||
Two-dimensional global, per-atom, or local array data from
|
||||
:f:func:`extract_fix` will be **transposed** from equivalent arrays in
|
||||
@ -1450,11 +1459,62 @@ Procedures Bound to the :f:type:`lammps` Derived Type
|
||||
an internal-style variable, an error is generated.
|
||||
|
||||
:p character(len=*) name: name of the variable
|
||||
:p read(c_double) val: new value to assign to the variable
|
||||
:p real(c_double) val: new value to assign to the variable
|
||||
:to: :cpp:func:`lammps_set_internal_variable`
|
||||
|
||||
--------
|
||||
|
||||
.. f:function:: eval(expr)
|
||||
|
||||
This function is a wrapper around :cpp:func:`lammps_eval` that takes a
|
||||
LAMMPS equal style variable string, evaluates it and returns the resulting
|
||||
scalar value as a floating-point number.
|
||||
|
||||
.. versionadded:: TBD
|
||||
|
||||
:p character(len=\*) expr: string to be evaluated
|
||||
:to: :cpp:func:`lammps_eval`
|
||||
:r value [real(c_double)]: result of the evaluated string
|
||||
|
||||
--------
|
||||
|
||||
.. f:subroutine:: clearstep_compute()
|
||||
|
||||
Clear whether a compute has been invoked
|
||||
|
||||
.. versionadded:: TBD
|
||||
|
||||
:to: :cpp:func:`lammps_clearstep_compute`
|
||||
|
||||
--------
|
||||
|
||||
.. f:subroutine:: addstep_compute(nextstep)
|
||||
|
||||
Add timestep to list of future compute invocations
|
||||
if the compute has been invoked on the current timestep
|
||||
|
||||
.. versionadded:: TBD
|
||||
|
||||
overloaded for 32-bit and 64-bit integer arguments
|
||||
|
||||
:p integer(kind=8 or kind=4) nextstep: next timestep
|
||||
:to: :cpp:func:`lammps_addstep_compute`
|
||||
|
||||
--------
|
||||
|
||||
.. f:subroutine:: addstep_compute_all(nextstep)
|
||||
|
||||
Add timestep to list of future compute invocations
|
||||
|
||||
.. versionadded:: TBD
|
||||
|
||||
overloaded for 32-bit and 64-bit integer arguments
|
||||
|
||||
:p integer(kind=8 or kind=4) nextstep: next timestep
|
||||
:to: :cpp:func:`lammps_addstep_compute_all`
|
||||
|
||||
--------
|
||||
|
||||
.. f:subroutine:: gather_atoms(name, count, data)
|
||||
|
||||
This function calls :cpp:func:`lammps_gather_atoms` to gather the named
|
||||
|
||||
@ -10,20 +10,21 @@ and/or pressure (P) is specified by the user, and the thermostat or
|
||||
barostat attempts to equilibrate the system to the requested T and/or
|
||||
P.
|
||||
|
||||
Barostatting in LAMMPS is performed by :doc:`fixes <fix>`. Two
|
||||
Barostatting in LAMMPS is performed by :doc:`fixes <fix>`. Three
|
||||
barostatting methods are currently available: Nose-Hoover (npt and
|
||||
nph) and Berendsen:
|
||||
nph), Berendsen, and various linear controllers in deform/pressure:
|
||||
|
||||
* :doc:`fix npt <fix_nh>`
|
||||
* :doc:`fix npt/sphere <fix_npt_sphere>`
|
||||
* :doc:`fix npt/asphere <fix_npt_asphere>`
|
||||
* :doc:`fix nph <fix_nh>`
|
||||
* :doc:`fix press/berendsen <fix_press_berendsen>`
|
||||
* :doc:`fix deform/pressure <fix_deform_pressure>`
|
||||
|
||||
The :doc:`fix npt <fix_nh>` commands include a Nose-Hoover thermostat
|
||||
and barostat. :doc:`Fix nph <fix_nh>` is just a Nose/Hoover barostat;
|
||||
it does no thermostatting. Both :doc:`fix nph <fix_nh>` and :doc:`fix press/berendsen <fix_press_berendsen>` can be used in conjunction
|
||||
with any of the thermostatting fixes.
|
||||
it does no thermostatting. The fixes :doc:`nph <fix_nh>`, :doc:`press/berendsen <fix_press_berendsen>`, and :doc:`deform/pressure <fix_deform_pressure>`
|
||||
can be used in conjunction with any of the thermostatting fixes.
|
||||
|
||||
As with the :doc:`thermostats <Howto_thermostat>`, :doc:`fix npt <fix_nh>`
|
||||
and :doc:`fix nph <fix_nh>` only use translational motion of the
|
||||
@ -44,9 +45,9 @@ a temperature or pressure compute to a barostatting fix.
|
||||
.. note::
|
||||
|
||||
As with the thermostats, the Nose/Hoover methods (:doc:`fix npt <fix_nh>` and :doc:`fix nph <fix_nh>`) perform time integration.
|
||||
:doc:`Fix press/berendsen <fix_press_berendsen>` does NOT, so it should
|
||||
be used with one of the constant NVE fixes or with one of the NVT
|
||||
fixes.
|
||||
:doc:`Fix press/berendsen <fix_press_berendsen>` and :doc:`fix deform/pressure <fix_deform_pressure>`
|
||||
do NOT, so they should be used with one of the constant NVE fixes or with
|
||||
one of the NVT fixes.
|
||||
|
||||
Thermodynamic output, which can be setup via the
|
||||
:doc:`thermo_style <thermo_style>` command, often includes pressure
|
||||
|
||||
@ -52,6 +52,7 @@ your machine and "release" is one of the 3 branches listed above.
|
||||
between them at any time using "git checkout <branch name>".)
|
||||
|
||||
.. admonition:: Saving time and disk space when using ``git clone``
|
||||
:class: note
|
||||
|
||||
The complete git history of the LAMMPS project is quite large because
|
||||
it contains the entire commit history of the project since fall 2006,
|
||||
|
||||
@ -13,6 +13,9 @@ fixes, or variables in LAMMPS using the following functions:
|
||||
- :cpp:func:`lammps_set_internal_variable`
|
||||
- :cpp:func:`lammps_variable_info`
|
||||
- :cpp:func:`lammps_eval`
|
||||
- :cpp:func:`lammps_clearstep_compute`
|
||||
- :cpp:func:`lammps_addstep_compute_all`
|
||||
- :cpp:func:`lammps_addstep_compute`
|
||||
|
||||
-----------------------
|
||||
|
||||
@ -61,6 +64,21 @@ fixes, or variables in LAMMPS using the following functions:
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_clearstep_compute
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_addstep_compute_all
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_addstep_compute
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenenum:: _LMP_DATATYPE_CONST
|
||||
|
||||
.. doxygenenum:: _LMP_STYLE_CONST
|
||||
|
||||
@ -45,6 +45,8 @@ class. See compute.h for details.
|
||||
+-----------------------+------------------------------------------------------------------+
|
||||
| pair_tally_callback | callback function for *tally*\ -style computes (optional). |
|
||||
+-----------------------+------------------------------------------------------------------+
|
||||
| modify_param | called when a compute_modify request is executed (optional) |
|
||||
+-----------------------+------------------------------------------------------------------+
|
||||
| memory_usage | tally memory usage (optional) |
|
||||
+-----------------------+------------------------------------------------------------------+
|
||||
|
||||
|
||||
@ -236,6 +236,7 @@ The individual style names on the :doc:`Commands compute <Commands_compute>` pag
|
||||
* :doc:`fep/ta <compute_fep_ta>` - compute free energies for a test area perturbation
|
||||
* :doc:`force/tally <compute_tally>` - force between two groups of atoms via the tally callback mechanism
|
||||
* :doc:`fragment/atom <compute_cluster_atom>` - fragment ID for each atom
|
||||
* :doc:`gaussian/grid/local <compute_gaussian_grid_local>` - local array of Gaussian atomic contributions on a regular grid
|
||||
* :doc:`global/atom <compute_global_atom>` - assign global values to each atom from arrays of global values
|
||||
* :doc:`group/group <compute_group_group>` - energy/force between two groups of atoms
|
||||
* :doc:`gyration <compute_gyration>` - radius of gyration of group of atoms
|
||||
|
||||
99
doc/src/compute_gaussian_grid_local.rst
Normal file
99
doc/src/compute_gaussian_grid_local.rst
Normal file
@ -0,0 +1,99 @@
|
||||
.. index:: compute gaussian/grid/local
|
||||
.. index:: compute gaussian/grid/local/kk
|
||||
|
||||
compute gaussian/grid/local command
|
||||
===================================
|
||||
|
||||
Accelerator Variants: *gaussian/grid/local/kk*
|
||||
|
||||
Syntax
|
||||
""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
compute ID group-ID gaussian/grid/local grid nx ny nz rcutfac R_1 R_2 ... sigma_1 sigma_2
|
||||
|
||||
* ID, group-ID are documented in :doc:`compute <compute>` command
|
||||
* gaussian/grid/local = style name of this compute command
|
||||
* *grid* values = nx, ny, nz, number of grid points in x, y, and z directions (positive integer)
|
||||
* *rcutfac* = scale factor applied to all cutoff radii (positive real)
|
||||
* *R_1, R_2,...* = list of cutoff radii, one for each type (distance units)
|
||||
* *sigma_1, sigma_2,...* = Gaussian widths, one for each type (distance units)
|
||||
|
||||
Examples
|
||||
""""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
compute mygrid all gaussian/grid/local grid 40 40 40 4.0 0.5 0.5 0.4 0.4
|
||||
|
||||
Description
|
||||
"""""""""""
|
||||
|
||||
.. versionadded:: TBD
|
||||
|
||||
Define a computation that calculates a Gaussian representation of the ionic
|
||||
structure. This representation is used for the efficient evaluation
|
||||
of quantities related to the structure factor in a grid-based workflow,
|
||||
such as the ML-DFT workflow MALA :ref:`(Ellis) <Ellis2021b>`, for which it was originally
|
||||
implemented. Usage of the workflow is described in a separate publication :ref:`(Fiedler) <Fiedler2023>`.
|
||||
|
||||
For each LAMMPS type, a separate sum of Gaussians is calculated, using
|
||||
a separate Gaussian broadening per type. The computation
|
||||
is always performed on the numerical grid, no atom-based version of this
|
||||
compute exists. The Gaussian representation can only be executed in a local
|
||||
fashion, thus the output array only contains rows for grid points
|
||||
that are local to the processor subdomain. The layout of the grid is the same
|
||||
as for the see :doc:`sna/grid/local <compute_sna_atom>` command.
|
||||
|
||||
Namely, the array contains one row for each of the
|
||||
local grid points, looping over the global index *ix* fastest,
|
||||
then *iy*, and *iz* slowest. Each row of the array contains
|
||||
the global indexes *ix*, *iy*, and *iz* first, followed by the *x*, *y*,
|
||||
and *z* coordinates of the grid point, followed by the values of the Gaussians
|
||||
(one floating point number per type per grid point).
|
||||
|
||||
----------
|
||||
|
||||
|
||||
.. include:: accel_styles.rst
|
||||
|
||||
|
||||
|
||||
----------
|
||||
|
||||
Output info
|
||||
"""""""""""
|
||||
|
||||
Compute *gaussian/grid/local* evaluates a local array.
|
||||
The array contains one row for each of the
|
||||
local grid points, looping over the global index *ix* fastest,
|
||||
then *iy*, and *iz* slowest. The array contains math :math:`ntypes+6` columns,
|
||||
where *ntypes* is the number of LAMMPS types. The first three columns are
|
||||
the global indexes *ix*, *iy*, and *iz*, followed by the *x*, *y*,
|
||||
and *z* coordinates of the grid point, followed by the *ntypes* columns
|
||||
containing the values of the Gaussians for each type.
|
||||
|
||||
Restrictions
|
||||
""""""""""""
|
||||
|
||||
These computes are part of the ML-SNAP package. They are only enabled
|
||||
if LAMMPS was built with that package. See the :doc:`Build package
|
||||
<Build_package>` page for more info.
|
||||
|
||||
Related commands
|
||||
""""""""""""""""
|
||||
|
||||
:doc:`compute sna/grid/local <compute_sna_atom>`
|
||||
|
||||
----------
|
||||
|
||||
.. _Ellis2021b:
|
||||
|
||||
**(Ellis)** Ellis, Fiedler, Popoola, Modine, Stephens, Thompson, Cangi, Rajamanickam, `Phys. Rev. B, 104, 035120, (2021) <https://doi.org/10.1103/PhysRevB.104.035120>`_
|
||||
|
||||
.. _Fiedler2023:
|
||||
|
||||
**(Fiedler)** Fiedler, Modine, Schmerler, Vogel, Popoola, Thompson, Rajamanickam, and Cangi,
|
||||
`npj Comp. Mater., 9, 115 (2023) <https://doi.org/10.1038/s41524-023-01070-z>`_
|
||||
|
||||
@ -3,7 +3,9 @@
|
||||
.. index:: compute snav/atom
|
||||
.. index:: compute snap
|
||||
.. index:: compute sna/grid
|
||||
.. index:: compute sna/grid/kk
|
||||
.. index:: compute sna/grid/local
|
||||
.. index:: compute sna/grid/local/kk
|
||||
|
||||
compute sna/atom command
|
||||
========================
|
||||
@ -20,9 +22,14 @@ compute snap command
|
||||
compute sna/grid command
|
||||
========================
|
||||
|
||||
compute sna/grid/kk command
|
||||
===========================
|
||||
|
||||
compute sna/grid/local command
|
||||
==============================
|
||||
|
||||
Accelerator Variants: *sna/grid/local/kk*
|
||||
|
||||
Syntax
|
||||
""""""
|
||||
|
||||
@ -33,17 +40,17 @@ Syntax
|
||||
compute ID group-ID snav/atom rcutfac rfac0 twojmax R_1 R_2 ... w_1 w_2 ... keyword values ...
|
||||
compute ID group-ID snap rcutfac rfac0 twojmax R_1 R_2 ... w_1 w_2 ... keyword values ...
|
||||
compute ID group-ID snap rcutfac rfac0 twojmax R_1 R_2 ... w_1 w_2 ... keyword values ...
|
||||
compute ID group-ID sna/grid nx ny nz rcutfac rfac0 twojmax R_1 R_2 ... w_1 w_2 ... keyword values ...
|
||||
compute ID group-ID sna/grid/local nx ny nz rcutfac rfac0 twojmax R_1 R_2 ... w_1 w_2 ... keyword values ...
|
||||
compute ID group-ID sna/grid grid nx ny nz rcutfac rfac0 twojmax R_1 R_2 ... w_1 w_2 ... keyword values ...
|
||||
compute ID group-ID sna/grid/local grid nx ny nz rcutfac rfac0 twojmax R_1 R_2 ... w_1 w_2 ... keyword values ...
|
||||
|
||||
* ID, group-ID are documented in :doc:`compute <compute>` command
|
||||
* sna/atom = style name of this compute command
|
||||
* rcutfac = scale factor applied to all cutoff radii (positive real)
|
||||
* rfac0 = parameter in distance to angle conversion (0 < rcutfac < 1)
|
||||
* twojmax = band limit for bispectrum components (non-negative integer)
|
||||
* R_1, R_2,... = list of cutoff radii, one for each type (distance units)
|
||||
* w_1, w_2,... = list of neighbor weights, one for each type
|
||||
* nx, ny, nz = number of grid points in x, y, and z directions (positive integer)
|
||||
* *rcutfac* = scale factor applied to all cutoff radii (positive real)
|
||||
* *rfac0* = parameter in distance to angle conversion (0 < rcutfac < 1)
|
||||
* *twojmax* = band limit for bispectrum components (non-negative integer)
|
||||
* *R_1, R_2,...* = list of cutoff radii, one for each type (distance units)
|
||||
* *w_1, w_2,...* = list of neighbor weights, one for each type
|
||||
* *grid* values = nx, ny, nz, number of grid points in x, y, and z directions (positive integer)
|
||||
* zero or more keyword/value pairs may be appended
|
||||
* keyword = *rmin0* or *switchflag* or *bzeroflag* or *quadraticflag* or *chem* or *bnormflag* or *wselfallflag* or *bikflag* or *switchinnerflag* or *sinner* or *dinner* or *dgradflag* or *nnn* or *wmode* or *delta*
|
||||
|
||||
@ -103,7 +110,7 @@ Examples
|
||||
compute snap all snap 1.4 0.95 6 2.0 1.0
|
||||
compute snap all snap 1.0 0.99363 6 3.81 3.83 1.0 0.93 chem 2 0 1
|
||||
compute snap all snap 1.0 0.99363 6 3.81 3.83 1.0 0.93 switchinnerflag 1 sinner 1.35 1.6 dinner 0.25 0.3
|
||||
compute bgrid all sna/grid/local 200 200 200 1.4 0.95 6 2.0 1.0
|
||||
compute bgrid all sna/grid/local grid 200 200 200 1.4 0.95 6 2.0 1.0
|
||||
compute bnnn all sna/atom 9.0 0.99363 8 0.5 1.0 rmin0 0.0 nnn 24 wmode 1 delta 0.2
|
||||
|
||||
Description
|
||||
@ -252,7 +259,8 @@ for finite-temperature Kohn-Sham density functional theory (:ref:`Ellis
|
||||
et al. <Ellis2021>`) Neighbor atoms not in the group do not contribute
|
||||
to the bispectrum components of the grid points. The distance cutoff
|
||||
:math:`R_{ii'}` assumes that *i* has the same type as the neighbor atom
|
||||
*i'*.
|
||||
*i'*. Both computes can be hardware accelerated with Kokkos by using the
|
||||
*sna/grid/kk* and *sna/grid/local/kk* commands, respectively.
|
||||
|
||||
Compute *sna/grid* calculates a global array containing bispectrum
|
||||
components for a regular grid of points.
|
||||
@ -463,6 +471,12 @@ fluctuations in the resulting local atomic environment fingerprint. The
|
||||
detailed formalism is given in the paper by Lafourcade et
|
||||
al. :ref:`(Lafourcade) <Lafourcade2023_2>`.
|
||||
|
||||
----------
|
||||
|
||||
|
||||
.. include:: accel_styles.rst
|
||||
|
||||
|
||||
----------
|
||||
|
||||
Output info
|
||||
@ -654,7 +668,7 @@ of Angular Momentum, World Scientific, Singapore (1987).
|
||||
|
||||
.. _Ellis2021:
|
||||
|
||||
**(Ellis)** Ellis, Fiedler, Popoola, Modine, Stephens, Thompson, Cangi, Rajamanickam, Phys Rev B, 104, 035120, (2021)
|
||||
**(Ellis)** Ellis, Fiedler, Popoola, Modine, Stephens, Thompson, Cangi, Rajamanickam, `Phys. Rev. B, 104, 035120, (2021) <https://doi.org/10.1103/PhysRevB.104.035120>`_
|
||||
|
||||
.. _Lafourcade2023_2:
|
||||
|
||||
|
||||
@ -66,6 +66,15 @@ gives access to the LAMMPS state from Python.
|
||||
from these callbacks, trying to execute input script commands will in the best
|
||||
case not work or in the worst case result in undefined behavior.
|
||||
|
||||
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
|
||||
""""""""""""
|
||||
|
||||
|
||||
@ -200,8 +200,8 @@ The 2 values in the global vector are as follows:
|
||||
The per-atom vector stores the molecule ID for each atom as identified
|
||||
by the fix. If an atom is not in a molecule, its ID will be 0.
|
||||
For atoms in the same molecule, the molecule ID for all of them
|
||||
will be the same and will be equal to the smallest atom ID of
|
||||
any atom in the molecule.
|
||||
will be the same, and molecule IDs will range from 1 to the number
|
||||
of molecules.
|
||||
|
||||
No parameter of this fix can be used with the *start/stop* keywords of
|
||||
the :doc:`run <run>` command.
|
||||
|
||||
@ -222,10 +222,10 @@ restart file, so that the operation of the fix continues in an
|
||||
uninterrupted fashion.
|
||||
|
||||
If the :code:`contacts` option is used, this fix generates a per-atom array
|
||||
with 8 columns as output, containing the contact information for owned
|
||||
with at least 8 columns as output, containing the contact information for owned
|
||||
particles (nlocal on each processor). All columns in this per-atom array will
|
||||
be zero if no contact has occurred. The values of these columns are listed in
|
||||
the following table:
|
||||
be zero if no contact has occurred. The first 8 values of these columns are
|
||||
listed in the following table.
|
||||
|
||||
+-------+----------------------------------------------------+----------------+
|
||||
| Index | Value | Units |
|
||||
@ -248,6 +248,14 @@ the following table:
|
||||
| 8 | Radius :math:`r` of atom | distance units |
|
||||
+-------+----------------------------------------------------+----------------+
|
||||
|
||||
If a granular sub-model calculates additional contact information (e.g. the
|
||||
heat sub-models calculate the amount of heat exchanged), these quantities
|
||||
are appended to the end of this array. First, any extra values from the
|
||||
normal sub-model are appended followed by the damping, tangential, rolling,
|
||||
twisting, then heat models. See the descriptions of granular sub-models in
|
||||
the :doc:`pair granular <pair_granular>` page for information on any extra
|
||||
quantities.
|
||||
|
||||
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. This fix is not invoked during :doc:`energy
|
||||
|
||||
@ -243,10 +243,10 @@ uninterrupted fashion.
|
||||
with a different region ID.
|
||||
|
||||
If the :code:`contacts` option is used, this fix generates a per-atom array
|
||||
with 8 columns as output, containing the contact information for owned
|
||||
with at least 8 columns as output, containing the contact information for owned
|
||||
particles (nlocal on each processor). All columns in this per-atom array will
|
||||
be zero if no contact has occurred. The values of these columns are listed in
|
||||
the following table:
|
||||
be zero if no contact has occurred. The first 8 values of these columns are
|
||||
listed in the following table.
|
||||
|
||||
+-------+----------------------------------------------------+----------------+
|
||||
| Index | Value | Units |
|
||||
@ -269,6 +269,14 @@ the following table:
|
||||
| 8 | Radius :math:`r` of atom | distance units |
|
||||
+-------+----------------------------------------------------+----------------+
|
||||
|
||||
If a granular sub-model calculates additional contact information (e.g. the
|
||||
heat sub-models calculate the amount of heat exchanged), these quantities
|
||||
are appended to the end of this array. First, any extra values from the
|
||||
normal sub-model are appended followed by the damping, tangential, rolling,
|
||||
twisting, then heat models. See the descriptions of granular sub-models in
|
||||
the :doc:`pair granular <pair_granular>` page for information on any extra
|
||||
quantities.
|
||||
|
||||
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. This fix is not invoked during :doc:`energy
|
||||
|
||||
@ -412,11 +412,9 @@ slab correction has also been extended to point dipole interactions
|
||||
.. note::
|
||||
|
||||
If you wish to apply an electric field in the Z-direction, in
|
||||
conjunction with the *slab* keyword, you should do it by adding
|
||||
explicit charged particles to the +/- Z surfaces. If you do it via
|
||||
the :doc:`fix efield <fix_efield>` command, it will not give the correct
|
||||
dielectric constant due to the Yeh/Berkowitz :ref:`(Yeh) <Yeh>` correction
|
||||
not being compatible with how :doc:`fix efield <fix_efield>` works.
|
||||
conjunction with the *slab* keyword, you can do it either by
|
||||
adding explicit oppositely charged particles to the +/- Z surfaces,
|
||||
or by using the :doc:`fix efield <fix_efield>` command.
|
||||
|
||||
----------
|
||||
|
||||
|
||||
@ -40,6 +40,9 @@ Examples
|
||||
pair_style granular
|
||||
pair_coeff * * hertz 1000.0 50.0 tangential mindlin 1000.0 1.0 0.4 heat area 0.1
|
||||
|
||||
pair_style granular
|
||||
pair_coeff * * mdr 5e6 0.4 1.9e5 2.0 0.5 0.5 tangential linear_history 940.0 0.0 0.7 rolling sds 2.7e5 0.0 0.6 damping none
|
||||
|
||||
Description
|
||||
"""""""""""
|
||||
|
||||
@ -82,6 +85,7 @@ and their required arguments are:
|
||||
3. *hertz/material* : E, :math:`\eta_{n0}` (or :math:`e`), :math:`\nu`
|
||||
4. *dmt* : E, :math:`\eta_{n0}` (or :math:`e`), :math:`\nu`, :math:`\gamma`
|
||||
5. *jkr* : E, :math:`\eta_{n0}` (or :math:`e`), :math:`\nu`, :math:`\gamma`
|
||||
6. *mdr* : :math:`E`, :math:`\nu`, :math:`Y`, :math:`\Delta\gamma`, :math:`\psi_b`, :math:`e`
|
||||
|
||||
Here, :math:`k_n` is spring stiffness (with units that depend on model
|
||||
choice, see below); :math:`\eta_{n0}` is a damping prefactor (or, in its
|
||||
@ -162,6 +166,144 @@ initially will not experience force until they come into contact
|
||||
experience a tensile force up to :math:`3\pi\gamma R`, at which point they
|
||||
lose contact.
|
||||
|
||||
The *mdr* model is a mechanically-derived contact model designed to capture the
|
||||
contact response between adhesive elastic-plastic particles into large deformation.
|
||||
The theoretical foundations of the *mdr* model are detailed in the
|
||||
two-part series :ref:`Zunker and Kamrin Part I <Zunker2024I>` and
|
||||
:ref:`Zunker and Kamrin Part II <Zunker2024II>`. Further development
|
||||
and demonstrations of its application to industrially relevant powder
|
||||
compaction processes are presented in :ref:`Zunker et al. <Zunker2025>`.
|
||||
|
||||
The model requires the following inputs:
|
||||
|
||||
1. *Young's modulus* :math:`E > 0` : The Young's modulus is commonly reported
|
||||
for various powders.
|
||||
|
||||
2. *Poisson's ratio* :math:`0 \le \nu \le 0.5` : The Poisson's ratio is commonly
|
||||
reported for various powders.
|
||||
|
||||
3. *Yield stress* :math:`Y \ge 0` : The yield stress is often known for powders
|
||||
composed of materials such as metals but may be unreported for ductile organic
|
||||
materials, in which case it can be treated as a free parameter.
|
||||
|
||||
4. *Effective surface energy* :math:`\Delta\gamma \ge 0` : The effective surface
|
||||
energy for powder compaction applications is most easily determined through its
|
||||
relation to the more commonly reported critical stress intensity factor
|
||||
:math:`K_{Ic} = \sqrt{2\Delta\gamma E/(1-\nu^2)}`.
|
||||
|
||||
5. *Critical confinement ratio* :math:`0 \le \psi_b \le 1` : The critical confinement
|
||||
ratio is a tunable parameter that determines when the bulk elastic response is
|
||||
triggered. Lower values of :math:`\psi_b` delay the onset of the bulk elastic
|
||||
response.
|
||||
|
||||
6. *Coefficient of restitution* :math:`0 \le e \le 1` : The coefficient of
|
||||
restitution is a tunable parameter that controls damping in the normal direction.
|
||||
|
||||
.. note::
|
||||
|
||||
The values for :math:`E`, :math:`\nu`, :math:`Y`, and :math:`\Delta\gamma` (i.e.,
|
||||
:math:`K_{Ic}`) should be selected for zero porosity to reflect the intrinsic
|
||||
material property rather than the bulk powder property.
|
||||
|
||||
The *mdr* model produces a nonlinear force-displacement response, therefore the
|
||||
critical timestep :math:`\Delta t` depends on the inputs and level of
|
||||
deformation. As a conservative starting point the timestep can be assumed to be
|
||||
dictated by the bulk elastic response such that
|
||||
:math:`\Delta t = 0.35\sqrt{m/k_\textrm{bulk}}`, where :math:`m` is the mass of
|
||||
the smallest particle and :math:`k_\textrm{bulk} = \kappa R_\textrm{min}` is an
|
||||
effective stiffness related to the bulk elastic response.
|
||||
Here, :math:`\kappa = E/(3(1-2\nu))` is the bulk modulus and
|
||||
:math:`R_\textrm{min}` is the radius of the smallest particle.
|
||||
|
||||
.. note::
|
||||
|
||||
The *mdr* model requires some specific settings to function properly,
|
||||
please read the following text carefully to ensure all requirements are
|
||||
followed.
|
||||
|
||||
The *atom_style* must be set to *sphere 1* to enable dynamic particle
|
||||
radii. The *mdr* model is designed to respect the incompressibility of
|
||||
plastic deformation and inherently tracks free surface displacements
|
||||
induced by all particle contacts. In practice, this means that all particles
|
||||
begin with an initial radius, however as compaction occurs and plastic
|
||||
deformation is accumulated, a new enlarged apparent radius is defined to
|
||||
ensure that that volume change due to plastic deformation is not lost.
|
||||
This apparent radius is stored as the *atom radius* meaning it is used
|
||||
for subsequent neighbor list builds and contact detection checks. The
|
||||
advantage of this is that multi-neighbor dependent effects such as
|
||||
formation of secondary contacts caused by radial expansion are captured
|
||||
by the *mdr* model. Setting *atom_style sphere 1* ensures that updates to
|
||||
the particle radii are properly reflected throughout the simulation.
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
atom_style sphere 1
|
||||
|
||||
Newton's third law must be set to *off*. This ensures that the neighbor lists
|
||||
are constructed properly for the topological penalty algorithm used to screen
|
||||
for non-physical contacts occurring through obstructing particles, an issue
|
||||
prevalent under large deformation conditions. For more information on this
|
||||
algorithm see :ref:`Zunker et al. <Zunker2025>`.
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
newton off
|
||||
|
||||
The damping model must be set to *none*. The *mdr* model already has a built
|
||||
in damping model.
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
pair_coeff * * mdr 5e6 0.4 1.9e5 2 0.5 0.5 damping none
|
||||
|
||||
The definition of multiple *mdr* models in the *pair_style* is currently not
|
||||
supported. Similarly, the *mdr* model cannot be combined with a different normal
|
||||
model in the *pair_style*. Physically this means that only one homogeneous
|
||||
collection of particles governed by a single *mdr* model is allowed.
|
||||
|
||||
The *mdr* model currently only supports *fix wall/gran/region*, not
|
||||
*fix wall/gran*. If the *mdr* model is specified for the *pair_style*
|
||||
any *fix wall/gran/region* commands must also use the *mdr* model.
|
||||
Additionally, the following *mdr* inputs must match between the
|
||||
*pair_style* and *fix wall/gran/region* definitions: :math:`E`,
|
||||
:math:`\nu`, :math:`Y`, :math:`\psi_b`, and :math:`e`. The exception
|
||||
is :math:`\Delta\gamma`, which may vary, permitting different
|
||||
adhesive behaviors between particle-particle and particle-wall interactions.
|
||||
|
||||
.. note::
|
||||
|
||||
The *mdr* model has a number of custom *property/atom* and *pair/local* definitions that
|
||||
can be called in the input file. The useful properties for visualization
|
||||
and analysis are described below.
|
||||
|
||||
In addition to contact forces the *mdr* model also tracks the following
|
||||
quantities for each particle: elastic volume change, average normal
|
||||
stress components, total surface area involved in
|
||||
contact, and individual contact areas. In the input script, these quantities are
|
||||
initialized by calling *run 0* and can then be accessed using subsequent *compute*
|
||||
commands. The last *compute* command uses *pair/local p13* to calculate the pairwise
|
||||
contact areas for each active contact in the *group-ID*. Due to the use of an apparent
|
||||
radius in the *mdr* model, the keyword/arg pair *cutoff radius* must be specified for
|
||||
*pair/local* to properly detect existing contacts.
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
run 0
|
||||
compute ID group-ID property/atom d_Velas
|
||||
compute ID group-ID property/atom d_sigmaxx
|
||||
compute ID group-ID property/atom d_sigmayy
|
||||
compute ID group-ID property/atom d_sigmazz
|
||||
compute ID group-ID property/atom d_Acon1
|
||||
compute ID group-ID pair/local p13 cutoff radius
|
||||
|
||||
.. note::
|
||||
|
||||
The *mdr* model has two example input scripts within the
|
||||
*examples/granular* directory. The first is a die compaction
|
||||
simulation involving 200 particles named *in.tableting.200*.
|
||||
The second is a triaxial compaction simulation involving 12
|
||||
particles named *in.triaxial.compaction.12*.
|
||||
|
||||
----------
|
||||
|
||||
In addition, the normal force is augmented by a damping term of the
|
||||
@ -674,7 +816,10 @@ supported are:
|
||||
2. *radius* : :math:`k_{s}`
|
||||
3. *area* : :math:`h_{s}`
|
||||
|
||||
If the *heat* keyword is not specified, the model defaults to *none*.
|
||||
If the *heat* keyword is not specified, the model defaults to *none*. All
|
||||
heat models calculate an additional pairwise quantity accessible by the
|
||||
single() function (described below) which is the heat conducted between the
|
||||
two particles.
|
||||
|
||||
For *heat* *radius*, the heat
|
||||
:math:`Q` conducted between two particles is given by
|
||||
@ -789,7 +934,7 @@ 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. However, the single() function also
|
||||
calculates 13 extra pairwise quantities. The first 3 are the
|
||||
calculates at least 13 extra pairwise quantities. The first 3 are the
|
||||
components of the tangential force between particles I and J, acting
|
||||
on particle I. The fourth is the magnitude of this tangential force.
|
||||
The next 3 (5-7) are the components of the rolling torque acting on
|
||||
@ -797,9 +942,17 @@ particle I. The next entry (8) is the magnitude of the rolling torque.
|
||||
The next entry (9) is the magnitude of the twisting torque acting
|
||||
about the vector connecting the two particle centers.
|
||||
The next 3 (10-12) are the components of the vector connecting
|
||||
the centers of the two particles (x_I - x_J). The last quantity (13)
|
||||
is the heat flow between the two particles, set to 0 if no heat model
|
||||
is active.
|
||||
the centers of the two particles (x_I - x_J). If a granular sub-model
|
||||
calculates additional contact information (e.g. the heat sub-models
|
||||
calculate the amount of heat exchanged), these quantities are appended
|
||||
to the end of this list. First, any extra values from the normal sub-model
|
||||
are appended followed by the damping, tangential, rolling, twisting, then
|
||||
heat models. See the descriptions of specific granular sub-models above
|
||||
for information on any extra quantities. If two or more models are
|
||||
defined by pair coefficients, the size of the array is set by the
|
||||
maximum number of extra quantities in a model but the order of quantities
|
||||
is determined by each model's specific set of sub-models. Any unused
|
||||
quantities are zeroed.
|
||||
|
||||
These extra quantities can be accessed by the :doc:`compute pair/local <compute_pair_local>` command, as *p1*, *p2*, ...,
|
||||
*p12*\ .
|
||||
@ -870,10 +1023,32 @@ solids. Proc. R. Soc. Lond. A, 324(1558), 301-313.
|
||||
|
||||
.. _DMT1975:
|
||||
|
||||
**Derjaguin et al, 1975)** Derjaguin, B. V., Muller, V. M., & Toporov,
|
||||
**(Derjaguin et al, 1975)** Derjaguin, B. V., Muller, V. M., & Toporov,
|
||||
Y. P. (1975). Effect of contact deformations on the adhesion of
|
||||
particles. Journal of Colloid and interface science, 53(2), 314-326.
|
||||
|
||||
.. _Zunker2024I:
|
||||
|
||||
**(Zunker and Kamrin, 2024)** Zunker, W., & Kamrin, K. (2024).
|
||||
A mechanically-derived contact model for adhesive elastic-perfectly
|
||||
plastic particles, Part I: Utilizing the method of dimensionality
|
||||
reduction. Journal of the Mechanics and Physics of Solids, 183, 105492.
|
||||
|
||||
.. _Zunker2024II:
|
||||
|
||||
**(Zunker and Kamrin, 2024)** Zunker, W., & Kamrin, K. (2024).
|
||||
A mechanically-derived contact model for adhesive elastic-perfectly
|
||||
plastic particles, Part II: Contact under high compaction-modeling
|
||||
a bulk elastic response. Journal of the Mechanics and Physics of Solids,
|
||||
183, 105493.
|
||||
|
||||
.. _Zunker2025:
|
||||
|
||||
**(Zunker et al, 2025)** Zunker, W., Dunatunga, S., Thakur, S.,
|
||||
Tang, P., & Kamrin, K. (2025). Experimentally validated DEM for large
|
||||
deformation powder compaction: mechanically-derived contact model and
|
||||
screening of non-physical contacts.
|
||||
|
||||
.. _Luding2008:
|
||||
|
||||
**(Luding, 2008)** Luding, S. (2008). Cohesive, frictional powders:
|
||||
|
||||
@ -1,30 +1,46 @@
|
||||
.. index:: pair_style hbond/dreiding/lj
|
||||
.. index:: pair_style hbond/dreiding/lj/omp
|
||||
.. index:: pair_style hbond/dreiding/lj/angleoffset
|
||||
.. index:: pair_style hbond/dreiding/lj/angleoffset/omp
|
||||
.. index:: pair_style hbond/dreiding/morse
|
||||
.. index:: pair_style hbond/dreiding/morse/omp
|
||||
.. index:: pair_style hbond/dreiding/morse/angleoffset
|
||||
.. index:: pair_style hbond/dreiding/morse/angleoffset/omp
|
||||
|
||||
pair_style hbond/dreiding/lj command
|
||||
====================================
|
||||
|
||||
Accelerator Variants: *hbond/dreiding/lj/omp*
|
||||
|
||||
pair_style hbond/dreiding/lj/angleoffset command
|
||||
================================================
|
||||
|
||||
Accelerator Variants: *hbond/dreiding/lj/angleoffset/omp*
|
||||
|
||||
pair_style hbond/dreiding/morse command
|
||||
=======================================
|
||||
|
||||
Accelerator Variants: *hbond/dreiding/morse/omp*
|
||||
|
||||
pair_style hbond/dreiding/morse/angleoffset command
|
||||
===================================================
|
||||
|
||||
Accelerator Variants: *hbond/dreiding/morse/angleoffset/omp*
|
||||
|
||||
|
||||
Syntax
|
||||
""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
pair_style style N inner_distance_cutoff outer_distance_cutoff angle_cutoff
|
||||
pair_style style N inner_distance_cutoff outer_distance_cutoff angle_cutoff equilibrium_angle
|
||||
|
||||
* style = *hbond/dreiding/lj* or *hbond/dreiding/morse*
|
||||
* style = *hbond/dreiding/lj* or *hbond/dreiding/morse* or *hbond/dreiding/lj/angleoffset* or *hbond/dreiding/morse/angleoffset*
|
||||
* N = power of cosine of angle theta (integer)
|
||||
* inner_distance_cutoff = global inner cutoff for Donor-Acceptor interactions (distance units)
|
||||
* outer_distance_cutoff = global cutoff for Donor-Acceptor interactions (distance units)
|
||||
* angle_cutoff = global angle cutoff for Acceptor-Hydrogen-Donor interactions (degrees)
|
||||
* (with style angleoffset) equilibrium_angle = global equilibrium angle for Acceptor-Hydrogen-Donor interactions (degrees)
|
||||
|
||||
Examples
|
||||
""""""""
|
||||
@ -40,6 +56,9 @@ Examples
|
||||
labelmap atom 1 C 2 O 3 H
|
||||
pair_coeff C O hbond/dreiding/morse H i 3.88 1.7241379 2.9 2 9.0 11.0 90.0
|
||||
|
||||
pair_style hybrid/overlay lj/cut 10.0 hbond/dreiding/lj 4 9.0 11.0 90 170.0
|
||||
pair_coeff 1 2 hbond/dreiding/lj 3 i 9.5 2.75 4 9.0 11.0 90.0
|
||||
|
||||
Description
|
||||
"""""""""""
|
||||
|
||||
@ -74,42 +93,53 @@ hydrogen (H) and the donor atoms:
|
||||
.. image:: JPG/dreiding_hbond.jpg
|
||||
:align: center
|
||||
|
||||
These 3-body interactions can be defined for pairs of acceptor and
|
||||
donor atoms, based on atom types. For each donor/acceptor atom pair,
|
||||
the third atom in the interaction is a hydrogen permanently bonded to
|
||||
the donor atom, e.g. in a bond list read in from a data file via the
|
||||
These 3-body interactions can be defined for pairs of acceptor and donor
|
||||
atoms, based on atom types. For each donor/acceptor atom pair, the
|
||||
third atom in the interaction is a hydrogen permanently bonded to the
|
||||
donor atom, e.g. in a bond list read in from a data file via the
|
||||
:doc:`read_data <read_data>` command. The atom types of possible
|
||||
hydrogen atoms for each donor/acceptor type pair are specified by the
|
||||
:doc:`pair_coeff <pair_coeff>` command (see below).
|
||||
|
||||
Style *hbond/dreiding/lj* is the original DREIDING potential of
|
||||
:ref:`(Mayo) <pair-Mayo>`. It uses a LJ 12/10 functional for the Donor-Acceptor
|
||||
interactions. To match the results in the original paper, use n = 4.
|
||||
:ref:`(Mayo) <pair-Mayo>`. It uses a LJ 12/10 functional for the
|
||||
Donor-Acceptor interactions. To match the results in the original paper,
|
||||
use n = 4.
|
||||
|
||||
Style *hbond/dreiding/morse* is an improved version using a Morse
|
||||
potential for the Donor-Acceptor interactions. :ref:`(Liu) <Liu>` showed
|
||||
that the Morse form gives improved results for Dendrimer simulations,
|
||||
when n = 2.
|
||||
|
||||
.. versionadded:: TBD
|
||||
|
||||
The style variants *hbond/dreiding/lj/angleoffset* and
|
||||
*hbond/dreiding/lj/angleoffset* take the equilibrium angle of the AHD as
|
||||
input, allowing it to reach 180 degrees. This variant option was added
|
||||
to account for cases (especially in some coarse-grained models) in which
|
||||
the equilibrium state of the bonds may equal the minimum energy state.
|
||||
|
||||
See the :doc:`Howto bioFF <Howto_bioFF>` page for more information
|
||||
on the DREIDING force field.
|
||||
|
||||
.. note::
|
||||
|
||||
Because the Dreiding hydrogen bond potential is only one portion
|
||||
of an overall force field which typically includes other pairwise
|
||||
interactions, it is common to use it as a sub-style in a :doc:`pair_style hybrid/overlay <pair_hybrid>` command, where another pair style
|
||||
provides the repulsive core interaction between pairs of atoms, e.g. a
|
||||
1/r\^12 Lennard-Jones repulsion.
|
||||
Because the Dreiding hydrogen bond potential is only one portion of
|
||||
an overall force field which typically includes other pairwise
|
||||
interactions, it is common to use it as a sub-style in a
|
||||
:doc:`pair_style hybrid/overlay <pair_hybrid>` command, where another
|
||||
pair style provides the repulsive core interaction between pairs of
|
||||
atoms, e.g. a 1/r\^12 Lennard-Jones repulsion.
|
||||
|
||||
.. note::
|
||||
|
||||
When using the hbond/dreiding pair styles with :doc:`pair_style hybrid/overlay <pair_hybrid>`, you should explicitly define pair
|
||||
When using the hbond/dreiding pair styles with :doc:`pair_style
|
||||
hybrid/overlay <pair_hybrid>`, you should explicitly define pair
|
||||
interactions between the donor atom and acceptor atoms, (as well as
|
||||
between these atoms and ALL other atoms in your system). Whenever
|
||||
:doc:`pair_style hybrid/overlay <pair_hybrid>` is used, ordinary mixing
|
||||
rules are not applied to atoms like the donor and acceptor atoms
|
||||
because they are typically referenced in multiple pair styles.
|
||||
:doc:`pair_style hybrid/overlay <pair_hybrid>` is used, ordinary
|
||||
mixing rules are not applied to atoms like the donor and acceptor
|
||||
atoms because they are typically referenced in multiple pair styles.
|
||||
Neglecting to do this can cause difficult-to-detect physics problems.
|
||||
|
||||
.. note::
|
||||
@ -119,6 +149,13 @@ on the DREIDING force field.
|
||||
special_bonds command (e.g. "special_bonds lj 0.0 0.0 1.0") to turn
|
||||
these interactions on.
|
||||
|
||||
.. note::
|
||||
|
||||
For the *angleoffset* variants, the referenced angle offset is the
|
||||
supplementary angle of the equilibrium angle parameter. It means if
|
||||
the equilibrium angle is 166.6 degrees, the calculated angle offset
|
||||
is 13.4 degrees.
|
||||
|
||||
----------
|
||||
|
||||
The following coefficients must be defined for pairs of eligible
|
||||
@ -169,7 +206,10 @@ follows:
|
||||
* distance cutoff :math:`r_{out}` (distance units)
|
||||
* angle cutoff (degrees)
|
||||
|
||||
A single hydrogen atom type K can be specified, or a wild-card asterisk
|
||||
For both the *hbond/dreiding/lj/angleoffset* and *hbond/dreiding/morse/angleoffset* styles an additional parameter is added:
|
||||
* equilibrium angle (degrees)
|
||||
|
||||
For all styles, a single hydrogen atom type K can be specified, or a wild-card asterisk
|
||||
can be used in place of or in conjunction with the K arguments to
|
||||
select multiple types as hydrogen atoms. This takes the form
|
||||
"\*" or "\*n" or "n\*" or "m\*n". See the :doc:`pair_coeff <pair_coeff>`
|
||||
@ -245,8 +285,7 @@ heading) the following commands could be included in an input script:
|
||||
Restrictions
|
||||
""""""""""""
|
||||
|
||||
This pair style can only be used if LAMMPS was built with the
|
||||
MOLECULE package. See the :doc:`Build package <Build_package>` doc page
|
||||
The base pair styles can only be used if LAMMPS was built with the MOLECULE package. The *angleoffset* variant also requires the EXTRA-MOLECULE package. See the :doc:`Build package <Build_package>` doc page
|
||||
for more info.
|
||||
|
||||
Related commands
|
||||
|
||||
@ -145,6 +145,7 @@ per line.
|
||||
The detail of *nn* module implementation can be found at :ref:`(Yanxon) <Yanxon2020>`.
|
||||
|
||||
.. admonition:: Notes on mliappy models
|
||||
:class: note
|
||||
|
||||
When the *model* keyword is *mliappy*, if the filename ends in '.pt',
|
||||
or '.pth', it will be loaded using pytorch; otherwise, it will be
|
||||
|
||||
@ -158,11 +158,36 @@ drops to zero.
|
||||
Optional keywords *safezone*, *mincap*, and *minhbonds* are used
|
||||
for allocating reaxff arrays. Increasing these values can avoid memory
|
||||
problems, such as segmentation faults and bondchk failed errors, that
|
||||
could occur under certain conditions. These keywords are not used by
|
||||
could occur under certain conditions. These keywords are **not** used by
|
||||
the Kokkos version, which instead uses a more robust memory allocation
|
||||
scheme that checks if the sizes of the arrays have been exceeded and
|
||||
automatically allocates more memory.
|
||||
|
||||
.. admonition:: Memory management problems with ReaxFF
|
||||
:class: tip
|
||||
|
||||
The LAMMPS implementation of ReaxFF is adapted from a standalone MD
|
||||
program written in C called `PuReMD
|
||||
<https://github.com/msu-sparta/PuReMD>`_. It inherits from this code
|
||||
a heuristic memory management that is different from what the rest of
|
||||
LAMMPS uses. It assumes that a system is dense and already well
|
||||
equilibrated, so that there are no large changes in how many and what
|
||||
types of neighbors atoms have. However, not all systems are like
|
||||
that, and thus there can be errors or segmentation faults if the
|
||||
system changes too much. If you run into problems, here are three
|
||||
options to avoid them:
|
||||
|
||||
- Use the KOKKOS version of ReaxFF (KOKKOS is not only for GPUs,
|
||||
but can also be compiled for serial or OpenMP execution) which
|
||||
uses a different memory management approach.
|
||||
- Break down a run command during which memory related errors happen
|
||||
into multiple smaller segments so that the memory management
|
||||
heuristics are re-initialized for each segment before they become
|
||||
invalid.
|
||||
- Increase the values for *safezone*, *mincap*, and *minhbonds* as
|
||||
needed. This can lead to significant increase of memory consumption
|
||||
through.
|
||||
|
||||
The keyword *tabulate* controls the size of interpolation table for
|
||||
Lennard-Jones and Coulomb interactions. Tabulation may also be set in the
|
||||
control file (see below). If tabulation is set in both the input script and the
|
||||
|
||||
@ -207,7 +207,9 @@ accelerated styles exist.
|
||||
* :doc:`gw/zbl <pair_gw>` - Gao-Weber potential with a repulsive ZBL core
|
||||
* :doc:`harmonic/cut <pair_harmonic_cut>` - repulsive-only harmonic potential
|
||||
* :doc:`hbond/dreiding/lj <pair_hbond_dreiding>` - DREIDING hydrogen bonding LJ potential
|
||||
* :doc:`hbond/dreiding/lj/angleoffset <pair_hbond_dreiding>` - DREIDING hydrogen bonding LJ potential with offset for hbond angle
|
||||
* :doc:`hbond/dreiding/morse <pair_hbond_dreiding>` - DREIDING hydrogen bonding Morse potential
|
||||
* :doc:`hbond/dreiding/morse/angleoffset <pair_hbond_dreiding>` - DREIDING hydrogen bonding Morse potential with offset for hbond angle
|
||||
* :doc:`hdnnp <pair_hdnnp>` - High-dimensional neural network potential
|
||||
* :doc:`hippo <pair_amoeba>` -
|
||||
* :doc:`ilp/graphene/hbn <pair_ilp_graphene_hbn>` - registry-dependent interlayer potential (ILP)
|
||||
|
||||
@ -56,7 +56,7 @@ Syntax
|
||||
random(x,y,z), normal(x,y,z), ceil(x), floor(x), round(x), ternary(x,y,z),
|
||||
ramp(x,y), stagger(x,y), logfreq(x,y,z), logfreq2(x,y,z),
|
||||
logfreq3(x,y,z), stride(x,y,z), stride2(x,y,z,a,b,c),
|
||||
vdisplace(x,y), swiggle(x,y,z), cwiggle(x,y,z)
|
||||
vdisplace(x,y), swiggle(x,y,z), cwiggle(x,y,z), sign(x)
|
||||
group functions = count(group), mass(group), charge(group),
|
||||
xcm(group,dim), vcm(group,dim), fcm(group,dim),
|
||||
bound(group,dir), gyration(group), ke(group),
|
||||
@ -532,37 +532,37 @@ functions, special functions, feature functions, atom values, atom
|
||||
vectors, custom atom properties, compute references, fix references, and references to other
|
||||
variables.
|
||||
|
||||
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Number | 0.2, 100, 1.0e20, -15.4, etc |
|
||||
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Constant | PI, version, on, off, true, false, yes, no |
|
||||
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Thermo keywords | vol, pe, ebond, etc |
|
||||
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Math operators | (), -x, x+y, x-y, x\*y, x/y, x\^y, x%y, x == y, x != y, x < y, x <= y, x > y, x >= y, x && y, x \|\| y, x \|\^ y, !x |
|
||||
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Math functions | sqrt(x), exp(x), ln(x), log(x), abs(x), sin(x), cos(x), tan(x), asin(x), acos(x), atan(x), atan2(y,x), random(x,y,z), normal(x,y,z), ceil(x), floor(x), round(x), ternary(x,y,z), ramp(x,y), stagger(x,y), logfreq(x,y,z), logfreq2(x,y,z), logfreq3(x,y,z), stride(x,y,z), stride2(x,y,z,a,b,c), vdisplace(x,y), swiggle(x,y,z), cwiggle(x,y,z) |
|
||||
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Math functions | sqrt(x), exp(x), ln(x), log(x), abs(x), sin(x), cos(x), tan(x), asin(x), acos(x), atan(x), atan2(y,x), random(x,y,z), normal(x,y,z), ceil(x), floor(x), round(x), ternary(x,y,z), ramp(x,y), stagger(x,y), logfreq(x,y,z), logfreq2(x,y,z), logfreq3(x,y,z), stride(x,y,z), stride2(x,y,z,a,b,c), vdisplace(x,y), swiggle(x,y,z), cwiggle(x,y,z), sign(x) |
|
||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Group functions | count(ID), mass(ID), charge(ID), xcm(ID,dim), vcm(ID,dim), fcm(ID,dim), bound(ID,dir), gyration(ID), ke(ID), angmom(ID,dim), torque(ID,dim), inertia(ID,dimdim), omega(ID,dim) |
|
||||
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Region functions | count(ID,IDR), mass(ID,IDR), charge(ID,IDR), xcm(ID,dim,IDR), vcm(ID,dim,IDR), fcm(ID,dim,IDR), bound(ID,dir,IDR), gyration(ID,IDR), ke(ID,IDR), angmom(ID,dim,IDR), torque(ID,dim,IDR), inertia(ID,dimdim,IDR), omega(ID,dim,IDR) |
|
||||
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Special functions | sum(x), min(x), max(x), ave(x), trap(x), slope(x), sort(x), rsort(x), gmask(x), rmask(x), grmask(x,y), next(x), is_file(name), is_os(name), extract_setting(name), label2type(kind,label), is_typelabel(kind,label), is_timeout() |
|
||||
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Feature functions | is_available(category,feature), is_active(category,feature), is_defined(category,id) |
|
||||
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Atom values | id[i], mass[i], type[i], mol[i], x[i], y[i], z[i], vx[i], vy[i], vz[i], fx[i], fy[i], fz[i], q[i] |
|
||||
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Atom vectors | id, mass, type, mol, x, y, z, vx, vy, vz, fx, fy, fz, q |
|
||||
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Custom atom properties | i_name, d_name, i_name[i], d_name[i], i2_name[i], d2_name[i], i2_name[i][j], d_name[i][j] |
|
||||
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Compute references | c_ID, c_ID[i], c_ID[i][j], C_ID, C_ID[i] |
|
||||
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Fix references | f_ID, f_ID[i], f_ID[i][j], F_ID, F_ID[i] |
|
||||
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Other variables | v_name, v_name[i] |
|
||||
+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
Most of the formula elements produce a scalar value. Some produce a
|
||||
global or per-atom vector of values. Global vectors can be produced
|
||||
@ -860,6 +860,9 @@ run, according to one of these formulas, where omega = 2 PI / period:
|
||||
|
||||
where dt = the timestep size.
|
||||
|
||||
The sign(x) function returns 1.0 if the value is greater than or equal
|
||||
to 0.0, and -1.0 otherwise.
|
||||
|
||||
The run begins on startstep. Startstep can span multiple runs, using
|
||||
the *start* keyword of the :doc:`run <run>` command. See the :doc:`run
|
||||
<run>` command for details of how to do this. Note that the
|
||||
|
||||
@ -108,6 +108,7 @@ Andrienko
|
||||
Andzelm
|
||||
Ang
|
||||
anglegrad
|
||||
angleoffset
|
||||
angletangrad
|
||||
angmom
|
||||
angmomx
|
||||
@ -1236,6 +1237,7 @@ fp
|
||||
fphi
|
||||
fPIC
|
||||
fplo
|
||||
fprintf
|
||||
Fqq
|
||||
Fraige
|
||||
framerate
|
||||
@ -1582,6 +1584,7 @@ Impropers
|
||||
imulator
|
||||
includelink
|
||||
incompressible
|
||||
incompressibility
|
||||
incrementing
|
||||
indenter
|
||||
indenters
|
||||
@ -1761,6 +1764,7 @@ Kadiri
|
||||
Kai
|
||||
Kalia
|
||||
Kamberaj
|
||||
Kamrin
|
||||
Kantorovich
|
||||
Kapfer
|
||||
Kapil
|
||||
@ -2531,6 +2535,7 @@ Nevery
|
||||
Nevins
|
||||
newfile
|
||||
Newns
|
||||
newstep
|
||||
newtype
|
||||
nextsort
|
||||
Neyts
|
||||
@ -3380,6 +3385,7 @@ Schilfgarde
|
||||
Schimansky
|
||||
Schiotz
|
||||
Schlitter
|
||||
Schmerler
|
||||
Schmid
|
||||
Schnieders
|
||||
Schoen
|
||||
@ -3729,6 +3735,7 @@ tgnpt
|
||||
tgnvt
|
||||
th
|
||||
Thakkar
|
||||
Thakur
|
||||
Thaokar
|
||||
thb
|
||||
thei
|
||||
@ -3767,6 +3774,7 @@ Tigran
|
||||
Tij
|
||||
Tildesley
|
||||
Timan
|
||||
timeflag
|
||||
timeI
|
||||
timespan
|
||||
timestamp
|
||||
@ -3829,6 +3837,7 @@ Tref
|
||||
Tretyakov
|
||||
tri
|
||||
triangleflag
|
||||
triaxial
|
||||
Tribello
|
||||
triclinic
|
||||
Triclinic
|
||||
@ -4042,6 +4051,7 @@ VMDARCH
|
||||
VMDHOME
|
||||
vn
|
||||
Voigt
|
||||
Vogel
|
||||
volfactor
|
||||
Volkov
|
||||
Volpe
|
||||
|
||||
@ -118,6 +118,9 @@ liblammpsplugin_t *liblammpsplugin_load(const char *lib)
|
||||
ADDSYM(set_internal_variable);
|
||||
ADDSYM(variable_info);
|
||||
ADDSYM(eval);
|
||||
ADDSYM(clearstep_compute);
|
||||
ADDSYM(addstep_compute);
|
||||
ADDSYM(addstep_compute_all);
|
||||
|
||||
ADDSYM(gather_atoms);
|
||||
ADDSYM(gather_atoms_concat);
|
||||
|
||||
@ -164,6 +164,9 @@ struct _liblammpsplugin {
|
||||
int (*set_internal_variable)(void *, const char *, double);
|
||||
int (*variable_info)(void *, int, char *, int);
|
||||
double (*eval)(void *, const char *);
|
||||
void (*clearstep_compute)(void *);
|
||||
void (*addstep_compute)(void *, void *);
|
||||
void (*addstep_compute_all)(void *, void *);
|
||||
|
||||
void (*gather_atoms)(void *, const char *, int, int, void *);
|
||||
void (*gather_atoms_concat)(void *, const char *, int, int, void *);
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
|
||||
#include <mpi.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -63,7 +64,7 @@ int main(int narg, char **arg)
|
||||
nprocs_lammps = atoi(arg[1]);
|
||||
if (nprocs_lammps > nprocs) {
|
||||
if (me == 0)
|
||||
printf("ERROR: LAMMPS cannot use more procs than available\n");
|
||||
printf("ERROR: LAMMPS cannot use more procs than available: %d\n", nprocs);
|
||||
MPI_Abort(MPI_COMM_WORLD,1);
|
||||
}
|
||||
|
||||
@ -76,7 +77,7 @@ int main(int narg, char **arg)
|
||||
if (me == 0) {
|
||||
fp = fopen(arg[2],"r");
|
||||
if (fp == NULL) {
|
||||
printf("ERROR: Could not open LAMMPS input script\n");
|
||||
printf("ERROR: Could not open LAMMPS input script %s: %s\n", arg[2], strerror(errno));
|
||||
MPI_Abort(MPI_COMM_WORLD,1);
|
||||
}
|
||||
}
|
||||
@ -87,9 +88,10 @@ int main(int narg, char **arg)
|
||||
all LAMMPS procs call lammps_command() on the line */
|
||||
|
||||
if (lammps == 1) {
|
||||
errno = 0;
|
||||
plugin = liblammpsplugin_load(arg[3]);
|
||||
if (plugin == NULL) {
|
||||
if (me == 0) printf("ERROR: Could not load shared LAMMPS library\n");
|
||||
if (me == 0) printf("ERROR: Could not load shared LAMMPS library file %s: %s\n", arg[3], strerror(errno));
|
||||
MPI_Abort(MPI_COMM_WORLD,1);
|
||||
}
|
||||
/* must match the plugin ABI version */
|
||||
|
||||
@ -32,7 +32,7 @@ fix 1 all nvt temp 0.7 0.7 0.2
|
||||
#dump_modify 3 pad 3
|
||||
|
||||
fix 2 all recenter NULL NULL 15 units lattice
|
||||
compute p1 all stress/cartesian z 0.5
|
||||
compute p1 all stress/cartesian z 0.5 NULL 0
|
||||
fix 3 all ave/time 100 1 100 c_p1[*] file flat.out mode vector
|
||||
|
||||
thermo 50
|
||||
|
||||
149
examples/granular/in.tableting.200
Normal file
149
examples/granular/in.tableting.200
Normal file
@ -0,0 +1,149 @@
|
||||
##################################### SIMULATION SETTINGS ###################################################
|
||||
|
||||
atom_style sphere 1
|
||||
atom_modify map array
|
||||
comm_modify vel yes
|
||||
units si
|
||||
newton off
|
||||
neighbor 1.0e-3 bin
|
||||
neigh_modify every 10 delay 60 check no
|
||||
timestep 4e-6
|
||||
#processors 2 2 1
|
||||
|
||||
############################## SIMULATION BOUNDING BOX AND INSERT PARTICLES #################################
|
||||
|
||||
boundary f f f
|
||||
read_data spheres200.data
|
||||
|
||||
#################################### ADD DIE AND ATOM PARAMETERIZATION ######################################
|
||||
|
||||
variable atomRadius equal 0.44e-3*1.25
|
||||
variable atomDiameter equal 2*${atomRadius}
|
||||
variable atomDensity equal 1560
|
||||
variable atomMassAvg equal ${atomDensity}*4.0/3.0*PI*${atomRadius}^3.0
|
||||
variable dieRadius equal 4e-3
|
||||
variable dieHeight equal 1e-2
|
||||
|
||||
############################## PARTICLE MATERIAL PROPERTIES AND FORCE MODEL ##################################
|
||||
|
||||
pair_style granular
|
||||
|
||||
# mdr = E, nu, Y, gamma, psi_b, CoR
|
||||
variable YoungsModulus equal 5e6
|
||||
variable YieldStress equal 1.9e5
|
||||
variable PoissonsRatio equal 0.4
|
||||
variable SurfaceEnergy equal 2
|
||||
variable SurfaceEnergyWall equal 0.0
|
||||
variable CoR equal 0.5
|
||||
variable psi_b equal 0.5
|
||||
|
||||
# linear_history = k_t, x_gammat, mu_s
|
||||
variable kt equal 2/7*${YoungsModulus}*${atomRadius}
|
||||
variable kt_wall equal 2/7*${YoungsModulus}*${atomRadius}
|
||||
variable xgammat equal 0.0
|
||||
variable mu_s equal 0.7
|
||||
variable mu_s_wall equal 0.1
|
||||
|
||||
# sds = mu_roll, k_roll, gamma_roll
|
||||
variable mu_roll equal 0.6
|
||||
variable k_roll equal 2.25*${mu_roll}*${mu_roll}*${YoungsModulus}*${atomRadius}
|
||||
variable gamma_roll equal 0.0
|
||||
|
||||
pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${CoR} tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} damping none
|
||||
|
||||
######################################### ADD DIE AND PUNCH WALLS ############################################
|
||||
|
||||
variable disp_upper equal 0.0
|
||||
variable disp_lower equal 0.0
|
||||
|
||||
variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${CoR} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} damping none"
|
||||
|
||||
variable dieHeight2 equal 2*${dieHeight}
|
||||
|
||||
region lowerPunch plane 0 0 0 0 0 1 side in units box move NULL NULL v_disp_lower units box
|
||||
region upperPunch plane 0 0 ${dieHeight} 0 0 -1 side in move NULL NULL v_disp_upper units box
|
||||
region die cylinder z 0 0 ${dieRadius} 0 ${dieHeight2} side in units box
|
||||
|
||||
fix lowerPunch all wall/gran/region ${wall_contact_string} region lowerPunch contacts
|
||||
fix upperPunch all wall/gran/region ${wall_contact_string} region upperPunch contacts
|
||||
fix die all wall/gran/region ${wall_contact_string} region die contacts
|
||||
|
||||
compute avgUpperPunchForce all reduce sum f_upperPunch[4]
|
||||
variable avgUpperPunchForce equal c_avgUpperPunchForce
|
||||
compute avgLowerPunchForce all reduce sum f_lowerPunch[4]
|
||||
variable avgLowerPunchForce equal c_avgLowerPunchForce
|
||||
|
||||
fix printFD all print 1 "${disp_upper} ${avgUpperPunchForce} ${avgLowerPunchForce}" file punch_force_disp_tableting200.csv screen no
|
||||
|
||||
##################################### INTEGRATION AND GRAVITY #################################################
|
||||
|
||||
fix 1 all nve/sphere
|
||||
fix grav all gravity 9.81 vector 0 0 -1
|
||||
|
||||
########################################### SCREEN OUTPUT ####################################################
|
||||
|
||||
compute 1 all erotate/sphere
|
||||
thermo_style custom dt step atoms ke vol v_disp_upper
|
||||
thermo 100
|
||||
thermo_modify lost ignore norm no
|
||||
|
||||
##################################### SET UP DUMP OUTPUTS ####################################################
|
||||
|
||||
compute ke all ke/atom
|
||||
variable output_rate equal round(1e-3/dt)
|
||||
|
||||
run 0
|
||||
|
||||
compute sigmaxx all property/atom d_sigmaxx
|
||||
compute sigmayy all property/atom d_sigmayy
|
||||
compute sigmazz all property/atom d_sigmazz
|
||||
compute Velas all property/atom d_Velas
|
||||
|
||||
compute sigmaxx_ave all reduce ave c_sigmaxx
|
||||
compute sigmayy_ave all reduce ave c_sigmayy
|
||||
compute sigmazz_ave all reduce ave c_sigmazz
|
||||
compute Velas_sum all reduce sum c_Velas
|
||||
|
||||
variable sxx_ave equal c_sigmaxx_ave
|
||||
variable syy_ave equal c_sigmayy_ave
|
||||
variable szz_ave equal c_sigmazz_ave
|
||||
variable Vparticles equal c_Velas_sum
|
||||
|
||||
fix log all print 1 "${sxx_ave} ${syy_ave} ${szz_ave} ${Vparticles}" file average_normal_stresses_tableting200.csv screen no
|
||||
dump dumpParticles all custom ${output_rate} tableting200.dump id type mass diameter x y z vx vy vz fx fy fz c_ke c_sigmaxx c_sigmayy c_sigmazz
|
||||
#dump dumpParticlesVTK all vtk ${output_rate} post/particles_*.vtk id x y z fx fy fz vx vy vz c_ke radius c_sigmaxx c_sigmayy c_sigmazz
|
||||
|
||||
############################################## RUN SIMULATION #################################################
|
||||
|
||||
variable upper_punch_stroke equal 0.6733*${dieHeight}
|
||||
variable vel_upper equal 0.25
|
||||
|
||||
variable settling_steps equal round(0.02/dt)
|
||||
variable compression_steps equal 2*round(${upper_punch_stroke}/${vel_upper}/dt)
|
||||
variable ejection_steps equal ${compression_steps}
|
||||
variable free_float_steps equal round(0.02/dt)
|
||||
|
||||
##### SETTLING #####
|
||||
|
||||
run ${settling_steps}
|
||||
|
||||
##### Compression & Release #####
|
||||
|
||||
variable punch_frequency equal PI/2/(dt*${compression_steps}/2)
|
||||
variable disp_upper equal -${upper_punch_stroke}*sin(${punch_frequency}*elapsed*dt)
|
||||
variable short_release equal round(${compression_steps}*1.0)
|
||||
run ${short_release}
|
||||
|
||||
##### EJECTION #####
|
||||
|
||||
variable punch_frequency equal PI/2/(dt*${ejection_steps})
|
||||
variable disp_lower equal ${dieHeight}*sin(${punch_frequency}*elapsed*dt)
|
||||
variable disp_upper equal 0.9*v_disp_lower
|
||||
run ${ejection_steps}
|
||||
|
||||
##### FREE FLOAT #####
|
||||
|
||||
variable disp_lower equal ${dieHeight}
|
||||
variable disp_upper equal ${dieHeight}*0.9
|
||||
variable max_disp equal ${dieRadius}*0.75
|
||||
run ${free_float_steps}
|
||||
109
examples/granular/in.triaxial.compaction.12
Normal file
109
examples/granular/in.triaxial.compaction.12
Normal file
@ -0,0 +1,109 @@
|
||||
############################### SIMULATION SETTINGS ###################################################
|
||||
|
||||
atom_style sphere 1
|
||||
atom_modify map array
|
||||
comm_modify vel yes
|
||||
units si
|
||||
newton off
|
||||
neighbor 2 bin
|
||||
neigh_modify delay 0
|
||||
timestep 1e-6
|
||||
|
||||
##################### SIMULATION BOUNDING BOX, INSERT PARTICLES, AND INTEGRATION #######################
|
||||
|
||||
boundary f f f
|
||||
read_data spheres12.data
|
||||
fix integr all nve/sphere
|
||||
|
||||
# create pair group for contact area outputs
|
||||
group particles_1_12 id 1 12
|
||||
|
||||
########################### PARTICLE MATERIAL PROPERTIES AND FORCE MODEL ###############################
|
||||
|
||||
variable atomRadius equal 0.5
|
||||
|
||||
pair_style granular
|
||||
|
||||
# mdr = E, nu, Y, gamma, psi_b, CoR
|
||||
variable YoungsModulus equal 1e9
|
||||
variable PoissonsRatio equal 0.3
|
||||
variable YieldStress equal 50e6
|
||||
variable SurfaceEnergy equal 0.0
|
||||
variable psi_b equal 0.5
|
||||
variable CoR equal 0.5
|
||||
|
||||
# linear_history = k_t, x_gamma,t, mu_s
|
||||
variable kt equal 2/7*${YoungsModulus}*${atomRadius}
|
||||
variable xgammat equal 0.0
|
||||
variable mu_s equal 0.5
|
||||
|
||||
pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${CoR} tangential linear_history ${kt} ${xgammat} ${mu_s} damping none
|
||||
|
||||
######################################### ADD IN PLANES ################################################
|
||||
|
||||
variable boxWidth equal 3
|
||||
variable halfBoxWidth equal ${boxWidth}/2
|
||||
|
||||
variable plane_disp equal 0.0
|
||||
variable plane_disp_neg equal 0.0
|
||||
|
||||
region plane_yz_pos plane ${halfBoxWidth} 0 0 -1 0 0 side in move v_plane_disp_neg NULL NULL units box
|
||||
region plane_yz_neg plane -${halfBoxWidth} 0 0 1 0 0 side in move v_plane_disp NULL NULL units box
|
||||
region plane_xz_pos plane 0 ${halfBoxWidth} 0 0 -1 0 side in move NULL v_plane_disp_neg NULL units box
|
||||
region plane_xz_neg plane 0 -${halfBoxWidth} 0 0 1 0 side in move NULL v_plane_disp NULL units box
|
||||
region plane_xy_pos plane 0 0 ${halfBoxWidth} 0 0 -1 side in move NULL NULL v_plane_disp_neg units box
|
||||
region plane_xy_neg plane 0 0 -${halfBoxWidth} 0 0 1 side in move NULL NULL v_plane_disp units box
|
||||
|
||||
variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${CoR} tangential linear_history ${kt} ${xgammat} ${mu_s} damping none"
|
||||
|
||||
fix plane_yz_pos all wall/gran/region ${wall_contact_string} region plane_yz_pos contacts
|
||||
fix plane_yz_neg all wall/gran/region ${wall_contact_string} region plane_yz_neg contacts
|
||||
fix plane_xz_pos all wall/gran/region ${wall_contact_string} region plane_xz_pos contacts
|
||||
fix plane_xz_neg all wall/gran/region ${wall_contact_string} region plane_xz_neg contacts
|
||||
fix plane_xy_pos all wall/gran/region ${wall_contact_string} region plane_xy_pos contacts
|
||||
fix plane_xy_neg all wall/gran/region ${wall_contact_string} region plane_xy_neg contacts
|
||||
|
||||
compute plane_xy_neg_force all reduce sum f_plane_xy_neg[4]
|
||||
variable plane_xy_neg_force equal c_plane_xy_neg_force
|
||||
|
||||
compute plane_xz_neg_force all reduce sum f_plane_xz_neg[3]
|
||||
variable plane_xz_neg_force equal c_plane_xz_neg_force
|
||||
|
||||
compute plane_yz_neg_force all reduce sum f_plane_yz_neg[2]
|
||||
variable plane_yz_neg_force equal c_plane_yz_neg_force
|
||||
|
||||
fix print1 all print 1 "${plane_disp} ${plane_xy_neg_force} ${plane_xz_neg_force} ${plane_yz_neg_force}" file force_disp_triaxial12.csv screen no
|
||||
|
||||
######################################## SCREEN OUTPUT ####################################################
|
||||
|
||||
compute 1 all erotate/sphere
|
||||
thermo_style custom dt step atoms ke c_1 vol
|
||||
thermo 100
|
||||
thermo_modify lost ignore norm no
|
||||
|
||||
##################################### DEFINE WALL MOVEMENT #################################################
|
||||
|
||||
variable disp_max equal 0.499
|
||||
variable ddisp equal 0.00001
|
||||
variable compression_steps equal round(${disp_max}/${ddisp})
|
||||
variable output_rate equal round(${compression_steps}/100)
|
||||
|
||||
##################################### SET UP DUMP OUTPUTS ####################################################
|
||||
|
||||
dump dumpParticles all custom ${output_rate} triaxial_compaction_12.dump id type mass x y z vx vy vz fx fy fz radius
|
||||
#dump dmp all vtk ${output_rate} post/triaxial12particles_*.vtk id type mass x y z vx vy vz fx fy fz radius
|
||||
|
||||
#################################### COMPRESS THE PARTICLES ##################################################
|
||||
|
||||
run 0
|
||||
|
||||
# print out contact area evolution for particles 1 and 12
|
||||
compute Ac_1_12 particles_1_12 pair/local p13 cutoff radius
|
||||
compute Ac_1_12_sum particles_1_12 reduce sum c_Ac_1_12 inputs local
|
||||
variable Ac_1_12 equal c_Ac_1_12_sum
|
||||
fix logArea all print 100 "${plane_disp} ${Ac_1_12}" file pair_1_12_contact_area_triaxial12.csv screen no
|
||||
|
||||
variable plane_disp equal ${ddisp}*elapsed
|
||||
variable plane_disp_neg equal -${ddisp}*elapsed
|
||||
|
||||
run ${compression_steps}
|
||||
23
examples/granular/spheres12.data
Normal file
23
examples/granular/spheres12.data
Normal file
@ -0,0 +1,23 @@
|
||||
#LAMMPS data file created by matlab.
|
||||
12 atoms
|
||||
|
||||
1 atom types
|
||||
|
||||
-10.0000000000 10.0000000000 xlo xhi
|
||||
-10.0000000000 10.0000000000 ylo yhi
|
||||
-10.0000000000 10.0000000000 zlo zhi
|
||||
|
||||
Atoms
|
||||
|
||||
1 1 0.8000000000 1000.0000000000 0.0717535226 -0.2092222842 0.3662146798
|
||||
2 1 1.2000000000 1000.0000000000 -0.8233763986 -0.7426114800 -0.8263932264
|
||||
3 1 0.8000000000 1000.0000000000 -1.0685863278 -0.4494609702 0.2196698078
|
||||
4 1 0.8000000000 1000.0000000000 0.5829432471 -1.0098803839 -0.7607543861
|
||||
5 1 0.8000000000 1000.0000000000 -0.8658471132 0.6951192569 0.0107556658
|
||||
6 1 1.2000000000 1000.0000000000 0.3966456126 0.7215053869 -0.7540113087
|
||||
7 1 1.2000000000 1000.0000000000 0.7316242921 0.8996483982 0.6751483031
|
||||
8 1 1.0000000000 1000.0000000000 0.6267527768 -0.8419367233 0.6964197101
|
||||
9 1 0.8000000000 1000.0000000000 -0.0409043189 -0.1452314035 -1.0102948313
|
||||
10 1 0.8000000000 1000.0000000000 -0.9495107709 0.6760151650 -0.9220534482
|
||||
11 1 1.0000000000 1000.0000000000 -0.7488486472 0.2188003421 0.7892021020
|
||||
12 1 1.2000000000 1000.0000000000 0.8968590780 -0.2350366437 -0.2006719701
|
||||
211
examples/granular/spheres200.data
Normal file
211
examples/granular/spheres200.data
Normal file
@ -0,0 +1,211 @@
|
||||
#LAMMPS data file created by matlab.
|
||||
200 atoms
|
||||
|
||||
1 atom types
|
||||
|
||||
-0.005000 0.005000 xlo xhi
|
||||
-0.005000 0.005000 ylo yhi
|
||||
-0.001000 0.020000 zlo zhi
|
||||
|
||||
Atoms
|
||||
|
||||
1 1 0.001206 1560.000000 -0.000938 0.000556 0.000883
|
||||
2 1 0.000953 1560.000000 -0.002626 -0.000145 0.002778
|
||||
3 1 0.001035 1560.000000 -0.000434 0.000172 0.008458
|
||||
4 1 0.001225 1560.000000 -0.003126 -0.000604 0.004986
|
||||
5 1 0.001119 1560.000000 0.000772 0.002972 0.002568
|
||||
6 1 0.001243 1560.000000 -0.000363 0.001184 0.004927
|
||||
7 1 0.001173 1560.000000 0.000218 0.000243 0.005475
|
||||
8 1 0.000937 1560.000000 0.000033 0.000029 0.003141
|
||||
9 1 0.001055 1560.000000 -0.001660 0.001975 0.008611
|
||||
10 1 0.000938 1560.000000 -0.001818 0.002352 0.002534
|
||||
11 1 0.000990 1560.000000 0.001592 0.000435 0.004416
|
||||
12 1 0.000927 1560.000000 -0.001659 -0.000004 0.005901
|
||||
13 1 0.001272 1560.000000 0.002972 0.000553 0.007291
|
||||
14 1 0.001226 1560.000000 0.002090 0.000983 0.001406
|
||||
15 1 0.000957 1560.000000 0.002241 -0.001608 0.001304
|
||||
16 1 0.001020 1560.000000 -0.001944 0.001290 0.002030
|
||||
17 1 0.001289 1560.000000 -0.002256 -0.001173 0.003474
|
||||
18 1 0.000998 1560.000000 0.000771 0.002127 0.000906
|
||||
19 1 0.000927 1560.000000 0.000186 0.000567 0.001207
|
||||
20 1 0.001095 1560.000000 -0.000937 -0.003179 0.008173
|
||||
21 1 0.001006 1560.000000 -0.001736 0.000751 0.004618
|
||||
22 1 0.001037 1560.000000 0.000784 0.001844 0.002380
|
||||
23 1 0.001297 1560.000000 0.000234 -0.001597 0.008560
|
||||
24 1 0.001017 1560.000000 0.002454 -0.000505 0.001171
|
||||
25 1 0.001110 1560.000000 -0.000803 -0.000415 0.003714
|
||||
26 1 0.001192 1560.000000 0.002283 0.000648 0.003048
|
||||
27 1 0.000992 1560.000000 -0.000065 -0.000545 0.007062
|
||||
28 1 0.001116 1560.000000 0.002174 -0.001463 0.005830
|
||||
29 1 0.001258 1560.000000 0.001602 0.001853 0.007246
|
||||
30 1 0.001055 1560.000000 -0.001535 -0.002770 0.007196
|
||||
31 1 0.000958 1560.000000 -0.000438 -0.000260 0.004709
|
||||
32 1 0.001188 1560.000000 0.000339 -0.000355 0.009171
|
||||
33 1 0.001166 1560.000000 0.002513 -0.001215 0.004434
|
||||
34 1 0.000907 1560.000000 0.001905 -0.000373 0.004921
|
||||
35 1 0.001245 1560.000000 -0.000091 -0.002620 0.004150
|
||||
36 1 0.001302 1560.000000 0.003292 0.000184 0.005377
|
||||
37 1 0.001305 1560.000000 0.002099 0.001261 0.008939
|
||||
38 1 0.000988 1560.000000 0.003274 0.000136 0.003667
|
||||
39 1 0.000892 1560.000000 0.001798 -0.002104 0.008610
|
||||
40 1 0.001247 1560.000000 -0.003058 -0.000575 0.000948
|
||||
41 1 0.000900 1560.000000 -0.000258 -0.000469 0.001478
|
||||
42 1 0.000945 1560.000000 -0.001434 -0.001711 0.004610
|
||||
43 1 0.000977 1560.000000 -0.001410 0.002808 0.004963
|
||||
44 1 0.000930 1560.000000 -0.002110 -0.001362 0.006749
|
||||
45 1 0.000931 1560.000000 0.001256 -0.000876 0.000844
|
||||
46 1 0.000901 1560.000000 0.000899 -0.001189 0.005316
|
||||
47 1 0.000940 1560.000000 -0.002189 -0.000047 0.007240
|
||||
48 1 0.001217 1560.000000 -0.000108 -0.001333 0.002257
|
||||
49 1 0.001088 1560.000000 0.001364 -0.000594 0.002789
|
||||
50 1 0.001143 1560.000000 -0.000311 -0.001425 0.006092
|
||||
51 1 0.001054 1560.000000 0.002262 0.002312 0.004315
|
||||
52 1 0.001016 1560.000000 -0.000724 0.000741 0.003295
|
||||
53 1 0.001051 1560.000000 0.000527 -0.001987 0.003307
|
||||
54 1 0.000905 1560.000000 0.000827 0.001457 0.005868
|
||||
55 1 0.001195 1560.000000 -0.001176 -0.000645 0.000798
|
||||
56 1 0.001253 1560.000000 0.002583 -0.001847 0.003310
|
||||
57 1 0.000982 1560.000000 0.001551 -0.002803 0.005076
|
||||
58 1 0.000945 1560.000000 -0.000481 0.000354 0.007220
|
||||
59 1 0.001040 1560.000000 -0.002736 0.001076 0.008769
|
||||
60 1 0.000917 1560.000000 0.000826 -0.001887 0.006449
|
||||
61 1 0.000914 1560.000000 -0.001171 -0.001592 0.007266
|
||||
62 1 0.000959 1560.000000 0.000834 -0.002671 0.007105
|
||||
63 1 0.000990 1560.000000 -0.000251 -0.001327 0.004339
|
||||
64 1 0.001220 1560.000000 0.001384 0.002896 0.005874
|
||||
65 1 0.000949 1560.000000 -0.001340 -0.000608 0.007496
|
||||
66 1 0.001306 1560.000000 0.002187 0.002068 0.002629
|
||||
67 1 0.001206 1560.000000 0.000148 0.001506 0.008517
|
||||
68 1 0.001123 1560.000000 0.001288 -0.000303 0.006613
|
||||
69 1 0.001151 1560.000000 -0.000876 0.001549 0.001740
|
||||
70 1 0.001315 1560.000000 -0.001902 -0.002590 0.001344
|
||||
71 1 0.000927 1560.000000 0.002285 -0.000866 0.006900
|
||||
72 1 0.001279 1560.000000 -0.000165 0.002689 0.007449
|
||||
73 1 0.000910 1560.000000 0.001009 0.001054 0.005049
|
||||
74 1 0.001148 1560.000000 -0.002229 -0.001285 0.008736
|
||||
75 1 0.001067 1560.000000 -0.000261 -0.002945 0.002157
|
||||
76 1 0.000993 1560.000000 -0.001641 0.002272 0.007601
|
||||
77 1 0.001228 1560.000000 0.001939 -0.000214 0.008903
|
||||
78 1 0.001076 1560.000000 0.000767 0.001172 0.003556
|
||||
79 1 0.001105 1560.000000 -0.000561 0.002493 0.004214
|
||||
80 1 0.001195 1560.000000 0.002694 -0.000817 0.007949
|
||||
81 1 0.001239 1560.000000 -0.000968 -0.003145 0.006096
|
||||
82 1 0.001083 1560.000000 -0.000808 0.001813 0.006396
|
||||
83 1 0.000923 1560.000000 0.000632 -0.001437 0.001310
|
||||
84 1 0.000981 1560.000000 -0.001842 0.002774 0.006508
|
||||
85 1 0.000998 1560.000000 -0.002775 0.001616 0.001453
|
||||
86 1 0.000979 1560.000000 -0.002520 0.001715 0.007741
|
||||
87 1 0.001002 1560.000000 -0.001465 -0.001931 0.006048
|
||||
88 1 0.000958 1560.000000 0.003264 0.000707 0.001189
|
||||
89 1 0.001052 1560.000000 -0.001314 -0.000701 0.002721
|
||||
90 1 0.001096 1560.000000 0.001154 0.002129 0.004403
|
||||
91 1 0.001104 1560.000000 0.002118 0.001977 0.000794
|
||||
92 1 0.001263 1560.000000 -0.001499 -0.002764 0.003441
|
||||
93 1 0.001086 1560.000000 -0.001096 0.002514 0.001154
|
||||
94 1 0.000895 1560.000000 0.001130 0.000029 0.001045
|
||||
95 1 0.000964 1560.000000 0.000905 -0.003200 0.000542
|
||||
96 1 0.000898 1560.000000 -0.000868 0.003148 0.008306
|
||||
97 1 0.000907 1560.000000 -0.001406 0.001144 0.007862
|
||||
98 1 0.001176 1560.000000 0.001246 -0.001074 0.004327
|
||||
99 1 0.001148 1560.000000 0.001512 -0.002739 0.003346
|
||||
100 1 0.000922 1560.000000 0.001470 -0.000036 0.007695
|
||||
101 1 0.001031 1560.000000 -0.002751 0.000928 0.004124
|
||||
102 1 0.001030 1560.000000 -0.000177 -0.002370 0.005374
|
||||
103 1 0.000915 1560.000000 0.000824 0.000521 0.007070
|
||||
104 1 0.001085 1560.000000 -0.002281 -0.000023 0.009123
|
||||
105 1 0.001004 1560.000000 -0.000167 0.002610 0.008905
|
||||
106 1 0.001060 1560.000000 -0.000389 -0.002220 0.007688
|
||||
107 1 0.000920 1560.000000 -0.000483 0.003231 0.006505
|
||||
108 1 0.001122 1560.000000 0.001781 -0.001547 0.002237
|
||||
109 1 0.001172 1560.000000 -0.002650 0.000830 0.005429
|
||||
110 1 0.001137 1560.000000 -0.000030 -0.003246 0.001024
|
||||
111 1 0.001315 1560.000000 0.001470 -0.001735 0.007580
|
||||
112 1 0.001245 1560.000000 0.000481 -0.003067 0.006025
|
||||
113 1 0.000904 1560.000000 0.000632 -0.000184 0.002010
|
||||
114 1 0.000883 1560.000000 -0.001828 0.002191 0.003819
|
||||
115 1 0.000974 1560.000000 0.002167 0.001616 0.006226
|
||||
116 1 0.001150 1560.000000 0.000871 -0.002731 0.002136
|
||||
117 1 0.001312 1560.000000 -0.000326 -0.001971 0.001000
|
||||
118 1 0.000914 1560.000000 0.001020 0.000810 0.002086
|
||||
119 1 0.001136 1560.000000 -0.000101 -0.003277 0.007246
|
||||
120 1 0.000991 1560.000000 -0.001944 0.000576 0.003215
|
||||
121 1 0.001216 1560.000000 -0.000913 -0.001165 0.008857
|
||||
122 1 0.001045 1560.000000 -0.003110 0.001062 0.002973
|
||||
123 1 0.000918 1560.000000 0.000348 0.000365 0.004046
|
||||
124 1 0.001279 1560.000000 -0.000884 0.003087 0.002268
|
||||
125 1 0.001065 1560.000000 -0.002238 0.001309 0.006452
|
||||
126 1 0.001012 1560.000000 -0.002059 -0.001354 0.001935
|
||||
127 1 0.001142 1560.000000 -0.003011 0.000567 0.001739
|
||||
128 1 0.000921 1560.000000 0.001764 0.002804 0.008177
|
||||
129 1 0.001151 1560.000000 -0.003105 -0.000384 0.006602
|
||||
130 1 0.000967 1560.000000 0.000932 0.000588 0.008823
|
||||
131 1 0.000908 1560.000000 -0.001873 -0.001947 0.007825
|
||||
132 1 0.000923 1560.000000 -0.002993 0.000883 0.007425
|
||||
133 1 0.001171 1560.000000 0.003310 -0.000405 0.006558
|
||||
134 1 0.000977 1560.000000 -0.000098 -0.000180 0.000492
|
||||
135 1 0.000938 1560.000000 -0.000706 -0.000129 0.006085
|
||||
136 1 0.001008 1560.000000 -0.000256 0.002333 0.000550
|
||||
137 1 0.001073 1560.000000 0.000534 -0.000055 0.008080
|
||||
138 1 0.000890 1560.000000 0.000351 0.001695 0.007195
|
||||
139 1 0.000973 1560.000000 0.002593 0.001907 0.005394
|
||||
140 1 0.001176 1560.000000 -0.001862 -0.000534 0.004494
|
||||
141 1 0.001306 1560.000000 -0.000951 0.001053 0.009299
|
||||
142 1 0.001103 1560.000000 -0.001937 -0.002711 0.008485
|
||||
143 1 0.001262 1560.000000 -0.002947 -0.001470 0.007682
|
||||
144 1 0.000914 1560.000000 0.002047 0.000811 0.005504
|
||||
145 1 0.000954 1560.000000 0.001935 -0.002349 0.006632
|
||||
146 1 0.001003 1560.000000 0.000766 -0.002635 0.008483
|
||||
147 1 0.001137 1560.000000 0.000102 0.003195 0.004922
|
||||
148 1 0.001006 1560.000000 -0.001982 0.001014 0.000685
|
||||
149 1 0.001255 1560.000000 -0.000718 0.001939 0.003056
|
||||
150 1 0.001057 1560.000000 -0.001189 -0.001717 0.003045
|
||||
151 1 0.001228 1560.000000 0.001581 0.002926 0.003510
|
||||
152 1 0.001052 1560.000000 -0.002172 0.001949 0.004831
|
||||
153 1 0.000979 1560.000000 -0.001817 0.000291 0.002048
|
||||
154 1 0.001286 1560.000000 -0.002647 -0.001839 0.004620
|
||||
155 1 0.001085 1560.000000 -0.000081 0.000850 0.002139
|
||||
156 1 0.000990 1560.000000 -0.000081 0.002105 0.005587
|
||||
157 1 0.001043 1560.000000 0.001636 -0.000112 0.001860
|
||||
158 1 0.001309 1560.000000 0.003216 -0.000851 0.002791
|
||||
159 1 0.000913 1560.000000 0.000608 0.003148 0.006565
|
||||
160 1 0.000919 1560.000000 0.000536 -0.003106 0.003249
|
||||
161 1 0.000943 1560.000000 0.003145 -0.000528 0.008915
|
||||
162 1 0.000993 1560.000000 -0.002811 -0.000099 0.008110
|
||||
163 1 0.001125 1560.000000 0.001415 -0.002271 0.000643
|
||||
164 1 0.000919 1560.000000 -0.001406 0.000223 0.006781
|
||||
165 1 0.001040 1560.000000 0.000690 0.003193 0.008329
|
||||
166 1 0.001055 1560.000000 0.001075 0.002584 0.009093
|
||||
167 1 0.001176 1560.000000 0.000851 0.003176 0.000591
|
||||
168 1 0.001003 1560.000000 -0.001462 0.001511 0.005544
|
||||
169 1 0.001126 1560.000000 -0.000077 0.003324 0.001347
|
||||
170 1 0.001068 1560.000000 0.003110 0.000810 0.008495
|
||||
171 1 0.001011 1560.000000 -0.001661 0.000117 0.008201
|
||||
172 1 0.001066 1560.000000 -0.000359 -0.003279 0.009094
|
||||
173 1 0.001303 1560.000000 0.003066 0.001188 0.004082
|
||||
174 1 0.000983 1560.000000 0.000354 0.002261 0.003558
|
||||
175 1 0.001137 1560.000000 0.002860 -0.001571 0.009180
|
||||
176 1 0.001070 1560.000000 0.001246 -0.001279 0.009104
|
||||
177 1 0.000886 1560.000000 0.002271 -0.000316 0.003675
|
||||
178 1 0.000983 1560.000000 -0.001987 -0.002490 0.005377
|
||||
179 1 0.000939 1560.000000 0.000601 -0.000861 0.003477
|
||||
180 1 0.001177 1560.000000 0.001522 0.002902 0.001690
|
||||
181 1 0.001036 1560.000000 -0.001200 -0.002874 0.004750
|
||||
182 1 0.000898 1560.000000 -0.001705 -0.001140 0.005503
|
||||
183 1 0.001315 1560.000000 0.002732 0.001766 0.007885
|
||||
184 1 0.001318 1560.000000 -0.002909 -0.001610 0.005936
|
||||
185 1 0.001218 1560.000000 0.003213 0.000884 0.002316
|
||||
186 1 0.001234 1560.000000 -0.002394 -0.002298 0.002575
|
||||
187 1 0.001160 1560.000000 -0.003313 -0.000065 0.003625
|
||||
188 1 0.001022 1560.000000 -0.003096 -0.001048 0.002151
|
||||
189 1 0.000966 1560.000000 0.001891 -0.002093 0.004404
|
||||
190 1 0.001048 1560.000000 -0.002367 0.002338 0.000697
|
||||
191 1 0.000995 1560.000000 -0.001204 -0.001912 0.002030
|
||||
192 1 0.001136 1560.000000 -0.001152 -0.002402 0.009223
|
||||
193 1 0.001083 1560.000000 -0.002588 -0.001768 0.000753
|
||||
194 1 0.000946 1560.000000 -0.001338 -0.000741 0.006527
|
||||
195 1 0.000943 1560.000000 -0.000073 0.003254 0.003663
|
||||
196 1 0.001059 1560.000000 0.000087 0.000958 0.006388
|
||||
197 1 0.001131 1560.000000 0.001030 0.001019 0.000752
|
||||
198 1 0.001257 1560.000000 -0.001365 0.002946 0.009266
|
||||
199 1 0.000891 1560.000000 -0.000445 -0.000273 0.002382
|
||||
200 1 0.001055 1560.000000 0.001781 0.000748 0.006583
|
||||
@ -1,4 +1,4 @@
|
||||
# Big colloid particles and small LJ particles
|
||||
# Binary granular system
|
||||
|
||||
units lj
|
||||
atom_style sphere
|
||||
|
||||
@ -9,5 +9,11 @@ in.snap.Mo_Chen # SNAP linear Mo potential
|
||||
in.snap.compute # SNAP compute for training a linear model
|
||||
in.snap.compute.quadratic # SNAP compute for training a quadratic model
|
||||
in.snap.scale.Ni_Zuo_JCPA2020 # SNAP linear Ni potential with thermodynamic integration (fix adapt scale)
|
||||
in.C_SNAP # SNAP carbon potential
|
||||
|
||||
compute_snap_dgrad.py # SNAP compute with dgradflag (dBi/dRj) for training a non-linear model
|
||||
|
||||
in.snap.grid # SNAP descriptors on a grid
|
||||
in.snap.grid.triclinic # SNAP descriptors on a grid, triclinic
|
||||
in.gaussian.grid # Gaussian descriptors on a grid
|
||||
|
||||
|
||||
68
examples/snap/in.gaussian.grid
Normal file
68
examples/snap/in.gaussian.grid
Normal file
@ -0,0 +1,68 @@
|
||||
# Demonstrate calculation of Gaussian descriptors on a grid
|
||||
# for a cell with two atoms of type 1 and type 2.
|
||||
# The output in dump.glocal shows that for grid points
|
||||
# sitting on an atom of type 1 or 2:
|
||||
# val1 = 1.0/(0.1355*sqrt(2.0*pi))**3 = 25.5219
|
||||
# val2 = 1.0/(0.2 *sqrt(2.0*pi))**3 = 7.93670
|
||||
# These values are extracted to the log file
|
||||
#
|
||||
|
||||
variable nrep index 1
|
||||
variable a index 3.316
|
||||
variable ngrid index 2
|
||||
|
||||
units metal
|
||||
atom_modify map hash
|
||||
|
||||
# generate the box and atom positions using a BCC lattice
|
||||
|
||||
variable nx equal ${nrep}
|
||||
variable ny equal ${nrep}
|
||||
variable nz equal ${nrep}
|
||||
|
||||
boundary p p p
|
||||
|
||||
lattice custom $a &
|
||||
a1 1 0 0 &
|
||||
a2 0 1 0 &
|
||||
a3 0 0 1 &
|
||||
basis 0 0 0 &
|
||||
basis 0.5 0.5 0.5 &
|
||||
|
||||
region box block 0 ${nx} 0 ${ny} 0 ${nz}
|
||||
create_box 2 box
|
||||
create_atoms 1 box basis 1 1 basis 2 2
|
||||
|
||||
mass * 180.88
|
||||
|
||||
# define atom compute and grid compute
|
||||
|
||||
variable rcutfac equal 4.67637
|
||||
variable radelem1 equal 0.5
|
||||
variable radelem2 equal 0.5
|
||||
variable sigmaelem1 equal 0.1355
|
||||
variable sigmaelem2 equal 0.2
|
||||
variable gaussian_options string &
|
||||
"${rcutfac} ${radelem1} ${radelem2} ${sigmaelem1} ${sigmaelem2}"
|
||||
|
||||
# build zero potential to force ghost atom creation
|
||||
|
||||
pair_style zero ${rcutfac}
|
||||
pair_coeff * *
|
||||
|
||||
# define atom and grid computes
|
||||
|
||||
compute mygridlocal all gaussian/grid/local grid ${ngrid} ${ngrid} ${ngrid} &
|
||||
${gaussian_options}
|
||||
|
||||
# define output
|
||||
|
||||
dump 1 all local 1000 dump.glocal c_mygridlocal[*]
|
||||
dump 2 all custom 1000 dump.gatom id x y z
|
||||
compute val1 all reduce max c_mygridlocal[7] inputs local
|
||||
compute val2 all reduce max c_mygridlocal[8] inputs local
|
||||
thermo_style custom step c_val1 c_val2
|
||||
|
||||
# run
|
||||
|
||||
run 0
|
||||
@ -47,7 +47,6 @@ lattice custom $a &
|
||||
basis 0.0 0.0 0.5 &
|
||||
spacing 1 1 1
|
||||
|
||||
box tilt large
|
||||
region box prism 0 ${nx} 0 ${ny} 0 ${nz} ${ny} ${nz} ${nz}
|
||||
create_box 1 box
|
||||
create_atoms 1 box
|
||||
129
examples/snap/log.10Dec24.gaussian.grid.g++.1
Normal file
129
examples/snap/log.10Dec24.gaussian.grid.g++.1
Normal file
@ -0,0 +1,129 @@
|
||||
LAMMPS (19 Nov 2024 - Development - patch_19Nov2024-59-g16e0a7788a)
|
||||
OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99)
|
||||
using 1 OpenMP thread(s) per MPI task
|
||||
# Demonstrate calculation of Gaussian descriptors on a grid
|
||||
# for a cell with two atoms of type 1 and type 2.
|
||||
# The output in dump.glocal shows that for grid points
|
||||
# sitting on an atom of type 1 or 2:
|
||||
# val1 = 1.0/(0.1355*sqrt(2.0*pi))**3 = 25.5219
|
||||
# val2 = 1.0/(0.2 *sqrt(2.0*pi))**3 = 7.93670
|
||||
# These values are extracted to the log file
|
||||
#
|
||||
|
||||
variable nrep index 1
|
||||
variable a index 3.316
|
||||
variable ngrid index 2
|
||||
|
||||
units metal
|
||||
atom_modify map hash
|
||||
|
||||
# generate the box and atom positions using a BCC lattice
|
||||
|
||||
variable nx equal ${nrep}
|
||||
variable nx equal 1
|
||||
variable ny equal ${nrep}
|
||||
variable ny equal 1
|
||||
variable nz equal ${nrep}
|
||||
variable nz equal 1
|
||||
|
||||
boundary p p p
|
||||
|
||||
lattice custom $a a1 1 0 0 a2 0 1 0 a3 0 0 1 basis 0 0 0 basis 0.5 0.5 0.5
|
||||
lattice custom 3.316 a1 1 0 0 a2 0 1 0 a3 0 0 1 basis 0 0 0 basis 0.5 0.5 0.5
|
||||
Lattice spacing in x,y,z = 3.316 3.316 3.316
|
||||
region box block 0 ${nx} 0 ${ny} 0 ${nz}
|
||||
region box block 0 1 0 ${ny} 0 ${nz}
|
||||
region box block 0 1 0 1 0 ${nz}
|
||||
region box block 0 1 0 1 0 1
|
||||
create_box 2 box
|
||||
Created orthogonal box = (0 0 0) to (3.316 3.316 3.316)
|
||||
1 by 1 by 1 MPI processor grid
|
||||
create_atoms 1 box basis 1 1 basis 2 2
|
||||
Created 2 atoms
|
||||
using lattice units in orthogonal box = (0 0 0) to (3.316 3.316 3.316)
|
||||
create_atoms CPU = 0.001 seconds
|
||||
|
||||
mass * 180.88
|
||||
|
||||
# define atom compute and grid compute
|
||||
|
||||
variable rcutfac equal 4.67637
|
||||
variable radelem1 equal 0.5
|
||||
variable radelem2 equal 0.5
|
||||
variable sigmaelem1 equal 0.1355
|
||||
variable sigmaelem2 equal 0.2
|
||||
variable gaussian_options string "${rcutfac} ${radelem1} ${radelem2} ${sigmaelem1} ${sigmaelem2}"
|
||||
4.67637 ${radelem1} ${radelem2} ${sigmaelem1} ${sigmaelem2}
|
||||
4.67637 0.5 ${radelem2} ${sigmaelem1} ${sigmaelem2}
|
||||
4.67637 0.5 0.5 ${sigmaelem1} ${sigmaelem2}
|
||||
4.67637 0.5 0.5 0.1355 ${sigmaelem2}
|
||||
4.67637 0.5 0.5 0.1355 0.2
|
||||
|
||||
# build zero potential to force ghost atom creation
|
||||
|
||||
pair_style zero ${rcutfac}
|
||||
pair_style zero 4.67637
|
||||
pair_coeff * *
|
||||
|
||||
# define atom and grid computes
|
||||
|
||||
compute mygridlocal all gaussian/grid/local grid ${ngrid} ${ngrid} ${ngrid} ${gaussian_options}
|
||||
compute mygridlocal all gaussian/grid/local grid 2 ${ngrid} ${ngrid} ${gaussian_options}
|
||||
compute mygridlocal all gaussian/grid/local grid 2 2 ${ngrid} ${gaussian_options}
|
||||
compute mygridlocal all gaussian/grid/local grid 2 2 2 ${gaussian_options}
|
||||
compute mygridlocal all gaussian/grid/local grid 2 2 2 4.67637 0.5 0.5 0.1355 0.2
|
||||
|
||||
# define output
|
||||
|
||||
dump 1 all local 1000 dump.glocal c_mygridlocal[*]
|
||||
dump 2 all custom 1000 dump.gatom id x y z
|
||||
compute val1 all reduce max c_mygridlocal[7] inputs local
|
||||
compute val2 all reduce max c_mygridlocal[8] inputs local
|
||||
thermo_style custom step c_val1 c_val2
|
||||
|
||||
# run
|
||||
|
||||
run 0
|
||||
WARNING: No fixes with time integration, atoms won't move (src/verlet.cpp:60)
|
||||
Generated 0 of 1 mixed pair_coeff terms from geometric mixing rule
|
||||
Neighbor list info ...
|
||||
update: every = 1 steps, delay = 0 steps, check = yes
|
||||
max neighbors/atom: 2000, page size: 100000
|
||||
master list distance cutoff = 6.67637
|
||||
ghost atom cutoff = 6.67637
|
||||
binsize = 3.338185, bins = 1 1 1
|
||||
1 neighbor lists, perpetual/occasional/extra = 1 0 0
|
||||
(1) pair zero, perpetual
|
||||
attributes: half, newton on
|
||||
pair build: half/bin/atomonly/newton
|
||||
stencil: half/bin/3d
|
||||
bin: standard
|
||||
Per MPI rank memory allocation (min/avg/max) = 3.492 | 3.492 | 3.492 Mbytes
|
||||
Step c_val1 c_val2
|
||||
0 25.521859 7.9367045
|
||||
Loop time of 1.088e-06 on 1 procs for 0 steps with 2 atoms
|
||||
|
||||
183.8% CPU use with 1 MPI tasks x 1 OpenMP threads
|
||||
|
||||
MPI task timing breakdown:
|
||||
Section | min time | avg time | max time |%varavg| %total
|
||||
---------------------------------------------------------------
|
||||
Pair | 0 | 0 | 0 | 0.0 | 0.00
|
||||
Neigh | 0 | 0 | 0 | 0.0 | 0.00
|
||||
Comm | 0 | 0 | 0 | 0.0 | 0.00
|
||||
Output | 0 | 0 | 0 | 0.0 | 0.00
|
||||
Modify | 0 | 0 | 0 | 0.0 | 0.00
|
||||
Other | | 1.088e-06 | | |100.00
|
||||
|
||||
Nlocal: 2 ave 2 max 2 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
Nghost: 339 ave 339 max 339 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
Neighs: 64 ave 64 max 64 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
|
||||
Total # of neighbors = 64
|
||||
Ave neighs/atom = 32
|
||||
Neighbor list builds = 0
|
||||
Dangerous builds = 0
|
||||
Total wall time: 0:00:00
|
||||
130
examples/snap/log.10Dec24.gaussian.grid.g++.4
Normal file
130
examples/snap/log.10Dec24.gaussian.grid.g++.4
Normal file
@ -0,0 +1,130 @@
|
||||
LAMMPS (19 Nov 2024 - Development - patch_19Nov2024-59-g16e0a7788a)
|
||||
OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99)
|
||||
using 1 OpenMP thread(s) per MPI task
|
||||
# Demonstrate calculation of Gaussian descriptors on a grid
|
||||
# for a cell with two atoms of type 1 and type 2.
|
||||
# The output in dump.glocal shows that for grid points
|
||||
# sitting on an atom of type 1 or 2:
|
||||
# val1 = 1.0/(0.1355*sqrt(2.0*pi))**3 = 25.5219
|
||||
# val2 = 1.0/(0.2 *sqrt(2.0*pi))**3 = 7.93670
|
||||
# These values are extracted to the log file
|
||||
#
|
||||
|
||||
variable nrep index 1
|
||||
variable a index 3.316
|
||||
variable ngrid index 2
|
||||
|
||||
units metal
|
||||
atom_modify map hash
|
||||
|
||||
# generate the box and atom positions using a BCC lattice
|
||||
|
||||
variable nx equal ${nrep}
|
||||
variable nx equal 1
|
||||
variable ny equal ${nrep}
|
||||
variable ny equal 1
|
||||
variable nz equal ${nrep}
|
||||
variable nz equal 1
|
||||
|
||||
boundary p p p
|
||||
|
||||
lattice custom $a a1 1 0 0 a2 0 1 0 a3 0 0 1 basis 0 0 0 basis 0.5 0.5 0.5
|
||||
lattice custom 3.316 a1 1 0 0 a2 0 1 0 a3 0 0 1 basis 0 0 0 basis 0.5 0.5 0.5
|
||||
Lattice spacing in x,y,z = 3.316 3.316 3.316
|
||||
region box block 0 ${nx} 0 ${ny} 0 ${nz}
|
||||
region box block 0 1 0 ${ny} 0 ${nz}
|
||||
region box block 0 1 0 1 0 ${nz}
|
||||
region box block 0 1 0 1 0 1
|
||||
create_box 2 box
|
||||
Created orthogonal box = (0 0 0) to (3.316 3.316 3.316)
|
||||
1 by 2 by 2 MPI processor grid
|
||||
create_atoms 1 box basis 1 1 basis 2 2
|
||||
Created 2 atoms
|
||||
using lattice units in orthogonal box = (0 0 0) to (3.316 3.316 3.316)
|
||||
create_atoms CPU = 0.001 seconds
|
||||
|
||||
mass * 180.88
|
||||
|
||||
# define atom compute and grid compute
|
||||
|
||||
variable rcutfac equal 4.67637
|
||||
variable radelem1 equal 0.5
|
||||
variable radelem2 equal 0.5
|
||||
variable sigmaelem1 equal 0.1355
|
||||
variable sigmaelem2 equal 0.2
|
||||
variable gaussian_options string "${rcutfac} ${radelem1} ${radelem2} ${sigmaelem1} ${sigmaelem2}"
|
||||
4.67637 ${radelem1} ${radelem2} ${sigmaelem1} ${sigmaelem2}
|
||||
4.67637 0.5 ${radelem2} ${sigmaelem1} ${sigmaelem2}
|
||||
4.67637 0.5 0.5 ${sigmaelem1} ${sigmaelem2}
|
||||
4.67637 0.5 0.5 0.1355 ${sigmaelem2}
|
||||
4.67637 0.5 0.5 0.1355 0.2
|
||||
|
||||
# build zero potential to force ghost atom creation
|
||||
|
||||
pair_style zero ${rcutfac}
|
||||
pair_style zero 4.67637
|
||||
pair_coeff * *
|
||||
|
||||
# define atom and grid computes
|
||||
|
||||
compute mygridlocal all gaussian/grid/local grid ${ngrid} ${ngrid} ${ngrid} ${gaussian_options}
|
||||
compute mygridlocal all gaussian/grid/local grid 2 ${ngrid} ${ngrid} ${gaussian_options}
|
||||
compute mygridlocal all gaussian/grid/local grid 2 2 ${ngrid} ${gaussian_options}
|
||||
compute mygridlocal all gaussian/grid/local grid 2 2 2 ${gaussian_options}
|
||||
compute mygridlocal all gaussian/grid/local grid 2 2 2 4.67637 0.5 0.5 0.1355 0.2
|
||||
|
||||
# define output
|
||||
|
||||
dump 1 all local 1000 dump.glocal c_mygridlocal[*]
|
||||
dump 2 all custom 1000 dump.gatom id x y z
|
||||
compute val1 all reduce max c_mygridlocal[7] inputs local
|
||||
compute val2 all reduce max c_mygridlocal[8] inputs local
|
||||
thermo_style custom step c_val1 c_val2
|
||||
|
||||
# run
|
||||
|
||||
run 0
|
||||
WARNING: No fixes with time integration, atoms won't move (src/verlet.cpp:60)
|
||||
Generated 0 of 1 mixed pair_coeff terms from geometric mixing rule
|
||||
Neighbor list info ...
|
||||
update: every = 1 steps, delay = 0 steps, check = yes
|
||||
max neighbors/atom: 2000, page size: 100000
|
||||
master list distance cutoff = 6.67637
|
||||
ghost atom cutoff = 6.67637
|
||||
binsize = 3.338185, bins = 1 1 1
|
||||
1 neighbor lists, perpetual/occasional/extra = 1 0 0
|
||||
(1) pair zero, perpetual
|
||||
attributes: half, newton on
|
||||
pair build: half/bin/atomonly/newton
|
||||
stencil: half/bin/3d
|
||||
bin: standard
|
||||
WARNING: Proc sub-domain size < neighbor skin, could lead to lost atoms (src/domain.cpp:1202)
|
||||
Per MPI rank memory allocation (min/avg/max) = 3.522 | 3.523 | 3.524 Mbytes
|
||||
Step c_val1 c_val2
|
||||
0 25.521859 7.9367045
|
||||
Loop time of 2.238e-06 on 4 procs for 0 steps with 2 atoms
|
||||
|
||||
89.4% CPU use with 4 MPI tasks x 1 OpenMP threads
|
||||
|
||||
MPI task timing breakdown:
|
||||
Section | min time | avg time | max time |%varavg| %total
|
||||
---------------------------------------------------------------
|
||||
Pair | 0 | 0 | 0 | 0.0 | 0.00
|
||||
Neigh | 0 | 0 | 0 | 0.0 | 0.00
|
||||
Comm | 0 | 0 | 0 | 0.0 | 0.00
|
||||
Output | 0 | 0 | 0 | 0.0 | 0.00
|
||||
Modify | 0 | 0 | 0 | 0.0 | 0.00
|
||||
Other | | 2.238e-06 | | |100.00
|
||||
|
||||
Nlocal: 0.5 ave 1 max 0 min
|
||||
Histogram: 2 0 0 0 0 0 0 0 0 2
|
||||
Nghost: 274.5 ave 275 max 274 min
|
||||
Histogram: 2 0 0 0 0 0 0 0 0 2
|
||||
Neighs: 16 ave 40 max 0 min
|
||||
Histogram: 2 0 0 0 0 0 1 0 0 1
|
||||
|
||||
Total # of neighbors = 64
|
||||
Ave neighs/atom = 32
|
||||
Neighbor list builds = 0
|
||||
Dangerous builds = 0
|
||||
Total wall time: 0:00:00
|
||||
@ -127,6 +127,16 @@ MODULE LIBLAMMPS
|
||||
PROCEDURE :: set_string_variable => lmp_set_string_variable
|
||||
PROCEDURE :: set_internal_variable => lmp_set_internal_variable
|
||||
PROCEDURE :: eval => lmp_eval
|
||||
|
||||
PROCEDURE :: clearstep_compute => lmp_clearstep_compute
|
||||
PROCEDURE, PRIVATE :: lmp_addstep_compute_smallint
|
||||
PROCEDURE, PRIVATE :: lmp_addstep_compute_bigint
|
||||
GENERIC :: addstep_compute => lmp_addstep_compute_smallint, lmp_addstep_compute_bigint
|
||||
PROCEDURE, PRIVATE :: lmp_addstep_compute_all_smallint
|
||||
PROCEDURE, PRIVATE :: lmp_addstep_compute_all_bigint
|
||||
GENERIC :: addstep_compute_all => lmp_addstep_compute_all_smallint, &
|
||||
lmp_addstep_compute_all_bigint
|
||||
|
||||
PROCEDURE, PRIVATE :: lmp_gather_atoms_int
|
||||
PROCEDURE, PRIVATE :: lmp_gather_atoms_double
|
||||
GENERIC :: gather_atoms => lmp_gather_atoms_int, &
|
||||
@ -626,6 +636,24 @@ MODULE LIBLAMMPS
|
||||
REAL(c_double) :: lammps_eval
|
||||
END FUNCTION lammps_eval
|
||||
|
||||
SUBROUTINE lammps_clearstep_compute(handle) BIND(C)
|
||||
IMPORT :: c_ptr
|
||||
IMPLICIT NONE
|
||||
TYPE(c_ptr), VALUE :: handle
|
||||
END SUBROUTINE lammps_clearstep_compute
|
||||
|
||||
SUBROUTINE lammps_addstep_compute(handle, step) BIND(C)
|
||||
IMPORT :: c_ptr
|
||||
IMPLICIT NONE
|
||||
TYPE(c_ptr), VALUE :: handle, step
|
||||
END SUBROUTINE lammps_addstep_compute
|
||||
|
||||
SUBROUTINE lammps_addstep_compute_all(handle, step) BIND(C)
|
||||
IMPORT :: c_ptr
|
||||
IMPLICIT NONE
|
||||
TYPE(c_ptr), VALUE :: handle, step
|
||||
END SUBROUTINE lammps_addstep_compute_all
|
||||
|
||||
SUBROUTINE lammps_gather_atoms(handle, name, TYPE, count, DATA) BIND(C)
|
||||
IMPORT :: c_int, c_ptr
|
||||
IMPLICIT NONE
|
||||
@ -1846,6 +1874,80 @@ CONTAINS
|
||||
CALL lammps_free(Cexpr)
|
||||
END FUNCTION lmp_eval
|
||||
|
||||
! equivalent subroutine to lammps_clearstep_compute
|
||||
SUBROUTINE lmp_clearstep_compute(self)
|
||||
CLASS(lammps), INTENT(IN) :: self
|
||||
CALL lammps_clearstep_compute(self%handle)
|
||||
END SUBROUTINE lmp_clearstep_compute
|
||||
|
||||
! equivalent subroutine to lammps_addstep_compute
|
||||
SUBROUTINE lmp_addstep_compute_bigint(self, nextstep)
|
||||
CLASS(lammps), INTENT(IN) :: self
|
||||
INTEGER(kind=8), INTENT(IN) :: nextstep
|
||||
INTEGER(c_int), TARGET :: smallstep
|
||||
INTEGER(c_int64_t), TARGET :: bigstep
|
||||
TYPE(c_ptr) :: ptrstep
|
||||
IF (SIZE_BIGINT == 4_c_int) THEN
|
||||
smallstep = INT(nextstep,kind=c_int)
|
||||
ptrstep = C_LOC(smallstep)
|
||||
ELSE
|
||||
bigstep = nextstep
|
||||
ptrstep = C_LOC(bigstep)
|
||||
END IF
|
||||
CALL lammps_addstep_compute(self%handle, ptrstep)
|
||||
END SUBROUTINE lmp_addstep_compute_bigint
|
||||
|
||||
! equivalent subroutine to lammps_addstep_compute
|
||||
SUBROUTINE lmp_addstep_compute_smallint(self, nextstep)
|
||||
CLASS(lammps), INTENT(IN) :: self
|
||||
INTEGER(kind=4), INTENT(IN) :: nextstep
|
||||
INTEGER(c_int), TARGET :: smallstep
|
||||
INTEGER(c_int64_t), TARGET :: bigstep
|
||||
TYPE(c_ptr) :: ptrstep
|
||||
IF (SIZE_BIGINT == 4_c_int) THEN
|
||||
smallstep = nextstep
|
||||
ptrstep = C_LOC(smallstep)
|
||||
ELSE
|
||||
bigstep = nextstep
|
||||
ptrstep = C_LOC(bigstep)
|
||||
END IF
|
||||
CALL lammps_addstep_compute(self%handle, ptrstep)
|
||||
END SUBROUTINE lmp_addstep_compute_smallint
|
||||
|
||||
! equivalent subroutine to lammps_addstep_compute_all
|
||||
SUBROUTINE lmp_addstep_compute_all_bigint(self, nextstep)
|
||||
CLASS(lammps), INTENT(IN) :: self
|
||||
INTEGER(kind=8), INTENT(IN) :: nextstep
|
||||
INTEGER(c_int), TARGET :: smallstep
|
||||
INTEGER(c_int64_t), TARGET :: bigstep
|
||||
TYPE(c_ptr) :: ptrstep
|
||||
IF (SIZE_BIGINT == 4_c_int) THEN
|
||||
smallstep = INT(nextstep,kind=c_int)
|
||||
ptrstep = C_LOC(smallstep)
|
||||
ELSE
|
||||
bigstep = nextstep
|
||||
ptrstep = C_LOC(bigstep)
|
||||
END IF
|
||||
CALL lammps_addstep_compute_all(self%handle, ptrstep)
|
||||
END SUBROUTINE lmp_addstep_compute_all_bigint
|
||||
|
||||
! equivalent subroutine to lammps_addstep_compute_all
|
||||
SUBROUTINE lmp_addstep_compute_all_smallint(self, nextstep)
|
||||
CLASS(lammps), INTENT(IN) :: self
|
||||
INTEGER(kind=4), INTENT(IN) :: nextstep
|
||||
INTEGER(c_int), TARGET :: smallstep
|
||||
INTEGER(c_int64_t), TARGET :: bigstep
|
||||
TYPE(c_ptr) :: ptrstep
|
||||
IF (SIZE_BIGINT == 4_c_int) THEN
|
||||
smallstep = nextstep
|
||||
ptrstep = C_LOC(smallstep)
|
||||
ELSE
|
||||
bigstep = nextstep
|
||||
ptrstep = C_LOC(bigstep)
|
||||
END IF
|
||||
CALL lammps_addstep_compute_all(self%handle, ptrstep)
|
||||
END SUBROUTINE lmp_addstep_compute_all_smallint
|
||||
|
||||
! equivalent function to lammps_gather_atoms (for integers)
|
||||
SUBROUTINE lmp_gather_atoms_int(self, name, count, data)
|
||||
CLASS(lammps), INTENT(IN) :: self
|
||||
|
||||
@ -19,7 +19,7 @@ parser = ArgumentParser(prog='Install.py',
|
||||
# Note: must also adjust check for supported API versions in
|
||||
# fix_plumed.cpp when version changes from v2.n.x to v2.n+1.y
|
||||
|
||||
version = "2.9.2"
|
||||
version = "2.9.3"
|
||||
mode = "static"
|
||||
|
||||
# help message
|
||||
@ -52,6 +52,7 @@ checksums = { \
|
||||
'2.9.0' : '661eabeebee05cf84bbf9dc23d7d5f46', \
|
||||
'2.9.1' : 'c3b2d31479c1e9ce211719d40e9efbd7', \
|
||||
'2.9.2' : '04862602a372c1013bdfee2d6d03bace', \
|
||||
'2.9.3' : 'ee1249805fe94bccee17d10610d3f6f1', \
|
||||
}
|
||||
|
||||
# parse and process arguments
|
||||
|
||||
@ -422,6 +422,10 @@ class lammps(object):
|
||||
self.lib.lammps_extract_variable_datatype.argtypes = [c_void_p, c_char_p]
|
||||
self.lib.lammps_extract_variable_datatype.restype = c_int
|
||||
|
||||
self.lib.lammps_clearstep_compute.argtype = [c_void_p]
|
||||
self.lib.lammps_addstep_compute.argtype = [c_void_p, c_void_p]
|
||||
self.lib.lammps_addstep_compute_all.argtype = [c_void_p, c_void_p]
|
||||
|
||||
self.lib.lammps_eval.argtypes = [c_void_p, c_char_p]
|
||||
self.lib.lammps_eval.restype = c_double
|
||||
|
||||
@ -1594,6 +1598,26 @@ class lammps(object):
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def clearstep_compute(self, nextstep):
|
||||
with ExceptionCheck(self):
|
||||
return self.lib.lammps_clearstep_compute(self.lmp)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def addstep_compute(self, nextstep):
|
||||
with ExceptionCheck(self):
|
||||
nextstep = self.c_bigint(nextstep)
|
||||
return self.lib.lammps_addstep_compute(self.lmp, POINTER(nextstep))
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def addstep_compute_all(self, nextstep):
|
||||
with ExceptionCheck(self):
|
||||
nextstep = self.c_bigint(nextstep)
|
||||
return self.lib.lammps_addstep_compute_all(self.lmp, POINTER(nextstep))
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def flush_buffers(self):
|
||||
"""Flush output buffers
|
||||
|
||||
@ -1694,7 +1718,6 @@ class lammps(object):
|
||||
|
||||
with ExceptionCheck(self):
|
||||
return self.lib.lammps_eval(self.lmp, newexpr)
|
||||
return None
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
|
||||
8
src/.gitignore
vendored
8
src/.gitignore
vendored
@ -252,6 +252,8 @@
|
||||
/*rheo*.cpp
|
||||
/*rheo*.h
|
||||
|
||||
/compute_gaussian_grid_local.cpp
|
||||
/compute_gaussian_grid_local.h
|
||||
/compute_grid.cpp
|
||||
/compute_grid.h
|
||||
/compute_grid_local.cpp
|
||||
@ -849,6 +851,8 @@
|
||||
/fix_ffl.h
|
||||
/fix_filter_corotate.cpp
|
||||
/fix_filter_corotate.h
|
||||
/fix_granular_mdr.cpp
|
||||
/fix_granular_mdr.h
|
||||
/fix_viscosity.cpp
|
||||
/fix_viscosity.h
|
||||
/fix_ehex.cpp
|
||||
@ -1277,6 +1281,10 @@
|
||||
/pair_hbond_dreiding_lj.h
|
||||
/pair_hbond_dreiding_morse.cpp
|
||||
/pair_hbond_dreiding_morse.h
|
||||
/pair_hbond_dreiding_lj_angleoffset.cpp
|
||||
/pair_hbond_dreiding_lj_angleoffset.h
|
||||
/pair_hbond_dreiding_morse_angleoffset.cpp
|
||||
/pair_hbond_dreiding_morse_angleoffset.h
|
||||
/pair_hdnnp.cpp
|
||||
/pair_hdnnp.h
|
||||
/pair_ilp_graphene_hbn.cpp
|
||||
|
||||
@ -773,9 +773,9 @@ bigint FixAmoebaPiTorsion::read_data_skip_lines(char *keyword)
|
||||
|
||||
void FixAmoebaPiTorsion::write_data_header(FILE *fp, int mth)
|
||||
{
|
||||
if (mth == 0) fmt::print(fp,"{} pitorsions\n",npitorsions);
|
||||
if (mth == 0) utils::print(fp,"{} pitorsions\n",npitorsions);
|
||||
else if (mth == 1)
|
||||
fmt::print(fp, "{} pitorsion types\n",npitorsion_types);
|
||||
utils::print(fp, "{} pitorsion types\n",npitorsion_types);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
|
||||
@ -261,22 +261,22 @@ int BodyNparticle::write_data_body(FILE *fp, double *buf)
|
||||
|
||||
// atomID ninteger ndouble
|
||||
|
||||
fmt::print(fp,"{} {} {}\n",ubuf(buf[m]).i,ubuf(buf[m+1]).i,ubuf(buf[m+2]).i);
|
||||
utils::print(fp,"{} {} {}\n",ubuf(buf[m]).i,ubuf(buf[m+1]).i,ubuf(buf[m+2]).i);
|
||||
m += 3;
|
||||
|
||||
const int nsub = (int) ubuf(buf[m++]).i;
|
||||
fmt::print(fp,"{}\n",nsub);
|
||||
utils::print(fp,"{}\n",nsub);
|
||||
|
||||
// inertia
|
||||
|
||||
fmt::print(fp,"{} {} {} {} {} {}\n",
|
||||
utils::print(fp,"{} {} {} {} {} {}\n",
|
||||
buf[m+0],buf[m+1],buf[m+2],buf[m+3],buf[m+4],buf[m+5]);
|
||||
m += 6;
|
||||
|
||||
// nsub vertices
|
||||
|
||||
for (int i = 0; i < nsub; i++) {
|
||||
fmt::print(fp,"{} {} {}\n",buf[m],buf[m+1],buf[m+2]);
|
||||
utils::print(fp,"{} {} {}\n",buf[m],buf[m+1],buf[m+2]);
|
||||
m += 3;
|
||||
}
|
||||
|
||||
|
||||
@ -398,27 +398,27 @@ int BodyRoundedPolygon::write_data_body(FILE *fp, double *buf)
|
||||
|
||||
// atomID ninteger ndouble
|
||||
|
||||
fmt::print(fp,"{} {} {}\n",ubuf(buf[m]).i,ubuf(buf[m+1]).i,ubuf(buf[m+2]).i);
|
||||
utils::print(fp,"{} {} {}\n",ubuf(buf[m]).i,ubuf(buf[m+1]).i,ubuf(buf[m+2]).i);
|
||||
m += 3;
|
||||
|
||||
const int nsub = (int) ubuf(buf[m++]).i;
|
||||
fmt::print(fp,"{}\n",nsub);
|
||||
utils::print(fp,"{}\n",nsub);
|
||||
|
||||
// inertia
|
||||
|
||||
fmt::print(fp,"{} {} {} {} {} {}\n",
|
||||
utils::print(fp,"{} {} {} {} {} {}\n",
|
||||
buf[m+0],buf[m+1],buf[m+2],buf[m+3],buf[m+4],buf[m+5]);
|
||||
m += 6;
|
||||
|
||||
// nsub vertices
|
||||
|
||||
for (int i = 0; i < nsub; i++, m+=3)
|
||||
fmt::print(fp,"{} {} {}\n",buf[m],buf[m+1],buf[m+2]);
|
||||
utils::print(fp,"{} {} {}\n",buf[m],buf[m+1],buf[m+2]);
|
||||
|
||||
// rounded diameter
|
||||
|
||||
double diameter = buf[m++];
|
||||
fmt::print(fp,"{}\n",diameter);
|
||||
utils::print(fp,"{}\n",diameter);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
@ -476,7 +476,7 @@ int BodyRoundedPolyhedron::write_data_body(FILE *fp, double *buf)
|
||||
|
||||
// atomID ninteger ndouble
|
||||
|
||||
fmt::print(fp,"{} {} {}\n",ubuf(buf[m]).i,ubuf(buf[m+1]).i,ubuf(buf[m+2]).i);
|
||||
utils::print(fp,"{} {} {}\n",ubuf(buf[m]).i,ubuf(buf[m+1]).i,ubuf(buf[m+2]).i);
|
||||
m += 3;
|
||||
|
||||
// nvert, nedge, nface
|
||||
@ -484,27 +484,27 @@ int BodyRoundedPolyhedron::write_data_body(FILE *fp, double *buf)
|
||||
const int nsub = (int) ubuf(buf[m++]).i;
|
||||
const int nedge = (int) ubuf(buf[m++]).i;
|
||||
const int nface = (int) ubuf(buf[m++]).i;
|
||||
fmt::print(fp,"{} {} {}\n",nsub,nedge,nface);
|
||||
utils::print(fp,"{} {} {}\n",nsub,nedge,nface);
|
||||
|
||||
// inertia
|
||||
|
||||
fmt::print(fp,"{} {} {} {} {} {}\n",
|
||||
utils::print(fp,"{} {} {} {} {} {}\n",
|
||||
buf[m+0],buf[m+1],buf[m+2],buf[m+3],buf[m+4],buf[m+5]);
|
||||
m += 6;
|
||||
|
||||
// nsub vertices
|
||||
|
||||
for (int i = 0; i < nsub; i++, m+=3)
|
||||
fmt::print(fp,"{} {} {}\n",buf[m],buf[m+1],buf[m+2]);
|
||||
utils::print(fp,"{} {} {}\n",buf[m],buf[m+1],buf[m+2]);
|
||||
|
||||
// nedge 2-tuples and nface 4-tuples
|
||||
// unless nsub = 1 or 2
|
||||
|
||||
if (nsub > 2) {
|
||||
for (int i = 0; i < nedge; i++, m+=2)
|
||||
fmt::print(fp,"{} {}\n",static_cast<int> (buf[m]),static_cast<int> (buf[m+1]));
|
||||
utils::print(fp,"{} {}\n",static_cast<int> (buf[m]),static_cast<int> (buf[m+1]));
|
||||
for (int i = 0; i < nface; i++, m+=4)
|
||||
fmt::print(fp,"{} {} {} {}\n",
|
||||
utils::print(fp,"{} {} {} {}\n",
|
||||
static_cast<int> (buf[m]),static_cast<int> (buf[m+1]),
|
||||
static_cast<int> (buf[m+2]),static_cast<int> (buf[m+3]));
|
||||
}
|
||||
@ -512,7 +512,7 @@ int BodyRoundedPolyhedron::write_data_body(FILE *fp, double *buf)
|
||||
// rounded diameter
|
||||
|
||||
double diameter = buf[m++];
|
||||
fmt::print(fp,"{}\n",diameter);
|
||||
utils::print(fp,"{}\n",diameter);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
@ -307,9 +307,16 @@ void FixRX::post_constructor()
|
||||
id_fix_species = utils::strdup(std::string(id)+"_SPECIES");
|
||||
id_fix_species_old = utils::strdup(std::string(id)+"_SPECIES_OLD");
|
||||
|
||||
const std::string fmtstr = "{} {} property/atom ";
|
||||
auto newcmd1 = fmt::format(fmtstr,id_fix_species,group->names[igroup]);
|
||||
auto newcmd2 = fmt::format(fmtstr,id_fix_species_old,group->names[igroup]);
|
||||
std::string newcmd1 = id_fix_species;
|
||||
newcmd1 += " ";
|
||||
newcmd1 += group->names[igroup];
|
||||
newcmd1 += " property/atom ";
|
||||
|
||||
std::string newcmd2 = id_fix_species_old;
|
||||
newcmd2 += " ";
|
||||
newcmd2 += group->names[igroup];
|
||||
newcmd2 += " property/atom ";
|
||||
|
||||
for (int ii=0; ii<nspecies; ii++) {
|
||||
newcmd1 += fmt::format(" d_{}", tmpspecies[ii]);
|
||||
newcmd2 += fmt::format(" d_{}Old", tmpspecies[ii]);
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
// clang-format off
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
@ -29,10 +28,9 @@ using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
ComputeTempDrude::ComputeTempDrude(LAMMPS *lmp, int narg, char **arg) :
|
||||
Compute(lmp, narg, arg)
|
||||
ComputeTempDrude::ComputeTempDrude(LAMMPS *lmp, int narg, char **arg) : Compute(lmp, narg, arg)
|
||||
{
|
||||
if (narg != 3) error->all(FLERR,"Illegal compute temp command");
|
||||
if (narg != 3) error->all(FLERR, "Incorrect number of arguments for compute temp/drude");
|
||||
|
||||
vector_flag = 1;
|
||||
scalar_flag = 1;
|
||||
@ -65,11 +63,13 @@ void ComputeTempDrude::init()
|
||||
{
|
||||
// Fix drude already checks that there is only one fix drude instance
|
||||
auto &fixes = modify->get_fix_by_style("^drude$");
|
||||
if (fixes.size() == 0) error->all(FLERR, "compute temp/drude requires fix drude");
|
||||
if (fixes.size() == 0)
|
||||
error->all(FLERR, Error::NOLASTLINE, "compute temp/drude requires fix drude");
|
||||
fix_drude = dynamic_cast<FixDrude *>(fixes[0]);
|
||||
|
||||
if (!comm->ghost_velocity)
|
||||
error->all(FLERR,"compute temp/drude requires ghost velocities. Use comm_modify vel yes");
|
||||
error->all(FLERR, Error::NOLASTLINE,
|
||||
"compute temp/drude requires ghost velocities. Use comm_modify vel yes");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
@ -113,7 +113,7 @@ void ComputeTempDrude::dof_compute()
|
||||
int ComputeTempDrude::modify_param(int narg, char **arg)
|
||||
{
|
||||
if (strcmp(arg[0], "temp") == 0) {
|
||||
if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
|
||||
if (narg < 2) utils::missing_cmd_args(FLERR, "compute_modify temp", error);
|
||||
delete[] id_temp;
|
||||
id_temp = utils::strdup(arg[1]);
|
||||
|
||||
@ -149,20 +149,32 @@ void ComputeTempDrude::compute_vector()
|
||||
double mcore, mdrude;
|
||||
double ecore, edrude;
|
||||
double *vcore, *vdrude;
|
||||
double kineng_core_loc = 0., kineng_drude_loc = 0.;
|
||||
double kineng_core_loc = 0.0, kineng_drude_loc = 0.0;
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
vdrude = nullptr;
|
||||
vcore = nullptr;
|
||||
if (groupbit & mask[i] && drudetype[type[i]] != DRUDE_TYPE) {
|
||||
if (drudetype[type[i]] == NOPOL_TYPE) {
|
||||
ecore = 0.;
|
||||
ecore = 0.0;
|
||||
vcore = v[i];
|
||||
if (temperature) temperature->remove_bias(i, vcore);
|
||||
for (int k = 0; k < dim; k++) ecore += vcore[k] * vcore[k];
|
||||
if (temperature) temperature->restore_bias(i, vcore);
|
||||
if (rmass) mcore = rmass[i];
|
||||
else mcore = mass[type[i]];
|
||||
if (rmass)
|
||||
mcore = rmass[i];
|
||||
else
|
||||
mcore = mass[type[i]];
|
||||
kineng_core_loc += mcore * ecore;
|
||||
} else { // CORE_TYPE
|
||||
int j = atom->map(drudeid[i]);
|
||||
if (j < 0) {
|
||||
if (drudeid[i] == 0) {
|
||||
error->one(FLERR, "Drude atom for core atom ID {} is not defined", atom->tag[i]);
|
||||
} else {
|
||||
error->one(FLERR, "Drude atom ID {} for core atom ID {} is out of range", drudeid[i],
|
||||
atom->tag[i]);
|
||||
}
|
||||
}
|
||||
if (rmass) {
|
||||
mcore = rmass[i];
|
||||
mdrude = rmass[j];
|
||||
@ -170,9 +182,9 @@ void ComputeTempDrude::compute_vector()
|
||||
mcore = mass[type[i]];
|
||||
mdrude = mass[type[j]];
|
||||
}
|
||||
double mtot_inv = 1. / (mcore + mdrude);
|
||||
ecore = 0.;
|
||||
edrude = 0.;
|
||||
double mtot_inv = 1.0 / (mcore + mdrude);
|
||||
ecore = 0.0;
|
||||
edrude = 0.0;
|
||||
vcore = v[i];
|
||||
vdrude = v[j];
|
||||
if (temperature) {
|
||||
@ -208,9 +220,9 @@ void ComputeTempDrude::compute_vector()
|
||||
vector[5] = kineng_drude;
|
||||
}
|
||||
|
||||
double ComputeTempDrude::compute_scalar() {
|
||||
double ComputeTempDrude::compute_scalar()
|
||||
{
|
||||
compute_vector();
|
||||
scalar = vector[0];
|
||||
return scalar;
|
||||
}
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ class ComputeTempDrude : public Compute {
|
||||
void setup() override;
|
||||
void compute_vector() override;
|
||||
double compute_scalar() override;
|
||||
int modify_param(int, char **);
|
||||
int modify_param(int, char **) override;
|
||||
|
||||
private:
|
||||
class FixDrude *fix_drude;
|
||||
|
||||
@ -33,7 +33,9 @@ using namespace FixConst;
|
||||
FixDrude::FixDrude(LAMMPS *lmp, int narg, char **arg) :
|
||||
Fix(lmp, narg, arg)
|
||||
{
|
||||
if (narg != 3 + atom->ntypes) error->all(FLERR,"Illegal fix drude command");
|
||||
if (narg != 3 + atom->ntypes)
|
||||
error->all(FLERR,"Incorrect number of arguments ({} instead of {}) for fix drude command",
|
||||
narg, 3 + atom->ntypes);
|
||||
|
||||
comm_border = 1; // drudeid
|
||||
special_alter_flag = 1;
|
||||
@ -49,7 +51,7 @@ FixDrude::FixDrude(LAMMPS *lmp, int narg, char **arg) :
|
||||
else if (arg[i][0] == 'd' || arg[i][0] == 'D' || arg[i][0] == '2')
|
||||
drudetype[i-2] = DRUDE_TYPE;
|
||||
else
|
||||
error->all(FLERR, "Illegal fix drude command");
|
||||
error->all(FLERR, i, "Unknown drude type {} for atom type {}", arg[i], i-2);
|
||||
}
|
||||
|
||||
drudeid = nullptr;
|
||||
@ -82,7 +84,8 @@ FixDrude::~FixDrude()
|
||||
|
||||
void FixDrude::init()
|
||||
{
|
||||
if (modify->get_fix_by_style("^drude$").size() > 1) error->all(FLERR,"More than one fix drude");
|
||||
if (modify->get_fix_by_style("^drude$").size() > 1)
|
||||
error->all(FLERR, Error::NOLASTLINE, "More than one fix drude");
|
||||
|
||||
if (!rebuildflag) rebuild_special();
|
||||
}
|
||||
@ -106,8 +109,7 @@ void FixDrude::build_drudeid() {
|
||||
std::vector<tagint> core_drude_vec;
|
||||
partner_set = new std::set<tagint>[nlocal]; // Temporary sets of bond partner tags
|
||||
|
||||
if (atom->molecular == Atom::MOLECULAR)
|
||||
{
|
||||
if (atom->molecular == Atom::MOLECULAR) {
|
||||
// Build list of my atoms' bond partners
|
||||
for (int i=0; i<nlocal; i++) {
|
||||
if (drudetype[type[i]] == NOPOL_TYPE) continue;
|
||||
@ -117,9 +119,7 @@ void FixDrude::build_drudeid() {
|
||||
core_drude_vec.push_back(atom->bond_atom[i][k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Template case
|
||||
class Molecule **atommols;
|
||||
atommols = atom->avec->onemols;
|
||||
@ -157,10 +157,17 @@ void FixDrude::build_drudeid() {
|
||||
// At this point each of my Drudes knows its core.
|
||||
// Send my list of Drudes to other procs and myself
|
||||
// so that each core finds its Drude.
|
||||
comm->ring(drude_vec.size(), sizeof(tagint),
|
||||
(char *) drude_vec.data(),
|
||||
comm->ring(drude_vec.size(), sizeof(tagint), (char *) drude_vec.data(),
|
||||
3, ring_search_drudeid, nullptr, (void *)this, 1);
|
||||
delete[] partner_set;
|
||||
|
||||
// Check if all cores have a drude particle attached
|
||||
for (int i=0; i<nlocal; i++) {
|
||||
if (drudetype[type[i]] == CORE_TYPE) {
|
||||
if (drudeid[i] == 0)
|
||||
error->one(FLERR, Error::NOLASTLINE, "Core atom ID {} has no drude atom", atom->tag[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
@ -347,7 +354,8 @@ void FixDrude::rebuild_special() {
|
||||
utils::logmesg(lmp, "New max number of 1-2 to 1-4 neighbors: {} (+{})\n", nspecmax, nspecmax - nspecmax_old);
|
||||
|
||||
if (atom->maxspecial < nspecmax)
|
||||
error->all(FLERR, "Not enough space in special: extra/special/per/atom should be at least {}", nspecmax - nspecmax_old);
|
||||
error->all(FLERR, Error::NOLASTLINE, "Not enough space for special neighbors list: "
|
||||
"use extra/special/per/atom with at least a value of {}", nspecmax - nspecmax_old);
|
||||
|
||||
// Build list of cores' special lists to communicate to ghost drude particles
|
||||
for (int i=0; i<nlocal; i++) {
|
||||
@ -512,7 +520,8 @@ void FixDrude::ring_copy_drude(int size, char *cbuf, void *ptr) {
|
||||
void FixDrude::set_arrays(int i) {
|
||||
if (drudetype[atom->type[i]] != NOPOL_TYPE) {
|
||||
if (atom->nspecial[i] == nullptr)
|
||||
error->all(FLERR, "Polarizable atoms cannot be inserted with special lists info from the molecule template");
|
||||
error->all(FLERR, Error::NOLASTLINE, "Polarizable atoms cannot be inserted "
|
||||
"with special lists info from the molecule template");
|
||||
drudeid[i] = atom->special[i][0]; // Drude partner should be at first place in the special list
|
||||
} else {
|
||||
drudeid[i] = 0;
|
||||
|
||||
@ -1363,10 +1363,10 @@ int FixElectrodeConp::setmask()
|
||||
void FixElectrodeConp::write_to_file(FILE *file, const std::vector<tagint> &tags,
|
||||
const std::vector<std::vector<double>> &mat)
|
||||
{
|
||||
for (const auto &t : tags) fmt::print(file, "{:20}", t);
|
||||
for (const auto &t : tags) utils::print(file, "{:20}", t);
|
||||
fputs("\n", file);
|
||||
for (const auto &vec : mat) {
|
||||
for (const auto &x : vec) fmt::print(file, "{:20.11e}", x);
|
||||
for (const auto &x : vec) utils::print(file, "{:20.11e}", x);
|
||||
fputs("\n", file);
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ void Group2Ndx::write_group(FILE *fp, int gid)
|
||||
if (gid == 0) {
|
||||
fputs("[ System ]\n", fp);
|
||||
} else {
|
||||
fmt::print(fp, "[ {} ]\n", group->names[gid]);
|
||||
utils::print(fp, "[ {} ]\n", group->names[gid]);
|
||||
}
|
||||
width = log10((double) atom->natoms) + 2;
|
||||
cols = 80 / width;
|
||||
@ -142,7 +142,7 @@ void Group2Ndx::write_group(FILE *fp, int gid)
|
||||
if (fp) {
|
||||
int i, j;
|
||||
for (i = 0, j = 0; i < gcount; ++i) {
|
||||
fmt::print(fp, "{:>{}}", recvlist[i], width);
|
||||
utils::print(fp, "{:>{}}", recvlist[i], width);
|
||||
++j;
|
||||
if (j == cols) {
|
||||
fputs("\n", fp);
|
||||
|
||||
@ -39,8 +39,6 @@ using MathConst::RAD2DEG;
|
||||
|
||||
enum { DEGREE, RADIAN, COSINE };
|
||||
|
||||
static constexpr double BIG = 1.0e20;
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
compute angular distribution functions for I, J, K atoms
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
@ -284,9 +284,9 @@ void ComputeStressCartesian::compute_array()
|
||||
// calculate number density and kinetic contribution to pressure
|
||||
if (compute_ke) {
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
int bin1 = (int) ((x[i][dir1] - boxlo[dir1]) / bin_width1) % nbins1;
|
||||
int bin1 = (int) floor((x[i][dir1] - boxlo[dir1]) / bin_width1) % nbins1;
|
||||
int bin2 = 0;
|
||||
if (dims == 2) bin2 = (int) ((x[i][dir2] - boxlo[dir2]) / bin_width2) % nbins2;
|
||||
if (dims == 2) bin2 = (int) floor((x[i][dir2] - boxlo[dir2]) / bin_width2) % nbins2;
|
||||
|
||||
// Apply periodic boundary conditions and avoid out of range access
|
||||
if (domain->periodicity[dir1] == 1) {
|
||||
@ -453,27 +453,6 @@ void ComputeStressCartesian::compute_pressure(double fpair, double xi, double yi
|
||||
int bin1 = next_bin1;
|
||||
int bin2 = next_bin2;
|
||||
|
||||
double l1;
|
||||
if (rij1 > 0)
|
||||
l1 = ((bin1 + 1) * bin_width1 - xi) / rij1;
|
||||
else
|
||||
l1 = (bin1 * bin_width1 - xi) / rij1;
|
||||
|
||||
double l2;
|
||||
if (rij2 > 0)
|
||||
l2 = ((bin2 + 1) * bin_width2 - yi) / rij2;
|
||||
else
|
||||
l2 = (bin2 * bin_width2 - yi) / rij2;
|
||||
|
||||
if ((l1 < l2 || l2 < lb + SMALL) && l1 <= 1.0 && l1 > lb) {
|
||||
lb = l1;
|
||||
next_bin1 = bin1 + (int) (rij1 / fabs(rij1));
|
||||
} else if (l2 <= 1.0 && l2 > lb) {
|
||||
lb = l2;
|
||||
next_bin2 = bin2 + (int) (rij2 / fabs(rij2));
|
||||
} else
|
||||
lb = 1.0;
|
||||
|
||||
// Periodic boundary conditions
|
||||
if (domain->periodicity[dir1] == 1) {
|
||||
if (bin1 < 0)
|
||||
@ -495,6 +474,33 @@ void ComputeStressCartesian::compute_pressure(double fpair, double xi, double yi
|
||||
else if (bin2 >= nbins2)
|
||||
bin2 = nbins2 - 1;
|
||||
|
||||
double l1;
|
||||
double tmp1[3] = {0.0, 0.0, 0.0};
|
||||
if (rij1 > 0)
|
||||
tmp1[dir1] = (bin1 + 1) * bin_width1 - xi;
|
||||
else
|
||||
tmp1[dir1] = bin1 * bin_width1 - xi;
|
||||
domain->minimum_image(tmp1[0],tmp1[1],tmp1[2]);
|
||||
l1 = tmp1[dir1] / rij1;
|
||||
|
||||
double l2;
|
||||
double tmp2[3] = {0.0, 0.0, 0.0};
|
||||
if (rij2 > 0)
|
||||
tmp2[dir2] = (bin2 + 1) * bin_width2 - yi;
|
||||
else
|
||||
tmp2[dir2] = bin2 * bin_width2 - yi;
|
||||
domain->minimum_image(tmp2[0],tmp2[1],tmp2[2]);
|
||||
l2 = tmp2[dir2] / rij2;
|
||||
|
||||
if ((dims == 1 || l1 < l2 || l2 < lb + SMALL) && l1 <= 1.0 && l1 > lb) {
|
||||
lb = l1;
|
||||
next_bin1 = bin1 + (int) (rij1 / fabs(rij1));
|
||||
} else if (dims == 2 && l2 <= 1.0 && l2 > lb) {
|
||||
lb = l2;
|
||||
next_bin2 = bin2 + (int) (rij2 / fabs(rij2));
|
||||
} else
|
||||
lb = 1.0;
|
||||
|
||||
if (bin1 + bin2 * nbins1 > nbins1 * nbins2) error->all(FLERR, "Bin outside: lb={:.16g}", lb);
|
||||
|
||||
tpcxx[bin1 + bin2 * nbins1] += (fpair * delx * delx * (lb - la));
|
||||
|
||||
@ -94,31 +94,31 @@ void DumpYAML::write_header(bigint ndump)
|
||||
|
||||
if (comm->me == 0) {
|
||||
const std::string boundary(boundstr);
|
||||
fmt::print(fp, "---\ncreator: LAMMPS\ntimestep: {}\n", update->ntimestep);
|
||||
if (unit_flag) fmt::print(fp, "units: {}\n", update->unit_style);
|
||||
if (time_flag) fmt::print(fp, "time: {:.16g}\n", compute_time());
|
||||
utils::print(fp, "---\ncreator: LAMMPS\ntimestep: {}\n", update->ntimestep);
|
||||
if (unit_flag) utils::print(fp, "units: {}\n", update->unit_style);
|
||||
if (time_flag) utils::print(fp, "time: {:.16g}\n", compute_time());
|
||||
|
||||
fmt::print(fp, "natoms: {}\n", ndump);
|
||||
utils::print(fp, "natoms: {}\n", ndump);
|
||||
fputs("boundary: [ ", fp);
|
||||
for (const auto &bflag : boundary) {
|
||||
if (bflag == ' ') continue;
|
||||
fmt::print(fp, "{}, ", bflag);
|
||||
utils::print(fp, "{}, ", bflag);
|
||||
}
|
||||
fputs("]\n", fp);
|
||||
|
||||
if (thermo) fmt::print(fp, thermo_data);
|
||||
if (thermo) utils::print(fp, thermo_data);
|
||||
|
||||
fmt::print(fp, "box:\n - [ {}, {} ]\n", boxxlo, boxxhi);
|
||||
fmt::print(fp, " - [ {}, {} ]\n", boxylo, boxyhi);
|
||||
fmt::print(fp, " - [ {}, {} ]\n", boxzlo, boxzhi);
|
||||
if (domain->triclinic) fmt::print(fp, " - [ {}, {}, {} ]\n", boxxy, boxxz, boxyz);
|
||||
utils::print(fp, "box:\n - [ {}, {} ]\n", boxxlo, boxxhi);
|
||||
utils::print(fp, " - [ {}, {} ]\n", boxylo, boxyhi);
|
||||
utils::print(fp, " - [ {}, {} ]\n", boxzlo, boxzhi);
|
||||
if (domain->triclinic) utils::print(fp, " - [ {}, {}, {} ]\n", boxxy, boxxz, boxyz);
|
||||
|
||||
fmt::print(fp, "keywords: [ ");
|
||||
utils::print(fp, "keywords: [ ");
|
||||
for (const auto &item : utils::split_words(columns)) {
|
||||
if (item.find_first_of(special_chars) == std::string::npos)
|
||||
fmt::print(fp, "{}, ", item);
|
||||
utils::print(fp, "{}, ", item);
|
||||
else
|
||||
fmt::print(fp, "'{}', ", item);
|
||||
utils::print(fp, "'{}', ", item);
|
||||
}
|
||||
fputs(" ]\ndata:\n", fp);
|
||||
} else // reset so that the remainder of the output is not multi-proc
|
||||
|
||||
@ -489,7 +489,7 @@ void FixAveCorrelateLong::end_of_step()
|
||||
if (fp && comm->me == 0) {
|
||||
clearerr(fp);
|
||||
if (overwrite) (void) platform::fseek(fp,filepos);
|
||||
fmt::print(fp,"# Timestep: {}\n", ntimestep);
|
||||
utils::print(fp,"# Timestep: {}\n", ntimestep);
|
||||
for (unsigned int i=0; i < npcorr; ++i) {
|
||||
fprintf(fp, "%lg ", t[i]*update->dt*nevery);
|
||||
for (int j=0; j < npair; ++j) {
|
||||
|
||||
@ -68,7 +68,8 @@ FixElectronStoppingFit::FixElectronStoppingFit(LAMMPS *lmp, int narg, char **arg
|
||||
error->all(FLERR,"Incorrect number of fix electron/stopping/fit arguments");
|
||||
}
|
||||
|
||||
scalar_flag = 1;
|
||||
scalar_flag = 1; // intensive total energy loss since start of run
|
||||
extscalar = 0;
|
||||
global_freq = 1;
|
||||
|
||||
energy_coh_in = new double[atom->ntypes+1];
|
||||
|
||||
@ -270,7 +270,7 @@ void FixTMD::initial_integrate(int /*vflag*/)
|
||||
work_lambda += lambda*(rho_target - rho_old);
|
||||
if (!(update->ntimestep % nfileevery) &&
|
||||
(previous_stat != update->ntimestep)) {
|
||||
fmt::print(fp, "{} {} {} {} {} {} {} {}\n", update->ntimestep,rho_target,rho_old,
|
||||
utils::print(fp, "{} {} {} {} {} {} {} {}\n", update->ntimestep,rho_target,rho_old,
|
||||
gamma_back,gamma_forward,lambda,work_lambda,work_analytical);
|
||||
fflush(fp);
|
||||
previous_stat = update->ntimestep;
|
||||
|
||||
@ -523,7 +523,7 @@ void FixTTM::write_electron_temperatures(const std::string &filename)
|
||||
FILE *fp = fopen(filename.c_str(),"w");
|
||||
if (!fp) error->one(FLERR,"Fix ttm could not open output file {}: {}",
|
||||
filename,utils::getsyserror());
|
||||
fmt::print(fp,"# DATE: {} UNITS: {} COMMENT: Electron temperature on "
|
||||
utils::print(fp,"# DATE: {} UNITS: {} COMMENT: Electron temperature on "
|
||||
"{}x{}x{} grid at step {} - created by fix {}\n", utils::current_date(),
|
||||
update->unit_style, nxgrid, nygrid, nzgrid, update->ntimestep, style);
|
||||
|
||||
|
||||
@ -411,7 +411,7 @@ void FixTTMGrid::write_restart_file(const char *file)
|
||||
if (fpout == nullptr)
|
||||
error->one(FLERR,"Cannot open fix ttm/grid restart file {}: {}",outfile,utils::getsyserror());
|
||||
|
||||
fmt::print(fpout,"# DATE: {} UNITS: {} COMMENT: "
|
||||
utils::print(fpout,"# DATE: {} UNITS: {} COMMENT: "
|
||||
"Electron temperature on {}x{}x{} grid at step {} - "
|
||||
"created by fix {}\n",
|
||||
utils::current_date(),update->unit_style,
|
||||
|
||||
@ -628,7 +628,7 @@ void FixTTMMod::write_electron_temperatures(const std::string &filename)
|
||||
FILE *fp = fopen(filename.c_str(),"w");
|
||||
if (!fp) error->one(FLERR,"Fix ttm/mod could not open output file {}: {}",
|
||||
filename, utils::getsyserror());
|
||||
fmt::print(fp,"# DATE: {} UNITS: {} COMMENT: Electron temperature "
|
||||
utils::print(fp,"# DATE: {} UNITS: {} COMMENT: Electron temperature "
|
||||
"{}x{}x{} grid at step {}. Created by fix {}\n", utils::current_date(),
|
||||
update->unit_style, nxgrid, nygrid, nzgrid, update->ntimestep, style);
|
||||
|
||||
|
||||
131
src/EXTRA-MOLECULE/pair_hbond_dreiding_lj_angleoffset.cpp
Normal file
131
src/EXTRA-MOLECULE/pair_hbond_dreiding_lj_angleoffset.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
// clang-format off
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
LAMMPS development team: developers@lammps.org
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Tod A Pascal (Caltech), Don Xu/EiPi Fun
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "pair_hbond_dreiding_lj_angleoffset.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "atom_vec.h"
|
||||
#include "domain.h"
|
||||
#include "error.h"
|
||||
#include "force.h"
|
||||
#include "math_const.h"
|
||||
#include "math_special.h"
|
||||
#include "memory.h"
|
||||
#include "molecule.h"
|
||||
#include "neigh_list.h"
|
||||
#include "neighbor.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
static constexpr double SMALL = 0.001;
|
||||
static constexpr int CHUNK = 8;
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
// using namespace MathSpecial;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairHbondDreidingLJAngleoffset::PairHbondDreidingLJAngleoffset(LAMMPS *lmp)
|
||||
: PairHbondDreidingLJ(lmp) {
|
||||
|
||||
angle_offset_flag = 1;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one or more type pairs
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairHbondDreidingLJAngleoffset::coeff(int narg, char **arg)
|
||||
{
|
||||
if (narg < 6 || narg > 11)
|
||||
error->all(FLERR,"Incorrect args for pair coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi,jlo,jhi,klo,khi;
|
||||
utils::bounds(FLERR, arg[0], 1, atom->ntypes, ilo, ihi, error);
|
||||
utils::bounds(FLERR, arg[1], 1, atom->ntypes, jlo, jhi, error);
|
||||
utils::bounds_typelabel(FLERR, arg[2], 1, atom->ntypes, klo, khi, lmp, Atom::ATOM);
|
||||
|
||||
int donor_flag;
|
||||
if (strcmp(arg[3],"i") == 0) donor_flag = 0;
|
||||
else if (strcmp(arg[3],"j") == 0) donor_flag = 1;
|
||||
else error->all(FLERR,"Incorrect args for pair coefficients");
|
||||
|
||||
double epsilon_one = utils::numeric(FLERR, arg[4], false, lmp);
|
||||
double sigma_one = utils::numeric(FLERR, arg[5], false, lmp);
|
||||
|
||||
int ap_one = ap_global;
|
||||
if (narg > 6) ap_one = utils::inumeric(FLERR, arg[6], false, lmp);
|
||||
double cut_inner_one = cut_inner_global;
|
||||
double cut_outer_one = cut_outer_global;
|
||||
if (narg > 8) {
|
||||
cut_inner_one = utils::numeric(FLERR, arg[7], false, lmp);
|
||||
cut_outer_one = utils::numeric(FLERR, arg[8], false, lmp);
|
||||
}
|
||||
if (cut_inner_one>cut_outer_one)
|
||||
error->all(FLERR,"Pair inner cutoff >= Pair outer cutoff");
|
||||
double cut_angle_one = cut_angle_global;
|
||||
if (narg > 9) cut_angle_one = utils::numeric(FLERR, arg[9], false, lmp) * MY_PI/180.0;
|
||||
double angle_offset_one = angle_offset_global;
|
||||
if (narg == 11) angle_offset_one = (180.0 - utils::numeric(FLERR, arg[10], false, lmp)) * MY_PI/180.0;
|
||||
if (angle_offset_one < 0.0 || angle_offset_one > 90.0 * MY_PI/180.0)
|
||||
error->all(FLERR,"Illegal angle offset");
|
||||
|
||||
// grow params array if necessary
|
||||
|
||||
if (nparams == maxparam) {
|
||||
maxparam += CHUNK;
|
||||
params = (Param *) memory->srealloc(params, maxparam*sizeof(Param),
|
||||
"pair:params");
|
||||
|
||||
// make certain all addional allocated storage is initialized
|
||||
// to avoid false positives when checking with valgrind
|
||||
|
||||
memset(params + nparams, 0, CHUNK*sizeof(Param));
|
||||
}
|
||||
|
||||
params[nparams].epsilon = epsilon_one;
|
||||
params[nparams].sigma = sigma_one;
|
||||
params[nparams].ap = ap_one;
|
||||
params[nparams].cut_inner = cut_inner_one;
|
||||
params[nparams].cut_outer = cut_outer_one;
|
||||
params[nparams].cut_innersq = cut_inner_one*cut_inner_one;
|
||||
params[nparams].cut_outersq = cut_outer_one*cut_outer_one;
|
||||
params[nparams].cut_angle = cut_angle_one;
|
||||
params[nparams].angle_offset = angle_offset_one;
|
||||
params[nparams].denom_vdw =
|
||||
(params[nparams].cut_outersq-params[nparams].cut_innersq) *
|
||||
(params[nparams].cut_outersq-params[nparams].cut_innersq) *
|
||||
(params[nparams].cut_outersq-params[nparams].cut_innersq);
|
||||
|
||||
// flag type2param with either i,j = D,A or j,i = D,A
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++)
|
||||
for (int j = MAX(jlo,i); j <= jhi; j++)
|
||||
for (int k = klo; k <= khi; k++) {
|
||||
if (donor_flag == 0) type2param[i][j][k] = nparams;
|
||||
else type2param[j][i][k] = nparams;
|
||||
count++;
|
||||
}
|
||||
nparams++;
|
||||
|
||||
if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
|
||||
}
|
||||
38
src/EXTRA-MOLECULE/pair_hbond_dreiding_lj_angleoffset.h
Normal file
38
src/EXTRA-MOLECULE/pair_hbond_dreiding_lj_angleoffset.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
LAMMPS development team: developers@lammps.org
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef PAIR_CLASS
|
||||
// clang-format off
|
||||
PairStyle(hbond/dreiding/lj/angleoffset,PairHbondDreidingLJAngleoffset);
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
#ifndef LMP_PAIR_HBOND_DREIDING_LJ_ANGLEOFFSET_H
|
||||
#define LMP_PAIR_HBOND_DREIDING_LJ_ANGLEOFFSET_H
|
||||
|
||||
#include "pair_hbond_dreiding_lj.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PairHbondDreidingLJAngleoffset : public PairHbondDreidingLJ {
|
||||
|
||||
public:
|
||||
PairHbondDreidingLJAngleoffset(class LAMMPS *);
|
||||
void coeff(int, char **) override;
|
||||
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
129
src/EXTRA-MOLECULE/pair_hbond_dreiding_morse_angleoffset.cpp
Normal file
129
src/EXTRA-MOLECULE/pair_hbond_dreiding_morse_angleoffset.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
// clang-format off
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
LAMMPS development team: developers@lammps.org
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Tod A Pascal (Caltech), Don Xu/EiPi Fun
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "pair_hbond_dreiding_morse_angleoffset.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "atom_vec.h"
|
||||
#include "domain.h"
|
||||
#include "error.h"
|
||||
#include "force.h"
|
||||
#include "math_const.h"
|
||||
#include "math_special.h"
|
||||
#include "memory.h"
|
||||
#include "molecule.h"
|
||||
#include "neigh_list.h"
|
||||
#include "neighbor.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
static constexpr int CHUNK = 8;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairHbondDreidingMorseAngleoffset::PairHbondDreidingMorseAngleoffset(LAMMPS *lmp) :
|
||||
PairHbondDreidingMorse(lmp) {
|
||||
|
||||
angle_offset_flag = 1;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* set coeffs for one or more type pairs
|
||||
* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairHbondDreidingMorseAngleoffset::coeff(int narg, char **arg)
|
||||
{
|
||||
if (narg < 7 || narg > 12)
|
||||
error->all(FLERR,"Incorrect args for pair coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi,jlo,jhi,klo,khi;
|
||||
utils::bounds(FLERR, arg[0], 1, atom->ntypes, ilo, ihi, error);
|
||||
utils::bounds(FLERR, arg[1], 1, atom->ntypes, jlo, jhi, error);
|
||||
utils::bounds_typelabel(FLERR, arg[2], 1, atom->ntypes, klo, khi, lmp, Atom::ATOM);
|
||||
|
||||
int donor_flag;
|
||||
if (strcmp(arg[3],"i") == 0) donor_flag = 0;
|
||||
else if (strcmp(arg[3],"j") == 0) donor_flag = 1;
|
||||
else error->all(FLERR,"Incorrect args for pair coefficients");
|
||||
|
||||
double d0_one = utils::numeric(FLERR, arg[4], false, lmp);
|
||||
double alpha_one = utils::numeric(FLERR, arg[5], false, lmp);
|
||||
double r0_one = utils::numeric(FLERR, arg[6], false, lmp);
|
||||
|
||||
int ap_one = ap_global;
|
||||
if (narg > 7) ap_one = utils::inumeric(FLERR, arg[7], false, lmp);
|
||||
double cut_inner_one = cut_inner_global;
|
||||
double cut_outer_one = cut_outer_global;
|
||||
if (narg > 9) {
|
||||
cut_inner_one = utils::numeric(FLERR, arg[8], false, lmp);
|
||||
cut_outer_one = utils::numeric(FLERR, arg[9], false, lmp);
|
||||
}
|
||||
if (cut_inner_one>cut_outer_one)
|
||||
error->all(FLERR,"Pair inner cutoff >= Pair outer cutoff");
|
||||
double cut_angle_one = cut_angle_global;
|
||||
if (narg > 10) cut_angle_one = utils::numeric(FLERR, arg[10], false, lmp) * MY_PI/180.0;
|
||||
double angle_offset_one = angle_offset_global;
|
||||
if (narg == 12) angle_offset_one = (180.0 - utils::numeric(FLERR, arg[11], false, lmp)) * MY_PI/180.0;
|
||||
if (angle_offset_one < 0.0 || angle_offset_one > 90.0 * MY_PI/180.0)
|
||||
error->all(FLERR,"Illegal angle offset {}", angle_offset_one);
|
||||
|
||||
// grow params array if necessary
|
||||
|
||||
if (nparams == maxparam) {
|
||||
maxparam += CHUNK;
|
||||
params = (Param *) memory->srealloc(params, maxparam*sizeof(Param),"pair:params");
|
||||
|
||||
// make certain all addional allocated storage is initialized
|
||||
// to avoid false positives when checking with valgrind
|
||||
|
||||
memset(params + nparams, 0, CHUNK*sizeof(Param));
|
||||
}
|
||||
|
||||
params[nparams].d0 = d0_one;
|
||||
params[nparams].alpha = alpha_one;
|
||||
params[nparams].r0 = r0_one;
|
||||
params[nparams].ap = ap_one;
|
||||
params[nparams].cut_inner = cut_inner_one;
|
||||
params[nparams].cut_outer = cut_outer_one;
|
||||
params[nparams].cut_innersq = cut_inner_one*cut_inner_one;
|
||||
params[nparams].cut_outersq = cut_outer_one*cut_outer_one;
|
||||
params[nparams].cut_angle = cut_angle_one;
|
||||
params[nparams].angle_offset = angle_offset_one;
|
||||
params[nparams].denom_vdw = (params[nparams].cut_outersq-params[nparams].cut_innersq) *
|
||||
(params[nparams].cut_outersq-params[nparams].cut_innersq) *
|
||||
(params[nparams].cut_outersq-params[nparams].cut_innersq);
|
||||
|
||||
// flag type2param with either i,j = D,A or j,i = D,A
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++)
|
||||
for (int j = MAX(jlo,i); j <= jhi; j++)
|
||||
for (int k = klo; k <= khi; k++) {
|
||||
if (donor_flag == 0) type2param[i][j][k] = nparams;
|
||||
else type2param[j][i][k] = nparams;
|
||||
count++;
|
||||
}
|
||||
nparams++;
|
||||
|
||||
if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
|
||||
}
|
||||
38
src/EXTRA-MOLECULE/pair_hbond_dreiding_morse_angleoffset.h
Normal file
38
src/EXTRA-MOLECULE/pair_hbond_dreiding_morse_angleoffset.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
LAMMPS development team: developers@lammps.org
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef PAIR_CLASS
|
||||
// clang-format off
|
||||
PairStyle(hbond/dreiding/morse/angleoffset,PairHbondDreidingMorseAngleoffset);
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
#ifndef LMP_PAIR_HBOND_DREIDING_MORSE_ANGLEOFFSET_H
|
||||
#define LMP_PAIR_HBOND_DREIDING_MORSE_ANGLEOFFSET_H
|
||||
|
||||
#include "pair_hbond_dreiding_morse.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PairHbondDreidingMorseAngleoffset : public PairHbondDreidingMorse {
|
||||
|
||||
public:
|
||||
PairHbondDreidingMorseAngleoffset(class LAMMPS *);
|
||||
void coeff(int, char **) override;
|
||||
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
702
src/GRANULAR/fix_granular_mdr.cpp
Normal file
702
src/GRANULAR/fix_granular_mdr.cpp
Normal file
@ -0,0 +1,702 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
LAMMPS development team: developers@lammps.org
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing authors:
|
||||
William Zunker (MIT), Sachith Dunatunga (MIT),
|
||||
Dan Bolintineanu (SNL), Joel Clemmer (SNL)
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include "fix_granular_mdr.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "error.h"
|
||||
#include "fix_wall_gran_region.h"
|
||||
#include "fix_neigh_history.h"
|
||||
#include "force.h"
|
||||
#include "granular_model.h"
|
||||
#include "gran_sub_mod_normal.h"
|
||||
#include "input.h"
|
||||
#include "math_const.h"
|
||||
#include "memory.h"
|
||||
#include "modify.h"
|
||||
#include "neigh_list.h"
|
||||
#include "pair.h"
|
||||
#include "pair_granular.h"
|
||||
#include "region.h"
|
||||
#include "update.h"
|
||||
#include "variable.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace Granular_NS;
|
||||
using namespace Granular_MDR_NS;
|
||||
using namespace FixConst;
|
||||
using MathConst::MY_PI;
|
||||
|
||||
static constexpr double EPSILON = 1e-16;
|
||||
static constexpr double OVERLAP_LIMIT = 0.75;
|
||||
|
||||
enum {COMM_1, COMM_2};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FixGranularMDR::FixGranularMDR(LAMMPS *lmp, int narg, char **arg) :
|
||||
Fix(lmp, narg, arg)
|
||||
{
|
||||
comm_forward = 5;
|
||||
create_attribute = 1;
|
||||
|
||||
id_fix = nullptr;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FixGranularMDR::~FixGranularMDR()
|
||||
{
|
||||
if (id_fix && modify->nfix)
|
||||
modify->delete_fix(id_fix);
|
||||
delete[] id_fix;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int FixGranularMDR::setmask()
|
||||
{
|
||||
int mask = 0;
|
||||
mask |= PRE_FORCE;
|
||||
return mask;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixGranularMDR::post_constructor()
|
||||
{
|
||||
int tmp1, tmp2;
|
||||
id_fix = utils::strdup("MDR_PARTICLE_HISTORY_VARIABLES");
|
||||
modify->add_fix(fmt::format("{} all property/atom d_Ro d_Vcaps d_Vgeo d_Velas d_eps_bar d_dRnumerator d_dRdenominator d_Acon0 d_Acon1 d_Atot d_Atot_sum d_ddelta_bar d_psi d_history_setup_flag d_sigmaxx d_sigmayy d_sigmazz ghost yes", id_fix));
|
||||
|
||||
index_Ro = atom->find_custom("Ro", tmp1, tmp2);
|
||||
index_Vcaps = atom->find_custom("Vcaps", tmp1, tmp2);
|
||||
index_Vgeo = atom->find_custom("Vgeo", tmp1, tmp2);
|
||||
index_Velas = atom->find_custom("Velas", tmp1, tmp2);
|
||||
index_eps_bar = atom->find_custom("eps_bar", tmp1, tmp2);
|
||||
index_dRnumerator = atom->find_custom("dRnumerator", tmp1, tmp2);
|
||||
index_dRdenominator = atom->find_custom("dRdenominator", tmp1, tmp2);
|
||||
index_Acon0 = atom->find_custom("Acon0", tmp1, tmp2);
|
||||
index_Acon1 = atom->find_custom("Acon1", tmp1, tmp2);
|
||||
index_Atot = atom->find_custom("Atot", tmp1, tmp2);
|
||||
index_Atot_sum = atom->find_custom("Atot_sum", tmp1, tmp2);
|
||||
index_ddelta_bar = atom->find_custom("ddelta_bar", tmp1, tmp2);
|
||||
index_psi = atom->find_custom("psi", tmp1, tmp2);
|
||||
index_history_setup_flag = atom->find_custom("history_setup_flag", tmp1, tmp2);
|
||||
index_sigmaxx = atom->find_custom("sigmaxx", tmp1, tmp2);
|
||||
index_sigmayy = atom->find_custom("sigmayy", tmp1, tmp2);
|
||||
index_sigmazz = atom->find_custom("sigmazz", tmp1, tmp2);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixGranularMDR::setup_pre_force(int /*vflag*/)
|
||||
{
|
||||
pair = dynamic_cast<PairGranular *>(force->pair_match("granular", 1));
|
||||
if (pair == nullptr)
|
||||
error->all(FLERR, "Must use pair granular with MDR model");
|
||||
|
||||
if (force->newton)
|
||||
error->all(FLERR, "MDR contact model requires Newton off");
|
||||
|
||||
// Confirm all MDR models are consistent
|
||||
|
||||
class GranularModel *pair_model, *fix_model;
|
||||
class GranularModel **models_list = pair->models_list;
|
||||
class GranSubModNormalMDR *norm_model = nullptr;
|
||||
for (int i = 0; i < pair->nmodels; i++) {
|
||||
pair_model = models_list[i];
|
||||
if (pair_model->normal_model->name == "mdr") {
|
||||
if (norm_model != nullptr)
|
||||
error->all(FLERR, "Cannot currently define multiple MDR normal models in the pairstyle");
|
||||
norm_model = dynamic_cast<GranSubModNormalMDR *>(pair_model->normal_model);
|
||||
} else {
|
||||
error->all(FLERR, "Cannot combine MDR normal model with a different normal model in the pairstyle");
|
||||
}
|
||||
}
|
||||
|
||||
if (norm_model == nullptr)
|
||||
error->all(FLERR, "Must specify MDR normal model with pair granular");
|
||||
psi_b_coeff = norm_model->psi_b;
|
||||
|
||||
fix_wall_list = modify->get_fix_by_style("wall/gran/region");
|
||||
class GranSubModNormalMDR *norm_model2;
|
||||
class FixWallGranRegion *fix;
|
||||
for (int i = 0; i < fix_wall_list.size(); i++) {
|
||||
if (!utils::strmatch(fix_wall_list[i]->style, "wall/gran/region"))
|
||||
error->all(FLERR, "MDR model currently only supports fix wall/gran/region, not fix wall/gran");
|
||||
|
||||
fix = dynamic_cast<FixWallGranRegion*>(fix_wall_list[i]);
|
||||
if (fix->model->normal_model->name != "mdr")
|
||||
error->all(FLERR, "Fix wall/gran/region must use an MDR normal model when using an MDR pair model");
|
||||
|
||||
norm_model2 = dynamic_cast<GranSubModNormalMDR *>(fix->model->normal_model);
|
||||
|
||||
if (norm_model->E != norm_model2->E)
|
||||
error->all(FLERR, "Young's modulus in pair style, {}, does not agree with value {} in fix gran/wall/region",
|
||||
norm_model->E, norm_model2->E);
|
||||
if (norm_model->nu != norm_model2->nu)
|
||||
error->all(FLERR, "Poisson's ratio in pair style, {}, does not agree with value {} in fix gran/wall/region",
|
||||
norm_model->nu, norm_model2->nu);
|
||||
if (norm_model->Y != norm_model2->Y)
|
||||
error->all(FLERR, "Yield stress in pair style, {}, does not agree with value {} in fix gran/wall/region",
|
||||
norm_model->Y, norm_model2->Y);
|
||||
if (norm_model->psi_b != norm_model2->psi_b)
|
||||
error->all(FLERR, "Bulk response trigger in pair style, {}, does not agree with value {} in fix gran/wall/region",
|
||||
norm_model->psi_b, norm_model2->psi_b);
|
||||
if (norm_model->CoR != norm_model2->CoR)
|
||||
error->all(FLERR, "Coefficient of restitution in pair style, {}, does not agree with value {} in fix gran/wall/region",
|
||||
norm_model->CoR, norm_model2->CoR);
|
||||
}
|
||||
|
||||
fix_history = dynamic_cast<FixNeighHistory *>(modify->get_fix_by_id("NEIGH_HISTORY_GRANULAR"));
|
||||
|
||||
pre_force(0);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixGranularMDR::pre_force(int)
|
||||
{
|
||||
double *radius = atom->radius;
|
||||
double *Ro = atom->dvector[index_Ro];
|
||||
double *Vgeo = atom->dvector[index_Vgeo];
|
||||
double *Velas = atom->dvector[index_Velas];
|
||||
double *Vcaps = atom->dvector[index_Vcaps];
|
||||
double *eps_bar = atom->dvector[index_eps_bar];
|
||||
double *dRnumerator = atom->dvector[index_dRnumerator];
|
||||
double *dRdenominator = atom->dvector[index_dRdenominator];
|
||||
double *Acon0 = atom->dvector[index_Acon0];
|
||||
double *Acon1 = atom->dvector[index_Acon1];
|
||||
double *Atot = atom->dvector[index_Atot];
|
||||
double *Atot_sum = atom->dvector[index_Atot_sum];
|
||||
double *psi = atom->dvector[index_psi];
|
||||
double *ddelta_bar = atom->dvector[index_ddelta_bar];
|
||||
double *sigmaxx = atom->dvector[index_sigmaxx];
|
||||
double *sigmayy = atom->dvector[index_sigmayy];
|
||||
double *sigmazz = atom->dvector[index_sigmazz];
|
||||
double *history_setup_flag = atom->dvector[index_history_setup_flag];
|
||||
|
||||
int new_atom;
|
||||
int nlocal = atom->nlocal;
|
||||
int ntotal = nlocal + atom->nghost;
|
||||
for (int i = 0; i < ntotal; i++) {
|
||||
// initialize new atoms
|
||||
new_atom = 0;
|
||||
if (history_setup_flag[i] < EPSILON) {
|
||||
Ro[i] = radius[i];
|
||||
Acon0[i] = 0.0;
|
||||
Acon1[i] = 0.0;
|
||||
Vcaps[i] = 0.0;
|
||||
eps_bar[i] = 0.0;
|
||||
dRnumerator[i] = 0.0;
|
||||
dRdenominator[i] = 0.0;
|
||||
Atot_sum[i] = 0.0;
|
||||
ddelta_bar[i] = 0.0;
|
||||
sigmaxx[i] = 0.0;
|
||||
sigmayy[i] = 0.0;
|
||||
sigmazz[i] = 0.0;
|
||||
history_setup_flag[i] = 1.0;
|
||||
new_atom = 1;
|
||||
}
|
||||
|
||||
// update apparent radius
|
||||
|
||||
// will forward to ghosts
|
||||
if (i >= nlocal) continue;
|
||||
|
||||
// only update outside of setup (unless a new atom)
|
||||
if (update->setupflag && (!new_atom)) continue;
|
||||
|
||||
const double R = radius[i];
|
||||
const double Vo = 4.0 / 3.0 * MY_PI * pow(Ro[i], 3.0);
|
||||
const double Vgeoi = 4.0 / 3.0 * MY_PI * pow(R, 3.0) - Vcaps[i];
|
||||
|
||||
Vgeo[i] = MIN(Vgeoi, Vo);
|
||||
Velas[i] = Vo * (1.0 + eps_bar[i]);
|
||||
Atot[i] = 4.0 * MY_PI * pow(R, 2.0) + Atot_sum[i];
|
||||
psi[i] = (Atot[i] - Acon1[i]) / Atot[i];
|
||||
|
||||
if (psi_b_coeff < psi[i]) {
|
||||
const double dR = MAX(dRnumerator[i] / (dRdenominator[i] - 4.0 * MY_PI * pow(R, 2.0)), 0.0);
|
||||
if ((radius[i] + dR) < (1.5 * Ro[i]))
|
||||
radius[i] += dR;
|
||||
}
|
||||
Acon0[i] = Acon1[i];
|
||||
}
|
||||
|
||||
comm_stage = COMM_1;
|
||||
comm->forward_comm(this, 5);
|
||||
|
||||
// rezero temporary variables for all atoms, no need to communicate
|
||||
for (int i = 0; i < ntotal; i++) {
|
||||
ddelta_bar[i] = 0.0;
|
||||
if (!update->setupflag) {
|
||||
Vcaps[i] = 0.0;
|
||||
eps_bar[i] = 0.0;
|
||||
dRnumerator[i] = 0.0;
|
||||
dRdenominator[i] = 0.0;
|
||||
Acon1[i] = 0.0;
|
||||
Atot_sum[i] = 0.0;
|
||||
sigmaxx[i] = 0.0;
|
||||
sigmayy[i] = 0.0;
|
||||
sigmazz[i] = 0.0;
|
||||
}
|
||||
}
|
||||
if (!update->setupflag) {
|
||||
calculate_contact_penalty();
|
||||
mean_surf_disp();
|
||||
update_fix_gran_wall();
|
||||
}
|
||||
|
||||
comm_stage = COMM_2;
|
||||
comm->forward_comm(this, 1);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int FixGranularMDR::pack_forward_comm(int n, int *list, double *buf, int /*pbc_flag*/,int * /*pbc*/)
|
||||
{
|
||||
double **dvector = atom->dvector;
|
||||
int m = 0;
|
||||
if (comm_stage == COMM_1) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
int j = list[i];
|
||||
buf[m++] = dvector[index_Vgeo][j]; // 2
|
||||
buf[m++] = dvector[index_Velas][j]; // 3
|
||||
buf[m++] = dvector[index_Acon0][j]; // 8
|
||||
buf[m++] = dvector[index_Atot][j]; // 10
|
||||
buf[m++] = dvector[index_psi][j]; // 13
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < n; i++) {
|
||||
int j = list[i];
|
||||
buf[m++] = dvector[index_ddelta_bar][j];
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixGranularMDR::unpack_forward_comm(int n, int first, double *buf)
|
||||
{
|
||||
double **dvector = atom->dvector;
|
||||
int m = 0;
|
||||
int last = first + n;
|
||||
|
||||
if (comm_stage == COMM_1) {
|
||||
for (int i = first; i < last; i++) {
|
||||
dvector[index_Vgeo][i] = buf[m++]; // 2
|
||||
dvector[index_Velas][i] = buf[m++]; // 3
|
||||
dvector[index_Acon0][i] = buf[m++]; // 8
|
||||
dvector[index_Atot][i] = buf[m++]; // 10
|
||||
dvector[index_psi][i] = buf[m++]; // 13
|
||||
}
|
||||
} else {
|
||||
for (int i = first; i < last; i++) {
|
||||
dvector[index_ddelta_bar][i] = buf[m++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
initialize setup flag to zero, called when atom is created
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void FixGranularMDR::set_arrays(int i)
|
||||
{
|
||||
atom->dvector[index_history_setup_flag][i] = 0.0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Screen for non-physical contacts occuring through obstructing particles.
|
||||
Assign non-zero penalties to these contacts to adjust force evaluation.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void FixGranularMDR::calculate_contact_penalty()
|
||||
{
|
||||
NeighList * list = pair->list;
|
||||
const int size_history = pair->get_size_history();
|
||||
|
||||
int i, j, k, lv1, ii, jj, inum, jnum;
|
||||
|
||||
int *ilist, *jlist, *numneigh, **firstneigh;
|
||||
int *touch, **firsttouch;
|
||||
double *history, *history_ij, *history_ik, *history_jk, *history_kj;
|
||||
double *allhistory, *allhistory_j, *allhistory_k, **firsthistory;
|
||||
|
||||
bool touchflag = false;
|
||||
|
||||
double **x = atom->x;
|
||||
double *radius = atom->radius;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
inum = list->inum;
|
||||
ilist = list->ilist;
|
||||
numneigh = list->numneigh;
|
||||
firstneigh = list->firstneigh;
|
||||
firsttouch = fix_history->firstflag;
|
||||
firsthistory = fix_history->firstvalue;
|
||||
|
||||
// zero existing penalties
|
||||
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
allhistory = firsthistory[i];
|
||||
jnum = numneigh[i];
|
||||
for (jj = 0; jj < jnum; jj++)
|
||||
(&allhistory[size_history * jj])[PENALTY] = 0.0;
|
||||
}
|
||||
|
||||
// contact penalty calculation
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
const double xtmp = x[i][0];
|
||||
const double ytmp = x[i][1];
|
||||
const double ztmp = x[i][2];
|
||||
allhistory = firsthistory[i];
|
||||
double radi = radius[i];
|
||||
jlist = firstneigh[i];
|
||||
jnum = numneigh[i];
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
j = jlist[jj];
|
||||
j &= NEIGHMASK;
|
||||
|
||||
double radj = radius[j];
|
||||
const double delx_ij = x[j][0] - xtmp;
|
||||
const double dely_ij = x[j][1] - ytmp;
|
||||
const double delz_ij = x[j][2] - ztmp;
|
||||
const double rsq_ij = delx_ij * delx_ij + dely_ij * dely_ij + delz_ij * delz_ij;
|
||||
const double r_ij = sqrt(rsq_ij);
|
||||
const double rinv_ij = 1.0 / r_ij;
|
||||
const double radsum_ij = radi + radj;
|
||||
const double deltan_ij = radsum_ij - r_ij;
|
||||
if (deltan_ij < 0.0) continue;
|
||||
for (int kk = jj + 1; kk < jnum; kk++) {
|
||||
k = jlist[kk];
|
||||
k &= NEIGHMASK;
|
||||
|
||||
const double delx_ik = x[k][0] - xtmp;
|
||||
const double dely_ik = x[k][1] - ytmp;
|
||||
const double delz_ik = x[k][2] - ztmp;
|
||||
const double rsq_ik = delx_ik * delx_ik + dely_ik * dely_ik + delz_ik *delz_ik;
|
||||
const double r_ik = sqrt(rsq_ik);
|
||||
const double rinv_ik = 1.0 / r_ik;
|
||||
const double radk = radius[k];
|
||||
const double radsum_ik = radi + radk;
|
||||
const double deltan_ik = radsum_ik - r_ik;
|
||||
|
||||
if (deltan_ik < 0.0) continue;
|
||||
|
||||
const double delx_jk = x[k][0] - x[j][0];
|
||||
const double dely_jk = x[k][1] - x[j][1];
|
||||
const double delz_jk = x[k][2] - x[j][2];
|
||||
const double rsq_jk = delx_jk * delx_jk + dely_jk * dely_jk + delz_jk *delz_jk;
|
||||
const double r_jk = sqrt(rsq_jk);
|
||||
const double rinv_jk = 1.0 / r_jk;
|
||||
const double radsum_jk = radj + radk;
|
||||
const double deltan_jk = radsum_jk - r_jk;
|
||||
|
||||
if (deltan_jk < 0.0) continue;
|
||||
|
||||
// pull ij history
|
||||
history_ij = &allhistory[size_history * jj];
|
||||
double * pij = &history_ij[PENALTY]; // penalty for contact i and j
|
||||
|
||||
// pull ik history
|
||||
history_ik = &allhistory[size_history * kk];
|
||||
double * pik = &history_ik[PENALTY]; // penalty for contact i and k
|
||||
|
||||
// Find pair of atoms with the smallest overlap, atoms a & b, 3rd atom c is central
|
||||
// if a & b are both local:
|
||||
// calculate ab penalty and add to the pab[0] history entry
|
||||
// if a is local & b is ghost or vice versa:
|
||||
// each processor has a-b in nlist and independently calculates + adds penalty
|
||||
// if a & b are both ghosts:
|
||||
// skip calculation since it's performed on other proc
|
||||
// This process requires newton off, or nlist may not include ab, ac, & bc
|
||||
|
||||
const double r_max = MAX(r_ij, MAX(r_ik, r_jk));
|
||||
if (r_ij == r_max) { // the central particle is k
|
||||
const double enx_ki = -delx_ik * rinv_ik;
|
||||
const double eny_ki = -dely_ik * rinv_ik;
|
||||
const double enz_ki = -delz_ik * rinv_ik;
|
||||
const double enx_kj = -delx_jk * rinv_jk;
|
||||
const double eny_kj = -dely_jk * rinv_jk;
|
||||
const double enz_kj = -delz_jk * rinv_jk;
|
||||
const double alpha = std::acos(enx_ki * enx_kj + eny_ki * eny_kj + enz_ki * enz_kj);
|
||||
pij[0] += 1.0 / (1.0 + std::exp(-50.0 * (alpha / MY_PI - 0.5)));
|
||||
} else if (r_ik == r_max) { // the central particle is j
|
||||
const double enx_ji = -delx_ij * rinv_ij;
|
||||
const double eny_ji = -dely_ij * rinv_ij;
|
||||
const double enz_ji = -delz_ij * rinv_ij;
|
||||
const double enx_jk = delx_jk * rinv_jk;
|
||||
const double eny_jk = dely_jk * rinv_jk;
|
||||
const double enz_jk = delz_jk * rinv_jk;
|
||||
const double alpha = std::acos(enx_ji * enx_jk + eny_ji * eny_jk + enz_ji * enz_jk);
|
||||
pik[0] += 1.0 / (1.0 + std::exp(-50.0 * (alpha / MY_PI - 0.5)));
|
||||
} else { // the central particle is i
|
||||
if (j < atom->nlocal || k < atom->nlocal) {
|
||||
const double enx_ij = delx_ij * rinv_ij;
|
||||
const double eny_ij = dely_ij * rinv_ij;
|
||||
const double enz_ij = delz_ij * rinv_ij;
|
||||
const double enx_ik = delx_ik * rinv_ik;
|
||||
const double eny_ik = dely_ik * rinv_ik;
|
||||
const double enz_ik = delz_ik * rinv_ik;
|
||||
const double alpha = std::acos(enx_ij * enx_ik + eny_ij * eny_ik + enz_ij * enz_ik);
|
||||
|
||||
// don't know who owns the contact, k may be in j's nlist or vice versa
|
||||
// need to search both to find owner
|
||||
double * pjk = nullptr;
|
||||
if (j < atom->nlocal) {
|
||||
int * const jklist = firstneigh[j];
|
||||
const int jknum = numneigh[j];
|
||||
for (int jk = 0; jk < jknum; jk++) {
|
||||
const int kneigh = jklist[jk] & NEIGHMASK;
|
||||
if (k == kneigh) {
|
||||
allhistory_j = firsthistory[j];
|
||||
history_jk = &allhistory_j[size_history * jk];
|
||||
pjk = &history_jk[PENALTY]; // penalty for contact j and k
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if j is in the neighbor list of k
|
||||
if (pjk == nullptr && k < atom->nlocal) {
|
||||
int * const kjlist = firstneigh[k];
|
||||
const int kjnum = numneigh[k];
|
||||
for (int kj = 0; kj < kjnum; kj++) {
|
||||
const int jneigh = kjlist[kj] & NEIGHMASK;
|
||||
if (j == jneigh) {
|
||||
allhistory_k = firsthistory[k];
|
||||
history_kj = &allhistory_k[size_history * kj];
|
||||
pjk = &history_kj[PENALTY]; // penalty for contact j and k
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pjk == nullptr)
|
||||
error->one(FLERR, "Contact between a pair of particles was detected by the MDR model, however it is not reflected in the neighbor lists. To solve this issue either build the neighbor lists more frequently or increase their size (e.g. increase the skin distance).");
|
||||
|
||||
pjk[0] += 1.0 / (1.0 + std::exp(-50.0 * (alpha / MY_PI - 0.5)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Calculate mean surface displacement increment for each particle
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void FixGranularMDR::mean_surf_disp()
|
||||
{
|
||||
NeighList * list = pair->list;
|
||||
|
||||
const int size_history = pair->get_size_history();
|
||||
int i, j, k, ii, jj, inum, jnum, itype, jtype;
|
||||
int *ilist, *jlist, *numneigh, **firstneigh;
|
||||
int *touch, **firsttouch;
|
||||
double *history, *allhistory, **firsthistory;
|
||||
|
||||
bool touchflag = false;
|
||||
class GranularModel* model;
|
||||
class GranularModel** models_list = pair->models_list;
|
||||
int ** types_indices = pair->types_indices;
|
||||
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
double *radius = atom->radius;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
double *Acon0 = atom->dvector[index_Acon0];
|
||||
double *ddelta_bar = atom->dvector[index_ddelta_bar];
|
||||
|
||||
inum = list->inum;
|
||||
ilist = list->ilist;
|
||||
numneigh = list->numneigh;
|
||||
firstneigh = list->firstneigh;
|
||||
firsttouch = fix_history->firstflag;
|
||||
firsthistory = fix_history->firstvalue;
|
||||
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
itype = type[i];
|
||||
touch = firsttouch[i];
|
||||
allhistory = firsthistory[i];
|
||||
jlist = firstneigh[i];
|
||||
jnum = numneigh[i];
|
||||
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
j = jlist[jj];
|
||||
j &= NEIGHMASK;
|
||||
|
||||
jtype = type[j];
|
||||
model = models_list[types_indices[itype][jtype]];
|
||||
|
||||
// Reset model and copy initial geometric data
|
||||
model->xi = x[i];
|
||||
model->xj = x[j];
|
||||
model->radi = radius[i];
|
||||
model->radj = radius[j];
|
||||
model->i = i;
|
||||
model->j = j;
|
||||
model->touch = touch[jj];
|
||||
touchflag = model->check_contact();
|
||||
|
||||
// is it necessary to clear the history here???
|
||||
if (!touchflag) {
|
||||
touch[jj] = 0;
|
||||
history = &allhistory[size_history * jj];
|
||||
for (k = 0; k < size_history; k++) history[k] = 0.0;
|
||||
continue;
|
||||
}
|
||||
|
||||
touch[jj] = 1;
|
||||
|
||||
history = &allhistory[size_history * jj];
|
||||
model->history = history;
|
||||
|
||||
const double delta = model->radsum - sqrt(model->rsq);
|
||||
|
||||
double deltamax = history[DELTA_MAX];
|
||||
double deltap0 = history[DELTAP_0];
|
||||
double deltap1 = history[DELTAP_1];
|
||||
|
||||
if (delta > deltamax) deltamax = delta;
|
||||
|
||||
double delta0old = history[DELTA_0];
|
||||
double delta1old = history[DELTA_1];
|
||||
|
||||
int i0;
|
||||
int i1;
|
||||
if (atom->tag[i] > atom->tag[j]) {
|
||||
i0 = i;
|
||||
i1 = j;
|
||||
} else {
|
||||
i0 = j;
|
||||
i1 = i;
|
||||
}
|
||||
|
||||
double R0 = radius[i0];
|
||||
double R1 = radius[i1];
|
||||
|
||||
double delta_geo0;
|
||||
double delta_geo1;
|
||||
double deltaOpt1 = deltamax * (deltamax - 2.0 * R1) / (2.0 * (deltamax - R0 - R1));
|
||||
double deltaOpt2 = deltamax * (deltamax - 2.0 * R0) / (2.0 * (deltamax - R0 - R1));
|
||||
(R0 < R1) ? delta_geo0 = MAX(deltaOpt1, deltaOpt2) : delta_geo0 = MIN(deltaOpt1, deltaOpt2);
|
||||
(R0 < R1) ? delta_geo1 = MIN(deltaOpt1, deltaOpt2) : delta_geo1 = MAX(deltaOpt1, deltaOpt2);
|
||||
|
||||
if (delta_geo0 / R0 > OVERLAP_LIMIT) {
|
||||
delta_geo0 = R0 * OVERLAP_LIMIT;
|
||||
delta_geo1 = deltamax - delta_geo0;
|
||||
} else if (delta_geo1 / R1 > OVERLAP_LIMIT) {
|
||||
delta_geo1 = R1 * OVERLAP_LIMIT;
|
||||
delta_geo0 = deltamax - delta_geo1;
|
||||
}
|
||||
|
||||
double deltap = deltap0 + deltap1;
|
||||
|
||||
double delta0 = delta_geo0 + (deltap0 - delta_geo0) / (deltap - deltamax) * (delta - deltamax);
|
||||
double delta1 = delta_geo1 + (deltap1 - delta_geo1) / (deltap - deltamax) * (delta - deltamax);
|
||||
|
||||
double ddel0 = delta0 - delta0old;
|
||||
double ddel1 = delta1 - delta1old;
|
||||
|
||||
if (Acon0[i0] != 0.0) {
|
||||
const double Ac_offset0 = history[AC_0];
|
||||
ddelta_bar[i0] += Ac_offset0 / Acon0[i0] * ddel0;
|
||||
}
|
||||
|
||||
if (Acon0[i1] != 0.0) {
|
||||
const double Ac_offset1 = history[AC_1];
|
||||
ddelta_bar[i1] += Ac_offset1 / Acon0[i1] * ddel1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Update instance of fix gran/wall
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void FixGranularMDR::update_fix_gran_wall()
|
||||
{
|
||||
int i, m, nc, iwall;
|
||||
|
||||
double **x = atom->x;
|
||||
double *radius = atom->radius;
|
||||
int *mask = atom->mask;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
double *Acon0 = atom->dvector[index_Acon0];
|
||||
double *ddelta_bar = atom->dvector[index_ddelta_bar];
|
||||
|
||||
for (int w = 0; w < fix_wall_list.size(); w++) {
|
||||
FixWallGranRegion *fix = dynamic_cast<FixWallGranRegion*>(fix_wall_list[w]);
|
||||
GranularModel *model = fix->model;
|
||||
const int size_history = model->size_history;
|
||||
Region *region = fix->region;
|
||||
|
||||
if (region->dynamic_check())
|
||||
region->prematch();
|
||||
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
if (!(mask[i] & groupbit)) continue;
|
||||
if (! region->match(x[i][0], x[i][1], x[i][2])) continue;
|
||||
|
||||
nc = region->surface(x[i][0], x[i][1], x[i][2], radius[i] + model->pulloff_distance(radius[i], 0.0));
|
||||
|
||||
if (nc == 0) {
|
||||
fix->ncontact[i] = 0;
|
||||
continue;
|
||||
}
|
||||
if (nc == 1) {
|
||||
fix->c2r[0] = 0;
|
||||
iwall = region->contact[0].iwall;
|
||||
if (fix->ncontact[i] == 0) {
|
||||
fix->ncontact[i] = 1;
|
||||
fix->walls[i][0] = iwall;
|
||||
for (m = 0; m < size_history; m++) fix->history_many[i][0] [m] = 0.0;
|
||||
} else if (fix->ncontact[i] > 1 || iwall != fix->walls[i][0])
|
||||
fix->update_contacts(i, nc);
|
||||
} else
|
||||
fix->update_contacts(i, nc);
|
||||
|
||||
// process current contacts
|
||||
for (int ic = 0; ic < nc; ic++) {
|
||||
const double wij = 1.0;
|
||||
if (Acon0[i] != 0.0) {
|
||||
const double delta = radius[i] - region->contact[ic].r;
|
||||
const double delta_offset0 = fix->history_many[i][fix->c2r[ic]][0];
|
||||
const double ddelta = delta - delta_offset0;
|
||||
const double Ac_offset0 = fix->history_many[i][fix->c2r[ic]][18];
|
||||
ddelta_bar[i] += wij * Ac_offset0 / Acon0[i] * ddelta;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
107
src/GRANULAR/fix_granular_mdr.h
Normal file
107
src/GRANULAR/fix_granular_mdr.h
Normal file
@ -0,0 +1,107 @@
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
LAMMPS development team: developers@lammps.org
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef FIX_CLASS
|
||||
// clang-format off
|
||||
FixStyle(GRANULAR/MDR,FixGranularMDR);
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
#ifndef LMP_FIX_GRANULAR_MDR_H
|
||||
#define LMP_FIX_GRANULAR_MDR_H
|
||||
|
||||
#include "fix.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
namespace Granular_MDR_NS {
|
||||
|
||||
enum HistoryIndex {
|
||||
DELTA_0 = 0, // apparent overlap
|
||||
DELTA_1,
|
||||
DELTAO_0, // displacement
|
||||
DELTAO_1,
|
||||
DELTA_MDR_0, // MDR apparent overlap
|
||||
DELTA_MDR_1,
|
||||
DELTA_BULK_0, // bulk displacement
|
||||
DELTA_BULK_1,
|
||||
DELTAMAX_MDR_0, // maximum MDR apparent overlap
|
||||
DELTAMAX_MDR_1,
|
||||
YFLAG_0, // yield flag
|
||||
YFLAG_1,
|
||||
DELTAY_0, // yield displacement
|
||||
DELTAY_1,
|
||||
CA_0, // contact area intercept
|
||||
CA_1,
|
||||
AADH_0, // adhesive contact radius
|
||||
AADH_1,
|
||||
AC_0, // contact area
|
||||
AC_1,
|
||||
EPS_BAR_0, // volume-averaged infinitesimal sor
|
||||
EPS_BAR_1,
|
||||
PENALTY, // contact penalty
|
||||
DELTA_MAX,
|
||||
DELTAP_0,
|
||||
DELTAP_1
|
||||
};
|
||||
|
||||
} // namespace Granular_MDR_NS
|
||||
|
||||
class FixGranularMDR : public Fix {
|
||||
public:
|
||||
FixGranularMDR(class LAMMPS *, int, char **);
|
||||
~FixGranularMDR() override;
|
||||
int setmask() override;
|
||||
void post_constructor() override;
|
||||
void setup_pre_force(int) override;
|
||||
void pre_force(int) override;
|
||||
int pack_forward_comm(int, int *, double *, int, int *) override;
|
||||
void unpack_forward_comm(int, int, double *) override;
|
||||
void set_arrays(int) override;
|
||||
|
||||
private:
|
||||
int comm_stage;
|
||||
char *id_fix;
|
||||
double psi_b_coeff;
|
||||
class PairGranular *pair;
|
||||
class FixNeighHistory *fix_history;
|
||||
std::vector<Fix *> fix_wall_list;
|
||||
|
||||
void mean_surf_disp();
|
||||
void calculate_contact_penalty();
|
||||
void update_fix_gran_wall();
|
||||
|
||||
int index_Ro; // initial radius
|
||||
int index_Vgeo; // geometric particle volume of apparent particle afterremoving spherical cap volume
|
||||
int index_Velas; // particle volume from linear elasticity
|
||||
int index_Vcaps; // spherical cap volume from intersection of apparentradius particle and contact planes
|
||||
int index_eps_bar; // volume-averaged infinitesimal strain tensor
|
||||
int index_dRnumerator; // summation of numerator terms in calculation of dR
|
||||
int index_dRdenominator; // summation of denominator terms in calculation of dR
|
||||
int index_Acon0; // total area involved in contacts: Acon^{n}
|
||||
int index_Acon1; // total area involved in contacts: Acon^{n+1}
|
||||
int index_Atot; // total particle area
|
||||
int index_Atot_sum; // running sum of contact area minus cap area
|
||||
int index_ddelta_bar; // change in mean surface displacement
|
||||
int index_psi; // ratio of free surface area to total surface area
|
||||
int index_sigmaxx; // xx-component of the stress tensor, not necessary forforce calculation
|
||||
int index_sigmayy; // yy-component of the stress tensor, not necessary forforce calculation
|
||||
int index_sigmazz; // zz-component of the stress tensor, not necessary forforce calculation
|
||||
int index_history_setup_flag; // flag to check if history variables have beeninitialized
|
||||
int index_contacts; // total contacts on particle
|
||||
int index_adhesive_length; // total length of adhesive contact on a particle
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@ -200,7 +200,7 @@ FixWallGran::FixWallGran(LAMMPS *lmp, int narg, char **arg) :
|
||||
iarg += 3;
|
||||
} else if (strcmp(arg[iarg],"contacts") == 0) {
|
||||
peratom_flag = 1;
|
||||
size_peratom_cols = 8;
|
||||
size_peratom_cols = 8 + model->nsvector;
|
||||
peratom_freq = 1;
|
||||
iarg += 1;
|
||||
} else if (strcmp(arg[iarg],"temperature") == 0) {
|
||||
@ -365,7 +365,7 @@ void FixWallGran::setup(int vflag)
|
||||
|
||||
void FixWallGran::post_force(int /*vflag*/)
|
||||
{
|
||||
int i,j;
|
||||
int i,j,n;
|
||||
double dx,dy,dz,del1,del2,delxy,delr,rwall,meff;
|
||||
double *forces, *torquesi;
|
||||
double vwall[3];
|
||||
@ -437,7 +437,9 @@ void FixWallGran::post_force(int /*vflag*/)
|
||||
|
||||
rwall = 0.0;
|
||||
|
||||
model->calculate_svector = 0;
|
||||
if (peratom_flag) {
|
||||
model->calculate_svector = 1;
|
||||
clear_stored_contacts();
|
||||
}
|
||||
|
||||
@ -546,6 +548,9 @@ void FixWallGran::post_force(int /*vflag*/)
|
||||
array_atom[i][5] = x[i][1] - dy;
|
||||
array_atom[i][6] = x[i][2] - dz;
|
||||
array_atom[i][7] = radius[i];
|
||||
|
||||
for (n = 0; n < model->nsvector; n++)
|
||||
array_atom[i][8 + n] = model->svector[n];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,14 +50,14 @@ class FixWallGran : public Fix {
|
||||
int maxsize_restart() override;
|
||||
void reset_dt() override;
|
||||
|
||||
// for granular model choices
|
||||
class Granular_NS::GranularModel *model;
|
||||
|
||||
protected:
|
||||
int wallstyle, wiggle, wshear, axis;
|
||||
int nlevels_respa;
|
||||
bigint time_origin;
|
||||
|
||||
// for granular model choices
|
||||
class Granular_NS::GranularModel *model;
|
||||
|
||||
double lo, hi, cylradius;
|
||||
double amplitude, period, omega, vshear;
|
||||
double dt;
|
||||
@ -84,7 +84,7 @@ class FixWallGran : public Fix {
|
||||
|
||||
// store particle interactions
|
||||
|
||||
int store;
|
||||
int nsvector;
|
||||
|
||||
void clear_stored_contacts();
|
||||
};
|
||||
|
||||
@ -118,7 +118,7 @@ void FixWallGranRegion::init()
|
||||
|
||||
void FixWallGranRegion::post_force(int /*vflag*/)
|
||||
{
|
||||
int i, m, nc, iwall;
|
||||
int i, n, m, nc, iwall;
|
||||
double *forces, *torquesi;
|
||||
double meff, vwall[3], w0[3] = {0.0, 0.0, 0.0};
|
||||
bool touchflag = false;
|
||||
@ -174,7 +174,11 @@ void FixWallGranRegion::post_force(int /*vflag*/)
|
||||
region->set_velocity();
|
||||
}
|
||||
|
||||
if (peratom_flag) clear_stored_contacts();
|
||||
model->calculate_svector = 0;
|
||||
if (peratom_flag) {
|
||||
model->calculate_svector = 1;
|
||||
clear_stored_contacts();
|
||||
}
|
||||
|
||||
// Define constant wall properties (atom j)
|
||||
model->radj = 0.0;
|
||||
@ -228,6 +232,9 @@ void FixWallGranRegion::post_force(int /*vflag*/)
|
||||
model->radi = radius[i];
|
||||
model->radj = region->contact[ic].radius;
|
||||
model->r = region->contact[ic].r;
|
||||
model->i = i;
|
||||
model->j = ic;
|
||||
|
||||
if (model->beyond_contact) model->touch = history_many[i][c2r[ic]][0];
|
||||
|
||||
touchflag = model->check_contact();
|
||||
@ -280,6 +287,9 @@ void FixWallGranRegion::post_force(int /*vflag*/)
|
||||
array_atom[i][5] = x[i][1] - model->dx[1];
|
||||
array_atom[i][6] = x[i][2] - model->dx[2];
|
||||
array_atom[i][7] = radius[i];
|
||||
|
||||
for (n = 0; n < model->nsvector; n++)
|
||||
array_atom[i][8 + n] = model->svector[n];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,9 +44,8 @@ class FixWallGranRegion : public FixWallGran {
|
||||
int size_restart(int) override;
|
||||
int maxsize_restart() override;
|
||||
|
||||
private:
|
||||
class Region *region;
|
||||
int nregion;
|
||||
void update_contacts(int, int);
|
||||
|
||||
// shear history for multiple contacts per particle
|
||||
|
||||
@ -57,10 +56,11 @@ class FixWallGranRegion : public FixWallGran {
|
||||
int *c2r; // contact to region mapping
|
||||
// c2r[i] = index of Ith contact in
|
||||
// region-contact[] list of contacts
|
||||
private:
|
||||
|
||||
int nregion;
|
||||
int motion_resetflag; // used by restart to indicate that region
|
||||
// vel info is to be reset
|
||||
|
||||
void update_contacts(int, int);
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
@ -42,6 +42,7 @@ GranSubMod::GranSubMod(class GranularModel *gm, LAMMPS *lmp) : Pointers(lmp)
|
||||
beyond_contact = 0;
|
||||
num_coeffs = 0;
|
||||
contact_radius_flag = 0;
|
||||
nsvector = 0;
|
||||
|
||||
nondefault_history_transfer = 0;
|
||||
transfer_history_factor = nullptr;
|
||||
|
||||
@ -46,6 +46,8 @@ namespace Granular_NS {
|
||||
|
||||
GranularModel *gm;
|
||||
|
||||
int nsvector, index_svector;
|
||||
|
||||
protected:
|
||||
int allocated;
|
||||
|
||||
|
||||
@ -50,6 +50,7 @@ GranSubModHeatRadius::GranSubModHeatRadius(GranularModel *gm, LAMMPS *lmp) : Gra
|
||||
num_coeffs = 1;
|
||||
contact_radius_flag = 1;
|
||||
conductivity = 0.0;
|
||||
nsvector = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
@ -65,7 +66,9 @@ void GranSubModHeatRadius::coeffs_to_local()
|
||||
|
||||
double GranSubModHeatRadius::calculate_heat()
|
||||
{
|
||||
return 2 * conductivity * gm->contact_radius * (gm->Tj - gm->Ti);
|
||||
double heat = 2 * conductivity * gm->contact_radius * (gm->Tj - gm->Ti);
|
||||
if (gm->calculate_svector) gm->svector[index_svector] = heat;
|
||||
return heat;
|
||||
}
|
||||
|
||||
|
||||
@ -78,6 +81,7 @@ GranSubModHeatArea::GranSubModHeatArea(GranularModel *gm, LAMMPS *lmp) : GranSub
|
||||
num_coeffs = 1;
|
||||
contact_radius_flag = 1;
|
||||
heat_transfer_coeff = 0.0;
|
||||
nsvector = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
@ -93,5 +97,7 @@ void GranSubModHeatArea::coeffs_to_local()
|
||||
|
||||
double GranSubModHeatArea::calculate_heat()
|
||||
{
|
||||
return heat_transfer_coeff * MY_PI * gm->contact_radius * gm->contact_radius * (gm->Tj - gm->Ti);
|
||||
double heat = heat_transfer_coeff * MY_PI * gm->contact_radius * gm->contact_radius * (gm->Tj - gm->Ti);
|
||||
if (gm->calculate_svector) gm->svector[index_svector] = heat;
|
||||
return heat;
|
||||
}
|
||||
|
||||
@ -13,25 +13,70 @@
|
||||
|
||||
#include "gran_sub_mod_normal.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "error.h"
|
||||
#include "citeme.h"
|
||||
#include "fix_granular_mdr.h"
|
||||
#include "granular_model.h"
|
||||
#include "math_const.h"
|
||||
#include "modify.h"
|
||||
#include "update.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace Granular_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
using MathConst::MY_2PI;
|
||||
using MathConst::MY_PI;
|
||||
|
||||
static constexpr double PI27SQ = 266.47931882941264802866; // 27*PI**2
|
||||
static constexpr double PISQ = 9.8696044010893579923; // PI^2
|
||||
static constexpr double PIINV = 0.318309886183790691216; // 1/PI
|
||||
static constexpr double PI27SQ = 266.479318829412648029; // 27*PI^2
|
||||
static constexpr double PITOFIVETHIRDS = 6.73880859569814116838; // PI^(5/3)
|
||||
static constexpr double CBRT2 = 1.25992104989487319067; // cbrt(2)
|
||||
static constexpr double SQRTHALFPI = 1.25331413731550012081; // sqrt(PI/2)
|
||||
static constexpr double CBRTHALFPI = 1.16244735150962652526; // cbrt(PI/2)
|
||||
static constexpr double FOURTHIRDS = 1.33333333333333333333; // 4/3
|
||||
static constexpr double THREEROOT3 = 5.19615242270663202362; // 3*sqrt(3)
|
||||
static constexpr double SIXROOT6 = 14.69693845669906728801; // 6*sqrt(6)
|
||||
static constexpr double INVROOT6 = 0.40824829046386307274; // 1/sqrt(6)
|
||||
static constexpr double FOURTHIRDS = (4.0 / 3.0); // 4/3
|
||||
static constexpr double JKRPREFIX = 1.2277228507842888; // cbrt(3*PI**2/16)
|
||||
|
||||
static constexpr int MDR_MAX_IT = 100; // Newton-Raphson for MDR
|
||||
static constexpr double MDR_EPSILON1 = 1e-10; // Newton-Raphson for MDR
|
||||
static constexpr double MDR_EPSILON2 = 1e-16; // Newton-Raphson for MDR
|
||||
static constexpr double MDR_EPSILON3 = 1e-20; // For precision checks
|
||||
static constexpr double MDR_OVERLAP_LIMIT = 0.75; // Maximum contact overlap for MDR
|
||||
|
||||
static const char cite_mdr[] =
|
||||
"MDR contact model command: (i) https://doi.org/10.1016/j.jmps.2023.105492 || (ii) https://doi.org/10.1016/j.jmps.2023.105493 || (iii) https://doi.org/10.31224/4289\n\n"
|
||||
"@Article{zunker2024mechanicallyI,\n"
|
||||
" author = {Zunker, William and Kamrin, Ken},\n"
|
||||
" title = {A mechanically-derived contact model for adhesive elastic-perfectly plastic particles,\n"
|
||||
" Part I: Utilizing the method of dimensionality reduction},\n"
|
||||
" journal = {Journal of the Mechanics and Physics of Solids},\n"
|
||||
" year = {2024},\n"
|
||||
" volume = {183},\n"
|
||||
" pages = {105492},\n"
|
||||
"}\n\n"
|
||||
"@Article{zunker2024mechanicallyII,\n"
|
||||
" author = {Zunker, William and Kamrin, Ken},\n"
|
||||
" title = {A mechanically-derived contact model for adhesive elastic-perfectly plastic particles,\n"
|
||||
" Part II: Contact under high compaction—modeling a bulk elastic response},\n"
|
||||
" journal = {Journal of the Mechanics and Physics of Solids},\n"
|
||||
" year = {2024},\n"
|
||||
" volume = {183},\n"
|
||||
" pages = {105493},\n"
|
||||
"}\n\n"
|
||||
"@Article{zunker2025experimentally,\n"
|
||||
" author = {Zunker, William and Dunatunga, Sachith and Thakur, Subhash and Tang, Pingjun and Kamrin, Ken},\n"
|
||||
" title = {Experimentally validated DEM for large deformation powder compaction:\n"
|
||||
" mechanically-derived contact model and screening of non-physical contacts},\n"
|
||||
" year = {2025},\n"
|
||||
" journal = {engrXiv},\n"
|
||||
"}\n\n";
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Default normal model
|
||||
------------------------------------------------------------------------- */
|
||||
@ -381,3 +426,574 @@ void GranSubModNormalJKR::set_fncrit()
|
||||
{
|
||||
Fncrit = fabs(Fne + 2.0 * F_pulloff);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
MDR contact model
|
||||
|
||||
Contributing authors:
|
||||
William Zunker (MIT), Sachith Dunatunga (MIT),
|
||||
Dan Bolintineanu (SNL), Joel Clemmer (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
GranSubModNormalMDR::GranSubModNormalMDR(GranularModel *gm, LAMMPS *lmp) :
|
||||
GranSubModNormal(gm, lmp)
|
||||
{
|
||||
if (lmp->citeme) lmp->citeme->add(cite_mdr);
|
||||
|
||||
num_coeffs = 6;
|
||||
contact_radius_flag = 1;
|
||||
size_history = 26;
|
||||
nsvector = 1;
|
||||
fix_mdr_flag = 0;
|
||||
id_fix = nullptr;
|
||||
|
||||
nondefault_history_transfer = 1;
|
||||
transfer_history_factor = new double[size_history];
|
||||
for (int i = 0; i < size_history; i++) {
|
||||
transfer_history_factor[i] = +1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
GranSubModNormalMDR::~GranSubModNormalMDR()
|
||||
{
|
||||
if (id_fix && modify->nfix)
|
||||
modify->delete_fix(id_fix);
|
||||
delete[] id_fix;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void GranSubModNormalMDR::coeffs_to_local()
|
||||
{
|
||||
E = coeffs[0]; // Young's modulus
|
||||
nu = coeffs[1]; // Poisson's ratio
|
||||
Y = coeffs[2]; // yield stress
|
||||
gamma = coeffs[3]; // effective surface energy
|
||||
psi_b = coeffs[4]; // bulk response trigger based on ratio of remaining free area: A_{free}/A_{total}
|
||||
CoR = coeffs[5]; // coefficent of restitution
|
||||
|
||||
if (E <= 0.0) error->all(FLERR, "Illegal MDR normal model, Young's modulus must be greater than 0");
|
||||
if (nu < 0.0 || nu > 0.5) error->all(FLERR, "Illegal MDR normal model, Poisson's ratio must be between 0 and 0.5");
|
||||
if (Y < 0.0) error->all(FLERR, "Illegal MDR normal model, yield stress must be greater than or equal to 0");
|
||||
if (gamma < 0.0) error->all(FLERR, "Illegal MDR normal model, effective surface energy must be greater than or equal to 0");
|
||||
if (psi_b < 0.0 || psi_b > 1.0) error->all(FLERR, "Illegal MDR normal model, psi_b must be between 0 and 1.0");
|
||||
if (CoR < 0.0 || CoR > 1.0) error->all(FLERR, "Illegal MDR normal model, coefficent of restitution must be between 0 and 1.0");
|
||||
|
||||
G = E / (2.0 * (1.0 + nu)); // shear modulus
|
||||
kappa = E / (3.0 * (1.0 - 2.0 * nu)); // bulk modulus
|
||||
Eeff = E / (1.0 - pow(nu, 2.0)); // composite plane strain modulus
|
||||
|
||||
// precomputing factors
|
||||
|
||||
Eeffinv = 1.0 / Eeff;
|
||||
Eeffsq = Eeff * Eeff;
|
||||
Eeffsqinv = Eeffinv * Eeffinv;
|
||||
|
||||
gammasq = gamma * gamma;
|
||||
gamma3 = gammasq * gamma;
|
||||
gamma4 = gammasq * gammasq;
|
||||
|
||||
warn_flag = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void GranSubModNormalMDR::init()
|
||||
{
|
||||
if (!fix_mdr_flag) {
|
||||
if (modify->get_fix_by_style("GRANULAR/MDR").size() == 0) {
|
||||
id_fix = utils::strdup("MDR");
|
||||
modify->add_fix(fmt::format("{} all GRANULAR/MDR", id_fix));
|
||||
}
|
||||
fix_mdr_flag = 1;
|
||||
}
|
||||
|
||||
// initialize particle history variables
|
||||
int tmp1, tmp2;
|
||||
index_Ro = atom->find_custom("Ro", tmp1, tmp2); // initial radius
|
||||
index_Vcaps = atom->find_custom("Vcaps", tmp1, tmp2); // spherical cap volume from intersection of apparent radius particle and contact planes
|
||||
index_Vgeo = atom->find_custom("Vgeo", tmp1, tmp2); // geometric particle volume of apparent particle after removing spherical cap volume
|
||||
index_Velas = atom->find_custom("Velas", tmp1, tmp2); // particle volume from linear elasticity
|
||||
index_eps_bar = atom->find_custom("eps_bar", tmp1, tmp2); // volume-averaged infinitesimal strain tensor
|
||||
index_dRnumerator = atom->find_custom("dRnumerator", tmp1, tmp2); // summation of numerator terms in calculation of dR
|
||||
index_dRdenominator = atom->find_custom("dRdenominator", tmp1, tmp2); // summation of denominator terms in calculation of dR
|
||||
index_Acon0 = atom->find_custom("Acon0", tmp1, tmp2); // total area involved in contacts: Acon^{n}
|
||||
index_Acon1 = atom->find_custom("Acon1", tmp1, tmp2); // total area involved in contacts: Acon^{n+1}
|
||||
index_Atot = atom->find_custom("Atot", tmp1, tmp2); // total particle area
|
||||
index_Atot_sum = atom->find_custom("Atot_sum", tmp1, tmp2); // running sum of contact area minus cap area
|
||||
index_ddelta_bar = atom->find_custom("ddelta_bar", tmp1, tmp2); // change in mean surface displacement
|
||||
index_psi = atom->find_custom("psi", tmp1, tmp2); // ratio of free surface area to total surface area
|
||||
index_sigmaxx = atom->find_custom("sigmaxx", tmp1, tmp2); // xx-component of the stress tensor, not necessary for force calculation
|
||||
index_sigmayy = atom->find_custom("sigmayy", tmp1, tmp2); // yy-component of the stress tensor, not necessary for force calculation
|
||||
index_sigmazz = atom->find_custom("sigmazz", tmp1, tmp2); // zz-component of the stress tensor, not necessary for force calculation
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double GranSubModNormalMDR::calculate_forces()
|
||||
{
|
||||
using namespace Granular_MDR_NS;
|
||||
// To understand the structure of the overall code it is important to consider
|
||||
// the following:
|
||||
//
|
||||
// The MDR contact model was developed by imagining individual particles being
|
||||
// squished between a number of rigid flats (references below). To allow
|
||||
// for many interacting particles, we extend the idea of isolated particles surrounded
|
||||
// by rigid flats. In particular, we imagine placing rigid flats at the overlaps
|
||||
// between particles. The force is calculated seperately on both sides
|
||||
// of the contact assuming interaction with a rigid flat. The two forces are then
|
||||
// averaged on either side of the contact to determine the final force. If the
|
||||
// contact is between a particle and wall then only one force evaluation is required.
|
||||
//
|
||||
// Zunker and Kamrin, 2024, Part I: https://doi.org/10.1016/j.jmps.2023.105492
|
||||
// Zunker and Kamrin, 2024, Part II: https://doi.org/10.1016/j.jmps.2023.105493
|
||||
// Zunker, Dunatunga, Thakur, Tang, and Kamrin, 2025:
|
||||
|
||||
double *Rinitial = atom->dvector[index_Ro];
|
||||
double *Vgeo = atom->dvector[index_Vgeo];
|
||||
double *Velas = atom->dvector[index_Velas];
|
||||
double *Vcaps = atom->dvector[index_Vcaps];
|
||||
double *eps_bar = atom->dvector[index_eps_bar];
|
||||
double *dRnumerator = atom->dvector[index_dRnumerator];
|
||||
double *dRdenominator = atom->dvector[index_dRdenominator];
|
||||
double *Acon0 = atom->dvector[index_Acon0];
|
||||
double *Acon1 = atom->dvector[index_Acon1];
|
||||
double *Atot = atom->dvector[index_Atot];
|
||||
double *Atot_sum = atom->dvector[index_Atot_sum];
|
||||
double *ddelta_bar = atom->dvector[index_ddelta_bar];
|
||||
double *psi = atom->dvector[index_psi];
|
||||
double *sigmaxx = atom->dvector[index_sigmaxx];
|
||||
double *sigmayy = atom->dvector[index_sigmayy];
|
||||
double *sigmazz = atom->dvector[index_sigmazz];
|
||||
|
||||
const int itag_true = atom->tag[gm->i]; // true i particle tag
|
||||
const int jtag_true = atom->tag[gm->j]; // true j particle tag
|
||||
const int i_true = gm->i; // true i particle index
|
||||
const int j_true = gm->j; // true j particle index
|
||||
const double radi_true = gm->radi; // true i particle initial radius
|
||||
const double radj_true = gm->radj; // true j particle initial radius
|
||||
|
||||
double F = 0.0; // average force
|
||||
double F0 = 0.0; // force on contact side 0
|
||||
double F1 = 0.0; // force on contact side 1
|
||||
double delta = gm->delta; // apparent overlap
|
||||
double Ac_avg = 0.0; // average contact area across both sides
|
||||
|
||||
double *history = & gm->history[history_index]; // load in all history variables
|
||||
int history_update = gm->history_update;
|
||||
|
||||
// Rigid flat placement scheme
|
||||
double *deltamax_offset = & history[DELTA_MAX];
|
||||
double *deltap_offset0 = & history[DELTAP_0];
|
||||
double *deltap_offset1 = & history[DELTAP_1];
|
||||
double deltap0 = *deltap_offset0;
|
||||
double deltap1 = *deltap_offset1;
|
||||
|
||||
// always update deltamax since gm->delta won't change until initial integrate
|
||||
// also need to define deltamax if an atom is created with an overlap
|
||||
double deltamaxi = *deltamax_offset;
|
||||
if (gm->delta >= *deltamax_offset) *deltamax_offset = gm->delta;
|
||||
double deltamax = *deltamax_offset;
|
||||
|
||||
|
||||
for (int contactSide = 0; contactSide < 2; contactSide++) {
|
||||
|
||||
double *delta_offset, *deltao_offset, *delta_MDR_offset, *delta_BULK_offset;
|
||||
double *deltamax_MDR_offset, *Yflag_offset, *deltaY_offset, *cA_offset, *aAdh_offset;
|
||||
double *Ac_offset, *eps_bar_offset, *penalty_offset, *deltap_offset;
|
||||
|
||||
if (gm->contact_type == PAIR) {
|
||||
// displacement partitioning only necessary for particle-particle contact
|
||||
|
||||
// itag and jtag persist after neighbor list builds, use tags to compare to match
|
||||
// contact history variables consistently across steps for a particle pair.
|
||||
if ((contactSide == 0 && itag_true > jtag_true) || (contactSide != 0 && itag_true < jtag_true)) {
|
||||
gm->i = i_true;
|
||||
gm->j = j_true;
|
||||
gm->radi = radi_true;
|
||||
gm->radj = radj_true;
|
||||
} else {
|
||||
gm->i = j_true;
|
||||
gm->j = i_true;
|
||||
gm->radi = radj_true;
|
||||
gm->radj = radi_true;
|
||||
}
|
||||
|
||||
// determine the two maximum experienced geometric overlaps on either side of rigid flat
|
||||
double delta_geo, delta_geo_alt;
|
||||
double denom = 1.0 / (2.0 * (deltamax - gm->radi - gm->radj));
|
||||
double delta_geoOpt1 = deltamax * (deltamax - 2.0 * gm->radj) * denom;
|
||||
double delta_geoOpt2 = deltamax * (deltamax - 2.0 * gm->radi) * denom;
|
||||
if (gm->radi < gm->radj) {
|
||||
delta_geo = MAX(delta_geoOpt1, delta_geoOpt2);
|
||||
delta_geo_alt = MIN(delta_geoOpt1,delta_geoOpt2);
|
||||
} else {
|
||||
delta_geo = MIN(delta_geoOpt1, delta_geoOpt2);
|
||||
delta_geo_alt = MAX(delta_geoOpt1, delta_geoOpt2);
|
||||
}
|
||||
|
||||
// cap displacement if exceeds the overlap limit, parition the remaining to the other side
|
||||
if (delta_geo / gm->radi > MDR_OVERLAP_LIMIT) {
|
||||
delta_geo = gm->radi * MDR_OVERLAP_LIMIT;
|
||||
} else if (delta_geo_alt / gm->radj > MDR_OVERLAP_LIMIT) {
|
||||
delta_geo = deltamax - gm->radj * MDR_OVERLAP_LIMIT;
|
||||
}
|
||||
|
||||
// determine final delta used for subsequent calculations
|
||||
double deltap = deltap0 + deltap1;
|
||||
if (contactSide == 0) {
|
||||
delta = delta_geo + (deltap0 - delta_geo) * (gm->delta - deltamax) / (deltap - deltamax);
|
||||
} else {
|
||||
delta = delta_geo + (deltap1 - delta_geo) * (gm->delta - deltamax) / (deltap - deltamax);
|
||||
}
|
||||
} else if (gm->contact_type != PAIR && contactSide != 0) {
|
||||
// contact with particle-wall requires only one evaluation
|
||||
break;
|
||||
}
|
||||
|
||||
delta_offset = &history[DELTA_0 + contactSide];
|
||||
deltao_offset = &history[DELTAO_0 + contactSide];
|
||||
delta_MDR_offset = &history[DELTA_MDR_0 + contactSide];
|
||||
delta_BULK_offset = &history[DELTA_BULK_0 + contactSide];
|
||||
deltamax_MDR_offset = &history[DELTAMAX_MDR_0 + contactSide];
|
||||
Yflag_offset = &history[YFLAG_0 + contactSide];
|
||||
deltaY_offset = &history[DELTAY_0 + contactSide];
|
||||
cA_offset = &history[CA_0 + contactSide];
|
||||
aAdh_offset = &history[AADH_0 + contactSide];
|
||||
Ac_offset = &history[AC_0 + contactSide];
|
||||
eps_bar_offset = &history[EPS_BAR_0 + contactSide];
|
||||
deltap_offset = &history[DELTAP_0 + contactSide];
|
||||
|
||||
// temporary i and j indices
|
||||
const int i = gm->i;
|
||||
const int j = gm->j;
|
||||
|
||||
// geometric property definitions
|
||||
const double Ro = Rinitial[i]; // initial radius
|
||||
const double R = gm->radi; // apparent radius
|
||||
|
||||
// kinematics
|
||||
const double ddelta = delta - *delta_offset;
|
||||
if (history_update) *delta_offset = delta;
|
||||
|
||||
const double deltao = delta - (R - Ro);
|
||||
const double ddeltao = deltao - *deltao_offset;
|
||||
if (history_update) *deltao_offset = deltao;
|
||||
|
||||
double ddelta_MDR, ddelta_BULK;
|
||||
if (psi[i] < psi_b) {
|
||||
// bulk response triggered, split displacement increment between MDR and BULK components
|
||||
ddelta_MDR = MIN(ddelta - ddelta_bar[i], delta - *delta_MDR_offset);
|
||||
ddelta_BULK = ddelta_bar[i];
|
||||
} else {
|
||||
// no bulk response, full displacement increment goes to the MDR component
|
||||
ddelta_BULK = 0.0;
|
||||
ddelta_MDR = ddelta;
|
||||
}
|
||||
|
||||
// calculate and update MDR/BULK displacements
|
||||
const double delta_MDR = *delta_MDR_offset + ddelta_MDR;
|
||||
if (history_update) *delta_MDR_offset = delta_MDR;
|
||||
const double delta_BULK = MAX(0.0, *delta_BULK_offset + ddelta_BULK);
|
||||
if (history_update) *delta_BULK_offset = delta_BULK;
|
||||
|
||||
if (delta_MDR > *deltamax_MDR_offset) *deltamax_MDR_offset = delta_MDR;
|
||||
const double deltamax_MDR = *deltamax_MDR_offset;
|
||||
|
||||
// average pressure along yield surface
|
||||
const double pY = Y * (1.75 * exp(-4.4 * deltamax_MDR / R) + 1.0);
|
||||
|
||||
if (*Yflag_offset == 0.0 && delta_MDR >= deltamax_MDR) {
|
||||
const double phertz = 4 * Eeff * sqrt(delta_MDR) / (3 * MY_PI * sqrt(R));
|
||||
if (!history_update && warn_flag && deltamaxi == 0 && phertz > pY) {
|
||||
error->warning(FLERR, "The newly inserted particles have pre-existing overlaps that "
|
||||
"have caused immediate plastic deformation. This could lead to "
|
||||
"non-physical results in the MDR model, as it handles some aspects "
|
||||
"related to plastic deformation incrementally.");
|
||||
warn_flag = 0;
|
||||
}
|
||||
if (history_update && phertz > pY) {
|
||||
*Yflag_offset = 1.0;
|
||||
*deltaY_offset = delta_MDR;
|
||||
*cA_offset = MY_PI * (pow(*deltaY_offset, 2) - *deltaY_offset * R);
|
||||
}
|
||||
}
|
||||
|
||||
// MDR force calculation
|
||||
double F_MDR;
|
||||
double A, Ainv; // height of elliptical indenter
|
||||
double B; // width of elliptical indenter
|
||||
double deltae1D; // transformed elastic displacement
|
||||
double deltaR; // displacement correction
|
||||
double amax, amaxsq; // maximum experienced contact radius
|
||||
const double cA = *cA_offset; // contact area intercept
|
||||
|
||||
if (*Yflag_offset == 0.0) {
|
||||
// elastic contact
|
||||
A = 4.0 * R;
|
||||
Ainv = 1.0 / A;
|
||||
B = 2.0 * R;
|
||||
deltae1D = delta_MDR;
|
||||
amax = sqrt(deltamax_MDR * R);
|
||||
} else {
|
||||
// plastic contact
|
||||
amax = sqrt(2.0 * deltamax_MDR * R - pow(deltamax_MDR, 2) + cA * PIINV);
|
||||
amaxsq = amax * amax;
|
||||
A = 4.0 * pY * Eeffinv * amax;
|
||||
Ainv = 1.0 / A;
|
||||
B = 2.0 * amax;
|
||||
|
||||
// maximum transformed elastic displacement
|
||||
const double deltae1Dmax = A * 0.5;
|
||||
|
||||
// force caused by full submersion of elliptical indenter to depth of A/2
|
||||
double Fmax = Eeff * (A * B * 0.25) * acos(1 - 2 * deltae1Dmax * Ainv);
|
||||
Fmax -= (2 - 4 * deltae1Dmax * Ainv) * sqrt(deltae1Dmax * Ainv - pow(deltae1Dmax * Ainv, 2));
|
||||
|
||||
// depth of particle center
|
||||
const double zR = R - (deltamax_MDR - deltae1Dmax);
|
||||
|
||||
deltaR = 2 * amaxsq * (-1 + nu) - (-1 + 2 * nu) * zR * (-zR + sqrt(amaxsq + pow(zR, 2)));
|
||||
deltaR *= Fmax / (MY_2PI * amaxsq * G * sqrt(amaxsq + pow(zR, 2)));
|
||||
|
||||
// transformed elastic displacement
|
||||
deltae1D = (delta_MDR - deltamax_MDR + deltae1Dmax + deltaR) / (1 + deltaR / deltae1Dmax);
|
||||
|
||||
// added for rigid flat placement
|
||||
if (history_update) *deltap_offset = deltamax_MDR - (deltae1Dmax + deltaR);
|
||||
}
|
||||
|
||||
double a_na;
|
||||
double a_fac = 0.99;
|
||||
(deltae1D >= 0.0) ? a_na = B * sqrt(A - deltae1D) * sqrt(deltae1D) * Ainv : a_na = 0.0;
|
||||
double aAdh = *aAdh_offset;
|
||||
if (aAdh > a_fac * amax) aAdh = a_fac * amax;
|
||||
|
||||
double Ainvsq = Ainv * Ainv;
|
||||
double Asq = A * A;
|
||||
double A3 = Asq * A;
|
||||
double A4 = Asq * Asq;
|
||||
|
||||
double Binv = 1.0 / B;
|
||||
double Bsq = B * B;
|
||||
double B4 = Bsq * Bsq;
|
||||
|
||||
if (gamma <= 0.0) {
|
||||
// non-adhesive contact
|
||||
|
||||
if (deltae1D <= 0.0) {
|
||||
F_MDR = 0.0;
|
||||
} else {
|
||||
F_MDR = calculate_nonadhesive_mdr_force(deltae1D, Ainv, Eeff, A, B);
|
||||
}
|
||||
|
||||
if (std::isnan(F_MDR)) {
|
||||
error->one(FLERR, "F_MDR is NaN, non-adhesive case");
|
||||
}
|
||||
|
||||
if (history_update) *aAdh_offset = a_na;
|
||||
} else {
|
||||
// adhesive contact
|
||||
double g_aAdh;
|
||||
|
||||
if (delta_MDR == deltamax_MDR || a_na >= aAdh) {
|
||||
// case 1: no tensile springs, purely compressive contact
|
||||
|
||||
if (deltae1D <= 0.0) {
|
||||
F_MDR = 0.0;
|
||||
} else {
|
||||
F_MDR = calculate_nonadhesive_mdr_force(deltae1D, Ainv, Eeff, A, B);
|
||||
}
|
||||
|
||||
if (std::isnan(F_MDR))
|
||||
error->one(FLERR, "F_MDR is NaN, case 1: no tensile springs");
|
||||
|
||||
if (history_update) *aAdh_offset = a_fac * a_na;
|
||||
} else {
|
||||
// case 2+3, tensile springs
|
||||
const double lmax = sqrt(MY_2PI * aAdh * gamma * Eeffinv);
|
||||
g_aAdh = A * 0.5 - A * Binv * sqrt(Bsq * 0.25 - pow(aAdh, 2));
|
||||
g_aAdh = round_up_negative_epsilon(g_aAdh);
|
||||
|
||||
double tmp = 27 * A4 * B4 * gamma * Eeffinv;
|
||||
tmp -= 2 * pow(B, 6) * gamma3 * PISQ * pow(Eeffinv, 3);
|
||||
tmp += sqrt(27) * Asq * B4 * sqrt(27 * A4 * Eeffsq * gammasq - 4 * Bsq * gamma4 * PISQ) * Eeffsqinv;
|
||||
tmp = cbrt(tmp);
|
||||
|
||||
double acrit = -Bsq * gamma * MY_PI * Ainvsq * Eeffinv;
|
||||
acrit += CBRT2 * B4 * gammasq * PITOFIVETHIRDS / (Asq * Eeffsq * tmp);
|
||||
acrit += CBRTHALFPI * tmp * Ainvsq;
|
||||
acrit /= 6;
|
||||
|
||||
if ((deltae1D + lmax - g_aAdh) >= 0.0) {
|
||||
// case 2: tensile springs do not exceed critical length --> deltae + lmax - g(aAdhes) >= 0
|
||||
const double deltaeAdh = g_aAdh;
|
||||
const double F_na = calculate_nonadhesive_mdr_force(deltaeAdh, Ainv, Eeff, A, B);
|
||||
const double F_Adhes = 2.0 * Eeff * (deltae1D - deltaeAdh) * aAdh;
|
||||
F_MDR = F_na + F_Adhes;
|
||||
if (std::isnan(F_MDR))
|
||||
error->one(FLERR, "F_MDR is NaN, case 2: tensile springs, but not exceeding critical length");
|
||||
} else {
|
||||
// case 3: tensile springs exceed critical length --> deltae + lmax - g(aAdhes) = 0
|
||||
|
||||
if (aAdh < acrit) {
|
||||
aAdh = 0.0;
|
||||
F_MDR = 0.0;
|
||||
} else {
|
||||
// newton-raphson to find aAdh
|
||||
double aAdh_tmp = aAdh;
|
||||
double fa, fa2, fa_tmp, dfda;
|
||||
for (int lv1 = 0; lv1 < MDR_MAX_IT; ++lv1) {
|
||||
fa_tmp = deltae1D - A * 0.5 + A * sqrt(Bsq * 0.25 - pow(aAdh_tmp, 2)) * Binv;
|
||||
fa = fa_tmp + sqrt(MY_2PI * aAdh_tmp * gamma * Eeffinv);
|
||||
if (abs(fa) < MDR_EPSILON1) {
|
||||
break;
|
||||
}
|
||||
dfda = -aAdh_tmp * A / (B * sqrt(-pow(aAdh_tmp, 2) + Bsq * 0.25));
|
||||
dfda += gamma * SQRTHALFPI / sqrt(aAdh_tmp * gamma * Eeff);
|
||||
aAdh_tmp = aAdh_tmp - fa / dfda;
|
||||
fa2 = fa_tmp + sqrt(MY_2PI * aAdh_tmp * gamma * Eeffinv);
|
||||
if (abs(fa - fa2) < MDR_EPSILON2) {
|
||||
break;
|
||||
}
|
||||
if (lv1 == MDR_MAX_IT - 1) {
|
||||
aAdh_tmp = 0.0;
|
||||
}
|
||||
}
|
||||
aAdh = aAdh_tmp;
|
||||
|
||||
g_aAdh = A * 0.5 - A * Binv * sqrt(Bsq * 0.25 - pow(aAdh, 2));
|
||||
g_aAdh = round_up_negative_epsilon(g_aAdh);
|
||||
|
||||
const double deltaeAdh = g_aAdh;
|
||||
const double F_na = calculate_nonadhesive_mdr_force(deltaeAdh, Ainv, Eeff, A, B);
|
||||
const double F_Adhes = 2.0 * Eeff * (deltae1D - deltaeAdh) * aAdh;
|
||||
F_MDR = F_na + F_Adhes;
|
||||
if (std::isnan(F_MDR))
|
||||
error->one(FLERR, "F_MDR is NaN, case 3: tensile springs exceed critical length");
|
||||
}
|
||||
if (history_update) *aAdh_offset = aAdh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// contact penalty scheme
|
||||
penalty_offset = &history[PENALTY];
|
||||
double pij = *penalty_offset;
|
||||
const double wij = MAX(1.0 - pij, 0.0);
|
||||
|
||||
// area related calculations
|
||||
double Ac;
|
||||
(*Yflag_offset == 0.0) ? Ac = MY_PI * delta * R : Ac = MY_PI * (2.0 * delta * R - pow(delta, 2)) + cA;
|
||||
if (Ac < 0.0) Ac = 0.0;
|
||||
if (history_update) {
|
||||
Atot_sum[i] += wij * (Ac - MY_2PI * R * (deltamax_MDR + delta_BULK));
|
||||
Acon1[i] += wij * Ac;
|
||||
}
|
||||
Ac_avg += wij * Ac;
|
||||
|
||||
// bulk force calculation
|
||||
double F_BULK;
|
||||
(delta_BULK <= 0.0) ? F_BULK = 0.0 : F_BULK = (1.0 / Vgeo[i]) * Acon0[i] * delta_BULK * kappa * Ac;
|
||||
|
||||
// total force calculation
|
||||
(contactSide == 0) ? F0 = F_MDR + F_BULK : F1 = F_MDR + F_BULK;
|
||||
|
||||
if (history_update) {
|
||||
// mean surface displacement calculation
|
||||
*Ac_offset = wij * Ac;
|
||||
|
||||
// radius update scheme quantity calculation
|
||||
Vcaps[i] += MY_PI * THIRD * pow(delta, 2) * (3.0 * R - delta);
|
||||
}
|
||||
|
||||
const double Fntmp = wij * (F_MDR + F_BULK);
|
||||
const double fx = Fntmp * gm->nx[0];
|
||||
const double fy = Fntmp * gm->nx[1];
|
||||
const double fz = Fntmp * gm->nx[2];
|
||||
const double bx = -(Ro - deltao) * gm->nx[0];
|
||||
const double by = -(Ro - deltao) * gm->nx[1];
|
||||
const double bz = -(Ro - deltao) * gm->nx[2];
|
||||
const double eps_bar_contact = (fx * bx + fy * by + fz * bz) / (3 * kappa * Velas[i]);
|
||||
if (history_update) eps_bar[i] += eps_bar_contact;
|
||||
|
||||
double desp_bar_contact = eps_bar_contact - *eps_bar_offset;
|
||||
if (history_update && delta_MDR == deltamax_MDR && *Yflag_offset > 0.0 && F_MDR > 0.0) {
|
||||
const double Vo = FOURTHIRDS * MY_PI * pow(Ro, 3);
|
||||
dRnumerator[i] -= Vo * (eps_bar_contact - *eps_bar_offset);
|
||||
dRnumerator[i] -= wij * MY_PI * ddeltao * (2 * deltao * Ro - pow(deltao, 2) + pow(R, 2) - pow(Ro, 2));
|
||||
dRdenominator[i] += wij * 2.0 * MY_PI * R * (deltao + R - Ro);
|
||||
}
|
||||
|
||||
if (history_update) {
|
||||
*eps_bar_offset = eps_bar_contact;
|
||||
sigmaxx[i] += fx * bx / Velas[i];
|
||||
sigmayy[i] += fy * by / Velas[i];
|
||||
sigmazz[i] += fz * bz / Velas[i];
|
||||
}
|
||||
}
|
||||
|
||||
// save contact area
|
||||
if (gm->calculate_svector) gm->svector[index_svector] = Ac_avg * 0.5;
|
||||
|
||||
gm->i = i_true;
|
||||
gm->j = j_true;
|
||||
gm->radi = radi_true;
|
||||
gm->radj = radj_true;
|
||||
|
||||
double *penalty_offset = &history[PENALTY];
|
||||
const double pij = *penalty_offset;
|
||||
const double wij = MAX(1.0 - pij, 0.0);
|
||||
|
||||
// assign final force
|
||||
if (gm->contact_type != PAIR) {
|
||||
F = wij * F0;
|
||||
} else {
|
||||
F = wij * (F0 + F1) * 0.5;
|
||||
}
|
||||
|
||||
// calculate damping force
|
||||
if (F > 0.0) {
|
||||
double Eeff2;
|
||||
double Reff2;
|
||||
if (gm->contact_type == PAIR) {
|
||||
Eeff2 = E / (2.0 * (1.0 - pow(nu, 2)));
|
||||
Reff2 = 1.0 / ((1.0 / gm->radi + 1.0 / gm->radj));
|
||||
} else {
|
||||
Eeff2 = E / (1.0 - pow(nu, 2));
|
||||
Reff2 = gm->radi;
|
||||
}
|
||||
const double kn = Eeff2 * Reff2;
|
||||
const double beta = -log(CoR) / sqrt(pow(log(CoR), 2) + PISQ);
|
||||
const double damp_prefactor = beta * sqrt(gm->meff * kn);
|
||||
const double F_DAMP = -damp_prefactor * gm->vnnr;
|
||||
|
||||
F += wij * F_DAMP;
|
||||
}
|
||||
|
||||
return F;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double GranSubModNormalMDR::calculate_nonadhesive_mdr_force(double delta, double Ainv, double Eeff, double A, double B)
|
||||
{
|
||||
double F_na = acos(1.0 - 2.0 * delta * Ainv);
|
||||
F_na -= (2 - 4 * delta * Ainv) * sqrt(delta * Ainv - pow(delta * Ainv, 2));
|
||||
F_na *= 0.25 * Eeff * A * B;
|
||||
|
||||
return F_na;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
round values within (-EPSILON,0.0) due to machine precision errors to zero
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double GranSubModNormalMDR::round_up_negative_epsilon(double value)
|
||||
{
|
||||
if (value < 0.0 && value > -MDR_EPSILON3) value = 0.0;
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ GranSubModStyle(hertz,GranSubModNormalHertz,NORMAL);
|
||||
GranSubModStyle(hertz/material,GranSubModNormalHertzMaterial,NORMAL);
|
||||
GranSubModStyle(dmt,GranSubModNormalDMT,NORMAL);
|
||||
GranSubModStyle(jkr,GranSubModNormalJKR,NORMAL);
|
||||
GranSubModStyle(mdr,GranSubModNormalMDR,NORMAL);
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
@ -133,6 +134,35 @@ namespace Granular_NS {
|
||||
int mixed_coefficients;
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
class GranSubModNormalMDR : public GranSubModNormal {
|
||||
public:
|
||||
GranSubModNormalMDR(class GranularModel *, class LAMMPS *);
|
||||
~GranSubModNormalMDR() override;
|
||||
void coeffs_to_local() override;
|
||||
void init() override;
|
||||
double calculate_forces() override;
|
||||
double E, nu, Y, gamma, CoR, psi_b; // specified coeffs
|
||||
|
||||
protected:
|
||||
double G, kappa, Eeff; // derived coeffs
|
||||
double Eeffsq, Eeffinv, Eeffsqinv;
|
||||
double gammasq, gamma3, gamma4;
|
||||
|
||||
int warn_flag;
|
||||
|
||||
int index_Ro, index_Vgeo, index_Velas, index_Vcaps, index_eps_bar, index_dRnumerator;
|
||||
int index_dRdenominator, index_Acon0, index_Acon1, index_Atot, index_Atot_sum, index_ddelta_bar;
|
||||
int index_psi, index_sigmaxx, index_sigmayy, index_sigmazz, index_contacts, index_adhesive_length;
|
||||
int fix_mdr_flag;
|
||||
|
||||
char *id_fix;
|
||||
|
||||
inline double calculate_nonadhesive_mdr_force(double, double, double, double, double);
|
||||
inline double round_up_negative_epsilon(double);
|
||||
};
|
||||
|
||||
} // namespace Granular_NS
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
#include "force.h"
|
||||
#include "gran_sub_mod.h"
|
||||
#include "math_extra.h"
|
||||
#include "memory.h"
|
||||
|
||||
#include "style_gran_sub_mod.h" // IWYU pragma: keep
|
||||
|
||||
@ -64,6 +65,10 @@ GranularModel::GranularModel(LAMMPS *lmp) : Pointers(lmp)
|
||||
twisting_model = nullptr;
|
||||
heat_model = nullptr;
|
||||
|
||||
calculate_svector = 0;
|
||||
nsvector = 0;
|
||||
svector = nullptr;
|
||||
|
||||
for (int i = 0; i < NSUBMODELS; i++) sub_models[i] = nullptr;
|
||||
transfer_history_factor = nullptr;
|
||||
|
||||
@ -100,6 +105,7 @@ GranularModel::~GranularModel()
|
||||
delete[] gran_sub_mod_class;
|
||||
delete[] gran_sub_mod_names;
|
||||
delete[] gran_sub_mod_types;
|
||||
delete[] svector;
|
||||
|
||||
for (int i = 0; i < NSUBMODELS; i++) delete sub_models[i];
|
||||
}
|
||||
@ -243,7 +249,12 @@ void GranularModel::init()
|
||||
|
||||
// Must have valid normal, damping, and tangential models
|
||||
if (normal_model->name == "none") error->all(FLERR, "Must specify normal granular model");
|
||||
if (normal_model->name == "mdr") {
|
||||
if (damping_model->name != "none")
|
||||
error->all(FLERR, "MDR require 'none' damping model. To damp, specify a coefficient of restitution < 1.");
|
||||
} else {
|
||||
if (damping_model->name == "none") error->all(FLERR, "Must specify damping granular model");
|
||||
}
|
||||
if (tangential_model->name == "none") error->all(FLERR, "Must specify tangential granular model");
|
||||
|
||||
// Twisting, rolling, and heat are optional
|
||||
@ -293,6 +304,21 @@ void GranularModel::init()
|
||||
}
|
||||
|
||||
for (int i = 0; i < NSUBMODELS; i++) sub_models[i]->init();
|
||||
|
||||
nsvector = 0;
|
||||
int index_svector = 0;
|
||||
for (int i = 0; i < NSUBMODELS; i++) {
|
||||
if (sub_models[i]->nsvector != 0) {
|
||||
sub_models[i]->index_svector = index_svector;
|
||||
nsvector += sub_models[i]->nsvector;
|
||||
index_svector += sub_models[i]->nsvector;
|
||||
}
|
||||
}
|
||||
|
||||
if (nsvector != 0) {
|
||||
delete[] svector;
|
||||
svector = new double[nsvector];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
@ -493,10 +519,9 @@ void GranularModel::calculate_forces()
|
||||
if (contact_type == PAIR) sub3(torquesj, tortwist, torquesj);
|
||||
}
|
||||
|
||||
if (heat_defined) {
|
||||
if (heat_defined)
|
||||
dq = heat_model->calculate_heat();
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
compute pull-off distance (beyond contact) for a given radius and atom type
|
||||
|
||||
@ -74,6 +74,9 @@ class GranularModel : protected Pointers {
|
||||
int beyond_contact, limit_damping, history_update;
|
||||
ContactType contact_type;
|
||||
|
||||
// Particle identifiers
|
||||
int i, j, itype, jtype;
|
||||
|
||||
// History variables
|
||||
int size_history, nondefault_history_transfer;
|
||||
double *transfer_history_factor;
|
||||
@ -93,6 +96,10 @@ class GranularModel : protected Pointers {
|
||||
double magtwist;
|
||||
bool touch;
|
||||
|
||||
// Extra output
|
||||
int calculate_svector, nsvector;
|
||||
double *svector;
|
||||
|
||||
protected:
|
||||
int rolling_defined, twisting_defined, heat_defined; // Flag optional sub models
|
||||
int classic_model; // Flag original pair/gran calculations
|
||||
|
||||
@ -199,6 +199,11 @@ void PairGranular::compute(int eflag, int vflag)
|
||||
model->xj = x[j];
|
||||
model->radi = radius[i];
|
||||
model->radj = radius[j];
|
||||
model->i = i;
|
||||
model->j = j;
|
||||
model->itype = itype;
|
||||
model->jtype = jtype;
|
||||
|
||||
if (use_history) model->touch = touch[jj];
|
||||
|
||||
touchflag = model->check_contact();
|
||||
@ -412,8 +417,10 @@ void PairGranular::init_style()
|
||||
error->all(FLERR,"Heat conduction in pair granular requires atom style with heatflow property");
|
||||
}
|
||||
|
||||
// allocate history and initialize models
|
||||
// allocate history and aggregate model information
|
||||
class GranularModel* model;
|
||||
double nsvector_total;
|
||||
extra_svector = 0;
|
||||
int size_max[NSUBMODELS] = {0};
|
||||
for (int n = 0; n < nmodels; n++) {
|
||||
model = models_list[n];
|
||||
@ -424,13 +431,23 @@ void PairGranular::init_style()
|
||||
}
|
||||
if (model->size_history != 0) use_history = 1;
|
||||
|
||||
for (int i = 0; i < NSUBMODELS; i++)
|
||||
nsvector_total = 0;
|
||||
for (int i = 0; i < NSUBMODELS; i++) {
|
||||
nsvector_total += model->sub_models[i]->nsvector;
|
||||
if (model->sub_models[i]->size_history > size_max[i])
|
||||
size_max[i] = model->sub_models[i]->size_history;
|
||||
}
|
||||
extra_svector = MAX(extra_svector, nsvector_total);
|
||||
|
||||
if (model->nondefault_history_transfer) nondefault_history_transfer = 1;
|
||||
}
|
||||
|
||||
if (extra_svector != 0) {
|
||||
single_extra = 12 + extra_svector;
|
||||
delete[] svector;
|
||||
svector = new double[single_extra];
|
||||
}
|
||||
|
||||
size_history = 0;
|
||||
if (use_history) {
|
||||
for (int i = 0; i < NSUBMODELS; i++) size_history += size_max[i];
|
||||
@ -711,6 +728,10 @@ double PairGranular::single(int i, int j, int itype, int jtype,
|
||||
model->xj = x[j];
|
||||
model->radi = radius[i];
|
||||
model->radj = radius[j];
|
||||
model->i = i;
|
||||
model->j = j;
|
||||
model->itype = itype;
|
||||
model->jtype = jtype;
|
||||
model->history_update = 0; // Don't update history
|
||||
|
||||
// If history is needed
|
||||
@ -765,7 +786,9 @@ double PairGranular::single(int i, int j, int itype, int jtype,
|
||||
model->omegaj = omega[j];
|
||||
model->history = history;
|
||||
|
||||
model->calculate_svector = 1;
|
||||
model->calculate_forces();
|
||||
model->calculate_svector = 0;
|
||||
|
||||
// apply forces & torques
|
||||
// Calculate normal component, normalized by r
|
||||
@ -785,6 +808,14 @@ double PairGranular::single(int i, int j, int itype, int jtype,
|
||||
svector[10] = model->dx[1];
|
||||
svector[11] = model->dx[2];
|
||||
|
||||
// add submodel-specific quantities
|
||||
for (int n = 0; n < model->nsvector; n++)
|
||||
svector[12 + n] = model->svector[n];
|
||||
|
||||
// zero any values unused by this specific model
|
||||
for (int n = 12 + model->nsvector; n < single_extra; n++)
|
||||
svector[n] = 0.0;
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
@ -46,6 +46,12 @@ class PairGranular : public Pair {
|
||||
double memory_usage() override;
|
||||
double atom2cut(int) override;
|
||||
double radii2cut(double, double) override;
|
||||
int get_size_history() const { return size_history; }
|
||||
|
||||
// granular models
|
||||
class Granular_NS::GranularModel** models_list;
|
||||
int **types_indices;
|
||||
int nmodels, maxmodels;
|
||||
|
||||
protected:
|
||||
int freeze_group_bit;
|
||||
@ -73,14 +79,11 @@ class PairGranular : public Pair {
|
||||
int size_history;
|
||||
int heat_flag;
|
||||
|
||||
// granular models
|
||||
int nmodels, maxmodels;
|
||||
class Granular_NS::GranularModel **models_list;
|
||||
int **types_indices;
|
||||
|
||||
// optional user-specified global cutoff, per-type user-specified cutoffs
|
||||
double **cutoff_type;
|
||||
double cutoff_global;
|
||||
|
||||
int extra_svector;
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
@ -94,7 +94,7 @@ void VerletLRTIntel::setup(int flag)
|
||||
if (comm->me == 0 && screen) {
|
||||
fputs("Setting up VerletLRTIntel run ...\n",screen);
|
||||
if (flag) {
|
||||
fmt::print(screen," Unit style : {}\n"
|
||||
utils::print(screen," Unit style : {}\n"
|
||||
" Current step : {}\n"
|
||||
" Time step : {}\n",
|
||||
update->unit_style,update->ntimestep,update->dt);
|
||||
|
||||
@ -119,6 +119,14 @@ action compute_composition_atom_kokkos.cpp compute_composition_atom.cpp
|
||||
action compute_composition_atom_kokkos.h compute_composition_atom.h
|
||||
action compute_orientorder_atom_kokkos.cpp
|
||||
action compute_orientorder_atom_kokkos.h
|
||||
action compute_sna_grid_kokkos.cpp compute_sna_grid.cpp
|
||||
action compute_sna_grid_kokkos.h compute_sna_grid.h
|
||||
action compute_sna_grid_kokkos_impl.h compute_sna_grid.cpp
|
||||
action compute_sna_grid_local_kokkos.cpp compute_sna_grid_local.cpp
|
||||
action compute_sna_grid_local_kokkos.h compute_sna_grid_local.h
|
||||
action compute_sna_grid_local_kokkos_impl.h compute_sna_grid_local.cpp
|
||||
action compute_gaussian_grid_local_kokkos.cpp compute_gaussian_grid_local.cpp
|
||||
action compute_gaussian_grid_local_kokkos.h compute_gaussian_grid_local.h
|
||||
action compute_temp_deform_kokkos.cpp
|
||||
action compute_temp_deform_kokkos.h
|
||||
action compute_temp_kokkos.cpp
|
||||
|
||||
308
src/KOKKOS/compute_gaussian_grid_local_kokkos.cpp
Normal file
308
src/KOKKOS/compute_gaussian_grid_local_kokkos.cpp
Normal file
@ -0,0 +1,308 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
LAMMPS development team: developers@lammps.org
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Drew Rohskopf (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "compute_gaussian_grid_local_kokkos.h"
|
||||
|
||||
#include "atom_kokkos.h"
|
||||
#include "atom_masks.h"
|
||||
#include "comm.h"
|
||||
#include "domain.h"
|
||||
#include "error.h"
|
||||
#include "force.h"
|
||||
#include "memory_kokkos.h"
|
||||
#include "modify.h"
|
||||
#include "neigh_list.h"
|
||||
#include "neigh_request.h"
|
||||
#include "neighbor_kokkos.h"
|
||||
#include "pair.h"
|
||||
#include "update.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType>
|
||||
ComputeGaussianGridLocalKokkos<DeviceType>::ComputeGaussianGridLocalKokkos(LAMMPS *lmp, int narg, char **arg) :
|
||||
ComputeGaussianGridLocal(lmp, narg, arg)
|
||||
{
|
||||
kokkosable = 1;
|
||||
atomKK = (AtomKokkos *) atom;
|
||||
execution_space = ExecutionSpaceFromDevice<DeviceType>::space;
|
||||
datamask_read = EMPTY_MASK;
|
||||
datamask_modify = EMPTY_MASK;
|
||||
|
||||
k_cutsq = tdual_fparams("ComputeSNAGridKokkos::cutsq",atom->ntypes+1,atom->ntypes+1);
|
||||
auto d_cutsq = k_cutsq.template view<DeviceType>();
|
||||
rnd_cutsq = d_cutsq;
|
||||
|
||||
host_flag = (execution_space == Host);
|
||||
|
||||
for (int i = 1; i <= atom->ntypes; i++) {
|
||||
for (int j = 1; j <= atom->ntypes; j++){
|
||||
k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutsq[i][j]; //cutsq_tmp;
|
||||
k_cutsq.template modify<LMPHostType>();
|
||||
}
|
||||
}
|
||||
// Set up element lists
|
||||
int n = atom->ntypes;
|
||||
MemKK::realloc_kokkos(d_radelem,"ComputeSNAGridKokkos::radelem",n);
|
||||
MemKK::realloc_kokkos(d_sigmaelem,"ComputeSNAGridKokkos::sigmaelem",n+1);
|
||||
MemKK::realloc_kokkos(d_prefacelem,"ComputeSNAGridKokkos::prefacelem",n+1);
|
||||
MemKK::realloc_kokkos(d_argfacelem,"ComputeSNAGridKokkos::argfacelem",n+1);
|
||||
MemKK::realloc_kokkos(d_map,"ComputeSNAGridKokkos::map",n+1);
|
||||
auto h_radelem = Kokkos::create_mirror_view(d_radelem);
|
||||
auto h_sigmaelem = Kokkos::create_mirror_view(d_sigmaelem);
|
||||
auto h_prefacelem = Kokkos::create_mirror_view(d_prefacelem);
|
||||
auto h_argfacelem = Kokkos::create_mirror_view(d_argfacelem);
|
||||
auto h_map = Kokkos::create_mirror_view(d_map);
|
||||
// start from index 1 because of how compute sna/grid is
|
||||
for (int i = 1; i <= atom->ntypes; i++) {
|
||||
h_radelem(i-1) = radelem[i];
|
||||
h_sigmaelem(i-1) = sigmaelem[i];
|
||||
h_prefacelem(i-1) = prefacelem[i];
|
||||
h_argfacelem(i-1) = argfacelem[i];
|
||||
}
|
||||
Kokkos::deep_copy(d_radelem,h_radelem);
|
||||
Kokkos::deep_copy(d_sigmaelem,h_sigmaelem);
|
||||
Kokkos::deep_copy(d_prefacelem, h_prefacelem);
|
||||
Kokkos::deep_copy(d_argfacelem, h_argfacelem);
|
||||
Kokkos::deep_copy(d_map,h_map);
|
||||
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType>
|
||||
ComputeGaussianGridLocalKokkos<DeviceType>::~ComputeGaussianGridLocalKokkos()
|
||||
{
|
||||
if (copymode) return;
|
||||
|
||||
memoryKK->destroy_kokkos(k_cutsq,cutsq);
|
||||
memoryKK->destroy_kokkos(k_alocal,alocal);
|
||||
//gridlocal_allocated = 0;
|
||||
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType>
|
||||
void ComputeGaussianGridLocalKokkos<DeviceType>::setup()
|
||||
{
|
||||
|
||||
ComputeGridLocal::setup();
|
||||
|
||||
// allocate arrays
|
||||
memoryKK->create_kokkos(k_alocal, alocal, size_local_rows, size_local_cols, "grid:alocal");
|
||||
array_local = alocal;
|
||||
d_alocal = k_alocal.template view<DeviceType>();
|
||||
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType>
|
||||
void ComputeGaussianGridLocalKokkos<DeviceType>::init()
|
||||
{
|
||||
ComputeGaussianGridLocal::init();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType>
|
||||
void ComputeGaussianGridLocalKokkos<DeviceType>::compute_local()
|
||||
{
|
||||
if (host_flag) {
|
||||
return;
|
||||
}
|
||||
|
||||
invoked_local = update->ntimestep;
|
||||
|
||||
copymode = 1;
|
||||
|
||||
zlen = nzhi-nzlo+1;
|
||||
ylen = nyhi-nylo+1;
|
||||
xlen = nxhi-nxlo+1;
|
||||
total_range = (nzhi-nzlo+1)*(nyhi-nylo+1)*(nxhi-nxlo+1);
|
||||
|
||||
atomKK->sync(execution_space,X_MASK|F_MASK|TYPE_MASK);
|
||||
x = atomKK->k_x.view<DeviceType>();
|
||||
type = atomKK->k_type.view<DeviceType>();
|
||||
k_cutsq.template sync<DeviceType>();
|
||||
|
||||
// max_neighs is defined here - think of more elaborate methods.
|
||||
max_neighs = 100;
|
||||
|
||||
// Pair snap/kk uses grow_ij with some max number of neighs but compute sna/grid uses total
|
||||
// number of atoms.
|
||||
ntotal = atomKK->nlocal + atomKK->nghost;
|
||||
// Allocate view for number of neighbors per grid point
|
||||
MemKK::realloc_kokkos(d_ninside,"ComputeSNAGridKokkos:ninside",total_range);
|
||||
|
||||
// "chunksize" variable is default 32768 in compute_sna_grid.cpp, and set by user
|
||||
// `total_range` is the number of grid points which may be larger than chunk size.
|
||||
// printf(">>> total_range: %d\n", total_range);
|
||||
chunksize = 32768; // 100*32768
|
||||
chunk_size = MIN(chunksize, total_range);
|
||||
chunk_offset = 0;
|
||||
|
||||
int vector_length_default = 1;
|
||||
int team_size_default = 1;
|
||||
if (!host_flag)
|
||||
team_size_default = 1; // cost will increase with increasing team size //32;//max_neighs;
|
||||
|
||||
if (triclinic){
|
||||
h0 = domain->h[0];
|
||||
h1 = domain->h[1];
|
||||
h2 = domain->h[2];
|
||||
h3 = domain->h[3];
|
||||
h4 = domain->h[4];
|
||||
h5 = domain->h[5];
|
||||
lo0 = domain->boxlo[0];
|
||||
lo1 = domain->boxlo[1];
|
||||
lo2 = domain->boxlo[2];
|
||||
}
|
||||
|
||||
while (chunk_offset < total_range) { // chunk up loop to prevent running out of memory
|
||||
|
||||
if (chunk_size > total_range - chunk_offset)
|
||||
chunk_size = total_range - chunk_offset;
|
||||
|
||||
//Neigh
|
||||
{
|
||||
int vector_length = vector_length_default;
|
||||
int team_size = team_size_default;
|
||||
check_team_size_for<TagComputeGaussianGridLocalNeigh>(chunk_size,team_size,vector_length);
|
||||
typename Kokkos::TeamPolicy<DeviceType, TagComputeGaussianGridLocalNeigh> policy_neigh(chunk_size,team_size,vector_length);
|
||||
Kokkos::parallel_for("ComputeGaussianGridLocalNeigh",policy_neigh,*this);
|
||||
}
|
||||
|
||||
// Proceed to the next chunk.
|
||||
chunk_offset += chunk_size;
|
||||
} // end while
|
||||
|
||||
copymode = 0;
|
||||
|
||||
k_alocal.template modify<DeviceType>();
|
||||
k_alocal.template sync<LMPHostType>();
|
||||
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeGaussianGridLocalKokkos<DeviceType>::operator() (TagComputeGaussianGridLocalNeigh,const typename Kokkos::TeamPolicy<DeviceType, TagComputeGaussianGridLocalNeigh>::member_type& team) const
|
||||
{
|
||||
const int ii = team.league_rank();
|
||||
|
||||
if (ii >= chunk_size) return;
|
||||
|
||||
// extract grid index
|
||||
int igrid = ii + chunk_offset;
|
||||
|
||||
// convert to grid indices
|
||||
|
||||
int iz = igrid/(xlen*ylen);
|
||||
int i2 = igrid - (iz*xlen*ylen);
|
||||
int iy = i2/xlen;
|
||||
int ix = i2 % xlen;
|
||||
iz += nzlo;
|
||||
iy += nylo;
|
||||
ix += nxlo;
|
||||
|
||||
double xgrid[3];
|
||||
|
||||
// index ii already captures the proper grid point
|
||||
//int igrid = iz * (nx * ny) + iy * nx + ix;
|
||||
|
||||
// grid2x converts igrid to ix,iy,iz like we've done before
|
||||
// multiply grid integers by grid spacing delx, dely, delz
|
||||
//grid2x(igrid, xgrid);
|
||||
xgrid[0] = ix * delx;
|
||||
xgrid[1] = iy * dely;
|
||||
xgrid[2] = iz * delz;
|
||||
|
||||
if (triclinic) {
|
||||
|
||||
// Do a conversion on `xgrid` here like we do in the CPU version.
|
||||
|
||||
// Can't do this:
|
||||
// domainKK->lamda2x(xgrid, xgrid);
|
||||
// Because calling a __host__ function("lamda2x") from a __host__ __device__ function("operator()") is not allowed
|
||||
|
||||
// Using domainKK-> gives segfault, use domain-> instead since we're just accessing floats.
|
||||
xgrid[0] = h0*xgrid[0] + h5*xgrid[1] + h4*xgrid[2] + lo0;
|
||||
xgrid[1] = h1*xgrid[1] + h3*xgrid[2] + lo1;
|
||||
xgrid[2] = h2*xgrid[2] + lo2;
|
||||
}
|
||||
|
||||
const F_FLOAT xtmp = xgrid[0];
|
||||
const F_FLOAT ytmp = xgrid[1];
|
||||
const F_FLOAT ztmp = xgrid[2];
|
||||
|
||||
// Zeroing out the components, which are filled as a sum.
|
||||
for (int icol = size_local_cols_base; icol < size_local_cols; icol++){
|
||||
d_alocal(igrid, icol) = 0.0;
|
||||
}
|
||||
|
||||
// Fill grid info columns
|
||||
d_alocal(igrid, 0) = ix;
|
||||
d_alocal(igrid, 1) = iy;
|
||||
d_alocal(igrid, 2) = iz;
|
||||
d_alocal(igrid, 3) = xtmp;
|
||||
d_alocal(igrid, 4) = ytmp;
|
||||
d_alocal(igrid, 5) = ztmp;
|
||||
|
||||
// Looping over ntotal for now.
|
||||
for (int j = 0; j < ntotal; j++){
|
||||
const F_FLOAT dx = x(j,0) - xtmp;
|
||||
const F_FLOAT dy = x(j,1) - ytmp;
|
||||
const F_FLOAT dz = x(j,2) - ztmp;
|
||||
int jtype = type(j);
|
||||
const F_FLOAT rsq = dx*dx + dy*dy + dz*dz;
|
||||
|
||||
if (rsq < rnd_cutsq(jtype, jtype) ) {
|
||||
int icol = size_local_cols_base + jtype - 1;
|
||||
d_alocal(igrid, icol) += d_prefacelem(jtype-1) * exp(-rsq * d_argfacelem(jtype-1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
check max team size
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType>
|
||||
template<class TagStyle>
|
||||
void ComputeGaussianGridLocalKokkos<DeviceType>::check_team_size_for(int inum, int &team_size, int vector_length) {
|
||||
int team_size_max;
|
||||
|
||||
team_size_max = Kokkos::TeamPolicy<DeviceType,TagStyle>(inum,Kokkos::AUTO).team_size_max(*this,Kokkos::ParallelForTag());
|
||||
|
||||
if (team_size*vector_length > team_size_max)
|
||||
team_size = team_size_max/vector_length;
|
||||
}
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
template class ComputeGaussianGridLocalKokkos<LMPDeviceType>;
|
||||
#ifdef LMP_KOKKOS_GPU
|
||||
template class ComputeGaussianGridLocalKokkos<LMPHostType>;
|
||||
#endif
|
||||
}
|
||||
96
src/KOKKOS/compute_gaussian_grid_local_kokkos.h
Normal file
96
src/KOKKOS/compute_gaussian_grid_local_kokkos.h
Normal file
@ -0,0 +1,96 @@
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
LAMMPS development team: developers@lammps.org
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef COMPUTE_CLASS
|
||||
// clang-format off
|
||||
ComputeStyle(gaussian/grid/local/kk,ComputeGaussianGridLocalKokkos<LMPDeviceType>);
|
||||
ComputeStyle(gaussian/grid/local/kk/device,ComputeGaussianGridLocalKokkos<LMPDeviceType>);
|
||||
ComputeStyle(gaussian/grid/local/kk/host,ComputeGaussianGridLocalKokkos<LMPHostType>);
|
||||
// clang-format on
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_COMPUTE_GAUSSIAN_GRID_LOCAL_KOKKOS_H
|
||||
#define LMP_COMPUTE_GAUSSIAN_GRID_LOCAL_KOKKOS_H
|
||||
|
||||
#include "compute_gaussian_grid_local.h"
|
||||
#include "kokkos_type.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
// clang-format off
|
||||
struct TagComputeGaussianGridLocalNeigh{};
|
||||
// clang-format on
|
||||
|
||||
template <class DeviceType> class ComputeGaussianGridLocalKokkos : public ComputeGaussianGridLocal {
|
||||
public:
|
||||
typedef DeviceType device_type;
|
||||
typedef ArrayTypes<DeviceType> AT;
|
||||
|
||||
// Static team/tile sizes for device offload
|
||||
|
||||
#ifdef KOKKOS_ENABLE_HIP
|
||||
static constexpr int team_size_compute_neigh = 2;
|
||||
#else
|
||||
static constexpr int team_size_compute_neigh = 4;
|
||||
#endif
|
||||
|
||||
ComputeGaussianGridLocalKokkos(class LAMMPS *, int, char **);
|
||||
~ComputeGaussianGridLocalKokkos() override;
|
||||
void setup() override;
|
||||
void init() override;
|
||||
void compute_local() override;
|
||||
|
||||
template<class TagStyle>
|
||||
void check_team_size_for(int, int&, int);
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagComputeGaussianGridLocalNeigh, const typename Kokkos::TeamPolicy<DeviceType, TagComputeGaussianGridLocalNeigh>::member_type& team) const;
|
||||
|
||||
private:
|
||||
Kokkos::View<double*, DeviceType> d_radelem; // element radii
|
||||
Kokkos::View<double*, DeviceType> d_sigmaelem;
|
||||
Kokkos::View<double*, DeviceType> d_prefacelem;
|
||||
Kokkos::View<double*, DeviceType> d_argfacelem;
|
||||
Kokkos::View<int*, DeviceType> d_ninside; // ninside for all atoms in list
|
||||
Kokkos::View<int*, DeviceType> d_map; // mapping from atom types to elements
|
||||
|
||||
typedef Kokkos::DualView<F_FLOAT**, DeviceType> tdual_fparams;
|
||||
tdual_fparams k_cutsq;
|
||||
typedef Kokkos::View<const F_FLOAT**, DeviceType,
|
||||
Kokkos::MemoryTraits<Kokkos::RandomAccess> > t_fparams_rnd;
|
||||
t_fparams_rnd rnd_cutsq;
|
||||
|
||||
|
||||
int max_neighs, inum, chunk_size, chunk_offset;
|
||||
int host_flag;
|
||||
int total_range; // total number of loop iterations in grid
|
||||
int xlen, ylen, zlen;
|
||||
int chunksize;
|
||||
int ntotal;
|
||||
|
||||
typename AT::t_x_array_randomread x;
|
||||
typename AT::t_int_1d_randomread type;
|
||||
|
||||
DAT::tdual_float_2d k_alocal;
|
||||
typename AT::t_float_2d d_alocal;
|
||||
|
||||
// triclinic vars
|
||||
double h0, h1, h2, h3, h4, h5;
|
||||
double lo0, lo1, lo2;
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
25
src/KOKKOS/compute_sna_grid_kokkos.cpp
Normal file
25
src/KOKKOS/compute_sna_grid_kokkos.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
// clang-format off
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
LAMMPS development team: developers@lammps.org
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "compute_sna_grid_kokkos.h"
|
||||
#include "compute_sna_grid_kokkos_impl.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
template class ComputeSNAGridKokkosDevice<LMPDeviceType>;
|
||||
#ifdef LMP_KOKKOS_GPU
|
||||
template class ComputeSNAGridKokkosHost<LMPHostType>;
|
||||
#endif
|
||||
|
||||
}
|
||||
297
src/KOKKOS/compute_sna_grid_kokkos.h
Normal file
297
src/KOKKOS/compute_sna_grid_kokkos.h
Normal file
@ -0,0 +1,297 @@
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
LAMMPS development team: developers@lammps.org
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef COMPUTE_CLASS
|
||||
// clang-format off
|
||||
ComputeStyle(sna/grid/kk,ComputeSNAGridKokkosDevice<LMPDeviceType>);
|
||||
ComputeStyle(sna/grid/kk/device,ComputeSNAGridKokkosDevice<LMPDeviceType>);
|
||||
#ifdef LMP_KOKKOS_GPU
|
||||
ComputeStyle(sna/grid/kk/host,ComputeSNAGridKokkosHost<LMPHostType>);
|
||||
#else
|
||||
ComputeStyle(sna/grid/kk/host,ComputeSNAGridKokkosDevice<LMPHostType>);
|
||||
#endif
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
// clang-format off
|
||||
#ifndef LMP_COMPUTE_SNA_GRID_KOKKOS_H
|
||||
#define LMP_COMPUTE_SNA_GRID_KOKKOS_H
|
||||
|
||||
#include "compute_sna_grid.h"
|
||||
#include "kokkos_type.h"
|
||||
#include "sna_kokkos.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
// Routines for both the CPU and GPU backend
|
||||
|
||||
// GPU backend only
|
||||
struct TagCSNAGridComputeNeigh{};
|
||||
struct TagCSNAGridComputeCayleyKlein{};
|
||||
struct TagCSNAGridPreUi{};
|
||||
struct TagCSNAGridComputeUiSmall{}; // more parallelism, more divergence
|
||||
struct TagCSNAGridComputeUiLarge{}; // less parallelism, no divergence
|
||||
struct TagCSNAGridTransformUi{}; // re-order ulisttot from SoA to AoSoA, zero ylist
|
||||
template <bool chemsnap> struct TagCSNAGridComputeZi{};
|
||||
template <bool chemsnap> struct TagCSNAGridComputeBi{};
|
||||
struct TagCSNAGridLocalFill{}; // fill the gridlocal array
|
||||
|
||||
struct TagComputeSNAGridLoop{};
|
||||
struct TagComputeSNAGrid3D{};
|
||||
|
||||
// CPU backend only
|
||||
struct TagComputeSNAGridLoopCPU{};
|
||||
|
||||
//template<class DeviceType>
|
||||
template<class DeviceType, typename real_type_, int vector_length_>
|
||||
class ComputeSNAGridKokkos : public ComputeSNAGrid {
|
||||
public:
|
||||
typedef DeviceType device_type;
|
||||
typedef ArrayTypes<DeviceType> AT;
|
||||
|
||||
static constexpr int vector_length = vector_length_;
|
||||
using real_type = real_type_;
|
||||
using complex = SNAComplex<real_type>;
|
||||
|
||||
// Static team/tile sizes for device offload
|
||||
|
||||
#ifdef KOKKOS_ENABLE_HIP
|
||||
static constexpr int team_size_compute_neigh = 2;
|
||||
static constexpr int tile_size_compute_ck = 2;
|
||||
static constexpr int tile_size_pre_ui = 2;
|
||||
static constexpr int team_size_compute_ui = 2;
|
||||
static constexpr int tile_size_transform_ui = 2;
|
||||
static constexpr int tile_size_compute_zi = 2;
|
||||
static constexpr int min_blocks_compute_zi = 0; // no minimum bound
|
||||
static constexpr int tile_size_compute_bi = 2;
|
||||
static constexpr int tile_size_compute_yi = 2;
|
||||
static constexpr int min_blocks_compute_yi = 0; // no minimum bound
|
||||
static constexpr int team_size_compute_fused_deidrj = 2;
|
||||
#else
|
||||
static constexpr int team_size_compute_neigh = 4;
|
||||
static constexpr int tile_size_compute_ck = 4;
|
||||
static constexpr int tile_size_pre_ui = 4;
|
||||
static constexpr int team_size_compute_ui = sizeof(real_type) == 4 ? 8 : 4;
|
||||
static constexpr int tile_size_transform_ui = 4;
|
||||
static constexpr int tile_size_compute_zi = 8;
|
||||
static constexpr int tile_size_compute_bi = 4;
|
||||
static constexpr int tile_size_compute_yi = 8;
|
||||
static constexpr int team_size_compute_fused_deidrj = sizeof(real_type) == 4 ? 4 : 2;
|
||||
|
||||
// this empirically reduces perf fluctuations from compiler version to compiler version
|
||||
static constexpr int min_blocks_compute_zi = 4;
|
||||
static constexpr int min_blocks_compute_yi = 4;
|
||||
#endif
|
||||
|
||||
// Custom MDRangePolicy, Rank3, to reduce verbosity of kernel launches
|
||||
// This hides the Kokkos::IndexType<int> and Kokkos::Rank<3...>
|
||||
// and reduces the verbosity of the LaunchBound by hiding the explicit
|
||||
// multiplication by vector_length
|
||||
template <class Device, int num_tiles, class TagComputeSNA, int min_blocks = 0>
|
||||
using Snap3DRangePolicy = typename Kokkos::MDRangePolicy<Device, Kokkos::IndexType<int>, Kokkos::Rank<3, Kokkos::Iterate::Left, Kokkos::Iterate::Left>, Kokkos::LaunchBounds<vector_length * num_tiles, min_blocks>, TagComputeSNA>;
|
||||
|
||||
// MDRangePolicy for the 3D grid loop:
|
||||
template <class Device, class TagComputeSNA>
|
||||
using CSNAGrid3DPolicy = typename Kokkos::MDRangePolicy<Device, Kokkos::IndexType<int>, Kokkos::Rank<3, Kokkos::Iterate::Left, Kokkos::Iterate::Left>>;
|
||||
|
||||
// Testing out team policies
|
||||
template <class Device, int num_teams, class TagComputeSNA>
|
||||
using CSNAGridTeamPolicy = typename Kokkos::TeamPolicy<Device, Kokkos::LaunchBounds<vector_length * num_teams>, TagComputeSNA>;
|
||||
//using CSNAGridTeamPolicy = typename Kokkos::TeamPolicy<Device, Kokkos::IndexType<int>, Kokkos::IndexType<int>, Kokkos::IndexType<int>, TagComputeSNA>;
|
||||
//using team_member = typename team_policy::member_type;
|
||||
|
||||
// Custom SnapAoSoATeamPolicy to reduce the verbosity of kernel launches
|
||||
// This hides the LaunchBounds abstraction by hiding the explicit
|
||||
// multiplication by vector length
|
||||
template <class Device, int num_teams, class TagComputeSNA>
|
||||
using SnapAoSoATeamPolicy = typename Kokkos::TeamPolicy<Device, Kokkos::LaunchBounds<vector_length * num_teams>, TagComputeSNA>;
|
||||
|
||||
// Helper routine that returns a CPU or a GPU policy as appropriate
|
||||
template <class Device, int num_tiles, class TagComputeSNA, int min_blocks = 0>
|
||||
auto snap_get_policy(const int& chunk_size_div, const int& second_loop) {
|
||||
return Snap3DRangePolicy<Device, num_tiles, TagComputeSNA, min_blocks>({0, 0, 0},
|
||||
{vector_length, second_loop, chunk_size_div},
|
||||
{vector_length, num_tiles, 1});
|
||||
}
|
||||
|
||||
ComputeSNAGridKokkos(class LAMMPS *, int, char **);
|
||||
~ComputeSNAGridKokkos() override;
|
||||
|
||||
void setup() override;
|
||||
void compute_array() override;
|
||||
|
||||
// Utility functions for teams
|
||||
|
||||
template<class TagStyle>
|
||||
void check_team_size_for(int, int&);
|
||||
|
||||
template<class TagStyle>
|
||||
void check_team_size_reduce(int, int&);
|
||||
|
||||
// operator function for example team policy
|
||||
//KOKKOS_INLINE_FUNCTION
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagComputeSNAGridLoop, const int& ) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagComputeSNAGridLoopCPU, const int&) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridComputeNeigh,const typename Kokkos::TeamPolicy<DeviceType, TagCSNAGridComputeNeigh>::member_type& team) const;
|
||||
|
||||
// 3D case - used by parallel_for
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator()(TagComputeSNAGrid3D, const int& iz, const int& iy, const int& ix) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridComputeCayleyKlein, const int iatom_mod, const int jnbor, const int iatom_div) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridPreUi, const int& iatom_mod, const int& j, const int& iatom_div) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridPreUi, const int& iatom, const int& j) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridPreUi, const int& iatom) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridComputeUiSmall,const typename Kokkos::TeamPolicy<DeviceType, TagCSNAGridComputeUiSmall>::member_type& team) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridComputeUiLarge,const typename Kokkos::TeamPolicy<DeviceType, TagCSNAGridComputeUiLarge>::member_type& team) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridTransformUi, const int& iatom_mod, const int& idxu, const int& iatom_div) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridTransformUi, const int& iatom, const int& idxu) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridTransformUi, const int& iatom) const;
|
||||
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridComputeZi<chemsnap>, const int& iatom_mod, const int& idxz, const int& iatom_div) const;
|
||||
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridComputeZi<chemsnap>, const int& iatom, const int& idxz) const;
|
||||
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridComputeZi<chemsnap>, const int& iatom) const;
|
||||
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridComputeBi<chemsnap>, const int& iatom_mod, const int& idxb, const int& iatom_div) const;
|
||||
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridComputeBi<chemsnap>, const int& iatom, const int& idxb) const;
|
||||
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridComputeBi<chemsnap>, const int& iatom) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocalFill,const int& ii) const;
|
||||
|
||||
protected:
|
||||
|
||||
SNAKokkos<DeviceType, real_type, vector_length> snaKK;
|
||||
|
||||
int max_neighs, chunk_size, chunk_offset;
|
||||
int host_flag;
|
||||
int ntotal;
|
||||
int total_range; // total number of loop iterations in grid
|
||||
int zlen; //= nzhi-nzlo+1;
|
||||
int ylen; //= nyhi-nylo+1;
|
||||
int xlen; //= nxhi-nxlo+1;
|
||||
|
||||
double cutsq_tmp; // temporary cutsq until we get a view
|
||||
|
||||
Kokkos::View<real_type*, DeviceType> d_radelem; // element radii
|
||||
Kokkos::View<real_type*, DeviceType> d_wjelem; // elements weights
|
||||
Kokkos::View<real_type**, Kokkos::LayoutRight, DeviceType> d_coeffelem; // element bispectrum coefficients
|
||||
Kokkos::View<real_type*, DeviceType> d_sinnerelem; // element inner cutoff midpoint
|
||||
Kokkos::View<real_type*, DeviceType> d_dinnerelem; // element inner cutoff half-width
|
||||
Kokkos::View<T_INT*, DeviceType> d_ninside; // ninside for all atoms in list
|
||||
Kokkos::View<T_INT*, DeviceType> d_map; // mapping from atom types to elements
|
||||
Kokkos::View<real_type*, DeviceType> d_test; // test view
|
||||
|
||||
typedef Kokkos::DualView<F_FLOAT**, DeviceType> tdual_fparams;
|
||||
tdual_fparams k_cutsq;
|
||||
typedef Kokkos::View<const F_FLOAT**, DeviceType,
|
||||
Kokkos::MemoryTraits<Kokkos::RandomAccess> > t_fparams_rnd;
|
||||
t_fparams_rnd rnd_cutsq;
|
||||
|
||||
typename AT::t_x_array_randomread x;
|
||||
typename AT::t_int_1d_randomread type;
|
||||
DAT::tdual_float_2d k_grid;
|
||||
DAT::tdual_float_2d k_gridall;
|
||||
typename AT::t_float_2d d_grid;
|
||||
typename AT::t_float_2d d_gridall;
|
||||
|
||||
DAT::tdual_float_4d k_gridlocal;
|
||||
typename AT::t_float_4d d_gridlocal;
|
||||
|
||||
|
||||
// Utility routine which wraps computing per-team scratch size requirements for
|
||||
// ComputeNeigh, ComputeUi, and ComputeFusedDeidrj
|
||||
template <typename scratch_type>
|
||||
int scratch_size_helper(int values_per_team);
|
||||
|
||||
class DomainKokkos *domainKK;
|
||||
|
||||
// triclinic vars
|
||||
double h0, h1, h2, h3, h4, h5;
|
||||
double lo0, lo1, lo2;
|
||||
|
||||
// Make SNAKokkos a friend
|
||||
friend class SNAKokkos<DeviceType, real_type, vector_length>;
|
||||
};
|
||||
|
||||
// These wrapper classes exist to make the compute style factory happy/avoid having
|
||||
// to extend the compute style factory to support Compute classes w/an arbitrary number
|
||||
// of extra template parameters
|
||||
|
||||
template <class DeviceType>
|
||||
class ComputeSNAGridKokkosDevice : public ComputeSNAGridKokkos<DeviceType, SNAP_KOKKOS_REAL, SNAP_KOKKOS_DEVICE_VECLEN> {
|
||||
|
||||
private:
|
||||
using Base = ComputeSNAGridKokkos<DeviceType, SNAP_KOKKOS_REAL, SNAP_KOKKOS_DEVICE_VECLEN>;
|
||||
|
||||
public:
|
||||
|
||||
ComputeSNAGridKokkosDevice(class LAMMPS *, int, char **);
|
||||
|
||||
void compute_array() override;
|
||||
|
||||
};
|
||||
|
||||
#ifdef LMP_KOKKOS_GPU
|
||||
template <class DeviceType>
|
||||
class ComputeSNAGridKokkosHost : public ComputeSNAGridKokkos<DeviceType, SNAP_KOKKOS_REAL, SNAP_KOKKOS_HOST_VECLEN> {
|
||||
|
||||
private:
|
||||
using Base = ComputeSNAGridKokkos<DeviceType, SNAP_KOKKOS_REAL, SNAP_KOKKOS_HOST_VECLEN>;
|
||||
|
||||
public:
|
||||
|
||||
ComputeSNAGridKokkosHost(class LAMMPS *, int, char **);
|
||||
|
||||
void compute_array() override;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
786
src/KOKKOS/compute_sna_grid_kokkos_impl.h
Normal file
786
src/KOKKOS/compute_sna_grid_kokkos_impl.h
Normal file
@ -0,0 +1,786 @@
|
||||
// clang-format off
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
LAMMPS development team: developers@lammps.org
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing authors: Christian Trott (SNL), Stan Moore (SNL),
|
||||
Evan Weinberg (NVIDIA)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "compute_sna_grid_kokkos.h"
|
||||
#include "pair_snap_kokkos.h"
|
||||
|
||||
#include "atom_kokkos.h"
|
||||
#include "atom_masks.h"
|
||||
#include "comm.h"
|
||||
#include "error.h"
|
||||
#include "memory_kokkos.h"
|
||||
#include "modify.h"
|
||||
#include "neigh_list.h"
|
||||
#include "neigh_request.h"
|
||||
#include "neighbor_kokkos.h"
|
||||
#include "domain.h"
|
||||
#include "domain_kokkos.h"
|
||||
#include "sna.h"
|
||||
#include "update.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#define MAXLINE 1024
|
||||
#define MAXWORD 3
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
// Constructor
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::ComputeSNAGridKokkos(LAMMPS *lmp, int narg, char **arg) : ComputeSNAGrid(lmp, narg, arg)
|
||||
{
|
||||
kokkosable = 1;
|
||||
atomKK = (AtomKokkos *) atom;
|
||||
domainKK = (DomainKokkos *) domain;
|
||||
execution_space = ExecutionSpaceFromDevice<DeviceType>::space;
|
||||
datamask_read = EMPTY_MASK;
|
||||
datamask_modify = EMPTY_MASK;
|
||||
|
||||
k_cutsq = tdual_fparams("ComputeSNAGridKokkos::cutsq",atom->ntypes+1,atom->ntypes+1);
|
||||
auto d_cutsq = k_cutsq.template view<DeviceType>();
|
||||
rnd_cutsq = d_cutsq;
|
||||
|
||||
host_flag = (execution_space == Host);
|
||||
|
||||
// TODO: Extract cutsq in double loop below, no need for cutsq_tmp
|
||||
|
||||
cutsq_tmp = cutsq[1][1];
|
||||
|
||||
for (int i = 1; i <= atom->ntypes; i++) {
|
||||
for (int j = 1; j <= atom->ntypes; j++){
|
||||
k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutsq_tmp;
|
||||
k_cutsq.template modify<LMPHostType>();
|
||||
}
|
||||
}
|
||||
|
||||
// Set up element lists
|
||||
MemKK::realloc_kokkos(d_radelem,"ComputeSNAGridKokkos::radelem",nelements);
|
||||
MemKK::realloc_kokkos(d_wjelem,"ComputeSNAGridKokkos:wjelem",nelements);
|
||||
MemKK::realloc_kokkos(d_sinnerelem,"ComputeSNAGridKokkos:sinnerelem",nelements);
|
||||
MemKK::realloc_kokkos(d_dinnerelem,"ComputeSNAGridKokkos:dinnerelem",nelements);
|
||||
// test
|
||||
MemKK::realloc_kokkos(d_test, "ComputeSNAGridKokkos::test", nelements);
|
||||
|
||||
int n = atom->ntypes;
|
||||
MemKK::realloc_kokkos(d_map,"ComputeSNAGridKokkos::map",n+1);
|
||||
|
||||
auto h_radelem = Kokkos::create_mirror_view(d_radelem);
|
||||
auto h_wjelem = Kokkos::create_mirror_view(d_wjelem);
|
||||
auto h_sinnerelem = Kokkos::create_mirror_view(d_sinnerelem);
|
||||
auto h_dinnerelem = Kokkos::create_mirror_view(d_dinnerelem);
|
||||
auto h_map = Kokkos::create_mirror_view(d_map);
|
||||
// test
|
||||
auto h_test = Kokkos::create_mirror_view(d_test);
|
||||
h_test(0) = 2.0;
|
||||
|
||||
// start from index 1 because of how compute sna/grid is
|
||||
for (int i = 1; i <= atom->ntypes; i++) {
|
||||
h_radelem(i-1) = radelem[i];
|
||||
h_wjelem(i-1) = wjelem[i];
|
||||
if (switchinnerflag){
|
||||
h_sinnerelem(i) = sinnerelem[i];
|
||||
h_dinnerelem(i) = dinnerelem[i];
|
||||
}
|
||||
}
|
||||
|
||||
// In pair snap some things like `map` get allocated regardless of chem flag.
|
||||
if (chemflag){
|
||||
for (int i = 1; i <= atom->ntypes; i++) {
|
||||
h_map(i) = map[i];
|
||||
}
|
||||
}
|
||||
|
||||
Kokkos::deep_copy(d_radelem,h_radelem);
|
||||
Kokkos::deep_copy(d_wjelem,h_wjelem);
|
||||
if (switchinnerflag){
|
||||
Kokkos::deep_copy(d_sinnerelem,h_sinnerelem);
|
||||
Kokkos::deep_copy(d_dinnerelem,h_dinnerelem);
|
||||
}
|
||||
if (chemflag){
|
||||
Kokkos::deep_copy(d_map,h_map);
|
||||
}
|
||||
Kokkos::deep_copy(d_test,h_test);
|
||||
|
||||
snaKK = SNAKokkos<DeviceType, real_type, vector_length>(*this);
|
||||
snaKK.grow_rij(0,0);
|
||||
snaKK.init();
|
||||
}
|
||||
|
||||
// Destructor
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::~ComputeSNAGridKokkos()
|
||||
{
|
||||
if (copymode) return;
|
||||
|
||||
memoryKK->destroy_kokkos(k_cutsq,cutsq);
|
||||
memoryKK->destroy_kokkos(k_gridall, gridall);
|
||||
}
|
||||
|
||||
// Setup
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::setup()
|
||||
{
|
||||
// Do not call ComputeGrid::setup(), we don't wanna allocate the grid array there.
|
||||
// Instead, call ComputeGrid::set_grid_global and set_grid_local to set the n indices.
|
||||
|
||||
ComputeGrid::set_grid_global();
|
||||
ComputeGrid::set_grid_local();
|
||||
|
||||
// allocate arrays
|
||||
memoryKK->create_kokkos(k_gridall, gridall, size_array_rows, size_array_cols, "grid:gridall");
|
||||
|
||||
// do not use or allocate gridlocal for now
|
||||
|
||||
gridlocal_allocated = 0;
|
||||
array = gridall;
|
||||
|
||||
d_gridlocal = k_gridlocal.template view<DeviceType>();
|
||||
d_gridall = k_gridall.template view<DeviceType>();
|
||||
}
|
||||
|
||||
// Compute
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::compute_array()
|
||||
{
|
||||
if (host_flag) {
|
||||
ComputeSNAGrid::compute_array();
|
||||
return;
|
||||
}
|
||||
|
||||
copymode = 1;
|
||||
|
||||
zlen = nzhi-nzlo+1;
|
||||
ylen = nyhi-nylo+1;
|
||||
xlen = nxhi-nxlo+1;
|
||||
total_range = (nzhi-nzlo+1)*(nyhi-nylo+1)*(nxhi-nxlo+1);
|
||||
|
||||
atomKK->sync(execution_space,X_MASK|F_MASK|TYPE_MASK);
|
||||
x = atomKK->k_x.view<DeviceType>();
|
||||
type = atomKK->k_type.view<DeviceType>();
|
||||
k_cutsq.template sync<DeviceType>();
|
||||
|
||||
// max_neighs is defined here - think of more elaborate methods.
|
||||
max_neighs = 100;
|
||||
|
||||
// Pair snap/kk uses grow_ij with some max number of neighs but compute sna/grid uses total
|
||||
// number of atoms.
|
||||
|
||||
ntotal = atomKK->nlocal + atomKK->nghost;
|
||||
// Allocate view for number of neighbors per grid point
|
||||
MemKK::realloc_kokkos(d_ninside,"ComputeSNAGridKokkos:ninside",total_range);
|
||||
|
||||
// "chunksize" variable is default 32768 in compute_sna_grid.cpp, and set by user
|
||||
// `total_range` is the number of grid points which may be larger than chunk size.
|
||||
chunk_size = MIN(chunksize, total_range);
|
||||
chunk_offset = 0;
|
||||
snaKK.grow_rij(chunk_size, max_neighs);
|
||||
|
||||
// Pre-compute ceil(chunk_size / vector_length) for code cleanliness
|
||||
const int chunk_size_div = (chunk_size + vector_length - 1) / vector_length;
|
||||
|
||||
if (triclinic) {
|
||||
h0 = domain->h[0];
|
||||
h1 = domain->h[1];
|
||||
h2 = domain->h[2];
|
||||
h3 = domain->h[3];
|
||||
h4 = domain->h[4];
|
||||
h5 = domain->h[5];
|
||||
lo0 = domain->boxlo[0];
|
||||
lo1 = domain->boxlo[1];
|
||||
lo2 = domain->boxlo[2];
|
||||
}
|
||||
|
||||
while (chunk_offset < total_range) { // chunk up loop to prevent running out of memory
|
||||
|
||||
if (chunk_size > total_range - chunk_offset)
|
||||
chunk_size = total_range - chunk_offset;
|
||||
|
||||
|
||||
//ComputeNeigh
|
||||
{
|
||||
int scratch_size = scratch_size_helper<int>(team_size_compute_neigh * max_neighs); //ntotal);
|
||||
|
||||
SnapAoSoATeamPolicy<DeviceType, team_size_compute_neigh, TagCSNAGridComputeNeigh>
|
||||
policy_neigh(chunk_size, team_size_compute_neigh, vector_length);
|
||||
policy_neigh = policy_neigh.set_scratch_size(0, Kokkos::PerTeam(scratch_size));
|
||||
Kokkos::parallel_for("ComputeNeigh",policy_neigh,*this);
|
||||
}
|
||||
|
||||
//ComputeCayleyKlein
|
||||
{
|
||||
// tile_size_compute_ck is defined in `compute_sna_grid_kokkos.h`
|
||||
Snap3DRangePolicy<DeviceType, tile_size_compute_ck, TagCSNAGridComputeCayleyKlein>
|
||||
policy_compute_ck({0,0,0}, {vector_length, max_neighs, chunk_size_div}, {vector_length, tile_size_compute_ck, 1});
|
||||
Kokkos::parallel_for("ComputeCayleyKlein", policy_compute_ck, *this);
|
||||
}
|
||||
|
||||
//PreUi
|
||||
{
|
||||
auto policy_pre_ui = snap_get_policy<DeviceType, tile_size_pre_ui, TagCSNAGridPreUi>(chunk_size_div, twojmax + 1);
|
||||
Kokkos::parallel_for("PreUi", policy_pre_ui, *this);
|
||||
}
|
||||
|
||||
// ComputeUi w/ vector parallelism, shared memory, direct atomicAdd into ulisttot
|
||||
{
|
||||
// team_size_compute_ui is defined in `compute_sna_grid_kokkos.h`
|
||||
// scratch size: 32 atoms * (twojmax+1) cached values, no double buffer
|
||||
const int tile_size = vector_length * (twojmax + 1);
|
||||
const int scratch_size = scratch_size_helper<complex>(team_size_compute_ui * tile_size);
|
||||
|
||||
if (chunk_size < parallel_thresh)
|
||||
{
|
||||
// Version with parallelism over j_bend
|
||||
|
||||
// total number of teams needed: (natoms / 32) * (ntotal) * ("bend" locations)
|
||||
const int n_teams = chunk_size_div * max_neighs * (twojmax + 1);
|
||||
const int n_teams_div = (n_teams + team_size_compute_ui - 1) / team_size_compute_ui;
|
||||
|
||||
SnapAoSoATeamPolicy<DeviceType, team_size_compute_ui, TagCSNAGridComputeUiSmall>
|
||||
policy_ui(n_teams_div, team_size_compute_ui, vector_length);
|
||||
policy_ui = policy_ui.set_scratch_size(0, Kokkos::PerTeam(scratch_size));
|
||||
Kokkos::parallel_for("ComputeUiSmall", policy_ui, *this);
|
||||
} else {
|
||||
// Version w/out parallelism over j_bend
|
||||
|
||||
// total number of teams needed: (natoms / 32) * (ntotal)
|
||||
const int n_teams = chunk_size_div * max_neighs;
|
||||
const int n_teams_div = (n_teams + team_size_compute_ui - 1) / team_size_compute_ui;
|
||||
|
||||
SnapAoSoATeamPolicy<DeviceType, team_size_compute_ui, TagCSNAGridComputeUiLarge>
|
||||
policy_ui(n_teams_div, team_size_compute_ui, vector_length);
|
||||
policy_ui = policy_ui.set_scratch_size(0, Kokkos::PerTeam(scratch_size));
|
||||
Kokkos::parallel_for("ComputeUiLarge", policy_ui, *this);
|
||||
}
|
||||
}
|
||||
|
||||
//TransformUi: un-"fold" ulisttot, zero ylist
|
||||
{
|
||||
// Expand ulisttot_re,_im -> ulisttot
|
||||
// Zero out ylist
|
||||
auto policy_transform_ui = snap_get_policy<DeviceType, tile_size_transform_ui, TagCSNAGridTransformUi>(chunk_size_div, snaKK.idxu_max);
|
||||
Kokkos::parallel_for("TransformUi", policy_transform_ui, *this);
|
||||
}
|
||||
|
||||
//Compute bispectrum
|
||||
// team_size_[compute_zi, compute_bi, transform_bi] are defined in `pair_snap_kokkos.h`
|
||||
|
||||
//ComputeZi and Bi
|
||||
if (nelements > 1) {
|
||||
auto policy_compute_zi = snap_get_policy<DeviceType, tile_size_compute_zi, TagCSNAGridComputeZi<true>, min_blocks_compute_zi>(chunk_size_div, snaKK.idxz_max);
|
||||
Kokkos::parallel_for("ComputeZiChemsnap", policy_compute_zi, *this);
|
||||
|
||||
auto policy_compute_bi = snap_get_policy<DeviceType, tile_size_compute_bi, TagCSNAGridComputeBi<true>>(chunk_size_div, snaKK.idxb_max);
|
||||
Kokkos::parallel_for("ComputeBiChemsnap", policy_compute_bi, *this);
|
||||
} else {
|
||||
auto policy_compute_zi = snap_get_policy<DeviceType, tile_size_compute_zi, TagCSNAGridComputeZi<false>, min_blocks_compute_zi>(chunk_size_div, snaKK.idxz_max);
|
||||
Kokkos::parallel_for("ComputeZi", policy_compute_zi, *this);
|
||||
|
||||
auto policy_compute_bi = snap_get_policy<DeviceType, tile_size_compute_bi, TagCSNAGridComputeBi<false>>(chunk_size_div, snaKK.idxb_max);
|
||||
Kokkos::parallel_for("ComputeBi", policy_compute_bi, *this);
|
||||
}
|
||||
|
||||
// Fill the grid array with bispectrum values
|
||||
{
|
||||
typename Kokkos::RangePolicy<DeviceType,TagCSNAGridLocalFill> policy_fill(0,chunk_size);
|
||||
Kokkos::parallel_for(policy_fill, *this);
|
||||
}
|
||||
|
||||
// Proceed to the next chunk.
|
||||
chunk_offset += chunk_size;
|
||||
|
||||
} // end while
|
||||
|
||||
copymode = 0;
|
||||
|
||||
k_gridlocal.template modify<DeviceType>();
|
||||
k_gridlocal.template sync<LMPHostType>();
|
||||
|
||||
k_gridall.template modify<DeviceType>();
|
||||
k_gridall.template sync<LMPHostType>();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Begin routines that are unique to the GPU codepath. These take advantage
|
||||
of AoSoA data layouts and scratch memory for recursive polynomials
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
Simple team policy functor seeing how many layers deep we can go with the parallelism.
|
||||
*/
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridComputeNeigh,const typename Kokkos::TeamPolicy<DeviceType,TagCSNAGridComputeNeigh>::member_type& team) const {
|
||||
|
||||
// This function follows similar procedure as ComputeNeigh of PairSNAPKokkos.
|
||||
// Main difference is that we don't use the neighbor class or neighbor variables here.
|
||||
// This is because the grid points are not atoms and therefore do not get assigned
|
||||
// neighbors in LAMMPS.
|
||||
// TODO: If we did make a neighborlist for each grid point, we could use current
|
||||
// routines and avoid having to loop over all atoms (which limits us to
|
||||
// natoms = max team size).
|
||||
|
||||
// basic quantities associated with this team:
|
||||
// team_rank : rank of thread in this team
|
||||
// league_rank : rank of team in this league
|
||||
// team_size : number of threads in this team
|
||||
|
||||
// extract loop index
|
||||
int ii = team.team_rank() + team.league_rank() * team.team_size();
|
||||
|
||||
if (ii >= chunk_size) return;
|
||||
|
||||
// extract grid index
|
||||
int igrid = ii + chunk_offset;
|
||||
|
||||
// get a pointer to scratch memory
|
||||
// This is used to cache whether or not an atom is within the cutoff.
|
||||
// If it is, type_cache is assigned to the atom type.
|
||||
// If it's not, it's assigned to -1.
|
||||
//const int tile_size = ntotal; //max_neighs; // number of elements per thread
|
||||
//const int team_rank = team.team_rank();
|
||||
//const int scratch_shift = team_rank * tile_size; // offset into pointer for entire team
|
||||
//int* type_cache = (int*)team.team_shmem().get_shmem(team.team_size() * tile_size * sizeof(int), 0) + scratch_shift;
|
||||
|
||||
// convert to grid indices
|
||||
|
||||
int iz = igrid/(xlen*ylen);
|
||||
int i2 = igrid - (iz*xlen*ylen);
|
||||
int iy = i2/xlen;
|
||||
int ix = i2 % xlen;
|
||||
iz += nzlo;
|
||||
iy += nylo;
|
||||
ix += nxlo;
|
||||
|
||||
double xgrid[3];
|
||||
|
||||
// index ii already captures the proper grid point
|
||||
//int igrid = iz * (nx * ny) + iy * nx + ix;
|
||||
|
||||
// grid2x converts igrid to ix,iy,iz like we've done before
|
||||
// multiply grid integers by grid spacing delx, dely, delz
|
||||
//grid2x(igrid, xgrid);
|
||||
xgrid[0] = ix * delx;
|
||||
xgrid[1] = iy * dely;
|
||||
xgrid[2] = iz * delz;
|
||||
|
||||
if (triclinic) {
|
||||
|
||||
// Do a conversion on `xgrid` here like we do in the CPU version.
|
||||
|
||||
// Can't do this:
|
||||
// domainKK->lamda2x(xgrid, xgrid);
|
||||
// Because calling a __host__ function("lamda2x") from a __host__ __device__ function("operator()") is not allowed
|
||||
|
||||
// Using domainKK-> gives segfault, use domain-> instead since we're just accessing floats.
|
||||
xgrid[0] = h0*xgrid[0] + h5*xgrid[1] + h4*xgrid[2] + lo0;
|
||||
xgrid[1] = h1*xgrid[1] + h3*xgrid[2] + lo1;
|
||||
xgrid[2] = h2*xgrid[2] + lo2;
|
||||
}
|
||||
|
||||
const F_FLOAT xtmp = xgrid[0];
|
||||
const F_FLOAT ytmp = xgrid[1];
|
||||
const F_FLOAT 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;
|
||||
if (chemflag) ielem = d_map[itype];
|
||||
//const double radi = d_radelem[ielem];
|
||||
|
||||
// Compute the number of neighbors, store rsq
|
||||
int ninside = 0;
|
||||
|
||||
// Looping over ntotal for now.
|
||||
for (int j = 0; j < ntotal; j++){
|
||||
const F_FLOAT dx = x(j,0) - xtmp;
|
||||
const F_FLOAT dy = x(j,1) - ytmp;
|
||||
const F_FLOAT dz = x(j,2) - ztmp;
|
||||
int jtype = type(j);
|
||||
const F_FLOAT rsq = dx*dx + dy*dy + dz*dz;
|
||||
|
||||
// don't include atoms that share location with grid point
|
||||
if (rsq >= rnd_cutsq(itype,jtype) || rsq < 1e-20) {
|
||||
jtype = -1; // use -1 to signal it's outside the radius
|
||||
}
|
||||
|
||||
if (jtype >= 0)
|
||||
ninside++;
|
||||
}
|
||||
|
||||
d_ninside(ii) = ninside;
|
||||
|
||||
// TODO: Adjust for multi-element, currently we set jelem = 0 regardless of type.
|
||||
int offset = 0;
|
||||
for (int j = 0; j < ntotal; j++){
|
||||
//const int jtype = type_cache[j];
|
||||
//if (jtype >= 0) {
|
||||
const F_FLOAT dx = x(j,0) - xtmp;
|
||||
const F_FLOAT dy = x(j,1) - ytmp;
|
||||
const F_FLOAT dz = x(j,2) - ztmp;
|
||||
const F_FLOAT rsq = dx*dx + dy*dy + dz*dz;
|
||||
int jtype = type(j);
|
||||
if (rsq < rnd_cutsq(itype,jtype) && rsq > 1e-20) {
|
||||
int jelem = 0;
|
||||
if (chemflag) jelem = d_map[jtype];
|
||||
snaKK.rij(ii,offset,0) = static_cast<real_type>(dx);
|
||||
snaKK.rij(ii,offset,1) = static_cast<real_type>(dy);
|
||||
snaKK.rij(ii,offset,2) = static_cast<real_type>(dz);
|
||||
// pair snap uses jelem here, but we use jtype, see compute_sna_grid.cpp
|
||||
// actually since the views here have values starting at 0, let's use jelem
|
||||
snaKK.wj(ii,offset) = static_cast<real_type>(d_wjelem[jelem]);
|
||||
snaKK.rcutij(ii,offset) = static_cast<real_type>((2.0 * d_radelem[jelem])*rcutfac);
|
||||
snaKK.inside(ii,offset) = j;
|
||||
if (switchinnerflag) {
|
||||
snaKK.sinnerij(ii,offset) = 0.5*(d_sinnerelem[ielem] + d_sinnerelem[jelem]);
|
||||
snaKK.dinnerij(ii,offset) = 0.5*(d_dinnerelem[ielem] + d_dinnerelem[jelem]);
|
||||
}
|
||||
if (chemflag)
|
||||
snaKK.element(ii,offset) = jelem;
|
||||
else
|
||||
snaKK.element(ii,offset) = 0;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Pre-compute the Cayley-Klein parameters for reuse in later routines
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridComputeCayleyKlein,const int iatom_mod, const int jnbor, const int iatom_div) const {
|
||||
|
||||
const int iatom = iatom_mod + iatom_div * vector_length;
|
||||
if (iatom >= chunk_size) return;
|
||||
|
||||
const int ninside = d_ninside(iatom);
|
||||
if (jnbor >= ninside) return;
|
||||
|
||||
snaKK.compute_cayley_klein(iatom, jnbor);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Initialize the "ulisttot" structure with non-zero on-diagonal terms
|
||||
and zero terms elsewhere
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridPreUi, const int& iatom_mod, const int& j, const int& iatom_div) const {
|
||||
const int iatom = iatom_mod + iatom_div * vector_length;
|
||||
if (iatom >= chunk_size) return;
|
||||
|
||||
int itype = type(iatom);
|
||||
int ielem = d_map[itype];
|
||||
|
||||
snaKK.pre_ui(iatom, j, ielem);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridPreUi, const int& iatom, const int& j) const {
|
||||
if (iatom >= chunk_size) return;
|
||||
|
||||
int itype = type(iatom);
|
||||
int ielem = d_map[itype];
|
||||
|
||||
snaKK.pre_ui(iatom, j, ielem);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridPreUi, const int& iatom) const {
|
||||
if (iatom >= chunk_size) return;
|
||||
|
||||
const int itype = type(iatom);
|
||||
const int ielem = d_map[itype];
|
||||
|
||||
for (int j = 0; j <= twojmax; j++)
|
||||
snaKK.pre_ui(iatom, j, ielem);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridComputeUiSmall,const typename Kokkos::TeamPolicy<DeviceType,TagCSNAGridComputeUiSmall>::member_type& team) const {
|
||||
|
||||
// extract flattened atom_div / neighbor number / bend location
|
||||
int flattened_idx = team.team_rank() + team.league_rank() * team_size_compute_ui;
|
||||
|
||||
// extract neighbor index, iatom_div
|
||||
int iatom_div = flattened_idx / (max_neighs * (twojmax + 1)); // removed "const" to work around GCC 7 bug
|
||||
const int jj_jbend = flattened_idx - iatom_div * (max_neighs * (twojmax + 1));
|
||||
const int jbend = jj_jbend / max_neighs;
|
||||
int jj = jj_jbend - jbend * max_neighs; // removed "const" to work around GCC 7 bug
|
||||
|
||||
Kokkos::parallel_for(Kokkos::ThreadVectorRange(team, vector_length),
|
||||
[&] (const int iatom_mod) {
|
||||
const int ii = iatom_mod + vector_length * iatom_div;
|
||||
if (ii >= chunk_size) return;
|
||||
|
||||
const int ninside = d_ninside(ii);
|
||||
if (jj >= ninside) return;
|
||||
|
||||
snaKK.compute_ui_small(team, iatom_mod, jbend, jj, iatom_div);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridComputeUiLarge,const typename Kokkos::TeamPolicy<DeviceType,TagCSNAGridComputeUiLarge>::member_type& team) const {
|
||||
|
||||
// extract flattened atom_div / neighbor number / bend location
|
||||
int flattened_idx = team.team_rank() + team.league_rank() * team_size_compute_ui;
|
||||
|
||||
// extract neighbor index, iatom_div
|
||||
int iatom_div = flattened_idx / max_neighs; // removed "const" to work around GCC 7 bug
|
||||
int jj = flattened_idx - iatom_div * max_neighs;
|
||||
|
||||
Kokkos::parallel_for(Kokkos::ThreadVectorRange(team, vector_length),
|
||||
[&] (const int iatom_mod) {
|
||||
const int ii = iatom_mod + vector_length * iatom_div;
|
||||
if (ii >= chunk_size) return;
|
||||
|
||||
const int ninside = d_ninside(ii);
|
||||
if (jj >= ninside) return;
|
||||
|
||||
snaKK.compute_ui_large(team,iatom_mod, jj, iatom_div);
|
||||
});
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
De-symmetrize ulisttot_re and _im and pack it into a unified ulisttot
|
||||
structure. Zero-initialize ylist. CPU and GPU.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridTransformUi, const int& iatom_mod, const int& idxu, const int& iatom_div) const {
|
||||
const int iatom = iatom_mod + iatom_div * vector_length;
|
||||
if (iatom >= chunk_size) return;
|
||||
if (idxu >= snaKK.idxu_max) return;
|
||||
snaKK.transform_ui(iatom, idxu);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridTransformUi, const int& iatom, const int& idxu) const {
|
||||
if (iatom >= chunk_size) return;
|
||||
snaKK.transform_ui(iatom, idxu);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridTransformUi, const int& iatom) const {
|
||||
if (iatom >= chunk_size) return;
|
||||
for (int idxu = 0; idxu < snaKK.idxu_max; idxu++)
|
||||
snaKK.transform_ui(iatom, idxu);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Compute all elements of the Z tensor and store them into the `zlist`
|
||||
view
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridComputeZi<chemsnap>, const int& iatom_mod, const int& jjz, const int& iatom_div) const {
|
||||
const int iatom = iatom_mod + iatom_div * vector_length;
|
||||
if (iatom >= chunk_size) return;
|
||||
if (jjz >= snaKK.idxz_max) return;
|
||||
snaKK.template compute_zi<chemsnap>(iatom, jjz);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridComputeZi<chemsnap>, const int& iatom, const int& jjz) const {
|
||||
if (iatom >= chunk_size) return;
|
||||
snaKK.template compute_zi<chemsnap>(iatom, jjz);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridComputeZi<chemsnap>, const int& iatom) const {
|
||||
if (iatom >= chunk_size) return;
|
||||
for (int jjz = 0; jjz < snaKK.idxz_max; jjz++)
|
||||
snaKK.template compute_zi<chemsnap>(iatom, jjz);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Compute the energy triple products and store in the "blist" view
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridComputeBi<chemsnap>, const int& iatom_mod, const int& jjb, const int& iatom_div) const {
|
||||
const int iatom = iatom_mod + iatom_div * vector_length;
|
||||
if (iatom >= chunk_size) return;
|
||||
if (jjb >= snaKK.idxb_max) return;
|
||||
snaKK.template compute_bi<chemsnap>(iatom, jjb);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridComputeBi<chemsnap>, const int& iatom, const int& jjb) const {
|
||||
if (iatom >= chunk_size) return;
|
||||
snaKK.template compute_bi<chemsnap>(iatom, jjb);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridComputeBi<chemsnap>, const int& iatom) const {
|
||||
if (iatom >= chunk_size) return;
|
||||
for (int jjb = 0; jjb < snaKK.idxb_max; jjb++)
|
||||
snaKK.template compute_bi<chemsnap>(iatom, jjb);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocalFill, const int& ii) const {
|
||||
|
||||
// extract grid index
|
||||
int igrid = ii + chunk_offset;
|
||||
|
||||
// convert to grid indices
|
||||
|
||||
int iz = igrid/(xlen*ylen);
|
||||
int i2 = igrid - (iz*xlen*ylen);
|
||||
int iy = i2/xlen;
|
||||
int ix = i2 % xlen;
|
||||
iz += nzlo;
|
||||
iy += nylo;
|
||||
ix += nxlo;
|
||||
|
||||
double xgrid[3];
|
||||
|
||||
// index ii already captures the proper grid point
|
||||
// int igrid = iz * (nx * ny) + iy * nx + ix;
|
||||
// printf("ii igrid: %d %d\n", ii, igrid);
|
||||
|
||||
// grid2x converts igrid to ix,iy,iz like we've done before
|
||||
//grid2x(igrid, xgrid);
|
||||
xgrid[0] = ix * delx;
|
||||
xgrid[1] = iy * dely;
|
||||
xgrid[2] = iz * delz;
|
||||
if (triclinic) {
|
||||
|
||||
// Do a conversion on `xgrid` here like we do in the CPU version.
|
||||
|
||||
// Can't do this:
|
||||
// domainKK->lamda2x(xgrid, xgrid);
|
||||
// Because calling a __host__ function("lamda2x") from a __host__ __device__ function("operator()") is not allowed
|
||||
|
||||
// Using domainKK-> gives segfault, use domain-> instead since we're just accessing floats.
|
||||
xgrid[0] = h0*xgrid[0] + h5*xgrid[1] + h4*xgrid[2] + lo0;
|
||||
xgrid[1] = h1*xgrid[1] + h3*xgrid[2] + lo1;
|
||||
xgrid[2] = h2*xgrid[2] + lo2;
|
||||
}
|
||||
|
||||
const F_FLOAT xtmp = xgrid[0];
|
||||
const F_FLOAT ytmp = xgrid[1];
|
||||
const F_FLOAT ztmp = xgrid[2];
|
||||
d_gridall(igrid,0) = xtmp;
|
||||
d_gridall(igrid,1) = ytmp;
|
||||
d_gridall(igrid,2) = ztmp;
|
||||
|
||||
const auto idxb_max = snaKK.idxb_max;
|
||||
|
||||
// linear contributions
|
||||
|
||||
for (int icoeff = 0; icoeff < ncoeff; icoeff++) {
|
||||
const auto idxb = icoeff % idxb_max;
|
||||
const auto idx_chem = icoeff / idxb_max;
|
||||
d_gridall(igrid,icoeff+3) = snaKK.blist(ii,idx_chem,idxb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
utility functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template<class TagStyle>
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::check_team_size_for(int inum, int &team_size) {
|
||||
int team_size_max;
|
||||
|
||||
team_size_max = Kokkos::TeamPolicy<DeviceType,TagStyle>(inum,Kokkos::AUTO).team_size_max(*this,Kokkos::ParallelForTag());
|
||||
|
||||
if (team_size*vector_length > team_size_max)
|
||||
team_size = team_size_max/vector_length;
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template<class TagStyle>
|
||||
void ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::check_team_size_reduce(int inum, int &team_size) {
|
||||
int team_size_max;
|
||||
|
||||
team_size_max = Kokkos::TeamPolicy<DeviceType,TagStyle>(inum,Kokkos::AUTO).team_size_max(*this,Kokkos::ParallelReduceTag());
|
||||
|
||||
if (team_size*vector_length > team_size_max)
|
||||
team_size = team_size_max/vector_length;
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template<typename scratch_type>
|
||||
int ComputeSNAGridKokkos<DeviceType, real_type, vector_length>::scratch_size_helper(int values_per_team) {
|
||||
typedef Kokkos::View<scratch_type*, Kokkos::DefaultExecutionSpace::scratch_memory_space, Kokkos::MemoryTraits<Kokkos::Unmanaged> > ScratchViewType;
|
||||
|
||||
return ScratchViewType::shmem_size(values_per_team);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
routines used by template reference classes
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
template<class DeviceType>
|
||||
ComputeSNAGridKokkosDevice<DeviceType>::ComputeSNAGridKokkosDevice(class LAMMPS *lmp, int narg, char **arg)
|
||||
: ComputeSNAGridKokkos<DeviceType, SNAP_KOKKOS_REAL, SNAP_KOKKOS_DEVICE_VECLEN>(lmp, narg, arg) { ; }
|
||||
|
||||
template<class DeviceType>
|
||||
void ComputeSNAGridKokkosDevice<DeviceType>::compute_array()
|
||||
{
|
||||
Base::compute_array();
|
||||
}
|
||||
|
||||
#ifdef LMP_KOKKOS_GPU
|
||||
template<class DeviceType>
|
||||
ComputeSNAGridKokkosHost<DeviceType>::ComputeSNAGridKokkosHost(class LAMMPS *lmp, int narg, char **arg)
|
||||
: ComputeSNAGridKokkos<DeviceType, SNAP_KOKKOS_REAL, SNAP_KOKKOS_HOST_VECLEN>(lmp, narg, arg) { ; }
|
||||
|
||||
template<class DeviceType>
|
||||
void ComputeSNAGridKokkosHost<DeviceType>::compute_array()
|
||||
{
|
||||
Base::compute_array();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
25
src/KOKKOS/compute_sna_grid_local_kokkos.cpp
Normal file
25
src/KOKKOS/compute_sna_grid_local_kokkos.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
// clang-format off
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
LAMMPS development team: developers@lammps.org
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "compute_sna_grid_local_kokkos.h"
|
||||
#include "compute_sna_grid_local_kokkos_impl.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
template class ComputeSNAGridLocalKokkosDevice<LMPDeviceType>;
|
||||
#ifdef LMP_KOKKOS_GPU
|
||||
template class ComputeSNAGridLocalKokkosHost<LMPHostType>;
|
||||
#endif
|
||||
|
||||
}
|
||||
288
src/KOKKOS/compute_sna_grid_local_kokkos.h
Normal file
288
src/KOKKOS/compute_sna_grid_local_kokkos.h
Normal file
@ -0,0 +1,288 @@
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
LAMMPS development team: developers@lammps.org
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef COMPUTE_CLASS
|
||||
// clang-format off
|
||||
ComputeStyle(sna/grid/local/kk,ComputeSNAGridLocalKokkosDevice<LMPDeviceType>);
|
||||
ComputeStyle(sna/grid/local/kk/device,ComputeSNAGridLocalKokkosDevice<LMPDeviceType>);
|
||||
#ifdef LMP_KOKKOS_GPU
|
||||
ComputeStyle(sna/grid/local/kk/host,ComputeSNAGridLocalKokkosHost<LMPHostType>);
|
||||
#else
|
||||
ComputeStyle(sna/grid/local/kk/host,ComputeSNAGridLocalKokkosDevice<LMPHostType>);
|
||||
#endif
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
// clang-format off
|
||||
#ifndef LMP_COMPUTE_SNA_GRID_LOCAL_KOKKOS_H
|
||||
#define LMP_COMPUTE_SNA_GRID_LOCAL_KOKKOS_H
|
||||
|
||||
#include "compute_sna_grid_local.h"
|
||||
#include "kokkos_type.h"
|
||||
#include "sna_kokkos.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
// Routines for both the CPU and GPU backend
|
||||
|
||||
// GPU backend only
|
||||
struct TagCSNAGridLocalComputeNeigh{};
|
||||
struct TagCSNAGridLocalComputeCayleyKlein{};
|
||||
struct TagCSNAGridLocalPreUi{};
|
||||
struct TagCSNAGridLocalComputeUiSmall{}; // more parallelism, more divergence
|
||||
struct TagCSNAGridLocalComputeUiLarge{}; // less parallelism, no divergence
|
||||
struct TagCSNAGridLocalTransformUi{}; // re-order ulisttot from SoA to AoSoA, zero ylist
|
||||
template <bool chemsnap> struct TagCSNAGridLocalComputeZi{};
|
||||
template <bool chemsnap> struct TagCSNAGridLocalComputeBi{};
|
||||
struct TagCSNAGridLocal2Fill{}; // fill the gridlocal array
|
||||
|
||||
struct TagComputeSNAGridLocalLoop{};
|
||||
struct TagComputeSNAGridLocal3D{};
|
||||
|
||||
// CPU backend only
|
||||
struct TagComputeSNAGridLocalLoopCPU{};
|
||||
|
||||
//template<class DeviceType>
|
||||
template<class DeviceType, typename real_type_, int vector_length_>
|
||||
class ComputeSNAGridLocalKokkos : public ComputeSNAGridLocal {
|
||||
public:
|
||||
typedef DeviceType device_type;
|
||||
typedef ArrayTypes<DeviceType> AT;
|
||||
|
||||
static constexpr int vector_length = vector_length_;
|
||||
using real_type = real_type_;
|
||||
using complex = SNAComplex<real_type>;
|
||||
|
||||
// Static team/tile sizes for device offload
|
||||
|
||||
#ifdef KOKKOS_ENABLE_HIP
|
||||
static constexpr int team_size_compute_neigh = 2;
|
||||
static constexpr int tile_size_compute_ck = 2;
|
||||
static constexpr int tile_size_pre_ui = 2;
|
||||
static constexpr int team_size_compute_ui = 2;
|
||||
static constexpr int tile_size_transform_ui = 2;
|
||||
static constexpr int tile_size_compute_zi = 2;
|
||||
static constexpr int min_blocks_compute_zi = 0; // no minimum bound
|
||||
static constexpr int tile_size_compute_bi = 2;
|
||||
static constexpr int tile_size_compute_yi = 2;
|
||||
static constexpr int min_blocks_compute_yi = 0; // no minimum bound
|
||||
static constexpr int team_size_compute_fused_deidrj = 2;
|
||||
#else
|
||||
static constexpr int team_size_compute_neigh = 4;
|
||||
static constexpr int tile_size_compute_ck = 4;
|
||||
static constexpr int tile_size_pre_ui = 4;
|
||||
static constexpr int team_size_compute_ui = sizeof(real_type) == 4 ? 8 : 4;
|
||||
static constexpr int tile_size_transform_ui = 4;
|
||||
static constexpr int tile_size_compute_zi = 8;
|
||||
static constexpr int tile_size_compute_bi = 4;
|
||||
static constexpr int tile_size_compute_yi = 8;
|
||||
static constexpr int team_size_compute_fused_deidrj = sizeof(real_type) == 4 ? 4 : 2;
|
||||
|
||||
// this empirically reduces perf fluctuations from compiler version to compiler version
|
||||
static constexpr int min_blocks_compute_zi = 4;
|
||||
static constexpr int min_blocks_compute_yi = 4;
|
||||
#endif
|
||||
|
||||
// Custom MDRangePolicy, Rank3, to reduce verbosity of kernel launches
|
||||
// This hides the Kokkos::IndexType<int> and Kokkos::Rank<3...>
|
||||
// and reduces the verbosity of the LaunchBound by hiding the explicit
|
||||
// multiplication by vector_length
|
||||
template <class Device, int num_tiles, class TagComputeSNA, int min_blocks = 0>
|
||||
using Snap3DRangePolicy = typename Kokkos::MDRangePolicy<Device, Kokkos::IndexType<int>, Kokkos::Rank<3, Kokkos::Iterate::Left, Kokkos::Iterate::Left>, Kokkos::LaunchBounds<vector_length * num_tiles, min_blocks>, TagComputeSNA>;
|
||||
|
||||
// MDRangePolicy for the 3D grid loop:
|
||||
template <class Device, class TagComputeSNA>
|
||||
using CSNAGridLocal3DPolicy = typename Kokkos::MDRangePolicy<Device, Kokkos::IndexType<int>, Kokkos::Rank<3, Kokkos::Iterate::Left, Kokkos::Iterate::Left>>;
|
||||
|
||||
// Testing out team policies
|
||||
template <class Device, int num_teams, class TagComputeSNA>
|
||||
using CSNAGridLocalTeamPolicy = typename Kokkos::TeamPolicy<Device, Kokkos::LaunchBounds<vector_length * num_teams>, TagComputeSNA>;
|
||||
|
||||
// Custom SnapAoSoATeamPolicy to reduce the verbosity of kernel launches
|
||||
// This hides the LaunchBounds abstraction by hiding the explicit
|
||||
// multiplication by vector length
|
||||
template <class Device, int num_teams, class TagComputeSNA>
|
||||
using SnapAoSoATeamPolicy = typename Kokkos::TeamPolicy<Device, Kokkos::LaunchBounds<vector_length * num_teams>, TagComputeSNA>;
|
||||
|
||||
// Helper routine that returns a CPU or a GPU policy as appropriate
|
||||
template <class Device, int num_tiles, class TagComputeSNA, int min_blocks = 0>
|
||||
auto snap_get_policy(const int& chunk_size_div, const int& second_loop) {
|
||||
return Snap3DRangePolicy<Device, num_tiles, TagComputeSNA, min_blocks>({0, 0, 0},
|
||||
{vector_length, second_loop, chunk_size_div},
|
||||
{vector_length, num_tiles, 1});
|
||||
}
|
||||
|
||||
ComputeSNAGridLocalKokkos(class LAMMPS *, int, char **);
|
||||
~ComputeSNAGridLocalKokkos() override;
|
||||
|
||||
void setup() override;
|
||||
void compute_local() override;
|
||||
|
||||
// Utility functions for teams
|
||||
|
||||
template<class TagStyle>
|
||||
void check_team_size_for(int, int&);
|
||||
|
||||
template<class TagStyle>
|
||||
void check_team_size_reduce(int, int&);
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagComputeSNAGridLocalLoop, const int& ) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagComputeSNAGridLocalLoopCPU, const int&) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocalComputeNeigh,const typename Kokkos::TeamPolicy<DeviceType, TagCSNAGridLocalComputeNeigh>::member_type& team) const;
|
||||
|
||||
// 3D case - used by parallel_for
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator()(TagComputeSNAGridLocal3D, const int& iz, const int& iy, const int& ix) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocalComputeCayleyKlein, const int iatom_mod, const int jnbor, const int iatom_div) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocalPreUi, const int& iatom_mod, const int& j, const int& iatom_div) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocalPreUi, const int& iatom, const int& j) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocalPreUi, const int& iatom) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocalComputeUiSmall,const typename Kokkos::TeamPolicy<DeviceType, TagCSNAGridLocalComputeUiSmall>::member_type& team) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocalComputeUiLarge,const typename Kokkos::TeamPolicy<DeviceType, TagCSNAGridLocalComputeUiLarge>::member_type& team) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocalTransformUi, const int& iatom_mod, const int& idxu, const int& iatom_div) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocalTransformUi, const int& iatom, const int& idxu) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocalTransformUi, const int& iatom) const;
|
||||
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocalComputeZi<chemsnap>, const int& iatom_mod, const int& idxz, const int& iatom_div) const;
|
||||
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocalComputeZi<chemsnap>, const int& iatom, const int& idxz) const;
|
||||
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocalComputeZi<chemsnap>, const int& iatom) const;
|
||||
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocalComputeBi<chemsnap>, const int& iatom_mod, const int& idxb, const int& iatom_div) const;
|
||||
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocalComputeBi<chemsnap>, const int& iatom, const int& idxb) const;
|
||||
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocalComputeBi<chemsnap>, const int& iatom) const;
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void operator() (TagCSNAGridLocal2Fill,const int& ii) const;
|
||||
|
||||
protected:
|
||||
|
||||
SNAKokkos<DeviceType, real_type, vector_length> snaKK;
|
||||
|
||||
int max_neighs, chunk_size, chunk_offset;
|
||||
int host_flag;
|
||||
int ntotal;
|
||||
int total_range; // total number of loop iterations in grid
|
||||
int zlen; //= nzhi-nzlo+1;
|
||||
int ylen; //= nyhi-nylo+1;
|
||||
int xlen; //= nxhi-nxlo+1;
|
||||
|
||||
double cutsq_tmp; // temporary cutsq until we get a view
|
||||
|
||||
Kokkos::View<real_type*, DeviceType> d_radelem; // element radii
|
||||
Kokkos::View<real_type*, DeviceType> d_wjelem; // elements weights
|
||||
Kokkos::View<real_type**, Kokkos::LayoutRight, DeviceType> d_coeffelem; // element bispectrum coefficients
|
||||
Kokkos::View<real_type*, DeviceType> d_sinnerelem; // element inner cutoff midpoint
|
||||
Kokkos::View<real_type*, DeviceType> d_dinnerelem; // element inner cutoff half-width
|
||||
Kokkos::View<T_INT*, DeviceType> d_ninside; // ninside for all atoms in list
|
||||
Kokkos::View<T_INT*, DeviceType> d_map; // mapping from atom types to elements
|
||||
Kokkos::View<real_type*, DeviceType> d_test; // test view
|
||||
|
||||
typedef Kokkos::DualView<F_FLOAT**, DeviceType> tdual_fparams;
|
||||
tdual_fparams k_cutsq;
|
||||
typedef Kokkos::View<const F_FLOAT**, DeviceType,
|
||||
Kokkos::MemoryTraits<Kokkos::RandomAccess> > t_fparams_rnd;
|
||||
t_fparams_rnd rnd_cutsq;
|
||||
|
||||
typename AT::t_x_array_randomread x;
|
||||
typename AT::t_int_1d_randomread type;
|
||||
|
||||
DAT::tdual_float_2d k_alocal;
|
||||
typename AT::t_float_2d d_alocal;
|
||||
|
||||
|
||||
// Utility routine which wraps computing per-team scratch size requirements for
|
||||
// ComputeNeigh, ComputeUi, and ComputeFusedDeidrj
|
||||
template <typename scratch_type>
|
||||
int scratch_size_helper(int values_per_team);
|
||||
|
||||
class DomainKokkos *domainKK;
|
||||
|
||||
// triclinic vars
|
||||
double h0, h1, h2, h3, h4, h5;
|
||||
double lo0, lo1, lo2;
|
||||
|
||||
// Make SNAKokkos a friend
|
||||
friend class SNAKokkos<DeviceType, real_type, vector_length>;
|
||||
};
|
||||
|
||||
// These wrapper classes exist to make the compute style factory happy/avoid having
|
||||
// to extend the compute style factory to support Compute classes w/an arbitrary number
|
||||
// of extra template parameters
|
||||
|
||||
template <class DeviceType>
|
||||
class ComputeSNAGridLocalKokkosDevice : public ComputeSNAGridLocalKokkos<DeviceType, SNAP_KOKKOS_REAL, SNAP_KOKKOS_DEVICE_VECLEN> {
|
||||
|
||||
private:
|
||||
using Base = ComputeSNAGridLocalKokkos<DeviceType, SNAP_KOKKOS_REAL, SNAP_KOKKOS_DEVICE_VECLEN>;
|
||||
|
||||
public:
|
||||
|
||||
ComputeSNAGridLocalKokkosDevice(class LAMMPS *, int, char **);
|
||||
|
||||
void compute_local() override;
|
||||
|
||||
};
|
||||
|
||||
#ifdef LMP_KOKKOS_GPU
|
||||
template <class DeviceType>
|
||||
class ComputeSNAGridLocalKokkosHost : public ComputeSNAGridLocalKokkos<DeviceType, SNAP_KOKKOS_REAL, SNAP_KOKKOS_HOST_VECLEN> {
|
||||
|
||||
private:
|
||||
using Base = ComputeSNAGridLocalKokkos<DeviceType, SNAP_KOKKOS_REAL, SNAP_KOKKOS_HOST_VECLEN>;
|
||||
|
||||
public:
|
||||
|
||||
ComputeSNAGridLocalKokkosHost(class LAMMPS *, int, char **);
|
||||
|
||||
void compute_local() override;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
783
src/KOKKOS/compute_sna_grid_local_kokkos_impl.h
Normal file
783
src/KOKKOS/compute_sna_grid_local_kokkos_impl.h
Normal file
@ -0,0 +1,783 @@
|
||||
// clang-format off
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
LAMMPS development team: developers@lammps.org
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing authors: Andrew Rohskopf (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "compute_sna_grid_local_kokkos.h"
|
||||
#include "pair_snap_kokkos.h"
|
||||
|
||||
#include "atom_kokkos.h"
|
||||
#include "atom_masks.h"
|
||||
#include "comm.h"
|
||||
#include "error.h"
|
||||
#include "memory_kokkos.h"
|
||||
#include "modify.h"
|
||||
#include "neigh_list.h"
|
||||
#include "neigh_request.h"
|
||||
#include "neighbor_kokkos.h"
|
||||
#include "domain.h"
|
||||
#include "domain_kokkos.h"
|
||||
#include "sna.h"
|
||||
#include "update.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#define MAXLINE 1024
|
||||
#define MAXWORD 3
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
// Constructor
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::ComputeSNAGridLocalKokkos(LAMMPS *lmp, int narg, char **arg) : ComputeSNAGridLocal(lmp, narg, arg)
|
||||
{
|
||||
kokkosable = 1;
|
||||
atomKK = (AtomKokkos *) atom;
|
||||
domainKK = (DomainKokkos *) domain;
|
||||
execution_space = ExecutionSpaceFromDevice<DeviceType>::space;
|
||||
datamask_read = EMPTY_MASK;
|
||||
datamask_modify = EMPTY_MASK;
|
||||
|
||||
k_cutsq = tdual_fparams("ComputeSNAGridLocalKokkos::cutsq",atom->ntypes+1,atom->ntypes+1);
|
||||
auto d_cutsq = k_cutsq.template view<DeviceType>();
|
||||
rnd_cutsq = d_cutsq;
|
||||
|
||||
host_flag = (execution_space == Host);
|
||||
|
||||
// TODO: Extract cutsq in double loop below, no need for cutsq_tmp
|
||||
|
||||
cutsq_tmp = cutsq[1][1];
|
||||
|
||||
for (int i = 1; i <= atom->ntypes; i++) {
|
||||
for (int j = 1; j <= atom->ntypes; j++){
|
||||
k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutsq_tmp;
|
||||
k_cutsq.template modify<LMPHostType>();
|
||||
}
|
||||
}
|
||||
|
||||
// Set up element lists
|
||||
MemKK::realloc_kokkos(d_radelem,"ComputeSNAGridLocalKokkos::radelem",nelements);
|
||||
MemKK::realloc_kokkos(d_wjelem,"ComputeSNAGridLocalKokkos:wjelem",nelements);
|
||||
MemKK::realloc_kokkos(d_sinnerelem,"ComputeSNAGridLocalKokkos:sinnerelem",nelements);
|
||||
MemKK::realloc_kokkos(d_dinnerelem,"ComputeSNAGridLocalKokkos:dinnerelem",nelements);
|
||||
// test
|
||||
MemKK::realloc_kokkos(d_test, "ComputeSNAGridLocalKokkos::test", nelements);
|
||||
|
||||
int n = atom->ntypes;
|
||||
MemKK::realloc_kokkos(d_map,"ComputeSNAGridLocalKokkos::map",n+1);
|
||||
|
||||
auto h_radelem = Kokkos::create_mirror_view(d_radelem);
|
||||
auto h_wjelem = Kokkos::create_mirror_view(d_wjelem);
|
||||
auto h_sinnerelem = Kokkos::create_mirror_view(d_sinnerelem);
|
||||
auto h_dinnerelem = Kokkos::create_mirror_view(d_dinnerelem);
|
||||
auto h_map = Kokkos::create_mirror_view(d_map);
|
||||
// test
|
||||
auto h_test = Kokkos::create_mirror_view(d_test);
|
||||
h_test(0) = 2.0;
|
||||
|
||||
// start from index 1 because of how compute sna/grid is
|
||||
for (int i = 1; i <= atom->ntypes; i++) {
|
||||
h_radelem(i-1) = radelem[i];
|
||||
h_wjelem(i-1) = wjelem[i];
|
||||
if (switchinnerflag){
|
||||
h_sinnerelem(i) = sinnerelem[i];
|
||||
h_dinnerelem(i) = dinnerelem[i];
|
||||
}
|
||||
}
|
||||
|
||||
// In pair snap some things like `map` get allocated regardless of chem flag.
|
||||
if (chemflag){
|
||||
for (int i = 1; i <= atom->ntypes; i++) {
|
||||
h_map(i) = map[i];
|
||||
}
|
||||
}
|
||||
|
||||
Kokkos::deep_copy(d_radelem,h_radelem);
|
||||
Kokkos::deep_copy(d_wjelem,h_wjelem);
|
||||
if (switchinnerflag){
|
||||
Kokkos::deep_copy(d_sinnerelem,h_sinnerelem);
|
||||
Kokkos::deep_copy(d_dinnerelem,h_dinnerelem);
|
||||
}
|
||||
if (chemflag){
|
||||
Kokkos::deep_copy(d_map,h_map);
|
||||
}
|
||||
Kokkos::deep_copy(d_test,h_test);
|
||||
|
||||
snaKK = SNAKokkos<DeviceType, real_type, vector_length>(*this);
|
||||
snaKK.grow_rij(0,0);
|
||||
snaKK.init();
|
||||
}
|
||||
|
||||
// Destructor
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::~ComputeSNAGridLocalKokkos()
|
||||
{
|
||||
if (copymode) return;
|
||||
|
||||
memoryKK->destroy_kokkos(k_cutsq,cutsq);
|
||||
memoryKK->destroy_kokkos(k_alocal,alocal);
|
||||
}
|
||||
|
||||
// Setup
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::setup()
|
||||
{
|
||||
|
||||
ComputeGridLocal::setup();
|
||||
|
||||
// allocate arrays
|
||||
memoryKK->create_kokkos(k_alocal, alocal, size_local_rows, size_local_cols, "grid:alocal");
|
||||
array_local = alocal;
|
||||
d_alocal = k_alocal.template view<DeviceType>();
|
||||
}
|
||||
|
||||
// Compute
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::compute_local()
|
||||
{
|
||||
if (host_flag) {
|
||||
ComputeSNAGridLocal::compute_array();
|
||||
return;
|
||||
}
|
||||
|
||||
copymode = 1;
|
||||
|
||||
zlen = nzhi-nzlo+1;
|
||||
ylen = nyhi-nylo+1;
|
||||
xlen = nxhi-nxlo+1;
|
||||
total_range = (nzhi-nzlo+1)*(nyhi-nylo+1)*(nxhi-nxlo+1);
|
||||
|
||||
atomKK->sync(execution_space,X_MASK|F_MASK|TYPE_MASK);
|
||||
x = atomKK->k_x.view<DeviceType>();
|
||||
type = atomKK->k_type.view<DeviceType>();
|
||||
k_cutsq.template sync<DeviceType>();
|
||||
|
||||
// max_neighs is defined here - think of more elaborate methods.
|
||||
max_neighs = 100;
|
||||
|
||||
// Pair snap/kk uses grow_ij with some max number of neighs but compute sna/grid uses total
|
||||
// number of atoms.
|
||||
|
||||
ntotal = atomKK->nlocal + atomKK->nghost;
|
||||
// Allocate view for number of neighbors per grid point
|
||||
MemKK::realloc_kokkos(d_ninside,"ComputeSNAGridLocalKokkos:ninside",total_range);
|
||||
|
||||
// "chunksize" variable is default 32768 in compute_sna_grid.cpp, and set by user
|
||||
// `total_range` is the number of grid points which may be larger than chunk size.
|
||||
chunk_size = MIN(chunksize, total_range);
|
||||
chunk_offset = 0;
|
||||
//snaKK.grow_rij(chunk_size, ntotal);
|
||||
snaKK.grow_rij(chunk_size, max_neighs);
|
||||
|
||||
//chunk_size = total_range;
|
||||
|
||||
// Pre-compute ceil(chunk_size / vector_length) for code cleanliness
|
||||
const int chunk_size_div = (chunk_size + vector_length - 1) / vector_length;
|
||||
|
||||
if (triclinic) {
|
||||
h0 = domain->h[0];
|
||||
h1 = domain->h[1];
|
||||
h2 = domain->h[2];
|
||||
h3 = domain->h[3];
|
||||
h4 = domain->h[4];
|
||||
h5 = domain->h[5];
|
||||
lo0 = domain->boxlo[0];
|
||||
lo1 = domain->boxlo[1];
|
||||
lo2 = domain->boxlo[2];
|
||||
}
|
||||
|
||||
while (chunk_offset < total_range) { // chunk up loop to prevent running out of memory
|
||||
|
||||
if (chunk_size > total_range - chunk_offset)
|
||||
chunk_size = total_range - chunk_offset;
|
||||
|
||||
|
||||
//ComputeNeigh
|
||||
{
|
||||
int scratch_size = scratch_size_helper<int>(team_size_compute_neigh * max_neighs); //ntotal);
|
||||
|
||||
SnapAoSoATeamPolicy<DeviceType, team_size_compute_neigh, TagCSNAGridLocalComputeNeigh>
|
||||
policy_neigh(chunk_size, team_size_compute_neigh, vector_length);
|
||||
policy_neigh = policy_neigh.set_scratch_size(0, Kokkos::PerTeam(scratch_size));
|
||||
Kokkos::parallel_for("ComputeNeigh",policy_neigh,*this);
|
||||
}
|
||||
|
||||
//ComputeCayleyKlein
|
||||
{
|
||||
// tile_size_compute_ck is defined in `compute_sna_grid_kokkos.h`
|
||||
Snap3DRangePolicy<DeviceType, tile_size_compute_ck, TagCSNAGridLocalComputeCayleyKlein>
|
||||
policy_compute_ck({0,0,0}, {vector_length, max_neighs, chunk_size_div}, {vector_length, tile_size_compute_ck, 1});
|
||||
Kokkos::parallel_for("ComputeCayleyKlein", policy_compute_ck, *this);
|
||||
}
|
||||
|
||||
//PreUi
|
||||
{
|
||||
auto policy_pre_ui = snap_get_policy<DeviceType, tile_size_pre_ui, TagCSNAGridLocalPreUi>(chunk_size_div, twojmax + 1);
|
||||
Kokkos::parallel_for("PreUi", policy_pre_ui, *this);
|
||||
}
|
||||
|
||||
// ComputeUi w/ vector parallelism, shared memory, direct atomicAdd into ulisttot
|
||||
{
|
||||
// team_size_compute_ui is defined in `compute_sna_grid_kokkos.h`
|
||||
// scratch size: 32 atoms * (twojmax+1) cached values, no double buffer
|
||||
const int tile_size = vector_length * (twojmax + 1);
|
||||
const int scratch_size = scratch_size_helper<complex>(team_size_compute_ui * tile_size);
|
||||
|
||||
if (chunk_size < parallel_thresh)
|
||||
{
|
||||
// Version with parallelism over j_bend
|
||||
|
||||
// total number of teams needed: (natoms / 32) * (ntotal) * ("bend" locations)
|
||||
const int n_teams = chunk_size_div * max_neighs * (twojmax + 1);
|
||||
const int n_teams_div = (n_teams + team_size_compute_ui - 1) / team_size_compute_ui;
|
||||
|
||||
SnapAoSoATeamPolicy<DeviceType, team_size_compute_ui, TagCSNAGridLocalComputeUiSmall>
|
||||
policy_ui(n_teams_div, team_size_compute_ui, vector_length);
|
||||
policy_ui = policy_ui.set_scratch_size(0, Kokkos::PerTeam(scratch_size));
|
||||
Kokkos::parallel_for("ComputeUiSmall", policy_ui, *this);
|
||||
} else {
|
||||
// Version w/out parallelism over j_bend
|
||||
|
||||
// total number of teams needed: (natoms / 32) * (ntotal)
|
||||
const int n_teams = chunk_size_div * max_neighs;
|
||||
const int n_teams_div = (n_teams + team_size_compute_ui - 1) / team_size_compute_ui;
|
||||
|
||||
SnapAoSoATeamPolicy<DeviceType, team_size_compute_ui, TagCSNAGridLocalComputeUiLarge>
|
||||
policy_ui(n_teams_div, team_size_compute_ui, vector_length);
|
||||
policy_ui = policy_ui.set_scratch_size(0, Kokkos::PerTeam(scratch_size));
|
||||
Kokkos::parallel_for("ComputeUiLarge", policy_ui, *this);
|
||||
}
|
||||
}
|
||||
|
||||
//TransformUi: un-"fold" ulisttot, zero ylist
|
||||
{
|
||||
// Expand ulisttot_re,_im -> ulisttot
|
||||
// Zero out ylist
|
||||
auto policy_transform_ui = snap_get_policy<DeviceType, tile_size_transform_ui, TagCSNAGridLocalTransformUi>(chunk_size_div, snaKK.idxu_max);
|
||||
Kokkos::parallel_for("TransformUi", policy_transform_ui, *this);
|
||||
}
|
||||
|
||||
//Compute bispectrum
|
||||
// team_size_[compute_zi, compute_bi, transform_bi] are defined in `pair_snap_kokkos.h`
|
||||
|
||||
//ComputeZi and Bi
|
||||
if (nelements > 1) {
|
||||
auto policy_compute_zi = snap_get_policy<DeviceType, tile_size_compute_zi, TagCSNAGridLocalComputeZi<true>, min_blocks_compute_zi>(chunk_size_div, snaKK.idxz_max);
|
||||
Kokkos::parallel_for("ComputeZiChemsnap", policy_compute_zi, *this);
|
||||
|
||||
auto policy_compute_bi = snap_get_policy<DeviceType, tile_size_compute_bi, TagCSNAGridLocalComputeBi<true>>(chunk_size_div, snaKK.idxb_max);
|
||||
Kokkos::parallel_for("ComputeBiChemsnap", policy_compute_bi, *this);
|
||||
} else {
|
||||
auto policy_compute_zi = snap_get_policy<DeviceType, tile_size_compute_zi, TagCSNAGridLocalComputeZi<false>, min_blocks_compute_zi>(chunk_size_div, snaKK.idxz_max);
|
||||
Kokkos::parallel_for("ComputeZi", policy_compute_zi, *this);
|
||||
|
||||
auto policy_compute_bi = snap_get_policy<DeviceType, tile_size_compute_bi, TagCSNAGridLocalComputeBi<false>>(chunk_size_div, snaKK.idxb_max);
|
||||
Kokkos::parallel_for("ComputeBi", policy_compute_bi, *this);
|
||||
}
|
||||
|
||||
// Fill the grid array with bispectrum values
|
||||
{
|
||||
typename Kokkos::RangePolicy<DeviceType,TagCSNAGridLocal2Fill> policy_fill(0,chunk_size);
|
||||
Kokkos::parallel_for(policy_fill, *this);
|
||||
}
|
||||
|
||||
// Proceed to the next chunk.
|
||||
chunk_offset += chunk_size;
|
||||
|
||||
} // end while
|
||||
|
||||
copymode = 0;
|
||||
|
||||
k_alocal.template modify<DeviceType>();
|
||||
k_alocal.template sync<LMPHostType>();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Begin routines that are unique to the GPU codepath. These take advantage
|
||||
of AoSoA data layouts and scratch memory for recursive polynomials
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
Simple team policy functor seeing how many layers deep we can go with the parallelism.
|
||||
*/
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocalComputeNeigh,const typename Kokkos::TeamPolicy<DeviceType,TagCSNAGridLocalComputeNeigh>::member_type& team) const {
|
||||
|
||||
// This function follows similar procedure as ComputeNeigh of PairSNAPKokkos.
|
||||
// Main difference is that we don't use the neighbor class or neighbor variables here.
|
||||
// This is because the grid points are not atoms and therefore do not get assigned
|
||||
// neighbors in LAMMPS.
|
||||
// TODO: If we did make a neighborlist for each grid point, we could use current
|
||||
// routines and avoid having to loop over all atoms (which limits us to
|
||||
// natoms = max team size).
|
||||
|
||||
// basic quantities associated with this team:
|
||||
// team_rank : rank of thread in this team
|
||||
// league_rank : rank of team in this league
|
||||
// team_size : number of threads in this team
|
||||
|
||||
// extract loop index
|
||||
int ii = team.team_rank() + team.league_rank() * team.team_size();
|
||||
|
||||
if (ii >= chunk_size) return;
|
||||
|
||||
// extract grid index
|
||||
int igrid = ii + chunk_offset;
|
||||
|
||||
// get a pointer to scratch memory
|
||||
// This is used to cache whether or not an atom is within the cutoff.
|
||||
// If it is, type_cache is assigned to the atom type.
|
||||
// If it's not, it's assigned to -1.
|
||||
//const int tile_size = ntotal; //max_neighs; // number of elements per thread
|
||||
//const int team_rank = team.team_rank();
|
||||
//const int scratch_shift = team_rank * tile_size; // offset into pointer for entire team
|
||||
//int* type_cache = (int*)team.team_shmem().get_shmem(team.team_size() * tile_size * sizeof(int), 0) + scratch_shift;
|
||||
|
||||
// convert to grid indices
|
||||
|
||||
int iz = igrid/(xlen*ylen);
|
||||
int i2 = igrid - (iz*xlen*ylen);
|
||||
int iy = i2/xlen;
|
||||
int ix = i2 % xlen;
|
||||
iz += nzlo;
|
||||
iy += nylo;
|
||||
ix += nxlo;
|
||||
|
||||
double xgrid[3];
|
||||
|
||||
// index ii already captures the proper grid point
|
||||
//int igrid = iz * (nx * ny) + iy * nx + ix;
|
||||
|
||||
// grid2x converts igrid to ix,iy,iz like we've done before
|
||||
// multiply grid integers by grid spacing delx, dely, delz
|
||||
//grid2x(igrid, xgrid);
|
||||
xgrid[0] = ix * delx;
|
||||
xgrid[1] = iy * dely;
|
||||
xgrid[2] = iz * delz;
|
||||
|
||||
if (triclinic) {
|
||||
|
||||
// Do a conversion on `xgrid` here like we do in the CPU version.
|
||||
|
||||
// Can't do this:
|
||||
// domainKK->lamda2x(xgrid, xgrid);
|
||||
// Because calling a __host__ function("lamda2x") from a __host__ __device__ function("operator()") is not allowed
|
||||
|
||||
// Using domainKK-> gives segfault, use domain-> instead since we're just accessing floats.
|
||||
xgrid[0] = h0*xgrid[0] + h5*xgrid[1] + h4*xgrid[2] + lo0;
|
||||
xgrid[1] = h1*xgrid[1] + h3*xgrid[2] + lo1;
|
||||
xgrid[2] = h2*xgrid[2] + lo2;
|
||||
}
|
||||
|
||||
const F_FLOAT xtmp = xgrid[0];
|
||||
const F_FLOAT ytmp = xgrid[1];
|
||||
const F_FLOAT ztmp = xgrid[2];
|
||||
|
||||
// Zeroing out the components, which are filled as a sum.
|
||||
for (int icol = size_local_cols_base; icol < size_local_cols; icol++){
|
||||
d_alocal(igrid, icol) = 0.0;
|
||||
}
|
||||
|
||||
// Fill grid info columns
|
||||
d_alocal(igrid, 0) = ix;
|
||||
d_alocal(igrid, 1) = iy;
|
||||
d_alocal(igrid, 2) = iz;
|
||||
d_alocal(igrid, 3) = xtmp;
|
||||
d_alocal(igrid, 4) = ytmp;
|
||||
d_alocal(igrid, 5) = ztmp;
|
||||
|
||||
// currently, all grid points are type 1
|
||||
// not clear what a better choice would be
|
||||
|
||||
const int itype = 1;
|
||||
int ielem = 0;
|
||||
if (chemflag) ielem = d_map[itype];
|
||||
//const double radi = d_radelem[ielem];
|
||||
|
||||
// Compute the number of neighbors, store rsq
|
||||
int ninside = 0;
|
||||
|
||||
// Looping over ntotal for now.
|
||||
for (int j = 0; j < ntotal; j++){
|
||||
const F_FLOAT dx = x(j,0) - xtmp;
|
||||
const F_FLOAT dy = x(j,1) - ytmp;
|
||||
const F_FLOAT dz = x(j,2) - ztmp;
|
||||
int jtype = type(j);
|
||||
const F_FLOAT rsq = dx*dx + dy*dy + dz*dz;
|
||||
|
||||
// don't include atoms that share location with grid point
|
||||
if (rsq >= rnd_cutsq(itype,jtype) || rsq < 1e-20) {
|
||||
jtype = -1; // use -1 to signal it's outside the radius
|
||||
}
|
||||
|
||||
if (jtype >= 0)
|
||||
ninside++;
|
||||
}
|
||||
|
||||
d_ninside(ii) = ninside;
|
||||
|
||||
// TODO: Adjust for multi-element, currently we set jelem = 0 regardless of type.
|
||||
int offset = 0;
|
||||
for (int j = 0; j < ntotal; j++){
|
||||
//const int jtype = type_cache[j];
|
||||
//if (jtype >= 0) {
|
||||
const F_FLOAT dx = x(j,0) - xtmp;
|
||||
const F_FLOAT dy = x(j,1) - ytmp;
|
||||
const F_FLOAT dz = x(j,2) - ztmp;
|
||||
const F_FLOAT rsq = dx*dx + dy*dy + dz*dz;
|
||||
int jtype = type(j);
|
||||
if (rsq < rnd_cutsq(itype,jtype) && rsq > 1e-20) {
|
||||
int jelem = 0;
|
||||
if (chemflag) jelem = d_map[jtype];
|
||||
snaKK.rij(ii,offset,0) = static_cast<real_type>(dx);
|
||||
snaKK.rij(ii,offset,1) = static_cast<real_type>(dy);
|
||||
snaKK.rij(ii,offset,2) = static_cast<real_type>(dz);
|
||||
// pair snap uses jelem here, but we use jtype, see compute_sna_grid.cpp
|
||||
// actually since the views here have values starting at 0, let's use jelem
|
||||
snaKK.wj(ii,offset) = static_cast<real_type>(d_wjelem[jelem]);
|
||||
snaKK.rcutij(ii,offset) = static_cast<real_type>((2.0 * d_radelem[jelem])*rcutfac);
|
||||
snaKK.inside(ii,offset) = j;
|
||||
if (switchinnerflag) {
|
||||
snaKK.sinnerij(ii,offset) = 0.5*(d_sinnerelem[ielem] + d_sinnerelem[jelem]);
|
||||
snaKK.dinnerij(ii,offset) = 0.5*(d_dinnerelem[ielem] + d_dinnerelem[jelem]);
|
||||
}
|
||||
if (chemflag)
|
||||
snaKK.element(ii,offset) = jelem;
|
||||
else
|
||||
snaKK.element(ii,offset) = 0;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Pre-compute the Cayley-Klein parameters for reuse in later routines
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocalComputeCayleyKlein,const int iatom_mod, const int jnbor, const int iatom_div) const {
|
||||
|
||||
const int iatom = iatom_mod + iatom_div * vector_length;
|
||||
if (iatom >= chunk_size) return;
|
||||
|
||||
const int ninside = d_ninside(iatom);
|
||||
if (jnbor >= ninside) return;
|
||||
|
||||
snaKK.compute_cayley_klein(iatom, jnbor);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Initialize the "ulisttot" structure with non-zero on-diagonal terms
|
||||
and zero terms elsewhere
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocalPreUi, const int& iatom_mod, const int& j, const int& iatom_div) const {
|
||||
const int iatom = iatom_mod + iatom_div * vector_length;
|
||||
if (iatom >= chunk_size) return;
|
||||
|
||||
int itype = type(iatom);
|
||||
int ielem = d_map[itype];
|
||||
|
||||
snaKK.pre_ui(iatom, j, ielem);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocalPreUi, const int& iatom, const int& j) const {
|
||||
if (iatom >= chunk_size) return;
|
||||
|
||||
int itype = type(iatom);
|
||||
int ielem = d_map[itype];
|
||||
|
||||
snaKK.pre_ui(iatom, j, ielem);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocalPreUi, const int& iatom) const {
|
||||
if (iatom >= chunk_size) return;
|
||||
|
||||
const int itype = type(iatom);
|
||||
const int ielem = d_map[itype];
|
||||
|
||||
for (int j = 0; j <= twojmax; j++)
|
||||
snaKK.pre_ui(iatom, j, ielem);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocalComputeUiSmall,const typename Kokkos::TeamPolicy<DeviceType,TagCSNAGridLocalComputeUiSmall>::member_type& team) const {
|
||||
|
||||
// extract flattened atom_div / neighbor number / bend location
|
||||
int flattened_idx = team.team_rank() + team.league_rank() * team_size_compute_ui;
|
||||
|
||||
// extract neighbor index, iatom_div
|
||||
int iatom_div = flattened_idx / (max_neighs * (twojmax + 1)); // removed "const" to work around GCC 7 bug
|
||||
const int jj_jbend = flattened_idx - iatom_div * (max_neighs * (twojmax + 1));
|
||||
const int jbend = jj_jbend / max_neighs;
|
||||
int jj = jj_jbend - jbend * max_neighs; // removed "const" to work around GCC 7 bug
|
||||
|
||||
Kokkos::parallel_for(Kokkos::ThreadVectorRange(team, vector_length),
|
||||
[&] (const int iatom_mod) {
|
||||
const int ii = iatom_mod + vector_length * iatom_div;
|
||||
if (ii >= chunk_size) return;
|
||||
|
||||
const int ninside = d_ninside(ii);
|
||||
if (jj >= ninside) return;
|
||||
|
||||
snaKK.compute_ui_small(team, iatom_mod, jbend, jj, iatom_div);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocalComputeUiLarge,const typename Kokkos::TeamPolicy<DeviceType,TagCSNAGridLocalComputeUiLarge>::member_type& team) const {
|
||||
|
||||
// extract flattened atom_div / neighbor number / bend location
|
||||
int flattened_idx = team.team_rank() + team.league_rank() * team_size_compute_ui;
|
||||
|
||||
// extract neighbor index, iatom_div
|
||||
int iatom_div = flattened_idx / max_neighs; // removed "const" to work around GCC 7 bug
|
||||
int jj = flattened_idx - iatom_div * max_neighs;
|
||||
|
||||
Kokkos::parallel_for(Kokkos::ThreadVectorRange(team, vector_length),
|
||||
[&] (const int iatom_mod) {
|
||||
const int ii = iatom_mod + vector_length * iatom_div;
|
||||
if (ii >= chunk_size) return;
|
||||
|
||||
const int ninside = d_ninside(ii);
|
||||
if (jj >= ninside) return;
|
||||
|
||||
snaKK.compute_ui_large(team,iatom_mod, jj, iatom_div);
|
||||
});
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
De-symmetrize ulisttot_re and _im and pack it into a unified ulisttot
|
||||
structure. Zero-initialize ylist. CPU and GPU.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocalTransformUi, const int& iatom_mod, const int& idxu, const int& iatom_div) const {
|
||||
const int iatom = iatom_mod + iatom_div * vector_length;
|
||||
if (iatom >= chunk_size) return;
|
||||
if (idxu >= snaKK.idxu_max) return;
|
||||
snaKK.transform_ui(iatom, idxu);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocalTransformUi, const int& iatom, const int& idxu) const {
|
||||
if (iatom >= chunk_size) return;
|
||||
snaKK.transform_ui(iatom, idxu);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocalTransformUi, const int& iatom) const {
|
||||
if (iatom >= chunk_size) return;
|
||||
for (int idxu = 0; idxu < snaKK.idxu_max; idxu++)
|
||||
snaKK.transform_ui(iatom, idxu);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Compute all elements of the Z tensor and store them into the `zlist`
|
||||
view
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocalComputeZi<chemsnap>, const int& iatom_mod, const int& jjz, const int& iatom_div) const {
|
||||
const int iatom = iatom_mod + iatom_div * vector_length;
|
||||
if (iatom >= chunk_size) return;
|
||||
if (jjz >= snaKK.idxz_max) return;
|
||||
snaKK.template compute_zi<chemsnap>(iatom, jjz);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocalComputeZi<chemsnap>, const int& iatom, const int& jjz) const {
|
||||
if (iatom >= chunk_size) return;
|
||||
snaKK.template compute_zi<chemsnap>(iatom, jjz);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocalComputeZi<chemsnap>, const int& iatom) const {
|
||||
if (iatom >= chunk_size) return;
|
||||
for (int jjz = 0; jjz < snaKK.idxz_max; jjz++)
|
||||
snaKK.template compute_zi<chemsnap>(iatom, jjz);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Compute the energy triple products and store in the "blist" view
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocalComputeBi<chemsnap>, const int& iatom_mod, const int& jjb, const int& iatom_div) const {
|
||||
const int iatom = iatom_mod + iatom_div * vector_length;
|
||||
if (iatom >= chunk_size) return;
|
||||
if (jjb >= snaKK.idxb_max) return;
|
||||
snaKK.template compute_bi<chemsnap>(iatom, jjb);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocalComputeBi<chemsnap>, const int& iatom, const int& jjb) const {
|
||||
if (iatom >= chunk_size) return;
|
||||
snaKK.template compute_bi<chemsnap>(iatom, jjb);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template <bool chemsnap> KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocalComputeBi<chemsnap>, const int& iatom) const {
|
||||
if (iatom >= chunk_size) return;
|
||||
for (int jjb = 0; jjb < snaKK.idxb_max; jjb++)
|
||||
snaKK.template compute_bi<chemsnap>(iatom, jjb);
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::operator() (TagCSNAGridLocal2Fill, const int& ii) const {
|
||||
|
||||
// extract grid index
|
||||
int igrid = ii + chunk_offset;
|
||||
|
||||
// convert to grid indices
|
||||
|
||||
int iz = igrid/(xlen*ylen);
|
||||
int i2 = igrid - (iz*xlen*ylen);
|
||||
int iy = i2/xlen;
|
||||
int ix = i2 % xlen;
|
||||
iz += nzlo;
|
||||
iy += nylo;
|
||||
ix += nxlo;
|
||||
|
||||
double xgrid[3];
|
||||
|
||||
// index ii already captures the proper grid point
|
||||
// int igrid = iz * (nx * ny) + iy * nx + ix;
|
||||
// printf("ii igrid: %d %d\n", ii, igrid);
|
||||
|
||||
// grid2x converts igrid to ix,iy,iz like we've done before
|
||||
//grid2x(igrid, xgrid);
|
||||
xgrid[0] = ix * delx;
|
||||
xgrid[1] = iy * dely;
|
||||
xgrid[2] = iz * delz;
|
||||
if (triclinic) {
|
||||
|
||||
// Do a conversion on `xgrid` here like we do in the CPU version.
|
||||
|
||||
// Can't do this:
|
||||
// domainKK->lamda2x(xgrid, xgrid);
|
||||
// Because calling a __host__ function("lamda2x") from a __host__ __device__ function("operator()") is not allowed
|
||||
|
||||
// Using domainKK-> gives segfault, use domain-> instead since we're just accessing floats.
|
||||
xgrid[0] = h0*xgrid[0] + h5*xgrid[1] + h4*xgrid[2] + lo0;
|
||||
xgrid[1] = h1*xgrid[1] + h3*xgrid[2] + lo1;
|
||||
xgrid[2] = h2*xgrid[2] + lo2;
|
||||
}
|
||||
|
||||
|
||||
const auto idxb_max = snaKK.idxb_max;
|
||||
|
||||
// linear contributions
|
||||
|
||||
for (int icoeff = 0; icoeff < ncoeff; icoeff++) {
|
||||
const auto idxb = icoeff % idxb_max;
|
||||
const auto idx_chem = icoeff / idxb_max;
|
||||
d_alocal(igrid,icoeff+6) = snaKK.blist(ii,idx_chem,idxb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
utility functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template<class TagStyle>
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::check_team_size_for(int inum, int &team_size) {
|
||||
int team_size_max;
|
||||
|
||||
team_size_max = Kokkos::TeamPolicy<DeviceType,TagStyle>(inum,Kokkos::AUTO).team_size_max(*this,Kokkos::ParallelForTag());
|
||||
|
||||
if (team_size*vector_length > team_size_max)
|
||||
team_size = team_size_max/vector_length;
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template<class TagStyle>
|
||||
void ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::check_team_size_reduce(int inum, int &team_size) {
|
||||
int team_size_max;
|
||||
|
||||
team_size_max = Kokkos::TeamPolicy<DeviceType,TagStyle>(inum,Kokkos::AUTO).team_size_max(*this,Kokkos::ParallelReduceTag());
|
||||
|
||||
if (team_size*vector_length > team_size_max)
|
||||
team_size = team_size_max/vector_length;
|
||||
}
|
||||
|
||||
template<class DeviceType, typename real_type, int vector_length>
|
||||
template<typename scratch_type>
|
||||
int ComputeSNAGridLocalKokkos<DeviceType, real_type, vector_length>::scratch_size_helper(int values_per_team) {
|
||||
typedef Kokkos::View<scratch_type*, Kokkos::DefaultExecutionSpace::scratch_memory_space, Kokkos::MemoryTraits<Kokkos::Unmanaged> > ScratchViewType;
|
||||
|
||||
return ScratchViewType::shmem_size(values_per_team);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
routines used by template reference classes
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
template<class DeviceType>
|
||||
ComputeSNAGridLocalKokkosDevice<DeviceType>::ComputeSNAGridLocalKokkosDevice(class LAMMPS *lmp, int narg, char **arg)
|
||||
: ComputeSNAGridLocalKokkos<DeviceType, SNAP_KOKKOS_REAL, SNAP_KOKKOS_DEVICE_VECLEN>(lmp, narg, arg) { ; }
|
||||
|
||||
template<class DeviceType>
|
||||
void ComputeSNAGridLocalKokkosDevice<DeviceType>::compute_local()
|
||||
{
|
||||
Base::compute_local();
|
||||
}
|
||||
|
||||
#ifdef LMP_KOKKOS_GPU
|
||||
template<class DeviceType>
|
||||
ComputeSNAGridLocalKokkosHost<DeviceType>::ComputeSNAGridLocalKokkosHost(class LAMMPS *lmp, int narg, char **arg)
|
||||
: ComputeSNAGridLocalKokkos<DeviceType, SNAP_KOKKOS_REAL, SNAP_KOKKOS_HOST_VECLEN>(lmp, narg, arg) { ; }
|
||||
|
||||
template<class DeviceType>
|
||||
void ComputeSNAGridLocalKokkosHost<DeviceType>::compute_local()
|
||||
{
|
||||
Base::compute_local();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
@ -225,7 +225,8 @@ void FixACKS2ReaxFFKokkos<DeviceType>::pre_force(int /*vflag*/)
|
||||
|
||||
allocate_array();
|
||||
|
||||
if (!allocated_flag || last_allocate < neighbor->lastcall) {
|
||||
if (!allocated_flag || last_allocate < neighbor->lastcall
|
||||
|| nlocal_last_allocate != nlocal) {
|
||||
|
||||
// get max number of neighbor
|
||||
|
||||
@ -281,6 +282,7 @@ void FixACKS2ReaxFFKokkos<DeviceType>::pre_force(int /*vflag*/)
|
||||
prev_last_rows_rank = last_rows_rank;
|
||||
|
||||
last_allocate = update->ntimestep;
|
||||
nlocal_last_allocate = nlocal;
|
||||
}
|
||||
|
||||
// compute_H
|
||||
@ -430,8 +432,6 @@ void FixACKS2ReaxFFKokkos<DeviceType>::num_neigh_item(int ii, bigint &totneigh)
|
||||
template<class DeviceType>
|
||||
void FixACKS2ReaxFFKokkos<DeviceType>::allocate_matrix()
|
||||
{
|
||||
nmax = atom->nmax;
|
||||
|
||||
// determine the total space for the H matrix
|
||||
|
||||
m_cap_big = 0;
|
||||
@ -456,15 +456,15 @@ void FixACKS2ReaxFFKokkos<DeviceType>::allocate_matrix()
|
||||
|
||||
// H matrix
|
||||
|
||||
d_firstnbr = typename AT::t_bigint_1d("acks2/kk:firstnbr",nmax);
|
||||
d_numnbrs = typename AT::t_int_1d("acks2/kk:numnbrs",nmax);
|
||||
d_firstnbr = typename AT::t_bigint_1d("acks2/kk:firstnbr",nlocal);
|
||||
d_numnbrs = typename AT::t_int_1d("acks2/kk:numnbrs",nlocal);
|
||||
d_jlist = typename AT::t_int_1d("acks2/kk:jlist",m_cap_big);
|
||||
d_val = typename AT::t_ffloat_1d("acks2/kk:val",m_cap_big);
|
||||
|
||||
// X matrix
|
||||
|
||||
d_firstnbr_X = typename AT::t_bigint_1d("acks2/kk:firstnbr_X",nmax);
|
||||
d_numnbrs_X = typename AT::t_int_1d("acks2/kk:numnbrs_X",nmax);
|
||||
d_firstnbr_X = typename AT::t_bigint_1d("acks2/kk:firstnbr_X",nlocal);
|
||||
d_numnbrs_X = typename AT::t_int_1d("acks2/kk:numnbrs_X",nlocal);
|
||||
d_jlist_X = typename AT::t_int_1d("acks2/kk:jlist_X",m_cap_big);
|
||||
d_val_X = typename AT::t_ffloat_1d("acks2/kk:val_X",m_cap_big);
|
||||
}
|
||||
|
||||
@ -243,7 +243,7 @@ class FixACKS2ReaxFFKokkos : public FixACKS2ReaxFF, public KokkosBase {
|
||||
void calculate_Q() override;
|
||||
|
||||
int neighflag;
|
||||
int nlocal,nall,nmax,newton_pair;
|
||||
int nlocal,nlocal_last_allocate,nall,nmax,newton_pair;
|
||||
int count, isuccess;
|
||||
double alpha, beta, omega, cutsq;
|
||||
|
||||
|
||||
@ -215,9 +215,11 @@ void FixQEqReaxFFKokkos<DeviceType>::pre_force(int /*vflag*/)
|
||||
|
||||
// get max number of neighbor
|
||||
|
||||
if (!allocated_flag || last_allocate < neighbor->lastcall) {
|
||||
if (!allocated_flag || last_allocate < neighbor->lastcall
|
||||
|| nlocal_last_allocate != nlocal) {
|
||||
allocate_matrix();
|
||||
last_allocate = update->ntimestep;
|
||||
nlocal_last_allocate = nlocal;
|
||||
}
|
||||
|
||||
// compute_H
|
||||
@ -313,8 +315,6 @@ void FixQEqReaxFFKokkos<DeviceType>::num_neigh_item(int ii, bigint &totneigh) co
|
||||
template<class DeviceType>
|
||||
void FixQEqReaxFFKokkos<DeviceType>::allocate_matrix()
|
||||
{
|
||||
nmax = atom->nmax;
|
||||
|
||||
// determine the total space for the H matrix
|
||||
|
||||
m_cap_big = 0;
|
||||
@ -332,8 +332,8 @@ void FixQEqReaxFFKokkos<DeviceType>::allocate_matrix()
|
||||
d_jlist = typename AT::t_int_1d();
|
||||
d_val = typename AT::t_ffloat_1d();
|
||||
|
||||
d_firstnbr = typename AT::t_bigint_1d("qeq/kk:firstnbr",nmax);
|
||||
d_numnbrs = typename AT::t_int_1d("qeq/kk:numnbrs",nmax);
|
||||
d_firstnbr = typename AT::t_bigint_1d("qeq/kk:firstnbr",nlocal);
|
||||
d_numnbrs = typename AT::t_int_1d("qeq/kk:numnbrs",nlocal);
|
||||
d_jlist = typename AT::t_int_1d("qeq/kk:jlist",m_cap_big);
|
||||
d_val = typename AT::t_ffloat_1d("qeq/kk:val",m_cap_big);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user