Merge pull request #4543 from d-immel/apip
adaptive-precision interatomic potentials (APIP)
This commit is contained in:
@ -277,6 +277,7 @@ option(CMAKE_VERBOSE_MAKEFILE "Generate verbose Makefiles" OFF)
|
||||
set(STANDARD_PACKAGES
|
||||
ADIOS
|
||||
AMOEBA
|
||||
APIP
|
||||
ASPHERE
|
||||
ATC
|
||||
AWPMD
|
||||
@ -476,6 +477,7 @@ pkg_depends(ELECTRODE KSPACE)
|
||||
pkg_depends(EXTRA-MOLECULE MOLECULE)
|
||||
pkg_depends(MESONT MOLECULE)
|
||||
pkg_depends(RHEO BPM)
|
||||
pkg_depends(APIP ML-PACE)
|
||||
|
||||
# detect if we may enable OpenMP support by default
|
||||
set(BUILD_OMP_DEFAULT OFF)
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
set(ALL_PACKAGES
|
||||
ADIOS
|
||||
AMOEBA
|
||||
APIP
|
||||
ASPHERE
|
||||
ATC
|
||||
AWPMD
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
set(ALL_PACKAGES
|
||||
ADIOS
|
||||
AMOEBA
|
||||
APIP
|
||||
ASPHERE
|
||||
ATC
|
||||
AWPMD
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
set(PACKAGES_WITH_LIB
|
||||
ADIOS
|
||||
APIP
|
||||
ATC
|
||||
AWPMD
|
||||
COMPRESS
|
||||
|
||||
@ -35,6 +35,7 @@ This is the list of packages that may require additional steps.
|
||||
:columns: 6
|
||||
|
||||
* :ref:`ADIOS <adios>`
|
||||
* :ref:`APIP <apip>`
|
||||
* :ref:`ATC <atc>`
|
||||
* :ref:`AWPMD <awpmd>`
|
||||
* :ref:`COLVARS <colvar>`
|
||||
@ -1272,6 +1273,34 @@ systems.
|
||||
|
||||
----------
|
||||
|
||||
.. _apip:
|
||||
|
||||
APIP package
|
||||
-----------------------------
|
||||
|
||||
The APIP package depends on the library of the
|
||||
:ref:`ML-PACE <ml-pace>` package.
|
||||
The code for the library can be found
|
||||
at: `https://github.com/ICAMS/lammps-user-pace/ <https://github.com/ICAMS/lammps-user-pace/>`_
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. tab:: CMake build
|
||||
|
||||
No additional settings are needed besides ``-D PKG_APIP=yes``
|
||||
and ``-D PKG_ML-PACE=yes``.
|
||||
One can use a local version of the ML-PACE library instead of
|
||||
automatically downloading the library as described :ref:`here <ml-pace>`.
|
||||
|
||||
|
||||
.. tab:: Traditional make
|
||||
|
||||
You need to install the ML-PACE package *first* and follow
|
||||
the instructions :ref:`here <ml-pace>` before installing
|
||||
the APIP package.
|
||||
|
||||
----------
|
||||
|
||||
.. _atc:
|
||||
|
||||
ATC package
|
||||
|
||||
@ -22,6 +22,7 @@ OPT.
|
||||
* :doc:`append/atoms <fix_append_atoms>`
|
||||
* :doc:`atc <fix_atc>`
|
||||
* :doc:`atom/swap <fix_atom_swap>`
|
||||
* :doc:`atom_weight/apip <fix_atom_weight_apip>`
|
||||
* :doc:`ave/atom <fix_ave_atom>`
|
||||
* :doc:`ave/chunk <fix_ave_chunk>`
|
||||
* :doc:`ave/correlate <fix_ave_correlate>`
|
||||
@ -91,6 +92,8 @@ OPT.
|
||||
* :doc:`imd <fix_imd>`
|
||||
* :doc:`indent <fix_indent>`
|
||||
* :doc:`ipi <fix_ipi>`
|
||||
* :doc:`lambda/apip <fix_lambda_apip>`
|
||||
* :doc:`lambda_thermostat/apip <fix_lambda_thermostat_apip>`
|
||||
* :doc:`langevin (k) <fix_langevin>`
|
||||
* :doc:`langevin/drude <fix_langevin_drude>`
|
||||
* :doc:`langevin/eff <fix_langevin_eff>`
|
||||
|
||||
@ -96,7 +96,9 @@ OPT.
|
||||
* :doc:`eam/cd <pair_eam>`
|
||||
* :doc:`eam/cd/old <pair_eam>`
|
||||
* :doc:`eam/fs (gikot) <pair_eam>`
|
||||
* :doc:`eam/fs/apip <pair_eam_apip>`
|
||||
* :doc:`eam/he <pair_eam>`
|
||||
* :doc:`eam/apip <pair_eam_apip>`
|
||||
* :doc:`edip (o) <pair_edip>`
|
||||
* :doc:`edip/multi <pair_edip>`
|
||||
* :doc:`edpd (g) <pair_mesodpd>`
|
||||
@ -124,6 +126,9 @@ OPT.
|
||||
* :doc:`ilp/tmd (t) <pair_ilp_tmd>`
|
||||
* :doc:`kolmogorov/crespi/full <pair_kolmogorov_crespi_full>`
|
||||
* :doc:`kolmogorov/crespi/z <pair_kolmogorov_crespi_z>`
|
||||
* :doc:`lambda/input/apip <pair_lambda_input_apip>`
|
||||
* :doc:`lambda/input/csp/apip <pair_lambda_input_apip>`
|
||||
* :doc:`lambda/zone/apip <pair_lambda_zone_apip>`
|
||||
* :doc:`lcbop <pair_lcbop>`
|
||||
* :doc:`lebedeva/z <pair_lebedeva_z>`
|
||||
* :doc:`lennard/mdf <pair_mdf>`
|
||||
@ -237,6 +242,9 @@ OPT.
|
||||
* :doc:`oxrna2/coaxstk <pair_oxrna2>`
|
||||
* :doc:`pace (k) <pair_pace>`
|
||||
* :doc:`pace/extrapolation (k) <pair_pace>`
|
||||
* :doc:`pace/apip <pair_pace_apip>`
|
||||
* :doc:`pace/fast/apip <pair_pace_apip>`
|
||||
* :doc:`pace/precise/apip <pair_pace_apip>`
|
||||
* :doc:`pedone (o) <pair_pedone>`
|
||||
* :doc:`pod (k) <pair_pod>`
|
||||
* :doc:`peri/eps <pair_peri>`
|
||||
|
||||
@ -93,6 +93,7 @@ Packages howto
|
||||
Howto_manifold
|
||||
Howto_rheo
|
||||
Howto_spins
|
||||
Howto_apip
|
||||
|
||||
Tutorials howto
|
||||
===============
|
||||
|
||||
225
doc/src/Howto_apip.rst
Normal file
225
doc/src/Howto_apip.rst
Normal file
@ -0,0 +1,225 @@
|
||||
Adaptive-precision interatomic potentials (APIP)
|
||||
================================================
|
||||
|
||||
The :ref:`PKG-APIP <PKG-APIP>` enables use of adaptive-precision potentials
|
||||
as described in :ref:`(Immel) <Immel2025_1>`.
|
||||
In the context of this package, precision refers to the accuracy of an interatomic
|
||||
potential.
|
||||
|
||||
Modern machine-learning (ML) potentials translate the accuracy of DFT
|
||||
simulations into MD simulations, i.e., ML potentials are more accurate
|
||||
compared to traditional empirical potentials.
|
||||
However, this accuracy comes at a cost: there is a considerable performance
|
||||
gap between the evaluation of classical and ML potentials, e.g., the force
|
||||
calculation of a classical EAM potential is 100-1000 times faster compared
|
||||
to the ML-based ACE method.
|
||||
The evaluation time difference results in a conflict between large time and
|
||||
length scales on the one hand and accuracy on the other.
|
||||
This conflict is resolved by an APIP model for simulations, in which the highest precision
|
||||
is required only locally but not globally.
|
||||
|
||||
An APIP model uses a precise but
|
||||
expensive ML potential only for a subset of atoms, while a fast
|
||||
potential is used for the remaining atoms.
|
||||
Whether the precise or the fast potential is used is determined
|
||||
by a continuous switching parameter :math:`\lambda_i` that can be defined for each
|
||||
atom :math:`i`.
|
||||
The switching parameter can be adjusted dynamically during a simulation or
|
||||
kept constant as explained below.
|
||||
|
||||
The potential energy :math:`E_i` of an atom :math:`i` described by an
|
||||
adaptive-precision
|
||||
interatomic potential is given by :ref:`(Immel) <Immel2025_1>`
|
||||
|
||||
.. math::
|
||||
|
||||
E_i = \lambda_i E_i^\text{(fast)} + (1-\lambda_i) E_i^\text{(precise)},
|
||||
|
||||
whereas :math:`E_i^\text{(fast)}` is the potential energy of atom :math:`i`
|
||||
according to a fast interatomic potential,
|
||||
:math:`E_i^\text{(precise)}` is the potential energy according to a precise
|
||||
interatomic potential and :math:`\lambda_i\in[0,1]` is the
|
||||
switching parameter that decides how the potential energies are weighted.
|
||||
|
||||
Adaptive-precision saves computation time when the computation of the
|
||||
precise potential is not required for many atoms, i.e., when
|
||||
:math:`\lambda_i=1` applies for many atoms.
|
||||
|
||||
The currently implemented potentials are:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Fast potential
|
||||
- Precise potential
|
||||
* - :doc:`ACE <pair_pace_apip>`
|
||||
- :doc:`ACE <pair_pace_apip>`
|
||||
* - :doc:`EAM <pair_eam_apip>`
|
||||
-
|
||||
|
||||
In theory, any short-range potential can be used for an adaptive-precision
|
||||
interatomic potential. How to implement a new (fast or precise)
|
||||
adaptive-precision
|
||||
potential is explained in :ref:`here <implementing_new_apip_styles>`.
|
||||
|
||||
The switching parameter :math:`\lambda_i` that combines the two potentials
|
||||
can be dynamically calculated during a
|
||||
simulation.
|
||||
Alternatively, one can set a constant switching parameter before the start
|
||||
of a simulation.
|
||||
To run a simulation with an adaptive-precision potential, one needs the
|
||||
following components:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. tab:: dynamic switching parameter
|
||||
|
||||
#. :doc:`atom_style apip <atom_style>` so that the switching parameter :math:`\lambda_i` can be stored.
|
||||
#. A fast potential: :doc:`eam/apip <pair_eam_apip>` or :doc:`pace/fast/apip <pair_pace_apip>`.
|
||||
#. A precise potential: :doc:`pace/precise/apip <pair_pace_apip>`.
|
||||
#. :doc:`pair_style lambda/input/apip <pair_lambda_input_apip>` to calculate :math:`\lambda_i^\text{input}`, from which :math:`\lambda_i` is calculated.
|
||||
#. :doc:`fix lambda/apip <fix_lambda_apip>` to calculate the switching parameter :math:`\lambda_i`.
|
||||
#. :doc:`pair_style lambda/zone/apip <pair_lambda_zone_apip>` to calculate the spatial transition zone of the switching parameter.
|
||||
#. :doc:`pair_style hybrid/overlay <pair_hybrid>` to combine the previously mentioned pair_styles.
|
||||
#. :doc:`fix lambda_thermostat/apip <fix_lambda_thermostat_apip>` to conserve the energy when switching parameters change.
|
||||
#. :doc:`fix atom_weight/apip <fix_atom_weight_apip>` to approximate the load caused by every atom, as the computations of the pair_styles are only required for a subset of atoms.
|
||||
#. :doc:`fix balance <fix_balance>` to perform dynamic load balancing with the calculated load.
|
||||
|
||||
.. tab:: constant switching parameter
|
||||
|
||||
#. :doc:`atom_style apip <atom_style>` so that the switching parameter :math:`\lambda_i` can be stored.
|
||||
#. A fast potential: :doc:`eam/apip <pair_eam_apip>` or :doc:`pace/fast/apip <pair_pace_apip>`.
|
||||
#. A precise potential: :doc:`pace/precise/apip <pair_pace_apip>`.
|
||||
#. :doc:`set <set>` command to set the switching parameter :math:`\lambda_i`.
|
||||
#. :doc:`pair_style hybrid/overlay <pair_hybrid>` to combine the previously mentioned pair_styles.
|
||||
#. :doc:`fix atom_weight/apip <fix_atom_weight_apip>` to approximate the load caused by every atom, as the computations of the pair_styles are only required for a subset of atoms.
|
||||
#. :doc:`fix balance <fix_balance>` to perform dynamic load balancing with the calculated load.
|
||||
|
||||
----------
|
||||
|
||||
Example
|
||||
"""""""
|
||||
.. note::
|
||||
|
||||
How to select the values of the parameters of an adaptive-precision
|
||||
interatomic potential is discussed in detail in :ref:`(Immel) <Immel2025_1>`.
|
||||
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. tab:: dynamic switching parameter
|
||||
|
||||
Lines like these would appear in the input script:
|
||||
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
atom_style apip
|
||||
comm_style tiled
|
||||
|
||||
pair_style hybrid/overlay eam/fs/apip pace/precise/apip lambda/input/csp/apip fcc cutoff 5.0 lambda/zone/apip 12.0
|
||||
pair_coeff * * eam/fs/apip Cu.eam.fs Cu
|
||||
pair_coeff * * pace/precise/apip Cu.yace Cu
|
||||
pair_coeff * * lambda/input/csp/apip
|
||||
pair_coeff * * lambda/zone/apip
|
||||
|
||||
fix 2 all lambda/apip 2.5 3.0 time_averaged_zone 4.0 12.0 110 110 min_delta_lambda 0.01
|
||||
fix 3 all lambda_thermostat/apip N_rescaling 200
|
||||
fix 4 all atom_weight/apip 100 eam ace lambda/input lambda/zone all
|
||||
|
||||
variable myweight atom f_4
|
||||
|
||||
fix 5 all balance 100 1.1 rcb weight var myweight
|
||||
|
||||
First, the :doc:`atom_style apip <atom_style>` and the communication style are set.
|
||||
|
||||
.. note::
|
||||
Note, that :doc:`comm_style <comm_style>` *tiled* is required for the style *rcb* of
|
||||
:doc:`fix balance <fix_balance>`, but not for APIP.
|
||||
However, the flexibility offered by the balancing style *rcb*, compared to the
|
||||
balancing style *shift*, is advantageous for APIP.
|
||||
|
||||
An adaptive-precision EAM-ACE potential, for which the switching parameter
|
||||
:math:`\lambda` is calculated from the CSP, is defined via
|
||||
:doc:`pair_style hybrid/overlay <pair_hybrid>`.
|
||||
The fixes ensure that the switching parameter is calculated, the energy conserved,
|
||||
the weight for the load balancing calculated and the load-balancing itself is done.
|
||||
|
||||
.. tab:: constant switching parameter
|
||||
|
||||
Lines like these would appear in the input script:
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
atom_style apip
|
||||
comm_style tiled
|
||||
|
||||
pair_style hybrid/overlay eam/fs/apip pace/precise/apip
|
||||
pair_coeff * * eam/fs/apip Cu.eam.fs Cu
|
||||
pair_coeff * * pace/precise/apip Cu.yace Cu
|
||||
|
||||
# calculate lambda somehow
|
||||
variable lambda atom ...
|
||||
set group all apip/lambda v_lambda
|
||||
|
||||
fix 4 all atom_weight/apip 100 eam ace lambda/input lambda/zone all
|
||||
|
||||
variable myweight atom f_4
|
||||
|
||||
fix 5 all balance 100 1.1 rcb weight var myweight
|
||||
|
||||
First, the :doc:`atom_style apip <atom_style>` and the communication style are set.
|
||||
|
||||
.. note::
|
||||
Note, that :doc:`comm_style <comm_style>` *tiled* is required for the style *rcb* of
|
||||
:doc:`fix balance <fix_balance>`, but not for APIP.
|
||||
However, the flexibility offered by the balancing style *rcb*, compared to the
|
||||
balancing style *shift*, is advantageous for APIP.
|
||||
|
||||
An adaptive-precision EAM-ACE potential is defined via
|
||||
:doc:`pair_style hybrid/overlay <pair_hybrid>`.
|
||||
The switching parameter :math:`\lambda_i` of the adaptive-precision
|
||||
EAM-ACE potential is set via the :doc:`set command <set>`.
|
||||
The parameter is not updated during the simulation.
|
||||
Therefore, the potential is conservative.
|
||||
The fixes ensure that the weight for the load balancing is calculated
|
||||
and the load-balancing itself is done.
|
||||
|
||||
----------
|
||||
|
||||
.. _implementing_new_apip_styles:
|
||||
|
||||
Implementing new APIP pair styles
|
||||
"""""""""""""""""""""""""""""""""
|
||||
|
||||
One can introduce adaptive-precision to an existing pair style by modifying
|
||||
the original pair style.
|
||||
One should calculate the force
|
||||
:math:`F_i = - \nabla_i \sum_j E_j^\text{original}` for a fast potential or
|
||||
:math:`F_i = - (1-\nabla_i) \sum_j E_j^\text{original}` for a precise
|
||||
potential from the original potential
|
||||
energy :math:`E_j^\text{original}` to see where the switching parameter
|
||||
:math:`\lambda_i` needs to be introduced in the force calculation.
|
||||
The switching parameter :math:`\lambda_i` is known for all atoms :math:`i`
|
||||
in force calculation routine.
|
||||
One needs to introduce an abortion criterion based on :math:`\lambda_i` to
|
||||
ensure that all not required calculations are skipped and compute time can
|
||||
be saved.
|
||||
Furthermore, one needs to provide the number of calculations and measure the
|
||||
computation time.
|
||||
Communication within the force calculation needs to be prevented to allow
|
||||
effective load-balancing.
|
||||
With communication, the load balancer cannot balance few calculations of the
|
||||
precise potential on one processor with many computations of the fast
|
||||
potential on another processor.
|
||||
|
||||
All changes in the pair_style pace/apip compared to the pair_style pace
|
||||
are annotated and commented.
|
||||
Thus, the pair_style pace/apip can serve as an example for the implementation
|
||||
of new adaptive-precision potentials.
|
||||
|
||||
----------
|
||||
|
||||
.. _Immel2025_1:
|
||||
|
||||
**(Immel)** Immel, Drautz and Sutmann, J Chem Phys, 162, 114119 (2025)
|
||||
@ -28,6 +28,7 @@ gives those details.
|
||||
|
||||
* :ref:`ADIOS <PKG-ADIOS>`
|
||||
* :ref:`AMOEBA <PKG-AMOEBA>`
|
||||
* :ref:`APIP <PKG-APIP>`
|
||||
* :ref:`ASPHERE <PKG-ASPHERE>`
|
||||
* :ref:`ATC <PKG-ATC>`
|
||||
* :ref:`AWPMD <PKG-AWPMD>`
|
||||
@ -186,6 +187,60 @@ provided by the Ponder group in their
|
||||
|
||||
----------
|
||||
|
||||
.. _PKG-APIP:
|
||||
|
||||
APIP package
|
||||
------------
|
||||
|
||||
**Contents:**
|
||||
|
||||
This package provides adaptive-precision interatomic potentials (APIP) as
|
||||
described in:
|
||||
|
||||
D. Immel, R. Drautz and G. Sutmann, "Adaptive-precision potentials for
|
||||
large-scale atomistic simulations", J. Chem. Phys. 162, 114119 (2025)
|
||||
`link <immel2025_doi_>`_
|
||||
|
||||
Adaptive-precision means, that a fast interatomic potential, such as EAM,
|
||||
is coupled to a precise interatomic potential, such as ACE.
|
||||
This package provides the required pair_styles and fixes to run an efficient,
|
||||
energy-conserving adaptive-precision simulation.
|
||||
|
||||
In the context of this package, precision refers to the accuracy of an interatomic
|
||||
potential.
|
||||
|
||||
.. _immel2025_doi: https://doi.org/10.1063/5.0245877
|
||||
|
||||
**Authors:**
|
||||
|
||||
This package was written by David Immel^1,
|
||||
Ralf Drautz^2 and Godehard Sutmann^1^2.
|
||||
|
||||
^1: Forschungszentrum Juelich, Juelich, Germany
|
||||
|
||||
^2: Ruhr-University Bochum, Bochum, Germany
|
||||
|
||||
**Install:**
|
||||
|
||||
The APIP package requires also the installation of ML-PACE, which has
|
||||
:ref:`specific installation instructions <ml-pace>` on the
|
||||
:doc:`Build extras <Build_extras>` page.
|
||||
|
||||
**Supporting info:**
|
||||
|
||||
* ``src/APIP``: filenames -> commands
|
||||
* :doc:`Howto APIP <Howto_apip>`
|
||||
* ``examples/PACKAGES/apip``
|
||||
* :doc:`fix atom_weight/apip <fix_atom_weight_apip>`
|
||||
* :doc:`fix lambda/apip <fix_lambda_apip>`
|
||||
* :doc:`fix lambda_thermostat/apip <fix_lambda_thermostat_apip>`
|
||||
* :doc:`pair_style eam/apip <pair_eam_apip>`
|
||||
* :doc:`pair_style lambda/zone/apip <pair_lambda_zone_apip>`
|
||||
* :doc:`pair_style lambda/input/apip <pair_lambda_input_apip>`
|
||||
* :doc:`pair_style pace/apip <pair_pace_apip>`
|
||||
|
||||
----------
|
||||
|
||||
.. _PKG-ASPHERE:
|
||||
|
||||
ASPHERE package
|
||||
|
||||
@ -38,6 +38,11 @@ whether an extra library is needed to build and use the package:
|
||||
- :doc:`AMOEBA and HIPPO howto <Howto_amoeba>`
|
||||
- amoeba
|
||||
- no
|
||||
* - :ref:`APIP <PKG-APIP>`
|
||||
- adaptive-precision interatomic potentials
|
||||
- :doc:`Howto APIP <Howto_apip>`
|
||||
- ``PACKAGES/apip``
|
||||
- ext
|
||||
* - :ref:`ASPHERE <PKG-ASPHERE>`
|
||||
- aspherical particle models
|
||||
- :doc:`Howto spherical <Howto_spherical>`
|
||||
|
||||
@ -10,7 +10,7 @@ Syntax
|
||||
|
||||
atom_style style args
|
||||
|
||||
* style = *amoeba* or *angle* or *atomic* or *body* or *bond* or *charge* or *dielectric* or *dipole* or *dpd* or *edpd* or *electron* or *ellipsoid* or *full* or *line* or *mdpd* or *molecular* or *oxdna* or *peri* or *smd* or *sph* or *sphere* or *bpm/sphere* or *spin* or *tdpd* or *tri* or *template* or *wavepacket* or *hybrid*
|
||||
* style = *amoeba* or *angle* or *apip* or *atomic* or *body* or *bond* or *charge* or *dielectric* or *dipole* or *dpd* or *edpd* or *electron* or *ellipsoid* or *full* or *line* or *mdpd* or *molecular* or *oxdna* or *peri* or *smd* or *sph* or *sphere* or *bpm/sphere* or *spin* or *tdpd* or *tri* or *template* or *wavepacket* or *hybrid*
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
@ -117,6 +117,10 @@ the Additional Information section below.
|
||||
- *bond* + "angle data"
|
||||
- :ref:`MOLECULE <PKG-MOLECULE>`
|
||||
- bead-spring polymers with stiffness
|
||||
* - *apip*
|
||||
- *atomic* + apip_lambda, apip_lambda_required, apip_lambda_input, apip_lambda_const, apip_lambda_input_ta, apip_e_fast, apip_e_precise, apip_f_const_lambda, apip_f_dyn_lambda
|
||||
- :ref:`APIP <PKG-APIP>`
|
||||
- adaptive-precision interatomic potentials(APIP), see :doc:`APIP howto <Howto_apip>`
|
||||
* - *atomic*
|
||||
- tag, type, x, v, f, image, mask
|
||||
-
|
||||
|
||||
@ -34,6 +34,8 @@ Syntax
|
||||
i_name, d_name, i2_name[I], d2_name[I],
|
||||
vfrac, s0, espin, eradius, ervel, erforce,
|
||||
rho, drho, e, de, cv, buckling,
|
||||
apip_lambda, apip_lambda_input, apip_e_fast,
|
||||
apip_e_precise
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
@ -70,6 +72,13 @@ Syntax
|
||||
*i2_name[I]* = Ith column of custom integer array with name
|
||||
*d2_name[I]* = Ith column of custom floating-point array with name
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
APIP package per-atom properties:
|
||||
*apip_lambda* = switching parameter
|
||||
*apip_lambda_input* = input used to calculate the switching parameter
|
||||
*apip_e_fast,apip_e_precise* = potential energies mixed by the adaptive-precision potential
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
PERI package per-atom properties:
|
||||
@ -162,6 +171,22 @@ segment particles and define the end points of each line segment.
|
||||
*corner2z*, *corner3x*, *corner3y*, *corner3z*, are defined for
|
||||
triangular particles and define the corner points of each triangle.
|
||||
|
||||
The accessible quantities from the :doc:`APIP package <Howto_apip>` are
|
||||
explained in the doc pages of this package in detail.
|
||||
In short: *apip_lambda* is the switching parameter :math:`\lambda\in[0,1]`,
|
||||
that is calculated from *apip_lambda_input* and that mixes the energies
|
||||
of a fast (*apip_e_fast*) and a precise (*apip_e_precise*) potential
|
||||
into an adaptive-precision energy.
|
||||
|
||||
.. note::
|
||||
|
||||
The energy according to the fast and the precise potential are only
|
||||
computed for the subset of atoms, for which it is required, i.e.,
|
||||
for an atom :math:`i` with :math:`\lambda_i=1` one does not need
|
||||
:math:`E_i^\text{precise}` and with :math:`\lambda_i=0` one does
|
||||
not need :math:`E_i^\text{fast}`.
|
||||
|
||||
|
||||
In addition, the various per-atom quantities listed above for specific
|
||||
packages are only accessible by this command.
|
||||
|
||||
|
||||
@ -201,6 +201,7 @@ accelerated styles exist.
|
||||
* :doc:`append/atoms <fix_append_atoms>` - append atoms to a running simulation
|
||||
* :doc:`atc <fix_atc>` - initiates a coupled MD/FE simulation
|
||||
* :doc:`atom/swap <fix_atom_swap>` - Monte Carlo atom type swapping
|
||||
* :doc:`atom_weight/apip <fix_atom_weight_apip>` - compute atomic load of an :doc:`APIP potential <Howto_apip>` for load balancing
|
||||
* :doc:`ave/atom <fix_ave_atom>` - compute per-atom time-averaged quantities
|
||||
* :doc:`ave/chunk <fix_ave_chunk>` - compute per-chunk time-averaged quantities
|
||||
* :doc:`ave/correlate <fix_ave_correlate>` - compute/output time correlations
|
||||
@ -270,6 +271,7 @@ accelerated styles exist.
|
||||
* :doc:`imd <fix_imd>` - implements the "Interactive MD" (IMD) protocol
|
||||
* :doc:`indent <fix_indent>` - impose force due to an indenter
|
||||
* :doc:`ipi <fix_ipi>` - enable LAMMPS to run as a client for i-PI path-integral simulations
|
||||
* :doc:`lambda/apip <fix_lambda_apip>` - compute switching parameter, that controls the precision of an :doc:`APIP potential <Howto_apip>`
|
||||
* :doc:`langevin <fix_langevin>` - Langevin temperature control
|
||||
* :doc:`langevin/drude <fix_langevin_drude>` - Langevin temperature control of Drude oscillators
|
||||
* :doc:`langevin/eff <fix_langevin_eff>` - Langevin temperature control for the electron force field model
|
||||
@ -278,6 +280,7 @@ accelerated styles exist.
|
||||
* :doc:`lb/momentum <fix_lb_momentum>` - :doc:`fix momentum <fix_momentum>` replacement for use with a lattice-Boltzmann fluid
|
||||
* :doc:`lb/viscous <fix_lb_viscous>` - :doc:`fix viscous <fix_viscous>` replacement for use with a lattice-Boltzmann fluid
|
||||
* :doc:`lineforce <fix_lineforce>` - constrain atoms to move in a line
|
||||
* :doc:`lambda_thermostat/apip <fix_lambda_thermostat_apip>` - apply energy conserving correction for an :doc:`APIP potential <Howto_apip>`
|
||||
* :doc:`manifoldforce <fix_manifoldforce>` - restrain atoms to a manifold during minimization
|
||||
* :doc:`mdi/qm <fix_mdi_qm>` - LAMMPS operates as a client for a quantum code via the MolSSI Driver Interface (MDI)
|
||||
* :doc:`mdi/qmmm <fix_mdi_qmmm>` - LAMMPS operates as client for QM/MM simulation with a quantum code via the MolSSI Driver Interface (MDI)
|
||||
|
||||
143
doc/src/fix_atom_weight_apip.rst
Normal file
143
doc/src/fix_atom_weight_apip.rst
Normal file
@ -0,0 +1,143 @@
|
||||
.. index:: fix atom_weight/apip
|
||||
|
||||
fix atom_weight/apip command
|
||||
============================
|
||||
|
||||
Syntax
|
||||
""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
fix ID group-ID atom_weight/apip nevery fast_potential precise_potential lambda_input lambda_zone group_lambda_input [no_rescale]
|
||||
|
||||
* ID, group-ID are documented in :doc:`fix <fix>` command
|
||||
* atom_weight/apip = style name of this fix command
|
||||
* nevery = perform load calculation every this many steps
|
||||
* fast_potential = *eam* or *ace* for time measurements of the corresponding pair_style or float for constant time
|
||||
* precise_potential = *ace* for a time measurement of the pair_style pace/apip or float for constant time
|
||||
* lambda_input = *lambda/input* for a time measurement of pair_style lambda/input/apip or float for constant time
|
||||
* lambda_zone = *lambda/zone* for a time measurement of pair_style lambda/zone/apip or float for constant time
|
||||
* group_lambda_input = group-ID of the group for which lambda_input is computed
|
||||
* no_rescale = do not rescale the work per processor to the measured total force-computation time
|
||||
|
||||
Examples
|
||||
""""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
fix 2 all atom_weight/apip 50 eam ace lambda/input lambda/zone all
|
||||
fix 2 all atom_weight/apip 50 1e-05 0.0004 4e-06 4e-06 all
|
||||
fix 2 all atom_weight/apip 50 ace ace 4e-06 4e-06 all no_rescale
|
||||
|
||||
Description
|
||||
"""""""""""
|
||||
|
||||
This command approximates the load every atom causes when an
|
||||
adaptive-precision interatomic potential (APIP) according to
|
||||
:ref:`(Immel) <Immel2025_2>` is used.
|
||||
This approximated load can be saved as atomic variable and
|
||||
used as input for the dynamic load balancing via the
|
||||
:doc:`fix balance <fix_balance>` command.
|
||||
|
||||
An adaptive-precision potential like :doc:`eam/apip <pair_eam_apip>`
|
||||
and :doc:`pace/apip <pair_pace_apip>` is calculated only
|
||||
for a subset of atoms.
|
||||
The switching parameter that determines per atom, which potential energy is
|
||||
used, can be also calculated by
|
||||
:doc:`pair_style lambda/input/apip <pair_lambda_input_apip>`.
|
||||
A spatial switching zone, that ensures a smooth transition between two
|
||||
different interatomic potentials, can be calculated by
|
||||
:doc:`pair_style lambda/zone/apip <pair_lambda_zone_apip>`.
|
||||
Thus, there are up to four force-subroutines, that are computed only for a
|
||||
subset of atoms and combined via the pair_style :doc:`hybrid/overlay <pair_hybrid>`.
|
||||
For all four force-subroutines, the average work per atom is be measured
|
||||
per processor by the corresponding pair_style.
|
||||
This fix extracts these measurements of the pair styles every *nevery*
|
||||
steps. The average compute times are used to calculates a per-atom vector with
|
||||
the approximated atomic weight, whereas the average compute time of the four
|
||||
subroutines contributes only to the load of atoms, for which the corresponding
|
||||
subroutine was calculated.
|
||||
If not disabled via *no_rescale*, the so calculated load is
|
||||
rescaled per processor so that the total atomic compute time matches the
|
||||
also measured total compute time of the whole pair_style.
|
||||
This atomic weight is intended to be used
|
||||
as input for :doc:`fix balance <fix_balance>`:
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
variable nevery equal 10
|
||||
fix weight_atom all atom_weight/apip ${nevery} eam ace lambda/input lambda/zone all
|
||||
variable myweight atom f_weight_atom
|
||||
fix balance all balance ${nevery} 1.1 rcb weight var myweight
|
||||
|
||||
Furthermore, this fix provides the over the processors averaged compute time of the
|
||||
four pair_styles, which are used to approximate the atomic weight, as vector.
|
||||
|
||||
----------
|
||||
|
||||
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.
|
||||
|
||||
This fix produces a per-atom vector that contains the atomic
|
||||
weight of each atom.
|
||||
The per-atom vector can only be accessed on timesteps that are multiples
|
||||
of *nevery*.
|
||||
|
||||
Furthermore, this fix computes a global vector of length 4 with
|
||||
statistical information about the four different (possibly)
|
||||
measured compute times per force subroutine. The four
|
||||
values in the vector are as follows:
|
||||
|
||||
#. average compute time for one atom using the fast pair_style
|
||||
#. average compute time for one atom using the precise pair_style
|
||||
#. average compute time of lambda/input/apip for one atom
|
||||
#. average compute time of lambda/zone/apip for one atom
|
||||
|
||||
The compute times are computed as average of all processors that
|
||||
measured at least one computation of the corresponding style.
|
||||
The vector values calculated by this fix are "intensive" and
|
||||
updated whenever the per-atom vector is computed, i.e., in
|
||||
timesteps that are multiples of *nevery*.
|
||||
|
||||
The vector and the per-atom vector can be accessed by various
|
||||
:doc:`output commands <Howto_output>`.
|
||||
|
||||
|
||||
No parameter of this fix can be used with the *start/stop* keywords of
|
||||
the :doc:`run <run>` command. This fix is not invoked during
|
||||
:doc:`energy minimization <minimize>`.
|
||||
|
||||
----------
|
||||
|
||||
Restrictions
|
||||
""""""""""""
|
||||
|
||||
This fix is part of the APIP package. It is only enabled if
|
||||
LAMMPS was built with that package. See the :doc:`Build package
|
||||
<Build_package>` page for more info.
|
||||
|
||||
Related commands
|
||||
""""""""""""""""
|
||||
|
||||
:doc:`fix balance <fix_balance>`,
|
||||
:doc:`fix lambda/apip <fix_lambda_apip>`,
|
||||
:doc:`fix lambda_thermostat/apip <fix_lambda_thermostat_apip>`,
|
||||
:doc:`pair_style lambda/zone/apip <pair_lambda_zone_apip>`,
|
||||
:doc:`pair_style lambda/input/apip <pair_lambda_input_apip>`,
|
||||
:doc:`pair_style eam/apip <pair_eam_apip>`,
|
||||
:doc:`pair_style pace/apip <pair_pace_apip>`,
|
||||
|
||||
Default
|
||||
"""""""
|
||||
|
||||
*no_rescale* is not used by default.
|
||||
|
||||
----------
|
||||
|
||||
.. _Immel2025_2:
|
||||
|
||||
**(Immel)** Immel, Drautz and Sutmann, J Chem Phys, 162, 114119 (2025)
|
||||
262
doc/src/fix_lambda_apip.rst
Normal file
262
doc/src/fix_lambda_apip.rst
Normal file
@ -0,0 +1,262 @@
|
||||
.. index:: fix lambda/apip
|
||||
|
||||
fix lambda/apip command
|
||||
=======================
|
||||
|
||||
Syntax
|
||||
""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
fix ID group-ID lambda/apip thr_lo thr_hi keyword args ...
|
||||
|
||||
* ID, group-ID are documented in :doc:`fix <fix>` command
|
||||
* lambda/apip = style name of this fix command
|
||||
* thr_lo = value below which :math:`\lambda_i^\text{input}` results in a switching parameter of 1
|
||||
* thr_hi = value above which :math:`\lambda_i^\text{input}` results in a switching parameter of 0
|
||||
* zero or one keyword/args pairs may be appended
|
||||
* keyword = *time_averaged_zone* or *min_delta_lambda* or *lambda_non_group* or *store_atomic_stats* or *dump_atomic_history* or *group_fast* or *group_precise* or *group_ignore_lambda_input*
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
*time_averaged_zone* args = cut_lo cut_hi history_len_lambda_input history_len_lambda
|
||||
cut_lo = distance at which the radial function decreases from 1
|
||||
cut_hi = distance from which on the radial function is 0
|
||||
history_len_lambda_input = number of time steps for which lambda_input is averaged
|
||||
history_len_lambda = number of time steps for which the switching parameter is averaged
|
||||
*min_delta_lambda* args = delta
|
||||
delta = value below which changes of the switching parameter are neglected (>= 0)
|
||||
*lambda_non_group* args = lambda_ng
|
||||
lambda_ng = *precise* or *fast* or float
|
||||
*precise* = assign a constant switching parameter of 0 to atoms, that are not in the group specified by group-ID
|
||||
*fast* = assign a constant switching parameter of 1 to atoms, that are not in the group specified by group-ID
|
||||
float = assign this constant switching parameter to atoms, that are not in the group specified by group-ID (0 <= float <= 1)
|
||||
*group_fast* args = group-ID-fast
|
||||
group-ID-fast = the switching parameter of 1 is used instead of the one computed by lambda_input for atoms in the group specified by group-ID-fast
|
||||
*group_precise* args = group-ID-precise
|
||||
group-ID-precise = the switching parameter of 0 is used instead of the one computed by lambda_input for atoms in the group specified by group-ID-precise
|
||||
*group_ignore_lambda_input* args = group-ID-ignore-lambda-input
|
||||
group-ID-ignore-lambda-input = the switching parameter of lambda_ng is used instead of the one computed by lambda_input for atoms in the group specified by group-ID-ignore-lambda-input
|
||||
*store_atomic_stats* args = none
|
||||
*dump_atomic_history* args = none
|
||||
|
||||
Examples
|
||||
""""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
fix 2 all lambda/apip 3.0 3.5 time_averaged_zone 4.0 12.0 110 110 min_delta_lambda 0.01
|
||||
fix 2 mobile lambda/apip 3.0 3.5 time_averaged_zone 4.0 12.0 110 110 min_delta_lambda 0.01 group_ignore_lambda_input immobile lambda_non_group fast
|
||||
|
||||
Description
|
||||
"""""""""""
|
||||
The potential energy :math:`E_i` of an atom :math:`i` of an adaptive-precision
|
||||
potential according to :ref:`(Immel) <Immel2025_3>` is given by
|
||||
|
||||
.. math::
|
||||
|
||||
E_i = \lambda_i E_i^\text{(fast)} + (1-\lambda_i) E_i^\text{(precise)},
|
||||
|
||||
whereas :math:`E_i^\text{(fast)}` is the potential energy of atom :math:`i`
|
||||
according to a fast interatomic potential like EAM,
|
||||
:math:`E_i^\text{(precise)}` is the potential energy according to a precise
|
||||
interatomic potential such as ACE and :math:`\lambda_i\in[0,1]` is the
|
||||
switching parameter that decides which potential energy is used.
|
||||
This fix calculates the switching parameter :math:`\lambda_i` based on the
|
||||
input provided from :doc:`pair_style lambda/input/apip <pair_lambda_input_apip>`.
|
||||
|
||||
The calculation of the switching parameter is described in detail in
|
||||
:ref:`(Immel) <Immel2025_3>`.
|
||||
This fix calculates the switching parameter for all atoms in the
|
||||
:doc:`group <group>`
|
||||
described by group-ID, while the value of *lambda_non_group* is used
|
||||
as switching parameter for all other atoms.
|
||||
|
||||
First, this fix calculates per atom :math:`i` the time averaged input
|
||||
:math:`\lambda^\text{input}_{\text{avg},i}` from
|
||||
:math:`\lambda^\text{input}_{i}`, whereas the number of averaged timesteps
|
||||
can be set via *time_averaged_zone*.
|
||||
|
||||
.. note::
|
||||
|
||||
:math:`\lambda^\text{input}_{i}` is calculated by
|
||||
:doc:`pair_style lambda/input/apip <pair_lambda_input_apip>`, which needs to be included
|
||||
in the input script as well.
|
||||
|
||||
The time averaged input :math:`\lambda^\text{input}_{\text{avg},i}` is then
|
||||
used to calculate the switching parameter
|
||||
|
||||
.. math::
|
||||
|
||||
\lambda_{0,i}(t) = f^\text{(cut)} \left(\frac{\lambda_{\text{avg},i}^\text{input}(t) - \lambda_\text{lo}^\text{input}}{\lambda_\text{hi}^\text{input} - \lambda_\text{lo}^\text{input}} \right)\,,
|
||||
|
||||
whereas the thresholds :math:`\lambda_\text{hi}^\text{input}`
|
||||
and :math:`\lambda_\text{lo}^\text{input}` are set by the
|
||||
values provided as *thr_lo* and *thr_hi* and :math:`f^\text{(cut)}(x)` is a cutoff function
|
||||
that is 1 for :math:`x\leq 0`, decays from 1 to 0 for :math:`x\in[0,1]`, and
|
||||
is 0 for :math:`x\geq 1`.
|
||||
If the *group_precise* argument is used, :math:`\lambda_{0,i}=0` is used for all
|
||||
atoms :math:`i` assigned to the corresponding :doc:`group <group>`.
|
||||
If the *group_fast* argument is used, :math:`\lambda_{0,i}=1` is used for all
|
||||
atoms :math:`i` assigned to the corresponding :doc:`group <group>`.
|
||||
If an atom is in the groups *group_fast* and *group_precise*,
|
||||
:math:`\lambda_{0,i}=0` is used.
|
||||
If the *group_ignore_lambda_input* argument is used,
|
||||
:math:`\lambda_i^\text{input}` is not computed for all atoms :math:`i` assigned
|
||||
to the corresponding :doc:`group <group>`; instead, if the value is not already
|
||||
set by *group_fast* or *group_precise*, the value of *lambda_non_group* is
|
||||
used.
|
||||
|
||||
.. note::
|
||||
|
||||
The computation of :math:`\lambda_i^\text{input}` is not required for
|
||||
atoms that are in the groups *group_fast* and *group_precise*.
|
||||
Thus, one should use *group_ignore_lambda_input* and prevent the
|
||||
computation of :math:`\lambda_i^\text{input}` for all atoms, for
|
||||
which a constant input is used.
|
||||
|
||||
A spatial transition zone between the fast and the precise potential is
|
||||
introduced via
|
||||
|
||||
.. math::
|
||||
|
||||
\lambda_{\text{min},i}(t) = \text{min}\left(\left\{1 - (1 -\lambda_{0,j}(t)) f^\text{(cut)}\left(\frac{r_{ij}(t)-r_{\lambda,\text{lo}}}{r_{\lambda,\text{hi}} - r_{\lambda,\text{lo}}}\right) : j \in \Omega_{\lambda,i} \right\}\right)\,,
|
||||
|
||||
whereas the thresholds :math:`r_{\lambda,\text{lo}}` and
|
||||
:math:`r_{\lambda,\text{hi}}`
|
||||
of the cutoff function are set via *time_averaged_zone* and
|
||||
:math:`\Omega_{\lambda,i}` is the set of
|
||||
neighboring atoms of atom :math:`i`.
|
||||
|
||||
.. note::
|
||||
|
||||
:math:`\lambda_{\text{min},i}` is calculated by
|
||||
:doc:`pair_style lambda/zone/apip <pair_lambda_zone_apip>`, which needs to be included
|
||||
in the input script as well.
|
||||
|
||||
The switching parameter is smoothed by the calculation of the time average
|
||||
|
||||
.. math::
|
||||
|
||||
\lambda_{\text{avg},i}(t) = \frac{1}{N_{\lambda,\text{avg}}} \sum_{n=1}^{N_{\lambda,\text{avg}}} \lambda_{\text{min},i}(t - n \Delta t)\,,
|
||||
|
||||
whereas :math:`\Delta t` is the :doc:`timestep <timestep>` and
|
||||
:math:`N_{\lambda,\text{avg}}` is the number of averaged timesteps, that
|
||||
can be set via *time_averaged_zone*.
|
||||
|
||||
Finally, numerical fluctuations of the switching parameter are suppressed by the usage of
|
||||
|
||||
.. math::
|
||||
|
||||
\lambda_{i}(t) = \left\{
|
||||
\begin{array}{ll}
|
||||
\lambda_{\text{avg},i}(t) & \text{ for } \left|\lambda_{\text{avg},i}(t) - \lambda_{i}(t-\Delta t)\right|\geq \Delta\lambda_\text{min} \text{ or } \lambda_{\text{avg},i}(t)\in\{0,1\}, \\
|
||||
\lambda_{i}(t-\Delta t) & \text{ otherwise}\,,
|
||||
\end{array}
|
||||
\right.
|
||||
|
||||
whereas the minimum change :math:`\Delta\lambda_\text{min}` is set by the
|
||||
*min_delta_lambda* argument.
|
||||
|
||||
.. note::
|
||||
|
||||
*group_fast* affects only :math:`\lambda_{0,i}(t)`. The switching parameter
|
||||
of atoms in this :doc:`group <group>` may change due to the calculation of the
|
||||
spatial switching zone.
|
||||
A switching parameter of 1 can be enforced by excluding the corresponding
|
||||
atoms from the :doc:`group <group>` described by group-ID and using *lambda_non_group* 1
|
||||
as argument.
|
||||
|
||||
----------
|
||||
|
||||
A code example for the calculation of the switching parameter for an
|
||||
adaptive-precision potential is given in the following:
|
||||
The adaptive-precision potential is created
|
||||
by combining :doc:`pair_style eam/fs/apip <pair_eam_apip>`
|
||||
and :doc:`pair_style pace/precise/apip <pair_pace_apip>`.
|
||||
The input, from which the switching parameter is calculated, is provided
|
||||
by :doc:`pair lambda/input/csp/apip <pair_lambda_input_apip>`.
|
||||
The switching parameter is calculated by this fix, whereas the spatial
|
||||
transition zone of the switching parameter is calculated by
|
||||
:doc:`pair_style lambda/zone/apip <pair_lambda_zone_apip>`.
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
pair_style hybrid/overlay eam/fs/apip pace/precise/apip lambda/input/csp/apip fcc cutoff 5.0 lambda/zone/apip 12.0
|
||||
pair_coeff * * eam/fs/apip Cu.eam.fs Cu
|
||||
pair_coeff * * pace/precise/apip Cu_precise.yace Cu
|
||||
pair_coeff * * lambda/input/csp/apip
|
||||
pair_coeff * * lambda/zone/apip
|
||||
fix 2 all lambda/apip 3.0 3.5 time_averaged_zone 4.0 12.0 110 110 min_delta_lambda 0.01
|
||||
|
||||
|
||||
----------
|
||||
|
||||
Restart, fix_modify, output, run start/stop, minimize info
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
The saved history of the switching parameter :math:`\lambda_i`
|
||||
and the saved history of
|
||||
:math:`\lambda_i^\text{input}` are written to
|
||||
:doc:`binary restart files <restart>` allow a smooth restart of a simulation.
|
||||
None of the :doc:`fix_modify <fix_modify>` options are relevant to this fix.
|
||||
|
||||
If the *store_atomic_stats* argument is used, basic statistics is provided as
|
||||
per-atom array:
|
||||
|
||||
#. :math:`\lambda_i^\text{input}(t)`
|
||||
#. :math:`\lambda_{\text{avg},i}^\text{input}(t)`
|
||||
#. :math:`\lambda_{0,i}(t)`
|
||||
#. :math:`\lambda_{\text{min},i}(t)`
|
||||
#. :math:`\lambda_{i}(t)`
|
||||
|
||||
If the *dump_atomic_history* argument is used, the whole saved history
|
||||
of :math:`\lambda_i^\text{input}(t)` is appended to the previously
|
||||
mentioned array per atom.
|
||||
|
||||
The per-atom vector can be accessed by various
|
||||
:doc:`output commands <Howto_output>`.
|
||||
|
||||
No parameter of this fix can be used with the *start/stop* keywords of
|
||||
the :doc:`run <run>` command. This fix is not invoked during
|
||||
:doc:`energy minimization <minimize>`.
|
||||
|
||||
----------
|
||||
|
||||
Restrictions
|
||||
""""""""""""
|
||||
|
||||
This fix is part of the APIP package. It is only enabled if
|
||||
LAMMPS was built with that package. See the :doc:`Build package
|
||||
<Build_package>` page for more info.
|
||||
|
||||
Related commands
|
||||
""""""""""""""""
|
||||
|
||||
:doc:`pair_style lambda/zone/apip <pair_lambda_zone_apip>`,
|
||||
:doc:`pair_style lambda/input/apip <pair_lambda_input_apip>`,
|
||||
:doc:`pair_style eam/apip <pair_eam_apip>`,
|
||||
:doc:`pair_style pace/apip <pair_pace_apip>`,
|
||||
:doc:`fix atom_weight/apip <fix_atom_weight_apip>`
|
||||
:doc:`fix lambda_thermostat/apip <fix_lambda_thermostat_apip>`,
|
||||
|
||||
Default
|
||||
"""""""
|
||||
|
||||
*min_delta_lambda* = 0,
|
||||
*lambda_non_group* = 1,
|
||||
*cut_lo* = 4.0,
|
||||
*cut_hi* = 12.0,
|
||||
*history_len_lambda_input* = 100,
|
||||
*history_len_lambda* = 100,
|
||||
*store_atomic_stats* is not used,
|
||||
*dump_atomic_history* is not used,
|
||||
*group_fast* is not used,
|
||||
*group_precise* is not used,
|
||||
*group_ignore_lambda_input* is not used
|
||||
|
||||
----------
|
||||
|
||||
.. _Immel2025_3:
|
||||
|
||||
**(Immel)** Immel, Drautz and Sutmann, J Chem Phys, 162, 114119 (2025)
|
||||
176
doc/src/fix_lambda_thermostat_apip.rst
Normal file
176
doc/src/fix_lambda_thermostat_apip.rst
Normal file
@ -0,0 +1,176 @@
|
||||
.. index:: fix lambda_thermostat/apip
|
||||
|
||||
fix lambda_thermostat/apip command
|
||||
==================================
|
||||
|
||||
Syntax
|
||||
""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
fix ID group-ID lambda_thermostat/apip keyword values ...
|
||||
|
||||
* ID, group-ID are documented in :doc:`fix <fix>` command
|
||||
* lambda_thermostat/apip = style name of this fix command
|
||||
* zero or more keyword/value pairs may be appended
|
||||
* keyword = *seed* or *store_atomic_forces* or *N_rescaling*
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
*seed* value = integer
|
||||
integer = integer that is used as seed for the random number generator (> 0)
|
||||
*store_atomic_forces* value = nevery
|
||||
nevery = provide per-atom output every this many steps
|
||||
*N_rescaling* value = groupsize
|
||||
groupsize = rescale this many neighboring atoms (> 1)
|
||||
|
||||
Examples
|
||||
""""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
fix 2 all lambda_thermostat/apip
|
||||
fix 2 all lambda_thermostat/apip N_rescaling 100
|
||||
fix 2 all lambda_thermostat/apip seed 42
|
||||
fix 2 all lambda_thermostat/apip seed 42 store_atomic_forces 1000
|
||||
|
||||
Description
|
||||
"""""""""""
|
||||
|
||||
This command applies the local thermostat described in
|
||||
:ref:`(Immel) <Immel2025_4>`
|
||||
to conserve the energy when the switching parameters of an
|
||||
:doc:`adaptive-precision interatomic potential <Howto_apip>` (APIP)
|
||||
are updated while the gradient
|
||||
of the switching parameter is neglected in the force calculation.
|
||||
|
||||
.. warning::
|
||||
|
||||
The temperature change caused by this fix is only the means to the end of
|
||||
conserving the energy. Thus, this fix is not a classical thermostat, that
|
||||
ensures a given temperature in the system.
|
||||
All available thermostats are listed :doc:`here <Howto_thermostat>`.
|
||||
|
||||
The potential energy :math:`E_i` of an atom :math:`i` is given by the formula from
|
||||
:ref:`(Immel) <Immel2025_4>`
|
||||
|
||||
.. math::
|
||||
|
||||
E_i = \lambda_i E_i^\text{(fast)} + (1-\lambda_i) E_i^\text{(precise)},
|
||||
|
||||
whereas :math:`E_i^\text{(fast)}` is the potential energy of atom :math:`i`
|
||||
according to a fast interatomic potential like EAM,
|
||||
:math:`E_i^\text{(precise)}` is the potential energy according to a precise
|
||||
interatomic potential such as ACE and :math:`\lambda_i\in[0,1]` is the
|
||||
switching parameter that decides which potential energy is used.
|
||||
This potential energy and the corresponding forces are conservative when
|
||||
the switching parameter :math:`\lambda_i` is constant in time for all atoms
|
||||
:math:`i`.
|
||||
|
||||
For a conservative force calculation and dynamic switching parameters,
|
||||
the atomic force on an atom is given by
|
||||
:math:`F_i = -\nabla_i \sum_j E_j` and includes the derivative of the switching
|
||||
parameter :math:`\lambda_i`.
|
||||
The force contribution of this gradient of the switching function can cause
|
||||
large forces which are not similar to the forces of the fast or the precise
|
||||
interatomic potential as discussed in :ref:`(Immel) <Immel2025_4>`.
|
||||
Thus, one can neglect the gradient of the switching parameter in the force
|
||||
calculation and compensate for the violation of energy conservation by
|
||||
the application of the local thermostat implemented in this fix.
|
||||
One can compute the violation of the energy conservation :math:`\Delta H_i`
|
||||
for all atoms :math:`i` as discussed in :ref:`(Immel) <Immel2025_4>`.
|
||||
To locally correct this energy violation :math:`\Delta H_i`, one
|
||||
can rescale the velocity of atom :math:`i` and of neighboring atoms.
|
||||
The rescaling is done relative to the center-of-mass velocity of the
|
||||
group and, thus, conserves the momentum.
|
||||
|
||||
.. note::
|
||||
|
||||
This local thermostat provides the NVE ensemble rather than the NVT
|
||||
ensemble as
|
||||
the energy :math:`\Delta H_i` determines the rescaling factor rather than
|
||||
a temperature.
|
||||
|
||||
Velocities :math:`v` are updated by the integrator according to
|
||||
:math:`\Delta v_i = (F_i/m_i)\Delta t`, whereas `m` denotes the mass of atom
|
||||
:math:`i` and :math:`\Delta t` is the time step.
|
||||
One can interpret the velocity difference :math:`\Delta v` caused by the
|
||||
rescaling as the application of an additional force which is given by
|
||||
:math:`F^\text{lt}_i = (v^\text{unscaled}_i - v^\text{rescaled}_i) m_i
|
||||
/ \Delta t` :ref:`(Immel) <Immel2025_4>`.
|
||||
This additional force is computed when the *store_atomic_forces* option
|
||||
is used.
|
||||
|
||||
The local thermostat is not appropriate for simulations at a temperature of 0K.
|
||||
|
||||
.. note::
|
||||
|
||||
The maximum decrease of the kinetic energy is achieved with a rescaling
|
||||
factor of 0, i.e., the relative velocity of the group of rescaled atoms
|
||||
is set to zero. One cannot decrease the energy further. Thus, the
|
||||
local thermostat can fail, which is, however, reported by the returned
|
||||
vector.
|
||||
|
||||
----------
|
||||
|
||||
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.
|
||||
|
||||
If the *store_atomic_forces* option is used, this fix produces every
|
||||
*nevery* time steps a per-atom array that contains the theoretical force
|
||||
applied by the local thermostat in all three spatial dimensions in the first
|
||||
three components. :math:`\Delta H_i` is the fourth component of the per-atom
|
||||
array.
|
||||
The per-atom array can only be accessed on timesteps that are multiples
|
||||
of *nevery*.
|
||||
|
||||
Furthermore, this fix computes a global vector of length 6 with
|
||||
information about the rescaling:
|
||||
|
||||
#. number of atoms whose energy changed due to the last :math:`\lambda` update
|
||||
#. contribution of the potential energy to the last computed :math:`\Delta H`
|
||||
#. contribution of the kinetic energy to the last computed :math:`\Delta H`
|
||||
#. sum over all atoms of the absolute energy change caused by the last rescaling step
|
||||
#. energy change that could not be compensated accumulated over all timesteps
|
||||
#. number of atoms whose energy change could not be compensated accumulated over all timesteps
|
||||
|
||||
The vector and the per-atom vector can be accessed by various
|
||||
:doc:`output commands <Howto_output>`.
|
||||
|
||||
No parameter of this fix can be used with the *start/stop* keywords of
|
||||
the :doc:`run <run>` command. This fix is not invoked during
|
||||
:doc:`energy minimization <minimize>`.
|
||||
|
||||
----------
|
||||
|
||||
Restrictions
|
||||
""""""""""""
|
||||
|
||||
This fix is part of the APIP package. It is only enabled if
|
||||
LAMMPS was built with that package. See the :doc:`Build package
|
||||
<Build_package>` page for more info.
|
||||
|
||||
Related commands
|
||||
""""""""""""""""
|
||||
|
||||
:doc:`fix lambda/apip <fix_lambda_apip>`,
|
||||
:doc:`pair_style lambda/zone/apip <pair_lambda_zone_apip>`,
|
||||
:doc:`pair_style lambda/input/apip <pair_lambda_input_apip>`,
|
||||
:doc:`pair_style eam/apip <pair_eam_apip>`,
|
||||
:doc:`pair_style pace/apip <pair_pace_apip>`,
|
||||
:doc:`fix atom_weight/apip <fix_atom_weight_apip>`
|
||||
|
||||
Default
|
||||
"""""""
|
||||
|
||||
seed = 42, N_rescaling = 200, *store_atomic_forces* is not used
|
||||
|
||||
----------
|
||||
|
||||
.. _Immel2025_4:
|
||||
|
||||
**(Immel)** Immel, Drautz and Sutmann, J Chem Phys, 162, 114119 (2025)
|
||||
127
doc/src/pair_eam_apip.rst
Normal file
127
doc/src/pair_eam_apip.rst
Normal file
@ -0,0 +1,127 @@
|
||||
.. index:: pair_style eam/apip
|
||||
.. index:: pair_style eam/fs/apip
|
||||
|
||||
pair_style eam/apip command
|
||||
=============================
|
||||
|
||||
Constant precision variant: *eam*
|
||||
|
||||
pair_style eam/fs/apip command
|
||||
================================
|
||||
|
||||
Constant precision variant: *eam/fs*
|
||||
|
||||
Syntax
|
||||
""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
pair_style eam/apip
|
||||
pair_style eam/fs/apip
|
||||
|
||||
Examples
|
||||
""""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
pair_style hybrid/overlay eam/fs/apip pace/precise/apip lambda/input/csp/apip fcc cutoff 5.0 lambda/zone/apip 12.0
|
||||
pair_coeff * * eam/fs/apip Cu.eam.fs Cu
|
||||
pair_coeff * * pace/precise/apip Cu_precise.yace Cu
|
||||
pair_coeff * * lambda/input/csp/apip
|
||||
pair_coeff * * lambda/zone/apip
|
||||
|
||||
|
||||
Description
|
||||
"""""""""""
|
||||
Style *eam* computes pairwise interactions for metals and metal alloys
|
||||
using embedded-atom method (EAM) potentials :ref:`(Daw) <Daw2>`. The total
|
||||
energy :math:`E_i` of an atom :math:`i` is given by
|
||||
|
||||
.. math::
|
||||
|
||||
E_i^\text{EAM} = F_\alpha \left(\sum_{j \neq i}\ \rho_\beta (r_{ij})\right) +
|
||||
\frac{1}{2} \sum_{j \neq i} \phi_{\alpha\beta} (r_{ij})
|
||||
|
||||
where :math:`F` is the embedding energy which is a function of the atomic
|
||||
electron density :math:`\rho`, :math:`\phi` is a pair potential interaction,
|
||||
and :math:`\alpha` and :math:`\beta` are the element types of atoms
|
||||
:math:`i` and :math:`j`. The multi-body nature of the EAM potential is a
|
||||
result of the embedding energy term. Both summations in the formula are over
|
||||
all neighbors :math:`j` of atom :math:`i` within the cutoff distance.
|
||||
EAM is documented in detail in :doc:`pair_style eam <pair_eam>`.
|
||||
|
||||
The potential energy :math:`E_i` of an atom :math:`i` of an adaptive-precision
|
||||
interatomic potential (APIP) according to :ref:`(Immel) <Immel2025_5>` is given by
|
||||
|
||||
.. math::
|
||||
|
||||
E_i^\text{APIP} = \lambda_i E_i^\text{(fast)} + (1-\lambda_i) E_i^\text{(precise)}\,,
|
||||
|
||||
whereas the switching parameter :math:`\lambda_i` is computed
|
||||
dynamically during a simulation by :doc:`fix lambda/apip <fix_lambda_apip>`
|
||||
or set prior to a simulation via :doc:`set <set>`.
|
||||
|
||||
The pair style *eam/fs/apip* computes the potential energy
|
||||
:math:`\lambda_i E_i^\text{EAM}` and the
|
||||
corresponding force and should be combined
|
||||
with a precise potential like
|
||||
:doc:`pair_style pace/precise/apip <pair_pace_apip>` that computes the
|
||||
potential energy :math:`(1-\lambda_i) E_i^\text{(precise)}` and the
|
||||
corresponding force via :doc:`pair_style hybrid/overlay <pair_hybrid>`.
|
||||
|
||||
Mixing, shift, table, tail correction, restart, rRESPA info
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
For atom type pairs I,J and I != J, where types I and J correspond to
|
||||
two different element types, mixing is performed by LAMMPS as
|
||||
described above with the individual styles. You never need to specify
|
||||
a pair_coeff command with I != J arguments for the eam/apip styles.
|
||||
|
||||
This pair style does not support the :doc:`pair_modify <pair_modify>`
|
||||
shift, table, and tail options.
|
||||
|
||||
The eam/apip pair styles do not write their information to :doc:`binary
|
||||
restart files <restart>`, since it is stored in tabulated potential
|
||||
files. Thus, you need to re-specify the pair_style and pair_coeff
|
||||
commands in an input script that reads a restart file.
|
||||
|
||||
The eam/apip pair styles can only be used via the *pair* keyword of the
|
||||
:doc:`run_style respa <run_style>` command. They do not support the
|
||||
*inner*, *middle*, *outer* keywords.
|
||||
|
||||
----------
|
||||
|
||||
Restrictions
|
||||
""""""""""""
|
||||
|
||||
This pair styles are part of the APIP package. It is only enabled if
|
||||
LAMMPS was built with that package. See the :doc:`Build package
|
||||
<Build_package>` page for more info.
|
||||
|
||||
Related commands
|
||||
""""""""""""""""
|
||||
|
||||
:doc:`pair_style eam <pair_eam>`,
|
||||
:doc:`pair_style hybrid/overlay <pair_hybrid>`,
|
||||
:doc:`fix lambda/apip <fix_lambda_apip>`,
|
||||
:doc:`fix lambda_thermostat/apip <fix_lambda_thermostat_apip>`,
|
||||
:doc:`pair_style lambda/zone/apip <pair_lambda_zone_apip>`,
|
||||
:doc:`pair_style lambda/input/apip <pair_lambda_input_apip>`,
|
||||
:doc:`pair_style pace/apip <pair_pace_apip>`,
|
||||
:doc:`fix atom_weight/apip <fix_atom_weight_apip>`
|
||||
|
||||
Default
|
||||
"""""""
|
||||
|
||||
none
|
||||
|
||||
----------
|
||||
|
||||
.. _Immel2025_5:
|
||||
|
||||
**(Immel)** Immel, Drautz and Sutmann, J Chem Phys, 162, 114119 (2025)
|
||||
|
||||
.. _Daw2:
|
||||
|
||||
**(Daw)** Daw, Baskes, Phys Rev Lett, 50, 1285 (1983).
|
||||
Daw, Baskes, Phys Rev B, 29, 6443 (1984).
|
||||
151
doc/src/pair_lambda_input_apip.rst
Normal file
151
doc/src/pair_lambda_input_apip.rst
Normal file
@ -0,0 +1,151 @@
|
||||
.. index:: pair_style lambda/input/apip
|
||||
.. index:: pair_style lambda/input/csp/apip
|
||||
|
||||
pair_style lambda/input/apip command
|
||||
====================================
|
||||
|
||||
Syntax
|
||||
""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
pair_style lambda/input/apip cutoff
|
||||
|
||||
* lambda/input/apip = style name of this pair style
|
||||
* cutoff = global cutoff (distance units)
|
||||
|
||||
pair_style lambda/input/csp/apip command
|
||||
========================================
|
||||
|
||||
Syntax
|
||||
""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
pair_style lambda/input/csp/apip lattice keyword args
|
||||
|
||||
* lambda/input/csp/apip = style name of this pair style
|
||||
* lattice = *fcc* or *bcc* or integer
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
*fcc* = use 12 nearest neighbors to calculate the CSP like in a perfect fcc lattice
|
||||
*bcc* = use 8 nearest neighbors to calculate the CSP like in a perfect bcc lattice
|
||||
integer = use N nearest neighbors to calculate the CSP
|
||||
|
||||
* zero or more keyword/args pairs may be appended
|
||||
* keyword = *cutoff* or *N_buffer*
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
*cutoff* args = cutoff
|
||||
cutoff = distance in which neighboring atoms are considered (> 0)
|
||||
*N_buffer* args = N_buffer
|
||||
N_buffer = number of additional neighbors, which are included in the j-j+N/2 calculation
|
||||
|
||||
Examples
|
||||
""""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
pair_style lambda/input/csp/apip fcc
|
||||
pair_style lambda/input/csp/apip fcc cutoff 5.0
|
||||
pair_style lambda/input/csp/apip bcc cutoff 5.0 N_buffer 2
|
||||
pair_style lambda/input/csp/apip 14
|
||||
|
||||
Description
|
||||
"""""""""""
|
||||
|
||||
This pair_styles calculates :math:`\lambda_i^\text{input}(t)`, which
|
||||
is required for :doc:`fix lambda/apip <fix_lambda_apip>`.
|
||||
|
||||
The pair_style lambda_input sets :math:`\lambda_i^\text{input}(t) = 0`.
|
||||
|
||||
The pair_style lambda_input/csp calculates
|
||||
:math:`\lambda_i^\text{input}(t) = \text{CSP}_i(t)`.
|
||||
The centro-symmetry parameter (CSP) :ref:`(Kelchner) <Kelchner_2>` is described
|
||||
in :doc:`compute centro/atom <compute_centro_atom>`.
|
||||
|
||||
The lattice argument is described in
|
||||
:doc:`compute centro/atom <compute_centro_atom>` and determines
|
||||
the number of neighboring atoms that are used to compute the CSP.
|
||||
The *N_buffer* argument allows to include more neighboring atoms in
|
||||
the calculation of the contributions from the pair j,j+N/2 to the CSP as
|
||||
discussed in :ref:`(Immel) <Immel2025_6>`.
|
||||
|
||||
The computation of :math:`\lambda_i^\text{input}(t)` is done by this
|
||||
pair_style instead of by :doc:`fix lambda/apip <fix_lambda_apip>`, as this computation
|
||||
takes time and this pair_style can be included in the load-balancing via
|
||||
:doc:`fix atom_weight/apip <fix_atom_weight_apip>`.
|
||||
|
||||
A code example for the calculation of the switching parameter for an adaptive-
|
||||
precision potential is given in the following:
|
||||
The adaptive-precision potential is created
|
||||
by combining :doc:`pair_style eam/fs/apip <pair_eam_apip>`
|
||||
and :doc:`pair_style pace/precise/apip <pair_pace_apip>`.
|
||||
The input, from which the switching parameter is calculated, is provided
|
||||
by this pair_style.
|
||||
The switching parameter is calculated by :doc:`fix lambda/apip <fix_lambda_apip>`,
|
||||
whereas the spatial
|
||||
transition zone of the switching parameter is calculated by
|
||||
:doc:`pair_style lambda/zone/apip <pair_lambda_zone_apip>`.
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
pair_style hybrid/overlay eam/fs/apip pace/precise/apip lambda/input/csp/apip fcc cutoff 5.0 lambda/zone/apip 12.0
|
||||
pair_coeff * * eam/fs/apip Cu.eam.fs Cu
|
||||
pair_coeff * * pace/precise/apip Cu_precise.yace Cu
|
||||
pair_coeff * * lambda/input/csp/apip
|
||||
pair_coeff * * lambda/zone/apip
|
||||
fix 2 all lambda/apip 3.0 3.5 time_averaged_zone 4.0 12.0 110 110 min_delta_lambda 0.01
|
||||
|
||||
----------
|
||||
|
||||
Mixing, shift, table, tail correction, restart, rRESPA info
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
The cutoff distance for this pair style can be mixed. The default mix
|
||||
value is *geometric*\ . See the "pair_modify" command for details.
|
||||
|
||||
This pair style does not support the :doc:`pair_modify <pair_modify>`
|
||||
shift, table, and tail options.
|
||||
|
||||
This pair style writes no information to :doc:`binary restart files <restart>`, so pair_style and pair_coeff commands need
|
||||
to be specified in an input script that reads a restart file.
|
||||
|
||||
This pair style does not support the use of the *inner*, *middle*,
|
||||
and *outer* keywords of the :doc:`run_style respa <run_style>` command.
|
||||
|
||||
----------
|
||||
|
||||
Restrictions
|
||||
""""""""""""
|
||||
This fix is part of the APIP package. It is only enabled if
|
||||
LAMMPS was built with that package. See the :doc:`Build package
|
||||
<Build_package>` page for more info.
|
||||
|
||||
Related commands
|
||||
""""""""""""""""
|
||||
|
||||
:doc:`compute centro/atom <compute_centro_atom>`,
|
||||
:doc:`fix lambda/apip <fix_lambda_apip>`,
|
||||
:doc:`fix lambda_thermostat/apip <fix_lambda_thermostat_apip>`,
|
||||
:doc:`pair_style lambda/zone/apip <pair_lambda_zone_apip>`,
|
||||
:doc:`pair_style eam/apip <pair_eam_apip>`,
|
||||
:doc:`pair_style pace/apip <pair_pace_apip>`,
|
||||
:doc:`fix atom_weight/apip <fix_atom_weight_apip>`
|
||||
|
||||
Default
|
||||
"""""""
|
||||
|
||||
N_buffer=0, cutoff=5.0
|
||||
|
||||
----------
|
||||
|
||||
.. _Kelchner_2:
|
||||
|
||||
**(Kelchner)** Kelchner, Plimpton, Hamilton, Phys Rev B, 58, 11085 (1998).
|
||||
|
||||
.. _Immel2025_6:
|
||||
|
||||
**(Immel)** Immel, Drautz and Sutmann, J Chem Phys, 162, 114119 (2025)
|
||||
106
doc/src/pair_lambda_zone_apip.rst
Normal file
106
doc/src/pair_lambda_zone_apip.rst
Normal file
@ -0,0 +1,106 @@
|
||||
.. index:: pair_style lambda/zone/apip
|
||||
|
||||
pair_style lambda/zone/apip command
|
||||
===================================
|
||||
|
||||
Syntax
|
||||
""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
pair_style lambda/zone/apip cutoff
|
||||
|
||||
* lambda/zone/apip = style name of this pair style
|
||||
* cutoff = global cutoff (distance units)
|
||||
|
||||
Examples
|
||||
""""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
pair_style lambda/zone/apip 12.0
|
||||
|
||||
Description
|
||||
"""""""""""
|
||||
|
||||
This pair_style calculates :math:`\lambda_{\text{min},i}`, which
|
||||
is required for :doc:`fix lambda/apip <fix_lambda_apip>`.
|
||||
The meaning of :math:`\lambda_{\text{min},i}` is documented in
|
||||
:doc:`fix lambda/apip <fix_lambda_apip>`, as this pair_style is for use with
|
||||
:doc:`fix lambda/apip <fix_lambda_apip>` only.
|
||||
|
||||
This pair_style requires only the global cutoff as argument.
|
||||
The remaining quantities, that are required to calculate
|
||||
:math:`\lambda_{\text{min},i}` are extracted from
|
||||
:doc:`fix lambda/apip <fix_lambda_apip>` and, thus,
|
||||
do not need to be passed to this pair_style as arguments.
|
||||
|
||||
.. warning::
|
||||
|
||||
The cutoff given as argument to this pair style is only relevant for the
|
||||
neighbor list creation. The radii, which define :math:`r_{\lambda,\text{hi}}` and :math:`r_{\lambda,\text{lo}}` are defined by :doc:`fix lambda/apip <fix_lambda_apip>`.
|
||||
|
||||
The computation of :math:`\lambda_{\text{min},i}` is done by this
|
||||
pair_style instead of by :doc:`fix lambda/apip <fix_lambda_apip>`, as this computation
|
||||
takes time and this pair_style can be included in the load-balancing via
|
||||
:doc:`fix atom_weight/apip <fix_atom_weight_apip>`.
|
||||
|
||||
A code example for the calculation of the switching parameter for an
|
||||
adaptive-precision interatomic potential (APIP) is given in the following:
|
||||
The adaptive-precision potential is created
|
||||
by combining :doc:`pair_style eam/fs/apip <pair_eam_apip>`
|
||||
and :doc:`pair_style pace/precise/apip <pair_pace_apip>`.
|
||||
The input, from which the switching parameter is calculated, is provided
|
||||
by :doc:`pair lambda/input/csp/apip <pair_lambda_input_apip>`.
|
||||
The switching parameter is calculated by :doc:`fix lambda/apip <fix_lambda_apip>`,
|
||||
whereas the spatial transition zone of the switching parameter is calculated
|
||||
by this pair style.
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
pair_style hybrid/overlay eam/fs/apip pace/precise/apip lambda/input/csp/apip fcc cutoff 5.0 lambda/zone/apip 12.0
|
||||
pair_coeff * * eam/fs/apip Cu.eam.fs Cu
|
||||
pair_coeff * * pace/precise/apip Cu_precise.yace Cu
|
||||
pair_coeff * * lambda/input/csp/apip
|
||||
pair_coeff * * lambda/zone/apip
|
||||
fix 2 all lambda/apip 3.0 3.5 time_averaged_zone 4.0 12.0 110 110 min_delta_lambda 0.01
|
||||
|
||||
----------
|
||||
|
||||
Mixing, shift, table, tail correction, restart, rRESPA info
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
The cutoff distance for this pair style can be mixed. The default mix
|
||||
value is *geometric*\ . See the "pair_modify" command for details.
|
||||
|
||||
This pair style does not support the :doc:`pair_modify <pair_modify>`
|
||||
shift, table, and tail options.
|
||||
|
||||
This pair style writes no information to :doc:`binary restart files <restart>`, so pair_style and pair_coeff commands need
|
||||
to be specified in an input script that reads a restart file.
|
||||
|
||||
This pair style does not support the use of the *inner*, *middle*,
|
||||
and *outer* keywords of the :doc:`run_style respa <run_style>` command.
|
||||
|
||||
----------
|
||||
|
||||
Restrictions
|
||||
""""""""""""
|
||||
This fix is part of the APIP package. It is only enabled if
|
||||
LAMMPS was built with that package. See the :doc:`Build package
|
||||
<Build_package>` page for more info.
|
||||
|
||||
Related commands
|
||||
""""""""""""""""
|
||||
|
||||
:doc:`fix lambda/apip <fix_lambda_apip>`,
|
||||
:doc:`fix atom_weight/apip <fix_atom_weight_apip>`
|
||||
:doc:`pair_style lambda/input/apip <pair_lambda_input_apip>`,
|
||||
:doc:`pair_style eam/apip <pair_eam_apip>`,
|
||||
:doc:`pair_style pace/apip <pair_pace_apip>`,
|
||||
:doc:`fix lambda_thermostat/apip <fix_lambda_thermostat_apip>`,
|
||||
|
||||
Default
|
||||
"""""""
|
||||
|
||||
none
|
||||
147
doc/src/pair_pace_apip.rst
Normal file
147
doc/src/pair_pace_apip.rst
Normal file
@ -0,0 +1,147 @@
|
||||
.. index:: pair_style pace/apip
|
||||
.. index:: pair_style pace/fast/apip
|
||||
.. index:: pair_style pace/precise/apip
|
||||
|
||||
pair_style pace/apip command
|
||||
============================
|
||||
|
||||
pair_style pace/fast/apip command
|
||||
=================================
|
||||
|
||||
pair_style pace/precise/apip command
|
||||
====================================
|
||||
|
||||
Constant precision variant: *pace*
|
||||
|
||||
Syntax
|
||||
""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
pair_style pace/apip ... keyword values ...
|
||||
pair_style pace/fast/apip ... keyword values ...
|
||||
pair_style pace/precise/apip ... keyword values ...
|
||||
|
||||
* one or more keyword/value pairs may be appended
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
keyword = keywords of :doc:`pair pace <pair_pace>`
|
||||
|
||||
Examples
|
||||
""""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
pair_style hybrid/overlay pace/fast/apip pace/precise/apip lambda/input/csp/apip fcc cutoff 5.0 lambda/zone/apip 12.0
|
||||
pair_coeff * * pace/fast/apip Cu_fast.yace Cu
|
||||
pair_coeff * * pace/precise/apip Cu_precise.yace Cu
|
||||
pair_coeff * * lambda/input/csp/apip
|
||||
pair_coeff * * lambda/zone/apip
|
||||
|
||||
pair_style hybrid/overlay eam/fs/apip pace/precise/apip lambda/input/csp/apip fcc cutoff 5.0 lambda/zone/apip 12.0
|
||||
pair_coeff * * eam/fs/apip Cu.eam.fs Cu
|
||||
pair_coeff * * pace/precise/apip Cu_precise.yace Cu
|
||||
pair_coeff * * lambda/input/csp/apip
|
||||
pair_coeff * * lambda/zone/apip
|
||||
|
||||
|
||||
Description
|
||||
"""""""""""
|
||||
|
||||
Pair style :doc:`pace <pair_pace>` computes interactions using the Atomic
|
||||
Cluster Expansion (ACE), which is a general expansion of the atomic energy in
|
||||
multi-body basis functions :ref:`(Drautz19) <Drautz2019_2>`. The *pace*
|
||||
pair style provides an efficient implementation that is described in
|
||||
this paper :ref:`(Lysogorskiy21) <Lysogorskiy20211_2>`.
|
||||
|
||||
The potential energy :math:`E_i` of an atom :math:`i` of an adaptive-precision
|
||||
interatomic potential (APIP) according to
|
||||
:ref:`(Immel25) <Immel2025_7>` is given by
|
||||
|
||||
.. math::
|
||||
|
||||
E_i^\text{APIP} = \lambda_i E_i^\text{(fast)} + (1-\lambda_i) E_i^\text{(precise)}\,,
|
||||
|
||||
whereas the switching parameter :math:`\lambda_i` is computed
|
||||
dynamically during a simulation by :doc:`fix lambda/apip <fix_lambda_apip>`
|
||||
or set prior to a simulation via :doc:`set <set>`.
|
||||
|
||||
The pair style *pace/precise/apip* computes the potential energy
|
||||
:math:`(1-\lambda_i) E_i^\text{(pace)}` and the
|
||||
corresponding force and should be combined
|
||||
with a fast potential that computes the potential energy
|
||||
:math:`\lambda_i E_i^\text{(fast)}` and the corresponding force
|
||||
via :doc:`pair_style hybrid/overlay <pair_hybrid>`.
|
||||
|
||||
The pair style *pace/fast/apip* computes the potential energy
|
||||
:math:`\lambda_i E_i^\text{(pace)}` and the
|
||||
corresponding force and should be combined
|
||||
with a precise potential that computes the potential energy
|
||||
:math:`(1-\lambda_i) E_i^\text{(precise)}` and the corresponding force
|
||||
via :doc:`pair_style hybrid/overlay <pair_hybrid>`.
|
||||
|
||||
The pair_styles *pace/fast/apip* and *pace/precise/apip*
|
||||
commands may be followed by the optional keywords of
|
||||
:doc:`pair_style pace <pair_pace>`, which are described
|
||||
:doc:`here <pair_pace>`.
|
||||
|
||||
Mixing, shift, table, tail correction, restart, rRESPA info
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
For atom type pairs I,J and I != J, where types I and J correspond to
|
||||
two different element types, mixing is performed by LAMMPS with
|
||||
user-specifiable parameters as described above. You never need to
|
||||
specify a pair_coeff command with I != J arguments for this style.
|
||||
|
||||
This pair styles does not support the :doc:`pair_modify <pair_modify>`
|
||||
shift, table, and tail options.
|
||||
|
||||
This pair styles does not write its information to :doc:`binary restart
|
||||
files <restart>`, since it is stored in potential files. Thus, you need
|
||||
to re-specify the pair_style and pair_coeff commands in an input script
|
||||
that reads a restart file.
|
||||
|
||||
This pair styles can only be used via the *pair* keyword of the
|
||||
:doc:`run_style respa <run_style>` command. It does not support the
|
||||
*inner*, *middle*, *outer* keywords.
|
||||
|
||||
----------
|
||||
|
||||
Restrictions
|
||||
""""""""""""
|
||||
|
||||
This pair styles are part of the APIP package. It is only enabled if
|
||||
LAMMPS was built with that package. See the :doc:`Build package
|
||||
<Build_package>` page for more info.
|
||||
|
||||
Related commands
|
||||
""""""""""""""""
|
||||
|
||||
:doc:`pair_style pace <pair_pace>`,
|
||||
:doc:`pair_style hybrid/overlay <pair_hybrid>`,
|
||||
:doc:`fix lambda/apip <fix_lambda_apip>`,
|
||||
:doc:`fix lambda_thermostat/apip <fix_lambda_thermostat_apip>`,
|
||||
:doc:`pair_style lambda/zone/apip <pair_lambda_zone_apip>`,
|
||||
:doc:`pair_style lambda/input/apip <pair_lambda_input_apip>`,
|
||||
:doc:`pair_style eam/apip <pair_eam_apip>`,
|
||||
:doc:`fix atom_weight/apip <fix_atom_weight_apip>`
|
||||
|
||||
Default
|
||||
"""""""
|
||||
|
||||
See :doc:`pair_style pace <pair_pace>`.
|
||||
|
||||
----------
|
||||
|
||||
.. _Drautz2019_2:
|
||||
|
||||
**(Drautz19)** Drautz, Phys Rev B, 99, 014104 (2019).
|
||||
|
||||
.. _Lysogorskiy20211_2:
|
||||
|
||||
**(Lysogorskiy21)** Lysogorskiy, van der Oord, Bochkarev, Menon, Rinaldi, Hammerschmidt, Mrovec, Thompson, Csanyi, Ortner, Drautz, npj Comp Mat, 7, 97 (2021).
|
||||
|
||||
.. _Immel2025_7:
|
||||
|
||||
**(Immel25)** Immel, Drautz and Sutmann, J Chem Phys, 162, 114119 (2025)
|
||||
@ -188,7 +188,9 @@ accelerated styles exist.
|
||||
* :doc:`eam/cd <pair_eam>` - concentration-dependent EAM
|
||||
* :doc:`eam/cd/old <pair_eam>` - older two-site model for concentration-dependent EAM
|
||||
* :doc:`eam/fs <pair_eam>` - Finnis-Sinclair EAM
|
||||
* :doc:`eam/fs/apip <pair_eam_apip>` - :doc:`adaptive precision <Howto_apip>` version of FS EAM, used as fast potential
|
||||
* :doc:`eam/he <pair_eam>` - Finnis-Sinclair EAM modified for Helium in metals
|
||||
* :doc:`eam/apip <pair_eam_apip>` - :doc:`adaptive-precision <Howto_apip>` version of EAM, used as fast potential
|
||||
* :doc:`edip <pair_edip>` - three-body EDIP potential
|
||||
* :doc:`edip/multi <pair_edip>` - multi-element EDIP potential
|
||||
* :doc:`edpd <pair_mesodpd>` - eDPD particle interactions
|
||||
@ -217,6 +219,9 @@ accelerated styles exist.
|
||||
* :doc:`kim <pair_kim>` - interface to potentials provided by KIM project
|
||||
* :doc:`kolmogorov/crespi/full <pair_kolmogorov_crespi_full>` - Kolmogorov-Crespi (KC) potential with no simplifications
|
||||
* :doc:`kolmogorov/crespi/z <pair_kolmogorov_crespi_z>` - Kolmogorov-Crespi (KC) potential with normals along z-axis
|
||||
* :doc:`lambda/input/apip <pair_lambda_input_apip>` - constant as input for the precision calculation of an :doc:`adaptive-precision interatomic potential (APIP) <Howto_apip>`
|
||||
* :doc:`lambda/input/csp/apip <pair_lambda_input_apip>` - CSP as input for the precision calculation of an :doc:`adaptive-precision interatomic potential (APIP) <Howto_apip>`
|
||||
* :doc:`lambda/zone/apip <pair_lambda_zone_apip>` - transition zone of an :doc:`adaptive-precision interatomic potential <Howto_apip>`
|
||||
* :doc:`lcbop <pair_lcbop>` - long-range bond-order potential (LCBOP)
|
||||
* :doc:`lebedeva/z <pair_lebedeva_z>` - Lebedeva interlayer potential for graphene with normals along z-axis
|
||||
* :doc:`lennard/mdf <pair_mdf>` - LJ potential in A/B form with a taper function
|
||||
@ -330,6 +335,9 @@ accelerated styles exist.
|
||||
* :doc:`oxrna2/xstk <pair_oxrna2>` -
|
||||
* :doc:`pace <pair_pace>` - Atomic Cluster Expansion (ACE) machine-learning potential
|
||||
* :doc:`pace/extrapolation <pair_pace>` - Atomic Cluster Expansion (ACE) machine-learning potential with extrapolation grades
|
||||
* :doc:`pace/apip <pair_pace_apip>` - :doc:`adaptive-precision <Howto_apip>` version of ACE, used as precise potential
|
||||
* :doc:`pace/fast/apip <pair_pace_apip>` - :doc:`adaptive-precision <Howto_apip>` version of ACE, used as fast potential
|
||||
* :doc:`pace/precise/apip <pair_pace_apip>` - :doc:`adaptive-precision <Howto_apip>` version of ACE, used as precise potential
|
||||
* :doc:`pedone <pair_pedone>` - Pedone (PMMCS) potential (non-Coulomb part)
|
||||
* :doc:`pod <pair_pod>` - Proper orthogonal decomposition (POD) machine-learning potential
|
||||
* :doc:`peri/eps <pair_peri>` - Peridynamic EPS potential
|
||||
|
||||
@ -16,12 +16,13 @@ Syntax
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
field = *x* or *y* or *z* or *vx* or *vy* or *vz* or *q* or *ix* or *iy* or *iz* or *fx* or *fy* or *fz*
|
||||
field = *x* or *y* or *z* or *vx* or *vy* or *vz* or *q* or *ix* or *iy* or *iz* or *fx* or *fy* or *fz* or *apip_lambda*
|
||||
*x*,\ *y*,\ *z* = atom coordinates
|
||||
*vx*,\ *vy*,\ *vz* = velocity components
|
||||
*q* = charge
|
||||
*ix*,\ *iy*,\ *iz* = image flags in each dimension
|
||||
*fx*,\ *fy*,\ *fz* = force components
|
||||
*apip_lambda* = switching parameter of an :doc:`adaptive-precision interatomic potential <Howto_apip>`
|
||||
|
||||
* zero or more keyword/value pairs may be appended
|
||||
* keyword = *nfile* or *box* or *timestep* or *replace* or *purge* or *trim* or *add* or *label* or *scaled* or *wrapped* or *format*
|
||||
|
||||
@ -23,8 +23,8 @@ Syntax
|
||||
|
||||
* one or more keyword/value pairs may be appended
|
||||
|
||||
* keyword = *angle* or *angmom* or *bond* or *cc* or *charge* or
|
||||
*density* or *density/disc* or *diameter* or *dihedral* or *dipole*
|
||||
* keyword = *angle* or *angmom* or *apip/lambda* or *bond* or *cc* or *charge*
|
||||
or *density* or *density/disc* or *diameter* or *dihedral* or *dipole*
|
||||
or *dipole/random* or *dpd/theta* or *edpd/cv* or *edpd/temp* or
|
||||
*epsilon* or *image* or *improper* or *length* or *mass* or *mol* or
|
||||
*omega* or *quat* or *quat/random* or *radius/electron* or *shape* or
|
||||
@ -41,6 +41,10 @@ Syntax
|
||||
*angmom* values = Lx Ly Lz
|
||||
Lx,Ly,Lz = components of angular momentum vector (distance-mass-velocity units)
|
||||
any of Lx,Ly,Lz can be an atom-style variable (see below)
|
||||
*apip/lambda* value = fast or precise or float
|
||||
fast = switching parameter of fast potential (1)
|
||||
precise = switching parameter of fast potential (0)
|
||||
float = constant float or atom-style variable (between 0 and 1)
|
||||
*bond* value = numeric bond type or bond type label, for all bonds between selected atoms
|
||||
*cc* values = index cc
|
||||
index = index of a chemical species (1 to Nspecies)
|
||||
@ -632,6 +636,13 @@ atoms.
|
||||
|
||||
Keywords *x*, *y*, *z* set the coordinates of all selected atoms.
|
||||
|
||||
Keyword *apip/lambda* sets the switching parameter of an
|
||||
adaptive-precision interatomic potential (:doc:`APIP <Howto_apip>`).
|
||||
The precise potential is used for an atom when its switching parameter
|
||||
:math:`\lambda` is 0. The fast potential is used for an atom when its
|
||||
switching parameter :math:`\lambda` is 1. Both potentials are partially
|
||||
used for :math:`\lambda\in(0,1)`.
|
||||
|
||||
Keywords *i_name*, *d_name*, *i2_name*, *d2_name* refer to custom
|
||||
per-atom integer and floating-point vectors or arrays that have been
|
||||
added via the :doc:`fix property/atom <fix_property_atom>` command.
|
||||
|
||||
@ -135,6 +135,8 @@ anton
|
||||
Antonelli
|
||||
anysize
|
||||
api
|
||||
apip
|
||||
APIP
|
||||
apolar
|
||||
Apoorva
|
||||
Appl
|
||||
@ -654,6 +656,7 @@ CSiC
|
||||
csld
|
||||
cslib
|
||||
CSlib
|
||||
csp
|
||||
cstdio
|
||||
cstdlib
|
||||
cstring
|
||||
@ -1384,6 +1387,7 @@ gmres
|
||||
gname
|
||||
gneb
|
||||
GNEB
|
||||
Godehard
|
||||
Goerigk
|
||||
Goga
|
||||
Goldfarb
|
||||
@ -1619,6 +1623,7 @@ Imageint
|
||||
Imagemagick
|
||||
imagename
|
||||
imd
|
||||
Immel
|
||||
Impey
|
||||
impl
|
||||
improperlist
|
||||
@ -3847,6 +3852,7 @@ Thiaville
|
||||
Thibaudeau
|
||||
Thijsse
|
||||
Thirumalai
|
||||
thr
|
||||
Threadripper
|
||||
threebody
|
||||
thrid
|
||||
|
||||
34
examples/PACKAGES/apip/Cu-1.yace
Normal file
34
examples/PACKAGES/apip/Cu-1.yace
Normal file
@ -0,0 +1,34 @@
|
||||
NOTE: This is a simple potential for the example. Production usage without testing is not recommended. Provided by Yury Lysogorskiy (ICAMS, RUB, Germany).
|
||||
elements: [Cu]
|
||||
E0: [0]
|
||||
deltaSplineBins: 0.001
|
||||
embeddings:
|
||||
0: {ndensity: 2, FS_parameters: [1, 1, 1, 0.5], npoti: FinnisSinclairShiftedScaled, rho_core_cutoff: 100000, drho_core_cutoff: 250}
|
||||
bonds:
|
||||
[0, 0]: {nradmax: 2, lmax: 2, nradbasemax: 15, radbasename: ChebPow, radparameters: [2], radcoefficients: [[[0.99440439385969503, -0.085048653403583918, -0.23248632054717755, -0.22732701549371864, 0.026354948476648921, 0.21853318667456997, 0.05745747498169812, -0.19717925712228765, -0.11474256770370879, 0.12738668745839368, 0.053777769435472259, -0.11094768379576209, 0.072620812391582482, -0.058715761632824881, 0.030359986427775303], [0.96259704765772924, -0.10129488003029259, -0.10345557604916655, -0.020393848425879282, 0.076671442494272601, 0.10318554794001746, 0.0555341702761026, 0.00083194423680727696, -0.018184436957498409, -0.021866885826555403, -0.020179969116479776, 0.021880011516616484, 0.053112509345249602, -0.083707026393616657, 0.020611714544479017], [1.001530579978529, -0.030080648426358471, -0.13318582671063051, -0.24371635685809706, -0.22760541127468878, -0.041144767051648642, 0.18080289144697201, 0.24543156067198274, 0.11014559411659355, -0.069512010077804498, -0.1172049950938457, -0.027509386703874331, 0.056985864219913585, 0.037536629112081353, -0.044222474537374087]], [[0.25716120576634355, 1.7485527550537943, 0.91889737965719875, 0.50902244208852199, -0.15895537149482841, -0.48109723575282892, -0.17843605933015286, 0.39450608859531944, 0.59293909285591195, 0.18268386912819001, -0.34706543720907351, -0.3210061634328315, 0.21678650779400246, 0.39500148786376449, -0.31820913370341625], [0.0079213202761679105, 1.0212489038630681, 0.011530454475879359, -0.049445152058907642, -0.15268524878755677, -0.2319378608755131, -0.20612580998548105, -0.067027395211212315, 0.08241096034972574, 0.11288597065081186, 0.01355948960244063, -0.074722461388416803, -0.022724332047049267, 0.088871664887057056, 0.031667459613258314], [-0.0069872405356639312, 0.9939655327342134, 0.035044055182587928, 0.099765277857093104, 0.11687607289674087, 0.030241996404391416, -0.12367698594314165, -0.22480900218170197, -0.17727517861619441, -0.015144941558075584, 0.11375495728241894, 0.090680932947050971, -0.041190210394591399, -0.10085768296286811, 0.055789864104988186]]], prehc: 0, lambdahc: 0, rcut: 3.8999999999999999, dcut: 0.01, rcut_in: 0, dcut_in: 0, inner_cutoff_type: density}
|
||||
functions:
|
||||
0:
|
||||
- {mu0: 0, rank: 1, ndensity: 2, num_ms_combs: 1, mus: [0], ns: [1], ls: [0], ms_combs: [0], ctildes: [0.26072556900842869, -0.03073189825062177]}
|
||||
- {mu0: 0, rank: 1, ndensity: 2, num_ms_combs: 1, mus: [0], ns: [2], ls: [0], ms_combs: [0], ctildes: [0.64429175483702295, -0.1630534353246999]}
|
||||
- {mu0: 0, rank: 1, ndensity: 2, num_ms_combs: 1, mus: [0], ns: [3], ls: [0], ms_combs: [0], ctildes: [0.51856313423563594, -0.4259316875879266]}
|
||||
- {mu0: 0, rank: 1, ndensity: 2, num_ms_combs: 1, mus: [0], ns: [4], ls: [0], ms_combs: [0], ctildes: [-0.078113533662468398, -0.70352070540668643]}
|
||||
- {mu0: 0, rank: 1, ndensity: 2, num_ms_combs: 1, mus: [0], ns: [5], ls: [0], ms_combs: [0], ctildes: [-0.45633111544093646, -0.7859368117550467]}
|
||||
- {mu0: 0, rank: 1, ndensity: 2, num_ms_combs: 1, mus: [0], ns: [6], ls: [0], ms_combs: [0], ctildes: [-0.19608401600520556, -0.59151667874441172]}
|
||||
- {mu0: 0, rank: 1, ndensity: 2, num_ms_combs: 1, mus: [0], ns: [7], ls: [0], ms_combs: [0], ctildes: [0.30580228338697285, -0.29248216980800118]}
|
||||
- {mu0: 0, rank: 1, ndensity: 2, num_ms_combs: 1, mus: [0], ns: [8], ls: [0], ms_combs: [0], ctildes: [0.40167461008815436, -0.15647925731818518]}
|
||||
- {mu0: 0, rank: 1, ndensity: 2, num_ms_combs: 1, mus: [0], ns: [9], ls: [0], ms_combs: [0], ctildes: [0.053519057558225343, -0.25900906688118652]}
|
||||
- {mu0: 0, rank: 1, ndensity: 2, num_ms_combs: 1, mus: [0], ns: [10], ls: [0], ms_combs: [0], ctildes: [-0.20446546815457517, -0.40019216010057629]}
|
||||
- {mu0: 0, rank: 1, ndensity: 2, num_ms_combs: 1, mus: [0], ns: [11], ls: [0], ms_combs: [0], ctildes: [-0.070020661105060208, -0.33441939205411986]}
|
||||
- {mu0: 0, rank: 1, ndensity: 2, num_ms_combs: 1, mus: [0], ns: [12], ls: [0], ms_combs: [0], ctildes: [0.15734064575001952, -0.055233119903794807]}
|
||||
- {mu0: 0, rank: 1, ndensity: 2, num_ms_combs: 1, mus: [0], ns: [13], ls: [0], ms_combs: [0], ctildes: [0.10021406559793103, 0.18641744536767416]}
|
||||
- {mu0: 0, rank: 1, ndensity: 2, num_ms_combs: 1, mus: [0], ns: [14], ls: [0], ms_combs: [0], ctildes: [-0.14066730990975543, 0.14711096149210373]}
|
||||
- {mu0: 0, rank: 1, ndensity: 2, num_ms_combs: 1, mus: [0], ns: [15], ls: [0], ms_combs: [0], ctildes: [0.031100766650549283, -0.13720067925313634]}
|
||||
- {mu0: 0, rank: 2, ndensity: 2, num_ms_combs: 1, mus: [0, 0], ns: [1, 1], ls: [0, 0], ms_combs: [0, 0], ctildes: [1.0984212008195524, 0.49756623164565855]}
|
||||
- {mu0: 0, rank: 2, ndensity: 2, num_ms_combs: 2, mus: [0, 0], ns: [1, 1], ls: [1, 1], ms_combs: [0, 0, 1, -1], ctildes: [0.2591109116320176, 0.21348077494861176, -0.5182218232640351, -0.4269615498972234]}
|
||||
- {mu0: 0, rank: 2, ndensity: 2, num_ms_combs: 3, mus: [0, 0], ns: [1, 1], ls: [2, 2], ms_combs: [0, 0, 1, -1, 2, -2], ctildes: [0.015905361441871636, 0.023783303055646809, -0.031810722883743273, -0.047566606111293624, 0.031810722883743286, 0.047566606111293638]}
|
||||
- {mu0: 0, rank: 2, ndensity: 2, num_ms_combs: 1, mus: [0, 0], ns: [2, 1], ls: [0, 0], ms_combs: [0, 0], ctildes: [0.63958612617724186, 1.6623415103929948]}
|
||||
- {mu0: 0, rank: 2, ndensity: 2, num_ms_combs: 2, mus: [0, 0], ns: [2, 1], ls: [1, 1], ms_combs: [0, 0, 1, -1], ctildes: [0.14199022782503917, 0.0069900458821809735, -0.28398045565007829, -0.013980091764361944]}
|
||||
- {mu0: 0, rank: 2, ndensity: 2, num_ms_combs: 3, mus: [0, 0], ns: [2, 1], ls: [2, 2], ms_combs: [0, 0, 1, -1, 2, -2], ctildes: [0.028732470496968317, -0.037173039560267927, -0.05746494099393664, 0.074346079120535868, 0.057464940993936654, -0.074346079120535882]}
|
||||
- {mu0: 0, rank: 2, ndensity: 2, num_ms_combs: 1, mus: [0, 0], ns: [2, 2], ls: [0, 0], ms_combs: [0, 0], ctildes: [0.056442895466964321, 0.0054387873274233034]}
|
||||
- {mu0: 0, rank: 2, ndensity: 2, num_ms_combs: 2, mus: [0, 0], ns: [2, 2], ls: [1, 1], ms_combs: [0, 0, 1, -1], ctildes: [0.025326283180140272, -0.19511149476156769, -0.050652566360280531, 0.39022298952313533]}
|
||||
- {mu0: 0, rank: 2, ndensity: 2, num_ms_combs: 3, mus: [0, 0], ns: [2, 2], ls: [2, 2], ms_combs: [0, 0, 1, -1, 2, -2], ctildes: [0.012754475331985416, -0.058934602152610385, -0.025508950663970836, 0.11786920430522078, 0.025508950663970843, -0.11786920430522081]}
|
||||
6006
examples/PACKAGES/apip/Cu_300K_Immel_2023.eam.fs
Normal file
6006
examples/PACKAGES/apip/Cu_300K_Immel_2023.eam.fs
Normal file
File diff suppressed because it is too large
Load Diff
11
examples/PACKAGES/apip/README
Normal file
11
examples/PACKAGES/apip/README
Normal file
@ -0,0 +1,11 @@
|
||||
The APIP package is based on the paper:
|
||||
|
||||
David Immel, Ralf Drautz, Godehard Sutmann; Adaptive-precision potentials for large-scale atomistic simulations. J. Chem. Phys. 14 March 2025; 162 (11): 114119. https://doi.org/10.1063/5.0245877
|
||||
|
||||
The pair_style pace/apip requires the installation of lib/pace of the ML-PACE package.
|
||||
The installation of lib/pace is described in src/ML-PACE/README .
|
||||
|
||||
Examples of how to use an adaptive-precision potential are provided in examples/PACKAGES/apip .
|
||||
|
||||
in.vacancy contains a small example that can be used to visualize the transition region and get a visual impression of the selected parameters.
|
||||
in.surface.balance in a more realistic example, in which a surface is simulated and the benefit of fix apip_atom_weight and fix balance for adaptive-precision interatomic potentials is demonstrated.
|
||||
80418
examples/PACKAGES/apip/data.surface.balance
Normal file
80418
examples/PACKAGES/apip/data.surface.balance
Normal file
File diff suppressed because it is too large
Load Diff
4112
examples/PACKAGES/apip/data.vacancy
Normal file
4112
examples/PACKAGES/apip/data.vacancy
Normal file
File diff suppressed because it is too large
Load Diff
80
examples/PACKAGES/apip/data.validate
Normal file
80
examples/PACKAGES/apip/data.validate
Normal file
@ -0,0 +1,80 @@
|
||||
LAMMPS data file via write_data, version 2 Apr 2025, timestep = 0, units = metal
|
||||
|
||||
31 atoms
|
||||
1 atom types
|
||||
|
||||
0 7.23 xlo xhi
|
||||
0 7.23 ylo yhi
|
||||
0 7.23 zlo zhi
|
||||
|
||||
Masses
|
||||
|
||||
1 63.546
|
||||
|
||||
Atoms # apip
|
||||
|
||||
1 1 3.255649577011424 2.1469408310018205 1.596546647595962 0 0 0
|
||||
2 1 5.312133977687514 0.2962629940541289 1.7986410677440656 0 0 0
|
||||
3 1 0.3570136530341179 1.9589665444185802 1.8227120430766197 0 0 0
|
||||
4 1 1.538770434276094 1.8506888783106994 3.5984777679252336 0 0 0
|
||||
5 1 5.414379916412933 1.9802551521608864 3.5428423680157133 0 0 0
|
||||
6 1 3.3396207511420926 0.34696444514694835 3.3284295847601864 0 0 0
|
||||
7 1 0.04692381499727436 3.470558659189874 0.20838500420697273 0 0 0
|
||||
8 1 3.5507628116865004 3.419576015011443 0.09808429731968064 0 0 0
|
||||
9 1 3.4359438466091845 3.3442299605630015 3.344947182361245 0 0 0
|
||||
10 1 3.262172986855113 1.8898900738753799 5.6074716235080135 0 0 0
|
||||
11 1 5.616180533384058 0.24272458584617107 5.728614316596936 0 0 0
|
||||
12 1 0.3320737270957668 2.133631298552561 5.648234772896504 0 0 0
|
||||
13 1 7.193910458696732 0.040079315967661934 7.007063468494249 -1 0 -1
|
||||
14 1 1.9428459507398523 2.008894084694746 6.974381464595852 0 0 -1
|
||||
15 1 5.17195441765988 1.6398976096007498 7.144624559798802 0 0 -1
|
||||
16 1 3.828212487222493 0.27427274843853566 7.084083006467942 0 0 -1
|
||||
17 1 0.3576896118392189 3.5593061817506357 3.8539966829342287 0 0 0
|
||||
18 1 5.549388330643712 3.3771731288636446 5.733276811271104 0 0 0
|
||||
19 1 1.474782367736 3.311754538948766 5.203036111913638 0 0 0
|
||||
20 1 3.353885621487343 5.483140337766679 1.559656844576661 0 0 0
|
||||
21 1 1.4600851633288363 5.3693400677513985 0.16901869775192754 0 0 0
|
||||
22 1 1.865319826459661 3.680823307523189 1.909829542233995 0 0 0
|
||||
23 1 6.919428313555163 5.704165921616911 1.5626446154218376 -1 0 0
|
||||
24 1 5.286111954406888 3.9741177165543746 1.894962129368895 0 0 0
|
||||
25 1 5.661441532175263 5.770831269632481 0.2726487131030991 0 0 0
|
||||
26 1 5.749451385769738 5.694440631979816 3.315201684766776 0 0 0
|
||||
27 1 2.1656354707333425 5.630356615286487 3.525133119978771 0 0 0
|
||||
28 1 3.4802512558478638 5.136357035041954 5.613687950103865 0 0 0
|
||||
29 1 6.9476459434582605 5.669871702976 5.748711917622347 -1 0 0
|
||||
30 1 0.3145319513743893 6.992506749359428 3.748936483911442 0 -1 0
|
||||
31 1 2.0688280140984934 7.144932953378388 5.071647430554334 0 -1 0
|
||||
|
||||
Velocities
|
||||
|
||||
1 0 0 0
|
||||
2 0 0 0
|
||||
3 0 0 0
|
||||
4 0 0 0
|
||||
5 0 0 0
|
||||
6 0 0 0
|
||||
7 0 0 0
|
||||
8 0 0 0
|
||||
9 0 0 0
|
||||
10 0 0 0
|
||||
11 0 0 0
|
||||
12 0 0 0
|
||||
13 0 0 0
|
||||
14 0 0 0
|
||||
15 0 0 0
|
||||
16 0 0 0
|
||||
17 0 0 0
|
||||
18 0 0 0
|
||||
19 0 0 0
|
||||
20 0 0 0
|
||||
21 0 0 0
|
||||
22 0 0 0
|
||||
23 0 0 0
|
||||
24 0 0 0
|
||||
25 0 0 0
|
||||
26 0 0 0
|
||||
27 0 0 0
|
||||
28 0 0 0
|
||||
29 0 0 0
|
||||
30 0 0 0
|
||||
31 0 0 0
|
||||
75
examples/PACKAGES/apip/in.surface.balance
Normal file
75
examples/PACKAGES/apip/in.surface.balance
Normal file
@ -0,0 +1,75 @@
|
||||
##################################################
|
||||
# parameters of the adaptive-precision potential #
|
||||
##################################################
|
||||
# We couple an EAM potential with an ACE potential.
|
||||
variable eamfs_file string "Cu_300K_Immel_2023.eam.fs"
|
||||
variable ace_file1 string "Cu-1.yace"
|
||||
variable ace_file2 string "../../../potentials/Cu-PBE-core-rep.ace"
|
||||
# The csp is used as detection mechanism for atoms of interest.
|
||||
variable csp_lattice string "fcc"
|
||||
variable csp_cutoff equal 6.0
|
||||
# The range [r_sw_lo, r_sw_hi] determines where the switching parameter changes from 0 to 1.
|
||||
variable r_sw_lo equal 4.0
|
||||
variable r_sw_hi equal 12.0
|
||||
# Thresholds between which the switching parameter changes from 1 to 0 based on the csp.
|
||||
variable lambda_input_thr_lo equal 7.5
|
||||
variable lambda_input_thr_hi equal 8.0
|
||||
# Number of averaged steps.
|
||||
variable lambda_input_histlen equal 110
|
||||
variable lambda_histlen equal 110
|
||||
# Minimum required change of the switching parameter
|
||||
variable min_delta_lambda equal 1/${lambda_histlen}
|
||||
# number of atoms rescaled by the lambda_thermostat
|
||||
variable N_rescaling equal 600
|
||||
|
||||
|
||||
|
||||
# basic stuff
|
||||
units metal
|
||||
dimension 3
|
||||
boundary p p s
|
||||
atom_style apip # own atom style required for APIP
|
||||
timestep 0.001
|
||||
|
||||
read_data data.surface.balance
|
||||
|
||||
fix nve all nve
|
||||
comm_style tiled
|
||||
|
||||
|
||||
# Only the upper surface should be treated precisely.
|
||||
# Thus, we create group, for whose atoms the csp is ignored, as the corresponding
|
||||
# argument of fix lambda is used.
|
||||
region bottom block INF INF INF INF INF 0 units box
|
||||
group group_ignore_csp region bottom
|
||||
|
||||
|
||||
# use adaptive-precision eam-ace potential with lambda_thermostat
|
||||
pair_style hybrid/overlay eam/fs/apip pace/apip lambda/input/csp/apip ${csp_lattice} cutoff ${csp_cutoff} lambda/zone/apip ${r_sw_hi}
|
||||
pair_coeff * * eam/fs/apip ${eamfs_file} Cu
|
||||
pair_coeff * * pace/apip ${ace_file2} Cu
|
||||
pair_coeff * * lambda/input/csp/apip
|
||||
pair_coeff * * lambda/zone/apip
|
||||
fix lambda all lambda/apip ${lambda_input_thr_lo} ${lambda_input_thr_hi} time_averaged_zone ${r_sw_lo} ${r_sw_hi} ${lambda_input_histlen} ${lambda_histlen} min_delta_lambda ${min_delta_lambda} group_ignore_lambda_input group_ignore_csp
|
||||
fix lambda_thermostat all lambda_thermostat/apip N_rescaling ${N_rescaling}
|
||||
fix weight_atom all atom_weight/apip 10 eam ace lambda/input lambda/zone all
|
||||
|
||||
# store weight in variable
|
||||
fix property_atom all property/atom d_usedweight
|
||||
variable myweight atom f_weight_atom
|
||||
#compute lambda all property/atom apip_lambda
|
||||
#compute lambda_input all property/atom apip_lambda_input
|
||||
#dump 1 all custom 10 dump/surface_ap_balance.dump.* id type x y z c_lambda c_lambda_input f_weight_atom proc d_usedweight
|
||||
|
||||
|
||||
## apply load balancing
|
||||
## no load-balancing
|
||||
#fix balance all balance 10 0.9 report weight time 1.0 weight store usedweight
|
||||
## load balancing with times per atom per processor
|
||||
#fix balance all balance 10 0.9 rcb weight time 1.0 weight store usedweight
|
||||
## load balancing with an approximated load per atom by fix apip_atom_weight
|
||||
fix balance all balance 10 0.9 rcb weight var myweight weight store usedweight
|
||||
|
||||
thermo_style custom step f_balance spcpu f_weight_atom[*]
|
||||
thermo 10
|
||||
run 100
|
||||
54
examples/PACKAGES/apip/in.vacancy.const.lambda
Normal file
54
examples/PACKAGES/apip/in.vacancy.const.lambda
Normal file
@ -0,0 +1,54 @@
|
||||
##################################################
|
||||
# parameters of the adaptive-precision potential #
|
||||
##################################################
|
||||
# We couple an EAM potential with an ACE potential.
|
||||
variable eamfs_file string "Cu_300K_Immel_2023.eam.fs"
|
||||
variable ace_file1 string "Cu-1.yace"
|
||||
variable ace_file2 string "../../../potentials/Cu-PBE-core-rep.ace"
|
||||
|
||||
|
||||
## basic stuff
|
||||
units metal
|
||||
atom_style apip # own atom style required for APIP
|
||||
timestep 0.001
|
||||
|
||||
# copper at room temperature with a vacancy
|
||||
read_data data.vacancy
|
||||
|
||||
|
||||
# set lambda
|
||||
group vacancy id 145 147 148 149 150 994 997 995 1024 1026 1028 1922
|
||||
group transition id 77 79 81 84 88 151 152 153 154 155 158 1089 188 189 192 1033 1039 1964 1022 1021 999 998 996 948 950 952 992 993 139 1025 1027 1029 1034 1035 1038 1088 1920 1921 1923 1924 1925 1930
|
||||
group bulk subtract all vacancy transition
|
||||
set group vacancy apip/lambda precise
|
||||
set group transition apip/lambda 0.5
|
||||
set group bulk apip/lambda fast
|
||||
|
||||
|
||||
fix nve all nve
|
||||
|
||||
|
||||
# Use adaptive-precision eam-ace potential with constant lambda.
|
||||
# Calculate atomic weight that could be used for load balancing.
|
||||
pair_style hybrid/overlay eam/fs/apip pace/apip
|
||||
pair_coeff * * eam/fs/apip ${eamfs_file} Cu
|
||||
pair_coeff * * pace/apip ${ace_file2} Cu
|
||||
fix weight_atom all atom_weight/apip 50 eam ace 0.5 0 all
|
||||
|
||||
|
||||
# get statistics about lambda
|
||||
compute lambda all property/atom apip_lambda
|
||||
compute lambda_input all property/atom apip_lambda_input
|
||||
variable flag_simple atom c_lambda==1
|
||||
variable flag_switch atom c_lambda<1&&c_lambda>0
|
||||
variable flag_complex atom c_lambda==0
|
||||
compute lambda_types all reduce sum v_flag_simple v_flag_switch v_flag_complex
|
||||
|
||||
|
||||
thermo_style custom step etotal c_lambda_types[*]
|
||||
thermo 1
|
||||
|
||||
run 100
|
||||
|
||||
# dump atoms
|
||||
#write_dump all custom dump.vacancy.* id type x y z fx fy fz c_lambda c_lambda_input f_weight_atom
|
||||
101
examples/PACKAGES/apip/in.vacancy.dynamic.lambda
Normal file
101
examples/PACKAGES/apip/in.vacancy.dynamic.lambda
Normal file
@ -0,0 +1,101 @@
|
||||
##################################################
|
||||
# parameters of the adaptive-precision potential #
|
||||
##################################################
|
||||
# We couple an EAM potential with an ACE potential.
|
||||
variable eamfs_file string "Cu_300K_Immel_2023.eam.fs"
|
||||
variable ace_file1 string "Cu-1.yace"
|
||||
variable ace_file2 string "../../../potentials/Cu-PBE-core-rep.ace"
|
||||
# The csp is used as detection mechanism for atoms of interest.
|
||||
variable csp_lattice string "fcc"
|
||||
variable csp_cutoff equal 6.0
|
||||
# The range [r_sw_lo, r_sw_hi] determines where the switching parameter changes from 0 to 1.
|
||||
variable r_sw_lo equal 2.0
|
||||
variable r_sw_hi equal 3.0
|
||||
# Thresholds between which the switching parameter changes from 1 to 0 based on the csp.
|
||||
variable lambda_input_thr_lo equal 2.5
|
||||
variable lambda_input_thr_hi equal 3.0
|
||||
# Number of averaged steps.
|
||||
variable lambda_input_histlen equal 110
|
||||
variable lambda_histlen equal 110
|
||||
# Minimum required change of the switching parameter
|
||||
variable min_delta_lambda equal 1/${lambda_histlen}
|
||||
# number of atoms rescaled by the lambda_thermostat
|
||||
variable N_rescaling equal 600
|
||||
|
||||
|
||||
|
||||
## basic stuff
|
||||
units metal
|
||||
atom_style apip # own atom style required for APIP
|
||||
timestep 0.001
|
||||
|
||||
# copper at room temperature with a vacancy
|
||||
read_data data.vacancy
|
||||
|
||||
fix nve all nve
|
||||
|
||||
|
||||
## Use adaptive-precision ace-ace potential without lambda_thermostat.
|
||||
## Calculate atomic weight that could be used for load balancing.
|
||||
#pair_style hybrid/overlay pace/fast/apip pace/precise/apip lambda/input/csp/apip ${csp_lattice} cutoff ${csp_cutoff} lambda/zone/apip ${r_sw_hi}
|
||||
#pair_coeff * * pace/fast/apip ${ace_file1} Cu
|
||||
#pair_coeff * * pace/precise/apip ${ace_file2} Cu
|
||||
#pair_coeff * * lambda/input/csp/apip
|
||||
#pair_coeff * * lambda/zone/apip
|
||||
#fix lambda all lambda/apip ${lambda_input_thr_lo} ${lambda_input_thr_hi} time_averaged_zone ${r_sw_lo} ${r_sw_hi} ${lambda_input_histlen} ${lambda_histlen} min_delta_lambda ${min_delta_lambda}
|
||||
#fix weight_atom all atom_weight/apip 100 ace ace lambda/input lambda/zone all
|
||||
|
||||
|
||||
# Use adaptive-precision eam-ace potential without lambda_thermostat.
|
||||
# Calculate atomic weight that could be used for load balancing.
|
||||
pair_style hybrid/overlay eam/fs/apip pace/apip lambda/input/csp/apip ${csp_lattice} cutoff ${csp_cutoff} lambda/zone/apip ${r_sw_hi}
|
||||
pair_coeff * * eam/fs/apip ${eamfs_file} Cu
|
||||
pair_coeff * * pace/apip ${ace_file2} Cu
|
||||
pair_coeff * * lambda/input/csp/apip
|
||||
pair_coeff * * lambda/zone/apip
|
||||
fix lambda all lambda/apip ${lambda_input_thr_lo} ${lambda_input_thr_hi} time_averaged_zone ${r_sw_lo} ${r_sw_hi} ${lambda_input_histlen} ${lambda_histlen} min_delta_lambda ${min_delta_lambda}
|
||||
fix weight_atom all atom_weight/apip 100 eam ace lambda/input lambda/zone all
|
||||
|
||||
|
||||
## One can comment out fix lambda_thermostat to see the energy change caused by the neglection of the
|
||||
## gradient of the switching function. This neglection can be compensated by the local thermostat and the
|
||||
## energy can be conserved within numerical precision.
|
||||
fix lambda_thermostat all lambda_thermostat/apip N_rescaling ${N_rescaling} store_atomic_forces 100
|
||||
|
||||
|
||||
# get statistics about lambda
|
||||
compute lambda all property/atom apip_lambda
|
||||
compute lambda_input all property/atom apip_lambda_input
|
||||
variable flag_simple atom c_lambda==1
|
||||
variable flag_switch atom c_lambda<1&&c_lambda>0
|
||||
variable flag_complex atom c_lambda==0
|
||||
compute lambda_types all reduce sum v_flag_simple v_flag_switch v_flag_complex
|
||||
|
||||
|
||||
thermo_style custom step etotal c_lambda_types[*]
|
||||
thermo 1
|
||||
|
||||
run 100
|
||||
|
||||
# dump atoms
|
||||
#write_dump all custom dump/vacancy.dump.* id type x y z fx fy fz c_lambda c_lambda_input f_weight_atom f_lambda_thermostat[*]
|
||||
|
||||
|
||||
|
||||
## A smooth restart of the simulation is possible as the history of lambda and lambda_input is stored.
|
||||
|
||||
#write_restart vacancy_ap.restart
|
||||
#clear
|
||||
#read_restart vacancy_ap.restart
|
||||
#pair_style hybrid/overlay eam/fs/apip pace/apip lambda/input/csp/apip fcc cutoff 6.0 lambda/zone/apip 12.0
|
||||
#pair_coeff * * eam/fs/apip "Cu_300K_Immel_2023.eam.fs" Cu
|
||||
#pair_coeff * * pace/apip "../../../potentials/Cu-PBE-core-rep.ace" Cu
|
||||
#pair_coeff * * lambda/input/csp/apip
|
||||
#pair_coeff * * lambda/zone/apip
|
||||
#fix lambda all lambda/apip 2.5 3.0 time_averaged_zone 4.0 12.0 110 110 min_delta_lambda $(1/110)
|
||||
#fix lambda_thermostat all lambda_thermostat/apip N_rescaling ${N_rescaling} store_atomic_forces 100
|
||||
#fix nve all nve
|
||||
#thermo_style custom step etotal
|
||||
#thermo 1
|
||||
#run 10
|
||||
#shell rm vacancy_ap.restart
|
||||
51
examples/PACKAGES/apip/in.validate
Normal file
51
examples/PACKAGES/apip/in.validate
Normal file
@ -0,0 +1,51 @@
|
||||
##################################################
|
||||
# parameters of the adaptive-precision potential #
|
||||
##################################################
|
||||
# We couple an EAM potential with an ACE potential.
|
||||
variable eamfs_file string "Cu_300K_Immel_2023.eam.fs"
|
||||
variable ace_file string "Cu-1.yace"
|
||||
|
||||
|
||||
## basic stuff
|
||||
units metal
|
||||
atom_style apip # own atom style required for APIP
|
||||
timestep 0.001
|
||||
|
||||
## copper with a vacancy
|
||||
#lattice fcc 3.615
|
||||
#region box block 0 2 0 2 0 2 units lattice
|
||||
#create_box 1 box
|
||||
#create_atoms 1 box
|
||||
#mass 1 63.546
|
||||
#displace_atoms all random 0.1 0.1 0.1 42 units lattice
|
||||
#delete_atoms random count 1 yes all NULL 42
|
||||
#write_data data.validate
|
||||
read_data data.validate
|
||||
|
||||
|
||||
fix 1 all nve
|
||||
thermo_style custom step pe fnorm fmax
|
||||
|
||||
|
||||
# use ACE potential
|
||||
pair_style pace
|
||||
pair_coeff * * ${ace_file} Cu
|
||||
run 0
|
||||
|
||||
# use adaptive-precision EAM-ACE potential with constant lambda
|
||||
pair_style hybrid/overlay eam/fs/apip pace/apip
|
||||
pair_coeff * * eam/fs/apip ${eamfs_file} Cu
|
||||
pair_coeff * * pace/apip ${ace_file} Cu
|
||||
|
||||
# use ACE of adaptive-precision potential
|
||||
set group all apip/lambda precise
|
||||
run 0
|
||||
|
||||
# use EAM of adaptive-precision potential
|
||||
set group all apip/lambda fast
|
||||
run 0
|
||||
|
||||
# Use EAM potential
|
||||
pair_style eam/fs
|
||||
pair_coeff * * ${eamfs_file} Cu
|
||||
run 0
|
||||
108
examples/PACKAGES/apip/log.02Apr25.surface.balance.nolb.g++.4
Normal file
108
examples/PACKAGES/apip/log.02Apr25.surface.balance.nolb.g++.4
Normal file
@ -0,0 +1,108 @@
|
||||
LAMMPS (2 Apr 2025 - Development - )
|
||||
Reading data file ...
|
||||
orthogonal box = (0 0 -1.1656272) to (36.15 36.15 362.81506)
|
||||
1 by 1 by 4 MPI processor grid
|
||||
reading atoms ...
|
||||
40200 atoms
|
||||
reading velocities ...
|
||||
40200 velocities
|
||||
read_data CPU = 0.135 seconds
|
||||
200 atoms in group group_ignore_csp
|
||||
ACE version: 2023.11.25
|
||||
Recursive evaluator is used by ACE
|
||||
Loading ../../../potentials/Cu-PBE-core-rep.ace
|
||||
Total number of basis functions
|
||||
Cu: 16 (r=1) 726 (r>1)
|
||||
Mapping LAMMPS atom type #1(Cu) -> ACE species type #0
|
||||
atomic load lambda:
|
||||
fast potential: extract eam/apip:time_per_atom
|
||||
precise potential: extract pace/apip:time_per_atom
|
||||
lambda_input: extract lambda/input/apip:time_per_atom
|
||||
lambda: extract lambda/zone/apip:time_per_atom
|
||||
|
||||
CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE
|
||||
|
||||
Your simulation uses code contributions which should be cited:
|
||||
- fix lambda command: doi.org/10.1063/5.0245877
|
||||
The log file lists these citations in BibTeX format.
|
||||
|
||||
CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE
|
||||
|
||||
Neighbor list info ...
|
||||
update: every = 1 steps, delay = 0 steps, check = yes
|
||||
max neighbors/atom: 2000, page size: 100000
|
||||
master list distance cutoff = 14
|
||||
ghost atom cutoff = 14
|
||||
binsize = 7, bins = 6 6 52
|
||||
5 neighbor lists, perpetual/occasional/extra = 5 0 0
|
||||
(1) pair eam/fs/apip, perpetual
|
||||
attributes: full, newton on
|
||||
pair build: full/bin/atomonly
|
||||
stencil: full/bin/3d
|
||||
bin: standard
|
||||
(2) pair pace/apip, perpetual, trim from (4)
|
||||
attributes: full, newton on, cut 9.4
|
||||
pair build: trim
|
||||
stencil: none
|
||||
bin: none
|
||||
(3) pair lambda/input/csp/apip, perpetual, trim from (2)
|
||||
attributes: full, newton on, cut 8
|
||||
pair build: trim
|
||||
stencil: none
|
||||
bin: none
|
||||
(4) pair lambda/zone/apip, perpetual
|
||||
attributes: full, newton on, ghost, cut 14
|
||||
pair build: full/bin/ghost
|
||||
stencil: full/ghost/bin/3d
|
||||
bin: standard
|
||||
(5) fix lambda_thermostat/apip, perpetual, copy from (1)
|
||||
attributes: full, newton on
|
||||
pair build: copy
|
||||
stencil: none
|
||||
bin: none
|
||||
Setting up Verlet run ...
|
||||
Unit style : metal
|
||||
Current step : 0
|
||||
Time step : 0.001
|
||||
Per MPI rank memory allocation (min/avg/max) = 297.9 | 306.9 | 315.9 Mbytes
|
||||
Step f_balance S/CPU f_weight_atom[1] f_weight_atom[2] f_weight_atom[3] f_weight_atom[4]
|
||||
0 1.0139303 0 0 0 0 0
|
||||
10 2.6176099 0.23789922 3.4933844e-05 0.0018769787 2.0912678e-05 3.414976e-05
|
||||
20 2.1242027 0.2259695 4.2800036e-05 0.0022124427 2.4613899e-05 4.0819606e-05
|
||||
30 2.1197082 0.22281117 4.3885117e-05 0.0022416604 2.4808124e-05 4.081464e-05
|
||||
40 2.1149313 0.2245266 4.3328755e-05 0.0022134411 2.4645468e-05 4.0892224e-05
|
||||
50 2.1066618 0.22308398 4.3884622e-05 0.0022085846 2.464161e-05 4.0909229e-05
|
||||
60 2.1000306 0.22186291 4.4839801e-05 0.0022299631 2.4816945e-05 4.1173119e-05
|
||||
70 2.1062658 0.22406791 4.3740709e-05 0.0022049729 2.4693417e-05 4.0963037e-05
|
||||
80 2.1072933 0.22241288 4.4160464e-05 0.0022245226 2.4854938e-05 4.2491144e-05
|
||||
90 2.0981181 0.22412189 4.3990788e-05 0.0022086162 2.4710948e-05 4.09478e-05
|
||||
100 2.1033304 0.2237968 4.3982714e-05 0.0022112815 2.4658851e-05 4.1060551e-05
|
||||
Loop time of 444.499 on 4 procs for 100 steps with 40200 atoms
|
||||
|
||||
Performance: 0.019 ns/day, 1234.721 hours/ns, 0.225 timesteps/s, 9.044 katom-step/s
|
||||
99.0% CPU use with 4 MPI tasks x no OpenMP threads
|
||||
|
||||
MPI task timing breakdown:
|
||||
Section | min time | avg time | max time |%varavg| %total
|
||||
---------------------------------------------------------------
|
||||
Pair | 67.764 | 146.15 | 378.03 |1107.5 | 32.88
|
||||
Neigh | 55.764 | 59.579 | 62.94 | 43.1 | 13.40
|
||||
Comm | 0.6589 | 153.57 | 302.72 |1199.1 | 34.55
|
||||
Output | 0.0032423 | 6.1068 | 24.01 | 418.3 | 1.37
|
||||
Modify | 8.0892 | 16.162 | 38.588 | 322.6 | 3.64
|
||||
Other | | 62.93 | | | 14.16
|
||||
|
||||
Nlocal: 10050 ave 10180 max 10000 min
|
||||
Histogram: 2 1 0 0 0 0 0 0 0 1
|
||||
Nghost: 27854.5 ave 30385 max 25525 min
|
||||
Histogram: 2 0 0 0 0 0 0 0 0 2
|
||||
Neighs: 0 ave 0 max 0 min
|
||||
Histogram: 4 0 0 0 0 0 0 0 0 0
|
||||
FullNghs: 9.49222e+06 ave 9.76687e+06 max 9.29466e+06 min
|
||||
Histogram: 2 0 0 0 0 0 1 0 0 1
|
||||
|
||||
Total # of neighbors = 37968882
|
||||
Ave neighs/atom = 944.49955
|
||||
Neighbor list builds = 10
|
||||
Dangerous builds = 0
|
||||
Total wall time: 0:07:25
|
||||
@ -0,0 +1,108 @@
|
||||
LAMMPS (2 Apr 2025 - Development - )
|
||||
Reading data file ...
|
||||
orthogonal box = (0 0 -1.1656272) to (36.15 36.15 362.81506)
|
||||
1 by 1 by 4 MPI processor grid
|
||||
reading atoms ...
|
||||
40200 atoms
|
||||
reading velocities ...
|
||||
40200 velocities
|
||||
read_data CPU = 0.161 seconds
|
||||
200 atoms in group group_ignore_csp
|
||||
ACE version: 2023.11.25
|
||||
Recursive evaluator is used by ACE
|
||||
Loading ../../../potentials/Cu-PBE-core-rep.ace
|
||||
Total number of basis functions
|
||||
Cu: 16 (r=1) 726 (r>1)
|
||||
Mapping LAMMPS atom type #1(Cu) -> ACE species type #0
|
||||
atomic load lambda:
|
||||
fast potential: extract eam/apip:time_per_atom
|
||||
precise potential: extract pace/apip:time_per_atom
|
||||
lambda_input: extract lambda/input/apip:time_per_atom
|
||||
lambda: extract lambda/zone/apip:time_per_atom
|
||||
|
||||
CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE
|
||||
|
||||
Your simulation uses code contributions which should be cited:
|
||||
- fix lambda command: doi.org/10.1063/5.0245877
|
||||
The log file lists these citations in BibTeX format.
|
||||
|
||||
CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE
|
||||
|
||||
Neighbor list info ...
|
||||
update: every = 1 steps, delay = 0 steps, check = yes
|
||||
max neighbors/atom: 2000, page size: 100000
|
||||
master list distance cutoff = 14
|
||||
ghost atom cutoff = 14
|
||||
binsize = 7, bins = 6 6 52
|
||||
5 neighbor lists, perpetual/occasional/extra = 5 0 0
|
||||
(1) pair eam/fs/apip, perpetual
|
||||
attributes: full, newton on
|
||||
pair build: full/bin/atomonly
|
||||
stencil: full/bin/3d
|
||||
bin: standard
|
||||
(2) pair pace/apip, perpetual, trim from (4)
|
||||
attributes: full, newton on, cut 9.4
|
||||
pair build: trim
|
||||
stencil: none
|
||||
bin: none
|
||||
(3) pair lambda/input/csp/apip, perpetual, trim from (2)
|
||||
attributes: full, newton on, cut 8
|
||||
pair build: trim
|
||||
stencil: none
|
||||
bin: none
|
||||
(4) pair lambda/zone/apip, perpetual
|
||||
attributes: full, newton on, ghost, cut 14
|
||||
pair build: full/bin/ghost
|
||||
stencil: full/ghost/bin/3d
|
||||
bin: standard
|
||||
(5) fix lambda_thermostat/apip, perpetual, copy from (1)
|
||||
attributes: full, newton on
|
||||
pair build: copy
|
||||
stencil: none
|
||||
bin: none
|
||||
Setting up Verlet run ...
|
||||
Unit style : metal
|
||||
Current step : 0
|
||||
Time step : 0.001
|
||||
Per MPI rank memory allocation (min/avg/max) = 298.1 | 306.3 | 314.5 Mbytes
|
||||
Step f_balance S/CPU f_weight_atom[1] f_weight_atom[2] f_weight_atom[3] f_weight_atom[4]
|
||||
0 1 0 0 0 0 0
|
||||
10 1.0018226 0.21929744 4.2082278e-05 0.0022147425 2.472285e-05 4.0694771e-05
|
||||
20 1.002451 0.38193369 4.9389333e-05 0.0023722824 2.4776133e-05 2.168819e-05
|
||||
30 1.0004234 0.39492198 4.8977088e-05 0.002249832 2.4610967e-05 2.1465621e-05
|
||||
40 1.0012276 0.39068387 4.9886201e-05 0.0022529811 2.4663509e-05 2.1540032e-05
|
||||
50 1.0013752 0.39170654 5.0527084e-05 0.002253323 2.4721079e-05 2.153442e-05
|
||||
60 1.0007053 0.3758265 5.0935226e-05 0.0022581901 2.4772692e-05 2.1596641e-05
|
||||
70 1.0003982 0.38524379 5.1685387e-05 0.002263544 2.495032e-05 2.1714264e-05
|
||||
80 1.0022848 0.38409158 5.1897166e-05 0.0022557711 2.4755235e-05 2.1595246e-05
|
||||
90 1.0012911 0.38122934 5.2440631e-05 0.0022574019 2.4795351e-05 2.1615786e-05
|
||||
100 1.0005279 0.37983246 5.2871808e-05 0.0022583136 2.484618e-05 2.1569403e-05
|
||||
Loop time of 279.389 on 4 procs for 100 steps with 40200 atoms
|
||||
|
||||
Performance: 0.031 ns/day, 776.081 hours/ns, 0.358 timesteps/s, 14.389 katom-step/s
|
||||
98.6% CPU use with 4 MPI tasks x no OpenMP threads
|
||||
|
||||
MPI task timing breakdown:
|
||||
Section | min time | avg time | max time |%varavg| %total
|
||||
---------------------------------------------------------------
|
||||
Pair | 148.19 | 155.34 | 175.77 | 94.7 | 55.60
|
||||
Neigh | 87.542 | 87.924 | 88.444 | 3.6 | 31.47
|
||||
Comm | 4.9019 | 18.932 | 33.429 | 322.2 | 6.78
|
||||
Output | 0.01326 | 0.04615 | 0.075485 | 10.3 | 0.02
|
||||
Modify | 9.5358 | 10.391 | 12.424 | 36.6 | 3.72
|
||||
Other | | 6.756 | | | 2.42
|
||||
|
||||
Nlocal: 10050 ave 10283 max 9838 min
|
||||
Histogram: 1 0 1 0 0 0 1 0 0 1
|
||||
Nghost: 52763 ave 52975 max 52530 min
|
||||
Histogram: 1 0 0 1 0 0 0 1 0 1
|
||||
Neighs: 0 ave 0 max 0 min
|
||||
Histogram: 4 0 0 0 0 0 0 0 0 0
|
||||
FullNghs: 9.49222e+06 ave 9.71459e+06 max 9.29015e+06 min
|
||||
Histogram: 1 0 1 0 0 0 1 0 0 1
|
||||
|
||||
Total # of neighbors = 37968882
|
||||
Ave neighs/atom = 944.49955
|
||||
Neighbor list builds = 10
|
||||
Dangerous builds = 0
|
||||
Total wall time: 0:04:48
|
||||
@ -0,0 +1,108 @@
|
||||
LAMMPS (2 Apr 2025 - Development - )
|
||||
Reading data file ...
|
||||
orthogonal box = (0 0 -1.1656272) to (36.15 36.15 362.81506)
|
||||
1 by 1 by 4 MPI processor grid
|
||||
reading atoms ...
|
||||
40200 atoms
|
||||
reading velocities ...
|
||||
40200 velocities
|
||||
read_data CPU = 0.134 seconds
|
||||
200 atoms in group group_ignore_csp
|
||||
ACE version: 2023.11.25
|
||||
Recursive evaluator is used by ACE
|
||||
Loading ../../../potentials/Cu-PBE-core-rep.ace
|
||||
Total number of basis functions
|
||||
Cu: 16 (r=1) 726 (r>1)
|
||||
Mapping LAMMPS atom type #1(Cu) -> ACE species type #0
|
||||
atomic load lambda:
|
||||
fast potential: extract eam/apip:time_per_atom
|
||||
precise potential: extract pace/apip:time_per_atom
|
||||
lambda_input: extract lambda/input/apip:time_per_atom
|
||||
lambda: extract lambda/zone/apip:time_per_atom
|
||||
|
||||
CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE
|
||||
|
||||
Your simulation uses code contributions which should be cited:
|
||||
- fix lambda command: doi.org/10.1063/5.0245877
|
||||
The log file lists these citations in BibTeX format.
|
||||
|
||||
CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE
|
||||
|
||||
Neighbor list info ...
|
||||
update: every = 1 steps, delay = 0 steps, check = yes
|
||||
max neighbors/atom: 2000, page size: 100000
|
||||
master list distance cutoff = 14
|
||||
ghost atom cutoff = 14
|
||||
binsize = 7, bins = 6 6 52
|
||||
5 neighbor lists, perpetual/occasional/extra = 5 0 0
|
||||
(1) pair eam/fs/apip, perpetual
|
||||
attributes: full, newton on
|
||||
pair build: full/bin/atomonly
|
||||
stencil: full/bin/3d
|
||||
bin: standard
|
||||
(2) pair pace/apip, perpetual, trim from (4)
|
||||
attributes: full, newton on, cut 9.4
|
||||
pair build: trim
|
||||
stencil: none
|
||||
bin: none
|
||||
(3) pair lambda/input/csp/apip, perpetual, trim from (2)
|
||||
attributes: full, newton on, cut 8
|
||||
pair build: trim
|
||||
stencil: none
|
||||
bin: none
|
||||
(4) pair lambda/zone/apip, perpetual
|
||||
attributes: full, newton on, ghost, cut 14
|
||||
pair build: full/bin/ghost
|
||||
stencil: full/ghost/bin/3d
|
||||
bin: standard
|
||||
(5) fix lambda_thermostat/apip, perpetual, copy from (1)
|
||||
attributes: full, newton on
|
||||
pair build: copy
|
||||
stencil: none
|
||||
bin: none
|
||||
Setting up Verlet run ...
|
||||
Unit style : metal
|
||||
Current step : 0
|
||||
Time step : 0.001
|
||||
Per MPI rank memory allocation (min/avg/max) = 298.1 | 306.3 | 314.5 Mbytes
|
||||
Step f_balance S/CPU f_weight_atom[1] f_weight_atom[2] f_weight_atom[3] f_weight_atom[4]
|
||||
0 1 0 0 0 0 0
|
||||
10 1.000245 0.23168829 2.8965377e-05 0.0016346261 1.8194173e-05 2.8621987e-05
|
||||
20 1.0001156 0.23012235 4.2703387e-05 0.0022174634 2.4522315e-05 4.0198928e-05
|
||||
30 1.0003479 0.24170843 4.2900821e-05 0.0022358654 2.4496934e-05 4.0262644e-05
|
||||
40 1.0000952 0.34743014 4.4687983e-05 0.0022336389 2.4626704e-05 2.8362965e-05
|
||||
50 1.000399 0.23273413 4.4278568e-05 0.0022319529 2.4645291e-05 4.0394287e-05
|
||||
60 1.000137 0.23531789 4.5212176e-05 0.0022671271 2.4758267e-05 4.0607561e-05
|
||||
70 1.0001901 0.34359487 4.5647742e-05 0.0022386998 2.473236e-05 2.8357019e-05
|
||||
80 1.0003173 0.23324348 4.5372627e-05 0.0022272881 2.4704053e-05 4.0760615e-05
|
||||
90 1.0009828 0.2360927 4.5867574e-05 0.0022616272 2.4715122e-05 4.0548519e-05
|
||||
100 1.0005337 0.34332801 4.6171376e-05 0.0022394199 2.4724815e-05 2.8552653e-05
|
||||
Loop time of 385.695 on 4 procs for 100 steps with 40200 atoms
|
||||
|
||||
Performance: 0.022 ns/day, 1071.376 hours/ns, 0.259 timesteps/s, 10.423 katom-step/s
|
||||
98.9% CPU use with 4 MPI tasks x no OpenMP threads
|
||||
|
||||
MPI task timing breakdown:
|
||||
Section | min time | avg time | max time |%varavg| %total
|
||||
---------------------------------------------------------------
|
||||
Pair | 80.949 | 145.84 | 287.45 | 683.6 | 37.81
|
||||
Neigh | 21.125 | 61.121 | 98.27 | 452.7 | 15.85
|
||||
Comm | 23.839 | 129.54 | 261.28 | 833.4 | 33.59
|
||||
Output | 0.10319 | 2.5231 | 8.6153 | 222.9 | 0.65
|
||||
Modify | 5.3228 | 13.101 | 29.2 | 267.2 | 3.40
|
||||
Other | | 33.57 | | | 8.70
|
||||
|
||||
Nlocal: 10050 ave 16825 max 3772 min
|
||||
Histogram: 2 0 0 0 0 0 0 0 0 2
|
||||
Nghost: 27618.8 ave 41748 max 12149 min
|
||||
Histogram: 1 1 0 0 0 0 0 0 0 2
|
||||
Neighs: 0 ave 0 max 0 min
|
||||
Histogram: 4 0 0 0 0 0 0 0 0 0
|
||||
FullNghs: 9.49222e+06 ave 1.58445e+07 max 3.337e+06 min
|
||||
Histogram: 2 0 0 0 0 0 0 0 0 2
|
||||
|
||||
Total # of neighbors = 37968882
|
||||
Ave neighs/atom = 944.49955
|
||||
Neighbor list builds = 10
|
||||
Dangerous builds = 0
|
||||
Total wall time: 0:06:27
|
||||
182
examples/PACKAGES/apip/log.02Apr25.vacancy.const.lambda.g++.1
Normal file
182
examples/PACKAGES/apip/log.02Apr25.vacancy.const.lambda.g++.1
Normal file
@ -0,0 +1,182 @@
|
||||
LAMMPS (2 Apr 2025 - Development - )
|
||||
Reading data file ...
|
||||
orthogonal box = (0 0 0) to (28.92 28.92 28.92)
|
||||
1 by 1 by 1 MPI processor grid
|
||||
reading atoms ...
|
||||
2047 atoms
|
||||
reading velocities ...
|
||||
2047 velocities
|
||||
read_data CPU = 0.009 seconds
|
||||
12 atoms in group vacancy
|
||||
42 atoms in group transition
|
||||
1993 atoms in group bulk
|
||||
Setting atom values ...
|
||||
12 settings made for apip/lambda
|
||||
Setting atom values ...
|
||||
42 settings made for apip/lambda
|
||||
Setting atom values ...
|
||||
1993 settings made for apip/lambda
|
||||
ACE version: 2023.11.25
|
||||
Recursive evaluator is used by ACE
|
||||
Loading ../../../potentials/Cu-PBE-core-rep.ace
|
||||
Total number of basis functions
|
||||
Cu: 16 (r=1) 726 (r>1)
|
||||
Mapping LAMMPS atom type #1(Cu) -> ACE species type #0
|
||||
atomic load lambda:
|
||||
fast potential: extract eam/apip:time_per_atom
|
||||
precise potential: extract pace/apip:time_per_atom
|
||||
lambda_input: const 0.5
|
||||
lambda: const 0
|
||||
Neighbor list info ...
|
||||
update: every = 1 steps, delay = 0 steps, check = yes
|
||||
max neighbors/atom: 2000, page size: 100000
|
||||
master list distance cutoff = 9.4
|
||||
ghost atom cutoff = 9.4
|
||||
binsize = 4.7, bins = 7 7 7
|
||||
2 neighbor lists, perpetual/occasional/extra = 2 0 0
|
||||
(1) pair eam/fs/apip, perpetual
|
||||
attributes: full, newton on
|
||||
pair build: full/bin/atomonly
|
||||
stencil: full/bin/3d
|
||||
bin: standard
|
||||
(2) pair pace/apip, perpetual
|
||||
attributes: full, newton on, cut 9.4
|
||||
pair build: full/bin/atomonly
|
||||
stencil: full/bin/3d
|
||||
bin: standard
|
||||
Setting up Verlet run ...
|
||||
Unit style : metal
|
||||
Current step : 0
|
||||
Time step : 0.001
|
||||
Per MPI rank memory allocation (min/avg/max) = 11.08 | 11.08 | 11.08 Mbytes
|
||||
Step TotEng c_lambda_types[1] c_lambda_types[2] c_lambda_types[3]
|
||||
0 -7408.6798 1993 42 12
|
||||
1 -7408.6798 1993 42 12
|
||||
2 -7408.6798 1993 42 12
|
||||
3 -7408.6798 1993 42 12
|
||||
4 -7408.6798 1993 42 12
|
||||
5 -7408.6798 1993 42 12
|
||||
6 -7408.6799 1993 42 12
|
||||
7 -7408.6799 1993 42 12
|
||||
8 -7408.6799 1993 42 12
|
||||
9 -7408.6799 1993 42 12
|
||||
10 -7408.6799 1993 42 12
|
||||
11 -7408.68 1993 42 12
|
||||
12 -7408.68 1993 42 12
|
||||
13 -7408.68 1993 42 12
|
||||
14 -7408.68 1993 42 12
|
||||
15 -7408.68 1993 42 12
|
||||
16 -7408.68 1993 42 12
|
||||
17 -7408.6801 1993 42 12
|
||||
18 -7408.6801 1993 42 12
|
||||
19 -7408.6801 1993 42 12
|
||||
20 -7408.6801 1993 42 12
|
||||
21 -7408.6801 1993 42 12
|
||||
22 -7408.6801 1993 42 12
|
||||
23 -7408.6801 1993 42 12
|
||||
24 -7408.6801 1993 42 12
|
||||
25 -7408.6801 1993 42 12
|
||||
26 -7408.6801 1993 42 12
|
||||
27 -7408.6801 1993 42 12
|
||||
28 -7408.6801 1993 42 12
|
||||
29 -7408.6801 1993 42 12
|
||||
30 -7408.6801 1993 42 12
|
||||
31 -7408.6801 1993 42 12
|
||||
32 -7408.68 1993 42 12
|
||||
33 -7408.68 1993 42 12
|
||||
34 -7408.68 1993 42 12
|
||||
35 -7408.68 1993 42 12
|
||||
36 -7408.68 1993 42 12
|
||||
37 -7408.68 1993 42 12
|
||||
38 -7408.68 1993 42 12
|
||||
39 -7408.68 1993 42 12
|
||||
40 -7408.6801 1993 42 12
|
||||
41 -7408.6801 1993 42 12
|
||||
42 -7408.6801 1993 42 12
|
||||
43 -7408.6801 1993 42 12
|
||||
44 -7408.6801 1993 42 12
|
||||
45 -7408.6801 1993 42 12
|
||||
46 -7408.6801 1993 42 12
|
||||
47 -7408.6801 1993 42 12
|
||||
48 -7408.6801 1993 42 12
|
||||
49 -7408.6802 1993 42 12
|
||||
50 -7408.6802 1993 42 12
|
||||
51 -7408.6802 1993 42 12
|
||||
52 -7408.6802 1993 42 12
|
||||
53 -7408.6802 1993 42 12
|
||||
54 -7408.6802 1993 42 12
|
||||
55 -7408.6802 1993 42 12
|
||||
56 -7408.6802 1993 42 12
|
||||
57 -7408.6802 1993 42 12
|
||||
58 -7408.6802 1993 42 12
|
||||
59 -7408.6801 1993 42 12
|
||||
60 -7408.6801 1993 42 12
|
||||
61 -7408.6801 1993 42 12
|
||||
62 -7408.6801 1993 42 12
|
||||
63 -7408.6801 1993 42 12
|
||||
64 -7408.68 1993 42 12
|
||||
65 -7408.68 1993 42 12
|
||||
66 -7408.68 1993 42 12
|
||||
67 -7408.68 1993 42 12
|
||||
68 -7408.68 1993 42 12
|
||||
69 -7408.6799 1993 42 12
|
||||
70 -7408.6799 1993 42 12
|
||||
71 -7408.6799 1993 42 12
|
||||
72 -7408.6799 1993 42 12
|
||||
73 -7408.6799 1993 42 12
|
||||
74 -7408.6799 1993 42 12
|
||||
75 -7408.6798 1993 42 12
|
||||
76 -7408.6798 1993 42 12
|
||||
77 -7408.6798 1993 42 12
|
||||
78 -7408.6798 1993 42 12
|
||||
79 -7408.6798 1993 42 12
|
||||
80 -7408.6798 1993 42 12
|
||||
81 -7408.6799 1993 42 12
|
||||
82 -7408.6799 1993 42 12
|
||||
83 -7408.6799 1993 42 12
|
||||
84 -7408.6799 1993 42 12
|
||||
85 -7408.6799 1993 42 12
|
||||
86 -7408.6799 1993 42 12
|
||||
87 -7408.6799 1993 42 12
|
||||
88 -7408.68 1993 42 12
|
||||
89 -7408.68 1993 42 12
|
||||
90 -7408.68 1993 42 12
|
||||
91 -7408.68 1993 42 12
|
||||
92 -7408.68 1993 42 12
|
||||
93 -7408.68 1993 42 12
|
||||
94 -7408.68 1993 42 12
|
||||
95 -7408.68 1993 42 12
|
||||
96 -7408.68 1993 42 12
|
||||
97 -7408.6801 1993 42 12
|
||||
98 -7408.6801 1993 42 12
|
||||
99 -7408.6801 1993 42 12
|
||||
100 -7408.6801 1993 42 12
|
||||
Loop time of 1.65093 on 1 procs for 100 steps with 2047 atoms
|
||||
|
||||
Performance: 5.233 ns/day, 4.586 hours/ns, 60.572 timesteps/s, 123.991 katom-step/s
|
||||
99.8% CPU use with 1 MPI tasks x no OpenMP threads
|
||||
|
||||
MPI task timing breakdown:
|
||||
Section | min time | avg time | max time |%varavg| %total
|
||||
---------------------------------------------------------------
|
||||
Pair | 1.6272 | 1.6272 | 1.6272 | 0.0 | 98.56
|
||||
Neigh | 0 | 0 | 0 | 0.0 | 0.00
|
||||
Comm | 0.012716 | 0.012716 | 0.012716 | 0.0 | 0.77
|
||||
Output | 0.0078409 | 0.0078409 | 0.0078409 | 0.0 | 0.47
|
||||
Modify | 0.0013654 | 0.0013654 | 0.0013654 | 0.0 | 0.08
|
||||
Other | | 0.001839 | | | 0.11
|
||||
|
||||
Nlocal: 2047 ave 2047 max 2047 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
Nghost: 7790 ave 7790 max 7790 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
Neighs: 0 ave 0 max 0 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
FullNghs: 648022 ave 648022 max 648022 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
|
||||
Total # of neighbors = 648022
|
||||
Ave neighs/atom = 316.57157
|
||||
Neighbor list builds = 0
|
||||
Dangerous builds = 0
|
||||
Total wall time: 0:00:01
|
||||
@ -0,0 +1,193 @@
|
||||
LAMMPS (2 Apr 2025 - Development - )
|
||||
Reading data file ...
|
||||
orthogonal box = (0 0 0) to (28.92 28.92 28.92)
|
||||
1 by 1 by 1 MPI processor grid
|
||||
reading atoms ...
|
||||
2047 atoms
|
||||
reading velocities ...
|
||||
2047 velocities
|
||||
read_data CPU = 0.009 seconds
|
||||
ACE version: 2023.11.25
|
||||
Recursive evaluator is used by ACE
|
||||
Loading ../../../potentials/Cu-PBE-core-rep.ace
|
||||
Total number of basis functions
|
||||
Cu: 16 (r=1) 726 (r>1)
|
||||
Mapping LAMMPS atom type #1(Cu) -> ACE species type #0
|
||||
atomic load lambda:
|
||||
fast potential: extract eam/apip:time_per_atom
|
||||
precise potential: extract pace/apip:time_per_atom
|
||||
lambda_input: extract lambda/input/apip:time_per_atom
|
||||
lambda: extract lambda/zone/apip:time_per_atom
|
||||
|
||||
CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE
|
||||
|
||||
Your simulation uses code contributions which should be cited:
|
||||
- fix lambda command: doi.org/10.1063/5.0245877
|
||||
The log file lists these citations in BibTeX format.
|
||||
|
||||
CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE
|
||||
|
||||
WARNING: The energy is not conserved when lambda changes as fix lambda_thermostat/apip is not used. (../fix_lambda_apip.cpp:248)
|
||||
Neighbor list info ...
|
||||
update: every = 1 steps, delay = 0 steps, check = yes
|
||||
max neighbors/atom: 2000, page size: 100000
|
||||
master list distance cutoff = 9.4
|
||||
ghost atom cutoff = 9.4
|
||||
binsize = 4.7, bins = 7 7 7
|
||||
4 neighbor lists, perpetual/occasional/extra = 4 0 0
|
||||
(1) pair eam/fs/apip, perpetual, trim from (3)
|
||||
attributes: full, newton on, cut 7.50679
|
||||
pair build: trim
|
||||
stencil: none
|
||||
bin: none
|
||||
(2) pair pace/apip, perpetual
|
||||
attributes: full, newton on, cut 9.4
|
||||
pair build: full/bin/atomonly
|
||||
stencil: full/bin/3d
|
||||
bin: standard
|
||||
(3) pair lambda/input/csp/apip, perpetual, trim from (2)
|
||||
attributes: full, newton on, cut 8
|
||||
pair build: trim
|
||||
stencil: none
|
||||
bin: none
|
||||
(4) pair lambda/zone/apip, perpetual
|
||||
attributes: full, newton on, ghost
|
||||
pair build: full/bin/ghost
|
||||
stencil: full/ghost/bin/3d
|
||||
bin: standard
|
||||
Setting up Verlet run ...
|
||||
Unit style : metal
|
||||
Current step : 0
|
||||
Time step : 0.001
|
||||
Per MPI rank memory allocation (min/avg/max) = 49.37 | 49.37 | 49.37 Mbytes
|
||||
Step TotEng c_lambda_types[1] c_lambda_types[2] c_lambda_types[3]
|
||||
0 -7408.7649 1993 42 12
|
||||
1 -7408.7649 1993 42 12
|
||||
2 -7408.7649 1993 42 12
|
||||
3 -7408.765 1993 42 12
|
||||
4 -7408.7657 1993 42 12
|
||||
5 -7408.7785 1993 42 12
|
||||
6 -7408.7769 1993 42 12
|
||||
7 -7408.778 1993 42 12
|
||||
8 -7408.7862 1993 42 12
|
||||
9 -7408.79 1993 42 12
|
||||
10 -7408.7912 1993 42 12
|
||||
11 -7408.8005 1993 42 12
|
||||
12 -7408.8012 1993 42 12
|
||||
13 -7408.8016 1993 42 12
|
||||
14 -7408.8123 1993 42 12
|
||||
15 -7408.8154 1993 42 12
|
||||
16 -7408.8144 1993 42 12
|
||||
17 -7408.8271 1993 42 12
|
||||
18 -7408.8277 1993 42 12
|
||||
19 -7408.8289 1993 42 12
|
||||
20 -7408.8352 1993 42 12
|
||||
21 -7408.8376 1993 42 12
|
||||
22 -7408.841 1993 42 12
|
||||
23 -7408.8507 1993 42 12
|
||||
24 -7408.8496 1993 42 12
|
||||
25 -7408.8544 1993 42 12
|
||||
26 -7408.8645 1993 42 12
|
||||
27 -7408.8665 1993 42 12
|
||||
28 -7408.8713 1993 42 12
|
||||
29 -7408.8763 1993 42 12
|
||||
30 -7408.8812 1993 42 12
|
||||
31 -7408.8842 1993 42 12
|
||||
32 -7408.8905 1993 42 12
|
||||
33 -7408.8947 1993 42 12
|
||||
34 -7408.9048 1993 42 12
|
||||
35 -7408.9099 1993 42 12
|
||||
36 -7408.9101 1993 42 12
|
||||
37 -7408.9159 1993 42 12
|
||||
38 -7408.9256 1993 42 12
|
||||
39 -7408.9241 1993 42 12
|
||||
40 -7408.9342 1993 42 12
|
||||
41 -7408.9423 1993 42 12
|
||||
42 -7408.9402 1993 42 12
|
||||
43 -7408.9452 1993 42 12
|
||||
44 -7408.9548 1993 42 12
|
||||
45 -7408.9543 1993 42 12
|
||||
46 -7408.9607 1993 42 12
|
||||
47 -7408.9699 1993 42 12
|
||||
48 -7408.9751 1993 42 12
|
||||
49 -7408.978 1993 42 12
|
||||
50 -7408.9797 1993 42 12
|
||||
51 -7408.9851 1993 42 12
|
||||
52 -7408.9937 1993 42 12
|
||||
53 -7408.9977 1993 42 12
|
||||
54 -7408.9961 1993 42 12
|
||||
55 -7409.0011 1993 42 12
|
||||
56 -7409.0098 1993 42 12
|
||||
57 -7409.0132 1993 42 12
|
||||
58 -7409.0173 1993 42 12
|
||||
59 -7409.0174 1993 42 12
|
||||
60 -7409.0204 1993 42 12
|
||||
61 -7409.0259 1993 42 12
|
||||
62 -7409.0324 1993 42 12
|
||||
63 -7409.0365 1993 42 12
|
||||
64 -7409.0407 1993 42 12
|
||||
65 -7409.0407 1993 42 12
|
||||
66 -7409.0428 1993 42 12
|
||||
67 -7409.0437 1993 42 12
|
||||
68 -7409.0437 1993 42 12
|
||||
69 -7409.0502 1993 42 12
|
||||
70 -7409.0558 1993 42 12
|
||||
71 -7409.0572 1993 42 12
|
||||
72 -7409.0624 1993 42 12
|
||||
73 -7409.0686 1993 42 12
|
||||
74 -7409.0721 1993 42 12
|
||||
75 -7409.075 1993 42 12
|
||||
76 -7409.0751 1993 42 12
|
||||
77 -7409.0728 1993 42 12
|
||||
78 -7409.0732 1993 42 12
|
||||
79 -7409.0764 1993 42 12
|
||||
80 -7409.077 1993 42 12
|
||||
81 -7409.0879 1993 42 12
|
||||
82 -7409.0898 1993 42 12
|
||||
83 -7409.0922 1993 42 12
|
||||
84 -7409.0916 1993 42 12
|
||||
85 -7409.0928 1993 42 12
|
||||
86 -7409.0944 1993 42 12
|
||||
87 -7409.1058 1993 42 12
|
||||
88 -7409.1084 1993 42 12
|
||||
89 -7409.1103 1993 42 12
|
||||
90 -7409.1121 1993 42 12
|
||||
91 -7409.1145 1993 42 12
|
||||
92 -7409.1133 1993 42 12
|
||||
93 -7409.1166 1993 42 12
|
||||
94 -7409.12 1993 42 12
|
||||
95 -7409.119 1993 42 12
|
||||
96 -7409.1208 1993 42 12
|
||||
97 -7409.1217 1993 42 12
|
||||
98 -7409.1229 1993 42 12
|
||||
99 -7409.1235 1993 42 12
|
||||
100 -7409.1206 1993 42 12
|
||||
Loop time of 2.01276 on 1 procs for 100 steps with 2047 atoms
|
||||
|
||||
Performance: 4.293 ns/day, 5.591 hours/ns, 49.683 timesteps/s, 101.701 katom-step/s
|
||||
99.8% CPU use with 1 MPI tasks x no OpenMP threads
|
||||
|
||||
MPI task timing breakdown:
|
||||
Section | min time | avg time | max time |%varavg| %total
|
||||
---------------------------------------------------------------
|
||||
Pair | 1.985 | 1.985 | 1.985 | 0.0 | 98.62
|
||||
Neigh | 0 | 0 | 0 | 0.0 | 0.00
|
||||
Comm | 0.012367 | 0.012367 | 0.012367 | 0.0 | 0.61
|
||||
Output | 0.0080612 | 0.0080612 | 0.0080612 | 0.0 | 0.40
|
||||
Modify | 0.0053111 | 0.0053111 | 0.0053111 | 0.0 | 0.26
|
||||
Other | | 0.002 | | | 0.10
|
||||
|
||||
Nlocal: 2047 ave 2047 max 2047 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
Nghost: 7790 ave 7790 max 7790 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
Neighs: 0 ave 0 max 0 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
FullNghs: 291196 ave 291196 max 291196 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
|
||||
Total # of neighbors = 291196
|
||||
Ave neighs/atom = 142.25501
|
||||
Neighbor list builds = 0
|
||||
Dangerous builds = 0
|
||||
Total wall time: 0:00:02
|
||||
@ -0,0 +1,197 @@
|
||||
LAMMPS (2 Apr 2025 - Development - )
|
||||
Reading data file ...
|
||||
orthogonal box = (0 0 0) to (28.92 28.92 28.92)
|
||||
1 by 1 by 1 MPI processor grid
|
||||
reading atoms ...
|
||||
2047 atoms
|
||||
reading velocities ...
|
||||
2047 velocities
|
||||
read_data CPU = 0.009 seconds
|
||||
ACE version: 2023.11.25
|
||||
Recursive evaluator is used by ACE
|
||||
Loading ../../../potentials/Cu-PBE-core-rep.ace
|
||||
Total number of basis functions
|
||||
Cu: 16 (r=1) 726 (r>1)
|
||||
Mapping LAMMPS atom type #1(Cu) -> ACE species type #0
|
||||
atomic load lambda:
|
||||
fast potential: extract eam/apip:time_per_atom
|
||||
precise potential: extract pace/apip:time_per_atom
|
||||
lambda_input: extract lambda/input/apip:time_per_atom
|
||||
lambda: extract lambda/zone/apip:time_per_atom
|
||||
|
||||
CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE
|
||||
|
||||
Your simulation uses code contributions which should be cited:
|
||||
- fix lambda command: doi.org/10.1063/5.0245877
|
||||
The log file lists these citations in BibTeX format.
|
||||
|
||||
CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE
|
||||
|
||||
Neighbor list info ...
|
||||
update: every = 1 steps, delay = 0 steps, check = yes
|
||||
max neighbors/atom: 2000, page size: 100000
|
||||
master list distance cutoff = 9.4
|
||||
ghost atom cutoff = 9.4
|
||||
binsize = 4.7, bins = 7 7 7
|
||||
5 neighbor lists, perpetual/occasional/extra = 5 0 0
|
||||
(1) pair eam/fs/apip, perpetual, trim from (3)
|
||||
attributes: full, newton on, cut 7.50679
|
||||
pair build: trim
|
||||
stencil: none
|
||||
bin: none
|
||||
(2) pair pace/apip, perpetual
|
||||
attributes: full, newton on, cut 9.4
|
||||
pair build: full/bin/atomonly
|
||||
stencil: full/bin/3d
|
||||
bin: standard
|
||||
(3) pair lambda/input/csp/apip, perpetual, trim from (2)
|
||||
attributes: full, newton on, cut 8
|
||||
pair build: trim
|
||||
stencil: none
|
||||
bin: none
|
||||
(4) pair lambda/zone/apip, perpetual
|
||||
attributes: full, newton on, ghost
|
||||
pair build: full/bin/ghost
|
||||
stencil: full/ghost/bin/3d
|
||||
bin: standard
|
||||
(5) fix lambda_thermostat/apip, perpetual, copy from (2)
|
||||
attributes: full, newton on
|
||||
pair build: copy
|
||||
stencil: none
|
||||
bin: none
|
||||
Setting up Verlet run ...
|
||||
Unit style : metal
|
||||
Current step : 0
|
||||
Time step : 0.001
|
||||
Per MPI rank memory allocation (min/avg/max) = 52.93 | 52.93 | 52.93 Mbytes
|
||||
Step TotEng c_lambda_types[1] c_lambda_types[2] c_lambda_types[3]
|
||||
0 -7408.7649 1993 42 12
|
||||
1 -7408.7649 1993 42 12
|
||||
2 -7408.7649 1993 42 12
|
||||
3 -7408.765 1993 42 12
|
||||
4 -7408.765 1993 42 12
|
||||
5 -7408.765 1993 42 12
|
||||
6 -7408.765 1993 42 12
|
||||
7 -7408.765 1993 42 12
|
||||
8 -7408.765 1993 42 12
|
||||
9 -7408.765 1993 42 12
|
||||
10 -7408.7651 1993 42 12
|
||||
11 -7408.7651 1993 42 12
|
||||
12 -7408.7651 1993 42 12
|
||||
13 -7408.7651 1993 42 12
|
||||
14 -7408.7651 1993 42 12
|
||||
15 -7408.7651 1993 42 12
|
||||
16 -7408.7652 1993 42 12
|
||||
17 -7408.7652 1993 42 12
|
||||
18 -7408.7652 1993 42 12
|
||||
19 -7408.7652 1993 42 12
|
||||
20 -7408.7652 1993 42 12
|
||||
21 -7408.7652 1993 42 12
|
||||
22 -7408.7652 1993 42 12
|
||||
23 -7408.7652 1993 42 12
|
||||
24 -7408.7652 1993 42 12
|
||||
25 -7408.7652 1993 42 12
|
||||
26 -7408.7652 1993 42 12
|
||||
27 -7408.7652 1993 42 12
|
||||
28 -7408.7652 1993 42 12
|
||||
29 -7408.7652 1993 42 12
|
||||
30 -7408.7652 1993 42 12
|
||||
31 -7408.7652 1993 42 12
|
||||
32 -7408.7652 1993 42 12
|
||||
33 -7408.7652 1993 42 12
|
||||
34 -7408.7652 1993 42 12
|
||||
35 -7408.7652 1993 42 12
|
||||
36 -7408.7652 1993 42 12
|
||||
37 -7408.7652 1993 42 12
|
||||
38 -7408.7652 1993 42 12
|
||||
39 -7408.7652 1993 42 12
|
||||
40 -7408.7652 1993 42 12
|
||||
41 -7408.7652 1993 42 12
|
||||
42 -7408.7652 1993 42 12
|
||||
43 -7408.7652 1993 42 12
|
||||
44 -7408.7652 1993 42 12
|
||||
45 -7408.7652 1993 42 12
|
||||
46 -7408.7652 1993 42 12
|
||||
47 -7408.7653 1993 42 12
|
||||
48 -7408.7653 1993 42 12
|
||||
49 -7408.7653 1993 42 12
|
||||
50 -7408.7653 1993 42 12
|
||||
51 -7408.7653 1993 42 12
|
||||
52 -7408.7653 1993 42 12
|
||||
53 -7408.7653 1993 42 12
|
||||
54 -7408.7653 1993 42 12
|
||||
55 -7408.7653 1993 42 12
|
||||
56 -7408.7653 1993 42 12
|
||||
57 -7408.7653 1993 42 12
|
||||
58 -7408.7653 1993 42 12
|
||||
59 -7408.7653 1993 42 12
|
||||
60 -7408.7652 1993 42 12
|
||||
61 -7408.7652 1993 42 12
|
||||
62 -7408.7652 1993 42 12
|
||||
63 -7408.7652 1993 42 12
|
||||
64 -7408.7652 1993 42 12
|
||||
65 -7408.7651 1993 42 12
|
||||
66 -7408.7651 1993 42 12
|
||||
67 -7408.7651 1993 42 12
|
||||
68 -7408.7651 1993 42 12
|
||||
69 -7408.7651 1993 42 12
|
||||
70 -7408.765 1993 42 12
|
||||
71 -7408.765 1993 42 12
|
||||
72 -7408.765 1993 42 12
|
||||
73 -7408.765 1993 42 12
|
||||
74 -7408.765 1993 42 12
|
||||
75 -7408.765 1993 42 12
|
||||
76 -7408.765 1993 42 12
|
||||
77 -7408.765 1993 42 12
|
||||
78 -7408.765 1993 42 12
|
||||
79 -7408.765 1993 42 12
|
||||
80 -7408.765 1993 42 12
|
||||
81 -7408.765 1993 42 12
|
||||
82 -7408.765 1993 42 12
|
||||
83 -7408.765 1993 42 12
|
||||
84 -7408.765 1993 42 12
|
||||
85 -7408.765 1993 42 12
|
||||
86 -7408.765 1993 42 12
|
||||
87 -7408.765 1993 42 12
|
||||
88 -7408.765 1993 42 12
|
||||
89 -7408.7651 1993 42 12
|
||||
90 -7408.7651 1993 42 12
|
||||
91 -7408.7651 1993 42 12
|
||||
92 -7408.7651 1993 42 12
|
||||
93 -7408.7651 1993 42 12
|
||||
94 -7408.7651 1993 42 12
|
||||
95 -7408.7651 1993 42 12
|
||||
96 -7408.7651 1993 42 12
|
||||
97 -7408.7651 1993 42 12
|
||||
98 -7408.7651 1993 42 12
|
||||
99 -7408.7651 1993 42 12
|
||||
100 -7408.7651 1993 42 12
|
||||
Loop time of 2.19492 on 1 procs for 100 steps with 2047 atoms
|
||||
|
||||
Performance: 3.936 ns/day, 6.097 hours/ns, 45.560 timesteps/s, 93.261 katom-step/s
|
||||
99.8% CPU use with 1 MPI tasks x no OpenMP threads
|
||||
|
||||
MPI task timing breakdown:
|
||||
Section | min time | avg time | max time |%varavg| %total
|
||||
---------------------------------------------------------------
|
||||
Pair | 2.0683 | 2.0683 | 2.0683 | 0.0 | 94.23
|
||||
Neigh | 0 | 0 | 0 | 0.0 | 0.00
|
||||
Comm | 0.012156 | 0.012156 | 0.012156 | 0.0 | 0.55
|
||||
Output | 0.0084851 | 0.0084851 | 0.0084851 | 0.0 | 0.39
|
||||
Modify | 0.10386 | 0.10386 | 0.10386 | 0.0 | 4.73
|
||||
Other | | 0.002096 | | | 0.10
|
||||
|
||||
Nlocal: 2047 ave 2047 max 2047 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
Nghost: 7790 ave 7790 max 7790 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
Neighs: 0 ave 0 max 0 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
FullNghs: 291196 ave 291196 max 291196 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
|
||||
Total # of neighbors = 291196
|
||||
Ave neighs/atom = 142.25501
|
||||
Neighbor list builds = 0
|
||||
Dangerous builds = 0
|
||||
Total wall time: 0:00:02
|
||||
201
examples/PACKAGES/apip/log.02Apr25.validate.g++.1
Normal file
201
examples/PACKAGES/apip/log.02Apr25.validate.g++.1
Normal file
@ -0,0 +1,201 @@
|
||||
LAMMPS (2 Apr 2025 - Development - )
|
||||
Reading data file ...
|
||||
orthogonal box = (0 0 0) to (7.23 7.23 7.23)
|
||||
1 by 1 by 1 MPI processor grid
|
||||
reading atoms ...
|
||||
31 atoms
|
||||
reading velocities ...
|
||||
31 velocities
|
||||
read_data CPU = 0.002 seconds
|
||||
ACE version: 2023.11.25
|
||||
Recursive evaluator is used
|
||||
Loading Cu-1.yace
|
||||
Total number of basis functions
|
||||
Cu: 15 (r=1) 9 (r>1)
|
||||
Mapping LAMMPS atom type #1(Cu) -> ACE species type #0
|
||||
Neighbor list info ...
|
||||
update: every = 1 steps, delay = 0 steps, check = yes
|
||||
max neighbors/atom: 2000, page size: 100000
|
||||
master list distance cutoff = 5.9
|
||||
ghost atom cutoff = 5.9
|
||||
binsize = 2.95, bins = 3 3 3
|
||||
1 neighbor lists, perpetual/occasional/extra = 1 0 0
|
||||
(1) pair pace, perpetual
|
||||
attributes: full, newton on
|
||||
pair build: full/bin/atomonly
|
||||
stencil: full/bin/3d
|
||||
bin: standard
|
||||
Setting up Verlet run ...
|
||||
Unit style : metal
|
||||
Current step : 0
|
||||
Time step : 0.001
|
||||
Per MPI rank memory allocation (min/avg/max) = 4.908 | 4.908 | 4.908 Mbytes
|
||||
Step PotEng Fnorm Fmax
|
||||
0 -98.699376 49.367618 19.563052
|
||||
Loop time of 6.74e-07 on 1 procs for 0 steps with 31 atoms
|
||||
|
||||
148.4% CPU use with 1 MPI tasks x no 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 | | 6.74e-07 | | |100.00
|
||||
|
||||
Nlocal: 31 ave 31 max 31 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
Nghost: 616 ave 616 max 616 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
Neighs: 0 ave 0 max 0 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
FullNghs: 2132 ave 2132 max 2132 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
|
||||
Total # of neighbors = 2132
|
||||
Ave neighs/atom = 68.774194
|
||||
Neighbor list builds = 0
|
||||
Dangerous builds = 0
|
||||
ACE version: 2023.11.25
|
||||
Recursive evaluator is used by ACE
|
||||
Loading Cu-1.yace
|
||||
Total number of basis functions
|
||||
Cu: 15 (r=1) 9 (r>1)
|
||||
Mapping LAMMPS atom type #1(Cu) -> ACE species type #0
|
||||
Setting atom values ...
|
||||
31 settings made for apip/lambda
|
||||
Neighbor list info ...
|
||||
update: every = 1 steps, delay = 0 steps, check = yes
|
||||
max neighbors/atom: 2000, page size: 100000
|
||||
master list distance cutoff = 7.50679
|
||||
ghost atom cutoff = 7.50679
|
||||
binsize = 3.753395, bins = 2 2 2
|
||||
2 neighbor lists, perpetual/occasional/extra = 2 0 0
|
||||
(1) pair eam/fs/apip, perpetual
|
||||
attributes: full, newton on, cut 7.50679
|
||||
pair build: full/bin/atomonly
|
||||
stencil: full/bin/3d
|
||||
bin: standard
|
||||
(2) pair pace/apip, perpetual, copy from (1)
|
||||
attributes: full, newton on
|
||||
pair build: copy
|
||||
stencil: none
|
||||
bin: none
|
||||
Setting up Verlet run ...
|
||||
Unit style : metal
|
||||
Current step : 0
|
||||
Time step : 0.001
|
||||
Per MPI rank memory allocation (min/avg/max) = 5.564 | 5.564 | 5.564 Mbytes
|
||||
Step PotEng Fnorm Fmax
|
||||
0 -98.699376 49.367618 19.563052
|
||||
Loop time of 5.62e-07 on 1 procs for 0 steps with 31 atoms
|
||||
|
||||
177.9% CPU use with 1 MPI tasks x no 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 | | 5.62e-07 | | |100.00
|
||||
|
||||
Nlocal: 31 ave 31 max 31 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
Nghost: 957 ave 957 max 957 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
Neighs: 0 ave 0 max 0 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
FullNghs: 4558 ave 4558 max 4558 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
|
||||
Total # of neighbors = 4558
|
||||
Ave neighs/atom = 147.03226
|
||||
Neighbor list builds = 0
|
||||
Dangerous builds = 0
|
||||
Setting atom values ...
|
||||
31 settings made for apip/lambda
|
||||
Setting up Verlet run ...
|
||||
Unit style : metal
|
||||
Current step : 0
|
||||
Time step : 0.001
|
||||
Per MPI rank memory allocation (min/avg/max) = 5.564 | 5.564 | 5.564 Mbytes
|
||||
Step PotEng Fnorm Fmax
|
||||
0 -85.025323 53.839249 22.182149
|
||||
Loop time of 5.49e-07 on 1 procs for 0 steps with 31 atoms
|
||||
|
||||
182.1% CPU use with 1 MPI tasks x no 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 | | 5.49e-07 | | |100.00
|
||||
|
||||
Nlocal: 31 ave 31 max 31 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
Nghost: 957 ave 957 max 957 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
Neighs: 0 ave 0 max 0 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
FullNghs: 4558 ave 4558 max 4558 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
|
||||
Total # of neighbors = 4558
|
||||
Ave neighs/atom = 147.03226
|
||||
Neighbor list builds = 0
|
||||
Dangerous builds = 0
|
||||
Neighbor list info ...
|
||||
update: every = 1 steps, delay = 0 steps, check = yes
|
||||
max neighbors/atom: 2000, page size: 100000
|
||||
master list distance cutoff = 7.50679
|
||||
ghost atom cutoff = 7.50679
|
||||
binsize = 3.753395, bins = 2 2 2
|
||||
1 neighbor lists, perpetual/occasional/extra = 1 0 0
|
||||
(1) pair eam/fs, perpetual
|
||||
attributes: half, newton on
|
||||
pair build: half/bin/atomonly/newton
|
||||
stencil: half/bin/3d
|
||||
bin: standard
|
||||
Setting up Verlet run ...
|
||||
Unit style : metal
|
||||
Current step : 0
|
||||
Time step : 0.001
|
||||
Per MPI rank memory allocation (min/avg/max) = 5.183 | 5.183 | 5.183 Mbytes
|
||||
Step PotEng Fnorm Fmax
|
||||
0 -85.025323 53.839249 22.182149
|
||||
Loop time of 4.77e-07 on 1 procs for 0 steps with 31 atoms
|
||||
|
||||
0.0% CPU use with 1 MPI tasks x no 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 | | 4.77e-07 | | |100.00
|
||||
|
||||
Nlocal: 31 ave 31 max 31 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
Nghost: 957 ave 957 max 957 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
Neighs: 2279 ave 2279 max 2279 min
|
||||
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||
|
||||
Total # of neighbors = 2279
|
||||
Ave neighs/atom = 73.516129
|
||||
Neighbor list builds = 0
|
||||
Dangerous builds = 0
|
||||
Total wall time: 0:00:00
|
||||
26
src/.gitignore
vendored
26
src/.gitignore
vendored
@ -109,6 +109,32 @@
|
||||
/pair_pace_extrapolation.cpp
|
||||
/pair_pace_extrapolation.h
|
||||
|
||||
/atom_vec_apip.cpp
|
||||
/atom_vec_apip.h
|
||||
/fix_lambda_apip.cpp
|
||||
/fix_lambda_apip.h
|
||||
/fix_lambda_thermostat_apip.cpp
|
||||
/fix_lambda_thermostat_apip.h
|
||||
/pair_lambda_input_apip.cpp
|
||||
/pair_lambda_input_apip.h
|
||||
/pair_lambda_input_csp_apip.cpp
|
||||
/pair_lambda_input_csp_apip.h
|
||||
/pair_eam_fs_apip.cpp
|
||||
/pair_eam_fs_apip.h
|
||||
/pair_eam_apip.cpp
|
||||
/pair_eam_apip.h
|
||||
/pair_lambda_zone_apip.cpp
|
||||
/pair_lambda_zone_apip.h
|
||||
/pair_pace_apip.cpp
|
||||
/pair_pace_apip.h
|
||||
/pair_pace_precise_apip.cpp
|
||||
/pair_pace_precise_apip.h
|
||||
/pair_pace_fast_apip.cpp
|
||||
/pair_pace_fast_apip.h
|
||||
/fix_atom_weight_apip.cpp
|
||||
/fix_atom_weight_apip.h
|
||||
|
||||
|
||||
/pair_pod.cpp
|
||||
/pair_pod.h
|
||||
/eapod.cpp
|
||||
|
||||
40
src/APIP/Install.sh
Normal file
40
src/APIP/Install.sh
Normal file
@ -0,0 +1,40 @@
|
||||
# Install/unInstall package files in LAMMPS
|
||||
# mode = 0/1/2 for uninstall/install/update
|
||||
|
||||
mode=$1
|
||||
|
||||
# enforce using portable C locale
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
# arg1 = file, arg2 = file it depends on
|
||||
|
||||
action () {
|
||||
if (test $mode = 0) then
|
||||
rm -f ../$1
|
||||
elif (! cmp -s $1 ../$1) then
|
||||
if (test -z "$2" || test -e ../$2) then
|
||||
cp $1 ..
|
||||
if (test $mode = 2) then
|
||||
echo " updating src/$1"
|
||||
fi
|
||||
fi
|
||||
elif (test -n "$2") then
|
||||
if (test ! -e ../$2) then
|
||||
rm -f ../$1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# some styles in APIP have depend on the ML-PACE package
|
||||
|
||||
if (test $1 = 1) then
|
||||
if (test ! -e ../pair_pace.cpp) then
|
||||
echo "Must install ML-PACE package with APIP package"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
for file in *.cpp *.h; do
|
||||
action ${file}
|
||||
done
|
||||
8
src/APIP/README
Normal file
8
src/APIP/README
Normal file
@ -0,0 +1,8 @@
|
||||
The APIP package is based on the paper:
|
||||
|
||||
David Immel, Ralf Drautz, Godehard Sutmann; Adaptive-precision potentials for large-scale atomistic simulations. J. Chem. Phys. 14 March 2025; 162 (11): 114119. https://doi.org/10.1063/5.0245877
|
||||
|
||||
Example of how to use an adaptive-precision potential is provided in examples/PACKAGES/APIP .
|
||||
|
||||
The pair_style pace/apip requires the installation of lib/pace of the ML-PACE package.
|
||||
The installation of lib/pace is described in src/ML-PACE/README .
|
||||
124
src/APIP/atom_vec_apip.cpp
Normal file
124
src/APIP/atom_vec_apip.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
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 "atom_vec_apip.h"
|
||||
|
||||
#include "atom.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AtomVecApip::AtomVecApip(LAMMPS *lmp) : AtomVec(lmp)
|
||||
{
|
||||
molecular = Atom::ATOMIC;
|
||||
mass_type = PER_TYPE;
|
||||
forceclearflag = 1;
|
||||
|
||||
double *apip_lambda, *apip_lambda_input, *apip_lambda_input_ta, *apip_lambda_const, *apip_e_fast,
|
||||
*apip_e_precise, **apip_f_const_lambda, **apip_f_dyn_lambda;
|
||||
int *apip_lambda_required;
|
||||
atom->apip_lambda_flag = 1;
|
||||
atom->apip_lambda_input_flag = 1;
|
||||
atom->apip_lambda_input_ta_flag = 1;
|
||||
atom->apip_lambda_const_flag = 1;
|
||||
atom->apip_lambda_required_flag = 1;
|
||||
atom->apip_e_fast_flag = 1;
|
||||
atom->apip_e_precise_flag = 1;
|
||||
atom->apip_f_const_lambda_flag = 1;
|
||||
atom->apip_f_dyn_lambda_flag = 1;
|
||||
|
||||
// strings with peratom variables to include in each AtomVec method
|
||||
// strings cannot contain fields in corresponding AtomVec default strings
|
||||
// order of fields in a string does not matter
|
||||
// except: fields_data_atom & fields_data_vel must match data file
|
||||
|
||||
// The full list of fields is in atom_vec.cpp
|
||||
fields_copy = {"apip_lambda", "apip_lambda_required", "apip_lambda_input", "apip_lambda_input_ta",
|
||||
"apip_lambda_const"};
|
||||
fields_comm = {"apip_lambda", "apip_lambda_required", "apip_lambda_input_ta",
|
||||
"apip_lambda_const"};
|
||||
fields_comm_vel = {};
|
||||
fields_border = {"apip_lambda", "apip_lambda_required", "apip_lambda_input_ta",
|
||||
"apip_lambda_const"};
|
||||
fields_border_vel = {};
|
||||
fields_exchange = {"apip_lambda", "apip_lambda_required", "apip_lambda_input_ta",
|
||||
"apip_lambda_const"};
|
||||
fields_restart = {"apip_lambda", "apip_lambda_required", "apip_lambda_input",
|
||||
"apip_lambda_input_ta", "apip_lambda_const"};
|
||||
fields_create = {};
|
||||
fields_grow = {
|
||||
"apip_lambda", "apip_lambda_required", "apip_lambda_input",
|
||||
"apip_lambda_input_ta", "apip_lambda_const", "apip_e_fast",
|
||||
"apip_e_precise", "apip_f_const_lambda", "apip_f_dyn_lambda"}; // allocates memory
|
||||
fields_reverse = {"apip_f_const_lambda",
|
||||
"apip_f_dyn_lambda"}; // communication of force after calculation
|
||||
fields_data_atom = {"id", "type", "x"};
|
||||
fields_data_vel = {"id", "v"};
|
||||
|
||||
setup_fields();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set local copies of all grow ptrs used by this class, except defaults
|
||||
needed in replicate when 2 atom classes exist and it calls pack_restart()
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AtomVecApip::grow_pointers()
|
||||
{
|
||||
apip_lambda = atom->apip_lambda;
|
||||
apip_lambda_required = atom->apip_lambda_required;
|
||||
apip_lambda_input = atom->apip_lambda_input;
|
||||
apip_lambda_input_ta = atom->apip_lambda_input_ta;
|
||||
apip_lambda_const = atom->apip_lambda_const;
|
||||
apip_e_fast = atom->apip_e_fast;
|
||||
apip_e_precise = atom->apip_e_precise;
|
||||
apip_f_const_lambda = atom->apip_f_const_lambda;
|
||||
apip_f_dyn_lambda = atom->apip_f_dyn_lambda;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
modify what AtomVec::data_atom() just unpacked
|
||||
or initialize other atom quantities
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AtomVecApip::data_atom_post(int ilocal)
|
||||
{
|
||||
apip_lambda[ilocal] = 0;
|
||||
apip_lambda_const[ilocal] = 0;
|
||||
apip_lambda_required[ilocal] = ApipLambdaRequired::UNKNOWN;
|
||||
apip_lambda_input[ilocal] = 0;
|
||||
apip_lambda_input_ta[ilocal] = 0;
|
||||
apip_e_fast[ilocal] = 0;
|
||||
apip_e_precise[ilocal] = 0;
|
||||
apip_f_const_lambda[ilocal][0] = 0;
|
||||
apip_f_const_lambda[ilocal][1] = 0;
|
||||
apip_f_const_lambda[ilocal][2] = 0;
|
||||
apip_f_dyn_lambda[ilocal][0] = 0;
|
||||
apip_f_dyn_lambda[ilocal][1] = 0;
|
||||
apip_f_dyn_lambda[ilocal][2] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
clear extra forces starting at atom n
|
||||
natoms = # of atoms to clear
|
||||
nbytes = natoms * sizeof(double)
|
||||
requires forceclearflag = 1 to be called
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AtomVecApip::force_clear(int n, size_t nbytes)
|
||||
{
|
||||
memset(&apip_f_const_lambda[n][0], 0, 3 * nbytes);
|
||||
memset(&apip_f_dyn_lambda[n][0], 0, 3 * nbytes);
|
||||
memset(&apip_lambda_required[n], 0, nbytes / sizeof(double) * sizeof(int));
|
||||
}
|
||||
59
src/APIP/atom_vec_apip.h
Normal file
59
src/APIP/atom_vec_apip.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* -*- 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 ATOM_CLASS
|
||||
// clang-format off
|
||||
AtomStyle(apip,AtomVecApip);
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
#ifndef LMP_ATOM_VEC_APIP_H
|
||||
#define LMP_ATOM_VEC_APIP_H
|
||||
|
||||
#include "atom_vec.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class AtomVecApip : public AtomVec {
|
||||
public:
|
||||
AtomVecApip(class LAMMPS *);
|
||||
|
||||
void grow_pointers();
|
||||
|
||||
void force_clear(int, size_t) override;
|
||||
void data_atom_post(int) override;
|
||||
|
||||
protected:
|
||||
double *apip_lambda, *apip_lambda_input, *apip_lambda_const, *apip_lambda_input_ta, *apip_e_fast,
|
||||
*apip_e_precise, **apip_f_const_lambda, **apip_f_dyn_lambda;
|
||||
int *apip_lambda_required;
|
||||
};
|
||||
|
||||
#ifndef LMP_ATOM_APIP_LAMBDA_REQUIRED
|
||||
#define LMP_ATOM_APIP_LAMBDA_REQUIRED
|
||||
namespace ApipLambdaRequired {
|
||||
|
||||
enum {
|
||||
UNKNOWN = 0,
|
||||
SIMPLE = 1 << 0,
|
||||
NO_SIMPLE = 1 << 1,
|
||||
COMPLEX = 1 << 2,
|
||||
NO_COMPLEX = 1 << 3,
|
||||
};
|
||||
} // namespace ApipLambdaRequired
|
||||
#endif
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
554
src/APIP/fix_atom_weight_apip.cpp
Normal file
554
src/APIP/fix_atom_weight_apip.cpp
Normal file
@ -0,0 +1,554 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
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: David Immel (d.immel@fz-juelich.de, FZJ, Germany)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "fix_atom_weight_apip.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "atom_vec_apip.h"
|
||||
#include "comm.h"
|
||||
#include "error.h"
|
||||
#include "fix_store_atom.h"
|
||||
#include "force.h"
|
||||
#include "group.h"
|
||||
#include "modify.h"
|
||||
#include "pair.h"
|
||||
#include "timer.h"
|
||||
#include "update.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace FixConst;
|
||||
|
||||
FixAtomWeightAPIP::FixAtomWeightAPIP(LAMMPS *lmp, int narg, char **arg) :
|
||||
Fix(lmp, narg, arg), fixstore(nullptr), time_simple_extract_name(nullptr),
|
||||
time_complex_extract_name(nullptr), time_lambda_extract_name(nullptr),
|
||||
time_group_extract_name(nullptr), time_group_name(nullptr), fix_lambda(nullptr),
|
||||
ap_timer(nullptr)
|
||||
{
|
||||
if (narg < 9) error->all(FLERR, "Illegal fix balance command");
|
||||
|
||||
ap_timer = new APIPtimer(lmp);
|
||||
|
||||
// set defaults
|
||||
time_simple_atom = time_complex_atom = time_group_atom = time_lambda_atom = -1;
|
||||
n_simple = n_complex = n_group = n_lambda = 0;
|
||||
nevery = -1;
|
||||
rescale_work = true;
|
||||
|
||||
peratom_flag = 1;
|
||||
size_peratom_cols = 0; // vector
|
||||
|
||||
time_group_i = -1;
|
||||
time_group_bit = 0;
|
||||
|
||||
vector_flag = 1;
|
||||
size_vector = 4;
|
||||
extvector = 0;
|
||||
|
||||
for (int i = 0; i < size_vector; i++) avg_time_atom[i] = 0;
|
||||
|
||||
nevery = utils::inumeric(FLERR, arg[3], false, lmp);
|
||||
|
||||
if (strcmp(arg[4], "eam") == 0) {
|
||||
time_simple_extract_name = utils::strdup("eam/apip:time_per_atom");
|
||||
} else if (strcmp(arg[4], "ace") == 0) {
|
||||
time_simple_extract_name = utils::strdup("pace/fast/apip:time_per_atom");
|
||||
} else {
|
||||
time_simple_atom = utils::numeric(FLERR, arg[4], false, lmp);
|
||||
avg_time_atom[0] = time_simple_atom;
|
||||
}
|
||||
|
||||
if (strcmp(arg[5], "ace") == 0) {
|
||||
time_complex_extract_name = utils::strdup("pace/apip:time_per_atom");
|
||||
} else {
|
||||
time_complex_atom = utils::numeric(FLERR, arg[5], false, lmp);
|
||||
avg_time_atom[1] = time_complex_atom;
|
||||
}
|
||||
|
||||
if (strcmp(arg[6], "lambda/input") == 0) {
|
||||
time_group_extract_name = utils::strdup("lambda/input/apip:time_per_atom");
|
||||
} else {
|
||||
time_group_atom = utils::numeric(FLERR, arg[6], false, lmp);
|
||||
avg_time_atom[2] = time_group_atom;
|
||||
}
|
||||
|
||||
if (strcmp(arg[7], "lambda/zone") == 0) {
|
||||
time_lambda_extract_name = utils::strdup("lambda/zone/apip:time_per_atom");
|
||||
} else {
|
||||
time_lambda_atom = utils::numeric(FLERR, arg[7], false, lmp);
|
||||
avg_time_atom[3] = time_lambda_atom;
|
||||
}
|
||||
|
||||
// read name of group
|
||||
time_group_name = utils::strdup(arg[8]);
|
||||
time_group_i = group->find(time_group_name);
|
||||
if (time_group_i == -1)
|
||||
error->all(FLERR, "atom_weight/apip: group {} does not exist", time_group_name);
|
||||
time_group_bit = group->bitmask[time_group_i];
|
||||
|
||||
// parse remaining arguments
|
||||
for (int iarg = 9; iarg < narg; iarg++) {
|
||||
if (strcmp(arg[iarg], "no_rescale") == 0) {
|
||||
rescale_work = false;
|
||||
} else {
|
||||
error->all(FLERR, "atom_weight/apip: unknown argument {}", arg[iarg]);
|
||||
}
|
||||
}
|
||||
|
||||
// check arguments
|
||||
if (nevery < 1) error->all(FLERR, "atom_weight/apip: nevery > 0 required");
|
||||
if (!atom->apip_lambda_required_flag)
|
||||
error->all(FLERR, "atom_weight/apip: atomic style with lambda_required required");
|
||||
|
||||
if (time_simple_extract_name || time_complex_extract_name || time_group_extract_name ||
|
||||
time_lambda_extract_name) {
|
||||
if (force->pair == nullptr)
|
||||
error->all(FLERR, "atom_weight/apip: extract requires a defined pair style");
|
||||
}
|
||||
|
||||
int useless_dim = -1;
|
||||
void *extracted_ptr = nullptr;
|
||||
|
||||
if (time_simple_extract_name) {
|
||||
if (force->pair->extract(time_simple_extract_name, useless_dim) == nullptr)
|
||||
error->all(FLERR, "atom_weight/apip: simple time cannot be extracted with {} from {}",
|
||||
time_simple_extract_name, force->pair_style);
|
||||
} else {
|
||||
if (time_simple_atom < 0)
|
||||
error->all(FLERR, "atom_weight/apip: time_simple_atom needs to be non-negative instead of {}",
|
||||
time_simple_atom);
|
||||
}
|
||||
|
||||
if (time_complex_extract_name) {
|
||||
if (force->pair->extract(time_complex_extract_name, useless_dim) == nullptr)
|
||||
error->all(FLERR, "atom_weight/apip: complex time cannot be extracted with {} from {}",
|
||||
time_complex_extract_name, force->pair_style);
|
||||
} else {
|
||||
if (time_complex_atom < 0)
|
||||
error->all(FLERR,
|
||||
"atom_weight/apip: time_complex_atom needs to be non-negative instead of {}",
|
||||
time_complex_atom);
|
||||
}
|
||||
|
||||
if (time_group_extract_name) {
|
||||
if (force->pair->extract(time_group_extract_name, useless_dim) == nullptr)
|
||||
error->all(FLERR, "atom_weight/apip: group time cannot be extracted with {} from {}",
|
||||
time_group_extract_name, force->pair_style);
|
||||
} else {
|
||||
if (time_group_atom < 0)
|
||||
error->all(FLERR, "atom_weight/apip: time_group_atom needs to be non-negative instead of {}",
|
||||
time_group_atom);
|
||||
}
|
||||
|
||||
if (time_lambda_extract_name) {
|
||||
if (force->pair->extract(time_lambda_extract_name, useless_dim) == nullptr)
|
||||
error->all(FLERR, "atom_weight/apip: lambda time cannot be extracted with {} from {}",
|
||||
time_lambda_extract_name, force->pair_style);
|
||||
} else {
|
||||
if (time_lambda_atom < 0)
|
||||
error->all(FLERR, "atom_weight/apip: time_lambda_atom needs to be non-negative instead of {}",
|
||||
time_lambda_atom);
|
||||
}
|
||||
|
||||
if (comm->me == 0) {
|
||||
utils::logmesg(lmp, "atomic load lambda:\n");
|
||||
if (time_simple_extract_name)
|
||||
utils::logmesg(lmp, "\tfast potential: extract {}\n", time_simple_extract_name);
|
||||
else
|
||||
utils::logmesg(lmp, "\tfast potential: const {}\n", time_simple_atom);
|
||||
if (time_complex_extract_name)
|
||||
utils::logmesg(lmp, "\tprecise potential: extract {}\n", time_complex_extract_name);
|
||||
else
|
||||
utils::logmesg(lmp, "\tprecise potential: const {}\n", time_complex_atom);
|
||||
if (time_group_extract_name)
|
||||
utils::logmesg(lmp, "\tlambda_input: extract {}\n", time_group_extract_name);
|
||||
else
|
||||
utils::logmesg(lmp, "\tlambda_input: const {}\n", time_group_atom);
|
||||
if (time_lambda_extract_name)
|
||||
utils::logmesg(lmp, "\tlambda: extract {}\n", time_lambda_extract_name);
|
||||
else
|
||||
utils::logmesg(lmp, "\tlambda: const {}\n", time_lambda_atom);
|
||||
}
|
||||
|
||||
global_freq = nevery;
|
||||
peratom_freq = nevery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deconstructor. Delete allocated memory.
|
||||
*/
|
||||
|
||||
FixAtomWeightAPIP::~FixAtomWeightAPIP()
|
||||
{
|
||||
delete ap_timer;
|
||||
delete[] time_simple_extract_name;
|
||||
delete[] time_complex_extract_name;
|
||||
delete[] time_lambda_extract_name;
|
||||
delete[] time_group_extract_name;
|
||||
delete[] time_group_name;
|
||||
|
||||
// check nfix in case all fixes have already been deleted
|
||||
if (fixstore && modify->nfix) modify->delete_fix(fixstore->id);
|
||||
fixstore = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* allocate per-particle weight storage via FixStoreAtom
|
||||
* fix could already be allocated if fix balance is re-specified
|
||||
*/
|
||||
|
||||
void FixAtomWeightAPIP::post_constructor()
|
||||
{
|
||||
std::string cmd;
|
||||
cmd = id;
|
||||
cmd += "LAMBDA_WEIGHT";
|
||||
fixstore = dynamic_cast<FixStoreAtom *>(modify->get_fix_by_id(cmd));
|
||||
if (!fixstore)
|
||||
fixstore = dynamic_cast<FixStoreAtom *>(modify->add_fix(cmd + " all STORE/ATOM 1 0 0 1"));
|
||||
|
||||
// do not carry weights with atoms during normal atom migration
|
||||
fixstore->disable = 1;
|
||||
vector_atom = fixstore->vstore;
|
||||
}
|
||||
|
||||
/**
|
||||
* For lammps.
|
||||
* @return mask
|
||||
*/
|
||||
|
||||
int FixAtomWeightAPIP::setmask()
|
||||
{
|
||||
int mask = 0;
|
||||
mask |= PRE_EXCHANGE;
|
||||
mask |= PRE_FORCE; // for setup_pre_force only
|
||||
mask |= END_OF_STEP;
|
||||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise calculated variables and setup timer objects.
|
||||
*/
|
||||
|
||||
void FixAtomWeightAPIP::init()
|
||||
{
|
||||
int counter = 0;
|
||||
for (int i = 0; i < modify->nfix; i++) {
|
||||
if (strcmp(modify->fix[i]->style, "atom_weight/apip") == 0) counter++;
|
||||
}
|
||||
if (counter > 1) error->all(FLERR, "More than one atom_weight/apip fix");
|
||||
|
||||
// get ptr to fix lambda
|
||||
counter = 0;
|
||||
for (int i = 0; i < modify->nfix; i++) {
|
||||
if (strcmp(modify->fix[i]->style, "lambda/apip") == 0) {
|
||||
fix_lambda = modify->fix[i];
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
if (counter > 1) error->all(FLERR, "More than one fix lambda");
|
||||
if (counter == 0 && (time_lambda_extract_name || time_lambda_atom > 0))
|
||||
error->all(FLERR, "fix lambda required to approximate weight of pair style lambda/zone");
|
||||
|
||||
// This fix is evaluated in pre_exchange, but needs to be evaluated before load-balancing fixes.
|
||||
for (auto ifix : modify->get_fix_list()) {
|
||||
if (strcmp(id, ifix->id) == 0) {
|
||||
// The remaining fixes are called after fix atom_load_lambda and ,thus, are not of interest.
|
||||
break;
|
||||
} else if (ifix->box_change == BOX_CHANGE_DOMAIN) {
|
||||
error->all(FLERR, "atom_weight/apip: fix {} should come after fix {}", ifix->id, id);
|
||||
}
|
||||
}
|
||||
|
||||
// check that group for time_group has not been deleted
|
||||
if (time_group_name) {
|
||||
time_group_i = group->find(time_group_name);
|
||||
if (time_group_i == -1)
|
||||
error->all(FLERR, "atom_weight/apip: group {} does not exist", time_group_name);
|
||||
time_group_bit = group->bitmask[time_group_i];
|
||||
}
|
||||
|
||||
ap_timer->init();
|
||||
|
||||
last_calc = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set 1 as initial weight as no forces have been calculated yet.
|
||||
*/
|
||||
|
||||
void FixAtomWeightAPIP::setup_pre_exchange()
|
||||
{
|
||||
// fix balance rebalances in setup_pre_exchange.
|
||||
// setup_pre_exchange is called prior to force-calculations.
|
||||
// Thus, there are no measured times yet.
|
||||
// Fix balance with weight time 1.0 uses 1.0 as weight for each atom.
|
||||
int i, nlocal;
|
||||
double *weight;
|
||||
|
||||
nlocal = atom->nlocal;
|
||||
|
||||
weight = fixstore->vstore;
|
||||
for (i = 0; i < nlocal; i++) weight[i] = 1;
|
||||
|
||||
// store pointer to weight for lammps
|
||||
vector_atom = fixstore->vstore;
|
||||
// fix balance can move particles and the weight information is required
|
||||
// at the end of the step for the dump output.
|
||||
// Thus, weights need to migrate with atoms.
|
||||
fixstore->disable = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initial atom migration is done.
|
||||
* The atoms do not need to migrate with atoms any more.
|
||||
*/
|
||||
|
||||
void FixAtomWeightAPIP::setup_pre_force(int /*vflag*/)
|
||||
{
|
||||
fixstore->disable = 1;
|
||||
// Atoms are with their weights now.
|
||||
// -> update vector_atom
|
||||
vector_atom = fixstore->vstore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute weight of particles for load balancing.
|
||||
*/
|
||||
|
||||
void FixAtomWeightAPIP::pre_exchange()
|
||||
{
|
||||
if (update->ntimestep % peratom_freq != 0) { return; }
|
||||
|
||||
calc_work_per_particle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update output pointer for output.
|
||||
*/
|
||||
|
||||
void FixAtomWeightAPIP::end_of_step()
|
||||
{
|
||||
if (update->ntimestep % peratom_freq != 0) { return; }
|
||||
|
||||
// The work is not calculated twice.
|
||||
// Call a second time as pre_exchange is not called when there is no exchange.
|
||||
calc_work_per_particle();
|
||||
|
||||
// weights should not migrate with atoms
|
||||
fixstore->disable = 1;
|
||||
vector_atom = fixstore->vstore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the work for a simple/complex atom.
|
||||
* Times and number of atoms are extracted from pair styles.
|
||||
* @note updates particle number and time variables of this class.
|
||||
*/
|
||||
|
||||
void FixAtomWeightAPIP::calc_work_per_particle()
|
||||
{
|
||||
// calculating twice would destroy time measurements
|
||||
if (update->ntimestep == last_calc) { return; }
|
||||
last_calc = update->ntimestep;
|
||||
|
||||
char *extract_name[4] = {time_simple_extract_name, time_complex_extract_name,
|
||||
time_group_extract_name, time_lambda_extract_name};
|
||||
double *time_pa_ptr[4] = {&time_simple_atom, &time_complex_atom, &time_group_atom,
|
||||
&time_lambda_atom};
|
||||
|
||||
double buffer[8];
|
||||
int useless_dim = -1;
|
||||
|
||||
// extract times per atom from pair styles if required
|
||||
|
||||
int counter = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (extract_name[i]) {
|
||||
// get time per atom
|
||||
*(time_pa_ptr[i]) = *((double *) force->pair->extract(extract_name[i], useless_dim));
|
||||
// save time per atom to buffer
|
||||
if (*(time_pa_ptr[i]) < 0) {
|
||||
// no calculations
|
||||
buffer[counter] = buffer[counter + 1] = 0;
|
||||
} else {
|
||||
// save time per calculation
|
||||
buffer[counter] = *(time_pa_ptr[i]);
|
||||
buffer[counter + 1] = 1;
|
||||
}
|
||||
counter += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (counter) {
|
||||
// do not use averaged values for all processors since they depend on the number of neighbours
|
||||
// (which can vary, e.g. at a surface
|
||||
// -> only use global value if there is no local one
|
||||
|
||||
MPI_Allreduce(MPI_IN_PLACE, buffer, counter, MPI_DOUBLE, MPI_SUM, world);
|
||||
|
||||
for (int i = 3; i >= 0; i--) {
|
||||
if (extract_name[i]) {
|
||||
// calculate average over all processors
|
||||
avg_time_atom[i] = buffer[counter - 1] > 0 ? buffer[counter - 2] / buffer[counter - 1] : 0;
|
||||
// use average if there is no local value
|
||||
if (*(time_pa_ptr[i]) < 0) *(time_pa_ptr[i]) = avg_time_atom[i];
|
||||
counter -= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//set weight for each particle
|
||||
|
||||
double work_atom, *weight, **lambda_input_history;
|
||||
int dim, *mask, *lambda_required;
|
||||
|
||||
weight = fixstore->vstore;
|
||||
mask = atom->mask;
|
||||
lambda_required = atom->apip_lambda_required;
|
||||
|
||||
int nlocal = atom->nlocal;
|
||||
// assume a homogeneous time per simple and complex particle
|
||||
n_simple = n_complex = 0;
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
work_atom = 0;
|
||||
if (lambda_required[i] & ApipLambdaRequired::SIMPLE) {
|
||||
work_atom += time_simple_atom;
|
||||
n_simple++;
|
||||
}
|
||||
if (lambda_required[i] & ApipLambdaRequired::COMPLEX) {
|
||||
work_atom += time_complex_atom;
|
||||
n_complex++;
|
||||
}
|
||||
weight[i] = work_atom;
|
||||
}
|
||||
|
||||
n_group = 0;
|
||||
if (time_group_atom > 0) {
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (mask[i] & time_group_bit) {
|
||||
weight[i] += time_group_atom;
|
||||
n_group++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
n_lambda = 0;
|
||||
if (time_lambda_atom > 0) {
|
||||
// get lambda(time averaged lambda input)
|
||||
lambda_input_history = (double **) fix_lambda->extract("fix_lambda:lambda_input_history", dim);
|
||||
const int histlen_lambda_input =
|
||||
*((int *) fix_lambda->extract("fix_lambda:lambda_input_history_len", dim));
|
||||
if (lambda_input_history == nullptr || histlen_lambda_input < 1)
|
||||
error->all(FLERR, "atom_weight/apip: extracting fix_lambda:lambda_input_history failed");
|
||||
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (lambda_input_history[i][histlen_lambda_input + 1] != 1) {
|
||||
weight[i] += time_lambda_atom;
|
||||
n_lambda++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rescale_work) {
|
||||
// calculate sum of vector work
|
||||
double work_atoms = 0;
|
||||
for (int i = 0; i < nlocal; i++) work_atoms += weight[i];
|
||||
// calculate rescale factor
|
||||
double rescale_factor = ap_timer->get_work() / work_atoms;
|
||||
// apply rescale factor
|
||||
for (int i = 0; i < nlocal; i++) weight[i] *= rescale_factor;
|
||||
}
|
||||
|
||||
// store pointer to weight for lammps
|
||||
vector_atom = fixstore->vstore;
|
||||
// weights need to migrate with atoms
|
||||
fixstore->disable = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide average compute times for the output.
|
||||
* 1st: time per simple atom
|
||||
* 2nd: time per complex atom
|
||||
* 3rd: time per lambda_input calculation
|
||||
* 4th: time per lambda calculation
|
||||
*/
|
||||
|
||||
double FixAtomWeightAPIP::compute_vector(int i)
|
||||
{
|
||||
if (i < size_vector) return avg_time_atom[i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set everything to zero.
|
||||
* @param[in] lmp lammps to get the Pointers class
|
||||
*/
|
||||
|
||||
APIPtimer::APIPtimer(LAMMPS *lmp) : Pointers(lmp)
|
||||
{
|
||||
for (int i = 0; i < 4; i++) {
|
||||
time[i] = 0;
|
||||
time_interval[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset times to zero.
|
||||
*/
|
||||
|
||||
void APIPtimer::init()
|
||||
{
|
||||
// do not use set_time();
|
||||
// lammps resets the timers to zero, but the timers are not zero at timer initialisation time
|
||||
for (int i = 0; i < 4; i++) {
|
||||
time[i] = 0;
|
||||
time_interval[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save values of lammps timers.
|
||||
* @note sets time
|
||||
*/
|
||||
|
||||
void APIPtimer::set_time()
|
||||
{
|
||||
time[0] = timer->get_wall(Timer::PAIR);
|
||||
time[1] = timer->get_wall(Timer::NEIGH);
|
||||
time[2] = timer->get_wall(Timer::BOND);
|
||||
time[3] = timer->get_wall(Timer::KSPACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get time work since last call.
|
||||
* @note sets time and time_interval
|
||||
* @return work
|
||||
*/
|
||||
|
||||
double APIPtimer::get_work()
|
||||
{
|
||||
double work = 0;
|
||||
// store old times
|
||||
for (int i = 0; i < 4; i++) time_interval[i] = -time[i];
|
||||
set_time();
|
||||
// calculate differences to new times
|
||||
for (int i = 0; i < 4; i++) {
|
||||
time_interval[i] += time[i];
|
||||
work += time_interval[i];
|
||||
}
|
||||
// add constant time to prevent balancing with numerically zero
|
||||
// e.g. (for few atoms per processor and balancing every step)
|
||||
return work + 0.1;
|
||||
}
|
||||
106
src/APIP/fix_atom_weight_apip.h
Normal file
106
src/APIP/fix_atom_weight_apip.h
Normal file
@ -0,0 +1,106 @@
|
||||
/* -*- 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 author: David Immel (d.immel@fz-juelich.de, FZJ, Germany)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef FIX_CLASS
|
||||
// clang-format off
|
||||
FixStyle(atom_weight/apip,FixAtomWeightAPIP);
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
#ifndef LMP_FIX_ATOM_WEIGHT_APIP_H
|
||||
#define LMP_FIX_ATOM_WEIGHT_APIP_H
|
||||
|
||||
#include "fix.h"
|
||||
#include "pointers.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
/**
|
||||
* Small wrapper for the lammps timers to get time intervals.
|
||||
*/
|
||||
|
||||
class APIPtimer : protected Pointers {
|
||||
public:
|
||||
APIPtimer(class LAMMPS *);
|
||||
void init();
|
||||
double get_work();
|
||||
|
||||
private:
|
||||
double time[4]; ///< value of lammps timers
|
||||
double time_interval[4]; ///< time interval between two calls
|
||||
|
||||
void set_time();
|
||||
};
|
||||
|
||||
/**
|
||||
* Fix to compute an atomic wegiht that can be used to load-balance an adaptive-precision potential.
|
||||
*/
|
||||
|
||||
class FixAtomWeightAPIP : public Fix {
|
||||
public:
|
||||
FixAtomWeightAPIP(class LAMMPS *, int, char **);
|
||||
~FixAtomWeightAPIP() override;
|
||||
int setmask() override;
|
||||
void post_constructor() override;
|
||||
void init() override;
|
||||
void end_of_step() override;
|
||||
void pre_exchange() override;
|
||||
void setup_pre_exchange() override;
|
||||
void setup_pre_force(int) override;
|
||||
double compute_vector(int) override;
|
||||
|
||||
private:
|
||||
bigint last_calc; ///< last timestep in which weights were calculated
|
||||
|
||||
// user set variables
|
||||
|
||||
// clang-format off
|
||||
bool rescale_work; ///< rescale total work of all atoms according to our model to the measured total work
|
||||
char * time_simple_extract_name; ///< argument for pair->extract to get the simple per_atom_time
|
||||
char * time_complex_extract_name; ///< argument for pair->extract to get the complex per_atom_time
|
||||
char * time_group_extract_name; ///< argument for pair->extract to get the time independent of lambda
|
||||
char * time_lambda_extract_name; ///< argument for pair->extract to get the time for lambda max calculation
|
||||
char * time_group_name; ///< name of group corresponding to time_group_extract_name
|
||||
int time_group_i; ///< id of group corresponding to time_group_extract_name
|
||||
int time_group_bit; ///< groupbit corresponding to time_group_extract_name
|
||||
// clang-format on
|
||||
|
||||
// calculated variables
|
||||
|
||||
double time_simple_atom; ///< time per particle of simple pair style
|
||||
double time_complex_atom; ///< time per particle of precise pair style
|
||||
double time_group_atom; ///< time per particle independent of lambda
|
||||
double time_lambda_atom; ///< time per atom with non-simple lambda_own
|
||||
int n_simple; ///< number of simple particles before load balancing z
|
||||
int n_complex; ///< number of complex particles before load balancing z
|
||||
int n_group; ///< number of group particles before load balancing z
|
||||
int n_lambda; ///< numebr of own_complex particles before load balancing z
|
||||
|
||||
double avg_time_atom[4]; ///< global average of per atom times per type
|
||||
|
||||
// class pointers
|
||||
|
||||
class FixStoreAtom *fixstore; ///< per-atom weights are stored in FixStore
|
||||
class APIPtimer *ap_timer; ///< wrapper for lammps timers
|
||||
class Fix *fix_lambda; ///< ptr to fix_lambda to extract information
|
||||
|
||||
void calc_work_per_particle();
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
784
src/APIP/fix_lambda_apip.cpp
Normal file
784
src/APIP/fix_lambda_apip.cpp
Normal file
@ -0,0 +1,784 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
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: David Immel (d.immel@fz-juelich.de, FZJ, Germany)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "fix_lambda_apip.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "citeme.h"
|
||||
#include "comm.h"
|
||||
#include "error.h"
|
||||
#include "fix_store_atom.h"
|
||||
#include "force.h"
|
||||
#include "group.h"
|
||||
#include "memory.h"
|
||||
#include "modify.h"
|
||||
#include "pair.h"
|
||||
#include "update.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace FixConst;
|
||||
|
||||
static const char cite_fix_lambda_c[] =
|
||||
"fix lambda command: doi.org/10.1063/5.0245877\n\n"
|
||||
"@Article{Immel25,\n"
|
||||
" author = {Immel, David and Drautz, Ralf and Sutmann, Godehard},\n"
|
||||
" title = {Adaptive-precision potentials for large-scale atomistic simulations},\n"
|
||||
" journal = {The Journal of Chemical Physics},\n"
|
||||
" volume = {162},\n"
|
||||
" number = {11},\n"
|
||||
" pages = {114119},\n"
|
||||
" year = {2025}\n"
|
||||
"}\n\n";
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FixLambdaAPIP::FixLambdaAPIP(LAMMPS *lmp, int narg, char **arg) :
|
||||
Fix(lmp, narg, arg), peratom_stats(nullptr), group_name_simple(nullptr),
|
||||
group_name_complex(nullptr), group_name_ignore_lambda_input(nullptr), fixstore(nullptr),
|
||||
fixstore2(nullptr), pair_lambda_input(nullptr), pair_lambda_zone(nullptr)
|
||||
{
|
||||
if (lmp->citeme) lmp->citeme->add(cite_fix_lambda_c);
|
||||
|
||||
// set defaults
|
||||
threshold_lo = threshold_hi = threshold_width = -1;
|
||||
cut_lo = 4.0;
|
||||
cut_hi = 12.0;
|
||||
lambda_non_group = 1; // simple
|
||||
history_last = history2_last = -1;
|
||||
history_length = history2_length = 100;
|
||||
history_used = history2_used = 0;
|
||||
min_delta_lambda = 0;
|
||||
|
||||
group_bit_simple = group_bit_complex = group_bit_ignore_lambda_input = 0;
|
||||
|
||||
// output
|
||||
peratom_flag = 0;
|
||||
peratom_freq = -1; // default from fix.cpp
|
||||
dump_history_flag = false;
|
||||
size_peratom_cols = 5;
|
||||
invoked_history_update = invoked_history2_update = -1;
|
||||
|
||||
if (narg < 4) error->all(FLERR, "fix lambda requires two arguments");
|
||||
threshold_lo = utils::numeric(FLERR, arg[3], false, lmp);
|
||||
threshold_hi = utils::numeric(FLERR, arg[4], false, lmp);
|
||||
threshold_width = threshold_hi - threshold_lo;
|
||||
|
||||
// parse remaining arguments
|
||||
for (int iarg = 5; iarg < narg; iarg++) {
|
||||
if (strcmp(arg[iarg], "time_averaged_zone") == 0) {
|
||||
if (iarg + 4 >= narg)
|
||||
error->all(FLERR, "fix lambda: time_averaged_zone requires four arguments");
|
||||
cut_lo = utils::numeric(FLERR, arg[iarg + 1], false, lmp);
|
||||
cut_hi = utils::numeric(FLERR, arg[iarg + 2], false, lmp);
|
||||
history_length = utils::inumeric(FLERR, arg[iarg + 3], false, lmp);
|
||||
history2_length = utils::inumeric(FLERR, arg[iarg + 4], false, lmp);
|
||||
iarg += 4;
|
||||
} else if (strcmp(arg[iarg], "min_delta_lambda") == 0) {
|
||||
if (iarg + 1 >= narg) error->all(FLERR, "fix lambda: min_delta_lambda requires one argument");
|
||||
min_delta_lambda = utils::numeric(FLERR, arg[iarg + 1], false, lmp);
|
||||
iarg += 1;
|
||||
} else if (strcmp(arg[iarg], "lambda_non_group") == 0) {
|
||||
if (iarg + 1 >= narg) error->all(FLERR, "fix lambda: lambda_non_group requires an argument");
|
||||
if (strcmp(arg[iarg + 1], "precise") == 0) {
|
||||
lambda_non_group = 0;
|
||||
} else if (strcmp(arg[iarg + 1], "fast") == 0) {
|
||||
lambda_non_group = 1;
|
||||
} else {
|
||||
lambda_non_group = utils::numeric(FLERR, arg[iarg + 1], false, lmp);
|
||||
if (lambda_non_group < 0 || lambda_non_group > 1)
|
||||
error->all(FLERR, "fix lambda: Illegal value of lambda_non_group");
|
||||
}
|
||||
iarg++;
|
||||
} else if (strcmp(arg[iarg], "store_atomic_stats") == 0) {
|
||||
peratom_flag = 1;
|
||||
} else if (strcmp(arg[iarg], "dump_atomic_history") == 0) {
|
||||
peratom_flag = 1;
|
||||
dump_history_flag = true;
|
||||
} else if (strcmp(arg[iarg], "group_fast") == 0) {
|
||||
// read name of group
|
||||
group_name_simple = utils::strdup(arg[iarg + 1]);
|
||||
int tmp = group->find(group_name_simple);
|
||||
if (tmp == -1) error->all(FLERR, "fix lambda: group {} does not exist", group_name_simple);
|
||||
group_bit_simple = group->bitmask[tmp];
|
||||
iarg++;
|
||||
} else if (strcmp(arg[iarg], "group_precise") == 0) {
|
||||
// read name of group
|
||||
group_name_complex = utils::strdup(arg[iarg + 1]);
|
||||
int tmp = group->find(group_name_complex);
|
||||
if (tmp == -1) error->all(FLERR, "fix lambda: group {} does not exist", group_name_complex);
|
||||
group_bit_complex = group->bitmask[tmp];
|
||||
iarg++;
|
||||
} else if (strcmp(arg[iarg], "group_ignore_lambda_input") == 0) {
|
||||
// read name of group
|
||||
group_name_ignore_lambda_input = utils::strdup(arg[iarg + 1]);
|
||||
int tmp = group->find(group_name_ignore_lambda_input);
|
||||
if (tmp == -1)
|
||||
error->all(FLERR, "fix lambda: group {} does not exist", group_name_ignore_lambda_input);
|
||||
group_bit_ignore_lambda_input = group->bitmask[tmp];
|
||||
iarg++;
|
||||
} else
|
||||
error->all(FLERR, "fix lambda: unknown argument {}", arg[iarg]);
|
||||
}
|
||||
cut_hi_sq = cut_hi * cut_hi;
|
||||
cut_width = cut_hi - cut_lo;
|
||||
|
||||
// verify arguments
|
||||
if (threshold_lo > threshold_hi || threshold_lo < 0)
|
||||
error->all(FLERR, "fix lambda: Illegal or missing threshold values");
|
||||
if (min_delta_lambda < 0)
|
||||
error->all(FLERR, "fix lambda: min_delta_lambda >= 0 required instead of {}", min_delta_lambda);
|
||||
|
||||
if (cut_lo < 0 || cut_hi < cut_lo) error->all(FLERR, "fix lambda: Illegal cutoff values");
|
||||
if (history_length < 2 || history2_length < 2)
|
||||
error->all(FLERR, "fix lambda: history_length > 1 required");
|
||||
|
||||
if (comm->me == 0 && ((group_bit_simple != 0) || (group_bit_complex != 0)) &&
|
||||
group_bit_ignore_lambda_input == 0)
|
||||
error->warning(FLERR,
|
||||
"group_ignore_lambda_input should be used to prevent the calculation of "
|
||||
"lambda_input for atoms that are in the groups group_fast and group_precise.");
|
||||
|
||||
if (!atom->apip_lambda_const_flag) {
|
||||
error->all(FLERR, "fix lambda requires atomic style with lambda_const.");
|
||||
}
|
||||
if (!atom->apip_lambda_flag) {
|
||||
error->all(FLERR, "fix lambda requires atomic style with lambda.");
|
||||
}
|
||||
if (!atom->apip_lambda_input_flag) {
|
||||
error->all(FLERR, "fix lambda requires atomic style with lambda_input.");
|
||||
}
|
||||
|
||||
comm_forward = 2; // up to two doubles per atom
|
||||
comm_forward_flag = FORWARD_TA;
|
||||
|
||||
restart_global = 1;
|
||||
|
||||
if (peratom_flag) {
|
||||
|
||||
if (dump_history_flag) size_peratom_cols += history_length + history2_length + 2;
|
||||
|
||||
peratom_freq = 1;
|
||||
// zero the array since dump may access it on timestep 0
|
||||
// zero the array since a variable may access it before first run
|
||||
|
||||
nmax_stats = atom->nmax;
|
||||
memory->create(peratom_stats, nmax_stats, size_peratom_cols, "lambda:peratom_stats");
|
||||
array_atom = peratom_stats;
|
||||
|
||||
int nlocal = atom->nlocal;
|
||||
for (int i = 0; i < nlocal; i++)
|
||||
for (int j = 0; j < size_peratom_cols; j++) peratom_stats[i][j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
modify cutoff setings
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int FixLambdaAPIP::modify_param(int narg, char **arg)
|
||||
{
|
||||
cut_lo = utils::numeric(FLERR, arg[0], false, lmp);
|
||||
cut_hi = utils::numeric(FLERR, arg[1], false, lmp);
|
||||
cut_hi_sq = cut_hi * cut_hi;
|
||||
cut_width = cut_hi - cut_lo;
|
||||
|
||||
if (cut_lo < 0 || cut_hi < cut_lo) error->all(FLERR, "fix lambda: Illegal cutoff values");
|
||||
|
||||
if (force->pair->cutforce < cut_hi)
|
||||
error->all(FLERR, "fix lambda: cutoff of potential smaller than cutoff of switching region");
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FixLambdaAPIP::~FixLambdaAPIP()
|
||||
{
|
||||
// check nfix in case all fixes have already been deleted
|
||||
if (fixstore && modify->nfix) modify->delete_fix(fixstore->id);
|
||||
if (fixstore2 && modify->nfix) modify->delete_fix(fixstore2->id);
|
||||
fixstore = fixstore2 = nullptr;
|
||||
|
||||
memory->destroy(peratom_stats);
|
||||
|
||||
delete[] group_name_simple;
|
||||
delete[] group_name_complex;
|
||||
delete[] group_name_ignore_lambda_input;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int FixLambdaAPIP::setmask()
|
||||
{
|
||||
int mask = 0;
|
||||
mask |= POST_INTEGRATE;
|
||||
mask |= PRE_FORCE; // for setup_pre_force only
|
||||
if (peratom_flag) mask |= END_OF_STEP;
|
||||
return mask;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixLambdaAPIP::init()
|
||||
{
|
||||
if (force->pair == nullptr) error->all(FLERR, "Fix lambda requires a pair style be defined");
|
||||
|
||||
// only one fix lambda
|
||||
int count = 0;
|
||||
for (int i = 0; i < modify->nfix; i++) {
|
||||
if (strcmp(modify->fix[i]->style, "lambda/apip") == 0) count++;
|
||||
}
|
||||
if (count > 1) error->all(FLERR, "More than one fix lambda.");
|
||||
|
||||
// warn if there is no fix lambda_thermostat/apip
|
||||
if (comm->me == 0 && modify->get_fix_by_style("lambda_thermostat/apip").size() == 0)
|
||||
error->warning(FLERR,
|
||||
"The energy is not conserved when lambda changes as fix lambda_thermostat/apip "
|
||||
"is not used.");
|
||||
|
||||
Pair *pair_tmp;
|
||||
// lambda_input
|
||||
pair_tmp = force->pair_match("lambda/input/", 0);
|
||||
if (!pair_tmp) error->all(FLERR, "fix lambda requires a `pair lambda_input`");
|
||||
pair_lambda_input = (PairLambdaInputAPIP *) pair_tmp;
|
||||
// lambda/zone
|
||||
pair_tmp = force->pair_match("lambda/zone/apip", 1);
|
||||
if (!pair_tmp) error->all(FLERR, "fix lambda requires a `pair lambda`");
|
||||
pair_lambda_zone = (PairLambdaZoneAPIP *) pair_tmp;
|
||||
|
||||
if (force->pair->cutforce < cut_hi)
|
||||
error->all(FLERR, "fix lambda: cutoff of potential smaller than cutoff of switching region");
|
||||
|
||||
if (strcmp(atom->atom_style, "apip")) error->all(FLERR, "fix lambda requires atom style apip");
|
||||
|
||||
// check that groups have not been deleted
|
||||
if (group_name_simple) {
|
||||
int tmp = group->find(group_name_simple);
|
||||
if (tmp == -1) error->all(FLERR, "fix lambda: group {} does not exist", group_name_simple);
|
||||
group_bit_simple = group->bitmask[tmp];
|
||||
}
|
||||
if (group_name_complex) {
|
||||
int tmp = group->find(group_name_complex);
|
||||
if (tmp == -1) error->all(FLERR, "fix lambda: group {} does not exist", group_name_complex);
|
||||
group_bit_complex = group->bitmask[tmp];
|
||||
}
|
||||
if (group_name_ignore_lambda_input) {
|
||||
int tmp = group->find(group_name_ignore_lambda_input);
|
||||
if (tmp == -1)
|
||||
error->all(FLERR, "fix lambda: group {} does not exist", group_name_ignore_lambda_input);
|
||||
group_bit_ignore_lambda_input = group->bitmask[tmp];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* allocate per-particle storage for past cs values via FixStoreAtom
|
||||
* fix could already be allocated if fix lambda is re-specified
|
||||
*/
|
||||
|
||||
void FixLambdaAPIP::post_constructor()
|
||||
{
|
||||
std::string cmd, cmd2;
|
||||
cmd = id;
|
||||
cmd2 = id;
|
||||
cmd += "LAMBDA_INPUT_HISTORY";
|
||||
cmd2 += "LAMBDA_HISTORY";
|
||||
|
||||
// delete existing fix store if existing
|
||||
fixstore = dynamic_cast<FixStoreAtom *>(modify->get_fix_by_id(cmd));
|
||||
fixstore2 = dynamic_cast<FixStoreAtom *>(modify->get_fix_by_id(cmd2));
|
||||
// check nfix in case all fixes have already been deleted
|
||||
if (fixstore && modify->nfix) modify->delete_fix(fixstore->id);
|
||||
if (fixstore2 && modify->nfix) modify->delete_fix(fixstore2->id);
|
||||
fixstore = nullptr;
|
||||
|
||||
// create new FixStoreAtom
|
||||
// store history_length of last values and the sum over all values
|
||||
char history_length_str[40], history2_length_str[40];
|
||||
sprintf(history_length_str, "%d", history_length + 2); // lambda_input
|
||||
sprintf(history2_length_str, "%d", history2_length + 1); // lambda
|
||||
|
||||
// arguments of peratom:
|
||||
// first: 1 -> store in restart file
|
||||
// second: number of doubles to store per atom
|
||||
cmd += " all STORE/ATOM ";
|
||||
cmd2 += " all STORE/ATOM ";
|
||||
cmd += history_length_str; // n1
|
||||
cmd2 += history2_length_str; // n1
|
||||
cmd += " 0 0 1"; // n2 gflag rflag
|
||||
cmd2 += " 0 0 1"; // n2 gflag rflag
|
||||
fixstore = dynamic_cast<FixStoreAtom *>(modify->add_fix(cmd));
|
||||
fixstore2 = dynamic_cast<FixStoreAtom *>(modify->add_fix(cmd2));
|
||||
|
||||
// carry weights with atoms during normal atom migration
|
||||
fixstore->disable = 0;
|
||||
fixstore2->disable = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate lambda for initial atoms if required.
|
||||
* If required, this includes communication.
|
||||
*/
|
||||
|
||||
void FixLambdaAPIP::setup_pre_force(int /*vflag*/)
|
||||
{
|
||||
// lambda, lambda_input, lambda_input_ta and lambda_const are written to restart files.
|
||||
|
||||
// Calculate lambda_input in pair style.
|
||||
pair_lambda_input->calculate_lambda_input();
|
||||
// Update lambda_input_history with lambda_input.
|
||||
update_lambda_input_history();
|
||||
// calculate and communicate lambda_input_ta to neighbours
|
||||
communicate_lambda_input_ta();
|
||||
// calculate lambda max with lambda_input_ta of own and ngh atoms
|
||||
pair_lambda_zone->calculate_lambda();
|
||||
// update lambda_history with calculated lambda_input_ta, set lambda, set lambda_input_ta to lambda(own ta lambda_input)
|
||||
post_integrate();
|
||||
// set initial lambda_const if required, communicate lambda and lambda_const to neighbours
|
||||
comm_forward_lambda();
|
||||
// pair_lambda_zone->calculate_lambda is again called as default setup force calculation
|
||||
// -> communicate lambda_input_ta again to have an appropriate input for this "force" calculation
|
||||
// increase invoked update to prevent double values
|
||||
communicate_lambda_input_ta();
|
||||
|
||||
// just to be sure
|
||||
write_peratom_stats();
|
||||
}
|
||||
|
||||
/**
|
||||
* The new lambda is stored for own atoms in lambda_input_ta since the last force calculation.
|
||||
* Update lambda and lambda_const with the running average including the new lambda.
|
||||
*/
|
||||
|
||||
void FixLambdaAPIP::post_integrate()
|
||||
{
|
||||
double *lambda, *lambda_const, *lambda_input_ta;
|
||||
|
||||
lambda = atom->apip_lambda;
|
||||
lambda_const = atom->apip_lambda_const;
|
||||
lambda_input_ta = atom->apip_lambda_input_ta;
|
||||
|
||||
update_lambda_history(); // update running average of lambda with lambda_input_ta
|
||||
get_lambda_average(); // and copy running average to lambda_input_ta
|
||||
|
||||
// use lambda_input_ta to set lambda max
|
||||
int nlocal = atom->nlocal;
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
lambda_const[i] = lambda[i];
|
||||
lambda[i] = lambda_input_ta[i];
|
||||
// prevent useless fluctuations in the switching zone just due to atomic fluctuations
|
||||
// the values 0 and 1 are always permitted to prevent atoms from keeping a lambda of epsilon forever
|
||||
if (fabs(lambda[i] - lambda_const[i]) < min_delta_lambda && lambda[i] != 1 && lambda[i] != 0)
|
||||
lambda[i] = lambda_const[i];
|
||||
}
|
||||
|
||||
// set lambda_input_ta to own lambda for new lambda calculation with pair_lambda_zone_apip.cpp
|
||||
calculate_lambda_input_ta();
|
||||
}
|
||||
|
||||
/**
|
||||
* write stats at end of step
|
||||
*/
|
||||
|
||||
void FixLambdaAPIP::end_of_step()
|
||||
{
|
||||
write_peratom_stats();
|
||||
}
|
||||
|
||||
/**
|
||||
* The new calculated lambda is stored in lambda.
|
||||
* Exchange lambda and lambda_const with neighbours.
|
||||
* Use only in setup_pre_force.
|
||||
*/
|
||||
|
||||
void FixLambdaAPIP::comm_forward_lambda()
|
||||
{
|
||||
if (history2_used == 1) {
|
||||
// There is only one one calculated lambda.
|
||||
// -> This is the first lambda calculation.
|
||||
// -> set lambda_const to lambda since there is no previous lambda
|
||||
double *lambda, *lambda_const;
|
||||
int nlocal;
|
||||
|
||||
lambda = atom->apip_lambda;
|
||||
lambda_const = atom->apip_lambda_const;
|
||||
nlocal = atom->nlocal;
|
||||
for (int i = 0; i < nlocal; i++) { lambda_const[i] = lambda[i]; }
|
||||
}
|
||||
|
||||
comm_forward_flag = FORWARD_MAX;
|
||||
comm->forward_comm(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* write per atom stats
|
||||
*/
|
||||
|
||||
void FixLambdaAPIP::write_peratom_stats()
|
||||
{
|
||||
if (!peratom_flag) return;
|
||||
|
||||
int i, j, nlocal;
|
||||
double **lambda_input_history, **lambda_history;
|
||||
|
||||
nlocal = atom->nlocal;
|
||||
lambda_input_history = fixstore->astore;
|
||||
lambda_history = fixstore2->astore;
|
||||
|
||||
// grow stats array if required
|
||||
if (atom->nmax > nmax_stats) {
|
||||
memory->destroy(peratom_stats);
|
||||
nmax_stats = atom->nmax;
|
||||
memory->create(peratom_stats, nmax_stats, size_peratom_cols, "lambda:peratom_stats");
|
||||
array_atom = peratom_stats;
|
||||
}
|
||||
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
peratom_stats[i][0] = lambda_input_history[i][history_last]; // lambda_input now
|
||||
peratom_stats[i][1] =
|
||||
lambda_input_history[i][history_length] / history_used; // lambda_input averaged
|
||||
peratom_stats[i][2] =
|
||||
lambda_input_history[i][history_length + 1]; // lambda of own ta lambda_input
|
||||
peratom_stats[i][3] = lambda_history[i][history2_last]; // lambda max now
|
||||
peratom_stats[i][4] =
|
||||
lambda_history[i][history2_length] / history2_used; // lambda max averaged
|
||||
}
|
||||
|
||||
if (dump_history_flag) {
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
// include lambda_input sum -> <= history_length
|
||||
for (j = 0; j <= history_length; j++) {
|
||||
peratom_stats[i][j + 5] = lambda_input_history[i][j]; // lambda_input history
|
||||
}
|
||||
for (j = 0; j <= history2_length; j++) {
|
||||
peratom_stats[i][j + 6 + history_length] = lambda_history[i][j]; // lambda_input history
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update running average of lambda_input.
|
||||
*/
|
||||
|
||||
void FixLambdaAPIP::update_lambda_input_history()
|
||||
{
|
||||
if (invoked_history_update == update->ntimestep) return;
|
||||
invoked_history_update = update->ntimestep;
|
||||
|
||||
double *lambda_input, **lambda_input_history;
|
||||
int *mask;
|
||||
int nlocal;
|
||||
|
||||
lambda_input = atom->apip_lambda_input;
|
||||
mask = atom->mask;
|
||||
lambda_input_history = fixstore->astore;
|
||||
nlocal = atom->nlocal;
|
||||
|
||||
// update stats about written values
|
||||
history_last = (history_last + 1) % history_length;
|
||||
history_used = std::min(history_used + 1, history_length);
|
||||
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (!(mask[i] & groupbit)) {
|
||||
lambda_input_history[i][history_length + 1] = lambda_non_group;
|
||||
continue;
|
||||
}
|
||||
|
||||
// lambda_input_history[particle_number][history_number]
|
||||
// history_number:
|
||||
// 0 - history_length - 1 : single lambda_input of past time step
|
||||
// history_length : sum of all stored past lambda_input values
|
||||
// history_length + 1 : lambda(time averaged lambda_input)
|
||||
|
||||
// subtract the lambda_input to be overwritten from sum
|
||||
lambda_input_history[i][history_length] -= lambda_input_history[i][history_last];
|
||||
// store new lambda_input value
|
||||
lambda_input_history[i][history_last] = lambda_input[i];
|
||||
// add the new lambda_input to sum
|
||||
lambda_input_history[i][history_length] += lambda_input_history[i][history_last];
|
||||
|
||||
// calculate lambda of new time average
|
||||
|
||||
if (group_name_complex && (mask[i] & group_bit_complex)) {
|
||||
// hard code complex with highest priority
|
||||
lambda_input_history[i][history_length + 1] = 0;
|
||||
} else if (group_name_simple && (mask[i] & group_bit_simple)) {
|
||||
// hard code simple with second highest priority
|
||||
lambda_input_history[i][history_length + 1] = 1;
|
||||
} else if ((mask[i] & groupbit) &&
|
||||
!(group_name_ignore_lambda_input && (mask[i] & group_bit_ignore_lambda_input))) {
|
||||
// calculate lambda based on lambda_input
|
||||
lambda_input_history[i][history_length + 1] =
|
||||
switching_function_poly(lambda_input_history[i][history_length] / history_used);
|
||||
} else {
|
||||
lambda_input_history[i][history_length + 1] = lambda_non_group;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update running average of lambda with lambda_input_ta.
|
||||
*/
|
||||
|
||||
void FixLambdaAPIP::update_lambda_history()
|
||||
{
|
||||
if (invoked_history2_update == update->ntimestep) return;
|
||||
invoked_history2_update = update->ntimestep;
|
||||
|
||||
double *lambda_input_ta, **lambda_history, **lambda_input_history;
|
||||
int *mask;
|
||||
int nlocal;
|
||||
|
||||
lambda_input_ta = atom->apip_lambda_input_ta;
|
||||
mask = atom->mask;
|
||||
lambda_history = fixstore2->astore;
|
||||
lambda_input_history = fixstore->astore;
|
||||
nlocal = atom->nlocal;
|
||||
|
||||
// update stats about written values
|
||||
history2_last = (history2_last + 1) % history2_length;
|
||||
history2_used = std::min(history2_used + 1, history2_length);
|
||||
|
||||
int tmp = 0;
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (!(mask[i] & groupbit)) continue;
|
||||
|
||||
// lambda_history[particle_number][history2_number]
|
||||
// history2_number:
|
||||
// 0 - history2_length - 1 : lambda of past time step
|
||||
// history2_length : sum of all stored past lambda values
|
||||
|
||||
// subtract the lambda to be overwritten from sum
|
||||
lambda_history[i][history2_length] -= lambda_history[i][history2_last];
|
||||
// store new lambda_input value
|
||||
lambda_history[i][history2_last] = lambda_input_ta[i];
|
||||
// add the new lambda_input to sum
|
||||
lambda_history[i][history2_length] += lambda_history[i][history2_last];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy running average of lambda to lambda_input_ta.
|
||||
*/
|
||||
|
||||
void FixLambdaAPIP::get_lambda_average()
|
||||
{
|
||||
double *lambda_input_ta, **lambda_history, avg;
|
||||
int *mask, nlocal;
|
||||
|
||||
mask = atom->mask;
|
||||
nlocal = atom->nlocal;
|
||||
lambda_history = fixstore2->astore;
|
||||
lambda_input_ta = atom->apip_lambda_input_ta;
|
||||
|
||||
// recalculate history sum to limit floating point issues since only changes of the sum are tracked
|
||||
if (history2_last == history2_length - 1) {
|
||||
double sum;
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
sum = 0;
|
||||
for (int j = 0; j < history2_length; j++) sum += lambda_history[i][j];
|
||||
lambda_history[i][history2_length] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (mask[i] & groupbit) {
|
||||
// avg is a division and not exactly 1 or 0
|
||||
// exact values are required otherwise many useless complex calculations follow since avg = 1 - epsilon < 1
|
||||
// -> hard code zero and one if required
|
||||
avg = lambda_history[i][history2_length] / history2_used;
|
||||
if (avg > 0.9999)
|
||||
lambda_input_ta[i] = 1; // simple
|
||||
else if (avg < 0.0001)
|
||||
lambda_input_ta[i] = 0; // complex
|
||||
else
|
||||
lambda_input_ta[i] = avg; // switching
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate lambda_input_ta for own atoms
|
||||
*/
|
||||
|
||||
void FixLambdaAPIP::calculate_lambda_input_ta()
|
||||
{
|
||||
int i, nlocal;
|
||||
int *mask;
|
||||
double *lambda_input_ta = atom->apip_lambda_input_ta;
|
||||
|
||||
nlocal = atom->nlocal;
|
||||
mask = atom->mask;
|
||||
|
||||
// store time averaged lambda_input for own atoms
|
||||
double **lambda_input_history = fixstore->astore;
|
||||
for (i = 0; i < nlocal; i++) { lambda_input_ta[i] = lambda_input_history[i][history_length + 1]; }
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Compute temporary lambda for owned atoms based on lambda_input_history of owned atoms.
|
||||
Save this temporary lambda as lambda_input_ta and send it to neighbours.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void FixLambdaAPIP::communicate_lambda_input_ta()
|
||||
{
|
||||
calculate_lambda_input_ta();
|
||||
|
||||
// lambda_input_ta is known only for own atoms
|
||||
// -> exchange lambda_input_ta
|
||||
comm_forward_flag = FORWARD_TA;
|
||||
comm->forward_comm(this);
|
||||
}
|
||||
|
||||
// helper function
|
||||
// similar to cutoff_func_poly in ace_radial.cpp
|
||||
// compare Phys Rev Mat 6, 013804 (2022) APPENDIX C: RADIAL AND CUTOFF FUNCTIONS 2. Cutoff function
|
||||
// the first two derivatives of the switching function lambda vanishes at the boundaries of the switching region
|
||||
double FixLambdaAPIP::switching_function_poly(double input)
|
||||
{
|
||||
// calculate lambda
|
||||
if (input <= threshold_lo) {
|
||||
return 1;
|
||||
} else if (input >= threshold_hi) {
|
||||
return 0;
|
||||
} else {
|
||||
double deltatmp = 1 - 2 * (1 + (input - threshold_hi) / (threshold_width));
|
||||
return 0.5 + 7.5 / 2. * (deltatmp / 4. - pow(deltatmp, 3) / 6. + pow(deltatmp, 5) / 20.);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send lambda to neighbours.
|
||||
*/
|
||||
|
||||
int FixLambdaAPIP::pack_forward_comm(int n, int *list, double *buf, int /*pbc_flag*/, int * /*pbc*/)
|
||||
{
|
||||
int i, j, m;
|
||||
double *lambda_input_ta = atom->apip_lambda_input_ta;
|
||||
m = 0;
|
||||
|
||||
if (comm_forward_flag == FORWARD_TA) {
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = lambda_input_ta[j];
|
||||
}
|
||||
} else if (comm_forward_flag == FORWARD_MAX) {
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = atom->apip_lambda[j];
|
||||
buf[m++] = atom->apip_lambda_const[j];
|
||||
}
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recv lambda from neighbours.
|
||||
*/
|
||||
|
||||
void FixLambdaAPIP::unpack_forward_comm(int n, int first, double *buf)
|
||||
{
|
||||
int i, m, last;
|
||||
double *lambda_input_ta = atom->apip_lambda_input_ta;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
if (comm_forward_flag == FORWARD_TA) {
|
||||
for (i = first; i < last; i++) { lambda_input_ta[i] = buf[m++]; }
|
||||
} else if (comm_forward_flag == FORWARD_MAX) {
|
||||
for (i = first; i < last; i++) {
|
||||
atom->apip_lambda[i] = buf[m++];
|
||||
atom->apip_lambda_const[i] = buf[m++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* store scalar history information
|
||||
*/
|
||||
|
||||
void FixLambdaAPIP::write_restart(FILE *fp)
|
||||
{
|
||||
int timesteps_since_invoked_history_update = update->ntimestep - invoked_history_update;
|
||||
int timesteps_since_invoked_history2_update = update->ntimestep - invoked_history2_update;
|
||||
|
||||
int n = 0;
|
||||
double list[8];
|
||||
list[n++] = history_length;
|
||||
list[n++] = history_used;
|
||||
list[n++] = history_last;
|
||||
list[n++] = timesteps_since_invoked_history_update;
|
||||
list[n++] = history2_length;
|
||||
list[n++] = history2_used;
|
||||
list[n++] = history2_last;
|
||||
list[n++] = timesteps_since_invoked_history2_update;
|
||||
|
||||
if (comm->me == 0) {
|
||||
int size = n * sizeof(double);
|
||||
fwrite(&size, sizeof(int), 1, fp);
|
||||
fwrite(list, sizeof(double), n, fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
use state info from restart file to restart the Fix
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void FixLambdaAPIP::restart(char *buf)
|
||||
{
|
||||
int timesteps_since_invoked_history_update, history_length_br,
|
||||
timesteps_since_invoked_history2_update, history2_length_br;
|
||||
bigint next_file_write_calculated;
|
||||
|
||||
int n = 0;
|
||||
auto list = (double *) buf;
|
||||
|
||||
history_length_br = static_cast<int>(list[n++]);
|
||||
history_used = static_cast<int>(list[n++]);
|
||||
history_last = static_cast<int>(list[n++]);
|
||||
invoked_history_update = update->ntimestep - (static_cast<int>(list[n++]));
|
||||
history2_length_br = static_cast<int>(list[n++]);
|
||||
history2_used = static_cast<int>(list[n++]);
|
||||
history2_last = static_cast<int>(list[n++]);
|
||||
invoked_history2_update = update->ntimestep - (static_cast<int>(list[n++]));
|
||||
|
||||
// simple comparisons first
|
||||
if (history_length != history_length_br)
|
||||
error->all(FLERR, "fix lambda: history_length = {} != {} = history_length_before_restart",
|
||||
history_length, history_length_br);
|
||||
if (history2_length != history2_length_br)
|
||||
error->all(FLERR, "fix lambda: history2_length = {} != {} = history2_length_before_restart",
|
||||
history2_length, history2_length_br);
|
||||
}
|
||||
|
||||
/**
|
||||
* extract lambda(time averaged lambda_input) and lambda_input_history_len
|
||||
*/
|
||||
|
||||
void *FixLambdaAPIP::extract(const char *str, int &dim)
|
||||
{
|
||||
dim = 2;
|
||||
if (strcmp(str, "fix_lambda:lambda_input_history") == 0 && fixstore) { return fixstore->astore; }
|
||||
dim = 0;
|
||||
if (strcmp(str, "fix_lambda:lambda_input_history_len") == 0) { return &history_length; }
|
||||
if (strcmp(str, "fix_lambda:cut_lo") == 0) { return &cut_lo; }
|
||||
if (strcmp(str, "fix_lambda:cut_hi") == 0) { return &cut_hi; }
|
||||
if (strcmp(str, "fix_lambda:cut_hi_sq") == 0) { return &cut_hi_sq; }
|
||||
if (strcmp(str, "fix_lambda:cut_width") == 0) { return &cut_width; }
|
||||
if (strcmp(str, "fix_lambda:lambda_non_group") == 0) { return &lambda_non_group; }
|
||||
return nullptr;
|
||||
}
|
||||
108
src/APIP/fix_lambda_apip.h
Normal file
108
src/APIP/fix_lambda_apip.h
Normal file
@ -0,0 +1,108 @@
|
||||
/* -*- 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 author: David Immel (d.immel@fz-juelich.de, FZJ, Germany)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef FIX_CLASS
|
||||
// clang-format off
|
||||
FixStyle(lambda/apip,FixLambdaAPIP);
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
#ifndef LMP_FIX_LAMBDA_APIP_H
|
||||
#define LMP_FIX_LAMBDA_APIP_H
|
||||
|
||||
#include "fix.h"
|
||||
#include "pair_lambda_input_apip.h"
|
||||
#include "pair_lambda_zone_apip.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class FixLambdaAPIP : public Fix {
|
||||
friend class PairLambdaInputAPIP;
|
||||
friend class PairLambdaZoneAPIP;
|
||||
|
||||
public:
|
||||
FixLambdaAPIP(class LAMMPS *, int, char **);
|
||||
~FixLambdaAPIP() override;
|
||||
int modify_param(int, char **) override;
|
||||
void init() override;
|
||||
int setmask() override;
|
||||
void post_constructor() override;
|
||||
void setup_pre_force(int) override;
|
||||
void post_integrate() override;
|
||||
void end_of_step() override;
|
||||
int pack_forward_comm(int, int *, double *, int, int *) override;
|
||||
void unpack_forward_comm(int, int, double *) override;
|
||||
void write_restart(FILE *) override;
|
||||
void restart(char *) override;
|
||||
void *extract(const char *, int &) override;
|
||||
|
||||
private:
|
||||
enum { FORWARD_MAX, FORWARD_TA };
|
||||
int comm_forward_flag; // flag that determines which variables are communicated in comm forward
|
||||
|
||||
class PairLambdaInputAPIP *pair_lambda_input;
|
||||
class PairLambdaZoneAPIP *pair_lambda_zone;
|
||||
|
||||
double cut_lo; ///< distance at which the cutoff function of the transition zone decays from 1
|
||||
double cut_hi; ///< distance at which the cutoff function of the transition zone is 0
|
||||
double cut_width; ///< cut_hi - cut_lo
|
||||
double cut_hi_sq; ///< cut_hi_sq * cut_hi_sq
|
||||
double threshold_lo; ///< threshold above which the fast potential starts to be turned off
|
||||
double threshold_hi; ///< threshold above which the fast potential is turned off completely
|
||||
double threshold_width; ///< threshold_hi - threshold_lo
|
||||
double min_delta_lambda; ///< minimum steps size of lambda
|
||||
|
||||
double lambda_non_group; ///< lambda for atoms that are not in the group of this fix
|
||||
|
||||
int history_length; ///< number of steps of which lambda_input is sterd at max
|
||||
int history_used; ///< number of steps of which lambda_input is currently stored
|
||||
int history_last; ///< index of last written lambda_input value
|
||||
class FixStoreAtom *fixstore; ///< ptr to stored lambda_input values
|
||||
|
||||
int history2_length; ///< number of steps of which lambda is stored at max
|
||||
int history2_used; ///< number of steps of which lambda is currently stored
|
||||
int history2_last; ///< index of last written lambda value
|
||||
class FixStoreAtom *fixstore2; ///< ptr to stored lambda values
|
||||
|
||||
double switching_function_poly(double);
|
||||
|
||||
bigint invoked_history_update; ///< last timestep with stored history
|
||||
bigint invoked_history2_update; ///< last timestep with stored history
|
||||
bool dump_history_flag; ///< dump whole stored history (for debugging)
|
||||
|
||||
int group_bit_simple; ///< hard coded simple atoms
|
||||
int group_bit_complex; ///< hard coded complex atoms
|
||||
int group_bit_ignore_lambda_input; ///< ignore lambda_input of this group
|
||||
char *group_name_simple; ///< hard coded simple atoms
|
||||
char *group_name_complex; ///< hard coded complex atoms
|
||||
char *group_name_ignore_lambda_input; ///< ignore lambda_input of this group
|
||||
|
||||
int nmax_stats; ///< number of allocated atoms for peratom_stats
|
||||
double **peratom_stats; ///< returned peratom vector
|
||||
|
||||
void calculate_lambda_input_ta();
|
||||
void comm_forward_lambda();
|
||||
void write_peratom_stats();
|
||||
void update_lambda_input_history();
|
||||
void communicate_lambda_input_ta();
|
||||
void get_lambda_average();
|
||||
void update_lambda_history();
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
635
src/APIP/fix_lambda_thermostat_apip.cpp
Normal file
635
src/APIP/fix_lambda_thermostat_apip.cpp
Normal file
@ -0,0 +1,635 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
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: David Immel (d.immel@fz-juelich.de, FZJ, Germany)
|
||||
------------------------------------------------------------------------- */
|
||||
#include "fix_lambda_thermostat_apip.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "error.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
#include "modify.h"
|
||||
#include "my_page.h"
|
||||
#include "neigh_list.h"
|
||||
#include "neighbor.h"
|
||||
#include "random_park.h"
|
||||
#include "update.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace FixConst;
|
||||
|
||||
#define PGDELTA 1
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FixLambdaThermostatAPIP::FixLambdaThermostatAPIP(LAMMPS *lmp, int narg, char **arg) :
|
||||
Fix(lmp, narg, arg), list(nullptr), energy_change_atom(nullptr), peratom_stats(nullptr),
|
||||
local_numneigh(nullptr), local_firstneigh(nullptr), ipage(nullptr), jlist_copy(nullptr)
|
||||
{
|
||||
// set global options for fix class
|
||||
|
||||
vector_flag = 1;
|
||||
size_vector = 6;
|
||||
extvector = 0;
|
||||
|
||||
// set default vaues
|
||||
dtf = 0;
|
||||
update_stats = false;
|
||||
int seed = 42;
|
||||
rescaling_N_neighbours = 200;
|
||||
// output
|
||||
peratom_flag = 0;
|
||||
peratom_freq = -1; // default from fix.cpp
|
||||
size_peratom_cols = 4;
|
||||
|
||||
// parse arguments
|
||||
for (int iarg = 3; iarg < narg; iarg++) {
|
||||
|
||||
if (strcmp(arg[iarg], "seed") == 0) {
|
||||
if (iarg + 1 >= narg)
|
||||
error->all(FLERR, "fix lambda_thermostat/apip: seed requires one argument");
|
||||
seed = utils::inumeric(FLERR, arg[iarg + 1], false, lmp);
|
||||
if (seed <= 0) { error->all(FLERR, "fix lambda_thermostat/apip seed <= 0"); }
|
||||
iarg++;
|
||||
|
||||
} else if (strcmp(arg[iarg], "store_atomic_forces") == 0) {
|
||||
if (iarg + 1 >= narg)
|
||||
error->all(FLERR, "fix lambda_thermostat/apip: store_atomic_forces requires one argument");
|
||||
peratom_flag = 1;
|
||||
peratom_freq = utils::inumeric(FLERR, arg[iarg + 1], false, lmp);
|
||||
if (peratom_freq < 1)
|
||||
error->all(FLERR, "fix lambda_thermostat/apip: frequency of store_atomic_forces < 1");
|
||||
iarg++;
|
||||
|
||||
} else if (strcmp(arg[iarg], "N_rescaling") == 0) {
|
||||
if (iarg + 1 >= narg)
|
||||
error->all(FLERR, "fix lambda_thermostat/apip: mode number requires one argument");
|
||||
rescaling_N_neighbours = utils::inumeric(FLERR, arg[iarg + 1], false, lmp);
|
||||
iarg += 1;
|
||||
|
||||
} else
|
||||
error->all(FLERR, "fix lambda_thermostat/apip: unknown argument {}", arg[iarg]);
|
||||
}
|
||||
|
||||
// error checks
|
||||
|
||||
if (!atom->apip_e_fast_flag) {
|
||||
error->all(FLERR, "fix lambda_thermostat/apip requires atomic style with e_simple.");
|
||||
}
|
||||
if (!atom->apip_e_precise_flag) {
|
||||
error->all(FLERR, "fix lambda_thermostat/apip requires atomic style with e_complex.");
|
||||
}
|
||||
if (!atom->apip_lambda_const_flag) {
|
||||
error->all(FLERR, "fix lambda_thermostat/apip requires atomic style with lambda_const.");
|
||||
}
|
||||
if (!atom->apip_lambda_flag) {
|
||||
error->all(FLERR, "fix lambda_thermostat/apip requires atomic style with lambda.");
|
||||
}
|
||||
if (!atom->apip_f_const_lambda_flag) {
|
||||
error->all(FLERR, "fix lambda_thermostat/apip requires atomic style with f_const_lambda.");
|
||||
}
|
||||
if (!atom->apip_f_dyn_lambda_flag) {
|
||||
error->all(FLERR, "fix lambda_thermostat/apip requires atomic style with f_dyn_lambda.");
|
||||
}
|
||||
if (rescaling_N_neighbours <= 1)
|
||||
error->all(FLERR, "fix lambda_thermostat/apip: rescaling_N_neighbours <= 1");
|
||||
|
||||
// rng for shuffle
|
||||
random_mt = std::mt19937(seed);
|
||||
|
||||
// init output values
|
||||
energy_change_kin = energy_change_pot = 0;
|
||||
nmax_energy = 0;
|
||||
|
||||
reduceflag = 0;
|
||||
for (int i = 0; i < size_vector; i++) { outvec[i] = 0; }
|
||||
sum_energy_change = sum_energy_violation = 0;
|
||||
n_energy_violation = n_energy_differences = 0;
|
||||
|
||||
if (peratom_flag) {
|
||||
// zero the array since dump may access it on timestep 0
|
||||
// zero the array since a variable may access it before first run
|
||||
|
||||
nmax_stats = atom->nmax;
|
||||
memory->create(peratom_stats, nmax_stats, size_peratom_cols,
|
||||
"lambda_thermostat/apip:peratom_stats");
|
||||
array_atom = peratom_stats;
|
||||
|
||||
int nlocal = atom->nlocal;
|
||||
for (int i = 0; i < nlocal; i++)
|
||||
for (int j = 0; j < size_peratom_cols; j++) peratom_stats[i][j] = 0;
|
||||
} else {
|
||||
nmax_stats = 0;
|
||||
}
|
||||
|
||||
nmax_list = 0;
|
||||
pgsize = oneatom = 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FixLambdaThermostatAPIP::~FixLambdaThermostatAPIP()
|
||||
{
|
||||
memory->destroy(energy_change_atom);
|
||||
memory->destroy(peratom_stats);
|
||||
|
||||
memory->destroy(local_numneigh);
|
||||
memory->sfree(local_firstneigh);
|
||||
memory->destroy(jlist_copy);
|
||||
delete[] ipage;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int FixLambdaThermostatAPIP::setmask()
|
||||
{
|
||||
int mask = 0;
|
||||
mask |= POST_FORCE;
|
||||
mask |= END_OF_STEP;
|
||||
return mask;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixLambdaThermostatAPIP::init()
|
||||
{
|
||||
dtf = 0.5 * update->dt * force->ftm2v;
|
||||
|
||||
// full neighbour list for thermostating
|
||||
neighbor->add_request(this, NeighConst::REQ_FULL);
|
||||
|
||||
int counter = 0;
|
||||
for (int i = 0; i < modify->nfix; i++)
|
||||
if (strcmp(modify->fix[i]->style, "lambda_thermostat/apip") == 0) counter++;
|
||||
if (counter > 1)
|
||||
error->all(FLERR, "fix lambda_thermostat/apip: more than one fix lambda_thermostat/apip");
|
||||
|
||||
// local neighbor list
|
||||
// create pages if first time or if neighbor pgsize/oneatom has changed
|
||||
|
||||
int create = 0;
|
||||
if (ipage == nullptr) create = 1;
|
||||
if (pgsize != neighbor->pgsize) create = 1;
|
||||
if (oneatom != neighbor->oneatom) create = 1;
|
||||
|
||||
if (oneatom != neighbor->oneatom || ipage == nullptr) {
|
||||
// allocate memory for copy of one ngh list
|
||||
memory->destroy(jlist_copy);
|
||||
memory->create(jlist_copy, neighbor->oneatom, "lambda_thermostat/apip:jlist_copy");
|
||||
}
|
||||
|
||||
if (create) {
|
||||
delete[] ipage;
|
||||
pgsize = neighbor->pgsize;
|
||||
oneatom = neighbor->oneatom;
|
||||
|
||||
int nmypage = comm->nthreads;
|
||||
ipage = new MyPage<int>[nmypage];
|
||||
for (int i = 0; i < nmypage; i++) ipage[i].init(oneatom, pgsize, PGDELTA);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixLambdaThermostatAPIP::init_list(int /*id*/, NeighList *ptr)
|
||||
{
|
||||
list = ptr;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Create neighbor list from main neighbor list with local atoms only.
|
||||
The velocity updates are dependent on the velocity.
|
||||
Thus, one would need to communicate a velocity change of a ghost atom directly to all neighbouring processors.
|
||||
This communication would kill the performance.
|
||||
Thus, update only local particles.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void FixLambdaThermostatAPIP::local_neighbour_list()
|
||||
{
|
||||
int i, j, ii, jj, n, inum, jnum, nlocal;
|
||||
int *ilist, *jlist, *numneigh, **firstneigh;
|
||||
int *neighptr;
|
||||
int *mask = atom->mask;
|
||||
|
||||
if (atom->nmax > nmax_list) {
|
||||
nmax_list = atom->nmax;
|
||||
memory->destroy(local_numneigh);
|
||||
memory->sfree(local_firstneigh);
|
||||
memory->create(local_numneigh, nmax_list, "lambda_thermostat/apip:numneigh");
|
||||
local_firstneigh =
|
||||
(int **) memory->smalloc(nmax_list * sizeof(int *), "lambda_thermostat/apip:firstneigh");
|
||||
}
|
||||
|
||||
nlocal = atom->nlocal;
|
||||
inum = list->inum;
|
||||
ilist = list->ilist;
|
||||
numneigh = list->numneigh;
|
||||
firstneigh = list->firstneigh;
|
||||
|
||||
// store all local neighbours of local atoms
|
||||
// scan full neighbor list of I
|
||||
|
||||
ipage->reset();
|
||||
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
|
||||
n = 0;
|
||||
neighptr = ipage->vget();
|
||||
|
||||
jlist = firstneigh[i];
|
||||
jnum = numneigh[i];
|
||||
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
j = jlist[jj];
|
||||
j &= NEIGHMASK;
|
||||
if (j < nlocal && mask[j] & groupbit) neighptr[n++] = j;
|
||||
}
|
||||
|
||||
local_firstneigh[i] = neighptr;
|
||||
local_numneigh[i] = n;
|
||||
ipage->vgot(n);
|
||||
if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double FixLambdaThermostatAPIP::calculate_kinetic_energy(int i)
|
||||
{
|
||||
double *v = atom->v[i];
|
||||
double m = (atom->rmass ? atom->rmass[i] : atom->mass[atom->type[i]]);
|
||||
return 0.5 * force->mvv2e * m * (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixLambdaThermostatAPIP::post_force(int /*vflag*/)
|
||||
{
|
||||
init_peratom_stats();
|
||||
calculate_energy_change();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixLambdaThermostatAPIP::end_of_step()
|
||||
{
|
||||
apply_thermostat();
|
||||
}
|
||||
|
||||
/**
|
||||
* Init per-atom array with zeros.
|
||||
*/
|
||||
|
||||
void FixLambdaThermostatAPIP::init_peratom_stats()
|
||||
{
|
||||
if ((!peratom_flag) || (update->ntimestep % peratom_freq != 0)) {
|
||||
update_stats = false;
|
||||
return;
|
||||
}
|
||||
|
||||
update_stats = true;
|
||||
int nlocal;
|
||||
|
||||
nlocal = atom->nlocal;
|
||||
|
||||
// grow stats array if required
|
||||
if (atom->nmax > nmax_stats) {
|
||||
memory->destroy(peratom_stats);
|
||||
nmax_stats = atom->nmax;
|
||||
memory->create(peratom_stats, nmax_stats, size_peratom_cols,
|
||||
"lambda_thermostat/apip:peratom_stats");
|
||||
array_atom = peratom_stats;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nlocal; i++)
|
||||
peratom_stats[i][0] = peratom_stats[i][1] = peratom_stats[i][2] = peratom_stats[i][3] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the energy difference of atoms that needs to be corrected
|
||||
* by the local thermostat.
|
||||
*/
|
||||
|
||||
void FixLambdaThermostatAPIP::calculate_energy_change()
|
||||
{
|
||||
double **v = atom->v;
|
||||
double *rmass = atom->rmass;
|
||||
double *mass = atom->mass;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int nlocal = atom->nlocal;
|
||||
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
|
||||
|
||||
double *e_simple = atom->apip_e_fast;
|
||||
double *e_complex = atom->apip_e_precise;
|
||||
double *lambda_const = atom->apip_lambda_const;
|
||||
double *lambda = atom->apip_lambda;
|
||||
double **f_const_lambda = atom->apip_f_const_lambda;
|
||||
double **f_dyn_lambda = atom->apip_f_dyn_lambda;
|
||||
|
||||
double masstmp, dtfm, changetmp;
|
||||
|
||||
// allocate memory for energy change
|
||||
if (atom->nmax > nmax_energy) {
|
||||
memory->destroy(energy_change_atom);
|
||||
nmax_energy = atom->nmax;
|
||||
memory->create(energy_change_atom, nmax_energy, "lambda_thermostat/apip:energy_change_atom");
|
||||
}
|
||||
|
||||
// reset calculated changes
|
||||
energy_change_pot = 0;
|
||||
energy_change_kin = 0;
|
||||
for (int i = 0; i < nlocal; i++) { energy_change_atom[i] = 0; }
|
||||
|
||||
// calculate potential energy differences
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if ((!(mask[i] & groupbit)) || lambda_const[i] == lambda[i]) { continue; }
|
||||
|
||||
if (e_simple[i] == 0 || e_complex[i] == 0)
|
||||
error->one(FLERR, "lambda = {} != {} = lambda_const and e_simple = {} and e_complex = {}",
|
||||
lambda[i], lambda_const[i], e_simple[i], e_complex[i]);
|
||||
changetmp =
|
||||
(lambda_const[i] - lambda[i]) * e_simple[i] + (lambda[i] - lambda_const[i]) * e_complex[i];
|
||||
|
||||
energy_change_atom[i] += changetmp;
|
||||
energy_change_pot += changetmp;
|
||||
}
|
||||
|
||||
// calculate kinetic energy difference
|
||||
// consider all local atoms
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (!(mask[i] & groupbit)) { continue; }
|
||||
|
||||
masstmp = (rmass ? rmass[i] : mass[type[i]]);
|
||||
dtfm = dtf / masstmp;
|
||||
// dtfm = Delta t / 2 (in corresponding units)
|
||||
changetmp = (v[i][0] * 2 * dtfm * (f_const_lambda[i][0] - f_dyn_lambda[i][0]) +
|
||||
dtfm * dtfm *
|
||||
(f_const_lambda[i][0] * f_const_lambda[i][0] -
|
||||
f_dyn_lambda[i][0] * f_dyn_lambda[i][0]) +
|
||||
v[i][1] * 2 * dtfm * (f_const_lambda[i][1] - f_dyn_lambda[i][1]) +
|
||||
dtfm * dtfm *
|
||||
(f_const_lambda[i][1] * f_const_lambda[i][1] -
|
||||
f_dyn_lambda[i][1] * f_dyn_lambda[i][1]) +
|
||||
v[i][2] * 2 * dtfm * (f_const_lambda[i][2] - f_dyn_lambda[i][2]) +
|
||||
dtfm * dtfm *
|
||||
(f_const_lambda[i][2] * f_const_lambda[i][2] -
|
||||
f_dyn_lambda[i][2] * f_dyn_lambda[i][2])) *
|
||||
masstmp * force->mvv2e * 0.5;
|
||||
|
||||
energy_change_atom[i] += changetmp;
|
||||
energy_change_kin += changetmp;
|
||||
}
|
||||
|
||||
if (update_stats) {
|
||||
for (int i = 0; i < nlocal; i++) peratom_stats[i][4] = energy_change_atom[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixLambdaThermostatAPIP::apply_thermostat()
|
||||
{
|
||||
double xtmp, ytmp, ztmp, delx, dely, delz, delvx, delvy, delvz, r, dotvu, masstmp, massj, muij,
|
||||
delv, delv_m, epsilon, epsilonsq, deltaK, rinv;
|
||||
double m_cm, v_cm[3], beta_rescaling, k_rel, v_rel[3], radicand;
|
||||
int i, ii, inum, *ilist;
|
||||
int j, jj, jnum, *jlist;
|
||||
|
||||
int nlocal = atom->nlocal;
|
||||
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
|
||||
|
||||
double **x = atom->x;
|
||||
double **v = atom->v;
|
||||
double *rmass = atom->rmass;
|
||||
double *mass = atom->mass;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
|
||||
double *e_simple = atom->apip_e_fast;
|
||||
double *e_complex = atom->apip_e_precise;
|
||||
double *lambda_const = atom->apip_lambda_const;
|
||||
double *lambda = atom->apip_lambda;
|
||||
|
||||
// calculate local neighbour list without ghost atoms
|
||||
local_neighbour_list();
|
||||
|
||||
inum = list->inum;
|
||||
ilist = list->ilist;
|
||||
|
||||
// reset stats
|
||||
// outvec has to be calculated again
|
||||
reduceflag = 1;
|
||||
sum_energy_change = 0;
|
||||
n_energy_differences = 0;
|
||||
|
||||
// perform bath collisions
|
||||
// consider all local atoms
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
|
||||
if (!(mask[i] & groupbit)) { continue; }
|
||||
if (energy_change_atom[i] == 0) { continue; }
|
||||
|
||||
// update stats
|
||||
n_energy_differences++;
|
||||
|
||||
// store constant information of target atom
|
||||
masstmp = (rmass ? rmass[i] : mass[type[i]]);
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
|
||||
// get neighbour list
|
||||
jlist = local_firstneigh[i];
|
||||
jnum = local_numneigh[i];
|
||||
|
||||
if (jnum == 0)
|
||||
error->one(FLERR,
|
||||
"fix lambda_thermostat/apip: thermostating required for particle with no local "
|
||||
"particles in neighbour list particle: {} {} {} groupbit {}\n",
|
||||
xtmp, ytmp, ztmp, mask[i] & groupbit);
|
||||
|
||||
int i_collisions = 0;
|
||||
double e_remain = energy_change_atom[i];
|
||||
|
||||
// copy ngh list
|
||||
for (jj = 0; jj < jnum; jj++) jlist_copy[jj] = jlist[jj];
|
||||
// shuffle neighbour list for random rescaling set
|
||||
std::shuffle(jlist_copy, jlist_copy + jnum, random_mt);
|
||||
|
||||
// rescale velocities relative to centre of mass velocity
|
||||
const int n_ngh = MIN(rescaling_N_neighbours, jnum);
|
||||
if (n_ngh < 2)
|
||||
error->one(FLERR,
|
||||
"fix lambda_thermostat/apip: rescaling not possible for local ngh list size {}",
|
||||
jnum);
|
||||
// 1. calculate centre of mass velocity
|
||||
|
||||
// start with own particle ...
|
||||
m_cm = masstmp;
|
||||
v_cm[0] = masstmp * v[i][0];
|
||||
v_cm[1] = masstmp * v[i][1];
|
||||
v_cm[2] = masstmp * v[i][2];
|
||||
// ... and include neighbours
|
||||
for (jj = 0; jj < n_ngh; jj++) {
|
||||
j = jlist_copy[jj];
|
||||
j &= NEIGHMASK;
|
||||
|
||||
massj = (rmass ? rmass[j] : mass[type[j]]);
|
||||
|
||||
m_cm += massj;
|
||||
v_cm[0] += massj * v[j][0];
|
||||
v_cm[1] += massj * v[j][1];
|
||||
v_cm[2] += massj * v[j][2];
|
||||
}
|
||||
// normalisation
|
||||
v_cm[0] /= m_cm;
|
||||
v_cm[1] /= m_cm;
|
||||
v_cm[2] /= m_cm;
|
||||
|
||||
// 2. calculate beta_rescaling
|
||||
// calculate kinetic energy of relative velocity for own particle ...
|
||||
v_rel[0] = v[i][0] - v_cm[0];
|
||||
v_rel[1] = v[i][1] - v_cm[1];
|
||||
v_rel[2] = v[i][2] - v_cm[2];
|
||||
k_rel = masstmp * (v_rel[0] * v_rel[0] + v_rel[1] * v_rel[1] + v_rel[2] * v_rel[2]);
|
||||
// ... and include neighbours
|
||||
for (jj = 0; jj < n_ngh; jj++) {
|
||||
j = jlist_copy[jj];
|
||||
j &= NEIGHMASK;
|
||||
|
||||
massj = (rmass ? rmass[j] : mass[type[j]]);
|
||||
v_rel[0] = v[j][0] - v_cm[0];
|
||||
v_rel[1] = v[j][1] - v_cm[1];
|
||||
v_rel[2] = v[j][2] - v_cm[2];
|
||||
k_rel += massj * (v_rel[0] * v_rel[0] + v_rel[1] * v_rel[1] + v_rel[2] * v_rel[2]);
|
||||
}
|
||||
// normalisation
|
||||
k_rel *= force->mvv2e / 2.0;
|
||||
radicand = e_remain / k_rel + 1;
|
||||
if (radicand < 0) {
|
||||
// cooling is not possible
|
||||
// e_remain is the requested energy change
|
||||
// radicand = 0 <=> e_remain = -k_rel
|
||||
// -> save the energy error
|
||||
sum_energy_violation += (-e_remain - k_rel); // > 0
|
||||
n_energy_violation++;
|
||||
e_remain += k_rel; // save corrected part
|
||||
// use smallest possible radicand
|
||||
radicand = 0;
|
||||
}
|
||||
beta_rescaling = sqrt(radicand) - 1;
|
||||
|
||||
// 3. apply velocity changes
|
||||
// start with own particle ...
|
||||
v_rel[0] = beta_rescaling * (v[i][0] - v_cm[0]);
|
||||
v_rel[1] = beta_rescaling * (v[i][1] - v_cm[1]);
|
||||
v_rel[2] = beta_rescaling * (v[i][2] - v_cm[2]);
|
||||
|
||||
v[i][0] += v_rel[0];
|
||||
v[i][1] += v_rel[1];
|
||||
v[i][2] += v_rel[2];
|
||||
|
||||
if (update_stats) {
|
||||
// forces
|
||||
peratom_stats[i][0] += v_rel[0] * masstmp / dtf;
|
||||
peratom_stats[i][1] += v_rel[1] * masstmp / dtf;
|
||||
peratom_stats[i][2] += v_rel[2] * masstmp / dtf;
|
||||
}
|
||||
|
||||
// ... continue with neighbours
|
||||
for (jj = 0; jj < n_ngh; jj++) {
|
||||
j = jlist_copy[jj];
|
||||
j &= NEIGHMASK;
|
||||
|
||||
v_rel[0] = beta_rescaling * (v[j][0] - v_cm[0]);
|
||||
v_rel[1] = beta_rescaling * (v[j][1] - v_cm[1]);
|
||||
v_rel[2] = beta_rescaling * (v[j][2] - v_cm[2]);
|
||||
v[j][0] += v_rel[0];
|
||||
v[j][1] += v_rel[1];
|
||||
v[j][2] += v_rel[2];
|
||||
|
||||
if (update_stats) {
|
||||
// forces
|
||||
massj = (rmass ? rmass[j] : mass[type[j]]);
|
||||
peratom_stats[j][0] += v_rel[0] * massj / dtf;
|
||||
peratom_stats[j][1] += v_rel[1] * massj / dtf;
|
||||
peratom_stats[j][2] += v_rel[2] * massj / dtf;
|
||||
}
|
||||
}
|
||||
sum_energy_change += fabs(e_remain);
|
||||
}
|
||||
|
||||
// lambda_const is used -> reset to lambda
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
if (mask[i] & groupbit) lambda_const[i] = lambda[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double FixLambdaThermostatAPIP::compute_vector(int i)
|
||||
{
|
||||
// 0 # atoms with energy differences compared to lambda_const
|
||||
// 1 # bath collisions
|
||||
// 2 total change of potential energy compared to lambda_const (sum over all atoms)
|
||||
// 3 total change of kinetic energy compared to lambda_const (sum over all atoms)
|
||||
// 4 total energy change due to thermostat
|
||||
if (reduceflag) {
|
||||
// perform reduction only once per step (if at all)
|
||||
outvec[0] = n_energy_differences;
|
||||
outvec[1] = energy_change_pot;
|
||||
outvec[2] = energy_change_kin;
|
||||
outvec[3] = sum_energy_change;
|
||||
outvec[4] = sum_energy_violation;
|
||||
outvec[5] = n_energy_violation;
|
||||
MPI_Allreduce(MPI_IN_PLACE, &outvec, size_vector, MPI_DOUBLE, MPI_SUM, world);
|
||||
reduceflag = 0;
|
||||
}
|
||||
|
||||
if (i < size_vector) return outvec[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixLambdaThermostatAPIP::reset_dt()
|
||||
{
|
||||
dtf = 0.5 * update->dt * force->ftm2v;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
memory usage of local atom-based arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double FixLambdaThermostatAPIP::memory_usage()
|
||||
{
|
||||
double bytes = 0;
|
||||
bytes += (double) nmax_energy * sizeof(double);
|
||||
|
||||
bytes += (double) nmax_stats * size_peratom_cols * sizeof(double);
|
||||
|
||||
bytes += (double) nmax_list * sizeof(int);
|
||||
bytes += (double) nmax_list * sizeof(int *);
|
||||
for (int i = 0; i < comm->nthreads; i++) bytes += ipage[i].size();
|
||||
|
||||
return bytes;
|
||||
}
|
||||
88
src/APIP/fix_lambda_thermostat_apip.h
Normal file
88
src/APIP/fix_lambda_thermostat_apip.h
Normal file
@ -0,0 +1,88 @@
|
||||
/* -*- 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 author: David Immel (d.immel@fz-juelich.de, FZJ, Germany)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef FIX_CLASS
|
||||
// clang-format off
|
||||
FixStyle(lambda_thermostat/apip,FixLambdaThermostatAPIP);
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
#ifndef LMP_FIX_LAMBDA_THERMOSTAT_APIP_H
|
||||
#define LMP_FIX_LAMBDA_THERMOSTAT_APIP_H
|
||||
|
||||
#include "fix.h"
|
||||
#include <random>
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class FixLambdaThermostatAPIP : public Fix {
|
||||
public:
|
||||
FixLambdaThermostatAPIP(class LAMMPS *, int, char **);
|
||||
~FixLambdaThermostatAPIP() override;
|
||||
|
||||
int setmask() override;
|
||||
void init() override;
|
||||
void init_list(int, class NeighList *) override;
|
||||
void post_force(int) override;
|
||||
void end_of_step() override;
|
||||
double memory_usage() override;
|
||||
void reset_dt() override;
|
||||
double compute_vector(int) override;
|
||||
|
||||
protected:
|
||||
void apply_thermostat();
|
||||
void calculate_energy_change();
|
||||
double calculate_kinetic_energy(int);
|
||||
void local_neighbour_list();
|
||||
void init_peratom_stats();
|
||||
|
||||
double dtf; // constant for time integration
|
||||
|
||||
class NeighList *list;
|
||||
double *energy_change_atom; // energy violation compared to const lambda case
|
||||
double **peratom_stats; // peratom output
|
||||
int nmax_energy; // number of atoms for which energy_change_atom is allocated
|
||||
int nmax_stats; // number of atoms for which peratom_stats is allocated
|
||||
|
||||
// own neighbour list
|
||||
int pgsize; // size of neighbor page
|
||||
int oneatom; // max # of neighbors for one atom
|
||||
int nmax_list; // size of numneigh, firstneigh arrays
|
||||
int *local_numneigh; // # of pair neighbors for each atom
|
||||
int **local_firstneigh; // ptr to 1st neighbor of each atom
|
||||
MyPage<int> *ipage; // neighbor list pages
|
||||
int *jlist_copy; // jlist for one atom
|
||||
|
||||
int reduceflag; // 1/0 calculation of compute_vector required/not required
|
||||
double outvec[6]; // vector returned by compute_vector
|
||||
double energy_change_pot; // energy conservation violation of all atoms
|
||||
double energy_change_kin; // energy conservation violation of all atoms
|
||||
int n_energy_differences; // number of atoms whose energy has changed compared to the constant lambda case
|
||||
double sum_energy_change; // absolute value of all energy changes due to rescaling
|
||||
double sum_energy_violation; // energy that could not be compensated, accumulated over time
|
||||
int n_energy_violation; // number of atoms whose energy could not be compensated, accumulated over time
|
||||
|
||||
int rescaling_N_neighbours; // requested neighbour list size used for rescaling
|
||||
|
||||
std::mt19937 random_mt; // mersenne twister for shuffle
|
||||
|
||||
bool update_stats; // true(false) peratom output needs(not) to be calculated
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
978
src/APIP/pair_eam_apip.cpp
Normal file
978
src/APIP/pair_eam_apip.cpp
Normal file
@ -0,0 +1,978 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
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: Stephen Foiles (SNL), Murray Daw (SNL) (EAM)
|
||||
David Immel (d.immel@fz-juelich.de, FZJ, Germany) for APIP
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "pair_eam_apip.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "atom_vec_apip.h"
|
||||
#include "comm.h"
|
||||
#include "error.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
#include "modify.h"
|
||||
#include "neigh_list.h"
|
||||
#include "neighbor.h"
|
||||
#include "potential_file_reader.h"
|
||||
#include "update.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairEAMAPIP::PairEAMAPIP(LAMMPS *lmp) : Pair(lmp)
|
||||
{
|
||||
restartinfo = 0;
|
||||
manybody_flag = 1;
|
||||
unit_convert_flag = utils::get_supported_conversions(utils::ENERGY);
|
||||
|
||||
nmax = 0;
|
||||
rho = nullptr;
|
||||
fp = nullptr;
|
||||
numforce = nullptr;
|
||||
type2frho = nullptr;
|
||||
|
||||
nfuncfl = 0;
|
||||
funcfl = nullptr;
|
||||
|
||||
setfl = nullptr;
|
||||
fs = nullptr;
|
||||
|
||||
frho = nullptr;
|
||||
rhor = nullptr;
|
||||
z2r = nullptr;
|
||||
scale = nullptr;
|
||||
|
||||
rhomax = rhomin = 0.0;
|
||||
|
||||
frho_spline = nullptr;
|
||||
rhor_spline = nullptr;
|
||||
z2r_spline = nullptr;
|
||||
|
||||
n_non_complex_accumulated = 0;
|
||||
time_per_atom = -1;
|
||||
time_wall_accumulated = 0;
|
||||
|
||||
lambda_thermostat = true;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
check if allocated, since class can be destructed when incomplete
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
PairEAMAPIP::~PairEAMAPIP()
|
||||
{
|
||||
if (copymode) return;
|
||||
|
||||
memory->destroy(rho);
|
||||
memory->destroy(fp);
|
||||
memory->destroy(numforce);
|
||||
|
||||
if (allocated) {
|
||||
memory->destroy(setflag);
|
||||
memory->destroy(cutsq);
|
||||
delete[] type2frho;
|
||||
type2frho = nullptr;
|
||||
memory->destroy(type2rhor);
|
||||
memory->destroy(type2z2r);
|
||||
memory->destroy(scale);
|
||||
}
|
||||
|
||||
if (funcfl) {
|
||||
for (int i = 0; i < nfuncfl; i++) {
|
||||
delete[] funcfl[i].file;
|
||||
memory->destroy(funcfl[i].frho);
|
||||
memory->destroy(funcfl[i].rhor);
|
||||
memory->destroy(funcfl[i].zr);
|
||||
}
|
||||
memory->sfree(funcfl);
|
||||
funcfl = nullptr;
|
||||
}
|
||||
|
||||
if (setfl) {
|
||||
for (int i = 0; i < setfl->nelements; i++) delete[] setfl->elements[i];
|
||||
delete[] setfl->elements;
|
||||
memory->destroy(setfl->mass);
|
||||
memory->destroy(setfl->frho);
|
||||
memory->destroy(setfl->rhor);
|
||||
memory->destroy(setfl->z2r);
|
||||
delete setfl;
|
||||
setfl = nullptr;
|
||||
}
|
||||
|
||||
if (fs) {
|
||||
for (int i = 0; i < fs->nelements; i++) delete[] fs->elements[i];
|
||||
delete[] fs->elements;
|
||||
memory->destroy(fs->mass);
|
||||
memory->destroy(fs->frho);
|
||||
memory->destroy(fs->rhor);
|
||||
memory->destroy(fs->z2r);
|
||||
delete fs;
|
||||
fs = nullptr;
|
||||
}
|
||||
|
||||
memory->destroy(frho);
|
||||
memory->destroy(rhor);
|
||||
memory->destroy(z2r);
|
||||
|
||||
memory->destroy(frho_spline);
|
||||
memory->destroy(rhor_spline);
|
||||
memory->destroy(z2r_spline);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMAPIP::compute(int eflag, int vflag)
|
||||
{
|
||||
// start timers
|
||||
double time_wall_start = platform::walltime();
|
||||
int n_non_complex = 0;
|
||||
|
||||
int i, j, ii, jj, m, inum, jnum, itype, jtype;
|
||||
double xtmp, ytmp, ztmp, delx, dely, delz, evdwl, fpair, lambda_ij, fpair_cl;
|
||||
double rsq, r, p, rhoip, rhojp, z2, z2p, recip, phip, psip, phi, psip_cl;
|
||||
double *coeff;
|
||||
int *ilist, *jlist, *numneigh, **firstneigh;
|
||||
|
||||
evdwl = 0.0;
|
||||
ev_init(eflag, vflag);
|
||||
|
||||
// grow energy and fp arrays if necessary
|
||||
// need to be atom->nmax in length
|
||||
|
||||
if (atom->nmax > nmax) {
|
||||
memory->destroy(rho);
|
||||
memory->destroy(fp);
|
||||
memory->destroy(numforce);
|
||||
nmax = atom->nmax;
|
||||
memory->create(rho, nmax, "pair:rho");
|
||||
memory->create(fp, nmax, "pair:fp");
|
||||
memory->create(numforce, nmax, "pair:numforce");
|
||||
}
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
double *lambda = atom->apip_lambda;
|
||||
int *lambda_required = atom->apip_lambda_required;
|
||||
|
||||
double **f_const_lambda = nullptr;
|
||||
double **f_dyn_lambda = nullptr;
|
||||
double *e_simple = nullptr;
|
||||
double *lambda_const = nullptr;
|
||||
if (lambda_thermostat) {
|
||||
f_const_lambda = atom->apip_f_const_lambda;
|
||||
f_dyn_lambda = atom->apip_f_dyn_lambda;
|
||||
e_simple = atom->apip_e_fast;
|
||||
lambda_const = atom->apip_lambda_const;
|
||||
}
|
||||
int *type = atom->type;
|
||||
int nlocal = atom->nlocal;
|
||||
int nall = nlocal + atom->nghost;
|
||||
int newton_pair = force->newton_pair;
|
||||
|
||||
inum = list->inum;
|
||||
ilist = list->ilist;
|
||||
numneigh = list->numneigh;
|
||||
firstneigh = list->firstneigh;
|
||||
|
||||
// zero out density
|
||||
|
||||
for (i = 0; i < nlocal; i++) rho[i] = 0.0;
|
||||
|
||||
// rho = density at each atom
|
||||
// loop over neighbors of my atoms
|
||||
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
itype = type[i];
|
||||
jlist = firstneigh[i];
|
||||
jnum = numneigh[i];
|
||||
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
j = jlist[jj];
|
||||
j &= NEIGHMASK;
|
||||
|
||||
// avoid double counting due to full neighbour list for two local particles
|
||||
// j < i implies j < nlocal
|
||||
if (j < i && i < nlocal) { continue; }
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx * delx + dely * dely + delz * delz;
|
||||
|
||||
if (rsq < cutforcesq) {
|
||||
jtype = type[j];
|
||||
p = sqrt(rsq) * rdr + 1.0;
|
||||
m = static_cast<int>(p);
|
||||
m = MIN(m, nr - 1);
|
||||
p -= m;
|
||||
p = MIN(p, 1.0);
|
||||
coeff = rhor_spline[type2rhor[jtype][itype]][m];
|
||||
rho[i] += ((coeff[3] * p + coeff[4]) * p + coeff[5]) * p + coeff[6];
|
||||
|
||||
// do not calculate rho for ghost atoms
|
||||
if (j < nlocal) {
|
||||
coeff = rhor_spline[type2rhor[itype][jtype]][m];
|
||||
rho[j] += ((coeff[3] * p + coeff[4]) * p + coeff[5]) * p + coeff[6];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fp = derivative of embedding energy at each atom
|
||||
// phi = embedding energy at each atom
|
||||
// if rho > rhomax (e.g. due to close approach of two atoms),
|
||||
// will exceed table, so add linear term to conserve energy
|
||||
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
p = rho[i] * rdrho + 1.0;
|
||||
m = static_cast<int>(p);
|
||||
m = MAX(1, MIN(m, nrho - 1));
|
||||
p -= m;
|
||||
p = MIN(p, 1.0);
|
||||
coeff = frho_spline[type2frho[type[i]]][m];
|
||||
fp[i] = (coeff[0] * p + coeff[1]) * p + coeff[2];
|
||||
if (eflag || e_simple) {
|
||||
phi = ((coeff[3] * p + coeff[4]) * p + coeff[5]) * p + coeff[6];
|
||||
if (rho[i] > rhomax) phi += fp[i] * (rho[i] - rhomax);
|
||||
phi *= scale[type[i]][type[i]];
|
||||
ev_tally_full(i, 2.0 * lambda[i] * phi, 0.0, 0.0, 0.0, 0.0, 0.0);
|
||||
if (e_simple) { e_simple[i] = phi; }
|
||||
}
|
||||
}
|
||||
|
||||
// compute forces on each atom
|
||||
// loop over neighbors of my atoms
|
||||
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
itype = type[i];
|
||||
|
||||
jlist = firstneigh[i];
|
||||
jnum = numneigh[i];
|
||||
numforce[i] = 0;
|
||||
|
||||
// The distances between atoms are not calculated.
|
||||
// The neighbour list contains more than the cutoff atoms.
|
||||
// The calculation of distances is probably not worth the compute time.
|
||||
// lambda_required is used to compute the weight of atoms for load balancing.
|
||||
// -> store information about required calculations
|
||||
if (lambda_required[i] & ApipLambdaRequired::NO_SIMPLE)
|
||||
continue;
|
||||
else if (!(lambda_required[i] & ApipLambdaRequired::SIMPLE)) {
|
||||
// neither SIMPLE nor NO_SIMPLE set
|
||||
|
||||
// check own atom
|
||||
if (lambda[i] != 0 || (lambda_thermostat && lambda_const[i] != 0)) {
|
||||
// set own atom
|
||||
lambda_required[i] |= ApipLambdaRequired::SIMPLE;
|
||||
// set neighbour list
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
j = jlist[jj];
|
||||
j &= NEIGHMASK;
|
||||
if (j < nlocal) lambda_required[j] |= ApipLambdaRequired::SIMPLE;
|
||||
}
|
||||
} else {
|
||||
// check neighbour list
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
j = jlist[jj];
|
||||
j &= NEIGHMASK;
|
||||
if (lambda[j] != 0 || (lambda_thermostat && lambda_const[j] != 0)) {
|
||||
lambda_required[i] |= ApipLambdaRequired::SIMPLE;
|
||||
// set lambda also for non-ghost j
|
||||
if (j < nlocal) lambda_required[j] |= ApipLambdaRequired::SIMPLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// SIMPLE not set -> set NO_SIMPLE
|
||||
if (!(lambda_required[i] & ApipLambdaRequired::SIMPLE)) {
|
||||
// go to next atom
|
||||
lambda_required[i] |= ApipLambdaRequired::NO_SIMPLE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
n_non_complex++;
|
||||
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
j = jlist[jj];
|
||||
j &= NEIGHMASK;
|
||||
|
||||
// avoid double counting due to full neighbour list for two local particles
|
||||
// j < i implies j < nlocal
|
||||
if (j < i && i < nlocal) { continue; }
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx * delx + dely * dely + delz * delz;
|
||||
|
||||
if (rsq < cutforcesq) {
|
||||
++numforce[i];
|
||||
jtype = type[j];
|
||||
r = sqrt(rsq);
|
||||
p = r * rdr + 1.0;
|
||||
m = static_cast<int>(p);
|
||||
m = MIN(m, nr - 1);
|
||||
p -= m;
|
||||
p = MIN(p, 1.0);
|
||||
|
||||
// rhoip = derivative of (density at atom j due to atom i)
|
||||
// rhojp = derivative of (density at atom i due to atom j)
|
||||
// phi = pair potential energy
|
||||
// phip = phi'
|
||||
// z2 = phi * r
|
||||
// z2p = (phi * r)' = (phi' r) + phi
|
||||
// psip needs both fp[i] and fp[j] terms since r_ij appears in two
|
||||
// terms of embed eng: Fi(sum rho_ij) and Fj(sum rho_ji)
|
||||
// hence embed' = Fi(sum rho_ij) rhojp + Fj(sum rho_ji) rhoip
|
||||
// scale factor can be applied by thermodynamic integration
|
||||
|
||||
coeff = rhor_spline[type2rhor[jtype][itype]][m];
|
||||
rhojp = (coeff[0] * p + coeff[1]) * p + coeff[2];
|
||||
coeff = z2r_spline[type2z2r[itype][jtype]][m];
|
||||
z2p = (coeff[0] * p + coeff[1]) * p + coeff[2];
|
||||
z2 = ((coeff[3] * p + coeff[4]) * p + coeff[5]) * p + coeff[6];
|
||||
|
||||
recip = 1.0 / r;
|
||||
phi = z2 * recip;
|
||||
phip = z2p * recip - phi * recip;
|
||||
if (j < nlocal) {
|
||||
coeff = rhor_spline[type2rhor[itype][jtype]][m];
|
||||
rhoip = (coeff[0] * p + coeff[1]) * p + coeff[2];
|
||||
psip = lambda[i] * fp[i] * rhojp + lambda[j] * fp[j] * rhoip +
|
||||
phip * (lambda[i] + lambda[j]) / 2;
|
||||
} else {
|
||||
// processor of j calculates the remaining terms (compared to psip in if case)
|
||||
psip = lambda[i] * fp[i] * rhojp + phip * 0.5 * lambda[i];
|
||||
}
|
||||
|
||||
fpair = -scale[itype][jtype] * psip * recip;
|
||||
|
||||
f[i][0] += delx * fpair;
|
||||
f[i][1] += dely * fpair;
|
||||
f[i][2] += delz * fpair;
|
||||
f[j][0] -= delx * fpair;
|
||||
f[j][1] -= dely * fpair;
|
||||
f[j][2] -= delz * fpair;
|
||||
if (lambda_thermostat) {
|
||||
|
||||
f_dyn_lambda[i][0] += delx * fpair;
|
||||
f_dyn_lambda[i][1] += dely * fpair;
|
||||
f_dyn_lambda[i][2] += delz * fpair;
|
||||
f_dyn_lambda[j][0] -= delx * fpair;
|
||||
f_dyn_lambda[j][1] -= dely * fpair;
|
||||
f_dyn_lambda[j][2] -= delz * fpair;
|
||||
|
||||
// psip_const
|
||||
if (j < nlocal) {
|
||||
psip_cl = lambda_const[i] * fp[i] * rhojp + lambda_const[j] * fp[j] * rhoip +
|
||||
phip * (lambda_const[i] + lambda_const[j]) / 2;
|
||||
} else {
|
||||
psip_cl = lambda_const[i] * fp[i] * rhojp + phip * 0.5 * lambda_const[i];
|
||||
}
|
||||
// calculate fpair_const
|
||||
fpair_cl = -scale[itype][jtype] * psip_cl * recip;
|
||||
// update f_const_lambda with fpair_const
|
||||
f_const_lambda[i][0] += delx * fpair_cl;
|
||||
f_const_lambda[i][1] += dely * fpair_cl;
|
||||
f_const_lambda[i][2] += delz * fpair_cl;
|
||||
f_const_lambda[j][0] -= delx * fpair_cl;
|
||||
f_const_lambda[j][1] -= dely * fpair_cl;
|
||||
f_const_lambda[j][2] -= delz * fpair_cl;
|
||||
}
|
||||
|
||||
if (eflag || e_simple) {
|
||||
evdwl = scale[itype][jtype] * phi;
|
||||
if (e_simple) {
|
||||
e_simple[i] += 0.5 * evdwl;
|
||||
if (j < nlocal) e_simple[j] += 0.5 * evdwl;
|
||||
}
|
||||
ev_tally_full(i, lambda[i] * evdwl, 0.0, 0.0, 0.0, 0.0, 0.0);
|
||||
if (j < nlocal) ev_tally_full(j, lambda[j] * evdwl, 0.0, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
if (vflag) ev_tally(i, j, nlocal, newton_pair, 0.0, 0.0, fpair, delx, dely, delz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vflag_fdotr) virial_fdotr_compute();
|
||||
|
||||
// stop timers
|
||||
time_wall_accumulated += platform::walltime() - time_wall_start;
|
||||
n_non_complex_accumulated += n_non_complex;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
allocate all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMAPIP::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->ntypes;
|
||||
|
||||
memory->create(setflag, n + 1, n + 1, "pair:setflag");
|
||||
for (int i = 1; i <= n; i++)
|
||||
for (int j = i; j <= n; j++) setflag[i][j] = 0;
|
||||
|
||||
memory->create(cutsq, n + 1, n + 1, "pair:cutsq");
|
||||
|
||||
delete[] map;
|
||||
map = new int[n + 1];
|
||||
for (int i = 1; i <= n; i++) map[i] = -1;
|
||||
|
||||
type2frho = new int[n + 1];
|
||||
memory->create(type2rhor, n + 1, n + 1, "pair:type2rhor");
|
||||
memory->create(type2z2r, n + 1, n + 1, "pair:type2z2r");
|
||||
memory->create(scale, n + 1, n + 1, "pair:scale");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
global settings
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMAPIP::settings(int narg, char ** /*arg*/)
|
||||
{
|
||||
if (narg > 0) error->all(FLERR, "Illegal pair_style command");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one or more type pairs
|
||||
read DYNAMO funcfl file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMAPIP::coeff(int narg, char **arg)
|
||||
{
|
||||
if (!allocated) allocate();
|
||||
|
||||
if (narg != 3) error->all(FLERR, "Incorrect args for pair coefficients");
|
||||
|
||||
// parse pair of atom types
|
||||
|
||||
int ilo, ihi, jlo, jhi;
|
||||
utils::bounds(FLERR, arg[0], 1, atom->ntypes, ilo, ihi, error);
|
||||
utils::bounds(FLERR, arg[1], 1, atom->ntypes, jlo, jhi, error);
|
||||
|
||||
// read funcfl file if hasn't already been read
|
||||
// store filename in Funcfl data struct
|
||||
|
||||
int ifuncfl;
|
||||
for (ifuncfl = 0; ifuncfl < nfuncfl; ifuncfl++)
|
||||
if (strcmp(arg[2], funcfl[ifuncfl].file) == 0) break;
|
||||
|
||||
if (ifuncfl == nfuncfl) {
|
||||
nfuncfl++;
|
||||
funcfl = (Funcfl *) memory->srealloc(funcfl, nfuncfl * sizeof(Funcfl), "pair:funcfl");
|
||||
read_file(arg[2]);
|
||||
funcfl[ifuncfl].file = utils::strdup(arg[2]);
|
||||
}
|
||||
|
||||
// set setflag and map only for i,i type pairs
|
||||
// set mass of atom type if i = j
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
for (int j = MAX(jlo, i); j <= jhi; j++) {
|
||||
if (i == j) {
|
||||
setflag[i][i] = 1;
|
||||
map[i] = ifuncfl;
|
||||
atom->set_mass(FLERR, i, funcfl[ifuncfl].mass);
|
||||
count++;
|
||||
}
|
||||
scale[i][j] = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) error->all(FLERR, "Incorrect args for pair coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init specific to this pair style
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMAPIP::init_style()
|
||||
{
|
||||
// convert read-in file(s) to arrays and spline them
|
||||
if (!atom->apip_lambda_flag)
|
||||
error->all(FLERR, "Pair style eam/apip requires an atom style with lambda");
|
||||
if (force->newton_pair == 0) error->all(FLERR, "Pair style eam/apip requires newton pair on");
|
||||
if (!atom->apip_lambda_required_flag)
|
||||
error->all(FLERR, "pair style eam/apip requires an atom style with lambda_required.");
|
||||
|
||||
file2array();
|
||||
array2spline();
|
||||
|
||||
// communication during computation should be avoided
|
||||
// -> do not exchange the derivative of the embedding function by default
|
||||
neighbor->add_request(this, NeighConst::REQ_FULL);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init for one type pair i,j and corresponding j,i
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double PairEAMAPIP::init_one(int i, int j)
|
||||
{
|
||||
// single global cutoff = max of cut from all files read in
|
||||
// for funcfl could be multiple files
|
||||
// for setfl or fs, just one file
|
||||
|
||||
if (setflag[i][j] == 0) scale[i][j] = 1.0;
|
||||
scale[j][i] = scale[i][j];
|
||||
|
||||
if (funcfl) {
|
||||
cutmax = 0.0;
|
||||
for (int m = 0; m < nfuncfl; m++) cutmax = MAX(cutmax, funcfl[m].cut);
|
||||
} else if (setfl)
|
||||
cutmax = setfl->cut;
|
||||
else if (fs)
|
||||
cutmax = fs->cut;
|
||||
|
||||
cutforcesq = cutmax * cutmax;
|
||||
|
||||
return cutmax;
|
||||
}
|
||||
|
||||
/**
|
||||
* setup specific to this pair style
|
||||
* Determine whether there is a fix lambda_thermostat/apip or not and set
|
||||
* lambda_thermostat.
|
||||
*/
|
||||
|
||||
void PairEAMAPIP::setup()
|
||||
{
|
||||
if (modify->get_fix_by_style("^lambda_thermostat/apip$").size() == 0) {
|
||||
lambda_thermostat = false;
|
||||
} else {
|
||||
lambda_thermostat = true;
|
||||
if (!atom->apip_lambda_const_flag)
|
||||
error->all(
|
||||
FLERR,
|
||||
"Pair style pace/apip requires an atom style with lambda_const for a local thermostat.");
|
||||
if (!atom->apip_e_fast_flag)
|
||||
error->all(
|
||||
FLERR,
|
||||
"Pair style pace/apip requires an atom style with e_simple for a local thermostat.");
|
||||
if (!atom->apip_f_const_lambda_flag)
|
||||
error->all(FLERR,
|
||||
"Pair style pace/apip requires an atom style with f_const_lambda for a local "
|
||||
"thermostat.");
|
||||
if (!atom->apip_f_dyn_lambda_flag)
|
||||
error->all(FLERR,
|
||||
"Pair style pace/apip requires an atom style with f_const_lambda for a local "
|
||||
"thermostat.");
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
read potential values from a DYNAMO single element funcfl file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMAPIP::read_file(char *filename)
|
||||
{
|
||||
Funcfl *file = &funcfl[nfuncfl - 1];
|
||||
|
||||
// read potential file
|
||||
if (comm->me == 0) {
|
||||
PotentialFileReader reader(lmp, filename, "eam", unit_convert_flag);
|
||||
|
||||
// transparently convert units for supported conversions
|
||||
|
||||
int unit_convert = reader.get_unit_convert();
|
||||
double conversion_factor = utils::get_conversion_factor(utils::ENERGY, unit_convert);
|
||||
try {
|
||||
reader.skip_line();
|
||||
|
||||
ValueTokenizer values = reader.next_values(2);
|
||||
values.next_int(); // ignore
|
||||
file->mass = values.next_double();
|
||||
|
||||
values = reader.next_values(5);
|
||||
file->nrho = values.next_int();
|
||||
file->drho = values.next_double();
|
||||
file->nr = values.next_int();
|
||||
file->dr = values.next_double();
|
||||
file->cut = values.next_double();
|
||||
|
||||
if ((file->nrho <= 0) || (file->nr <= 0) || (file->dr <= 0.0))
|
||||
error->one(FLERR, "Invalid EAM potential file");
|
||||
|
||||
memory->create(file->frho, (file->nrho + 1), "pair:frho");
|
||||
memory->create(file->rhor, (file->nr + 1), "pair:rhor");
|
||||
memory->create(file->zr, (file->nr + 1), "pair:zr");
|
||||
|
||||
reader.next_dvector(&file->frho[1], file->nrho);
|
||||
reader.next_dvector(&file->zr[1], file->nr);
|
||||
reader.next_dvector(&file->rhor[1], file->nr);
|
||||
|
||||
if (unit_convert) {
|
||||
const double sqrt_conv = sqrt(conversion_factor);
|
||||
for (int i = 1; i <= file->nrho; ++i) file->frho[i] *= conversion_factor;
|
||||
for (int j = 1; j <= file->nr; ++j) file->zr[j] *= sqrt_conv;
|
||||
}
|
||||
} catch (TokenizerException &e) {
|
||||
error->one(FLERR, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
MPI_Bcast(&file->mass, 1, MPI_DOUBLE, 0, world);
|
||||
MPI_Bcast(&file->nrho, 1, MPI_INT, 0, world);
|
||||
MPI_Bcast(&file->drho, 1, MPI_DOUBLE, 0, world);
|
||||
MPI_Bcast(&file->nr, 1, MPI_INT, 0, world);
|
||||
MPI_Bcast(&file->dr, 1, MPI_DOUBLE, 0, world);
|
||||
MPI_Bcast(&file->cut, 1, MPI_DOUBLE, 0, world);
|
||||
|
||||
if (comm->me != 0) {
|
||||
memory->create(file->frho, (file->nrho + 1), "pair:frho");
|
||||
memory->create(file->rhor, (file->nr + 1), "pair:rhor");
|
||||
memory->create(file->zr, (file->nr + 1), "pair:zr");
|
||||
}
|
||||
|
||||
MPI_Bcast(&file->frho[1], file->nrho, MPI_DOUBLE, 0, world);
|
||||
MPI_Bcast(&file->zr[1], file->nr, MPI_DOUBLE, 0, world);
|
||||
MPI_Bcast(&file->rhor[1], file->nr, MPI_DOUBLE, 0, world);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
convert read-in funcfl potential(s) to standard array format
|
||||
interpolate all file values to a single grid and cutoff
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMAPIP::file2array()
|
||||
{
|
||||
int i, j, k, m, n;
|
||||
int ntypes = atom->ntypes;
|
||||
double sixth = 1.0 / 6.0;
|
||||
|
||||
// determine max function params from all active funcfl files
|
||||
// active means some element is pointing at it via map
|
||||
|
||||
int active;
|
||||
double rmax;
|
||||
dr = drho = rmax = rhomax = 0.0;
|
||||
|
||||
for (int i = 0; i < nfuncfl; i++) {
|
||||
active = 0;
|
||||
for (j = 1; j <= ntypes; j++)
|
||||
if (map[j] == i) active = 1;
|
||||
if (active == 0) continue;
|
||||
Funcfl *file = &funcfl[i];
|
||||
dr = MAX(dr, file->dr);
|
||||
drho = MAX(drho, file->drho);
|
||||
rmax = MAX(rmax, (file->nr - 1) * file->dr);
|
||||
rhomax = MAX(rhomax, (file->nrho - 1) * file->drho);
|
||||
}
|
||||
|
||||
// set nr,nrho from cutoff and spacings
|
||||
// 0.5 is for round-off in divide
|
||||
|
||||
nr = static_cast<int>(rmax / dr + 0.5);
|
||||
nrho = static_cast<int>(rhomax / drho + 0.5);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// setup frho arrays
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
// allocate frho arrays
|
||||
// nfrho = # of funcfl files + 1 for zero array
|
||||
|
||||
nfrho = nfuncfl + 1;
|
||||
memory->destroy(frho);
|
||||
memory->create(frho, nfrho, nrho + 1, "pair:frho");
|
||||
|
||||
// interpolate each file's frho to a single grid and cutoff
|
||||
|
||||
double r, p, cof1, cof2, cof3, cof4;
|
||||
|
||||
n = 0;
|
||||
for (i = 0; i < nfuncfl; i++) {
|
||||
Funcfl *file = &funcfl[i];
|
||||
for (m = 1; m <= nrho; m++) {
|
||||
r = (m - 1) * drho;
|
||||
p = r / file->drho + 1.0;
|
||||
k = static_cast<int>(p);
|
||||
k = MIN(k, file->nrho - 2);
|
||||
k = MAX(k, 2);
|
||||
p -= k;
|
||||
p = MIN(p, 2.0);
|
||||
cof1 = -sixth * p * (p - 1.0) * (p - 2.0);
|
||||
cof2 = 0.5 * (p * p - 1.0) * (p - 2.0);
|
||||
cof3 = -0.5 * p * (p + 1.0) * (p - 2.0);
|
||||
cof4 = sixth * p * (p * p - 1.0);
|
||||
frho[n][m] = cof1 * file->frho[k - 1] + cof2 * file->frho[k] + cof3 * file->frho[k + 1] +
|
||||
cof4 * file->frho[k + 2];
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
// add extra frho of zeroes for non-EAM types to point to (pair hybrid)
|
||||
// this is necessary b/c fp is still computed for non-EAM atoms
|
||||
|
||||
for (m = 1; m <= nrho; m++) frho[nfrho - 1][m] = 0.0;
|
||||
|
||||
// type2frho[i] = which frho array (0 to nfrho-1) each atom type maps to
|
||||
// if atom type doesn't point to file (non-EAM atom in pair hybrid)
|
||||
// then map it to last frho array of zeroes
|
||||
|
||||
for (i = 1; i <= ntypes; i++)
|
||||
if (map[i] >= 0)
|
||||
type2frho[i] = map[i];
|
||||
else
|
||||
type2frho[i] = nfrho - 1;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// setup rhor arrays
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
// allocate rhor arrays
|
||||
// nrhor = # of funcfl files
|
||||
|
||||
nrhor = nfuncfl;
|
||||
memory->destroy(rhor);
|
||||
memory->create(rhor, nrhor, nr + 1, "pair:rhor");
|
||||
|
||||
// interpolate each file's rhor to a single grid and cutoff
|
||||
|
||||
n = 0;
|
||||
for (i = 0; i < nfuncfl; i++) {
|
||||
Funcfl *file = &funcfl[i];
|
||||
for (m = 1; m <= nr; m++) {
|
||||
r = (m - 1) * dr;
|
||||
p = r / file->dr + 1.0;
|
||||
k = static_cast<int>(p);
|
||||
k = MIN(k, file->nr - 2);
|
||||
k = MAX(k, 2);
|
||||
p -= k;
|
||||
p = MIN(p, 2.0);
|
||||
cof1 = -sixth * p * (p - 1.0) * (p - 2.0);
|
||||
cof2 = 0.5 * (p * p - 1.0) * (p - 2.0);
|
||||
cof3 = -0.5 * p * (p + 1.0) * (p - 2.0);
|
||||
cof4 = sixth * p * (p * p - 1.0);
|
||||
rhor[n][m] = cof1 * file->rhor[k - 1] + cof2 * file->rhor[k] + cof3 * file->rhor[k + 1] +
|
||||
cof4 * file->rhor[k + 2];
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
// type2rhor[i][j] = which rhor array (0 to nrhor-1) each type pair maps to
|
||||
// for funcfl files, I,J mapping only depends on I
|
||||
// OK if map = -1 (non-EAM atom in pair hybrid) b/c type2rhor not used
|
||||
|
||||
for (i = 1; i <= ntypes; i++)
|
||||
for (j = 1; j <= ntypes; j++) type2rhor[i][j] = map[i];
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// setup z2r arrays
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
// allocate z2r arrays
|
||||
// nz2r = N*(N+1)/2 where N = # of funcfl files
|
||||
|
||||
nz2r = nfuncfl * (nfuncfl + 1) / 2;
|
||||
memory->destroy(z2r);
|
||||
memory->create(z2r, nz2r, nr + 1, "pair:z2r");
|
||||
|
||||
// create a z2r array for each file against other files, only for I >= J
|
||||
// interpolate zri and zrj to a single grid and cutoff
|
||||
// final z2r includes unit conversion of 27.2 eV/Hartree and 0.529 Ang/Bohr
|
||||
|
||||
double zri, zrj;
|
||||
|
||||
n = 0;
|
||||
for (i = 0; i < nfuncfl; i++) {
|
||||
Funcfl *ifile = &funcfl[i];
|
||||
for (j = 0; j <= i; j++) {
|
||||
Funcfl *jfile = &funcfl[j];
|
||||
|
||||
for (m = 1; m <= nr; m++) {
|
||||
r = (m - 1) * dr;
|
||||
|
||||
p = r / ifile->dr + 1.0;
|
||||
k = static_cast<int>(p);
|
||||
k = MIN(k, ifile->nr - 2);
|
||||
k = MAX(k, 2);
|
||||
p -= k;
|
||||
p = MIN(p, 2.0);
|
||||
cof1 = -sixth * p * (p - 1.0) * (p - 2.0);
|
||||
cof2 = 0.5 * (p * p - 1.0) * (p - 2.0);
|
||||
cof3 = -0.5 * p * (p + 1.0) * (p - 2.0);
|
||||
cof4 = sixth * p * (p * p - 1.0);
|
||||
zri = cof1 * ifile->zr[k - 1] + cof2 * ifile->zr[k] + cof3 * ifile->zr[k + 1] +
|
||||
cof4 * ifile->zr[k + 2];
|
||||
|
||||
p = r / jfile->dr + 1.0;
|
||||
k = static_cast<int>(p);
|
||||
k = MIN(k, jfile->nr - 2);
|
||||
k = MAX(k, 2);
|
||||
p -= k;
|
||||
p = MIN(p, 2.0);
|
||||
cof1 = -sixth * p * (p - 1.0) * (p - 2.0);
|
||||
cof2 = 0.5 * (p * p - 1.0) * (p - 2.0);
|
||||
cof3 = -0.5 * p * (p + 1.0) * (p - 2.0);
|
||||
cof4 = sixth * p * (p * p - 1.0);
|
||||
zrj = cof1 * jfile->zr[k - 1] + cof2 * jfile->zr[k] + cof3 * jfile->zr[k + 1] +
|
||||
cof4 * jfile->zr[k + 2];
|
||||
|
||||
z2r[n][m] = 27.2 * 0.529 * zri * zrj;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
// type2z2r[i][j] = which z2r array (0 to nz2r-1) each type pair maps to
|
||||
// set of z2r arrays only fill lower triangular Nelement matrix
|
||||
// value = n = sum over rows of lower-triangular matrix until reach irow,icol
|
||||
// swap indices when irow < icol to stay lower triangular
|
||||
// if map = -1 (non-EAM atom in pair hybrid):
|
||||
// type2z2r is not used by non-opt
|
||||
// but set type2z2r to 0 since accessed by opt
|
||||
|
||||
int irow, icol;
|
||||
for (i = 1; i <= ntypes; i++) {
|
||||
for (j = 1; j <= ntypes; j++) {
|
||||
irow = map[i];
|
||||
icol = map[j];
|
||||
if (irow == -1 || icol == -1) {
|
||||
type2z2r[i][j] = 0;
|
||||
continue;
|
||||
}
|
||||
if (irow < icol) {
|
||||
irow = map[j];
|
||||
icol = map[i];
|
||||
}
|
||||
n = 0;
|
||||
for (m = 0; m < irow; m++) n += m + 1;
|
||||
n += icol;
|
||||
type2z2r[i][j] = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMAPIP::array2spline()
|
||||
{
|
||||
rdr = 1.0 / dr;
|
||||
rdrho = 1.0 / drho;
|
||||
|
||||
memory->destroy(frho_spline);
|
||||
memory->destroy(rhor_spline);
|
||||
memory->destroy(z2r_spline);
|
||||
|
||||
memory->create(frho_spline, nfrho, nrho + 1, 7, "pair:frho");
|
||||
memory->create(rhor_spline, nrhor, nr + 1, 7, "pair:rhor");
|
||||
memory->create(z2r_spline, nz2r, nr + 1, 7, "pair:z2r");
|
||||
|
||||
for (int i = 0; i < nfrho; i++) interpolate(nrho, drho, frho[i], frho_spline[i]);
|
||||
|
||||
for (int i = 0; i < nrhor; i++) interpolate(nr, dr, rhor[i], rhor_spline[i]);
|
||||
|
||||
for (int i = 0; i < nz2r; i++) interpolate(nr, dr, z2r[i], z2r_spline[i]);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMAPIP::interpolate(int n, double delta, double *f, double **spline)
|
||||
{
|
||||
for (int m = 1; m <= n; m++) spline[m][6] = f[m];
|
||||
|
||||
spline[1][5] = spline[2][6] - spline[1][6];
|
||||
spline[2][5] = 0.5 * (spline[3][6] - spline[1][6]);
|
||||
spline[n - 1][5] = 0.5 * (spline[n][6] - spline[n - 2][6]);
|
||||
spline[n][5] = spline[n][6] - spline[n - 1][6];
|
||||
|
||||
for (int m = 3; m <= n - 2; m++)
|
||||
spline[m][5] =
|
||||
((spline[m - 2][6] - spline[m + 2][6]) + 8.0 * (spline[m + 1][6] - spline[m - 1][6])) /
|
||||
12.0;
|
||||
|
||||
for (int m = 1; m <= n - 1; m++) {
|
||||
spline[m][4] = 3.0 * (spline[m + 1][6] - spline[m][6]) - 2.0 * spline[m][5] - spline[m + 1][5];
|
||||
spline[m][3] = spline[m][5] + spline[m + 1][5] - 2.0 * (spline[m + 1][6] - spline[m][6]);
|
||||
}
|
||||
|
||||
spline[n][4] = 0.0;
|
||||
spline[n][3] = 0.0;
|
||||
|
||||
for (int m = 1; m <= n; m++) {
|
||||
spline[m][2] = spline[m][5] / delta;
|
||||
spline[m][1] = 2.0 * spline[m][4] / delta;
|
||||
spline[m][0] = 3.0 * spline[m][3] / delta;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
memory usage of local atom-based arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double PairEAMAPIP::memory_usage()
|
||||
{
|
||||
double bytes = (double) maxeatom * sizeof(double);
|
||||
bytes += (double) maxvatom * 6 * sizeof(double);
|
||||
bytes += (double) 2 * nmax * sizeof(double);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
swap fp array with one passed in by caller
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMAPIP::swap_eam(double *fp_caller, double **fp_caller_hold)
|
||||
{
|
||||
double *tmp = fp;
|
||||
fp = fp_caller;
|
||||
*fp_caller_hold = tmp;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set return values for timers and counted particles
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMAPIP::calculate_time_per_atom()
|
||||
{
|
||||
if (n_non_complex_accumulated > 0)
|
||||
time_per_atom = time_wall_accumulated / n_non_complex_accumulated;
|
||||
else
|
||||
time_per_atom = -1;
|
||||
|
||||
// reset
|
||||
time_wall_accumulated = 0;
|
||||
n_non_complex_accumulated = 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void *PairEAMAPIP::extract(const char *str, int &dim)
|
||||
{
|
||||
dim = 2;
|
||||
if (strcmp(str, "scale") == 0) return (void *) scale;
|
||||
dim = 0;
|
||||
if (strcmp(str, "eam/apip:time_per_atom") == 0) {
|
||||
calculate_time_per_atom();
|
||||
return (void *) &time_per_atom;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
123
src/APIP/pair_eam_apip.h
Normal file
123
src/APIP/pair_eam_apip.h
Normal file
@ -0,0 +1,123 @@
|
||||
/* -*- 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: Stephen Foiles (SNL), Murray Daw (SNL) (EAM)
|
||||
David Immel (d.immel@fz-juelich.de, FZJ, Germany) (APIP)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef PAIR_CLASS
|
||||
// clang-format off
|
||||
PairStyle(eam/apip,PairEAMAPIP);
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
#ifndef LMP_PAIR_EAM_APIP_H
|
||||
#define LMP_PAIR_EAM_APIP_H
|
||||
|
||||
#include "pair.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PairEAMAPIP : public Pair {
|
||||
public:
|
||||
friend class FixSemiGrandCanonicalMC; // Alex Stukowski option
|
||||
|
||||
// public variables so ATC package can access them
|
||||
|
||||
double cutmax;
|
||||
|
||||
// potentials as array data
|
||||
|
||||
int nrho, nr;
|
||||
int nfrho, nrhor, nz2r;
|
||||
double **frho, **rhor, **z2r;
|
||||
int *type2frho, **type2rhor, **type2z2r;
|
||||
|
||||
// potentials in spline form used for force computation
|
||||
|
||||
double dr, rdr, drho, rdrho, rhomax, rhomin;
|
||||
double ***rhor_spline, ***frho_spline, ***z2r_spline;
|
||||
|
||||
PairEAMAPIP(class LAMMPS *);
|
||||
~PairEAMAPIP() override;
|
||||
void compute(int, int) override;
|
||||
void settings(int, char **) override;
|
||||
void setup() override;
|
||||
void coeff(int, char **) override;
|
||||
void init_style() override;
|
||||
double init_one(int, int) override;
|
||||
void *extract(const char *, int &) override;
|
||||
|
||||
double memory_usage() override;
|
||||
void swap_eam(double *, double **) override;
|
||||
|
||||
protected:
|
||||
int nmax; // allocated size of per-atom arrays
|
||||
double cutforcesq;
|
||||
double **scale;
|
||||
|
||||
// per-atom arrays
|
||||
|
||||
double *rho, *fp;
|
||||
int *numforce;
|
||||
|
||||
// potentials as file data
|
||||
|
||||
struct Funcfl {
|
||||
char *file;
|
||||
int nrho, nr;
|
||||
double drho, dr, cut, mass;
|
||||
double *frho, *rhor, *zr;
|
||||
};
|
||||
Funcfl *funcfl;
|
||||
int nfuncfl;
|
||||
|
||||
struct Setfl {
|
||||
char **elements;
|
||||
int nelements, nrho, nr;
|
||||
double drho, dr, cut;
|
||||
double *mass;
|
||||
double **frho, **rhor, ***z2r;
|
||||
};
|
||||
Setfl *setfl;
|
||||
|
||||
struct Fs {
|
||||
char **elements;
|
||||
int nelements, nrho, nr;
|
||||
double drho, dr, cut;
|
||||
double *mass;
|
||||
double **frho, ***rhor, ***z2r;
|
||||
};
|
||||
Fs *fs;
|
||||
|
||||
virtual void allocate();
|
||||
virtual void array2spline();
|
||||
void interpolate(int, double, double *, double **);
|
||||
|
||||
virtual void read_file(char *);
|
||||
virtual void file2array();
|
||||
|
||||
// stats required for load balancing
|
||||
int n_non_complex_accumulated; // number of calculated atoms
|
||||
double time_wall_accumulated; // time required for the atom calculation
|
||||
double time_per_atom; // time for one calculation
|
||||
|
||||
void calculate_time_per_atom();
|
||||
|
||||
bool lambda_thermostat; // true/false there is one/no fix lambda_thermostat
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
365
src/APIP/pair_eam_fs_apip.cpp
Normal file
365
src/APIP/pair_eam_fs_apip.cpp
Normal file
@ -0,0 +1,365 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
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: Tim Lau (MIT) for EAM/FS
|
||||
David Immel (d.immel@fz-juelich.de, FZJ, Germany) for APIP
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "pair_eam_fs_apip.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "error.h"
|
||||
#include "memory.h"
|
||||
#include "potential_file_reader.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairEAMFSAPIP::PairEAMFSAPIP(LAMMPS *lmp) : PairEAMAPIP(lmp)
|
||||
{
|
||||
one_coeff = 1;
|
||||
manybody_flag = 1;
|
||||
he_flag = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one or more type pairs
|
||||
read EAM Finnis-Sinclair file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMFSAPIP::coeff(int narg, char **arg)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (!allocated) allocate();
|
||||
|
||||
if (narg != 3 + atom->ntypes) error->all(FLERR, "Incorrect args for pair coefficients");
|
||||
|
||||
// insure I,J args are * *
|
||||
|
||||
if (strcmp(arg[0], "*") != 0 || strcmp(arg[1], "*") != 0)
|
||||
error->all(FLERR, "Incorrect args for pair coefficients");
|
||||
|
||||
// read EAM Finnis-Sinclair file
|
||||
|
||||
if (fs) {
|
||||
for (i = 0; i < fs->nelements; i++) delete[] fs->elements[i];
|
||||
delete[] fs->elements;
|
||||
memory->destroy(fs->mass);
|
||||
memory->destroy(fs->frho);
|
||||
memory->destroy(fs->rhor);
|
||||
memory->destroy(fs->z2r);
|
||||
delete fs;
|
||||
}
|
||||
fs = new Fs();
|
||||
read_file(arg[2]);
|
||||
|
||||
// read args that map atom types to elements in potential file
|
||||
// map[i] = which element the Ith atom type is, -1 if "NULL"
|
||||
|
||||
for (i = 3; i < narg; i++) {
|
||||
if (strcmp(arg[i], "NULL") == 0) {
|
||||
map[i - 2] = -1;
|
||||
continue;
|
||||
}
|
||||
for (j = 0; j < fs->nelements; j++)
|
||||
if (strcmp(arg[i], fs->elements[j]) == 0) break;
|
||||
if (j < fs->nelements)
|
||||
map[i - 2] = j;
|
||||
else
|
||||
error->all(FLERR, "No matching element in EAM potential file");
|
||||
}
|
||||
|
||||
// clear setflag since coeff() called once with I,J = * *
|
||||
|
||||
int n = atom->ntypes;
|
||||
for (i = 1; i <= n; i++)
|
||||
for (j = i; j <= n; j++) setflag[i][j] = 0;
|
||||
|
||||
// set setflag i,j for type pairs where both are mapped to elements
|
||||
// set mass of atom type if i = j
|
||||
|
||||
int count = 0;
|
||||
for (i = 1; i <= n; i++) {
|
||||
for (j = i; j <= n; j++) {
|
||||
if (map[i] >= 0 && map[j] >= 0) {
|
||||
setflag[i][j] = 1;
|
||||
if (i == j) atom->set_mass(FLERR, i, fs->mass[map[i]]);
|
||||
count++;
|
||||
}
|
||||
scale[i][j] = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) error->all(FLERR, "Incorrect args for pair coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
read a multi-element DYNAMO setfl file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMFSAPIP::read_file(char *filename)
|
||||
{
|
||||
Fs *file = fs;
|
||||
|
||||
// read potential file
|
||||
if (comm->me == 0) {
|
||||
PotentialFileReader reader(lmp, filename, he_flag ? "eam/he" : "eam/fs", unit_convert_flag);
|
||||
|
||||
// transparently convert units for supported conversions
|
||||
|
||||
int unit_convert = reader.get_unit_convert();
|
||||
double conversion_factor = utils::get_conversion_factor(utils::ENERGY, unit_convert);
|
||||
try {
|
||||
reader.skip_line();
|
||||
reader.skip_line();
|
||||
reader.skip_line();
|
||||
|
||||
// extract element names from nelements line
|
||||
ValueTokenizer values = reader.next_values(1);
|
||||
file->nelements = values.next_int();
|
||||
|
||||
if ((int) values.count() != file->nelements + 1)
|
||||
error->one(FLERR, "Incorrect element names in EAM potential file");
|
||||
|
||||
file->elements = new char *[file->nelements];
|
||||
for (int i = 0; i < file->nelements; i++) {
|
||||
const std::string word = values.next_string();
|
||||
const int n = word.length() + 1;
|
||||
file->elements[i] = new char[n];
|
||||
strcpy(file->elements[i], word.c_str());
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if (he_flag)
|
||||
values = reader.next_values(6);
|
||||
else
|
||||
values = reader.next_values(5);
|
||||
file->nrho = values.next_int();
|
||||
file->drho = values.next_double();
|
||||
file->nr = values.next_int();
|
||||
file->dr = values.next_double();
|
||||
file->cut = values.next_double();
|
||||
if (he_flag) rhomax = values.next_double();
|
||||
|
||||
if ((file->nrho <= 0) || (file->nr <= 0) || (file->dr <= 0.0))
|
||||
error->one(FLERR, "Invalid EAM potential file");
|
||||
|
||||
memory->create(file->mass, file->nelements, "pair:mass");
|
||||
memory->create(file->frho, file->nelements, file->nrho + 1, "pair:frho");
|
||||
memory->create(file->rhor, file->nelements, file->nelements, file->nr + 1, "pair:rhor");
|
||||
memory->create(file->z2r, file->nelements, file->nelements, file->nr + 1, "pair:z2r");
|
||||
|
||||
for (int i = 0; i < file->nelements; i++) {
|
||||
values = reader.next_values(2);
|
||||
values.next_int(); // ignore
|
||||
file->mass[i] = values.next_double();
|
||||
|
||||
reader.next_dvector(&file->frho[i][1], file->nrho);
|
||||
if (unit_convert) {
|
||||
for (int j = 1; j <= file->nrho; ++j) file->frho[i][j] *= conversion_factor;
|
||||
}
|
||||
|
||||
for (int j = 0; j < file->nelements; j++) {
|
||||
reader.next_dvector(&file->rhor[i][j][1], file->nr);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < file->nelements; i++) {
|
||||
for (int j = 0; j <= i; j++) {
|
||||
reader.next_dvector(&file->z2r[i][j][1], file->nr);
|
||||
if (unit_convert) {
|
||||
for (int k = 1; k <= file->nr; ++k) file->z2r[i][j][k] *= conversion_factor;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (TokenizerException &e) {
|
||||
error->one(FLERR, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
// broadcast potential information
|
||||
MPI_Bcast(&file->nelements, 1, MPI_INT, 0, world);
|
||||
|
||||
MPI_Bcast(&file->nrho, 1, MPI_INT, 0, world);
|
||||
MPI_Bcast(&file->drho, 1, MPI_DOUBLE, 0, world);
|
||||
MPI_Bcast(&file->nr, 1, MPI_INT, 0, world);
|
||||
MPI_Bcast(&file->dr, 1, MPI_DOUBLE, 0, world);
|
||||
MPI_Bcast(&file->cut, 1, MPI_DOUBLE, 0, world);
|
||||
MPI_Bcast(&rhomax, 1, MPI_DOUBLE, 0, world);
|
||||
|
||||
// allocate memory on other procs
|
||||
if (comm->me != 0) {
|
||||
file->elements = new char *[file->nelements];
|
||||
for (int i = 0; i < file->nelements; i++) file->elements[i] = nullptr;
|
||||
memory->create(file->mass, file->nelements, "pair:mass");
|
||||
memory->create(file->frho, file->nelements, file->nrho + 1, "pair:frho");
|
||||
memory->create(file->rhor, file->nelements, file->nelements, file->nr + 1, "pair:rhor");
|
||||
memory->create(file->z2r, file->nelements, file->nelements, file->nr + 1, "pair:z2r");
|
||||
}
|
||||
|
||||
// broadcast file->elements string array
|
||||
for (int i = 0; i < file->nelements; i++) {
|
||||
int n;
|
||||
if (comm->me == 0) n = strlen(file->elements[i]) + 1;
|
||||
MPI_Bcast(&n, 1, MPI_INT, 0, world);
|
||||
if (comm->me != 0) file->elements[i] = new char[n];
|
||||
MPI_Bcast(file->elements[i], n, MPI_CHAR, 0, world);
|
||||
}
|
||||
|
||||
// broadcast file->mass, frho, rhor
|
||||
for (int i = 0; i < file->nelements; i++) {
|
||||
MPI_Bcast(&file->mass[i], 1, MPI_DOUBLE, 0, world);
|
||||
MPI_Bcast(&file->frho[i][1], file->nrho, MPI_DOUBLE, 0, world);
|
||||
|
||||
for (int j = 0; j < file->nelements; j++) {
|
||||
MPI_Bcast(&file->rhor[i][j][1], file->nr, MPI_DOUBLE, 0, world);
|
||||
}
|
||||
}
|
||||
|
||||
// broadcast file->z2r
|
||||
for (int i = 0; i < file->nelements; i++) {
|
||||
for (int j = 0; j <= i; j++) { MPI_Bcast(&file->z2r[i][j][1], file->nr, MPI_DOUBLE, 0, world); }
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
copy read-in setfl potential to standard array format
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMFSAPIP::file2array()
|
||||
{
|
||||
int i, j, m, n;
|
||||
int ntypes = atom->ntypes;
|
||||
|
||||
// set function params directly from fs file
|
||||
|
||||
nrho = fs->nrho;
|
||||
nr = fs->nr;
|
||||
drho = fs->drho;
|
||||
dr = fs->dr;
|
||||
if (he_flag)
|
||||
rhomin = rhomax - (nrho - 1) * drho;
|
||||
else
|
||||
rhomax = (nrho - 1) * drho;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// setup frho arrays
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
// allocate frho arrays
|
||||
// nfrho = # of fs elements + 1 for zero array
|
||||
|
||||
nfrho = fs->nelements + 1;
|
||||
memory->destroy(frho);
|
||||
memory->create(frho, nfrho, nrho + 1, "pair:frho");
|
||||
|
||||
// copy each element's frho to global frho
|
||||
|
||||
for (i = 0; i < fs->nelements; i++)
|
||||
for (m = 1; m <= nrho; m++) frho[i][m] = fs->frho[i][m];
|
||||
|
||||
// add extra frho of zeroes for non-EAM types to point to (pair hybrid)
|
||||
// this is necessary b/c fp is still computed for non-EAM atoms
|
||||
|
||||
for (m = 1; m <= nrho; m++) frho[nfrho - 1][m] = 0.0;
|
||||
|
||||
// type2frho[i] = which frho array (0 to nfrho-1) each atom type maps to
|
||||
// if atom type doesn't point to element (non-EAM atom in pair hybrid)
|
||||
// then map it to last frho array of zeroes
|
||||
|
||||
for (i = 1; i <= ntypes; i++)
|
||||
if (map[i] >= 0)
|
||||
type2frho[i] = map[i];
|
||||
else
|
||||
type2frho[i] = nfrho - 1;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// setup rhor arrays
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
// allocate rhor arrays
|
||||
// nrhor = square of # of fs elements
|
||||
|
||||
nrhor = fs->nelements * fs->nelements;
|
||||
memory->destroy(rhor);
|
||||
memory->create(rhor, nrhor, nr + 1, "pair:rhor");
|
||||
|
||||
// copy each element pair rhor to global rhor
|
||||
|
||||
n = 0;
|
||||
for (i = 0; i < fs->nelements; i++)
|
||||
for (j = 0; j < fs->nelements; j++) {
|
||||
for (m = 1; m <= nr; m++) rhor[n][m] = fs->rhor[i][j][m];
|
||||
n++;
|
||||
}
|
||||
|
||||
// type2rhor[i][j] = which rhor array (0 to nrhor-1) each type pair maps to
|
||||
// for fs files, there is a full NxN set of rhor arrays
|
||||
// OK if map = -1 (non-EAM atom in pair hybrid) b/c type2rhor not used
|
||||
|
||||
for (i = 1; i <= ntypes; i++)
|
||||
for (j = 1; j <= ntypes; j++) type2rhor[i][j] = map[i] * fs->nelements + map[j];
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// setup z2r arrays
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
// allocate z2r arrays
|
||||
// nz2r = N*(N+1)/2 where N = # of fs elements
|
||||
|
||||
nz2r = fs->nelements * (fs->nelements + 1) / 2;
|
||||
memory->destroy(z2r);
|
||||
memory->create(z2r, nz2r, nr + 1, "pair:z2r");
|
||||
|
||||
// copy each element pair z2r to global z2r, only for I >= J
|
||||
|
||||
n = 0;
|
||||
for (i = 0; i < fs->nelements; i++)
|
||||
for (j = 0; j <= i; j++) {
|
||||
for (m = 1; m <= nr; m++) z2r[n][m] = fs->z2r[i][j][m];
|
||||
n++;
|
||||
}
|
||||
|
||||
// type2z2r[i][j] = which z2r array (0 to nz2r-1) each type pair maps to
|
||||
// set of z2r arrays only fill lower triangular Nelement matrix
|
||||
// value = n = sum over rows of lower-triangular matrix until reach irow,icol
|
||||
// swap indices when irow < icol to stay lower triangular
|
||||
// if map = -1 (non-EAM atom in pair hybrid):
|
||||
// type2z2r is not used by non-opt
|
||||
// but set type2z2r to 0 since accessed by opt
|
||||
|
||||
int irow, icol;
|
||||
for (i = 1; i <= ntypes; i++) {
|
||||
for (j = 1; j <= ntypes; j++) {
|
||||
irow = map[i];
|
||||
icol = map[j];
|
||||
if (irow == -1 || icol == -1) {
|
||||
type2z2r[i][j] = 0;
|
||||
continue;
|
||||
}
|
||||
if (irow < icol) {
|
||||
irow = map[j];
|
||||
icol = map[i];
|
||||
}
|
||||
n = 0;
|
||||
for (m = 0; m < irow; m++) n += m + 1;
|
||||
n += icol;
|
||||
type2z2r[i][j] = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
48
src/APIP/pair_eam_fs_apip.h
Normal file
48
src/APIP/pair_eam_fs_apip.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* -*- 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 author: Tim Lau (MIT) for EAM/FS
|
||||
David Immel (d.immel@fz-juelich.de, FZJ, Germany) for APIP
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef PAIR_CLASS
|
||||
// clang-format off
|
||||
PairStyle(eam/fs/apip,PairEAMFSAPIP);
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
#ifndef LMP_PAIR_EAM_FS_APIP_H
|
||||
#define LMP_PAIR_EAM_FS_APIP_H
|
||||
|
||||
#include "pair_eam_apip.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
// need virtual public b/c of how eam/fs/opt inherits from it
|
||||
|
||||
class PairEAMFSAPIP : virtual public PairEAMAPIP {
|
||||
public:
|
||||
PairEAMFSAPIP(class LAMMPS *);
|
||||
|
||||
void coeff(int, char **) override;
|
||||
|
||||
protected:
|
||||
void read_file(char *) override;
|
||||
void file2array() override;
|
||||
int he_flag;
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
218
src/APIP/pair_lambda_input_apip.cpp
Normal file
218
src/APIP/pair_lambda_input_apip.cpp
Normal file
@ -0,0 +1,218 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
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: David Immel (d.immel@fz-juelich.de, FZJ, Germany)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "pair_lambda_input_apip.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "error.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
#include "modify.h"
|
||||
#include "neigh_list.h"
|
||||
#include "neighbor.h"
|
||||
#include "update.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairLambdaInputAPIP::PairLambdaInputAPIP(LAMMPS *lmp) : Pair(lmp), fix_lambda(nullptr), cut(nullptr)
|
||||
{
|
||||
|
||||
cut_global = -1;
|
||||
ignore_group_bit = 0;
|
||||
timer = 0;
|
||||
n_calculations = 0;
|
||||
time_per_atom = -1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairLambdaInputAPIP::~PairLambdaInputAPIP()
|
||||
{
|
||||
if (copymode) return;
|
||||
|
||||
if (allocated) {
|
||||
memory->destroy(setflag);
|
||||
memory->destroy(cutsq);
|
||||
|
||||
memory->destroy(cut);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
void PairLambdaInputAPIP::coeff(int narg, char **arg)
|
||||
{
|
||||
if (narg != 2) error->all(FLERR, "Incorrect args for pair coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo, ihi, jlo, jhi;
|
||||
utils::bounds(FLERR, arg[0], 1, atom->ntypes, ilo, ihi, error);
|
||||
utils::bounds(FLERR, arg[1], 1, atom->ntypes, jlo, jhi, error);
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
for (int j = MAX(jlo, i); j <= jhi; j++) {
|
||||
setflag[i][j] = 1;
|
||||
cut[i][j] = cut_global;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) error->all(FLERR, "Incorrect args for pair coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
allocate all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLambdaInputAPIP::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->ntypes + 1;
|
||||
|
||||
memory->create(setflag, n, n, "pair:setflag");
|
||||
for (int i = 1; i < n; i++)
|
||||
for (int j = i; j < n; j++) setflag[i][j] = 0;
|
||||
|
||||
memory->create(cutsq, n, n, "pair:cutsq");
|
||||
memory->create(cut, n, n, "pair:cut");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairLambdaInputAPIP::compute(int eflag, int vflag)
|
||||
{
|
||||
// basic stuff (see pair_zero)
|
||||
ev_init(eflag, vflag);
|
||||
if (vflag_fdotr) virial_fdotr_compute();
|
||||
|
||||
double timer_start = platform::walltime();
|
||||
|
||||
n_calculations += calculate_lambda_input();
|
||||
|
||||
timer += platform::walltime() - timer_start;
|
||||
|
||||
fix_lambda->update_lambda_input_history();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
global settings
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLambdaInputAPIP::settings(int narg, char **arg)
|
||||
{
|
||||
if (narg < 1) utils::missing_cmd_args(FLERR, "pair_style lambda_input", error);
|
||||
|
||||
cut_global = utils::numeric(FLERR, arg[0], false, lmp);
|
||||
|
||||
// reset cutoffs that have been explicitly set
|
||||
if (allocated) {
|
||||
int i, j;
|
||||
for (i = 1; i <= atom->ntypes; i++)
|
||||
for (j = i; j <= atom->ntypes; j++)
|
||||
if (setflag[i][j]) cut[i][j] = cut_global;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init specific to this pair style
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLambdaInputAPIP::init_style()
|
||||
{
|
||||
if (!atom->apip_lambda_input_flag)
|
||||
error->all(FLERR, "pair_lambda input requires an atom style with lambda_input");
|
||||
|
||||
// find fix lambda
|
||||
int count = 0;
|
||||
for (int i = 0; i < modify->nfix; i++) {
|
||||
if (strcmp(modify->fix[i]->style, "lambda/apip") == 0) {
|
||||
fix_lambda = (FixLambdaAPIP *) modify->fix[i];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count != 1) error->all(FLERR, "Exact one fix lambda required");
|
||||
|
||||
// get group whose input is ignored from fix lambda
|
||||
ignore_group_bit = fix_lambda->group_bit_ignore_lambda_input;
|
||||
|
||||
neighbor->add_request(this, NeighConst::REQ_FULL);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init for one type pair i,j and corresponding j,i
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double PairLambdaInputAPIP::init_one(int i, int j)
|
||||
{
|
||||
if (setflag[i][j] == 0) { cut[i][j] = mix_distance(cut[i][i], cut[j][j]); }
|
||||
return cut[i][j];
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute lambda_input and write it to atom->apip_lambda_input.
|
||||
* Count the number of computations and measure the compute time for
|
||||
* fix atom_weight/apip.
|
||||
*/
|
||||
|
||||
int PairLambdaInputAPIP::calculate_lambda_input()
|
||||
{
|
||||
int i, ii, inum;
|
||||
int *ilist;
|
||||
|
||||
inum = list->inum;
|
||||
ilist = list->ilist;
|
||||
|
||||
double *lambda_input = atom->apip_lambda_input;
|
||||
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
// "compute" and set lambda input
|
||||
lambda_input[i] = 0;
|
||||
}
|
||||
// return number of calculations
|
||||
return inum;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set return values for timers and counted particles
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLambdaInputAPIP::calculate_time_per_atom()
|
||||
{
|
||||
if (n_calculations > 0)
|
||||
time_per_atom = timer / n_calculations;
|
||||
else
|
||||
time_per_atom = -1;
|
||||
|
||||
// reset
|
||||
timer = 0;
|
||||
n_calculations = 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void *PairLambdaInputAPIP::extract(const char *str, int &dim)
|
||||
{
|
||||
dim = 0;
|
||||
if (strcmp(str, "lambda/input/apip:time_per_atom") == 0) {
|
||||
calculate_time_per_atom();
|
||||
return (void *) &time_per_atom;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
64
src/APIP/pair_lambda_input_apip.h
Normal file
64
src/APIP/pair_lambda_input_apip.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* -*- 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 author: David Immel (d.immel@fz-juelich.de, FZJ, Germany)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef PAIR_CLASS
|
||||
// clang-format off
|
||||
PairStyle(lambda/input/apip,PairLambdaInputAPIP);
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
#ifndef LMP_PAIR_LAMBDA_INPUT_APIP_H
|
||||
#define LMP_PAIR_LAMBDA_INPUT_APIP_H
|
||||
|
||||
#include "fix_lambda_apip.h"
|
||||
#include "pair.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PairLambdaInputAPIP : public Pair {
|
||||
friend class FixLambdaAPIP;
|
||||
|
||||
public:
|
||||
PairLambdaInputAPIP(class LAMMPS *);
|
||||
~PairLambdaInputAPIP() override;
|
||||
void compute(int, int) override;
|
||||
virtual void settings(int, char **) override;
|
||||
void coeff(int, char **) override;
|
||||
void init_style() override;
|
||||
double init_one(int, int) override;
|
||||
void *extract(const char *, int &) override;
|
||||
|
||||
protected:
|
||||
class FixLambdaAPIP *fix_lambda; // ptr to fix lambda to store the calculated lambda_input
|
||||
|
||||
// pro forma pair style variables
|
||||
double cut_global;
|
||||
double **cut;
|
||||
|
||||
double timer; // accumulated compute time
|
||||
double time_per_atom; // compute time of one calculaiton
|
||||
int n_calculations; // number of accumulated calculations
|
||||
int ignore_group_bit; // groupbit of the group that must not be calculated
|
||||
|
||||
void allocate();
|
||||
void calculate_time_per_atom();
|
||||
virtual int calculate_lambda_input();
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
319
src/APIP/pair_lambda_input_csp_apip.cpp
Normal file
319
src/APIP/pair_lambda_input_csp_apip.cpp
Normal file
@ -0,0 +1,319 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
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: David Immel (d.immel@fz-juelich.de, FZJ, Germany)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "pair_lambda_input_csp_apip.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "error.h"
|
||||
#include "memory.h"
|
||||
#include "neigh_list.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairLambdaInputCSPAPIP::PairLambdaInputCSPAPIP(LAMMPS *lmp) :
|
||||
PairLambdaInputAPIP(lmp), distsq(nullptr), nearest(nullptr)
|
||||
{
|
||||
// set defaults
|
||||
nnn = 0;
|
||||
nnn_buffer = 0;
|
||||
maxneigh = 0;
|
||||
cut_csp_sq = -1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairLambdaInputCSPAPIP::~PairLambdaInputCSPAPIP()
|
||||
{
|
||||
if (copymode) return;
|
||||
|
||||
memory->destroy(distsq);
|
||||
memory->destroy(nearest);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
global settings
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLambdaInputCSPAPIP::settings(int narg, char **arg)
|
||||
{
|
||||
double cut_csp = 5;
|
||||
|
||||
// parse arguments
|
||||
if (narg < 1) error->all(FLERR, "pair lambda_input/csp: lattice requires one argument");
|
||||
|
||||
if (strcmp(arg[0], "fcc") == 0)
|
||||
nnn = 12;
|
||||
else if (strcmp(arg[0], "bcc") == 0)
|
||||
nnn = 8;
|
||||
else
|
||||
nnn = utils::inumeric(FLERR, arg[0], false, lmp);
|
||||
|
||||
int iarg = 1;
|
||||
while (iarg < narg) {
|
||||
if (strcmp(arg[iarg], "cutoff") == 0) {
|
||||
if (iarg + 1 >= narg)
|
||||
error->all(FLERR, "pair lambda_input/csp: threshold requires an argument");
|
||||
cut_csp = utils::numeric(FLERR, arg[iarg + 1], false, lmp);
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg], "N_buffer") == 0) {
|
||||
if (iarg + 1 >= narg)
|
||||
error->all(FLERR, "pair lambda_input/csp: N_buffer requires an argument");
|
||||
nnn_buffer = utils::inumeric(FLERR, arg[iarg + 1], false, lmp);
|
||||
iarg += 2;
|
||||
} else
|
||||
error->all(FLERR, "pair_lambda_input_csp: unknown argument {}", arg[iarg]);
|
||||
}
|
||||
|
||||
if (nnn <= 1 || nnn % 2)
|
||||
error->all(FLERR,
|
||||
"pair_lambda_input_csp: even number of neighbours > 1 for csp calculation required");
|
||||
if (cut_csp <= 0) error->all(FLERR, "pair_lambda_input_csp: cut_csp <= 0");
|
||||
if (nnn_buffer < 0) error->all(FLERR, "pair_lambda_input_csp: N_buffer negative");
|
||||
|
||||
cut_global = cut_csp;
|
||||
cut_csp_sq = cut_csp * cut_csp;
|
||||
|
||||
// reset cutoffs that have been explicitly set
|
||||
if (allocated) {
|
||||
int i, j;
|
||||
for (i = 1; i <= atom->ntypes; i++)
|
||||
for (j = i; j <= atom->ntypes; j++)
|
||||
if (setflag[i][j]) cut[i][j] = cut_global;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute CSP and write it to atom->apip_lambda_input.
|
||||
* Count the number of computations and measure the compute time for
|
||||
* fix atom_weight/apip.
|
||||
*/
|
||||
|
||||
int PairLambdaInputCSPAPIP::calculate_lambda_input()
|
||||
{
|
||||
int i, j, k, ii, jj, kk, n, n_cutoff, inum, jnum;
|
||||
double xtmp, ytmp, ztmp, delx, dely, delz, rsq, value;
|
||||
int *ilist, *jlist, *numneigh, **firstneigh, *mask;
|
||||
|
||||
inum = list->inum;
|
||||
ilist = list->ilist;
|
||||
numneigh = list->numneigh;
|
||||
firstneigh = list->firstneigh;
|
||||
mask = atom->mask;
|
||||
|
||||
// npairs = number of unique pairs
|
||||
|
||||
int nhalf = nnn / 2;
|
||||
int nnn_all = nnn + nnn_buffer;
|
||||
int npairs = nnn_all * (nnn_all - 1) / 2;
|
||||
auto pairs = new double[npairs];
|
||||
|
||||
double **x = atom->x;
|
||||
double *lambda_input = atom->apip_lambda_input;
|
||||
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
|
||||
if (mask[i] & ignore_group_bit) {
|
||||
// do not calculate the input as it is not used later
|
||||
lambda_input[i] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
jlist = firstneigh[i];
|
||||
jnum = numneigh[i];
|
||||
|
||||
// ensure distsq and nearest arrays are long enough
|
||||
|
||||
if (jnum > maxneigh) {
|
||||
memory->destroy(distsq);
|
||||
memory->destroy(nearest);
|
||||
maxneigh = jnum;
|
||||
memory->create(distsq, maxneigh, "pair lambda_input/csp:distsq");
|
||||
memory->create(nearest, maxneigh, "pair lambda_input/csp:nearest");
|
||||
}
|
||||
|
||||
// loop over list of all neighbors within force cutoff
|
||||
// distsq[] = distance sq to each
|
||||
// nearest[] = atom indices of neighbors
|
||||
|
||||
n_cutoff = 0;
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
j = jlist[jj];
|
||||
j &= NEIGHMASK;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx * delx + dely * dely + delz * delz;
|
||||
// do not use cutsq since cutsq may be quite large due to the maximum search of lambda
|
||||
if (rsq < cut_csp_sq) {
|
||||
distsq[n_cutoff] = rsq;
|
||||
nearest[n_cutoff++] = j;
|
||||
}
|
||||
}
|
||||
|
||||
if (n_cutoff >= nnn_all) {
|
||||
// calculate the values of the centro symmetry parameter for this atom
|
||||
|
||||
// store nnn_all nearest neighs in 1st nnn_all locations of distsq and nearest
|
||||
|
||||
select2(nnn_all, n_cutoff, distsq, nearest);
|
||||
|
||||
// R = Ri + Rj for each of npairs i,j pairs among nnn_all neighbors
|
||||
// pairs = squared length of each R
|
||||
|
||||
n = 0;
|
||||
for (j = 0; j < nnn_all; j++) {
|
||||
jj = nearest[j];
|
||||
for (k = j + 1; k < nnn_all; k++) {
|
||||
kk = nearest[k];
|
||||
delx = x[jj][0] + x[kk][0] - 2.0 * xtmp;
|
||||
dely = x[jj][1] + x[kk][1] - 2.0 * ytmp;
|
||||
delz = x[jj][2] + x[kk][2] - 2.0 * ztmp;
|
||||
pairs[n++] = delx * delx + dely * dely + delz * delz;
|
||||
}
|
||||
}
|
||||
|
||||
// store nhalf smallest pair distances in 1st nhalf locations of pairs
|
||||
|
||||
select(nhalf, npairs, pairs);
|
||||
|
||||
// centrosymmetry = sum of nhalf smallest squared values
|
||||
|
||||
// calculate centro symmetry parameter of this atom
|
||||
value = 0.0;
|
||||
for (j = 0; j < nhalf; j++) value += pairs[j];
|
||||
|
||||
} else {
|
||||
// cannot calculate nnn/2 neighbour pairs
|
||||
// -> just set a high value
|
||||
value = 1000.0;
|
||||
}
|
||||
|
||||
// store cs for this atom
|
||||
lambda_input[i] = value;
|
||||
}
|
||||
|
||||
delete[] pairs;
|
||||
|
||||
// return number of calculations
|
||||
return inum;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
2 select routines from Numerical Recipes (slightly modified)
|
||||
find k smallest values in array of length n
|
||||
2nd routine sorts auxiliary array at same time
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLambdaInputCSPAPIP::select(int k, int n, double *arr)
|
||||
{
|
||||
int i, ir, j, l, mid;
|
||||
double a;
|
||||
|
||||
arr--;
|
||||
l = 1;
|
||||
ir = n;
|
||||
for (;;) {
|
||||
if (ir <= l + 1) {
|
||||
if (ir == l + 1 && arr[ir] < arr[l]) { std::swap(arr[l], arr[ir]); }
|
||||
return;
|
||||
} else {
|
||||
mid = (l + ir) >> 1;
|
||||
std::swap(arr[mid], arr[l + 1]);
|
||||
if (arr[l] > arr[ir]) { std::swap(arr[l], arr[ir]); }
|
||||
if (arr[l + 1] > arr[ir]) { std::swap(arr[l + 1], arr[ir]); }
|
||||
if (arr[l] > arr[l + 1]) { std::swap(arr[l], arr[l + 1]); }
|
||||
i = l + 1;
|
||||
j = ir;
|
||||
a = arr[l + 1];
|
||||
for (;;) {
|
||||
do i++;
|
||||
while (arr[i] < a);
|
||||
do j--;
|
||||
while (arr[j] > a);
|
||||
if (j < i) break;
|
||||
std::swap(arr[i], arr[j]);
|
||||
}
|
||||
arr[l + 1] = arr[j];
|
||||
arr[j] = a;
|
||||
if (j >= k) ir = j - 1;
|
||||
if (j <= k) l = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairLambdaInputCSPAPIP::select2(int k, int n, double *arr, int *iarr)
|
||||
{
|
||||
int i, ir, j, l, mid, ia, itmp;
|
||||
double a;
|
||||
|
||||
arr--;
|
||||
iarr--;
|
||||
l = 1;
|
||||
ir = n;
|
||||
for (;;) {
|
||||
if (ir <= l + 1) {
|
||||
if (ir == l + 1 && arr[ir] < arr[l]) {
|
||||
std::swap(arr[l], arr[ir]);
|
||||
std::swap(iarr[l], iarr[ir]);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
mid = (l + ir) >> 1;
|
||||
std::swap(arr[mid], arr[l + 1]);
|
||||
std::swap(iarr[mid], iarr[l + 1]);
|
||||
if (arr[l] > arr[ir]) {
|
||||
std::swap(arr[l], arr[ir]);
|
||||
std::swap(iarr[l], iarr[ir]);
|
||||
}
|
||||
if (arr[l + 1] > arr[ir]) {
|
||||
std::swap(arr[l + 1], arr[ir]);
|
||||
std::swap(iarr[l + 1], iarr[ir]);
|
||||
}
|
||||
if (arr[l] > arr[l + 1]) {
|
||||
std::swap(arr[l], arr[l + 1]);
|
||||
std::swap(iarr[l], iarr[l + 1]);
|
||||
}
|
||||
i = l + 1;
|
||||
j = ir;
|
||||
a = arr[l + 1];
|
||||
ia = iarr[l + 1];
|
||||
for (;;) {
|
||||
do i++;
|
||||
while (arr[i] < a);
|
||||
do j--;
|
||||
while (arr[j] > a);
|
||||
if (j < i) break;
|
||||
std::swap(arr[i], arr[j]);
|
||||
std::swap(iarr[i], iarr[j]);
|
||||
}
|
||||
arr[l + 1] = arr[j];
|
||||
arr[j] = a;
|
||||
iarr[l + 1] = iarr[j];
|
||||
iarr[j] = ia;
|
||||
if (j >= k) ir = j - 1;
|
||||
if (j <= k) l = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
54
src/APIP/pair_lambda_input_csp_apip.h
Normal file
54
src/APIP/pair_lambda_input_csp_apip.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* -*- 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 author: David Immel (d.immel@fz-juelich.de, FZJ, Germany)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef PAIR_CLASS
|
||||
// clang-format off
|
||||
PairStyle(lambda/input/csp/apip,PairLambdaInputCSPAPIP);
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
#ifndef LMP_PAIR_LAMBDA_INPUT_CSP_APIP_H
|
||||
#define LMP_PAIR_LAMBDA_INPUT_CSP_APIP_H
|
||||
|
||||
#include "pair_lambda_input_apip.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PairLambdaInputCSPAPIP : virtual public PairLambdaInputAPIP {
|
||||
|
||||
public:
|
||||
PairLambdaInputCSPAPIP(class LAMMPS *);
|
||||
~PairLambdaInputCSPAPIP();
|
||||
void settings(int, char **) override;
|
||||
|
||||
protected:
|
||||
// csp variables
|
||||
double cut_csp_sq; ///< squared cutoff
|
||||
int maxneigh; ///< number of atoms for which distsq and nearest are allocated
|
||||
int nnn; ///< number of nearest neighbours that are used in the csp calculation
|
||||
int nnn_buffer; ///< number of additional (to nnn) stored nearest neighbours
|
||||
double *distsq; ///< distance sq to each neighbor
|
||||
int *nearest; ///< atom indices of neighbors
|
||||
|
||||
int calculate_lambda_input() override;
|
||||
void select(int, int, double *);
|
||||
void select2(int, int, double *, int *);
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
311
src/APIP/pair_lambda_zone_apip.cpp
Normal file
311
src/APIP/pair_lambda_zone_apip.cpp
Normal file
@ -0,0 +1,311 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
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: David Immel (d.immel@fz-juelich.de, FZJ, Germany)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "pair_lambda_zone_apip.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "error.h"
|
||||
#include "fix.h"
|
||||
#include "memory.h"
|
||||
#include "modify.h"
|
||||
#include "neigh_list.h"
|
||||
#include "neighbor.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairLambdaZoneAPIP::PairLambdaZoneAPIP(LAMMPS *lmp) :
|
||||
Pair(lmp), lambda_ta(nullptr), cut(nullptr)
|
||||
{
|
||||
// set defaults
|
||||
|
||||
cut_global = cut_lo = cut_hi = cut_hi_sq = cut_width = lambda_non_group = -1;
|
||||
groupbit = -1;
|
||||
nmax_ta = 0;
|
||||
|
||||
timer = 0;
|
||||
n_calculations = 0;
|
||||
time_per_atom = -1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairLambdaZoneAPIP::~PairLambdaZoneAPIP()
|
||||
{
|
||||
if (copymode) return;
|
||||
|
||||
if (allocated) {
|
||||
memory->destroy(setflag);
|
||||
memory->destroy(cutsq);
|
||||
|
||||
memory->destroy(cut);
|
||||
}
|
||||
|
||||
if (nmax_ta > 0) memory->destroy(lambda_ta);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
void PairLambdaZoneAPIP::coeff(int narg, char **arg)
|
||||
{
|
||||
if (narg != 2) error->all(FLERR, "Incorrect args for pair coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo, ihi, jlo, jhi;
|
||||
utils::bounds(FLERR, arg[0], 1, atom->ntypes, ilo, ihi, error);
|
||||
utils::bounds(FLERR, arg[1], 1, atom->ntypes, jlo, jhi, error);
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
for (int j = MAX(jlo, i); j <= jhi; j++) {
|
||||
setflag[i][j] = 1;
|
||||
cut[i][j] = cut_global;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) error->all(FLERR, "Incorrect args for pair coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
allocate all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLambdaZoneAPIP::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->ntypes + 1;
|
||||
|
||||
memory->create(setflag, n, n, "pair:setflag");
|
||||
for (int i = 1; i < n; i++)
|
||||
for (int j = i; j < n; j++) setflag[i][j] = 0;
|
||||
|
||||
memory->create(cutsq, n, n, "pair:cutsq");
|
||||
memory->create(cut, n, n, "pair:cut");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairLambdaZoneAPIP::compute(int eflag, int vflag)
|
||||
{
|
||||
// basic stuff (see pair_zero)
|
||||
ev_init(eflag, vflag);
|
||||
if (vflag_fdotr) virial_fdotr_compute();
|
||||
|
||||
calculate_lambda();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
global settings
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLambdaZoneAPIP::settings(int narg, char **arg)
|
||||
{
|
||||
// parse arguments
|
||||
if (narg != 1) error->all(FLERR, "pair_lambda_zone: expected 1 instead of {} arguments", narg);
|
||||
|
||||
cut_global = utils::numeric(FLERR, arg[0], false, lmp);
|
||||
|
||||
if (cut_global <= 0) error->all(FLERR, "pair_lambda_zone: cut_global = {} <= 0", cut_global);
|
||||
|
||||
// reset cutoffs that have been explicitly set
|
||||
if (allocated) {
|
||||
int i, j;
|
||||
for (i = 1; i <= atom->ntypes; i++)
|
||||
for (j = i; j <= atom->ntypes; j++)
|
||||
if (setflag[i][j]) cut[i][j] = cut_global;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init specific to this pair style
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLambdaZoneAPIP::init_style()
|
||||
{
|
||||
if (!atom->apip_lambda_input_ta_flag)
|
||||
error->all(FLERR, "pair_lambda_zone requires an atom style with lambda_input_ta");
|
||||
|
||||
// find fix lambda/apip
|
||||
class Fix * fix_lambda = nullptr;
|
||||
int count = 0;
|
||||
for (int i = 0; i < modify->nfix; i++) {
|
||||
if (strcmp(modify->fix[i]->style, "lambda/apip") == 0) {
|
||||
fix_lambda = modify->fix[i];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count != 1) error->all(FLERR, "Exact one fix lambda required");
|
||||
|
||||
int dim = 0;
|
||||
cut_lo = *((double *) fix_lambda->extract("fix_lambda:cut_lo", dim));
|
||||
cut_hi = *((double *) fix_lambda->extract("fix_lambda:cut_hi", dim));
|
||||
cut_hi_sq = *((double *) fix_lambda->extract("fix_lambda:cut_hi_sq", dim));
|
||||
cut_width = *((double *) fix_lambda->extract("fix_lambda:cut_width", dim));
|
||||
lambda_non_group = *((double *) fix_lambda->extract("fix_lambda:lambda_non_group", dim));
|
||||
groupbit = fix_lambda->groupbit;
|
||||
|
||||
if (cut_hi > cut_global) error->all(FLERR, "The r_lambda_hi > neighbour_list_cutoff.");
|
||||
|
||||
neighbor->add_request(this, NeighConst::REQ_FULL | NeighConst::REQ_GHOST);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init for one type pair i,j and corresponding j,i
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double PairLambdaZoneAPIP::init_one(int i, int j)
|
||||
{
|
||||
if (setflag[i][j] == 0) { cut[i][j] = mix_distance(cut[i][i], cut[j][j]); }
|
||||
return cut[i][j];
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate new lambda with lambda_input_ta of own and ghost atoms.
|
||||
* Search local maximum of neighbouring atoms for each atom.
|
||||
* input: lambda_input_ta of own + ghost particles
|
||||
* output: lambda_input_ta of own particles
|
||||
*/
|
||||
|
||||
void PairLambdaZoneAPIP::calculate_lambda()
|
||||
{
|
||||
double timer_start = platform::walltime();
|
||||
|
||||
double xtmp, ytmp, ztmp, delx, dely, delz, lambda_tmp, rsq, lambda_new;
|
||||
double **x, *lambda_input_ta;
|
||||
int allnum, ii, i, nlocal, nall, jnum, j, jj, loop_iterations;
|
||||
int *ilist, *mask, *jlist, *numneigh, **firstneigh;
|
||||
|
||||
mask = atom->mask;
|
||||
x = atom->x;
|
||||
lambda_input_ta = atom->apip_lambda_input_ta;
|
||||
|
||||
nlocal = atom->nlocal;
|
||||
nall = nlocal + atom->nghost;
|
||||
|
||||
if (nlocal > nmax_ta) {
|
||||
memory->destroy(lambda_ta);
|
||||
nmax_ta = nlocal;
|
||||
memory->create(lambda_ta, nmax_ta, "pair/lambda:lambda_ta");
|
||||
}
|
||||
|
||||
// 1 set lambda for own particles
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
lambda_ta[i] = (mask[i] & groupbit) ? lambda_input_ta[i] : lambda_non_group;
|
||||
}
|
||||
|
||||
// 2 loop over all atoms with non-simple lambda
|
||||
loop_iterations = 0;
|
||||
|
||||
if (cut_hi_sq > 0) {
|
||||
ilist = list->ilist;
|
||||
allnum = list->inum + list->gnum;
|
||||
numneigh = list->numneigh;
|
||||
firstneigh = list->firstneigh;
|
||||
|
||||
for (ii = 0; ii < allnum; ii++) {
|
||||
i = ilist[ii];
|
||||
|
||||
// skip simple atoms and non-group atoms
|
||||
// which do not influence the lambda_ta of neighbouring atoms
|
||||
if (lambda_input_ta[i] == 1 || (!(mask[i] & groupbit))) { continue; }
|
||||
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
lambda_tmp = 1 - lambda_input_ta[i];
|
||||
jlist = firstneigh[i];
|
||||
jnum = numneigh[i];
|
||||
|
||||
loop_iterations++;
|
||||
|
||||
// 3 loop over neighbours to set their lambda_ta
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
j = jlist[jj];
|
||||
j &= NEIGHMASK;
|
||||
|
||||
// it is not required to set lambda_ta of ghosts or non-group atoms
|
||||
if (j >= nlocal || (!(mask[j] & groupbit))) { continue; }
|
||||
|
||||
// the neighbour j is already complex -> skip
|
||||
if (lambda_ta[j] == 0) { continue; }
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx * delx + dely * dely + delz * delz;
|
||||
|
||||
if (rsq >= cut_hi_sq) { continue; }
|
||||
|
||||
lambda_new = 1 - lambda_tmp * switching_function_poly_distance(sqrt(rsq));
|
||||
|
||||
// more complex lambda_ta found ? set lambda_ta for ngh
|
||||
if (lambda_new < lambda_ta[j]) lambda_ta[j] = lambda_new;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// copy calculated lambda max back to lambda_ta
|
||||
for (i = 0; i < nlocal; i++) lambda_input_ta[i] = lambda_ta[i];
|
||||
|
||||
timer += platform::walltime() - timer_start;
|
||||
n_calculations += loop_iterations;
|
||||
}
|
||||
|
||||
// helper function
|
||||
// similar to cutoff_func_poly in ace_radial.cpp
|
||||
// compare Phys Rev Mat 6, 013804 (2022) APPENDIX C: RADIAL AND CUTOFF FUNCTIONS 2. Cutoff function
|
||||
// the first two derivatives of the switching function lambda vanishes at the boundaries of the switching region
|
||||
double PairLambdaZoneAPIP::switching_function_poly_distance(double input)
|
||||
{
|
||||
// calculate lambda
|
||||
if (input <= cut_lo) {
|
||||
return 1;
|
||||
} else if (input >= cut_hi) {
|
||||
return 0;
|
||||
} else {
|
||||
double deltatmp = 1 - 2 * (1 + (input - cut_hi) / (cut_width));
|
||||
return 0.5 + 7.5 / 2. * (deltatmp / 4. - pow(deltatmp, 3) / 6. + pow(deltatmp, 5) / 20.);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set return values for timers and counted particles
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLambdaZoneAPIP::calculate_time_per_atom()
|
||||
{
|
||||
if (n_calculations > 0)
|
||||
time_per_atom = timer / n_calculations;
|
||||
else
|
||||
time_per_atom = -1;
|
||||
|
||||
// reset
|
||||
timer = 0;
|
||||
n_calculations = 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void *PairLambdaZoneAPIP::extract(const char *str, int &dim)
|
||||
{
|
||||
dim = 0;
|
||||
if (strcmp(str, "lambda/zone/apip:time_per_atom") == 0) {
|
||||
calculate_time_per_atom();
|
||||
return (void *) &time_per_atom;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
73
src/APIP/pair_lambda_zone_apip.h
Normal file
73
src/APIP/pair_lambda_zone_apip.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* -*- 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 author: David Immel (d.immel@fz-juelich.de, FZJ, Germany)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef PAIR_CLASS
|
||||
// clang-format off
|
||||
PairStyle(lambda/zone/apip,PairLambdaZoneAPIP);
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
#ifndef LMP_PAIR_LAMBDA_ZONE_APIP_H
|
||||
#define LMP_PAIR_LAMBDA_ZONE_APIP_H
|
||||
|
||||
#include "pair.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PairLambdaZoneAPIP : public Pair {
|
||||
friend class FixLambdaAPIP;
|
||||
|
||||
public:
|
||||
PairLambdaZoneAPIP(class LAMMPS *);
|
||||
~PairLambdaZoneAPIP() override;
|
||||
void compute(int, int) override;
|
||||
void settings(int, char **) override;
|
||||
void coeff(int, char **) override;
|
||||
void init_style() override;
|
||||
double init_one(int, int) override;
|
||||
void *extract(const char *, int &) override;
|
||||
|
||||
protected:
|
||||
// pro forma pair style variables
|
||||
double **cut;
|
||||
|
||||
// lambda calculation variables
|
||||
double timer; ///< accumulated compute time
|
||||
double time_per_atom; ///< compute time for one atom
|
||||
int n_calculations; ///< number of accumulated computations
|
||||
|
||||
double cut_global; ///< used cutoff
|
||||
double cut_lo; ///< distance at which the cutoff function of the transition zone decays from 1
|
||||
double cut_hi; ///< distance at which the cutoff function of the transition zone is 0
|
||||
double cut_width; ///< cut_hi - cut_lo
|
||||
double cut_hi_sq; ///< cut_hi_sq * cut_hi_sq
|
||||
double lambda_non_group; ///< lambda for atoms that are not in the group of the fix
|
||||
int groupbit; ///< group for which lambda is calculated
|
||||
|
||||
// variables for calculation
|
||||
double *lambda_ta; ///< time averaged lambda input
|
||||
int nmax_ta; ///< size of lambda_ta
|
||||
|
||||
virtual void allocate();
|
||||
void calculate_time_per_atom();
|
||||
void calculate_lambda();
|
||||
double switching_function_poly_distance(double);
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
609
src/APIP/pair_pace_apip.cpp
Normal file
609
src/APIP/pair_pace_apip.cpp
Normal file
@ -0,0 +1,609 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
This file is a modified version of src/ML-PACE/pair_pace.cpp.
|
||||
|
||||
Original copyright:
|
||||
Copyright 2021 Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
||||
Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
||||
Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
||||
|
||||
^1: Ruhr-University Bochum, Bochum, Germany
|
||||
^2: University of Cambridge, Cambridge, United Kingdom
|
||||
^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
||||
^4: University of British Columbia, Vancouver, BC, Canada
|
||||
*/
|
||||
|
||||
//
|
||||
// Originally created by Lysogorskiy Yury on 27.02.20.
|
||||
// Adaptive precision added by David Immel in 2025
|
||||
// (d.immel@fz-juelich.de, FZJ, Germany).
|
||||
//
|
||||
|
||||
#include "pair_pace_apip.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "atom_vec_apip.h"
|
||||
#include "comm.h"
|
||||
#include "error.h"
|
||||
#include "force.h"
|
||||
#include "math_const.h"
|
||||
#include "memory.h"
|
||||
#include "modify.h"
|
||||
#include "neigh_list.h"
|
||||
#include "neighbor.h"
|
||||
#include "update.h"
|
||||
|
||||
#include <exception>
|
||||
|
||||
#include "ace-evaluator/ace_c_basis.h"
|
||||
#include "ace-evaluator/ace_evaluator.h"
|
||||
#include "ace-evaluator/ace_recursive.h"
|
||||
#include "ace-evaluator/ace_version.h"
|
||||
#include "ace/ace_b_basis.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
struct ACEImpl {
|
||||
ACEImpl() : basis_set(nullptr), ace(nullptr) {}
|
||||
~ACEImpl()
|
||||
{
|
||||
delete basis_set;
|
||||
delete ace;
|
||||
}
|
||||
ACECTildeBasisSet *basis_set;
|
||||
ACERecursiveEvaluator *ace;
|
||||
};
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
static char const *const elements_pace[] = {
|
||||
"X", "H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne", "Na", "Mg", "Al", "Si",
|
||||
"P", "S", "Cl", "Ar", "K", "Ca", "Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu",
|
||||
"Zn", "Ga", "Ge", "As", "Se", "Br", "Kr", "Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", "Ru",
|
||||
"Rh", "Pd", "Ag", "Cd", "In", "Sn", "Sb", "Te", "I", "Xe", "Cs", "Ba", "La", "Ce", "Pr",
|
||||
"Nd", "Pm", "Sm", "Eu", "Gd", "Tb", "Dy", "Ho", "Er", "Tm", "Yb", "Lu", "Hf", "Ta", "W",
|
||||
"Re", "Os", "Ir", "Pt", "Au", "Hg", "Tl", "Pb", "Bi", "Po", "At", "Rn", "Fr", "Ra", "Ac",
|
||||
"Th", "Pa", "U", "Np", "Pu", "Am", "Cm", "Bk", "Cf", "Es", "Fm", "Md", "No", "Lr"};
|
||||
static constexpr int elements_num_pace = sizeof(elements_pace) / sizeof(const char *);
|
||||
|
||||
static int AtomicNumberByName_pace(char *elname)
|
||||
{
|
||||
for (int i = 1; i < elements_num_pace; i++)
|
||||
if (strcmp(elname, elements_pace[i]) == 0) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
PairPACEAPIP::PairPACEAPIP(LAMMPS *lmp) : Pair(lmp)
|
||||
{
|
||||
single_enable = 0;
|
||||
restartinfo = 0;
|
||||
one_coeff = 1;
|
||||
manybody_flag = 1;
|
||||
|
||||
nmax_corerep = 0;
|
||||
flag_corerep_factor = 0;
|
||||
corerep_factor = nullptr;
|
||||
|
||||
aceimpl = new ACEImpl;
|
||||
recursive = false;
|
||||
|
||||
scale = nullptr;
|
||||
|
||||
chunksize = 4096;
|
||||
|
||||
// start of adaptive-precision modifications by DI
|
||||
lambda_thermostat = true;
|
||||
|
||||
n_computations_accumulated = 0;
|
||||
time_wall_accumulated = 0;
|
||||
time_per_atom = -1;
|
||||
// end of adaptive-precision modifications by DI
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
check if allocated, since class can be destructed when incomplete
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
PairPACEAPIP::~PairPACEAPIP()
|
||||
{
|
||||
if (copymode) return;
|
||||
|
||||
delete aceimpl;
|
||||
|
||||
if (allocated) {
|
||||
memory->destroy(setflag);
|
||||
memory->destroy(cutsq);
|
||||
memory->destroy(scale);
|
||||
memory->destroy(corerep_factor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set lambda_required based on lambda and lambda_const
|
||||
* @return true if this calculation is not required
|
||||
*/
|
||||
|
||||
// written by DI. This function is required for the adaptive-precision.
|
||||
int PairPACEAPIP::check_abort_condition(double *lambda, double *lambda_const, int *lambda_required,
|
||||
int i)
|
||||
{
|
||||
if ((lambda[i] == 1) && ((!lambda_thermostat) || (lambda_thermostat && lambda_const[i] == 1))) {
|
||||
lambda_required[i] |= ApipLambdaRequired::NO_COMPLEX;
|
||||
return 1;
|
||||
}
|
||||
lambda_required[i] |= ApipLambdaRequired::COMPLEX;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return prefactor 1-lambda which is used for a precise ACE potential
|
||||
*/
|
||||
|
||||
// written by DI. This function is required for the adaptive-precision.
|
||||
double PairPACEAPIP::compute_factor_lambda(double lambda)
|
||||
{
|
||||
return 1 - lambda;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return atom->apip_e_precise which is used for a precise ACE potential
|
||||
*/
|
||||
|
||||
// written by DI. This function is required for the adaptive-precision.
|
||||
double *PairPACEAPIP::get_e_ref_ptr()
|
||||
{
|
||||
return atom->apip_e_precise;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairPACEAPIP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
// start of adaptive-precision modifications by DI
|
||||
// start timers
|
||||
double time_wall_start = platform::walltime();
|
||||
double *lambda = atom->apip_lambda;
|
||||
int *lambda_required = atom->apip_lambda_required;
|
||||
|
||||
double **f_const_lambda = nullptr;
|
||||
double **f_dyn_lambda = nullptr;
|
||||
double *e_ref = nullptr;
|
||||
double *lambda_const = nullptr;
|
||||
if (lambda_thermostat) {
|
||||
f_const_lambda = atom->apip_f_const_lambda;
|
||||
f_dyn_lambda = atom->apip_f_dyn_lambda;
|
||||
e_ref = get_e_ref_ptr();
|
||||
lambda_const = atom->apip_lambda_const;
|
||||
}
|
||||
int n_computations = 0;
|
||||
// end of adaptive-precision modifications by DI
|
||||
|
||||
int i, j, ii, jj, inum, jnum;
|
||||
double delx, dely, delz, evdwl;
|
||||
double fij[3];
|
||||
int *ilist, *jlist, *numneigh, **firstneigh;
|
||||
|
||||
ev_init(eflag, vflag);
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int *type = atom->type;
|
||||
|
||||
// number of atoms in cell
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_pair = force->newton_pair;
|
||||
|
||||
// inum: length of the neighborlists list
|
||||
inum = list->inum;
|
||||
|
||||
// ilist: list of "i" atoms for which neighbor lists exist
|
||||
ilist = list->ilist;
|
||||
|
||||
//numneigh: the length of each these neigbor list
|
||||
numneigh = list->numneigh;
|
||||
|
||||
// the pointer to the list of neighbors of "i"
|
||||
firstneigh = list->firstneigh;
|
||||
|
||||
if (flag_corerep_factor && atom->nlocal > nmax_corerep) {
|
||||
memory->destroy(corerep_factor);
|
||||
nmax_corerep = atom->nlocal;
|
||||
memory->create(corerep_factor, nmax_corerep, "pace/atom:corerep_factor");
|
||||
//zeroify array
|
||||
memset(corerep_factor, 0, nmax_corerep * sizeof(*corerep_factor));
|
||||
}
|
||||
|
||||
//determine the maximum number of neighbours
|
||||
int max_jnum = 0;
|
||||
int nei = 0;
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
jnum = numneigh[i];
|
||||
nei = nei + jnum;
|
||||
if (jnum > max_jnum) max_jnum = jnum;
|
||||
}
|
||||
|
||||
aceimpl->ace->resize_neighbours_cache(max_jnum);
|
||||
|
||||
//loop over atoms
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = list->ilist[ii];
|
||||
const int itype = type[i];
|
||||
|
||||
const double xtmp = x[i][0];
|
||||
const double ytmp = x[i][1];
|
||||
const double ztmp = x[i][2];
|
||||
|
||||
jlist = firstneigh[i];
|
||||
jnum = numneigh[i];
|
||||
|
||||
// start of adaptive-precision modifications by DI
|
||||
// Abort calculation when ace is not required for this atom.
|
||||
// All force and energy contributions calculated in the following are weighted with
|
||||
// 1-lambda when ace is used as precise potential (and with lambda if ace is used as simple potential).
|
||||
// As this weighting factor can be 0, i.e. there is no contribution, one can abort the calculation
|
||||
// of this atom in this case.
|
||||
if (check_abort_condition(lambda, lambda_const, lambda_required, i)) { continue; }
|
||||
n_computations++;
|
||||
// set factor required for forces and for energy summation
|
||||
// fast potential: lambda
|
||||
// precise potential: 1-lambda
|
||||
const double factor_lambda_i = compute_factor_lambda(lambda[i]);
|
||||
const double factor_lambdaconst_i =
|
||||
(lambda_thermostat ? compute_factor_lambda(lambda_const[i]) : 0);
|
||||
// end of adaptive-precision modifications by DI
|
||||
|
||||
// checking if neighbours are actually within cutoff range is done inside compute_atom
|
||||
// mapping from LAMMPS atom types ('type' array) to ACE species is done inside compute_atom
|
||||
// by using 'aceimpl->ace->element_type_mapping' array
|
||||
// x: [r0 ,r1, r2, ..., r100]
|
||||
// i = 0 ,1
|
||||
// jnum(0) = 50
|
||||
// jlist(neigh ind of 0-atom) = [1,2,10,7,99,25, .. 50 element in total]
|
||||
|
||||
try {
|
||||
aceimpl->ace->compute_atom(i, x, type, jnum, jlist);
|
||||
} catch (std::exception &e) {
|
||||
error->one(FLERR, e.what());
|
||||
}
|
||||
|
||||
if (flag_corerep_factor) corerep_factor[i] = 1 - aceimpl->ace->ace_fcut;
|
||||
|
||||
// 'compute_atom' will update the `aceimpl->ace->e_atom` and `aceimpl->ace->neighbours_forces(jj, alpha)` arrays
|
||||
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
j = jlist[jj];
|
||||
j &= NEIGHMASK;
|
||||
delx = x[j][0] - xtmp;
|
||||
dely = x[j][1] - ytmp;
|
||||
delz = x[j][2] - ztmp;
|
||||
|
||||
fij[0] = scale[itype][itype] * aceimpl->ace->neighbours_forces(jj, 0);
|
||||
fij[1] = scale[itype][itype] * aceimpl->ace->neighbours_forces(jj, 1);
|
||||
fij[2] = scale[itype][itype] * aceimpl->ace->neighbours_forces(jj, 2);
|
||||
|
||||
// start of adaptive-precision modifications by DI
|
||||
// The force contributions fij need to be weighted with 1-lambda[i]
|
||||
// (or lambda[i] in case of a fast ace potential).
|
||||
f[i][0] += factor_lambda_i * fij[0];
|
||||
f[i][1] += factor_lambda_i * fij[1];
|
||||
f[i][2] += factor_lambda_i * fij[2];
|
||||
f[j][0] -= factor_lambda_i * fij[0];
|
||||
f[j][1] -= factor_lambda_i * fij[1];
|
||||
f[j][2] -= factor_lambda_i * fij[2];
|
||||
|
||||
if (lambda_thermostat) {
|
||||
f_dyn_lambda[i][0] += factor_lambda_i * fij[0];
|
||||
f_dyn_lambda[i][1] += factor_lambda_i * fij[1];
|
||||
f_dyn_lambda[i][2] += factor_lambda_i * fij[2];
|
||||
f_dyn_lambda[j][0] -= factor_lambda_i * fij[0];
|
||||
f_dyn_lambda[j][1] -= factor_lambda_i * fij[1];
|
||||
f_dyn_lambda[j][2] -= factor_lambda_i * fij[2];
|
||||
f_const_lambda[i][0] += factor_lambdaconst_i * fij[0];
|
||||
f_const_lambda[i][1] += factor_lambdaconst_i * fij[1];
|
||||
f_const_lambda[i][2] += factor_lambdaconst_i * fij[2];
|
||||
f_const_lambda[j][0] -= factor_lambdaconst_i * fij[0];
|
||||
f_const_lambda[j][1] -= factor_lambdaconst_i * fij[1];
|
||||
f_const_lambda[j][2] -= factor_lambdaconst_i * fij[2];
|
||||
}
|
||||
// end of adaptive-precision modifications by DI
|
||||
|
||||
// tally per-atom virial contribution
|
||||
if (vflag_either)
|
||||
// following line of code modified by DI
|
||||
ev_tally_xyz(i, j, nlocal, newton_pair, 0.0, 0.0, factor_lambda_i * fij[0],
|
||||
factor_lambda_i * fij[1], factor_lambda_i * fij[2], -delx, -dely, -delz);
|
||||
}
|
||||
|
||||
// tally energy contribution
|
||||
// start of adaptive-precision modifications by DI
|
||||
if (eflag_either || lambda_thermostat) {
|
||||
// The potential energy needs to be stored to apply the
|
||||
// energy correction with the local thermostat.
|
||||
if (e_ref) e_ref[i] = scale[itype][itype] * aceimpl->ace->e_atom;
|
||||
// evdwl = energy of atom I
|
||||
// The potential energy is weighted with lambda[i] as well.
|
||||
evdwl = factor_lambda_i * scale[itype][itype] * aceimpl->ace->e_atom;
|
||||
// end of adaptive-precision modifications by DI
|
||||
ev_tally_full(i, 2.0 * evdwl, 0.0, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
if (vflag_fdotr) virial_fdotr_compute();
|
||||
|
||||
// end modifications YL
|
||||
|
||||
// start of adaptive-precision modifications by DI
|
||||
// stop timers
|
||||
time_wall_accumulated += platform::walltime() - time_wall_start;
|
||||
n_computations_accumulated += n_computations;
|
||||
// end of adaptive-precision modifications by DI
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairPACEAPIP::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->ntypes + 1;
|
||||
|
||||
memory->create(setflag, n, n, "pair:setflag");
|
||||
memory->create(cutsq, n, n, "pair:cutsq");
|
||||
memory->create(scale, n, n, "pair:scale");
|
||||
map = new int[n];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
global settings
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairPACEAPIP::settings(int narg, char **arg)
|
||||
{
|
||||
if (narg > 3) utils::missing_cmd_args(FLERR, "pair_style pace", error);
|
||||
|
||||
// ACE potentials are parameterized in metal units
|
||||
if (strcmp("metal", update->unit_style) != 0)
|
||||
error->all(FLERR, "ACE potentials require 'metal' units");
|
||||
|
||||
recursive = true; // default evaluator style: RECURSIVE
|
||||
|
||||
int iarg = 0;
|
||||
while (iarg < narg) {
|
||||
if (strcmp(arg[iarg], "recursive") == 0) {
|
||||
recursive = true;
|
||||
iarg += 1;
|
||||
} else if (strcmp(arg[iarg], "product") == 0) {
|
||||
recursive = false;
|
||||
iarg += 1;
|
||||
} else if (strcmp(arg[iarg], "chunksize") == 0) {
|
||||
chunksize = utils::inumeric(FLERR, arg[iarg + 1], false, lmp);
|
||||
iarg += 2;
|
||||
} else
|
||||
error->all(FLERR, "Unknown pair_style pace keyword: {}", arg[iarg]);
|
||||
}
|
||||
|
||||
if (comm->me == 0) {
|
||||
utils::logmesg(lmp, "ACE version: {}.{}.{}\n", VERSION_YEAR, VERSION_MONTH, VERSION_DAY);
|
||||
if (recursive)
|
||||
utils::logmesg(lmp, "Recursive evaluator is used by ACE\n");
|
||||
else
|
||||
utils::logmesg(lmp, "Product evaluator is used by ACE\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one or more type pairs
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairPACEAPIP::coeff(int narg, char **arg)
|
||||
{
|
||||
|
||||
if (!allocated) allocate();
|
||||
|
||||
map_element2type(narg - 3, arg + 3);
|
||||
|
||||
auto potential_file_name = utils::get_potential_file_path(arg[2]);
|
||||
|
||||
//load potential file
|
||||
delete aceimpl->basis_set;
|
||||
if (comm->me == 0) utils::logmesg(lmp, "Loading {}\n", potential_file_name);
|
||||
// if potential is in ACEBBasisSet (YAML) format, then convert to ACECTildeBasisSet automatically
|
||||
if (utils::strmatch(potential_file_name, ".*\\.yaml$")) {
|
||||
ACEBBasisSet bBasisSet = ACEBBasisSet(potential_file_name);
|
||||
ACECTildeBasisSet cTildeBasisSet = bBasisSet.to_ACECTildeBasisSet();
|
||||
aceimpl->basis_set = new ACECTildeBasisSet(cTildeBasisSet);
|
||||
} else {
|
||||
aceimpl->basis_set = new ACECTildeBasisSet(potential_file_name);
|
||||
}
|
||||
|
||||
if (comm->me == 0) {
|
||||
utils::logmesg(lmp, "Total number of basis functions\n");
|
||||
|
||||
for (SPECIES_TYPE mu = 0; mu < aceimpl->basis_set->nelements; mu++) {
|
||||
int n_r1 = aceimpl->basis_set->total_basis_size_rank1[mu];
|
||||
int n = aceimpl->basis_set->total_basis_size[mu];
|
||||
utils::logmesg(lmp, "\t{}: {} (r=1) {} (r>1)\n", aceimpl->basis_set->elements_name[mu], n_r1,
|
||||
n);
|
||||
}
|
||||
}
|
||||
|
||||
// read args that map atom types to PACE elements
|
||||
// map[i] = which element the Ith atom type is, -1 if not mapped
|
||||
// map[0] is not used
|
||||
|
||||
delete aceimpl->ace;
|
||||
aceimpl->ace = new ACERecursiveEvaluator();
|
||||
aceimpl->ace->set_recursive(recursive);
|
||||
aceimpl->ace->element_type_mapping.init(atom->ntypes + 1);
|
||||
|
||||
const int n = atom->ntypes;
|
||||
for (int i = 1; i <= n; i++) {
|
||||
char *elemname = arg[2 + i];
|
||||
if (strcmp(elemname, "NULL") == 0) {
|
||||
// species_type=-1 value will not reach ACE Evaluator::compute_atom,
|
||||
// but if it will ,then error will be thrown there
|
||||
aceimpl->ace->element_type_mapping(i) = -1;
|
||||
map[i] = -1;
|
||||
if (comm->me == 0) utils::logmesg(lmp, "Skipping LAMMPS atom type #{}(NULL)\n", i);
|
||||
} else {
|
||||
int atomic_number = AtomicNumberByName_pace(elemname);
|
||||
if (atomic_number == -1) error->all(FLERR, "'{}' is not a valid element\n", elemname);
|
||||
SPECIES_TYPE mu = aceimpl->basis_set->get_species_index_by_name(elemname);
|
||||
if (mu != -1) {
|
||||
if (comm->me == 0)
|
||||
utils::logmesg(lmp, "Mapping LAMMPS atom type #{}({}) -> ACE species type #{}\n", i,
|
||||
elemname, mu);
|
||||
map[i] = mu;
|
||||
// set up LAMMPS atom type to ACE species mapping for ace evaluator
|
||||
aceimpl->ace->element_type_mapping(i) = mu;
|
||||
} else {
|
||||
error->all(FLERR, "Element {} is not supported by ACE-potential from file {}", elemname,
|
||||
potential_file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// initialize scale factor
|
||||
for (int i = 1; i <= n; i++) {
|
||||
for (int j = i; j <= n; j++) scale[i][j] = 1.0;
|
||||
}
|
||||
|
||||
aceimpl->ace->set_basis(*aceimpl->basis_set, 1);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init specific to this pair style
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairPACEAPIP::init_style()
|
||||
{
|
||||
if (atom->tag_enable == 0) error->all(FLERR, "Pair style pace requires atom IDs");
|
||||
if (force->newton_pair == 0) error->all(FLERR, "Pair style pace requires newton pair on");
|
||||
|
||||
// start of adaptive-precision modifications by DI
|
||||
if (!atom->apip_lambda_required_flag)
|
||||
error->all(FLERR, "pair style pace/apip requires an atom style with lambda_required.");
|
||||
if (!atom->apip_lambda_flag)
|
||||
error->all(FLERR, "Pair style pace/apip requires an atom style with lambda");
|
||||
// end of adaptive-precision modifications by DI
|
||||
|
||||
// request a full neighbor list
|
||||
neighbor->add_request(this, NeighConst::REQ_FULL);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init for one type pair i,j and corresponding j,i
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double PairPACEAPIP::init_one(int i, int j)
|
||||
{
|
||||
if (setflag[i][j] == 0) error->all(FLERR, "All pair coeffs are not set");
|
||||
//cutoff from the basis set's radial functions settings
|
||||
scale[j][i] = scale[i][j];
|
||||
return aceimpl->basis_set->radial_functions->cut(map[i], map[j]);
|
||||
}
|
||||
|
||||
/**
|
||||
* setup specific to this pair style
|
||||
* Determine whether there is a fix lambda_thermostat/apip or not and set
|
||||
* lambda_thermostat.
|
||||
*/
|
||||
|
||||
// written by DI. This function is required for the adaptive-precision.
|
||||
void PairPACEAPIP::setup()
|
||||
{
|
||||
if (modify->get_fix_by_style("^lambda_thermostat/apip$").size() == 0) {
|
||||
lambda_thermostat = false;
|
||||
} else {
|
||||
lambda_thermostat = true;
|
||||
if (!atom->apip_lambda_const_flag)
|
||||
error->all(
|
||||
FLERR,
|
||||
"Pair style pace/apip requires an atom style with lambda_const for a local thermostat.");
|
||||
if (!atom->apip_e_fast_flag)
|
||||
error->all(
|
||||
FLERR,
|
||||
"Pair style pace/apip requires an atom style with e_simple for a local thermostat.");
|
||||
if (!atom->apip_e_precise_flag)
|
||||
error->all(
|
||||
FLERR,
|
||||
"Pair style pace/apip requires an atom style with e_complex for a local thermostat.");
|
||||
if (!atom->apip_f_const_lambda_flag)
|
||||
error->all(FLERR,
|
||||
"Pair style pace/apip requires an atom style with f_const_lambda for a local "
|
||||
"thermostat.");
|
||||
if (!atom->apip_f_dyn_lambda_flag)
|
||||
error->all(FLERR,
|
||||
"Pair style pace/apip requires an atom style with f_const_lambda for a local "
|
||||
"thermostat.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set return values for timers and number of computed particles
|
||||
*/
|
||||
|
||||
// written by DI. This function is required for the adaptive-precision.
|
||||
void PairPACEAPIP::calculate_time_per_atom()
|
||||
{
|
||||
if (n_computations_accumulated > 0)
|
||||
time_per_atom = time_wall_accumulated / n_computations_accumulated;
|
||||
else
|
||||
time_per_atom = -1;
|
||||
|
||||
// reset
|
||||
time_wall_accumulated = 0;
|
||||
n_computations_accumulated = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
extract method for extracting value of scale variable
|
||||
---------------------------------------------------------------------- */
|
||||
void *PairPACEAPIP::extract(const char *str, int &dim)
|
||||
{
|
||||
dim = 0;
|
||||
//check if str=="corerep_flag" then compute extrapolation grades on this iteration
|
||||
if (strcmp(str, "corerep_flag") == 0) return (void *) &flag_corerep_factor;
|
||||
// DI: The following option is required for the adaptive precision.
|
||||
if (strcmp(str, "pace/apip:time_per_atom") == 0) {
|
||||
calculate_time_per_atom();
|
||||
return (void *) &time_per_atom;
|
||||
}
|
||||
|
||||
dim = 2;
|
||||
if (strcmp(str, "scale") == 0) return (void *) scale;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
peratom requests from FixPair
|
||||
return ptr to requested data
|
||||
also return ncol = # of quantites per atom
|
||||
0 = per-atom vector
|
||||
1 or more = # of columns in per-atom array
|
||||
return NULL if str is not recognized
|
||||
---------------------------------------------------------------------- */
|
||||
void *PairPACEAPIP::extract_peratom(const char *str, int &ncol)
|
||||
{
|
||||
if (strcmp(str, "corerep") == 0) {
|
||||
ncol = 0;
|
||||
return (void *) corerep_factor;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
90
src/APIP/pair_pace_apip.h
Normal file
90
src/APIP/pair_pace_apip.h
Normal file
@ -0,0 +1,90 @@
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
LAMMPS development team: developers@lammps.org
|
||||
|
||||
This software is distributed under the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
This file is a modified version of src/ML-PACE/pair_pace.h.
|
||||
|
||||
Original copyright:
|
||||
Copyright 2021 Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
|
||||
Sarath Menon^1, Matteo Rinaldi^1, Thomas Hammerschmidt^1, Matous Mrovec^1,
|
||||
Aidan Thompson^3, Gabor Csanyi^2, Christoph Ortner^4, Ralf Drautz^1
|
||||
|
||||
^1: Ruhr-University Bochum, Bochum, Germany
|
||||
^2: University of Cambridge, Cambridge, United Kingdom
|
||||
^3: Sandia National Laboratories, Albuquerque, New Mexico, USA
|
||||
^4: University of British Columbia, Vancouver, BC, Canada
|
||||
*/
|
||||
|
||||
//
|
||||
// Originally created by Lysogorskiy Yury on 27.02.20.
|
||||
// Adaptive precision added by David Immel in 2025
|
||||
// (d.immel@fz-juelich.de, FZJ, Germany).
|
||||
//
|
||||
|
||||
#ifdef PAIR_CLASS
|
||||
// clang-format off
|
||||
PairStyle(pace/apip,PairPACEAPIP);
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
#ifndef LMP_PAIR_PACE_APIP_H
|
||||
#define LMP_PAIR_PACE_APIP_H
|
||||
|
||||
#include "pair.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PairPACEAPIP : public Pair {
|
||||
public:
|
||||
PairPACEAPIP(class LAMMPS *);
|
||||
~PairPACEAPIP() override;
|
||||
|
||||
void compute(int, int) override;
|
||||
void settings(int, char **) override;
|
||||
void coeff(int, char **) override;
|
||||
void init_style() override;
|
||||
double init_one(int, int) override;
|
||||
void setup() override;
|
||||
|
||||
void *extract(const char *, int &) override;
|
||||
void *extract_peratom(const char *, int &) override;
|
||||
|
||||
protected:
|
||||
struct ACEImpl *aceimpl;
|
||||
int nmax_corerep;
|
||||
|
||||
virtual void allocate();
|
||||
double *corerep_factor; //per-atom core-rep factor (= 1 - fcut)
|
||||
int flag_corerep_factor;
|
||||
|
||||
double **scale;
|
||||
bool recursive; // "recursive" option for ACERecursiveEvaluator
|
||||
|
||||
int chunksize;
|
||||
|
||||
// start of adaptive-precision modifications by DI
|
||||
virtual double *get_e_ref_ptr();
|
||||
virtual double compute_factor_lambda(double);
|
||||
virtual int check_abort_condition(double *, double *, int *, int);
|
||||
|
||||
bool lambda_thermostat; // true/false there is one/no fix lambda_thermostat
|
||||
|
||||
void calculate_time_per_atom();
|
||||
|
||||
// stats required for load balancing
|
||||
int n_computations_accumulated; // number of accumulated computations
|
||||
double time_wall_accumulated; // accumulated compute time
|
||||
double time_per_atom; // average time of one computation
|
||||
// end of adaptive-precision modifications by DI
|
||||
};
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
73
src/APIP/pair_pace_fast_apip.cpp
Normal file
73
src/APIP/pair_pace_fast_apip.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
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: David Immel (d.immel@fz-juelich.de, FZJ, Germany)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "pair_pace_fast_apip.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "atom_vec_apip.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
PairPACEFastAPIP::PairPACEFastAPIP(LAMMPS *lmp) : PairPACEAPIP(lmp) {}
|
||||
|
||||
/**
|
||||
* Set lambda_required based on lambda and lambda_const
|
||||
* @return true if this calculation is not required
|
||||
*/
|
||||
|
||||
int PairPACEFastAPIP::check_abort_condition(double *lambda, double *lambda_const,
|
||||
int *lambda_required, int i)
|
||||
{
|
||||
if ((lambda[i] == 0) && ((!lambda_thermostat) || (lambda_thermostat && lambda_const[i] == 0))) {
|
||||
lambda_required[i] |= ApipLambdaRequired::NO_SIMPLE;
|
||||
return 1;
|
||||
}
|
||||
lambda_required[i] |= ApipLambdaRequired::SIMPLE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return prefactor lambda which is used for a fast ACE potential
|
||||
*/
|
||||
|
||||
double PairPACEFastAPIP::compute_factor_lambda(double lambda)
|
||||
{
|
||||
return lambda;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return atom->apip_e_fast which is used for a fast ACE potential
|
||||
*/
|
||||
|
||||
double *PairPACEFastAPIP::get_e_ref_ptr()
|
||||
{
|
||||
return atom->apip_e_fast;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
extract method for extracting value of scale variable
|
||||
---------------------------------------------------------------------- */
|
||||
void *PairPACEFastAPIP::extract(const char *str, int &dim)
|
||||
{
|
||||
dim = 2;
|
||||
if (strcmp(str, "scale") == 0) return (void *) scale;
|
||||
dim = 0;
|
||||
if (strcmp(str, "pace/fast/apip:time_per_atom") == 0) {
|
||||
calculate_time_per_atom();
|
||||
return (void *) &time_per_atom;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
44
src/APIP/pair_pace_fast_apip.h
Normal file
44
src/APIP/pair_pace_fast_apip.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* -*- 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 author: David Immel (d.immel@fz-juelich.de, FZJ, Germany)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef PAIR_CLASS
|
||||
// clang-format off
|
||||
PairStyle(pace/fast/apip,PairPACEFastAPIP);
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
#ifndef LMP_PAIR_PACE_FAST_APIP_H
|
||||
#define LMP_PAIR_PACE_FAST_APIP_H
|
||||
|
||||
#include "pair_pace_apip.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PairPACEFastAPIP : public PairPACEAPIP {
|
||||
public:
|
||||
PairPACEFastAPIP(class LAMMPS *);
|
||||
void *extract(const char *, int &) override;
|
||||
|
||||
protected:
|
||||
double *get_e_ref_ptr() override;
|
||||
double compute_factor_lambda(double) override;
|
||||
int check_abort_condition(double *, double *, int *, int) override;
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
73
src/APIP/pair_pace_precise_apip.cpp
Normal file
73
src/APIP/pair_pace_precise_apip.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
/* -*- 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 author: David Immel (d.immel@fz-juelich.de, FZJ, Germany)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "pair_pace_precise_apip.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "atom_vec_apip.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
PairPACEPreciseAPIP::PairPACEPreciseAPIP(LAMMPS *lmp) : PairPACEAPIP(lmp) {}
|
||||
|
||||
/**
|
||||
* Set lambda_required based on lambda and lambda_const
|
||||
* @return true if this calculation is not required
|
||||
*/
|
||||
|
||||
int PairPACEPreciseAPIP::check_abort_condition(double *lambda, double *lambda_const,
|
||||
int *lambda_required, int i)
|
||||
{
|
||||
if ((lambda[i] == 1) && ((!lambda_thermostat) || (lambda_thermostat && lambda_const[i] == 1))) {
|
||||
lambda_required[i] |= ApipLambdaRequired::NO_COMPLEX;
|
||||
return 1;
|
||||
}
|
||||
lambda_required[i] |= ApipLambdaRequired::COMPLEX;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return prefactor 1-lambda which is used for a precise ACE potential
|
||||
*/
|
||||
|
||||
double PairPACEPreciseAPIP::compute_factor_lambda(double lambda)
|
||||
{
|
||||
return 1 - lambda;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return atom->apip_e_precise which is used for a precise ACE potential
|
||||
*/
|
||||
|
||||
double *PairPACEPreciseAPIP::get_e_ref_ptr()
|
||||
{
|
||||
return atom->apip_e_precise;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
extract method for extracting value of scale variable
|
||||
---------------------------------------------------------------------- */
|
||||
void *PairPACEPreciseAPIP::extract(const char *str, int &dim)
|
||||
{
|
||||
dim = 2;
|
||||
if (strcmp(str, "scale") == 0) return (void *) scale;
|
||||
dim = 0;
|
||||
if (strcmp(str, "pace/apip:time_per_atom") == 0) {
|
||||
calculate_time_per_atom();
|
||||
return (void *) &time_per_atom;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
44
src/APIP/pair_pace_precise_apip.h
Normal file
44
src/APIP/pair_pace_precise_apip.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* -*- 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 author: David Immel (d.immel@fz-juelich.de, FZJ, Germany)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef PAIR_CLASS
|
||||
// clang-format off
|
||||
PairStyle(pace/precise/apip,PairPACEPreciseAPIP);
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
#ifndef LMP_PAIR_PACE_PRECISE_APIP_H
|
||||
#define LMP_PAIR_PACE_PRECISE_APIP_H
|
||||
|
||||
#include "pair_pace_apip.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PairPACEPreciseAPIP : public PairPACEAPIP {
|
||||
public:
|
||||
PairPACEPreciseAPIP(class LAMMPS *);
|
||||
void *extract(const char *, int &) override;
|
||||
|
||||
protected:
|
||||
double *get_e_ref_ptr() override;
|
||||
double compute_factor_lambda(double) override;
|
||||
int check_abort_condition(double *, double *, int *, int) override;
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@ -53,6 +53,7 @@ PACKAGE = \
|
||||
kspace \
|
||||
adios \
|
||||
amoeba \
|
||||
apip \
|
||||
asphere \
|
||||
awpmd \
|
||||
bocs \
|
||||
@ -219,6 +220,7 @@ PACKLIB = \
|
||||
python \
|
||||
voronoi \
|
||||
adios \
|
||||
apip \
|
||||
atc \
|
||||
awpmd \
|
||||
colvars \
|
||||
@ -246,6 +248,7 @@ PACKINT = atc awpmd colvars electrode gpu kokkos lepton ml-pod poems
|
||||
|
||||
PACKEXT = \
|
||||
adios \
|
||||
apip \
|
||||
h5md \
|
||||
kim \
|
||||
machdyn \
|
||||
|
||||
54
src/atom.cpp
54
src/atom.cpp
@ -220,6 +220,12 @@ Atom::Atom(LAMMPS *_lmp) : Pointers(_lmp), atom_style(nullptr), avec(nullptr), a
|
||||
|
||||
area = ed = em = epsilon = curvature = q_scaled = nullptr;
|
||||
|
||||
// APIP package
|
||||
|
||||
apip_lambda_const = apip_lambda = apip_lambda_input = apip_lambda_input_ta = apip_e_fast = apip_e_precise = nullptr;
|
||||
apip_lambda_required = nullptr;
|
||||
apip_f_const_lambda = apip_f_dyn_lambda = nullptr;
|
||||
|
||||
// end of customization section
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@ -575,6 +581,18 @@ void Atom::peratom_create()
|
||||
add_peratom("curvature",&curvature,DOUBLE,0);
|
||||
add_peratom("q_scaled",&q_scaled,DOUBLE,0);
|
||||
|
||||
// APIP package
|
||||
|
||||
add_peratom("apip_lambda",&apip_lambda,DOUBLE,0);
|
||||
add_peratom("apip_lambda_required",&apip_lambda_required,INT,0);
|
||||
add_peratom("apip_lambda_input",&apip_lambda_input,DOUBLE,0);
|
||||
add_peratom("apip_lambda_input_ta",&apip_lambda_input_ta,DOUBLE,0);
|
||||
add_peratom("apip_e_fast",&apip_e_fast,DOUBLE,0);
|
||||
add_peratom("apip_e_precise",&apip_e_precise,DOUBLE,0);
|
||||
add_peratom("apip_lambda_const",&apip_lambda_const,DOUBLE,0);
|
||||
add_peratom("apip_f_const_lambda",&apip_f_const_lambda,DOUBLE,3,1);
|
||||
add_peratom("apip_f_dyn_lambda",&apip_f_dyn_lambda,DOUBLE,3,1);
|
||||
|
||||
// end of customization section
|
||||
// --------------------------------------------------------------------
|
||||
}
|
||||
@ -658,6 +676,7 @@ void Atom::set_atomflag_defaults()
|
||||
contact_radius_flag = smd_data_9_flag = smd_stress_flag = 0;
|
||||
eff_plastic_strain_flag = eff_plastic_strain_rate_flag = 0;
|
||||
nspecial15_flag = 0;
|
||||
apip_lambda_flag = apip_e_fast_flag = apip_e_precise_flag = apip_lambda_input_flag = apip_lambda_input_ta_flag = apip_lambda_required_flag = apip_f_const_lambda_flag = apip_f_dyn_lambda_flag = apip_lambda_const_flag = 0;
|
||||
|
||||
pdscale = 1.0;
|
||||
}
|
||||
@ -3167,6 +3186,18 @@ void *Atom::extract(const char *name)
|
||||
if (strcmp(name,"curvature") == 0) return (void *) curvature;
|
||||
if (strcmp(name,"q_scaled") == 0) return (void *) q_scaled;
|
||||
|
||||
// APIP package
|
||||
|
||||
if (strcmp(name,"apip_lambda") == 0) return (void *) apip_lambda;
|
||||
if (strcmp(name,"apip_lambda_required") == 0) return (void *) apip_lambda_required;
|
||||
if (strcmp(name,"apip_lambda_input") == 0) return (void *) apip_lambda_input;
|
||||
if (strcmp(name,"apip_lambda_input_ta") == 0) return (void *) apip_lambda_input_ta;
|
||||
if (strcmp(name,"apip_e_fast") == 0) return (void *) apip_e_fast;
|
||||
if (strcmp(name,"apip_e_precise") == 0) return (void *) apip_e_precise;
|
||||
if (strcmp(name,"apip_f_const_lambda") == 0) return (void *) apip_f_const_lambda;
|
||||
if (strcmp(name,"apip_f_dyn_lambda") == 0) return (void *) apip_f_dyn_lambda;
|
||||
if (strcmp(name,"apip_lambda_const") == 0) return (void *) apip_lambda_const;
|
||||
|
||||
// end of customization section
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@ -3325,6 +3356,17 @@ int Atom::extract_datatype(const char *name)
|
||||
if (strcmp(name,"curvature") == 0) return LAMMPS_DOUBLE;
|
||||
if (strcmp(name,"q_unscaled") == 0) return LAMMPS_DOUBLE;
|
||||
|
||||
// APIP package
|
||||
|
||||
if (strcmp(name,"apip_lambda") == 0) return LAMMPS_DOUBLE;
|
||||
if (strcmp(name,"apip_lambda_required") == 0) return LAMMPS_INT;
|
||||
if (strcmp(name,"apip_lambda_input") == 0) return LAMMPS_DOUBLE;
|
||||
if (strcmp(name,"apip_lambda_input_ta") == 0) return LAMMPS_DOUBLE;
|
||||
if (strcmp(name,"apip_e_fast") == 0) return LAMMPS_DOUBLE;
|
||||
if (strcmp(name,"apip_e_precise") == 0) return LAMMPS_DOUBLE;
|
||||
if (strcmp(name,"apip_lambda_const") == 0) return LAMMPS_DOUBLE;
|
||||
if (strcmp(name,"apip_f_const_lambda") == 0) return LAMMPS_DOUBLE_2D;
|
||||
if (strcmp(name,"apip_f_dyn_lambda") == 0) return LAMMPS_DOUBLE_2D;
|
||||
// end of customization section
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@ -3461,6 +3503,18 @@ int Atom::extract_size(const char *name, int type)
|
||||
|
||||
if (strcmp(name, "smd_data_9") == 0) return 9;
|
||||
if (strcmp(name, "smd_stress") == 0) return 6;
|
||||
|
||||
// APIP package
|
||||
|
||||
if (strcmp(name, "apip_lambda") == 0) return nlocal;
|
||||
if (strcmp(name, "apip_lambda_required") == 0) return nlocal;
|
||||
if (strcmp(name, "apip_lambda_input") == 0) return nlocal;
|
||||
if (strcmp(name, "apip_lambda_input_ta") == 0) return nlocal;
|
||||
if (strcmp(name, "apip_e_fast") == 0) return nlocal;
|
||||
if (strcmp(name, "apip_e_precise") == 0) return nlocal;
|
||||
if (strcmp(name, "apip_lambda_const") == 0) return nlocal;
|
||||
if (strcmp(name, "apip_f_const_lambda") == 0) return nall;
|
||||
if (strcmp(name, "apip_f_dyn_lambda") == 0) return nall;
|
||||
}
|
||||
|
||||
// custom arrays
|
||||
|
||||
@ -179,6 +179,11 @@ class Atom : protected Pointers {
|
||||
|
||||
double *area, *ed, *em, *epsilon, *curvature, *q_scaled;
|
||||
|
||||
// APIP package
|
||||
|
||||
double *apip_lambda, *apip_lambda_input, *apip_lambda_input_ta, *apip_e_fast, *apip_e_precise, **apip_f_const_lambda, **apip_f_dyn_lambda, *apip_lambda_const;
|
||||
int *apip_lambda_required;
|
||||
|
||||
// end of customization section
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@ -227,6 +232,10 @@ class Atom : protected Pointers {
|
||||
|
||||
int dielectric_flag;
|
||||
|
||||
// APIP package
|
||||
|
||||
int apip_lambda_flag, apip_e_fast_flag, apip_e_precise_flag, apip_lambda_input_flag, apip_lambda_input_ta_flag, apip_lambda_required_flag, apip_f_const_lambda_flag, apip_f_dyn_lambda_flag, apip_lambda_const_flag;
|
||||
|
||||
// end of customization section
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
||||
@ -331,6 +331,25 @@ ComputePropertyAtom::ComputePropertyAtom(LAMMPS *lmp, int narg, char **arg) :
|
||||
error->all(FLERR,"Compute property/atom {} requires atom style tri", arg[iarg]);
|
||||
pack_choice[i] = &ComputePropertyAtom::pack_corner3z;
|
||||
|
||||
// APIP package
|
||||
|
||||
} else if (strcmp(arg[iarg],"apip_lambda") == 0) {
|
||||
if (!atom->apip_lambda_flag)
|
||||
error->all(FLERR,"Compute property/atom {} is not available", arg[iarg]);
|
||||
pack_choice[i] = &ComputePropertyAtom::pack_apip_lambda;
|
||||
} else if (strcmp(arg[iarg],"apip_lambda_input") == 0) {
|
||||
if (!atom->apip_lambda_input_flag)
|
||||
error->all(FLERR,"Compute property/atom {} is not available", arg[iarg]);
|
||||
pack_choice[i] = &ComputePropertyAtom::pack_apip_lambda_input;
|
||||
} else if (strcmp(arg[iarg],"apip_e_fast") == 0) {
|
||||
if (!atom->apip_e_fast_flag)
|
||||
error->all(FLERR,"Compute property/atom {} is not available", arg[iarg]);
|
||||
pack_choice[i] = &ComputePropertyAtom::pack_apip_e_fast;
|
||||
} else if (strcmp(arg[iarg],"apip_e_precise") == 0) {
|
||||
if (!atom->apip_e_precise_flag)
|
||||
error->all(FLERR,"Compute property/atom {} is not available", arg[iarg]);
|
||||
pack_choice[i] = &ComputePropertyAtom::pack_apip_e_precise;
|
||||
|
||||
// custom per-atom vector or array
|
||||
|
||||
} else if (utils::strmatch(arg[iarg],"^[id]2?_")) {
|
||||
@ -1564,6 +1583,66 @@ void ComputePropertyAtom::pack_tqz(int n)
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ComputePropertyAtom::pack_apip_lambda(int n)
|
||||
{
|
||||
double *lambda = atom->apip_lambda;
|
||||
int *mask = atom->mask;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (mask[i] & groupbit) buf[n] = lambda[i];
|
||||
else buf[n] = 0.0;
|
||||
n += nvalues;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ComputePropertyAtom::pack_apip_lambda_input(int n)
|
||||
{
|
||||
double *lambda_input = atom->apip_lambda_input;
|
||||
int *mask = atom->mask;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (mask[i] & groupbit) buf[n] = lambda_input[i];
|
||||
else buf[n] = 0.0;
|
||||
n += nvalues;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ComputePropertyAtom::pack_apip_e_fast(int n)
|
||||
{
|
||||
double *e_simple = atom->apip_e_fast;
|
||||
int *mask = atom->mask;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (mask[i] & groupbit) buf[n] = e_simple[i];
|
||||
else buf[n] = 0.0;
|
||||
n += nvalues;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ComputePropertyAtom::pack_apip_e_precise(int n)
|
||||
{
|
||||
double *e_complex = atom->apip_e_precise;
|
||||
int *mask = atom->mask;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (mask[i] & groupbit) buf[n] = e_complex[i];
|
||||
else buf[n] = 0.0;
|
||||
n += nvalues;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ComputePropertyAtom::pack_end1x(int n)
|
||||
{
|
||||
AtomVecLine::Bonus *bonus = avec_line->bonus;
|
||||
|
||||
@ -137,6 +137,11 @@ class ComputePropertyAtom : public Compute {
|
||||
void pack_d2name(int);
|
||||
|
||||
void pack_atom_style(int);
|
||||
|
||||
void pack_apip_lambda(int);
|
||||
void pack_apip_lambda_input(int);
|
||||
void pack_apip_e_fast(int);
|
||||
void pack_apip_e_precise(int);
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
@ -815,6 +815,7 @@ void ReadDump::process_atoms()
|
||||
double **x = atom->x;
|
||||
double **v = atom->v;
|
||||
double *q = atom->q;
|
||||
double *apip_lambda = atom->apip_lambda;
|
||||
double **f = atom->f;
|
||||
tagint *tag = atom->tag;
|
||||
imageint *image = atom->image;
|
||||
@ -864,6 +865,9 @@ void ReadDump::process_atoms()
|
||||
case Reader::Q:
|
||||
q[m] = fields[i][ifield];
|
||||
break;
|
||||
case Reader::APIP_LAMBDA:
|
||||
apip_lambda[m] = fields[i][ifield];
|
||||
break;
|
||||
case Reader::VY:
|
||||
v[m][1] = fields[i][ifield];
|
||||
break;
|
||||
@ -979,6 +983,7 @@ void ReadDump::process_atoms()
|
||||
tag = atom->tag;
|
||||
v = atom->v;
|
||||
q = atom->q;
|
||||
apip_lambda = atom->apip_lambda;
|
||||
image = atom->image;
|
||||
|
||||
// set atom attributes from other dump file fields
|
||||
@ -1003,6 +1008,9 @@ void ReadDump::process_atoms()
|
||||
case Reader::Q:
|
||||
q[m] = fields[i][ifield];
|
||||
break;
|
||||
case Reader::APIP_LAMBDA:
|
||||
apip_lambda[m] = fields[i][ifield];
|
||||
break;
|
||||
case Reader::IX:
|
||||
xbox = static_cast<int> (fields[i][ifield]);
|
||||
break;
|
||||
@ -1165,6 +1173,8 @@ int ReadDump::fields_and_keywords(int narg, char **arg)
|
||||
if (type < 0) break;
|
||||
if (type == Reader::Q && !atom->q_flag)
|
||||
error->all(FLERR,"Read dump of charge property that isn't supported by atom style");
|
||||
if (type == Reader::APIP_LAMBDA && !atom->apip_lambda_flag)
|
||||
error->all(FLERR,"Read dump of apip_lambda property that isn't supported by atom style");
|
||||
fieldtype[nfield++] = type;
|
||||
iarg++;
|
||||
}
|
||||
@ -1290,6 +1300,7 @@ int ReadDump::whichtype(char *str)
|
||||
else if (strcmp(str,"vy") == 0) type = Reader::VY;
|
||||
else if (strcmp(str,"vz") == 0) type = Reader::VZ;
|
||||
else if (strcmp(str,"q") == 0) type = Reader::Q;
|
||||
else if (strcmp(str,"apip_lambda") == 0) type = Reader::APIP_LAMBDA;
|
||||
else if (strcmp(str,"ix") == 0) type = Reader::IX;
|
||||
else if (strcmp(str,"iy") == 0) type = Reader::IY;
|
||||
else if (strcmp(str,"iz") == 0) type = Reader::IZ;
|
||||
|
||||
@ -22,7 +22,7 @@ namespace LAMMPS_NS {
|
||||
|
||||
class Reader : protected Pointers {
|
||||
public:
|
||||
enum { ID, TYPE, X, Y, Z, VX, VY, VZ, Q, IX, IY, IZ, FX, FY, FZ };
|
||||
enum { ID, TYPE, X, Y, Z, VX, VY, VZ, Q, IX, IY, IZ, FX, FY, FZ, APIP_LAMBDA };
|
||||
enum { UNSET, NOSCALE_NOWRAP, NOSCALE_WRAP, SCALE_NOWRAP, SCALE_WRAP };
|
||||
|
||||
Reader(class LAMMPS *);
|
||||
|
||||
@ -419,6 +419,9 @@ bigint ReaderNative::read_header(double box[3][3], int &boxinfo, int &triclinic,
|
||||
fieldindex[i] = find_label("iy", labels);
|
||||
else if (fieldtype[i] == IZ)
|
||||
fieldindex[i] = find_label("iz", labels);
|
||||
|
||||
else if (fieldtype[i] == APIP_LAMBDA)
|
||||
fieldindex[i] = find_label("apip_lambda", labels);
|
||||
}
|
||||
|
||||
// set fieldflag = -1 if any unfound fields
|
||||
|
||||
43
src/set.cpp
43
src/set.cpp
@ -46,7 +46,7 @@ enum{SETCOMMAND,FIXSET}; // also used in FixSet class
|
||||
|
||||
enum{ATOM_SELECT,MOL_SELECT,TYPE_SELECT,GROUP_SELECT,REGION_SELECT};
|
||||
|
||||
enum{ANGLE,ANGMOM,BOND,CC,CHARGE,DENSITY,DIAMETER,DIHEDRAL,DIPOLE,
|
||||
enum{ANGLE,ANGMOM,APIP_LAMBDA,BOND,CC,CHARGE,DENSITY,DIAMETER,DIHEDRAL,DIPOLE,
|
||||
DIPOLE_RANDOM,DPD_THETA,EDPD_CV,EDPD_TEMP,EPSILON,IMAGE,IMPROPER,LENGTH,
|
||||
MASS,MOLECULE,OMEGA,QUAT,QUAT_RANDOM,RADIUS_ELECTRON,SHAPE,
|
||||
SMD_CONTACT_RADIUS,SMD_MASS_DENSITY,SPH_CV,SPH_E,SPH_RHO,
|
||||
@ -208,6 +208,10 @@ void Set::process_args(int caller_flag, int narg, char **arg)
|
||||
action->keyword = ANGMOM;
|
||||
process_angmom(iarg,narg,arg,action);
|
||||
invoke_choice[naction++] = &Set::invoke_angmom;
|
||||
} else if (strcmp(arg[iarg],"apip/lambda") == 0) {
|
||||
action->keyword = APIP_LAMBDA;
|
||||
process_apip_lambda(iarg,narg,arg,action);
|
||||
invoke_choice[naction++] = &Set::invoke_apip_lambda;
|
||||
} else if (strcmp(arg[iarg],"bond") == 0) {
|
||||
action->keyword = BOND;
|
||||
process_bond(iarg,narg,arg,action);
|
||||
@ -1066,6 +1070,43 @@ void Set::invoke_angmom(Action *action)
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void Set::process_apip_lambda(int &iarg, int narg, char **arg, Action *action)
|
||||
{
|
||||
if (!atom->apip_lambda_flag)
|
||||
error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style());
|
||||
if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set apip/lambda", error);
|
||||
|
||||
if (strcmp(arg[iarg+1],"fast") == 0) action->dvalue1 = 1;
|
||||
else if (strcmp(arg[iarg+1],"precise") == 0) action->dvalue1 = 0;
|
||||
else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action);
|
||||
else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp);
|
||||
|
||||
iarg += 2;
|
||||
}
|
||||
|
||||
void Set::invoke_apip_lambda(Action *action)
|
||||
{
|
||||
int nlocal = atom->nlocal;
|
||||
double *apip_lambda = atom->apip_lambda;
|
||||
|
||||
if (action->varflag1) {
|
||||
for(int i = 0; i < nlocal; i++) {
|
||||
if (!select[i]) continue;
|
||||
if (vec1[i] < 0 || vec1[i] > 1) error->one(FLERR,"apip/lambda {} not in [0,1]", vec1[i]);
|
||||
apip_lambda[i] = vec1[i];
|
||||
}
|
||||
} else {
|
||||
double lambda = action->dvalue1;
|
||||
if (lambda < 0 || lambda > 1) error->all(FLERR,"apip/lambda {} not in [0,1]", lambda);
|
||||
for(int i = 0; i < nlocal; i++) {
|
||||
if (!select[i]) continue;
|
||||
apip_lambda[i] = lambda;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void Set::process_bond(int &iarg, int narg, char **arg, Action *action)
|
||||
{
|
||||
if (atom->avec->bonds_allow == 0)
|
||||
|
||||
@ -89,6 +89,7 @@ class Set : public Command {
|
||||
|
||||
void process_angle(int &, int, char **, Action *);
|
||||
void process_angmom(int &, int, char **, Action *);
|
||||
void process_apip_lambda(int &, int, char **, Action *);
|
||||
void process_bond(int &, int, char **, Action *);
|
||||
void process_cc(int &, int, char **, Action *);
|
||||
void process_charge(int &, int, char **, Action *);
|
||||
@ -141,6 +142,7 @@ class Set : public Command {
|
||||
|
||||
void invoke_angle(Action *);
|
||||
void invoke_angmom(Action *);
|
||||
void invoke_apip_lambda(Action *);
|
||||
void invoke_bond(Action *);
|
||||
void invoke_cc(Action *);
|
||||
void invoke_charge(Action *);
|
||||
|
||||
Reference in New Issue
Block a user