LCOV - code coverage report
Current view: top level - src - rt_propagation_velocity_gauge.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:9ccafda) Lines: 96.0 % 278 267
Test Date: 2026-10-15 00:55:44 Functions: 100.0 % 6 6

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Routines to perform the RTP in the velocity gauge
      10              : ! **************************************************************************************************
      11              : 
      12              : MODULE rt_propagation_velocity_gauge
      13              :    USE ai_moments,                      ONLY: expikr
      14              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      15              :                                               get_atomic_kind_set
      16              :    USE basis_set_types,                 ONLY: gto_basis_set_p_type,&
      17              :                                               gto_basis_set_type
      18              :    USE bibliography,                    ONLY: Mattiat2022,&
      19              :                                               cite_reference
      20              :    USE cell_types,                      ONLY: cell_type,&
      21              :                                               pbc
      22              :    USE core_ppnl,                       ONLY: build_core_ppnl
      23              :    USE cp_control_types,                ONLY: dft_control_type
      24              :    USE cp_dbcsr_api,                    ONLY: dbcsr_add,&
      25              :                                               dbcsr_create,&
      26              :                                               dbcsr_get_block_p,&
      27              :                                               dbcsr_init_p,&
      28              :                                               dbcsr_p_type,&
      29              :                                               dbcsr_set,&
      30              :                                               dbcsr_type_antisymmetric,&
      31              :                                               dbcsr_type_symmetric
      32              :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      33              :    USE cp_dbcsr_operations,             ONLY: dbcsr_allocate_matrix_set,&
      34              :                                               dbcsr_deallocate_matrix_set
      35              :    USE efield_utils,                    ONLY: make_field
      36              :    USE external_potential_types,        ONLY: gth_potential_p_type,&
      37              :                                               gth_potential_type,&
      38              :                                               sgp_potential_p_type,&
      39              :                                               sgp_potential_type
      40              :    USE input_section_types,             ONLY: section_vals_type
      41              :    USE kinds,                           ONLY: dp,&
      42              :                                               int_8
      43              :    USE kpoint_types,                    ONLY: get_kpoint_info,&
      44              :                                               kpoint_type
      45              :    USE mathconstants,                   ONLY: one,&
      46              :                                               zero
      47              :    USE orbital_pointers,                ONLY: init_orbital_pointers,&
      48              :                                               nco,&
      49              :                                               ncoset
      50              :    USE particle_types,                  ONLY: particle_type
      51              :    USE qs_environment_types,            ONLY: get_qs_env,&
      52              :                                               qs_environment_type
      53              :    USE qs_force_types,                  ONLY: qs_force_type
      54              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      55              :                                               get_qs_kind_set,&
      56              :                                               qs_kind_type
      57              :    USE qs_ks_types,                     ONLY: get_ks_env,&
      58              :                                               qs_ks_env_type
      59              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      60              :    USE qs_operators_ao,                 ONLY: build_lin_mom_matrix
      61              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      62              :                                               qs_rho_type
      63              :    USE sap_kind_types,                  ONLY: alist_complex_type,&
      64              :                                               clist_complex_type,&
      65              :                                               get_alist,&
      66              :                                               release_sap_int,&
      67              :                                               sap_int_complex_type,&
      68              :                                               sap_sort
      69              :    USE virial_types,                    ONLY: virial_type
      70              : 
      71              : !$ USE OMP_LIB, ONLY: omp_lock_kind, &
      72              : !$                    omp_init_lock, omp_set_lock, &
      73              : !$                    omp_unset_lock, omp_destroy_lock
      74              : 
      75              : #include "./base/base_uses.f90"
      76              : 
      77              :    IMPLICIT NONE
      78              : 
      79              :    PRIVATE
      80              : 
      81              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'rt_propagation_velocity_gauge'
      82              : 
      83              :    PUBLIC :: velocity_gauge_ks_matrix, update_vector_potential, velocity_gauge_nl_force, &
      84              :              velocity_gauge_nl_commutator
      85              : 
      86              : CONTAINS
      87              : 
      88              : ! **************************************************************************************************
      89              : !> \brief ...
      90              : !> \param qs_env ...
      91              : !> \param subtract_nl_term ...
      92              : ! **************************************************************************************************
      93           82 :    SUBROUTINE velocity_gauge_ks_matrix(qs_env, subtract_nl_term)
      94              :       TYPE(qs_environment_type), POINTER                 :: qs_env
      95              :       LOGICAL, INTENT(IN), OPTIONAL                      :: subtract_nl_term
      96              : 
      97              :       CHARACTER(len=*), PARAMETER :: routineN = 'velocity_gauge_ks_matrix'
      98              : 
      99              :       INTEGER                                            :: handle, idir, image, nder, nimages
     100           82 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
     101              :       LOGICAL                                            :: calculate_forces, my_subtract_nl_term, &
     102              :                                                             ppnl_present, use_virial
     103              :       REAL(KIND=dp)                                      :: eps_ppnl, factor
     104              :       REAL(KIND=dp), DIMENSION(3)                        :: vec_pot
     105           82 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     106              :       TYPE(cell_type), POINTER                           :: cell
     107           82 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: momentum, nl_term
     108           82 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_h, matrix_h_im, matrix_nl, &
     109           82 :                                                             matrix_p, matrix_s
     110              :       TYPE(dft_control_type), POINTER                    :: dft_control
     111              :       TYPE(kpoint_type), POINTER                         :: kpoints
     112              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     113           82 :          POINTER                                         :: sab_orb, sap_ppnl
     114           82 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     115           82 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
     116           82 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     117              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     118              :       TYPE(qs_rho_type), POINTER                         :: rho
     119              :       TYPE(section_vals_type), POINTER                   :: input
     120              :       TYPE(virial_type), POINTER                         :: virial
     121              : 
     122           82 :       CALL timeset(routineN, handle)
     123              : 
     124           82 :       CALL cite_reference(Mattiat2022)
     125              : 
     126           82 :       my_subtract_nl_term = .FALSE.
     127           82 :       IF (PRESENT(subtract_nl_term)) my_subtract_nl_term = subtract_nl_term
     128              : 
     129           82 :       NULLIFY (dft_control, matrix_s, sab_orb, matrix_h, cell, input, matrix_h_im, kpoints, cell_to_index, &
     130           82 :                sap_ppnl, particle_set, qs_kind_set, atomic_kind_set, virial, force, matrix_p, rho, matrix_nl)
     131              : 
     132              :       CALL get_qs_env(qs_env, &
     133              :                       rho=rho, &
     134              :                       dft_control=dft_control, &
     135              :                       sab_orb=sab_orb, &
     136              :                       sap_ppnl=sap_ppnl, &
     137              :                       matrix_s_kp=matrix_s, &
     138              :                       matrix_h_kp=matrix_h, &
     139              :                       cell=cell, &
     140              :                       input=input, &
     141           82 :                       matrix_h_im_kp=matrix_h_im)
     142              : 
     143           82 :       nimages = dft_control%nimages
     144           82 :       ppnl_present = ASSOCIATED(sap_ppnl)
     145              : 
     146           82 :       IF (nimages > 1) THEN
     147            0 :          CALL get_ks_env(ks_env=ks_env, kpoints=kpoints)
     148            0 :          CALL get_kpoint_info(kpoint=kpoints, cell_to_index=cell_to_index)
     149              :       END IF
     150              : 
     151           82 :       IF (my_subtract_nl_term) THEN
     152           12 :          IF (ppnl_present) THEN
     153              :             CALL get_qs_env(qs_env, &
     154              :                             qs_kind_set=qs_kind_set, &
     155              :                             particle_set=particle_set, &
     156              :                             atomic_kind_set=atomic_kind_set, &
     157              :                             virial=virial, &
     158              :                             rho=rho, &
     159            8 :                             force=force)
     160              : 
     161            8 :             CALL qs_rho_get(rho, rho_ao_kp=matrix_p)
     162            8 :             calculate_forces = .FALSE.
     163            8 :             use_virial = .FALSE.
     164            8 :             nder = 1
     165            8 :             eps_ppnl = dft_control%qs_control%eps_ppnl
     166              : 
     167            8 :             CALL dbcsr_allocate_matrix_set(matrix_nl, 1, nimages)
     168           16 :             DO image = 1, nimages
     169            8 :                ALLOCATE (matrix_nl(1, image)%matrix)
     170            8 :                CALL dbcsr_create(matrix_nl(1, image)%matrix, template=matrix_s(1, 1)%matrix)
     171            8 :                CALL cp_dbcsr_alloc_block_from_nbl(matrix_nl(1, image)%matrix, sab_orb)
     172           16 :                CALL dbcsr_set(matrix_nl(1, image)%matrix, zero)
     173              :             END DO
     174              : 
     175              :             CALL build_core_ppnl(matrix_nl, matrix_p, force, virial, calculate_forces, use_virial, nder, &
     176              :                                  qs_kind_set, atomic_kind_set, particle_set, sab_orb, sap_ppnl, eps_ppnl, &
     177            8 :                                  nimages, cell_to_index, "ORB")
     178              : 
     179           16 :             DO image = 1, nimages
     180           16 :                CALL dbcsr_add(matrix_h(1, image)%matrix, matrix_nl(1, image)%matrix, one, -one)
     181              :             END DO
     182              : 
     183            8 :             CALL dbcsr_deallocate_matrix_set(matrix_nl)
     184              :          END IF
     185              :       END IF
     186              : 
     187              :       !get vector potential
     188          328 :       vec_pot = dft_control%rtp_control%vec_pot
     189              : 
     190              :       ! allocate and build matrices for linear momentum term
     191           82 :       NULLIFY (momentum)
     192           82 :       CALL dbcsr_allocate_matrix_set(momentum, 3)
     193          328 :       DO idir = 1, 3
     194          246 :          CALL dbcsr_init_p(momentum(idir)%matrix)
     195              :          CALL dbcsr_create(momentum(idir)%matrix, template=matrix_s(1, 1)%matrix, &
     196          246 :                            matrix_type=dbcsr_type_antisymmetric)
     197          246 :          CALL cp_dbcsr_alloc_block_from_nbl(momentum(idir)%matrix, sab_orb)
     198          328 :          CALL dbcsr_set(momentum(idir)%matrix, zero)
     199              :       END DO
     200           82 :       CALL build_lin_mom_matrix(qs_env, momentum)
     201              : 
     202              :       ! set imaginary part of KS matrix to zero
     203          164 :       DO image = 1, nimages
     204          164 :          CALL dbcsr_set(matrix_h_im(1, image)%matrix, zero)
     205              :       END DO
     206              : 
     207              :       ! add linear term in vector potential to imaginary part of KS-matrix
     208          164 :       DO image = 1, nimages
     209          410 :          DO idir = 1, 3
     210          328 :             CALL dbcsr_add(matrix_h_im(1, image)%matrix, momentum(idir)%matrix, one, -vec_pot(idir))
     211              :          END DO
     212              :       END DO
     213              : 
     214           82 :       CALL dbcsr_deallocate_matrix_set(momentum)
     215              : 
     216              :       ! add quadratic term to real part of KS matrix
     217           82 :       factor = 0._dp
     218          328 :       DO idir = 1, 3
     219          328 :          factor = factor + vec_pot(idir)**2
     220              :       END DO
     221              : 
     222          164 :       DO image = 1, nimages
     223          164 :          CALL dbcsr_add(matrix_h(1, image)%matrix, matrix_s(1, image)%matrix, one, 0.5_dp*factor)
     224              :       END DO
     225              : 
     226              :       ! add Non local term
     227           82 :       IF (ppnl_present) THEN
     228           60 :          IF (dft_control%rtp_control%nl_gauge_transform) THEN
     229           60 :             NULLIFY (nl_term)
     230           60 :             CALL dbcsr_allocate_matrix_set(nl_term, 2)
     231              : 
     232           60 :             CALL dbcsr_init_p(nl_term(1)%matrix)
     233              :             CALL dbcsr_create(nl_term(1)%matrix, template=matrix_s(1, 1)%matrix, &
     234           60 :                               matrix_type=dbcsr_type_symmetric, name="nl gauge term real part")
     235           60 :             CALL cp_dbcsr_alloc_block_from_nbl(nl_term(1)%matrix, sab_orb)
     236           60 :             CALL dbcsr_set(nl_term(1)%matrix, zero)
     237              : 
     238           60 :             CALL dbcsr_init_p(nl_term(2)%matrix)
     239              :             CALL dbcsr_create(nl_term(2)%matrix, template=matrix_s(1, 1)%matrix, &
     240           60 :                               matrix_type=dbcsr_type_antisymmetric, name="nl gauge term imaginary part")
     241           60 :             CALL cp_dbcsr_alloc_block_from_nbl(nl_term(2)%matrix, sab_orb)
     242           60 :             CALL dbcsr_set(nl_term(2)%matrix, zero)
     243              : 
     244           60 :             CALL velocity_gauge_nl_term(qs_env, nl_term, vec_pot)
     245              : 
     246          120 :             DO image = 1, nimages
     247           60 :                CALL dbcsr_add(matrix_h(1, image)%matrix, nl_term(1)%matrix, one, one)
     248          120 :                CALL dbcsr_add(matrix_h_im(1, image)%matrix, nl_term(2)%matrix, one, one)
     249              :             END DO
     250           60 :             CALL dbcsr_deallocate_matrix_set(nl_term)
     251              :          END IF
     252              :       END IF
     253              : 
     254           82 :       CALL timestop(handle)
     255              : 
     256           82 :    END SUBROUTINE velocity_gauge_ks_matrix
     257              : 
     258              : ! **************************************************************************************************
     259              : !> \brief Update the vector potential in the case where a time-dependant
     260              : !>        electric field is apply.
     261              : !> \param qs_env ...
     262              : !> \param dft_control ...
     263              : ! **************************************************************************************************
     264           36 :    SUBROUTINE update_vector_potential(qs_env, dft_control)
     265              :       TYPE(qs_environment_type), INTENT(INOUT), POINTER  :: qs_env
     266              :       TYPE(dft_control_type), INTENT(INOUT), POINTER     :: dft_control
     267              : 
     268              :       REAL(kind=dp)                                      :: field(3)
     269              : 
     270           36 :       CALL make_field(dft_control, field, qs_env%sim_step, qs_env%sim_time)
     271          144 :       dft_control%rtp_control%field = field
     272          144 :       dft_control%rtp_control%vec_pot = dft_control%rtp_control%vec_pot - field*qs_env%rtp%dt
     273              :       ! Update the vec_pot_initial value for RTP restart:
     274          144 :       dft_control%efield_fields(1)%efield%vec_pot_initial = dft_control%rtp_control%vec_pot
     275              : 
     276           36 :    END SUBROUTINE update_vector_potential
     277              : 
     278              : ! **************************************************************************************************
     279              : !> \brief ...
     280              : !> \param qs_env ...
     281              : !> \param nl_term ...
     282              : !> \param vec_pot ...
     283              : ! **************************************************************************************************
     284           60 :    SUBROUTINE velocity_gauge_nl_term(qs_env, nl_term, vec_pot)
     285              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     286              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT), &
     287              :          POINTER                                         :: nl_term
     288              :       REAL(KIND=dp), DIMENSION(3), INTENT(in)            :: vec_pot
     289              : 
     290              :       CHARACTER(len=*), PARAMETER :: routiuneN = "velocity_gauge_nl_term"
     291              : 
     292           60 :       COMPLEX(KIND=dp), ALLOCATABLE                      :: zblock(:, :)
     293           60 :       COMPLEX(KIND=dp), DIMENSION(:, :, :), POINTER      :: achint, bcint
     294              :       INTEGER                                            :: handle, iac, iatom, ibc, icol, ikind, &
     295              :                                                             irow, jatom, jkind, kac, kbc, kkind, &
     296              :                                                             maxl, maxlgto, maxlppnl, na, natom, &
     297              :                                                             nb, nkind, np, slot
     298              :       INTEGER, DIMENSION(3)                              :: cell_b
     299              :       LOGICAL                                            :: found
     300              :       REAL(dp)                                           :: eps_ppnl
     301              :       REAL(KIND=dp), DIMENSION(3)                        :: rab
     302           60 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: imag_block, real_block
     303              :       TYPE(alist_complex_type), POINTER                  :: alist_ac, alist_bc
     304           60 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     305              :       TYPE(cell_type), POINTER                           :: cell
     306              :       TYPE(dft_control_type), POINTER                    :: dft_control
     307              :       TYPE(gto_basis_set_p_type), ALLOCATABLE, &
     308           60 :          DIMENSION(:)                                    :: basis_set
     309              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
     310              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     311           60 :          POINTER                                         :: sab_orb, sap_ppnl
     312           60 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     313           60 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     314           60 :       TYPE(sap_int_complex_type), DIMENSION(:), POINTER  :: sap_int
     315              : 
     316              : !$    INTEGER(kind=omp_lock_kind), &
     317           60 : !$       ALLOCATABLE, DIMENSION(:) :: locks
     318              : !$    INTEGER(KIND=int_8)                                :: iatom8
     319              : !$    INTEGER                                            :: lock_num, hash
     320              : !$    INTEGER, PARAMETER                                 :: nlock = 501
     321              : 
     322              :       MARK_USED(int_8)
     323              : 
     324           60 :       CALL timeset(routiuneN, handle)
     325              : 
     326           60 :       NULLIFY (sap_ppnl, sab_orb)
     327              :       CALL get_qs_env(qs_env, &
     328              :                       sap_ppnl=sap_ppnl, &
     329           60 :                       sab_orb=sab_orb)
     330              : 
     331           60 :       IF (ASSOCIATED(sap_ppnl)) THEN
     332           60 :          NULLIFY (qs_kind_set, particle_set, cell, dft_control)
     333              :          CALL get_qs_env(qs_env, &
     334              :                          dft_control=dft_control, &
     335              :                          qs_kind_set=qs_kind_set, &
     336              :                          particle_set=particle_set, &
     337              :                          cell=cell, &
     338           60 :                          atomic_kind_set=atomic_kind_set)
     339              : 
     340           60 :          nkind = SIZE(atomic_kind_set)
     341           60 :          natom = SIZE(particle_set)
     342           60 :          eps_ppnl = dft_control%qs_control%eps_ppnl
     343              : 
     344              :          CALL get_qs_kind_set(qs_kind_set, &
     345              :                               maxlgto=maxlgto, &
     346           60 :                               maxlppnl=maxlppnl)
     347              : 
     348           60 :          maxl = MAX(maxlppnl, maxlgto)
     349           60 :          CALL init_orbital_pointers(maxl + 1)
     350              : 
     351              :          ! initalize sab_int types to store the integrals
     352           60 :          NULLIFY (sap_int)
     353          420 :          ALLOCATE (sap_int(nkind*nkind))
     354              : 
     355              :          ! get basis set
     356          300 :          ALLOCATE (basis_set(nkind))
     357          180 :          DO ikind = 1, nkind
     358          120 :             CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set)
     359          180 :             IF (ASSOCIATED(orb_basis_set)) THEN
     360          120 :                basis_set(ikind)%gto_basis_set => orb_basis_set
     361              :             ELSE
     362            0 :                NULLIFY (basis_set(ikind)%gto_basis_set)
     363              :             END IF
     364              :          END DO
     365              : 
     366              :          ! calculate exponential integrals
     367              :          CALL build_sap_exp_ints(sap_int, sap_ppnl, qs_kind_set, particle_set, &
     368              :                                  cell, kvec=vec_pot, basis_set=basis_set, nkind=nkind, &
     369           60 :                                  derivative=.FALSE.)
     370              : 
     371           60 :          CALL sap_sort(sap_int)
     372              : 
     373              :          ! assemble the integrals for the gauge term
     374              : !$OMP PARALLEL &
     375              : !$OMP DEFAULT (NONE) &
     376              : !$OMP SHARED (basis_set, nl_term, sab_orb, sap_int, eps_ppnl, locks, nkind, natom) &
     377              : !$OMP PRIVATE (real_block, imag_block, achint, bcint, &
     378              : !$OMP           slot, ikind, jkind, iatom, jatom, cell_b, rab, irow, icol,&
     379              : !$OMP          found, kkind, iac, ibc, alist_ac, alist_bc, kac, kbc, &
     380           60 : !$OMP          zblock, na, np, nb, iatom8, hash, lock_num)
     381              : 
     382              : !$OMP SINGLE
     383              : !$       ALLOCATE (locks(nlock))
     384              : !$OMP END SINGLE
     385              : 
     386              : !$OMP DO
     387              : !$       DO lock_num = 1, nlock
     388              : !$          call omp_init_lock(locks(lock_num))
     389              : !$       END DO
     390              : !$OMP END DO
     391              : 
     392              :          NULLIFY (real_block, imag_block)
     393              :          NULLIFY (achint, bcint)
     394              : 
     395              :          ! loop over atom pairs
     396              : !$OMP DO SCHEDULE(GUIDED)
     397              :          DO slot = 1, sab_orb(1)%nl_size
     398              :             ikind = sab_orb(1)%nlist_task(slot)%ikind
     399              :             jkind = sab_orb(1)%nlist_task(slot)%jkind
     400              :             iatom = sab_orb(1)%nlist_task(slot)%iatom
     401              :             jatom = sab_orb(1)%nlist_task(slot)%jatom
     402              :             cell_b(:) = sab_orb(1)%nlist_task(slot)%cell
     403              :             rab(1:3) = sab_orb(1)%nlist_task(slot)%r(1:3)
     404              : 
     405              :             IF (.NOT. ASSOCIATED(basis_set(ikind)%gto_basis_set)) CYCLE
     406              :             IF (.NOT. ASSOCIATED(basis_set(jkind)%gto_basis_set)) CYCLE
     407              : 
     408              :             IF (iatom <= jatom) THEN
     409              :                irow = iatom
     410              :                icol = jatom
     411              :             ELSE
     412              :                irow = jatom
     413              :                icol = iatom
     414              :             END IF
     415              : 
     416              :             CALL dbcsr_get_block_p(nl_term(1)%matrix, irow, icol, real_block, found)
     417              :             CALL dbcsr_get_block_p(nl_term(2)%matrix, irow, icol, imag_block, found)
     418              : 
     419              :             IF (ASSOCIATED(real_block) .AND. ASSOCIATED(imag_block)) THEN
     420              :                ! loop over the <gto_a|ppln_c>h_ij<ppnl_c|gto_b> pairs
     421              :                DO kkind = 1, nkind
     422              :                   iac = ikind + nkind*(kkind - 1)
     423              :                   ibc = jkind + nkind*(kkind - 1)
     424              :                   IF (.NOT. ASSOCIATED(sap_int(iac)%alist)) CYCLE
     425              :                   IF (.NOT. ASSOCIATED(sap_int(ibc)%alist)) CYCLE
     426              :                   CALL get_alist(sap_int(iac), alist_ac, iatom)
     427              :                   CALL get_alist(sap_int(ibc), alist_bc, jatom)
     428              :                   IF (.NOT. ASSOCIATED(alist_ac)) CYCLE
     429              :                   IF (.NOT. ASSOCIATED(alist_bc)) CYCLE
     430              :                   DO kac = 1, alist_ac%nclist
     431              :                      DO kbc = 1, alist_bc%nclist
     432              :                         IF (alist_ac%clist(kac)%catom /= alist_bc%clist(kbc)%catom) CYCLE
     433              :                         IF (ALL(cell_b + alist_bc%clist(kbc)%cell - alist_ac%clist(kac)%cell == 0)) THEN
     434              :                            ! screening
     435              :                            IF (alist_ac%clist(kac)%maxac*alist_bc%clist(kbc)%maxach < eps_ppnl) CYCLE
     436              : 
     437              :                            ! Orient the projector factors to the stored upper atom block.
     438              :                            IF (iatom <= jatom) THEN
     439              :                               achint => alist_ac%clist(kac)%achint
     440              :                               bcint => alist_bc%clist(kbc)%acint
     441              :                            ELSE
     442              :                               achint => alist_bc%clist(kbc)%achint
     443              :                               bcint => alist_ac%clist(kac)%acint
     444              :                            END IF
     445              : 
     446              :                            na = SIZE(achint, 1)
     447              :                            np = SIZE(achint, 2)
     448              :                            nb = SIZE(bcint, 1)
     449              :                            ALLOCATE (zblock(na, nb))
     450              : !$                         iatom8 = INT(iatom - 1, int_8)*INT(natom, int_8) + INT(jatom, int_8)
     451              : !$                         hash = INT(MOD(iatom8, INT(nlock, int_8)) + 1)
     452              : !$                         CALL omp_set_lock(locks(hash))
     453              :                            ! The gauge-dressed operator uses the conjugated bra phase.
     454              :                            zblock(:, :) = MATMUL(CONJG(achint(1:na, 1:np, 1)), TRANSPOSE(bcint(1:nb, 1:np, 1)))
     455              :                            real_block(1:na, 1:nb) = real_block(1:na, 1:nb) + REAL(zblock, KIND=dp)
     456              :                            imag_block(1:na, 1:nb) = imag_block(1:na, 1:nb) + AIMAG(zblock)
     457              : !$                         CALL omp_unset_lock(locks(hash))
     458              :                            DEALLOCATE (zblock)
     459              :                            EXIT
     460              :                         END IF
     461              :                      END DO
     462              :                   END DO
     463              :                END DO
     464              :             END IF
     465              : 
     466              :          END DO
     467              : 
     468              : !$OMP DO
     469              : !$       DO lock_num = 1, nlock
     470              : !$          call omp_destroy_lock(locks(lock_num))
     471              : !$       END DO
     472              : !$OMP END DO
     473              : 
     474              : !$OMP SINGLE
     475              : !$       DEALLOCATE (locks)
     476              : !$OMP END SINGLE NOWAIT
     477              : 
     478              : !$OMP END PARALLEL
     479           60 :          CALL release_sap_int(sap_int)
     480              : 
     481          120 :          DEALLOCATE (basis_set)
     482              :       END IF
     483              : 
     484           60 :       CALL timestop(handle)
     485              : 
     486          120 :    END SUBROUTINE velocity_gauge_nl_term
     487              : 
     488              : ! **************************************************************************************************
     489              : !> \brief Calculate the commutator [Vnl~, r_d] (d=x,y,z) of the gauge-transformed nonlocal
     490              : !>        pseudopotential with the position operator, needed for the nonlocal correction
     491              : !>        to the integrated electronic current in RTP/EMD.
     492              : !>        The moment is taken relative to each projector center, which makes the result
     493              : !>        origin-independent (the constant shifts cancel exactly in the commutator).
     494              : !>        For vec_pot = 0 the plain commutator [Vnl, r_d] is obtained (matrix_cim = 0).
     495              : !> \param qs_env ...
     496              : !> \param matrix_cre real part of the commutator, antisymmetric, dimension(3)
     497              : !> \param matrix_cim imaginary part of the commutator, symmetric, dimension(3)
     498              : !> \param vec_pot vector potential defining the gauge phase, use 0 for no gauge transform
     499              : ! **************************************************************************************************
     500           92 :    SUBROUTINE velocity_gauge_nl_commutator(qs_env, matrix_cre, matrix_cim, vec_pot)
     501              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     502              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT), &
     503              :          POINTER                                         :: matrix_cre, matrix_cim
     504              :       REAL(KIND=dp), DIMENSION(3), INTENT(in)            :: vec_pot
     505              : 
     506              :       CHARACTER(len=*), PARAMETER :: routiuneN = "velocity_gauge_nl_commutator"
     507              : 
     508           92 :       COMPLEX(KIND=dp), ALLOCATABLE                      :: zblock(:, :)
     509           92 :       COMPLEX(KIND=dp), DIMENSION(:, :, :), POINTER      :: achint, bcint
     510              :       INTEGER                                            :: handle, iac, iatom, ibc, icol, idir, &
     511              :                                                             ikind, irow, jatom, jkind, kac, kbc, &
     512              :                                                             kkind, m, maxl, maxlgto, maxlppnl, na, &
     513              :                                                             natom, nb, nkind, np, slot
     514              :       INTEGER, DIMENSION(3)                              :: cell_b
     515              :       LOGICAL                                            :: found
     516              :       REAL(dp)                                           :: eps_ppnl
     517              :       REAL(KIND=dp), DIMENSION(3)                        :: rab
     518           92 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: imag_block, real_block
     519              :       TYPE(alist_complex_type), POINTER                  :: alist_ac, alist_bc
     520           92 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     521              :       TYPE(cell_type), POINTER                           :: cell
     522              :       TYPE(dft_control_type), POINTER                    :: dft_control
     523              :       TYPE(gto_basis_set_p_type), ALLOCATABLE, &
     524           92 :          DIMENSION(:)                                    :: basis_set
     525              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
     526              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     527           92 :          POINTER                                         :: sab_orb, sap_ppnl
     528           92 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     529           92 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     530           92 :       TYPE(sap_int_complex_type), DIMENSION(:), POINTER  :: sap_int
     531              : 
     532              : !$    INTEGER(kind=omp_lock_kind), &
     533           92 : !$       ALLOCATABLE, DIMENSION(:) :: locks
     534              : !$    INTEGER(KIND=int_8)                                :: iatom8
     535              : !$    INTEGER                                            :: lock_num, hash
     536              : !$    INTEGER, PARAMETER                                 :: nlock = 501
     537              : 
     538              :       MARK_USED(int_8)
     539              : 
     540           92 :       CALL timeset(routiuneN, handle)
     541              : 
     542           92 :       NULLIFY (sap_ppnl, sab_orb)
     543              :       CALL get_qs_env(qs_env, &
     544              :                       sap_ppnl=sap_ppnl, &
     545           92 :                       sab_orb=sab_orb)
     546              : 
     547           92 :       IF (ASSOCIATED(sap_ppnl)) THEN
     548           92 :          NULLIFY (qs_kind_set, particle_set, cell, dft_control)
     549              :          CALL get_qs_env(qs_env, &
     550              :                          dft_control=dft_control, &
     551              :                          qs_kind_set=qs_kind_set, &
     552              :                          particle_set=particle_set, &
     553              :                          cell=cell, &
     554           92 :                          atomic_kind_set=atomic_kind_set)
     555              : 
     556           92 :          nkind = SIZE(atomic_kind_set)
     557           92 :          natom = SIZE(particle_set)
     558           92 :          eps_ppnl = dft_control%qs_control%eps_ppnl
     559              : 
     560              :          CALL get_qs_kind_set(qs_kind_set, &
     561              :                               maxlgto=maxlgto, &
     562           92 :                               maxlppnl=maxlppnl)
     563              : 
     564              :          ! Coordinate moments use one raised basis degree in the recurrence.
     565           92 :          maxl = MAX(maxlppnl, maxlgto)
     566           92 :          CALL init_orbital_pointers(maxl + 1)
     567              : 
     568              :          ! initalize sab_int types to store the integrals
     569           92 :          NULLIFY (sap_int)
     570          692 :          ALLOCATE (sap_int(nkind*nkind))
     571              : 
     572              :          ! get basis set
     573          468 :          ALLOCATE (basis_set(nkind))
     574          284 :          DO ikind = 1, nkind
     575          192 :             CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set)
     576          284 :             IF (ASSOCIATED(orb_basis_set)) THEN
     577          192 :                basis_set(ikind)%gto_basis_set => orb_basis_set
     578              :             ELSE
     579            0 :                NULLIFY (basis_set(ikind)%gto_basis_set)
     580              :             END IF
     581              :          END DO
     582              : 
     583              :          ! calculate exponential integrals, plain (slot 1) and moment-weighted (slots 2:4)
     584              :          CALL build_sap_exp_ints(sap_int, sap_ppnl, qs_kind_set, particle_set, &
     585              :                                  cell, kvec=vec_pot, basis_set=basis_set, nkind=nkind, &
     586           92 :                                  derivative=.FALSE., moment=.TRUE.)
     587              : 
     588           92 :          CALL sap_sort(sap_int)
     589              : 
     590              :          ! assemble the commutator matrices
     591              : !$OMP PARALLEL &
     592              : !$OMP DEFAULT (NONE) &
     593              : !$OMP SHARED (basis_set, matrix_cre, matrix_cim, sab_orb, sap_int, eps_ppnl, locks, nkind, natom) &
     594              : !$OMP PRIVATE (real_block, imag_block, achint, bcint, &
     595              : !$OMP           slot, ikind, jkind, iatom, jatom, cell_b, rab, irow, icol,&
     596              : !$OMP          found, kkind, iac, ibc, alist_ac, alist_bc, kac, kbc, &
     597           92 : !$OMP          zblock, na, np, nb, idir, m, iatom8, hash, lock_num)
     598              : 
     599              : !$OMP SINGLE
     600              : !$       ALLOCATE (locks(nlock))
     601              : !$OMP END SINGLE
     602              : 
     603              : !$OMP DO
     604              : !$       DO lock_num = 1, nlock
     605              : !$          call omp_init_lock(locks(lock_num))
     606              : !$       END DO
     607              : !$OMP END DO
     608              : 
     609              :          NULLIFY (real_block, imag_block)
     610              :          NULLIFY (achint, bcint)
     611              : 
     612              :          ! loop over atom pairs
     613              : !$OMP DO SCHEDULE(GUIDED)
     614              :          DO slot = 1, sab_orb(1)%nl_size
     615              :             ikind = sab_orb(1)%nlist_task(slot)%ikind
     616              :             jkind = sab_orb(1)%nlist_task(slot)%jkind
     617              :             iatom = sab_orb(1)%nlist_task(slot)%iatom
     618              :             jatom = sab_orb(1)%nlist_task(slot)%jatom
     619              :             cell_b(:) = sab_orb(1)%nlist_task(slot)%cell
     620              :             rab(1:3) = sab_orb(1)%nlist_task(slot)%r(1:3)
     621              : 
     622              :             IF (.NOT. ASSOCIATED(basis_set(ikind)%gto_basis_set)) CYCLE
     623              :             IF (.NOT. ASSOCIATED(basis_set(jkind)%gto_basis_set)) CYCLE
     624              : 
     625              :             IF (iatom <= jatom) THEN
     626              :                irow = iatom
     627              :                icol = jatom
     628              :             ELSE
     629              :                irow = jatom
     630              :                icol = iatom
     631              :             END IF
     632              : 
     633              :             ! loop over the <gto_a|ppln_c>h_ij<ppnl_c|gto_b> pairs
     634              :             DO kkind = 1, nkind
     635              :                iac = ikind + nkind*(kkind - 1)
     636              :                ibc = jkind + nkind*(kkind - 1)
     637              :                IF (.NOT. ASSOCIATED(sap_int(iac)%alist)) CYCLE
     638              :                IF (.NOT. ASSOCIATED(sap_int(ibc)%alist)) CYCLE
     639              :                CALL get_alist(sap_int(iac), alist_ac, iatom)
     640              :                CALL get_alist(sap_int(ibc), alist_bc, jatom)
     641              :                IF (.NOT. ASSOCIATED(alist_ac)) CYCLE
     642              :                IF (.NOT. ASSOCIATED(alist_bc)) CYCLE
     643              :                DO kac = 1, alist_ac%nclist
     644              :                   DO kbc = 1, alist_bc%nclist
     645              :                      IF (alist_ac%clist(kac)%catom /= alist_bc%clist(kbc)%catom) CYCLE
     646              :                      IF (ALL(cell_b + alist_bc%clist(kbc)%cell - alist_ac%clist(kac)%cell == 0)) THEN
     647              :                         ! screening
     648              :                         IF (alist_ac%clist(kac)%maxac*alist_bc%clist(kbc)%maxach < eps_ppnl) CYCLE
     649              : 
     650              :                         ! Orient the projector factors to the stored upper atom block.
     651              :                         IF (iatom <= jatom) THEN
     652              :                            achint => alist_ac%clist(kac)%achint
     653              :                            bcint => alist_bc%clist(kbc)%acint
     654              :                         ELSE
     655              :                            achint => alist_bc%clist(kbc)%achint
     656              :                            bcint => alist_ac%clist(kac)%acint
     657              :                         END IF
     658              : 
     659              :                         na = SIZE(achint, 1)
     660              :                         np = SIZE(achint, 2)
     661              :                         nb = SIZE(bcint, 1)
     662              :                         ALLOCATE (zblock(na, nb))
     663              : !$                      iatom8 = INT(iatom - 1, int_8)*INT(natom, int_8) + INT(jatom, int_8)
     664              : !$                      hash = INT(MOD(iatom8, INT(nlock, int_8)) + 1)
     665              : !$                      CALL omp_set_lock(locks(hash))
     666              :                         DO idir = 1, 3
     667              :                            m = 1 + idir
     668              :                            CALL dbcsr_get_block_p(matrix_cre(idir)%matrix, irow, icol, real_block, found)
     669              :                            CALL dbcsr_get_block_p(matrix_cim(idir)%matrix, irow, icol, imag_block, found)
     670              :                            IF (.NOT. (ASSOCIATED(real_block) .AND. ASSOCIATED(imag_block))) CYCLE
     671              :                            ! <a|Vnl~ (r_d - R_c)|b> - <a|(r_d - R_c) Vnl~|b>
     672              :                            zblock(:, :) = MATMUL(CONJG(achint(1:na, 1:np, 1)), TRANSPOSE(bcint(1:nb, 1:np, m))) - &
     673              :                                           MATMUL(CONJG(achint(1:na, 1:np, m)), TRANSPOSE(bcint(1:nb, 1:np, 1)))
     674              :                            real_block(1:na, 1:nb) = real_block(1:na, 1:nb) + REAL(zblock, KIND=dp)
     675              :                            imag_block(1:na, 1:nb) = imag_block(1:na, 1:nb) + AIMAG(zblock)
     676              :                         END DO
     677              : !$                      CALL omp_unset_lock(locks(hash))
     678              :                         DEALLOCATE (zblock)
     679              :                         EXIT
     680              :                      END IF
     681              :                   END DO
     682              :                END DO
     683              :             END DO
     684              : 
     685              :          END DO
     686              : 
     687              : !$OMP DO
     688              : !$       DO lock_num = 1, nlock
     689              : !$          call omp_destroy_lock(locks(lock_num))
     690              : !$       END DO
     691              : !$OMP END DO
     692              : 
     693              : !$OMP SINGLE
     694              : !$       DEALLOCATE (locks)
     695              : !$OMP END SINGLE NOWAIT
     696              : 
     697              : !$OMP END PARALLEL
     698           92 :          CALL release_sap_int(sap_int)
     699              : 
     700          184 :          DEALLOCATE (basis_set)
     701              :       END IF
     702              : 
     703           92 :       CALL timestop(handle)
     704              : 
     705          184 :    END SUBROUTINE velocity_gauge_nl_commutator
     706              : 
     707              : ! **************************************************************************************************
     708              : !> \brief Calculate complex plane-wave projector integrals in sap_int_complex_type.
     709              : !>        adapted from build_sap_ints
     710              : !>        Do this on each MPI task as the integrals need to be available globally.
     711              : !>        Might be faster than communicating as the integrals are obtained analytically.
     712              : !>        If asked, compute basis-center derivatives of the plane-wave integrals.
     713              : !>        If moment is requested, compute the moment-weighted integrals
     714              : !>        <a|exp(i k.r) (r_d - R_c,d)|p> (d=x,y,z) in slots 2:4, with the moment taken
     715              : !>        relative to the projector center R_c (the frame origin used here)
     716              : !> \param sap_int complex plane-wave integrals and their derivatives or coordinate moments
     717              : !> \param sap_ppnl ...
     718              : !> \param qs_kind_set ...
     719              : !> \param particle_set ...
     720              : !> \param cell ...
     721              : !> \param kvec ...
     722              : !> \param basis_set ...
     723              : !> \param nkind ...
     724              : !> \param derivative ...
     725              : !> \param moment ...
     726              : ! **************************************************************************************************
     727          184 :    SUBROUTINE build_sap_exp_ints(sap_int, sap_ppnl, qs_kind_set, particle_set, cell, &
     728          184 :                                  kvec, basis_set, nkind, derivative, moment)
     729              :       TYPE(sap_int_complex_type), DIMENSION(:), &
     730              :          INTENT(INOUT), POINTER                          :: sap_int
     731              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     732              :          INTENT(IN), POINTER                             :: sap_ppnl
     733              :       TYPE(qs_kind_type), DIMENSION(:), INTENT(IN), &
     734              :          POINTER                                         :: qs_kind_set
     735              :       TYPE(particle_type), DIMENSION(:), INTENT(IN), &
     736              :          POINTER                                         :: particle_set
     737              :       TYPE(cell_type), INTENT(IN), POINTER               :: cell
     738              :       REAL(KIND=dp), DIMENSION(3), INTENT(in)            :: kvec
     739              :       TYPE(gto_basis_set_p_type), DIMENSION(:), &
     740              :          INTENT(IN)                                      :: basis_set
     741              :       INTEGER, INTENT(IN)                                :: nkind
     742              :       LOGICAL, INTENT(IN)                                :: derivative
     743              :       LOGICAL, INTENT(IN), OPTIONAL                      :: moment
     744              : 
     745              :       CHARACTER(len=*), PARAMETER :: routiuneN = "build_sap_exp_ints"
     746              : 
     747          184 :       COMPLEX(KIND=dp), ALLOCATABLE                      :: ai_work_dz(:, :, :), ai_work_z(:, :), &
     748          184 :                                                             work_dz(:, :, :), work_z(:, :)
     749              :       INTEGER :: handle, i, iac, iatom, idir, ikind, ilist, iset, jneighbor, katom, kkind, l, &
     750              :          lc_max, lc_min, ldints, lppnl, maxco, maxlppnl, maxppnl, maxsgf, na, nb, ncoa, ncoc, &
     751              :          nlist, nneighbor, np, nppnl, nprjc, nseta, nsgfa, nsl, prjc, sgfa, slot
     752              :       INTEGER, DIMENSION(3)                              :: cell_c
     753          184 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, npgfa, nprj_ppnl, &
     754          184 :                                                             nsgf_seta
     755          184 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa
     756              :       LOGICAL                                            :: dogth, my_moment
     757              :       REAL(KIND=dp)                                      :: dac, ppnl_radius
     758              :       REAL(KIND=dp), DIMENSION(1)                        :: rprjc, zetc
     759              :       REAL(KIND=dp), DIMENSION(3)                        :: ra, rac, raf, rc, rcf
     760          184 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: alpha_ppnl, set_radius_a
     761          184 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: cprj, rpgfa, sphi_a, vprj_ppnl, zeta
     762              :       TYPE(clist_complex_type), POINTER                  :: clist
     763          184 :       TYPE(gth_potential_p_type), DIMENSION(:), POINTER  :: gpotential
     764              :       TYPE(gth_potential_type), POINTER                  :: gth_potential
     765          184 :       TYPE(sgp_potential_p_type), DIMENSION(:), POINTER  :: spotential
     766              :       TYPE(sgp_potential_type), POINTER                  :: sgp_potential
     767              : 
     768          184 :       CALL timeset(routiuneN, handle)
     769              : 
     770          184 :       my_moment = .FALSE.
     771          184 :       IF (PRESENT(moment)) my_moment = moment
     772              :       ! derivative and moment integrals use the same storage slots 2:4
     773          184 :       CPASSERT(.NOT. (derivative .AND. my_moment))
     774          184 :       nsl = 1
     775          184 :       IF (derivative .OR. my_moment) nsl = 4
     776              : 
     777              :       CALL get_qs_kind_set(qs_kind_set, &
     778              :                            maxco=maxco, &
     779              :                            maxlppnl=maxlppnl, &
     780              :                            maxppnl=maxppnl, &
     781          184 :                            maxsgf=maxsgf)
     782              : 
     783              :       ! maximum dimensions for allocations
     784          184 :       ldints = MAX(maxco, ncoset(maxlppnl), maxsgf, maxppnl)
     785              : 
     786              :       !set up direct access to basis and potential
     787          184 :       NULLIFY (gpotential, spotential)
     788         1672 :       ALLOCATE (gpotential(nkind), spotential(nkind))
     789          560 :       DO ikind = 1, nkind
     790          376 :          CALL get_qs_kind(qs_kind_set(ikind), gth_potential=gth_potential, sgp_potential=sgp_potential)
     791          376 :          NULLIFY (gpotential(ikind)%gth_potential)
     792          376 :          NULLIFY (spotential(ikind)%sgp_potential)
     793          560 :          IF (ASSOCIATED(gth_potential)) THEN
     794          376 :             gpotential(ikind)%gth_potential => gth_potential
     795            0 :          ELSE IF (ASSOCIATED(sgp_potential)) THEN
     796            0 :             spotential(ikind)%sgp_potential => sgp_potential
     797              :          END IF
     798              :       END DO
     799              : 
     800              :       !allocate sap int
     801          184 :       NULLIFY (clist)
     802         2364 :       DO slot = 1, sap_ppnl(1)%nl_size
     803              : 
     804         2180 :          ikind = sap_ppnl(1)%nlist_task(slot)%ikind
     805         2180 :          kkind = sap_ppnl(1)%nlist_task(slot)%jkind
     806         2180 :          iatom = sap_ppnl(1)%nlist_task(slot)%iatom
     807         2180 :          katom = sap_ppnl(1)%nlist_task(slot)%jatom
     808         2180 :          nlist = sap_ppnl(1)%nlist_task(slot)%nlist
     809         2180 :          ilist = sap_ppnl(1)%nlist_task(slot)%ilist
     810         2180 :          nneighbor = sap_ppnl(1)%nlist_task(slot)%nnode
     811              : 
     812         2180 :          iac = ikind + nkind*(kkind - 1)
     813         2180 :          IF (.NOT. ASSOCIATED(basis_set(ikind)%gto_basis_set)) CYCLE
     814         2180 :          IF (.NOT. ASSOCIATED(gpotential(kkind)%gth_potential) .AND. &
     815              :              .NOT. ASSOCIATED(spotential(kkind)%sgp_potential)) CYCLE
     816         2180 :          IF (.NOT. ASSOCIATED(sap_int(iac)%alist)) THEN
     817          416 :             sap_int(iac)%a_kind = ikind
     818          416 :             sap_int(iac)%p_kind = kkind
     819          416 :             sap_int(iac)%nalist = nlist
     820         2256 :             ALLOCATE (sap_int(iac)%alist(nlist))
     821         1424 :             DO i = 1, nlist
     822         1008 :                NULLIFY (sap_int(iac)%alist(i)%clist)
     823         1008 :                sap_int(iac)%alist(i)%aatom = 0
     824         1424 :                sap_int(iac)%alist(i)%nclist = 0
     825              :             END DO
     826              :          END IF
     827         2364 :          IF (.NOT. ASSOCIATED(sap_int(iac)%alist(ilist)%clist)) THEN
     828         1008 :             sap_int(iac)%alist(ilist)%aatom = iatom
     829         1008 :             sap_int(iac)%alist(ilist)%nclist = nneighbor
     830        12260 :             ALLOCATE (sap_int(iac)%alist(ilist)%clist(nneighbor))
     831         3188 :             DO i = 1, nneighbor
     832         2180 :                clist => sap_int(iac)%alist(ilist)%clist(i)
     833         2180 :                clist%catom = 0
     834         2180 :                NULLIFY (clist%acint)
     835         2180 :                NULLIFY (clist%achint)
     836         3188 :                NULLIFY (clist%sgf_list)
     837              :             END DO
     838              :          END IF
     839              :       END DO
     840              : 
     841              :       ! actual calculation of the complex plane-wave projector integrals
     842              :       ! allocate temporary storage using maximum dimensions
     843              : 
     844              : !$OMP PARALLEL DEFAULT(NONE) &
     845              : !$OMP SHARED (basis_set, gpotential, ncoset, sap_ppnl, sap_int, nkind, ldints, maxco, nco, cell, &
     846              : !$OMP         particle_set, kvec, derivative, my_moment, nsl) &
     847              : !$OMP PRIVATE (slot, ikind, kkind, iatom, katom, nlist, ilist, nneighbor, jneighbor, cell_c, rac, dac, &
     848              : !$OMP          iac, first_sgfa, la_max, la_min, npgfa, nseta, nsgfa, nsgf_seta, rpgfa, set_radius_a, &
     849              : !$OMP          sphi_a, zeta, alpha_ppnl, cprj, lppnl, nppnl, nprj_ppnl, ppnl_radius, vprj_ppnl, clist, &
     850              : !$OMP          ra, rc, ncoa, sgfa, prjc, work_z, nprjc, rprjc, lc_max, lc_min, zetc, ncoc, ai_work_z, &
     851          184 : !$OMP          na, nb, np, dogth, raf, rcf, work_dz, ai_work_dz, idir)
     852              : 
     853              :       ALLOCATE (work_z(ldints, ldints), ai_work_z(maxco, maxco))
     854              :       IF (derivative .OR. my_moment) THEN
     855              :          ALLOCATE (work_dz(ldints, ldints, 3), ai_work_dz(maxco, maxco, 3))
     856              :       END IF
     857              :       work_z = 0.0_dp
     858              :       ai_work_z = 0.0_dp
     859              :       dogth = .FALSE.
     860              : 
     861              :       NULLIFY (first_sgfa, la_max, la_min, npgfa, nsgf_seta, rpgfa, set_radius_a, sphi_a, zeta)
     862              :       NULLIFY (alpha_ppnl, cprj, nprj_ppnl, vprj_ppnl)
     863              :       NULLIFY (clist)
     864              : 
     865              : !$OMP DO SCHEDULE(GUIDED)
     866              :       DO slot = 1, sap_ppnl(1)%nl_size
     867              :          ikind = sap_ppnl(1)%nlist_task(slot)%ikind
     868              :          kkind = sap_ppnl(1)%nlist_task(slot)%jkind
     869              :          iatom = sap_ppnl(1)%nlist_task(slot)%iatom
     870              :          katom = sap_ppnl(1)%nlist_task(slot)%jatom
     871              :          nlist = sap_ppnl(1)%nlist_task(slot)%nlist
     872              :          ilist = sap_ppnl(1)%nlist_task(slot)%ilist
     873              :          nneighbor = sap_ppnl(1)%nlist_task(slot)%nnode
     874              :          jneighbor = sap_ppnl(1)%nlist_task(slot)%inode
     875              :          cell_c(:) = sap_ppnl(1)%nlist_task(slot)%cell(:)
     876              :          rac(1:3) = sap_ppnl(1)%nlist_task(slot)%r(1:3)
     877              :          dac = NORM2(rac)
     878              : 
     879              :          iac = ikind + nkind*(kkind - 1)
     880              :          IF (.NOT. ASSOCIATED(basis_set(ikind)%gto_basis_set)) CYCLE
     881              :          ! get definition of gto basis set
     882              :          first_sgfa => basis_set(ikind)%gto_basis_set%first_sgf
     883              :          la_max => basis_set(ikind)%gto_basis_set%lmax
     884              :          la_min => basis_set(ikind)%gto_basis_set%lmin
     885              :          npgfa => basis_set(ikind)%gto_basis_set%npgf
     886              :          nseta = basis_set(ikind)%gto_basis_set%nset
     887              :          nsgfa = basis_set(ikind)%gto_basis_set%nsgf
     888              :          nsgf_seta => basis_set(ikind)%gto_basis_set%nsgf_set
     889              :          rpgfa => basis_set(ikind)%gto_basis_set%pgf_radius
     890              :          set_radius_a => basis_set(ikind)%gto_basis_set%set_radius
     891              :          sphi_a => basis_set(ikind)%gto_basis_set%sphi
     892              :          zeta => basis_set(ikind)%gto_basis_set%zet
     893              : 
     894              :          IF (ASSOCIATED(gpotential(kkind)%gth_potential)) THEN
     895              :             ! GTH potential
     896              :             dogth = .TRUE.
     897              :             alpha_ppnl => gpotential(kkind)%gth_potential%alpha_ppnl
     898              :             cprj => gpotential(kkind)%gth_potential%cprj
     899              :             lppnl = gpotential(kkind)%gth_potential%lppnl
     900              :             nppnl = gpotential(kkind)%gth_potential%nppnl
     901              :             nprj_ppnl => gpotential(kkind)%gth_potential%nprj_ppnl
     902              :             ppnl_radius = gpotential(kkind)%gth_potential%ppnl_radius
     903              :             vprj_ppnl => gpotential(kkind)%gth_potential%vprj_ppnl
     904              :          ELSE
     905              :             CYCLE
     906              :          END IF
     907              : 
     908              :          clist => sap_int(iac)%alist(ilist)%clist(jneighbor)
     909              : 
     910              :          clist%catom = katom
     911              :          clist%cell = cell_c
     912              :          clist%rac = rac
     913              : 
     914              :          ALLOCATE (clist%acint(nsgfa, nppnl, nsl), clist%achint(nsgfa, nppnl, nsl))
     915              :          clist%acint = 0.0_dp
     916              :          clist%achint = 0.0_dp
     917              :          clist%nsgf_cnt = 0
     918              : 
     919              :          ! reference point at zero
     920              :          ra(:) = pbc(particle_set(iatom)%r(:), cell)
     921              :          rc(:) = ra + rac
     922              : 
     923              :          ! reference point at pseudized atom
     924              :          raf(:) = ra - rc
     925              :          rcf(:) = 0._dp
     926              : 
     927              :          DO iset = 1, nseta
     928              :             ncoa = npgfa(iset)*ncoset(la_max(iset))
     929              :             sgfa = first_sgfa(1, iset)
     930              :             IF (dogth) THEN
     931              :                prjc = 1
     932              :                work_z = 0.0_dp
     933              :                IF (derivative .OR. my_moment) work_dz = 0.0_dp
     934              :                DO l = 0, lppnl
     935              :                   nprjc = nprj_ppnl(l)*nco(l)
     936              :                   IF (nprjc == 0) CYCLE
     937              :                   rprjc(1) = ppnl_radius
     938              :                   IF (set_radius_a(iset) + rprjc(1) < dac) CYCLE
     939              :                   lc_max = l + 2*(nprj_ppnl(l) - 1)
     940              :                   lc_min = l
     941              :                   zetc(1) = alpha_ppnl(l)
     942              :                   ncoc = ncoset(lc_max)
     943              : 
     944              :                   IF (derivative) THEN
     945              :                      CALL expikr(la_max(iset), npgfa(iset), zeta(:, iset), rpgfa(:, iset), la_min(iset), &
     946              :                                  lc_max, 1, zetc, rprjc, lc_min, raf, rcf, kvec, ai_work_z, dexpab=ai_work_dz)
     947              :                   ELSE IF (my_moment) THEN
     948              :                      ! Coordinate-weighted integrals relative to the projector center.
     949              :                      CALL expikr(la_max(iset), npgfa(iset), zeta(:, iset), rpgfa(:, iset), la_min(iset), &
     950              :                                  lc_max, 1, zetc, rprjc, lc_min, raf, rcf, kvec, ai_work_z, momentab=ai_work_dz)
     951              :                   ELSE
     952              :                      CALL expikr(la_max(iset), npgfa(iset), zeta(:, iset), rpgfa(:, iset), la_min(iset), &
     953              :                                  lc_max, 1, zetc, rprjc, lc_min, raf, rcf, kvec, ai_work_z)
     954              :                   END IF
     955              :                   ! projector functions: Cartesian -> spherical
     956              :                   na = ncoa
     957              :                   nb = nprjc
     958              :                   np = ncoc
     959              :                   work_z(1:na, prjc:prjc + nb - 1) = &
     960              :                      MATMUL(ai_work_z(1:na, 1:np), cprj(1:np, prjc:prjc + nb - 1))
     961              : 
     962              :                   IF (derivative .OR. my_moment) THEN
     963              :                      DO idir = 1, 3
     964              :                         work_dz(1:na, prjc:prjc + nb - 1, idir) = &
     965              :                            MATMUL(ai_work_dz(1:na, 1:np, idir), cprj(1:np, prjc:prjc + nb - 1))
     966              :                      END DO
     967              :                   END IF
     968              : 
     969              :                   prjc = prjc + nprjc
     970              :                END DO
     971              : 
     972              :                ! contract gto basis set into acint
     973              :                na = nsgf_seta(iset)
     974              :                nb = nppnl
     975              :                np = ncoa
     976              :                clist%acint(sgfa:sgfa + na - 1, 1:nb, 1) = &
     977              :                   MATMUL(TRANSPOSE(sphi_a(1:np, sgfa:sgfa + na - 1)), work_z(1:np, 1:nb))
     978              :                IF (derivative .OR. my_moment) THEN
     979              :                   DO idir = 1, 3
     980              :                      clist%acint(sgfa:sgfa + na - 1, 1:nb, 1 + idir) = &
     981              :                         MATMUL(TRANSPOSE(sphi_a(1:np, sgfa:sgfa + na - 1)), work_dz(1:np, 1:nb, idir))
     982              :                   END DO
     983              :                END IF
     984              : 
     985              :                ! Apply the real projector interaction to each complex integral slot.
     986              :                DO idir = 1, nsl
     987              :                   clist%achint(sgfa:sgfa + na - 1, 1:nb, idir) = &
     988              :                      MATMUL(clist%acint(sgfa:sgfa + na - 1, 1:nb, idir), vprj_ppnl(1:nb, 1:nb))
     989              :                END DO
     990              :             END IF
     991              : 
     992              :          END DO
     993              :          ! Retain the component-wise screening bound used by the split representation.
     994              :          clist%maxac = MAXVAL(MAX(ABS(REAL(clist%acint(:, :, 1), KIND=dp)), ABS(AIMAG(clist%acint(:, :, 1)))))
     995              :          clist%maxach = MAXVAL(MAX(ABS(REAL(clist%achint(:, :, 1), KIND=dp)), ABS(AIMAG(clist%achint(:, :, 1)))))
     996              :       END DO
     997              : 
     998              :       DEALLOCATE (work_z, ai_work_z)
     999              :       IF (derivative .OR. my_moment) DEALLOCATE (work_dz, ai_work_dz)
    1000              : 
    1001              : !$OMP END PARALLEL
    1002              : 
    1003          184 :       DEALLOCATE (gpotential, spotential)
    1004              : 
    1005          184 :       CALL timestop(handle)
    1006              : 
    1007          552 :    END SUBROUTINE build_sap_exp_ints
    1008              : 
    1009              : ! **************************************************************************************************
    1010              : !> \brief Calculate the force associated to non-local pseudo potential in the velocity gauge
    1011              : !> \param qs_env ...
    1012              : !> \param particle_set ...
    1013              : !> \date    09.2023
    1014              : !> \author  Guillaume Le Breton
    1015              : ! **************************************************************************************************
    1016           32 :    SUBROUTINE velocity_gauge_nl_force(qs_env, particle_set)
    1017              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1018              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1019              : 
    1020              :       CHARACTER(len=*), PARAMETER :: routiuneN = "velocity_gauge_nl_force"
    1021              : 
    1022           32 :       COMPLEX(KIND=dp), ALLOCATABLE                      :: zblock(:, :), zblock_b(:, :)
    1023           32 :       COMPLEX(KIND=dp), DIMENSION(:, :, :), POINTER      :: achint, acint, bchint, bcint
    1024              :       INTEGER :: handle, i, iac, iatom, ibc, icol, idir, ikind, irow, jatom, jkind, kac, katom, &
    1025              :          kbc, kkind, maxl, maxlgto, maxlppnl, na, natom, nb, nkind, np, slot
    1026           32 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_of_kind, kind_of
    1027              :       INTEGER, DIMENSION(3)                              :: cell_b
    1028              :       LOGICAL                                            :: found_imag, found_real
    1029              :       REAL(dp)                                           :: eps_ppnl, f0, sign_imag
    1030              :       REAL(KIND=dp), DIMENSION(3)                        :: fa, fb, rab, vec_pot
    1031              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1032           32 :          POINTER                                         :: sab_orb, sap_ppnl
    1033              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
    1034              :       TYPE(gto_basis_set_p_type), ALLOCATABLE, &
    1035           32 :          DIMENSION(:)                                    :: basis_set
    1036              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1037           32 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: rho_ao, rho_ao_im
    1038              :       TYPE(cell_type), POINTER                           :: cell
    1039           32 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1040              :       TYPE(alist_complex_type), POINTER                  :: alist_ac, alist_bc
    1041           32 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: matrix_p_imag, matrix_p_real
    1042           64 :       REAL(KIND=dp), DIMENSION(3, SIZE(particle_set))    :: force_thread
    1043           32 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
    1044           32 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1045              :       TYPE(qs_rho_type), POINTER                         :: rho
    1046           32 :       TYPE(sap_int_complex_type), DIMENSION(:), POINTER  :: sap_int
    1047              : 
    1048           32 :       CALL timeset(routiuneN, handle)
    1049              : 
    1050           32 :       NULLIFY (sap_ppnl)
    1051              : 
    1052              :       CALL get_qs_env(qs_env, &
    1053           32 :                       sap_ppnl=sap_ppnl)
    1054              : 
    1055           32 :       IF (ASSOCIATED(sap_ppnl)) THEN
    1056           32 :          NULLIFY (qs_kind_set, cell, dft_control, force, sab_orb, atomic_kind_set, &
    1057           32 :                   sap_int)
    1058              :          ! Load and initialized the required quantities
    1059              : 
    1060              :          CALL get_qs_env(qs_env, &
    1061              :                          sab_orb=sab_orb, &
    1062              :                          force=force, &
    1063              :                          dft_control=dft_control, &
    1064              :                          qs_kind_set=qs_kind_set, &
    1065              :                          cell=cell, &
    1066              :                          atomic_kind_set=atomic_kind_set, &
    1067           32 :                          rho=rho)
    1068              : 
    1069           32 :          nkind = SIZE(atomic_kind_set)
    1070           32 :          natom = SIZE(particle_set)
    1071           32 :          eps_ppnl = dft_control%qs_control%eps_ppnl
    1072              : 
    1073              :          CALL get_qs_kind_set(qs_kind_set, &
    1074              :                               maxlgto=maxlgto, &
    1075           32 :                               maxlppnl=maxlppnl)
    1076              : 
    1077           32 :          maxl = MAX(maxlppnl, maxlgto)
    1078           32 :          CALL init_orbital_pointers(maxl + 1)
    1079              : 
    1080              :          ! initalize sab_int types to store the integrals
    1081          224 :          ALLOCATE (sap_int(nkind*nkind))
    1082              : 
    1083              :          ! get basis set
    1084          160 :          ALLOCATE (basis_set(nkind))
    1085           96 :          DO ikind = 1, nkind
    1086           64 :             CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set)
    1087           96 :             IF (ASSOCIATED(orb_basis_set)) THEN
    1088           64 :                basis_set(ikind)%gto_basis_set => orb_basis_set
    1089              :             ELSE
    1090            0 :                NULLIFY (basis_set(ikind)%gto_basis_set)
    1091              :             END IF
    1092              :          END DO
    1093              : 
    1094              :          !get vector potential
    1095          128 :          vec_pot = dft_control%rtp_control%vec_pot
    1096              : 
    1097          536 :          force_thread = 0.0_dp
    1098              : 
    1099           32 :          CALL qs_rho_get(rho_struct=rho, rho_ao=rho_ao, rho_ao_im=rho_ao_im)
    1100              :          ! To avoid FOR loop over spin, sum the 2 spin into the first one directly. Undone later on
    1101           32 :          IF (SIZE(rho_ao) == 2) THEN
    1102              :             CALL dbcsr_add(rho_ao(1)%matrix, rho_ao(2)%matrix, &
    1103            0 :                            alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
    1104              :             CALL dbcsr_add(rho_ao_im(1)%matrix, rho_ao_im(2)%matrix, &
    1105            0 :                            alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
    1106              :          END IF
    1107              : 
    1108              :          ! Compute complex plane-wave projector integrals and their basis-center derivatives.
    1109              :          CALL build_sap_exp_ints(sap_int, sap_ppnl, qs_kind_set, particle_set, &
    1110           32 :                                  cell, kvec=vec_pot, basis_set=basis_set, nkind=nkind, derivative=.TRUE.)
    1111           32 :          CALL sap_sort(sap_int)
    1112              : 
    1113              :          ! Compute the force, on nuclei A it is given by: Re(P_ab) Re(dV_ab/dRA) - Im(P_ab) Im(dV_ab/dRA)
    1114              : 
    1115              : !$OMP PARALLEL &
    1116              : !$OMP DEFAULT (NONE) &
    1117              : !$OMP SHARED (basis_set, sab_orb, sap_int, eps_ppnl, nkind, natom,&
    1118              : !$OMP         rho_ao, rho_ao_im) &
    1119              : !$OMP PRIVATE (matrix_p_real, matrix_p_imag, acint, achint, bcint, bchint, &
    1120              : !$OMP           slot, ikind, jkind, iatom, jatom,&
    1121              : !$OMP          cell_b, rab, irow, icol, fa, fb, f0, found_real, found_imag, sign_imag, &
    1122              : !$OMP          kkind, iac, ibc, alist_ac, alist_bc, kac, kbc,&
    1123              : !$OMP          zblock, zblock_b, na, np, nb,  katom) &
    1124           32 : !$OMP REDUCTION (+ : force_thread )
    1125              : 
    1126              :          NULLIFY (acint, bcint, achint, bchint)
    1127              : 
    1128              :          ! loop over atom pairs
    1129              : !$OMP DO SCHEDULE(GUIDED)
    1130              :          DO slot = 1, sab_orb(1)%nl_size
    1131              :             ikind = sab_orb(1)%nlist_task(slot)%ikind
    1132              :             jkind = sab_orb(1)%nlist_task(slot)%jkind
    1133              :             iatom = sab_orb(1)%nlist_task(slot)%iatom
    1134              :             jatom = sab_orb(1)%nlist_task(slot)%jatom
    1135              :             cell_b(:) = sab_orb(1)%nlist_task(slot)%cell
    1136              :             rab(1:3) = sab_orb(1)%nlist_task(slot)%r(1:3)
    1137              : 
    1138              :             IF (.NOT. ASSOCIATED(basis_set(ikind)%gto_basis_set)) CYCLE
    1139              :             IF (.NOT. ASSOCIATED(basis_set(jkind)%gto_basis_set)) CYCLE
    1140              : 
    1141              :             ! Use the symmetry of the first derivatives
    1142              :             IF (iatom == jatom) THEN
    1143              :                f0 = 1.0_dp
    1144              :             ELSE
    1145              :                f0 = 2.0_dp
    1146              :             END IF
    1147              : 
    1148              :             fa = 0.0_dp
    1149              :             fb = 0.0_dp
    1150              : 
    1151              :             IF (iatom <= jatom) THEN
    1152              :                irow = iatom
    1153              :                icol = jatom
    1154              :                sign_imag = +1.0_dp
    1155              :             ELSE
    1156              :                irow = jatom
    1157              :                icol = iatom
    1158              :                sign_imag = -1.0_dp
    1159              :             END IF
    1160              :             NULLIFY (matrix_p_real, matrix_p_imag)
    1161              :             CALL dbcsr_get_block_p(rho_ao(1)%matrix, irow, icol, matrix_p_real, found_real)
    1162              :             CALL dbcsr_get_block_p(rho_ao_im(1)%matrix, irow, icol, matrix_p_imag, found_imag)
    1163              : 
    1164              :             IF (found_real .OR. found_imag) THEN
    1165              :                ! loop over the <gto_a|ppln_c>h_ij<ppnl_c|gto_b> pairs
    1166              :                DO kkind = 1, nkind
    1167              :                   iac = ikind + nkind*(kkind - 1)
    1168              :                   ibc = jkind + nkind*(kkind - 1)
    1169              :                   IF (.NOT. ASSOCIATED(sap_int(iac)%alist)) CYCLE
    1170              :                   IF (.NOT. ASSOCIATED(sap_int(ibc)%alist)) CYCLE
    1171              :                   CALL get_alist(sap_int(iac), alist_ac, iatom)
    1172              :                   CALL get_alist(sap_int(ibc), alist_bc, jatom)
    1173              :                   IF (.NOT. ASSOCIATED(alist_ac)) CYCLE
    1174              :                   IF (.NOT. ASSOCIATED(alist_bc)) CYCLE
    1175              :                   DO kac = 1, alist_ac%nclist
    1176              :                      DO kbc = 1, alist_bc%nclist
    1177              :                         IF (alist_ac%clist(kac)%catom /= alist_bc%clist(kbc)%catom) CYCLE
    1178              :                         IF (ALL(cell_b + alist_bc%clist(kbc)%cell - alist_ac%clist(kac)%cell == 0)) THEN
    1179              :                            ! screening
    1180              :                            IF (alist_ac%clist(kac)%maxac*alist_bc%clist(kbc)%maxach < eps_ppnl) CYCLE
    1181              : 
    1182              :                            acint => alist_ac%clist(kac)%acint
    1183              :                            bcint => alist_bc%clist(kbc)%acint
    1184              :                            achint => alist_ac%clist(kac)%achint
    1185              :                            bchint => alist_bc%clist(kbc)%achint
    1186              : 
    1187              :                            na = SIZE(acint, 1)
    1188              :                            np = SIZE(acint, 2)
    1189              :                            nb = SIZE(bcint, 1)
    1190              :                            ! Differentiate the complex projector product on each basis center.
    1191              :                            katom = alist_ac%clist(kac)%catom
    1192              :                            ALLOCATE (zblock(MERGE(na, nb, iatom <= jatom), MERGE(nb, na, iatom <= jatom)))
    1193              :                            ALLOCATE (zblock_b(SIZE(zblock, 1), SIZE(zblock, 2)))
    1194              :                            DO idir = 1, 3
    1195              :                               IF (iatom <= jatom) THEN
    1196              :                                  zblock(:, :) = MATMUL(acint(1:na, 1:np, 1 + idir), &
    1197              :                                                        CONJG(TRANSPOSE(bchint(1:nb, 1:np, 1))))
    1198              :                                  zblock_b(:, :) = MATMUL(achint(1:na, 1:np, 1), &
    1199              :                                                          CONJG(TRANSPOSE(bcint(1:nb, 1:np, 1 + idir))))
    1200              :                               ELSE
    1201              :                                  zblock(:, :) = MATMUL(bchint(1:nb, 1:np, 1), &
    1202              :                                                        CONJG(TRANSPOSE(acint(1:na, 1:np, 1 + idir))))
    1203              :                                  zblock_b(:, :) = MATMUL(bcint(1:nb, 1:np, 1 + idir), &
    1204              :                                                          CONJG(TRANSPOSE(achint(1:na, 1:np, 1))))
    1205              :                               END IF
    1206              :                               fa(idir) = 0.0_dp
    1207              :                               fb(idir) = 0.0_dp
    1208              :                               IF (found_real) THEN
    1209              :                                  fa(idir) = SUM(matrix_p_real(1:SIZE(zblock, 1), 1:SIZE(zblock, 2))*REAL(zblock, KIND=dp))
    1210              :                                  fb(idir) = SUM(matrix_p_real(1:SIZE(zblock_b, 1), 1:SIZE(zblock_b, 2))*REAL(zblock_b, KIND=dp))
    1211              :                               END IF
    1212              :                               IF (found_imag) THEN
    1213              :                               fa(idir) = fa(idir) - sign_imag*SUM(matrix_p_imag(1:SIZE(zblock, 1), 1:SIZE(zblock, 2))*AIMAG(zblock))
    1214              :                         fb(idir) = fb(idir) - sign_imag*SUM(matrix_p_imag(1:SIZE(zblock_b, 1), 1:SIZE(zblock_b, 2))*AIMAG(zblock_b))
    1215              :                               END IF
    1216              :                               force_thread(idir, iatom) = force_thread(idir, iatom) + f0*fa(idir)
    1217              :                               force_thread(idir, katom) = force_thread(idir, katom) - f0*fa(idir)
    1218              :                               force_thread(idir, jatom) = force_thread(idir, jatom) + f0*fb(idir)
    1219              :                               force_thread(idir, katom) = force_thread(idir, katom) - f0*fb(idir)
    1220              :                            END DO
    1221              :                            DEALLOCATE (zblock, zblock_b)
    1222              :                            EXIT
    1223              :                         END IF
    1224              :                      END DO
    1225              :                   END DO
    1226              :                END DO
    1227              :             END IF
    1228              : 
    1229              :          END DO
    1230              : 
    1231              : !$OMP END PARALLEL
    1232              : 
    1233              :          ! Update the force
    1234           32 :          CALL get_atomic_kind_set(atomic_kind_set, atom_of_kind=atom_of_kind, kind_of=kind_of)
    1235              : !$OMP DO
    1236              :          DO iatom = 1, natom
    1237          126 :             i = atom_of_kind(iatom)
    1238          126 :             ikind = kind_of(iatom)
    1239          504 :             force(ikind)%gth_ppnl(:, i) = force(ikind)%gth_ppnl(:, i) + force_thread(:, iatom)
    1240              :          END DO
    1241              : !$OMP END DO
    1242              : 
    1243              :          ! Clean up
    1244           32 :          IF (SIZE(rho_ao) == 2) THEN
    1245              :             CALL dbcsr_add(rho_ao(1)%matrix, rho_ao(2)%matrix, &
    1246            0 :                            alpha_scalar=1.0_dp, beta_scalar=-1.0_dp)
    1247              :             CALL dbcsr_add(rho_ao_im(1)%matrix, rho_ao_im(2)%matrix, &
    1248            0 :                            alpha_scalar=1.0_dp, beta_scalar=-1.0_dp)
    1249              :          END IF
    1250           32 :          CALL release_sap_int(sap_int)
    1251              : 
    1252           64 :          DEALLOCATE (basis_set, atom_of_kind, kind_of)
    1253              : 
    1254              :       END IF
    1255              : 
    1256           32 :       CALL timestop(handle)
    1257              : 
    1258           64 :    END SUBROUTINE velocity_gauge_nl_force
    1259              : 
    1260              : END MODULE rt_propagation_velocity_gauge
        

Generated by: LCOV version 2.0-1