LCOV - code coverage report
Current view: top level - src - nnp_acsf.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 625 660 94.7 %
Date: 2024-12-21 06:28:57 Functions: 15 15 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief  Functionality for atom centered symmetry functions
      10             : !>         for neural network potentials
      11             : !> \author Christoph Schran (christoph.schran@rub.de)
      12             : !> \date   2020-10-10
      13             : ! **************************************************************************************************
      14             : MODULE nnp_acsf
      15             :    USE cell_types,                      ONLY: cell_type,&
      16             :                                               pbc
      17             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      18             :                                               cp_logger_get_default_unit_nr,&
      19             :                                               cp_logger_type
      20             :    USE kinds,                           ONLY: default_string_length,&
      21             :                                               dp
      22             :    USE mathconstants,                   ONLY: pi
      23             :    USE message_passing,                 ONLY: mp_para_env_type
      24             :    USE nnp_environment_types,           ONLY: nnp_acsf_ang_type,&
      25             :                                               nnp_acsf_rad_type,&
      26             :                                               nnp_cut_cos,&
      27             :                                               nnp_cut_tanh,&
      28             :                                               nnp_env_get,&
      29             :                                               nnp_neighbor_type,&
      30             :                                               nnp_type
      31             :    USE periodic_table,                  ONLY: get_ptable_info
      32             : #include "./base/base_uses.f90"
      33             : 
      34             :    IMPLICIT NONE
      35             : 
      36             :    PRIVATE
      37             : 
      38             :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
      39             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'nnp_acsf'
      40             :    ! Public subroutines ***
      41             :    PUBLIC :: nnp_calc_acsf, &
      42             :              nnp_init_acsf_groups, &
      43             :              nnp_sort_acsf, &
      44             :              nnp_sort_ele, &
      45             :              nnp_write_acsf
      46             : 
      47             : CONTAINS
      48             : 
      49             : ! **************************************************************************************************
      50             : !> \brief Calculate atom centered symmetry functions for given atom i
      51             : !> \param nnp ...
      52             : !> \param i ...
      53             : !> \param dsymdxyz ...
      54             : !> \param stress ...
      55             : !> \date   2020-10-10
      56             : !> \author Christoph Schran (christoph.schran@rub.de)
      57             : ! **************************************************************************************************
      58      248177 :    SUBROUTINE nnp_calc_acsf(nnp, i, dsymdxyz, stress)
      59             : 
      60             :       TYPE(nnp_type), INTENT(INOUT), POINTER             :: nnp
      61             :       INTEGER, INTENT(IN)                                :: i
      62             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT), &
      63             :          OPTIONAL                                        :: dsymdxyz, stress
      64             : 
      65             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'nnp_calc_acsf'
      66             : 
      67             :       INTEGER                                            :: handle, handle_sf, ind, j, jj, k, kk, l, &
      68             :                                                             m, off, s, sf
      69             :       REAL(KIND=dp)                                      :: r1, r2, r3
      70      248177 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: symtmp
      71      248177 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: forcetmp
      72      248177 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: force3tmp
      73             :       REAL(KIND=dp), DIMENSION(3)                        :: rvect1, rvect2, rvect3
      74      992708 :       TYPE(nnp_neighbor_type)                            :: neighbor
      75             : 
      76      248177 :       CALL timeset(routineN, handle)
      77             : 
      78             :       !determine index of atom type
      79      248177 :       ind = nnp%ele_ind(i)
      80             : 
      81             :       ! compute neighbors of atom i
      82      248177 :       CALL nnp_neighbor_create(nnp, ind, nnp%num_atoms, neighbor)
      83      248177 :       CALL nnp_compute_neighbors(nnp, neighbor, i)
      84             : 
      85             :       ! Reset y:
      86     3722461 :       nnp%rad(ind)%y = 0.0_dp
      87     2067689 :       nnp%ang(ind)%y = 0.0_dp
      88             : 
      89             :       !calc forces
      90      248177 :       IF (PRESENT(dsymdxyz)) THEN
      91             :          !loop over radial sym fnct grps
      92       19105 :          CALL timeset('nnp_acsf_radial', handle_sf)
      93       60515 :          DO s = 1, nnp%rad(ind)%n_symfgrp
      94      124230 :             ALLOCATE (symtmp(nnp%rad(ind)%symfgrp(s)%n_symf))
      95      124230 :             ALLOCATE (forcetmp(3, nnp%rad(ind)%symfgrp(s)%n_symf))
      96             :             !loop over associated neighbors
      97     1401178 :             DO j = 1, neighbor%n_rad(s)
      98     5439072 :                rvect1 = neighbor%dist_rad(1:3, j, s)
      99     1359768 :                r1 = neighbor%dist_rad(4, j, s)
     100     1359768 :                CALL nnp_calc_rad(nnp, ind, s, rvect1, r1, symtmp, forcetmp)
     101     1359768 :                jj = neighbor%ind_rad(j, s)
     102    12256054 :                DO sf = 1, nnp%rad(ind)%symfgrp(s)%n_symf
     103    10854876 :                   m = nnp%rad(ind)%symfgrp(s)%symf(sf)
     104             :                   ! update forces into dsymdxyz
     105    43419504 :                   DO l = 1, 3
     106    32564628 :                      dsymdxyz(l, m, i) = dsymdxyz(l, m, i) + forcetmp(l, sf)
     107    43419504 :                      dsymdxyz(l, m, jj) = dsymdxyz(l, m, jj) - forcetmp(l, sf)
     108             :                   END DO
     109    10854876 :                   IF (PRESENT(stress)) THEN
     110     7184768 :                      DO l = 1, 3
     111    23350496 :                         stress(:, l, m) = stress(:, l, m) + rvect1(:)*forcetmp(l, sf)
     112             :                      END DO
     113             :                   END IF
     114    12214644 :                   nnp%rad(ind)%y(m) = nnp%rad(ind)%y(m) + symtmp(sf)
     115             :                END DO
     116             :             END DO
     117       41410 :             DEALLOCATE (symtmp)
     118       60515 :             DEALLOCATE (forcetmp)
     119             :          END DO
     120       19105 :          CALL timestop(handle_sf)
     121             :          !loop over angular sym fnct grps
     122       19105 :          CALL timeset('nnp_acsf_angular', handle_sf)
     123       19105 :          off = nnp%n_rad(ind)
     124       61550 :          DO s = 1, nnp%ang(ind)%n_symfgrp
     125      127335 :             ALLOCATE (symtmp(nnp%ang(ind)%symfgrp(s)%n_symf))
     126      127335 :             ALLOCATE (force3tmp(3, 3, nnp%ang(ind)%symfgrp(s)%n_symf))
     127             :             !loop over associated neighbors
     128       42445 :             IF (nnp%ang(ind)%symfgrp(s)%ele(1) == nnp%ang(ind)%symfgrp(s)%ele(2)) THEN
     129      774360 :                DO j = 1, neighbor%n_ang1(s)
     130     3016880 :                   rvect1 = neighbor%dist_ang1(1:3, j, s)
     131      754220 :                   r1 = neighbor%dist_ang1(4, j, s)
     132    19195970 :                   DO k = j + 1, neighbor%n_ang1(s)
     133    73686440 :                      rvect2 = neighbor%dist_ang1(1:3, k, s)
     134    18421610 :                      r2 = neighbor%dist_ang1(4, k, s)
     135    73686440 :                      rvect3 = rvect2 - rvect1
     136    73686440 :                      r3 = NORM2(rvect3(:))
     137    19175830 :                      IF (r3 < nnp%ang(ind)%symfgrp(s)%cutoff) THEN
     138     8481295 :                         jj = neighbor%ind_ang1(j, s)
     139     8481295 :                         kk = neighbor%ind_ang1(k, s)
     140             :                         CALL nnp_calc_ang(nnp, ind, s, rvect1, rvect2, rvect3, &
     141     8481295 :                                           r1, r2, r3, symtmp, force3tmp)
     142    52399787 :                         DO sf = 1, nnp%ang(ind)%symfgrp(s)%n_symf
     143    43918492 :                            m = off + nnp%ang(ind)%symfgrp(s)%symf(sf)
     144             :                            ! update forces into dsymdxy
     145   175673968 :                            DO l = 1, 3
     146             :                               dsymdxyz(l, m, i) = dsymdxyz(l, m, i) &
     147   131755476 :                                                   + force3tmp(l, 1, sf)
     148             :                               dsymdxyz(l, m, jj) = dsymdxyz(l, m, jj) &
     149   131755476 :                                                    + force3tmp(l, 2, sf)
     150             :                               dsymdxyz(l, m, kk) = dsymdxyz(l, m, kk) &
     151   175673968 :                                                    + force3tmp(l, 3, sf)
     152             :                            END DO
     153    43918492 :                            IF (PRESENT(stress)) THEN
     154    29217640 :                               DO l = 1, 3
     155    87652920 :                                  stress(:, l, m) = stress(:, l, m) - rvect1(:)*force3tmp(l, 2, sf)
     156    94957330 :                                  stress(:, l, m) = stress(:, l, m) - rvect2(:)*force3tmp(l, 3, sf)
     157             :                               END DO
     158             :                            END IF
     159    52399787 :                            nnp%ang(ind)%y(m - off) = nnp%ang(ind)%y(m - off) + symtmp(sf)
     160             :                         END DO
     161             :                      END IF
     162             :                   END DO
     163             :                END DO
     164             :             ELSE
     165      932948 :                DO j = 1, neighbor%n_ang1(s)
     166     3642572 :                   rvect1 = neighbor%dist_ang1(1:3, j, s)
     167      910643 :                   r1 = neighbor%dist_ang1(4, j, s)
     168    32831058 :                   DO k = 1, neighbor%n_ang2(s)
     169   127592440 :                      rvect2 = neighbor%dist_ang2(1:3, k, s)
     170    31898110 :                      r2 = neighbor%dist_ang2(4, k, s)
     171   127592440 :                      rvect3 = rvect2 - rvect1
     172   127592440 :                      r3 = NORM2(rvect3(:))
     173    32808753 :                      IF (r3 < nnp%ang(ind)%symfgrp(s)%cutoff) THEN
     174    14833666 :                         jj = neighbor%ind_ang1(j, s)
     175    14833666 :                         kk = neighbor%ind_ang1(k, s)
     176             :                         CALL nnp_calc_ang(nnp, ind, s, rvect1, rvect2, rvect3, &
     177    14833666 :                                           r1, r2, r3, symtmp, force3tmp)
     178             :                         !loop over associated sym fncts
     179   104150027 :                         DO sf = 1, nnp%ang(ind)%symfgrp(s)%n_symf
     180    89316361 :                            m = off + nnp%ang(ind)%symfgrp(s)%symf(sf)
     181    89316361 :                            jj = neighbor%ind_ang1(j, s)
     182    89316361 :                            kk = neighbor%ind_ang2(k, s)
     183             :                            ! update forces into dsymdxy
     184   357265444 :                            DO l = 1, 3
     185             :                               dsymdxyz(l, m, i) = dsymdxyz(l, m, i) &
     186   267949083 :                                                   + force3tmp(l, 1, sf)
     187             :                               dsymdxyz(l, m, jj) = dsymdxyz(l, m, jj) &
     188   267949083 :                                                    + force3tmp(l, 2, sf)
     189             :                               dsymdxyz(l, m, kk) = dsymdxyz(l, m, kk) &
     190   357265444 :                                                    + force3tmp(l, 3, sf)
     191             :                            END DO
     192    89316361 :                            IF (PRESENT(stress)) THEN
     193    59415432 :                               DO l = 1, 3
     194   178246296 :                                  stress(:, l, m) = stress(:, l, m) - rvect1(:)*force3tmp(l, 2, sf)
     195   193100154 :                                  stress(:, l, m) = stress(:, l, m) - rvect2(:)*force3tmp(l, 3, sf)
     196             :                               END DO
     197             :                            END IF
     198   104150027 :                            nnp%ang(ind)%y(m - off) = nnp%ang(ind)%y(m - off) + symtmp(sf)
     199             :                         END DO
     200             :                      END IF
     201             :                   END DO
     202             :                END DO
     203             :             END IF
     204       42445 :             DEALLOCATE (symtmp)
     205       61550 :             DEALLOCATE (force3tmp)
     206             :          END DO
     207       19105 :          CALL timestop(handle_sf)
     208             :          !no forces
     209             :       ELSE
     210             :          !loop over radial sym fnct grps
     211      229072 :          CALL timeset('nnp_acsf_radial', handle_sf)
     212      794360 :          DO s = 1, nnp%rad(ind)%n_symfgrp
     213     1695864 :             ALLOCATE (symtmp(nnp%rad(ind)%symfgrp(s)%n_symf))
     214             :             !loop over associated neighbors
     215     2495804 :             DO j = 1, neighbor%n_rad(s)
     216     7722064 :                rvect1 = neighbor%dist_rad(1:3, j, s)
     217     1930516 :                r1 = neighbor%dist_rad(4, j, s)
     218     1930516 :                CALL nnp_calc_rad(nnp, ind, s, rvect1, r1, symtmp)
     219    17187322 :                DO sf = 1, nnp%rad(ind)%symfgrp(s)%n_symf
     220    14691518 :                   m = nnp%rad(ind)%symfgrp(s)%symf(sf)
     221    16622034 :                   nnp%rad(ind)%y(m) = nnp%rad(ind)%y(m) + symtmp(sf)
     222             :                END DO
     223             :             END DO
     224      794360 :             DEALLOCATE (symtmp)
     225             :          END DO
     226      229072 :          CALL timestop(handle_sf)
     227             :          !loop over angular sym fnct grps
     228      229072 :          CALL timeset('nnp_acsf_angular', handle_sf)
     229      229072 :          off = nnp%n_rad(ind)
     230      692144 :          DO s = 1, nnp%ang(ind)%n_symfgrp
     231     1389216 :             ALLOCATE (symtmp(nnp%ang(ind)%symfgrp(s)%n_symf))
     232             :             !loop over associated neighbors
     233      463072 :             IF (nnp%ang(ind)%symfgrp(s)%ele(1) == nnp%ang(ind)%symfgrp(s)%ele(2)) THEN
     234     1121116 :                DO j = 1, neighbor%n_ang1(s)
     235     3977040 :                   rvect1 = neighbor%dist_ang1(1:3, j, s)
     236      994260 :                   r1 = neighbor%dist_ang1(4, j, s)
     237    22659329 :                   DO k = j + 1, neighbor%n_ang1(s)
     238    86152852 :                      rvect2 = neighbor%dist_ang1(1:3, k, s)
     239    21538213 :                      r2 = neighbor%dist_ang1(4, k, s)
     240    86152852 :                      rvect3 = rvect2 - rvect1
     241    86152852 :                      r3 = NORM2(rvect3(:))
     242    22532473 :                      IF (r3 < nnp%ang(ind)%symfgrp(s)%cutoff) THEN
     243     9944571 :                         CALL nnp_calc_ang(nnp, ind, s, rvect1, rvect2, rvect3, r1, r2, r3, symtmp)
     244    61315369 :                         DO sf = 1, nnp%ang(ind)%symfgrp(s)%n_symf
     245    51370798 :                            m = off + nnp%ang(ind)%symfgrp(s)%symf(sf)
     246    61315369 :                            nnp%ang(ind)%y(m - off) = nnp%ang(ind)%y(m - off) + symtmp(sf)
     247             :                         END DO
     248             :                      END IF
     249             :                   END DO
     250             :                END DO
     251             :             ELSE
     252     1719216 :                DO j = 1, neighbor%n_ang1(s)
     253     5532000 :                   rvect1 = neighbor%dist_ang1(1:3, j, s)
     254     1383000 :                   r1 = neighbor%dist_ang1(4, j, s)
     255    39030025 :                   DO k = 1, neighbor%n_ang2(s)
     256   149243236 :                      rvect2 = neighbor%dist_ang2(1:3, k, s)
     257    37310809 :                      r2 = neighbor%dist_ang2(4, k, s)
     258   149243236 :                      rvect3 = rvect2 - rvect1
     259   149243236 :                      r3 = NORM2(rvect3(:))
     260    38693809 :                      IF (r3 < nnp%ang(ind)%symfgrp(s)%cutoff) THEN
     261    17429498 :                         CALL nnp_calc_ang(nnp, ind, s, rvect1, rvect2, rvect3, r1, r2, r3, symtmp)
     262             :                         !loop over associated sym fncts
     263   121983157 :                         DO sf = 1, nnp%ang(ind)%symfgrp(s)%n_symf
     264   104553659 :                            m = off + nnp%ang(ind)%symfgrp(s)%symf(sf)
     265   121983157 :                            nnp%ang(ind)%y(m - off) = nnp%ang(ind)%y(m - off) + symtmp(sf)
     266             :                         END DO
     267             :                      END IF
     268             :                   END DO
     269             :                END DO
     270             :             END IF
     271      692144 :             DEALLOCATE (symtmp)
     272             :          END DO
     273      229072 :          CALL timestop(handle_sf)
     274             :       END IF
     275             : 
     276             :       !check extrapolation
     277      248177 :       CALL nnp_check_extrapolation(nnp, ind)
     278             : 
     279      248177 :       IF (PRESENT(dsymdxyz)) THEN
     280       19105 :          IF (PRESENT(stress)) THEN
     281        2112 :             CALL nnp_scale_acsf(nnp, ind, dsymdxyz, stress)
     282             :          ELSE
     283       16993 :             CALL nnp_scale_acsf(nnp, ind, dsymdxyz)
     284             :          END IF
     285             :       ELSE
     286      229072 :          CALL nnp_scale_acsf(nnp, ind)
     287             :       END IF
     288             : 
     289      248177 :       CALL nnp_neighbor_release(neighbor)
     290      248177 :       CALL timestop(handle)
     291             : 
     292      248177 :    END SUBROUTINE nnp_calc_acsf
     293             : 
     294             : ! **************************************************************************************************
     295             : !> \brief Check if the nnp is extrapolating
     296             : !> \param nnp ...
     297             : !> \param ind ...
     298             : !> \date   2020-10-10
     299             : !> \author Christoph Schran (christoph.schran@rub.de)
     300             : ! **************************************************************************************************
     301      248177 :    SUBROUTINE nnp_check_extrapolation(nnp, ind)
     302             : 
     303             :       TYPE(nnp_type), INTENT(INOUT)                      :: nnp
     304             :       INTEGER, INTENT(IN)                                :: ind
     305             : 
     306             :       REAL(KIND=dp), PARAMETER                           :: threshold = 0.0001_dp
     307             : 
     308             :       INTEGER                                            :: j
     309             :       LOGICAL                                            :: extrapolate
     310             : 
     311      248177 :       extrapolate = nnp%output_expol
     312             : 
     313     3722461 :       DO j = 1, nnp%n_rad(ind)
     314     3474284 :          IF (nnp%rad(ind)%y(j) - &
     315      248177 :              nnp%rad(ind)%loc_max(j) > threshold) THEN
     316             :             extrapolate = .TRUE.
     317     3474284 :          ELSE IF (-nnp%rad(ind)%y(j) + &
     318             :                   nnp%rad(ind)%loc_min(j) > threshold) THEN
     319         164 :             extrapolate = .TRUE.
     320             :          END IF
     321             :       END DO
     322     2067689 :       DO j = 1, nnp%n_ang(ind)
     323     1819512 :          IF (nnp%ang(ind)%y(j) - &
     324      248177 :              nnp%ang(ind)%loc_max(j) > threshold) THEN
     325             :             extrapolate = .TRUE.
     326     1819512 :          ELSE IF (-nnp%ang(ind)%y(j) + &
     327             :                   nnp%ang(ind)%loc_min(j) > threshold) THEN
     328          30 :             extrapolate = .TRUE.
     329             :          END IF
     330             :       END DO
     331             : 
     332      248177 :       nnp%output_expol = extrapolate
     333             : 
     334      248177 :    END SUBROUTINE nnp_check_extrapolation
     335             : 
     336             : ! **************************************************************************************************
     337             : !> \brief Scale and center symetry functions (and gradients)
     338             : !> \param nnp ...
     339             : !> \param ind ...
     340             : !> \param dsymdxyz ...
     341             : !> \param stress ...
     342             : !> \date   2020-10-10
     343             : !> \author Christoph Schran (christoph.schran@rub.de)
     344             : ! **************************************************************************************************
     345      248177 :    SUBROUTINE nnp_scale_acsf(nnp, ind, dsymdxyz, stress)
     346             : 
     347             :       TYPE(nnp_type), INTENT(INOUT)                      :: nnp
     348             :       INTEGER, INTENT(IN)                                :: ind
     349             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(OUT), &
     350             :          OPTIONAL                                        :: dsymdxyz, stress
     351             : 
     352             :       INTEGER                                            :: j, k, off
     353             : 
     354      248177 :       IF (nnp%center_acsf) THEN
     355     3722461 :          DO j = 1, nnp%n_rad(ind)
     356             :             nnp%arc(ind)%layer(1)%node(j) = &
     357     3722461 :                (nnp%rad(ind)%y(j) - nnp%rad(ind)%loc_av(j))
     358             :          END DO
     359      248177 :          off = nnp%n_rad(ind)
     360     2067689 :          DO j = 1, nnp%n_ang(ind)
     361             :             nnp%arc(ind)%layer(1)%node(j + off) = &
     362     2067689 :                (nnp%ang(ind)%y(j) - nnp%ang(ind)%loc_av(j))
     363             :          END DO
     364             : 
     365      248177 :          IF (nnp%scale_acsf) THEN
     366     3722461 :             DO j = 1, nnp%n_rad(ind)
     367             :                nnp%arc(ind)%layer(1)%node(j) = &
     368             :                   nnp%arc(ind)%layer(1)%node(j)/ &
     369             :                   (nnp%rad(ind)%loc_max(j) - nnp%rad(ind)%loc_min(j))* &
     370     3722461 :                   (nnp%scmax - nnp%scmin) + nnp%scmin
     371             :             END DO
     372      248177 :             off = nnp%n_rad(ind)
     373     2067689 :             DO j = 1, nnp%n_ang(ind)
     374             :                nnp%arc(ind)%layer(1)%node(j + off) = &
     375             :                   nnp%arc(ind)%layer(1)%node(j + off)/ &
     376             :                   (nnp%ang(ind)%loc_max(j) - nnp%ang(ind)%loc_min(j))* &
     377     2067689 :                   (nnp%scmax - nnp%scmin) + nnp%scmin
     378             :             END DO
     379             :          END IF
     380           0 :       ELSE IF (nnp%scale_acsf) THEN
     381           0 :          DO j = 1, nnp%n_rad(ind)
     382             :             nnp%arc(ind)%layer(1)%node(j) = &
     383             :                (nnp%rad(ind)%y(j) - nnp%rad(ind)%loc_min(j))/ &
     384             :                (nnp%rad(ind)%loc_max(j) - nnp%rad(ind)%loc_min(j))* &
     385           0 :                (nnp%scmax - nnp%scmin) + nnp%scmin
     386             :          END DO
     387           0 :          off = nnp%n_rad(ind)
     388           0 :          DO j = 1, nnp%n_ang(ind)
     389             :             nnp%arc(ind)%layer(1)%node(j + off) = &
     390             :                (nnp%ang(ind)%y(j) - nnp%ang(ind)%loc_min(j))/ &
     391             :                (nnp%ang(ind)%loc_max(j) - nnp%ang(ind)%loc_min(j))* &
     392           0 :                (nnp%scmax - nnp%scmin) + nnp%scmin
     393             :          END DO
     394           0 :       ELSE IF (nnp%scale_sigma_acsf) THEN
     395           0 :          DO j = 1, nnp%n_rad(ind)
     396             :             nnp%arc(ind)%layer(1)%node(j) = &
     397             :                (nnp%rad(ind)%y(j) - nnp%rad(ind)%loc_av(j))/ &
     398             :                nnp%rad(ind)%sigma(j)* &
     399           0 :                (nnp%scmax - nnp%scmin) + nnp%scmin
     400             :          END DO
     401           0 :          off = nnp%n_rad(ind)
     402           0 :          DO j = 1, nnp%n_ang(ind)
     403             :             nnp%arc(ind)%layer(1)%node(j + off) = &
     404             :                (nnp%ang(ind)%y(j) - nnp%ang(ind)%loc_av(j))/ &
     405             :                nnp%ang(ind)%sigma(j)* &
     406           0 :                (nnp%scmax - nnp%scmin) + nnp%scmin
     407             :          END DO
     408             :       ELSE
     409           0 :          DO j = 1, nnp%n_rad(ind)
     410           0 :             nnp%arc(ind)%layer(1)%node(j) = nnp%rad(ind)%y(j)
     411             :          END DO
     412           0 :          off = nnp%n_rad(ind)
     413           0 :          DO j = 1, nnp%n_ang(ind)
     414           0 :             nnp%arc(ind)%layer(1)%node(j + off) = nnp%ang(ind)%y(j)
     415             :          END DO
     416             :       END IF
     417             : 
     418      248177 :       IF (PRESENT(dsymdxyz)) THEN
     419       19105 :          IF (nnp%scale_acsf) THEN
     420     2477828 :             DO k = 1, nnp%num_atoms
     421    41759796 :                DO j = 1, nnp%n_rad(ind)
     422             :                   dsymdxyz(:, j, k) = dsymdxyz(:, j, k)/ &
     423             :                                       (nnp%rad(ind)%loc_max(j) - &
     424             :                                        nnp%rad(ind)%loc_min(j))* &
     425   159586595 :                                       (nnp%scmax - nnp%scmin)
     426             :                END DO
     427             :             END DO
     428       19105 :             off = nnp%n_rad(ind)
     429     2477828 :             DO k = 1, nnp%num_atoms
     430    31848104 :                DO j = 1, nnp%n_ang(ind)
     431             :                   dsymdxyz(:, j + off, k) = dsymdxyz(:, j + off, k)/ &
     432             :                                             (nnp%ang(ind)%loc_max(j) - &
     433             :                                              nnp%ang(ind)%loc_min(j))* &
     434   119939827 :                                             (nnp%scmax - nnp%scmin)
     435             :                END DO
     436             :             END DO
     437           0 :          ELSE IF (nnp%scale_sigma_acsf) THEN
     438           0 :             DO k = 1, nnp%num_atoms
     439           0 :                DO j = 1, nnp%n_rad(ind)
     440             :                   dsymdxyz(:, j, k) = dsymdxyz(:, j, k)/ &
     441             :                                       nnp%rad(ind)%sigma(j)* &
     442           0 :                                       (nnp%scmax - nnp%scmin)
     443             :                END DO
     444             :             END DO
     445           0 :             off = nnp%n_rad(ind)
     446           0 :             DO k = 1, nnp%num_atoms
     447           0 :                DO j = 1, nnp%n_ang(ind)
     448             :                   dsymdxyz(:, j + off, k) = dsymdxyz(:, j + off, k)/ &
     449             :                                             nnp%ang(ind)%sigma(j)* &
     450           0 :                                             (nnp%scmax - nnp%scmin)
     451             :                END DO
     452             :             END DO
     453             :          END IF
     454             :       END IF
     455             : 
     456      248177 :       IF (PRESENT(stress)) THEN
     457        2112 :          IF (nnp%scale_acsf) THEN
     458       35904 :             DO j = 1, nnp%n_rad(ind)
     459             :                stress(:, :, j) = stress(:, :, j)/ &
     460             :                                  (nnp%rad(ind)%loc_max(j) - &
     461             :                                   nnp%rad(ind)%loc_min(j))* &
     462      441408 :                                  (nnp%scmax - nnp%scmin)
     463             :             END DO
     464        2112 :             off = nnp%n_rad(ind)
     465       27456 :             DO j = 1, nnp%n_ang(ind)
     466             :                stress(:, :, j + off) = stress(:, :, j + off)/ &
     467             :                                        (nnp%ang(ind)%loc_max(j) - &
     468             :                                         nnp%ang(ind)%loc_min(j))* &
     469      331584 :                                        (nnp%scmax - nnp%scmin)
     470             :             END DO
     471           0 :          ELSE IF (nnp%scale_sigma_acsf) THEN
     472           0 :             DO j = 1, nnp%n_rad(ind)
     473             :                stress(:, :, j) = stress(:, :, j)/ &
     474             :                                  nnp%rad(ind)%sigma(j)* &
     475           0 :                                  (nnp%scmax - nnp%scmin)
     476             :             END DO
     477           0 :             off = nnp%n_rad(ind)
     478           0 :             DO j = 1, nnp%n_ang(ind)
     479             :                stress(:, :, j + off) = stress(:, :, j + off)/ &
     480             :                                        nnp%ang(ind)%sigma(j)* &
     481           0 :                                        (nnp%scmax - nnp%scmin)
     482             :             END DO
     483             :          END IF
     484             :       END IF
     485             : 
     486      248177 :    END SUBROUTINE nnp_scale_acsf
     487             : 
     488             : ! **************************************************************************************************
     489             : !> \brief Calculate radial symmetry function and gradient (optinal)
     490             : !>        for given displacment vecotr rvect of atom i and j
     491             : !> \param nnp ...
     492             : !> \param ind ...
     493             : !> \param s ...
     494             : !> \param rvect ...
     495             : !> \param r ...
     496             : !> \param sym ...
     497             : !> \param force ...
     498             : !> \date   2020-10-10
     499             : !> \author Christoph Schran (christoph.schran@rub.de)
     500             : ! **************************************************************************************************
     501     3290284 :    SUBROUTINE nnp_calc_rad(nnp, ind, s, rvect, r, sym, force)
     502             : 
     503             :       TYPE(nnp_type), INTENT(IN)                         :: nnp
     504             :       INTEGER, INTENT(IN)                                :: ind, s
     505             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rvect
     506             :       REAL(KIND=dp), INTENT(IN)                          :: r
     507             :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: sym
     508             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT), &
     509             :          OPTIONAL                                        :: force
     510             : 
     511             :       INTEGER                                            :: k, sf
     512             :       REAL(KIND=dp)                                      :: dfcutdr, dsymdr, eta, fcut, funccut, rs, &
     513             :                                                             tmp
     514             :       REAL(KIND=dp), DIMENSION(3)                        :: drdx
     515             : 
     516             :       !init
     517     3290284 :       drdx = 0.0_dp
     518     3290284 :       fcut = 0.0_dp
     519     3290284 :       dfcutdr = 0.0_dp
     520             : 
     521             :       !Calculate cutoff function and partial derivative
     522     3290284 :       funccut = nnp%rad(ind)%symfgrp(s)%cutoff !cutoff
     523     3659254 :       SELECT CASE (nnp%cut_type)
     524             :       CASE (nnp_cut_cos)
     525      368970 :          tmp = pi*r/funccut
     526      368970 :          fcut = 0.5_dp*(COS(tmp) + 1.0_dp)
     527      368970 :          IF (PRESENT(force)) THEN
     528       10956 :             dfcutdr = 0.5_dp*(-SIN(tmp))*(pi/funccut)
     529             :          END IF
     530             :       CASE (nnp_cut_tanh)
     531     2921314 :          tmp = TANH(1.0_dp - r/funccut)
     532     2921314 :          fcut = tmp**3
     533     2921314 :          IF (PRESENT(force)) THEN
     534     1348812 :             dfcutdr = (-3.0_dp/funccut)*(tmp**2 - tmp**4)
     535             :          END IF
     536             :       CASE DEFAULT
     537     3290284 :          CPABORT("NNP| Cutoff function unknown")
     538             :       END SELECT
     539             : 
     540     7369588 :       IF (PRESENT(force)) drdx(:) = rvect(:)/r
     541             : 
     542             :       !loop over sym fncts of sym fnct group s
     543    28836678 :       DO sf = 1, nnp%rad(ind)%symfgrp(s)%n_symf
     544    25546394 :          k = nnp%rad(ind)%symfgrp(s)%symf(sf) !symf indice
     545    25546394 :          eta = nnp%rad(ind)%eta(k) !eta
     546    25546394 :          rs = nnp%rad(ind)%rs(k) !rshift
     547             : 
     548             :          ! Calculate radial symmetry function
     549    25546394 :          sym(sf) = EXP(-eta*(r - rs)**2)
     550             : 
     551             :          ! Calculate partial derivatives of symmetry function and distance
     552             :          ! and combine them to obtain force
     553    25546394 :          IF (PRESENT(force)) THEN
     554    10854876 :             dsymdr = sym(sf)*(-2.0_dp*eta*(r - rs))
     555    43419504 :             force(:, sf) = fcut*dsymdr*drdx(:) + sym(sf)*dfcutdr*drdx(:)
     556             :          END IF
     557             : 
     558             :          ! combine radial symmetry function and cutoff function
     559    28836678 :          sym(sf) = sym(sf)*fcut
     560             :       END DO
     561             : 
     562     3290284 :    END SUBROUTINE nnp_calc_rad
     563             : 
     564             : ! **************************************************************************************************
     565             : !> \brief Calculate angular symmetry function and gradient (optinal)
     566             : !>        for given displacment vectors rvect1,2,3 of atom i,j and k
     567             : !> \param nnp ...
     568             : !> \param ind ...
     569             : !> \param s ...
     570             : !> \param rvect1 ...
     571             : !> \param rvect2 ...
     572             : !> \param rvect3 ...
     573             : !> \param r1 ...
     574             : !> \param r2 ...
     575             : !> \param r3 ...
     576             : !> \param sym ...
     577             : !> \param force ...
     578             : !> \date   2020-10-10
     579             : !> \author Christoph Schran (christoph.schran@rub.de)
     580             : ! **************************************************************************************************
     581    50689030 :    SUBROUTINE nnp_calc_ang(nnp, ind, s, rvect1, rvect2, rvect3, r1, r2, r3, sym, force)
     582             : 
     583             :       TYPE(nnp_type), INTENT(IN)                         :: nnp
     584             :       INTEGER, INTENT(IN)                                :: ind, s
     585             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rvect1, rvect2, rvect3
     586             :       REAL(KIND=dp), INTENT(IN)                          :: r1, r2, r3
     587             :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: sym
     588             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(OUT), &
     589             :          OPTIONAL                                        :: force
     590             : 
     591             :       INTEGER                                            :: i, m, sf
     592             :       REAL(KIND=dp) :: angular, costheta, dfcutdr1, dfcutdr2, dfcutdr3, dsymdr1, dsymdr2, dsymdr3, &
     593             :          eta, f, fcut, fcut1, fcut2, fcut3, ftot, g, lam, pref, prefzeta, rsqr1, rsqr2, rsqr3, &
     594             :          symtmp, tmp, tmp1, tmp2, tmp3, tmpzeta, zeta
     595             :       REAL(KIND=dp), DIMENSION(3) :: dangulardx1, dangulardx2, dangulardx3, dcosthetadx1, &
     596             :          dcosthetadx2, dcosthetadx3, dfdx1, dfdx2, dfdx3, dgdx1, dgdx2, dgdx3, dr1dx, dr2dx, dr3dx
     597             : 
     598    50689030 :       rsqr1 = r1**2
     599    50689030 :       rsqr2 = r2**2
     600    50689030 :       rsqr3 = r3**2
     601             : 
     602             :       !init
     603    50689030 :       dangulardx1 = 0.0_dp
     604    50689030 :       dangulardx2 = 0.0_dp
     605    50689030 :       dangulardx3 = 0.0_dp
     606    50689030 :       dr1dx = 0.0_dp
     607    50689030 :       dr2dx = 0.0_dp
     608    50689030 :       dr3dx = 0.0_dp
     609    50689030 :       ftot = 0.0_dp
     610    50689030 :       dfcutdr1 = 0.0_dp
     611    50689030 :       dfcutdr2 = 0.0_dp
     612    50689030 :       dfcutdr3 = 0.0_dp
     613             : 
     614             :       ! Calculate cos(theta)
     615             :       ! use law of cosine for theta
     616             :       ! cos(ang(r1,r2)) = (r3**2 - r1**2 - r2**2)/(-2*r1*r2)
     617             :       !                   |          f           |    g    |
     618    50689030 :       f = (rsqr3 - rsqr1 - rsqr2)
     619    50689030 :       g = -2.0_dp*r1*r2
     620    50689030 :       costheta = f/g
     621             : 
     622             :       ! Calculate cutoff function and partial derivatives
     623    50689030 :       fcut = nnp%ang(ind)%symfgrp(s)%cutoff !cutoff
     624    50894834 :       SELECT CASE (nnp%cut_type)
     625             :       CASE (nnp_cut_cos)
     626      205804 :          tmp1 = pi*r1/fcut
     627      205804 :          tmp2 = pi*r2/fcut
     628      205804 :          tmp3 = pi*r3/fcut
     629      205804 :          fcut1 = 0.5_dp*(COS(tmp1) + 1.0_dp)
     630      205804 :          fcut2 = 0.5_dp*(COS(tmp2) + 1.0_dp)
     631      205804 :          fcut3 = 0.5_dp*(COS(tmp3) + 1.0_dp)
     632      205804 :          ftot = fcut1*fcut2*fcut3
     633      205804 :          IF (PRESENT(force)) THEN
     634        6242 :             pref = 0.5_dp*(pi/fcut)
     635        6242 :             dfcutdr1 = pref*(-SIN(tmp1))*fcut2*fcut3
     636        6242 :             dfcutdr2 = pref*(-SIN(tmp2))*fcut1*fcut3
     637        6242 :             dfcutdr3 = pref*(-SIN(tmp3))*fcut1*fcut2
     638             :          END IF
     639             :       CASE (nnp_cut_tanh)
     640    50483226 :          tmp1 = TANH(1.0_dp - r1/fcut)
     641    50483226 :          tmp2 = TANH(1.0_dp - r2/fcut)
     642    50483226 :          tmp3 = TANH(1.0_dp - r3/fcut)
     643    50483226 :          fcut1 = tmp1**3
     644    50483226 :          fcut2 = tmp2**3
     645    50483226 :          fcut3 = tmp3**3
     646    50483226 :          ftot = fcut1*fcut2*fcut3
     647    50483226 :          IF (PRESENT(force)) THEN
     648    23308719 :             pref = -3.0_dp/fcut
     649    23308719 :             dfcutdr1 = pref*(tmp1**2 - tmp1**4)*fcut2*fcut3
     650    23308719 :             dfcutdr2 = pref*(tmp2**2 - tmp2**4)*fcut1*fcut3
     651    23308719 :             dfcutdr3 = pref*(tmp3**2 - tmp3**4)*fcut1*fcut2
     652             :          END IF
     653             :       CASE DEFAULT
     654    50689030 :          CPABORT("NNP| Cutoff function unknown")
     655             :       END SELECT
     656             : 
     657    50689030 :       IF (PRESENT(force)) THEN
     658    93259844 :          dr1dx(:) = rvect1(:)/r1
     659    93259844 :          dr2dx(:) = rvect2(:)/r2
     660    93259844 :          dr3dx(:) = rvect3(:)/r3
     661             :       END IF
     662             : 
     663             :       !loop over associated sym fncts
     664   339848340 :       DO sf = 1, nnp%ang(ind)%symfgrp(s)%n_symf
     665   289159310 :          m = nnp%ang(ind)%symfgrp(s)%symf(sf)
     666   289159310 :          lam = nnp%ang(ind)%lam(m) !lambda
     667   289159310 :          zeta = nnp%ang(ind)%zeta(m) !zeta
     668   289159310 :          prefzeta = nnp%ang(ind)%prefzeta(m) ! 2**(1-zeta)
     669   289159310 :          eta = nnp%ang(ind)%eta(m) !eta
     670             : 
     671   289159310 :          tmp = (1.0_dp + lam*costheta)
     672             : 
     673   289159310 :          IF (tmp <= 0.0_dp) THEN
     674           0 :             sym(sf) = 0.0_dp
     675           0 :             IF (PRESENT(force)) force(:, :, sf) = 0.0_dp
     676             :             CYCLE
     677             :          END IF
     678             : 
     679             :          ! Calculate symmetry function
     680             :          ! Calculate angular symmetry function
     681             :          ! ang = (1+lam*cos(theta_ijk))**zeta
     682   289159310 :          i = NINT(zeta)
     683   289159310 :          IF (1.0_dp*i == zeta) THEN
     684   289159310 :             tmpzeta = tmp**(i - 1)   ! integer power is a LOT faster
     685             :          ELSE
     686           0 :             tmpzeta = tmp**(zeta - 1.0_dp)
     687             :          END IF
     688   289159310 :          angular = tmpzeta*tmp
     689             :          ! exponential part:
     690             :          ! exp(-eta*(r1**2+r2**2+r3**2))
     691   289159310 :          symtmp = EXP(-eta*(rsqr1 + rsqr2 + rsqr3))
     692             : 
     693             :          ! Partial derivatives (f/g)' = (f'g - fg')/g^2
     694   289159310 :          IF (PRESENT(force)) THEN
     695   133234853 :             pref = zeta*(tmpzeta)/g**2
     696   532939412 :             DO i = 1, 3
     697   399704559 :                dfdx1(i) = -2.0_dp*lam*(rvect1(i) + rvect2(i))
     698   399704559 :                dfdx2(i) = 2.0_dp*lam*(rvect3(i) + rvect1(i))
     699   399704559 :                dfdx3(i) = 2.0_dp*lam*(rvect2(i) - rvect3(i))
     700             : 
     701   399704559 :                tmp1 = 2.0_dp*r2*dr1dx(i)
     702   399704559 :                tmp2 = 2.0_dp*r1*dr2dx(i)
     703   399704559 :                dgdx1(i) = -(tmp1 + tmp2)
     704             :                dgdx2(i) = tmp1
     705             :                dgdx3(i) = tmp2
     706             : 
     707   399704559 :                dcosthetadx1(i) = dfdx1(i)*g - lam*f*dgdx1(i)
     708   399704559 :                dcosthetadx2(i) = dfdx2(i)*g - lam*f*dgdx2(i)
     709   399704559 :                dcosthetadx3(i) = dfdx3(i)*g - lam*f*dgdx3(i)
     710             : 
     711   399704559 :                dangulardx1(i) = pref*dcosthetadx1(i)
     712   399704559 :                dangulardx2(i) = pref*dcosthetadx2(i)
     713   532939412 :                dangulardx3(i) = pref*dcosthetadx3(i)
     714             :             END DO
     715             : 
     716             :             ! Calculate partial derivatives of exponential part and distance
     717             :             ! and combine partial derivatives to obtain force
     718   133234853 :             pref = prefzeta
     719   133234853 :             tmp = -2.0_dp*symtmp*eta
     720   133234853 :             dsymdr1 = tmp*r1
     721   133234853 :             dsymdr2 = tmp*r2
     722   133234853 :             dsymdr3 = tmp*r3
     723             : 
     724             :             ! G(r1,r2,r3) = pref*angular(r1,r2,r3)*exp(r1,r2,r3)*fcut(r1,r2,r3)
     725             :             ! dG/dx1 = (dangular/dx1*  exp    *    fcut   +
     726             :             !            angular    * dexp/dx1*    fcut   +
     727             :             !            angular    *  exp    *  dfcut/dx1)*pref
     728             :             ! dr1/dx1 = -dr1/dx2
     729   133234853 :             tmp = pref*symtmp*ftot
     730   133234853 :             tmp1 = pref*angular*(ftot*dsymdr1 + dfcutdr1*symtmp)
     731   133234853 :             tmp2 = pref*angular*(ftot*dsymdr2 + dfcutdr2*symtmp)
     732   133234853 :             tmp3 = pref*angular*(ftot*dsymdr3 + dfcutdr3*symtmp)
     733   532939412 :             DO i = 1, 3
     734   399704559 :                force(i, 1, sf) = tmp*dangulardx1(i) + tmp1*dr1dx(i) + tmp2*dr2dx(i)
     735   399704559 :                force(i, 2, sf) = tmp*dangulardx2(i) - tmp1*dr1dx(i) + tmp3*dr3dx(i)
     736   532939412 :                force(i, 3, sf) = tmp*dangulardx3(i) - tmp2*dr2dx(i) - tmp3*dr3dx(i)
     737             :             END DO
     738             :          END IF
     739             : 
     740             :          ! Don't forget prefactor: 2**(1-ang%zeta)
     741   289159310 :          pref = prefzeta
     742             :          ! combine angular and exponential part with cutoff function
     743   339848340 :          sym(sf) = pref*angular*symtmp*ftot
     744             :       END DO
     745             : 
     746    50689030 :    END SUBROUTINE nnp_calc_ang
     747             : 
     748             : ! **************************************************************************************************
     749             : !> \brief Sort element array according to atomic number
     750             : !> \param ele ...
     751             : !> \param nuc_ele ...
     752             : !> \date   2020-10-10
     753             : !> \author Christoph Schran (christoph.schran@rub.de)
     754             : ! **************************************************************************************************
     755          15 :    SUBROUTINE nnp_sort_ele(ele, nuc_ele)
     756             :       CHARACTER(len=2), DIMENSION(:), INTENT(INOUT)      :: ele
     757             :       INTEGER, DIMENSION(:), INTENT(INOUT)               :: nuc_ele
     758             : 
     759             :       CHARACTER(len=2)                                   :: tmp_ele
     760             :       INTEGER                                            :: i, j, loc, minimum, tmp_nuc_ele
     761             : 
     762             :       ! Determine atomic number
     763          46 :       DO i = 1, SIZE(ele)
     764          46 :          CALL get_ptable_info(ele(i), number=nuc_ele(i))
     765             :       END DO
     766             : 
     767             :       ! Sort both arrays
     768          31 :       DO i = 1, SIZE(ele) - 1
     769          16 :          minimum = nuc_ele(i)
     770          16 :          loc = i
     771          33 :          DO j = i + 1, SIZE(ele)
     772          33 :             IF (nuc_ele(j) .LT. minimum) THEN
     773          16 :                loc = j
     774          16 :                minimum = nuc_ele(j)
     775             :             END IF
     776             :          END DO
     777          16 :          tmp_nuc_ele = nuc_ele(i)
     778          16 :          nuc_ele(i) = nuc_ele(loc)
     779          16 :          nuc_ele(loc) = tmp_nuc_ele
     780             : 
     781          16 :          tmp_ele = ele(i)
     782          16 :          ele(i) = ele(loc)
     783          31 :          ele(loc) = tmp_ele
     784             : 
     785             :       END DO
     786             : 
     787          15 :    END SUBROUTINE nnp_sort_ele
     788             : 
     789             : ! **************************************************************************************************
     790             : !> \brief Sort symmetry functions according to different criteria
     791             : !> \param nnp ...
     792             : !> \date   2020-10-10
     793             : !> \author Christoph Schran (christoph.schran@rub.de)
     794             : ! **************************************************************************************************
     795          15 :    SUBROUTINE nnp_sort_acsf(nnp)
     796             :       TYPE(nnp_type), INTENT(INOUT)                      :: nnp
     797             : 
     798             :       INTEGER                                            :: i, j, k, loc
     799             : 
     800             :       ! First sort is according to symmetry function type
     801             :       ! This is done manually, since data structures are separate
     802             :       ! Note: Bubble sort is OK here, since small sort + special
     803          46 :       DO i = 1, nnp%n_ele
     804             :          ! sort by cutoff
     805             :          ! rad
     806         486 :          DO j = 1, nnp%n_rad(i) - 1
     807         455 :             loc = j
     808        4051 :             DO k = j + 1, nnp%n_rad(i)
     809        4051 :                IF (nnp%rad(i)%funccut(loc) .GT. nnp%rad(i)%funccut(k)) THEN
     810           6 :                   loc = k
     811             :                END IF
     812             :             END DO
     813             :             ! swap symfnct
     814         486 :             CALL nnp_swaprad(nnp%rad(i), j, loc)
     815             :          END DO
     816             : 
     817             :          ! sort by eta
     818             :          ! rad
     819         486 :          DO j = 1, nnp%n_rad(i) - 1
     820         455 :             loc = j
     821        4051 :             DO k = j + 1, nnp%n_rad(i)
     822        3596 :                IF (nnp%rad(i)%funccut(loc) .EQ. nnp%rad(i)%funccut(k) .AND. &
     823         455 :                    nnp%rad(i)%eta(loc) .GT. nnp%rad(i)%eta(k)) THEN
     824         484 :                   loc = k
     825             :                END IF
     826             :             END DO
     827             :             ! swap symfnct
     828         486 :             CALL nnp_swaprad(nnp%rad(i), j, loc)
     829             :          END DO
     830             : 
     831             :          ! sort by rshift
     832             :          ! rad
     833         486 :          DO j = 1, nnp%n_rad(i) - 1
     834         455 :             loc = j
     835        4051 :             DO k = j + 1, nnp%n_rad(i)
     836             :                IF (nnp%rad(i)%funccut(loc) .EQ. nnp%rad(i)%funccut(k) .AND. &
     837        3596 :                    nnp%rad(i)%eta(loc) .EQ. nnp%rad(i)%eta(k) .AND. &
     838         455 :                    nnp%rad(i)%rs(loc) .GT. nnp%rad(i)%rs(k)) THEN
     839          56 :                   loc = k
     840             :                END IF
     841             :             END DO
     842             :             ! swap symfnct
     843         486 :             CALL nnp_swaprad(nnp%rad(i), j, loc)
     844             :          END DO
     845             : 
     846             :          ! sort by ele
     847             :          ! rad
     848         486 :          DO j = 1, nnp%n_rad(i) - 1
     849         455 :             loc = j
     850        4051 :             DO k = j + 1, nnp%n_rad(i)
     851             :                IF (nnp%rad(i)%funccut(loc) .EQ. nnp%rad(i)%funccut(k) .AND. &
     852             :                    nnp%rad(i)%eta(loc) .EQ. nnp%rad(i)%eta(k) .AND. &
     853        3596 :                    nnp%rad(i)%rs(loc) .EQ. nnp%rad(i)%rs(k) .AND. &
     854         455 :                    nnp%rad(i)%nuc_ele(loc) .GT. nnp%rad(i)%nuc_ele(k)) THEN
     855           0 :                   loc = k
     856             :                END IF
     857             :             END DO
     858             :             ! swap symfnct
     859         486 :             CALL nnp_swaprad(nnp%rad(i), j, loc)
     860             :          END DO
     861             : 
     862             :          ! ang
     863             :          ! sort by cutoff
     864         370 :          DO j = 1, nnp%n_ang(i) - 1
     865         339 :             loc = j
     866        2440 :             DO k = j + 1, nnp%n_ang(i)
     867        2440 :                IF (nnp%ang(i)%funccut(loc) .GT. nnp%ang(i)%funccut(k)) THEN
     868           3 :                   loc = k
     869             :                END IF
     870             :             END DO
     871             :             ! swap symfnct
     872         370 :             CALL nnp_swapang(nnp%ang(i), j, loc)
     873             :          END DO
     874             : 
     875             :          ! sort by eta
     876             :          ! ang
     877         370 :          DO j = 1, nnp%n_ang(i) - 1
     878         339 :             loc = j
     879        2440 :             DO k = j + 1, nnp%n_ang(i)
     880        2101 :                IF (nnp%ang(i)%funccut(loc) .EQ. nnp%ang(i)%funccut(k) .AND. &
     881         339 :                    nnp%ang(i)%eta(loc) .GT. nnp%ang(i)%eta(k)) THEN
     882         392 :                   loc = k
     883             :                END IF
     884             :             END DO
     885             :             ! swap symfnct
     886         370 :             CALL nnp_swapang(nnp%ang(i), j, loc)
     887             :          END DO
     888             : 
     889             :          ! sort by zeta
     890             :          ! ang
     891         370 :          DO j = 1, nnp%n_ang(i) - 1
     892         339 :             loc = j
     893        2440 :             DO k = j + 1, nnp%n_ang(i)
     894             :                IF (nnp%ang(i)%funccut(loc) .EQ. nnp%ang(i)%funccut(k) .AND. &
     895        2101 :                    nnp%ang(i)%eta(loc) .EQ. nnp%ang(i)%eta(k) .AND. &
     896         339 :                    nnp%ang(i)%zeta(loc) .GT. nnp%ang(i)%zeta(k)) THEN
     897           7 :                   loc = k
     898             :                END IF
     899             :             END DO
     900             :             ! swap symfnct
     901         370 :             CALL nnp_swapang(nnp%ang(i), j, loc)
     902             :          END DO
     903             : 
     904             :          ! sort by lambda
     905             :          ! ang
     906         370 :          DO j = 1, nnp%n_ang(i) - 1
     907         339 :             loc = j
     908        2440 :             DO k = j + 1, nnp%n_ang(i)
     909             :                IF (nnp%ang(i)%funccut(loc) .EQ. nnp%ang(i)%funccut(k) .AND. &
     910             :                    nnp%ang(i)%eta(loc) .EQ. nnp%ang(i)%eta(k) .AND. &
     911        2101 :                    nnp%ang(i)%zeta(loc) .EQ. nnp%ang(i)%zeta(k) .AND. &
     912         339 :                    nnp%ang(i)%lam(loc) .GT. nnp%ang(i)%lam(k)) THEN
     913         148 :                   loc = k
     914             :                END IF
     915             :             END DO
     916             :             ! swap symfnct
     917         370 :             CALL nnp_swapang(nnp%ang(i), j, loc)
     918             :          END DO
     919             : 
     920             :          ! sort by ele
     921             :          ! ang, ele1
     922         370 :          DO j = 1, nnp%n_ang(i) - 1
     923         339 :             loc = j
     924        2440 :             DO k = j + 1, nnp%n_ang(i)
     925             :                IF (nnp%ang(i)%funccut(loc) .EQ. nnp%ang(i)%funccut(k) .AND. &
     926             :                    nnp%ang(i)%eta(loc) .EQ. nnp%ang(i)%eta(k) .AND. &
     927             :                    nnp%ang(i)%zeta(loc) .EQ. nnp%ang(i)%zeta(k) .AND. &
     928        2101 :                    nnp%ang(i)%lam(loc) .EQ. nnp%ang(i)%lam(k) .AND. &
     929         339 :                    nnp%ang(i)%nuc_ele1(loc) .GT. nnp%ang(i)%nuc_ele1(k)) THEN
     930          42 :                   loc = k
     931             :                END IF
     932             :             END DO
     933             :             ! swap symfnct
     934         370 :             CALL nnp_swapang(nnp%ang(i), j, loc)
     935             :          END DO
     936             :          ! ang, ele2
     937         385 :          DO j = 1, nnp%n_ang(i) - 1
     938         339 :             loc = j
     939        2440 :             DO k = j + 1, nnp%n_ang(i)
     940             :                IF (nnp%ang(i)%funccut(loc) .EQ. nnp%ang(i)%funccut(k) .AND. &
     941             :                    nnp%ang(i)%eta(loc) .EQ. nnp%ang(i)%eta(k) .AND. &
     942             :                    nnp%ang(i)%zeta(loc) .EQ. nnp%ang(i)%zeta(k) .AND. &
     943             :                    nnp%ang(i)%lam(loc) .EQ. nnp%ang(i)%lam(k) .AND. &
     944        2101 :                    nnp%ang(i)%nuc_ele1(loc) .EQ. nnp%ang(i)%nuc_ele1(k) .AND. &
     945         339 :                    nnp%ang(i)%nuc_ele2(loc) .GT. nnp%ang(i)%nuc_ele2(k)) THEN
     946          29 :                   loc = k
     947             :                END IF
     948             :             END DO
     949             :             ! swap symfnct
     950         370 :             CALL nnp_swapang(nnp%ang(i), j, loc)
     951             :          END DO
     952             :       END DO
     953             : 
     954          15 :    END SUBROUTINE nnp_sort_acsf
     955             : 
     956             : ! **************************************************************************************************
     957             : !> \brief Swap two radial symmetry functions
     958             : !> \param rad ...
     959             : !> \param i ...
     960             : !> \param j ...
     961             : !> \date   2020-10-10
     962             : !> \author Christoph Schran (christoph.schran@rub.de)
     963             : ! **************************************************************************************************
     964        1820 :    SUBROUTINE nnp_swaprad(rad, i, j)
     965             :       TYPE(nnp_acsf_rad_type), INTENT(INOUT)             :: rad
     966             :       INTEGER, INTENT(IN)                                :: i, j
     967             : 
     968             :       CHARACTER(len=2)                                   :: tmpc
     969             :       INTEGER                                            :: tmpi
     970             :       REAL(KIND=dp)                                      :: tmpr
     971             : 
     972        1820 :       tmpr = rad%funccut(i)
     973        1820 :       rad%funccut(i) = rad%funccut(j)
     974        1820 :       rad%funccut(j) = tmpr
     975             : 
     976        1820 :       tmpr = rad%eta(i)
     977        1820 :       rad%eta(i) = rad%eta(j)
     978        1820 :       rad%eta(j) = tmpr
     979             : 
     980        1820 :       tmpr = rad%rs(i)
     981        1820 :       rad%rs(i) = rad%rs(j)
     982        1820 :       rad%rs(j) = tmpr
     983             : 
     984        1820 :       tmpc = rad%ele(i)
     985        1820 :       rad%ele(i) = rad%ele(j)
     986        1820 :       rad%ele(j) = tmpc
     987             : 
     988        1820 :       tmpi = rad%nuc_ele(i)
     989        1820 :       rad%nuc_ele(i) = rad%nuc_ele(j)
     990        1820 :       rad%nuc_ele(j) = tmpi
     991             : 
     992        1820 :    END SUBROUTINE nnp_swaprad
     993             : 
     994             : ! **************************************************************************************************
     995             : !> \brief Swap two angular symmetry functions
     996             : !> \param ang ...
     997             : !> \param i ...
     998             : !> \param j ...
     999             : !> \date   2020-10-10
    1000             : !> \author Christoph Schran (christoph.schran@rub.de)
    1001             : ! **************************************************************************************************
    1002        2034 :    SUBROUTINE nnp_swapang(ang, i, j)
    1003             :       TYPE(nnp_acsf_ang_type), INTENT(INOUT)             :: ang
    1004             :       INTEGER, INTENT(IN)                                :: i, j
    1005             : 
    1006             :       CHARACTER(len=2)                                   :: tmpc
    1007             :       INTEGER                                            :: tmpi
    1008             :       REAL(KIND=dp)                                      :: tmpr
    1009             : 
    1010        2034 :       tmpr = ang%funccut(i)
    1011        2034 :       ang%funccut(i) = ang%funccut(j)
    1012        2034 :       ang%funccut(j) = tmpr
    1013             : 
    1014        2034 :       tmpr = ang%eta(i)
    1015        2034 :       ang%eta(i) = ang%eta(j)
    1016        2034 :       ang%eta(j) = tmpr
    1017             : 
    1018        2034 :       tmpr = ang%zeta(i)
    1019        2034 :       ang%zeta(i) = ang%zeta(j)
    1020        2034 :       ang%zeta(j) = tmpr
    1021             : 
    1022        2034 :       tmpr = ang%prefzeta(i)
    1023        2034 :       ang%prefzeta(i) = ang%prefzeta(j)
    1024        2034 :       ang%prefzeta(j) = tmpr
    1025             : 
    1026        2034 :       tmpr = ang%lam(i)
    1027        2034 :       ang%lam(i) = ang%lam(j)
    1028        2034 :       ang%lam(j) = tmpr
    1029             : 
    1030        2034 :       tmpc = ang%ele1(i)
    1031        2034 :       ang%ele1(i) = ang%ele1(j)
    1032        2034 :       ang%ele1(j) = tmpc
    1033             : 
    1034        2034 :       tmpi = ang%nuc_ele1(i)
    1035        2034 :       ang%nuc_ele1(i) = ang%nuc_ele1(j)
    1036        2034 :       ang%nuc_ele1(j) = tmpi
    1037             : 
    1038        2034 :       tmpc = ang%ele2(i)
    1039        2034 :       ang%ele2(i) = ang%ele2(j)
    1040        2034 :       ang%ele2(j) = tmpc
    1041             : 
    1042        2034 :       tmpi = ang%nuc_ele2(i)
    1043        2034 :       ang%nuc_ele2(i) = ang%nuc_ele2(j)
    1044        2034 :       ang%nuc_ele2(j) = tmpi
    1045             : 
    1046        2034 :    END SUBROUTINE nnp_swapang
    1047             : 
    1048             : ! **************************************************************************************************
    1049             : !> \brief Initialize symmetry function groups
    1050             : !> \param nnp ...
    1051             : !> \date   2020-10-10
    1052             : !> \author Christoph Schran (christoph.schran@rub.de)
    1053             : ! **************************************************************************************************
    1054          15 :    SUBROUTINE nnp_init_acsf_groups(nnp)
    1055             : 
    1056             :       TYPE(nnp_type), INTENT(INOUT)                      :: nnp
    1057             : 
    1058             :       INTEGER                                            :: ang, i, j, k, rad, s
    1059             :       REAL(KIND=dp)                                      :: funccut
    1060             : 
    1061             :       !find out how many symmetry functions groups are needed
    1062          46 :       DO i = 1, nnp%n_ele
    1063          31 :          nnp%rad(i)%n_symfgrp = 0
    1064          31 :          nnp%ang(i)%n_symfgrp = 0
    1065             :          !search radial symmetry functions
    1066          96 :          DO j = 1, nnp%n_ele
    1067          65 :             funccut = -1.0_dp
    1068        1106 :             DO s = 1, nnp%n_rad(i)
    1069        1075 :                IF (nnp%rad(i)%ele(s) == nnp%ele(j)) THEN
    1070         486 :                   IF (ABS(nnp%rad(i)%funccut(s) - funccut) > 1.0e-5_dp) THEN
    1071          63 :                      nnp%rad(i)%n_symfgrp = nnp%rad(i)%n_symfgrp + 1
    1072          63 :                      funccut = nnp%rad(i)%funccut(s)
    1073             :                   END IF
    1074             :                END IF
    1075             :             END DO
    1076             :          END DO
    1077             :          !search angular symmetry functions
    1078         111 :          DO j = 1, nnp%n_ele
    1079         198 :             DO k = j, nnp%n_ele
    1080         102 :                funccut = -1.0_dp
    1081        1337 :                DO s = 1, nnp%n_ang(i)
    1082             :                   IF ((nnp%ang(i)%ele1(s) == nnp%ele(j) .AND. &
    1083        1170 :                        nnp%ang(i)%ele2(s) == nnp%ele(k)) .OR. &
    1084             :                       (nnp%ang(i)%ele1(s) == nnp%ele(k) .AND. &
    1085         102 :                        nnp%ang(i)%ele2(s) == nnp%ele(j))) THEN
    1086         370 :                      IF (ABS(nnp%ang(i)%funccut(s) - funccut) > 1.0e-5_dp) THEN
    1087          76 :                         nnp%ang(i)%n_symfgrp = nnp%ang(i)%n_symfgrp + 1
    1088          76 :                         funccut = nnp%ang(i)%funccut(s)
    1089             :                      END IF
    1090             :                   END IF
    1091             :                END DO
    1092             :             END DO
    1093             :          END DO
    1094             :       END DO
    1095             : 
    1096             :       !allocate memory for symmetry functions group
    1097          46 :       DO i = 1, nnp%n_ele
    1098         156 :          ALLOCATE (nnp%rad(i)%symfgrp(nnp%rad(i)%n_symfgrp))
    1099         169 :          ALLOCATE (nnp%ang(i)%symfgrp(nnp%ang(i)%n_symfgrp))
    1100          94 :          DO j = 1, nnp%rad(i)%n_symfgrp
    1101          94 :             nnp%rad(i)%symfgrp(j)%n_symf = 0
    1102             :          END DO
    1103         122 :          DO j = 1, nnp%ang(i)%n_symfgrp
    1104         107 :             nnp%ang(i)%symfgrp(j)%n_symf = 0
    1105             :          END DO
    1106             :       END DO
    1107             : 
    1108             :       !init symmetry functions group
    1109          46 :       DO i = 1, nnp%n_ele
    1110             :          rad = 0
    1111          96 :          ang = 0
    1112          96 :          DO j = 1, nnp%n_ele
    1113          65 :             funccut = -1.0_dp
    1114        1106 :             DO s = 1, nnp%n_rad(i)
    1115        1075 :                IF (nnp%rad(i)%ele(s) == nnp%ele(j)) THEN
    1116         486 :                   IF (ABS(nnp%rad(i)%funccut(s) - funccut) > 1.0e-5_dp) THEN
    1117          63 :                      rad = rad + 1
    1118          63 :                      funccut = nnp%rad(i)%funccut(s)
    1119          63 :                      nnp%rad(i)%symfgrp(rad)%cutoff = funccut
    1120          63 :                      ALLOCATE (nnp%rad(i)%symfgrp(rad)%ele(1))
    1121          63 :                      ALLOCATE (nnp%rad(i)%symfgrp(rad)%ele_ind(1))
    1122          63 :                      nnp%rad(i)%symfgrp(rad)%ele(1) = nnp%ele(j)
    1123          63 :                      nnp%rad(i)%symfgrp(rad)%ele_ind(1) = j
    1124             :                   END IF
    1125         486 :                   nnp%rad(i)%symfgrp(rad)%n_symf = nnp%rad(i)%symfgrp(rad)%n_symf + 1
    1126             :                END IF
    1127             :             END DO
    1128             :          END DO
    1129         111 :          DO j = 1, nnp%n_ele
    1130         198 :             DO k = j, nnp%n_ele
    1131         102 :                funccut = -1.0_dp
    1132        1337 :                DO s = 1, nnp%n_ang(i)
    1133             :                   IF ((nnp%ang(i)%ele1(s) == nnp%ele(j) .AND. &
    1134        1170 :                        nnp%ang(i)%ele2(s) == nnp%ele(k)) .OR. &
    1135             :                       (nnp%ang(i)%ele1(s) == nnp%ele(k) .AND. &
    1136         102 :                        nnp%ang(i)%ele2(s) == nnp%ele(j))) THEN
    1137         370 :                      IF (ABS(nnp%ang(i)%funccut(s) - funccut) > 1.0e-5_dp) THEN
    1138          76 :                         ang = ang + 1
    1139          76 :                         funccut = nnp%ang(i)%funccut(s)
    1140          76 :                         nnp%ang(i)%symfgrp(ang)%cutoff = funccut
    1141          76 :                         ALLOCATE (nnp%ang(i)%symfgrp(ang)%ele(2))
    1142          76 :                         ALLOCATE (nnp%ang(i)%symfgrp(ang)%ele_ind(2))
    1143          76 :                         nnp%ang(i)%symfgrp(ang)%ele(1) = nnp%ele(j)
    1144          76 :                         nnp%ang(i)%symfgrp(ang)%ele(2) = nnp%ele(k)
    1145          76 :                         nnp%ang(i)%symfgrp(ang)%ele_ind(1) = j
    1146          76 :                         nnp%ang(i)%symfgrp(ang)%ele_ind(2) = k
    1147             :                      END IF
    1148         370 :                      nnp%ang(i)%symfgrp(ang)%n_symf = nnp%ang(i)%symfgrp(ang)%n_symf + 1
    1149             :                   END IF
    1150             :                END DO
    1151             :             END DO
    1152             :          END DO
    1153             :       END DO
    1154             : 
    1155             :       !add symmetry functions to associated groups
    1156          46 :       DO i = 1, nnp%n_ele
    1157          94 :          DO j = 1, nnp%rad(i)%n_symfgrp
    1158         189 :             ALLOCATE (nnp%rad(i)%symfgrp(j)%symf(nnp%rad(i)%symfgrp(j)%n_symf))
    1159          63 :             rad = 0
    1160        1083 :             DO s = 1, nnp%n_rad(i)
    1161        1052 :                IF (nnp%rad(i)%ele(s) == nnp%rad(i)%symfgrp(j)%ele(1)) THEN
    1162         486 :                   IF (ABS(nnp%rad(i)%funccut(s) - nnp%rad(i)%symfgrp(j)%cutoff) <= 1.0e-5_dp) THEN
    1163         486 :                      rad = rad + 1
    1164         486 :                      nnp%rad(i)%symfgrp(j)%symf(rad) = s
    1165             :                   END IF
    1166             :                END IF
    1167             :             END DO
    1168             :          END DO
    1169         122 :          DO j = 1, nnp%ang(i)%n_symfgrp
    1170         228 :             ALLOCATE (nnp%ang(i)%symfgrp(j)%symf(nnp%ang(i)%symfgrp(j)%n_symf))
    1171          76 :             ang = 0
    1172        1043 :             DO s = 1, nnp%n_ang(i)
    1173             :                IF ((nnp%ang(i)%ele1(s) == nnp%ang(i)%symfgrp(j)%ele(1) .AND. &
    1174         936 :                     nnp%ang(i)%ele2(s) == nnp%ang(i)%symfgrp(j)%ele(2)) .OR. &
    1175             :                    (nnp%ang(i)%ele1(s) == nnp%ang(i)%symfgrp(j)%ele(2) .AND. &
    1176          76 :                     nnp%ang(i)%ele2(s) == nnp%ang(i)%symfgrp(j)%ele(1))) THEN
    1177         370 :                   IF (ABS(nnp%ang(i)%funccut(s) - nnp%ang(i)%symfgrp(j)%cutoff) <= 1.0e-5_dp) THEN
    1178         370 :                      ang = ang + 1
    1179         370 :                      nnp%ang(i)%symfgrp(j)%symf(ang) = s
    1180             :                   END IF
    1181             :                END IF
    1182             :             END DO
    1183             :          END DO
    1184             :       END DO
    1185             : 
    1186          15 :    END SUBROUTINE nnp_init_acsf_groups
    1187             : 
    1188             : ! **************************************************************************************************
    1189             : !> \brief Write symmetry function information
    1190             : !> \param nnp ...
    1191             : !> \param para_env ...
    1192             : !> \param printtag ...
    1193             : !> \date   2020-10-10
    1194             : !> \author Christoph Schran (christoph.schran@rub.de)
    1195             : ! **************************************************************************************************
    1196          15 :    SUBROUTINE nnp_write_acsf(nnp, para_env, printtag)
    1197             :       TYPE(nnp_type), INTENT(INOUT)                      :: nnp
    1198             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1199             :       CHARACTER(LEN=*), INTENT(IN)                       :: printtag
    1200             : 
    1201             :       CHARACTER(len=default_string_length)               :: my_label
    1202             :       INTEGER                                            :: i, j, unit_nr
    1203             :       TYPE(cp_logger_type), POINTER                      :: logger
    1204             : 
    1205          15 :       NULLIFY (logger)
    1206          15 :       logger => cp_get_default_logger()
    1207             : 
    1208          15 :       my_label = TRIM(printtag)//"| "
    1209          15 :       IF (para_env%is_source()) THEN
    1210           8 :          unit_nr = cp_logger_get_default_unit_nr(logger)
    1211           8 :          WRITE (unit_nr, '(1X,A,1X,10(I2,1X))') TRIM(my_label)//" Activation functions:", nnp%actfnct(:)
    1212          25 :          DO i = 1, nnp%n_ele
    1213             :             WRITE (unit_nr, *) TRIM(my_label)//" short range atomic symmetry functions element "// &
    1214          17 :                nnp%ele(i)//":"
    1215         279 :             DO j = 1, nnp%n_rad(i)
    1216         262 :                WRITE (unit_nr, '(1X,A,1X,I3,1X,A2,1X,I2,1X,A2,11X,3(F6.3,1X))') TRIM(my_label), j, nnp%ele(i), 2, &
    1217         262 :                   nnp%rad(i)%ele(j), nnp%rad(i)%eta(j), &
    1218         541 :                   nnp%rad(i)%rs(j), nnp%rad(i)%funccut(j)
    1219             :             END DO
    1220         220 :             DO j = 1, nnp%n_ang(i)
    1221             :                WRITE (unit_nr, '(1X,A,1X,I3,1X,A2,1X,I2,2(1X,A2),1X,4(F6.3,1X))') &
    1222         195 :                   TRIM(my_label), j, nnp%ele(i), 3, &
    1223         195 :                   nnp%ang(i)%ele1(j), nnp%ang(i)%ele2(j), &
    1224         195 :                   nnp%ang(i)%eta(j), nnp%ang(i)%lam(j), &
    1225         407 :                   nnp%ang(i)%zeta(j), nnp%ang(i)%funccut(j)
    1226             :             END DO
    1227             :          END DO
    1228             :       END IF
    1229             : 
    1230          15 :       RETURN
    1231             : 
    1232             :    END SUBROUTINE nnp_write_acsf
    1233             : 
    1234             : ! **************************************************************************************************
    1235             : !> \brief Create neighbor object
    1236             : !> \param nnp ...
    1237             : !> \param ind ...
    1238             : !> \param nat ...
    1239             : !> \param neighbor ...
    1240             : !> \date   2020-10-10
    1241             : !> \author Christoph Schran (christoph.schran@rub.de)
    1242             : ! **************************************************************************************************
    1243      248177 :    SUBROUTINE nnp_neighbor_create(nnp, ind, nat, neighbor)
    1244             : 
    1245             :       TYPE(nnp_type), INTENT(INOUT), POINTER             :: nnp
    1246             :       INTEGER, INTENT(IN)                                :: ind, nat
    1247             :       TYPE(nnp_neighbor_type), INTENT(INOUT)             :: neighbor
    1248             : 
    1249             :       INTEGER                                            :: n
    1250             :       TYPE(cell_type), POINTER                           :: cell
    1251             : 
    1252      248177 :       NULLIFY (cell)
    1253      248177 :       CALL nnp_env_get(nnp_env=nnp, cell=cell)
    1254             : 
    1255      248177 :       CALL nnp_compute_pbc_copies(neighbor%pbc_copies, cell, nnp%max_cut)
    1256      992708 :       n = (SUM(neighbor%pbc_copies) + 1)*nat
    1257      992708 :       ALLOCATE (neighbor%dist_rad(4, n, nnp%rad(ind)%n_symfgrp))
    1258      992708 :       ALLOCATE (neighbor%dist_ang1(4, n, nnp%ang(ind)%n_symfgrp))
    1259      992708 :       ALLOCATE (neighbor%dist_ang2(4, n, nnp%ang(ind)%n_symfgrp))
    1260      992708 :       ALLOCATE (neighbor%ind_rad(n, nnp%rad(ind)%n_symfgrp))
    1261      992708 :       ALLOCATE (neighbor%ind_ang1(n, nnp%ang(ind)%n_symfgrp))
    1262      992708 :       ALLOCATE (neighbor%ind_ang2(n, nnp%ang(ind)%n_symfgrp))
    1263      744531 :       ALLOCATE (neighbor%n_rad(nnp%rad(ind)%n_symfgrp))
    1264      744531 :       ALLOCATE (neighbor%n_ang1(nnp%ang(ind)%n_symfgrp))
    1265      744531 :       ALLOCATE (neighbor%n_ang2(nnp%ang(ind)%n_symfgrp))
    1266      854875 :       neighbor%n_rad(:) = 0
    1267      753694 :       neighbor%n_ang1(:) = 0
    1268      753694 :       neighbor%n_ang2(:) = 0
    1269             : 
    1270      248177 :    END SUBROUTINE nnp_neighbor_create
    1271             : 
    1272             : ! **************************************************************************************************
    1273             : !> \brief Destroy neighbor object
    1274             : !> \param neighbor ...
    1275             : !> \date   2020-10-10
    1276             : !> \author Christoph Schran (christoph.schran@rub.de)
    1277             : ! **************************************************************************************************
    1278      248177 :    SUBROUTINE nnp_neighbor_release(neighbor)
    1279             : 
    1280             :       TYPE(nnp_neighbor_type), INTENT(INOUT)             :: neighbor
    1281             : 
    1282      248177 :       DEALLOCATE (neighbor%dist_rad)
    1283      248177 :       DEALLOCATE (neighbor%dist_ang1)
    1284      248177 :       DEALLOCATE (neighbor%dist_ang2)
    1285      248177 :       DEALLOCATE (neighbor%ind_rad)
    1286      248177 :       DEALLOCATE (neighbor%ind_ang1)
    1287      248177 :       DEALLOCATE (neighbor%ind_ang2)
    1288      248177 :       DEALLOCATE (neighbor%n_rad)
    1289      248177 :       DEALLOCATE (neighbor%n_ang1)
    1290      248177 :       DEALLOCATE (neighbor%n_ang2)
    1291             : 
    1292      248177 :    END SUBROUTINE nnp_neighbor_release
    1293             : 
    1294             : ! **************************************************************************************************
    1295             : !> \brief Generate neighboring list for an atomic configuration
    1296             : !> \param nnp ...
    1297             : !> \param neighbor ...
    1298             : !> \param i ...
    1299             : !> \date   2020-10-10
    1300             : !> \author Christoph Schran (christoph.schran@rub.de)
    1301             : ! **************************************************************************************************
    1302      248177 :    SUBROUTINE nnp_compute_neighbors(nnp, neighbor, i)
    1303             : 
    1304             :       TYPE(nnp_type), INTENT(INOUT), POINTER             :: nnp
    1305             :       TYPE(nnp_neighbor_type), INTENT(INOUT)             :: neighbor
    1306             :       INTEGER, INTENT(IN)                                :: i
    1307             : 
    1308             :       INTEGER                                            :: c1, c2, c3, ind, j, s
    1309             :       INTEGER, DIMENSION(3)                              :: nl
    1310             :       REAL(KIND=dp)                                      :: norm
    1311             :       REAL(KIND=dp), DIMENSION(3)                        :: dr
    1312             :       TYPE(cell_type), POINTER                           :: cell
    1313             : 
    1314      248177 :       NULLIFY (cell)
    1315      248177 :       CALL nnp_env_get(nnp_env=nnp, cell=cell)
    1316             : 
    1317      248177 :       ind = nnp%ele_ind(i)
    1318             : 
    1319     6402580 :       DO j = 1, nnp%num_atoms
    1320    23100087 :          DO c1 = 1, 2*neighbor%pbc_copies(1) + 1
    1321    16697507 :             nl(1) = -neighbor%pbc_copies(1) + c1 - 1
    1322    71178729 :             DO c2 = 1, 2*neighbor%pbc_copies(2) + 1
    1323    48326819 :                nl(2) = -neighbor%pbc_copies(2) + c2 - 1
    1324   208239081 :                DO c3 = 1, 2*neighbor%pbc_copies(3) + 1
    1325   143214755 :                   nl(3) = -neighbor%pbc_copies(3) + c3 - 1
    1326   143214755 :                   IF (j == i .AND. nl(1) == 0 .AND. nl(2) == 0 .AND. nl(3) == 0) CYCLE
    1327   571866312 :                   dr(:) = nnp%coord(:, i) - nnp%coord(:, j)
    1328             :                   !Apply pbc, but subtract nl boxes from periodic image
    1329   571866312 :                   dr = pbc(dr, cell, nl)
    1330   571866312 :                   norm = NORM2(dr(:))
    1331   429230766 :                   DO s = 1, nnp%rad(ind)%n_symfgrp
    1332   429230766 :                      IF (nnp%ele_ind(j) == nnp%rad(ind)%symfgrp(s)%ele_ind(1)) THEN
    1333   142966578 :                         IF (norm < nnp%rad(ind)%symfgrp(s)%cutoff) THEN
    1334     3290284 :                            neighbor%n_rad(s) = neighbor%n_rad(s) + 1
    1335     3290284 :                            neighbor%ind_rad(neighbor%n_rad(s), s) = j
    1336    13161136 :                            neighbor%dist_rad(1:3, neighbor%n_rad(s), s) = dr(:)
    1337     3290284 :                            neighbor%dist_rad(4, neighbor%n_rad(s), s) = norm
    1338             :                         END IF
    1339             :                      END IF
    1340             :                   END DO
    1341   524661391 :                   DO s = 1, nnp%ang(ind)%n_symfgrp
    1342   476582749 :                      IF (norm < nnp%ang(ind)%symfgrp(s)%cutoff) THEN
    1343     7532482 :                         IF (nnp%ele_ind(j) == nnp%ang(ind)%symfgrp(s)%ele_ind(1)) THEN
    1344     4042123 :                            neighbor%n_ang1(s) = neighbor%n_ang1(s) + 1
    1345     4042123 :                            neighbor%ind_ang1(neighbor%n_ang1(s), s) = j
    1346    16168492 :                            neighbor%dist_ang1(1:3, neighbor%n_ang1(s), s) = dr(:)
    1347     4042123 :                            neighbor%dist_ang1(4, neighbor%n_ang1(s), s) = norm
    1348             :                         END IF
    1349     7532482 :                         IF (nnp%ele_ind(j) == nnp%ang(ind)%symfgrp(s)%ele_ind(2)) THEN
    1350     2855465 :                            neighbor%n_ang2(s) = neighbor%n_ang2(s) + 1
    1351     2855465 :                            neighbor%ind_ang2(neighbor%n_ang2(s), s) = j
    1352    11421860 :                            neighbor%dist_ang2(1:3, neighbor%n_ang2(s), s) = dr(:)
    1353     2855465 :                            neighbor%dist_ang2(4, neighbor%n_ang2(s), s) = norm
    1354             :                         END IF
    1355             :                      END IF
    1356             :                   END DO
    1357             :                END DO
    1358             :             END DO
    1359             :          END DO
    1360             :       END DO
    1361             : 
    1362      248177 :    END SUBROUTINE nnp_compute_neighbors
    1363             : 
    1364             : ! **************************************************************************************************
    1365             : !> \brief Determine required pbc copies for small cells
    1366             : !> \param pbc_copies ...
    1367             : !> \param cell ...
    1368             : !> \param cutoff ...
    1369             : !> \date   2020-10-10
    1370             : !> \author Christoph Schran (christoph.schran@rub.de)
    1371             : ! **************************************************************************************************
    1372      248177 :    SUBROUTINE nnp_compute_pbc_copies(pbc_copies, cell, cutoff)
    1373             :       INTEGER, DIMENSION(3), INTENT(INOUT)               :: pbc_copies
    1374             :       TYPE(cell_type), INTENT(IN), POINTER               :: cell
    1375             :       REAL(KIND=dp), INTENT(IN)                          :: cutoff
    1376             : 
    1377             :       REAL(KIND=dp)                                      :: proja, projb, projc
    1378             :       REAL(KIND=dp), DIMENSION(3)                        :: axb, axc, bxc
    1379             : 
    1380      248177 :       axb(1) = cell%hmat(2, 1)*cell%hmat(3, 2) - cell%hmat(3, 1)*cell%hmat(2, 2)
    1381      248177 :       axb(2) = cell%hmat(3, 1)*cell%hmat(1, 2) - cell%hmat(1, 1)*cell%hmat(3, 2)
    1382      248177 :       axb(3) = cell%hmat(1, 1)*cell%hmat(2, 2) - cell%hmat(2, 1)*cell%hmat(1, 2)
    1383     1737239 :       axb(:) = axb(:)/NORM2(axb(:))
    1384             : 
    1385      248177 :       axc(1) = cell%hmat(2, 1)*cell%hmat(3, 3) - cell%hmat(3, 1)*cell%hmat(2, 3)
    1386      248177 :       axc(2) = cell%hmat(3, 1)*cell%hmat(1, 3) - cell%hmat(1, 1)*cell%hmat(3, 3)
    1387      248177 :       axc(3) = cell%hmat(1, 1)*cell%hmat(2, 3) - cell%hmat(2, 1)*cell%hmat(1, 3)
    1388     1737239 :       axc(:) = axc(:)/NORM2(axc(:))
    1389             : 
    1390      248177 :       bxc(1) = cell%hmat(2, 2)*cell%hmat(3, 3) - cell%hmat(3, 2)*cell%hmat(2, 3)
    1391      248177 :       bxc(2) = cell%hmat(3, 2)*cell%hmat(1, 3) - cell%hmat(1, 2)*cell%hmat(3, 3)
    1392      248177 :       bxc(3) = cell%hmat(1, 2)*cell%hmat(2, 3) - cell%hmat(2, 2)*cell%hmat(1, 3)
    1393     1737239 :       bxc(:) = bxc(:)/NORM2(bxc(:))
    1394             : 
    1395      992708 :       proja = ABS(SUM(cell%hmat(:, 1)*bxc(:)))*0.5_dp
    1396      992708 :       projb = ABS(SUM(cell%hmat(:, 2)*axc(:)))*0.5_dp
    1397      992708 :       projc = ABS(SUM(cell%hmat(:, 3)*axb(:)))*0.5_dp
    1398             : 
    1399      248177 :       pbc_copies(:) = 0
    1400      937730 :       DO WHILE ((pbc_copies(1) + 1)*proja <= cutoff)
    1401      689553 :          pbc_copies(1) = pbc_copies(1) + 1
    1402             :       END DO
    1403      937730 :       DO WHILE ((pbc_copies(2) + 1)*projb <= cutoff)
    1404      689553 :          pbc_copies(2) = pbc_copies(2) + 1
    1405             :       END DO
    1406      937730 :       DO WHILE ((pbc_copies(3) + 1)*projc <= cutoff)
    1407      689553 :          pbc_copies(3) = pbc_copies(3) + 1
    1408             :       END DO
    1409             :       ! Apply non periodic setting
    1410      992708 :       pbc_copies(:) = pbc_copies(:)*cell%perd(:)
    1411             : 
    1412      248177 :    END SUBROUTINE nnp_compute_pbc_copies
    1413             : 
    1414             : END MODULE nnp_acsf

Generated by: LCOV version 1.15