LCOV - code coverage report
Current view: top level - src - commutator_rpnl.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:9ccafda) Lines: 70.4 % 142 100
Test Date: 2026-10-15 00:55:44 Functions: 66.7 % 3 2

            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              : !> \brief Calculation of the non-local pseudopotential contribution to the core Hamiltonian
       9              : !>         <a|V(non-local)|b> = <a|p(l,i)>*h(i,j)*<p(l,j)|b>
      10              : !> \par History
      11              : !>      - refactered from qs_core_hamiltian [Joost VandeVondele, 2008-11-01]
      12              : !>      - full rewrite [jhu, 2009-01-23]
      13              : ! **************************************************************************************************
      14              : MODULE commutator_rpnl
      15              :    USE basis_set_types,                 ONLY: gto_basis_set_p_type,&
      16              :                                               gto_basis_set_type
      17              :    USE block_p_types,                   ONLY: block_p_type
      18              :    USE cell_types,                      ONLY: cell_type
      19              :    USE cp_dbcsr_api,                    ONLY: dbcsr_get_block_p,&
      20              :                                               dbcsr_p_type
      21              :    USE kinds,                           ONLY: dp
      22              :    USE particle_types,                  ONLY: particle_type
      23              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      24              :                                               qs_kind_type
      25              :    USE qs_neighbor_list_types,          ONLY: get_neighbor_list_set_p,&
      26              :                                               neighbor_list_set_p_type
      27              :    USE sap_kind_types,                  ONLY: alist_type,&
      28              :                                               build_sap_ints,&
      29              :                                               get_alist,&
      30              :                                               release_sap_int,&
      31              :                                               sap_int_type,&
      32              :                                               sap_sort
      33              : 
      34              : !$ USE OMP_LIB, ONLY: omp_lock_kind, &
      35              : !$                    omp_init_lock, omp_set_lock, &
      36              : !$                    omp_unset_lock, omp_destroy_lock
      37              : 
      38              : #include "./base/base_uses.f90"
      39              : 
      40              :    IMPLICIT NONE
      41              : 
      42              :    PRIVATE
      43              : 
      44              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'commutator_rpnl'
      45              : 
      46              :    PUBLIC :: build_com_mom_nl, build_com_nl_mag, build_com_vnl_giao
      47              : 
      48              : CONTAINS
      49              : 
      50              : ! **************************************************************************************************
      51              : !> \brief Calculate [r,Vnl] (matrix_rv), r x [r,Vnl] (matrix_rxrv)
      52              : !>        or [rr,Vnl] (matrix_rrv) in AO basis.
      53              : !>        Reference point is required for the two latter options
      54              : !>        Update: Calculate rxVnlxr (matrix_rvr) and rxrxVnl + Vnlxrxr (matrix_rrv_vrr)
      55              : !>        in AO basis. Added in the first place for current correction in
      56              : !>        the VG formalism (first order wrt vector potential).
      57              : !> \param qs_kind_set ...
      58              : !> \param sab_all ...
      59              : !> \param sap_ppnl ...
      60              : !> \param eps_ppnl ...
      61              : !> \param particle_set ...
      62              : !> \param cell ...
      63              : !> \param matrix_rv ...
      64              : !> \param matrix_rxrv ...
      65              : !> \param matrix_rrv ...
      66              : !> \param matrix_rvr ...
      67              : !> \param matrix_rrv_vrr ...
      68              : !> \param matrix_r_rxvr ...
      69              : !> \param matrix_rxvr_r ...
      70              : !> \param matrix_r_doublecom ...
      71              : !> \param pseudoatom ...
      72              : !> \param ref_point ...
      73              : ! **************************************************************************************************
      74          208 :    SUBROUTINE build_com_mom_nl(qs_kind_set, sab_all, sap_ppnl, eps_ppnl, particle_set, cell, matrix_rv, matrix_rxrv, &
      75          312 :                     matrix_rrv, matrix_rvr, matrix_rrv_vrr, matrix_r_rxvr, matrix_rxvr_r, matrix_r_doublecom, pseudoatom, ref_point)
      76              : 
      77              :       TYPE(qs_kind_type), DIMENSION(:), INTENT(IN), &
      78              :          POINTER                                         :: qs_kind_set
      79              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
      80              :          INTENT(IN), POINTER                             :: sab_all, sap_ppnl
      81              :       REAL(KIND=dp), INTENT(IN)                          :: eps_ppnl
      82              :       TYPE(particle_type), DIMENSION(:), INTENT(IN), &
      83              :          POINTER                                         :: particle_set
      84              :       TYPE(cell_type), INTENT(IN), POINTER               :: cell
      85              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT), &
      86              :          OPTIONAL                                        :: matrix_rv, matrix_rxrv, matrix_rrv, &
      87              :                                                             matrix_rvr, matrix_rrv_vrr
      88              :       TYPE(dbcsr_p_type), DIMENSION(:, :), &
      89              :          INTENT(INOUT), OPTIONAL                         :: matrix_r_rxvr, matrix_rxvr_r, &
      90              :                                                             matrix_r_doublecom
      91              :       INTEGER, INTENT(in), OPTIONAL                      :: pseudoatom
      92              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN), OPTIONAL  :: ref_point
      93              : 
      94              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'build_com_mom_nl'
      95              :       INTEGER, PARAMETER :: i_x = 2, i_xx = 5, i_xy = 6, i_xz = 7, i_y = 3, i_yx = i_xy, i_yy = 8, &
      96              :          i_yz = 9, i_z = 4, i_zx = i_xz, i_zy = i_yz, i_zz = 10
      97              : 
      98              :       INTEGER                                            :: handle, i, iab, iac, iatom, ibc, icol, &
      99              :                                                             ikind, ind, ind2, irow, jatom, jkind, &
     100              :                                                             kac, kbc, kkind, na, natom, nb, nkind, &
     101              :                                                             np, order, slot
     102              :       INTEGER, DIMENSION(3)                              :: cell_b
     103              :       LOGICAL :: asso_r_doublecom, asso_r_rxvr, asso_rrv, asso_rrv_vrr, asso_rv, asso_rvr, &
     104              :          asso_rxrv, asso_rxvr_r, do_symmetric, found, go, my_r_doublecom, my_r_rxvr, my_ref, &
     105              :          my_rrv, my_rrv_vrr, my_rv, my_rvr, my_rxrv, my_rxvr_r, periodic, ppnl_present, trans
     106              :       REAL(KIND=dp), DIMENSION(3)                        :: rab, rf
     107          104 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: achint, acint, bchint, bcint
     108              :       TYPE(alist_type), POINTER                          :: alist_ac, alist_bc
     109          104 :       TYPE(block_p_type), ALLOCATABLE, DIMENSION(:)      :: blocks_rrv, blocks_rrv_vrr, blocks_rv, &
     110          104 :                                                             blocks_rvr, blocks_rxrv
     111          104 :       TYPE(block_p_type), ALLOCATABLE, DIMENSION(:, :)   :: blocks_r_doublecom, blocks_r_rxvr, &
     112          104 :                                                             blocks_rxvr_r
     113              :       TYPE(gto_basis_set_p_type), ALLOCATABLE, &
     114          104 :          DIMENSION(:)                                    :: basis_set
     115              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
     116          104 :       TYPE(sap_int_type), DIMENSION(:), POINTER          :: sap_int
     117              : 
     118              : !$    INTEGER(kind=omp_lock_kind), &
     119          104 : !$       ALLOCATABLE, DIMENSION(:) :: locks
     120              : !$    INTEGER                                            :: lock_num, hash
     121              : !$    INTEGER, PARAMETER                                 :: nlock = 501
     122              : 
     123          104 :       ppnl_present = ASSOCIATED(sap_ppnl)
     124          104 :       IF (.NOT. ppnl_present) RETURN
     125              : 
     126           80 :       CALL timeset(routineN, handle)
     127              : 
     128           80 :       my_r_doublecom = .FALSE.
     129           80 :       my_r_rxvr = .FALSE.
     130           80 :       my_rxvr_r = .FALSE.
     131           80 :       my_rxrv = .FALSE.
     132           80 :       my_rrv = .FALSE.
     133           80 :       my_rv = .FALSE.
     134           80 :       my_rvr = .FALSE.
     135           80 :       my_rrv_vrr = .FALSE.
     136           80 :       IF (PRESENT(matrix_r_doublecom)) my_r_doublecom = .TRUE.
     137           80 :       IF (PRESENT(matrix_r_rxvr)) my_r_rxvr = .TRUE.
     138           80 :       IF (PRESENT(matrix_rxvr_r)) my_rxvr_r = .TRUE.
     139           80 :       IF (PRESENT(matrix_rxrv)) my_rxrv = .TRUE.
     140           80 :       IF (PRESENT(matrix_rrv)) my_rrv = .TRUE.
     141           80 :       IF (PRESENT(matrix_rv)) my_rv = .TRUE.
     142           80 :       IF (PRESENT(matrix_rvr)) my_rvr = .TRUE.
     143           80 :       IF (PRESENT(matrix_rrv_vrr)) my_rrv_vrr = .TRUE.
     144           80 :       IF (.NOT. (my_rv .OR. my_rxrv .OR. my_rrv .OR. my_rvr .OR. my_rrv_vrr .OR. my_r_rxvr .OR. my_rxvr_r .OR. my_r_doublecom)) THEN
     145            0 :          CPABORT('No dbcsr matrix provided for commutator calculation!')
     146              :       END IF
     147              : 
     148           80 :       natom = SIZE(particle_set)
     149              : 
     150           80 :       IF (my_rxrv .OR. my_rrv .OR. my_r_rxvr .OR. my_rxvr_r .OR. my_r_doublecom) THEN
     151           46 :          CPASSERT(PRESENT(ref_point)) ! need reference point for r x [r,Vnl] and [rr,Vnl]
     152              :       END IF
     153              : 
     154              :       ! Only products with two coordinates on the same side need second-order SAP moments.
     155           80 :       order = 1
     156           80 :       IF (my_rrv .OR. my_rrv_vrr .OR. my_r_rxvr .OR. my_rxvr_r .OR. my_r_doublecom) order = 2
     157              : 
     158              :       ! When we want the double commutator [[Vnl, r], r], we also want to fix the pseudoatom
     159           20 :       IF (my_r_doublecom) THEN
     160            6 :          CPASSERT(PRESENT(pseudoatom))
     161              :       END IF
     162              : 
     163          200 :       periodic = ANY(cell%perd > 0)
     164           80 :       my_ref = .FALSE.
     165           80 :       IF (PRESENT(ref_point)) THEN
     166           52 :          IF (.NOT. periodic) THEN
     167           16 :             rf = ref_point
     168           16 :             my_ref = .TRUE.
     169              :          ELSE ! use my_ref = False in periodic case, corresponds to distributed ref point
     170              :             ! Reference-point diagnostics depend on the operator, not the SAP moment order.
     171           36 :             IF (order > 1 .OR. my_rxrv .OR. my_rvr) THEN
     172           36 :                CPWARN("Not clear how to define reference point for order > 1 in periodic cells.")
     173              :             END IF
     174              :          END IF
     175              :       END IF
     176              : 
     177           80 :       nkind = SIZE(qs_kind_set)
     178              : 
     179              :       !sap_int needs to be shared as multiple threads need to access this
     180           80 :       NULLIFY (sap_int)
     181          752 :       ALLOCATE (sap_int(nkind*nkind))
     182          592 :       DO i = 1, nkind*nkind
     183          512 :          NULLIFY (sap_int(i)%alist, sap_int(i)%asort, sap_int(i)%aindex)
     184          592 :          sap_int(i)%nalist = 0
     185              :       END DO
     186              : 
     187           80 :       IF (my_ref) THEN
     188              :          ! calculate integrals <a|x^n|p>
     189              :          CALL build_sap_ints(sap_int, sap_ppnl, qs_kind_set, order, moment_mode=.TRUE., refpoint=rf, &
     190           16 :                              particle_set=particle_set, cell=cell)
     191              :       ELSE
     192           64 :          CALL build_sap_ints(sap_int, sap_ppnl, qs_kind_set, order, moment_mode=.TRUE.)
     193              :       END IF
     194              : 
     195              :       ! *** Set up a sorting index
     196           80 :       CALL sap_sort(sap_int)
     197              : 
     198          432 :       ALLOCATE (basis_set(nkind))
     199          272 :       DO ikind = 1, nkind
     200          192 :          CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set)
     201          272 :          IF (ASSOCIATED(orb_basis_set)) THEN
     202          192 :             basis_set(ikind)%gto_basis_set => orb_basis_set
     203              :          ELSE
     204            0 :             NULLIFY (basis_set(ikind)%gto_basis_set)
     205              :          END IF
     206              :       END DO
     207              : 
     208              :       ! *** All integrals needed have been calculated and stored in sap_int
     209              :       ! *** We now calculate the commutator matrix elements
     210           80 :       CALL get_neighbor_list_set_p(neighbor_list_sets=sab_all, symmetric=do_symmetric)
     211              : 
     212              : !$OMP PARALLEL &
     213              : !$OMP DEFAULT (NONE) &
     214              : !$OMP SHARED  (basis_set, matrix_rv, matrix_rxrv, matrix_rrv, &
     215              : !$OMP          matrix_rvr, matrix_rrv_vrr, matrix_r_doublecom, &
     216              : !$OMP          sap_int, natom, nkind, eps_ppnl, locks, sab_all, &
     217              : !$OMP          my_rv, my_rxrv, my_rrv, my_rvr, my_rrv_vrr, &
     218              : !$OMP          my_r_doublecom, &
     219              : !$OMP          matrix_r_rxvr, matrix_rxvr_r, my_r_rxvr, my_rxvr_r, &
     220              : !$OMP          pseudoatom, do_symmetric) &
     221              : !$OMP PRIVATE (ikind, jkind, iatom, jatom, cell_b, rab, ind, ind2, &
     222              : !$OMP          iab, irow, icol, lock_num, &
     223              : !$OMP          blocks_rv, blocks_rxrv, blocks_rrv, blocks_rvr, blocks_rrv_vrr, &
     224              : !$OMP          blocks_r_rxvr, blocks_rxvr_r, blocks_r_doublecom, &
     225              : !$OMP          found, iac, ibc, alist_ac, alist_bc, &
     226              : !$OMP          na, np, nb, kkind, kac, kbc, i, &
     227              : !$OMP          go, asso_rv, asso_rxrv, asso_rrv, asso_rvr, asso_rrv_vrr, &
     228              : !$OMP          asso_r_rxvr, asso_rxvr_r, asso_r_doublecom, hash, &
     229           80 : !$OMP          acint, achint, bcint, bchint, trans)
     230              : 
     231              : !$OMP SINGLE
     232              : !$    ALLOCATE (locks(nlock))
     233              : !$OMP END SINGLE
     234              : 
     235              : !$OMP DO
     236              : !$    DO lock_num = 1, nlock
     237              : !$       call omp_init_lock(locks(lock_num))
     238              : !$    END DO
     239              : !$OMP END DO
     240              : 
     241              : !$OMP DO SCHEDULE(GUIDED)
     242              : 
     243              :       DO slot = 1, sab_all(1)%nl_size
     244              : 
     245              :          ikind = sab_all(1)%nlist_task(slot)%ikind
     246              :          jkind = sab_all(1)%nlist_task(slot)%jkind
     247              :          iatom = sab_all(1)%nlist_task(slot)%iatom
     248              :          jatom = sab_all(1)%nlist_task(slot)%jatom
     249              :          cell_b(:) = sab_all(1)%nlist_task(slot)%cell(:)
     250              :          rab(1:3) = sab_all(1)%nlist_task(slot)%r(1:3)
     251              : 
     252              :          IF (.NOT. ASSOCIATED(basis_set(ikind)%gto_basis_set)) CYCLE
     253              :          IF (.NOT. ASSOCIATED(basis_set(jkind)%gto_basis_set)) CYCLE
     254              :          iab = ikind + nkind*(jkind - 1)
     255              : 
     256              :          IF (do_symmetric) THEN
     257              :             IF (iatom <= jatom) THEN
     258              :                irow = iatom
     259              :                icol = jatom
     260              :             ELSE
     261              :                irow = jatom
     262              :                icol = iatom
     263              :             END IF
     264              :          ELSE
     265              :             irow = iatom
     266              :             icol = jatom
     267              :          END IF
     268              :          trans = do_symmetric .AND. (iatom > jatom)
     269              : 
     270              :          ! allocate blocks
     271              :          IF (my_rv) THEN
     272              :             ALLOCATE (blocks_rv(3))
     273              :          END IF
     274              :          IF (my_rxrv) THEN
     275              :             ALLOCATE (blocks_rxrv(3))
     276              :          END IF
     277              :          IF (my_rrv) THEN
     278              :             ALLOCATE (blocks_rrv(6))
     279              :          END IF
     280              :          IF (my_rvr) THEN
     281              :             ALLOCATE (blocks_rvr(6))
     282              :          END IF
     283              :          IF (my_rrv_vrr) THEN
     284              :             ALLOCATE (blocks_rrv_vrr(6))
     285              :          END IF
     286              :          IF (my_r_rxvr) THEN
     287              :             ALLOCATE (blocks_r_rxvr(3, 3))
     288              :          END IF
     289              : 
     290              :          IF (my_rxvr_r) THEN
     291              :             ALLOCATE (blocks_rxvr_r(3, 3))
     292              :          END IF
     293              : 
     294              :          IF (my_r_doublecom) THEN
     295              :             ALLOCATE (blocks_r_doublecom(3, 3))
     296              :          END IF
     297              : 
     298              :          ! get blocks
     299              :          IF (my_rv) THEN
     300              :             DO ind = 1, 3
     301              :                CALL dbcsr_get_block_p(matrix_rv(ind)%matrix, irow, icol, blocks_rv(ind)%block, found)
     302              :             END DO
     303              :          END IF
     304              : 
     305              :          IF (my_rxrv) THEN
     306              :             DO ind = 1, 3
     307              :                CALL dbcsr_get_block_p(matrix_rxrv(ind)%matrix, irow, icol, blocks_rxrv(ind)%block, found)
     308              :                blocks_rxrv(ind)%block(:, :) = 0._dp
     309              :             END DO
     310              :          END IF
     311              : 
     312              :          IF (my_rrv) THEN
     313              :             DO ind = 1, 6
     314              :                CALL dbcsr_get_block_p(matrix_rrv(ind)%matrix, irow, icol, blocks_rrv(ind)%block, found)
     315              :             END DO
     316              :          END IF
     317              : 
     318              :          IF (my_rvr) THEN
     319              :             DO ind = 1, 6
     320              :                CALL dbcsr_get_block_p(matrix_rvr(ind)%matrix, irow, icol, blocks_rvr(ind)%block, found)
     321              :             END DO
     322              :          END IF
     323              : 
     324              :          IF (my_rrv_vrr) THEN
     325              :             DO ind = 1, 6
     326              :                CALL dbcsr_get_block_p(matrix_rrv_vrr(ind)%matrix, irow, icol, blocks_rrv_vrr(ind)%block, found)
     327              :             END DO
     328              :          END IF
     329              : 
     330              :          IF (my_r_rxvr) THEN
     331              :             DO ind = 1, 3
     332              :                DO ind2 = 1, 3
     333              :                   CALL dbcsr_get_block_p(matrix_r_rxvr(ind, ind2)%matrix, irow, icol, &
     334              :                                          blocks_r_rxvr(ind, ind2)%block, found)
     335              :                   blocks_r_rxvr(ind, ind2)%block(:, :) = 0._dp
     336              :                END DO
     337              :             END DO
     338              :          END IF
     339              : 
     340              :          IF (my_rxvr_r) THEN
     341              :             DO ind = 1, 3
     342              :                DO ind2 = 1, 3
     343              :                   CALL dbcsr_get_block_p(matrix_rxvr_r(ind, ind2)%matrix, irow, icol, &
     344              :                                          blocks_rxvr_r(ind, ind2)%block, found)
     345              :                   blocks_rxvr_r(ind, ind2)%block(:, :) = 0._dp
     346              :                END DO
     347              :             END DO
     348              :          END IF
     349              : 
     350              :          IF (my_r_doublecom) THEN
     351              :             DO ind = 1, 3
     352              :                DO ind2 = 1, 3
     353              :                   CALL dbcsr_get_block_p(matrix_r_doublecom(ind, ind2)%matrix, irow, icol, &
     354              :                                          blocks_r_doublecom(ind, ind2)%block, found)
     355              :                   blocks_r_doublecom(ind, ind2)%block(:, :) = 0._dp
     356              :                END DO
     357              :             END DO
     358              :          END IF
     359              : 
     360              :          ! check whether all blocks are associated
     361              :          go = .TRUE.
     362              :          IF (my_rv) THEN
     363              :             asso_rv = (ASSOCIATED(blocks_rv(1)%block) .AND. ASSOCIATED(blocks_rv(2)%block) .AND. &
     364              :                        ASSOCIATED(blocks_rv(3)%block))
     365              :             go = go .AND. asso_rv
     366              :          END IF
     367              : 
     368              :          IF (my_rxrv) THEN
     369              :             asso_rxrv = (ASSOCIATED(blocks_rxrv(1)%block) .AND. ASSOCIATED(blocks_rxrv(2)%block) .AND. &
     370              :                          ASSOCIATED(blocks_rxrv(3)%block))
     371              :             go = go .AND. asso_rxrv
     372              :          END IF
     373              : 
     374              :          IF (my_rrv) THEN
     375              :             asso_rrv = (ASSOCIATED(blocks_rrv(1)%block) .AND. ASSOCIATED(blocks_rrv(2)%block) .AND. &
     376              :                         ASSOCIATED(blocks_rrv(3)%block) .AND. ASSOCIATED(blocks_rrv(4)%block) .AND. &
     377              :                         ASSOCIATED(blocks_rrv(5)%block) .AND. ASSOCIATED(blocks_rrv(6)%block))
     378              :             go = go .AND. asso_rrv
     379              :          END IF
     380              : 
     381              :          IF (my_rvr) THEN
     382              :             asso_rvr = (ASSOCIATED(blocks_rvr(1)%block) .AND. ASSOCIATED(blocks_rvr(2)%block) .AND. &
     383              :                         ASSOCIATED(blocks_rvr(3)%block) .AND. ASSOCIATED(blocks_rvr(4)%block) .AND. &
     384              :                         ASSOCIATED(blocks_rvr(5)%block) .AND. ASSOCIATED(blocks_rvr(6)%block))
     385              :             go = go .AND. asso_rvr
     386              :          END IF
     387              : 
     388              :          IF (my_rrv_vrr) THEN
     389              :             asso_rrv_vrr = (ASSOCIATED(blocks_rrv_vrr(1)%block) .AND. ASSOCIATED(blocks_rrv_vrr(2)%block) .AND. &
     390              :                             ASSOCIATED(blocks_rrv_vrr(3)%block) .AND. ASSOCIATED(blocks_rrv_vrr(4)%block) .AND. &
     391              :                             ASSOCIATED(blocks_rrv_vrr(5)%block) .AND. ASSOCIATED(blocks_rrv_vrr(6)%block))
     392              :             go = go .AND. asso_rrv_vrr
     393              :          END IF
     394              : 
     395              :          IF (my_r_rxvr) THEN
     396              :             asso_r_rxvr = .TRUE.
     397              :             DO ind = 1, 3
     398              :                DO ind2 = 1, 3
     399              :                   asso_r_rxvr = asso_r_rxvr .AND. ASSOCIATED(blocks_r_rxvr(ind, ind2)%block)
     400              :                END DO
     401              :             END DO
     402              :             go = go .AND. asso_r_rxvr
     403              :          END IF
     404              : 
     405              :          IF (my_rxvr_r) THEN
     406              :             asso_rxvr_r = .TRUE.
     407              :             DO ind = 1, 3
     408              :                DO ind2 = 1, 3
     409              :                   asso_rxvr_r = asso_rxvr_r .AND. ASSOCIATED(blocks_rxvr_r(ind, ind2)%block)
     410              :                END DO
     411              :             END DO
     412              :             go = go .AND. asso_rxvr_r
     413              :          END IF
     414              : 
     415              :          IF (my_r_doublecom) THEN
     416              :             asso_r_doublecom = .TRUE.
     417              :             DO ind = 1, 3
     418              :                DO ind2 = 1, 3
     419              :                   asso_r_doublecom = asso_r_doublecom .AND. ASSOCIATED(blocks_r_doublecom(ind, ind2)%block)
     420              :                END DO
     421              :             END DO
     422              :             go = go .AND. asso_r_doublecom
     423              :          END IF
     424              : 
     425              :          ! loop over all kinds for projector atom
     426              :          ! < iatom | katom > h < katom | jatom >
     427              :          IF (go) THEN
     428              :             DO kkind = 1, nkind
     429              :                iac = ikind + nkind*(kkind - 1)
     430              :                ibc = jkind + nkind*(kkind - 1)
     431              :                IF (.NOT. ASSOCIATED(sap_int(iac)%alist)) CYCLE
     432              :                IF (.NOT. ASSOCIATED(sap_int(ibc)%alist)) CYCLE
     433              :                CALL get_alist(sap_int(iac), alist_ac, iatom)
     434              :                CALL get_alist(sap_int(ibc), alist_bc, jatom)
     435              :                IF (.NOT. ASSOCIATED(alist_ac)) CYCLE
     436              :                IF (.NOT. ASSOCIATED(alist_bc)) CYCLE
     437              :                DO kac = 1, alist_ac%nclist
     438              :                   DO kbc = 1, alist_bc%nclist
     439              :                      IF (alist_ac%clist(kac)%catom /= alist_bc%clist(kbc)%catom) CYCLE
     440              :                      IF (PRESENT(pseudoatom)) THEN
     441              :                         IF (alist_ac%clist(kac)%catom /= pseudoatom) CYCLE
     442              :                      END IF
     443              : 
     444              :                      IF (ALL(cell_b + alist_bc%clist(kbc)%cell - alist_ac%clist(kac)%cell == 0)) THEN
     445              :                         IF (alist_ac%clist(kac)%maxac*alist_bc%clist(kbc)%maxach < eps_ppnl) CYCLE
     446              :                         acint => alist_ac%clist(kac)%acint
     447              :                         bcint => alist_bc%clist(kbc)%acint
     448              :                         achint => alist_ac%clist(kac)%achint
     449              :                         bchint => alist_bc%clist(kbc)%achint
     450              :                         na = SIZE(acint, 1)
     451              :                         np = SIZE(acint, 2)
     452              :                         nb = SIZE(bcint, 1)
     453              : !$                      hash = MOD((iatom - 1)*natom + jatom, nlock) + 1
     454              : !$                      CALL omp_set_lock(locks(hash))
     455              :                         IF (my_rv) THEN
     456              :                            ! r*Vnl
     457              :                            ! with LAPACK
     458              :                            ! CALL dgemm("N", "T", na, nb, np, 1._dp, achint(1, 1, 2), na, &
     459              :                            !            bcint(1, 1, 1), nb, 1.0_dp, blocks_rv(1)%block, SIZE(blocks_rv(1)%block, 1)) ! xV
     460              :                            ! CALL dgemm("N", "T", na, nb, np, 1._dp, achint(1, 1, 3), na, &
     461              :                            !            bcint(1, 1, 1), nb, 1.0_dp, blocks_rv(2)%block, SIZE(blocks_rv(2)%block, 1)) ! yV
     462              :                            ! CALL dgemm("N", "T", na, nb, np, 1._dp, achint(1, 1, 4), na, &
     463              :                            !            bcint(1, 1, 1), nb, 1.0_dp, blocks_rv(3)%block, SIZE(blocks_rv(3)%block, 1)) ! zV
     464              :                            IF (.NOT. trans) THEN
     465              :                               ! with MATMUL
     466              :                               blocks_rv(1)%block(1:na, 1:nb) = blocks_rv(1)%block(1:na, 1:nb) + &
     467              :                                                                MATMUL(achint(1:na, 1:np, 2), TRANSPOSE(bcint(1:nb, 1:np, 1))) ! xV
     468              :                               blocks_rv(2)%block(1:na, 1:nb) = blocks_rv(2)%block(1:na, 1:nb) + &
     469              :                                                                MATMUL(achint(1:na, 1:np, 3), TRANSPOSE(bcint(1:nb, 1:np, 1))) ! yV
     470              :                               blocks_rv(3)%block(1:na, 1:nb) = blocks_rv(3)%block(1:na, 1:nb) + &
     471              :                                                                MATMUL(achint(1:na, 1:np, 4), TRANSPOSE(bcint(1:nb, 1:np, 1))) ! zV
     472              :                            ELSE
     473              :                               blocks_rv(1)%block(1:nb, 1:na) = blocks_rv(1)%block(1:nb, 1:na) + &
     474              :                                                                MATMUL(bchint(1:nb, 1:np, 2), TRANSPOSE(acint(1:na, 1:np, 1)))
     475              :                               blocks_rv(2)%block(1:nb, 1:na) = blocks_rv(2)%block(1:nb, 1:na) + &
     476              :                                                                MATMUL(bchint(1:nb, 1:np, 3), TRANSPOSE(acint(1:na, 1:np, 1)))
     477              :                               blocks_rv(3)%block(1:nb, 1:na) = blocks_rv(3)%block(1:nb, 1:na) + &
     478              :                                                                MATMUL(bchint(1:nb, 1:np, 4), TRANSPOSE(acint(1:na, 1:np, 1)))
     479              :                            END IF
     480              :                            ! -Vnl r
     481              :                            ! with LAPACK
     482              :                            ! CALL dgemm("N", "T", na, nb, np, -1._dp, achint(1, 1, 1), na, &
     483              :                            !            bcint(1, 1, 2), nb, 1.0_dp, blocks_rv(1)%block, SIZE(blocks_rv(1)%block, 1)) ! -Vx
     484              :                            ! CALL dgemm("N", "T", na, nb, np, -1._dp, achint(1, 1, 1), na, &
     485              :                            !            bcint(1, 1, 3), nb, 1.0_dp, blocks_rv(2)%block, SIZE(blocks_rv(2)%block, 1)) ! -Vy
     486              :                            ! CALL dgemm("N", "T", na, nb, np, -1._dp, achint(1, 1, 1), na, &
     487              :                            !            bcint(1, 1, 4), nb, 1.0_dp, blocks_rv(3)%block, SIZE(blocks_rv(3)%block, 1)) ! -Vz
     488              :                            ! with MATMUL
     489              :                            IF (.NOT. trans) THEN
     490              :                               blocks_rv(1)%block(1:na, 1:nb) = blocks_rv(1)%block(1:na, 1:nb) - &
     491              :                                                                MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 2))) ! -Vx
     492              :                               blocks_rv(2)%block(1:na, 1:nb) = blocks_rv(2)%block(1:na, 1:nb) - &
     493              :                                                                MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 3))) ! -Vy
     494              :                               blocks_rv(3)%block(1:na, 1:nb) = blocks_rv(3)%block(1:na, 1:nb) - &
     495              :                                                                MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 4))) ! -Vz
     496              :                            ELSE
     497              :                               blocks_rv(1)%block(1:nb, 1:na) = blocks_rv(1)%block(1:nb, 1:na) - &
     498              :                                                                MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 2)))
     499              :                               blocks_rv(2)%block(1:nb, 1:na) = blocks_rv(2)%block(1:nb, 1:na) - &
     500              :                                                                MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 3)))
     501              :                               blocks_rv(3)%block(1:nb, 1:na) = blocks_rv(3)%block(1:nb, 1:na) - &
     502              :                                                                MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 4)))
     503              :                            END IF
     504              : 
     505              :                         END IF
     506              : 
     507              :                         IF (my_rxrv) THEN
     508              :                            ! The same-side quadratic terms cancel in each cross-product component.
     509              :                            ! x-component (y [z,Vnl] - z [y, Vnl])
     510              :                            IF (iatom <= jatom) THEN
     511              :                               ! -yVz
     512              :                               blocks_rxrv(1)%block(1:na, 1:nb) = blocks_rxrv(1)%block(1:na, 1:nb) - &
     513              :                                                                  MATMUL(achint(1:na, 1:np, 3), TRANSPOSE(bcint(1:nb, 1:np, 4)))
     514              :                               ! zVy
     515              :                               blocks_rxrv(1)%block(1:na, 1:nb) = blocks_rxrv(1)%block(1:na, 1:nb) + &
     516              :                                                                  MATMUL(achint(1:na, 1:np, 4), TRANSPOSE(bcint(1:nb, 1:np, 3)))
     517              :                            ELSE
     518              :                               ! -yVz
     519              :                               blocks_rxrv(1)%block(1:nb, 1:na) = blocks_rxrv(1)%block(1:nb, 1:na) - &
     520              :                                                                  MATMUL(bchint(1:nb, 1:np, 3), TRANSPOSE(acint(1:na, 1:np, 4)))
     521              :                               ! zVy
     522              :                               blocks_rxrv(1)%block(1:nb, 1:na) = blocks_rxrv(1)%block(1:nb, 1:na) + &
     523              :                                                                  MATMUL(bchint(1:nb, 1:np, 4), TRANSPOSE(acint(1:na, 1:np, 3)))
     524              :                            END IF
     525              : 
     526              :                            ! y-component (z [x,Vnl] - x [z, Vnl])
     527              :                            IF (iatom <= jatom) THEN
     528              :                               ! -zVx
     529              :                               blocks_rxrv(2)%block(1:na, 1:nb) = blocks_rxrv(2)%block(1:na, 1:nb) - &
     530              :                                                                  MATMUL(achint(1:na, 1:np, 4), TRANSPOSE(bcint(1:nb, 1:np, 2)))
     531              :                               ! xVz
     532              :                               blocks_rxrv(2)%block(1:na, 1:nb) = blocks_rxrv(2)%block(1:na, 1:nb) + &
     533              :                                                                  MATMUL(achint(1:na, 1:np, 2), TRANSPOSE(bcint(1:nb, 1:np, 4)))
     534              :                            ELSE
     535              :                               ! -zVx
     536              :                               blocks_rxrv(2)%block(1:nb, 1:na) = blocks_rxrv(2)%block(1:nb, 1:na) - &
     537              :                                                                  MATMUL(bchint(1:nb, 1:np, 4), TRANSPOSE(acint(1:na, 1:np, 2)))
     538              :                               ! xVz
     539              :                               blocks_rxrv(2)%block(1:nb, 1:na) = blocks_rxrv(2)%block(1:nb, 1:na) + &
     540              :                                                                  MATMUL(bchint(1:nb, 1:np, 2), TRANSPOSE(acint(1:na, 1:np, 4)))
     541              :                            END IF
     542              : 
     543              :                            ! z-component (x [y,Vnl] - y [x, Vnl])
     544              :                            IF (iatom <= jatom) THEN
     545              :                               ! -xVy
     546              :                               blocks_rxrv(3)%block(1:na, 1:nb) = blocks_rxrv(3)%block(1:na, 1:nb) - &
     547              :                                                                  MATMUL(achint(1:na, 1:np, 2), TRANSPOSE(bcint(1:nb, 1:np, 3)))
     548              :                               ! yVx
     549              :                               blocks_rxrv(3)%block(1:na, 1:nb) = blocks_rxrv(3)%block(1:na, 1:nb) + &
     550              :                                                                  MATMUL(achint(1:na, 1:np, 3), TRANSPOSE(bcint(1:nb, 1:np, 2)))
     551              :                            ELSE
     552              :                               ! -xVy
     553              :                               blocks_rxrv(3)%block(1:nb, 1:na) = blocks_rxrv(3)%block(1:nb, 1:na) - &
     554              :                                                                  MATMUL(bchint(1:nb, 1:np, 2), TRANSPOSE(acint(1:na, 1:np, 3)))
     555              :                               ! yVx
     556              :                               blocks_rxrv(3)%block(1:nb, 1:na) = blocks_rxrv(3)%block(1:nb, 1:na) + &
     557              :                                                                  MATMUL(bchint(1:nb, 1:np, 3), TRANSPOSE(acint(1:na, 1:np, 2)))
     558              :                            END IF
     559              :                         END IF
     560              : 
     561              :                         IF (my_rrv) THEN
     562              :                            ! r_alpha * r_beta * Vnl
     563              :                            IF (iatom <= jatom) THEN
     564              :                               ! xxV
     565              :                               blocks_rrv(1)%block(1:na, 1:nb) = blocks_rrv(1)%block(1:na, 1:nb) + &
     566              :                                                                 MATMUL(achint(1:na, 1:np, 5), TRANSPOSE(bcint(1:nb, 1:np, 1)))
     567              :                               ! xyV
     568              :                               blocks_rrv(2)%block(1:na, 1:nb) = blocks_rrv(2)%block(1:na, 1:nb) + &
     569              :                                                                 MATMUL(achint(1:na, 1:np, 6), TRANSPOSE(bcint(1:nb, 1:np, 1)))
     570              :                               ! xzV
     571              :                               blocks_rrv(3)%block(1:na, 1:nb) = blocks_rrv(3)%block(1:na, 1:nb) + &
     572              :                                                                 MATMUL(achint(1:na, 1:np, 7), TRANSPOSE(bcint(1:nb, 1:np, 1)))
     573              :                               ! yyV
     574              :                               blocks_rrv(4)%block(1:na, 1:nb) = blocks_rrv(4)%block(1:na, 1:nb) + &
     575              :                                                                 MATMUL(achint(1:na, 1:np, 8), TRANSPOSE(bcint(1:nb, 1:np, 1)))
     576              :                               ! yzV
     577              :                               blocks_rrv(5)%block(1:na, 1:nb) = blocks_rrv(5)%block(1:na, 1:nb) + &
     578              :                                                                 MATMUL(achint(1:na, 1:np, 9), TRANSPOSE(bcint(1:nb, 1:np, 1)))
     579              :                               ! zzV
     580              :                               blocks_rrv(6)%block(1:na, 1:nb) = blocks_rrv(6)%block(1:na, 1:nb) + &
     581              :                                                                 MATMUL(achint(1:na, 1:np, 10), TRANSPOSE(bcint(1:nb, 1:np, 1)))
     582              :                            ELSE
     583              :                               ! xxV
     584              :                               blocks_rrv(1)%block(1:nb, 1:na) = blocks_rrv(1)%block(1:nb, 1:na) + &
     585              :                                                                 MATMUL(bchint(1:nb, 1:np, 5), TRANSPOSE(acint(1:na, 1:np, 1)))
     586              :                               ! xyV
     587              :                               blocks_rrv(2)%block(1:nb, 1:na) = blocks_rrv(2)%block(1:nb, 1:na) + &
     588              :                                                                 MATMUL(bchint(1:nb, 1:np, 6), TRANSPOSE(acint(1:na, 1:np, 1)))
     589              :                               ! xzV
     590              :                               blocks_rrv(3)%block(1:nb, 1:na) = blocks_rrv(3)%block(1:nb, 1:na) + &
     591              :                                                                 MATMUL(bchint(1:nb, 1:np, 7), TRANSPOSE(acint(1:na, 1:np, 1)))
     592              :                               ! yyV
     593              :                               blocks_rrv(4)%block(1:nb, 1:na) = blocks_rrv(4)%block(1:nb, 1:na) + &
     594              :                                                                 MATMUL(bchint(1:nb, 1:np, 8), TRANSPOSE(acint(1:na, 1:np, 1)))
     595              :                               ! yzV
     596              :                               blocks_rrv(5)%block(1:nb, 1:na) = blocks_rrv(5)%block(1:nb, 1:na) + &
     597              :                                                                 MATMUL(bchint(1:nb, 1:np, 9), TRANSPOSE(acint(1:na, 1:np, 1)))
     598              :                               ! zzV
     599              :                               blocks_rrv(6)%block(1:nb, 1:na) = blocks_rrv(6)%block(1:nb, 1:na) + &
     600              :                                                                 MATMUL(bchint(1:nb, 1:np, 10), TRANSPOSE(acint(1:na, 1:np, 1)))
     601              :                            END IF
     602              : 
     603              :                            ! - Vnl * r_alpha * r_beta
     604              :                            IF (iatom <= jatom) THEN
     605              :                               ! -Vxx
     606              :                               blocks_rrv(1)%block(1:na, 1:nb) = blocks_rrv(1)%block(1:na, 1:nb) - &
     607              :                                                                 MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 5)))
     608              :                               ! -Vxy
     609              :                               blocks_rrv(2)%block(1:na, 1:nb) = blocks_rrv(2)%block(1:na, 1:nb) - &
     610              :                                                                 MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 6)))
     611              :                               ! -Vxz
     612              :                               blocks_rrv(3)%block(1:na, 1:nb) = blocks_rrv(3)%block(1:na, 1:nb) - &
     613              :                                                                 MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 7)))
     614              :                               ! -Vyy
     615              :                               blocks_rrv(4)%block(1:na, 1:nb) = blocks_rrv(4)%block(1:na, 1:nb) - &
     616              :                                                                 MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 8)))
     617              :                               ! -Vyz
     618              :                               blocks_rrv(5)%block(1:na, 1:nb) = blocks_rrv(5)%block(1:na, 1:nb) - &
     619              :                                                                 MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 9)))
     620              :                               ! -Vzz
     621              :                               blocks_rrv(6)%block(1:na, 1:nb) = blocks_rrv(6)%block(1:na, 1:nb) - &
     622              :                                                                 MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 10)))
     623              :                            ELSE
     624              :                               ! -Vxx
     625              :                               blocks_rrv(1)%block(1:nb, 1:na) = blocks_rrv(1)%block(1:nb, 1:na) - &
     626              :                                                                 MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 5)))
     627              :                               ! -Vxy
     628              :                               blocks_rrv(2)%block(1:nb, 1:na) = blocks_rrv(2)%block(1:nb, 1:na) - &
     629              :                                                                 MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 6)))
     630              :                               ! -Vxz
     631              :                               blocks_rrv(3)%block(1:nb, 1:na) = blocks_rrv(3)%block(1:nb, 1:na) - &
     632              :                                                                 MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 7)))
     633              :                               ! -Vyy
     634              :                               blocks_rrv(4)%block(1:nb, 1:na) = blocks_rrv(4)%block(1:nb, 1:na) - &
     635              :                                                                 MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 8)))
     636              :                               ! -Vyz
     637              :                               blocks_rrv(5)%block(1:nb, 1:na) = blocks_rrv(5)%block(1:nb, 1:na) - &
     638              :                                                                 MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 9)))
     639              :                               ! -Vzz
     640              :                               blocks_rrv(6)%block(1:nb, 1:na) = blocks_rrv(6)%block(1:nb, 1:na) - &
     641              :                                                                 MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 10)))
     642              :                            END IF
     643              :                         END IF
     644              : 
     645              :                         IF (my_rvr) THEN
     646              :                            ! r_alpha * Vnl * r_beta
     647              :                            IF (iatom <= jatom) THEN
     648              :                               ! xVx
     649              :                               blocks_rvr(1)%block(1:na, 1:nb) = blocks_rvr(1)%block(1:na, 1:nb) + &
     650              :                                                                 MATMUL(achint(1:na, 1:np, 2), TRANSPOSE(bcint(1:nb, 1:np, 2)))
     651              :                               ! xVy
     652              :                               blocks_rvr(2)%block(1:na, 1:nb) = blocks_rvr(2)%block(1:na, 1:nb) + &
     653              :                                                                 MATMUL(achint(1:na, 1:np, 2), TRANSPOSE(bcint(1:nb, 1:np, 3)))
     654              :                               ! xVz
     655              :                               blocks_rvr(3)%block(1:na, 1:nb) = blocks_rvr(3)%block(1:na, 1:nb) + &
     656              :                                                                 MATMUL(achint(1:na, 1:np, 2), TRANSPOSE(bcint(1:nb, 1:np, 4)))
     657              :                               ! yVy
     658              :                               blocks_rvr(4)%block(1:na, 1:nb) = blocks_rvr(4)%block(1:na, 1:nb) + &
     659              :                                                                 MATMUL(achint(1:na, 1:np, 3), TRANSPOSE(bcint(1:nb, 1:np, 3)))
     660              :                               ! yVz
     661              :                               blocks_rvr(5)%block(1:na, 1:nb) = blocks_rvr(5)%block(1:na, 1:nb) + &
     662              :                                                                 MATMUL(achint(1:na, 1:np, 3), TRANSPOSE(bcint(1:nb, 1:np, 4)))
     663              :                               ! zVz
     664              :                               blocks_rvr(6)%block(1:na, 1:nb) = blocks_rvr(6)%block(1:na, 1:nb) + &
     665              :                                                                 MATMUL(achint(1:na, 1:np, 4), TRANSPOSE(bcint(1:nb, 1:np, 4)))
     666              :                            ELSE
     667              :                               ! xVx
     668              :                               blocks_rvr(1)%block(1:nb, 1:na) = blocks_rvr(1)%block(1:nb, 1:na) + &
     669              :                                                                 MATMUL(bchint(1:nb, 1:np, 2), TRANSPOSE(acint(1:na, 1:np, 2)))
     670              :                               ! xVy
     671              :                               blocks_rvr(2)%block(1:nb, 1:na) = blocks_rvr(2)%block(1:nb, 1:na) + &
     672              :                                                                 MATMUL(bchint(1:nb, 1:np, 2), TRANSPOSE(acint(1:na, 1:np, 3)))
     673              :                               ! xVz
     674              :                               blocks_rvr(3)%block(1:nb, 1:na) = blocks_rvr(3)%block(1:nb, 1:na) + &
     675              :                                                                 MATMUL(bchint(1:nb, 1:np, 2), TRANSPOSE(acint(1:na, 1:np, 4)))
     676              :                               ! yVy
     677              :                               blocks_rvr(4)%block(1:nb, 1:na) = blocks_rvr(4)%block(1:nb, 1:na) + &
     678              :                                                                 MATMUL(bchint(1:nb, 1:np, 3), TRANSPOSE(acint(1:na, 1:np, 3)))
     679              :                               ! yVz
     680              :                               blocks_rvr(5)%block(1:nb, 1:na) = blocks_rvr(5)%block(1:nb, 1:na) + &
     681              :                                                                 MATMUL(bchint(1:nb, 1:np, 3), TRANSPOSE(acint(1:na, 1:np, 4)))
     682              :                               ! zVz
     683              :                               blocks_rvr(6)%block(1:nb, 1:na) = blocks_rvr(6)%block(1:nb, 1:na) + &
     684              :                                                                 MATMUL(bchint(1:nb, 1:np, 4), TRANSPOSE(acint(1:na, 1:np, 4)))
     685              :                            END IF
     686              :                         END IF
     687              : 
     688              :                         IF (my_rrv_vrr) THEN
     689              :                            ! r_alpha * r_beta * Vnl
     690              :                            IF (iatom <= jatom) THEN
     691              :                               ! xxV
     692              :                               blocks_rrv_vrr(1)%block(1:na, 1:nb) = blocks_rrv_vrr(1)%block(1:na, 1:nb) + &
     693              :                                                                     MATMUL(achint(1:na, 1:np, 5), TRANSPOSE(bcint(1:nb, 1:np, 1)))
     694              :                               ! xyV
     695              :                               blocks_rrv_vrr(2)%block(1:na, 1:nb) = blocks_rrv_vrr(2)%block(1:na, 1:nb) + &
     696              :                                                                     MATMUL(achint(1:na, 1:np, 6), TRANSPOSE(bcint(1:nb, 1:np, 1)))
     697              :                               ! xzV
     698              :                               blocks_rrv_vrr(3)%block(1:na, 1:nb) = blocks_rrv_vrr(3)%block(1:na, 1:nb) + &
     699              :                                                                     MATMUL(achint(1:na, 1:np, 7), TRANSPOSE(bcint(1:nb, 1:np, 1)))
     700              :                               ! yyV
     701              :                               blocks_rrv_vrr(4)%block(1:na, 1:nb) = blocks_rrv_vrr(4)%block(1:na, 1:nb) + &
     702              :                                                                     MATMUL(achint(1:na, 1:np, 8), TRANSPOSE(bcint(1:nb, 1:np, 1)))
     703              :                               ! yzV
     704              :                               blocks_rrv_vrr(5)%block(1:na, 1:nb) = blocks_rrv_vrr(5)%block(1:na, 1:nb) + &
     705              :                                                                     MATMUL(achint(1:na, 1:np, 9), TRANSPOSE(bcint(1:nb, 1:np, 1)))
     706              :                               ! zzV
     707              :                               blocks_rrv_vrr(6)%block(1:na, 1:nb) = blocks_rrv_vrr(6)%block(1:na, 1:nb) + &
     708              :                                                                     MATMUL(achint(1:na, 1:np, 10), TRANSPOSE(bcint(1:nb, 1:np, 1)))
     709              :                            ELSE
     710              :                               ! xxV
     711              :                               blocks_rrv_vrr(1)%block(1:nb, 1:na) = blocks_rrv_vrr(1)%block(1:nb, 1:na) + &
     712              :                                                                     MATMUL(bchint(1:nb, 1:np, 5), TRANSPOSE(acint(1:na, 1:np, 1)))
     713              :                               ! xyV
     714              :                               blocks_rrv_vrr(2)%block(1:nb, 1:na) = blocks_rrv_vrr(2)%block(1:nb, 1:na) + &
     715              :                                                                     MATMUL(bchint(1:nb, 1:np, 6), TRANSPOSE(acint(1:na, 1:np, 1)))
     716              :                               ! xzV
     717              :                               blocks_rrv_vrr(3)%block(1:nb, 1:na) = blocks_rrv_vrr(3)%block(1:nb, 1:na) + &
     718              :                                                                     MATMUL(bchint(1:nb, 1:np, 7), TRANSPOSE(acint(1:na, 1:np, 1)))
     719              :                               ! yyV
     720              :                               blocks_rrv_vrr(4)%block(1:nb, 1:na) = blocks_rrv_vrr(4)%block(1:nb, 1:na) + &
     721              :                                                                     MATMUL(bchint(1:nb, 1:np, 8), TRANSPOSE(acint(1:na, 1:np, 1)))
     722              :                               ! yzV
     723              :                               blocks_rrv_vrr(5)%block(1:nb, 1:na) = blocks_rrv_vrr(5)%block(1:nb, 1:na) + &
     724              :                                                                     MATMUL(bchint(1:nb, 1:np, 9), TRANSPOSE(acint(1:na, 1:np, 1)))
     725              :                               ! zzV
     726              :                               blocks_rrv_vrr(6)%block(1:nb, 1:na) = blocks_rrv_vrr(6)%block(1:nb, 1:na) + &
     727              :                                                                     MATMUL(bchint(1:nb, 1:np, 10), TRANSPOSE(acint(1:na, 1:np, 1)))
     728              :                            END IF
     729              :                            ! + Vnl * r_alpha * r_beta
     730              :                            IF (iatom <= jatom) THEN
     731              :                               ! +Vxx
     732              :                               blocks_rrv_vrr(1)%block(1:na, 1:nb) = blocks_rrv_vrr(1)%block(1:na, 1:nb) + &
     733              :                                                                     MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 5)))
     734              :                               ! +Vxy
     735              :                               blocks_rrv_vrr(2)%block(1:na, 1:nb) = blocks_rrv_vrr(2)%block(1:na, 1:nb) + &
     736              :                                                                     MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 6)))
     737              :                               ! +Vxz
     738              :                               blocks_rrv_vrr(3)%block(1:na, 1:nb) = blocks_rrv_vrr(3)%block(1:na, 1:nb) + &
     739              :                                                                     MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 7)))
     740              :                               ! +Vyy
     741              :                               blocks_rrv_vrr(4)%block(1:na, 1:nb) = blocks_rrv_vrr(4)%block(1:na, 1:nb) + &
     742              :                                                                     MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 8)))
     743              :                               ! +Vyz
     744              :                               blocks_rrv_vrr(5)%block(1:na, 1:nb) = blocks_rrv_vrr(5)%block(1:na, 1:nb) + &
     745              :                                                                     MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 9)))
     746              :                               ! +Vzz
     747              :                               blocks_rrv_vrr(6)%block(1:na, 1:nb) = blocks_rrv_vrr(6)%block(1:na, 1:nb) + &
     748              :                                                                     MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 10)))
     749              :                            ELSE
     750              :                               ! +Vxx
     751              :                               blocks_rrv_vrr(1)%block(1:nb, 1:na) = blocks_rrv_vrr(1)%block(1:nb, 1:na) + &
     752              :                                                                     MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 5)))
     753              :                               ! +Vxy
     754              :                               blocks_rrv_vrr(2)%block(1:nb, 1:na) = blocks_rrv_vrr(2)%block(1:nb, 1:na) + &
     755              :                                                                     MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 6)))
     756              :                               ! +Vxz
     757              :                               blocks_rrv_vrr(3)%block(1:nb, 1:na) = blocks_rrv_vrr(3)%block(1:nb, 1:na) + &
     758              :                                                                     MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 7)))
     759              :                               ! +Vyy
     760              :                               blocks_rrv_vrr(4)%block(1:nb, 1:na) = blocks_rrv_vrr(4)%block(1:nb, 1:na) + &
     761              :                                                                     MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 8)))
     762              :                               ! +Vyz
     763              :                               blocks_rrv_vrr(5)%block(1:nb, 1:na) = blocks_rrv_vrr(5)%block(1:nb, 1:na) + &
     764              :                                                                     MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 9)))
     765              :                               ! +Vzz
     766              :                               blocks_rrv_vrr(6)%block(1:nb, 1:na) = blocks_rrv_vrr(6)%block(1:nb, 1:na) + &
     767              :                                                                     MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 10)))
     768              :                            END IF
     769              :                         END IF
     770              : 
     771              :                         ! The indices are stored in i_1, i_x, ..., i_zzz
     772              : 
     773              :                         ! TODO: is this set to zero before?
     774              :                         IF (my_r_rxvr) THEN
     775              :                            ! beta = 1
     776              :                            ! matrix_r_rxvr(x, x) = x * y * V_nl * z  -  x * z * V_nl * y
     777              :                            blocks_r_rxvr(1, 1)%block(1:na, 1:nb) = &
     778              :                               blocks_r_rxvr(1, 1)%block(1:na, 1:nb) + &
     779              :                               MATMUL(achint(1:na, 1:np, i_xy), TRANSPOSE(bcint(1:nb, 1:np, i_z)))
     780              :                            blocks_r_rxvr(1, 1)%block(1:na, 1:nb) = &
     781              :                               blocks_r_rxvr(1, 1)%block(1:na, 1:nb) - &
     782              :                               MATMUL(achint(1:na, 1:np, i_xz), TRANSPOSE(bcint(1:nb, 1:np, i_y)))
     783              : 
     784              :                            ! matrix_r_rxvr(y, x) = x * z * V_nl * x  -  x * x * V_nl * z
     785              :                            blocks_r_rxvr(2, 1)%block(1:na, 1:nb) = &
     786              :                               blocks_r_rxvr(2, 1)%block(1:na, 1:nb) + &
     787              :                               MATMUL(achint(1:na, 1:np, i_xz), TRANSPOSE(bcint(1:nb, 1:np, i_x)))
     788              :                            blocks_r_rxvr(2, 1)%block(1:na, 1:nb) = &
     789              :                               blocks_r_rxvr(2, 1)%block(1:na, 1:nb) - &
     790              :                               MATMUL(achint(1:na, 1:np, i_xx), TRANSPOSE(bcint(1:nb, 1:np, i_z)))
     791              : 
     792              :                            ! matrix_r_rxvr(z, x) = x * x * V_nl * y  -  x * y * V_nl * x
     793              :                            blocks_r_rxvr(3, 1)%block(1:na, 1:nb) = &
     794              :                               blocks_r_rxvr(3, 1)%block(1:na, 1:nb) + &
     795              :                               MATMUL(achint(1:na, 1:np, i_xx), TRANSPOSE(bcint(1:nb, 1:np, i_y)))
     796              :                            blocks_r_rxvr(3, 1)%block(1:na, 1:nb) = &
     797              :                               blocks_r_rxvr(3, 1)%block(1:na, 1:nb) - &
     798              :                               MATMUL(achint(1:na, 1:np, i_xy), TRANSPOSE(bcint(1:nb, 1:np, i_x)))
     799              : 
     800              :                            ! beta = 2
     801              :                            ! matrix_r_rxvr(x, y) = y * y * V_nl * z  -  y * z * V_nl * y
     802              :                            blocks_r_rxvr(1, 2)%block(1:na, 1:nb) = &
     803              :                               blocks_r_rxvr(1, 2)%block(1:na, 1:nb) + &
     804              :                               MATMUL(achint(1:na, 1:np, i_yy), TRANSPOSE(bcint(1:nb, 1:np, i_z)))
     805              :                            blocks_r_rxvr(1, 2)%block(1:na, 1:nb) = &
     806              :                               blocks_r_rxvr(1, 2)%block(1:na, 1:nb) - &
     807              :                               MATMUL(achint(1:na, 1:np, i_yz), TRANSPOSE(bcint(1:nb, 1:np, i_y)))
     808              : 
     809              :                            ! matrix_r_rxvr(y, y) = y * z * V_nl * x  -  y * x * V_nl * z
     810              :                            blocks_r_rxvr(2, 2)%block(1:na, 1:nb) = &
     811              :                               blocks_r_rxvr(2, 2)%block(1:na, 1:nb) + &
     812              :                               MATMUL(achint(1:na, 1:np, i_yz), TRANSPOSE(bcint(1:nb, 1:np, i_x)))
     813              :                            blocks_r_rxvr(2, 2)%block(1:na, 1:nb) = &
     814              :                               blocks_r_rxvr(2, 2)%block(1:na, 1:nb) - &
     815              :                               MATMUL(achint(1:na, 1:np, i_yx), TRANSPOSE(bcint(1:nb, 1:np, i_z)))
     816              : 
     817              :                            ! matrix_r_rxvr(z, y) = y * x * V_nl * y  -  y * y * V_nl * x
     818              :                            blocks_r_rxvr(3, 2)%block(1:na, 1:nb) = &
     819              :                               blocks_r_rxvr(3, 2)%block(1:na, 1:nb) + &
     820              :                               MATMUL(achint(1:na, 1:np, i_yx), TRANSPOSE(bcint(1:nb, 1:np, i_y)))
     821              :                            blocks_r_rxvr(3, 2)%block(1:na, 1:nb) = &
     822              :                               blocks_r_rxvr(3, 2)%block(1:na, 1:nb) - &
     823              :                               MATMUL(achint(1:na, 1:np, i_yy), TRANSPOSE(bcint(1:nb, 1:np, i_x)))
     824              : 
     825              :                            ! beta = 3
     826              :                            ! matrix_r_rxvr(x, z) = z * y * V_nl * z  -  z * z * V_nl * y
     827              :                            blocks_r_rxvr(1, 3)%block(1:na, 1:nb) = &
     828              :                               blocks_r_rxvr(1, 3)%block(1:na, 1:nb) + &
     829              :                               MATMUL(achint(1:na, 1:np, i_zy), TRANSPOSE(bcint(1:nb, 1:np, i_z)))
     830              :                            blocks_r_rxvr(1, 3)%block(1:na, 1:nb) = &
     831              :                               blocks_r_rxvr(1, 3)%block(1:na, 1:nb) - &
     832              :                               MATMUL(achint(1:na, 1:np, i_zz), TRANSPOSE(bcint(1:nb, 1:np, i_y)))
     833              : 
     834              :                            ! matrix_r_rxvr(y, z) = z * z * V_nl * x  -  z * x * V_nl * z
     835              :                            blocks_r_rxvr(2, 3)%block(1:na, 1:nb) = &
     836              :                               blocks_r_rxvr(2, 3)%block(1:na, 1:nb) + &
     837              :                               MATMUL(achint(1:na, 1:np, i_zz), TRANSPOSE(bcint(1:nb, 1:np, i_x)))
     838              :                            blocks_r_rxvr(2, 3)%block(1:na, 1:nb) = &
     839              :                               blocks_r_rxvr(2, 3)%block(1:na, 1:nb) - &
     840              :                               MATMUL(achint(1:na, 1:np, i_zx), TRANSPOSE(bcint(1:nb, 1:np, i_z)))
     841              : 
     842              :                            ! matrix_r_rxvr(z, z) = z * x * V_nl * y  -  z * y * V_nl * x
     843              :                            blocks_r_rxvr(3, 3)%block(1:na, 1:nb) = &
     844              :                               blocks_r_rxvr(3, 3)%block(1:na, 1:nb) + &
     845              :                               MATMUL(achint(1:na, 1:np, i_zx), TRANSPOSE(bcint(1:nb, 1:np, i_y)))
     846              :                            blocks_r_rxvr(3, 3)%block(1:na, 1:nb) = &
     847              :                               blocks_r_rxvr(3, 3)%block(1:na, 1:nb) - &
     848              :                               MATMUL(achint(1:na, 1:np, i_zy), TRANSPOSE(bcint(1:nb, 1:np, i_x)))
     849              : 
     850              :                         END IF ! my_r_rxvr
     851              : 
     852              :                         ! The indices are stored in i_1, i_x, ..., i_zzz
     853              :                         ! This will put into blocks_rxvr_r
     854              :                         ! matrix_rxvr_r(alpha, beta) = sum_(gamma delta) epsilon_(alpha gamma delta)
     855              :                         !                              r_gamma * V_nl * r_delta * r_beta
     856              :                         IF (my_rxvr_r) THEN
     857              :                            ! beta = 1
     858              :                            ! matrix_rxvr_r(x, x) = yV zx - zV yx
     859              :                            blocks_rxvr_r(1, 1)%block(1:na, 1:nb) = &
     860              :                               blocks_rxvr_r(1, 1)%block(1:na, 1:nb) + &
     861              :                               MATMUL(achint(1:na, 1:np, i_y), TRANSPOSE(bcint(1:nb, 1:np, i_zx)))
     862              :                            blocks_rxvr_r(1, 1)%block(1:na, 1:nb) = &
     863              :                               blocks_rxvr_r(1, 1)%block(1:na, 1:nb) - &
     864              :                               MATMUL(achint(1:na, 1:np, i_z), TRANSPOSE(bcint(1:nb, 1:np, i_yx)))
     865              : 
     866              :                            ! matrix_rxvr_r(y, x) = zV xx - xV zx
     867              :                            blocks_rxvr_r(2, 1)%block(1:na, 1:nb) = &
     868              :                               blocks_rxvr_r(2, 1)%block(1:na, 1:nb) + &
     869              :                               MATMUL(achint(1:na, 1:np, i_z), TRANSPOSE(bcint(1:nb, 1:np, i_xx)))
     870              :                            blocks_rxvr_r(2, 1)%block(1:na, 1:nb) = &
     871              :                               blocks_rxvr_r(2, 1)%block(1:na, 1:nb) - &
     872              :                               MATMUL(achint(1:na, 1:np, i_x), TRANSPOSE(bcint(1:nb, 1:np, i_zx)))
     873              : 
     874              :                            ! matrix_rxvr_r(z, x) = xV yx - yV xx
     875              :                            blocks_rxvr_r(3, 1)%block(1:na, 1:nb) = &
     876              :                               blocks_rxvr_r(3, 1)%block(1:na, 1:nb) + &
     877              :                               MATMUL(achint(1:na, 1:np, i_x), TRANSPOSE(bcint(1:nb, 1:np, i_yx)))
     878              :                            blocks_rxvr_r(3, 1)%block(1:na, 1:nb) = &
     879              :                               blocks_rxvr_r(3, 1)%block(1:na, 1:nb) - &
     880              :                               MATMUL(achint(1:na, 1:np, i_y), TRANSPOSE(bcint(1:nb, 1:np, i_xx)))
     881              : 
     882              :                            ! beta = 2
     883              :                            ! matrix_rxvr_r(x, y) = yV zy - zV yy
     884              :                            blocks_rxvr_r(1, 2)%block(1:na, 1:nb) = &
     885              :                               blocks_rxvr_r(1, 2)%block(1:na, 1:nb) + &
     886              :                               MATMUL(achint(1:na, 1:np, i_y), TRANSPOSE(bcint(1:nb, 1:np, i_zy)))
     887              :                            blocks_rxvr_r(1, 2)%block(1:na, 1:nb) = &
     888              :                               blocks_rxvr_r(1, 2)%block(1:na, 1:nb) - &
     889              :                               MATMUL(achint(1:na, 1:np, i_z), TRANSPOSE(bcint(1:nb, 1:np, i_yy)))
     890              : 
     891              :                            ! matrix_rxvr_r(y, y) = zV xy - xV zy
     892              :                            blocks_rxvr_r(2, 2)%block(1:na, 1:nb) = &
     893              :                               blocks_rxvr_r(2, 2)%block(1:na, 1:nb) + &
     894              :                               MATMUL(achint(1:na, 1:np, i_z), TRANSPOSE(bcint(1:nb, 1:np, i_xy)))
     895              :                            blocks_rxvr_r(2, 2)%block(1:na, 1:nb) = &
     896              :                               blocks_rxvr_r(2, 2)%block(1:na, 1:nb) - &
     897              :                               MATMUL(achint(1:na, 1:np, i_x), TRANSPOSE(bcint(1:nb, 1:np, i_zy)))
     898              : 
     899              :                            ! matrix_rxvr_r(z, y) = xV yy - yV xy
     900              :                            blocks_rxvr_r(3, 2)%block(1:na, 1:nb) = &
     901              :                               blocks_rxvr_r(3, 2)%block(1:na, 1:nb) + &
     902              :                               MATMUL(achint(1:na, 1:np, i_x), TRANSPOSE(bcint(1:nb, 1:np, i_yy)))
     903              :                            blocks_rxvr_r(3, 2)%block(1:na, 1:nb) = &
     904              :                               blocks_rxvr_r(3, 2)%block(1:na, 1:nb) - &
     905              :                               MATMUL(achint(1:na, 1:np, i_y), TRANSPOSE(bcint(1:nb, 1:np, i_xy)))
     906              : 
     907              :                            ! beta = 3
     908              :                            ! matrix_rxvr_r(x, z) = yV zz - zV yz
     909              :                            blocks_rxvr_r(1, 3)%block(1:na, 1:nb) = &
     910              :                               blocks_rxvr_r(1, 3)%block(1:na, 1:nb) + &
     911              :                               MATMUL(achint(1:na, 1:np, i_y), TRANSPOSE(bcint(1:nb, 1:np, i_zz)))
     912              :                            blocks_rxvr_r(1, 3)%block(1:na, 1:nb) = &
     913              :                               blocks_rxvr_r(1, 3)%block(1:na, 1:nb) - &
     914              :                               MATMUL(achint(1:na, 1:np, i_z), TRANSPOSE(bcint(1:nb, 1:np, i_yz)))
     915              : 
     916              :                            ! matrix_rxvr_r(y, z) = zV xz - xV zz
     917              :                            blocks_rxvr_r(2, 3)%block(1:na, 1:nb) = &
     918              :                               blocks_rxvr_r(2, 3)%block(1:na, 1:nb) + &
     919              :                               MATMUL(achint(1:na, 1:np, i_z), TRANSPOSE(bcint(1:nb, 1:np, i_xz)))
     920              :                            blocks_rxvr_r(2, 3)%block(1:na, 1:nb) = &
     921              :                               blocks_rxvr_r(2, 3)%block(1:na, 1:nb) - &
     922              :                               MATMUL(achint(1:na, 1:np, i_x), TRANSPOSE(bcint(1:nb, 1:np, i_zz)))
     923              : 
     924              :                            ! matrix_rxvr_r(z, z) = xV yz - yV xz
     925              :                            blocks_rxvr_r(3, 3)%block(1:na, 1:nb) = &
     926              :                               blocks_rxvr_r(3, 3)%block(1:na, 1:nb) + &
     927              :                               MATMUL(achint(1:na, 1:np, i_x), TRANSPOSE(bcint(1:nb, 1:np, i_yz)))
     928              :                            blocks_rxvr_r(3, 3)%block(1:na, 1:nb) = &
     929              :                               blocks_rxvr_r(3, 3)%block(1:na, 1:nb) - &
     930              :                               MATMUL(achint(1:na, 1:np, i_y), TRANSPOSE(bcint(1:nb, 1:np, i_xz)))
     931              : 
     932              :                         END IF ! my_rxvr_r
     933              : 
     934              :                         ! matrix_r_doublecom(alpha, beta) = sum_(gamma delta) epsilon_(alpha gamma delta)
     935              :                         !                                gamma V^pseudoatom beta delta - gamma beta V^pseudoatom delta
     936              : 
     937              :                         IF (my_r_doublecom) THEN
     938              :                            ! beta = 1
     939              :                            ! matrix_r_doublecom(x, x) = yV xz  -  zV xy  -  yxV z  +  zxV y
     940              :                            blocks_r_doublecom(1, 1)%block(1:na, 1:nb) = &
     941              :                               blocks_r_doublecom(1, 1)%block(1:na, 1:nb) + &
     942              :                               MATMUL(achint(1:na, 1:np, i_y), TRANSPOSE(bcint(1:nb, 1:np, i_xz)))
     943              :                            blocks_r_doublecom(1, 1)%block(1:na, 1:nb) = &
     944              :                               blocks_r_doublecom(1, 1)%block(1:na, 1:nb) - &
     945              :                               MATMUL(achint(1:na, 1:np, i_z), TRANSPOSE(bcint(1:nb, 1:np, i_xy)))
     946              :                            blocks_r_doublecom(1, 1)%block(1:na, 1:nb) = &
     947              :                               blocks_r_doublecom(1, 1)%block(1:na, 1:nb) - &
     948              :                               MATMUL(achint(1:na, 1:np, i_yx), TRANSPOSE(bcint(1:nb, 1:np, i_z)))
     949              :                            blocks_r_doublecom(1, 1)%block(1:na, 1:nb) = &
     950              :                               blocks_r_doublecom(1, 1)%block(1:na, 1:nb) + &
     951              :                               MATMUL(achint(1:na, 1:np, i_zx), TRANSPOSE(bcint(1:nb, 1:np, i_y)))
     952              : 
     953              :                            ! matrix_r_doublecom(y, x) = zV xx  -  xV xz  -  zxV x  +  xxV z
     954              :                            blocks_r_doublecom(2, 1)%block(1:na, 1:nb) = &
     955              :                               blocks_r_doublecom(2, 1)%block(1:na, 1:nb) + &
     956              :                               MATMUL(achint(1:na, 1:np, i_z), TRANSPOSE(bcint(1:nb, 1:np, i_xx)))
     957              :                            blocks_r_doublecom(2, 1)%block(1:na, 1:nb) = &
     958              :                               blocks_r_doublecom(2, 1)%block(1:na, 1:nb) - &
     959              :                               MATMUL(achint(1:na, 1:np, i_x), TRANSPOSE(bcint(1:nb, 1:np, i_xz)))
     960              :                            blocks_r_doublecom(2, 1)%block(1:na, 1:nb) = &
     961              :                               blocks_r_doublecom(2, 1)%block(1:na, 1:nb) - &
     962              :                               MATMUL(achint(1:na, 1:np, i_zx), TRANSPOSE(bcint(1:nb, 1:np, i_x)))
     963              :                            blocks_r_doublecom(2, 1)%block(1:na, 1:nb) = &
     964              :                               blocks_r_doublecom(2, 1)%block(1:na, 1:nb) + &
     965              :                               MATMUL(achint(1:na, 1:np, i_xx), TRANSPOSE(bcint(1:nb, 1:np, i_z)))
     966              : 
     967              :                            ! matrix_r_doublecom(z, x) = xV xy  -  yV xx  -  xxV y  +  yxV x
     968              :                            blocks_r_doublecom(3, 1)%block(1:na, 1:nb) = &
     969              :                               blocks_r_doublecom(3, 1)%block(1:na, 1:nb) + &
     970              :                               MATMUL(achint(1:na, 1:np, i_x), TRANSPOSE(bcint(1:nb, 1:np, i_xy)))
     971              :                            blocks_r_doublecom(3, 1)%block(1:na, 1:nb) = &
     972              :                               blocks_r_doublecom(3, 1)%block(1:na, 1:nb) - &
     973              :                               MATMUL(achint(1:na, 1:np, i_y), TRANSPOSE(bcint(1:nb, 1:np, i_xx)))
     974              :                            blocks_r_doublecom(3, 1)%block(1:na, 1:nb) = &
     975              :                               blocks_r_doublecom(3, 1)%block(1:na, 1:nb) - &
     976              :                               MATMUL(achint(1:na, 1:np, i_xx), TRANSPOSE(bcint(1:nb, 1:np, i_y)))
     977              :                            blocks_r_doublecom(3, 1)%block(1:na, 1:nb) = &
     978              :                               blocks_r_doublecom(3, 1)%block(1:na, 1:nb) + &
     979              :                               MATMUL(achint(1:na, 1:np, i_yx), TRANSPOSE(bcint(1:nb, 1:np, i_x)))
     980              : 
     981              :                            ! beta = 2
     982              :                            ! matrix_r_doublecom(x, y) = yV yz  -  zV yy  -  yyV z  +  zyV y
     983              :                            blocks_r_doublecom(1, 2)%block(1:na, 1:nb) = &
     984              :                               blocks_r_doublecom(1, 2)%block(1:na, 1:nb) + &
     985              :                               MATMUL(achint(1:na, 1:np, i_y), TRANSPOSE(bcint(1:nb, 1:np, i_yz)))
     986              :                            blocks_r_doublecom(1, 2)%block(1:na, 1:nb) = &
     987              :                               blocks_r_doublecom(1, 2)%block(1:na, 1:nb) - &
     988              :                               MATMUL(achint(1:na, 1:np, i_z), TRANSPOSE(bcint(1:nb, 1:np, i_yy)))
     989              :                            blocks_r_doublecom(1, 2)%block(1:na, 1:nb) = &
     990              :                               blocks_r_doublecom(1, 2)%block(1:na, 1:nb) - &
     991              :                               MATMUL(achint(1:na, 1:np, i_yy), TRANSPOSE(bcint(1:nb, 1:np, i_z)))
     992              :                            blocks_r_doublecom(1, 2)%block(1:na, 1:nb) = &
     993              :                               blocks_r_doublecom(1, 2)%block(1:na, 1:nb) + &
     994              :                               MATMUL(achint(1:na, 1:np, i_zy), TRANSPOSE(bcint(1:nb, 1:np, i_y)))
     995              : 
     996              :                            ! matrix_r_doublecom(y, y) = zV yx  -  xV yz  -  zyV x  +  xyV z
     997              :                            blocks_r_doublecom(2, 2)%block(1:na, 1:nb) = &
     998              :                               blocks_r_doublecom(2, 2)%block(1:na, 1:nb) + &
     999              :                               MATMUL(achint(1:na, 1:np, i_z), TRANSPOSE(bcint(1:nb, 1:np, i_yx)))
    1000              :                            blocks_r_doublecom(2, 2)%block(1:na, 1:nb) = &
    1001              :                               blocks_r_doublecom(2, 2)%block(1:na, 1:nb) - &
    1002              :                               MATMUL(achint(1:na, 1:np, i_x), TRANSPOSE(bcint(1:nb, 1:np, i_yz)))
    1003              :                            blocks_r_doublecom(2, 2)%block(1:na, 1:nb) = &
    1004              :                               blocks_r_doublecom(2, 2)%block(1:na, 1:nb) - &
    1005              :                               MATMUL(achint(1:na, 1:np, i_zy), TRANSPOSE(bcint(1:nb, 1:np, i_x)))
    1006              :                            blocks_r_doublecom(2, 2)%block(1:na, 1:nb) = &
    1007              :                               blocks_r_doublecom(2, 2)%block(1:na, 1:nb) + &
    1008              :                               MATMUL(achint(1:na, 1:np, i_xy), TRANSPOSE(bcint(1:nb, 1:np, i_z)))
    1009              : 
    1010              :                            ! matrix_r_doublecom(z, y) = xV yy  -  yV yx  -  xyV y  +  yyV x
    1011              :                            blocks_r_doublecom(3, 2)%block(1:na, 1:nb) = &
    1012              :                               blocks_r_doublecom(3, 2)%block(1:na, 1:nb) + &
    1013              :                               MATMUL(achint(1:na, 1:np, i_x), TRANSPOSE(bcint(1:nb, 1:np, i_yy)))
    1014              :                            blocks_r_doublecom(3, 2)%block(1:na, 1:nb) = &
    1015              :                               blocks_r_doublecom(3, 2)%block(1:na, 1:nb) - &
    1016              :                               MATMUL(achint(1:na, 1:np, i_y), TRANSPOSE(bcint(1:nb, 1:np, i_yx)))
    1017              :                            blocks_r_doublecom(3, 2)%block(1:na, 1:nb) = &
    1018              :                               blocks_r_doublecom(3, 2)%block(1:na, 1:nb) - &
    1019              :                               MATMUL(achint(1:na, 1:np, i_xy), TRANSPOSE(bcint(1:nb, 1:np, i_y)))
    1020              :                            blocks_r_doublecom(3, 2)%block(1:na, 1:nb) = &
    1021              :                               blocks_r_doublecom(3, 2)%block(1:na, 1:nb) + &
    1022              :                               MATMUL(achint(1:na, 1:np, i_yy), TRANSPOSE(bcint(1:nb, 1:np, i_x)))
    1023              : 
    1024              :                            ! beta = 3
    1025              :                            ! matrix_r_doublecom(x, z) = yV zz  -  zV zy  -  yzV z  +  zzV y
    1026              :                            blocks_r_doublecom(1, 3)%block(1:na, 1:nb) = &
    1027              :                               blocks_r_doublecom(1, 3)%block(1:na, 1:nb) + &
    1028              :                               MATMUL(achint(1:na, 1:np, i_y), TRANSPOSE(bcint(1:nb, 1:np, i_zz)))
    1029              :                            blocks_r_doublecom(1, 3)%block(1:na, 1:nb) = &
    1030              :                               blocks_r_doublecom(1, 3)%block(1:na, 1:nb) - &
    1031              :                               MATMUL(achint(1:na, 1:np, i_z), TRANSPOSE(bcint(1:nb, 1:np, i_zy)))
    1032              :                            blocks_r_doublecom(1, 3)%block(1:na, 1:nb) = &
    1033              :                               blocks_r_doublecom(1, 3)%block(1:na, 1:nb) - &
    1034              :                               MATMUL(achint(1:na, 1:np, i_yz), TRANSPOSE(bcint(1:nb, 1:np, i_z)))
    1035              :                            blocks_r_doublecom(1, 3)%block(1:na, 1:nb) = &
    1036              :                               blocks_r_doublecom(1, 3)%block(1:na, 1:nb) + &
    1037              :                               MATMUL(achint(1:na, 1:np, i_zz), TRANSPOSE(bcint(1:nb, 1:np, i_y)))
    1038              : 
    1039              :                            ! matrix_r_doublecom(y, z) = zV zx  -  xV zz  -  zzV x  +  xzV z
    1040              :                            blocks_r_doublecom(2, 3)%block(1:na, 1:nb) = &
    1041              :                               blocks_r_doublecom(2, 3)%block(1:na, 1:nb) + &
    1042              :                               MATMUL(achint(1:na, 1:np, i_z), TRANSPOSE(bcint(1:nb, 1:np, i_zx)))
    1043              :                            blocks_r_doublecom(2, 3)%block(1:na, 1:nb) = &
    1044              :                               blocks_r_doublecom(2, 3)%block(1:na, 1:nb) - &
    1045              :                               MATMUL(achint(1:na, 1:np, i_x), TRANSPOSE(bcint(1:nb, 1:np, i_zz)))
    1046              :                            blocks_r_doublecom(2, 3)%block(1:na, 1:nb) = &
    1047              :                               blocks_r_doublecom(2, 3)%block(1:na, 1:nb) - &
    1048              :                               MATMUL(achint(1:na, 1:np, i_zz), TRANSPOSE(bcint(1:nb, 1:np, i_x)))
    1049              :                            blocks_r_doublecom(2, 3)%block(1:na, 1:nb) = &
    1050              :                               blocks_r_doublecom(2, 3)%block(1:na, 1:nb) + &
    1051              :                               MATMUL(achint(1:na, 1:np, i_xz), TRANSPOSE(bcint(1:nb, 1:np, i_z)))
    1052              : 
    1053              :                            ! matrix_r_doublecom(z, z) = xV zy  -  yV zx  -  xzV y  +  yzV x
    1054              :                            blocks_r_doublecom(3, 3)%block(1:na, 1:nb) = &
    1055              :                               blocks_r_doublecom(3, 3)%block(1:na, 1:nb) + &
    1056              :                               MATMUL(achint(1:na, 1:np, i_x), TRANSPOSE(bcint(1:nb, 1:np, i_zy)))
    1057              :                            blocks_r_doublecom(3, 3)%block(1:na, 1:nb) = &
    1058              :                               blocks_r_doublecom(3, 3)%block(1:na, 1:nb) - &
    1059              :                               MATMUL(achint(1:na, 1:np, i_y), TRANSPOSE(bcint(1:nb, 1:np, i_zx)))
    1060              :                            blocks_r_doublecom(3, 3)%block(1:na, 1:nb) = &
    1061              :                               blocks_r_doublecom(3, 3)%block(1:na, 1:nb) - &
    1062              :                               MATMUL(achint(1:na, 1:np, i_xz), TRANSPOSE(bcint(1:nb, 1:np, i_y)))
    1063              :                            blocks_r_doublecom(3, 3)%block(1:na, 1:nb) = &
    1064              :                               blocks_r_doublecom(3, 3)%block(1:na, 1:nb) + &
    1065              :                               MATMUL(achint(1:na, 1:np, i_yz), TRANSPOSE(bcint(1:nb, 1:np, i_x)))
    1066              : 
    1067              :                         END IF ! my_r_doublecom
    1068              : !$                      CALL omp_unset_lock(locks(hash))
    1069              :                         EXIT ! We have found a match and there can be only one single match
    1070              :                      END IF
    1071              :                   END DO
    1072              :                END DO
    1073              :             END DO
    1074              :          END IF
    1075              :          IF (my_rv) THEN
    1076              :             DO ind = 1, 3
    1077              :                NULLIFY (blocks_rv(ind)%block)
    1078              :             END DO
    1079              :             DEALLOCATE (blocks_rv)
    1080              :          END IF
    1081              :          IF (my_rxrv) THEN
    1082              :             DO ind = 1, 3
    1083              :                NULLIFY (blocks_rxrv(ind)%block)
    1084              :             END DO
    1085              :             DEALLOCATE (blocks_rxrv)
    1086              :          END IF
    1087              :          IF (my_rrv) THEN
    1088              :             DO ind = 1, 6
    1089              :                NULLIFY (blocks_rrv(ind)%block)
    1090              :             END DO
    1091              :             DEALLOCATE (blocks_rrv)
    1092              :          END IF
    1093              :          IF (my_rvr) THEN
    1094              :             DO ind = 1, 6
    1095              :                NULLIFY (blocks_rvr(ind)%block)
    1096              :             END DO
    1097              :             DEALLOCATE (blocks_rvr)
    1098              :          END IF
    1099              :          IF (my_rrv_vrr) THEN
    1100              :             DO ind = 1, 6
    1101              :                NULLIFY (blocks_rrv_vrr(ind)%block)
    1102              :             END DO
    1103              :             DEALLOCATE (blocks_rrv_vrr)
    1104              :          END IF
    1105              :          IF (my_r_rxvr) THEN
    1106              :             DO ind = 1, 3
    1107              :                DO ind2 = 1, 3
    1108              :                   NULLIFY (blocks_r_rxvr(ind, ind2)%block)
    1109              :                END DO
    1110              :             END DO
    1111              :             DEALLOCATE (blocks_r_rxvr)
    1112              :          END IF
    1113              :          IF (my_rxvr_r) THEN
    1114              :             DO ind = 1, 3
    1115              :                DO ind2 = 1, 3
    1116              :                   NULLIFY (blocks_rxvr_r(ind, ind2)%block)
    1117              :                END DO
    1118              :             END DO
    1119              :             DEALLOCATE (blocks_rxvr_r)
    1120              :          END IF
    1121              :          IF (my_r_doublecom) THEN
    1122              :             DO ind = 1, 3
    1123              :                DO ind2 = 1, 3
    1124              :                   NULLIFY (blocks_r_doublecom(ind, ind2)%block)
    1125              :                END DO
    1126              :             END DO
    1127              :             DEALLOCATE (blocks_r_doublecom)
    1128              :          END IF
    1129              :       END DO
    1130              : 
    1131              : !$OMP DO
    1132              : !$    DO lock_num = 1, nlock
    1133              : !$       call omp_destroy_lock(locks(lock_num))
    1134              : !$    END DO
    1135              : !$OMP END DO
    1136              : 
    1137              : !$OMP SINGLE
    1138              : !$    DEALLOCATE (locks)
    1139              : !$OMP END SINGLE NOWAIT
    1140              : 
    1141              : !$OMP END PARALLEL
    1142              : 
    1143           80 :       CALL release_sap_int(sap_int)
    1144              : 
    1145           80 :       DEALLOCATE (basis_set)
    1146              : 
    1147           80 :       CALL timestop(handle)
    1148              : 
    1149          264 :    END SUBROUTINE build_com_mom_nl
    1150              : 
    1151              : ! **************************************************************************************************
    1152              : !> \brief calculate \sum_R_ps (R_ps - R_nu) x [V_nl, r] summing over all pseudized atoms R
    1153              : !> \param qs_kind_set ...
    1154              : !> \param sab_all ...
    1155              : !> \param sap_ppnl ...
    1156              : !> \param eps_ppnl ...
    1157              : !> \param particle_set ...
    1158              : !> \param matrix_mag_nl ...
    1159              : !> \param refpoint ...
    1160              : !> \param cell ...
    1161              : ! **************************************************************************************************
    1162            8 :    SUBROUTINE build_com_nl_mag(qs_kind_set, sab_all, sap_ppnl, eps_ppnl, particle_set, matrix_mag_nl, refpoint, cell)
    1163              : 
    1164              :       TYPE(qs_kind_type), DIMENSION(:), INTENT(IN), &
    1165              :          POINTER                                         :: qs_kind_set
    1166              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1167              :          INTENT(IN), POINTER                             :: sab_all, sap_ppnl
    1168              :       REAL(KIND=dp), INTENT(IN)                          :: eps_ppnl
    1169              :       TYPE(particle_type), DIMENSION(:), INTENT(IN), &
    1170              :          POINTER                                         :: particle_set
    1171              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN), &
    1172              :          POINTER                                         :: matrix_mag_nl
    1173              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN), OPTIONAL  :: refpoint
    1174              :       TYPE(cell_type), INTENT(IN), OPTIONAL, POINTER     :: cell
    1175              : 
    1176              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'build_com_nl_mag'
    1177              : 
    1178              :       INTEGER                                            :: handle, iab, iac, iatom, ibc, icol, &
    1179              :                                                             ikind, ind, irow, jatom, jkind, kac, &
    1180              :                                                             kbc, kkind, na, natom, nb, nkind, np, &
    1181              :                                                             order, slot
    1182              :       INTEGER, DIMENSION(3)                              :: cell_b
    1183              :       LOGICAL                                            :: found, go, my_ref, ppnl_present
    1184              :       REAL(KIND=dp), DIMENSION(3)                        :: r_b, r_ps, rab
    1185            8 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: achint, acint, bchint, bcint
    1186              :       TYPE(alist_type), POINTER                          :: alist_ac, alist_bc
    1187            8 :       TYPE(block_p_type), ALLOCATABLE, DIMENSION(:)      :: blocks_mag
    1188              :       TYPE(gto_basis_set_p_type), ALLOCATABLE, &
    1189            8 :          DIMENSION(:)                                    :: basis_set
    1190              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
    1191            8 :       TYPE(sap_int_type), DIMENSION(:), POINTER          :: sap_int
    1192              : 
    1193              : !$    INTEGER(kind=omp_lock_kind), &
    1194            8 : !$       ALLOCATABLE, DIMENSION(:) :: locks
    1195              : !$    INTEGER                                            :: lock_num, hash
    1196              : !$    INTEGER, PARAMETER                                 :: nlock = 501
    1197              : 
    1198            8 :       ppnl_present = ASSOCIATED(sap_ppnl)
    1199            8 :       IF (.NOT. ppnl_present) RETURN
    1200              : 
    1201            8 :       CALL timeset(routineN, handle)
    1202              : 
    1203            8 :       my_ref = .FALSE.
    1204            8 :       IF (PRESENT(refpoint)) THEN
    1205            8 :          my_ref = .TRUE.
    1206            8 :          CPASSERT(PRESENT(cell))
    1207              :       END IF
    1208              : 
    1209            8 :       natom = SIZE(particle_set)
    1210            8 :       nkind = SIZE(qs_kind_set)
    1211              : 
    1212              :       ! allocate integral storage
    1213            8 :       NULLIFY (sap_int)
    1214           56 :       ALLOCATE (sap_int(nkind*nkind))
    1215           40 :       DO ind = 1, nkind*nkind
    1216           32 :          NULLIFY (sap_int(ind)%alist, sap_int(ind)%asort, sap_int(ind)%aindex)
    1217           40 :          sap_int(ind)%nalist = 0
    1218              :       END DO
    1219              : 
    1220              :       ! build integrals over GTO + projector functions, refpoint actually
    1221            8 :       order = 1   ! only need first moments (x, y, z)
    1222              :       ! refpoint actually does not matter in this case, i. e. (order = 1 .and. commutator)
    1223            8 :       IF (my_ref) THEN
    1224              :          CALL build_sap_ints(sap_int, sap_ppnl, qs_kind_set, order, moment_mode=.TRUE., refpoint=refpoint, &
    1225            8 :                              particle_set=particle_set, cell=cell)
    1226              :       ELSE
    1227            0 :          CALL build_sap_ints(sap_int, sap_ppnl, qs_kind_set, order, moment_mode=.TRUE.)
    1228              :       END IF
    1229              : 
    1230            8 :       CALL sap_sort(sap_int)
    1231              : 
    1232              :       ! get access to basis sets
    1233           40 :       ALLOCATE (basis_set(nkind))
    1234           24 :       DO ikind = 1, nkind
    1235           16 :          CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set)
    1236           24 :          IF (ASSOCIATED(orb_basis_set)) THEN
    1237           16 :             basis_set(ikind)%gto_basis_set => orb_basis_set
    1238              :          ELSE
    1239            0 :             NULLIFY (basis_set(ikind)%gto_basis_set)
    1240              :          END IF
    1241              :       END DO
    1242              : 
    1243              : !$OMP PARALLEL &
    1244              : !$OMP DEFAULT (NONE) &
    1245              : !$OMP SHARED  (basis_set, matrix_mag_nl, sap_int, natom, nkind, eps_ppnl, locks, sab_all, &
    1246              : !$OMP          particle_set, my_ref, refpoint) &
    1247              : !$OMP PRIVATE (ikind, jkind, iatom, jatom, cell_b, rab, lock_num, &
    1248              : !$OMP          iab, irow, icol, blocks_mag, r_ps, r_b, go, hash, &
    1249              : !$OMP          found, iac, ibc, alist_ac, alist_bc, acint, bcint, &
    1250            8 : !$OMP          achint, bchint, na, np, nb, kkind, kac, kbc)
    1251              : 
    1252              : !$OMP SINGLE
    1253              : !$    ALLOCATE (locks(nlock))
    1254              : !$OMP END SINGLE
    1255              : 
    1256              : !$OMP DO
    1257              : !$    DO lock_num = 1, nlock
    1258              : !$       call omp_init_lock(locks(lock_num))
    1259              : !$    END DO
    1260              : !$OMP END DO
    1261              : 
    1262              : !$OMP DO SCHEDULE(GUIDED)
    1263              :       DO slot = 1, sab_all(1)%nl_size
    1264              :          ! get indices
    1265              :          ikind = sab_all(1)%nlist_task(slot)%ikind
    1266              :          jkind = sab_all(1)%nlist_task(slot)%jkind
    1267              :          iatom = sab_all(1)%nlist_task(slot)%iatom
    1268              :          jatom = sab_all(1)%nlist_task(slot)%jatom
    1269              :          cell_b(:) = sab_all(1)%nlist_task(slot)%cell(:)
    1270              :          rab(1:3) = sab_all(1)%nlist_task(slot)%r(1:3)
    1271              : 
    1272              :          IF (.NOT. ASSOCIATED(basis_set(ikind)%gto_basis_set)) CYCLE
    1273              :          IF (.NOT. ASSOCIATED(basis_set(jkind)%gto_basis_set)) CYCLE
    1274              :          iab = ikind + nkind*(jkind - 1)
    1275              : 
    1276              :          IF (iatom <= jatom) THEN
    1277              :             irow = iatom
    1278              :             icol = jatom
    1279              :          ELSE
    1280              :             irow = jatom
    1281              :             icol = iatom
    1282              :          END IF
    1283              : 
    1284              :          ! get blocks
    1285              :          ALLOCATE (blocks_mag(3))
    1286              :          DO ind = 1, 3
    1287              :             CALL dbcsr_get_block_p(matrix_mag_nl(ind)%matrix, irow, icol, blocks_mag(ind)%block, found)
    1288              :          END DO
    1289              : 
    1290              :          go = (ASSOCIATED(blocks_mag(1)%block) .AND. ASSOCIATED(blocks_mag(2)%block) .AND. ASSOCIATED(blocks_mag(3)%block))
    1291              : 
    1292              :          IF (go) THEN
    1293              :             DO kkind = 1, nkind
    1294              :                iac = ikind + nkind*(kkind - 1)
    1295              :                ibc = jkind + nkind*(kkind - 1)
    1296              :                IF (.NOT. ASSOCIATED(sap_int(iac)%alist)) CYCLE
    1297              :                IF (.NOT. ASSOCIATED(sap_int(ibc)%alist)) CYCLE
    1298              :                CALL get_alist(sap_int(iac), alist_ac, iatom)
    1299              :                CALL get_alist(sap_int(ibc), alist_bc, jatom)
    1300              :                IF (.NOT. ASSOCIATED(alist_ac)) CYCLE
    1301              :                IF (.NOT. ASSOCIATED(alist_bc)) CYCLE
    1302              :                DO kac = 1, alist_ac%nclist
    1303              :                   DO kbc = 1, alist_bc%nclist
    1304              :                      IF (alist_ac%clist(kac)%catom /= alist_bc%clist(kbc)%catom) CYCLE
    1305              :                      IF (ALL(cell_b + alist_bc%clist(kbc)%cell - alist_ac%clist(kac)%cell == 0)) THEN
    1306              :                         IF (alist_ac%clist(kac)%maxac*alist_bc%clist(kbc)%maxach < eps_ppnl) CYCLE
    1307              : 
    1308              :                         acint => alist_ac%clist(kac)%acint
    1309              :                         bcint => alist_bc%clist(kbc)%acint
    1310              :                         achint => alist_ac%clist(kac)%achint
    1311              :                         bchint => alist_bc%clist(kbc)%achint
    1312              :                         na = SIZE(acint, 1)
    1313              :                         np = SIZE(acint, 2)
    1314              :                         nb = SIZE(bcint, 1)
    1315              :                         ! Position of the pseudized atom
    1316              :                         r_ps = particle_set(alist_ac%clist(kac)%catom)%r
    1317              :                         r_b = refpoint
    1318              : 
    1319              : !$                      hash = MOD((iatom - 1)*natom + jatom, nlock) + 1
    1320              : !$                      CALL omp_set_lock(locks(hash))
    1321              :                         ! assemble integrals
    1322              :                         IF (iatom <= jatom) THEN
    1323              :                            blocks_mag(1)%block(1:na, 1:nb) = blocks_mag(1)%block(1:na, 1:nb) + &
    1324              :                                               (r_ps(2) - r_b(2))*(MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 4))) - &
    1325              :                                                  MATMUL(achint(1:na, 1:np, 4), TRANSPOSE(bcint(1:nb, 1:np, 1)))) & !   R_y [V_nl, z]
    1326              :                                             - (r_ps(3) - r_b(3))*(MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 3))) - &
    1327              :                                                  MATMUL(achint(1:na, 1:np, 3), TRANSPOSE(bcint(1:nb, 1:np, 1))))   ! - R_z [V_nl, y]
    1328              :                            blocks_mag(2)%block(1:na, 1:nb) = blocks_mag(2)%block(1:na, 1:nb) + &
    1329              :                                               (r_ps(3) - r_b(3))*(MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 2))) - &
    1330              :                                                  MATMUL(achint(1:na, 1:np, 2), TRANSPOSE(bcint(1:nb, 1:np, 1)))) & !   R_z [V_nl, x]
    1331              :                                             - (r_ps(1) - r_b(1))*(MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 4))) - &
    1332              :                                                  MATMUL(achint(1:na, 1:np, 4), TRANSPOSE(bcint(1:nb, 1:np, 1))))   ! - R_x [V_nl, z]
    1333              :                            blocks_mag(3)%block(1:na, 1:nb) = blocks_mag(3)%block(1:na, 1:nb) + &
    1334              :                                               (r_ps(1) - r_b(1))*(MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 3))) - &
    1335              :                                                 MATMUL(achint(1:na, 1:np, 3), TRANSPOSE(bcint(1:nb, 1:np, 1)))) &  !   R_x [V_nl, y]
    1336              :                                             - (r_ps(2) - r_b(2))*(MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 2))) - &
    1337              :                                                 MATMUL(achint(1:na, 1:np, 2), TRANSPOSE(bcint(1:nb, 1:np, 1))))    ! - R_y [V_nl, x]
    1338              :                         ELSE
    1339              :                            blocks_mag(1)%block(1:nb, 1:na) = blocks_mag(1)%block(1:nb, 1:na) + &
    1340              :                                               (r_ps(2) - r_b(2))*(MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 4))) - &
    1341              :                                                  MATMUL(bchint(1:nb, 1:np, 4), TRANSPOSE(acint(1:na, 1:np, 1)))) & !   R_y [V_nl, z]
    1342              :                                             - (r_ps(3) - r_b(3))*(MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 3))) - &
    1343              :                                                  MATMUL(bchint(1:nb, 1:np, 3), TRANSPOSE(acint(1:na, 1:np, 1))))   ! - R_z [V_nl, y]
    1344              :                            blocks_mag(2)%block(1:nb, 1:na) = blocks_mag(2)%block(1:nb, 1:na) + &
    1345              :                                               (r_ps(3) - r_b(3))*(MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 2))) - &
    1346              :                                                  MATMUL(bchint(1:nb, 1:np, 2), TRANSPOSE(acint(1:na, 1:np, 1)))) & !   R_z [V_nl, x]
    1347              :                                             - (r_ps(1) - r_b(1))*(MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 4))) - &
    1348              :                                                  MATMUL(bchint(1:nb, 1:np, 4), TRANSPOSE(acint(1:na, 1:np, 1))))   ! - R_x [V_nl, z]
    1349              :                            blocks_mag(3)%block(1:nb, 1:na) = blocks_mag(3)%block(1:nb, 1:na) + &
    1350              :                                               (r_ps(1) - r_b(1))*(MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 3))) - &
    1351              :                                                 MATMUL(bchint(1:nb, 1:np, 3), TRANSPOSE(acint(1:na, 1:np, 1)))) &  !   R_x [V_nl, y]
    1352              :                                             - (r_ps(2) - r_b(2))*(MATMUL(bchint(1:nb, 1:np, 1), TRANSPOSE(acint(1:na, 1:np, 2))) - &
    1353              :                                                 MATMUL(bchint(1:nb, 1:np, 2), TRANSPOSE(acint(1:na, 1:np, 1))))    ! - R_y [V_nl, x]
    1354              :                         END IF
    1355              : !$                      CALL omp_unset_lock(locks(hash))
    1356              :                         EXIT ! We have found a match and there can be only one single match
    1357              :                      END IF
    1358              :                   END DO
    1359              :                END DO
    1360              :             END DO
    1361              :          END IF
    1362              : 
    1363              :          DO ind = 1, 3
    1364              :             NULLIFY (blocks_mag(ind)%block)
    1365              :          END DO
    1366              :          DEALLOCATE (blocks_mag)
    1367              :       END DO
    1368              : 
    1369              : !$OMP DO
    1370              : !$    DO lock_num = 1, nlock
    1371              : !$       call omp_destroy_lock(locks(lock_num))
    1372              : !$    END DO
    1373              : !$OMP END DO
    1374              : 
    1375              : !$OMP SINGLE
    1376              : !$    DEALLOCATE (locks)
    1377              : !$OMP END SINGLE NOWAIT
    1378              : 
    1379              : !$OMP END PARALLEL
    1380              : 
    1381            8 :       DEALLOCATE (basis_set)
    1382            8 :       CALL release_sap_int(sap_int)
    1383              : 
    1384            8 :       CALL timestop(handle)
    1385              : 
    1386           16 :    END SUBROUTINE build_com_nl_mag
    1387              : 
    1388              : ! **************************************************************************************************
    1389              : !> \brief Calculate matrix_rv(gamma, delta) = < R^eta_gamma * Vnl * r_delta > for GIAOs
    1390              : !> \param qs_kind_set ...
    1391              : !> \param sab_all ...
    1392              : !> \param sap_ppnl ...
    1393              : !> \param eps_ppnl ...
    1394              : !> \param particle_set ...
    1395              : !> \param matrix_rv ...
    1396              : !> \param ref_point ...
    1397              : !> \param cell ...
    1398              : !> \param direction_Or If set to true: calculate Vnl * r_delta
    1399              : !>                     Otherwise       calculate r_delta * Vnl
    1400              : ! **************************************************************************************************
    1401            0 :    SUBROUTINE build_com_vnl_giao(qs_kind_set, sab_all, sap_ppnl, eps_ppnl, particle_set, &
    1402              :                                  matrix_rv, ref_point, cell, direction_Or)
    1403              : 
    1404              :       TYPE(qs_kind_type), DIMENSION(:), INTENT(IN), &
    1405              :          POINTER                                         :: qs_kind_set
    1406              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1407              :          INTENT(IN), POINTER                             :: sab_all, sap_ppnl
    1408              :       REAL(KIND=dp), INTENT(IN)                          :: eps_ppnl
    1409              :       TYPE(particle_type), DIMENSION(:), INTENT(IN), &
    1410              :          POINTER                                         :: particle_set
    1411              :       TYPE(dbcsr_p_type), DIMENSION(:, :), &
    1412              :          INTENT(INOUT), OPTIONAL, POINTER                :: matrix_rv
    1413              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN), OPTIONAL  :: ref_point
    1414              :       TYPE(cell_type), INTENT(IN), OPTIONAL, POINTER     :: cell
    1415              :       LOGICAL                                            :: direction_Or
    1416              : 
    1417              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'build_com_vnl_giao'
    1418              :       INTEGER, PARAMETER                                 :: i_1 = 1
    1419              : 
    1420              :       INTEGER                                            :: delta, gamma, handle, i, iab, iac, &
    1421              :                                                             iatom, ibc, icol, ikind, irow, j, &
    1422              :                                                             jatom, jkind, kac, kbc, kkind, na, &
    1423              :                                                             natom, nb, nkind, np, order, slot
    1424              :       INTEGER, DIMENSION(3)                              :: cell_b
    1425              :       LOGICAL                                            :: found, my_ref, ppnl_present
    1426              :       REAL(KIND=dp), DIMENSION(3)                        :: rab, rf
    1427            0 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: achint, acint, bchint, bcint
    1428              :       TYPE(alist_type), POINTER                          :: alist_ac, alist_bc
    1429            0 :       TYPE(block_p_type), ALLOCATABLE, DIMENSION(:, :)   :: blocks_rv
    1430              :       TYPE(gto_basis_set_p_type), ALLOCATABLE, &
    1431            0 :          DIMENSION(:)                                    :: basis_set
    1432              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
    1433            0 :       TYPE(sap_int_type), DIMENSION(:), POINTER          :: sap_int
    1434              : 
    1435              : !$    INTEGER(kind=omp_lock_kind), &
    1436            0 : !$       ALLOCATABLE, DIMENSION(:) :: locks
    1437              : !$    INTEGER                                            :: lock_num, hash
    1438              : !$    INTEGER, PARAMETER                                 :: nlock = 501
    1439              : 
    1440            0 :       ppnl_present = ASSOCIATED(sap_ppnl)
    1441            0 :       IF (.NOT. ppnl_present) RETURN
    1442              : 
    1443            0 :       CALL timeset(routineN, handle)
    1444              : 
    1445            0 :       natom = SIZE(particle_set)
    1446              : 
    1447            0 :       my_ref = .FALSE.
    1448            0 :       IF (PRESENT(ref_point)) THEN
    1449            0 :          CPASSERT(PRESENT(cell)) ! need cell as well if refpoint is provided
    1450            0 :          rf = ref_point
    1451            0 :          my_ref = .TRUE.
    1452              :       END IF
    1453              : 
    1454            0 :       nkind = SIZE(qs_kind_set)
    1455              : 
    1456              :       ! sap_int needs to be shared as multiple threads need to access this
    1457            0 :       NULLIFY (sap_int)
    1458            0 :       ALLOCATE (sap_int(nkind*nkind))
    1459            0 :       DO i = 1, nkind*nkind
    1460            0 :          NULLIFY (sap_int(i)%alist, sap_int(i)%asort, sap_int(i)%aindex)
    1461            0 :          sap_int(i)%nalist = 0
    1462              :       END DO
    1463              : 
    1464            0 :       order = 1
    1465            0 :       IF (my_ref) THEN
    1466              :          ! calculate integrals <a|x^n|p>
    1467              :          CALL build_sap_ints(sap_int, sap_ppnl, qs_kind_set, order, moment_mode=.TRUE., refpoint=rf, &
    1468            0 :                              particle_set=particle_set, cell=cell)
    1469              :       ELSE
    1470            0 :          CALL build_sap_ints(sap_int, sap_ppnl, qs_kind_set, order, moment_mode=.TRUE.)
    1471              :       END IF
    1472              : 
    1473              :       ! *** Set up a sorting index
    1474            0 :       CALL sap_sort(sap_int)
    1475              : 
    1476            0 :       ALLOCATE (basis_set(nkind))
    1477            0 :       DO ikind = 1, nkind
    1478            0 :          CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set)
    1479            0 :          IF (ASSOCIATED(orb_basis_set)) THEN
    1480            0 :             basis_set(ikind)%gto_basis_set => orb_basis_set
    1481              :          ELSE
    1482            0 :             NULLIFY (basis_set(ikind)%gto_basis_set)
    1483              :          END IF
    1484              :       END DO
    1485              : 
    1486            0 :       CALL get_neighbor_list_set_p(neighbor_list_sets=sab_all)
    1487              :       ! *** All integrals needed have been calculated and stored in sap_int
    1488              :       ! *** We now calculate the commutator matrix elements
    1489              : 
    1490              : !$OMP PARALLEL &
    1491              : !$OMP DEFAULT (NONE) &
    1492              : !$OMP SHARED  (basis_set, matrix_rv, &
    1493              : !$OMP          sap_int, nkind, eps_ppnl, locks, sab_all, &
    1494              : !$OMP          particle_set, direction_Or) &
    1495              : !$OMP PRIVATE (ikind, jkind, iatom, jatom, cell_b, rab, &
    1496              : !$OMP          iab, irow, icol, blocks_rv, &
    1497              : !$OMP          found, iac, ibc, alist_ac, alist_bc, &
    1498              : !$OMP          na, np, nb, kkind, kac, kbc, i, lock_num, &
    1499            0 : !$OMP          hash, natom, delta, gamma, achint, bchint, acint, bcint)
    1500              : 
    1501              : !$OMP SINGLE
    1502              : !$    ALLOCATE (locks(nlock))
    1503              : !$OMP END SINGLE
    1504              : 
    1505              : !$OMP DO
    1506              : !$    DO lock_num = 1, nlock
    1507              : !$       call omp_init_lock(locks(lock_num))
    1508              : !$    END DO
    1509              : !$OMP END DO
    1510              : 
    1511              : !$OMP DO SCHEDULE(GUIDED)
    1512              : 
    1513              :       DO slot = 1, sab_all(1)%nl_size
    1514              : 
    1515              :          ikind = sab_all(1)%nlist_task(slot)%ikind
    1516              :          jkind = sab_all(1)%nlist_task(slot)%jkind
    1517              :          iatom = sab_all(1)%nlist_task(slot)%iatom
    1518              :          jatom = sab_all(1)%nlist_task(slot)%jatom
    1519              :          cell_b(:) = sab_all(1)%nlist_task(slot)%cell(:)
    1520              :          rab(1:3) = sab_all(1)%nlist_task(slot)%r(1:3)
    1521              : 
    1522              :          IF (.NOT. ASSOCIATED(basis_set(ikind)%gto_basis_set)) CYCLE
    1523              :          IF (.NOT. ASSOCIATED(basis_set(jkind)%gto_basis_set)) CYCLE
    1524              :          iab = ikind + nkind*(jkind - 1)
    1525              : 
    1526              :          irow = iatom
    1527              :          icol = jatom
    1528              : 
    1529              :          ! allocate blocks
    1530              :          ALLOCATE (blocks_rv(3, 3))
    1531              : 
    1532              :          ! get blocks
    1533              :          DO i = 1, 3
    1534              :             DO j = 1, 3
    1535              :                CALL dbcsr_get_block_p(matrix_rv(i, j)%matrix, irow, icol, &
    1536              :                                       blocks_rv(i, j)%block, found)
    1537              :                blocks_rv(i, j)%block(:, :) = 0.0_dp
    1538              :                CPASSERT(found)
    1539              :             END DO
    1540              :          END DO
    1541              : 
    1542              :          ! loop over all kinds for projector atom
    1543              :          ! < iatom | katom > h < katom | jatom >
    1544              :          DO kkind = 1, nkind
    1545              :             iac = ikind + nkind*(kkind - 1)
    1546              :             ibc = jkind + nkind*(kkind - 1)
    1547              :             IF (.NOT. ASSOCIATED(sap_int(iac)%alist)) CYCLE
    1548              :             IF (.NOT. ASSOCIATED(sap_int(ibc)%alist)) CYCLE
    1549              :             CALL get_alist(sap_int(iac), alist_ac, iatom)
    1550              :             CALL get_alist(sap_int(ibc), alist_bc, jatom)
    1551              :             IF (.NOT. ASSOCIATED(alist_ac)) CYCLE
    1552              :             IF (.NOT. ASSOCIATED(alist_bc)) CYCLE
    1553              :             DO kac = 1, alist_ac%nclist
    1554              :                DO kbc = 1, alist_bc%nclist
    1555              :                   IF (alist_ac%clist(kac)%catom /= alist_bc%clist(kbc)%catom) CYCLE
    1556              : 
    1557              :                   IF (ALL(cell_b + alist_bc%clist(kbc)%cell - alist_ac%clist(kac)%cell == 0)) THEN
    1558              :                      IF (alist_ac%clist(kac)%maxac*alist_bc%clist(kbc)%maxach < eps_ppnl) CYCLE
    1559              :                      acint => alist_ac%clist(kac)%acint
    1560              :                      bcint => alist_bc%clist(kbc)%acint
    1561              :                      achint => alist_ac%clist(kac)%achint
    1562              :                      bchint => alist_bc%clist(kbc)%achint
    1563              :                      na = SIZE(acint, 1)
    1564              :                      np = SIZE(acint, 2)
    1565              :                      nb = SIZE(bcint, 1)
    1566              : !$                   hash = MOD((iatom - 1)*natom + jatom, nlock) + 1
    1567              : !$                   CALL omp_set_lock(locks(hash))
    1568              : 
    1569              :                      !! The atom index is alist_ac%clist(kac)%catom
    1570              :                      ! The coordinate is particle_set(alist_ac%clist(kac)%catom)%r(:)
    1571              :                      IF (direction_Or) THEN  ! V * r_delta * (R^eta_gamma - R^nu_gamma)
    1572              :                         DO delta = 1, 3
    1573              :                            DO gamma = 1, 3
    1574              :                               blocks_rv(gamma, delta)%block(1:na, 1:nb) &
    1575              :                                  = blocks_rv(gamma, delta)%block(1:na, 1:nb) + &
    1576              :                                    MATMUL(achint(1:na, 1:np, i_1), TRANSPOSE(bcint(1:nb, 1:np, delta + 1))) &
    1577              :                                    *(particle_set(alist_ac%clist(kac)%catom)%r(gamma) - particle_set(jatom)%r(gamma))
    1578              :                            END DO
    1579              :                         END DO
    1580              :                      ELSE                   ! r_delta * V * (R^eta_gamma - R^nu_gamma)
    1581              :                         DO delta = 1, 3
    1582              :                            DO gamma = 1, 3
    1583              :                               blocks_rv(gamma, delta)%block(1:na, 1:nb) &
    1584              :                                  = blocks_rv(gamma, delta)%block(1:na, 1:nb) + &
    1585              :                                    MATMUL(achint(1:na, 1:np, delta + 1), TRANSPOSE(bcint(1:nb, 1:np, i_1))) &
    1586              :                                    *(particle_set(alist_ac%clist(kac)%catom)%r(gamma) - particle_set(jatom)%r(gamma))
    1587              :                            END DO
    1588              :                         END DO
    1589              :                      END IF
    1590              : 
    1591              : !$                   CALL omp_unset_lock(locks(hash))
    1592              :                      EXIT ! We have found a match and there can be only one single match
    1593              :                   END IF
    1594              :                END DO
    1595              :             END DO
    1596              :          END DO
    1597              :          DO delta = 1, 3
    1598              :             DO gamma = 1, 3
    1599              :                NULLIFY (blocks_rv(gamma, delta)%block)
    1600              :             END DO
    1601              :          END DO
    1602              :          DEALLOCATE (blocks_rv)
    1603              :       END DO
    1604              : 
    1605              : !$OMP DO
    1606              : !$    DO lock_num = 1, nlock
    1607              : !$       call omp_destroy_lock(locks(lock_num))
    1608              : !$    END DO
    1609              : !$OMP END DO
    1610              : 
    1611              : !$OMP SINGLE
    1612              : !$    DEALLOCATE (locks)
    1613              : !$OMP END SINGLE NOWAIT
    1614              : 
    1615              : !$OMP END PARALLEL
    1616              : 
    1617            0 :       CALL release_sap_int(sap_int)
    1618              : 
    1619            0 :       DEALLOCATE (basis_set)
    1620              : 
    1621            0 :       CALL timestop(handle)
    1622              : 
    1623            0 :    END SUBROUTINE build_com_vnl_giao
    1624              : 
    1625              : END MODULE commutator_rpnl
        

Generated by: LCOV version 2.0-1