LCOV - code coverage report
Current view: top level - src - qs_vcd_ao.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:b1f098b) Lines: 503 536 93.8 %
Date: 2024-05-05 06:30:09 Functions: 12 13 92.3 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : MODULE qs_vcd_ao
       8             :    USE ai_contraction,                  ONLY: block_add,&
       9             :                                               contraction
      10             :    USE ai_kinetic,                      ONLY: kinetic
      11             :    USE ai_overlap_ppl,                  ONLY: ppl_integral
      12             :    USE ao_util,                         ONLY: exp_radius_very_extended
      13             :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      14             :                                               get_atomic_kind_set
      15             :    USE basis_set_types,                 ONLY: get_gto_basis_set,&
      16             :                                               gto_basis_set_p_type,&
      17             :                                               gto_basis_set_type
      18             :    USE block_p_types,                   ONLY: block_p_type
      19             :    USE cell_types,                      ONLY: cell_type,&
      20             :                                               pbc
      21             :    USE cp_control_types,                ONLY: dft_control_type
      22             :    USE cp_dbcsr_operations,             ONLY: dbcsr_allocate_matrix_set,&
      23             :                                               dbcsr_deallocate_matrix_set
      24             :    USE dbcsr_api,                       ONLY: &
      25             :         dbcsr_add, dbcsr_copy, dbcsr_desymmetrize, dbcsr_distribution_get, &
      26             :         dbcsr_distribution_type, dbcsr_finalize, dbcsr_get_block_p, dbcsr_get_info, dbcsr_init_p, &
      27             :         dbcsr_p_type, dbcsr_scale, dbcsr_set, dbcsr_type, dbcsr_work_create
      28             :    USE external_potential_types,        ONLY: get_potential,&
      29             :                                               gth_potential_type,&
      30             :                                               sgp_potential_type
      31             :    USE gaussian_gridlevels,             ONLY: gridlevel_info_type
      32             :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      33             :                                               section_vals_type
      34             :    USE kinds,                           ONLY: default_string_length,&
      35             :                                               dp,&
      36             :                                               int_8
      37             :    USE memory_utilities,                ONLY: reallocate
      38             :    USE message_passing,                 ONLY: mp_comm_type
      39             :    USE orbital_pointers,                ONLY: coset,&
      40             :                                               init_orbital_pointers,&
      41             :                                               ncoset
      42             :    USE particle_types,                  ONLY: particle_type
      43             :    USE pw_env_types,                    ONLY: pw_env_get,&
      44             :                                               pw_env_type
      45             :    USE pw_methods,                      ONLY: pw_axpy,&
      46             :                                               pw_zero
      47             :    USE pw_pool_types,                   ONLY: pw_pool_type
      48             :    USE pw_types,                        ONLY: pw_r3d_rs_type
      49             :    USE qs_energy_types,                 ONLY: qs_energy_type
      50             :    USE qs_environment_types,            ONLY: get_qs_env,&
      51             :                                               qs_environment_type
      52             :    USE qs_integral_utils,               ONLY: basis_set_list_setup,&
      53             :                                               get_memory_usage
      54             :    USE qs_integrate_potential,          ONLY: integrate_pgf_product
      55             :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      56             :                                               get_qs_kind_set,&
      57             :                                               qs_kind_type
      58             :    USE qs_ks_types,                     ONLY: qs_ks_env_type
      59             :    USE qs_linres_types,                 ONLY: vcd_env_type
      60             :    USE qs_moments,                      ONLY: build_dsdv_moments
      61             :    USE qs_neighbor_list_types,          ONLY: &
      62             :         get_iterator_info, get_neighbor_list_set_p, neighbor_list_iterate, &
      63             :         neighbor_list_iterator_create, neighbor_list_iterator_p_type, &
      64             :         neighbor_list_iterator_release, neighbor_list_set_p_type, nl_set_sub_iterator, &
      65             :         nl_sub_iterate
      66             :    USE qs_rho_types,                    ONLY: qs_rho_type
      67             :    USE qs_vxc,                          ONLY: qs_vxc_create
      68             :    USE realspace_grid_types,            ONLY: realspace_grid_type
      69             :    USE rs_pw_interface,                 ONLY: potential_pw2rs
      70             :    USE sap_kind_types,                  ONLY: alist_type,&
      71             :                                               build_sap_ints,&
      72             :                                               get_alist,&
      73             :                                               release_sap_int,&
      74             :                                               sap_int_type,&
      75             :                                               sap_sort
      76             :    USE task_list_types,                 ONLY: atom_pair_type,&
      77             :                                               task_list_type,&
      78             :                                               task_type
      79             :    USE virial_types,                    ONLY: virial_type
      80             : 
      81             : !$ USE OMP_LIB, ONLY: omp_get_max_threads, omp_get_thread_num, omp_get_num_threads
      82             : !$ USE OMP_LIB, ONLY: omp_lock_kind, &
      83             : !$                    omp_init_lock, omp_set_lock, &
      84             : !$                    omp_unset_lock, omp_destroy_lock
      85             : 
      86             : #include "./base/base_uses.f90"
      87             : 
      88             :    IMPLICIT NONE
      89             : 
      90             :    PRIVATE
      91             : 
      92             : ! *** Global parameters ***
      93             : 
      94             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_vcd_ao'
      95             :    INTEGER, PARAMETER :: bi_1 = 1, bi_x = 2, bi_y = 3, bi_z = 4, bi_xx = 5, &
      96             :                          bi_xy = 6, bi_xz = 7, bi_yy = 8, bi_yz = 9, bi_zz = 10
      97             : 
      98             : ! *** Public subroutines ***
      99             : 
     100             :    PUBLIC :: build_dSdV_matrix, build_com_rpnl_r, &
     101             :              hr_mult_by_delta_3d, hr_mult_by_delta_1d, build_dcom_rpnl, build_drpnl_matrix, &
     102             :              build_tr_matrix, &
     103             :              build_rcore_matrix, &
     104             :              build_rpnl_matrix, &
     105             :              build_matrix_r_vhxc, &
     106             :              build_matrix_hr_rh
     107             : 
     108             : CONTAINS
     109             : 
     110             : ! **************************************************************************************************
     111             : !> \brief Build the matrix Hr*delta_nu^\lambda - rH*delta_mu^\lambda
     112             : !> \param vcd_env ...
     113             : !> \param qs_env ...
     114             : !> \param rc ...
     115             : !> \author Edward Ditler
     116             : ! **************************************************************************************************
     117          36 :    SUBROUTINE build_matrix_hr_rh(vcd_env, qs_env, rc)
     118             :       TYPE(vcd_env_type)                                 :: vcd_env
     119             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     120             :       REAL(dp), DIMENSION(3)                             :: rc
     121             : 
     122             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'build_matrix_hr_rh'
     123             :       INTEGER, PARAMETER                                 :: ispin = 1
     124             : 
     125             :       INTEGER                                            :: handle, i
     126             :       REAL(KIND=dp)                                      :: eps_ppnl
     127             :       TYPE(cell_type), POINTER                           :: cell
     128             :       TYPE(dft_control_type), POINTER                    :: dft_control
     129             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     130          36 :          POINTER                                         :: sab_all, sap_ppnl
     131          36 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     132          36 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     133             : 
     134          36 :       CALL timeset(routineN, handle)
     135             : 
     136             :       CALL get_qs_env(qs_env=qs_env, &
     137             :                       dft_control=dft_control, &
     138             :                       particle_set=particle_set, &
     139             :                       sab_all=sab_all, &
     140             :                       sap_ppnl=sap_ppnl, &
     141             :                       qs_kind_set=qs_kind_set, &
     142          36 :                       cell=cell)
     143             : 
     144          36 :       eps_ppnl = dft_control%qs_control%eps_ppnl
     145         144 :       DO i = 1, 3
     146         108 :          CALL dbcsr_set(vcd_env%matrix_hr(ispin, i)%matrix, 0._dp)
     147         144 :          CALL dbcsr_set(vcd_env%matrix_rh(ispin, i)%matrix, 0._dp)
     148             :       END DO
     149             : 
     150             :       ASSOCIATE (my_matrix_hr_1d => vcd_env%matrix_hr(ispin, 1:3))
     151             :          CALL build_rpnl_matrix(my_matrix_hr_1d, qs_kind_set, particle_set, sab_all, sap_ppnl, &
     152             :                                 dft_control%qs_control%eps_ppnl, cell, rc, &
     153          36 :                                 direction_Or=.TRUE.)
     154             :          CALL build_tr_matrix(my_matrix_hr_1d, qs_env, qs_kind_set, "ORB", sab_all, &
     155          36 :                               direction_Or=.TRUE., rc=rc)
     156          36 :          CALL build_rcore_matrix(my_matrix_hr_1d, qs_env, qs_kind_set, "ORB", sab_all, rc)
     157          72 :          CALL build_matrix_r_vhxc(vcd_env%matrix_hr, qs_env, rc)
     158             :       END ASSOCIATE
     159             : 
     160             :       ASSOCIATE (my_matrix_hr_1d => vcd_env%matrix_rh(ispin, 1:3))
     161             :          CALL build_rpnl_matrix(my_matrix_hr_1d, qs_kind_set, particle_set, sab_all, sap_ppnl, &
     162             :                                 dft_control%qs_control%eps_ppnl, cell, rc, &
     163          36 :                                 direction_Or=.FALSE.)
     164             :          CALL build_tr_matrix(my_matrix_hr_1d, qs_env, qs_kind_set, "ORB", sab_all, &
     165          36 :                               direction_Or=.FALSE., rc=rc)
     166          36 :          CALL build_rcore_matrix(my_matrix_hr_1d, qs_env, qs_kind_set, "ORB", sab_all, rc)
     167          72 :          CALL build_matrix_r_vhxc(vcd_env%matrix_rh, qs_env, rc)
     168             :       END ASSOCIATE
     169             : 
     170          36 :       CALL timestop(handle)
     171          36 :    END SUBROUTINE build_matrix_hr_rh
     172             : 
     173             : ! **************************************************************************************************
     174             : !> \brief Product of r with V_nl. Adapted from build_com_rpnl.
     175             : !> \param matrix_rv ...
     176             : !> \param qs_kind_set ...
     177             : !> \param particle_set ...
     178             : !> \param sab_all ...
     179             : !> \param sap_ppnl ...
     180             : !> \param eps_ppnl ...
     181             : !> \param cell ...
     182             : !> \param ref_point ...
     183             : !> \param direction_Or ...
     184             : !> \author Edward Ditler, Tomas Zimmermann
     185             : ! **************************************************************************************************
     186          76 :    SUBROUTINE build_rpnl_matrix(matrix_rv, qs_kind_set, particle_set, sab_all, sap_ppnl, eps_ppnl, &
     187             :                                 cell, ref_point, direction_Or)
     188             : 
     189             :       TYPE(dbcsr_p_type), DIMENSION(:)                   :: matrix_rv
     190             :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     191             :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     192             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     193             :          POINTER                                         :: sab_all, sap_ppnl
     194             :       REAL(KIND=dp), INTENT(IN)                          :: eps_ppnl
     195             :       TYPE(cell_type), INTENT(IN), OPTIONAL, POINTER     :: cell
     196             :       REAL(KIND=dp), DIMENSION(3)                        :: ref_point
     197             :       LOGICAL                                            :: direction_Or
     198             : 
     199             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'build_rpnl_matrix'
     200             : 
     201             :       INTEGER                                            :: handle, i, iab, iac, iatom, ibc, icol, &
     202             :                                                             ikind, irow, jatom, jkind, kac, kbc, &
     203             :                                                             kkind, na, natom, nb, nkind, np, slot
     204             :       INTEGER, DIMENSION(3)                              :: cell_b
     205             :       LOGICAL                                            :: found, ppnl_present
     206          76 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: achint, acint, bchint, bcint
     207             :       TYPE(alist_type), POINTER                          :: alist_ac, alist_bc
     208         304 :       TYPE(block_p_type), DIMENSION(3)                   :: blocks_rv
     209          76 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set
     210             :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
     211          76 :       TYPE(sap_int_type), DIMENSION(:), POINTER          :: sap_int
     212             : 
     213             : !$    INTEGER(kind=omp_lock_kind), &
     214          76 : !$       ALLOCATABLE, DIMENSION(:) :: locks
     215             : !$    INTEGER                                            :: lock_num, hash
     216             : !$    INTEGER, PARAMETER                                 :: nlock = 501
     217             : 
     218          76 :       ppnl_present = ASSOCIATED(sap_ppnl)
     219          76 :       IF (.NOT. ppnl_present) RETURN
     220             : 
     221          76 :       CALL timeset(routineN, handle)
     222          76 :       nkind = SIZE(qs_kind_set)
     223          76 :       natom = SIZE(particle_set)
     224             : 
     225             :       ! sap_int needs to be shared as multiple threads need to access this
     226          76 :       NULLIFY (sap_int)
     227         532 :       ALLOCATE (sap_int(nkind*nkind))
     228         380 :       DO i = 1, nkind*nkind
     229         304 :          NULLIFY (sap_int(i)%alist, sap_int(i)%asort, sap_int(i)%aindex)
     230         380 :          sap_int(i)%nalist = 0
     231             :       END DO
     232             : 
     233             :       MARK_USED(ref_point)
     234             :       ! "nder" in moment_mode is "order"
     235             :       CALL build_sap_ints(sap_int, sap_ppnl, qs_kind_set, nder=1, moment_mode=.TRUE., &
     236          76 :                           particle_set=particle_set, cell=cell, refpoint=ref_point)
     237             : 
     238             :       ! *** Set up a sorting index
     239          76 :       CALL sap_sort(sap_int)
     240             : 
     241         380 :       ALLOCATE (basis_set(nkind))
     242         228 :       DO ikind = 1, nkind
     243         152 :          CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set)
     244         228 :          IF (ASSOCIATED(orb_basis_set)) THEN
     245         152 :             basis_set(ikind)%gto_basis_set => orb_basis_set
     246             :          ELSE
     247           0 :             NULLIFY (basis_set(ikind)%gto_basis_set)
     248             :          END IF
     249             :       END DO
     250             : 
     251             :       ! *** All integrals needed have been calculated and stored in sap_int
     252             :       ! *** We now calculate the commutator matrix elements
     253             : 
     254             : !$OMP PARALLEL &
     255             : !$OMP DEFAULT (NONE) &
     256             : !$OMP SHARED  (basis_set, matrix_rv, &
     257             : !$OMP          sap_int, nkind, eps_ppnl, locks, sab_all, direction_Or) &
     258             : !$OMP PRIVATE (ikind, jkind, iatom, jatom, cell_b, &
     259             : !$OMP          iab, irow, icol, blocks_rv, &
     260             : !$OMP          found, iac, ibc, alist_ac, alist_bc, &
     261             : !$OMP          na, np, nb, kkind, kac, kbc, i, &
     262          76 : !$OMP          hash, natom, acint, bcint, achint, bchint)
     263             : 
     264             : !$OMP SINGLE
     265             : !$    ALLOCATE (locks(nlock))
     266             : !$OMP END SINGLE
     267             : 
     268             : !$OMP DO
     269             : !$    DO lock_num = 1, nlock
     270             : !$       call omp_init_lock(locks(lock_num))
     271             : !$    END DO
     272             : !$OMP END DO
     273             : 
     274             : !$OMP DO SCHEDULE(GUIDED)
     275             : 
     276             :       DO slot = 1, sab_all(1)%nl_size
     277             : 
     278             :          ikind = sab_all(1)%nlist_task(slot)%ikind
     279             :          jkind = sab_all(1)%nlist_task(slot)%jkind
     280             :          iatom = sab_all(1)%nlist_task(slot)%iatom
     281             :          jatom = sab_all(1)%nlist_task(slot)%jatom
     282             :          cell_b(:) = sab_all(1)%nlist_task(slot)%cell(:)
     283             : 
     284             :          IF (.NOT. ASSOCIATED(basis_set(ikind)%gto_basis_set)) CYCLE
     285             :          IF (.NOT. ASSOCIATED(basis_set(jkind)%gto_basis_set)) CYCLE
     286             :          iab = ikind + nkind*(jkind - 1)
     287             : 
     288             :          ! *** Create matrix blocks for a new matrix block column ***
     289             :          irow = iatom
     290             :          icol = jatom
     291             :          DO i = 1, 3
     292             :             CALL dbcsr_get_block_p(matrix_rv(i)%matrix, irow, icol, blocks_rv(i)%block, found)
     293             :             CPASSERT(found)
     294             :          END DO
     295             : 
     296             :          ! loop over all kinds for projector atom
     297             :          DO kkind = 1, nkind
     298             :             iac = ikind + nkind*(kkind - 1)
     299             :             ibc = jkind + nkind*(kkind - 1)
     300             :             IF (.NOT. ASSOCIATED(sap_int(iac)%alist)) CYCLE
     301             :             IF (.NOT. ASSOCIATED(sap_int(ibc)%alist)) CYCLE
     302             :             CALL get_alist(sap_int(iac), alist_ac, iatom)
     303             :             CALL get_alist(sap_int(ibc), alist_bc, jatom)
     304             : 
     305             :             IF (.NOT. ASSOCIATED(alist_ac)) CYCLE
     306             :             IF (.NOT. ASSOCIATED(alist_bc)) CYCLE
     307             :             DO kac = 1, alist_ac%nclist
     308             :                DO kbc = 1, alist_bc%nclist
     309             :                   IF (alist_ac%clist(kac)%catom /= alist_bc%clist(kbc)%catom) CYCLE
     310             :                   IF (ALL(cell_b + alist_bc%clist(kbc)%cell - alist_ac%clist(kac)%cell == 0)) THEN
     311             :                      IF (alist_ac%clist(kac)%maxac*alist_bc%clist(kbc)%maxach < eps_ppnl) CYCLE
     312             :                      acint => alist_ac%clist(kac)%acint
     313             :                      bcint => alist_bc%clist(kbc)%acint
     314             :                      achint => alist_ac%clist(kac)%achint
     315             :                      bchint => alist_bc%clist(kbc)%achint
     316             :                      na = SIZE(acint, 1)
     317             :                      np = SIZE(acint, 2)
     318             :                      nb = SIZE(bcint, 1)
     319             : !$                   hash = MOD((iatom - 1)*natom + jatom, nlock) + 1
     320             : !$                   CALL omp_set_lock(locks(hash))
     321             :                      IF (direction_Or) THEN
     322             :                         ! Vnl*r
     323             :                         blocks_rv(1)%block(1:na, 1:nb) = blocks_rv(1)%block(1:na, 1:nb) + &
     324             :                                                          MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 2)))
     325             :                         blocks_rv(2)%block(1:na, 1:nb) = blocks_rv(2)%block(1:na, 1:nb) + &
     326             :                                                          MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 3)))
     327             :                         blocks_rv(3)%block(1:na, 1:nb) = blocks_rv(3)%block(1:na, 1:nb) + &
     328             :                                                          MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, 4)))
     329             :                      ELSE
     330             :                         ! r*Vnl
     331             :                         blocks_rv(1)%block(1:na, 1:nb) = blocks_rv(1)%block(1:na, 1:nb) + &
     332             :                                                          MATMUL(achint(1:na, 1:np, 2), TRANSPOSE(bcint(1:nb, 1:np, 1)))
     333             :                         blocks_rv(2)%block(1:na, 1:nb) = blocks_rv(2)%block(1:na, 1:nb) + &
     334             :                                                          MATMUL(achint(1:na, 1:np, 3), TRANSPOSE(bcint(1:nb, 1:np, 1)))
     335             :                         blocks_rv(3)%block(1:na, 1:nb) = blocks_rv(3)%block(1:na, 1:nb) + &
     336             :                                                          MATMUL(achint(1:na, 1:np, 4), TRANSPOSE(bcint(1:nb, 1:np, 1)))
     337             :                      END IF
     338             : !$                   CALL omp_unset_lock(locks(hash))
     339             :                      EXIT ! We have found a match and there can be only one single match
     340             :                   END IF
     341             :                END DO
     342             :             END DO
     343             :          END DO
     344             :          DO i = 1, 3
     345             :             NULLIFY (blocks_rv(i)%block)
     346             :          END DO
     347             :       END DO
     348             : 
     349             : !$OMP DO
     350             : !$    DO lock_num = 1, nlock
     351             : !$       call omp_destroy_lock(locks(lock_num))
     352             : !$    END DO
     353             : !$OMP END DO
     354             : 
     355             : !$OMP SINGLE
     356             : !$    DEALLOCATE (locks)
     357             : !$OMP END SINGLE NOWAIT
     358             : 
     359             : !$OMP END PARALLEL
     360             : 
     361          76 :       CALL release_sap_int(sap_int)
     362             : 
     363          76 :       DEALLOCATE (basis_set)
     364             : 
     365          76 :       CALL timestop(handle)
     366             : 
     367         228 :    END SUBROUTINE build_rpnl_matrix
     368             : 
     369             : ! **************************************************************************************************
     370             : !> \brief   Calculation of the product Tr or rT over Cartesian Gaussian functions.
     371             : !> \param   matrix_tr ...
     372             : !> \param   qs_env ...
     373             : !> \param   qs_kind_set ...
     374             : !> \param   basis_type basis set to be used
     375             : !> \param   sab_nl pair list (must be consistent with basis sets!)
     376             : !> \param   direction_Or ...
     377             : !> \param   rc ...
     378             : !> \date    11.10.2010
     379             : !> \par     History
     380             : !>          Ported from qs_overlap, replaces code in build_core_hamiltonian
     381             : !>          Refactoring [07.2014] JGH
     382             : !>          Simplify options and use new kinetic energy integral routine
     383             : !>          Adapted from qs_kinetic [07.2016]
     384             : !>          Adapted from build_com_tr_matrix [2021] by ED
     385             : !> \author  JGH
     386             : !> \version 1.0
     387             : ! **************************************************************************************************
     388          76 :    SUBROUTINE build_tr_matrix(matrix_tr, qs_env, qs_kind_set, basis_type, sab_nl, direction_Or, rc)
     389             : 
     390             :       TYPE(dbcsr_p_type), DIMENSION(:)                   :: matrix_tr
     391             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     392             :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     393             :       CHARACTER(LEN=*), INTENT(IN)                       :: basis_type
     394             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     395             :          POINTER                                         :: sab_nl
     396             :       LOGICAL                                            :: direction_Or
     397             :       REAL(KIND=dp), DIMENSION(3), OPTIONAL              :: rc
     398             : 
     399             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'build_tr_matrix'
     400             : 
     401             :       INTEGER                                            :: handle, iatom, icol, ikind, ir, irow, &
     402             :                                                             iset, jatom, jkind, jset, ldsab, ltab, &
     403             :                                                             natom, ncoa, ncob, nkind, nseta, &
     404             :                                                             nsetb, sgfa, sgfb, slot
     405             :       INTEGER, DIMENSION(3)                              :: cell
     406          76 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, lb_min, npgfa, &
     407          76 :                                                             npgfb, nsgfa, nsgfb
     408          76 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
     409             :       LOGICAL                                            :: do_symmetric, found, trans
     410             :       REAL(KIND=dp)                                      :: tab
     411          76 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: qab, tkab
     412          76 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: kab
     413             :       REAL(KIND=dp), DIMENSION(3)                        :: ra, rab, rac, rb, rbc
     414          76 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a, set_radius_b
     415          76 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: kx_block, ky_block, kz_block, rpgfa, &
     416          76 :                                                             rpgfb, scon_a, scon_b, zeta, zetb
     417             :       TYPE(cell_type), POINTER                           :: qs_cell
     418          76 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
     419             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
     420          76 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     421             : 
     422             : !$    INTEGER(kind=omp_lock_kind), &
     423          76 : !$       ALLOCATABLE, DIMENSION(:) :: locks
     424             : !$    INTEGER                                            :: lock_num, hash, hash1, hash2
     425             : !$    INTEGER(KIND=int_8)                                :: iatom8
     426             : !$    INTEGER, PARAMETER                                 :: nlock = 501
     427             : 
     428             :       MARK_USED(int_8)
     429             : 
     430          76 :       CALL timeset(routineN, handle)
     431             : 
     432          76 :       nkind = SIZE(qs_kind_set)
     433             : 
     434             :       ! check for symmetry
     435          76 :       CPASSERT(SIZE(sab_nl) > 0)
     436          76 :       CALL get_neighbor_list_set_p(neighbor_list_sets=sab_nl, symmetric=do_symmetric)
     437             : 
     438             :       ! prepare basis set
     439         380 :       ALLOCATE (basis_set_list(nkind))
     440          76 :       CALL basis_set_list_setup(basis_set_list, basis_type, qs_kind_set)
     441             : 
     442             :       ! *** Allocate work storage ***
     443          76 :       ldsab = get_memory_usage(qs_kind_set, basis_type)
     444             : 
     445             :       CALL get_qs_env(qs_env=qs_env, &
     446             :                       particle_set=particle_set, &
     447             :                       cell=qs_cell, &
     448          76 :                       natom=natom)
     449             : 
     450             : !$OMP PARALLEL DEFAULT(NONE) &
     451             : !$OMP SHARED (ldsab,do_symmetric, sab_nl, rc,&
     452             : !$OMP         ncoset,matrix_tr,basis_set_list,qs_cell,natom,locks)  &
     453             : !$OMP PRIVATE (kx_block,ky_block,kz_block,kab,qab,tab,ikind,jkind,iatom,jatom,rab,rac,rbc,cell, &
     454             : !$OMP          basis_set_a, basis_set_b, nseta, ncoa, ncob, ltab, nsetb, tkab, &
     455             : !$OMP          irow, icol, found, trans, sgfa, sgfb, iset, jset, &
     456             : !$OMP          hash, hash1, hash2, iatom8, slot) &
     457             : !$OMP PRIVATE (first_sgfa, la_max, la_min, npgfa, nsgfa, rpgfa, set_radius_a, zeta, scon_a) &
     458             : !$OMP PRIVATE (first_sgfb, lb_max, lb_min, npgfb, nsgfb, rpgfb, set_radius_b, zetb, scon_b) &
     459             : !$OMP SHARED(particle_set, direction_or) &
     460          76 : !$OMP PRIVATE(ra, rb)
     461             : 
     462             : !$OMP SINGLE
     463             : !$    ALLOCATE (locks(nlock))
     464             : !$OMP END SINGLE
     465             : 
     466             : !$OMP DO
     467             : !$    DO lock_num = 1, nlock
     468             : !$       call omp_init_lock(locks(lock_num))
     469             : !$    END DO
     470             : !$OMP END DO
     471             : 
     472             :       ALLOCATE (kab(ldsab, ldsab, 3), qab(ldsab, ldsab))
     473             : 
     474             : !$OMP DO SCHEDULE(GUIDED)
     475             :       DO slot = 1, sab_nl(1)%nl_size
     476             : 
     477             :          ikind = sab_nl(1)%nlist_task(slot)%ikind
     478             :          jkind = sab_nl(1)%nlist_task(slot)%jkind
     479             :          iatom = sab_nl(1)%nlist_task(slot)%iatom
     480             :          jatom = sab_nl(1)%nlist_task(slot)%jatom
     481             :          cell(:) = sab_nl(1)%nlist_task(slot)%cell(:)
     482             :          rab(1:3) = sab_nl(1)%nlist_task(slot)%r(1:3)
     483             : 
     484             :          basis_set_a => basis_set_list(ikind)%gto_basis_set
     485             :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
     486             :          basis_set_b => basis_set_list(jkind)%gto_basis_set
     487             :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
     488             : 
     489             : !$       iatom8 = INT(iatom - 1, int_8)*INT(natom, int_8) + INT(jatom, int_8)
     490             : !$       hash1 = INT(MOD(iatom8, INT(nlock, int_8)) + 1)
     491             : 
     492             :          ! basis ikind
     493             :          first_sgfa => basis_set_a%first_sgf
     494             :          la_max => basis_set_a%lmax
     495             :          la_min => basis_set_a%lmin
     496             :          npgfa => basis_set_a%npgf
     497             :          nsgfa => basis_set_a%nsgf_set
     498             :          rpgfa => basis_set_a%pgf_radius
     499             :          set_radius_a => basis_set_a%set_radius
     500             :          scon_a => basis_set_a%scon
     501             :          zeta => basis_set_a%zet
     502             :          ! basis jkind
     503             :          first_sgfb => basis_set_b%first_sgf
     504             :          lb_max => basis_set_b%lmax
     505             :          lb_min => basis_set_b%lmin
     506             :          npgfb => basis_set_b%npgf
     507             :          nsgfb => basis_set_b%nsgf_set
     508             :          rpgfb => basis_set_b%pgf_radius
     509             :          set_radius_b => basis_set_b%set_radius
     510             :          scon_b => basis_set_b%scon
     511             :          zetb => basis_set_b%zet
     512             : 
     513             :          nseta = basis_set_a%nset
     514             :          nsetb = basis_set_b%nset
     515             : 
     516             :          IF (do_symmetric) THEN
     517             :             IF (iatom <= jatom) THEN
     518             :                irow = iatom
     519             :                icol = jatom
     520             :             ELSE
     521             :                irow = jatom
     522             :                icol = iatom
     523             :             END IF
     524             :          ELSE
     525             :             irow = iatom
     526             :             icol = jatom
     527             :          END IF
     528             :          NULLIFY (kx_block)
     529             :          CALL dbcsr_get_block_p(matrix=matrix_tr(1)%matrix, &
     530             :                                 row=irow, col=icol, BLOCK=kx_block, found=found)
     531             :          CPASSERT(found)
     532             :          NULLIFY (ky_block)
     533             :          CALL dbcsr_get_block_p(matrix=matrix_tr(2)%matrix, &
     534             :                                 row=irow, col=icol, BLOCK=ky_block, found=found)
     535             :          CPASSERT(found)
     536             :          NULLIFY (kz_block)
     537             :          CALL dbcsr_get_block_p(matrix=matrix_tr(3)%matrix, &
     538             :                                 row=irow, col=icol, BLOCK=kz_block, found=found)
     539             :          CPASSERT(found)
     540             : 
     541             :          ! The kinetic integrals depend only on rab (also for the screening)
     542             :          tab = NORM2(rab)
     543             : 
     544             :          ! With and without MIC, rab(:) is the vector giving us the coordinates of rb.
     545             :          ra = pbc(particle_set(iatom)%r(:), qs_cell)
     546             :          rb(:) = ra(:) + rab(:)
     547             :          rac = pbc(rc, ra, qs_cell)
     548             :          rbc = rac + rab
     549             : 
     550             :          trans = do_symmetric .AND. (iatom > jatom)
     551             : 
     552             :          DO iset = 1, nseta
     553             : 
     554             :             ncoa = npgfa(iset)*(ncoset(la_max(iset)) - ncoset(la_min(iset) - 1))
     555             :             sgfa = first_sgfa(1, iset)
     556             : 
     557             :             DO jset = 1, nsetb
     558             : 
     559             :                IF (set_radius_a(iset) + set_radius_b(jset) < tab) CYCLE
     560             : 
     561             : !$             hash2 = MOD((iset - 1)*nsetb + jset, nlock) + 1
     562             : !$             hash = MOD(hash1 + hash2, nlock) + 1
     563             : 
     564             :                ncob = npgfb(jset)*(ncoset(lb_max(jset)) - ncoset(lb_min(jset) - 1))
     565             :                sgfb = first_sgfb(1, jset)
     566             : 
     567             :                ! calculate integrals
     568             :                ltab = MAX(npgfa(iset)*ncoset(la_max(iset) + 1), npgfb(jset)*ncoset(lb_max(jset) + 1))
     569             :                ALLOCATE (tkab(ltab, ltab))
     570             :                CALL kinetic(la_max(iset) + 1, la_min(iset), npgfa(iset), rpgfa(:, iset), zeta(:, iset), &
     571             :                             lb_max(jset) + 1, lb_min(jset), npgfb(jset), rpgfb(:, jset), zetb(:, jset), &
     572             :                             rab, tkab)
     573             :                ! commutator
     574             :                CALL ab_opr(la_max(iset), npgfa(iset), rpgfa(:, iset), la_min(iset), &
     575             :                            lb_max(jset), npgfb(jset), rpgfb(:, jset), lb_min(jset), &
     576             :                            tab, tkab, kab, rac, rbc, direction_Or)
     577             : 
     578             :                DEALLOCATE (tkab)
     579             :                ! Contraction step
     580             :                DO ir = 1, 3
     581             :                   CALL contraction(kab(:, :, ir), qab, ca=scon_a(:, sgfa:), na=ncoa, ma=nsgfa(iset), &
     582             :                                    cb=scon_b(:, sgfb:), nb=ncob, mb=nsgfb(jset), trans=trans)
     583             : 
     584             : !$                CALL omp_set_lock(locks(hash))
     585             :                   SELECT CASE (ir)
     586             :                   CASE (1)
     587             :                      CALL block_add("IN", qab, nsgfa(iset), nsgfb(jset), kx_block, sgfa, sgfb, trans=trans)
     588             :                   CASE (2)
     589             :                      CALL block_add("IN", qab, nsgfa(iset), nsgfb(jset), ky_block, sgfa, sgfb, trans=trans)
     590             :                   CASE (3)
     591             :                      CALL block_add("IN", qab, nsgfa(iset), nsgfb(jset), kz_block, sgfa, sgfb, trans=trans)
     592             :                   END SELECT
     593             : !$                CALL omp_unset_lock(locks(hash))
     594             :                END DO
     595             : 
     596             :             END DO
     597             :          END DO
     598             :       END DO !iterator
     599             :       DEALLOCATE (kab, qab)
     600             : !$OMP DO
     601             : !$    DO lock_num = 1, nlock
     602             : !$       call omp_destroy_lock(locks(lock_num))
     603             : !$    END DO
     604             : !$OMP END DO
     605             : 
     606             : !$OMP SINGLE
     607             : !$    DEALLOCATE (locks)
     608             : !$OMP END SINGLE NOWAIT
     609             : 
     610             : !$OMP END PARALLEL
     611             : 
     612             :       ! Release work storage
     613          76 :       DEALLOCATE (basis_set_list)
     614          76 :       CALL timestop(handle)
     615             : 
     616         228 :    END SUBROUTINE build_tr_matrix
     617             : 
     618             : ! **************************************************************************************************
     619             : !> \brief Commutator of the of the local part of the pseudopotential with r
     620             : !> \param matrix_rcore ...
     621             : !> \param qs_env ...
     622             : !> \param qs_kind_set ...
     623             : !> \param basis_type ...
     624             : !> \param sab_nl ...
     625             : !> \param rf ...
     626             : !> \author Edward Ditler, Tomas Zimmermann
     627             : ! **************************************************************************************************
     628          76 :    SUBROUTINE build_rcore_matrix(matrix_rcore, qs_env, qs_kind_set, basis_type, sab_nl, rf)
     629             :       TYPE(dbcsr_p_type), DIMENSION(:)                   :: matrix_rcore
     630             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     631             :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     632             :       CHARACTER(LEN=*)                                   :: basis_type
     633             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     634             :          POINTER                                         :: sab_nl
     635             :       REAL(KIND=dp), DIMENSION(3), OPTIONAL              :: rf
     636             : 
     637             :       CHARACTER(len=*), PARAMETER :: routineN = 'build_rcore_matrix'
     638             :       INTEGER, PARAMETER                                 :: nexp_max = 30
     639             : 
     640             :       INTEGER :: atom_a, atom_b, handle, i, iatom, icol, idir, ikind, inode, irow, iset, jatom, &
     641             :          jkind, jset, katom, kkind, ldai, ldsab, maxco, maxder, maxl, maxlgto, maxlppl, maxnset, &
     642             :          maxsgf, mepos, n_local, ncoa, ncob, nder, nexp_lpot, nexp_ppl, nimages, nkind, nloc, &
     643             :          nseta, nsetb, nthread, sgfa, sgfb
     644          76 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_of_kind
     645             :       INTEGER, DIMENSION(1:10)                           :: nrloc
     646             :       INTEGER, DIMENSION(3)                              :: cellind
     647          76 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, lb_min, &
     648          76 :                                                             nct_lpot, npgfa, npgfb, nsgfa, nsgfb
     649          76 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
     650             :       INTEGER, DIMENSION(nexp_max)                       :: nct_ppl
     651             :       LOGICAL                                            :: do_symmetric, dokp, ecp_local, &
     652             :                                                             ecp_semi_local, found, lpotextended
     653             :       REAL(KIND=dp)                                      :: alpha, dab, dac, dbc, ppl_radius
     654          76 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: hab, qab
     655          76 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: ppl_work, rhab, work
     656             :       REAL(KIND=dp), DIMENSION(1:10)                     :: aloc, bloc
     657             :       REAL(KIND=dp), DIMENSION(3)                        :: ra, rab, rac, raf, rb, rbc, rbf
     658             :       REAL(KIND=dp), DIMENSION(4, nexp_max)              :: cval_ppl
     659          76 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: a_local, alpha_lpot, c_local, cexp_ppl, &
     660          76 :                                                             set_radius_a, set_radius_b
     661          76 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: cval_lpot, hx_block, hy_block, hz_block, &
     662          76 :                                                             rpgfa, rpgfb, scon_a, scon_b, sphi_a, &
     663          76 :                                                             sphi_b, zeta, zetb
     664             :       REAL(KIND=dp), DIMENSION(nexp_max)                 :: alpha_ppl
     665          76 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     666             :       TYPE(cell_type), POINTER                           :: cell
     667             :       TYPE(gth_potential_type), POINTER                  :: gth_potential
     668          76 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
     669             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
     670             :       TYPE(neighbor_list_iterator_p_type), &
     671          76 :          DIMENSION(:), POINTER                           :: ap_iterator, nl_iterator
     672             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     673          76 :          POINTER                                         :: sac_ppl
     674          76 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     675             :       TYPE(sgp_potential_type), POINTER                  :: sgp_potential
     676             : 
     677          76 :       CALL timeset(routineN, handle)
     678             : 
     679             :       CALL get_qs_env(qs_env=qs_env, &
     680             :                       atomic_kind_set=atomic_kind_set, &
     681             :                       qs_kind_set=qs_kind_set, &
     682             :                       particle_set=particle_set, &
     683             :                       sac_ppl=sac_ppl, &
     684          76 :                       cell=cell)
     685             : 
     686             :       ! check for symmetry
     687          76 :       CPASSERT(SIZE(sab_nl) > 0)
     688          76 :       CALL get_neighbor_list_set_p(neighbor_list_sets=sab_nl, symmetric=do_symmetric)
     689             : 
     690          76 :       nkind = SIZE(qs_kind_set)
     691             : 
     692             :       ! prepare basis set
     693         380 :       ALLOCATE (basis_set_list(nkind))
     694          76 :       CALL basis_set_list_setup(basis_set_list, basis_type, qs_kind_set)
     695             : 
     696          76 :       nder = 0
     697          76 :       nimages = 1
     698             : 
     699             :       alpha_ppl = 0
     700             :       nct_ppl = 0
     701             :       cval_ppl = 0
     702             : 
     703          76 :       nkind = SIZE(atomic_kind_set)
     704             : 
     705          76 :       dokp = (nimages > 1)
     706             : 
     707          76 :       CALL get_atomic_kind_set(atomic_kind_set=atomic_kind_set, atom_of_kind=atom_of_kind)
     708             : 
     709          76 :       maxder = ncoset(nder)
     710             : 
     711             :       CALL get_qs_kind_set(qs_kind_set, maxco=maxco, maxlgto=maxlgto, &
     712             :                            maxsgf=maxsgf, maxnset=maxnset, maxlppl=maxlppl, &
     713          76 :                            basis_type=basis_type)
     714             : 
     715          76 :       maxl = MAX(maxlgto, maxlppl)
     716          76 :       CALL init_orbital_pointers(2*maxl + 2*nder + 2)
     717             : 
     718             :       !tz: maxco in maxco*ncoset(maxlgto+1) is an overkill,
     719             :       !    properly there should be maxpgf*ncoset(maxlgto+1), but maxpgf is difficult to get
     720          76 :       ldsab = MAX(maxco, ncoset(maxlppl), maxsgf, maxlppl, maxco*ncoset(maxlgto + 1))
     721          76 :       ldai = ncoset(2*maxlgto + 2)
     722             : 
     723         228 :       DO ikind = 1, nkind
     724         152 :          CALL get_qs_kind(qs_kind_set(ikind), basis_set=basis_set_a, basis_type=basis_type)
     725         228 :          IF (ASSOCIATED(basis_set_a)) THEN
     726         152 :             basis_set_list(ikind)%gto_basis_set => basis_set_a
     727             :          ELSE
     728           0 :             NULLIFY (basis_set_list(ikind)%gto_basis_set)
     729             :          END IF
     730             :       END DO
     731             : 
     732             :       nthread = 1
     733          76 : !$    nthread = omp_get_max_threads()
     734             : 
     735          76 :       CALL neighbor_list_iterator_create(nl_iterator, sab_nl, nthread=nthread)
     736             : 
     737             :       ! iterator for basis/potential list
     738          76 :       CALL neighbor_list_iterator_create(ap_iterator, sac_ppl, search=.TRUE., nthread=nthread)
     739             : 
     740             : !$OMP PARALLEL &
     741             : !$OMP DEFAULT (NONE) &
     742             : !$OMP SHARED  (nl_iterator, ap_iterator, basis_set_list, &
     743             : !$OMP          atomic_kind_set, qs_kind_set, particle_set, &
     744             : !$OMP          sab_nl, sac_ppl, nthread, ncoset, nkind, &
     745             : !$OMP          atom_of_kind, ldsab,  maxnset, maxder, &
     746             : !$OMP          maxlgto, nder, maxco, dokp, cell) &
     747             : !$OMP SHARED (matrix_rcore, rf) &
     748             : !$OMP PRIVATE (ikind, jkind, inode, iatom, jatom, rab, basis_set_a, basis_set_b, atom_a) &
     749             : !$OMP PRIVATE (atom_b) &
     750             : !$OMP PRIVATE (nsetb) &
     751             : !$OMP PRIVATE (dab, irow, icol, hx_block, hy_block, hz_block, found, iset, ncoa) &
     752             : !$OMP PRIVATE (sgfa, jset, ncob, sgfb, work, hab, rhab, kkind, nseta) &
     753             : !$OMP PRIVATE (gth_potential, sgp_potential, alpha, cexp_ppl, lpotextended) &
     754             : !$OMP PRIVATE (ppl_radius, nexp_lpot, nexp_ppl, alpha_ppl, alpha_lpot, nct_ppl) &
     755             : !$OMP PRIVATE (ecp_semi_local, nct_lpot, cval_ppl, cval_lpot, rac, dac, rbc, dbc) &
     756             : !$OMP PRIVATE (mepos) &
     757             : !$OMP PRIVATE (katom, ppl_work, cellind, ecp_local) &
     758             : !$OMP PRIVATE (first_sgfa, la_max, la_min, npgfa, nsgfa, rpgfa, set_radius_a, sphi_a, zeta, scon_a) &
     759             : !$OMP PRIVATE (first_sgfb, lb_max, lb_min, npgfb, nsgfb, rpgfb, set_radius_b, sphi_b, zetb, scon_b) &
     760             : !$OMP PRIVATE (nloc, nrloc, aloc, bloc, n_local, a_local, c_local, ldai) &
     761          76 : !$OMP PRIVATE (ra, rb, qab, raf, rbf)
     762             : 
     763             :       mepos = 0
     764             : !$    mepos = omp_get_thread_num()
     765             : 
     766             :       ALLOCATE (hab(ldsab, ldsab), rhab(ldsab, ldsab, 3), work(ldsab, ldsab*(nder + 1), 3))
     767             :       ALLOCATE (qab(ldsab, ldsab))
     768             : 
     769             :       ldai = ncoset(2*maxlgto + 2)
     770             :       ALLOCATE (ppl_work(ldai, ldai, MAX(maxder, 2*maxlgto + 2 + 1)))
     771             : 
     772             :       DO WHILE (neighbor_list_iterate(nl_iterator, mepos=mepos) == 0)
     773             : 
     774             :          CALL get_iterator_info(nl_iterator, mepos=mepos, ikind=ikind, jkind=jkind, inode=inode, &
     775             :                                 iatom=iatom, jatom=jatom, r=rab, cell=cellind)
     776             : 
     777             :          basis_set_a => basis_set_list(ikind)%gto_basis_set
     778             :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
     779             :          basis_set_b => basis_set_list(jkind)%gto_basis_set
     780             :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
     781             : 
     782             :          atom_a = atom_of_kind(iatom)
     783             :          atom_b = atom_of_kind(jatom)
     784             : 
     785             :          ! basis ikind
     786             :          first_sgfa => basis_set_a%first_sgf
     787             :          la_max => basis_set_a%lmax
     788             :          la_min => basis_set_a%lmin
     789             :          npgfa => basis_set_a%npgf
     790             :          nsgfa => basis_set_a%nsgf_set
     791             :          rpgfa => basis_set_a%pgf_radius
     792             :          set_radius_a => basis_set_a%set_radius
     793             :          sphi_a => basis_set_a%sphi
     794             :          zeta => basis_set_a%zet
     795             :          scon_a => basis_set_a%scon
     796             :          ! basis jkind
     797             :          first_sgfb => basis_set_b%first_sgf
     798             :          lb_max => basis_set_b%lmax
     799             :          lb_min => basis_set_b%lmin
     800             :          npgfb => basis_set_b%npgf
     801             :          nsgfb => basis_set_b%nsgf_set
     802             :          rpgfb => basis_set_b%pgf_radius
     803             :          set_radius_b => basis_set_b%set_radius
     804             :          sphi_b => basis_set_b%sphi
     805             :          zetb => basis_set_b%zet
     806             :          scon_b => basis_set_b%scon
     807             : 
     808             :          nseta = basis_set_a%nset
     809             :          nsetb = basis_set_b%nset
     810             : 
     811             :          ! *** Create matrix blocks for a new matrix block column ***
     812             :          irow = iatom
     813             :          icol = jatom
     814             : 
     815             :          NULLIFY (hx_block)
     816             :          NULLIFY (hy_block)
     817             :          NULLIFY (hz_block)
     818             :          CALL dbcsr_get_block_p(matrix=matrix_rcore(1)%matrix, &
     819             :                                 row=irow, col=icol, BLOCK=hx_block, found=found)
     820             :          CPASSERT(found)
     821             :          CALL dbcsr_get_block_p(matrix=matrix_rcore(2)%matrix, &
     822             :                                 row=irow, col=icol, BLOCK=hy_block, found=found)
     823             :          CPASSERT(found)
     824             :          CALL dbcsr_get_block_p(matrix=matrix_rcore(3)%matrix, &
     825             :                                 row=irow, col=icol, BLOCK=hz_block, found=found)
     826             :          CPASSERT(found)
     827             : 
     828             :          dab = NORM2(rab)
     829             :          ra = pbc(particle_set(iatom)%r(:), cell)
     830             :          rb(:) = ra(:) + rab(:)
     831             : 
     832             :          raf = pbc(rf, ra, cell)
     833             :          rbf = raf + rab
     834             : 
     835             :          ! loop over all kinds for pseudopotential atoms
     836             :          DO kkind = 1, nkind
     837             :             CALL get_qs_kind(qs_kind_set(kkind), gth_potential=gth_potential, &
     838             :                              sgp_potential=sgp_potential)
     839             :             IF (ASSOCIATED(gth_potential)) THEN
     840             :                CALL get_potential(potential=gth_potential, &
     841             :                                   alpha_ppl=alpha, cexp_ppl=cexp_ppl, &
     842             :                                   lpot_present=lpotextended, ppl_radius=ppl_radius)
     843             :                nexp_ppl = 1
     844             :                alpha_ppl(1) = alpha
     845             :                nct_ppl(1) = SIZE(cexp_ppl)
     846             :                cval_ppl(1:nct_ppl(1), 1) = cexp_ppl(1:nct_ppl(1))
     847             :                IF (lpotextended) THEN
     848             :                   CALL get_potential(potential=gth_potential, &
     849             :                                      nexp_lpot=nexp_lpot, alpha_lpot=alpha_lpot, nct_lpot=nct_lpot, cval_lpot=cval_lpot)
     850             :                   CPASSERT(nexp_lpot < nexp_max)
     851             :                   nexp_ppl = nexp_lpot + 1
     852             :                   alpha_ppl(2:nexp_lpot + 1) = alpha_lpot(1:nexp_lpot)
     853             :                   nct_ppl(2:nexp_lpot + 1) = nct_lpot(1:nexp_lpot)
     854             :                   DO i = 1, nexp_lpot
     855             :                      cval_ppl(1:nct_lpot(i), i + 1) = cval_lpot(1:nct_lpot(i), i)
     856             :                   END DO
     857             :                END IF
     858             :             ELSE IF (ASSOCIATED(sgp_potential)) THEN
     859             :                CALL get_potential(potential=sgp_potential, ecp_local=ecp_local, ecp_semi_local=ecp_semi_local, &
     860             :                                   ppl_radius=ppl_radius)
     861             :                IF (ecp_local) THEN
     862             :                   CALL get_potential(potential=sgp_potential, nloc=nloc, nrloc=nrloc, aloc=aloc, bloc=bloc)
     863             :                   IF (SUM(ABS(aloc(1:nloc))) < 1.0e-12_dp) CYCLE
     864             :                   nexp_ppl = nloc
     865             :                   CPASSERT(nexp_ppl <= nexp_max)
     866             :                   nct_ppl(1:nloc) = nrloc(1:nloc) - 1
     867             :                   alpha_ppl(1:nloc) = bloc(1:nloc)
     868             :                   cval_ppl(1, 1:nloc) = aloc(1:nloc)
     869             :                ELSE
     870             :                   CALL get_potential(potential=sgp_potential, n_local=n_local, a_local=a_local, c_local=c_local)
     871             :                   nexp_ppl = n_local
     872             :                   CPASSERT(nexp_ppl <= nexp_max)
     873             :                   nct_ppl(1:n_local) = 1
     874             :                   alpha_ppl(1:n_local) = a_local(1:n_local)
     875             :                   cval_ppl(1, 1:n_local) = c_local(1:n_local)
     876             :                END IF
     877             :                IF (ecp_semi_local) THEN
     878             :                   CPABORT("VCD with semi-local ECPs not implemented")
     879             :                END IF
     880             :             ELSE
     881             :                CYCLE
     882             :             END IF
     883             : 
     884             :             CALL nl_set_sub_iterator(ap_iterator, ikind, kkind, iatom, mepos=mepos)
     885             : 
     886             :             DO WHILE (nl_sub_iterate(ap_iterator, mepos=mepos) == 0)
     887             : 
     888             :                CALL get_iterator_info(ap_iterator, mepos=mepos, jatom=katom, r=rac)
     889             :                dac = SQRT(SUM(rac*rac))
     890             :                rbc(:) = rac(:) - rab(:)
     891             :                dbc = SQRT(SUM(rbc*rbc))
     892             :                IF ((MAXVAL(set_radius_a(:)) + ppl_radius < dac) .OR. &
     893             :                    (MAXVAL(set_radius_b(:)) + ppl_radius < dbc)) THEN
     894             :                   CYCLE
     895             :                END IF
     896             :                DO iset = 1, nseta
     897             :                   IF (set_radius_a(iset) + ppl_radius < dac) CYCLE
     898             :                   ncoa = npgfa(iset)*ncoset(la_max(iset))
     899             :                   !                  ncoa = npgfa(iset)*(ncoset(la_max(iset))-ncoset(la_min(iset)-1))
     900             :                   sgfa = first_sgfa(1, iset)
     901             :                   DO jset = 1, nsetb
     902             :                      IF (set_radius_b(jset) + ppl_radius < dbc) CYCLE
     903             :                      ncob = npgfb(jset)*ncoset(lb_max(jset))
     904             :                      !                     ncob = npgfb(jset)*(ncoset(lb_max(jset))-ncoset(lb_min(jset)-1))
     905             :                      sgfb = first_sgfb(1, jset)
     906             :                      IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
     907             :                      ! *** Calculate the GTH pseudo potential forces ***
     908             :                      hab = 0
     909             :                      rhab = 0
     910             :                      ppl_work = 0
     911             :                      work = 0
     912             : 
     913             :                      CALL ppl_integral( &
     914             :                         la_max(iset) + 1, la_min(iset), npgfa(iset), &
     915             :                         rpgfa(:, iset), zeta(:, iset), &
     916             :                         lb_max(jset) + 1, lb_min(jset), npgfb(jset), &
     917             :                         rpgfb(:, jset), zetb(:, jset), &
     918             :                         nexp_ppl, alpha_ppl, nct_ppl, cval_ppl, ppl_radius, &
     919             :                         rab, dab, rac, dac, rbc, dbc, hab(:, :), ppl_work)
     920             : 
     921             :                      ! product with r
     922             :                      CALL ab_opr(la_max(iset), npgfa(iset), rpgfa(:, iset), 0, &
     923             :                                  lb_max(jset), npgfb(jset), rpgfb(:, jset), 0, &
     924             :                                  dab, hab(:, :), rhab(:, :, :), raf, rbf, &
     925             :                                  direction_Or=.FALSE.)
     926             : 
     927             :                      DO idir = 1, 3
     928             :                         CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
     929             :                                    1.0_dp, rhab(1, 1, idir), SIZE(rhab, 1), &
     930             :                                    sphi_b(1, sgfb), SIZE(sphi_b, 1), &
     931             :                                    0.0_dp, work(1, 1, idir), SIZE(work, 1))
     932             : !$OMP CRITICAL(h_block_critical)
     933             :                         SELECT CASE (idir)
     934             :                         CASE (1)
     935             :                            CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
     936             :                                       1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
     937             :                                       work(1, 1, idir), SIZE(work, 1), &
     938             :                                       1.0_dp, hx_block(sgfa, sgfb), SIZE(hx_block, 1))
     939             :                         CASE (2)
     940             :                            CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
     941             :                                       1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
     942             :                                       work(1, 1, idir), SIZE(work, 1), &
     943             :                                       1.0_dp, hy_block(sgfa, sgfb), SIZE(hy_block, 1))
     944             :                         CASE (3)
     945             :                            CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
     946             :                                       1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
     947             :                                       work(1, 1, idir), SIZE(work, 1), &
     948             :                                       1.0_dp, hz_block(sgfa, sgfb), SIZE(hz_block, 1))
     949             :                         END SELECT
     950             : !$OMP END CRITICAL(h_block_critical)
     951             :                      END DO
     952             :                   END DO
     953             :                END DO
     954             :             END DO
     955             :          END DO
     956             :       END DO ! iterator
     957             : 
     958             :       DEALLOCATE (hab, rhab, work, ppl_work)
     959             : 
     960             : !$OMP END PARALLEL
     961             : 
     962          76 :       CALL neighbor_list_iterator_release(ap_iterator)
     963          76 :       CALL neighbor_list_iterator_release(nl_iterator)
     964             : 
     965          76 :       DEALLOCATE (atom_of_kind, basis_set_list)
     966             : 
     967          76 :       CALL timestop(handle)
     968             : 
     969         304 :    END SUBROUTINE build_rcore_matrix
     970             : 
     971             : ! **************************************************************************************************
     972             : !> \brief Commutator of the Hartree+XC potentials with r
     973             : !> \param matrix_rv ...
     974             : !> \param qs_env ...
     975             : !> \param rc ...
     976             : !> \author Edward Ditler, Tomas Zimmermann
     977             : ! **************************************************************************************************
     978          76 :    SUBROUTINE build_matrix_r_vhxc(matrix_rv, qs_env, rc)
     979             :       TYPE(dbcsr_p_type), DIMENSION(:, :), &
     980             :          INTENT(INOUT), POINTER                          :: matrix_rv
     981             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     982             :       REAL(KIND=dp), DIMENSION(3)                        :: rc
     983             : 
     984             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'build_matrix_r_vhxc'
     985             :       INTEGER, PARAMETER                                 :: nspins = 1
     986             : 
     987             :       INTEGER                                            :: handle, idir, ispin
     988             :       REAL(kind=dp)                                      :: edisp
     989          76 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks
     990          76 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_rvxc, matrix_rvxc_desymm
     991             :       TYPE(pw_env_type), POINTER                         :: pw_env
     992             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     993          76 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: v_rspace, v_tau_rspace
     994             :       TYPE(pw_r3d_rs_type), POINTER                      :: v_hartree_rspace
     995             :       TYPE(qs_energy_type), POINTER                      :: energy
     996             :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     997             :       TYPE(qs_rho_type), POINTER                         :: rho_struct
     998             :       TYPE(section_vals_type), POINTER                   :: input, xc_section
     999             : 
    1000          76 :       CALL timeset(routineN, handle)
    1001             : 
    1002             :       CALL get_qs_env(qs_env, matrix_ks=matrix_ks, &
    1003             :                       ks_env=ks_env, &
    1004             :                       pw_env=pw_env, &
    1005             :                       input=input, &
    1006             :                       v_hartree_rspace=v_hartree_rspace, &
    1007          76 :                       energy=energy)
    1008             : 
    1009          76 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    1010             : 
    1011             :       ! matrix_rv(nspin, 3) was allocated as
    1012             :       ! CALL dbcsr_init_p(vcd_env%matrix_hr(ispin, i)%matrix)
    1013             :       ! CALL dbcsr_copy(vcd_env%matrix_hr(ispin, i)%matrix, vcd_env%matrix_nosym_temp(1)%matrix)
    1014             : 
    1015          76 :       NULLIFY (matrix_rvxc, matrix_rvxc_desymm)
    1016          76 :       CALL dbcsr_allocate_matrix_set(matrix_rvxc, nspins, 3)
    1017          76 :       CALL dbcsr_allocate_matrix_set(matrix_rvxc_desymm, nspins, 3)
    1018             : 
    1019         152 :       DO ispin = 1, nspins
    1020         380 :          DO idir = 1, 3
    1021         228 :             CALL dbcsr_init_p(matrix_rvxc(ispin, idir)%matrix)
    1022         228 :             CALL dbcsr_init_p(matrix_rvxc_desymm(ispin, idir)%matrix)
    1023             : 
    1024         228 :             CALL dbcsr_copy(matrix_rvxc_desymm(ispin, idir)%matrix, matrix_rv(1, 1)%matrix)
    1025         228 :             CALL dbcsr_set(matrix_rvxc_desymm(ispin, idir)%matrix, 0._dp)
    1026             : 
    1027         228 :             CALL dbcsr_copy(matrix_rvxc(ispin, idir)%matrix, matrix_ks(ispin)%matrix)
    1028         304 :             CALL dbcsr_set(matrix_rvxc(ispin, idir)%matrix, 0.0_dp)
    1029             :          END DO
    1030             :       END DO
    1031             : 
    1032          76 :       xc_section => section_vals_get_subs_vals(input, "DFT%XC")
    1033          76 :       CALL get_qs_env(qs_env=qs_env, rho=rho_struct)
    1034             : 
    1035          76 :       NULLIFY (v_rspace)
    1036          76 :       NULLIFY (v_tau_rspace)
    1037             :       CALL qs_vxc_create(ks_env=ks_env, rho_struct=rho_struct, xc_section=xc_section, &
    1038             :                          vxc_rho=v_rspace, vxc_tau=v_tau_rspace, exc=energy%exc, &
    1039             :                          edisp=edisp, dispersion_env=qs_env%dispersion_env, &
    1040          76 :                          just_energy=.FALSE.)
    1041             : 
    1042          76 :       IF (.NOT. ASSOCIATED(v_rspace)) THEN
    1043           0 :          ALLOCATE (v_rspace(nspins))
    1044           0 :          DO ispin = 1, nspins
    1045           0 :             CALL auxbas_pw_pool%create_pw(v_rspace(ispin))
    1046           0 :             CALL pw_zero(v_rspace(ispin))
    1047             :          END DO
    1048             :       END IF
    1049             : 
    1050         152 :       DO ispin = 1, nspins
    1051          76 :          CALL pw_axpy(v_hartree_rspace, v_rspace(ispin), 1.0_dp/v_hartree_rspace%pw_grid%dvol)
    1052             :          CALL integrate_rv_rspace(v_rspace=v_rspace(ispin), hmat=matrix_rvxc(ispin, :), qs_env=qs_env, &
    1053          76 :                                   rc=rc)
    1054             : 
    1055         380 :          DO idir = 1, 3
    1056         228 :             CALL dbcsr_scale(matrix_rvxc(ispin, idir)%matrix, v_rspace(ispin)%pw_grid%dvol)
    1057         228 :             CALL dbcsr_desymmetrize(matrix_rvxc(ispin, idir)%matrix, matrix_rvxc_desymm(ispin, idir)%matrix)
    1058         304 :             CALL dbcsr_add(matrix_rv(ispin, idir)%matrix, matrix_rvxc_desymm(ispin, idir)%matrix, 1.0_dp, 1.0_dp)
    1059             :          END DO
    1060             :       END DO
    1061             : 
    1062             :       ! return pw grids
    1063         152 :       DO ispin = 1, nspins
    1064         152 :          CALL auxbas_pw_pool%give_back_pw(v_rspace(ispin))
    1065             :       END DO
    1066          76 :       DEALLOCATE (v_rspace)
    1067             : 
    1068          76 :       CALL dbcsr_deallocate_matrix_set(matrix_rvxc)
    1069          76 :       CALL dbcsr_deallocate_matrix_set(matrix_rvxc_desymm)
    1070             : 
    1071          76 :       CALL timestop(handle)
    1072             : 
    1073          76 :    END SUBROUTINE build_matrix_r_vhxc
    1074             : 
    1075             : ! **************************************************************************************************
    1076             : !> \brief Calculates the integrals < mu | r * V | nu >
    1077             : !>        There is no direction_Or argument, because the potentials commute with r
    1078             : !>        This routine uses integrate_pgf_product directly. It could probably be rewritten to use
    1079             : !>          the new task_list interface.
    1080             : !> \param v_rspace ...
    1081             : !> \param hmat ...
    1082             : !> \param qs_env ...
    1083             : !> \param rc ...
    1084             : !> \author Edward Ditler
    1085             : ! **************************************************************************************************
    1086          76 :    SUBROUTINE integrate_rv_rspace(v_rspace, hmat, qs_env, rc)
    1087             : 
    1088             :       TYPE(pw_r3d_rs_type)                               :: v_rspace
    1089             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT)    :: hmat
    1090             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1091             :       REAL(KIND=dp), DIMENSION(3)                        :: rc
    1092             : 
    1093             :       CHARACTER(len=*), PARAMETER :: routineN = 'integrate_rv_rspace'
    1094             : 
    1095             :       CHARACTER(len=default_string_length)               :: my_basis_type
    1096             :       INTEGER :: bcol, brow, handle, iatom, idir, igrid_level, ikind, ikind_old, ilevel, img, &
    1097             :          ipair, ipgf, ipgf_new, iset, iset_new, iset_old, itask, ithread, jatom, jkind, jkind_old, &
    1098             :          jpgf, jpgf_new, jset, jset_new, jset_old, ldsab, maxco, maxlgto, maxpgf, maxset, &
    1099             :          maxsgf_set, na1, na2, natom, nb1, nb2, ncoa, ncoa_full, ncob, ncob_full, nkind, nseta, &
    1100             :          nsetb, nthread, sgfa, sgfb
    1101          76 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, lb_min, npgfa, &
    1102          76 :                                                             npgfb, nsgfa, nsgfb
    1103          76 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
    1104             :       LOGICAL :: atom_pair_changed, atom_pair_done, distributed_grids, found, has_threads, &
    1105             :          my_compute_tau, my_gapw, new_set_pair_coming
    1106             :       REAL(KIND=dp)                                      :: dab, eps_rho_rspace, f, prefactor, &
    1107             :                                                             radius, zetp
    1108             :       REAL(KIND=dp), DIMENSION(3)                        :: ra, rab, rab_inv, rac, rb, rbc, rp
    1109          76 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a, set_radius_b
    1110          76 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: hab, rpgfa, rpgfb, sphi_a, sphi_b, work, &
    1111          76 :                                                             zeta, zetb
    1112          76 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: habt, rhab, workt
    1113          76 :       TYPE(atom_pair_type), DIMENSION(:), POINTER        :: atom_pair_recv, atom_pair_send
    1114          76 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1115          76 :       TYPE(block_p_type), ALLOCATABLE, DIMENSION(:)      :: h_block
    1116             :       TYPE(cell_type), POINTER                           :: cell
    1117             :       TYPE(dbcsr_distribution_type)                      :: dist
    1118             :       TYPE(dft_control_type), POINTER                    :: dft_control
    1119             :       TYPE(gridlevel_info_type), POINTER                 :: gridlevel_info
    1120             :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
    1121             :       TYPE(mp_comm_type)                                 :: group
    1122          76 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1123             :       TYPE(pw_env_type), POINTER                         :: pw_env
    1124          76 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1125          76 :       TYPE(realspace_grid_type), DIMENSION(:), POINTER   :: rs_v
    1126             :       TYPE(task_list_type), POINTER                      :: task_list, task_list_soft
    1127          76 :       TYPE(task_type), DIMENSION(:), POINTER             :: tasks
    1128             :       TYPE(virial_type), POINTER                         :: virial
    1129             : 
    1130          76 :       CALL timeset(routineN, handle)
    1131             : 
    1132          76 :       my_compute_tau = .FALSE.
    1133          76 :       my_gapw = .FALSE.
    1134          76 :       my_basis_type = "ORB"
    1135             : 
    1136             :       ! get the task lists
    1137             :       CALL get_qs_env(qs_env=qs_env, &
    1138             :                       task_list=task_list, &
    1139          76 :                       task_list_soft=task_list_soft)
    1140          76 :       CPASSERT(ASSOCIATED(task_list))
    1141             : 
    1142             :       ! the information on the grids is provided through pw_env
    1143             :       ! pw_env has to be the parent env for the potential grid (input)
    1144             :       ! there is an option to provide an external grid
    1145          76 :       CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
    1146          76 :       CPASSERT(ASSOCIATED(pw_env))
    1147             : 
    1148             :       ! get all the general information on the system we are working on
    1149             :       CALL get_qs_env(qs_env=qs_env, &
    1150             :                       atomic_kind_set=atomic_kind_set, &
    1151             :                       qs_kind_set=qs_kind_set, &
    1152             :                       cell=cell, &
    1153             :                       dft_control=dft_control, &
    1154             :                       particle_set=particle_set, &
    1155             :                       virial=virial, &
    1156          76 :                       natom=natom)
    1157             : 
    1158          76 :       rab = 0._dp
    1159          76 :       rac = 0._dp
    1160          76 :       rbc = 0._dp
    1161             : 
    1162             :       ! short cuts to task list variables
    1163          76 :       tasks => task_list%tasks
    1164          76 :       atom_pair_send => task_list%atom_pair_send
    1165          76 :       atom_pair_recv => task_list%atom_pair_recv
    1166             : 
    1167          76 :       CPASSERT(ASSOCIATED(pw_env))
    1168          76 :       CALL pw_env_get(pw_env, rs_grids=rs_v)
    1169             : 
    1170             :       ! get mpi group from rs_v
    1171          76 :       group = rs_v(1)%desc%group
    1172             : 
    1173             :       ! assign from pw_env
    1174          76 :       gridlevel_info => pw_env%gridlevel_info
    1175             : 
    1176             :       ! transform the potential on the rs_multigrids
    1177          76 :       CALL potential_pw2rs(rs_v, v_rspace, pw_env)
    1178             : 
    1179          76 :       nkind = SIZE(qs_kind_set)
    1180             : 
    1181             :       ! needs to be consistent with rho_rspace
    1182          76 :       eps_rho_rspace = dft_control%qs_control%eps_rho_rspace
    1183             : 
    1184             :       CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
    1185             :                            maxco=maxco, &
    1186             :                            maxlgto=maxlgto, &
    1187             :                            maxsgf_set=maxsgf_set, &
    1188          76 :                            basis_type=my_basis_type)
    1189             : 
    1190          76 :       distributed_grids = .FALSE.
    1191         380 :       DO igrid_level = 1, gridlevel_info%ngrid_levels
    1192          76 :          IF (rs_v(igrid_level)%desc%distributed) THEN
    1193         304 :             distributed_grids = .TRUE.
    1194             :          END IF
    1195             :       END DO
    1196             : 
    1197             :       nthread = 1
    1198          76 : !$    nthread = omp_get_max_threads()
    1199             : 
    1200             :       ! get maximum numbers
    1201          76 :       maxset = 0
    1202          76 :       maxpgf = 0
    1203         228 :       DO ikind = 1, nkind
    1204             :          CALL get_qs_kind(qs_kind_set(ikind), &
    1205         152 :                           basis_set=orb_basis_set, basis_type=my_basis_type)
    1206             : 
    1207         152 :          IF (.NOT. ASSOCIATED(orb_basis_set)) CYCLE
    1208             : 
    1209             :          CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
    1210         152 :                                 npgf=npgfa, nset=nseta)
    1211             : 
    1212         152 :          maxset = MAX(nseta, maxset)
    1213         380 :          maxpgf = MAX(MAXVAL(npgfa), maxpgf)
    1214             :       END DO
    1215             : 
    1216          76 :       ldsab = MAX(maxco, maxsgf_set, maxpgf*ncoset(maxlgto + 1))
    1217             : 
    1218             :       !   *** Allocate work storage ***
    1219          76 :       NULLIFY (habt, workt)
    1220          76 :       CALL reallocate(habt, 1, ldsab, 1, ldsab, 0, nthread)
    1221          76 :       CALL reallocate(workt, 1, ldsab, 1, maxsgf_set, 0, nthread)
    1222         380 :       ALLOCATE (rhab(ldsab, ldsab, 3))
    1223             : 
    1224         304 :       ALLOCATE (h_block(3))
    1225             : 
    1226          76 :       ithread = 0
    1227          76 : !$    ithread = omp_get_thread_num()
    1228          76 :       work => workt(:, :, ithread)
    1229          76 :       hab => habt(:, :, ithread)
    1230      124716 :       hab(:, :) = 0._dp
    1231             : 
    1232          76 :       iset_old = -1; jset_old = -1
    1233          76 :       ikind_old = -1; jkind_old = -1
    1234             : 
    1235             :       ! Here we loop over gridlevels first, finalising the matrix after each grid level is
    1236             :       ! completed.  On each grid level, we loop over atom pairs, which will only access
    1237             :       ! a single block of each matrix, so with OpenMP, each matrix block is only touched
    1238             :       ! by a single thread for each grid level
    1239         380 :       loop_gridlevels: DO igrid_level = 1, gridlevel_info%ngrid_levels
    1240        1216 :          DO idir = 1, 3
    1241         912 :             CALL dbcsr_work_create(hmat(idir)%matrix, work_mutable=.TRUE., n=nthread)
    1242         912 :             CALL dbcsr_get_info(hmat(idir)%matrix, distribution=dist)
    1243         912 :             CALL dbcsr_distribution_get(dist, has_threads=has_threads)
    1244         912 : !$          IF (.NOT. has_threads) &
    1245        1216 : !$             CPABORT("No thread distribution defined.")
    1246             :          END DO
    1247             : 
    1248         988 :          loop_pairs: DO ipair = 1, task_list%npairs(igrid_level)
    1249        4598 :          loop_tasks: DO itask = task_list%taskstart(ipair, igrid_level), task_list%taskstop(ipair, igrid_level)
    1250        3610 :             ilevel = tasks(itask)%grid_level
    1251        3610 :             img = tasks(itask)%image
    1252        3610 :             iatom = tasks(itask)%iatom
    1253        3610 :             jatom = tasks(itask)%jatom
    1254        3610 :             iset = tasks(itask)%iset
    1255        3610 :             jset = tasks(itask)%jset
    1256        3610 :             ipgf = tasks(itask)%ipgf
    1257        3610 :             jpgf = tasks(itask)%jpgf
    1258        3610 :             CPASSERT(img == 1)
    1259             : 
    1260             :             ! At the start of a block of tasks, get atom data (and kind data, if needed)
    1261        3610 :             IF (itask .EQ. task_list%taskstart(ipair, igrid_level)) THEN
    1262             : 
    1263         684 :                ikind = particle_set(iatom)%atomic_kind%kind_number
    1264         684 :                jkind = particle_set(jatom)%atomic_kind%kind_number
    1265             : 
    1266         684 :                IF (iatom <= jatom) THEN
    1267         456 :                   brow = iatom
    1268         456 :                   bcol = jatom
    1269             :                ELSE
    1270         228 :                   brow = jatom
    1271         228 :                   bcol = iatom
    1272             :                END IF
    1273             : 
    1274         684 :                IF (ikind .NE. ikind_old) THEN
    1275             :                   CALL get_qs_kind(qs_kind_set(ikind), &
    1276          76 :                                    basis_set=orb_basis_set, basis_type=my_basis_type)
    1277             : 
    1278             :                   CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
    1279             :                                          first_sgf=first_sgfa, &
    1280             :                                          lmax=la_max, &
    1281             :                                          lmin=la_min, &
    1282             :                                          npgf=npgfa, &
    1283             :                                          nset=nseta, &
    1284             :                                          nsgf_set=nsgfa, &
    1285             :                                          pgf_radius=rpgfa, &
    1286             :                                          set_radius=set_radius_a, &
    1287             :                                          sphi=sphi_a, &
    1288          76 :                                          zet=zeta)
    1289             :                END IF
    1290             : 
    1291         684 :                IF (jkind .NE. jkind_old) THEN
    1292             :                   CALL get_qs_kind(qs_kind_set(jkind), &
    1293         456 :                                    basis_set=orb_basis_set, basis_type=my_basis_type)
    1294             :                   CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
    1295             :                                          first_sgf=first_sgfb, &
    1296             :                                          lmax=lb_max, &
    1297             :                                          lmin=lb_min, &
    1298             :                                          npgf=npgfb, &
    1299             :                                          nset=nsetb, &
    1300             :                                          nsgf_set=nsgfb, &
    1301             :                                          pgf_radius=rpgfb, &
    1302             :                                          set_radius=set_radius_b, &
    1303             :                                          sphi=sphi_b, &
    1304         456 :                                          zet=zetb)
    1305             : 
    1306             :                END IF
    1307             : 
    1308        2736 :                DO idir = 1, 3
    1309        2052 :                   NULLIFY (h_block(idir)%block)
    1310        2052 :                   CALL dbcsr_get_block_p(hmat(idir)%matrix, brow, bcol, h_block(idir)%block, found)
    1311        2736 :                   CPASSERT(found)
    1312             :                END DO
    1313             : 
    1314             :                ikind_old = ikind
    1315             :                jkind_old = jkind
    1316             : 
    1317             :                atom_pair_changed = .TRUE.
    1318             : 
    1319             :             ELSE
    1320             : 
    1321             :                atom_pair_changed = .FALSE.
    1322             : 
    1323             :             END IF
    1324             : 
    1325        3610 :             IF (atom_pair_changed .OR. iset_old .NE. iset .OR. jset_old .NE. jset) THEN
    1326             :                ! We reuse the hab(:, :) array to put the new integrals in.
    1327             : 
    1328         684 :                ncoa = npgfa(iset)*ncoset(la_max(iset))
    1329         684 :                ncoa_full = npgfa(iset)*ncoset(la_max(iset) + 1)
    1330         684 :                sgfa = first_sgfa(1, iset)
    1331         684 :                ncob = npgfb(jset)*ncoset(lb_max(jset))
    1332         684 :                ncob_full = npgfb(jset)*ncoset(lb_max(jset) + 1)
    1333         684 :                sgfb = first_sgfb(1, jset)
    1334             : 
    1335         684 :                IF (iatom <= jatom) THEN
    1336      324216 :                   hab(1:ncoa_full, 1:ncob_full) = 0._dp
    1337             :                ELSE
    1338      106020 :                   hab(1:ncob_full, 1:ncoa_full) = 0._dp
    1339             :                END IF
    1340             : 
    1341             :                iset_old = iset
    1342             :                jset_old = jset
    1343             : 
    1344             :             END IF
    1345             : 
    1346       14440 :             rab = tasks(itask)%rab
    1347       14440 :             dab = norm2(rab)
    1348             :             ! With and without MIC, rab(:) is the vector giving us the coordinates of rb.
    1349        3610 :             ra = pbc(particle_set(iatom)%r(:), cell)
    1350       14440 :             rb(:) = ra(:) + rab(:)
    1351        3610 :             rac = pbc(rc, ra, cell)
    1352       14440 :             rbc = rac + rab
    1353             : 
    1354        3610 :             zetp = zeta(ipgf, iset) + zetb(jpgf, jset)
    1355        3610 :             f = zetb(jpgf, jset)/zetp
    1356       14440 :             rp(:) = ra(:) + f*rab(:)
    1357             : 
    1358       14440 :             prefactor = EXP(-zeta(ipgf, iset)*f*DOT_PRODUCT(rab, rab))
    1359             :             radius = exp_radius_very_extended(la_min=la_min(iset), la_max=la_max(iset), &
    1360             :                                               lb_min=lb_min(jset), lb_max=lb_max(jset), &
    1361             :                                               ra=ra, rb=rb, rp=rp, &
    1362             :                                               zetp=zetp, eps=eps_rho_rspace, &
    1363        3610 :                                               prefactor=prefactor, cutoff=1.0_dp)
    1364             : 
    1365        3610 :             na1 = (ipgf - 1)*ncoset(la_max(iset) + 1) + 1
    1366        3610 :             na2 = ipgf*ncoset(la_max(iset) + 1)
    1367        3610 :             nb1 = (jpgf - 1)*ncoset(lb_max(jset) + 1) + 1
    1368        3610 :             nb2 = jpgf*ncoset(lb_max(jset) + 1)
    1369             : 
    1370        3610 :             IF (iatom <= jatom) THEN
    1371             :                CALL integrate_pgf_product( &
    1372             :                   la_max(iset) + 1, zeta(ipgf, iset), la_min(iset), &
    1373             :                   lb_max(jset) + 1, zetb(jpgf, jset), lb_min(jset), &
    1374             :                   ra, rab, rs_v(igrid_level), &
    1375             :                   hab, o1=na1 - 1, o2=nb1 - 1, &
    1376             :                   radius=radius, &
    1377        2432 :                   calculate_forces=.FALSE.)
    1378             :             ELSE
    1379        4712 :                rab_inv = -rab
    1380             :                CALL integrate_pgf_product( &
    1381             :                   lb_max(jset) + 1, zetb(jpgf, jset), lb_min(jset), &
    1382             :                   la_max(iset) + 1, zeta(ipgf, iset), la_min(iset), &
    1383             :                   rb, rab_inv, rs_v(igrid_level), &
    1384             :                   hab, o1=nb1 - 1, o2=na1 - 1, &
    1385             :                   radius=radius, &
    1386        1178 :                   calculate_forces=.FALSE.)
    1387             :             END IF
    1388             : 
    1389        3610 :             new_set_pair_coming = .FALSE.
    1390        3610 :             atom_pair_done = .FALSE.
    1391        3610 :             IF (itask < task_list%taskstop(ipair, igrid_level)) THEN
    1392        2926 :                ilevel = tasks(itask + 1)%grid_level
    1393        2926 :                img = tasks(itask + 1)%image
    1394        2926 :                iatom = tasks(itask + 1)%iatom
    1395        2926 :                jatom = tasks(itask + 1)%jatom
    1396        2926 :                iset_new = tasks(itask + 1)%iset
    1397        2926 :                jset_new = tasks(itask + 1)%jset
    1398        2926 :                ipgf_new = tasks(itask + 1)%ipgf
    1399        2926 :                jpgf_new = tasks(itask + 1)%jpgf
    1400        2926 :                IF (iset_new .NE. iset .OR. jset_new .NE. jset) THEN
    1401           0 :                   new_set_pair_coming = .TRUE.
    1402             :                END IF
    1403             :             ELSE
    1404             :                ! do not forget the last block
    1405             :                new_set_pair_coming = .TRUE.
    1406        3610 :                atom_pair_done = .TRUE.
    1407             :             END IF
    1408             : 
    1409        4294 :             IF (new_set_pair_coming) THEN
    1410             :                ! Increase lx, ly, lz by one to account for the | r * b >
    1411         684 :                IF (iatom <= jatom) THEN
    1412             :                   ! direction_Or = .false. so that we use rac
    1413             :                   CALL ab_opr(la_max(iset), npgfa(iset), rpgfa(:, iset), 0, &
    1414             :                               lb_max(jset), npgfb(jset), rpgfb(:, jset), 0, &
    1415         456 :                               dab, hab(:, :), rhab(:, :, :), rac, rbc, direction_Or=.FALSE.)
    1416             : 
    1417             :                ELSE
    1418             :                   ! direction_Or = .true. so that we use rac
    1419             :                   CALL ab_opr(lb_max(jset), npgfb(jset), rpgfb(:, jset), 0, &
    1420             :                               la_max(iset), npgfa(iset), rpgfa(:, iset), 0, &
    1421         228 :                               dab, hab(:, :), rhab(:, :, :), rbc, rac, direction_Or=.TRUE.)
    1422             :                END IF
    1423             : 
    1424             :                ! contract the block into h if we're done with the current set pair
    1425        2736 :                DO idir = 1, 3
    1426        2736 :                   IF (iatom <= jatom) THEN
    1427      225720 :                      work = 0._dp
    1428     1752750 :                      work(1:ncoa, 1:nsgfb(jset)) = MATMUL(rhab(1:ncoa, 1:ncob, idir), sphi_b(1:ncob, sgfb:sgfb + nsgfb(jset) - 1))
    1429             :                      h_block(idir)%block(sgfa:sgfa + nsgfa(iset) - 1, sgfb:sgfb + nsgfb(jset) - 1) = &
    1430             :                         h_block(idir)%block(sgfa:sgfa + nsgfa(iset) - 1, sgfb:sgfb + nsgfb(jset) - 1) + &
    1431      148428 :                         MATMUL(TRANSPOSE(sphi_a(1:ncoa, sgfa:sgfa + nsgfa(iset) - 1)), work(1:ncoa, 1:nsgfb(jset)))
    1432             :                   ELSE
    1433      154584 :                      work(1:ncob, 1:nsgfa(iset)) = MATMUL(rhab(1:ncob, 1:ncoa, idir), sphi_a(1:ncoa, sgfa:sgfa + nsgfa(iset) - 1))
    1434             :                      h_block(idir)%block(sgfb:sgfb + nsgfb(jset) - 1, sgfa:sgfa + nsgfa(iset) - 1) = &
    1435             :                         h_block(idir)%block(sgfb:sgfb + nsgfb(jset) - 1, sgfa:sgfa + nsgfa(iset) - 1) + &
    1436       34200 :                         MATMUL(TRANSPOSE(sphi_b(1:ncob, sgfb:sgfb + nsgfb(jset) - 1)), work(1:ncob, 1:nsgfa(iset)))
    1437             :                   END IF
    1438             :                END DO
    1439             :             END IF
    1440             : 
    1441             :          END DO loop_tasks
    1442             :          END DO loop_pairs
    1443             : 
    1444        1292 :          DO idir = 1, 3
    1445        1216 :             CALL dbcsr_finalize(hmat(idir)%matrix)
    1446             :          END DO
    1447             : 
    1448             :       END DO loop_gridlevels
    1449             : 
    1450             :       !   *** Release work storage ***
    1451          76 :       DEALLOCATE (habt, rhab, workt, h_block)
    1452             : 
    1453          76 :       CALL timestop(handle)
    1454             : 
    1455         152 :    END SUBROUTINE integrate_rv_rspace
    1456             : 
    1457             : ! **************************************************************************************************
    1458             : !> \brief Builds the overlap derivative wrt nuclear velocities
    1459             : !>         dS/dV = < mu | r | nu > * (nu - mu)
    1460             : !> \param qs_env ...
    1461             : !> \param matrix_dsdv ...
    1462             : !> \param deltaR ...
    1463             : !> \param rcc ...
    1464             : !> \author Edward Ditler
    1465             : ! **************************************************************************************************
    1466           6 :    SUBROUTINE build_dSdV_matrix(qs_env, matrix_dsdv, deltaR, rcc)
    1467             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1468             :       TYPE(dbcsr_p_type), DIMENSION(:)                   :: matrix_dsdv
    1469             :       REAL(KIND=dp), DIMENSION(:, :)                     :: deltaR
    1470             :       REAL(KIND=dp), DIMENSION(3)                        :: rcc
    1471             : 
    1472             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'build_dSdV_matrix'
    1473             : 
    1474             :       INTEGER                                            :: handle, i
    1475           6 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, my_matrix_dsdv, &
    1476           6 :                                                             my_matrix_dsdv2, my_matrix_mom
    1477             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1478           6 :          POINTER                                         :: sab_all
    1479           6 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1480             : 
    1481           6 :       CALL timeset(routineN, handle)
    1482             : 
    1483           6 :       NULLIFY (my_matrix_mom, my_matrix_dsdv, my_matrix_dsdv2, sab_all, qs_kind_set)
    1484             : 
    1485             :       CALL get_qs_env(qs_env=qs_env, &
    1486             :                       sab_all=sab_all, &
    1487             :                       qs_kind_set=qs_kind_set, &
    1488           6 :                       matrix_ks=matrix_ks)
    1489             : 
    1490             :       ! my_matrix_mom is needed because build_local_moment only works correctly with symmetric matrices
    1491           6 :       CALL dbcsr_allocate_matrix_set(my_matrix_dsdv, 3)
    1492           6 :       CALL dbcsr_allocate_matrix_set(my_matrix_dsdv2, 3)
    1493           6 :       CALL dbcsr_allocate_matrix_set(my_matrix_mom, 3)
    1494             : 
    1495          24 :       DO i = 1, 3
    1496          18 :          ALLOCATE (my_matrix_dsdv(i)%matrix)
    1497          18 :          ALLOCATE (my_matrix_dsdv2(i)%matrix)
    1498          18 :          ALLOCATE (my_matrix_mom(i)%matrix)
    1499             : 
    1500          18 :          CALL dbcsr_copy(my_matrix_dsdv(i)%matrix, matrix_dsdv(i)%matrix)
    1501          18 :          CALL dbcsr_copy(my_matrix_dsdv2(i)%matrix, matrix_dsdv(i)%matrix)
    1502          18 :          CALL dbcsr_copy(my_matrix_mom(i)%matrix, matrix_ks(1)%matrix)
    1503             : 
    1504          18 :          CALL dbcsr_set(my_matrix_dsdv2(i)%matrix, 0.0_dp)
    1505          18 :          CALL dbcsr_set(my_matrix_dsdv(i)%matrix, 0.0_dp)
    1506          18 :          CALL dbcsr_set(my_matrix_mom(i)%matrix, 0.0_dp)
    1507          24 :          CALL dbcsr_set(matrix_dsdv(i)%matrix, 0.0_dp)
    1508             :       END DO
    1509             : 
    1510           6 :       CALL build_dsdv_moments(qs_env, my_matrix_mom, 1, rcc)
    1511             : 
    1512          24 :       DO i = 1, 3
    1513          18 :          CALL dbcsr_desymmetrize(my_matrix_mom(i)%matrix, my_matrix_dsdv(i)%matrix)
    1514          24 :          CALL dbcsr_copy(my_matrix_dsdv2(i)%matrix, my_matrix_dsdv(i)%matrix)
    1515             :       END DO
    1516             : 
    1517             :       ! delta_nu^A <mu|r|nu>
    1518             :       CALL hr_mult_by_delta_3d(my_matrix_dsdv, qs_kind_set, "ORB", sab_all, &
    1519           6 :                                deltaR, direction_Or=.TRUE.)
    1520             :       ! -delta_mu^A <mu|r|nu>
    1521             :       CALL hr_mult_by_delta_3d(my_matrix_dsdv2, qs_kind_set, "ORB", sab_all, &
    1522           6 :                                deltaR, direction_Or=.FALSE.)
    1523          24 :       DO i = 1, 3
    1524          18 :          CALL dbcsr_copy(matrix_dsdv(i)%matrix, my_matrix_dsdv(i)%matrix)
    1525          24 :          CALL dbcsr_add(matrix_dsdv(i)%matrix, my_matrix_dsdv2(i)%matrix, 1.0_dp, -1.0_dp)
    1526             :       END DO
    1527             : 
    1528           6 :       CALL dbcsr_deallocate_matrix_set(my_matrix_dsdv)
    1529           6 :       CALL dbcsr_deallocate_matrix_set(my_matrix_dsdv2)
    1530           6 :       CALL dbcsr_deallocate_matrix_set(my_matrix_mom)
    1531             : 
    1532           6 :       CALL timestop(handle)
    1533             : 
    1534           6 :    END SUBROUTINE build_dSdV_matrix
    1535             : 
    1536             : ! **************************************************************************************************
    1537             : !> \brief Builds the  [Vnl, r] * r from either side
    1538             : !> \param matrix_rv ...
    1539             : !> \param qs_kind_set ...
    1540             : !> \param sab_all ...
    1541             : !> \param sap_ppnl ...
    1542             : !> \param eps_ppnl ...
    1543             : !> \param particle_set ...
    1544             : !> \param cell ...
    1545             : !> \param direction_Or ...
    1546             : !> \author Edward Ditler, Tomas Zimmermann
    1547             : ! **************************************************************************************************
    1548           4 :    SUBROUTINE build_com_rpnl_r(matrix_rv, qs_kind_set, sab_all, sap_ppnl, eps_ppnl, &
    1549             :                                particle_set, cell, direction_Or)
    1550             : 
    1551             :       TYPE(dbcsr_p_type), DIMENSION(:, :)                :: matrix_rv
    1552             :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1553             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1554             :          POINTER                                         :: sab_all, sap_ppnl
    1555             :       REAL(KIND=dp), INTENT(IN)                          :: eps_ppnl
    1556             :       TYPE(particle_type), DIMENSION(:), INTENT(IN), &
    1557             :          POINTER                                         :: particle_set
    1558             :       TYPE(cell_type), POINTER                           :: cell
    1559             :       LOGICAL, INTENT(IN)                                :: direction_Or
    1560             : 
    1561             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'build_com_rpnl_r'
    1562             : 
    1563             :       INTEGER                                            :: handle, i, iab, iac, iatom, ibc, icol, &
    1564             :                                                             ikind, irow, j, jatom, jkind, kac, &
    1565             :                                                             kbc, kkind, na, natom, nb, nkind, np, &
    1566             :                                                             slot
    1567             :       INTEGER, DIMENSION(3)                              :: cell_b
    1568             :       LOGICAL                                            :: found, ppnl_present
    1569             :       REAL(KIND=dp), DIMENSION(3)                        :: rab
    1570           4 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: achint, acint, bchint, bcint
    1571             :       TYPE(alist_type), POINTER                          :: alist_ac, alist_bc
    1572          52 :       TYPE(block_p_type), DIMENSION(3, 3)                :: blocks_rvr
    1573           4 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set
    1574             :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
    1575           4 :       TYPE(sap_int_type), DIMENSION(:), POINTER          :: sap_int
    1576             : 
    1577             : !$    INTEGER(kind=omp_lock_kind), &
    1578           4 : !$       ALLOCATABLE, DIMENSION(:) :: locks
    1579             : !$    INTEGER                                            :: lock_num, hash
    1580             : !$    INTEGER, PARAMETER                                 :: nlock = 501
    1581             : 
    1582           4 :       ppnl_present = ASSOCIATED(sap_ppnl)
    1583           4 :       IF (.NOT. ppnl_present) RETURN
    1584             : 
    1585           4 :       CALL timeset(routineN, handle)
    1586           4 :       nkind = SIZE(qs_kind_set)
    1587           4 :       natom = SIZE(particle_set)
    1588             : 
    1589             :       ! sap_int needs to be shared as multiple threads need to access this
    1590           4 :       NULLIFY (sap_int)
    1591          28 :       ALLOCATE (sap_int(nkind*nkind))
    1592          20 :       DO i = 1, nkind*nkind
    1593          16 :          NULLIFY (sap_int(i)%alist, sap_int(i)%asort, sap_int(i)%aindex)
    1594          20 :          sap_int(i)%nalist = 0
    1595             :       END DO
    1596             : 
    1597             :       ! We put zero as a reference point, because actually in the integrals we need two different ones:
    1598             :       !  < a | (r - R^\lambda_\beta) * [V, r_\alpha - R^\eta_\alpha] | b >
    1599             :       !  The first reference point can be added in a seperate step as the term will be
    1600             :       !        - R^\lambda_\beta * < a | [V, r_\alpha] | b >
    1601             :       !      = + R^\lambda_\beta * < a | [r_\alpha, V] | b >
    1602             :       !  The second reference point is not important, because it disappears in the commutator
    1603             :       CALL build_sap_ints(sap_int, sap_ppnl, qs_kind_set, nder=2, moment_mode=.TRUE., &
    1604           4 :                           particle_set=particle_set, cell=cell, refpoint=[0._dp, 0._dp, 0._dp])
    1605             : 
    1606             :       ! *** Set up a sorting index
    1607           4 :       CALL sap_sort(sap_int)
    1608             : 
    1609          20 :       ALLOCATE (basis_set(nkind))
    1610          12 :       DO ikind = 1, nkind
    1611           8 :          CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set)
    1612          12 :          IF (ASSOCIATED(orb_basis_set)) THEN
    1613           8 :             basis_set(ikind)%gto_basis_set => orb_basis_set
    1614             :          ELSE
    1615           0 :             NULLIFY (basis_set(ikind)%gto_basis_set)
    1616             :          END IF
    1617             :       END DO
    1618             : 
    1619             :       ! *** All integrals needed have been calculated and stored in sap_int
    1620             :       ! *** We now calculate the commutator matrix elements
    1621             : 
    1622             : !$OMP PARALLEL &
    1623             : !$OMP DEFAULT (NONE) &
    1624             : !$OMP SHARED  (basis_set, matrix_rv, direction_Or, &
    1625             : !$OMP          sap_int, nkind, eps_ppnl, locks, sab_all) &
    1626             : !$OMP PRIVATE (ikind, jkind, iatom, jatom, cell_b, rab, &
    1627             : !$OMP          iab, irow, icol, blocks_rvr, &
    1628             : !$OMP          found, iac, ibc, alist_ac, alist_bc, &
    1629             : !$OMP          na, np, nb, kkind, kac, kbc, i, j, &
    1630           4 : !$OMP          hash, natom, acint, bcint, achint, bchint)
    1631             : 
    1632             : !$OMP SINGLE
    1633             : !$    ALLOCATE (locks(nlock))
    1634             : !$OMP END SINGLE
    1635             : 
    1636             : !$OMP DO
    1637             : !$    DO lock_num = 1, nlock
    1638             : !$       call omp_init_lock(locks(lock_num))
    1639             : !$    END DO
    1640             : !$OMP END DO
    1641             : 
    1642             : !$OMP DO SCHEDULE(GUIDED)
    1643             : 
    1644             :       DO slot = 1, sab_all(1)%nl_size
    1645             : 
    1646             :          ikind = sab_all(1)%nlist_task(slot)%ikind
    1647             :          jkind = sab_all(1)%nlist_task(slot)%jkind
    1648             :          iatom = sab_all(1)%nlist_task(slot)%iatom
    1649             :          jatom = sab_all(1)%nlist_task(slot)%jatom
    1650             :          cell_b(:) = sab_all(1)%nlist_task(slot)%cell(:)
    1651             :          rab(1:3) = sab_all(1)%nlist_task(slot)%r(1:3)
    1652             : 
    1653             :          IF (.NOT. ASSOCIATED(basis_set(ikind)%gto_basis_set)) CYCLE
    1654             :          IF (.NOT. ASSOCIATED(basis_set(jkind)%gto_basis_set)) CYCLE
    1655             :          iab = ikind + nkind*(jkind - 1)
    1656             : 
    1657             :          ! *** Create matrix blocks for a new matrix block column ***
    1658             :          irow = iatom
    1659             :          icol = jatom
    1660             :          DO i = 1, 3
    1661             :             DO j = 1, 3
    1662             :                ! t_alpha = MOD(i - 1, 3) + 1
    1663             :                ! t_beta = FLOOR(REAL(i - 1, dp)/3._dp) + 1
    1664             : 
    1665             :                CALL dbcsr_get_block_p(matrix_rv(i, j)%matrix, irow, icol, blocks_rvr(i, j)%block, found)
    1666             :                CPASSERT(found)
    1667             :             END DO
    1668             :          END DO
    1669             : 
    1670             :          ! loop over all kinds for projector atom
    1671             :          DO kkind = 1, nkind
    1672             :             iac = ikind + nkind*(kkind - 1)
    1673             :             ibc = jkind + nkind*(kkind - 1)
    1674             :             IF (.NOT. ASSOCIATED(sap_int(iac)%alist)) CYCLE
    1675             :             IF (.NOT. ASSOCIATED(sap_int(ibc)%alist)) CYCLE
    1676             :             CALL get_alist(sap_int(iac), alist_ac, iatom)
    1677             :             CALL get_alist(sap_int(ibc), alist_bc, jatom)
    1678             :             IF (.NOT. ASSOCIATED(alist_ac)) CYCLE
    1679             :             IF (.NOT. ASSOCIATED(alist_bc)) CYCLE
    1680             :             DO kac = 1, alist_ac%nclist
    1681             :                DO kbc = 1, alist_bc%nclist
    1682             :                   IF (alist_ac%clist(kac)%catom /= alist_bc%clist(kbc)%catom) CYCLE
    1683             : 
    1684             :                   ! Some documention, considering the C1 O1 O2 molecule
    1685             :                   ! The integrals are <a|p>
    1686             :                   ! sap_int(1:2, 1:2) -> [(a=C, p=C), (a=C, p=O), (a=O, p=C), (a=O, p=0)]
    1687             :                   ! the (a=O, p=C) entry has an alist
    1688             :                   !  alist has two elements: O1, O2
    1689             :                   !     alist(O1) -> clist(C1)%acint are the integrals
    1690             :                   !     alist(O2) -> clist(C1)%acint are the integrals
    1691             : 
    1692             :                   IF (ALL(cell_b + alist_bc%clist(kbc)%cell - alist_ac%clist(kac)%cell == 0)) THEN
    1693             :                      IF (alist_ac%clist(kac)%maxac*alist_bc%clist(kbc)%maxach < eps_ppnl) CYCLE
    1694             :                      acint => alist_ac%clist(kac)%acint
    1695             :                      bcint => alist_bc%clist(kbc)%acint
    1696             :                      achint => alist_ac%clist(kac)%achint
    1697             :                      bchint => alist_bc%clist(kbc)%achint
    1698             :                      na = SIZE(acint, 1)
    1699             :                      np = SIZE(acint, 2)
    1700             :                      nb = SIZE(bcint, 1)
    1701             : !$                   hash = MOD((iatom - 1)*natom + jatom, nlock) + 1
    1702             : !$                   CALL omp_set_lock(locks(hash))
    1703             : 
    1704             :                      ! Template:
    1705             :                      ! blocks_rv(1)%block(1:na, 1:nb) = blocks_rv(1)%block(1:na, 1:nb) + &
    1706             :                      !                                  MATMUL(achint(1:na, 1:np, 2), TRANSPOSE(bcint(1:nb, 1:np, 1))) ! xV
    1707             :                      ! 1, x, y, z, xx, xy, xz, yy, yz, zz
    1708             :                      IF (direction_Or) THEN
    1709             :                         ! (Vnl*r_alpha)*r_beta
    1710             : 
    1711             :                         ! This part is symmetric because [r_beta, r_alpha] = 0
    1712             :                         ! matrix_rvr(x, gamma) += <mu|p>h_ij * <p|x*gamma|nu>
    1713             :                         blocks_rvr(1, 1)%block(1:na, 1:nb) = blocks_rvr(1, 1)%block(1:na, 1:nb) + &
    1714             :                                                              MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_xx)))
    1715             :                         blocks_rvr(1, 2)%block(1:na, 1:nb) = blocks_rvr(1, 2)%block(1:na, 1:nb) + &
    1716             :                                                              MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_xy)))
    1717             :                         blocks_rvr(1, 3)%block(1:na, 1:nb) = blocks_rvr(1, 3)%block(1:na, 1:nb) + &
    1718             :                                                              MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_xz)))
    1719             : 
    1720             :                         ! matrix_rvr(y, gamma) += <mu|p>h_ij * <p|y*gamma|nu>
    1721             :                         blocks_rvr(2, 1)%block(1:na, 1:nb) = blocks_rvr(2, 1)%block(1:na, 1:nb) + &
    1722             :                                                              MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_xy)))
    1723             :                         blocks_rvr(2, 2)%block(1:na, 1:nb) = blocks_rvr(2, 2)%block(1:na, 1:nb) + &
    1724             :                                                              MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_yy)))
    1725             :                         blocks_rvr(2, 3)%block(1:na, 1:nb) = blocks_rvr(2, 3)%block(1:na, 1:nb) + &
    1726             :                                                              MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_yz)))
    1727             : 
    1728             :                         ! matrix_rvr(z, gamma) += <mu|p>h_ij * <p|z*gamma|nu>
    1729             :                         blocks_rvr(3, 1)%block(1:na, 1:nb) = blocks_rvr(3, 1)%block(1:na, 1:nb) + &
    1730             :                                                              MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_xz)))
    1731             :                         blocks_rvr(3, 2)%block(1:na, 1:nb) = blocks_rvr(3, 2)%block(1:na, 1:nb) + &
    1732             :                                                              MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_yz)))
    1733             :                         blocks_rvr(3, 3)%block(1:na, 1:nb) = blocks_rvr(3, 3)%block(1:na, 1:nb) + &
    1734             :                                                              MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_zz)))
    1735             : 
    1736             :                         ! -(r_alpha*Vnl)*r_beta
    1737             :                         ! matrix_rvr(x, gamma) += <mu|gamma|p>h_ij * <p|x|nu>
    1738             :                         blocks_rvr(1, 1)%block(1:na, 1:nb) = blocks_rvr(1, 1)%block(1:na, 1:nb) - &
    1739             :                                                              MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
    1740             :                         blocks_rvr(1, 2)%block(1:na, 1:nb) = blocks_rvr(1, 2)%block(1:na, 1:nb) - &
    1741             :                                                              MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
    1742             :                         blocks_rvr(1, 3)%block(1:na, 1:nb) = blocks_rvr(1, 3)%block(1:na, 1:nb) - &
    1743             :                                                              MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
    1744             : 
    1745             :                         ! matrix_rvr(y, gamma) += <mu|gamma|p>h_ij * <p|y|nu>
    1746             :                         blocks_rvr(2, 1)%block(1:na, 1:nb) = blocks_rvr(2, 1)%block(1:na, 1:nb) - &
    1747             :                                                              MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
    1748             :                         blocks_rvr(2, 2)%block(1:na, 1:nb) = blocks_rvr(2, 2)%block(1:na, 1:nb) - &
    1749             :                                                              MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
    1750             :                         blocks_rvr(2, 3)%block(1:na, 1:nb) = blocks_rvr(2, 3)%block(1:na, 1:nb) - &
    1751             :                                                              MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
    1752             : 
    1753             :                         ! matrix_rvr(z, gamma) += <mu|gamma|p>h_ij * <p|z|nu>
    1754             :                         blocks_rvr(3, 1)%block(1:na, 1:nb) = blocks_rvr(3, 1)%block(1:na, 1:nb) - &
    1755             :                                                              MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
    1756             :                         blocks_rvr(3, 2)%block(1:na, 1:nb) = blocks_rvr(3, 2)%block(1:na, 1:nb) - &
    1757             :                                                              MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
    1758             :                         blocks_rvr(3, 3)%block(1:na, 1:nb) = blocks_rvr(3, 3)%block(1:na, 1:nb) - &
    1759             :                                                              MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
    1760             : 
    1761             :                         ! This means that we have
    1762             :                         ! blocks_rvr(1:3, 1:3) = blocks_rvr(alpha, beta)
    1763             :                      ELSE
    1764             :                         ! r_beta*(Vnl*r_alpha)
    1765             :                         blocks_rvr(1, 1)%block(1:na, 1:nb) = blocks_rvr(1, 1)%block(1:na, 1:nb) + &
    1766             :                                                              MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
    1767             :                         blocks_rvr(1, 2)%block(1:na, 1:nb) = blocks_rvr(1, 2)%block(1:na, 1:nb) + &
    1768             :                                                              MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
    1769             :                         blocks_rvr(1, 3)%block(1:na, 1:nb) = blocks_rvr(1, 3)%block(1:na, 1:nb) + &
    1770             :                                                              MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
    1771             : 
    1772             :                         blocks_rvr(2, 1)%block(1:na, 1:nb) = blocks_rvr(2, 1)%block(1:na, 1:nb) + &
    1773             :                                                              MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
    1774             :                         blocks_rvr(2, 2)%block(1:na, 1:nb) = blocks_rvr(2, 2)%block(1:na, 1:nb) + &
    1775             :                                                              MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
    1776             :                         blocks_rvr(2, 3)%block(1:na, 1:nb) = blocks_rvr(2, 3)%block(1:na, 1:nb) + &
    1777             :                                                              MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
    1778             : 
    1779             :                         blocks_rvr(3, 1)%block(1:na, 1:nb) = blocks_rvr(3, 1)%block(1:na, 1:nb) + &
    1780             :                                                              MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
    1781             :                         blocks_rvr(3, 2)%block(1:na, 1:nb) = blocks_rvr(3, 2)%block(1:na, 1:nb) + &
    1782             :                                                              MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
    1783             :                         blocks_rvr(3, 3)%block(1:na, 1:nb) = blocks_rvr(3, 3)%block(1:na, 1:nb) + &
    1784             :                                                              MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
    1785             : 
    1786             :                         ! -r_beta*(r_alpha*Vnl)
    1787             :                         blocks_rvr(1, 1)%block(1:na, 1:nb) = blocks_rvr(1, 1)%block(1:na, 1:nb) - &
    1788             :                                                              MATMUL(achint(1:na, 1:np, bi_xx), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    1789             :                         blocks_rvr(1, 2)%block(1:na, 1:nb) = blocks_rvr(1, 2)%block(1:na, 1:nb) - &
    1790             :                                                              MATMUL(achint(1:na, 1:np, bi_xy), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    1791             :                         blocks_rvr(1, 3)%block(1:na, 1:nb) = blocks_rvr(1, 3)%block(1:na, 1:nb) - &
    1792             :                                                              MATMUL(achint(1:na, 1:np, bi_xz), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    1793             : 
    1794             :                         blocks_rvr(2, 1)%block(1:na, 1:nb) = blocks_rvr(2, 1)%block(1:na, 1:nb) - &
    1795             :                                                              MATMUL(achint(1:na, 1:np, bi_xy), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    1796             :                         blocks_rvr(2, 2)%block(1:na, 1:nb) = blocks_rvr(2, 2)%block(1:na, 1:nb) - &
    1797             :                                                              MATMUL(achint(1:na, 1:np, bi_yy), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    1798             :                         blocks_rvr(2, 3)%block(1:na, 1:nb) = blocks_rvr(2, 3)%block(1:na, 1:nb) - &
    1799             :                                                              MATMUL(achint(1:na, 1:np, bi_yz), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    1800             : 
    1801             :                         blocks_rvr(3, 1)%block(1:na, 1:nb) = blocks_rvr(3, 1)%block(1:na, 1:nb) - &
    1802             :                                                              MATMUL(achint(1:na, 1:np, bi_xz), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    1803             :                         blocks_rvr(3, 2)%block(1:na, 1:nb) = blocks_rvr(3, 2)%block(1:na, 1:nb) - &
    1804             :                                                              MATMUL(achint(1:na, 1:np, bi_yz), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    1805             :                         blocks_rvr(3, 3)%block(1:na, 1:nb) = blocks_rvr(3, 3)%block(1:na, 1:nb) - &
    1806             :                                                              MATMUL(achint(1:na, 1:np, bi_zz), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    1807             :                      END IF
    1808             : 
    1809             : !$                   CALL omp_unset_lock(locks(hash))
    1810             :                      EXIT ! We have found a match and there can be only one single match
    1811             :                   END IF
    1812             :                END DO
    1813             :             END DO
    1814             :          END DO
    1815             :          DO i = 1, 3
    1816             :             NULLIFY (blocks_rvr(i, 1)%block)
    1817             :             NULLIFY (blocks_rvr(i, 2)%block)
    1818             :             NULLIFY (blocks_rvr(i, 3)%block)
    1819             :          END DO
    1820             :       END DO
    1821             : 
    1822             : !$OMP DO
    1823             : !$    DO lock_num = 1, nlock
    1824             : !$       call omp_destroy_lock(locks(lock_num))
    1825             : !$    END DO
    1826             : !$OMP END DO
    1827             : 
    1828             : !$OMP SINGLE
    1829             : !$    DEALLOCATE (locks)
    1830             : !$OMP END SINGLE NOWAIT
    1831             : 
    1832             : !$OMP END PARALLEL
    1833             : 
    1834           4 :       CALL release_sap_int(sap_int)
    1835             : 
    1836           4 :       DEALLOCATE (basis_set)
    1837             : 
    1838           4 :       CALL timestop(handle)
    1839             : 
    1840          12 :    END SUBROUTINE build_com_rpnl_r
    1841             : 
    1842             : ! **************************************************************************************************
    1843             : !> \brief Calculate the double commutator [[Vnl, r], r]
    1844             : !> \param matrix_rv ...
    1845             : !> \param qs_kind_set ...
    1846             : !> \param sab_orb ...
    1847             : !> \param sap_ppnl ...
    1848             : !> \param eps_ppnl ...
    1849             : !> \param particle_set ...
    1850             : !> \param pseudoatom Only consider pseudopotentials on atom lambda
    1851             : !> \author Edward Ditler
    1852             : ! **************************************************************************************************
    1853           6 :    SUBROUTINE build_dcom_rpnl(matrix_rv, qs_kind_set, sab_orb, sap_ppnl, eps_ppnl, particle_set, pseudoatom)
    1854             : 
    1855             :       TYPE(dbcsr_p_type), DIMENSION(:, :)                :: matrix_rv
    1856             :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1857             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1858             :          POINTER                                         :: sab_orb, sap_ppnl
    1859             :       REAL(KIND=dp), INTENT(IN)                          :: eps_ppnl
    1860             :       TYPE(particle_type), DIMENSION(:), INTENT(IN), &
    1861             :          POINTER                                         :: particle_set
    1862             :       INTEGER, INTENT(IN)                                :: pseudoatom
    1863             : 
    1864             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'build_dcom_rpnl'
    1865             : 
    1866             :       INTEGER                                            :: handle, i, iab, iac, iatom, ibc, icol, &
    1867             :                                                             ikind, irow, j, jatom, jkind, kac, &
    1868             :                                                             kbc, kkind, na, natom, nb, nkind, np, &
    1869             :                                                             slot
    1870             :       INTEGER, DIMENSION(3)                              :: cell_b
    1871             :       LOGICAL                                            :: found, ppnl_present
    1872             :       REAL(KIND=dp), DIMENSION(3)                        :: rab
    1873           6 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: achint, acint, bchint, bcint
    1874             :       TYPE(alist_type), POINTER                          :: alist_ac, alist_bc
    1875          78 :       TYPE(block_p_type), DIMENSION(3, 3)                :: blocks_rv
    1876           6 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set
    1877             :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
    1878           6 :       TYPE(sap_int_type), DIMENSION(:), POINTER          :: sap_int
    1879             : 
    1880             : !$    INTEGER(kind=omp_lock_kind), &
    1881           6 : !$       ALLOCATABLE, DIMENSION(:) :: locks
    1882             : !$    INTEGER                                            :: lock_num, hash
    1883             : !$    INTEGER, PARAMETER                                 :: nlock = 501
    1884             : 
    1885           6 :       ppnl_present = ASSOCIATED(sap_ppnl)
    1886           6 :       IF (.NOT. ppnl_present) RETURN
    1887             : 
    1888           6 :       CALL timeset(routineN, handle)
    1889           6 :       nkind = SIZE(qs_kind_set)
    1890           6 :       natom = SIZE(particle_set)
    1891             : 
    1892             :       ! sap_int needs to be shared as multiple threads need to access this
    1893           6 :       NULLIFY (sap_int)
    1894          42 :       ALLOCATE (sap_int(nkind*nkind))
    1895          30 :       DO i = 1, nkind*nkind
    1896          24 :          NULLIFY (sap_int(i)%alist, sap_int(i)%asort, sap_int(i)%aindex)
    1897          30 :          sap_int(i)%nalist = 0
    1898             :       END DO
    1899             : 
    1900             :       ! "nder" in moment_mode is "order"
    1901             :       CALL build_sap_ints(sap_int, sap_ppnl, qs_kind_set, nder=2, moment_mode=.TRUE., &
    1902           6 :                           particle_set=particle_set, pseudoatom=pseudoatom)
    1903             : 
    1904             :       ! *** Set up a sorting index
    1905           6 :       CALL sap_sort(sap_int)
    1906             : 
    1907          30 :       ALLOCATE (basis_set(nkind))
    1908          18 :       DO ikind = 1, nkind
    1909          12 :          CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set)
    1910          18 :          IF (ASSOCIATED(orb_basis_set)) THEN
    1911          12 :             basis_set(ikind)%gto_basis_set => orb_basis_set
    1912             :          ELSE
    1913           0 :             NULLIFY (basis_set(ikind)%gto_basis_set)
    1914             :          END IF
    1915             :       END DO
    1916             : 
    1917             :       ! *** All integrals needed have been calculated and stored in sap_int
    1918             :       ! *** We now calculate the commutator matrix elements
    1919             : 
    1920             : !$OMP PARALLEL &
    1921             : !$OMP DEFAULT (NONE) &
    1922             : !$OMP SHARED  (basis_set, matrix_rv, &
    1923             : !$OMP          sap_int, nkind, eps_ppnl, locks, sab_orb) &
    1924             : !$OMP PRIVATE (ikind, jkind, iatom, jatom, cell_b, rab, &
    1925             : !$OMP          iab, irow, icol, blocks_rv, &
    1926             : !$OMP          found, iac, ibc, alist_ac, alist_bc, &
    1927             : !$OMP          na, np, nb, kkind, kac, kbc, i, j, &
    1928           6 : !$OMP          hash, natom, acint, bcint, achint, bchint)
    1929             : 
    1930             : !$OMP SINGLE
    1931             : !$    ALLOCATE (locks(nlock))
    1932             : !$OMP END SINGLE
    1933             : 
    1934             : !$OMP DO
    1935             : !$    DO lock_num = 1, nlock
    1936             : !$       call omp_init_lock(locks(lock_num))
    1937             : !$    END DO
    1938             : !$OMP END DO
    1939             : 
    1940             : !$OMP DO SCHEDULE(GUIDED)
    1941             : 
    1942             :       DO slot = 1, sab_orb(1)%nl_size
    1943             : 
    1944             :          ikind = sab_orb(1)%nlist_task(slot)%ikind
    1945             :          jkind = sab_orb(1)%nlist_task(slot)%jkind
    1946             :          iatom = sab_orb(1)%nlist_task(slot)%iatom
    1947             :          jatom = sab_orb(1)%nlist_task(slot)%jatom
    1948             :          cell_b(:) = sab_orb(1)%nlist_task(slot)%cell(:)
    1949             :          rab(1:3) = sab_orb(1)%nlist_task(slot)%r(1:3)
    1950             : 
    1951             :          IF (.NOT. ASSOCIATED(basis_set(ikind)%gto_basis_set)) CYCLE
    1952             :          IF (.NOT. ASSOCIATED(basis_set(jkind)%gto_basis_set)) CYCLE
    1953             :          iab = ikind + nkind*(jkind - 1)
    1954             : 
    1955             :          ! *** Create matrix blocks for a new matrix block column ***
    1956             :          IF (iatom <= jatom) THEN
    1957             :             irow = iatom
    1958             :             icol = jatom
    1959             :          ELSE
    1960             :             irow = jatom
    1961             :             icol = iatom
    1962             :          END IF
    1963             : 
    1964             :          DO i = 1, 3
    1965             :             DO j = 1, 3
    1966             :                CALL dbcsr_get_block_p(matrix_rv(i, j)%matrix, irow, icol, blocks_rv(i, j)%block, found)
    1967             :                blocks_rv(i, j)%block = 0._dp
    1968             :                CPASSERT(found)
    1969             :             END DO
    1970             :          END DO
    1971             : 
    1972             :          ! loop over all kinds for projector atom
    1973             :          DO kkind = 1, nkind
    1974             :             iac = ikind + nkind*(kkind - 1)
    1975             :             ibc = jkind + nkind*(kkind - 1)
    1976             :             IF (.NOT. ASSOCIATED(sap_int(iac)%alist)) CYCLE
    1977             :             IF (.NOT. ASSOCIATED(sap_int(ibc)%alist)) CYCLE
    1978             :             CALL get_alist(sap_int(iac), alist_ac, iatom)
    1979             :             CALL get_alist(sap_int(ibc), alist_bc, jatom)
    1980             :             IF (.NOT. ASSOCIATED(alist_ac)) CYCLE
    1981             :             IF (.NOT. ASSOCIATED(alist_bc)) CYCLE
    1982             :             DO kac = 1, alist_ac%nclist
    1983             :                DO kbc = 1, alist_bc%nclist
    1984             :                   IF (alist_ac%clist(kac)%catom /= alist_bc%clist(kbc)%catom) CYCLE
    1985             :                   IF (ALL(cell_b + alist_bc%clist(kbc)%cell - alist_ac%clist(kac)%cell == 0)) THEN
    1986             :                      IF (alist_ac%clist(kac)%maxac*alist_bc%clist(kbc)%maxach < eps_ppnl) CYCLE
    1987             :                      acint => alist_ac%clist(kac)%acint
    1988             :                      bcint => alist_bc%clist(kbc)%acint
    1989             :                      achint => alist_ac%clist(kac)%achint
    1990             :                      bchint => alist_bc%clist(kbc)%achint
    1991             :                      na = SIZE(acint, 1)
    1992             :                      np = SIZE(acint, 2)
    1993             :                      nb = SIZE(bcint, 1)
    1994             : !$                   hash = MOD((iatom - 1)*natom + jatom, nlock) + 1
    1995             : !$                   CALL omp_set_lock(locks(hash))
    1996             :                      ! Template:
    1997             :                      ! blocks_rv(1)%block(1:na, 1:nb) = blocks_rv(1)%block(1:na, 1:nb) + &
    1998             :                      !                                  MATMUL(achint(1:na, 1:np, 2), TRANSPOSE(bcint(1:nb, 1:np, 1))) ! xV
    1999             :                      IF (iatom <= jatom) THEN
    2000             :                         ! r_alpha*Vnl*r_beta
    2001             :                         blocks_rv(1, 1)%block(1:na, 1:nb) = blocks_rv(1, 1)%block(1:na, 1:nb) + &
    2002             :                                                             MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
    2003             : 
    2004             :                         blocks_rv(1, 2)%block(1:na, 1:nb) = blocks_rv(1, 2)%block(1:na, 1:nb) + &
    2005             :                                                             MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
    2006             : 
    2007             :                         blocks_rv(1, 3)%block(1:na, 1:nb) = blocks_rv(1, 3)%block(1:na, 1:nb) + &
    2008             :                                                             MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
    2009             : 
    2010             :                         blocks_rv(2, 1)%block(1:na, 1:nb) = blocks_rv(2, 1)%block(1:na, 1:nb) + &
    2011             :                                                             MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
    2012             : 
    2013             :                         blocks_rv(2, 2)%block(1:na, 1:nb) = blocks_rv(2, 2)%block(1:na, 1:nb) + &
    2014             :                                                             MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
    2015             : 
    2016             :                         blocks_rv(2, 3)%block(1:na, 1:nb) = blocks_rv(2, 3)%block(1:na, 1:nb) + &
    2017             :                                                             MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
    2018             : 
    2019             :                         blocks_rv(3, 1)%block(1:na, 1:nb) = blocks_rv(3, 1)%block(1:na, 1:nb) + &
    2020             :                                                             MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
    2021             : 
    2022             :                         blocks_rv(3, 2)%block(1:na, 1:nb) = blocks_rv(3, 2)%block(1:na, 1:nb) + &
    2023             :                                                             MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
    2024             : 
    2025             :                         blocks_rv(3, 3)%block(1:na, 1:nb) = blocks_rv(3, 3)%block(1:na, 1:nb) + &
    2026             :                                                             MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
    2027             : 
    2028             :                         ! -r_alpha*r_beta*Vnl
    2029             :                         blocks_rv(1, 1)%block(1:na, 1:nb) = blocks_rv(1, 1)%block(1:na, 1:nb) - &
    2030             :                                                             MATMUL(achint(1:na, 1:np, bi_xx), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    2031             : 
    2032             :                         blocks_rv(1, 2)%block(1:na, 1:nb) = blocks_rv(1, 2)%block(1:na, 1:nb) - &
    2033             :                                                             MATMUL(achint(1:na, 1:np, bi_xy), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    2034             : 
    2035             :                         blocks_rv(1, 3)%block(1:na, 1:nb) = blocks_rv(1, 3)%block(1:na, 1:nb) - &
    2036             :                                                             MATMUL(achint(1:na, 1:np, bi_xz), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    2037             : 
    2038             :                         blocks_rv(2, 1)%block(1:na, 1:nb) = blocks_rv(2, 1)%block(1:na, 1:nb) - &
    2039             :                                                             MATMUL(achint(1:na, 1:np, bi_xy), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    2040             : 
    2041             :                         blocks_rv(2, 2)%block(1:na, 1:nb) = blocks_rv(2, 2)%block(1:na, 1:nb) - &
    2042             :                                                             MATMUL(achint(1:na, 1:np, bi_yy), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    2043             : 
    2044             :                         blocks_rv(2, 3)%block(1:na, 1:nb) = blocks_rv(2, 3)%block(1:na, 1:nb) - &
    2045             :                                                             MATMUL(achint(1:na, 1:np, bi_yz), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    2046             : 
    2047             :                         blocks_rv(3, 1)%block(1:na, 1:nb) = blocks_rv(3, 1)%block(1:na, 1:nb) - &
    2048             :                                                             MATMUL(achint(1:na, 1:np, bi_xz), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    2049             : 
    2050             :                         blocks_rv(3, 2)%block(1:na, 1:nb) = blocks_rv(3, 2)%block(1:na, 1:nb) - &
    2051             :                                                             MATMUL(achint(1:na, 1:np, bi_yz), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    2052             : 
    2053             :                         blocks_rv(3, 3)%block(1:na, 1:nb) = blocks_rv(3, 3)%block(1:na, 1:nb) - &
    2054             :                                                             MATMUL(achint(1:na, 1:np, bi_zz), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    2055             : 
    2056             :                         ! -Vnl*r_beta*r_alpha
    2057             :                         blocks_rv(1, 1)%block(1:na, 1:nb) = blocks_rv(1, 1)%block(1:na, 1:nb) - &
    2058             :                                                             MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_xx)))
    2059             : 
    2060             :                         blocks_rv(1, 2)%block(1:na, 1:nb) = blocks_rv(1, 2)%block(1:na, 1:nb) - &
    2061             :                                                             MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_xy)))
    2062             : 
    2063             :                         blocks_rv(1, 3)%block(1:na, 1:nb) = blocks_rv(1, 3)%block(1:na, 1:nb) - &
    2064             :                                                             MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_xz)))
    2065             : 
    2066             :                         blocks_rv(2, 1)%block(1:na, 1:nb) = blocks_rv(2, 1)%block(1:na, 1:nb) - &
    2067             :                                                             MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_xy)))
    2068             : 
    2069             :                         blocks_rv(2, 2)%block(1:na, 1:nb) = blocks_rv(2, 2)%block(1:na, 1:nb) - &
    2070             :                                                             MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_yy)))
    2071             : 
    2072             :                         blocks_rv(2, 3)%block(1:na, 1:nb) = blocks_rv(2, 3)%block(1:na, 1:nb) - &
    2073             :                                                             MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_yz)))
    2074             : 
    2075             :                         blocks_rv(3, 1)%block(1:na, 1:nb) = blocks_rv(3, 1)%block(1:na, 1:nb) - &
    2076             :                                                             MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_xz)))
    2077             : 
    2078             :                         blocks_rv(3, 2)%block(1:na, 1:nb) = blocks_rv(3, 2)%block(1:na, 1:nb) - &
    2079             :                                                             MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_yz)))
    2080             : 
    2081             :                         blocks_rv(3, 3)%block(1:na, 1:nb) = blocks_rv(3, 3)%block(1:na, 1:nb) - &
    2082             :                                                             MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_zz)))
    2083             : 
    2084             :                         ! +r_beta*Vnl*r_alpha
    2085             :                         blocks_rv(1, 1)%block(1:na, 1:nb) = blocks_rv(1, 1)%block(1:na, 1:nb) + &
    2086             :                                                             MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
    2087             : 
    2088             :                         blocks_rv(1, 2)%block(1:na, 1:nb) = blocks_rv(1, 2)%block(1:na, 1:nb) + &
    2089             :                                                             MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
    2090             : 
    2091             :                         blocks_rv(1, 3)%block(1:na, 1:nb) = blocks_rv(1, 3)%block(1:na, 1:nb) + &
    2092             :                                                             MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
    2093             : 
    2094             :                         blocks_rv(2, 1)%block(1:na, 1:nb) = blocks_rv(2, 1)%block(1:na, 1:nb) + &
    2095             :                                                             MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
    2096             : 
    2097             :                         blocks_rv(2, 2)%block(1:na, 1:nb) = blocks_rv(2, 2)%block(1:na, 1:nb) + &
    2098             :                                                             MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
    2099             : 
    2100             :                         blocks_rv(2, 3)%block(1:na, 1:nb) = blocks_rv(2, 3)%block(1:na, 1:nb) + &
    2101             :                                                             MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
    2102             : 
    2103             :                         blocks_rv(3, 1)%block(1:na, 1:nb) = blocks_rv(3, 1)%block(1:na, 1:nb) + &
    2104             :                                                             MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
    2105             : 
    2106             :                         blocks_rv(3, 2)%block(1:na, 1:nb) = blocks_rv(3, 2)%block(1:na, 1:nb) + &
    2107             :                                                             MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
    2108             : 
    2109             :                         blocks_rv(3, 3)%block(1:na, 1:nb) = blocks_rv(3, 3)%block(1:na, 1:nb) + &
    2110             :                                                             MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
    2111             :                      ELSE
    2112             :                         ! r_alpha*Vnl*r_beta
    2113             :                         blocks_rv(1, 1)%block(1:nb, 1:na) = blocks_rv(1, 1)%block(1:nb, 1:na) + &
    2114             :                                                             MATMUL(bchint(1:nb, 1:np, bi_x), TRANSPOSE(acint(1:na, 1:np, bi_x)))
    2115             : 
    2116             :                         blocks_rv(1, 2)%block(1:nb, 1:na) = blocks_rv(1, 2)%block(1:nb, 1:na) + &
    2117             :                                                             MATMUL(bchint(1:nb, 1:np, bi_x), TRANSPOSE(acint(1:na, 1:np, bi_y)))
    2118             : 
    2119             :                         blocks_rv(1, 3)%block(1:nb, 1:na) = blocks_rv(1, 3)%block(1:nb, 1:na) + &
    2120             :                                                             MATMUL(bchint(1:nb, 1:np, bi_x), TRANSPOSE(acint(1:na, 1:np, bi_z)))
    2121             : 
    2122             :                         blocks_rv(2, 1)%block(1:nb, 1:na) = blocks_rv(2, 1)%block(1:nb, 1:na) + &
    2123             :                                                             MATMUL(bchint(1:nb, 1:np, bi_y), TRANSPOSE(acint(1:na, 1:np, bi_x)))
    2124             : 
    2125             :                         blocks_rv(2, 2)%block(1:nb, 1:na) = blocks_rv(2, 2)%block(1:nb, 1:na) + &
    2126             :                                                             MATMUL(bchint(1:nb, 1:np, bi_y), TRANSPOSE(acint(1:na, 1:np, bi_y)))
    2127             : 
    2128             :                         blocks_rv(2, 3)%block(1:nb, 1:na) = blocks_rv(2, 3)%block(1:nb, 1:na) + &
    2129             :                                                             MATMUL(bchint(1:nb, 1:np, bi_y), TRANSPOSE(acint(1:na, 1:np, bi_z)))
    2130             : 
    2131             :                         blocks_rv(3, 1)%block(1:nb, 1:na) = blocks_rv(3, 1)%block(1:nb, 1:na) + &
    2132             :                                                             MATMUL(bchint(1:nb, 1:np, bi_z), TRANSPOSE(acint(1:na, 1:np, bi_x)))
    2133             : 
    2134             :                         blocks_rv(3, 2)%block(1:nb, 1:na) = blocks_rv(3, 2)%block(1:nb, 1:na) + &
    2135             :                                                             MATMUL(bchint(1:nb, 1:np, bi_z), TRANSPOSE(acint(1:na, 1:np, bi_y)))
    2136             : 
    2137             :                         blocks_rv(3, 3)%block(1:nb, 1:na) = blocks_rv(3, 3)%block(1:nb, 1:na) + &
    2138             :                                                             MATMUL(bchint(1:nb, 1:np, bi_z), TRANSPOSE(acint(1:na, 1:np, bi_z)))
    2139             : 
    2140             :                         ! -r_alpha*r_beta*Vnl
    2141             :                         blocks_rv(1, 1)%block(1:nb, 1:na) = blocks_rv(1, 1)%block(1:nb, 1:na) - &
    2142             :                                                             MATMUL(bchint(1:nb, 1:np, bi_xx), TRANSPOSE(acint(1:na, 1:np, bi_1)))
    2143             : 
    2144             :                         blocks_rv(1, 2)%block(1:nb, 1:na) = blocks_rv(1, 2)%block(1:nb, 1:na) - &
    2145             :                                                             MATMUL(bchint(1:nb, 1:np, bi_xy), TRANSPOSE(acint(1:na, 1:np, bi_1)))
    2146             : 
    2147             :                         blocks_rv(1, 3)%block(1:nb, 1:na) = blocks_rv(1, 3)%block(1:nb, 1:na) - &
    2148             :                                                             MATMUL(bchint(1:nb, 1:np, bi_xz), TRANSPOSE(acint(1:na, 1:np, bi_1)))
    2149             : 
    2150             :                         blocks_rv(2, 1)%block(1:nb, 1:na) = blocks_rv(2, 1)%block(1:nb, 1:na) - &
    2151             :                                                             MATMUL(bchint(1:nb, 1:np, bi_xy), TRANSPOSE(acint(1:na, 1:np, bi_1)))
    2152             : 
    2153             :                         blocks_rv(2, 2)%block(1:nb, 1:na) = blocks_rv(2, 2)%block(1:nb, 1:na) - &
    2154             :                                                             MATMUL(bchint(1:nb, 1:np, bi_yy), TRANSPOSE(acint(1:na, 1:np, bi_1)))
    2155             : 
    2156             :                         blocks_rv(2, 3)%block(1:nb, 1:na) = blocks_rv(2, 3)%block(1:nb, 1:na) - &
    2157             :                                                             MATMUL(bchint(1:nb, 1:np, bi_yz), TRANSPOSE(acint(1:na, 1:np, bi_1)))
    2158             : 
    2159             :                         blocks_rv(3, 1)%block(1:nb, 1:na) = blocks_rv(3, 1)%block(1:nb, 1:na) - &
    2160             :                                                             MATMUL(bchint(1:nb, 1:np, bi_xz), TRANSPOSE(acint(1:na, 1:np, bi_1)))
    2161             : 
    2162             :                         blocks_rv(3, 2)%block(1:nb, 1:na) = blocks_rv(3, 2)%block(1:nb, 1:na) - &
    2163             :                                                             MATMUL(bchint(1:nb, 1:np, bi_yz), TRANSPOSE(acint(1:na, 1:np, bi_1)))
    2164             : 
    2165             :                         blocks_rv(3, 3)%block(1:nb, 1:na) = blocks_rv(3, 3)%block(1:nb, 1:na) - &
    2166             :                                                             MATMUL(bchint(1:nb, 1:np, bi_zz), TRANSPOSE(acint(1:na, 1:np, bi_1)))
    2167             : 
    2168             :                         ! -Vnl*r_beta*r_alpha
    2169             :                         blocks_rv(1, 1)%block(1:nb, 1:na) = blocks_rv(1, 1)%block(1:nb, 1:na) - &
    2170             :                                                             MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_xx)))
    2171             : 
    2172             :                         blocks_rv(1, 2)%block(1:nb, 1:na) = blocks_rv(1, 2)%block(1:nb, 1:na) - &
    2173             :                                                             MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_xy)))
    2174             : 
    2175             :                         blocks_rv(1, 3)%block(1:nb, 1:na) = blocks_rv(1, 3)%block(1:nb, 1:na) - &
    2176             :                                                             MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_xz)))
    2177             : 
    2178             :                         blocks_rv(2, 1)%block(1:nb, 1:na) = blocks_rv(2, 1)%block(1:nb, 1:na) - &
    2179             :                                                             MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_xy)))
    2180             : 
    2181             :                         blocks_rv(2, 2)%block(1:nb, 1:na) = blocks_rv(2, 2)%block(1:nb, 1:na) - &
    2182             :                                                             MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_yy)))
    2183             : 
    2184             :                         blocks_rv(2, 3)%block(1:nb, 1:na) = blocks_rv(2, 3)%block(1:nb, 1:na) - &
    2185             :                                                             MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_yz)))
    2186             : 
    2187             :                         blocks_rv(3, 1)%block(1:nb, 1:na) = blocks_rv(3, 1)%block(1:nb, 1:na) - &
    2188             :                                                             MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_xz)))
    2189             : 
    2190             :                         blocks_rv(3, 2)%block(1:nb, 1:na) = blocks_rv(3, 2)%block(1:nb, 1:na) - &
    2191             :                                                             MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_yz)))
    2192             : 
    2193             :                         blocks_rv(3, 3)%block(1:nb, 1:na) = blocks_rv(3, 3)%block(1:nb, 1:na) - &
    2194             :                                                             MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_zz)))
    2195             : 
    2196             :                         ! +r_beta*Vnl*r_alpha
    2197             :                         blocks_rv(1, 1)%block(1:nb, 1:na) = blocks_rv(1, 1)%block(1:nb, 1:na) + &
    2198             :                                                             MATMUL(bchint(1:nb, 1:np, bi_x), TRANSPOSE(acint(1:na, 1:np, bi_x)))
    2199             : 
    2200             :                         blocks_rv(1, 2)%block(1:nb, 1:na) = blocks_rv(1, 2)%block(1:nb, 1:na) + &
    2201             :                                                             MATMUL(bchint(1:nb, 1:np, bi_y), TRANSPOSE(acint(1:na, 1:np, bi_x)))
    2202             : 
    2203             :                         blocks_rv(1, 3)%block(1:nb, 1:na) = blocks_rv(1, 3)%block(1:nb, 1:na) + &
    2204             :                                                             MATMUL(bchint(1:nb, 1:np, bi_z), TRANSPOSE(acint(1:na, 1:np, bi_x)))
    2205             : 
    2206             :                         blocks_rv(2, 1)%block(1:nb, 1:na) = blocks_rv(2, 1)%block(1:nb, 1:na) + &
    2207             :                                                             MATMUL(bchint(1:nb, 1:np, bi_x), TRANSPOSE(acint(1:na, 1:np, bi_y)))
    2208             : 
    2209             :                         blocks_rv(2, 2)%block(1:nb, 1:na) = blocks_rv(2, 2)%block(1:nb, 1:na) + &
    2210             :                                                             MATMUL(bchint(1:nb, 1:np, bi_y), TRANSPOSE(acint(1:na, 1:np, bi_y)))
    2211             : 
    2212             :                         blocks_rv(2, 3)%block(1:nb, 1:na) = blocks_rv(2, 3)%block(1:nb, 1:na) + &
    2213             :                                                             MATMUL(bchint(1:nb, 1:np, bi_z), TRANSPOSE(acint(1:na, 1:np, bi_y)))
    2214             : 
    2215             :                         blocks_rv(3, 1)%block(1:nb, 1:na) = blocks_rv(3, 1)%block(1:nb, 1:na) + &
    2216             :                                                             MATMUL(bchint(1:nb, 1:np, bi_x), TRANSPOSE(acint(1:na, 1:np, bi_z)))
    2217             : 
    2218             :                         blocks_rv(3, 2)%block(1:nb, 1:na) = blocks_rv(3, 2)%block(1:nb, 1:na) + &
    2219             :                                                             MATMUL(bchint(1:nb, 1:np, bi_y), TRANSPOSE(acint(1:na, 1:np, bi_z)))
    2220             : 
    2221             :                         blocks_rv(3, 3)%block(1:nb, 1:na) = blocks_rv(3, 3)%block(1:nb, 1:na) + &
    2222             :                                                             MATMUL(bchint(1:nb, 1:np, bi_z), TRANSPOSE(acint(1:na, 1:np, bi_z)))
    2223             : 
    2224             :                      END IF
    2225             : !$                   CALL omp_unset_lock(locks(hash))
    2226             :                      EXIT ! We have found a match and there can be only one single match
    2227             :                   END IF
    2228             :                END DO
    2229             :             END DO
    2230             :          END DO
    2231             :          DO i = 1, 3
    2232             :             NULLIFY (blocks_rv(i, 1)%block)
    2233             :             NULLIFY (blocks_rv(i, 2)%block)
    2234             :             NULLIFY (blocks_rv(i, 3)%block)
    2235             :          END DO
    2236             :       END DO
    2237             : 
    2238             : !$OMP DO
    2239             : !$    DO lock_num = 1, nlock
    2240             : !$       call omp_destroy_lock(locks(lock_num))
    2241             : !$    END DO
    2242             : !$OMP END DO
    2243             : 
    2244             : !$OMP SINGLE
    2245             : !$    DEALLOCATE (locks)
    2246             : !$OMP END SINGLE NOWAIT
    2247             : 
    2248             : !$OMP END PARALLEL
    2249             : 
    2250           6 :       CALL release_sap_int(sap_int)
    2251             : 
    2252           6 :       DEALLOCATE (basis_set)
    2253             : 
    2254           6 :       CALL timestop(handle)
    2255             : 
    2256          18 :    END SUBROUTINE build_dcom_rpnl
    2257             : 
    2258             : ! **************************************************************************************************
    2259             : !> \brief dV_nl/dV. Adapted from build_com_rpnl.
    2260             : !> \param matrix_rv ...
    2261             : !> \param qs_kind_set ...
    2262             : !> \param sab_all ...
    2263             : !> \param sap_ppnl ...
    2264             : !> \param eps_ppnl ...
    2265             : !> \param particle_set ...
    2266             : !> \param pseudoatom ...
    2267             : !> \author Edward Ditler
    2268             : ! **************************************************************************************************
    2269           6 :    SUBROUTINE build_drpnl_matrix(matrix_rv, qs_kind_set, sab_all, sap_ppnl, eps_ppnl, particle_set, pseudoatom)
    2270             : 
    2271             :       TYPE(dbcsr_p_type), DIMENSION(:)                   :: matrix_rv
    2272             :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    2273             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    2274             :          POINTER                                         :: sab_all, sap_ppnl
    2275             :       REAL(KIND=dp), INTENT(IN)                          :: eps_ppnl
    2276             :       TYPE(particle_type), DIMENSION(:), INTENT(IN), &
    2277             :          POINTER                                         :: particle_set
    2278             :       INTEGER                                            :: pseudoatom
    2279             : 
    2280             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'build_drpnl_matrix'
    2281             : 
    2282             :       INTEGER                                            :: handle, i, iab, iac, iatom, ibc, icol, &
    2283             :                                                             ikind, irow, jatom, jkind, kac, kbc, &
    2284             :                                                             kkind, na, natom, nb, nkind, np, slot
    2285             :       INTEGER, DIMENSION(3)                              :: cell_b
    2286             :       LOGICAL                                            :: found, ppnl_present
    2287             :       REAL(KIND=dp), DIMENSION(3)                        :: rab
    2288           6 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: achint, acint, bchint, bcint
    2289             :       TYPE(alist_type), POINTER                          :: alist_ac, alist_bc
    2290          24 :       TYPE(block_p_type), DIMENSION(3)                   :: blocks_rv
    2291           6 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set
    2292             :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
    2293           6 :       TYPE(sap_int_type), DIMENSION(:), POINTER          :: sap_int
    2294             : 
    2295             : !$    INTEGER(kind=omp_lock_kind), &
    2296           6 : !$       ALLOCATABLE, DIMENSION(:) :: locks
    2297             : !$    INTEGER                                            :: lock_num, hash
    2298             : !$    INTEGER, PARAMETER                                 :: nlock = 501
    2299             : 
    2300           6 :       ppnl_present = ASSOCIATED(sap_ppnl)
    2301           6 :       IF (.NOT. ppnl_present) RETURN
    2302             : 
    2303           6 :       CALL timeset(routineN, handle)
    2304           6 :       nkind = SIZE(qs_kind_set)
    2305           6 :       natom = SIZE(particle_set)
    2306             : 
    2307             :       ! sap_int needs to be shared as multiple threads need to access this
    2308           6 :       NULLIFY (sap_int)
    2309          42 :       ALLOCATE (sap_int(nkind*nkind))
    2310          30 :       DO i = 1, nkind*nkind
    2311          24 :          NULLIFY (sap_int(i)%alist, sap_int(i)%asort, sap_int(i)%aindex)
    2312          30 :          sap_int(i)%nalist = 0
    2313             :       END DO
    2314             : 
    2315             :       ! "nder" in moment_mode is "order"
    2316           6 :       CALL build_sap_ints(sap_int, sap_ppnl, qs_kind_set, nder=1, moment_mode=.TRUE., pseudoatom=pseudoatom)
    2317             : 
    2318             :       ! *** Set up a sorting index
    2319           6 :       CALL sap_sort(sap_int)
    2320             : 
    2321          30 :       ALLOCATE (basis_set(nkind))
    2322          18 :       DO ikind = 1, nkind
    2323          12 :          CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set)
    2324          18 :          IF (ASSOCIATED(orb_basis_set)) THEN
    2325          12 :             basis_set(ikind)%gto_basis_set => orb_basis_set
    2326             :          ELSE
    2327           0 :             NULLIFY (basis_set(ikind)%gto_basis_set)
    2328             :          END IF
    2329             :       END DO
    2330             : 
    2331             :       ! *** All integrals needed have been calculated and stored in sap_int
    2332             :       ! *** We now calculate the commutator matrix elements
    2333             : 
    2334             : !$OMP PARALLEL &
    2335             : !$OMP DEFAULT (NONE) &
    2336             : !$OMP SHARED  (basis_set, matrix_rv, &
    2337             : !$OMP          sap_int, nkind, eps_ppnl, locks, sab_all) &
    2338             : !$OMP PRIVATE (ikind, jkind, iatom, jatom, cell_b, rab, &
    2339             : !$OMP          iab, irow, icol, blocks_rv, &
    2340             : !$OMP          found, iac, ibc, alist_ac, alist_bc, &
    2341             : !$OMP          na, np, nb, kkind, kac, kbc, i, &
    2342           6 : !$OMP          hash, natom, acint, bcint, achint, bchint)
    2343             : 
    2344             : !$OMP SINGLE
    2345             : !$    ALLOCATE (locks(nlock))
    2346             : !$OMP END SINGLE
    2347             : 
    2348             : !$OMP DO
    2349             : !$    DO lock_num = 1, nlock
    2350             : !$       call omp_init_lock(locks(lock_num))
    2351             : !$    END DO
    2352             : !$OMP END DO
    2353             : 
    2354             : !$OMP DO SCHEDULE(GUIDED)
    2355             : 
    2356             :       DO slot = 1, sab_all(1)%nl_size
    2357             : 
    2358             :          ikind = sab_all(1)%nlist_task(slot)%ikind
    2359             :          jkind = sab_all(1)%nlist_task(slot)%jkind
    2360             :          iatom = sab_all(1)%nlist_task(slot)%iatom
    2361             :          jatom = sab_all(1)%nlist_task(slot)%jatom
    2362             :          cell_b(:) = sab_all(1)%nlist_task(slot)%cell(:)
    2363             :          rab(1:3) = sab_all(1)%nlist_task(slot)%r(1:3)
    2364             : 
    2365             :          IF (.NOT. ASSOCIATED(basis_set(ikind)%gto_basis_set)) CYCLE
    2366             :          IF (.NOT. ASSOCIATED(basis_set(jkind)%gto_basis_set)) CYCLE
    2367             :          iab = ikind + nkind*(jkind - 1)
    2368             : 
    2369             :          ! *** Create matrix blocks for a new matrix block column ***
    2370             :          irow = iatom
    2371             :          icol = jatom
    2372             :          DO i = 1, 3
    2373             :             CALL dbcsr_get_block_p(matrix_rv(i)%matrix, irow, icol, blocks_rv(i)%block, found)
    2374             :             CPASSERT(found)
    2375             :          END DO
    2376             : 
    2377             :          ! loop over all kinds for projector atom
    2378             :          DO kkind = 1, nkind
    2379             :             iac = ikind + nkind*(kkind - 1)
    2380             :             ibc = jkind + nkind*(kkind - 1)
    2381             :             IF (.NOT. ASSOCIATED(sap_int(iac)%alist)) CYCLE
    2382             :             IF (.NOT. ASSOCIATED(sap_int(ibc)%alist)) CYCLE
    2383             :             CALL get_alist(sap_int(iac), alist_ac, iatom)
    2384             :             CALL get_alist(sap_int(ibc), alist_bc, jatom)
    2385             : 
    2386             :             IF (.NOT. ASSOCIATED(alist_ac)) CYCLE
    2387             :             IF (.NOT. ASSOCIATED(alist_bc)) CYCLE
    2388             :             DO kac = 1, alist_ac%nclist
    2389             :                DO kbc = 1, alist_bc%nclist
    2390             :                   IF (alist_ac%clist(kac)%catom /= alist_bc%clist(kbc)%catom) CYCLE
    2391             :                   IF (ALL(cell_b + alist_bc%clist(kbc)%cell - alist_ac%clist(kac)%cell == 0)) THEN
    2392             :                      IF (alist_ac%clist(kac)%maxac*alist_bc%clist(kbc)%maxach < eps_ppnl) CYCLE
    2393             :                      acint => alist_ac%clist(kac)%acint
    2394             :                      bcint => alist_bc%clist(kbc)%acint
    2395             :                      achint => alist_ac%clist(kac)%achint
    2396             :                      bchint => alist_bc%clist(kbc)%achint
    2397             :                      na = SIZE(acint, 1)
    2398             :                      np = SIZE(acint, 2)
    2399             :                      nb = SIZE(bcint, 1)
    2400             : !$                   hash = MOD((iatom - 1)*natom + jatom, nlock) + 1
    2401             : !$                   CALL omp_set_lock(locks(hash))
    2402             :                      ! Vnl*r
    2403             :                      blocks_rv(1)%block(1:na, 1:nb) = blocks_rv(1)%block(1:na, 1:nb) + &
    2404             :                                                       MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
    2405             :                      blocks_rv(2)%block(1:na, 1:nb) = blocks_rv(2)%block(1:na, 1:nb) + &
    2406             :                                                       MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
    2407             :                      blocks_rv(3)%block(1:na, 1:nb) = blocks_rv(3)%block(1:na, 1:nb) + &
    2408             :                                                       MATMUL(achint(1:na, 1:np, 1), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
    2409             : 
    2410             :                      ! r*Vnl
    2411             :                      blocks_rv(1)%block(1:na, 1:nb) = blocks_rv(1)%block(1:na, 1:nb) - &
    2412             :                                                       MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    2413             :                      blocks_rv(2)%block(1:na, 1:nb) = blocks_rv(2)%block(1:na, 1:nb) - &
    2414             :                                                       MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    2415             :                      blocks_rv(3)%block(1:na, 1:nb) = blocks_rv(3)%block(1:na, 1:nb) - &
    2416             :                                                       MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
    2417             : 
    2418             : !$                   CALL omp_unset_lock(locks(hash))
    2419             :                      EXIT ! We have found a match and there can be only one single match
    2420             :                   END IF
    2421             :                END DO
    2422             :             END DO
    2423             :          END DO
    2424             :          DO i = 1, 3
    2425             :             NULLIFY (blocks_rv(i)%block)
    2426             :          END DO
    2427             :       END DO
    2428             : 
    2429             : !$OMP DO
    2430             : !$    DO lock_num = 1, nlock
    2431             : !$       call omp_destroy_lock(locks(lock_num))
    2432             : !$    END DO
    2433             : !$OMP END DO
    2434             : 
    2435             : !$OMP SINGLE
    2436             : !$    DEALLOCATE (locks)
    2437             : !$OMP END SINGLE NOWAIT
    2438             : 
    2439             : !$OMP END PARALLEL
    2440             : 
    2441           6 :       CALL release_sap_int(sap_int)
    2442             : 
    2443           6 :       DEALLOCATE (basis_set)
    2444             : 
    2445           6 :       CALL timestop(handle)
    2446             : 
    2447          18 :    END SUBROUTINE build_drpnl_matrix
    2448             : 
    2449             : ! **************************************************************************************************
    2450             : !> \brief   Adapted from comab_opr. Calculate the product O*r or r*O from the integrals [a|O|b].
    2451             : !>          We assume that on input all integrals [a+1|O|b+1] are available.
    2452             : !> \param la_max ...
    2453             : !> \param npgfa ...
    2454             : !> \param rpgfa ...
    2455             : !> \param la_min ...
    2456             : !> \param lb_max ...
    2457             : !> \param npgfb ...
    2458             : !> \param rpgfb ...
    2459             : !> \param lb_min ...
    2460             : !> \param dab ...
    2461             : !> \param ab ...
    2462             : !> \param comabr ...
    2463             : !>
    2464             : !> \param ra ...
    2465             : !> \param rb ...
    2466             : !> \param direction_Or ...
    2467             : !> \par Literature
    2468             : !>          S. Obara and A. Saika, J. Chem. Phys. 84, 3963 (1986)
    2469             : !> \par Parameters
    2470             : !>      - ax,ay,az  : Angular momentum index numbers of orbital a.
    2471             : !>      - bx,by,bz  : Angular momentum index numbers of orbital b.
    2472             : !>      - coset     : Cartesian orbital set pointer.
    2473             : !>      - l{a,b}    : Angular momentum quantum number of shell a or b.
    2474             : !>      - l{a,b}_max: Maximum angular momentum quantum number of shell a or b.
    2475             : !>      - l{a,b}_min: Minimum angular momentum quantum number of shell a or b.
    2476             : !>      - ncoset    : Number of orbitals in a Cartesian orbital set.
    2477             : !>      - npgf{a,b} : Degree of contraction of shell a or b.
    2478             : !>      - rab       : Distance vector between the atomic centers a and b.
    2479             : !>      - rab2      : Square of the distance between the atomic centers a and b.
    2480             : !>      - rac       : Distance vector between the atomic centers a and c.
    2481             : !>      - rac2      : Square of the distance between the atomic centers a and c.
    2482             : !>      - rbc       : Distance vector between the atomic centers b and c.
    2483             : !>      - rbc2      : Square of the distance between the atomic centers b and c.
    2484             : !>      - rpgf{a,b} : Radius of the primitive Gaussian-type function a or b.
    2485             : !>      - zet{a,b}  : Exponents of the Gaussian-type functions a or b.
    2486             : !>      - zetp      : Reciprocal of the sum of the exponents of orbital a and b.
    2487             : !>
    2488             : !> \author  Tomas Zimmermann
    2489             : ! **************************************************************************************************
    2490        2052 :    SUBROUTINE ab_opr(la_max, npgfa, rpgfa, la_min, lb_max, npgfb, rpgfb, lb_min, &
    2491        4104 :                      dab, ab, comabr, ra, rb, direction_Or)
    2492             :       INTEGER, INTENT(IN)                                :: la_max, npgfa
    2493             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rpgfa
    2494             :       INTEGER, INTENT(IN)                                :: la_min, lb_max, npgfb
    2495             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rpgfb
    2496             :       INTEGER, INTENT(IN)                                :: lb_min
    2497             :       REAL(KIND=dp), INTENT(IN)                          :: dab
    2498             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: ab
    2499             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(OUT)     :: comabr
    2500             :       REAL(KIND=dp), DIMENSION(1:3), INTENT(IN)          :: ra, rb
    2501             :       LOGICAL                                            :: direction_Or
    2502             : 
    2503             :       INTEGER                                            :: ax, ay, az, bx, by, bz, coa, coap, &
    2504             :                                                             coapx, coapy, coapz, cob, cobp, cobpx, &
    2505             :                                                             cobpy, cobpz, ipgf, jpgf, la, lb, na, &
    2506             :                                                             nap, nb, nbp, ofa, ofb
    2507             : 
    2508    82941840 :       comabr = 0.0_dp
    2509             : 
    2510        2052 :       ofa = ncoset(la_min - 1)
    2511        2052 :       ofb = ncoset(lb_min - 1)
    2512             : 
    2513        2052 :       na = 0
    2514        2052 :       nap = 0
    2515       10260 :       DO ipgf = 1, npgfa
    2516        8208 :          nb = 0
    2517        8208 :          nbp = 0
    2518       41040 :          DO jpgf = 1, npgfb
    2519       32832 :             IF (rpgfa(ipgf) + rpgfb(jpgf) > dab) THEN
    2520       77596 :                DO la = la_min, la_max
    2521      135546 :                   DO ax = 0, la
    2522      173850 :                      DO ay = 0, la - ax
    2523       70718 :                         az = la - ax - ay
    2524       70718 :                         coa = na + coset(ax, ay, az) - ofa
    2525       70718 :                         coap = nap + coset(ax, ay, az) - ofa
    2526       70718 :                         coapx = nap + coset(ax + 1, ay, az) - ofa
    2527       70718 :                         coapy = nap + coset(ax, ay + 1, az) - ofa
    2528       70718 :                         coapz = nap + coset(ax, ay, az + 1) - ofa
    2529      221274 :                         DO lb = lb_min, lb_max
    2530      277818 :                            DO bx = 0, lb
    2531      343482 :                               DO by = 0, lb - bx
    2532      136382 :                                  bz = lb - bx - by
    2533      136382 :                                  cob = nb + coset(bx, by, bz) - ofb
    2534      136382 :                                  cobp = nbp + coset(bx, by, bz) - ofb
    2535      136382 :                                  cobpx = nbp + coset(bx + 1, by, bz) - ofb
    2536      136382 :                                  cobpy = nbp + coset(bx, by + 1, bz) - ofb
    2537      136382 :                                  cobpz = nbp + coset(bx, by, bz + 1) - ofb
    2538      250876 :                                  IF (direction_Or) THEN
    2539             :                                     ! [a|O * x|b] = [a|O|b(x+1)] + [a|O|b] * X_b
    2540             :                                     !             = [a|O * (x - X_b)|b] + [a|O|b] * X_b
    2541             :                                     ! So the second term makes sure that we actually calculate
    2542             :                                     !  <O*r> and not <O*(r-R)>
    2543       19912 :                                     comabr(coa, cob, 1) = ab(coap, cobpx) + ab(coap, cobp)*rb(1)
    2544       19912 :                                     comabr(coa, cob, 2) = ab(coap, cobpy) + ab(coap, cobp)*rb(2)
    2545       19912 :                                     comabr(coa, cob, 3) = ab(coap, cobpz) + ab(coap, cobp)*rb(3)
    2546             :                                  ELSE
    2547      116470 :                                     comabr(coa, cob, 1) = ab(coapx, cobp) + ab(coap, cobp)*ra(1)
    2548      116470 :                                     comabr(coa, cob, 2) = ab(coapy, cobp) + ab(coap, cobp)*ra(2)
    2549      116470 :                                     comabr(coa, cob, 3) = ab(coapz, cobp) + ab(coap, cobp)*ra(3)
    2550             :                                  END IF
    2551             :                               END DO
    2552             :                            END DO
    2553             :                         END DO
    2554             :                      END DO
    2555             :                   END DO
    2556             :                END DO
    2557             :             END IF
    2558       32832 :             nb = nb + ncoset(lb_max) - ofb
    2559       41040 :             nbp = nbp + ncoset(lb_max + 1) - ofb
    2560             :          END DO
    2561        8208 :          na = na + ncoset(la_max) - ofa
    2562       10260 :          nap = nap + ncoset(la_max + 1) - ofa
    2563             :       END DO
    2564             : 
    2565        2052 :    END SUBROUTINE ab_opr
    2566             : 
    2567             : ! **************************************************************************************************
    2568             : !> \brief Apply the operator \delta_\mu^\lambda to zero out all elements of the matrix
    2569             : !>         which don't fulfill the condition.
    2570             : !> \param matrix ...
    2571             : !> \param qs_kind_set ...
    2572             : !> \param basis_type ...
    2573             : !> \param sab_nl ...
    2574             : !> \param lambda ...
    2575             : !> \param direction_Or ...
    2576             : !> \author Edward Ditler
    2577             : ! **************************************************************************************************
    2578           0 :    SUBROUTINE hr_mult_by_delta_1d(matrix, qs_kind_set, basis_type, sab_nl, lambda, direction_Or)
    2579             : 
    2580             :       TYPE(dbcsr_type)                                   :: matrix
    2581             :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    2582             :       CHARACTER(LEN=*), INTENT(IN)                       :: basis_type
    2583             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    2584             :          POINTER                                         :: sab_nl
    2585             :       INTEGER, INTENT(IN)                                :: lambda
    2586             :       LOGICAL                                            :: direction_Or
    2587             : 
    2588             :       CHARACTER(len=*), PARAMETER :: routineN = 'hr_mult_by_delta_1d'
    2589             : 
    2590             :       INTEGER                                            :: handle, iatom, icol, ikind, irow, jatom, &
    2591             :                                                             jkind, ldsab, mepos, nkind, nseta, &
    2592             :                                                             nsetb, nthread
    2593             :       INTEGER, DIMENSION(3)                              :: cell
    2594           0 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, lb_min, npgfa, &
    2595           0 :                                                             npgfb, nsgfa, nsgfb
    2596           0 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
    2597             :       LOGICAL                                            :: do_symmetric, found
    2598             :       REAL(KIND=dp), DIMENSION(3)                        :: rab
    2599           0 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a, set_radius_b
    2600           0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: k_block, rpgfa, rpgfb, scon_a, scon_b, &
    2601           0 :                                                             sphi_a, sphi_b, zeta, zetb
    2602           0 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
    2603             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
    2604             :       TYPE(neighbor_list_iterator_p_type), &
    2605           0 :          DIMENSION(:), POINTER                           :: nl_iterator
    2606             : 
    2607           0 :       CALL timeset(routineN, handle)
    2608             : 
    2609           0 :       nkind = SIZE(qs_kind_set)
    2610             : 
    2611             :       ! check for symmetry
    2612           0 :       CPASSERT(SIZE(sab_nl) > 0)
    2613           0 :       CALL get_neighbor_list_set_p(neighbor_list_sets=sab_nl, symmetric=do_symmetric)
    2614             : 
    2615             :       ! prepare basis set
    2616           0 :       ALLOCATE (basis_set_list(nkind))
    2617           0 :       CALL basis_set_list_setup(basis_set_list, basis_type, qs_kind_set)
    2618             : 
    2619             :       ! *** Allocate work storage ***
    2620           0 :       ldsab = get_memory_usage(qs_kind_set, basis_type)
    2621             : 
    2622             :       nthread = 1
    2623           0 : !$    nthread = omp_get_max_threads()
    2624             :       ! Iterate of neighbor list
    2625           0 :       CALL neighbor_list_iterator_create(nl_iterator, sab_nl, nthread=nthread)
    2626             : 
    2627             : !$OMP PARALLEL DEFAULT(NONE) &
    2628             : !$OMP SHARED (nthread,ldsab,nl_iterator, do_symmetric) &
    2629             : !$OMP SHARED (ncoset,matrix,basis_set_list) &
    2630             : !$OMP SHARED (direction_or, lambda) &
    2631             : !$OMP PRIVATE (k_block,mepos,ikind,jkind,iatom,jatom,rab,cell) &
    2632             : !$OMP PRIVATE (basis_set_a,basis_set_b) &
    2633             : !$OMP PRIVATE (first_sgfa, la_max, la_min, npgfa, nsgfa, nseta, rpgfa, set_radius_a) &
    2634             : !$OMP PRIVATE (zeta, first_sgfb, lb_max, lb_min, npgfb, nsetb, rpgfb, set_radius_b, nsgfb) &
    2635           0 : !$OMP PRIVATE (zetb, scon_a, scon_b, irow, icol, found, sphi_a, sphi_b)
    2636             : 
    2637             :       mepos = 0
    2638             : !$    mepos = omp_get_thread_num()
    2639             : 
    2640             :       DO WHILE (neighbor_list_iterate(nl_iterator, mepos=mepos) == 0)
    2641             :          CALL get_iterator_info(nl_iterator, mepos=mepos, ikind=ikind, jkind=jkind, &
    2642             :                                 iatom=iatom, jatom=jatom, r=rab, cell=cell)
    2643             :          basis_set_a => basis_set_list(ikind)%gto_basis_set
    2644             :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
    2645             :          basis_set_b => basis_set_list(jkind)%gto_basis_set
    2646             :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
    2647             :          ! basis ikind
    2648             :          first_sgfa => basis_set_a%first_sgf
    2649             :          la_max => basis_set_a%lmax
    2650             :          la_min => basis_set_a%lmin
    2651             :          npgfa => basis_set_a%npgf
    2652             :          nsgfa => basis_set_a%nsgf_set
    2653             :          rpgfa => basis_set_a%pgf_radius
    2654             :          set_radius_a => basis_set_a%set_radius
    2655             :          sphi_a => basis_set_a%sphi
    2656             :          zeta => basis_set_a%zet
    2657             :          scon_a => basis_set_a%scon
    2658             :          ! basis jkind
    2659             :          first_sgfb => basis_set_b%first_sgf
    2660             :          lb_max => basis_set_b%lmax
    2661             :          lb_min => basis_set_b%lmin
    2662             :          npgfb => basis_set_b%npgf
    2663             :          nsgfb => basis_set_b%nsgf_set
    2664             :          rpgfb => basis_set_b%pgf_radius
    2665             :          set_radius_b => basis_set_b%set_radius
    2666             :          sphi_b => basis_set_b%sphi
    2667             :          zetb => basis_set_b%zet
    2668             :          scon_b => basis_set_b%scon
    2669             : 
    2670             :          nseta = basis_set_a%nset
    2671             :          nsetb = basis_set_b%nset
    2672             : 
    2673             :          IF (do_symmetric) THEN
    2674             :             IF (iatom <= jatom) THEN
    2675             :                irow = iatom
    2676             :                icol = jatom
    2677             :             ELSE
    2678             :                irow = jatom
    2679             :                icol = iatom
    2680             :             END IF
    2681             :          ELSE
    2682             :             irow = iatom
    2683             :             icol = jatom
    2684             :          END IF
    2685             : 
    2686             :          NULLIFY (k_block)
    2687             :          CALL dbcsr_get_block_p(matrix, irow, icol, k_block, found)
    2688             :          CPASSERT(found)
    2689             : 
    2690             :          IF (direction_Or) THEN
    2691             :             IF (jatom /= lambda) k_block(:, :) = 0._dp
    2692             :          ELSE IF (.NOT. direction_Or) THEN
    2693             :             IF (iatom /= lambda) k_block(:, :) = 0._dp
    2694             :          END IF
    2695             :       END DO
    2696             : !$OMP END PARALLEL
    2697           0 :       CALL neighbor_list_iterator_release(nl_iterator)
    2698             : 
    2699             :       ! Release work storage
    2700           0 :       DEALLOCATE (basis_set_list)
    2701             : 
    2702           0 :       CALL timestop(handle)
    2703             : 
    2704           0 :    END SUBROUTINE hr_mult_by_delta_1d
    2705             : 
    2706             : ! **************************************************************************************************
    2707             : !> \brief Apply the operator \delta_\mu^\lambda to zero out all elements of the matrix
    2708             : !>         which don't fulfill the condition.
    2709             : !>        Operates on matrix_hr(1:3) instead of a single matrix
    2710             : !> \param matrix_hr ...
    2711             : !> \param qs_kind_set ...
    2712             : !> \param basis_type ...
    2713             : !> \param sab_nl ...
    2714             : !> \param deltaR ...
    2715             : !> \param direction_Or ...
    2716             : !> \author Edward Ditler
    2717             : ! **************************************************************************************************
    2718          18 :    SUBROUTINE hr_mult_by_delta_3d(matrix_hr, qs_kind_set, basis_type, sab_nl, deltaR, direction_Or)
    2719             : 
    2720             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_hr
    2721             :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    2722             :       CHARACTER(LEN=*), INTENT(IN)                       :: basis_type
    2723             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    2724             :          POINTER                                         :: sab_nl
    2725             :       REAL(KIND=dp), DIMENSION(:, :)                     :: deltaR
    2726             :       LOGICAL                                            :: direction_Or
    2727             : 
    2728             :       CHARACTER(len=*), PARAMETER :: routineN = 'hr_mult_by_delta_3d'
    2729             : 
    2730             :       INTEGER                                            :: handle, iatom, icol, ikind, ir, irow, &
    2731             :                                                             jatom, jkind, ldsab, mepos, nkind, &
    2732             :                                                             nseta, nsetb, nthread
    2733             :       INTEGER, DIMENSION(3)                              :: cell
    2734          18 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, lb_min, npgfa, &
    2735          18 :                                                             npgfb, nsgfa, nsgfb
    2736          18 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
    2737             :       LOGICAL                                            :: do_symmetric, found
    2738             :       REAL(KIND=dp), DIMENSION(3)                        :: rab
    2739          18 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a, set_radius_b
    2740          18 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: kx_block, ky_block, kz_block, rpgfa, &
    2741          18 :                                                             rpgfb, scon_a, scon_b, sphi_a, sphi_b, &
    2742          18 :                                                             zeta, zetb
    2743          18 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
    2744             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
    2745             :       TYPE(neighbor_list_iterator_p_type), &
    2746          18 :          DIMENSION(:), POINTER                           :: nl_iterator
    2747             : 
    2748          18 :       CALL timeset(routineN, handle)
    2749             : 
    2750          18 :       nkind = SIZE(qs_kind_set)
    2751             : 
    2752             :       ! check for symmetry
    2753          18 :       CPASSERT(SIZE(sab_nl) > 0)
    2754          18 :       CALL get_neighbor_list_set_p(neighbor_list_sets=sab_nl, symmetric=do_symmetric)
    2755             : 
    2756             :       ! prepare basis set
    2757          90 :       ALLOCATE (basis_set_list(nkind))
    2758          18 :       CALL basis_set_list_setup(basis_set_list, basis_type, qs_kind_set)
    2759             : 
    2760             :       ! *** Allocate work storage ***
    2761          18 :       ldsab = get_memory_usage(qs_kind_set, basis_type)
    2762             : 
    2763             :       nthread = 1
    2764          18 : !$    nthread = omp_get_max_threads()
    2765             :       ! Iterate of neighbor list
    2766          18 :       CALL neighbor_list_iterator_create(nl_iterator, sab_nl, nthread=nthread)
    2767             : 
    2768             : !$OMP PARALLEL DEFAULT(NONE) &
    2769             : !$OMP SHARED (nthread,ldsab,nl_iterator, do_symmetric) &
    2770             : !$OMP SHARED (ncoset,matrix_hr,basis_set_list) &
    2771             : !$OMP SHARED (direction_or, deltar) &
    2772             : !$OMP PRIVATE (kx_block,ky_block,kz_block,mepos,ikind,jkind,iatom,jatom,rab,cell) &
    2773             : !$OMP PRIVATE (basis_set_a,basis_set_b) &
    2774             : !$OMP PRIVATE (nseta, nsetb) &
    2775             : !$OMP PRIVATE (first_sgfa, la_max, la_min, npgfa, nsgfa, rpgfa, set_radius_a, sphi_a, zeta, scon_a) &
    2776             : !$OMP PRIVATE (first_sgfb, lb_max, lb_min, npgfb, nsgfb, rpgfb, set_radius_b, sphi_b, zetb, scon_b) &
    2777          18 : !$OMP PRIVATE (irow, icol, found)
    2778             : 
    2779             :       mepos = 0
    2780             : !$    mepos = omp_get_thread_num()
    2781             : 
    2782             :       DO WHILE (neighbor_list_iterate(nl_iterator, mepos=mepos) == 0)
    2783             :          CALL get_iterator_info(nl_iterator, mepos=mepos, ikind=ikind, jkind=jkind, &
    2784             :                                 iatom=iatom, jatom=jatom, r=rab, cell=cell)
    2785             :          basis_set_a => basis_set_list(ikind)%gto_basis_set
    2786             :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
    2787             :          basis_set_b => basis_set_list(jkind)%gto_basis_set
    2788             :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
    2789             :          ! basis ikind
    2790             :          first_sgfa => basis_set_a%first_sgf
    2791             :          la_max => basis_set_a%lmax
    2792             :          la_min => basis_set_a%lmin
    2793             :          npgfa => basis_set_a%npgf
    2794             :          nsgfa => basis_set_a%nsgf_set
    2795             :          rpgfa => basis_set_a%pgf_radius
    2796             :          set_radius_a => basis_set_a%set_radius
    2797             :          sphi_a => basis_set_a%sphi
    2798             :          zeta => basis_set_a%zet
    2799             :          scon_a => basis_set_a%scon
    2800             :          ! basis jkind
    2801             :          first_sgfb => basis_set_b%first_sgf
    2802             :          lb_max => basis_set_b%lmax
    2803             :          lb_min => basis_set_b%lmin
    2804             :          npgfb => basis_set_b%npgf
    2805             :          nsgfb => basis_set_b%nsgf_set
    2806             :          rpgfb => basis_set_b%pgf_radius
    2807             :          set_radius_b => basis_set_b%set_radius
    2808             :          sphi_b => basis_set_b%sphi
    2809             :          zetb => basis_set_b%zet
    2810             :          scon_b => basis_set_b%scon
    2811             : 
    2812             :          nseta = basis_set_a%nset
    2813             :          nsetb = basis_set_b%nset
    2814             : 
    2815             :          IF (do_symmetric) THEN
    2816             :             IF (iatom <= jatom) THEN
    2817             :                irow = iatom
    2818             :                icol = jatom
    2819             :             ELSE
    2820             :                irow = jatom
    2821             :                icol = iatom
    2822             :             END IF
    2823             :          ELSE
    2824             :             irow = iatom
    2825             :             icol = jatom
    2826             :          END IF
    2827             : 
    2828             :          NULLIFY (kx_block, ky_block, kz_block)
    2829             :          CALL dbcsr_get_block_p(matrix_hr(1)%matrix, irow, icol, kx_block, found)
    2830             :          CPASSERT(found)
    2831             :          CALL dbcsr_get_block_p(matrix_hr(2)%matrix, irow, icol, ky_block, found)
    2832             :          CPASSERT(found)
    2833             :          CALL dbcsr_get_block_p(matrix_hr(3)%matrix, irow, icol, kz_block, found)
    2834             :          CPASSERT(found)
    2835             : 
    2836             :          IF (direction_Or) THEN
    2837             :             DO ir = 1, 3
    2838             : !$OMP CRITICAL(blockadd)
    2839             :                SELECT CASE (ir)
    2840             :                CASE (1)
    2841             :                   kx_block(:, :) = kx_block(:, :)*deltaR(ir, jatom)
    2842             :                CASE (2)
    2843             :                   ky_block(:, :) = ky_block(:, :)*deltaR(ir, jatom)
    2844             :                CASE (3)
    2845             :                   kz_block(:, :) = kz_block(:, :)*deltaR(ir, jatom)
    2846             :                END SELECT
    2847             : !$OMP END CRITICAL(blockadd)
    2848             :             END DO
    2849             :          ELSE
    2850             :             DO ir = 1, 3
    2851             : !$OMP CRITICAL(blockadd)
    2852             :                SELECT CASE (ir)
    2853             :                CASE (1)
    2854             :                   kx_block(:, :) = kx_block(:, :)*deltaR(ir, iatom)
    2855             :                CASE (2)
    2856             :                   ky_block(:, :) = ky_block(:, :)*deltaR(ir, iatom)
    2857             :                CASE (3)
    2858             :                   kz_block(:, :) = kz_block(:, :)*deltaR(ir, iatom)
    2859             :                END SELECT
    2860             : !$OMP END CRITICAL(blockadd)
    2861             :             END DO
    2862             :          END IF
    2863             :       END DO
    2864             : !$OMP END PARALLEL
    2865          18 :       CALL neighbor_list_iterator_release(nl_iterator)
    2866             : 
    2867             :       ! Release work storage
    2868          18 :       DEALLOCATE (basis_set_list)
    2869             : 
    2870          18 :       CALL timestop(handle)
    2871             : 
    2872          36 :    END SUBROUTINE hr_mult_by_delta_3d
    2873             : 
    2874        4104 : END MODULE qs_vcd_ao
    2875             : 

Generated by: LCOV version 1.15