force_fields: Unify and upgrade NequIP and Allegro interfaces (#4898)

This commit is contained in:
Gabriele Tocci 2026-03-03 16:41:12 +01:00 committed by GitHub
parent f66d47d961
commit ab353c7fcf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 963 additions and 1707 deletions

Binary file not shown.

Binary file not shown.

View file

@ -1,76 +1,86 @@
# Nequip and Allegro
# NequIP and Allegro
This
[Colab tutorial](https://colab.research.google.com/github/gabriele16/cp2k/blob/nequip-cp2k-colab/colab/allegro-cp2k-tutorial.ipynb)
illustrates how to train an equivariant neural network interatomic potential for bulk water using
the Allegro framework. You will learn how to train a model, deploy it in production, and run
molecular dynamics simulations in CP2K. The training and inference will be carried out on the GPU
provided by the Colab environment.
NequIP and Allegro are frameworks designed for developing interatomic potentials for molecular
dynamics simulations using deep equivariant neural networks. The methodology and recent
high-performance upgrades are described in detail in the literature ([](#Batzner2022),
[](#Musaelian2023), [](#Tan2025)).
Allegro is designed for constructing highly accurate and scalable interatomic potentials for
molecular dynamics simulations. The methodology is described in detail in this paper
([](#Musaelian2023)). An open-source package that implements
[Allegro](https://github.com/mir-group/allegro), built on the
[Nequip framework](https://github.com/mir-group/nequip) was developed by the Allegro and NequIP
authors, A. Musaelian, S. Batzner, A. Johansson, L. Sun, C. J. Owen, M. Kornbluth, B. Kozinsky.
The CP2K interface is compatible with models trained and compiled with NequIP version >= 0.7.0, and
it is consistent with the LAMMPS `pair_nequip_allegro` (v0.7.0) integration.
## Input Section
Inference in CP2K is performed through the
[NEQUIP](#CP2K_INPUT.FORCE_EVAL.MM.FORCEFIELD.NONBONDED.NEQUIP) and
[ALLEGRO](#CP2K_INPUT.FORCE_EVAL.MM.FORCEFIELD.NONBONDED.ALLEGRO) sections. As an example, the
relevant section for Allegro (or similarly for NequIP) is:
Inference in CP2K has been unified and is configured entirely through the
[NEQUIP](#CP2K_INPUT.FORCE_EVAL.MM.FORCEFIELD.NONBONDED.NEQUIP) section within the `&NONBONDED`
forcefield parameters.
An example of the input configuration:
```text
&FORCEFIELD
&NONBONDED
&NEQUIP
MODEL_TYPE NEQUIP # possible choices are NEQUIP or ALLEGRO
ATOMS H O
POT_FILE_NAME NequIP/waterscan-neq0.16.nequip.pth
UNIT_ENERGY eV
UNIT_FORCES eV*angstrom^-1
UNIT_LENGTH angstrom
&END NEQUIP
&END NONBONDED
&END FORCEFIELD
```none
&ALLEGRO
ATOMS Si
PARM_FILE_NAME Allegro/si-deployed.pth
UNIT_COORDS angstrom
UNIT_ENERGY eV
UNIT_FORCES eV*angstrom^-1
&END ALLEGRO
```
where the `si-deployed.pth` refers to the PyTorch model that was deployed using the Allegro
framework, and the `UNIT` tags refer to the units of the coordinates, energy and forces of the model
itself. An example for the full input file can be found in the
[Colab tutorial](https://colab.research.google.com/github/gabriele16/cp2k/blob/nequip-cp2k-colab/colab/allegro-cp2k-tutorial.ipynb)
and on the regtests, see
[Allegro_si_MD.inp](https://github.com/cp2k/cp2k/blob/master/tests/Fist/regtest-allegro/Allegro_si_MD.inp)
- [MODEL_TYPE](#CP2K_INPUT.FORCE_EVAL.MM.FORCEFIELD.NONBONDED.NEQUIP.MODEL_TYPE): Specifies the
architecture of the loaded model (`NEQUIP` or `ALLEGRO`).
- [ATOMS](#CP2K_INPUT.FORCE_EVAL.MM.FORCEFIELD.NONBONDED.NEQUIP.ATOMS): Expects a list of
elements/kinds.
- [POT_FILE_NAME](#CP2K_INPUT.FORCE_EVAL.MM.FORCEFIELD.NONBONDED.NEQUIP.POT_FILE_NAME): The path to
the NequIP/Allegro model.
- **`UNIT_*`**: These tags explicitly define the units for the model's internal lengths, energies,
and forces.
### Input details
Full example input files demonstrating production-ready molecular dynamics setups can be found in
the CP2K regression tests directory:
The tag [ATOMS](#CP2K_INPUT.FORCE_EVAL.MM.FORCEFIELD.NONBONDED.ALLEGRO.ATOMS) expects a list of
elements/kinds in a way and order that is consistent with the YAML file of NequIP and Allegro. If
this is not done unphysical results will be obtained. Additionally, the atomic coordinates in the
[COORD](#CP2K_INPUT.FORCE_EVAL.SUBSYS.COORD) or [TOPOLOGY](#CP2K_INPUT.FORCE_EVAL.SUBSYS.TOPOLOGY)
section have to be provided in a way that is consistent with the YAML file. If this is not done
unphysical results will be obtained. Spotting such issues is quite straightforward as the energy is
significantly wrong. For example, by inverting the order of one of the elements in the test
`regtest-nequip/NequIP_water.inp`, the error with respect to the reference value is of the order of
1 eV. Additionally, running MD leads rapidly to highly unstable simulations.
- `tests/Fist/regtest-nequip/water-bulk.inp`
- `tests/Fist/regtest-allegro/water-bulk.inp`
## Compiling CP2K with LibTorch
Running with NequIP or Allegro requires compiling CP2K with the libtorch library. For the CP2K
binaries running on CPUs installing the toolchain using the flag `--with-libtorch` is enough. To
benefit from (often significant) GPU acceleration, the precompiled Libtorch library for CUDA can be
obtained at [https://pytorch.org](https://pytorch.org), for example for CUDA 11.8:
Running NequIP or Allegro requires compiling CP2K with the LibTorch library. Versions of LibTorch
(2.4 through 2.7) are supported.
For CP2K binaries running on CPUs, installing the toolchain using the flag `--with-libtorch` is
sufficient.
To benefit from GPU acceleration, either compile LibTorch from scratch or download the precompiled
LibTorch library for CUDA from [PyTorch](https://pytorch.org) and provide the appropriate path to
the toolchain script:
```shell
wget https://download.pytorch.org/libtorch/cu118/libtorch-cxx11-abi-shared-with-deps-2.0.0%2Bcu118.zip
./install_cp2k_toolchain.sh --with-libtorch=<path-to-libtorch-cuda>
```
After extracting the libtorch CUDA binaries, the toolchain script `./install_cp2k_toolchain.sh` can
be run providing the appropriate path with the flag `--with-libtorch=<path-to-libtorch-cuda>`.
## Validation & Reproducibility
- **Comparison with LAMMPS:** We have verified that this implementation numerically reproduces the
results of the LAMMPS `pair_nequip_allegro` plugin.
- **Data:** The training datasets, model files inside `data/NequIP` and `data/Allegro`, input
scripts, and parity plots used for validation are available on Zenodo:
[doi:10.5281/zenodo.18848354](https://doi.org/10.5281/zenodo.18848354).
## Further Resources
For additional references on NequIP, Allegro and equivariant neural networks (e3nn) see:
For additional references on NequIP, Allegro, and equivariant neural networks (e3nn), see:
- Allegro paper [](#Musaelian2023) and code <https://github.com/mir-group/allegro>
- NequIP paper [](#Batzner2022) and code <https://github.com/mir-group/nequip>
- A Tutorial on LAMMPS by the NequIP/Allegro authors is found at the Colab notebook
[here](https://colab.research.google.com/drive/1yq2UwnET4loJYg_Fptt9kpklVaZvoHnq)
- For an introduction to e3nn see [e3nn.org](https://e3nn.org) and
[doi:10.5281/zenodo.7430260](https://dx.doi.org/10.5281/zenodo.7430260)
- **High-Performance Upgrades:** Paper [](#Tan2025) and source code at
[github.com/mir-group/pair_nequip_allegro](https://github.com/mir-group/pair_nequip_allegro).
- **Allegro:** Paper [](#Musaelian2023) and source code at
[github.com/mir-group/allegro](https://github.com/mir-group/allegro).
- **NequIP:** Paper [](#Batzner2022) and source code at
[github.com/mir-group/nequip](https://github.com/mir-group/nequip).
- **e3nn:** For an introduction to Euclidean neural networks, visit [e3nn.org](https://e3nn.org) and
[doi:10.5281/zenodo.7430260](https://dx.doi.org/10.5281/zenodo.7430260).

View file

@ -346,7 +346,6 @@ list(
manybody_deepmd.F
manybody_gal21.F
manybody_gal.F
manybody_allegro.F
manybody_nequip.F
manybody_potential.F
manybody_siepmann.F

View file

@ -91,7 +91,7 @@ MODULE bibliography
Sander2015, Schreiber2008, vanSetten2015, Setyawan2010, Ahart2024, Knysh2024, &
Schambeck2024, Mewes2018, Sertcan2024, Drautz2019, Lysogorskiy2021, Bochkarev2024, &
VazdaCruz2021, Chen2025, Hernandez2025, Marek2025, Hehn2022, Hehn2024, Pasquier2025, &
Hanasaki2025
Hanasaki2025, Tan2025
CONTAINS
@ -672,6 +672,14 @@ CONTAINS
source="J. Comput. Chem.", volume="3", pages="227-228", &
year=1982, doi="10.1002/jcc.540030214")
CALL add_reference(key=Tan2025, &
authors=s2a("C. W. Tan", "M. L. Descoteaux", "M. Kotak", "G. de Miranda Nascimento", &
"S. R. Kavanagh", "L. Zichi", "M. Wang", "A. Saluja", "Y. R. Hu", &
"T. Smidt", "A. Johansson", "W. C. Witt", "B. Kozinsky", "A. Musaelian"), &
title="High-performance training and inference for deep equivariant interatomic potentials", &
source="arXiv", pages="2504.16068", &
year=2025, doi="10.48550/arXiv.2504.16068")
CALL add_reference(key=Tao2003, &
authors=s2a("J. M. Tao", "J. P. Perdew", "V. N. Staroverov", "G. E. Scuseria"), &
title="Climbing the density functional ladder: Nonempirical meta-generalized "// &

View file

@ -230,10 +230,10 @@ CONTAINS
IF (ANY(potparm%pot(ikind, jkind)%pot%type == gal21_type)) THEN
full_nl(ikind, jkind) = .TRUE.
END IF
IF (ANY(potparm%pot(ikind, jkind)%pot%type == nequip_type)) THEN
IF (ANY(potparm%pot(ikind, jkind)%pot%type == allegro_type)) THEN
full_nl(ikind, jkind) = .TRUE.
END IF
IF (ANY(potparm%pot(ikind, jkind)%pot%type == allegro_type)) THEN
IF (ANY(potparm%pot(ikind, jkind)%pot%type == nequip_type)) THEN
full_nl(ikind, jkind) = .TRUE.
END IF
IF (ANY(potparm%pot(ikind, jkind)%pot%type == ace_type)) THEN

View file

@ -22,14 +22,9 @@ MODULE fist_nonbond_env_types
fist_neighbor_type
USE kinds, ONLY: default_string_length,&
dp
USE pair_potential_types, ONLY: ace_type,&
gal21_type,&
gal_type,&
nequip_type,&
pair_potential_pp_release,&
pair_potential_pp_type,&
siepmann_type,&
tersoff_type
USE pair_potential_types, ONLY: &
ace_type, allegro_type, gal21_type, gal_type, nequip_type, pair_potential_pp_release, &
pair_potential_pp_type, siepmann_type, tersoff_type
USE torch_api, ONLY: torch_model_release,&
torch_model_type
#include "./base/base_uses.f90"
@ -41,7 +36,7 @@ MODULE fist_nonbond_env_types
PUBLIC :: fist_nonbond_env_type, fist_nonbond_env_set, &
fist_nonbond_env_get, fist_nonbond_env_create, &
fist_nonbond_env_release, pos_type, eam_type, &
nequip_data_type, allegro_data_type, &
nequip_data_type, &
deepmd_data_type, ace_data_type
! **************************************************************************************************
@ -61,13 +56,6 @@ MODULE fist_nonbond_env_types
TYPE(torch_model_type) :: model
END TYPE nequip_data_type
TYPE allegro_data_type
INTEGER, POINTER :: use_indices(:) => NULL()
REAL(KIND=dp), POINTER :: force(:, :) => NULL()
REAL(KIND=dp) :: virial(3, 3) = 0.0_dp
TYPE(torch_model_type) :: model
END TYPE allegro_data_type
TYPE deepmd_data_type
INTEGER, POINTER :: use_indices(:) => NULL()
REAL(KIND=dp), POINTER :: force(:, :) => NULL()
@ -124,8 +112,7 @@ MODULE fist_nonbond_env_types
TYPE(eam_type), DIMENSION(:), POINTER :: eam_data => NULL()
TYPE(deepmd_data_type), POINTER :: deepmd_data => NULL()
TYPE(ace_data_type), POINTER :: ace_data => NULL()
TYPE(nequip_data_type), POINTER :: nequip_data => NULL()
TYPE(allegro_data_type), POINTER :: allegro_data => NULL()
TYPE(nequip_data_type), POINTER :: nequip_data => NULL()
END TYPE fist_nonbond_env_type
CONTAINS
@ -157,7 +144,6 @@ CONTAINS
!> \param ij_kind_full_fac ...
!> \param eam_data ...
!> \param nequip_data ...
!> \param allegro_data ...
!> \param deepmd_data ...
!> \param ace_data ...
!> \param charges ...
@ -170,7 +156,7 @@ CONTAINS
shift_cutoff, do_electrostatics, r_last_update, r_last_update_pbc, rshell_last_update_pbc, &
rcore_last_update_pbc, cell_last_update, num_update, last_update, &
counter, natom_types, long_range_correction, ij_kind_full_fac, eam_data, &
nequip_data, allegro_data, deepmd_data, ace_data, charges)
nequip_data, deepmd_data, ace_data, charges)
TYPE(fist_nonbond_env_type), INTENT(IN) :: fist_nonbond_env
TYPE(pair_potential_pp_type), OPTIONAL, POINTER :: potparm14, potparm
@ -188,7 +174,6 @@ CONTAINS
REAL(KIND=dp), DIMENSION(:, :), OPTIONAL, POINTER :: ij_kind_full_fac
TYPE(eam_type), DIMENSION(:), OPTIONAL, POINTER :: eam_data
TYPE(nequip_data_type), OPTIONAL, POINTER :: nequip_data
TYPE(allegro_data_type), OPTIONAL, POINTER :: allegro_data
TYPE(deepmd_data_type), OPTIONAL, POINTER :: deepmd_data
TYPE(ace_data_type), OPTIONAL, POINTER :: ace_data
REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER :: charges
@ -197,7 +182,6 @@ CONTAINS
IF (PRESENT(potparm14)) potparm14 => fist_nonbond_env%potparm14
IF (PRESENT(eam_data)) eam_data => fist_nonbond_env%eam_data
IF (PRESENT(nequip_data)) nequip_data => fist_nonbond_env%nequip_data
IF (PRESENT(allegro_data)) allegro_data => fist_nonbond_env%allegro_data
IF (PRESENT(deepmd_data)) deepmd_data => fist_nonbond_env%deepmd_data
IF (PRESENT(ace_data)) ace_data => fist_nonbond_env%ace_data
IF (PRESENT(potparm)) potparm => fist_nonbond_env%potparm
@ -256,7 +240,6 @@ CONTAINS
!> \param long_range_correction ...
!> \param eam_data ...
!> \param nequip_data ...
!> \param allegro_data ...
!> \param deepmd_data ...
!> \param ace_data ...
!> \param charges ...
@ -269,7 +252,7 @@ CONTAINS
shift_cutoff, do_electrostatics, r_last_update, r_last_update_pbc, rshell_last_update_pbc, &
rcore_last_update_pbc, cell_last_update, num_update, last_update, &
counter, natom_types, long_range_correction, eam_data, &
nequip_data, allegro_data, deepmd_data, ace_data, charges)
nequip_data, deepmd_data, ace_data, charges)
TYPE(fist_nonbond_env_type), INTENT(INOUT) :: fist_nonbond_env
TYPE(pair_potential_pp_type), OPTIONAL, POINTER :: potparm14, potparm
@ -286,7 +269,6 @@ CONTAINS
REAL(KIND=dp), OPTIONAL :: long_range_correction
TYPE(eam_type), DIMENSION(:), OPTIONAL, POINTER :: eam_data
TYPE(nequip_data_type), OPTIONAL, POINTER :: nequip_data
TYPE(allegro_data_type), OPTIONAL, POINTER :: allegro_data
TYPE(deepmd_data_type), OPTIONAL, POINTER :: deepmd_data
TYPE(ace_data_type), OPTIONAL, POINTER :: ace_data
REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER :: charges
@ -294,7 +276,6 @@ CONTAINS
IF (PRESENT(potparm14)) fist_nonbond_env%potparm14 => potparm14
IF (PRESENT(eam_data)) fist_nonbond_env%eam_data => eam_data
IF (PRESENT(nequip_data)) fist_nonbond_env%nequip_data => nequip_data
IF (PRESENT(allegro_data)) fist_nonbond_env%allegro_data => allegro_data
IF (PRESENT(deepmd_data)) fist_nonbond_env%deepmd_data => deepmd_data
IF (PRESENT(ace_data)) fist_nonbond_env%ace_data => ace_data
IF (PRESENT(potparm)) fist_nonbond_env%potparm => potparm
@ -368,7 +349,6 @@ CONTAINS
NULLIFY (fist_nonbond_env%rcore_last_update_pbc)
NULLIFY (fist_nonbond_env%eam_data)
NULLIFY (fist_nonbond_env%nequip_data)
NULLIFY (fist_nonbond_env%allegro_data)
NULLIFY (fist_nonbond_env%deepmd_data)
NULLIFY (fist_nonbond_env%ace_data)
NULLIFY (fist_nonbond_env%charges)
@ -503,6 +483,10 @@ CONTAINS
fist_nonbond_env%ij_kind_full_fac(idim, jdim) = 0.5_dp
fist_nonbond_env%ij_kind_full_fac(idim, jdim) = 0.5_dp
END IF
IF (ANY(potparm%pot(idim, jdim)%pot%type == allegro_type)) THEN
fist_nonbond_env%ij_kind_full_fac(idim, jdim) = 0.5_dp
fist_nonbond_env%ij_kind_full_fac(idim, jdim) = 0.5_dp
END IF
ELSE
! In case we don't use potparm for initialization let's account
! only for the real-space part of the Ewald sum.
@ -561,16 +545,6 @@ CONTAINS
CALL torch_model_release(fist_nonbond_env%nequip_data%model)
DEALLOCATE (fist_nonbond_env%nequip_data)
END IF
IF (ASSOCIATED(fist_nonbond_env%allegro_data)) THEN
IF (ASSOCIATED(fist_nonbond_env%allegro_data%force)) THEN
DEALLOCATE (fist_nonbond_env%allegro_data%force)
END IF
IF (ASSOCIATED(fist_nonbond_env%allegro_data%use_indices)) THEN
DEALLOCATE (fist_nonbond_env%allegro_data%use_indices)
END IF
CALL torch_model_release(fist_nonbond_env%allegro_data%model)
DEALLOCATE (fist_nonbond_env%allegro_data)
END IF
IF (ASSOCIATED(fist_nonbond_env%deepmd_data)) THEN
IF (ASSOCIATED(fist_nonbond_env%deepmd_data%force)) THEN
DEALLOCATE (fist_nonbond_env%deepmd_data%force)

View file

@ -67,12 +67,11 @@ MODULE force_fields_input
USE memory_utilities, ONLY: reallocate
USE message_passing, ONLY: mp_para_env_type
USE pair_potential_types, ONLY: &
ace_type, allegro_pot_type, allegro_type, b4_type, bm_type, deepmd_type, &
do_potential_single_allocation, ea_type, eam_pot_type, ft_pot_type, ft_type, ftd_type, &
gal21_type, gal_type, gp_type, gw_type, ip_type, ipbv_pot_type, lj_charmm_type, &
nequip_pot_type, nequip_type, no_potential_single_allocation, pair_potential_p_type, &
pair_potential_reallocate, potential_single_allocation, siepmann_type, tab_pot_type, &
tab_type, tersoff_type, wl_type
ace_type, allegro_type, b4_type, bm_type, deepmd_type, do_potential_single_allocation, &
ea_type, eam_pot_type, ft_pot_type, ft_type, ftd_type, gal21_type, gal_type, gp_type, &
gw_type, ip_type, ipbv_pot_type, lj_charmm_type, nequip_pot_type, nequip_type, &
no_potential_single_allocation, pair_potential_p_type, pair_potential_reallocate, &
potential_single_allocation, siepmann_type, tab_pot_type, tab_type, tersoff_type, wl_type
USE shell_potential_types, ONLY: shell_p_create,&
shell_p_type
USE string_utilities, ONLY: uppercase
@ -109,9 +108,9 @@ CONTAINS
CHARACTER(LEN=default_string_length), &
DIMENSION(:), POINTER :: atm_names
INTEGER :: nace, nallegro, nb4, nbends, nbm, nbmhft, nbmhftd, nbonds, nchg, ndeepmd, neam, &
ngal, ngal21, ngd, ngp, nimpr, nipbv, nlj, nnequip, nopbend, nshell, nsiepmann, ntab, &
ntersoff, ntors, ntot, nubs, nwl
INTEGER :: nace, nb4, nbends, nbm, nbmhft, nbmhftd, nbonds, nchg, ndeepmd, neam, ngal, &
ngal21, ngd, ngp, nimpr, nipbv, nlj, nnequip, nopbend, nshell, nsiepmann, ntab, ntersoff, &
ntors, ntot, nubs, nwl
LOGICAL :: explicit, unique_spline
REAL(KIND=dp) :: min_eps_spline_allowed
TYPE(input_info_type), POINTER :: inp_info
@ -293,22 +292,10 @@ CONTAINS
CALL read_nequip_section(inp_info%nonbonded, tmp_section2, ntot)
END IF
tmp_section2 => section_vals_get_subs_vals(tmp_section, "allegro")
CALL section_vals_get(tmp_section2, explicit=explicit, n_repetition=nallegro)
ntot = nlj + nwl + neam + ngd + nipbv + nbmhft + nbmhftd + nb4 + nbm + ngp + ntersoff + &
ngal + ngal21 + nsiepmann + nnequip
IF (explicit) THEN
! avoid repeating the allegro section for each pair
CALL section_vals_val_get(tmp_section2, "ATOMS", c_vals=atm_names)
nallegro = nallegro - 1 + SIZE(atm_names) + (SIZE(atm_names)*SIZE(atm_names) - SIZE(atm_names))/2
CALL pair_potential_reallocate(inp_info%nonbonded, 1, ntot + nallegro, allegro=.TRUE.)
CALL read_allegro_section(inp_info%nonbonded, tmp_section2, ntot)
END IF
tmp_section2 => section_vals_get_subs_vals(tmp_section, "TABPOT")
CALL section_vals_get(tmp_section2, explicit=explicit, n_repetition=ntab)
ntot = nlj + nwl + neam + ngd + nipbv + nbmhft + nbmhftd + nb4 + nbm + ngp + ntersoff + &
ngal + ngal21 + nsiepmann + nnequip + nallegro
ngal + ngal21 + nsiepmann + nnequip
IF (explicit) THEN
CALL pair_potential_reallocate(inp_info%nonbonded, 1, ntot + ntab, tab=.TRUE.)
CALL read_tabpot_section(inp_info%nonbonded, tmp_section2, ntot, para_env, mm_section)
@ -317,7 +304,7 @@ CONTAINS
tmp_section2 => section_vals_get_subs_vals(tmp_section, "DEEPMD")
CALL section_vals_get(tmp_section2, explicit=explicit, n_repetition=ndeepmd)
ntot = nlj + nwl + neam + ngd + nipbv + nbmhft + nbmhftd + nb4 + nbm + ngp + ntersoff + &
ngal + ngal21 + nsiepmann + nnequip + nallegro + ntab
ngal + ngal21 + nsiepmann + nnequip + ntab
IF (explicit) THEN
! avoid repeating the deepmd section for each pair
CALL section_vals_val_get(tmp_section2, "ATOMS", c_vals=atm_names)
@ -329,7 +316,7 @@ CONTAINS
tmp_section2 => section_vals_get_subs_vals(tmp_section, "ACE")
CALL section_vals_get(tmp_section2, explicit=explicit, n_repetition=nace)
ntot = nlj + nwl + neam + ngd + nipbv + nbmhft + nbmhftd + nb4 + nbm + ngp + ntersoff + &
ngal + ngal21 + nsiepmann + nnequip + nallegro + ntab + ndeepmd
ngal + ngal21 + nsiepmann + nnequip + ntab + ndeepmd
IF (explicit) THEN
! avoid repeating the ace section for each pair
CALL section_vals_val_get(tmp_section2, "ATOMS", c_vals=atm_names)
@ -789,35 +776,43 @@ CONTAINS
TYPE(section_vals_type), POINTER :: section
INTEGER, INTENT(IN) :: start
CHARACTER(LEN=default_string_length) :: nequip_file_name, unit_cell, &
unit_coords, unit_energy, unit_forces
CHARACTER(LEN=default_string_length) :: model_type_str, pot_file_name, &
unit_energy, unit_forces, unit_length
CHARACTER(LEN=default_string_length), &
DIMENSION(:), POINTER :: atm_names
INTEGER :: isec, jsec, n_items
INTEGER :: chosen_type, isec, jsec, n_items
TYPE(nequip_pot_type) :: nequip
n_items = 1
isec = 1
n_items = isec*n_items
CALL section_vals_val_get(section, "ATOMS", c_vals=atm_names)
CALL section_vals_val_get(section, "PARM_FILE_NAME", c_val=nequip_file_name)
CALL section_vals_val_get(section, "UNIT_COORDS", c_val=unit_coords)
CALL section_vals_val_get(section, "POT_FILE_NAME", c_val=pot_file_name)
CALL section_vals_val_get(section, "UNIT_LENGTH", c_val=unit_length)
CALL section_vals_val_get(section, "UNIT_ENERGY", c_val=unit_energy)
CALL section_vals_val_get(section, "UNIT_FORCES", c_val=unit_forces)
CALL section_vals_val_get(section, "UNIT_CELL", c_val=unit_cell)
CALL section_vals_val_get(section, "MODEL_TYPE", c_val=model_type_str)
CALL uppercase(model_type_str)
! Since reading nequip metadata is expensive we do it only once.
nequip%nequip_file_name = discover_file(nequip_file_name)
nequip%unit_coords = unit_coords
IF (TRIM(model_type_str) == "ALLEGRO") THEN
chosen_type = allegro_type
ELSE IF (TRIM(model_type_str) == "NEQUIP") THEN
chosen_type = nequip_type
ELSE
CALL cp_abort(__LOCATION__, &
"Unknown MODEL_TYPE: "//TRIM(model_type_str)//". Use NEQUIP or ALLEGRO.")
END IF
nequip%pot_file_name = discover_file(pot_file_name)
nequip%unit_length = unit_length
nequip%unit_forces = unit_forces
nequip%unit_energy = unit_energy
nequip%unit_cell = unit_cell
CALL read_nequip_data(nequip)
CALL check_cp2k_atom_names_in_torch(atm_names, nequip%type_names_torch)
DO isec = 1, SIZE(atm_names)
DO jsec = isec, SIZE(atm_names)
nonbonded%pot(start + n_items)%pot%type = nequip_type
nonbonded%pot(start + n_items)%pot%type = chosen_type
nonbonded%pot(start + n_items)%pot%at1 = atm_names(isec)
nonbonded%pot(start + n_items)%pot%at2 = atm_names(jsec)
CALL uppercase(nonbonded%pot(start + n_items)%pot%at1)
@ -830,58 +825,6 @@ CONTAINS
END SUBROUTINE read_nequip_section
! **************************************************************************************************
!> \brief Reads the ALLEGRO section
!> \param nonbonded ...
!> \param section ...
!> \param start ...
!> \author Gabriele Tocci
! **************************************************************************************************
SUBROUTINE read_allegro_section(nonbonded, section, start)
TYPE(pair_potential_p_type), POINTER :: nonbonded
TYPE(section_vals_type), POINTER :: section
INTEGER, INTENT(IN) :: start
CHARACTER(LEN=default_string_length) :: allegro_file_name, unit_cell, &
unit_coords, unit_energy, unit_forces
CHARACTER(LEN=default_string_length), &
DIMENSION(:), POINTER :: atm_names
INTEGER :: isec, jsec, n_items
TYPE(allegro_pot_type) :: allegro
n_items = 1
isec = 1
n_items = isec*n_items
CALL section_vals_val_get(section, "ATOMS", c_vals=atm_names)
CALL section_vals_val_get(section, "PARM_FILE_NAME", c_val=allegro_file_name)
CALL section_vals_val_get(section, "UNIT_COORDS", c_val=unit_coords)
CALL section_vals_val_get(section, "UNIT_ENERGY", c_val=unit_energy)
CALL section_vals_val_get(section, "UNIT_FORCES", c_val=unit_forces)
CALL section_vals_val_get(section, "UNIT_CELL", c_val=unit_cell)
! Since reading allegro metadata is expensive we do it only once.
allegro%allegro_file_name = discover_file(allegro_file_name)
allegro%unit_coords = unit_coords
allegro%unit_forces = unit_forces
allegro%unit_energy = unit_energy
allegro%unit_cell = unit_cell
CALL read_allegro_data(allegro)
CALL check_cp2k_atom_names_in_torch(atm_names, allegro%type_names_torch)
DO isec = 1, SIZE(atm_names)
DO jsec = isec, SIZE(atm_names)
nonbonded%pot(start + n_items)%pot%type = allegro_type
nonbonded%pot(start + n_items)%pot%at1 = atm_names(isec)
nonbonded%pot(start + n_items)%pot%at2 = atm_names(jsec)
CALL uppercase(nonbonded%pot(start + n_items)%pot%at1)
CALL uppercase(nonbonded%pot(start + n_items)%pot%at2)
nonbonded%pot(start + n_items)%pot%set(1)%allegro = allegro
nonbonded%pot(start + n_items)%pot%rcutsq = allegro%rcutsq
n_items = n_items + 1
END DO
END DO
END SUBROUTINE read_allegro_section
! **************************************************************************************************
!> \brief Reads the LJ section
!> \param nonbonded ...
@ -2467,56 +2410,91 @@ CONTAINS
TYPE(nequip_pot_type) :: nequip
CHARACTER(LEN=*), PARAMETER :: routineN = 'read_nequip_data'
CHARACTER(LEN=1), PARAMETER :: delimiter = ' '
CHARACTER(LEN=100), ALLOCATABLE, DIMENSION(:) :: tokenized_string
CHARACTER(LEN=default_path_length) :: allow_tf32_str, cutoff_str, &
default_dtype, model_dtype, types_str
INTEGER :: handle
LOGICAL :: allow_tf32, found
CHARACTER(LEN=4000) :: cutoff_matrix_str
CHARACTER(LEN=default_path_length) :: allow_tf32_str, cutoff_str, model_dtype, &
num_types_str, types_str
INTEGER :: handle, i, j, k, len_path
LOGICAL :: allow_tf32, found_model_file
REAL(KIND=dp) :: cut_val
CALL timeset(routineN, handle)
INQUIRE (FILE=nequip%nequip_file_name, EXIST=found)
IF (.NOT. found) THEN
INQUIRE (FILE=nequip%pot_file_name, EXIST=found_model_file)
IF (.NOT. found_model_file) THEN
CALL cp_abort(__LOCATION__, &
"Nequip model file <"//TRIM(nequip%nequip_file_name)// &
"Nequip model file <"//TRIM(nequip%pot_file_name)// &
"> not found.")
END IF
nequip%nequip_version = torch_model_read_metadata(nequip%nequip_file_name, "nequip_version")
cutoff_str = torch_model_read_metadata(nequip%nequip_file_name, "r_max")
types_str = torch_model_read_metadata(nequip%nequip_file_name, "type_names")
CALL tokenize_string(TRIM(types_str), delimiter, tokenized_string)
len_path = LEN_TRIM(nequip%pot_file_name)
IF (len_path >= 4) THEN
IF (nequip%pot_file_name(len_path - 3:len_path) == ".pt2") THEN
CALL cp_abort(__LOCATION__, &
"AOT compiled models (.pt2) are not yet supported in CP2K. " &
//"Please use TorchScript (.pth or .pt) models compiled with nequip-compile.")
END IF
END IF
num_types_str = torch_model_read_metadata(nequip%pot_file_name, "num_types")
READ (num_types_str, *) nequip%num_types
cutoff_str = torch_model_read_metadata(nequip%pot_file_name, "r_max")
types_str = torch_model_read_metadata(nequip%pot_file_name, "type_names")
CALL tokenize_string(TRIM(types_str), tokenized_string)
IF (SIZE(tokenized_string) /= nequip%num_types) THEN
CALL cp_abort(__LOCATION__, &
"NequIP Metadata Error: 'num_types' does not match count of 'type_names'")
END IF
IF (ALLOCATED(nequip%type_names_torch)) THEN
DEALLOCATE (nequip%type_names_torch)
END IF
ALLOCATE (nequip%type_names_torch(SIZE(tokenized_string)))
nequip%type_names_torch(:) = tokenized_string(:)
IF (ALLOCATED(nequip%cutoff_matrix)) DEALLOCATE (nequip%cutoff_matrix)
ALLOCATE (nequip%cutoff_matrix(nequip%num_types, nequip%num_types))
READ (cutoff_str, *) nequip%rcutsq
nequip%rcutsq = cp_unit_to_cp2k(nequip%rcutsq, nequip%unit_coords)
nequip%rcutsq = cp_unit_to_cp2k(nequip%rcutsq, nequip%unit_length)
nequip%rcutsq = nequip%rcutsq*nequip%rcutsq
nequip%unit_coords_val = cp_unit_to_cp2k(nequip%unit_coords_val, nequip%unit_coords)
nequip%unit_length_val = cp_unit_to_cp2k(nequip%unit_length_val, nequip%unit_length)
nequip%unit_forces_val = cp_unit_to_cp2k(nequip%unit_forces_val, nequip%unit_forces)
nequip%unit_energy_val = cp_unit_to_cp2k(nequip%unit_energy_val, nequip%unit_energy)
nequip%unit_cell_val = cp_unit_to_cp2k(nequip%unit_cell_val, nequip%unit_cell)
default_dtype = torch_model_read_metadata(nequip%nequip_file_name, "default_dtype")
model_dtype = torch_model_read_metadata(nequip%nequip_file_name, "model_dtype")
IF (TRIM(default_dtype) == "float32" .AND. TRIM(model_dtype) == "float32") THEN
nequip%do_nequip_sp = .TRUE.
ELSE IF (TRIM(default_dtype) == "float64" .AND. TRIM(model_dtype) == "float64") THEN
nequip%do_nequip_sp = .FALSE.
cutoff_matrix_str = torch_model_read_metadata(nequip%pot_file_name, "per_edge_type_cutoff")
IF (LEN_TRIM(cutoff_matrix_str) > 0) THEN
CALL tokenize_string(TRIM(cutoff_matrix_str), tokenized_string)
IF (SIZE(tokenized_string) /= nequip%num_types**2) THEN
CALL cp_abort(__LOCATION__, "per_edge_type_cutoff size does not match num_types^2")
END IF
k = 0
DO i = 1, nequip%num_types
DO j = 1, nequip%num_types
k = k + 1
READ (tokenized_string(k), *) cut_val
cut_val = cp_unit_to_cp2k(cut_val, nequip%unit_length)
nequip%cutoff_matrix(i, j) = cut_val*cut_val
END DO
END DO
ELSE
CALL cp_abort(__LOCATION__, &
"Both default_dtype and model_dtype should be either float32 or float64. Currently, default_dtype is <"// &
TRIM(default_dtype)//"> and model_dtype is <"//TRIM(model_dtype)//">.")
! Fallback: Fill with global r_max squared
nequip%cutoff_matrix(:, :) = nequip%rcutsq
END IF
allow_tf32_str = torch_model_read_metadata(nequip%nequip_file_name, "allow_tf32")
model_dtype = torch_model_read_metadata(nequip%pot_file_name, "model_dtype")
IF (TRIM(model_dtype) == "float32") THEN
nequip%mixed_precision = .TRUE.
ELSE IF (TRIM(model_dtype) == "float64") THEN
nequip%mixed_precision = .FALSE.
END IF
allow_tf32_str = torch_model_read_metadata(nequip%pot_file_name, "allow_tf32")
allow_tf32 = (TRIM(allow_tf32_str) == "1")
IF (TRIM(allow_tf32_str) /= "1" .AND. TRIM(allow_tf32_str) /= "0") THEN
CALL cp_abort(__LOCATION__, &
@ -2528,150 +2506,61 @@ CONTAINS
CALL timestop(handle)
END SUBROUTINE read_nequip_data
! **************************************************************************************************
!> \brief reads ALLEGRO potential from .pth file
!> \param allegro ...
!> \author Gabriele Tocci
! **************************************************************************************************
SUBROUTINE read_allegro_data(allegro)
TYPE(allegro_pot_type) :: allegro
CHARACTER(len=*), PARAMETER :: routineN = 'read_allegro_data'
CHARACTER(LEN=1), PARAMETER :: delimiter = ' '
CHARACTER(LEN=100), ALLOCATABLE, DIMENSION(:) :: tokenized_string
CHARACTER(LEN=default_path_length) :: allow_tf32_str, cutoff_str, &
default_dtype, model_dtype, types_str
INTEGER :: handle
LOGICAL :: allow_tf32, found
CALL timeset(routineN, handle)
INQUIRE (FILE=allegro%allegro_file_name, EXIST=found)
IF (.NOT. found) THEN
CALL cp_abort(__LOCATION__, &
"Allegro model file <"//TRIM(allegro%allegro_file_name)// &
"> not found.")
END IF
allegro%nequip_version = torch_model_read_metadata(allegro%allegro_file_name, "nequip_version")
IF (allegro%nequip_version == "") THEN
CALL cp_abort(__LOCATION__, &
"Allegro model file <"//TRIM(allegro%allegro_file_name)// &
"> has not been deployed; did you forget to run `nequip-deploy`?")
END IF
cutoff_str = torch_model_read_metadata(allegro%allegro_file_name, "r_max")
types_str = torch_model_read_metadata(allegro%allegro_file_name, "type_names")
CALL tokenize_string(TRIM(types_str), delimiter, tokenized_string)
IF (ALLOCATED(allegro%type_names_torch)) THEN
DEALLOCATE (allegro%type_names_torch)
END IF
ALLOCATE (allegro%type_names_torch(SIZE(tokenized_string)))
allegro%type_names_torch(:) = tokenized_string(:)
READ (cutoff_str, *) allegro%rcutsq
allegro%rcutsq = cp_unit_to_cp2k(allegro%rcutsq, allegro%unit_coords)
allegro%rcutsq = allegro%rcutsq*allegro%rcutsq
allegro%unit_coords_val = cp_unit_to_cp2k(allegro%unit_coords_val, allegro%unit_coords)
allegro%unit_forces_val = cp_unit_to_cp2k(allegro%unit_forces_val, allegro%unit_forces)
allegro%unit_energy_val = cp_unit_to_cp2k(allegro%unit_energy_val, allegro%unit_energy)
allegro%unit_cell_val = cp_unit_to_cp2k(allegro%unit_cell_val, allegro%unit_cell)
default_dtype = torch_model_read_metadata(allegro%allegro_file_name, "default_dtype")
model_dtype = torch_model_read_metadata(allegro%allegro_file_name, "model_dtype")
IF (TRIM(default_dtype) == "float32" .AND. TRIM(model_dtype) == "float32") THEN
allegro%do_allegro_sp = .TRUE.
ELSE IF (TRIM(default_dtype) == "float64" .AND. TRIM(model_dtype) == "float64") THEN
allegro%do_allegro_sp = .FALSE.
ELSE
CALL cp_abort(__LOCATION__, &
"Both default_dtype and model_dtype should be either float32 or float64. Currently, default_dtype is <"// &
TRIM(default_dtype)//"> and model_dtype is <"//TRIM(model_dtype)//">.")
END IF
allow_tf32_str = torch_model_read_metadata(allegro%allegro_file_name, "allow_tf32")
allow_tf32 = (TRIM(allow_tf32_str) == "1")
IF (TRIM(allow_tf32_str) /= "1" .AND. TRIM(allow_tf32_str) /= "0") THEN
CALL cp_abort(__LOCATION__, &
"The value for allow_tf32 <"//TRIM(allow_tf32_str)// &
"> is not supported. Check the .yaml and .pth files.")
END IF
CALL torch_allow_tf32(allow_tf32)
CALL timestop(handle)
END SUBROUTINE read_allegro_data
! **************************************************************************************************
!> \brief returns tokenized string of kinds from .pth file
!> \param element ...
!> \param delimiter ...
!> \param tokenized_array ...
!> \author Maria Bilichenko
! **************************************************************************************************
SUBROUTINE tokenize_string(element, delimiter, tokenized_array)
SUBROUTINE tokenize_string(element, tokenized_array)
CHARACTER(LEN=*), INTENT(IN) :: element
CHARACTER(LEN=1), INTENT(IN) :: delimiter
CHARACTER(LEN=100), ALLOCATABLE, DIMENSION(:), &
INTENT(OUT) :: tokenized_array
CHARACTER(LEN=100) :: temp_kinds
INTEGER :: end_pos, i, num_elements, start
LOGICAL, ALLOCATABLE, DIMENSION(:) :: delim_positions
CHARACTER(LEN=1) :: ch
CHARACTER(LEN=100) :: current
INTEGER :: i, L, n
! Find positions of delimiter within element
ALLOCATE (delim_positions(LEN(element)))
delim_positions = .FALSE.
L = LEN_TRIM(element)
DO i = 1, LEN(element)
IF (element(i:i) == delimiter) delim_positions(i) = .TRUE.
END DO
n = 0
current = ""
DO i = 1, L
ch = element(i:i)
num_elements = COUNT(delim_positions) + 1
ALLOCATE (tokenized_array(num_elements))
start = 1
DO i = 1, num_elements
IF (LEN(element) < 3 .AND. COUNT(delim_positions) == 0) THEN ! if there is 1 kind only and it has one or two
!characters (C or Cl) the end_pos will be the index of the last character (1 or 2)
end_pos = LEN(element)
ELSE ! else, the end_pos is determined by the index of the space - 1
end_pos = find_end_pos(start, delim_positions)
IF ((ch >= 'A' .AND. ch <= 'Z') .OR. (ch >= 'a' .AND. ch <= 'z')) THEN
current(LEN_TRIM(current) + 1:LEN_TRIM(current) + 1) = ch
ELSE
IF (LEN_TRIM(current) > 0) THEN
n = n + 1
current = ""
END IF
END IF
temp_kinds = element(start:end_pos)
IF (TRIM(temp_kinds) /= '') THEN
tokenized_array(i) = temp_kinds
END IF
start = end_pos + 2
END DO
DEALLOCATE (delim_positions)
IF (LEN_TRIM(current) > 0) n = n + 1
ALLOCATE (tokenized_array(n))
n = 0
current = ""
DO i = 1, L
ch = element(i:i)
IF ((ch >= 'A' .AND. ch <= 'Z') .OR. (ch >= 'a' .AND. ch <= 'z')) THEN
current(LEN_TRIM(current) + 1:LEN_TRIM(current) + 1) = ch
ELSE
IF (LEN_TRIM(current) > 0) THEN
n = n + 1
tokenized_array(n) = TRIM(current)
current = ""
END IF
END IF
END DO
IF (LEN_TRIM(current) > 0) THEN
n = n + 1
tokenized_array(n) = TRIM(current)
END IF
END SUBROUTINE tokenize_string
! **************************************************************************************************
!> \brief finds the position of the atom by the spacing
!> \param start ...
!> \param delim_positions ...
!> \return ...
!> \author Maria Bilichenko
! **************************************************************************************************
INTEGER FUNCTION find_end_pos(start, delim_positions)
INTEGER, INTENT(IN) :: start
LOGICAL, DIMENSION(:), INTENT(IN) :: delim_positions
INTEGER :: end_pos, i
end_pos = start
DO i = start, SIZE(delim_positions)
IF (delim_positions(i)) THEN
end_pos = i - 1
EXIT
END IF
END DO
find_end_pos = end_pos
END FUNCTION find_end_pos
! **************************************************************************************************
!> \brief checks if all the ATOMS from *.inp file are available in *.pth file
!> \param cp2k_inp_atom_types ...
@ -2682,17 +2571,17 @@ CONTAINS
CHARACTER(LEN=*), DIMENSION(:), INTENT(IN) :: cp2k_inp_atom_types, torch_atom_types
INTEGER :: i, j
LOGICAL :: found
LOGICAL :: found_atom
DO i = 1, SIZE(cp2k_inp_atom_types)
found = .FALSE.
found_atom = .FALSE.
DO j = 1, SIZE(torch_atom_types)
IF (TRIM(cp2k_inp_atom_types(i)) == TRIM(torch_atom_types(j))) THEN
found = .TRUE.
found_atom = .TRUE.
EXIT
END IF
END DO
IF (.NOT. found) THEN
IF (.NOT. found_atom) THEN
CALL cp_abort(__LOCATION__, &
"Atom "//TRIM(cp2k_inp_atom_types(i))// &
" is defined in the CP2K input file but is missing in the torch model file")

View file

@ -16,8 +16,8 @@
MODULE input_cp2k_mm
USE bibliography, ONLY: &
Batzner2022, Bochkarev2024, Clabaut2020, Clabaut2021, Devynck2012, Dick1958, Drautz2019, &
Foiles1986, Lysogorskiy2021, Mitchell1993, Musaelian2023, Siepmann1995, Tersoff1988, &
Tosi1964a, Tosi1964b, Wang2018, Yamada2000, Zeng2023
Foiles1986, Lysogorskiy2021, Mitchell1993, Musaelian2023, Siepmann1995, Tan2025, &
Tersoff1988, Tosi1964a, Tosi1964b, Wang2018, Yamada2000, Zeng2023
USE cp_output_handling, ONLY: cp_print_key_section_create,&
debug_print_level,&
high_print_level,&
@ -1181,10 +1181,6 @@ CONTAINS
CALL section_add_subsection(section, subsection)
CALL section_release(subsection)
CALL create_ALLEGRO_section(subsection)
CALL section_add_subsection(section, subsection)
CALL section_release(subsection)
CALL create_ACE_section(subsection)
CALL section_add_subsection(section, subsection)
CALL section_release(subsection)
@ -1428,11 +1424,12 @@ CONTAINS
CPASSERT(.NOT. ASSOCIATED(section))
CALL section_create(section, __LOCATION__, name="NEQUIP", &
description="This section specifies the input parameters for NEQUIP potential type "// &
"based on equivariant neural networks with message passing. Starting from the NequIP 0.6.0, "// &
"one can predict stress if the config.yaml file has the StressForceOutput keyword, "// &
"regardless of whether the model has been trained on the stress. "// &
"based on equivariant neural networks, and for ALLEGRO, a local large-scale variant. "// &
"Note: To enable the prediction of stress, along with energies and forces, the keyword "// &
"StressForceOutput must be included in the nequip config *.yaml file used to train the "// &
"model, regardless of whether the model has been trained on the stress. "// &
"Requires linking with libtorch library from <https://pytorch.org/cppdocs/installing.html>.", &
citations=[Batzner2022], n_keywords=1, n_subsections=0, repeats=.FALSE.)
citations=[Batzner2022, Musaelian2023, Tan2025], n_keywords=1, n_subsections=0, repeats=.FALSE.)
NULLIFY (keyword)
@ -1446,18 +1443,25 @@ CONTAINS
CALL section_add_keyword(section, keyword)
CALL keyword_release(keyword)
CALL keyword_create(keyword, __LOCATION__, name="PARM_FILE_NAME", &
variants=["PARMFILE"], &
description="Specifies the filename that contains the NEQUIP model.", &
usage="PARM_FILE_NAME {FILENAME}", default_lc_val="model.pth")
CALL keyword_create(keyword, __LOCATION__, name="MODEL_TYPE", &
variants=["MODEL"], &
description="Specifies the type of model used. Allowed values are NEQUIP or ALLEGRO.", &
usage="MODEL_TYPE {NEQUIP}", default_lc_val=" ")
CALL section_add_keyword(section, keyword)
CALL keyword_release(keyword)
CALL keyword_create(keyword, __LOCATION__, name="UNIT_COORDS", &
description="Units of coordinates in the NEQUIP model.pth file. "// &
"The units of positions, energies and forces must be self-consistent: "// &
CALL keyword_create(keyword, __LOCATION__, name="POT_FILE_NAME", &
variants=["MODEL_FILE_NAME"], &
description="Specifies the filename that contains the NEQUIP model.", &
usage="POT_FILE_NAME {FILENAME}", default_lc_val=" ")
CALL section_add_keyword(section, keyword)
CALL keyword_release(keyword)
CALL keyword_create(keyword, __LOCATION__, name="UNIT_LENGTH", &
description="Units of length in the NEQUIP model.pth file. "// &
"The units of positions, cell, energies and forces must be self-consistent: "// &
"e.g. coordinates in Angstrom, energies in eV, forces in eV/Angstrom. ", &
usage="UNIT_COORDS angstrom", default_c_val="angstrom")
usage="UNIT_LENGTH angstrom", default_c_val="angstrom")
CALL section_add_keyword(section, keyword)
CALL keyword_release(keyword)
@ -1477,88 +1481,8 @@ CONTAINS
CALL section_add_keyword(section, keyword)
CALL keyword_release(keyword)
CALL keyword_create(keyword, __LOCATION__, name="UNIT_CELL", &
description="Units of the cell vectors in the NEQUIP model.pth file. "// &
"The units of positions, energies and forces must be self-consistent: "// &
"e.g. coordinates in Angstrom, energies in eV, forces in eV/Angstrom. ", &
usage="UNIT_CELL angstrom", default_c_val="angstrom")
CALL section_add_keyword(section, keyword)
CALL keyword_release(keyword)
END SUBROUTINE create_NEQUIP_section
! **************************************************************************************************
!> \brief This section specifies the input parameters for ALLEGRO potential type
!> \param section the section to create
!> \author teo
! **************************************************************************************************
SUBROUTINE create_ALLEGRO_section(section)
TYPE(section_type), POINTER :: section
TYPE(keyword_type), POINTER :: keyword
CPASSERT(.NOT. ASSOCIATED(section))
CALL section_create(section, __LOCATION__, name="ALLEGRO", &
description="This section specifies the input parameters for ALLEGRO potential type "// &
"based on equivariant neural network potentials. Starting from the NequIP 0.6.0, "// &
"one can predict stress if the config.yaml file has the StressForceOutput keyword, "// &
"regardless of whether the model has been trained on the stress. "// &
"Requires linking with libtorch library from <https://pytorch.org/cppdocs/installing.html>.", &
citations=[Musaelian2023], n_keywords=1, n_subsections=0, repeats=.FALSE.)
NULLIFY (keyword)
CALL keyword_create(keyword, __LOCATION__, name="ATOMS", &
description="Defines the atomic kinds involved in the ALLEGRO potential. "// &
"Provide a list of each element, making sure that the mapping from the ATOMS list "// &
"to NequIP atom types is correct. This mapping should also be consistent for the "// &
"atomic coordinates as specified in the sections COORDS or TOPOLOGY.", &
usage="ATOMS {KIND 1} {KIND 2} .. {KIND N}", type_of_var=char_t, &
n_var=-1)
CALL section_add_keyword(section, keyword)
CALL keyword_release(keyword)
CALL keyword_create(keyword, __LOCATION__, name="PARM_FILE_NAME", &
variants=["PARMFILE"], &
description="Specifies the filename that contains the ALLEGRO model.", &
usage="PARM_FILE_NAME {FILENAME}", default_lc_val="model.pth")
CALL section_add_keyword(section, keyword)
CALL keyword_release(keyword)
CALL keyword_create(keyword, __LOCATION__, name="UNIT_COORDS", &
description="Units of coordinates in the ALLEGRO model.pth file. "// &
"The units of positions, energies and forces must be self-consistent: "// &
"e.g. coordinates in Angstrom, energies in eV, forces in eV/Angstrom. ", &
usage="UNIT_COORDS angstrom", default_c_val="angstrom")
CALL section_add_keyword(section, keyword)
CALL keyword_release(keyword)
CALL keyword_create(keyword, __LOCATION__, name="UNIT_ENERGY", &
description="Units of energy in the ALLEGRO model.pth file. "// &
"The units of positions, energies and forces must be self-consistent: "// &
"e.g. coordinates in Angstrom, energies in eV, forces in eV/Angstrom. ", &
usage="UNIT_ENERGY hartree", default_c_val="eV")
CALL section_add_keyword(section, keyword)
CALL keyword_release(keyword)
CALL keyword_create(keyword, __LOCATION__, name="UNIT_FORCES", &
description="Units of the forces in the ALLEGRO model.pth file. "// &
"The units of positions, energies and forces must be self-consistent: "// &
"e.g. coordinates in Angstrom, energies in eV, forces in eV/Angstrom. ", &
usage="UNIT_FORCES hartree/bohr", default_c_val="eV/Angstrom")
CALL section_add_keyword(section, keyword)
CALL keyword_release(keyword)
CALL keyword_create(keyword, __LOCATION__, name="UNIT_CELL", &
description="Units of the cell vectors in the ALLEGRO model.pth file. "// &
"The units of positions, energies and forces must be self-consistent: "// &
"e.g. coordinates in Angstrom, energies in eV, forces in eV/Angstrom. ", &
usage="UNIT_CELL angstrom", default_c_val="angstrom")
CALL section_add_keyword(section, keyword)
CALL keyword_release(keyword)
END SUBROUTINE create_ALLEGRO_section
! **************************************************************************************************
!> \brief This section specifies the input parameters for ACE potential type
!> \param section the section to create

View file

@ -1,527 +0,0 @@
!--------------------------------------------------------------------------------------------------!
! CP2K: A general program to perform molecular dynamics simulations !
! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
! !
! SPDX-License-Identifier: GPL-2.0-or-later !
!--------------------------------------------------------------------------------------------------!
! **************************************************************************************************
!> \par History
!> allegro implementation
!> \author Gabriele Tocci
! **************************************************************************************************
MODULE manybody_allegro
USE atomic_kind_types, ONLY: atomic_kind_type
USE cell_types, ONLY: cell_type
USE fist_neighbor_list_types, ONLY: fist_neighbor_type,&
neighbor_kind_pairs_type
USE fist_nonbond_env_types, ONLY: allegro_data_type,&
fist_nonbond_env_get,&
fist_nonbond_env_set,&
fist_nonbond_env_type,&
pos_type
USE kinds, ONLY: dp,&
int_8,&
sp
USE message_passing, ONLY: mp_para_env_type
USE pair_potential_types, ONLY: allegro_pot_type,&
allegro_type,&
pair_potential_pp_type,&
pair_potential_single_type
USE particle_types, ONLY: particle_type
USE torch_api, ONLY: &
torch_dict_create, torch_dict_get, torch_dict_insert, torch_dict_release, torch_dict_type, &
torch_model_forward, torch_model_freeze, torch_model_load, torch_tensor_data_ptr, &
torch_tensor_from_array, torch_tensor_release, torch_tensor_type
USE util, ONLY: sort
#include "./base/base_uses.f90"
IMPLICIT NONE
PRIVATE
PUBLIC :: setup_allegro_arrays, destroy_allegro_arrays, &
allegro_energy_store_force_virial, allegro_add_force_virial
CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'manybody_allegro'
CONTAINS
! **************************************************************************************************
!> \brief ...
!> \param nonbonded ...
!> \param potparm ...
!> \param glob_loc_list ...
!> \param glob_cell_v ...
!> \param glob_loc_list_a ...
!> \param unique_list_a ...
!> \param cell ...
!> \par History
!> Implementation of the allegro potential - [gtocci] 2023
!> \author Gabriele Tocci - University of Zurich
! **************************************************************************************************
SUBROUTINE setup_allegro_arrays(nonbonded, potparm, glob_loc_list, glob_cell_v, glob_loc_list_a, &
unique_list_a, cell)
TYPE(fist_neighbor_type), POINTER :: nonbonded
TYPE(pair_potential_pp_type), POINTER :: potparm
INTEGER, DIMENSION(:, :), POINTER :: glob_loc_list
REAL(KIND=dp), DIMENSION(:, :), POINTER :: glob_cell_v
INTEGER, DIMENSION(:), POINTER :: glob_loc_list_a, unique_list_a
TYPE(cell_type), POINTER :: cell
CHARACTER(LEN=*), PARAMETER :: routineN = 'setup_allegro_arrays'
INTEGER :: handle, i, iend, igrp, ikind, ilist, &
ipair, istart, jkind, nkinds, nlocal, &
npairs, npairs_tot
INTEGER, ALLOCATABLE, DIMENSION(:) :: temp_unique_list_a, work_list, work_list2
INTEGER, DIMENSION(:, :), POINTER :: list
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: rwork_list
REAL(KIND=dp), DIMENSION(3) :: cell_v, cvi
TYPE(neighbor_kind_pairs_type), POINTER :: neighbor_kind_pair
TYPE(pair_potential_single_type), POINTER :: pot
CPASSERT(.NOT. ASSOCIATED(glob_loc_list))
CPASSERT(.NOT. ASSOCIATED(glob_loc_list_a))
CPASSERT(.NOT. ASSOCIATED(unique_list_a))
CPASSERT(.NOT. ASSOCIATED(glob_cell_v))
CALL timeset(routineN, handle)
npairs_tot = 0
nkinds = SIZE(potparm%pot, 1)
DO ilist = 1, nonbonded%nlists
neighbor_kind_pair => nonbonded%neighbor_kind_pairs(ilist)
npairs = neighbor_kind_pair%npairs
IF (npairs == 0) CYCLE
Kind_Group_Loop1: DO igrp = 1, neighbor_kind_pair%ngrp_kind
istart = neighbor_kind_pair%grp_kind_start(igrp)
iend = neighbor_kind_pair%grp_kind_end(igrp)
ikind = neighbor_kind_pair%ij_kind(1, igrp)
jkind = neighbor_kind_pair%ij_kind(2, igrp)
pot => potparm%pot(ikind, jkind)%pot
npairs = iend - istart + 1
IF (pot%no_mb) CYCLE Kind_Group_Loop1
DO i = 1, SIZE(pot%type)
IF (pot%type(i) == allegro_type) npairs_tot = npairs_tot + npairs
END DO
END DO Kind_Group_Loop1
END DO
ALLOCATE (work_list(npairs_tot))
ALLOCATE (work_list2(npairs_tot))
ALLOCATE (glob_loc_list(2, npairs_tot))
ALLOCATE (glob_cell_v(3, npairs_tot))
! Fill arrays with data
npairs_tot = 0
DO ilist = 1, nonbonded%nlists
neighbor_kind_pair => nonbonded%neighbor_kind_pairs(ilist)
npairs = neighbor_kind_pair%npairs
IF (npairs == 0) CYCLE
Kind_Group_Loop2: DO igrp = 1, neighbor_kind_pair%ngrp_kind
istart = neighbor_kind_pair%grp_kind_start(igrp)
iend = neighbor_kind_pair%grp_kind_end(igrp)
ikind = neighbor_kind_pair%ij_kind(1, igrp)
jkind = neighbor_kind_pair%ij_kind(2, igrp)
list => neighbor_kind_pair%list
cvi = neighbor_kind_pair%cell_vector
pot => potparm%pot(ikind, jkind)%pot
npairs = iend - istart + 1
IF (pot%no_mb) CYCLE Kind_Group_Loop2
cell_v = MATMUL(cell%hmat, cvi)
DO i = 1, SIZE(pot%type)
! ALLEGRO
IF (pot%type(i) == allegro_type) THEN
DO ipair = 1, npairs
glob_loc_list(:, npairs_tot + ipair) = list(:, istart - 1 + ipair)
glob_cell_v(1:3, npairs_tot + ipair) = cell_v(1:3)
END DO
npairs_tot = npairs_tot + npairs
END IF
END DO
END DO Kind_Group_Loop2
END DO
! Order the arrays w.r.t. the first index of glob_loc_list
CALL sort(glob_loc_list(1, :), npairs_tot, work_list)
DO ipair = 1, npairs_tot
work_list2(ipair) = glob_loc_list(2, work_list(ipair))
END DO
glob_loc_list(2, :) = work_list2
DEALLOCATE (work_list2)
ALLOCATE (rwork_list(3, npairs_tot))
DO ipair = 1, npairs_tot
rwork_list(:, ipair) = glob_cell_v(:, work_list(ipair))
END DO
glob_cell_v = rwork_list
DEALLOCATE (rwork_list)
DEALLOCATE (work_list)
ALLOCATE (glob_loc_list_a(npairs_tot))
glob_loc_list_a = glob_loc_list(1, :)
ALLOCATE (temp_unique_list_a(npairs_tot))
nlocal = 1
temp_unique_list_a(1) = glob_loc_list_a(1)
DO ipair = 2, npairs_tot
IF (glob_loc_list_a(ipair - 1) /= glob_loc_list_a(ipair)) THEN
nlocal = nlocal + 1
temp_unique_list_a(nlocal) = glob_loc_list_a(ipair)
END IF
END DO
ALLOCATE (unique_list_a(nlocal))
unique_list_a(:) = temp_unique_list_a(:nlocal)
DEALLOCATE (temp_unique_list_a)
CALL timestop(handle)
END SUBROUTINE setup_allegro_arrays
! **************************************************************************************************
!> \brief ...
!> \param glob_loc_list ...
!> \param glob_cell_v ...
!> \param glob_loc_list_a ...
!> \param unique_list_a ...
!> \par History
!> Implementation of the allegro potential - [gtocci] 2023
!> \author Gabriele Tocci - University of Zurich
! **************************************************************************************************
SUBROUTINE destroy_allegro_arrays(glob_loc_list, glob_cell_v, glob_loc_list_a, unique_list_a)
INTEGER, DIMENSION(:, :), POINTER :: glob_loc_list
REAL(KIND=dp), DIMENSION(:, :), POINTER :: glob_cell_v
INTEGER, DIMENSION(:), POINTER :: glob_loc_list_a, unique_list_a
IF (ASSOCIATED(glob_loc_list)) THEN
DEALLOCATE (glob_loc_list)
END IF
IF (ASSOCIATED(glob_loc_list_a)) THEN
DEALLOCATE (glob_loc_list_a)
END IF
IF (ASSOCIATED(glob_cell_v)) THEN
DEALLOCATE (glob_cell_v)
END IF
IF (ASSOCIATED(unique_list_a)) THEN
DEALLOCATE (unique_list_a)
END IF
END SUBROUTINE destroy_allegro_arrays
! **************************************************************************************************
!> \brief ...
!> \param nonbonded ...
!> \param particle_set ...
!> \param cell ...
!> \param atomic_kind_set ...
!> \param potparm ...
!> \param allegro ...
!> \param glob_loc_list_a ...
!> \param r_last_update_pbc ...
!> \param pot_allegro ...
!> \param fist_nonbond_env ...
!> \param unique_list_a ...
!> \param para_env ...
!> \param use_virial ...
!> \par History
!> Implementation of the allegro potential - [gtocci] 2023
!> Index mapping of atoms from .xyz to Allegro config.yaml file - [mbilichenko] 2024
!> \author Gabriele Tocci - University of Zurich
! **************************************************************************************************
SUBROUTINE allegro_energy_store_force_virial(nonbonded, particle_set, cell, atomic_kind_set, &
potparm, allegro, glob_loc_list_a, r_last_update_pbc, &
pot_allegro, fist_nonbond_env, unique_list_a, para_env, use_virial)
TYPE(fist_neighbor_type), POINTER :: nonbonded
TYPE(particle_type), POINTER :: particle_set(:)
TYPE(cell_type), POINTER :: cell
TYPE(atomic_kind_type), POINTER :: atomic_kind_set(:)
TYPE(pair_potential_pp_type), POINTER :: potparm
TYPE(allegro_pot_type), POINTER :: allegro
INTEGER, DIMENSION(:), POINTER :: glob_loc_list_a
TYPE(pos_type), DIMENSION(:), POINTER :: r_last_update_pbc
REAL(kind=dp) :: pot_allegro
TYPE(fist_nonbond_env_type), POINTER :: fist_nonbond_env
INTEGER, DIMENSION(:), POINTER :: unique_list_a
TYPE(mp_para_env_type), POINTER :: para_env
LOGICAL, INTENT(IN) :: use_virial
CHARACTER(LEN=*), PARAMETER :: routineN = 'allegro_energy_store_force_virial'
INTEGER :: atom_a, atom_b, atom_idx, handle, i, iat, iat_use, iend, ifirst, igrp, ikind, &
ilast, ilist, ipair, istart, iunique, jkind, junique, mpair, n_atoms, n_atoms_use, &
nedges, nloc_size, npairs, nunique
INTEGER(kind=int_8), ALLOCATABLE :: atom_types(:), temp_atom_types(:)
INTEGER(kind=int_8), ALLOCATABLE, DIMENSION(:, :) :: edge_index, t_edge_index, temp_edge_index
INTEGER, ALLOCATABLE, DIMENSION(:) :: work_list
INTEGER, DIMENSION(:, :), POINTER :: list, sort_list
LOGICAL, ALLOCATABLE :: use_atom(:)
REAL(kind=dp) :: drij, rab2_max, rij(3)
REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: edge_cell_shifts, lattice, &
new_edge_cell_shifts, pos
REAL(kind=dp), DIMENSION(3) :: cell_v, cvi
REAL(kind=dp), DIMENSION(:, :), POINTER :: atomic_energy, forces, virial
REAL(kind=dp), DIMENSION(:, :, :), POINTER :: virial3d
REAL(kind=sp), ALLOCATABLE, DIMENSION(:, :) :: lattice_sp, new_edge_cell_shifts_sp, &
pos_sp
REAL(kind=sp), DIMENSION(:, :), POINTER :: atomic_energy_sp, forces_sp
TYPE(allegro_data_type), POINTER :: allegro_data
TYPE(neighbor_kind_pairs_type), POINTER :: neighbor_kind_pair
TYPE(pair_potential_single_type), POINTER :: pot
TYPE(torch_dict_type) :: inputs, outputs
TYPE(torch_tensor_type) :: atom_types_tensor, atomic_energy_tensor, forces_tensor, &
lattice_tensor, new_edge_cell_shifts_tensor, pos_tensor, t_edge_index_tensor, &
virial_tensor
CALL timeset(routineN, handle)
NULLIFY (atomic_energy, forces, atomic_energy_sp, forces_sp, virial3d, virial)
n_atoms = SIZE(particle_set)
ALLOCATE (use_atom(n_atoms))
use_atom = .FALSE.
DO ikind = 1, SIZE(atomic_kind_set)
DO jkind = 1, SIZE(atomic_kind_set)
pot => potparm%pot(ikind, jkind)%pot
DO i = 1, SIZE(pot%type)
IF (pot%type(i) /= allegro_type) CYCLE
DO iat = 1, n_atoms
IF (particle_set(iat)%atomic_kind%kind_number == ikind .OR. &
particle_set(iat)%atomic_kind%kind_number == jkind) use_atom(iat) = .TRUE.
END DO ! iat
END DO ! i
END DO ! jkind
END DO ! ikind
n_atoms_use = COUNT(use_atom)
! get allegro_data to save force, virial info and to load model
CALL fist_nonbond_env_get(fist_nonbond_env, allegro_data=allegro_data)
IF (.NOT. ASSOCIATED(allegro_data)) THEN
ALLOCATE (allegro_data)
CALL fist_nonbond_env_set(fist_nonbond_env, allegro_data=allegro_data)
NULLIFY (allegro_data%use_indices, allegro_data%force)
CALL torch_model_load(allegro_data%model, pot%set(1)%allegro%allegro_file_name)
CALL torch_model_freeze(allegro_data%model)
END IF
IF (ASSOCIATED(allegro_data%force)) THEN
IF (SIZE(allegro_data%force, 2) /= n_atoms_use) THEN
DEALLOCATE (allegro_data%force, allegro_data%use_indices)
END IF
END IF
IF (.NOT. ASSOCIATED(allegro_data%force)) THEN
ALLOCATE (allegro_data%force(3, n_atoms_use))
ALLOCATE (allegro_data%use_indices(n_atoms_use))
END IF
iat_use = 0
DO iat = 1, n_atoms_use
IF (use_atom(iat)) THEN
iat_use = iat_use + 1
allegro_data%use_indices(iat_use) = iat
END IF
END DO
nedges = 0
ALLOCATE (edge_index(2, SIZE(glob_loc_list_a)))
ALLOCATE (edge_cell_shifts(3, SIZE(glob_loc_list_a)))
ALLOCATE (temp_atom_types(SIZE(glob_loc_list_a)))
DO ilist = 1, nonbonded%nlists
neighbor_kind_pair => nonbonded%neighbor_kind_pairs(ilist)
npairs = neighbor_kind_pair%npairs
IF (npairs == 0) CYCLE
Kind_Group_Loop_Allegro: DO igrp = 1, neighbor_kind_pair%ngrp_kind
istart = neighbor_kind_pair%grp_kind_start(igrp)
iend = neighbor_kind_pair%grp_kind_end(igrp)
ikind = neighbor_kind_pair%ij_kind(1, igrp)
jkind = neighbor_kind_pair%ij_kind(2, igrp)
list => neighbor_kind_pair%list
cvi = neighbor_kind_pair%cell_vector
pot => potparm%pot(ikind, jkind)%pot
DO i = 1, SIZE(pot%type)
IF (pot%type(i) /= allegro_type) CYCLE
rab2_max = pot%set(i)%allegro%rcutsq
cell_v = MATMUL(cell%hmat, cvi)
pot => potparm%pot(ikind, jkind)%pot
allegro => pot%set(i)%allegro
npairs = iend - istart + 1
IF (npairs /= 0) THEN
ALLOCATE (sort_list(2, npairs), work_list(npairs))
sort_list = list(:, istart:iend)
! Sort the list of neighbors, this increases the efficiency for single
! potential contributions
CALL sort(sort_list(1, :), npairs, work_list)
DO ipair = 1, npairs
work_list(ipair) = sort_list(2, work_list(ipair))
END DO
sort_list(2, :) = work_list
! find number of unique elements of array index 1
nunique = 1
DO ipair = 1, npairs - 1
IF (sort_list(1, ipair + 1) /= sort_list(1, ipair)) nunique = nunique + 1
END DO
ipair = 1
junique = sort_list(1, ipair)
ifirst = 1
DO iunique = 1, nunique
atom_a = junique
IF (glob_loc_list_a(ifirst) > atom_a) CYCLE
DO mpair = ifirst, SIZE(glob_loc_list_a)
IF (glob_loc_list_a(mpair) == atom_a) EXIT
END DO
ifirst = mpair
DO mpair = ifirst, SIZE(glob_loc_list_a)
IF (glob_loc_list_a(mpair) /= atom_a) EXIT
END DO
ilast = mpair - 1
nloc_size = 0
IF (ifirst /= 0) nloc_size = ilast - ifirst + 1
DO WHILE (ipair <= npairs)
IF (sort_list(1, ipair) /= junique) EXIT
atom_b = sort_list(2, ipair)
rij(:) = r_last_update_pbc(atom_b)%r(:) - r_last_update_pbc(atom_a)%r(:) + cell_v
drij = DOT_PRODUCT(rij, rij)
ipair = ipair + 1
IF (drij <= rab2_max) THEN
nedges = nedges + 1
edge_index(:, nedges) = [atom_a - 1, atom_b - 1]
edge_cell_shifts(:, nedges) = cvi
END IF
END DO
ifirst = ilast + 1
IF (ipair <= npairs) junique = sort_list(1, ipair)
END DO
DEALLOCATE (sort_list, work_list)
END IF
END DO
END DO Kind_Group_Loop_Allegro
END DO
allegro => pot%set(1)%allegro
ALLOCATE (temp_edge_index(2, nedges))
temp_edge_index(:, :) = edge_index(:, :nedges)
ALLOCATE (new_edge_cell_shifts(3, nedges))
new_edge_cell_shifts(:, :) = edge_cell_shifts(:, :nedges)
DEALLOCATE (edge_cell_shifts)
ALLOCATE (t_edge_index(nedges, 2))
t_edge_index(:, :) = TRANSPOSE(temp_edge_index)
DEALLOCATE (temp_edge_index, edge_index)
ALLOCATE (lattice(3, 3), lattice_sp(3, 3))
lattice(:, :) = cell%hmat/pot%set(1)%allegro%unit_cell_val
lattice_sp(:, :) = REAL(lattice, kind=sp)
iat_use = 0
ALLOCATE (pos(3, n_atoms_use), atom_types(n_atoms_use))
DO iat = 1, n_atoms_use
IF (.NOT. use_atom(iat)) CYCLE
iat_use = iat_use + 1
! Find index of the element based on its position in config.yaml file to have correct mapping
DO i = 1, SIZE(allegro%type_names_torch)
IF (particle_set(iat)%atomic_kind%element_symbol == allegro%type_names_torch(i)) THEN
atom_idx = i - 1
END IF
END DO
atom_types(iat_use) = atom_idx
pos(:, iat) = r_last_update_pbc(iat)%r(:)/allegro%unit_coords_val
END DO
CALL torch_dict_create(inputs)
IF (allegro%do_allegro_sp) THEN
ALLOCATE (new_edge_cell_shifts_sp(3, nedges), pos_sp(3, n_atoms_use))
new_edge_cell_shifts_sp(:, :) = REAL(new_edge_cell_shifts(:, :), kind=sp)
pos_sp(:, :) = REAL(pos(:, :), kind=sp)
DEALLOCATE (pos, new_edge_cell_shifts)
CALL torch_tensor_from_array(pos_tensor, pos_sp)
CALL torch_tensor_from_array(new_edge_cell_shifts_tensor, new_edge_cell_shifts_sp)
CALL torch_tensor_from_array(lattice_tensor, lattice_sp)
ELSE
CALL torch_tensor_from_array(pos_tensor, pos)
CALL torch_tensor_from_array(new_edge_cell_shifts_tensor, new_edge_cell_shifts)
CALL torch_tensor_from_array(lattice_tensor, lattice)
END IF
CALL torch_dict_insert(inputs, "pos", pos_tensor)
CALL torch_dict_insert(inputs, "edge_cell_shift", new_edge_cell_shifts_tensor)
CALL torch_dict_insert(inputs, "cell", lattice_tensor)
CALL torch_tensor_release(pos_tensor)
CALL torch_tensor_release(new_edge_cell_shifts_tensor)
CALL torch_tensor_release(lattice_tensor)
CALL torch_tensor_from_array(t_edge_index_tensor, t_edge_index)
CALL torch_dict_insert(inputs, "edge_index", t_edge_index_tensor)
CALL torch_tensor_release(t_edge_index_tensor)
CALL torch_tensor_from_array(atom_types_tensor, atom_types)
CALL torch_dict_insert(inputs, "atom_types", atom_types_tensor)
CALL torch_tensor_release(atom_types_tensor)
CALL torch_dict_create(outputs)
CALL torch_model_forward(allegro_data%model, inputs, outputs)
pot_allegro = 0.0_dp
CALL torch_dict_get(outputs, "atomic_energy", atomic_energy_tensor)
CALL torch_dict_get(outputs, "forces", forces_tensor)
IF (allegro%do_allegro_sp) THEN
CALL torch_tensor_data_ptr(atomic_energy_tensor, atomic_energy_sp)
CALL torch_tensor_data_ptr(forces_tensor, forces_sp)
allegro_data%force(:, :) = REAL(forces_sp(:, :), kind=dp)*allegro%unit_forces_val
DO iat_use = 1, SIZE(unique_list_a)
i = unique_list_a(iat_use)
pot_allegro = pot_allegro + REAL(atomic_energy_sp(1, i), kind=dp)*allegro%unit_energy_val
END DO
DEALLOCATE (new_edge_cell_shifts_sp, pos_sp)
ELSE
CALL torch_tensor_data_ptr(atomic_energy_tensor, atomic_energy)
CALL torch_tensor_data_ptr(forces_tensor, forces)
allegro_data%force(:, :) = forces(:, :)*allegro%unit_forces_val
DO iat_use = 1, SIZE(unique_list_a)
i = unique_list_a(iat_use)
pot_allegro = pot_allegro + atomic_energy(1, i)*allegro%unit_energy_val
END DO
DEALLOCATE (pos, new_edge_cell_shifts)
END IF
CALL torch_tensor_release(atomic_energy_tensor)
CALL torch_tensor_release(forces_tensor)
IF (use_virial) THEN
CALL torch_dict_get(outputs, "virial", virial_tensor)
CALL torch_tensor_data_ptr(virial_tensor, virial3d)
allegro_data%virial(:, :) = RESHAPE(virial3d, [3, 3])*allegro%unit_energy_val
CALL torch_tensor_release(virial_tensor)
END IF
CALL torch_dict_release(inputs)
CALL torch_dict_release(outputs)
DEALLOCATE (t_edge_index, atom_types)
IF (use_virial) allegro_data%virial(:, :) = allegro_data%virial/REAL(para_env%num_pe, dp)
CALL timestop(handle)
END SUBROUTINE allegro_energy_store_force_virial
! **************************************************************************************************
!> \brief ...
!> \param fist_nonbond_env ...
!> \param f_nonbond ...
!> \param pv_nonbond ...
!> \param use_virial ...
! **************************************************************************************************
SUBROUTINE allegro_add_force_virial(fist_nonbond_env, f_nonbond, pv_nonbond, use_virial)
TYPE(fist_nonbond_env_type), POINTER :: fist_nonbond_env
REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT) :: f_nonbond, pv_nonbond
LOGICAL, INTENT(IN) :: use_virial
INTEGER :: iat, iat_use
TYPE(allegro_data_type), POINTER :: allegro_data
CALL fist_nonbond_env_get(fist_nonbond_env, allegro_data=allegro_data)
IF (use_virial) THEN
pv_nonbond = pv_nonbond + allegro_data%virial
END IF
DO iat_use = 1, SIZE(allegro_data%use_indices)
iat = allegro_data%use_indices(iat_use)
CPASSERT(iat >= 1 .AND. iat <= SIZE(f_nonbond, 2))
f_nonbond(1:3, iat) = f_nonbond(1:3, iat) + allegro_data%force(1:3, iat_use)
END DO
END SUBROUTINE allegro_add_force_virial
END MODULE manybody_allegro

File diff suppressed because it is too large Load diff

View file

@ -28,10 +28,6 @@ MODULE manybody_potential
USE kinds, ONLY: dp
USE manybody_ace, ONLY: ace_add_force_virial,&
ace_energy_store_force_virial
USE manybody_allegro, ONLY: allegro_add_force_virial,&
allegro_energy_store_force_virial,&
destroy_allegro_arrays,&
setup_allegro_arrays
USE manybody_deepmd, ONLY: deepmd_add_force_virial,&
deepmd_energy_store_force_virial
USE manybody_eam, ONLY: get_force_eam
@ -43,10 +39,8 @@ MODULE manybody_potential
gal21_energy,&
gal21_forces,&
setup_gal21_arrays
USE manybody_nequip, ONLY: destroy_nequip_arrays,&
nequip_add_force_virial,&
nequip_energy_store_force_virial,&
setup_nequip_arrays
USE manybody_nequip, ONLY: nequip_add_force_virial,&
nequip_energy_store_force_virial
USE manybody_siepmann, ONLY: destroy_siepmann_arrays,&
print_nr_ions_siepmann,&
setup_siepmann_arrays,&
@ -59,10 +53,9 @@ MODULE manybody_potential
tersoff_forces
USE message_passing, ONLY: mp_para_env_type
USE pair_potential_types, ONLY: &
ace_type, allegro_pot_type, allegro_type, deepmd_type, ea_type, eam_pot_type, &
gal21_pot_type, gal21_type, gal_pot_type, gal_type, nequip_pot_type, nequip_type, &
pair_potential_pp_type, pair_potential_single_type, siepmann_pot_type, siepmann_type, &
tersoff_pot_type, tersoff_type
ace_type, allegro_type, deepmd_type, ea_type, eam_pot_type, gal21_pot_type, gal21_type, &
gal_pot_type, gal_type, nequip_type, pair_potential_pp_type, pair_potential_single_type, &
siepmann_pot_type, siepmann_type, tersoff_pot_type, tersoff_type
USE particle_types, ONLY: particle_type
USE util, ONLY: sort
#include "./base/base_uses.f90"
@ -109,7 +102,7 @@ CONTAINS
INTEGER :: atom_a, atom_b, handle, i, iend, ifirst, igrp, ikind, ilast, ilist, indexa, &
ipair, iparticle, iparticle_local, istart, iunique, jkind, junique, mpair, nkinds, &
nloc_size, npairs, nparticle, nparticle_local, nr_h3O, nr_o, nr_oh, nunique
INTEGER, DIMENSION(:), POINTER :: glob_loc_list_a, unique_list_a, work_list
INTEGER, DIMENSION(:), POINTER :: glob_loc_list_a, work_list
INTEGER, DIMENSION(:, :), POINTER :: glob_loc_list, list, sort_list
LOGICAL :: any_ace, any_allegro, any_deepmd, &
any_gal, any_gal21, any_nequip, &
@ -120,14 +113,12 @@ CONTAINS
REAL(KIND=dp), DIMENSION(3) :: cell_v, cvi
REAL(KIND=dp), DIMENSION(:, :), POINTER :: glob_cell_v
REAL(KIND=dp), POINTER :: fembed(:)
TYPE(allegro_pot_type), POINTER :: allegro
TYPE(eam_pot_type), POINTER :: eam
TYPE(eam_type), DIMENSION(:), POINTER :: eam_data
TYPE(fist_neighbor_type), POINTER :: nonbonded
TYPE(gal21_pot_type), POINTER :: gal21
TYPE(gal_pot_type), POINTER :: gal
TYPE(neighbor_kind_pairs_type), POINTER :: neighbor_kind_pair
TYPE(nequip_pot_type), POINTER :: nequip
TYPE(pair_potential_pp_type), POINTER :: potparm
TYPE(pair_potential_single_type), POINTER :: pot
TYPE(pos_type), DIMENSION(:), POINTER :: r_last_update_pbc
@ -139,8 +130,8 @@ CONTAINS
any_siepmann = .FALSE.
any_gal = .FALSE.
any_gal21 = .FALSE.
any_nequip = .FALSE.
any_allegro = .FALSE.
any_nequip = .FALSE.
any_ace = .FALSE.
any_deepmd = .FALSE.
CALL timeset(routineN, handle)
@ -186,8 +177,8 @@ CONTAINS
pot => potparm%pot(ikind, jkind)%pot
any_tersoff = any_tersoff .OR. ANY(pot%type == tersoff_type)
any_nequip = any_nequip .OR. ANY(pot%type == nequip_type)
any_allegro = any_allegro .OR. ANY(pot%type == allegro_type)
any_ace = any_ace .OR. ANY(pot%type == ace_type)
any_allegro = any_allegro .OR. ANY(pot%type == allegro_type)
any_deepmd = any_deepmd .OR. ANY(pot%type == deepmd_type)
any_siepmann = any_siepmann .OR. ANY(pot%type == siepmann_type)
any_gal = any_gal .OR. ANY(pot%type == gal_type)
@ -198,23 +189,20 @@ CONTAINS
! NEQUIP
IF (any_nequip) THEN
NULLIFY (glob_loc_list, glob_cell_v, glob_loc_list_a)
CALL setup_nequip_arrays(nonbonded, potparm, glob_loc_list, glob_cell_v, glob_loc_list_a, cell)
CALL nequip_energy_store_force_virial(nonbonded, particle_set, cell, atomic_kind_set, potparm, &
nequip, glob_loc_list_a, r_last_update_pbc, pot_nequip, &
fist_nonbond_env, para_env, use_virial)
CALL nequip_energy_store_force_virial(nonbonded, particle_set, local_particles, cell, &
atomic_kind_set, potparm, r_last_update_pbc, &
pot_nequip, fist_nonbond_env, &
para_env, use_virial, nequip_type)
pot_manybody = pot_manybody + pot_nequip
CALL destroy_nequip_arrays(glob_loc_list, glob_cell_v, glob_loc_list_a)
END IF
! ALLEGRO
IF (any_allegro) THEN
NULLIFY (glob_loc_list, glob_cell_v, glob_loc_list_a, unique_list_a)
CALL setup_allegro_arrays(nonbonded, potparm, glob_loc_list, glob_cell_v, glob_loc_list_a, &
unique_list_a, cell)
CALL allegro_energy_store_force_virial(nonbonded, particle_set, cell, atomic_kind_set, potparm, &
allegro, glob_loc_list_a, r_last_update_pbc, pot_allegro, &
fist_nonbond_env, unique_list_a, para_env, use_virial)
NULLIFY (glob_loc_list, glob_cell_v, glob_loc_list_a)
CALL nequip_energy_store_force_virial(nonbonded, particle_set, local_particles, cell, &
atomic_kind_set, potparm, r_last_update_pbc, &
pot_allegro, fist_nonbond_env, &
para_env, use_virial, allegro_type)
pot_manybody = pot_manybody + pot_allegro
CALL destroy_allegro_arrays(glob_loc_list, glob_cell_v, glob_loc_list_a, unique_list_a)
END IF
! ACE
IF (any_ace) THEN
@ -609,8 +597,8 @@ CONTAINS
TYPE(tersoff_pot_type), POINTER :: tersoff
any_tersoff = .FALSE.
any_nequip = .FALSE.
any_allegro = .FALSE.
any_nequip = .FALSE.
any_siepmann = .FALSE.
any_ace = .FALSE.
any_deepmd = .FALSE.
@ -663,6 +651,26 @@ CONTAINS
IF (any_deepmd) &
CALL deepmd_add_force_virial(fist_nonbond_env, f_nonbond, pv_nonbond, use_virial)
! NEQUIP
DO ikind = 1, nkinds
DO jkind = ikind, nkinds
any_nequip = any_nequip .OR. ANY(potparm%pot(ikind, jkind)%pot%type == nequip_type)
END DO
END DO
IF (any_nequip) THEN
CALL nequip_add_force_virial(fist_nonbond_env, f_nonbond, pv_nonbond, use_virial)
END IF
! ALLEGRO
DO ikind = 1, nkinds
DO jkind = ikind, nkinds
any_allegro = any_allegro .OR. ANY(potparm%pot(ikind, jkind)%pot%type == allegro_type)
END DO
END DO
IF (any_allegro) THEN
CALL nequip_add_force_virial(fist_nonbond_env, f_nonbond, pv_nonbond, use_virial)
END IF
! starting the force loop
DO ilist = 1, nonbonded%nlists
neighbor_kind_pair => nonbonded%neighbor_kind_pairs(ilist)
@ -1054,16 +1062,6 @@ CONTAINS
CALL destroy_gal_arrays(glob_loc_list, glob_cell_v, glob_loc_list_a)
END IF
! NEQUIP
IF (any_nequip) THEN
CALL nequip_add_force_virial(fist_nonbond_env, f_nonbond, pv_nonbond, use_virial)
END IF
! ALLEGRO
IF (any_allegro) THEN
CALL allegro_add_force_virial(fist_nonbond_env, f_nonbond, pv_nonbond, use_virial)
END IF
IF (use_virial) THEN
pv_nonbond(1, 1) = pv_nonbond(1, 1) + ptens11
pv_nonbond(1, 2) = pv_nonbond(1, 2) + ptens12

View file

@ -188,7 +188,7 @@ CONTAINS
DO k = 1, SIZE(pot%type)
SELECT CASE (pot%type(k))
CASE (lj_type, lj_charmm_type, wl_type, gw_type, ft_type, ftd_type, ip_type, &
b4_type, bm_type, gp_type, ea_type, nequip_type, allegro_type, tab_type, deepmd_type, ace_type)
b4_type, bm_type, gp_type, ea_type, allegro_type, nequip_type, tab_type, deepmd_type, ace_type)
pot%no_pp = .FALSE.
CASE (tersoff_type)
pot%no_mb = .FALSE.
@ -688,12 +688,9 @@ CONTAINS
pot_par(nk, 2) = potparm%pot(i, j)%pot%set(1)%eam%drhoar
pot_par(nk, 3) = potparm%pot(i, j)%pot%set(1)%eam%acutal
pot_par(nk, 4) = potparm%pot(i, j)%pot%set(1)%eam%npoints
CASE (nequip_type)
CASE (nequip_type, allegro_type)
pot_par(nk, 1) = str2id( &
TRIM(potparm%pot(i, j)%pot%set(1)%nequip%nequip_file_name))
CASE (allegro_type)
pot_par(nk, 1) = str2id( &
TRIM(potparm%pot(i, j)%pot%set(1)%allegro%allegro_file_name))
TRIM(potparm%pot(i, j)%pot%set(1)%nequip%pot_file_name))
CASE (ace_type)
pot_par(nk, 1) = str2id( &
TRIM(potparm%pot(i, j)%pot%set(1)%ace%ace_file_name))

View file

@ -109,7 +109,6 @@ MODULE pair_potential_types
ipbv_pot_type, &
eam_pot_type, &
nequip_pot_type, &
allegro_pot_type, &
deepmd_pot_type, &
ace_pot_type, &
tersoff_pot_type, &
@ -191,30 +190,17 @@ MODULE pair_potential_types
! **************************************************************************************************
TYPE nequip_pot_type
CHARACTER(LEN=default_path_length) :: nequip_file_name = 'NULL', nequip_version = 'NULL', &
unit_coords = 'NULL', unit_forces = 'NULL', &
unit_energy = 'NULL', unit_cell = 'NULL'
CHARACTER(LEN=default_path_length) :: pot_file_name = 'NULL', &
unit_length = 'NULL', unit_forces = 'NULL', &
unit_energy = 'NULL'
CHARACTER(LEN=100), DIMENSION(:), ALLOCATABLE :: type_names_torch
REAL(KIND=dp) :: rcutsq = 0.0_dp, unit_coords_val = 1.0_dp, &
unit_forces_val = 1.0_dp, unit_energy_val = 1.0_dp, &
unit_cell_val = 1.0_dp
LOGICAL :: do_nequip_sp = .FALSE.
REAL(KIND=dp), DIMENSION(:, :), ALLOCATABLE :: cutoff_matrix
INTEGER :: num_types = 0
REAL(KIND=dp) :: rcutsq = 0.0_dp, unit_length_val = 1.0_dp, &
unit_forces_val = 1.0_dp, unit_energy_val = 1.0_dp
LOGICAL :: mixed_precision = .FALSE.
END TYPE nequip_pot_type
! **************************************************************************************************
TYPE allegro_pot_type
CHARACTER(LEN=default_path_length) :: allegro_file_name = 'NULL', unit_cell = 'NULL', &
nequip_version = 'NULL', unit_coords = 'NULL', &
unit_forces = 'NULL', unit_energy = 'NULL'
CHARACTER(LEN=100), DIMENSION(:), ALLOCATABLE :: type_names_torch
REAL(KIND=dp) :: rcutsq = 0.0_dp, unit_coords_val = 1.0_dp, &
unit_forces_val = 1.0_dp, unit_cell_val = 1.0_dp, &
unit_energy_val = 1.0_dp
LOGICAL :: do_allegro_sp = .FALSE.
END TYPE allegro_pot_type
! **************************************************************************************************
TYPE buck4ran_pot_type
REAL(KIND=dp) :: a = 0.0_dp
@ -367,7 +353,6 @@ MODULE pair_potential_types
TYPE(goodwin_pot_type), POINTER :: goodwin => NULL()
TYPE(eam_pot_type), POINTER :: eam => NULL()
TYPE(nequip_pot_type), POINTER :: nequip => NULL()
TYPE(allegro_pot_type), POINTER :: allegro => NULL()
TYPE(ace_pot_type), POINTER :: ace => NULL()
TYPE(deepmd_pot_type), POINTER :: deepmd => NULL()
TYPE(buck4ran_pot_type), POINTER :: buck4r => NULL()
@ -483,18 +468,11 @@ CONTAINS
CASE (deepmd_type)
IF ((pot1%set(i)%deepmd%deepmd_file_name == pot2%set(i)%deepmd%deepmd_file_name) .AND. &
(pot1%set(i)%deepmd%atom_deepmd_type == pot2%set(i)%deepmd%atom_deepmd_type)) mycompare = .TRUE.
CASE (nequip_type)
IF ((pot1%set(i)%nequip%nequip_file_name == pot2%set(i)%nequip%nequip_file_name) .AND. &
(pot1%set(i)%nequip%unit_coords == pot2%set(i)%nequip%unit_coords) .AND. &
CASE (nequip_type, allegro_type)
IF ((pot1%set(i)%nequip%pot_file_name == pot2%set(i)%nequip%pot_file_name) .AND. &
(pot1%set(i)%nequip%unit_length == pot2%set(i)%nequip%unit_length) .AND. &
(pot1%set(i)%nequip%unit_forces == pot2%set(i)%nequip%unit_forces) .AND. &
(pot1%set(i)%nequip%unit_energy == pot2%set(i)%nequip%unit_energy) .AND. &
(pot1%set(i)%nequip%unit_cell == pot2%set(i)%nequip%unit_cell)) mycompare = .TRUE.
CASE (allegro_type)
IF ((pot1%set(i)%allegro%allegro_file_name == pot2%set(i)%allegro%allegro_file_name) .AND. &
(pot1%set(i)%allegro%unit_coords == pot2%set(i)%allegro%unit_coords) .AND. &
(pot1%set(i)%allegro%unit_forces == pot2%set(i)%allegro%unit_forces) .AND. &
(pot1%set(i)%allegro%unit_energy == pot2%set(i)%allegro%unit_energy) .AND. &
(pot1%set(i)%allegro%unit_cell == pot2%set(i)%allegro%unit_cell)) mycompare = .TRUE.
(pot1%set(i)%nequip%unit_energy == pot2%set(i)%nequip%unit_energy)) mycompare = .TRUE.
CASE (ft_type)
IF ((pot1%set(i)%ft%A == pot2%set(i)%ft%A) .AND. &
(pot1%set(i)%ft%B == pot2%set(i)%ft%B) .AND. &
@ -631,7 +609,6 @@ CONTAINS
potparm%set(i)%goodwin, &
potparm%set(i)%eam, &
potparm%set(i)%nequip, &
potparm%set(i)%allegro, &
potparm%set(i)%ace, &
potparm%set(i)%deepmd, &
potparm%set(i)%buck4r, &
@ -677,7 +654,6 @@ CONTAINS
CALL pair_potential_goodwin_clean(potparm%set(i)%goodwin)
CALL pair_potential_eam_clean(potparm%set(i)%eam)
CALL pair_potential_nequip_clean(potparm%set(i)%nequip)
CALL pair_potential_allegro_clean(potparm%set(i)%allegro)
CALL pair_potential_ace_clean(potparm%set(i)%ace)
CALL pair_potential_deepmd_clean(potparm%set(i)%deepmd)
CALL pair_potential_buck4r_clean(potparm%set(i)%buck4r)
@ -735,7 +711,6 @@ CONTAINS
CALL pair_potential_goodwin_copy(potparm_source%set(i)%goodwin, potparm_dest%set(i)%goodwin)
CALL pair_potential_eam_copy(potparm_source%set(i)%eam, potparm_dest%set(i)%eam)
CALL pair_potential_nequip_copy(potparm_source%set(i)%nequip, potparm_dest%set(i)%nequip)
CALL pair_potential_allegro_copy(potparm_source%set(i)%allegro, potparm_dest%set(i)%allegro)
CALL pair_potential_ace_copy(potparm_source%set(i)%ace, potparm_dest%set(i)%ace)
CALL pair_potential_deepmd_copy(potparm_source%set(i)%deepmd, potparm_dest%set(i)%deepmd)
CALL pair_potential_bmhft_copy(potparm_source%set(i)%ft, potparm_dest%set(i)%ft)
@ -786,7 +761,6 @@ CONTAINS
(ASSOCIATED(potparm_dest%set(1)%goodwin)) .OR. &
(ASSOCIATED(potparm_dest%set(1)%eam)) .OR. &
(ASSOCIATED(potparm_dest%set(1)%nequip)) .OR. &
(ASSOCIATED(potparm_dest%set(1)%allegro)) .OR. &
(ASSOCIATED(potparm_dest%set(1)%ace)) .OR. &
(ASSOCIATED(potparm_dest%set(1)%deepmd)) .OR. &
(ASSOCIATED(potparm_dest%set(1)%ft)) .OR. &
@ -839,7 +813,6 @@ CONTAINS
CALL pair_potential_goodwin_copy(potparm_tmp%set(i)%goodwin, potparm_dest%set(i)%goodwin)
CALL pair_potential_eam_copy(potparm_tmp%set(i)%eam, potparm_dest%set(i)%eam)
CALL pair_potential_nequip_copy(potparm_tmp%set(i)%nequip, potparm_dest%set(i)%nequip)
CALL pair_potential_allegro_copy(potparm_tmp%set(i)%allegro, potparm_dest%set(i)%allegro)
CALL pair_potential_ace_copy(potparm_tmp%set(i)%ace, potparm_dest%set(i)%ace)
CALL pair_potential_deepmd_copy(potparm_tmp%set(i)%deepmd, potparm_dest%set(i)%deepmd)
CALL pair_potential_bmhft_copy(potparm_tmp%set(i)%ft, potparm_dest%set(i)%ft)
@ -876,7 +849,6 @@ CONTAINS
CALL pair_potential_goodwin_copy(potparm_source%set(j)%goodwin, potparm_dest%set(i)%goodwin)
CALL pair_potential_eam_copy(potparm_source%set(j)%eam, potparm_dest%set(i)%eam)
CALL pair_potential_nequip_copy(potparm_source%set(j)%nequip, potparm_dest%set(i)%nequip)
CALL pair_potential_allegro_copy(potparm_source%set(j)%allegro, potparm_dest%set(i)%allegro)
CALL pair_potential_ace_copy(potparm_source%set(j)%ace, potparm_dest%set(i)%ace)
CALL pair_potential_deepmd_copy(potparm_source%set(j)%deepmd, potparm_dest%set(i)%deepmd)
CALL pair_potential_bmhft_copy(potparm_source%set(j)%ft, potparm_dest%set(i)%ft)
@ -915,7 +887,6 @@ CONTAINS
CALL pair_potential_goodwin_release(potparm%set(i)%goodwin)
CALL pair_potential_eam_release(potparm%set(i)%eam)
CALL pair_potential_nequip_release(potparm%set(i)%nequip)
CALL pair_potential_allegro_release(potparm%set(i)%allegro)
CALL pair_potential_ace_release(potparm%set(i)%ace)
CALL pair_potential_deepmd_release(potparm%set(i)%deepmd)
CALL pair_potential_buck4r_release(potparm%set(i)%buck4r)
@ -1091,7 +1062,6 @@ CONTAINS
!> \param goodwin ...
!> \param eam ...
!> \param nequip ...
!> \param allegro ...
!> \param bmhft ...
!> \param bmhftd ...
!> \param ipbv ...
@ -1108,17 +1078,16 @@ CONTAINS
!> \author Teodoro Laino [Teo] 11.2005
! **************************************************************************************************
SUBROUTINE pair_potential_reallocate(p, lb1_new, ub1_new, lj, lj_charmm, williams, goodwin, eam, &
nequip, allegro, bmhft, bmhftd, ipbv, buck4r, buckmo, &
nequip, bmhft, bmhftd, ipbv, buck4r, buckmo, &
gp, tersoff, siepmann, gal, gal21, tab, deepmd, ace)
TYPE(pair_potential_p_type), POINTER :: p
INTEGER, INTENT(IN) :: lb1_new, ub1_new
LOGICAL, INTENT(IN), OPTIONAL :: lj, lj_charmm, williams, goodwin, eam, nequip, allegro, &
bmhft, bmhftd, ipbv, buck4r, buckmo, gp, tersoff, siepmann, gal, gal21, tab, deepmd, ace
LOGICAL, INTENT(IN), OPTIONAL :: lj, lj_charmm, williams, goodwin, eam, nequip, bmhft, &
bmhftd, ipbv, buck4r, buckmo, gp, tersoff, siepmann, gal, gal21, tab, deepmd, ace
INTEGER :: i, ipot, lb1_old, std_dim, ub1_old
LOGICAL :: check, lace, lallegro, lbmhft, lbmhftd, lbuck4r, lbuckmo, ldeepmd, leam, lgal, &
lgal21, lgoodwin, lgp, lipbv, llj, llj_charmm, lnequip, lsiepmann, ltab, ltersoff, &
lwilliams
LOGICAL :: check, lace, lbmhft, lbmhftd, lbuck4r, lbuckmo, ldeepmd, leam, lgal, lgal21, &
lgoodwin, lgp, lipbv, llj, llj_charmm, lnequip, lsiepmann, ltab, ltersoff, lwilliams
TYPE(pair_potential_p_type), POINTER :: work
NULLIFY (work)
@ -1129,7 +1098,6 @@ CONTAINS
lgoodwin = .FALSE.; IF (PRESENT(goodwin)) lgoodwin = goodwin
leam = .FALSE.; IF (PRESENT(eam)) leam = eam
lnequip = .FALSE.; IF (PRESENT(nequip)) lnequip = nequip
lallegro = .FALSE.; IF (PRESENT(allegro)) lallegro = allegro
lace = .FALSE.; IF (PRESENT(ace)) lace = ace
ldeepmd = .FALSE.; IF (PRESENT(deepmd)) ldeepmd = deepmd
lbmhft = .FALSE.; IF (PRESENT(bmhft)) lbmhft = bmhft
@ -1146,49 +1114,42 @@ CONTAINS
IF (llj) THEN
ipot = lj_type
check = .NOT. (llj_charmm .OR. lwilliams .OR. lgoodwin .OR. leam .OR. lnequip .OR. lallegro &
check = .NOT. (llj_charmm .OR. lwilliams .OR. lgoodwin .OR. leam .OR. lnequip &
.OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
.OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd .OR. lace)
CPASSERT(check)
END IF
IF (llj_charmm) THEN
ipot = lj_charmm_type
check = .NOT. (llj .OR. lwilliams .OR. lgoodwin .OR. leam .OR. lnequip .OR. lallegro &
check = .NOT. (llj .OR. lwilliams .OR. lgoodwin .OR. leam .OR. lnequip &
.OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
.OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd .OR. lace)
CPASSERT(check)
END IF
IF (lwilliams) THEN
ipot = wl_type
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. leam .OR. lnequip .OR. lallegro &
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. leam .OR. lnequip &
.OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
.OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd .OR. lace)
CPASSERT(check)
END IF
IF (lgoodwin) THEN
ipot = gw_type
check = .NOT. (llj .OR. llj_charmm .OR. lwilliams .OR. leam .OR. lnequip .OR. lallegro &
check = .NOT. (llj .OR. llj_charmm .OR. lwilliams .OR. leam .OR. lnequip &
.OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
.OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd .OR. lace)
CPASSERT(check)
END IF
IF (leam) THEN
ipot = ea_type
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. lnequip .OR. lallegro &
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. lnequip &
.OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
.OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd .OR. lace)
CPASSERT(check)
END IF
IF (lnequip) THEN
ipot = nequip_type
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lallegro &
.OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
.OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd .OR. lace)
CPASSERT(check)
END IF
IF (lallegro) THEN
ipot = allegro_type
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lnequip &
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam &
.OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
.OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd .OR. lace)
CPASSERT(check)
@ -1196,42 +1157,42 @@ CONTAINS
IF (lace) THEN
ipot = ace_type
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lnequip &
.OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp &
.OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp &
.OR. ltersoff .OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd)
CPASSERT(check)
END IF
IF (ldeepmd) THEN
ipot = deepmd_type
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lnequip &
.OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp &
.OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp &
.OR. ltersoff .OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. lace)
CPASSERT(check)
END IF
IF (lbmhft) THEN
ipot = ft_type
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lnequip &
.OR. lallegro .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
.OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
.OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd .OR. lace)
CPASSERT(check)
END IF
IF (lbmhftd) THEN
ipot = ftd_type
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lnequip &
.OR. lallegro .OR. lbmhft .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
.OR. lbmhft .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
.OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd .OR. lace)
CPASSERT(check)
END IF
IF (lipbv) THEN
ipot = ip_type
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lnequip &
.OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
.OR. lbmhft .OR. lbmhftd .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
.OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd .OR. lace)
CPASSERT(check)
END IF
IF (lbuck4r) THEN
ipot = b4_type
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lnequip &
.OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuckmo .OR. lgp .OR. ltersoff &
.OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuckmo .OR. lgp .OR. ltersoff &
.OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd .OR. lace)
CPASSERT(check)
END IF
@ -1245,42 +1206,42 @@ CONTAINS
IF (ltersoff) THEN
ipot = tersoff_type
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lnequip &
.OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgp .OR. lbuckmo &
.OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgp .OR. lbuckmo &
.OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd .OR. lace)
CPASSERT(check)
END IF
IF (lsiepmann) THEN
ipot = siepmann_type
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lnequip &
.OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgp .OR. lbuckmo &
.OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgp .OR. lbuckmo &
.OR. ltersoff .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd .OR. lace)
CPASSERT(check)
END IF
IF (lgal) THEN
ipot = gal_type
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lnequip &
.OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgp .OR. lbuckmo &
.OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgp .OR. lbuckmo &
.OR. ltersoff .OR. lsiepmann .OR. lgal21 .OR. ltab .OR. ldeepmd .OR. lace)
CPASSERT(check)
END IF
IF (lgal21) THEN
ipot = gal21_type
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lnequip &
.OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgp .OR. lbuckmo &
.OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgp .OR. lbuckmo &
.OR. ltersoff .OR. lsiepmann .OR. lgal .OR. ltab .OR. ldeepmd .OR. lace)
CPASSERT(check)
END IF
IF (lgp) THEN
ipot = gp_type
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lnequip &
.OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgal21 .OR. lbuckmo &
.OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgal21 .OR. lbuckmo &
.OR. ltersoff .OR. lsiepmann .OR. lgal .OR. ltab .OR. ldeepmd .OR. lace)
CPASSERT(check)
END IF
IF (ltab) THEN
ipot = tab_type
check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lnequip &
.OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgp .OR. lgal21 &
.OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgp .OR. lgal21 &
.OR. lbuckmo .OR. ltersoff .OR. lsiepmann .OR. lgal .OR. lace)
CPASSERT(check)
END IF
@ -1321,10 +1282,8 @@ CONTAINS
CALL pair_potential_goodwin_create(p%pot(i)%pot%set(std_dim)%goodwin)
CASE (ea_type)
CALL pair_potential_eam_create(p%pot(i)%pot%set(std_dim)%eam)
CASE (nequip_type)
CASE (nequip_type, allegro_type)
CALL pair_potential_nequip_create(p%pot(i)%pot%set(std_dim)%nequip)
CASE (allegro_type)
CALL pair_potential_allegro_create(p%pot(i)%pot%set(std_dim)%allegro)
CASE (ace_type)
CALL pair_potential_ace_create(p%pot(i)%pot%set(std_dim)%ace)
CASE (deepmd_type)
@ -1893,59 +1852,6 @@ CONTAINS
END IF
END SUBROUTINE pair_potential_nequip_release
! **************************************************************************************************
!> \brief Creates the ALLEGRO potential type
!> \param allegro ...
!> \author Gabriele Tocci 2023
! **************************************************************************************************
SUBROUTINE pair_potential_allegro_create(allegro)
TYPE(allegro_pot_type), POINTER :: allegro
CPASSERT(.NOT. ASSOCIATED(allegro))
ALLOCATE (allegro)
END SUBROUTINE pair_potential_allegro_create
! **************************************************************************************************
!> \brief Copy two ALLEGRO potential type
!> \param allegro_source ...
!> \param allegro_dest ...
!> \author Gabriele Tocci 2023
! **************************************************************************************************
SUBROUTINE pair_potential_allegro_copy(allegro_source, allegro_dest)
TYPE(allegro_pot_type), POINTER :: allegro_source, allegro_dest
IF (.NOT. ASSOCIATED(allegro_source)) RETURN
IF (ASSOCIATED(allegro_dest)) CALL pair_potential_allegro_release(allegro_dest)
CALL pair_potential_allegro_create(allegro_dest)
allegro_dest = allegro_source
END SUBROUTINE pair_potential_allegro_copy
! **************************************************************************************************
!> \brief Creates the ALLEGRO potential type
!> \param allegro ...
!> \author Gabriele Tocci 2023
! **************************************************************************************************
SUBROUTINE pair_potential_allegro_clean(allegro)
TYPE(allegro_pot_type), POINTER :: allegro
IF (.NOT. ASSOCIATED(allegro)) RETURN
allegro = allegro_pot_type()
END SUBROUTINE pair_potential_allegro_clean
! **************************************************************************************************
!> \brief Destroys the ALLEGRO potential type
!> \param allegro ...
!> \author Gabriele Tocci 2023
! **************************************************************************************************
SUBROUTINE pair_potential_allegro_release(allegro)
TYPE(allegro_pot_type), POINTER :: allegro
IF (ASSOCIATED(allegro)) THEN
DEALLOCATE (allegro)
END IF
END SUBROUTINE pair_potential_allegro_release
! **************************************************************************************************
!> \brief Creates the BMHFT (TOSI-FUMI) potential type
!> \param ft ...

View file

@ -211,6 +211,11 @@ void torch_c_dict_release(torch_c_dict_t *dict) { delete (dict); }
******************************************************************************/
void torch_c_model_load(torch_c_model_t **model_out, const char *filename) {
assert(*model_out == NULL);
// JIT Fusion strategy optimization, hardcode dynamic 10, see also
// https://github.com/mir-group/pair_nequip_allegro.git
torch::jit::FusionStrategy strategy = {
{torch::jit::FusionBehavior::DYNAMIC, 10}};
torch::jit::setFusionStrategy(strategy);
torch::jit::Module *model = new torch::jit::Module();
*model = torch::jit::load(filename, get_device());
model->eval(); // Set to evaluation mode to disable gradients, drop-out, etc.

View file

@ -1,61 +0,0 @@
&GLOBAL
PROJECT Si
RUN_TYPE MD
&END GLOBAL
&MOTION
&MD
ENSEMBLE NVT
STEPS 0
TEMPERATURE 300.0
TIMESTEP 1
&THERMOSTAT
REGION GLOBAL
TYPE CSVR
&CSVR
TIMECON 100.
&END CSVR
&END THERMOSTAT
&END MD
&PRINT
&FORCES
UNIT eV*angstrom^-1
&EACH
MD 1
&END EACH
&END FORCES
&END PRINT
&END MOTION
&FORCE_EVAL
METHOD FIST
&MM
&FORCEFIELD
&NONBONDED
&ALLEGRO
ATOMS Si
PARM_FILE_NAME Allegro/si-deployed-neq060dp.pth
UNIT_COORDS angstrom
UNIT_ENERGY eV
UNIT_FORCES eV*angstrom^-1
&END ALLEGRO
&END NONBONDED
&END FORCEFIELD
&POISSON
&EWALD
EWALD_TYPE none
&END EWALD
&END POISSON
&END MM
&SUBSYS
&CELL
ABC 10.861999859992501 10.861999859992501 10.861999859992501
# MULTIPLE_UNIT_CELL 4 4 4
&END CELL
&TOPOLOGY
COORD_FILE_FORMAT XYZ
COORD_FILE_NAME Si.xyz
# MULTIPLE_UNIT_CELL 4 4 4
&END TOPOLOGY
&END SUBSYS
&END FORCE_EVAL

View file

@ -1,66 +0,0 @@
64
Si 0.10000000 0.00000000 0.00000000
Si 0.10000000 2.71549996 2.71549996
Si 2.71549996 2.71549996 0.00000000
Si 2.71549996 0.00000000 2.71549996
Si 4.07324995 1.35774998 4.07324995
Si 1.35774998 1.35774998 1.35774998
Si 1.35774998 4.07324995 4.07324995
Si 4.07324995 4.07324995 1.35774998
Si 0.00000000 0.00000000 5.43099993
Si 0.00000000 2.71549996 8.14649989
Si 2.71549996 2.71549996 5.43099993
Si 2.71549996 0.00000000 8.14649989
Si 4.07324995 1.35774998 9.50424988
Si 1.35774998 1.35774998 6.78874991
Si 1.35774998 4.07324995 9.50424988
Si 4.07324995 4.07324995 6.78874991
Si 0.00000000 5.43099993 0.00000000
Si 0.00000000 8.14649989 2.71549996
Si 2.71549996 8.14649989 0.00000000
Si 2.71549996 5.43099993 2.71549996
Si 4.07324995 6.78874991 4.07324995
Si 1.35774998 6.78874991 1.35774998
Si 1.35774998 9.50424988 4.07324995
Si 4.07324995 9.50424988 1.35774998
Si 0.00000000 5.43099993 5.43099993
Si 0.00000000 8.14649989 8.14649989
Si 2.71549996 8.14649989 5.43099993
Si 2.71549996 5.43099993 8.14649989
Si 4.07324995 6.78874991 9.50424988
Si 1.35774998 6.78874991 6.78874991
Si 1.35774998 9.50424988 9.50424988
Si 4.07324995 9.50424988 6.78874991
Si 5.43099993 0.00000000 0.00000000
Si 5.43099993 2.71549996 2.71549996
Si 8.14649989 2.71549996 0.00000000
Si 8.14649989 0.00000000 2.71549996
Si 9.50424988 1.35774998 4.07324995
Si 6.78874991 1.35774998 1.35774998
Si 6.78874991 4.07324995 4.07324995
Si 9.50424988 4.07324995 1.35774998
Si 5.43099993 0.00000000 5.43099993
Si 5.43099993 2.71549996 8.14649989
Si 8.14649989 2.71549996 5.43099993
Si 8.14649989 0.00000000 8.14649989
Si 9.50424988 1.35774998 9.50424988
Si 6.78874991 1.35774998 6.78874991
Si 6.78874991 4.07324995 9.50424988
Si 9.50424988 4.07324995 6.78874991
Si 5.43099993 5.43099993 0.00000000
Si 5.43099993 8.14649989 2.71549996
Si 8.14649989 8.14649989 0.00000000
Si 8.14649989 5.43099993 2.71549996
Si 9.50424988 6.78874991 4.07324995
Si 6.78874991 6.78874991 1.35774998
Si 6.78874991 9.50424988 4.07324995
Si 9.50424988 9.50424988 1.35774998
Si 5.43099993 5.43099993 5.43099993
Si 5.43099993 8.14649989 8.14649989
Si 8.14649989 8.14649989 5.43099993
Si 8.14649989 5.43099993 8.14649989
Si 9.50424988 6.78874991 9.50424988
Si 6.78874991 6.78874991 6.78874991
Si 6.78874991 9.50424988 9.50424988
Si 9.60424988 9.50424988 6.78874991

View file

@ -1,4 +1,4 @@
# Test of Allegro using libtorch https://pytorch.org/cppdocs/installing.html
"Si-dp.inp" = [{matcher="M011", tol=1.0E-12, ref=-305.905681109061788}]
"water-bulk-sp.inp" = [{matcher="M011", tol=1.0E-6, ref=-556.070399189654040}]
"water-bulk.inp" = [{matcher="M011", tol=1.0E-9, ref=-550.634583715432086},
{matcher="M031", tol=1.0E-6, ref=3.40720924931E+04}]
#EOF

View file

@ -20,16 +20,18 @@
&FORCE_EVAL
METHOD FIST
STRESS_TENSOR ANALYTICAL
&MM
&FORCEFIELD
&NONBONDED
&ALLEGRO
&NEQUIP
ATOMS H O
PARM_FILE_NAME Allegro/gra-water-deployed-neq060sp.pth
UNIT_COORDS angstrom
MODEL_TYPE ALLEGRO
POT_FILE_NAME Allegro/waterscan-allegro0.8.0.nequip.pth
UNIT_ENERGY eV
UNIT_FORCES eV*angstrom^-1
&END ALLEGRO
UNIT_LENGTH angstrom
&END NEQUIP
&END NONBONDED
&END FORCEFIELD
&POISSON
@ -41,6 +43,11 @@
&PRINT
&FORCES
&END FORCES
&STRESS_TENSOR
&EACH
MD 1
&END EACH
&END STRESS_TENSOR
&END PRINT
&SUBSYS
&CELL
@ -50,7 +57,6 @@
&END CELL
&TOPOLOGY
COORD_FILE_FORMAT XYZ
# coordinates must be ordered by atomic number
COORD_FILE_NAME ../regtest-nequip/water-bulk.xyz
&END TOPOLOGY
&END SUBSYS

View file

@ -1,4 +1,4 @@
# Test of NequIP using libtorch https://pytorch.org/cppdocs/installing.html
"water-sp.inp" = [{matcher="M011", tol=1.0E-6, ref=-17.195440909240052}]
"water-bulk-dp.inp" = [{matcher="M031", tol=1.0E-9, ref=3.78036960937E+04}]
"water-bulk.inp" = [{matcher="M011", tol=1.0E-9, ref=-550.635061584740356},
{matcher="M031", tol=1.0E-6, ref=3.41015357500E+04}]
#EOF

View file

@ -25,10 +25,11 @@
&NONBONDED
&NEQUIP
ATOMS H O
PARM_FILE_NAME NequIP/water-deployed-neq060dp.pth
UNIT_COORDS angstrom
MODEL_TYPE NEQUIP
POT_FILE_NAME NequIP/waterscan-neq0.16.nequip.pth
UNIT_ENERGY eV
UNIT_FORCES eV*angstrom^-1
UNIT_LENGTH angstrom
&END NEQUIP
&END NONBONDED
&END FORCEFIELD
@ -53,7 +54,6 @@
&END CELL
&TOPOLOGY
COORD_FILE_FORMAT XYZ
# coordinates must be ordered by atomic number
COORD_FILE_NAME ./water-bulk.xyz
&END TOPOLOGY
&END SUBSYS

View file

@ -1,47 +0,0 @@
&GLOBAL
PROJECT water
RUN_TYPE ENERGY_FORCE
&PRINT DEBUG
&END PRINT
&END GLOBAL
&FORCE_EVAL
METHOD FIST
&MM
&FORCEFIELD
&NONBONDED
&NEQUIP
ATOMS H O
PARM_FILE_NAME NequIP/water-deployed-neq060sp.pth
UNIT_COORDS angstrom
UNIT_ENERGY eV
UNIT_FORCES eV*angstrom^-1
&END NEQUIP
&END NONBONDED
&END FORCEFIELD
&POISSON
&EWALD
EWALD_TYPE none
&END EWALD
&END POISSON
&END MM
&PRINT
&FORCES
&END FORCES
&END PRINT
&SUBSYS
&CELL
ABC 9.85 9.85 9.85
# MULTIPLE_UNIT_CELL 4 4 4
&END CELL
# coordinates must be ordered by atomic number
&COORD
H 42.886169670000001 -0.055681660000000001 38.329161120000002
H 34.202588720000001 -0.6185484 37.365568080000003
O 43.209908720000001 -0.062845650000000003 47.25931559
&END COORD
&TOPOLOGY
# MULTIPLE_UNIT_CELL 4 4 4
&END TOPOLOGY
&END SUBSYS
&END FORCE_EVAL