Add APIP package.
This commit is contained in:
@ -276,6 +276,7 @@ option(CMAKE_VERBOSE_MAKEFILE "Generate verbose Makefiles" OFF)
|
|||||||
set(STANDARD_PACKAGES
|
set(STANDARD_PACKAGES
|
||||||
ADIOS
|
ADIOS
|
||||||
AMOEBA
|
AMOEBA
|
||||||
|
APIP
|
||||||
ASPHERE
|
ASPHERE
|
||||||
ATC
|
ATC
|
||||||
AWPMD
|
AWPMD
|
||||||
@ -605,7 +606,7 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
foreach(PKG_WITH_INCL KSPACE PYTHON ML-IAP VORONOI COLVARS ML-HDNNP MDI MOLFILE NETCDF
|
foreach(PKG_WITH_INCL KSPACE PYTHON ML-IAP VORONOI COLVARS ML-HDNNP MDI MOLFILE NETCDF
|
||||||
PLUMED QMMM ML-QUIP SCAFACOS MACHDYN VTK KIM COMPRESS ML-PACE LEPTON EXTRA-COMMAND)
|
PLUMED QMMM ML-QUIP SCAFACOS MACHDYN VTK KIM COMPRESS APIP ML-PACE LEPTON EXTRA-COMMAND)
|
||||||
if(PKG_${PKG_WITH_INCL})
|
if(PKG_${PKG_WITH_INCL})
|
||||||
include(Packages/${PKG_WITH_INCL})
|
include(Packages/${PKG_WITH_INCL})
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
3
cmake/Modules/Packages/APIP.cmake
Normal file
3
cmake/Modules/Packages/APIP.cmake
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
if(NOT PKG_ML-PACE)
|
||||||
|
message(FATAL_ERROR "Must enable ML-PACE package for enabling APIP package")
|
||||||
|
endif()
|
||||||
@ -4,6 +4,7 @@
|
|||||||
set(ALL_PACKAGES
|
set(ALL_PACKAGES
|
||||||
ADIOS
|
ADIOS
|
||||||
AMOEBA
|
AMOEBA
|
||||||
|
APIP
|
||||||
ASPHERE
|
ASPHERE
|
||||||
ATC
|
ATC
|
||||||
AWPMD
|
AWPMD
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
set(ALL_PACKAGES
|
set(ALL_PACKAGES
|
||||||
ADIOS
|
ADIOS
|
||||||
AMOEBA
|
AMOEBA
|
||||||
|
APIP
|
||||||
ASPHERE
|
ASPHERE
|
||||||
ATC
|
ATC
|
||||||
AWPMD
|
AWPMD
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
set(PACKAGES_WITH_LIB
|
set(PACKAGES_WITH_LIB
|
||||||
ADIOS
|
ADIOS
|
||||||
|
APIP
|
||||||
ATC
|
ATC
|
||||||
AWPMD
|
AWPMD
|
||||||
COMPRESS
|
COMPRESS
|
||||||
|
|||||||
@ -22,6 +22,7 @@ OPT.
|
|||||||
* :doc:`append/atoms <fix_append_atoms>`
|
* :doc:`append/atoms <fix_append_atoms>`
|
||||||
* :doc:`atc <fix_atc>`
|
* :doc:`atc <fix_atc>`
|
||||||
* :doc:`atom/swap <fix_atom_swap>`
|
* :doc:`atom/swap <fix_atom_swap>`
|
||||||
|
* :doc:`apip_atom_weight <fix_apip_atom_weight>`
|
||||||
* :doc:`ave/atom <fix_ave_atom>`
|
* :doc:`ave/atom <fix_ave_atom>`
|
||||||
* :doc:`ave/chunk <fix_ave_chunk>`
|
* :doc:`ave/chunk <fix_ave_chunk>`
|
||||||
* :doc:`ave/correlate <fix_ave_correlate>`
|
* :doc:`ave/correlate <fix_ave_correlate>`
|
||||||
@ -89,6 +90,7 @@ OPT.
|
|||||||
* :doc:`imd <fix_imd>`
|
* :doc:`imd <fix_imd>`
|
||||||
* :doc:`indent <fix_indent>`
|
* :doc:`indent <fix_indent>`
|
||||||
* :doc:`ipi <fix_ipi>`
|
* :doc:`ipi <fix_ipi>`
|
||||||
|
* :doc:`lambda <fix_lambda>`
|
||||||
* :doc:`langevin (k) <fix_langevin>`
|
* :doc:`langevin (k) <fix_langevin>`
|
||||||
* :doc:`langevin/drude <fix_langevin_drude>`
|
* :doc:`langevin/drude <fix_langevin_drude>`
|
||||||
* :doc:`langevin/eff <fix_langevin_eff>`
|
* :doc:`langevin/eff <fix_langevin_eff>`
|
||||||
@ -97,6 +99,7 @@ OPT.
|
|||||||
* :doc:`lb/momentum <fix_lb_momentum>`
|
* :doc:`lb/momentum <fix_lb_momentum>`
|
||||||
* :doc:`lb/viscous <fix_lb_viscous>`
|
* :doc:`lb/viscous <fix_lb_viscous>`
|
||||||
* :doc:`lineforce <fix_lineforce>`
|
* :doc:`lineforce <fix_lineforce>`
|
||||||
|
* :doc:`lambda_thermostat <fix_lambda_thermostat>`
|
||||||
* :doc:`manifoldforce <fix_manifoldforce>`
|
* :doc:`manifoldforce <fix_manifoldforce>`
|
||||||
* :doc:`mdi/qm <fix_mdi_qm>`
|
* :doc:`mdi/qm <fix_mdi_qm>`
|
||||||
* :doc:`mdi/qmmm <fix_mdi_qmmm>`
|
* :doc:`mdi/qmmm <fix_mdi_qmmm>`
|
||||||
|
|||||||
@ -96,7 +96,9 @@ OPT.
|
|||||||
* :doc:`eam/cd <pair_eam>`
|
* :doc:`eam/cd <pair_eam>`
|
||||||
* :doc:`eam/cd/old <pair_eam>`
|
* :doc:`eam/cd/old <pair_eam>`
|
||||||
* :doc:`eam/fs (gikot) <pair_eam>`
|
* :doc:`eam/fs (gikot) <pair_eam>`
|
||||||
|
* :doc:`eam/fs/apip <pair_eam_apip>`
|
||||||
* :doc:`eam/he <pair_eam>`
|
* :doc:`eam/he <pair_eam>`
|
||||||
|
* :doc:`eam/apip <pair_eam_apip>`
|
||||||
* :doc:`edip (o) <pair_edip>`
|
* :doc:`edip (o) <pair_edip>`
|
||||||
* :doc:`edip/multi <pair_edip>`
|
* :doc:`edip/multi <pair_edip>`
|
||||||
* :doc:`edpd (g) <pair_mesodpd>`
|
* :doc:`edpd (g) <pair_mesodpd>`
|
||||||
@ -124,6 +126,9 @@ OPT.
|
|||||||
* :doc:`ilp/tmd (t) <pair_ilp_tmd>`
|
* :doc:`ilp/tmd (t) <pair_ilp_tmd>`
|
||||||
* :doc:`kolmogorov/crespi/full <pair_kolmogorov_crespi_full>`
|
* :doc:`kolmogorov/crespi/full <pair_kolmogorov_crespi_full>`
|
||||||
* :doc:`kolmogorov/crespi/z <pair_kolmogorov_crespi_z>`
|
* :doc:`kolmogorov/crespi/z <pair_kolmogorov_crespi_z>`
|
||||||
|
* :doc:`lambda/zone <pair_lambda_zone>`
|
||||||
|
* :doc:`lambda_input <pair_lambda_input>`
|
||||||
|
* :doc:`lambda_input/csp <pair_lambda_input>`
|
||||||
* :doc:`lcbop <pair_lcbop>`
|
* :doc:`lcbop <pair_lcbop>`
|
||||||
* :doc:`lebedeva/z <pair_lebedeva_z>`
|
* :doc:`lebedeva/z <pair_lebedeva_z>`
|
||||||
* :doc:`lennard/mdf <pair_mdf>`
|
* :doc:`lennard/mdf <pair_mdf>`
|
||||||
@ -236,6 +241,9 @@ OPT.
|
|||||||
* :doc:`oxrna2/coaxstk <pair_oxrna2>`
|
* :doc:`oxrna2/coaxstk <pair_oxrna2>`
|
||||||
* :doc:`pace (k) <pair_pace>`
|
* :doc:`pace (k) <pair_pace>`
|
||||||
* :doc:`pace/extrapolation (k) <pair_pace>`
|
* :doc:`pace/extrapolation (k) <pair_pace>`
|
||||||
|
* :doc:`pace/apip <pair_pace_apip>`
|
||||||
|
* :doc:`pace/apip/fast <pair_pace_apip>`
|
||||||
|
* :doc:`pace/apip/precise <pair_pace_apip>`
|
||||||
* :doc:`pedone (o) <pair_pedone>`
|
* :doc:`pedone (o) <pair_pedone>`
|
||||||
* :doc:`pod (k) <pair_pod>`
|
* :doc:`pod (k) <pair_pod>`
|
||||||
* :doc:`peri/eps <pair_peri>`
|
* :doc:`peri/eps <pair_peri>`
|
||||||
|
|||||||
@ -91,6 +91,7 @@ Packages howto
|
|||||||
Howto_manifold
|
Howto_manifold
|
||||||
Howto_rheo
|
Howto_rheo
|
||||||
Howto_spins
|
Howto_spins
|
||||||
|
Howto_apip
|
||||||
|
|
||||||
Tutorials howto
|
Tutorials howto
|
||||||
===============
|
===============
|
||||||
|
|||||||
130
doc/src/Howto_apip.rst
Normal file
130
doc/src/Howto_apip.rst
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
Adaptive-precision interatomic potentials (APIP)
|
||||||
|
================================================
|
||||||
|
|
||||||
|
The :ref:`APIP package <PKG-APIP>` allows to use adaptive-precision potentials
|
||||||
|
according to :ref:`(Immel) <Immel2025_1>`.
|
||||||
|
The potential energy :math:`E_i` of an atom :math:`i` of 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 which potential energy is used.
|
||||||
|
|
||||||
|
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>`.
|
||||||
|
|
||||||
|
To run a simulation with an adaptive-precision potential, one needs the
|
||||||
|
following components:
|
||||||
|
|
||||||
|
#. :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/apip/fast <pair_pace_apip>`.
|
||||||
|
#. A precise potential: :doc:`pace/apip/precise <pair_pace_apip>`.
|
||||||
|
#. :doc:`pair_style lambda_input <pair_lambda_input>` to calculate :math:`\lambda_i^\text{input}`, from which :math:`\lambda_i` is calculated.
|
||||||
|
#. :doc:`fix lambda <fix_lambda>` to calculate the switching parameter.
|
||||||
|
#. :doc:`pair_style lambda/zone <pair_lambda_zone>` 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 <fix_lambda_thermostat>` to conserve the energy when switching parameters change.
|
||||||
|
#. :doc:`fix apip_atom_weight <fix_apip_atom_weight>` 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>`.
|
||||||
|
|
||||||
|
The affected parts of a LAMMPS script can look as follows:
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
atom_style apip
|
||||||
|
comm_style tiled
|
||||||
|
|
||||||
|
pair_style hybrid/overlay eam/fs/apip pace/apip/precise lambda_input/csp fcc cutoff 5.0 lambda/zone 12.0
|
||||||
|
pair_coeff * * eam/fs/apip Cu.eam.fs Cu
|
||||||
|
pair_coeff * * pace/apip Cu.yace Cu
|
||||||
|
pair_coeff * * lambda_input/csp
|
||||||
|
pair_coeff * * lambda/zone
|
||||||
|
|
||||||
|
fix 2 all lambda 2.5 3.0 time_averaged_zone 4.0 12.0 110 110 min_delta_lambda 0.01
|
||||||
|
fix 3 all lambda_thermostat N_rescaling 200
|
||||||
|
fix 4 all apip_atom_weight 100 eam ace lambda_input lambda all
|
||||||
|
|
||||||
|
variable myweight atom f_4
|
||||||
|
|
||||||
|
fix 5 all balance 100 1.1 rcb weight var myweight
|
||||||
|
|
||||||
|
First, the :doc:`atom_style <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.
|
||||||
|
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. _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:`ADIOS <PKG-ADIOS>`
|
||||||
* :ref:`AMOEBA <PKG-AMOEBA>`
|
* :ref:`AMOEBA <PKG-AMOEBA>`
|
||||||
|
* :ref:`APIP <PKG-APIP>`
|
||||||
* :ref:`ASPHERE <PKG-ASPHERE>`
|
* :ref:`ASPHERE <PKG-ASPHERE>`
|
||||||
* :ref:`ATC <PKG-ATC>`
|
* :ref:`ATC <PKG-ATC>`
|
||||||
* :ref:`AWPMD <PKG-AWPMD>`
|
* :ref:`AWPMD <PKG-AWPMD>`
|
||||||
@ -186,6 +187,58 @@ 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.
|
||||||
|
|
||||||
|
.. _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 apip_atom_weight <fix_apip_atom_weight>`
|
||||||
|
* :doc:`fix lambda <fix_lambda>`
|
||||||
|
* :doc:`fix lambda_thermostat <fix_lambda_thermostat>`
|
||||||
|
* :doc:`pair_style eam/apip <pair_eam_apip>`
|
||||||
|
* :doc:`pair_style lambda/zone <pair_lambda_zone>`
|
||||||
|
* :doc:`pair_style lambda_input <pair_lambda_input>`
|
||||||
|
* :doc:`pair_style pace/apip <pair_pace_apip>`
|
||||||
|
|
||||||
|
----------
|
||||||
|
|
||||||
.. _PKG-ASPHERE:
|
.. _PKG-ASPHERE:
|
||||||
|
|
||||||
ASPHERE package
|
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>`
|
- :doc:`AMOEBA and HIPPO howto <Howto_amoeba>`
|
||||||
- amoeba
|
- amoeba
|
||||||
- no
|
- no
|
||||||
|
* - :ref:`APIP <PKG-APIP>`
|
||||||
|
- adaptive-precision interatomic potentials
|
||||||
|
- :doc:`Howto APIP <Howto_apip>`
|
||||||
|
- ``PACKAGES/APIP``
|
||||||
|
- ext
|
||||||
* - :ref:`ASPHERE <PKG-ASPHERE>`
|
* - :ref:`ASPHERE <PKG-ASPHERE>`
|
||||||
- aspherical particle models
|
- aspherical particle models
|
||||||
- :doc:`Howto spherical <Howto_spherical>`
|
- :doc:`Howto spherical <Howto_spherical>`
|
||||||
|
|||||||
@ -10,7 +10,7 @@ Syntax
|
|||||||
|
|
||||||
atom_style style args
|
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::
|
.. parsed-literal::
|
||||||
|
|
||||||
@ -117,6 +117,10 @@ the Additional Information section below.
|
|||||||
- *bond* + "angle data"
|
- *bond* + "angle data"
|
||||||
- :ref:`MOLECULE <PKG-MOLECULE>`
|
- :ref:`MOLECULE <PKG-MOLECULE>`
|
||||||
- bead-spring polymers with stiffness
|
- bead-spring polymers with stiffness
|
||||||
|
* - *apip*
|
||||||
|
- *atomic* + lambda, lambda_required, lambda_input, lambda_const, lambda_input_ta, e_simple, e_complex, f_const_lambda, f_dyn_lambda
|
||||||
|
- :ref:`APIP <PKG-APIP>`
|
||||||
|
- adaptive-precision interatomic potentials(APIP), see :doc:`APIP howto <Howto_apip>`
|
||||||
* - *atomic*
|
* - *atomic*
|
||||||
- tag, type, x, v, f, image, mask
|
- tag, type, x, v, f, image, mask
|
||||||
-
|
-
|
||||||
|
|||||||
@ -201,6 +201,7 @@ accelerated styles exist.
|
|||||||
* :doc:`append/atoms <fix_append_atoms>` - append atoms to a running simulation
|
* :doc:`append/atoms <fix_append_atoms>` - append atoms to a running simulation
|
||||||
* :doc:`atc <fix_atc>` - initiates a coupled MD/FE simulation
|
* :doc:`atc <fix_atc>` - initiates a coupled MD/FE simulation
|
||||||
* :doc:`atom/swap <fix_atom_swap>` - Monte Carlo atom type swapping
|
* :doc:`atom/swap <fix_atom_swap>` - Monte Carlo atom type swapping
|
||||||
|
* :doc:`apip_atom_weight <fix_apip_atom_weight>` - 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/atom <fix_ave_atom>` - compute per-atom time-averaged quantities
|
||||||
* :doc:`ave/chunk <fix_ave_chunk>` - compute per-chunk 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
|
* :doc:`ave/correlate <fix_ave_correlate>` - compute/output time correlations
|
||||||
@ -268,6 +269,7 @@ accelerated styles exist.
|
|||||||
* :doc:`imd <fix_imd>` - implements the "Interactive MD" (IMD) protocol
|
* :doc:`imd <fix_imd>` - implements the "Interactive MD" (IMD) protocol
|
||||||
* :doc:`indent <fix_indent>` - impose force due to an indenter
|
* :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:`ipi <fix_ipi>` - enable LAMMPS to run as a client for i-PI path-integral simulations
|
||||||
|
* :doc:`lambda <fix_lambda>` - compute switching parameter, that controls the precision of an :doc:`APIP potential <Howto_apip>`
|
||||||
* :doc:`langevin <fix_langevin>` - Langevin temperature control
|
* :doc:`langevin <fix_langevin>` - Langevin temperature control
|
||||||
* :doc:`langevin/drude <fix_langevin_drude>` - Langevin temperature control of Drude oscillators
|
* :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
|
* :doc:`langevin/eff <fix_langevin_eff>` - Langevin temperature control for the electron force field model
|
||||||
@ -276,6 +278,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/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:`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:`lineforce <fix_lineforce>` - constrain atoms to move in a line
|
||||||
|
* :doc:`lambda_thermostat <fix_lambda_thermostat>` - apply energy conserving correction for an :doc:`APIP potential <Howto_apip>`
|
||||||
* :doc:`manifoldforce <fix_manifoldforce>` - restrain atoms to a manifold during minimization
|
* :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/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)
|
* :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_apip_atom_weight.rst
Normal file
143
doc/src/fix_apip_atom_weight.rst
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
.. index:: fix apip_atom_weight
|
||||||
|
|
||||||
|
fix apip_atom_weight command
|
||||||
|
============================
|
||||||
|
|
||||||
|
Syntax
|
||||||
|
""""""
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
fix ID group-ID apip_atom_weight nevery fast_potential precise_potential lambda_input lambda group_lambda_input [no_rescale]
|
||||||
|
|
||||||
|
* ID, group-ID are documented in :doc:`fix <fix>` command
|
||||||
|
* apip_atom_weight = 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 or float for constant time
|
||||||
|
* lambda = *lambda/zone* for a time measurement of pair_style lambda/zone 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 apip_atom_weight 50 eam ace lambda_input lambda/zone all
|
||||||
|
fix 2 all apip_atom_weight 50 1e-05 0.0004 4e-06 4e-06 all
|
||||||
|
fix 2 all apip_atom_weight 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 <pair_lambda_input>`.
|
||||||
|
A spatial switching zone, that ensures a smooth transition between two
|
||||||
|
different interatomic potentials, can be calculated by
|
||||||
|
:doc:`pair_style lambda/zone <pair_lambda_zone>`.
|
||||||
|
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 apip_atom_weight ${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 for one atom
|
||||||
|
#. average compute time of lambda/zone 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 <fix_lambda>`,
|
||||||
|
:doc:`fix lambda_thermostat <fix_lambda_thermostat>`,
|
||||||
|
:doc:`pair_style lambda/zone <pair_lambda_zone>`,
|
||||||
|
:doc:`pair_style lambda_input <pair_lambda_input>`,
|
||||||
|
: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.rst
Normal file
262
doc/src/fix_lambda.rst
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
.. index:: fix lambda
|
||||||
|
|
||||||
|
fix lambda command
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Syntax
|
||||||
|
""""""
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
fix ID group-ID lambda thr_lo thr_hi keyword args ...
|
||||||
|
|
||||||
|
* ID, group-ID are documented in :doc:`fix <fix>` command
|
||||||
|
* lambda = 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 neglegted (>= 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 3.0 3.5 time_averaged_zone 4.0 12.0 110 110 min_delta_lambda 0.01
|
||||||
|
fix 2 mobile lambda 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 <pair_lambda_input>`.
|
||||||
|
|
||||||
|
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 <pair_lambda_input>`, 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 <pair_lambda_zone>`, 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/apip/precise <pair_pace_apip>`.
|
||||||
|
The input, from which the switching parameter is calculated, is provided
|
||||||
|
by :doc:`pair lambda_input/csp <pair_lambda_input>`.
|
||||||
|
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 <pair_lambda_zone>`.
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
pair_style hybrid/overlay eam/fs/apip pace/apip/precise lambda_input/csp fcc cutoff 5.0 lambda 12.0
|
||||||
|
pair_coeff * * eam/fs/apip Cu.eam.fs Cu
|
||||||
|
pair_coeff * * pace/apip Cu_precise.yace Cu
|
||||||
|
pair_coeff * * lambda_input/csp
|
||||||
|
pair_coeff * * lambda
|
||||||
|
fix 2 all lambda 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 <pair_lambda_zone>`,
|
||||||
|
:doc:`pair_style lambda_input <pair_lambda_input>`,
|
||||||
|
:doc:`pair_style eam/apip <pair_eam_apip>`,
|
||||||
|
:doc:`pair_style pace/apip <pair_pace_apip>`,
|
||||||
|
:doc:`fix apip_atom_weight <fix_apip_atom_weight>`
|
||||||
|
:doc:`fix lambda_thermostat <fix_lambda_thermostat>`,
|
||||||
|
|
||||||
|
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.rst
Normal file
176
doc/src/fix_lambda_thermostat.rst
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
.. index:: fix lambda_thermostat
|
||||||
|
|
||||||
|
fix lambda_thermostat command
|
||||||
|
=============================
|
||||||
|
|
||||||
|
Syntax
|
||||||
|
""""""
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
fix ID group-ID lambda_thermostat keyword values ...
|
||||||
|
|
||||||
|
* ID, group-ID are documented in :doc:`fix <fix>` command
|
||||||
|
* lambda_thermostat = 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
|
||||||
|
fix 2 all lambda_thermostat N_rescaling 100
|
||||||
|
fix 2 all lambda_thermostat seed 42
|
||||||
|
fix 2 all lambda_thermostat 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 <fix_lambda>`,
|
||||||
|
:doc:`pair_style lambda/zone <pair_lambda_zone>`,
|
||||||
|
:doc:`pair_style lambda_input <pair_lambda_input>`,
|
||||||
|
:doc:`pair_style eam/apip <pair_eam_apip>`,
|
||||||
|
:doc:`pair_style pace/apip <pair_pace_apip>`,
|
||||||
|
:doc:`fix apip_atom_weight <fix_apip_atom_weight>`
|
||||||
|
|
||||||
|
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)
|
||||||
126
doc/src/pair_eam_apip.rst
Normal file
126
doc/src/pair_eam_apip.rst
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
.. 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/apip/precise lambda_input/csp fcc cutoff 5.0 lambda 12.0
|
||||||
|
pair_coeff * * eam/fs/apip Cu.eam.fs Cu
|
||||||
|
pair_coeff * * pace/apip Cu_precise.yace Cu
|
||||||
|
pair_coeff * * lambda_input/csp
|
||||||
|
pair_coeff * * lambda
|
||||||
|
|
||||||
|
|
||||||
|
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 by
|
||||||
|
:doc:`fix lambda <fix_lambda>`.
|
||||||
|
|
||||||
|
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/apip/precise <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 <fix_lambda>`,
|
||||||
|
:doc:`fix lambda_thermostat <fix_lambda_thermostat>`,
|
||||||
|
:doc:`pair_style lambda/zone <pair_lambda_zone>`,
|
||||||
|
:doc:`pair_style lambda_input <pair_lambda_input>`,
|
||||||
|
:doc:`pair_style pace/apip <pair_pace_apip>`,
|
||||||
|
:doc:`fix apip_atom_weight <fix_apip_atom_weight>`
|
||||||
|
|
||||||
|
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.rst
Normal file
151
doc/src/pair_lambda_input.rst
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
.. index:: pair_style lambda_input
|
||||||
|
.. index:: pair_style lambda_input/csp
|
||||||
|
|
||||||
|
pair_style lambda_input command
|
||||||
|
===============================
|
||||||
|
|
||||||
|
Syntax
|
||||||
|
""""""
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
pair_style lambda_input cutoff
|
||||||
|
|
||||||
|
* lambda_input = style name of this pair style
|
||||||
|
* cutoff = global cutoff (distance units)
|
||||||
|
|
||||||
|
pair_style lambda_input/csp command
|
||||||
|
===================================
|
||||||
|
|
||||||
|
Syntax
|
||||||
|
""""""
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
pair_style lambda_input/csp lattice keyword args
|
||||||
|
|
||||||
|
* lambda_input/csp = 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 neighbouring atoms are considered (> 0)
|
||||||
|
*N_buffer* args = N_buffer
|
||||||
|
N_buffer = numer of additional neighbours, which are included in the j-j+N/2 calculation
|
||||||
|
|
||||||
|
Examples
|
||||||
|
""""""""
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
pair_style lambda_input/csp fcc
|
||||||
|
pair_style lambda_input/csp fcc cutoff 5.0
|
||||||
|
pair_style lambda_input/csp bcc cutoff 5.0 N_buffer 2
|
||||||
|
pair_style lambda_input/csp 14
|
||||||
|
|
||||||
|
Description
|
||||||
|
"""""""""""
|
||||||
|
|
||||||
|
This pair_styles calculates :math:`\lambda_i^\text{input}(t)`, which
|
||||||
|
is required for :doc:`fix lambda <fix_lambda>`.
|
||||||
|
|
||||||
|
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 <fix_lambda>`, as this computation
|
||||||
|
takes time and this pair_style can be included in the load-balancing via
|
||||||
|
:doc:`fix apip_atom_weight <fix_apip_atom_weight>`.
|
||||||
|
|
||||||
|
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/apip/precise <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 <fix_lambda>`,
|
||||||
|
whereas the spatial
|
||||||
|
transition zone of the switching parameter is calculated by
|
||||||
|
:doc:`pair_style lambda/zone <pair_lambda_zone>`.
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
pair_style hybrid/overlay eam/fs/apip pace/apip/precise lambda_input/csp fcc cutoff 5.0 lambda 12.0
|
||||||
|
pair_coeff * * eam/fs/apip Cu.eam.fs Cu
|
||||||
|
pair_coeff * * pace/apip Cu_precise.yace Cu
|
||||||
|
pair_coeff * * lambda_input/csp
|
||||||
|
pair_coeff * * lambda
|
||||||
|
fix 2 all lambda 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 <fix_lambda>`,
|
||||||
|
:doc:`fix lambda_thermostat <fix_lambda_thermostat>`,
|
||||||
|
:doc:`pair_style lambda/zone <pair_lambda_zone>`,
|
||||||
|
:doc:`pair_style eam/apip <pair_eam_apip>`,
|
||||||
|
:doc:`pair_style pace/apip <pair_pace_apip>`,
|
||||||
|
:doc:`fix apip_atom_weight <fix_apip_atom_weight>`
|
||||||
|
|
||||||
|
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.rst
Normal file
106
doc/src/pair_lambda_zone.rst
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
.. index:: pair_style lambda/zone
|
||||||
|
|
||||||
|
pair_style lambda/zone command
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Syntax
|
||||||
|
""""""
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
pair_style lambda/zone cutoff
|
||||||
|
|
||||||
|
* lambda/zone = style name of this pair style
|
||||||
|
* cutoff = global cutoff (distance units)
|
||||||
|
|
||||||
|
Examples
|
||||||
|
""""""""
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
pair_style lambda/zone 12.0
|
||||||
|
|
||||||
|
Description
|
||||||
|
"""""""""""
|
||||||
|
|
||||||
|
This pair_style calculates :math:`\lambda_{\text{min},i}`, which
|
||||||
|
is required for :doc:`fix lambda <fix_lambda>`.
|
||||||
|
The meaning of :math:`\lambda_{\text{min},i}` is documented in
|
||||||
|
:doc:`fix lambda <fix_lambda>`, as this pair_style is for use with
|
||||||
|
:doc:`fix lambda <fix_lambda>` 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 <fix_lambda>` 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 <fix_lambda>`.
|
||||||
|
|
||||||
|
The computation of :math:`\lambda_{\text{min},i}` is done by this
|
||||||
|
pair_style instead of by :doc:`fix lambda <fix_lambda>`, as this computation
|
||||||
|
takes time and this pair_style can be included in the load-balancing via
|
||||||
|
:doc:`fix apip_atom_weight <fix_apip_atom_weight>`.
|
||||||
|
|
||||||
|
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/apip/precise <pair_pace_apip>`.
|
||||||
|
The input, from which the switching parameter is calculated, is provided
|
||||||
|
by :doc:`pair lambda_input/csp <pair_lambda_input>`.
|
||||||
|
The switching parameter is calculated by :doc:`fix lambda <fix_lambda>`,
|
||||||
|
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/apip/precise lambda_input/csp fcc cutoff 5.0 lambda/zone 12.0
|
||||||
|
pair_coeff * * eam/fs/apip Cu.eam.fs Cu
|
||||||
|
pair_coeff * * pace/apip Cu_precise.yace Cu
|
||||||
|
pair_coeff * * lambda_input/csp
|
||||||
|
pair_coeff * * lambda/zone
|
||||||
|
fix 2 all lambda 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 <fix_lambda>`,
|
||||||
|
:doc:`fix apip_atom_weight <fix_apip_atom_weight>`
|
||||||
|
:doc:`pair_style lambda_input <pair_lambda_input>`,
|
||||||
|
:doc:`pair_style eam/apip <pair_eam_apip>`,
|
||||||
|
:doc:`pair_style pace/apip <pair_pace_apip>`,
|
||||||
|
:doc:`fix lambda_thermostat <fix_lambda_thermostat>`,
|
||||||
|
|
||||||
|
Default
|
||||||
|
"""""""
|
||||||
|
|
||||||
|
none
|
||||||
146
doc/src/pair_pace_apip.rst
Normal file
146
doc/src/pair_pace_apip.rst
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
.. index:: pair_style pace/apip
|
||||||
|
.. index:: pair_style pace/apip/fast
|
||||||
|
.. index:: pair_style pace/apip/precise
|
||||||
|
|
||||||
|
pair_style pace/apip command
|
||||||
|
==============================
|
||||||
|
|
||||||
|
pair_style pace/apip/fast command
|
||||||
|
===================================
|
||||||
|
|
||||||
|
pair_style pace/apip/precise command
|
||||||
|
======================================
|
||||||
|
|
||||||
|
Constant precision variant: *pace*
|
||||||
|
|
||||||
|
Syntax
|
||||||
|
""""""
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
pair_style pace/apip ... keyword values ...
|
||||||
|
pair_style pace/apip/fast ... keyword values ...
|
||||||
|
pair_style pace/apip/precise ... 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/apip/fast pace/apip/precise lambda_input/csp fcc cutoff 5.0 lambda 12.0
|
||||||
|
pair_coeff * * pace/apip/fast Cu_fast.yace Cu
|
||||||
|
pair_coeff * * pace/apip/precise Cu_precise.yace Cu
|
||||||
|
pair_coeff * * lambda_input/csp
|
||||||
|
pair_coeff * * lambda
|
||||||
|
|
||||||
|
pair_style hybrid/overlay eam/fs/apip pace/apip/precise lambda_input/csp fcc cutoff 5.0 lambda 12.0
|
||||||
|
pair_coeff * * eam/fs/apip Cu.eam.fs Cu
|
||||||
|
pair_coeff * * pace/apip Cu_precise.yace Cu
|
||||||
|
pair_coeff * * lambda_input/csp
|
||||||
|
pair_coeff * * lambda
|
||||||
|
|
||||||
|
|
||||||
|
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 by
|
||||||
|
:doc:`fix lambda <fix_lambda>`.
|
||||||
|
|
||||||
|
The pair style *pace/apip/precise* 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/apip/fast* 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/apip/fast* and *pace/apip/precise*
|
||||||
|
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 <fix_lambda>`,
|
||||||
|
:doc:`fix lambda_thermostat <fix_lambda_thermostat>`,
|
||||||
|
:doc:`pair_style lambda/zone <pair_lambda_zone>`,
|
||||||
|
:doc:`pair_style lambda_input <pair_lambda_input>`,
|
||||||
|
:doc:`pair_style eam/apip <pair_eam_apip>`,
|
||||||
|
:doc:`fix apip_atom_weight <fix_apip_atom_weight>`
|
||||||
|
|
||||||
|
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 <pair_eam>` - concentration-dependent EAM
|
||||||
* :doc:`eam/cd/old <pair_eam>` - older two-site model for 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 <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/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 <pair_edip>` - three-body EDIP potential
|
||||||
* :doc:`edip/multi <pair_edip>` - multi-element EDIP potential
|
* :doc:`edip/multi <pair_edip>` - multi-element EDIP potential
|
||||||
* :doc:`edpd <pair_mesodpd>` - eDPD particle interactions
|
* :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:`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/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:`kolmogorov/crespi/z <pair_kolmogorov_crespi_z>` - Kolmogorov-Crespi (KC) potential with normals along z-axis
|
||||||
|
* :doc:`lambda/zone <pair_lambda_zone>` - transition zone of an :doc:`adaptive-precision interatomic potential <Howto_apip>`
|
||||||
|
* :doc:`lambda_input <pair_lambda_input>` - constant as input for the precision calculation of an :doc:`adaptive-precision interatomic potential (APIP) <Howto_apip>`
|
||||||
|
* :doc:`lambda_input/csp <pair_lambda_input>` - CSP as input for the precision calculation of an :doc:`adaptive-precision interatomic potential (APIP) <Howto_apip>`
|
||||||
* :doc:`lcbop <pair_lcbop>` - long-range bond-order potential (LCBOP)
|
* :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:`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
|
* :doc:`lennard/mdf <pair_mdf>` - LJ potential in A/B form with a taper function
|
||||||
@ -329,6 +334,9 @@ accelerated styles exist.
|
|||||||
* :doc:`oxrna2/xstk <pair_oxrna2>` -
|
* :doc:`oxrna2/xstk <pair_oxrna2>` -
|
||||||
* :doc:`pace <pair_pace>` - Atomic Cluster Expansion (ACE) machine-learning potential
|
* :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/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/apip/fast <pair_pace_apip>` - :doc:`adaptive-precision <Howto_apip>` version of ACE, used as fast potential
|
||||||
|
* :doc:`pace/apip/precise <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:`pedone <pair_pedone>` - Pedone (PMMCS) potential (non-Coulomb part)
|
||||||
* :doc:`pod <pair_pod>` - Proper orthogonal decomposition (POD) machine-learning potential
|
* :doc:`pod <pair_pod>` - Proper orthogonal decomposition (POD) machine-learning potential
|
||||||
* :doc:`peri/eps <pair_peri>` - Peridynamic EPS potential
|
* :doc:`peri/eps <pair_peri>` - Peridynamic EPS potential
|
||||||
|
|||||||
@ -131,6 +131,8 @@ anton
|
|||||||
Antonelli
|
Antonelli
|
||||||
anysize
|
anysize
|
||||||
api
|
api
|
||||||
|
apip
|
||||||
|
APIP
|
||||||
apolar
|
apolar
|
||||||
Apoorva
|
Apoorva
|
||||||
Appl
|
Appl
|
||||||
@ -640,6 +642,7 @@ CSiC
|
|||||||
csld
|
csld
|
||||||
cslib
|
cslib
|
||||||
CSlib
|
CSlib
|
||||||
|
csp
|
||||||
cstdio
|
cstdio
|
||||||
cstdlib
|
cstdlib
|
||||||
cstring
|
cstring
|
||||||
@ -1354,6 +1357,7 @@ gmres
|
|||||||
gname
|
gname
|
||||||
gneb
|
gneb
|
||||||
GNEB
|
GNEB
|
||||||
|
Godehard
|
||||||
Goerigk
|
Goerigk
|
||||||
Goga
|
Goga
|
||||||
Goldfarb
|
Goldfarb
|
||||||
@ -1588,6 +1592,7 @@ Imageint
|
|||||||
Imagemagick
|
Imagemagick
|
||||||
imagename
|
imagename
|
||||||
imd
|
imd
|
||||||
|
Immel
|
||||||
Impey
|
Impey
|
||||||
impl
|
impl
|
||||||
impropers
|
impropers
|
||||||
@ -3780,6 +3785,7 @@ Thiaville
|
|||||||
Thibaudeau
|
Thibaudeau
|
||||||
Thijsse
|
Thijsse
|
||||||
Thirumalai
|
Thirumalai
|
||||||
|
thr
|
||||||
threebody
|
threebody
|
||||||
thrid
|
thrid
|
||||||
ThunderX
|
ThunderX
|
||||||
|
|||||||
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
73
examples/PACKAGES/apip/in.surface.balance
Normal file
73
examples/PACKAGES/apip/in.surface.balance
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
##################################################
|
||||||
|
# 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 ${csp_lattice} cutoff ${csp_cutoff} lambda/zone ${r_sw_hi}
|
||||||
|
pair_coeff * * eam/fs/apip ${eamfs_file} Cu
|
||||||
|
pair_coeff * * pace/apip ${ace_file2} Cu
|
||||||
|
pair_coeff * * lambda_input/csp
|
||||||
|
pair_coeff * * lambda/zone
|
||||||
|
fix lambda all lambda ${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 N_rescaling ${N_rescaling}
|
||||||
|
fix weight_atom all apip_atom_weight 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
|
||||||
|
#dump 1 all custom 10 dump/surface_ap_balance.dump.* id type x y z lambda 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
|
||||||
92
examples/PACKAGES/apip/in.vacancy
Normal file
92
examples/PACKAGES/apip/in.vacancy
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
##################################################
|
||||||
|
# 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 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/apip/fast pace/apip/precise lambda_input/csp ${csp_lattice} cutoff ${csp_cutoff} lambda/zone ${r_sw_hi}
|
||||||
|
#pair_coeff * * pace/apip/fast ${ace_file1} Cu
|
||||||
|
#pair_coeff * * pace/apip/precise ${ace_file2} Cu
|
||||||
|
#pair_coeff * * lambda_input/csp
|
||||||
|
#pair_coeff * * lambda/zone
|
||||||
|
#fix lambda all lambda ${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 apip_atom_weight 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 ${csp_lattice} cutoff ${csp_cutoff} lambda/zone ${r_sw_hi}
|
||||||
|
pair_coeff * * eam/fs/apip ${eamfs_file} Cu
|
||||||
|
pair_coeff * * pace/apip ${ace_file2} Cu
|
||||||
|
pair_coeff * * lambda_input/csp
|
||||||
|
pair_coeff * * lambda/zone
|
||||||
|
fix lambda all lambda ${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 apip_atom_weight 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 N_rescaling ${N_rescaling} store_atomic_forces 100
|
||||||
|
|
||||||
|
|
||||||
|
thermo_style custom step etotal
|
||||||
|
thermo 1
|
||||||
|
|
||||||
|
run 100
|
||||||
|
|
||||||
|
# dump atoms
|
||||||
|
#write_dump all custom dump/vacancy.dump.* id type x y z fx fy fz lambda 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 fcc cutoff 6.0 lambda/zone 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
|
||||||
|
#pair_coeff * * lambda/zone
|
||||||
|
#fix lambda all lambda 2.5 3.0 time_averaged_zone 4.0 12.0 110 110 min_delta_lambda $(1/110)
|
||||||
|
#fix lambda_thermostat all lambda_thermostat 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
|
||||||
108
examples/PACKAGES/apip/log.04Feb25.surface.balance.nolb.g++.4
Normal file
108
examples/PACKAGES/apip/log.04Feb25.surface.balance.nolb.g++.4
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
LAMMPS (4 Feb 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 = 1.143 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:time_per_atom
|
||||||
|
lambda: extract lambda_zone: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, perpetual, trim from (2)
|
||||||
|
attributes: full, newton on, cut 8
|
||||||
|
pair build: trim
|
||||||
|
stencil: none
|
||||||
|
bin: none
|
||||||
|
(4) pair lambda/zone, perpetual
|
||||||
|
attributes: full, newton on, ghost, cut 14
|
||||||
|
pair build: full/bin/ghost
|
||||||
|
stencil: full/ghost/bin/3d
|
||||||
|
bin: standard
|
||||||
|
(5) fix lambda_thermostat, 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.4606058 1.8697255 5.5957166e-06 0.0002553649 2.7500342e-06 4.6802407e-06
|
||||||
|
20 2.0765883 1.7644069 5.9864867e-06 0.0002751227 2.9574758e-06 5.078614e-06
|
||||||
|
30 2.0955022 1.729507 5.9541701e-06 0.00028593742 3.1165205e-06 5.2349106e-06
|
||||||
|
40 2.1015667 1.7241359 6.0115135e-06 0.00028640643 3.1154236e-06 5.2528746e-06
|
||||||
|
50 2.0981491 1.6201337 6.0470102e-06 0.00028778687 3.1443635e-06 5.2497711e-06
|
||||||
|
60 2.1327959 1.3101362 7.7658865e-06 0.00037855901 4.1641447e-06 6.9162514e-06
|
||||||
|
70 2.098134 1.3357863 7.5378657e-06 0.00037046011 4.0510159e-06 6.9345367e-06
|
||||||
|
80 2.1000138 1.3475583 7.5679751e-06 0.00036818876 4.0188623e-06 6.7257237e-06
|
||||||
|
90 2.0966073 1.1728052 7.6393621e-06 0.00036755436 4.0052073e-06 6.6818754e-06
|
||||||
|
100 1.8896711 1.3506386 7.5946481e-06 0.00036649967 3.984174e-06 6.6518701e-06
|
||||||
|
Loop time of 67.2407 on 4 procs for 100 steps with 40200 atoms
|
||||||
|
|
||||||
|
Performance: 0.128 ns/day, 186.780 hours/ns, 1.487 timesteps/s, 59.785 katom-step/s
|
||||||
|
99.8% CPU use with 4 MPI tasks x no OpenMP threads
|
||||||
|
|
||||||
|
MPI task timing breakdown:
|
||||||
|
Section | min time | avg time | max time |%varavg| %total
|
||||||
|
---------------------------------------------------------------
|
||||||
|
Pair | 10.34 | 21.891 | 56.059 | 421.6 | 32.56
|
||||||
|
Neigh | 8.1064 | 9.1925 | 10.667 | 33.9 | 13.67
|
||||||
|
Comm | 1.3105 | 23.525 | 45.141 | 437.6 | 34.99
|
||||||
|
Output | 0.00053598 | 0.73462 | 2.8834 | 144.7 | 1.09
|
||||||
|
Modify | 1.4504 | 2.6152 | 5.8041 | 114.0 | 3.89
|
||||||
|
Other | | 9.282 | | | 13.80
|
||||||
|
|
||||||
|
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:01:11
|
||||||
@ -0,0 +1,108 @@
|
|||||||
|
LAMMPS (4 Feb 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 = 1.141 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:time_per_atom
|
||||||
|
lambda: extract lambda_zone: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, perpetual, trim from (2)
|
||||||
|
attributes: full, newton on, cut 8
|
||||||
|
pair build: trim
|
||||||
|
stencil: none
|
||||||
|
bin: none
|
||||||
|
(4) pair lambda/zone, perpetual
|
||||||
|
attributes: full, newton on, ghost, cut 14
|
||||||
|
pair build: full/bin/ghost
|
||||||
|
stencil: full/ghost/bin/3d
|
||||||
|
bin: standard
|
||||||
|
(5) fix lambda_thermostat, 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.0010585 1.8144651 5.3526071e-06 0.00025703793 2.7730117e-06 4.7190461e-06
|
||||||
|
20 1.0016587 3.0895281 6.0547706e-06 0.00030627156 2.9311147e-06 2.8627034e-06
|
||||||
|
30 1.0006595 2.1815977 7.7086095e-06 0.00034346642 3.4831025e-06 3.6494203e-06
|
||||||
|
40 1.0003702 2.7847348 6.9889341e-06 0.00031605872 3.2092228e-06 2.9177266e-06
|
||||||
|
50 1.0013639 2.8085372 7.1723284e-06 0.00032050748 3.2148509e-06 2.9280764e-06
|
||||||
|
60 1.001567 2.7692583 7.3191318e-06 0.00032348311 3.2792367e-06 3.0731907e-06
|
||||||
|
70 1.0008473 2.7848811 7.4547446e-06 0.00032207119 3.2487866e-06 3.0045227e-06
|
||||||
|
80 1.0008791 2.1902426 8.8463371e-06 0.00037692301 3.878561e-06 3.5166374e-06
|
||||||
|
90 1.0005633 2.0207998 1.0049193e-05 0.00043004983 4.4508803e-06 4.0369005e-06
|
||||||
|
100 1.0011185 2.11148 9.5552543e-06 0.00040548477 4.282726e-06 4.0021617e-06
|
||||||
|
Loop time of 41.9356 on 4 procs for 100 steps with 40200 atoms
|
||||||
|
|
||||||
|
Performance: 0.206 ns/day, 116.488 hours/ns, 2.385 timesteps/s, 95.861 katom-step/s
|
||||||
|
99.2% CPU use with 4 MPI tasks x no OpenMP threads
|
||||||
|
|
||||||
|
MPI task timing breakdown:
|
||||||
|
Section | min time | avg time | max time |%varavg| %total
|
||||||
|
---------------------------------------------------------------
|
||||||
|
Pair | 21.856 | 23.33 | 25.627 | 29.8 | 55.63
|
||||||
|
Neigh | 12.078 | 12.235 | 12.335 | 2.8 | 29.18
|
||||||
|
Comm | 1.8098 | 3.4438 | 5.8848 | 91.3 | 8.21
|
||||||
|
Output | 0.0013883 | 0.0067437 | 0.010676 | 4.1 | 0.02
|
||||||
|
Modify | 1.7044 | 1.8301 | 1.9304 | 7.0 | 4.36
|
||||||
|
Other | | 1.09 | | | 2.60
|
||||||
|
|
||||||
|
Nlocal: 10050 ave 10381 max 9892 min
|
||||||
|
Histogram: 1 2 0 0 0 0 0 0 0 1
|
||||||
|
Nghost: 52763 ave 52921 max 52432 min
|
||||||
|
Histogram: 1 0 0 0 0 0 0 0 2 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.80751e+06 max 9.34231e+06 min
|
||||||
|
Histogram: 1 2 0 0 0 0 0 0 0 1
|
||||||
|
|
||||||
|
Total # of neighbors = 37968882
|
||||||
|
Ave neighs/atom = 944.49955
|
||||||
|
Neighbor list builds = 10
|
||||||
|
Dangerous builds = 0
|
||||||
|
Total wall time: 0:00:46
|
||||||
@ -0,0 +1,108 @@
|
|||||||
|
LAMMPS (4 Feb 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 = 1.549 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:time_per_atom
|
||||||
|
lambda: extract lambda_zone: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, perpetual, trim from (2)
|
||||||
|
attributes: full, newton on, cut 8
|
||||||
|
pair build: trim
|
||||||
|
stencil: none
|
||||||
|
bin: none
|
||||||
|
(4) pair lambda/zone, perpetual
|
||||||
|
attributes: full, newton on, ghost, cut 14
|
||||||
|
pair build: full/bin/ghost
|
||||||
|
stencil: full/ghost/bin/3d
|
||||||
|
bin: standard
|
||||||
|
(5) fix lambda_thermostat, 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.0001725 1.7198837 5.5314343e-06 0.00025930431 2.7883957e-06 4.707143e-06
|
||||||
|
20 1.0001862 1.8265719 5.6099429e-06 0.00027931903 2.9758981e-06 5.002563e-06
|
||||||
|
30 1.00056 1.8317507 5.9076763e-06 0.0002894911 3.1109902e-06 5.1394341e-06
|
||||||
|
40 1.0004862 2.5730799 6.243133e-06 0.00030439841 3.1674858e-06 3.784468e-06
|
||||||
|
50 1.0001422 1.7867846 6.1734458e-06 0.00029065411 3.1286655e-06 5.1705237e-06
|
||||||
|
60 1.0008942 1.4365047 7.2226216e-06 0.00035501193 3.8052887e-06 6.42234e-06
|
||||||
|
70 1.0001463 1.9946081 8.1287731e-06 0.00038928999 4.1631973e-06 4.9840279e-06
|
||||||
|
80 1.0004234 1.4099223 7.8487793e-06 0.00037185703 4.022587e-06 6.8562431e-06
|
||||||
|
90 1.000166 1.6477504 1.1740135e-05 0.00039310073 4.5190508e-06 5.9037201e-06
|
||||||
|
100 1.0004352 1.3977939 7.9664586e-06 0.00037057101 4.0412051e-06 6.8616558e-06
|
||||||
|
Loop time of 58.5219 on 4 procs for 100 steps with 40200 atoms
|
||||||
|
|
||||||
|
Performance: 0.148 ns/day, 162.561 hours/ns, 1.709 timesteps/s, 68.692 katom-step/s
|
||||||
|
99.7% CPU use with 4 MPI tasks x no OpenMP threads
|
||||||
|
|
||||||
|
MPI task timing breakdown:
|
||||||
|
Section | min time | avg time | max time |%varavg| %total
|
||||||
|
---------------------------------------------------------------
|
||||||
|
Pair | 13.129 | 22.408 | 43.047 | 253.7 | 38.29
|
||||||
|
Neigh | 2.9649 | 8.8754 | 14.209 | 175.4 | 15.17
|
||||||
|
Comm | 4.4729 | 19.561 | 38.596 | 306.3 | 33.43
|
||||||
|
Output | 0.0076245 | 0.28239 | 0.93926 | 72.3 | 0.48
|
||||||
|
Modify | 1.0567 | 2.2026 | 4.445 | 92.5 | 3.76
|
||||||
|
Other | | 5.192 | | | 8.87
|
||||||
|
|
||||||
|
Nlocal: 10050 ave 16633 max 2176 min
|
||||||
|
Histogram: 1 0 1 0 0 0 0 0 0 2
|
||||||
|
Nghost: 27619 ave 42218 max 8849 min
|
||||||
|
Histogram: 1 0 0 1 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.56603e+07 max 1.80672e+06 min
|
||||||
|
Histogram: 1 0 1 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:01:02
|
||||||
@ -0,0 +1,193 @@
|
|||||||
|
LAMMPS (4 Feb 2025 - Development - )
|
||||||
|
Reading data file ...
|
||||||
|
orthogonal box = (0 0 0) to (28.92 28.92 28.92)
|
||||||
|
1 by 2 by 2 MPI processor grid
|
||||||
|
reading atoms ...
|
||||||
|
2047 atoms
|
||||||
|
reading velocities ...
|
||||||
|
2047 velocities
|
||||||
|
read_data CPU = 0.037 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:time_per_atom
|
||||||
|
lambda: extract lambda_zone: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 is not used. (../fix_lambda.cpp:247)
|
||||||
|
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 = 5 5 5
|
||||||
|
4 neighbor lists, perpetual/occasional/extra = 4 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, perpetual, trim from (2)
|
||||||
|
attributes: full, newton on, cut 8
|
||||||
|
pair build: trim
|
||||||
|
stencil: none
|
||||||
|
bin: none
|
||||||
|
(4) pair lambda/zone, perpetual
|
||||||
|
attributes: full, newton on, ghost, cut 14
|
||||||
|
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) = 58.65 | 58.75 | 59.03 Mbytes
|
||||||
|
Step TotEng
|
||||||
|
0 -7409.9869
|
||||||
|
1 -7409.9869
|
||||||
|
2 -7409.987
|
||||||
|
3 -7409.987
|
||||||
|
4 -7409.987
|
||||||
|
5 -7409.987
|
||||||
|
6 -7409.987
|
||||||
|
7 -7409.987
|
||||||
|
8 -7409.987
|
||||||
|
9 -7409.987
|
||||||
|
10 -7409.9871
|
||||||
|
11 -7409.9876
|
||||||
|
12 -7409.9876
|
||||||
|
13 -7409.9876
|
||||||
|
14 -7409.988
|
||||||
|
15 -7409.9876
|
||||||
|
16 -7409.9864
|
||||||
|
17 -7409.9864
|
||||||
|
18 -7409.9853
|
||||||
|
19 -7409.9847
|
||||||
|
20 -7409.9865
|
||||||
|
21 -7409.9852
|
||||||
|
22 -7409.9867
|
||||||
|
23 -7409.9864
|
||||||
|
24 -7409.9869
|
||||||
|
25 -7409.9844
|
||||||
|
26 -7409.9849
|
||||||
|
27 -7409.9856
|
||||||
|
28 -7409.9851
|
||||||
|
29 -7409.9835
|
||||||
|
30 -7409.9843
|
||||||
|
31 -7409.9861
|
||||||
|
32 -7409.9862
|
||||||
|
33 -7409.9869
|
||||||
|
34 -7409.9863
|
||||||
|
35 -7409.9885
|
||||||
|
36 -7409.9924
|
||||||
|
37 -7409.9945
|
||||||
|
38 -7409.9942
|
||||||
|
39 -7409.9903
|
||||||
|
40 -7409.9909
|
||||||
|
41 -7409.9962
|
||||||
|
42 -7409.996
|
||||||
|
43 -7409.9959
|
||||||
|
44 -7410.0004
|
||||||
|
45 -7410.0044
|
||||||
|
46 -7409.9993
|
||||||
|
47 -7409.9948
|
||||||
|
48 -7409.9923
|
||||||
|
49 -7409.9844
|
||||||
|
50 -7409.9861
|
||||||
|
51 -7409.9849
|
||||||
|
52 -7409.986
|
||||||
|
53 -7409.9828
|
||||||
|
54 -7409.9799
|
||||||
|
55 -7409.9804
|
||||||
|
56 -7409.9782
|
||||||
|
57 -7409.9777
|
||||||
|
58 -7409.9777
|
||||||
|
59 -7409.9781
|
||||||
|
60 -7409.982
|
||||||
|
61 -7409.982
|
||||||
|
62 -7409.9824
|
||||||
|
63 -7409.9844
|
||||||
|
64 -7409.9826
|
||||||
|
65 -7409.9816
|
||||||
|
66 -7409.9788
|
||||||
|
67 -7409.9769
|
||||||
|
68 -7409.9727
|
||||||
|
69 -7409.9716
|
||||||
|
70 -7409.9693
|
||||||
|
71 -7409.9674
|
||||||
|
72 -7409.9691
|
||||||
|
73 -7409.9693
|
||||||
|
74 -7409.9682
|
||||||
|
75 -7409.9664
|
||||||
|
76 -7409.9678
|
||||||
|
77 -7409.966
|
||||||
|
78 -7409.9674
|
||||||
|
79 -7409.9654
|
||||||
|
80 -7409.9649
|
||||||
|
81 -7409.9636
|
||||||
|
82 -7409.967
|
||||||
|
83 -7409.9693
|
||||||
|
84 -7409.9655
|
||||||
|
85 -7409.9654
|
||||||
|
86 -7409.9644
|
||||||
|
87 -7409.961
|
||||||
|
88 -7409.9609
|
||||||
|
89 -7409.9594
|
||||||
|
90 -7409.96
|
||||||
|
91 -7409.9643
|
||||||
|
92 -7409.9603
|
||||||
|
93 -7409.9622
|
||||||
|
94 -7409.9603
|
||||||
|
95 -7409.9584
|
||||||
|
96 -7409.9555
|
||||||
|
97 -7409.9596
|
||||||
|
98 -7409.9587
|
||||||
|
99 -7409.9585
|
||||||
|
100 -7409.9602
|
||||||
|
Loop time of 10.6279 on 4 procs for 100 steps with 2047 atoms
|
||||||
|
|
||||||
|
Performance: 0.813 ns/day, 29.522 hours/ns, 9.409 timesteps/s, 19.261 katom-step/s
|
||||||
|
99.2% CPU use with 4 MPI tasks x no OpenMP threads
|
||||||
|
|
||||||
|
MPI task timing breakdown:
|
||||||
|
Section | min time | avg time | max time |%varavg| %total
|
||||||
|
---------------------------------------------------------------
|
||||||
|
Pair | 7.4326 | 8.9455 | 10.524 | 49.4 | 84.17
|
||||||
|
Neigh | 0 | 0 | 0 | 0.0 | 0.00
|
||||||
|
Comm | 0.089305 | 1.6676 | 3.18 | 114.5 | 15.69
|
||||||
|
Output | 0.0028034 | 0.0041679 | 0.0061404 | 1.9 | 0.04
|
||||||
|
Modify | 0.0040779 | 0.0053928 | 0.0062702 | 1.1 | 0.05
|
||||||
|
Other | | 0.005266 | | | 0.05
|
||||||
|
|
||||||
|
Nlocal: 511.75 ave 529 max 502 min
|
||||||
|
Histogram: 1 1 0 1 0 0 0 0 0 1
|
||||||
|
Nghost: 7684.25 ave 7693 max 7668 min
|
||||||
|
Histogram: 1 0 0 0 0 0 0 1 1 1
|
||||||
|
Neighs: 0 ave 0 max 0 min
|
||||||
|
Histogram: 4 0 0 0 0 0 0 0 0 0
|
||||||
|
FullNghs: 490648 ave 507159 max 481313 min
|
||||||
|
Histogram: 1 1 0 1 0 0 0 0 0 1
|
||||||
|
|
||||||
|
Total # of neighbors = 1962590
|
||||||
|
Ave neighs/atom = 958.76404
|
||||||
|
Neighbor list builds = 0
|
||||||
|
Dangerous builds = 0
|
||||||
|
Total wall time: 0:00:12
|
||||||
@ -0,0 +1,197 @@
|
|||||||
|
LAMMPS (4 Feb 2025 - Development - )
|
||||||
|
Reading data file ...
|
||||||
|
orthogonal box = (0 0 0) to (28.92 28.92 28.92)
|
||||||
|
1 by 2 by 2 MPI processor grid
|
||||||
|
reading atoms ...
|
||||||
|
2047 atoms
|
||||||
|
reading velocities ...
|
||||||
|
2047 velocities
|
||||||
|
read_data CPU = 0.041 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:time_per_atom
|
||||||
|
lambda: extract lambda_zone: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 = 5 5 5
|
||||||
|
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, perpetual, trim from (2)
|
||||||
|
attributes: full, newton on, cut 8
|
||||||
|
pair build: trim
|
||||||
|
stencil: none
|
||||||
|
bin: none
|
||||||
|
(4) pair lambda/zone, perpetual
|
||||||
|
attributes: full, newton on, ghost, cut 14
|
||||||
|
pair build: full/bin/ghost
|
||||||
|
stencil: full/ghost/bin/3d
|
||||||
|
bin: standard
|
||||||
|
(5) fix lambda_thermostat, 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) = 61.44 | 61.63 | 62.2 Mbytes
|
||||||
|
Step TotEng
|
||||||
|
0 -7409.9869
|
||||||
|
1 -7409.9869
|
||||||
|
2 -7409.987
|
||||||
|
3 -7409.987
|
||||||
|
4 -7409.987
|
||||||
|
5 -7409.987
|
||||||
|
6 -7409.987
|
||||||
|
7 -7409.987
|
||||||
|
8 -7409.987
|
||||||
|
9 -7409.987
|
||||||
|
10 -7409.987
|
||||||
|
11 -7409.9871
|
||||||
|
12 -7409.9871
|
||||||
|
13 -7409.9871
|
||||||
|
14 -7409.9871
|
||||||
|
15 -7409.9871
|
||||||
|
16 -7409.9871
|
||||||
|
17 -7409.9871
|
||||||
|
18 -7409.9871
|
||||||
|
19 -7409.9872
|
||||||
|
20 -7409.9872
|
||||||
|
21 -7409.9872
|
||||||
|
22 -7409.9872
|
||||||
|
23 -7409.9872
|
||||||
|
24 -7409.9872
|
||||||
|
25 -7409.9872
|
||||||
|
26 -7409.9872
|
||||||
|
27 -7409.9872
|
||||||
|
28 -7409.9872
|
||||||
|
29 -7409.9872
|
||||||
|
30 -7409.9872
|
||||||
|
31 -7409.9872
|
||||||
|
32 -7409.9872
|
||||||
|
33 -7409.9872
|
||||||
|
34 -7409.9872
|
||||||
|
35 -7409.9872
|
||||||
|
36 -7409.9872
|
||||||
|
37 -7409.9873
|
||||||
|
38 -7409.9873
|
||||||
|
39 -7409.9873
|
||||||
|
40 -7409.9873
|
||||||
|
41 -7409.9873
|
||||||
|
42 -7409.9874
|
||||||
|
43 -7409.9874
|
||||||
|
44 -7409.9874
|
||||||
|
45 -7409.9874
|
||||||
|
46 -7409.9875
|
||||||
|
47 -7409.9875
|
||||||
|
48 -7409.9875
|
||||||
|
49 -7409.9875
|
||||||
|
50 -7409.9875
|
||||||
|
51 -7409.9876
|
||||||
|
52 -7409.9876
|
||||||
|
53 -7409.9876
|
||||||
|
54 -7409.9876
|
||||||
|
55 -7409.9876
|
||||||
|
56 -7409.9876
|
||||||
|
57 -7409.9876
|
||||||
|
58 -7409.9876
|
||||||
|
59 -7409.9876
|
||||||
|
60 -7409.9876
|
||||||
|
61 -7409.9876
|
||||||
|
62 -7409.9875
|
||||||
|
63 -7409.9875
|
||||||
|
64 -7409.9875
|
||||||
|
65 -7409.9875
|
||||||
|
66 -7409.9874
|
||||||
|
67 -7409.9874
|
||||||
|
68 -7409.9874
|
||||||
|
69 -7409.9873
|
||||||
|
70 -7409.9873
|
||||||
|
71 -7409.9873
|
||||||
|
72 -7409.9873
|
||||||
|
73 -7409.9872
|
||||||
|
74 -7409.9872
|
||||||
|
75 -7409.9872
|
||||||
|
76 -7409.9872
|
||||||
|
77 -7409.9872
|
||||||
|
78 -7409.9871
|
||||||
|
79 -7409.9871
|
||||||
|
80 -7409.9871
|
||||||
|
81 -7409.9871
|
||||||
|
82 -7409.9871
|
||||||
|
83 -7409.9871
|
||||||
|
84 -7409.9871
|
||||||
|
85 -7409.9871
|
||||||
|
86 -7409.9871
|
||||||
|
87 -7409.9871
|
||||||
|
88 -7409.9871
|
||||||
|
89 -7409.9871
|
||||||
|
90 -7409.9871
|
||||||
|
91 -7409.9871
|
||||||
|
92 -7409.9871
|
||||||
|
93 -7409.9872
|
||||||
|
94 -7409.9872
|
||||||
|
95 -7409.9872
|
||||||
|
96 -7409.9872
|
||||||
|
97 -7409.9872
|
||||||
|
98 -7409.9872
|
||||||
|
99 -7409.9872
|
||||||
|
100 -7409.9872
|
||||||
|
Loop time of 11.8395 on 4 procs for 100 steps with 2047 atoms
|
||||||
|
|
||||||
|
Performance: 0.730 ns/day, 32.887 hours/ns, 8.446 timesteps/s, 17.290 katom-step/s
|
||||||
|
99.2% CPU use with 4 MPI tasks x no OpenMP threads
|
||||||
|
|
||||||
|
MPI task timing breakdown:
|
||||||
|
Section | min time | avg time | max time |%varavg| %total
|
||||||
|
---------------------------------------------------------------
|
||||||
|
Pair | 8.1066 | 9.7912 | 11.642 | 53.8 | 82.70
|
||||||
|
Neigh | 0 | 0 | 0 | 0.0 | 0.00
|
||||||
|
Comm | 0.057574 | 1.9086 | 3.5932 | 121.8 | 16.12
|
||||||
|
Output | 0.022525 | 0.027196 | 0.031414 | 2.2 | 0.23
|
||||||
|
Modify | 0.10334 | 0.10795 | 0.11223 | 1.2 | 0.91
|
||||||
|
Other | | 0.004525 | | | 0.04
|
||||||
|
|
||||||
|
Nlocal: 511.75 ave 529 max 502 min
|
||||||
|
Histogram: 1 1 0 1 0 0 0 0 0 1
|
||||||
|
Nghost: 7684.25 ave 7693 max 7668 min
|
||||||
|
Histogram: 1 0 0 0 0 0 0 1 1 1
|
||||||
|
Neighs: 0 ave 0 max 0 min
|
||||||
|
Histogram: 4 0 0 0 0 0 0 0 0 0
|
||||||
|
FullNghs: 490648 ave 507159 max 481313 min
|
||||||
|
Histogram: 1 1 0 1 0 0 0 0 0 1
|
||||||
|
|
||||||
|
Total # of neighbors = 1962590
|
||||||
|
Ave neighs/atom = 958.76404
|
||||||
|
Neighbor list builds = 0
|
||||||
|
Dangerous builds = 0
|
||||||
|
Total wall time: 0:00:13
|
||||||
24
src/.gitignore
vendored
24
src/.gitignore
vendored
@ -109,6 +109,30 @@
|
|||||||
/pair_pace_extrapolation.cpp
|
/pair_pace_extrapolation.cpp
|
||||||
/pair_pace_extrapolation.h
|
/pair_pace_extrapolation.h
|
||||||
|
|
||||||
|
/fix_lambda.cpp
|
||||||
|
/fix_lambda.h
|
||||||
|
/fix_lambda_thermostat.cpp
|
||||||
|
/fix_lambda_thermostat.h
|
||||||
|
/pair_lambda_input.cpp
|
||||||
|
/pair_lambda_input.h
|
||||||
|
/pair_lambda_input_csp.cpp
|
||||||
|
/pair_lambda_input_csp.h
|
||||||
|
/pair_eam_fs_apip.cpp
|
||||||
|
/pair_eam_fs_apip.h
|
||||||
|
/pair_eam_apip.cpp
|
||||||
|
/pair_eam_apip.h
|
||||||
|
/pair_lambda_zone.cpp
|
||||||
|
/pair_lambda_zone.h
|
||||||
|
/pair_pace_apip.cpp
|
||||||
|
/pair_pace_apip.h
|
||||||
|
/pair_pace_apip_precise.cpp
|
||||||
|
/pair_pace_apip_precise.h
|
||||||
|
/pair_pace_apip_fast.cpp
|
||||||
|
/pair_pace_apip_fast.h
|
||||||
|
/fix_apip_atom_weight.cpp
|
||||||
|
/fix_apip_atom_weight.h
|
||||||
|
|
||||||
|
|
||||||
/pair_pod.cpp
|
/pair_pod.cpp
|
||||||
/pair_pod.h
|
/pair_pod.h
|
||||||
/eapod.cpp
|
/eapod.cpp
|
||||||
|
|||||||
73
src/APIP/Install.sh
Normal file
73
src/APIP/Install.sh
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# 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
|
||||||
|
}
|
||||||
|
|
||||||
|
# all package files with no dependencies
|
||||||
|
|
||||||
|
for file in *.cpp *.h; do
|
||||||
|
test -f ${file} && action $file
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
# edit 2 Makefile.package files to include/exclude package info
|
||||||
|
|
||||||
|
if (test $1 = 1) then
|
||||||
|
|
||||||
|
if (test -e ../Makefile.package) then
|
||||||
|
sed -i -e 's/[^ \t]*pace[^ \t]* //' ../Makefile.package
|
||||||
|
sed -i -e 's|^PKG_SYSINC =[ \t]*|&$(pace_SYSINC) |' ../Makefile.package
|
||||||
|
sed -i -e 's|^PKG_SYSLIB =[ \t]*|&$(pace_SYSLIB) |' ../Makefile.package
|
||||||
|
sed -i -e 's|^PKG_SYSPATH =[ \t]*|&$(pace_SYSPATH) |' ../Makefile.package
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (test -e ../Makefile.package.settings) then
|
||||||
|
sed -i -e '/^[ \t]*include.*pace.*$/d' ../Makefile.package.settings
|
||||||
|
# multiline form needed for BSD sed on Macs
|
||||||
|
sed -i -e '4 i \
|
||||||
|
include ..\/..\/lib\/pace\/Makefile.lammps
|
||||||
|
' ../Makefile.package.settings
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif (test $1 = 0) then
|
||||||
|
|
||||||
|
# The ML-PACE package depends also on the pace library.
|
||||||
|
# Remove in Makefiles only if there are no remaining includes from ML-PACE.
|
||||||
|
# grep searches also in kspace.cpp and thus returns no error.
|
||||||
|
if (test $(grep '#include "ace' ../*pace*.cpp | wc -l) = 0) then
|
||||||
|
|
||||||
|
# update Makefiles
|
||||||
|
if (test -e ../Makefile.package) then
|
||||||
|
sed -i -e 's/[^ \t]*pace[^ \t]* //' ../Makefile.package
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (test -e ../Makefile.package.settings) then
|
||||||
|
sed -i -e '/^[ \t]*include.*pace.*$/d' ../Makefile.package.settings
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
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 .
|
||||||
539
src/APIP/fix_apip_atom_weight.cpp
Normal file
539
src/APIP/fix_apip_atom_weight.cpp
Normal file
@ -0,0 +1,539 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
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_apip_atom_weight.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;
|
||||||
|
|
||||||
|
FixApipAtomWeight::FixApipAtomWeight(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/apip/fast: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: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: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, "apip_atom_weight: 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, "apip_atom_weight: unknown argument {}", arg[iarg]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check arguments
|
||||||
|
if (nevery < 1) error->all(FLERR, "apip_atom_weight: nevery > 0 required");
|
||||||
|
if (!atom->lambda_required_flag)
|
||||||
|
error->all(FLERR, "apip_atom_weight: 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, "apip_atom_weight: 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, "apip_atom_weight: simple time cannot be extracted with {} from {}",
|
||||||
|
time_simple_extract_name, force->pair_style);
|
||||||
|
} else {
|
||||||
|
if (time_simple_atom <= 0)
|
||||||
|
error->all(FLERR, "apip_atom_weight: time_simple_atom needs to be positive instead of {}",
|
||||||
|
time_simple_atom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time_complex_extract_name) {
|
||||||
|
if (force->pair->extract(time_complex_extract_name, useless_dim) == nullptr)
|
||||||
|
error->all(FLERR, "apip_atom_weight: complex time cannot be extracted with {} from {}",
|
||||||
|
time_complex_extract_name, force->pair_style);
|
||||||
|
} else {
|
||||||
|
if (time_complex_atom <= 0)
|
||||||
|
error->all(FLERR, "apip_atom_weight: time_complex_atom needs to be positive instead of {}",
|
||||||
|
time_complex_atom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time_group_extract_name) {
|
||||||
|
if (force->pair->extract(time_group_extract_name, useless_dim) == nullptr)
|
||||||
|
error->all(FLERR, "apip_atom_weight: group time cannot be extracted with {} from {}",
|
||||||
|
time_group_extract_name, force->pair_style);
|
||||||
|
} else {
|
||||||
|
if (time_group_atom <= 0)
|
||||||
|
error->all(FLERR, "apip_atom_weight: time_group_atom needs to be positive instead of {}",
|
||||||
|
time_group_atom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time_lambda_extract_name) {
|
||||||
|
if (force->pair->extract(time_lambda_extract_name, useless_dim) == nullptr)
|
||||||
|
error->all(FLERR, "apip_atom_weight: lambda time cannot be extracted with {} from {}",
|
||||||
|
time_lambda_extract_name, force->pair_style);
|
||||||
|
} else {
|
||||||
|
if (time_lambda_atom <= 0)
|
||||||
|
error->all(FLERR, "apip_atom_weight: time_lambda_atom needs to be positive 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
FixApipAtomWeight::~FixApipAtomWeight()
|
||||||
|
{
|
||||||
|
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 FixApipAtomWeight::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 FixApipAtomWeight::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 FixApipAtomWeight::init()
|
||||||
|
{
|
||||||
|
int counter = 0;
|
||||||
|
for (int i = 0; i < modify->nfix; i++) {
|
||||||
|
if (strcmp(modify->fix[i]->style, "apip_atom_weight") == 0) counter++;
|
||||||
|
}
|
||||||
|
if (counter > 1) error->all(FLERR, "More than one apip_atom_weight fix");
|
||||||
|
|
||||||
|
// get ptr to fix lambda
|
||||||
|
counter = 0;
|
||||||
|
for (int i = 0; i < modify->nfix; i++) {
|
||||||
|
if (strcmp(modify->fix[i]->style, "lambda") == 0) {
|
||||||
|
fix_lambda = modify->fix[i];
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (counter > 1) error->all(FLERR, "More than one fix lambda");
|
||||||
|
|
||||||
|
// 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, "apip_atom_weight: 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, "apip_atom_weight: 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 FixApipAtomWeight::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 FixApipAtomWeight::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 FixApipAtomWeight::pre_exchange()
|
||||||
|
{
|
||||||
|
if (update->ntimestep % peratom_freq != 0) { return; }
|
||||||
|
|
||||||
|
calc_work_per_particle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update output pointer for output.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void FixApipAtomWeight::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 FixApipAtomWeight::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->lambda_required;
|
||||||
|
|
||||||
|
// 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, "apip_atom_weight: extracting fix_lambda:lambda_input_history failed");
|
||||||
|
|
||||||
|
int nlocal = atom->nlocal;
|
||||||
|
// assume a homogeneous time per simple and complex particle
|
||||||
|
n_simple = n_complex = n_group = n_lambda = 0;
|
||||||
|
for (int i = 0; i < nlocal; i++) {
|
||||||
|
work_atom = 0;
|
||||||
|
if (lambda_required[i] & LambdaRequired::SIMPLE) {
|
||||||
|
work_atom += time_simple_atom;
|
||||||
|
n_simple++;
|
||||||
|
}
|
||||||
|
if (lambda_required[i] & LambdaRequired::COMPLEX) {
|
||||||
|
work_atom += time_complex_atom;
|
||||||
|
n_complex++;
|
||||||
|
}
|
||||||
|
if (mask[i] & time_group_bit) {
|
||||||
|
work_atom += time_group_atom;
|
||||||
|
n_group++;
|
||||||
|
}
|
||||||
|
if (lambda_input_history[i][histlen_lambda_input + 1] != 1) {
|
||||||
|
work_atom += time_lambda_atom;
|
||||||
|
n_lambda++;
|
||||||
|
}
|
||||||
|
weight[i] = work_atom;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 FixApipAtomWeight::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_apip_atom_weight.h
Normal file
106
src/APIP/fix_apip_atom_weight.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(apip_atom_weight,FixApipAtomWeight);
|
||||||
|
// clang-format on
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef LMP_FIX_APIP_ATOM_WEIGHT_H
|
||||||
|
#define LMP_FIX_APIP_ATOM_WEIGHT_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 FixApipAtomWeight : public Fix {
|
||||||
|
public:
|
||||||
|
FixApipAtomWeight(class LAMMPS *, int, char **);
|
||||||
|
~FixApipAtomWeight() 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
|
||||||
782
src/APIP/fix_lambda.cpp
Normal file
782
src/APIP/fix_lambda.cpp
Normal file
@ -0,0 +1,782 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
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.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";
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
FixLambda::FixLambda(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->lambda_const_flag) {
|
||||||
|
error->all(FLERR, "fix lambda requires atomic style with lambda_const.");
|
||||||
|
}
|
||||||
|
if (!atom->lambda_flag) { error->all(FLERR, "fix lambda requires atomic style with lambda."); }
|
||||||
|
if (!atom->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 FixLambda::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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
FixLambda::~FixLambda()
|
||||||
|
{
|
||||||
|
// 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 FixLambda::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 FixLambda::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") == 0) count++;
|
||||||
|
}
|
||||||
|
if (count > 1) error->all(FLERR, "More than one fix lambda.");
|
||||||
|
|
||||||
|
// warn if there is no fix lambda_thermostat
|
||||||
|
if (comm->me == 0 && modify->get_fix_by_style("lambda_thermostat").size() == 0)
|
||||||
|
error->warning(
|
||||||
|
FLERR,
|
||||||
|
"The energy is not conserved when lambda changes as fix lambda_thermostat 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 = (PairLambdaInput *) pair_tmp;
|
||||||
|
// lambda/zone
|
||||||
|
pair_tmp = force->pair_match("lambda/zone", 1);
|
||||||
|
if (!pair_tmp) error->all(FLERR, "fix lambda requires a `pair lambda`");
|
||||||
|
pair_lambda_zone = (PairLambdaZone *) 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 FixLambda::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 FixLambda::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 FixLambda::post_integrate()
|
||||||
|
{
|
||||||
|
double *lambda, *lambda_const, *lambda_input_ta;
|
||||||
|
|
||||||
|
lambda = atom->lambda;
|
||||||
|
lambda_const = atom->lambda_const;
|
||||||
|
lambda_input_ta = atom->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.cpp
|
||||||
|
calculate_lambda_input_ta();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write stats at end of step
|
||||||
|
*/
|
||||||
|
|
||||||
|
void FixLambda::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 FixLambda::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->lambda;
|
||||||
|
lambda_const = atom->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 FixLambda::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 FixLambda::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->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 FixLambda::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->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 FixLambda::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->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 FixLambda::calculate_lambda_input_ta()
|
||||||
|
{
|
||||||
|
int i, nlocal;
|
||||||
|
int *mask;
|
||||||
|
double *lambda_input_ta = atom->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 FixLambda::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 FixLambda::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 FixLambda::pack_forward_comm(int n, int *list, double *buf, int /*pbc_flag*/, int * /*pbc*/)
|
||||||
|
{
|
||||||
|
int i, j, m;
|
||||||
|
double *lambda_input_ta = atom->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->lambda[j];
|
||||||
|
buf[m++] = atom->lambda_const[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recv lambda from neighbours.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void FixLambda::unpack_forward_comm(int n, int first, double *buf)
|
||||||
|
{
|
||||||
|
int i, m, last;
|
||||||
|
double *lambda_input_ta = atom->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->lambda[i] = buf[m++];
|
||||||
|
atom->lambda_const[i] = buf[m++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* store scalar history information
|
||||||
|
*/
|
||||||
|
|
||||||
|
void FixLambda::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 FixLambda::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 *FixLambda::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.h
Normal file
108
src/APIP/fix_lambda.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,FixLambda);
|
||||||
|
// clang-format on
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef LMP_FIX_LAMBDA_H
|
||||||
|
#define LMP_FIX_LAMBDA_H
|
||||||
|
|
||||||
|
#include "fix.h"
|
||||||
|
#include "pair_lambda_input.h"
|
||||||
|
#include "pair_lambda_zone.h"
|
||||||
|
|
||||||
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class FixLambda : public Fix {
|
||||||
|
friend class PairLambdaInput;
|
||||||
|
friend class PairLambdaZone;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FixLambda(class LAMMPS *, int, char **);
|
||||||
|
~FixLambda() 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 PairLambdaInput *pair_lambda_input;
|
||||||
|
class PairLambdaZone *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
|
||||||
630
src/APIP/fix_lambda_thermostat.cpp
Normal file
630
src/APIP/fix_lambda_thermostat.cpp
Normal file
@ -0,0 +1,630 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
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.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
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
FixLambdaThermostat::FixLambdaThermostat(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: seed requires one argument");
|
||||||
|
seed = utils::inumeric(FLERR, arg[iarg + 1], false, lmp);
|
||||||
|
if (seed <= 0) { error->all(FLERR, "fix lambda_thermostat seed <= 0"); }
|
||||||
|
iarg++;
|
||||||
|
|
||||||
|
} else if (strcmp(arg[iarg], "store_atomic_forces") == 0) {
|
||||||
|
if (iarg + 1 >= narg)
|
||||||
|
error->all(FLERR, "fix lambda_thermostat: 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: 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: 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: unknown argument {}", arg[iarg]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// error checks
|
||||||
|
|
||||||
|
if (!atom->e_simple_flag) {
|
||||||
|
error->all(FLERR, "fix lambda_thermostat requires atomic style with e_simple.");
|
||||||
|
}
|
||||||
|
if (!atom->e_complex_flag) {
|
||||||
|
error->all(FLERR, "fix lambda_thermostat requires atomic style with e_complex.");
|
||||||
|
}
|
||||||
|
if (!atom->lambda_const_flag) {
|
||||||
|
error->all(FLERR, "fix lambda_thermostat requires atomic style with lambda_const.");
|
||||||
|
}
|
||||||
|
if (!atom->lambda_flag) {
|
||||||
|
error->all(FLERR, "fix lambda_thermostat requires atomic style with lambda.");
|
||||||
|
}
|
||||||
|
if (!atom->f_const_lambda_flag) {
|
||||||
|
error->all(FLERR, "fix lambda_thermostat requires atomic style with f_const_lambda.");
|
||||||
|
}
|
||||||
|
if (!atom->f_dyn_lambda_flag) {
|
||||||
|
error->all(FLERR, "fix lambda_thermostat requires atomic style with f_dyn_lambda.");
|
||||||
|
}
|
||||||
|
if (rescaling_N_neighbours <= 1)
|
||||||
|
error->all(FLERR, "fix lambda_thermostat: 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: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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
FixLambdaThermostat::~FixLambdaThermostat()
|
||||||
|
{
|
||||||
|
memory->destroy(energy_change_atom);
|
||||||
|
memory->destroy(peratom_stats);
|
||||||
|
|
||||||
|
memory->destroy(local_numneigh);
|
||||||
|
memory->sfree(local_firstneigh);
|
||||||
|
memory->destroy(jlist_copy);
|
||||||
|
delete[] ipage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int FixLambdaThermostat::setmask()
|
||||||
|
{
|
||||||
|
int mask = 0;
|
||||||
|
mask |= POST_FORCE;
|
||||||
|
mask |= END_OF_STEP;
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void FixLambdaThermostat::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") == 0) counter++;
|
||||||
|
if (counter > 1) error->all(FLERR, "fix lambda_thermostat: more than one fix lambda_thermostat");
|
||||||
|
|
||||||
|
// 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: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 FixLambdaThermostat::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 FixLambdaThermostat::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:numneigh");
|
||||||
|
local_firstneigh =
|
||||||
|
(int **) memory->smalloc(nmax_list * sizeof(int *), "lambda_thermostat: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 FixLambdaThermostat::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 FixLambdaThermostat::post_force(int /*vflag*/)
|
||||||
|
{
|
||||||
|
init_peratom_stats();
|
||||||
|
calculate_energy_change();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void FixLambdaThermostat::end_of_step()
|
||||||
|
{
|
||||||
|
apply_thermostat();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init per-atom array with zeros.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void FixLambdaThermostat::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: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 FixLambdaThermostat::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->e_simple;
|
||||||
|
double *e_complex = atom->e_complex;
|
||||||
|
double *lambda_const = atom->lambda_const;
|
||||||
|
double *lambda = atom->lambda;
|
||||||
|
double **f_const_lambda = atom->f_const_lambda;
|
||||||
|
double **f_dyn_lambda = atom->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: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 FixLambdaThermostat::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->e_simple;
|
||||||
|
double *e_complex = atom->e_complex;
|
||||||
|
double *lambda_const = atom->lambda_const;
|
||||||
|
double *lambda = atom->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: 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: 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 FixLambdaThermostat::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 FixLambdaThermostat::reset_dt()
|
||||||
|
{
|
||||||
|
dtf = 0.5 * update->dt * force->ftm2v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
memory usage of local atom-based arrays
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
double FixLambdaThermostat::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.h
Normal file
88
src/APIP/fix_lambda_thermostat.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,FixLambdaThermostat);
|
||||||
|
// clang-format on
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef LMP_FIX_LAMBDA_THERMOSTAT_H
|
||||||
|
#define LMP_FIX_LAMBDA_THERMOSTAT_H
|
||||||
|
|
||||||
|
#include "fix.h"
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class FixLambdaThermostat : public Fix {
|
||||||
|
public:
|
||||||
|
FixLambdaThermostat(class LAMMPS *, int, char **);
|
||||||
|
~FixLambdaThermostat() 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->lambda;
|
||||||
|
int *lambda_required = atom->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->f_const_lambda;
|
||||||
|
f_dyn_lambda = atom->f_dyn_lambda;
|
||||||
|
e_simple = atom->e_simple;
|
||||||
|
lambda_const = atom->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] & LambdaRequired::NO_SIMPLE)
|
||||||
|
continue;
|
||||||
|
else if (!(lambda_required[i] & LambdaRequired::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] |= LambdaRequired::SIMPLE;
|
||||||
|
// set neighbour list
|
||||||
|
for (jj = 0; jj < jnum; jj++) {
|
||||||
|
j = jlist[jj];
|
||||||
|
j &= NEIGHMASK;
|
||||||
|
if (j < nlocal) lambda_required[j] |= LambdaRequired::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] |= LambdaRequired::SIMPLE;
|
||||||
|
// set lambda also for non-ghost j
|
||||||
|
if (j < nlocal) lambda_required[j] |= LambdaRequired::SIMPLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// SIMPLE not set -> set NO_SIMPLE
|
||||||
|
if (!(lambda_required[i] & LambdaRequired::SIMPLE)) {
|
||||||
|
// go to next atom
|
||||||
|
lambda_required[i] |= LambdaRequired::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->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->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 or not and set
|
||||||
|
* lambda_thermostat.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void PairEAMapip::setup()
|
||||||
|
{
|
||||||
|
if (modify->get_fix_by_style("^lambda_thermostat$").size() == 0) {
|
||||||
|
lambda_thermostat = false;
|
||||||
|
} else {
|
||||||
|
lambda_thermostat = true;
|
||||||
|
if (!atom->lambda_const_flag)
|
||||||
|
error->all(
|
||||||
|
FLERR,
|
||||||
|
"Pair style pace/apip requires an atom style with lambda_const for a local thermostat.");
|
||||||
|
if (!atom->e_simple_flag)
|
||||||
|
error->all(
|
||||||
|
FLERR,
|
||||||
|
"Pair style pace/apip requires an atom style with e_simple for a local thermostat.");
|
||||||
|
if (!atom->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->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.cpp
Normal file
218
src/APIP/pair_lambda_input.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.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;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
PairLambdaInput::PairLambdaInput(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
PairLambdaInput::~PairLambdaInput()
|
||||||
|
{
|
||||||
|
if (copymode) return;
|
||||||
|
|
||||||
|
if (allocated) {
|
||||||
|
memory->destroy(setflag);
|
||||||
|
memory->destroy(cutsq);
|
||||||
|
|
||||||
|
memory->destroy(cut);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
void PairLambdaInput::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 PairLambdaInput::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 PairLambdaInput::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 PairLambdaInput::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 PairLambdaInput::init_style()
|
||||||
|
{
|
||||||
|
if (!atom->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") == 0) {
|
||||||
|
fix_lambda = (FixLambda *) 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 PairLambdaInput::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->lambda_input.
|
||||||
|
* Count the number of computations and measure the compute time for
|
||||||
|
* fix apip_atom_weight.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int PairLambdaInput::calculate_lambda_input()
|
||||||
|
{
|
||||||
|
int i, ii, inum;
|
||||||
|
int *ilist;
|
||||||
|
|
||||||
|
inum = list->inum;
|
||||||
|
ilist = list->ilist;
|
||||||
|
|
||||||
|
double *lambda_input = atom->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 PairLambdaInput::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 *PairLambdaInput::extract(const char *str, int &dim)
|
||||||
|
{
|
||||||
|
dim = 0;
|
||||||
|
if (strcmp(str, "lambda_input:time_per_atom") == 0) {
|
||||||
|
calculate_time_per_atom();
|
||||||
|
return (void *) &time_per_atom;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
64
src/APIP/pair_lambda_input.h
Normal file
64
src/APIP/pair_lambda_input.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,PairLambdaInput);
|
||||||
|
// clang-format on
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef LMP_PAIR_LAMBDA_INPUT_H
|
||||||
|
#define LMP_PAIR_LAMBDA_INPUT_H
|
||||||
|
|
||||||
|
#include "fix_lambda.h"
|
||||||
|
#include "pair.h"
|
||||||
|
|
||||||
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class PairLambdaInput : public Pair {
|
||||||
|
friend class FixLambda;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PairLambdaInput(class LAMMPS *);
|
||||||
|
~PairLambdaInput() 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 FixLambda *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.cpp
Normal file
319
src/APIP/pair_lambda_input_csp.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.h"
|
||||||
|
|
||||||
|
#include "atom.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "neigh_list.h"
|
||||||
|
|
||||||
|
using namespace LAMMPS_NS;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
PairLambdaInputCsp::PairLambdaInputCsp(LAMMPS *lmp) :
|
||||||
|
PairLambdaInput(lmp), distsq(nullptr), nearest(nullptr)
|
||||||
|
{
|
||||||
|
// set defaults
|
||||||
|
nnn = 0;
|
||||||
|
nnn_buffer = 0;
|
||||||
|
maxneigh = 0;
|
||||||
|
cut_csp_sq = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
PairLambdaInputCsp::~PairLambdaInputCsp()
|
||||||
|
{
|
||||||
|
if (copymode) return;
|
||||||
|
|
||||||
|
memory->destroy(distsq);
|
||||||
|
memory->destroy(nearest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
global settings
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void PairLambdaInputCsp::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->lambda_input.
|
||||||
|
* Count the number of computations and measure the compute time for
|
||||||
|
* fix apip_atom_weight.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int PairLambdaInputCsp::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->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 PairLambdaInputCsp::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 PairLambdaInputCsp::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.h
Normal file
54
src/APIP/pair_lambda_input_csp.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,PairLambdaInputCsp);
|
||||||
|
// clang-format on
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef LMP_PAIR_LAMBDA_INPUT_CSP_H
|
||||||
|
#define LMP_PAIR_LAMBDA_INPUT_CSP_H
|
||||||
|
|
||||||
|
#include "pair_lambda_input.h"
|
||||||
|
|
||||||
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class PairLambdaInputCsp : virtual public PairLambdaInput {
|
||||||
|
|
||||||
|
public:
|
||||||
|
PairLambdaInputCsp(class LAMMPS *);
|
||||||
|
~PairLambdaInputCsp();
|
||||||
|
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
|
||||||
309
src/APIP/pair_lambda_zone.cpp
Normal file
309
src/APIP/pair_lambda_zone.cpp
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
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.h"
|
||||||
|
|
||||||
|
#include "atom.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "modify.h"
|
||||||
|
#include "neigh_list.h"
|
||||||
|
#include "neighbor.h"
|
||||||
|
|
||||||
|
using namespace LAMMPS_NS;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
PairLambdaZone::PairLambdaZone(LAMMPS *lmp) :
|
||||||
|
Pair(lmp), fix_lambda(nullptr), 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
PairLambdaZone::~PairLambdaZone()
|
||||||
|
{
|
||||||
|
if (copymode) return;
|
||||||
|
|
||||||
|
if (allocated) {
|
||||||
|
memory->destroy(setflag);
|
||||||
|
memory->destroy(cutsq);
|
||||||
|
|
||||||
|
memory->destroy(cut);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nmax_ta > 0) memory->destroy(lambda_ta);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
void PairLambdaZone::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 PairLambdaZone::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 PairLambdaZone::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 PairLambdaZone::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 PairLambdaZone::init_style()
|
||||||
|
{
|
||||||
|
if (!atom->lambda_input_ta_flag)
|
||||||
|
error->all(FLERR, "pair_lambda_zone requires an atom style with lambda_input_ta");
|
||||||
|
|
||||||
|
// find thermo style
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < modify->nfix; i++) {
|
||||||
|
if (strcmp(modify->fix[i]->style, "lambda") == 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 PairLambdaZone::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 PairLambdaZone::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->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 PairLambdaZone::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 PairLambdaZone::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 *PairLambdaZone::extract(const char *str, int &dim)
|
||||||
|
{
|
||||||
|
dim = 0;
|
||||||
|
if (strcmp(str, "lambda_zone:time_per_atom") == 0) {
|
||||||
|
calculate_time_per_atom();
|
||||||
|
return (void *) &time_per_atom;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
76
src/APIP/pair_lambda_zone.h
Normal file
76
src/APIP/pair_lambda_zone.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/* -*- 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,PairLambdaZone);
|
||||||
|
// clang-format on
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef LMP_PAIR_LAMBDA_ZONE_H
|
||||||
|
#define LMP_PAIR_LAMBDA_ZONE_H
|
||||||
|
|
||||||
|
#include "fix.h"
|
||||||
|
#include "pair.h"
|
||||||
|
|
||||||
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class PairLambdaZone : public Pair {
|
||||||
|
friend class FixLambda;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PairLambdaZone(class LAMMPS *);
|
||||||
|
~PairLambdaZone() 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:
|
||||||
|
class Fix *fix_lambda;
|
||||||
|
|
||||||
|
// 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 this 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] |= LambdaRequired::NO_COMPLEX;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
lambda_required[i] |= LambdaRequired::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->e_complex 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->e_complex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
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->lambda;
|
||||||
|
int *lambda_required = atom->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->f_const_lambda;
|
||||||
|
f_dyn_lambda = atom->f_dyn_lambda;
|
||||||
|
e_ref = get_e_ref_ptr();
|
||||||
|
lambda_const = atom->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->lambda_required_flag)
|
||||||
|
error->all(FLERR, "pair style pace/apip requires an atom style with lambda_required.");
|
||||||
|
if (!atom->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 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$").size() == 0) {
|
||||||
|
lambda_thermostat = false;
|
||||||
|
} else {
|
||||||
|
lambda_thermostat = true;
|
||||||
|
if (!atom->lambda_const_flag)
|
||||||
|
error->all(
|
||||||
|
FLERR,
|
||||||
|
"Pair style pace/apip requires an atom style with lambda_const for a local thermostat.");
|
||||||
|
if (!atom->e_simple_flag)
|
||||||
|
error->all(
|
||||||
|
FLERR,
|
||||||
|
"Pair style pace/apip requires an atom style with e_simple for a local thermostat.");
|
||||||
|
if (!atom->e_complex_flag)
|
||||||
|
error->all(
|
||||||
|
FLERR,
|
||||||
|
"Pair style pace/apip requires an atom style with e_complex for a local thermostat.");
|
||||||
|
if (!atom->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->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_apip_fast.cpp
Normal file
73
src/APIP/pair_pace_apip_fast.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_apip_fast.h"
|
||||||
|
|
||||||
|
#include "atom.h"
|
||||||
|
#include "atom_vec_apip.h"
|
||||||
|
|
||||||
|
using namespace LAMMPS_NS;
|
||||||
|
|
||||||
|
PairPACEapipFast::PairPACEapipFast(LAMMPS *lmp) : PairPACEapip(lmp) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set lambda_required based on lambda and lambda_const
|
||||||
|
* @return true if this calculation is not required
|
||||||
|
*/
|
||||||
|
|
||||||
|
int PairPACEapipFast::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] |= LambdaRequired::NO_SIMPLE;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
lambda_required[i] |= LambdaRequired::SIMPLE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return prefactor lambda which is used for a fast ACE potential
|
||||||
|
*/
|
||||||
|
|
||||||
|
double PairPACEapipFast::compute_factor_lambda(double lambda)
|
||||||
|
{
|
||||||
|
return lambda;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return atom->e_simple which is used for a fast ACE potential
|
||||||
|
*/
|
||||||
|
|
||||||
|
double *PairPACEapipFast::get_e_ref_ptr()
|
||||||
|
{
|
||||||
|
return atom->e_simple;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
extract method for extracting value of scale variable
|
||||||
|
---------------------------------------------------------------------- */
|
||||||
|
void *PairPACEapipFast::extract(const char *str, int &dim)
|
||||||
|
{
|
||||||
|
dim = 2;
|
||||||
|
if (strcmp(str, "scale") == 0) return (void *) scale;
|
||||||
|
dim = 0;
|
||||||
|
if (strcmp(str, "pace/apip/fast:time_per_atom") == 0) {
|
||||||
|
calculate_time_per_atom();
|
||||||
|
return (void *) &time_per_atom;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
44
src/APIP/pair_pace_apip_fast.h
Normal file
44
src/APIP/pair_pace_apip_fast.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/apip/fast,PairPACEapipFast);
|
||||||
|
// clang-format on
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef LMP_PAIR_PACE_APIP_FAST_H
|
||||||
|
#define LMP_PAIR_PACE_APIP_FAST_H
|
||||||
|
|
||||||
|
#include "pair_pace_apip.h"
|
||||||
|
|
||||||
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class PairPACEapipFast : public PairPACEapip {
|
||||||
|
public:
|
||||||
|
PairPACEapipFast(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_apip_precise.cpp
Normal file
73
src/APIP/pair_pace_apip_precise.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_apip_precise.h"
|
||||||
|
|
||||||
|
#include "atom.h"
|
||||||
|
#include "atom_vec_apip.h"
|
||||||
|
|
||||||
|
using namespace LAMMPS_NS;
|
||||||
|
|
||||||
|
PairPACEapipPrecise::PairPACEapipPrecise(LAMMPS *lmp) : PairPACEapip(lmp) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set lambda_required based on lambda and lambda_const
|
||||||
|
* @return true if this calculation is not required
|
||||||
|
*/
|
||||||
|
|
||||||
|
int PairPACEapipPrecise::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] |= LambdaRequired::NO_COMPLEX;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
lambda_required[i] |= LambdaRequired::COMPLEX;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return prefactor 1-lambda which is used for a precise ACE potential
|
||||||
|
*/
|
||||||
|
|
||||||
|
double PairPACEapipPrecise::compute_factor_lambda(double lambda)
|
||||||
|
{
|
||||||
|
return 1 - lambda;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return atom->e_complex which is used for a precise ACE potential
|
||||||
|
*/
|
||||||
|
|
||||||
|
double *PairPACEapipPrecise::get_e_ref_ptr()
|
||||||
|
{
|
||||||
|
return atom->e_complex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
extract method for extracting value of scale variable
|
||||||
|
---------------------------------------------------------------------- */
|
||||||
|
void *PairPACEapipPrecise::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_apip_precise.h
Normal file
44
src/APIP/pair_pace_apip_precise.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/apip/precise,PairPACEapipPrecise);
|
||||||
|
// clang-format on
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef LMP_PAIR_PACE_APIP_PRECISE_H
|
||||||
|
#define LMP_PAIR_PACE_APIP_PRECISE_H
|
||||||
|
|
||||||
|
#include "pair_pace_apip.h"
|
||||||
|
|
||||||
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class PairPACEapipPrecise : public PairPACEapip {
|
||||||
|
public:
|
||||||
|
PairPACEapipPrecise(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
|
||||||
@ -32,6 +32,7 @@ for file in *.cpp *.h; do
|
|||||||
test -f ${file} && action $file
|
test -f ${file} && action $file
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
# edit 2 Makefile.package files to include/exclude package info
|
# edit 2 Makefile.package files to include/exclude package info
|
||||||
|
|
||||||
if (test $1 = 1) then
|
if (test $1 = 1) then
|
||||||
@ -53,12 +54,20 @@ include ..\/..\/lib\/pace\/Makefile.lammps
|
|||||||
|
|
||||||
elif (test $1 = 0) then
|
elif (test $1 = 0) then
|
||||||
|
|
||||||
if (test -e ../Makefile.package) then
|
# The APIP package depends also on the pace library.
|
||||||
sed -i -e 's/[^ \t]*pace[^ \t]* //' ../Makefile.package
|
# Remove in Makefiles only if there are no remaining includes from APIP.
|
||||||
fi
|
# grep searches also in kspace.cpp and thus returns no error.
|
||||||
|
if (test $(grep '#include "ace' ../*pace*.cpp | wc -l) = 0) then
|
||||||
|
|
||||||
|
# update Makefiles
|
||||||
|
if (test -e ../Makefile.package) then
|
||||||
|
sed -i -e 's/[^ \t]*pace[^ \t]* //' ../Makefile.package
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (test -e ../Makefile.package.settings) then
|
||||||
|
sed -i -e '/^[ \t]*include.*pace.*$/d' ../Makefile.package.settings
|
||||||
|
fi
|
||||||
|
|
||||||
if (test -e ../Makefile.package.settings) then
|
|
||||||
sed -i -e '/^[ \t]*include.*pace.*$/d' ../Makefile.package.settings
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|||||||
@ -59,6 +59,7 @@ PACKAGE = \
|
|||||||
kspace \
|
kspace \
|
||||||
adios \
|
adios \
|
||||||
amoeba \
|
amoeba \
|
||||||
|
apip \
|
||||||
asphere \
|
asphere \
|
||||||
awpmd \
|
awpmd \
|
||||||
bocs \
|
bocs \
|
||||||
@ -225,6 +226,7 @@ PACKLIB = \
|
|||||||
python \
|
python \
|
||||||
voronoi \
|
voronoi \
|
||||||
adios \
|
adios \
|
||||||
|
apip \
|
||||||
atc \
|
atc \
|
||||||
awpmd \
|
awpmd \
|
||||||
colvars \
|
colvars \
|
||||||
@ -252,6 +254,7 @@ PACKINT = atc awpmd colvars electrode gpu kokkos lepton ml-pod poems
|
|||||||
|
|
||||||
PACKEXT = \
|
PACKEXT = \
|
||||||
adios \
|
adios \
|
||||||
|
apip \
|
||||||
h5md \
|
h5md \
|
||||||
kim \
|
kim \
|
||||||
machdyn \
|
machdyn \
|
||||||
|
|||||||
52
src/atom.cpp
52
src/atom.cpp
@ -220,6 +220,11 @@ Atom::Atom(LAMMPS *_lmp) : Pointers(_lmp), atom_style(nullptr), avec(nullptr), a
|
|||||||
|
|
||||||
area = ed = em = epsilon = curvature = q_scaled = nullptr;
|
area = ed = em = epsilon = curvature = q_scaled = nullptr;
|
||||||
|
|
||||||
|
// APIP package
|
||||||
|
lambda_const = lambda = lambda_input = lambda_input_ta = e_simple = e_complex = nullptr;
|
||||||
|
lambda_required = nullptr;
|
||||||
|
f_const_lambda = f_dyn_lambda = nullptr;
|
||||||
|
|
||||||
// end of customization section
|
// end of customization section
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
@ -575,6 +580,17 @@ void Atom::peratom_create()
|
|||||||
add_peratom("curvature",&curvature,DOUBLE,0);
|
add_peratom("curvature",&curvature,DOUBLE,0);
|
||||||
add_peratom("q_scaled",&q_scaled,DOUBLE,0);
|
add_peratom("q_scaled",&q_scaled,DOUBLE,0);
|
||||||
|
|
||||||
|
// APIP package
|
||||||
|
add_peratom("lambda",&lambda,DOUBLE,0);
|
||||||
|
add_peratom("lambda_required",&lambda_required,INT,0);
|
||||||
|
add_peratom("lambda_input",&lambda_input,DOUBLE,0);
|
||||||
|
add_peratom("lambda_input_ta",&lambda_input_ta,DOUBLE,0);
|
||||||
|
add_peratom("e_simple",&e_simple,DOUBLE,0);
|
||||||
|
add_peratom("e_complex",&e_complex,DOUBLE,0);
|
||||||
|
add_peratom("lambda_const",&lambda_const,DOUBLE,0);
|
||||||
|
add_peratom("f_const_lambda",&f_const_lambda,DOUBLE,3,1);
|
||||||
|
add_peratom("f_dyn_lambda",&f_dyn_lambda,DOUBLE,3,1);
|
||||||
|
|
||||||
// end of customization section
|
// end of customization section
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
@ -658,6 +674,7 @@ void Atom::set_atomflag_defaults()
|
|||||||
contact_radius_flag = smd_data_9_flag = smd_stress_flag = 0;
|
contact_radius_flag = smd_data_9_flag = smd_stress_flag = 0;
|
||||||
eff_plastic_strain_flag = eff_plastic_strain_rate_flag = 0;
|
eff_plastic_strain_flag = eff_plastic_strain_rate_flag = 0;
|
||||||
nspecial15_flag = 0;
|
nspecial15_flag = 0;
|
||||||
|
lambda_flag = e_simple_flag = e_complex_flag = lambda_input_flag = lambda_input_ta_flag = lambda_required_flag = f_const_lambda_flag = f_dyn_lambda_flag = lambda_const_flag = 0;
|
||||||
|
|
||||||
pdscale = 1.0;
|
pdscale = 1.0;
|
||||||
}
|
}
|
||||||
@ -3116,6 +3133,18 @@ void *Atom::extract(const char *name)
|
|||||||
if (strcmp(name,"curvature") == 0) return (void *) curvature;
|
if (strcmp(name,"curvature") == 0) return (void *) curvature;
|
||||||
if (strcmp(name,"q_scaled") == 0) return (void *) q_scaled;
|
if (strcmp(name,"q_scaled") == 0) return (void *) q_scaled;
|
||||||
|
|
||||||
|
// APIP package
|
||||||
|
|
||||||
|
if (strcmp(name,"lambda") == 0) return (void *) lambda;
|
||||||
|
if (strcmp(name,"lambda_required") == 0) return (void *) lambda_required;
|
||||||
|
if (strcmp(name,"lambda_input") == 0) return (void *) lambda_input;
|
||||||
|
if (strcmp(name,"lambda_input_ta") == 0) return (void *) lambda_input_ta;
|
||||||
|
if (strcmp(name,"e_simple") == 0) return (void *) e_simple;
|
||||||
|
if (strcmp(name,"e_complex") == 0) return (void *) e_complex;
|
||||||
|
if (strcmp(name,"f_const_lambda") == 0) return (void *) f_const_lambda;
|
||||||
|
if (strcmp(name,"f_dyn_lambda") == 0) return (void *) f_dyn_lambda;
|
||||||
|
if (strcmp(name,"lambda_const") == 0) return (void *) lambda_const;
|
||||||
|
|
||||||
// end of customization section
|
// end of customization section
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
@ -3247,6 +3276,17 @@ int Atom::extract_datatype(const char *name)
|
|||||||
if (strcmp(name,"curvature") == 0) return LAMMPS_DOUBLE;
|
if (strcmp(name,"curvature") == 0) return LAMMPS_DOUBLE;
|
||||||
if (strcmp(name,"q_unscaled") == 0) return LAMMPS_DOUBLE;
|
if (strcmp(name,"q_unscaled") == 0) return LAMMPS_DOUBLE;
|
||||||
|
|
||||||
|
// PACE package
|
||||||
|
|
||||||
|
if (strcmp(name,"lambda") == 0) return LAMMPS_DOUBLE;
|
||||||
|
if (strcmp(name,"lambda_required") == 0) return LAMMPS_INT;
|
||||||
|
if (strcmp(name,"lambda_input") == 0) return LAMMPS_DOUBLE;
|
||||||
|
if (strcmp(name,"lambda_input_ta") == 0) return LAMMPS_DOUBLE;
|
||||||
|
if (strcmp(name,"e_simple") == 0) return LAMMPS_DOUBLE;
|
||||||
|
if (strcmp(name,"e_complex") == 0) return LAMMPS_DOUBLE;
|
||||||
|
if (strcmp(name,"lambda_const") == 0) return LAMMPS_DOUBLE;
|
||||||
|
if (strcmp(name,"f_const_lambda") == 0) return LAMMPS_DOUBLE_2D;
|
||||||
|
if (strcmp(name,"f_dyn_lambda") == 0) return LAMMPS_DOUBLE_2D;
|
||||||
// end of customization section
|
// end of customization section
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
@ -3383,6 +3423,18 @@ int Atom::extract_size(const char *name, int type)
|
|||||||
|
|
||||||
if (strcmp(name, "smd_data_9") == 0) return 9;
|
if (strcmp(name, "smd_data_9") == 0) return 9;
|
||||||
if (strcmp(name, "smd_stress") == 0) return 6;
|
if (strcmp(name, "smd_stress") == 0) return 6;
|
||||||
|
|
||||||
|
// APIP package
|
||||||
|
if (strcmp(name, "lambda") == 0) return nlocal;
|
||||||
|
if (strcmp(name, "lambda_required") == 0) return nlocal;
|
||||||
|
if (strcmp(name, "lambda_input") == 0) return nlocal;
|
||||||
|
if (strcmp(name, "lambda_input_ta") == 0) return nlocal;
|
||||||
|
if (strcmp(name, "e_simple") == 0) return nlocal;
|
||||||
|
if (strcmp(name, "e_complex") == 0) return nlocal;
|
||||||
|
if (strcmp(name, "lambda_const") == 0) return nlocal;
|
||||||
|
if (strcmp(name, "f_const_lambda") == 0) return nall;
|
||||||
|
if (strcmp(name, "f_dyn_lambda") == 0) return nall;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// custom arrays
|
// custom arrays
|
||||||
|
|||||||
@ -177,6 +177,11 @@ class Atom : protected Pointers {
|
|||||||
|
|
||||||
double *area, *ed, *em, *epsilon, *curvature, *q_scaled;
|
double *area, *ed, *em, *epsilon, *curvature, *q_scaled;
|
||||||
|
|
||||||
|
// APIP package
|
||||||
|
|
||||||
|
double *lambda, *lambda_input, *lambda_input_ta, *e_simple, *e_complex, **f_const_lambda, **f_dyn_lambda, *lambda_const;
|
||||||
|
int *lambda_required;
|
||||||
|
|
||||||
// end of customization section
|
// end of customization section
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
@ -225,6 +230,10 @@ class Atom : protected Pointers {
|
|||||||
|
|
||||||
int dielectric_flag;
|
int dielectric_flag;
|
||||||
|
|
||||||
|
// APIP package
|
||||||
|
|
||||||
|
int lambda_flag, e_simple_flag, e_complex_flag, lambda_input_flag, lambda_input_ta_flag, lambda_required_flag, f_const_lambda_flag, f_dyn_lambda_flag, lambda_const_flag;
|
||||||
|
|
||||||
// end of customization section
|
// end of customization section
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
96
src/atom_vec_apip.cpp
Normal file
96
src/atom_vec_apip.cpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
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 *lambda, *lambda_input, *lambda_input_ta, *lambda_const, *e_simple, *e_complex,
|
||||||
|
**f_const_lambda, **f_dyn_lambda;
|
||||||
|
int *lambda_required;
|
||||||
|
atom->lambda_flag = 1;
|
||||||
|
atom->lambda_input_flag = 1;
|
||||||
|
atom->lambda_input_ta_flag = 1;
|
||||||
|
atom->lambda_const_flag = 1;
|
||||||
|
atom->lambda_required_flag = 1;
|
||||||
|
atom->e_simple_flag = 1;
|
||||||
|
atom->e_complex_flag = 1;
|
||||||
|
atom->f_const_lambda_flag = 1;
|
||||||
|
atom->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 = {"lambda", "lambda_required", "lambda_input", "lambda_input_ta", "lambda_const"};
|
||||||
|
fields_comm = {"lambda", "lambda_required", "lambda_input_ta", "lambda_const"};
|
||||||
|
fields_comm_vel = {};
|
||||||
|
fields_border = {"lambda", "lambda_required", "lambda_input_ta", "lambda_const"};
|
||||||
|
fields_border_vel = {};
|
||||||
|
fields_exchange = {"lambda", "lambda_required", "lambda_input_ta", "lambda_const"};
|
||||||
|
fields_restart = {"lambda", "lambda_required", "lambda_input", "lambda_input_ta", "lambda_const"};
|
||||||
|
fields_create = {};
|
||||||
|
fields_grow = {
|
||||||
|
"lambda", "lambda_required", "lambda_input", "lambda_input_ta", "lambda_const",
|
||||||
|
"e_simple", "e_complex", "f_const_lambda", "f_dyn_lambda"}; // allocates memory
|
||||||
|
fields_reverse = {"f_const_lambda",
|
||||||
|
"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()
|
||||||
|
{
|
||||||
|
lambda = atom->lambda;
|
||||||
|
lambda_required = atom->lambda_required;
|
||||||
|
lambda_input = atom->lambda_input;
|
||||||
|
lambda_input_ta = atom->lambda_input_ta;
|
||||||
|
lambda_const = atom->lambda_const;
|
||||||
|
e_simple = atom->e_simple;
|
||||||
|
e_complex = atom->e_complex;
|
||||||
|
f_const_lambda = atom->f_const_lambda;
|
||||||
|
f_dyn_lambda = atom->f_dyn_lambda;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
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(&f_const_lambda[n][0], 0, 3 * nbytes);
|
||||||
|
memset(&f_dyn_lambda[n][0], 0, 3 * nbytes);
|
||||||
|
memset(&lambda_required[n], 0, nbytes / sizeof(double) * sizeof(int));
|
||||||
|
}
|
||||||
58
src/atom_vec_apip.h
Normal file
58
src/atom_vec_apip.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/* -*- 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;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
double *lambda, *lambda_input, *lambda_const, *lambda_input_ta, *e_simple, *e_complex,
|
||||||
|
**f_const_lambda, **f_dyn_lambda;
|
||||||
|
int *lambda_required;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef LMP_ATOM_LAMBDA_REQUIRED
|
||||||
|
#define LMP_ATOM_LAMBDA_REQUIRED
|
||||||
|
namespace LambdaRequired {
|
||||||
|
|
||||||
|
enum {
|
||||||
|
UNKNOWN = 0,
|
||||||
|
SIMPLE = 1 << 0,
|
||||||
|
NO_SIMPLE = 1 << 1,
|
||||||
|
COMPLEX = 1 << 2,
|
||||||
|
NO_COMPLEX = 1 << 3,
|
||||||
|
};
|
||||||
|
} // namespace LambdaRequired
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace LAMMPS_NS
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@ -331,6 +331,27 @@ ComputePropertyAtom::ComputePropertyAtom(LAMMPS *lmp, int narg, char **arg) :
|
|||||||
error->all(FLERR,"Compute property/atom {} requires atom style tri", arg[iarg]);
|
error->all(FLERR,"Compute property/atom {} requires atom style tri", arg[iarg]);
|
||||||
pack_choice[i] = &ComputePropertyAtom::pack_corner3z;
|
pack_choice[i] = &ComputePropertyAtom::pack_corner3z;
|
||||||
|
|
||||||
|
} else if (strcmp(arg[iarg],"lambda") == 0) {
|
||||||
|
if (!atom->lambda_flag)
|
||||||
|
error->all(FLERR,"Compute property/atom {} is not available", arg[iarg]);
|
||||||
|
pack_choice[i] = &ComputePropertyAtom::pack_lambda;
|
||||||
|
} else if (strcmp(arg[iarg],"lambda_input") == 0) {
|
||||||
|
if (!atom->lambda_input_flag)
|
||||||
|
error->all(FLERR,"Compute property/atom {} is not available", arg[iarg]);
|
||||||
|
pack_choice[i] = &ComputePropertyAtom::pack_lambda_input;
|
||||||
|
} else if (strcmp(arg[iarg],"lambda_required") == 0) {
|
||||||
|
if (!atom->lambda_required_flag)
|
||||||
|
error->all(FLERR,"Compute property/atom {} is not available", arg[iarg]);
|
||||||
|
pack_choice[i] = &ComputePropertyAtom::pack_lambda_required;
|
||||||
|
} else if (strcmp(arg[iarg],"e_simple") == 0) {
|
||||||
|
if (!atom->e_simple_flag)
|
||||||
|
error->all(FLERR,"Compute property/atom {} is not available", arg[iarg]);
|
||||||
|
pack_choice[i] = &ComputePropertyAtom::pack_e_simple;
|
||||||
|
} else if (strcmp(arg[iarg],"e_complex") == 0) {
|
||||||
|
if (!atom->e_complex_flag)
|
||||||
|
error->all(FLERR,"Compute property/atom {} is not available", arg[iarg]);
|
||||||
|
pack_choice[i] = &ComputePropertyAtom::pack_e_complex;
|
||||||
|
|
||||||
// custom per-atom vector or array
|
// custom per-atom vector or array
|
||||||
|
|
||||||
} else if (utils::strmatch(arg[iarg],"^[id]2?_")) {
|
} else if (utils::strmatch(arg[iarg],"^[id]2?_")) {
|
||||||
@ -1564,6 +1585,81 @@ void ComputePropertyAtom::pack_tqz(int n)
|
|||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void ComputePropertyAtom::pack_lambda(int n)
|
||||||
|
{
|
||||||
|
double *lambda = atom->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_lambda_input(int n)
|
||||||
|
{
|
||||||
|
double *lambda_input = atom->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_lambda_required(int n)
|
||||||
|
{
|
||||||
|
int *lambda_required = atom->lambda_required;
|
||||||
|
int *mask = atom->mask;
|
||||||
|
int nlocal = atom->nlocal;
|
||||||
|
|
||||||
|
for (int i = 0; i < nlocal; i++) {
|
||||||
|
if (mask[i] & groupbit) buf[n] = lambda_required[i];
|
||||||
|
else buf[n] = 0.0;
|
||||||
|
n += nvalues;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void ComputePropertyAtom::pack_e_simple(int n)
|
||||||
|
{
|
||||||
|
double *e_simple = atom->e_simple;
|
||||||
|
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_e_complex(int n)
|
||||||
|
{
|
||||||
|
double *e_complex = atom->e_complex;
|
||||||
|
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)
|
void ComputePropertyAtom::pack_end1x(int n)
|
||||||
{
|
{
|
||||||
AtomVecLine::Bonus *bonus = avec_line->bonus;
|
AtomVecLine::Bonus *bonus = avec_line->bonus;
|
||||||
|
|||||||
@ -137,6 +137,12 @@ class ComputePropertyAtom : public Compute {
|
|||||||
void pack_d2name(int);
|
void pack_d2name(int);
|
||||||
|
|
||||||
void pack_atom_style(int);
|
void pack_atom_style(int);
|
||||||
|
|
||||||
|
void pack_lambda(int);
|
||||||
|
void pack_lambda_required(int);
|
||||||
|
void pack_lambda_input(int);
|
||||||
|
void pack_e_simple(int);
|
||||||
|
void pack_e_complex(int);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace LAMMPS_NS
|
} // namespace LAMMPS_NS
|
||||||
|
|||||||
@ -45,6 +45,7 @@ enum{ID,MOL,PROC,PROCP1,TYPE,TYPELABEL,ELEMENT,MASS,
|
|||||||
Q,MUX,MUY,MUZ,MU,RADIUS,DIAMETER,
|
Q,MUX,MUY,MUZ,MU,RADIUS,DIAMETER,
|
||||||
OMEGAX,OMEGAY,OMEGAZ,ANGMOMX,ANGMOMY,ANGMOMZ,
|
OMEGAX,OMEGAY,OMEGAZ,ANGMOMX,ANGMOMY,ANGMOMZ,
|
||||||
TQX,TQY,TQZ,
|
TQX,TQY,TQZ,
|
||||||
|
LAMBDA,LAMBDA_INPUT,LAMBDA_REQUIRED,ESIMPLE,ECOMPLEX, // APIP package
|
||||||
COMPUTE,FIX,VARIABLE,IVEC,DVEC,IARRAY,DARRAY};
|
COMPUTE,FIX,VARIABLE,IVEC,DVEC,IARRAY,DARRAY};
|
||||||
enum{LT,LE,GT,GE,EQ,NEQ,XOR};
|
enum{LT,LE,GT,GE,EQ,NEQ,XOR};
|
||||||
|
|
||||||
@ -1223,6 +1224,25 @@ int DumpCustom::count()
|
|||||||
double **darray = atom->darray[iwhich];
|
double **darray = atom->darray[iwhich];
|
||||||
ptr = &darray[0][argindex[i]-1];
|
ptr = &darray[0][argindex[i]-1];
|
||||||
nstride = atom->dcols[iwhich];
|
nstride = atom->dcols[iwhich];
|
||||||
|
|
||||||
|
// APIP package
|
||||||
|
} else if (thresh_array[ithresh] == LAMBDA) {
|
||||||
|
ptr = &atom->lambda[0];
|
||||||
|
nstride = 1;
|
||||||
|
} else if (thresh_array[ithresh] == LAMBDA_INPUT) {
|
||||||
|
ptr = &atom->lambda_input[0];
|
||||||
|
nstride = 1;
|
||||||
|
} else if (thresh_array[ithresh] == LAMBDA_REQUIRED) {
|
||||||
|
int *lambda_required = atom->lambda_required;
|
||||||
|
for (i = 0; i < nlocal; i++) dchoose[i] = lambda_required[i];
|
||||||
|
ptr = dchoose;
|
||||||
|
nstride = 1;
|
||||||
|
} else if (thresh_array[ithresh] == ESIMPLE) {
|
||||||
|
ptr = &atom->e_simple[0];
|
||||||
|
nstride = 1;
|
||||||
|
} else if (thresh_array[ithresh] == ECOMPLEX) {
|
||||||
|
ptr = &atom->e_complex[0];
|
||||||
|
nstride = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// unselect atoms that don't meet threshold criterion
|
// unselect atoms that don't meet threshold criterion
|
||||||
@ -1624,6 +1644,33 @@ int DumpCustom::parse_fields(int narg, char **arg)
|
|||||||
pack_choice[iarg] = &DumpCustom::pack_tqz;
|
pack_choice[iarg] = &DumpCustom::pack_tqz;
|
||||||
vtype[iarg] = Dump::DOUBLE;
|
vtype[iarg] = Dump::DOUBLE;
|
||||||
|
|
||||||
|
// APIP package
|
||||||
|
} else if (strcmp(arg[iarg],"lambda") == 0) {
|
||||||
|
if (!atom->lambda_flag)
|
||||||
|
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||||
|
pack_choice[iarg] = &DumpCustom::pack_lambda;
|
||||||
|
vtype[iarg] = Dump::DOUBLE;
|
||||||
|
} else if (strcmp(arg[iarg],"lambda_input") == 0) {
|
||||||
|
if (!atom->lambda_input_flag)
|
||||||
|
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||||
|
pack_choice[iarg] = &DumpCustom::pack_lambda_input;
|
||||||
|
vtype[iarg] = Dump::DOUBLE;
|
||||||
|
} else if (strcmp(arg[iarg],"lambda_required") == 0) {
|
||||||
|
if (!atom->lambda_required_flag)
|
||||||
|
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||||
|
pack_choice[iarg] = &DumpCustom::pack_lambda_required;
|
||||||
|
vtype[iarg] = Dump::INT;
|
||||||
|
} else if (strcmp(arg[iarg],"e_simple") == 0) {
|
||||||
|
if (!atom->e_simple_flag)
|
||||||
|
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||||
|
pack_choice[iarg] = &DumpCustom::pack_e_simple;
|
||||||
|
vtype[iarg] = Dump::DOUBLE;
|
||||||
|
} else if (strcmp(arg[iarg],"e_complex") == 0) {
|
||||||
|
if (!atom->e_complex_flag)
|
||||||
|
error->all(FLERR,"Dumping an atom property that isn't allocated");
|
||||||
|
pack_choice[iarg] = &DumpCustom::pack_e_complex;
|
||||||
|
vtype[iarg] = Dump::DOUBLE;
|
||||||
|
|
||||||
// compute or fix or variable or custom vector/array
|
// compute or fix or variable or custom vector/array
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -2067,6 +2114,13 @@ int DumpCustom::modify_param(int narg, char **arg)
|
|||||||
else if (strcmp(arg[1],"tqy") == 0) thresh_array[nthresh] = TQY;
|
else if (strcmp(arg[1],"tqy") == 0) thresh_array[nthresh] = TQY;
|
||||||
else if (strcmp(arg[1],"tqz") == 0) thresh_array[nthresh] = TQZ;
|
else if (strcmp(arg[1],"tqz") == 0) thresh_array[nthresh] = TQZ;
|
||||||
|
|
||||||
|
// APIP package
|
||||||
|
else if (strcmp(arg[1],"lambda") == 0) thresh_array[nthresh] = LAMBDA;
|
||||||
|
else if (strcmp(arg[1],"lambda_input") == 0) thresh_array[nthresh] = LAMBDA_INPUT;
|
||||||
|
else if (strcmp(arg[1],"lambda_required") == 0) thresh_array[nthresh] = LAMBDA_REQUIRED;
|
||||||
|
else if (strcmp(arg[1],"e_simple") == 0) thresh_array[nthresh] = ESIMPLE;
|
||||||
|
else if (strcmp(arg[1],"e_complex") == 0) thresh_array[nthresh] = ECOMPLEX;
|
||||||
|
|
||||||
// compute or fix or variable or custom vector/array
|
// compute or fix or variable or custom vector/array
|
||||||
// must grow field2index and argindex arrays, since access is beyond nfield
|
// must grow field2index and argindex arrays, since access is beyond nfield
|
||||||
|
|
||||||
@ -3448,3 +3502,63 @@ void DumpCustom::pack_tqz_triclinic_general(int n)
|
|||||||
n += size_one;
|
n += size_one;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DumpCustom::pack_lambda(int n)
|
||||||
|
{
|
||||||
|
double *lambda = atom->lambda;
|
||||||
|
|
||||||
|
for (int i = 0; i < nchoose; i++) {
|
||||||
|
buf[n] = lambda[clist[i]];
|
||||||
|
n += size_one;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DumpCustom::pack_lambda_input(int n)
|
||||||
|
{
|
||||||
|
double *lambda_input = atom->lambda_input;
|
||||||
|
|
||||||
|
for (int i = 0; i < nchoose; i++) {
|
||||||
|
buf[n] = lambda_input[clist[i]];
|
||||||
|
n += size_one;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DumpCustom::pack_lambda_required(int n)
|
||||||
|
{
|
||||||
|
int *lambda_required = atom->lambda_required;
|
||||||
|
|
||||||
|
for (int i = 0; i < nchoose; i++) {
|
||||||
|
buf[n] = lambda_required[clist[i]];
|
||||||
|
n += size_one;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DumpCustom::pack_e_simple(int n)
|
||||||
|
{
|
||||||
|
double *e_simple = atom->e_simple;
|
||||||
|
|
||||||
|
for (int i = 0; i < nchoose; i++) {
|
||||||
|
buf[n] = e_simple[clist[i]];
|
||||||
|
n += size_one;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DumpCustom::pack_e_complex(int n)
|
||||||
|
{
|
||||||
|
double *e_complex = atom->e_complex;
|
||||||
|
|
||||||
|
for (int i = 0; i < nchoose; i++) {
|
||||||
|
buf[n] = e_complex[clist[i]];
|
||||||
|
n += size_one;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -235,6 +235,12 @@ class DumpCustom : public Dump {
|
|||||||
void pack_tqx_triclinic_general(int);
|
void pack_tqx_triclinic_general(int);
|
||||||
void pack_tqy_triclinic_general(int);
|
void pack_tqy_triclinic_general(int);
|
||||||
void pack_tqz_triclinic_general(int);
|
void pack_tqz_triclinic_general(int);
|
||||||
|
|
||||||
|
void pack_lambda(int);
|
||||||
|
void pack_lambda_input(int);
|
||||||
|
void pack_lambda_required(int);
|
||||||
|
void pack_e_simple(int);
|
||||||
|
void pack_e_complex(int);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace LAMMPS_NS
|
} // namespace LAMMPS_NS
|
||||||
|
|||||||
@ -141,6 +141,11 @@ FixStoreState::FixStoreState(LAMMPS *lmp, int narg, char **arg) :
|
|||||||
error->all(FLERR, "Cannot use fix store/state {} for atom style {}",
|
error->all(FLERR, "Cannot use fix store/state {} for atom style {}",
|
||||||
arg[iarg], atom->get_style());
|
arg[iarg], atom->get_style());
|
||||||
val.pack_choice = &FixStoreState::pack_q;
|
val.pack_choice = &FixStoreState::pack_q;
|
||||||
|
} else if (strcmp(arg[iarg],"lambda") == 0) {
|
||||||
|
if (!atom->lambda_flag)
|
||||||
|
error->all(FLERR, "Cannot use fix store/state {} for atom style {}",
|
||||||
|
arg[iarg], atom->get_style());
|
||||||
|
val.pack_choice = &FixStoreState::pack_lambda;
|
||||||
} else if (strcmp(arg[iarg],"mux") == 0) {
|
} else if (strcmp(arg[iarg],"mux") == 0) {
|
||||||
if (!atom->mu_flag)
|
if (!atom->mu_flag)
|
||||||
error->all(FLERR, "Cannot use fix store/state {} for atom style {}",
|
error->all(FLERR, "Cannot use fix store/state {} for atom style {}",
|
||||||
@ -1269,6 +1274,21 @@ void FixStoreState::pack_q(int n)
|
|||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void FixStoreState::pack_lambda(int n)
|
||||||
|
{
|
||||||
|
double *lambda = atom->lambda;
|
||||||
|
int *mask = atom->mask;
|
||||||
|
int nlocal = atom->nlocal;
|
||||||
|
|
||||||
|
for (int i = 0; i < nlocal; i++) {
|
||||||
|
if (mask[i] & groupbit) vbuf[n] = lambda[i];
|
||||||
|
else vbuf[n] = 0.0;
|
||||||
|
n += values.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
void FixStoreState::pack_mux(int n)
|
void FixStoreState::pack_mux(int n)
|
||||||
{
|
{
|
||||||
double **mu = atom->mu;
|
double **mu = atom->mu;
|
||||||
|
|||||||
@ -106,6 +106,7 @@ class FixStoreState : public Fix {
|
|||||||
void pack_fy(int);
|
void pack_fy(int);
|
||||||
void pack_fz(int);
|
void pack_fz(int);
|
||||||
void pack_q(int);
|
void pack_q(int);
|
||||||
|
void pack_lambda(int);
|
||||||
void pack_mux(int);
|
void pack_mux(int);
|
||||||
void pack_muy(int);
|
void pack_muy(int);
|
||||||
void pack_muz(int);
|
void pack_muz(int);
|
||||||
|
|||||||
@ -813,6 +813,7 @@ void ReadDump::process_atoms()
|
|||||||
double **x = atom->x;
|
double **x = atom->x;
|
||||||
double **v = atom->v;
|
double **v = atom->v;
|
||||||
double *q = atom->q;
|
double *q = atom->q;
|
||||||
|
double *lambda = atom->lambda;
|
||||||
double **f = atom->f;
|
double **f = atom->f;
|
||||||
tagint *tag = atom->tag;
|
tagint *tag = atom->tag;
|
||||||
imageint *image = atom->image;
|
imageint *image = atom->image;
|
||||||
@ -862,6 +863,9 @@ void ReadDump::process_atoms()
|
|||||||
case Reader::Q:
|
case Reader::Q:
|
||||||
q[m] = fields[i][ifield];
|
q[m] = fields[i][ifield];
|
||||||
break;
|
break;
|
||||||
|
case Reader::LAMBDA:
|
||||||
|
lambda[m] = fields[i][ifield];
|
||||||
|
break;
|
||||||
case Reader::VY:
|
case Reader::VY:
|
||||||
v[m][1] = fields[i][ifield];
|
v[m][1] = fields[i][ifield];
|
||||||
break;
|
break;
|
||||||
@ -977,6 +981,7 @@ void ReadDump::process_atoms()
|
|||||||
tag = atom->tag;
|
tag = atom->tag;
|
||||||
v = atom->v;
|
v = atom->v;
|
||||||
q = atom->q;
|
q = atom->q;
|
||||||
|
lambda = atom->lambda;
|
||||||
image = atom->image;
|
image = atom->image;
|
||||||
|
|
||||||
// set atom attributes from other dump file fields
|
// set atom attributes from other dump file fields
|
||||||
@ -1001,6 +1006,9 @@ void ReadDump::process_atoms()
|
|||||||
case Reader::Q:
|
case Reader::Q:
|
||||||
q[m] = fields[i][ifield];
|
q[m] = fields[i][ifield];
|
||||||
break;
|
break;
|
||||||
|
case Reader::LAMBDA:
|
||||||
|
lambda[m] = fields[i][ifield];
|
||||||
|
break;
|
||||||
case Reader::IX:
|
case Reader::IX:
|
||||||
xbox = static_cast<int> (fields[i][ifield]);
|
xbox = static_cast<int> (fields[i][ifield]);
|
||||||
break;
|
break;
|
||||||
@ -1163,6 +1171,8 @@ int ReadDump::fields_and_keywords(int narg, char **arg)
|
|||||||
if (type < 0) break;
|
if (type < 0) break;
|
||||||
if (type == Reader::Q && !atom->q_flag)
|
if (type == Reader::Q && !atom->q_flag)
|
||||||
error->all(FLERR,"Read dump of charge property that isn't supported by atom style");
|
error->all(FLERR,"Read dump of charge property that isn't supported by atom style");
|
||||||
|
if (type == Reader::LAMBDA && !atom->lambda_flag)
|
||||||
|
error->all(FLERR,"Read dump of lambda property that isn't supported by atom style");
|
||||||
fieldtype[nfield++] = type;
|
fieldtype[nfield++] = type;
|
||||||
iarg++;
|
iarg++;
|
||||||
}
|
}
|
||||||
@ -1288,6 +1298,7 @@ int ReadDump::whichtype(char *str)
|
|||||||
else if (strcmp(str,"vy") == 0) type = Reader::VY;
|
else if (strcmp(str,"vy") == 0) type = Reader::VY;
|
||||||
else if (strcmp(str,"vz") == 0) type = Reader::VZ;
|
else if (strcmp(str,"vz") == 0) type = Reader::VZ;
|
||||||
else if (strcmp(str,"q") == 0) type = Reader::Q;
|
else if (strcmp(str,"q") == 0) type = Reader::Q;
|
||||||
|
else if (strcmp(str,"lambda") == 0) type = Reader::LAMBDA;
|
||||||
else if (strcmp(str,"ix") == 0) type = Reader::IX;
|
else if (strcmp(str,"ix") == 0) type = Reader::IX;
|
||||||
else if (strcmp(str,"iy") == 0) type = Reader::IY;
|
else if (strcmp(str,"iy") == 0) type = Reader::IY;
|
||||||
else if (strcmp(str,"iz") == 0) type = Reader::IZ;
|
else if (strcmp(str,"iz") == 0) type = Reader::IZ;
|
||||||
|
|||||||
@ -22,7 +22,7 @@ namespace LAMMPS_NS {
|
|||||||
|
|
||||||
class Reader : protected Pointers {
|
class Reader : protected Pointers {
|
||||||
public:
|
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, LAMBDA, IX, IY, IZ, FX, FY, FZ };
|
||||||
enum { UNSET, NOSCALE_NOWRAP, NOSCALE_WRAP, SCALE_NOWRAP, SCALE_WRAP };
|
enum { UNSET, NOSCALE_NOWRAP, NOSCALE_WRAP, SCALE_NOWRAP, SCALE_WRAP };
|
||||||
|
|
||||||
Reader(class LAMMPS *);
|
Reader(class LAMMPS *);
|
||||||
|
|||||||
@ -413,6 +413,9 @@ bigint ReaderNative::read_header(double box[3][3], int &boxinfo, int &triclinic,
|
|||||||
else if (fieldtype[i] == Q)
|
else if (fieldtype[i] == Q)
|
||||||
fieldindex[i] = find_label("q", labels);
|
fieldindex[i] = find_label("q", labels);
|
||||||
|
|
||||||
|
else if (fieldtype[i] == LAMBDA)
|
||||||
|
fieldindex[i] = find_label("lambda", labels);
|
||||||
|
|
||||||
else if (fieldtype[i] == IX)
|
else if (fieldtype[i] == IX)
|
||||||
fieldindex[i] = find_label("ix", labels);
|
fieldindex[i] = find_label("ix", labels);
|
||||||
else if (fieldtype[i] == IY)
|
else if (fieldtype[i] == IY)
|
||||||
|
|||||||
@ -4992,6 +4992,30 @@ void Variable::peratom2global(int flag, char *word, double *vector, int nstride,
|
|||||||
if (!atom->q_flag)
|
if (!atom->q_flag)
|
||||||
error->one(FLERR,"Variable uses atom property that isn't allocated");
|
error->one(FLERR,"Variable uses atom property that isn't allocated");
|
||||||
mine = atom->q[index];
|
mine = atom->q[index];
|
||||||
|
} else if (strcmp(word,"lambda") == 0) {
|
||||||
|
if (!atom->lambda_flag)
|
||||||
|
error->one(FLERR,"Variable uses atom property that isn't allocated");
|
||||||
|
mine = atom->lambda[index];
|
||||||
|
} else if (strcmp(word,"lambda_required") == 0) {
|
||||||
|
if (!atom->lambda_required_flag)
|
||||||
|
error->one(FLERR,"Variable uses atom property that isn't allocated");
|
||||||
|
mine = atom->lambda_required[index];
|
||||||
|
} else if (strcmp(word,"lambda_input") == 0) {
|
||||||
|
if (!atom->lambda_input_flag)
|
||||||
|
error->one(FLERR,"Variable uses atom property that isn't allocated");
|
||||||
|
mine = atom->lambda_input[index];
|
||||||
|
} else if (strcmp(word,"lambda_const") == 0) {
|
||||||
|
if (!atom->lambda_const_flag)
|
||||||
|
error->one(FLERR,"Variable uses atom property that isn't allocated");
|
||||||
|
mine = atom->lambda_const[index];
|
||||||
|
} else if (strcmp(word,"e_simple") == 0) {
|
||||||
|
if (!atom->e_simple_flag)
|
||||||
|
error->one(FLERR,"Variable uses atom property that isn't allocated");
|
||||||
|
mine = atom->e_simple[index];
|
||||||
|
} else if (strcmp(word,"e_complex") == 0) {
|
||||||
|
if (!atom->e_complex_flag)
|
||||||
|
error->one(FLERR,"Variable uses atom property that isn't allocated");
|
||||||
|
mine = atom->e_complex[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strcmp(word,"x") == 0) mine = atom->x[index][0];
|
else if (strcmp(word,"x") == 0) mine = atom->x[index][0];
|
||||||
@ -5087,6 +5111,12 @@ int Variable::is_atom_vector(char *word)
|
|||||||
if (strcmp(word,"fx") == 0) return 1;
|
if (strcmp(word,"fx") == 0) return 1;
|
||||||
if (strcmp(word,"fy") == 0) return 1;
|
if (strcmp(word,"fy") == 0) return 1;
|
||||||
if (strcmp(word,"fz") == 0) return 1;
|
if (strcmp(word,"fz") == 0) return 1;
|
||||||
|
if (strcmp(word,"lambda") == 0) return 1;
|
||||||
|
if (strcmp(word,"lambda_input") == 0) return 1;
|
||||||
|
if (strcmp(word,"lambda_required") == 0) return 1;
|
||||||
|
if (strcmp(word,"lambda_const") == 0) return 1;
|
||||||
|
if (strcmp(word,"e_simple") == 0) return 1;
|
||||||
|
if (strcmp(word,"e_complex") == 0) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5155,6 +5185,37 @@ void Variable::atom_vector(char *word, Tree **tree, Tree **treestack, int &ntree
|
|||||||
error->one(FLERR,"Variable uses atom property 'q' that isn't allocated");
|
error->one(FLERR,"Variable uses atom property 'q' that isn't allocated");
|
||||||
newtree->array = atom->q;
|
newtree->array = atom->q;
|
||||||
newtree->nstride = 1;
|
newtree->nstride = 1;
|
||||||
|
} else if (strcmp(word,"lambda") == 0) {
|
||||||
|
if (!atom->lambda_flag)
|
||||||
|
error->one(FLERR,"Variable uses atom property 'lambda' that isn't allocated");
|
||||||
|
newtree->array = atom->lambda;
|
||||||
|
newtree->nstride = 1;
|
||||||
|
} else if (strcmp(word,"lambda_required") == 0) {
|
||||||
|
if (!atom->lambda_required_flag)
|
||||||
|
error->one(FLERR,"Variable uses atom property 'lambda_required' that isn't allocated");
|
||||||
|
newtree->type = INTARRAY;
|
||||||
|
newtree->nstride = 1;
|
||||||
|
newtree->iarray = atom->lambda_required;
|
||||||
|
} else if (strcmp(word,"lambda_input") == 0) {
|
||||||
|
if (!atom->lambda_input_flag)
|
||||||
|
error->one(FLERR,"Variable uses atom property 'lambda_input' that isn't allocated");
|
||||||
|
newtree->array = atom->lambda_input;
|
||||||
|
newtree->nstride = 1;
|
||||||
|
} else if (strcmp(word,"lambda_const") == 0) {
|
||||||
|
if (!atom->lambda_const_flag)
|
||||||
|
error->one(FLERR,"Variable uses atom property 'lambda_const' that isn't allocated");
|
||||||
|
newtree->array = atom->lambda_const;
|
||||||
|
newtree->nstride = 1;
|
||||||
|
} else if (strcmp(word,"e_simple") == 0) {
|
||||||
|
if (!atom->e_simple_flag)
|
||||||
|
error->one(FLERR,"Variable uses atom property 'e_simple' that isn't allocated");
|
||||||
|
newtree->array = atom->e_simple;
|
||||||
|
newtree->nstride = 1;
|
||||||
|
} else if (strcmp(word,"e_complex") == 0) {
|
||||||
|
if (!atom->e_complex_flag)
|
||||||
|
error->one(FLERR,"Variable uses atom property 'e_complex' that isn't allocated");
|
||||||
|
newtree->array = atom->e_complex;
|
||||||
|
newtree->nstride = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strcmp(word,"x") == 0) newtree->array = &atom->x[0][0];
|
else if (strcmp(word,"x") == 0) newtree->array = &atom->x[0][0];
|
||||||
|
|||||||
Reference in New Issue
Block a user