LCOV - code coverage report
Current view: top level - src - qs_moments.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 1287 1487 86.6 %
Date: 2024-12-21 06:28:57 Functions: 15 16 93.8 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief Calculates the moment integrals <a|r^m|b> and <a|r x d/dr|b>
      10             : !> \par History
      11             : !>      added angular moments (JGH 11.2012)
      12             : !> \author JGH (20.07.2006)
      13             : ! **************************************************************************************************
      14             : MODULE qs_moments
      15             :    USE ai_angmom,                       ONLY: angmom
      16             :    USE ai_moments,                      ONLY: contract_cossin,&
      17             :                                               cossin,&
      18             :                                               diff_momop,&
      19             :                                               diff_momop2,&
      20             :                                               diff_momop_velocity,&
      21             :                                               moment
      22             :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      23             :                                               get_atomic_kind
      24             :    USE basis_set_types,                 ONLY: gto_basis_set_p_type,&
      25             :                                               gto_basis_set_type
      26             :    USE bibliography,                    ONLY: Mattiat2019,&
      27             :                                               cite_reference
      28             :    USE block_p_types,                   ONLY: block_p_type
      29             :    USE cell_types,                      ONLY: cell_type,&
      30             :                                               pbc
      31             :    USE commutator_rpnl,                 ONLY: build_com_mom_nl
      32             :    USE cp_cfm_basic_linalg,             ONLY: cp_cfm_det
      33             :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      34             :                                               cp_cfm_get_info,&
      35             :                                               cp_cfm_release,&
      36             :                                               cp_cfm_type
      37             :    USE cp_control_types,                ONLY: dft_control_type
      38             :    USE cp_dbcsr_api,                    ONLY: &
      39             :         dbcsr_copy, dbcsr_create, dbcsr_deallocate_matrix, dbcsr_distribution_type, dbcsr_dot, &
      40             :         dbcsr_get_block_p, dbcsr_init_p, dbcsr_multiply, dbcsr_p_type, dbcsr_set, dbcsr_trace, &
      41             :         dbcsr_type, dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, dbcsr_type_symmetric
      42             :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      43             :    USE cp_dbcsr_operations,             ONLY: cp_dbcsr_sm_fm_multiply,&
      44             :                                               dbcsr_allocate_matrix_set,&
      45             :                                               dbcsr_deallocate_matrix_set
      46             :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      47             :                                               cp_fm_struct_double,&
      48             :                                               cp_fm_struct_release,&
      49             :                                               cp_fm_struct_type
      50             :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      51             :                                               cp_fm_get_info,&
      52             :                                               cp_fm_release,&
      53             :                                               cp_fm_set_all,&
      54             :                                               cp_fm_type
      55             :    USE cp_result_methods,               ONLY: cp_results_erase,&
      56             :                                               put_results
      57             :    USE cp_result_types,                 ONLY: cp_result_type
      58             :    USE distribution_1d_types,           ONLY: distribution_1d_type
      59             :    USE kinds,                           ONLY: default_string_length,&
      60             :                                               dp
      61             :    USE kpoint_types,                    ONLY: get_kpoint_info,&
      62             :                                               kpoint_type
      63             :    USE mathconstants,                   ONLY: pi,&
      64             :                                               twopi
      65             :    USE message_passing,                 ONLY: mp_para_env_type
      66             :    USE moments_utils,                   ONLY: get_reference_point
      67             :    USE orbital_pointers,                ONLY: current_maxl,&
      68             :                                               indco,&
      69             :                                               ncoset
      70             :    USE parallel_gemm_api,               ONLY: parallel_gemm
      71             :    USE particle_methods,                ONLY: get_particle_set
      72             :    USE particle_types,                  ONLY: particle_type
      73             :    USE physcon,                         ONLY: bohr,&
      74             :                                               debye
      75             :    USE qs_environment_types,            ONLY: get_qs_env,&
      76             :                                               qs_environment_type
      77             :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      78             :                                               get_qs_kind_set,&
      79             :                                               qs_kind_type
      80             :    USE qs_ks_types,                     ONLY: get_ks_env,&
      81             :                                               qs_ks_env_type
      82             :    USE qs_mo_types,                     ONLY: get_mo_set,&
      83             :                                               mo_set_type
      84             :    USE qs_neighbor_list_types,          ONLY: get_iterator_info,&
      85             :                                               neighbor_list_iterate,&
      86             :                                               neighbor_list_iterator_create,&
      87             :                                               neighbor_list_iterator_p_type,&
      88             :                                               neighbor_list_iterator_release,&
      89             :                                               neighbor_list_set_p_type
      90             :    USE qs_operators_ao,                 ONLY: build_lin_mom_matrix
      91             :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      92             :                                               qs_rho_type
      93             :    USE rt_propagation_types,            ONLY: get_rtp,&
      94             :                                               rt_prop_type
      95             : #include "./base/base_uses.f90"
      96             : 
      97             :    IMPLICIT NONE
      98             : 
      99             :    PRIVATE
     100             : 
     101             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_moments'
     102             : 
     103             :    ! Public subroutines
     104             :    PUBLIC :: build_berry_moment_matrix, build_local_moment_matrix
     105             :    PUBLIC :: build_berry_kpoint_matrix, build_local_magmom_matrix
     106             :    PUBLIC :: qs_moment_berry_phase, qs_moment_locop
     107             :    PUBLIC :: dipole_deriv_ao
     108             :    PUBLIC :: build_local_moments_der_matrix
     109             :    PUBLIC :: build_dsdv_moments
     110             :    PUBLIC :: dipole_velocity_deriv
     111             : 
     112             : CONTAINS
     113             : 
     114             : ! *****************************************************************************
     115             : !> \brief This returns the derivative of the moment integrals [a|\mu|b], with respect
     116             : !>        to the basis function on the right
     117             : !>        difdip(beta, alpha) = < mu | r_beta | ∂_alpha nu >  * (mu - nu)
     118             : !> \param qs_env ...
     119             : !> \param difdip ...
     120             : !> \param order The order of the derivative (1 for dipole moment)
     121             : !> \param lambda The atom on which we take the derivative
     122             : !> \param rc ...
     123             : !> \author Edward Ditler
     124             : ! **************************************************************************************************
     125           6 :    SUBROUTINE dipole_velocity_deriv(qs_env, difdip, order, lambda, rc)
     126             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     127             :       TYPE(dbcsr_p_type), DIMENSION(:, :), INTENT(INOUT) :: difdip
     128             :       INTEGER, INTENT(IN)                                :: order, lambda
     129             :       REAL(KIND=dp), DIMENSION(3)                        :: rc
     130             : 
     131             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'dipole_velocity_deriv'
     132             : 
     133             :       INTEGER :: handle, i, iatom, icol, idir, ikind, inode, irow, iset, j, jatom, jkind, jset, &
     134             :          last_jatom, lda, ldab, ldb, M_dim, maxsgf, natom, ncoa, ncob, nkind, nseta, nsetb, sgfa, &
     135             :          sgfb
     136             :       LOGICAL                                            :: found
     137             :       REAL(dp)                                           :: dab
     138             :       REAL(dp), DIMENSION(3)                             :: ra, rab, rac, rb, rbc
     139           6 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: work
     140           6 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: mab
     141           6 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :, :)  :: difmab, difmab2
     142           6 :       TYPE(block_p_type), ALLOCATABLE, DIMENSION(:, :)   :: mint, mint2
     143             :       TYPE(cell_type), POINTER                           :: cell
     144           6 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
     145             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
     146             :       TYPE(neighbor_list_iterator_p_type), &
     147           6 :          DIMENSION(:), POINTER                           :: nl_iterator
     148             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     149           6 :          POINTER                                         :: sab_all
     150           6 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     151           6 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     152             :       TYPE(qs_kind_type), POINTER                        :: qs_kind
     153             : 
     154           6 :       CALL timeset(routineN, handle)
     155             : 
     156           6 :       NULLIFY (cell, particle_set, qs_kind_set, sab_all)
     157             :       CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set, &
     158           6 :                       qs_kind_set=qs_kind_set, sab_all=sab_all)
     159             :       CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
     160           6 :                            maxco=ldab, maxsgf=maxsgf)
     161             : 
     162           6 :       nkind = SIZE(qs_kind_set)
     163           6 :       natom = SIZE(particle_set)
     164             : 
     165           6 :       M_dim = ncoset(order) - 1
     166             : 
     167          30 :       ALLOCATE (basis_set_list(nkind))
     168             : 
     169          30 :       ALLOCATE (mab(ldab, ldab, M_dim))
     170          36 :       ALLOCATE (difmab2(ldab, ldab, M_dim, 3))
     171          24 :       ALLOCATE (work(ldab, maxsgf))
     172          78 :       ALLOCATE (mint(3, 3))
     173          78 :       ALLOCATE (mint2(3, 3))
     174             : 
     175        4920 :       mab(1:ldab, 1:ldab, 1:M_dim) = 0.0_dp
     176       14766 :       difmab2(1:ldab, 1:ldab, 1:M_dim, 1:3) = 0.0_dp
     177         414 :       work(1:ldab, 1:maxsgf) = 0.0_dp
     178             : 
     179          24 :       DO i = 1, 3
     180          78 :       DO j = 1, 3
     181          54 :          NULLIFY (mint(i, j)%block)
     182          72 :          NULLIFY (mint2(i, j)%block)
     183             :       END DO
     184             :       END DO
     185             : 
     186             :       ! Set the basis_set_list(nkind) to point to the corresponding basis sets
     187          18 :       DO ikind = 1, nkind
     188          12 :          qs_kind => qs_kind_set(ikind)
     189          12 :          CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a)
     190          18 :          IF (ASSOCIATED(basis_set_a)) THEN
     191          12 :             basis_set_list(ikind)%gto_basis_set => basis_set_a
     192             :          ELSE
     193           0 :             NULLIFY (basis_set_list(ikind)%gto_basis_set)
     194             :          END IF
     195             :       END DO
     196             : 
     197           6 :       CALL neighbor_list_iterator_create(nl_iterator, sab_all)
     198          33 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     199             :          CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
     200          27 :                                 iatom=iatom, jatom=jatom, r=rab)
     201             : 
     202          27 :          basis_set_a => basis_set_list(ikind)%gto_basis_set
     203          27 :          basis_set_b => basis_set_list(jkind)%gto_basis_set
     204          27 :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
     205          27 :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
     206             : 
     207             :          ASSOCIATE ( &
     208             :             ! basis ikind
     209             :             first_sgfa => basis_set_a%first_sgf, &
     210             :             la_max => basis_set_a%lmax, &
     211             :             la_min => basis_set_a%lmin, &
     212             :             npgfa => basis_set_a%npgf, &
     213             :             nsgfa => basis_set_a%nsgf_set, &
     214             :             rpgfa => basis_set_a%pgf_radius, &
     215             :             set_radius_a => basis_set_a%set_radius, &
     216             :             sphi_a => basis_set_a%sphi, &
     217             :             zeta => basis_set_a%zet, &
     218             :             ! basis jkind, &
     219             :             first_sgfb => basis_set_b%first_sgf, &
     220             :             lb_max => basis_set_b%lmax, &
     221             :             lb_min => basis_set_b%lmin, &
     222             :             npgfb => basis_set_b%npgf, &
     223             :             nsgfb => basis_set_b%nsgf_set, &
     224             :             rpgfb => basis_set_b%pgf_radius, &
     225             :             set_radius_b => basis_set_b%set_radius, &
     226             :             sphi_b => basis_set_b%sphi, &
     227             :             zetb => basis_set_b%zet)
     228             : 
     229          27 :             nseta = basis_set_a%nset
     230          27 :             nsetb = basis_set_b%nset
     231             : 
     232          18 :             IF (inode == 1) last_jatom = 0
     233             : 
     234             :             ! this guarantees minimum image convention
     235             :             ! anything else would not make sense
     236          27 :             IF (jatom == last_jatom) THEN
     237             :                CYCLE
     238             :             END IF
     239             : 
     240          27 :             last_jatom = jatom
     241             : 
     242          27 :             irow = iatom
     243          27 :             icol = jatom
     244             : 
     245         108 :             DO i = 1, 3
     246         351 :             DO j = 1, 3
     247         243 :                NULLIFY (mint(i, j)%block)
     248             :                CALL dbcsr_get_block_p(matrix=difdip(i, j)%matrix, &
     249             :                                       row=irow, col=icol, BLOCK=mint(i, j)%block, &
     250         243 :                                       found=found)
     251         243 :                CPASSERT(found)
     252        2025 :                mint(i, j)%block = 0._dp
     253             :             END DO
     254             :             END DO
     255             : 
     256             :             ! With and without MIC, rab(:) is the vector giving us the coordinates of rb.
     257          27 :             ra = pbc(particle_set(iatom)%r(:), cell)
     258         108 :             rb(:) = ra(:) + rab(:)
     259          27 :             rac = pbc(rc, ra, cell)
     260         108 :             rbc = rac + rab
     261         108 :             dab = norm2(rab)
     262             : 
     263          81 :             DO iset = 1, nseta
     264          27 :                ncoa = npgfa(iset)*ncoset(la_max(iset))
     265          27 :                sgfa = first_sgfa(1, iset)
     266          81 :                DO jset = 1, nsetb
     267          27 :                   IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
     268          27 :                   ncob = npgfb(jset)*ncoset(lb_max(jset))
     269          27 :                   sgfb = first_sgfb(1, jset)
     270          27 :                   ldab = MAX(ncoa, ncob)
     271          27 :                   lda = ncoset(la_max(iset))*npgfa(iset)
     272          27 :                   ldb = ncoset(lb_max(jset))*npgfb(jset)
     273         162 :                   ALLOCATE (difmab(lda, ldb, M_dim, 3))
     274             : 
     275             :                   ! Calculate integral difmab(beta, alpha) = (a|r_beta|db_alpha)
     276             :                   ! difmab(beta, alpha) = < a | r_beta | ∂_alpha b >
     277             :                   ! difmab(j, idir) = < a | r_j | ∂_idir b >
     278             :                   CALL diff_momop_velocity(la_max(iset), npgfa(iset), zeta(:, iset), &
     279             :                                            rpgfa(:, iset), la_min(iset), lb_max(jset), npgfb(jset), &
     280             :                                            zetb(:, jset), rpgfb(:, jset), lb_min(jset), order, rac, rbc, &
     281          27 :                                            difmab, lambda=lambda, iatom=iatom, jatom=jatom)
     282             : 
     283             :                   !                  *** Contraction step ***
     284             : 
     285         108 :                   DO idir = 1, 3 ! derivative of AO function
     286         351 :                   DO j = 1, 3     ! position operator r_j
     287             :                      CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
     288             :                                 1.0_dp, difmab(1, 1, j, idir), SIZE(difmab, 1), &
     289             :                                 sphi_b(1, sgfb), SIZE(sphi_b, 1), &
     290         243 :                                 0.0_dp, work(1, 1), SIZE(work, 1))
     291             : 
     292             :                      CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
     293             :                                 1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
     294             :                                 work(1, 1), SIZE(work, 1), &
     295             :                                 1.0_dp, mint(j, idir)%block(sgfa, sgfb), &
     296         324 :                                 SIZE(mint(j, idir)%block, 1))
     297             :                   END DO !j
     298             :                   END DO !idir
     299          54 :                   DEALLOCATE (difmab)
     300             :                END DO !jset
     301             :             END DO !iset
     302             :          END ASSOCIATE
     303             :       END DO!iterator
     304             : 
     305           6 :       CALL neighbor_list_iterator_release(nl_iterator)
     306             : 
     307          24 :       DO i = 1, 3
     308          78 :       DO j = 1, 3
     309          72 :          NULLIFY (mint(i, j)%block)
     310             :       END DO
     311             :       END DO
     312             : 
     313           6 :       DEALLOCATE (mab, difmab2, basis_set_list, work, mint, mint2)
     314             : 
     315           6 :       CALL timestop(handle)
     316          18 :    END SUBROUTINE dipole_velocity_deriv
     317             : 
     318             : ! **************************************************************************************************
     319             : !> \brief Builds the moments for the derivative of the overlap with respect to nuclear velocities
     320             : !> \param qs_env ...
     321             : !> \param moments ...
     322             : !> \param nmoments ...
     323             : !> \param ref_point ...
     324             : !> \param ref_points ...
     325             : !> \param basis_type ...
     326             : !> \author Edward Ditler
     327             : ! **************************************************************************************************
     328           6 :    SUBROUTINE build_dsdv_moments(qs_env, moments, nmoments, ref_point, ref_points, basis_type)
     329             : 
     330             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     331             :       TYPE(dbcsr_p_type), DIMENSION(:)                   :: moments
     332             :       INTEGER, INTENT(IN)                                :: nmoments
     333             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL  :: ref_point
     334             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN), &
     335             :          OPTIONAL                                        :: ref_points
     336             :       CHARACTER(len=*), OPTIONAL                         :: basis_type
     337             : 
     338             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'build_dsdv_moments'
     339             : 
     340             :       INTEGER :: handle, i, iatom, icol, ikind, inode, irow, iset, jatom, jkind, jset, last_jatom, &
     341             :          maxco, maxsgf, natom, ncoa, ncob, nkind, nm, nseta, nsetb, sgfa, sgfb
     342             :       INTEGER, DIMENSION(3)                              :: image_cell
     343             :       LOGICAL                                            :: found
     344             :       REAL(KIND=dp)                                      :: dab
     345           6 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: work
     346           6 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: mab
     347             :       REAL(KIND=dp), DIMENSION(3)                        :: ra, rab, rac, rb, rbc, rc
     348           6 :       TYPE(block_p_type), ALLOCATABLE, DIMENSION(:)      :: mint
     349             :       TYPE(cell_type), POINTER                           :: cell
     350           6 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
     351             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
     352             :       TYPE(neighbor_list_iterator_p_type), &
     353           6 :          DIMENSION(:), POINTER                           :: nl_iterator
     354             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     355           6 :          POINTER                                         :: sab_orb
     356           6 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     357           6 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     358             :       TYPE(qs_kind_type), POINTER                        :: qs_kind
     359             : 
     360           6 :       IF (nmoments < 1) RETURN
     361             : 
     362           6 :       CALL timeset(routineN, handle)
     363             : 
     364           6 :       NULLIFY (qs_kind_set, cell, particle_set, sab_orb)
     365             : 
     366           6 :       nm = (6 + 11*nmoments + 6*nmoments**2 + nmoments**3)/6 - 1
     367           6 :       CPASSERT(SIZE(moments) >= nm)
     368             : 
     369           6 :       NULLIFY (qs_kind_set, particle_set, sab_orb, cell)
     370             :       CALL get_qs_env(qs_env=qs_env, &
     371             :                       qs_kind_set=qs_kind_set, &
     372             :                       particle_set=particle_set, cell=cell, &
     373           6 :                       sab_orb=sab_orb)
     374             : 
     375           6 :       nkind = SIZE(qs_kind_set)
     376           6 :       natom = SIZE(particle_set)
     377             : 
     378             :       ! Allocate work storage
     379             :       CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
     380             :                            maxco=maxco, maxsgf=maxsgf, &
     381          12 :                            basis_type=basis_type)
     382             : 
     383          30 :       ALLOCATE (mab(maxco, maxco, nm))
     384        4920 :       mab(:, :, :) = 0.0_dp
     385             : 
     386          24 :       ALLOCATE (work(maxco, maxsgf))
     387         414 :       work(:, :) = 0.0_dp
     388             : 
     389          36 :       ALLOCATE (mint(nm))
     390          24 :       DO i = 1, nm
     391          24 :          NULLIFY (mint(i)%block)
     392             :       END DO
     393             : 
     394          30 :       ALLOCATE (basis_set_list(nkind))
     395          18 :       DO ikind = 1, nkind
     396          12 :          qs_kind => qs_kind_set(ikind)
     397          12 :          CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a, basis_type=basis_type)
     398          18 :          IF (ASSOCIATED(basis_set_a)) THEN
     399          12 :             basis_set_list(ikind)%gto_basis_set => basis_set_a
     400             :          ELSE
     401           0 :             NULLIFY (basis_set_list(ikind)%gto_basis_set)
     402             :          END IF
     403             :       END DO
     404           6 :       CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
     405          24 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     406             :          CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
     407          18 :                                 iatom=iatom, jatom=jatom, r=rab, cell=image_cell)
     408          18 :          basis_set_a => basis_set_list(ikind)%gto_basis_set
     409          18 :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
     410          18 :          basis_set_b => basis_set_list(jkind)%gto_basis_set
     411          18 :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
     412             :          ! basis ikind
     413             :          ASSOCIATE ( &
     414             :             first_sgfa => basis_set_a%first_sgf, &
     415             :             la_max => basis_set_a%lmax, &
     416             :             la_min => basis_set_a%lmin, &
     417             :             npgfa => basis_set_a%npgf, &
     418             :             nsgfa => basis_set_a%nsgf_set, &
     419             :             rpgfa => basis_set_a%pgf_radius, &
     420             :             set_radius_a => basis_set_a%set_radius, &
     421             :             sphi_a => basis_set_a%sphi, &
     422             :             zeta => basis_set_a%zet, &
     423             :             ! basis jkind, &
     424             :             first_sgfb => basis_set_b%first_sgf, &
     425             :             lb_max => basis_set_b%lmax, &
     426             :             lb_min => basis_set_b%lmin, &
     427             :             npgfb => basis_set_b%npgf, &
     428             :             nsgfb => basis_set_b%nsgf_set, &
     429             :             rpgfb => basis_set_b%pgf_radius, &
     430             :             set_radius_b => basis_set_b%set_radius, &
     431             :             sphi_b => basis_set_b%sphi, &
     432             :             zetb => basis_set_b%zet)
     433             : 
     434          18 :             nseta = basis_set_a%nset
     435          18 :             nsetb = basis_set_b%nset
     436             : 
     437          15 :             IF (inode == 1) last_jatom = 0
     438             : 
     439             :             ! this guarantees minimum image convention
     440             :             ! anything else would not make sense
     441          18 :             IF (jatom == last_jatom) THEN
     442             :                CYCLE
     443             :             END IF
     444             : 
     445          18 :             last_jatom = jatom
     446             : 
     447          18 :             IF (iatom <= jatom) THEN
     448          12 :                irow = iatom
     449          12 :                icol = jatom
     450             :             ELSE
     451           6 :                irow = jatom
     452           6 :                icol = iatom
     453             :             END IF
     454             : 
     455          72 :             DO i = 1, nm
     456          54 :                NULLIFY (mint(i)%block)
     457             :                CALL dbcsr_get_block_p(matrix=moments(i)%matrix, &
     458          54 :                                       row=irow, col=icol, BLOCK=mint(i)%block, found=found)
     459         396 :                mint(i)%block = 0._dp
     460             :             END DO
     461             : 
     462             :             ! fold atomic position back into unit cell
     463          18 :             IF (PRESENT(ref_points)) THEN
     464           0 :                rc(:) = 0.5_dp*(ref_points(:, iatom) + ref_points(:, jatom))
     465          18 :             ELSE IF (PRESENT(ref_point)) THEN
     466          72 :                rc(:) = ref_point(:)
     467             :             ELSE
     468           0 :                rc(:) = 0._dp
     469             :             END IF
     470             :             ! using PBC here might screw a molecule that fits the box (but e.g. hasn't been shifted by center_molecule)
     471             :             ! by folding around the center, such screwing can be avoided for a proper choice of center.
     472             :             ! we dont use PBC at this point
     473             : 
     474             :             ! With and without MIC, rab(:) is the vector giving us the coordinates of rb.
     475          72 :             ra(:) = particle_set(iatom)%r(:)
     476          72 :             rb(:) = ra(:) + rab(:)
     477          18 :             rac = pbc(rc, ra, cell)
     478          72 :             rbc = rac + rab
     479             : 
     480          72 :             dab = NORM2(rab)
     481             : 
     482          54 :             DO iset = 1, nseta
     483             : 
     484          18 :                ncoa = npgfa(iset)*ncoset(la_max(iset))
     485          18 :                sgfa = first_sgfa(1, iset)
     486             : 
     487          54 :                DO jset = 1, nsetb
     488             : 
     489          18 :                   IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
     490             : 
     491          18 :                   ncob = npgfb(jset)*ncoset(lb_max(jset))
     492          18 :                   sgfb = first_sgfb(1, jset)
     493             : 
     494             :                   ! Calculate the primitive integrals
     495             :                   CALL moment(la_max(iset), npgfa(iset), zeta(:, iset), &
     496             :                               rpgfa(:, iset), la_min(iset), &
     497             :                               lb_max(jset), npgfb(jset), zetb(:, jset), &
     498          18 :                               rpgfb(:, jset), nmoments, rac, rbc, mab)
     499             : 
     500             :                   ! Contraction step
     501          90 :                   DO i = 1, nm
     502             : 
     503             :                      CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
     504             :                                 1.0_dp, mab(1, 1, i), SIZE(mab, 1), &
     505             :                                 sphi_b(1, sgfb), SIZE(sphi_b, 1), &
     506          54 :                                 0.0_dp, work(1, 1), SIZE(work, 1))
     507             : 
     508          72 :                      IF (iatom <= jatom) THEN
     509             : 
     510             :                         CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
     511             :                                    1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
     512             :                                    work(1, 1), SIZE(work, 1), &
     513             :                                    1.0_dp, mint(i)%block(sgfa, sgfb), &
     514          36 :                                    SIZE(mint(i)%block, 1))
     515             : 
     516             :                      ELSE
     517             : 
     518             :                         CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
     519             :                                    1.0_dp, work(1, 1), SIZE(work, 1), &
     520             :                                    sphi_a(1, sgfa), SIZE(sphi_a, 1), &
     521             :                                    1.0_dp, mint(i)%block(sgfb, sgfa), &
     522          18 :                                    SIZE(mint(i)%block, 1))
     523             : 
     524             :                      END IF
     525             : 
     526             :                   END DO
     527             : 
     528             :                END DO
     529             :             END DO
     530             :          END ASSOCIATE
     531             : 
     532             :       END DO ! iterator
     533             : 
     534           6 :       CALL neighbor_list_iterator_release(nl_iterator)
     535             : 
     536             :       ! Release work storage
     537           6 :       DEALLOCATE (mab, basis_set_list)
     538           6 :       DEALLOCATE (work)
     539          24 :       DO i = 1, nm
     540          24 :          NULLIFY (mint(i)%block)
     541             :       END DO
     542           6 :       DEALLOCATE (mint)
     543             : 
     544           6 :       CALL timestop(handle)
     545             : 
     546          12 :    END SUBROUTINE build_dsdv_moments
     547             : 
     548             : ! **************************************************************************************************
     549             : !> \brief ...
     550             : !> \param qs_env ...
     551             : !> \param moments ...
     552             : !> \param nmoments ...
     553             : !> \param ref_point ...
     554             : !> \param ref_points ...
     555             : !> \param basis_type ...
     556             : ! **************************************************************************************************
     557        2586 :    SUBROUTINE build_local_moment_matrix(qs_env, moments, nmoments, ref_point, ref_points, basis_type)
     558             : 
     559             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     560             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: moments
     561             :       INTEGER, INTENT(IN)                                :: nmoments
     562             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL  :: ref_point
     563             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN), &
     564             :          OPTIONAL                                        :: ref_points
     565             :       CHARACTER(len=*), OPTIONAL                         :: basis_type
     566             : 
     567             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'build_local_moment_matrix'
     568             : 
     569             :       INTEGER :: handle, i, iatom, icol, ikind, inode, irow, iset, jatom, jkind, jset, last_jatom, &
     570             :          maxco, maxsgf, natom, ncoa, ncob, nkind, nm, nseta, nsetb, sgfa, sgfb
     571             :       LOGICAL                                            :: found
     572             :       REAL(KIND=dp)                                      :: dab
     573        2586 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: work
     574        2586 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: mab
     575             :       REAL(KIND=dp), DIMENSION(3)                        :: ra, rab, rac, rb, rbc, rc
     576        2586 :       TYPE(block_p_type), ALLOCATABLE, DIMENSION(:)      :: mint
     577             :       TYPE(cell_type), POINTER                           :: cell
     578        2586 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
     579             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
     580             :       TYPE(neighbor_list_iterator_p_type), &
     581        2586 :          DIMENSION(:), POINTER                           :: nl_iterator
     582             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     583        2586 :          POINTER                                         :: sab_orb
     584        2586 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     585        2586 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     586             :       TYPE(qs_kind_type), POINTER                        :: qs_kind
     587             : 
     588        2586 :       IF (nmoments < 1) RETURN
     589             : 
     590        2586 :       CALL timeset(routineN, handle)
     591             : 
     592        2586 :       NULLIFY (qs_kind_set, cell, particle_set, sab_orb)
     593             : 
     594        2586 :       nm = (6 + 11*nmoments + 6*nmoments**2 + nmoments**3)/6 - 1
     595        2586 :       CPASSERT(SIZE(moments) >= nm)
     596             : 
     597        2586 :       NULLIFY (qs_kind_set, particle_set, sab_orb, cell)
     598             :       CALL get_qs_env(qs_env=qs_env, &
     599             :                       qs_kind_set=qs_kind_set, &
     600             :                       particle_set=particle_set, cell=cell, &
     601        2586 :                       sab_orb=sab_orb)
     602             : 
     603        2586 :       nkind = SIZE(qs_kind_set)
     604        2586 :       natom = SIZE(particle_set)
     605             : 
     606             :       ! Allocate work storage
     607             :       CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
     608             :                            maxco=maxco, maxsgf=maxsgf, &
     609        5066 :                            basis_type=basis_type)
     610             : 
     611       12930 :       ALLOCATE (mab(maxco, maxco, nm))
     612     2888802 :       mab(:, :, :) = 0.0_dp
     613             : 
     614       10344 :       ALLOCATE (work(maxco, maxsgf))
     615      466396 :       work(:, :) = 0.0_dp
     616             : 
     617       15662 :       ALLOCATE (mint(nm))
     618       10490 :       DO i = 1, nm
     619       10490 :          NULLIFY (mint(i)%block)
     620             :       END DO
     621             : 
     622       13006 :       ALLOCATE (basis_set_list(nkind))
     623        7834 :       DO ikind = 1, nkind
     624        5248 :          qs_kind => qs_kind_set(ikind)
     625        5248 :          CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a, basis_type=basis_type)
     626        7834 :          IF (ASSOCIATED(basis_set_a)) THEN
     627        5248 :             basis_set_list(ikind)%gto_basis_set => basis_set_a
     628             :          ELSE
     629           0 :             NULLIFY (basis_set_list(ikind)%gto_basis_set)
     630             :          END IF
     631             :       END DO
     632        2586 :       CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
     633       30650 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     634             :          CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
     635       28064 :                                 iatom=iatom, jatom=jatom, r=rab)
     636       28064 :          basis_set_a => basis_set_list(ikind)%gto_basis_set
     637       28064 :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
     638       28064 :          basis_set_b => basis_set_list(jkind)%gto_basis_set
     639       28064 :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
     640             :          ASSOCIATE ( &
     641             :             ! basis ikind
     642             :             first_sgfa => basis_set_a%first_sgf, &
     643             :             la_max => basis_set_a%lmax, &
     644             :             la_min => basis_set_a%lmin, &
     645             :             npgfa => basis_set_a%npgf, &
     646             :             nsgfa => basis_set_a%nsgf_set, &
     647             :             rpgfa => basis_set_a%pgf_radius, &
     648             :             set_radius_a => basis_set_a%set_radius, &
     649             :             sphi_a => basis_set_a%sphi, &
     650             :             zeta => basis_set_a%zet, &
     651             :             ! basis jkind, &
     652             :             first_sgfb => basis_set_b%first_sgf, &
     653             :             lb_max => basis_set_b%lmax, &
     654             :             lb_min => basis_set_b%lmin, &
     655             :             npgfb => basis_set_b%npgf, &
     656             :             nsgfb => basis_set_b%nsgf_set, &
     657             :             rpgfb => basis_set_b%pgf_radius, &
     658             :             set_radius_b => basis_set_b%set_radius, &
     659             :             sphi_b => basis_set_b%sphi, &
     660             :             zetb => basis_set_b%zet)
     661             : 
     662       28064 :             nseta = basis_set_a%nset
     663       28064 :             nsetb = basis_set_b%nset
     664             : 
     665        6702 :             IF (inode == 1) last_jatom = 0
     666             : 
     667             :             ! this guarantees minimum image convention
     668             :             ! anything else would not make sense
     669       28064 :             IF (jatom == last_jatom) THEN
     670             :                CYCLE
     671             :             END IF
     672             : 
     673        7984 :             last_jatom = jatom
     674             : 
     675        7984 :             IF (iatom <= jatom) THEN
     676        5199 :                irow = iatom
     677        5199 :                icol = jatom
     678             :             ELSE
     679        2785 :                irow = jatom
     680        2785 :                icol = iatom
     681             :             END IF
     682             : 
     683       32602 :             DO i = 1, nm
     684       24618 :                NULLIFY (mint(i)%block)
     685             :                CALL dbcsr_get_block_p(matrix=moments(i)%matrix, &
     686       24618 :                                       row=irow, col=icol, BLOCK=mint(i)%block, found=found)
     687     1304924 :                mint(i)%block = 0._dp
     688             :             END DO
     689             : 
     690             :             ! fold atomic position back into unit cell
     691        7984 :             IF (PRESENT(ref_points)) THEN
     692           0 :                rc(:) = 0.5_dp*(ref_points(:, iatom) + ref_points(:, jatom))
     693        7984 :             ELSE IF (PRESENT(ref_point)) THEN
     694       29408 :                rc(:) = ref_point(:)
     695             :             ELSE
     696         632 :                rc(:) = 0._dp
     697             :             END IF
     698             :             ! using PBC here might screw a molecule that fits the box (but e.g. hasn't been shifted by center_molecule)
     699             :             ! by folding around the center, such screwing can be avoided for a proper choice of center.
     700       63872 :             ra(:) = pbc(particle_set(iatom)%r(:) - rc, cell) + rc
     701       63872 :             rb(:) = pbc(particle_set(jatom)%r(:) - rc, cell) + rc
     702             :             ! we dont use PBC at this point
     703       31936 :             rab(:) = ra(:) - rb(:)
     704       31936 :             rac(:) = ra(:) - rc(:)
     705       31936 :             rbc(:) = rb(:) - rc(:)
     706       31936 :             dab = NORM2(rab)
     707             : 
     708       48728 :             DO iset = 1, nseta
     709             : 
     710       12680 :                ncoa = npgfa(iset)*ncoset(la_max(iset))
     711       12680 :                sgfa = first_sgfa(1, iset)
     712             : 
     713       42971 :                DO jset = 1, nsetb
     714             : 
     715       22307 :                   IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
     716             : 
     717       22226 :                   ncob = npgfb(jset)*ncoset(lb_max(jset))
     718       22226 :                   sgfb = first_sgfb(1, jset)
     719             : 
     720             :                   ! Calculate the primitive integrals
     721             :                   CALL moment(la_max(iset), npgfa(iset), zeta(:, iset), &
     722             :                               rpgfa(:, iset), la_min(iset), &
     723             :                               lb_max(jset), npgfb(jset), zetb(:, jset), &
     724       22226 :                               rpgfb(:, jset), nmoments, rac, rbc, mab)
     725             : 
     726             :                   ! Contraction step
     727      104428 :                   DO i = 1, nm
     728             : 
     729             :                      CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
     730             :                                 1.0_dp, mab(1, 1, i), SIZE(mab, 1), &
     731             :                                 sphi_b(1, sgfb), SIZE(sphi_b, 1), &
     732       69522 :                                 0.0_dp, work(1, 1), SIZE(work, 1))
     733             : 
     734       91829 :                      IF (iatom <= jatom) THEN
     735             : 
     736             :                         CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
     737             :                                    1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
     738             :                                    work(1, 1), SIZE(work, 1), &
     739             :                                    1.0_dp, mint(i)%block(sgfa, sgfb), &
     740       45643 :                                    SIZE(mint(i)%block, 1))
     741             : 
     742             :                      ELSE
     743             : 
     744             :                         CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
     745             :                                    1.0_dp, work(1, 1), SIZE(work, 1), &
     746             :                                    sphi_a(1, sgfa), SIZE(sphi_a, 1), &
     747             :                                    1.0_dp, mint(i)%block(sgfb, sgfa), &
     748       23879 :                                    SIZE(mint(i)%block, 1))
     749             : 
     750             :                      END IF
     751             : 
     752             :                   END DO
     753             : 
     754             :                END DO
     755             :             END DO
     756             :          END ASSOCIATE
     757             : 
     758             :       END DO
     759        2586 :       CALL neighbor_list_iterator_release(nl_iterator)
     760             : 
     761             :       ! Release work storage
     762        2586 :       DEALLOCATE (mab, basis_set_list)
     763        2586 :       DEALLOCATE (work)
     764       10490 :       DO i = 1, nm
     765       10490 :          NULLIFY (mint(i)%block)
     766             :       END DO
     767        2586 :       DEALLOCATE (mint)
     768             : 
     769        2586 :       CALL timestop(handle)
     770             : 
     771        5172 :    END SUBROUTINE build_local_moment_matrix
     772             : 
     773             : ! **************************************************************************************************
     774             : !> \brief Calculate right-hand sided derivatives of multipole moments, e. g. < a | xy d/dz | b >
     775             : !>        Optionally stores the multipole moments themselves for free.
     776             : !>        Note that the multipole moments are symmetric while their derivatives are anti-symmetric
     777             : !>        Only first derivatives are performed, e. g. x d/dy
     778             : !> \param qs_env ...
     779             : !> \param moments_der will contain the derivatives of the multipole moments
     780             : !> \param nmoments_der order of the moments with derivatives
     781             : !> \param nmoments order of the multipole moments (no derivatives, same output as
     782             : !>        build_local_moment_matrix, needs moments as arguments to store results)
     783             : !> \param ref_point ...
     784             : !> \param moments contains the multipole moments, optionally for free, up to order nmoments
     785             : !> \note
     786             : !>        Adapted from rRc_xyz_der_ao in qs_operators_ao
     787             : ! **************************************************************************************************
     788          30 :    SUBROUTINE build_local_moments_der_matrix(qs_env, moments_der, nmoments_der, nmoments, &
     789          30 :                                              ref_point, moments)
     790             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     791             :       TYPE(dbcsr_p_type), DIMENSION(:, :), &
     792             :          INTENT(INOUT), POINTER                          :: moments_der
     793             :       INTEGER, INTENT(IN)                                :: nmoments_der, nmoments
     794             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL  :: ref_point
     795             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT), &
     796             :          OPTIONAL, POINTER                               :: moments
     797             : 
     798             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'build_local_moments_der_matrix'
     799             : 
     800             :       INTEGER :: dimders, handle, i, iatom, icol, ider, ii, ikind, inode, ipgf, irow, iset, j, &
     801             :          jatom, jkind, jpgf, jset, last_jatom, M_dim, maxco, maxsgf, na, nb, ncoa, ncob, nda, ndb, &
     802             :          nders, nkind, nm, nmom_build, nseta, nsetb, sgfa, sgfb
     803             :       LOGICAL                                            :: found
     804             :       REAL(KIND=dp)                                      :: dab
     805          30 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: work
     806          30 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: mab
     807          30 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :, :)  :: difmab
     808             :       REAL(KIND=dp), DIMENSION(3)                        :: ra, rab, rac, rb, rbc, rc
     809          30 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: mab_tmp
     810          30 :       TYPE(block_p_type), ALLOCATABLE, DIMENSION(:)      :: mom_block
     811          30 :       TYPE(block_p_type), ALLOCATABLE, DIMENSION(:, :)   :: mom_block_der
     812             :       TYPE(cell_type), POINTER                           :: cell
     813          30 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
     814             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
     815             :       TYPE(neighbor_list_iterator_p_type), &
     816          30 :          DIMENSION(:), POINTER                           :: nl_iterator
     817             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     818          30 :          POINTER                                         :: sab_orb
     819          30 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     820          30 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     821             :       TYPE(qs_kind_type), POINTER                        :: qs_kind
     822             : 
     823          30 :       nmom_build = MAX(nmoments, nmoments_der)      ! build moments up to order nmom_buiod
     824          30 :       IF (nmom_build < 1) RETURN
     825             : 
     826          30 :       CALL timeset(routineN, handle)
     827             : 
     828          30 :       nders = 1                                    ! only first order derivatives
     829          30 :       dimders = ncoset(nders) - 1
     830             : 
     831          30 :       NULLIFY (qs_kind_set, particle_set, sab_orb, cell)
     832             :       CALL get_qs_env(qs_env=qs_env, &
     833             :                       qs_kind_set=qs_kind_set, &
     834             :                       particle_set=particle_set, &
     835             :                       cell=cell, &
     836          30 :                       sab_orb=sab_orb)
     837             : 
     838          30 :       nkind = SIZE(qs_kind_set)
     839             : 
     840             :       ! Work storage
     841             :       CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
     842          30 :                            maxco=maxco, maxsgf=maxsgf)
     843             : 
     844          30 :       IF (nmoments > 0) THEN
     845          28 :          CPASSERT(PRESENT(moments))
     846          28 :          nm = (6 + 11*nmoments + 6*nmoments**2 + nmoments**3)/6 - 1
     847          28 :          CPASSERT(SIZE(moments) == nm)
     848             :          ! storage for integrals
     849         140 :          ALLOCATE (mab(maxco, maxco, nm))
     850             :          ! blocks
     851      272620 :          mab(:, :, :) = 0.0_dp
     852         336 :          ALLOCATE (mom_block(nm))
     853         280 :          DO i = 1, nm
     854         280 :             NULLIFY (mom_block(i)%block)
     855             :          END DO
     856             :       END IF
     857             : 
     858          30 :       IF (nmoments_der > 0) THEN
     859          30 :          M_dim = ncoset(nmoments_der) - 1
     860          30 :          CPASSERT(SIZE(moments_der, dim=1) == M_dim)
     861          30 :          CPASSERT(SIZE(moments_der, dim=2) == dimders)
     862             :          ! storage for integrals
     863         180 :          ALLOCATE (difmab(maxco, maxco, M_dim, dimders))
     864      287454 :          difmab(:, :, :, :) = 0.0_dp
     865             :          ! blocks
     866         516 :          ALLOCATE (mom_block_der(M_dim, dimders))
     867         132 :          DO i = 1, M_dim
     868         438 :             DO ider = 1, dimders
     869         408 :                NULLIFY (mom_block_der(i, ider)%block)
     870             :             END DO
     871             :          END DO
     872             :       END IF
     873             : 
     874         120 :       ALLOCATE (work(maxco, maxsgf))
     875        6254 :       work(:, :) = 0.0_dp
     876             : 
     877          30 :       NULLIFY (basis_set_a, basis_set_b, basis_set_list)
     878          30 :       NULLIFY (qs_kind)
     879         128 :       ALLOCATE (basis_set_list(nkind))
     880          68 :       DO ikind = 1, nkind
     881          38 :          qs_kind => qs_kind_set(ikind)
     882          38 :          CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a)
     883          68 :          IF (ASSOCIATED(basis_set_a)) THEN
     884          38 :             basis_set_list(ikind)%gto_basis_set => basis_set_a
     885             :          ELSE
     886           0 :             NULLIFY (basis_set_list(ikind)%gto_basis_set)
     887             :          END IF
     888             :       END DO
     889             : 
     890             :       ! Calculate derivatives looping over neighbour list
     891          30 :       NULLIFY (nl_iterator)
     892          30 :       CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
     893         213 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     894             :          CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
     895         183 :                                 iatom=iatom, jatom=jatom, r=rab)
     896         183 :          basis_set_a => basis_set_list(ikind)%gto_basis_set
     897         183 :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
     898         183 :          basis_set_b => basis_set_list(jkind)%gto_basis_set
     899         183 :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
     900             :          ASSOCIATE ( &
     901             :             ! basis ikind
     902             :             first_sgfa => basis_set_a%first_sgf, &
     903             :             la_max => basis_set_a%lmax, &
     904             :             la_min => basis_set_a%lmin, &
     905             :             npgfa => basis_set_a%npgf, &
     906             :             nsgfa => basis_set_a%nsgf_set, &
     907             :             rpgfa => basis_set_a%pgf_radius, &
     908             :             set_radius_a => basis_set_a%set_radius, &
     909             :             sphi_a => basis_set_a%sphi, &
     910             :             zeta => basis_set_a%zet, &
     911             :             ! basis jkind, &
     912             :             first_sgfb => basis_set_b%first_sgf, &
     913             :             lb_max => basis_set_b%lmax, &
     914             :             lb_min => basis_set_b%lmin, &
     915             :             npgfb => basis_set_b%npgf, &
     916             :             nsgfb => basis_set_b%nsgf_set, &
     917             :             rpgfb => basis_set_b%pgf_radius, &
     918             :             set_radius_b => basis_set_b%set_radius, &
     919             :             sphi_b => basis_set_b%sphi, &
     920             :             zetb => basis_set_b%zet)
     921             : 
     922         183 :             nseta = basis_set_a%nset
     923         183 :             nsetb = basis_set_b%nset
     924             : 
     925             :             ! reference point
     926         183 :             IF (PRESENT(ref_point)) THEN
     927         732 :                rc(:) = ref_point(:)
     928             :             ELSE
     929           0 :                rc(:) = 0._dp
     930             :             END IF
     931             :             ! using PBC here might screw a molecule that fits the box (but e.g. hasn't been shifted by center_molecule)
     932             :             ! by folding around the center, such screwing can be avoided for a proper choice of center.
     933        1464 :             ra(:) = pbc(particle_set(iatom)%r(:) - rc, cell) + rc
     934        1464 :             rb(:) = pbc(particle_set(jatom)%r(:) - rc, cell) + rc
     935             :             ! we dont use PBC at this point
     936         732 :             rab(:) = ra(:) - rb(:)
     937         732 :             rac(:) = ra(:) - rc(:)
     938         732 :             rbc(:) = rb(:) - rc(:)
     939         732 :             dab = NORM2(rab)
     940             : 
     941             :             ! get blocks
     942         183 :             IF (inode == 1) last_jatom = 0
     943             : 
     944         183 :             IF (jatom == last_jatom) THEN
     945             :                CYCLE
     946             :             END IF
     947             : 
     948          57 :             last_jatom = jatom
     949             : 
     950          57 :             IF (iatom <= jatom) THEN
     951          38 :                irow = iatom
     952          38 :                icol = jatom
     953             :             ELSE
     954          19 :                irow = jatom
     955          19 :                icol = iatom
     956             :             END IF
     957             : 
     958          57 :             IF (nmoments > 0) THEN
     959         510 :                DO i = 1, nm
     960         459 :                   NULLIFY (mom_block(i)%block)
     961             :                   ! get block from pre calculated overlap matrix
     962             :                   CALL dbcsr_get_block_p(matrix=moments(i)%matrix, &
     963         459 :                                          row=irow, col=icol, BLOCK=mom_block(i)%block, found=found)
     964         459 :                   CPASSERT(found .AND. ASSOCIATED(mom_block(i)%block))
     965       21003 :                   mom_block(i)%block = 0._dp
     966             :                END DO
     967             :             END IF
     968          57 :             IF (nmoments_der > 0) THEN
     969         264 :                DO i = 1, M_dim
     970         885 :                   DO ider = 1, dimders
     971         621 :                      NULLIFY (mom_block_der(i, ider)%block)
     972             :                      CALL dbcsr_get_block_p(matrix=moments_der(i, ider)%matrix, &
     973             :                                             row=irow, col=icol, &
     974             :                                             block=mom_block_der(i, ider)%block, &
     975         621 :                                             found=found)
     976         621 :                      CPASSERT(found .AND. ASSOCIATED(mom_block_der(i, ider)%block))
     977       22455 :                      mom_block_der(i, ider)%block = 0._dp
     978             :                   END DO
     979             :                END DO
     980             :             END IF
     981             : 
     982         330 :             DO iset = 1, nseta
     983             : 
     984          90 :                ncoa = npgfa(iset)*ncoset(la_max(iset))
     985          90 :                sgfa = first_sgfa(1, iset)
     986             : 
     987         303 :                DO jset = 1, nsetb
     988             : 
     989         156 :                   IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
     990             : 
     991         156 :                   ncob = npgfb(jset)*ncoset(lb_max(jset))
     992         156 :                   sgfb = first_sgfb(1, jset)
     993             : 
     994         156 :                   NULLIFY (mab_tmp)
     995             :                   ALLOCATE (mab_tmp(npgfa(iset)*ncoset(la_max(iset) + 1), &
     996         780 :                                     npgfb(jset)*ncoset(lb_max(jset) + 1), ncoset(nmom_build) - 1))
     997             : 
     998             :                   ! Calculate the primitive integrals (need l+1 for derivatives)
     999             :                   CALL moment(la_max(iset) + 1, npgfa(iset), zeta(:, iset), &
    1000             :                               rpgfa(:, iset), la_min(iset), &
    1001             :                               lb_max(jset) + 1, npgfb(jset), zetb(:, jset), &
    1002         156 :                               rpgfb(:, jset), nmom_build, rac, rbc, mab_tmp)
    1003             : 
    1004         156 :                   IF (nmoments_der > 0) THEN
    1005             :                      CALL diff_momop(la_max(iset), npgfa(iset), zeta(:, iset), &
    1006             :                                      rpgfa(:, iset), la_min(iset), &
    1007             :                                      lb_max(jset), npgfb(jset), zetb(:, jset), &
    1008             :                                      rpgfb(:, jset), lb_min(jset), &
    1009         156 :                                      nmoments_der, rac, rbc, difmab, mab_ext=mab_tmp)
    1010             :                   END IF
    1011             : 
    1012         156 :                   IF (nmoments > 0) THEN
    1013             :                      ! copy subset of mab_tmp (l+1) to mab (l)
    1014      830400 :                      mab = 0.0_dp
    1015        1500 :                      DO ii = 1, nm
    1016        1350 :                         na = 0
    1017        1350 :                         nda = 0
    1018        5604 :                         DO ipgf = 1, npgfa(iset)
    1019        4104 :                            nb = 0
    1020        4104 :                            ndb = 0
    1021       19467 :                            DO jpgf = 1, npgfb(jset)
    1022       74871 :                               DO j = 1, ncoset(lb_max(jset))
    1023      395523 :                                  DO i = 1, ncoset(la_max(iset))
    1024      380160 :                                     mab(i + na, j + nb, ii) = mab_tmp(i + nda, j + ndb, ii)
    1025             :                                  END DO ! i
    1026             :                               END DO ! j
    1027       15363 :                               nb = nb + ncoset(lb_max(jset))
    1028       19467 :                               ndb = ndb + ncoset(lb_max(jset) + 1)
    1029             :                            END DO ! jpgf
    1030        4104 :                            na = na + ncoset(la_max(iset))
    1031        5454 :                            nda = nda + ncoset(la_max(iset) + 1)
    1032             :                         END DO ! ipgf
    1033             :                      END DO
    1034             :                      ! Contraction step
    1035        1500 :                      DO i = 1, nm
    1036             : 
    1037             :                         CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
    1038             :                                    1.0_dp, mab(1, 1, i), SIZE(mab, 1), &
    1039             :                                    sphi_b(1, sgfb), SIZE(sphi_b, 1), &
    1040        1350 :                                    0.0_dp, work(1, 1), SIZE(work, 1))
    1041             : 
    1042        1500 :                         IF (iatom <= jatom) THEN
    1043             :                            CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
    1044             :                                       1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
    1045             :                                       work(1, 1), SIZE(work, 1), &
    1046             :                                       1.0_dp, mom_block(i)%block(sgfa, sgfb), &
    1047         900 :                                       SIZE(mom_block(i)%block, 1))
    1048             :                         ELSE
    1049             :                            CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
    1050             :                                       1.0_dp, work(1, 1), SIZE(work, 1), &
    1051             :                                       sphi_a(1, sgfa), SIZE(sphi_a, 1), &
    1052             :                                       1.0_dp, mom_block(i)%block(sgfb, sgfa), &
    1053         450 :                                       SIZE(mom_block(i)%block, 1))
    1054             :                         END IF
    1055             :                      END DO
    1056             :                   END IF
    1057             : 
    1058         156 :                   IF (nmoments_der > 0) THEN
    1059         660 :                      DO i = 1, M_dim
    1060        2172 :                         DO ider = 1, dimders
    1061             :                            CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
    1062             :                                       1.0_dp, difmab(1, 1, i, ider), SIZE(difmab, 1), &
    1063             :                                       sphi_b(1, sgfb), SIZE(sphi_b, 1), &
    1064        1512 :                                       0._dp, work(1, 1), SIZE(work, 1))
    1065             : 
    1066        2016 :                            IF (iatom <= jatom) THEN
    1067             :                               CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
    1068             :                                          1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
    1069             :                                          work(1, 1), SIZE(work, 1), &
    1070             :                                          1._dp, mom_block_der(i, ider)%block(sgfa, sgfb), &
    1071        1008 :                                          SIZE(mom_block_der(i, ider)%block, 1))
    1072             :                            ELSE
    1073             :                               CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
    1074             :                                          -1.0_dp, work(1, 1), SIZE(work, 1), &
    1075             :                                          sphi_a(1, sgfa), SIZE(sphi_a, 1), &
    1076             :                                          1.0_dp, mom_block_der(i, ider)%block(sgfb, sgfa), &
    1077         504 :                                          SIZE(mom_block_der(i, ider)%block, 1))
    1078             :                            END IF
    1079             :                         END DO
    1080             :                      END DO
    1081             :                   END IF
    1082         246 :                   DEALLOCATE (mab_tmp)
    1083             :                END DO
    1084             :             END DO
    1085             :          END ASSOCIATE
    1086             :       END DO
    1087          30 :       CALL neighbor_list_iterator_release(nl_iterator)
    1088             : 
    1089             :       ! deallocations
    1090          30 :       DEALLOCATE (basis_set_list)
    1091          30 :       DEALLOCATE (work)
    1092          30 :       IF (nmoments > 0) THEN
    1093          28 :          DEALLOCATE (mab)
    1094         280 :          DO i = 1, nm
    1095         280 :             NULLIFY (mom_block(i)%block)
    1096             :          END DO
    1097          28 :          DEALLOCATE (mom_block)
    1098             :       END IF
    1099          30 :       IF (nmoments_der > 0) THEN
    1100          30 :          DEALLOCATE (difmab)
    1101         132 :          DO i = 1, M_dim
    1102         438 :             DO ider = 1, dimders
    1103         408 :                NULLIFY (mom_block_der(i, ider)%block)
    1104             :             END DO
    1105             :          END DO
    1106          30 :          DEALLOCATE (mom_block_der)
    1107             :       END IF
    1108             : 
    1109          30 :       CALL timestop(handle)
    1110             : 
    1111          90 :    END SUBROUTINE build_local_moments_der_matrix
    1112             : 
    1113             : ! **************************************************************************************************
    1114             : !> \brief ...
    1115             : !> \param qs_env ...
    1116             : !> \param magmom ...
    1117             : !> \param nmoments ...
    1118             : !> \param ref_point ...
    1119             : !> \param ref_points ...
    1120             : !> \param basis_type ...
    1121             : ! **************************************************************************************************
    1122          16 :    SUBROUTINE build_local_magmom_matrix(qs_env, magmom, nmoments, ref_point, ref_points, basis_type)
    1123             : 
    1124             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1125             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: magmom
    1126             :       INTEGER, INTENT(IN)                                :: nmoments
    1127             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL  :: ref_point
    1128             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN), &
    1129             :          OPTIONAL                                        :: ref_points
    1130             :       CHARACTER(len=*), OPTIONAL                         :: basis_type
    1131             : 
    1132             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'build_local_magmom_matrix'
    1133             : 
    1134             :       INTEGER :: handle, i, iatom, icol, ikind, inode, irow, iset, jatom, jkind, jset, maxco, &
    1135             :          maxsgf, natom, ncoa, ncob, nkind, nm, nseta, nsetb, sgfa, sgfb
    1136             :       LOGICAL                                            :: found
    1137             :       REAL(KIND=dp)                                      :: dab
    1138          16 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: work
    1139          16 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: mab
    1140             :       REAL(KIND=dp), DIMENSION(3)                        :: ra, rab, rac, rb, rbc, rc
    1141          16 :       TYPE(block_p_type), ALLOCATABLE, DIMENSION(:)      :: mint
    1142             :       TYPE(cell_type), POINTER                           :: cell
    1143          16 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
    1144          16 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
    1145             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
    1146             :       TYPE(neighbor_list_iterator_p_type), &
    1147          16 :          DIMENSION(:), POINTER                           :: nl_iterator
    1148             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1149          16 :          POINTER                                         :: sab_orb
    1150          16 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1151          16 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1152             :       TYPE(qs_kind_type), POINTER                        :: qs_kind
    1153             : 
    1154          16 :       IF (nmoments < 1) RETURN
    1155             : 
    1156          16 :       CALL timeset(routineN, handle)
    1157             : 
    1158          16 :       NULLIFY (qs_kind_set, cell, particle_set, sab_orb)
    1159          16 :       NULLIFY (matrix_s)
    1160             : 
    1161          16 :       CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s)
    1162             : 
    1163             :       ! magnetic dipoles/angular moments only
    1164          16 :       nm = 3
    1165             : 
    1166          16 :       NULLIFY (qs_kind_set, particle_set, sab_orb, cell)
    1167             :       CALL get_qs_env(qs_env=qs_env, &
    1168             :                       qs_kind_set=qs_kind_set, &
    1169             :                       particle_set=particle_set, cell=cell, &
    1170          16 :                       sab_orb=sab_orb)
    1171             : 
    1172          16 :       nkind = SIZE(qs_kind_set)
    1173          16 :       natom = SIZE(particle_set)
    1174             : 
    1175             :       ! Allocate work storage
    1176             :       CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
    1177          16 :                            maxco=maxco, maxsgf=maxsgf)
    1178             : 
    1179          80 :       ALLOCATE (mab(maxco, maxco, nm))
    1180      210436 :       mab(:, :, :) = 0.0_dp
    1181             : 
    1182          64 :       ALLOCATE (work(maxco, maxsgf))
    1183       13380 :       work(:, :) = 0.0_dp
    1184             : 
    1185          64 :       ALLOCATE (mint(nm))
    1186          64 :       DO i = 1, nm
    1187          64 :          NULLIFY (mint(i)%block)
    1188             :       END DO
    1189             : 
    1190          80 :       ALLOCATE (basis_set_list(nkind))
    1191          48 :       DO ikind = 1, nkind
    1192          32 :          qs_kind => qs_kind_set(ikind)
    1193          64 :          CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a, basis_type=basis_type)
    1194          48 :          IF (ASSOCIATED(basis_set_a)) THEN
    1195          32 :             basis_set_list(ikind)%gto_basis_set => basis_set_a
    1196             :          ELSE
    1197           0 :             NULLIFY (basis_set_list(ikind)%gto_basis_set)
    1198             :          END IF
    1199             :       END DO
    1200          16 :       CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
    1201         175 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
    1202             :          CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
    1203         159 :                                 iatom=iatom, jatom=jatom, r=rab)
    1204         159 :          basis_set_a => basis_set_list(ikind)%gto_basis_set
    1205         159 :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
    1206         159 :          basis_set_b => basis_set_list(jkind)%gto_basis_set
    1207         159 :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
    1208             :          ASSOCIATE ( &
    1209             :             ! basis ikind
    1210             :             first_sgfa => basis_set_a%first_sgf, &
    1211             :             la_max => basis_set_a%lmax, &
    1212             :             la_min => basis_set_a%lmin, &
    1213             :             npgfa => basis_set_a%npgf, &
    1214             :             nsgfa => basis_set_a%nsgf_set, &
    1215             :             rpgfa => basis_set_a%pgf_radius, &
    1216             :             set_radius_a => basis_set_a%set_radius, &
    1217             :             sphi_a => basis_set_a%sphi, &
    1218             :             zeta => basis_set_a%zet, &
    1219             :             ! basis jkind, &
    1220             :             first_sgfb => basis_set_b%first_sgf, &
    1221             :             lb_max => basis_set_b%lmax, &
    1222             :             lb_min => basis_set_b%lmin, &
    1223             :             npgfb => basis_set_b%npgf, &
    1224             :             nsgfb => basis_set_b%nsgf_set, &
    1225             :             rpgfb => basis_set_b%pgf_radius, &
    1226             :             set_radius_b => basis_set_b%set_radius, &
    1227             :             sphi_b => basis_set_b%sphi, &
    1228             :             zetb => basis_set_b%zet)
    1229             : 
    1230         159 :             nseta = basis_set_a%nset
    1231         159 :             nsetb = basis_set_b%nset
    1232             : 
    1233         159 :             IF (iatom <= jatom) THEN
    1234         106 :                irow = iatom
    1235         106 :                icol = jatom
    1236             :             ELSE
    1237          53 :                irow = jatom
    1238          53 :                icol = iatom
    1239             :             END IF
    1240             : 
    1241         636 :             DO i = 1, nm
    1242         477 :                NULLIFY (mint(i)%block)
    1243             :                CALL dbcsr_get_block_p(matrix=magmom(i)%matrix, &
    1244         477 :                                       row=irow, col=icol, BLOCK=mint(i)%block, found=found)
    1245       33123 :                mint(i)%block = 0._dp
    1246        1113 :                CPASSERT(ASSOCIATED(mint(i)%block))
    1247             :             END DO
    1248             : 
    1249             :             ! fold atomic position back into unit cell
    1250         159 :             IF (PRESENT(ref_points)) THEN
    1251           0 :                rc(:) = 0.5_dp*(ref_points(:, iatom) + ref_points(:, jatom))
    1252         159 :             ELSE IF (PRESENT(ref_point)) THEN
    1253         636 :                rc(:) = ref_point(:)
    1254             :             ELSE
    1255           0 :                rc(:) = 0._dp
    1256             :             END IF
    1257             :             ! using PBC here might screw a molecule that fits the box (but e.g. hasn't been shifted by center_molecule)
    1258             :             ! by folding around the center, such screwing can be avoided for a proper choice of center.
    1259        1272 :             ra(:) = pbc(particle_set(iatom)%r(:) - rc, cell) + rc
    1260        1272 :             rb(:) = pbc(particle_set(jatom)%r(:) - rc, cell) + rc
    1261             :             ! we dont use PBC at this point
    1262         636 :             rab(:) = ra(:) - rb(:)
    1263         636 :             rac(:) = ra(:) - rc(:)
    1264         636 :             rbc(:) = rb(:) - rc(:)
    1265         636 :             dab = NORM2(rab)
    1266             : 
    1267         594 :             DO iset = 1, nseta
    1268             : 
    1269         276 :                ncoa = npgfa(iset)*ncoset(la_max(iset))
    1270         276 :                sgfa = first_sgfa(1, iset)
    1271             : 
    1272         945 :                DO jset = 1, nsetb
    1273             : 
    1274         510 :                   IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
    1275             : 
    1276         510 :                   ncob = npgfb(jset)*ncoset(lb_max(jset))
    1277         510 :                   sgfb = first_sgfb(1, jset)
    1278             : 
    1279             :                   ! Calculate the primitive integrals
    1280             :                   CALL angmom(la_max(iset), npgfa(iset), zeta(:, iset), &
    1281             :                               rpgfa(:, iset), la_min(iset), &
    1282             :                               lb_max(jset), npgfb(jset), zetb(:, jset), &
    1283         510 :                               rpgfb(:, jset), rac, rbc, mab)
    1284             : 
    1285             :                   ! Contraction step
    1286        2316 :                   DO i = 1, nm
    1287             :                      CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
    1288             :                                 1.0_dp, mab(1, 1, i), SIZE(mab, 1), &
    1289             :                                 sphi_b(1, sgfb), SIZE(sphi_b, 1), &
    1290        1530 :                                 0.0_dp, work(1, 1), SIZE(work, 1))
    1291             : 
    1292        2040 :                      IF (iatom <= jatom) THEN
    1293             :                         CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
    1294             :                                    1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
    1295             :                                    work(1, 1), SIZE(work, 1), &
    1296             :                                    1.0_dp, mint(i)%block(sgfa, sgfb), &
    1297        1020 :                                    SIZE(mint(i)%block, 1))
    1298             :                      ELSE
    1299             :                         CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
    1300             :                                    -1.0_dp, work(1, 1), SIZE(work, 1), &
    1301             :                                    sphi_a(1, sgfa), SIZE(sphi_a, 1), &
    1302             :                                    1.0_dp, mint(i)%block(sgfb, sgfa), &
    1303         510 :                                    SIZE(mint(i)%block, 1))
    1304             :                      END IF
    1305             : 
    1306             :                   END DO
    1307             : 
    1308             :                END DO
    1309             :             END DO
    1310             :          END ASSOCIATE
    1311             :       END DO
    1312          16 :       CALL neighbor_list_iterator_release(nl_iterator)
    1313             : 
    1314             :       ! Release work storage
    1315          16 :       DEALLOCATE (mab, basis_set_list)
    1316          16 :       DEALLOCATE (work)
    1317          64 :       DO i = 1, nm
    1318          64 :          NULLIFY (mint(i)%block)
    1319             :       END DO
    1320          16 :       DEALLOCATE (mint)
    1321             : 
    1322          16 :       CALL timestop(handle)
    1323             : 
    1324          48 :    END SUBROUTINE build_local_magmom_matrix
    1325             : 
    1326             : ! **************************************************************************************************
    1327             : !> \brief ...
    1328             : !> \param qs_env ...
    1329             : !> \param cosmat ...
    1330             : !> \param sinmat ...
    1331             : !> \param kvec ...
    1332             : !> \param sab_orb_external ...
    1333             : !> \param basis_type ...
    1334             : ! **************************************************************************************************
    1335        8660 :    SUBROUTINE build_berry_moment_matrix(qs_env, cosmat, sinmat, kvec, sab_orb_external, basis_type)
    1336             : 
    1337             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1338             :       TYPE(dbcsr_type), POINTER                          :: cosmat, sinmat
    1339             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: kvec
    1340             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1341             :          OPTIONAL, POINTER                               :: sab_orb_external
    1342             :       CHARACTER(len=*), OPTIONAL                         :: basis_type
    1343             : 
    1344             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'build_berry_moment_matrix'
    1345             : 
    1346             :       INTEGER :: handle, iatom, icol, ikind, inode, irow, iset, jatom, jkind, jset, ldab, ldsa, &
    1347             :          ldsb, ldwork, natom, ncoa, ncob, nkind, nseta, nsetb, sgfa, sgfb
    1348             :       LOGICAL                                            :: found
    1349        8660 :       REAL(dp), DIMENSION(:, :), POINTER                 :: cblock, cosab, sblock, sinab, work
    1350             :       REAL(KIND=dp)                                      :: dab
    1351             :       REAL(KIND=dp), DIMENSION(3)                        :: ra, rab, rb
    1352             :       TYPE(cell_type), POINTER                           :: cell
    1353        8660 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
    1354             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
    1355             :       TYPE(neighbor_list_iterator_p_type), &
    1356        8660 :          DIMENSION(:), POINTER                           :: nl_iterator
    1357             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1358        8660 :          POINTER                                         :: sab_orb
    1359        8660 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1360        8660 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1361             :       TYPE(qs_kind_type), POINTER                        :: qs_kind
    1362             : 
    1363        8660 :       CALL timeset(routineN, handle)
    1364             : 
    1365        8660 :       NULLIFY (qs_kind_set, particle_set, sab_orb, cell)
    1366             :       CALL get_qs_env(qs_env=qs_env, &
    1367             :                       qs_kind_set=qs_kind_set, &
    1368             :                       particle_set=particle_set, cell=cell, &
    1369        8660 :                       sab_orb=sab_orb)
    1370             : 
    1371        8660 :       IF (PRESENT(sab_orb_external)) sab_orb => sab_orb_external
    1372             : 
    1373        8660 :       CALL dbcsr_set(sinmat, 0.0_dp)
    1374        8660 :       CALL dbcsr_set(cosmat, 0.0_dp)
    1375             : 
    1376       10768 :       CALL get_qs_kind_set(qs_kind_set=qs_kind_set, maxco=ldwork, basis_type=basis_type)
    1377        8660 :       ldab = ldwork
    1378       34640 :       ALLOCATE (cosab(ldab, ldab))
    1379       25980 :       ALLOCATE (sinab(ldab, ldab))
    1380       25980 :       ALLOCATE (work(ldwork, ldwork))
    1381             : 
    1382        8660 :       nkind = SIZE(qs_kind_set)
    1383        8660 :       natom = SIZE(particle_set)
    1384             : 
    1385       43360 :       ALLOCATE (basis_set_list(nkind))
    1386       26040 :       DO ikind = 1, nkind
    1387       17380 :          qs_kind => qs_kind_set(ikind)
    1388       17380 :          CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a, basis_type=basis_type)
    1389       26040 :          IF (ASSOCIATED(basis_set_a)) THEN
    1390       17380 :             basis_set_list(ikind)%gto_basis_set => basis_set_a
    1391             :          ELSE
    1392           0 :             NULLIFY (basis_set_list(ikind)%gto_basis_set)
    1393             :          END IF
    1394             :       END DO
    1395        8660 :       CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
    1396      385932 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
    1397             :          CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
    1398      377272 :                                 iatom=iatom, jatom=jatom, r=rab)
    1399      377272 :          basis_set_a => basis_set_list(ikind)%gto_basis_set
    1400      377272 :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
    1401      377272 :          basis_set_b => basis_set_list(jkind)%gto_basis_set
    1402      377272 :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
    1403             :          ASSOCIATE ( &
    1404             :             ! basis ikind
    1405             :             first_sgfa => basis_set_a%first_sgf, &
    1406             :             la_max => basis_set_a%lmax, &
    1407             :             la_min => basis_set_a%lmin, &
    1408             :             npgfa => basis_set_a%npgf, &
    1409             :             nsgfa => basis_set_a%nsgf_set, &
    1410             :             rpgfa => basis_set_a%pgf_radius, &
    1411             :             set_radius_a => basis_set_a%set_radius, &
    1412             :             sphi_a => basis_set_a%sphi, &
    1413             :             zeta => basis_set_a%zet, &
    1414             :             ! basis jkind, &
    1415             :             first_sgfb => basis_set_b%first_sgf, &
    1416             :             lb_max => basis_set_b%lmax, &
    1417             :             lb_min => basis_set_b%lmin, &
    1418             :             npgfb => basis_set_b%npgf, &
    1419             :             nsgfb => basis_set_b%nsgf_set, &
    1420             :             rpgfb => basis_set_b%pgf_radius, &
    1421             :             set_radius_b => basis_set_b%set_radius, &
    1422             :             sphi_b => basis_set_b%sphi, &
    1423             :             zetb => basis_set_b%zet)
    1424             : 
    1425      377272 :             nseta = basis_set_a%nset
    1426      377272 :             nsetb = basis_set_b%nset
    1427             : 
    1428      377272 :             ldsa = SIZE(sphi_a, 1)
    1429      377272 :             ldsb = SIZE(sphi_b, 1)
    1430             : 
    1431      377272 :             IF (iatom <= jatom) THEN
    1432      212258 :                irow = iatom
    1433      212258 :                icol = jatom
    1434             :             ELSE
    1435      165014 :                irow = jatom
    1436      165014 :                icol = iatom
    1437             :             END IF
    1438             : 
    1439      377272 :             NULLIFY (cblock)
    1440             :             CALL dbcsr_get_block_p(matrix=cosmat, &
    1441      377272 :                                    row=irow, col=icol, BLOCK=cblock, found=found)
    1442      377272 :             NULLIFY (sblock)
    1443             :             CALL dbcsr_get_block_p(matrix=sinmat, &
    1444      377272 :                                    row=irow, col=icol, BLOCK=sblock, found=found)
    1445      377272 :             IF (ASSOCIATED(cblock) .AND. .NOT. ASSOCIATED(sblock) .OR. &
    1446      377272 :                 .NOT. ASSOCIATED(cblock) .AND. ASSOCIATED(sblock)) THEN
    1447           0 :                CPABORT("")
    1448             :             END IF
    1449             : 
    1450     1131816 :             IF (ASSOCIATED(cblock) .AND. ASSOCIATED(sblock)) THEN
    1451             : 
    1452      377272 :                ra(:) = pbc(particle_set(iatom)%r(:), cell)
    1453     1509088 :                rb(:) = ra + rab
    1454      377272 :                dab = SQRT(rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3))
    1455             : 
    1456     1317470 :                DO iset = 1, nseta
    1457             : 
    1458      940198 :                   ncoa = npgfa(iset)*ncoset(la_max(iset))
    1459      940198 :                   sgfa = first_sgfa(1, iset)
    1460             : 
    1461     4583145 :                   DO jset = 1, nsetb
    1462             : 
    1463     3265675 :                      IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
    1464             : 
    1465     1462057 :                      ncob = npgfb(jset)*ncoset(lb_max(jset))
    1466     1462057 :                      sgfb = first_sgfb(1, jset)
    1467             : 
    1468             :                      ! Calculate the primitive integrals
    1469             :                      CALL cossin(la_max(iset), npgfa(iset), zeta(:, iset), rpgfa(:, iset), la_min(iset), &
    1470             :                                  lb_max(jset), npgfb(jset), zetb(:, jset), rpgfb(:, jset), lb_min(jset), &
    1471     1462057 :                                  ra, rb, kvec, cosab, sinab)
    1472             :                      CALL contract_cossin(cblock, sblock, &
    1473             :                                           iatom, ncoa, nsgfa(iset), sgfa, sphi_a, ldsa, &
    1474             :                                           jatom, ncob, nsgfb(jset), sgfb, sphi_b, ldsb, &
    1475     4205873 :                                           cosab, sinab, ldab, work, ldwork)
    1476             : 
    1477             :                   END DO
    1478             :                END DO
    1479             : 
    1480             :             END IF
    1481             :          END ASSOCIATE
    1482             :       END DO
    1483        8660 :       CALL neighbor_list_iterator_release(nl_iterator)
    1484             : 
    1485        8660 :       DEALLOCATE (cosab)
    1486        8660 :       DEALLOCATE (sinab)
    1487        8660 :       DEALLOCATE (work)
    1488        8660 :       DEALLOCATE (basis_set_list)
    1489             : 
    1490        8660 :       CALL timestop(handle)
    1491             : 
    1492        8660 :    END SUBROUTINE build_berry_moment_matrix
    1493             : 
    1494             : ! **************************************************************************************************
    1495             : !> \brief ...
    1496             : !> \param qs_env ...
    1497             : !> \param cosmat ...
    1498             : !> \param sinmat ...
    1499             : !> \param kvec ...
    1500             : !> \param basis_type ...
    1501             : ! **************************************************************************************************
    1502           0 :    SUBROUTINE build_berry_kpoint_matrix(qs_env, cosmat, sinmat, kvec, basis_type)
    1503             : 
    1504             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1505             :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: cosmat, sinmat
    1506             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: kvec
    1507             :       CHARACTER(len=*), OPTIONAL                         :: basis_type
    1508             : 
    1509             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'build_berry_kpoint_matrix'
    1510             : 
    1511             :       INTEGER :: handle, i, iatom, ic, icol, ikind, inode, irow, iset, jatom, jkind, jset, ldab, &
    1512             :          ldsa, ldsb, ldwork, natom, ncoa, ncob, nimg, nkind, nseta, nsetb, sgfa, sgfb
    1513             :       INTEGER, DIMENSION(3)                              :: icell
    1514           0 :       INTEGER, DIMENSION(:), POINTER                     :: row_blk_sizes
    1515           0 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    1516             :       LOGICAL                                            :: found, use_cell_mapping
    1517           0 :       REAL(dp), DIMENSION(:, :), POINTER                 :: cblock, cosab, sblock, sinab, work
    1518             :       REAL(KIND=dp)                                      :: dab
    1519             :       REAL(KIND=dp), DIMENSION(3)                        :: ra, rab, rb
    1520             :       TYPE(cell_type), POINTER                           :: cell
    1521             :       TYPE(dbcsr_distribution_type), POINTER             :: dbcsr_dist
    1522             :       TYPE(dft_control_type), POINTER                    :: dft_control
    1523           0 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
    1524             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set, basis_set_a, basis_set_b
    1525             :       TYPE(kpoint_type), POINTER                         :: kpoints
    1526             :       TYPE(neighbor_list_iterator_p_type), &
    1527           0 :          DIMENSION(:), POINTER                           :: nl_iterator
    1528             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1529           0 :          POINTER                                         :: sab_orb
    1530           0 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1531           0 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1532             :       TYPE(qs_kind_type), POINTER                        :: qs_kind
    1533             :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
    1534             : 
    1535           0 :       CALL timeset(routineN, handle)
    1536             : 
    1537             :       CALL get_qs_env(qs_env, &
    1538             :                       ks_env=ks_env, &
    1539           0 :                       dft_control=dft_control)
    1540           0 :       nimg = dft_control%nimages
    1541           0 :       IF (nimg > 1) THEN
    1542           0 :          CALL get_ks_env(ks_env=ks_env, kpoints=kpoints)
    1543           0 :          CALL get_kpoint_info(kpoint=kpoints, cell_to_index=cell_to_index)
    1544           0 :          use_cell_mapping = .TRUE.
    1545             :       ELSE
    1546             :          use_cell_mapping = .FALSE.
    1547             :       END IF
    1548             : 
    1549             :       CALL get_qs_env(qs_env=qs_env, &
    1550             :                       qs_kind_set=qs_kind_set, &
    1551             :                       particle_set=particle_set, cell=cell, &
    1552           0 :                       sab_orb=sab_orb)
    1553             : 
    1554           0 :       nkind = SIZE(qs_kind_set)
    1555           0 :       natom = SIZE(particle_set)
    1556           0 :       ALLOCATE (basis_set_list(nkind))
    1557           0 :       DO ikind = 1, nkind
    1558           0 :          qs_kind => qs_kind_set(ikind)
    1559           0 :          CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set, basis_type=basis_type)
    1560           0 :          IF (ASSOCIATED(basis_set)) THEN
    1561           0 :             basis_set_list(ikind)%gto_basis_set => basis_set
    1562             :          ELSE
    1563           0 :             NULLIFY (basis_set_list(ikind)%gto_basis_set)
    1564             :          END IF
    1565             :       END DO
    1566             : 
    1567           0 :       ALLOCATE (row_blk_sizes(natom))
    1568             :       CALL get_particle_set(particle_set, qs_kind_set, nsgf=row_blk_sizes, &
    1569           0 :                             basis=basis_set_list)
    1570           0 :       CALL get_ks_env(ks_env, dbcsr_dist=dbcsr_dist)
    1571             :       ! (re)allocate matrix sets
    1572           0 :       CALL dbcsr_allocate_matrix_set(sinmat, 1, nimg)
    1573           0 :       CALL dbcsr_allocate_matrix_set(cosmat, 1, nimg)
    1574           0 :       DO i = 1, nimg
    1575             :          ! sin
    1576           0 :          ALLOCATE (sinmat(1, i)%matrix)
    1577             :          CALL dbcsr_create(matrix=sinmat(1, i)%matrix, &
    1578             :                            name="SINMAT", &
    1579             :                            dist=dbcsr_dist, matrix_type=dbcsr_type_symmetric, &
    1580             :                            row_blk_size=row_blk_sizes, col_blk_size=row_blk_sizes, &
    1581           0 :                            nze=0)
    1582           0 :          CALL cp_dbcsr_alloc_block_from_nbl(sinmat(1, i)%matrix, sab_orb)
    1583           0 :          CALL dbcsr_set(sinmat(1, i)%matrix, 0.0_dp)
    1584             :          ! cos
    1585           0 :          ALLOCATE (cosmat(1, i)%matrix)
    1586             :          CALL dbcsr_create(matrix=cosmat(1, i)%matrix, &
    1587             :                            name="COSMAT", &
    1588             :                            dist=dbcsr_dist, matrix_type=dbcsr_type_symmetric, &
    1589             :                            row_blk_size=row_blk_sizes, col_blk_size=row_blk_sizes, &
    1590           0 :                            nze=0)
    1591           0 :          CALL cp_dbcsr_alloc_block_from_nbl(cosmat(1, i)%matrix, sab_orb)
    1592           0 :          CALL dbcsr_set(cosmat(1, i)%matrix, 0.0_dp)
    1593             :       END DO
    1594             : 
    1595           0 :       CALL get_qs_kind_set(qs_kind_set=qs_kind_set, maxco=ldwork)
    1596           0 :       ldab = ldwork
    1597           0 :       ALLOCATE (cosab(ldab, ldab))
    1598           0 :       ALLOCATE (sinab(ldab, ldab))
    1599           0 :       ALLOCATE (work(ldwork, ldwork))
    1600             : 
    1601           0 :       CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
    1602           0 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
    1603             :          CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
    1604           0 :                                 iatom=iatom, jatom=jatom, r=rab, cell=icell)
    1605           0 :          basis_set_a => basis_set_list(ikind)%gto_basis_set
    1606           0 :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
    1607           0 :          basis_set_b => basis_set_list(jkind)%gto_basis_set
    1608           0 :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
    1609             :          ASSOCIATE ( &
    1610             :             ! basis ikind
    1611             :             first_sgfa => basis_set_a%first_sgf, &
    1612             :             la_max => basis_set_a%lmax, &
    1613             :             la_min => basis_set_a%lmin, &
    1614             :             npgfa => basis_set_a%npgf, &
    1615             :             nsgfa => basis_set_a%nsgf_set, &
    1616             :             rpgfa => basis_set_a%pgf_radius, &
    1617             :             set_radius_a => basis_set_a%set_radius, &
    1618             :             sphi_a => basis_set_a%sphi, &
    1619             :             zeta => basis_set_a%zet, &
    1620             :             ! basis jkind, &
    1621             :             first_sgfb => basis_set_b%first_sgf, &
    1622             :             lb_max => basis_set_b%lmax, &
    1623             :             lb_min => basis_set_b%lmin, &
    1624             :             npgfb => basis_set_b%npgf, &
    1625             :             nsgfb => basis_set_b%nsgf_set, &
    1626             :             rpgfb => basis_set_b%pgf_radius, &
    1627             :             set_radius_b => basis_set_b%set_radius, &
    1628             :             sphi_b => basis_set_b%sphi, &
    1629           0 :             zetb => basis_set_b%zet)
    1630             : 
    1631           0 :             nseta = basis_set_a%nset
    1632           0 :             nsetb = basis_set_b%nset
    1633             : 
    1634           0 :             ldsa = SIZE(sphi_a, 1)
    1635           0 :             ldsb = SIZE(sphi_b, 1)
    1636             : 
    1637           0 :             IF (iatom <= jatom) THEN
    1638           0 :                irow = iatom
    1639           0 :                icol = jatom
    1640             :             ELSE
    1641           0 :                irow = jatom
    1642           0 :                icol = iatom
    1643             :             END IF
    1644             : 
    1645           0 :             IF (use_cell_mapping) THEN
    1646           0 :                ic = cell_to_index(icell(1), icell(2), icell(3))
    1647           0 :                CPASSERT(ic > 0)
    1648             :             ELSE
    1649             :                ic = 1
    1650             :             END IF
    1651             : 
    1652           0 :             NULLIFY (sblock)
    1653             :             CALL dbcsr_get_block_p(matrix=sinmat(1, ic)%matrix, &
    1654           0 :                                    row=irow, col=icol, BLOCK=sblock, found=found)
    1655           0 :             CPASSERT(found)
    1656           0 :             NULLIFY (cblock)
    1657             :             CALL dbcsr_get_block_p(matrix=cosmat(1, ic)%matrix, &
    1658           0 :                                    row=irow, col=icol, BLOCK=cblock, found=found)
    1659           0 :             CPASSERT(found)
    1660             : 
    1661           0 :             ra(:) = pbc(particle_set(iatom)%r(:), cell)
    1662           0 :             rb(:) = ra + rab
    1663           0 :             dab = SQRT(rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3))
    1664             : 
    1665           0 :             DO iset = 1, nseta
    1666             : 
    1667           0 :                ncoa = npgfa(iset)*ncoset(la_max(iset))
    1668           0 :                sgfa = first_sgfa(1, iset)
    1669             : 
    1670           0 :                DO jset = 1, nsetb
    1671             : 
    1672           0 :                   IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
    1673             : 
    1674           0 :                   ncob = npgfb(jset)*ncoset(lb_max(jset))
    1675           0 :                   sgfb = first_sgfb(1, jset)
    1676             : 
    1677             :                   ! Calculate the primitive integrals
    1678             :                   CALL cossin(la_max(iset), npgfa(iset), zeta(:, iset), rpgfa(:, iset), la_min(iset), &
    1679             :                               lb_max(jset), npgfb(jset), zetb(:, jset), rpgfb(:, jset), lb_min(jset), &
    1680           0 :                               ra, rb, kvec, cosab, sinab)
    1681             :                   CALL contract_cossin(cblock, sblock, &
    1682             :                                        iatom, ncoa, nsgfa(iset), sgfa, sphi_a, ldsa, &
    1683             :                                        jatom, ncob, nsgfb(jset), sgfb, sphi_b, ldsb, &
    1684           0 :                                        cosab, sinab, ldab, work, ldwork)
    1685             : 
    1686             :                END DO
    1687             :             END DO
    1688             :          END ASSOCIATE
    1689             :       END DO
    1690           0 :       CALL neighbor_list_iterator_release(nl_iterator)
    1691             : 
    1692           0 :       DEALLOCATE (cosab)
    1693           0 :       DEALLOCATE (sinab)
    1694           0 :       DEALLOCATE (work)
    1695           0 :       DEALLOCATE (basis_set_list)
    1696           0 :       DEALLOCATE (row_blk_sizes)
    1697             : 
    1698           0 :       CALL timestop(handle)
    1699             : 
    1700           0 :    END SUBROUTINE build_berry_kpoint_matrix
    1701             : 
    1702             : ! **************************************************************************************************
    1703             : !> \brief ...
    1704             : !> \param qs_env ...
    1705             : !> \param magnetic ...
    1706             : !> \param nmoments ...
    1707             : !> \param reference ...
    1708             : !> \param ref_point ...
    1709             : !> \param unit_number ...
    1710             : ! **************************************************************************************************
    1711         340 :    SUBROUTINE qs_moment_berry_phase(qs_env, magnetic, nmoments, reference, ref_point, unit_number)
    1712             : 
    1713             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1714             :       LOGICAL, INTENT(IN)                                :: magnetic
    1715             :       INTEGER, INTENT(IN)                                :: nmoments, reference
    1716             :       REAL(dp), DIMENSION(:), POINTER                    :: ref_point
    1717             :       INTEGER, INTENT(IN)                                :: unit_number
    1718             : 
    1719             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_moment_berry_phase'
    1720             : 
    1721         340 :       CHARACTER(LEN=8), ALLOCATABLE, DIMENSION(:)        :: rlab
    1722             :       CHARACTER(LEN=default_string_length)               :: description
    1723             :       COMPLEX(dp)                                        :: xphase(3), zdet, zdeta, zi(3), &
    1724             :                                                             zij(3, 3), zijk(3, 3, 3), &
    1725             :                                                             zijkl(3, 3, 3, 3), zphase(3), zz
    1726             :       INTEGER                                            :: handle, i, ia, idim, ikind, ispin, ix, &
    1727             :                                                             iy, iz, j, k, l, nao, nm, nmo, nmom, &
    1728             :                                                             nmotot, tmp_dim
    1729             :       LOGICAL                                            :: floating, ghost, uniform
    1730             :       REAL(dp)                                           :: charge, ci(3), cij(3, 3), dd, occ, trace
    1731         340 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: mmom
    1732         340 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: rmom
    1733             :       REAL(dp), DIMENSION(3)                             :: kvec, qq, rcc, ria
    1734             :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
    1735             :       TYPE(cell_type), POINTER                           :: cell
    1736         340 :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:)       :: eigrmat
    1737             :       TYPE(cp_fm_struct_type), POINTER                   :: tmp_fm_struct
    1738         340 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: opvec
    1739         340 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: op_fm_set
    1740         340 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: mos_new
    1741             :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    1742             :       TYPE(cp_result_type), POINTER                      :: results
    1743         340 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s, rho_ao
    1744             :       TYPE(dbcsr_type), POINTER                          :: cosmat, sinmat
    1745             :       TYPE(dft_control_type), POINTER                    :: dft_control
    1746             :       TYPE(distribution_1d_type), POINTER                :: local_particles
    1747         340 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    1748             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1749         340 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1750         340 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1751             :       TYPE(qs_rho_type), POINTER                         :: rho
    1752             :       TYPE(rt_prop_type), POINTER                        :: rtp
    1753             : 
    1754           0 :       CPASSERT(ASSOCIATED(qs_env))
    1755             : 
    1756         340 :       IF (ASSOCIATED(qs_env%ls_scf_env)) THEN
    1757           0 :          IF (unit_number > 0) WRITE (unit_number, *) "Periodic moment calculation not implemented in linear scaling code"
    1758           0 :          RETURN
    1759             :       END IF
    1760             : 
    1761         340 :       CALL timeset(routineN, handle)
    1762             : 
    1763             :       ! restrict maximum moment available
    1764         340 :       nmom = MIN(nmoments, 2)
    1765             : 
    1766         340 :       nm = (6 + 11*nmom + 6*nmom**2 + nmom**3)/6 - 1
    1767             :       ! rmom(:,1)=electronic
    1768             :       ! rmom(:,2)=nuclear
    1769             :       ! rmom(:,1)=total
    1770        1700 :       ALLOCATE (rmom(nm + 1, 3))
    1771        1020 :       ALLOCATE (rlab(nm + 1))
    1772        5440 :       rmom = 0.0_dp
    1773        1700 :       rlab = ""
    1774         340 :       IF (magnetic) THEN
    1775           0 :          nm = 3
    1776           0 :          ALLOCATE (mmom(nm))
    1777           0 :          mmom = 0._dp
    1778             :       END IF
    1779             : 
    1780         340 :       NULLIFY (dft_control, rho, cell, particle_set, results, para_env, &
    1781         340 :                local_particles, matrix_s, mos, rho_ao)
    1782             : 
    1783             :       CALL get_qs_env(qs_env, &
    1784             :                       dft_control=dft_control, &
    1785             :                       rho=rho, &
    1786             :                       cell=cell, &
    1787             :                       results=results, &
    1788             :                       particle_set=particle_set, &
    1789             :                       qs_kind_set=qs_kind_set, &
    1790             :                       para_env=para_env, &
    1791             :                       local_particles=local_particles, &
    1792             :                       matrix_s=matrix_s, &
    1793         340 :                       mos=mos)
    1794             : 
    1795         340 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
    1796             : 
    1797         340 :       NULLIFY (cosmat, sinmat)
    1798         340 :       ALLOCATE (cosmat, sinmat)
    1799         340 :       CALL dbcsr_copy(cosmat, matrix_s(1)%matrix, 'COS MOM')
    1800         340 :       CALL dbcsr_copy(sinmat, matrix_s(1)%matrix, 'SIN MOM')
    1801         340 :       CALL dbcsr_set(cosmat, 0.0_dp)
    1802         340 :       CALL dbcsr_set(sinmat, 0.0_dp)
    1803             : 
    1804        2106 :       ALLOCATE (op_fm_set(2, dft_control%nspins))
    1805        1382 :       ALLOCATE (opvec(dft_control%nspins))
    1806        1382 :       ALLOCATE (eigrmat(dft_control%nspins))
    1807         340 :       nmotot = 0
    1808         702 :       DO ispin = 1, dft_control%nspins
    1809         362 :          NULLIFY (tmp_fm_struct, mo_coeff)
    1810         362 :          CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, nao=nao, nmo=nmo)
    1811         362 :          nmotot = nmotot + nmo
    1812         362 :          CALL cp_fm_create(opvec(ispin), mo_coeff%matrix_struct)
    1813             :          CALL cp_fm_struct_create(tmp_fm_struct, nrow_global=nmo, &
    1814         362 :                                   ncol_global=nmo, para_env=para_env, context=mo_coeff%matrix_struct%context)
    1815        1086 :          DO i = 1, SIZE(op_fm_set, 1)
    1816        1086 :             CALL cp_fm_create(op_fm_set(i, ispin), tmp_fm_struct)
    1817             :          END DO
    1818         362 :          CALL cp_cfm_create(eigrmat(ispin), op_fm_set(1, ispin)%matrix_struct)
    1819        1064 :          CALL cp_fm_struct_release(tmp_fm_struct)
    1820             :       END DO
    1821             : 
    1822             :       ! occupation
    1823         702 :       DO ispin = 1, dft_control%nspins
    1824         362 :          CALL get_mo_set(mo_set=mos(ispin), maxocc=occ, uniform_occupation=uniform)
    1825         702 :          IF (.NOT. uniform) THEN
    1826           0 :             CPWARN("Berry phase moments for non uniform MOs' occupation numbers not implemented")
    1827             :          END IF
    1828             :       END DO
    1829             : 
    1830             :       ! reference point
    1831         340 :       CALL get_reference_point(rcc, qs_env=qs_env, reference=reference, ref_point=ref_point)
    1832        1360 :       rcc = pbc(rcc, cell)
    1833             : 
    1834             :       ! label
    1835        1360 :       DO l = 1, nm
    1836        1020 :          ix = indco(1, l + 1)
    1837        1020 :          iy = indco(2, l + 1)
    1838        1020 :          iz = indco(3, l + 1)
    1839        1360 :          CALL set_label(rlab(l + 1), ix, iy, iz)
    1840             :       END DO
    1841             : 
    1842             :       ! nuclear contribution
    1843        1380 :       DO ia = 1, SIZE(particle_set)
    1844        1040 :          atomic_kind => particle_set(ia)%atomic_kind
    1845        1040 :          CALL get_atomic_kind(atomic_kind, kind_number=ikind)
    1846        1040 :          CALL get_qs_kind(qs_kind_set(ikind), core_charge=charge, ghost=ghost, floating=floating)
    1847        1380 :          IF (.NOT. ghost .AND. .NOT. floating) THEN
    1848        1040 :             rmom(1, 2) = rmom(1, 2) - charge
    1849             :          END IF
    1850             :       END DO
    1851        5440 :       ria = twopi*MATMUL(cell%h_inv, rcc)
    1852        1360 :       zphase = CMPLX(COS(ria), SIN(ria), dp)**rmom(1, 2)
    1853             : 
    1854         340 :       zi = 0._dp
    1855         340 :       zij = 0._dp
    1856             :       zijk = 0._dp
    1857             :       zijkl = 0._dp
    1858             : 
    1859         680 :       DO l = 1, nmom
    1860         340 :          SELECT CASE (l)
    1861             :          CASE (1)
    1862             :             ! Dipole
    1863        1360 :             zi(:) = CMPLX(1._dp, 0._dp, dp)
    1864        1380 :             DO ia = 1, SIZE(particle_set)
    1865        1040 :                atomic_kind => particle_set(ia)%atomic_kind
    1866        1040 :                CALL get_atomic_kind(atomic_kind, kind_number=ikind)
    1867        1040 :                CALL get_qs_kind(qs_kind_set(ikind), core_charge=charge, ghost=ghost, floating=floating)
    1868        1380 :                IF (.NOT. ghost .AND. .NOT. floating) THEN
    1869        4160 :                   ria = particle_set(ia)%r
    1870        4160 :                   ria = pbc(ria, cell)
    1871        4160 :                   DO i = 1, 3
    1872       12480 :                      kvec(:) = twopi*cell%h_inv(i, :)
    1873       12480 :                      dd = SUM(kvec(:)*ria(:))
    1874        3120 :                      zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)**charge
    1875        4160 :                      zi(i) = zi(i)*zdeta
    1876             :                   END DO
    1877             :                END IF
    1878             :             END DO
    1879        1360 :             zi = zi*zphase
    1880        1360 :             ci = AIMAG(LOG(zi))/twopi
    1881        1360 :             qq = AIMAG(LOG(zi))
    1882        5440 :             rmom(2:4, 2) = MATMUL(cell%hmat, ci)
    1883             :          CASE (2)
    1884             :             ! Quadrupole
    1885           0 :             CPABORT("Berry phase moments bigger than 1 not implemented")
    1886           0 :             zij(:, :) = CMPLX(1._dp, 0._dp, dp)
    1887           0 :             DO ia = 1, SIZE(particle_set)
    1888           0 :                atomic_kind => particle_set(ia)%atomic_kind
    1889           0 :                CALL get_atomic_kind(atomic_kind, kind_number=ikind)
    1890           0 :                CALL get_qs_kind(qs_kind_set(ikind), core_charge=charge)
    1891           0 :                ria = particle_set(ia)%r
    1892           0 :                ria = pbc(ria, cell)
    1893           0 :                DO i = 1, 3
    1894           0 :                   DO j = i, 3
    1895           0 :                      kvec(:) = twopi*(cell%h_inv(i, :) + cell%h_inv(j, :))
    1896           0 :                      dd = SUM(kvec(:)*ria(:))
    1897           0 :                      zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)**charge
    1898           0 :                      zij(i, j) = zij(i, j)*zdeta
    1899           0 :                      zij(j, i) = zij(i, j)
    1900             :                   END DO
    1901             :                END DO
    1902             :             END DO
    1903           0 :             DO i = 1, 3
    1904           0 :                DO j = 1, 3
    1905           0 :                   zij(i, j) = zij(i, j)*zphase(i)*zphase(j)
    1906           0 :                   zz = zij(i, j)/zi(i)/zi(j)
    1907           0 :                   cij(i, j) = AIMAG(LOG(zz))/twopi
    1908             :                END DO
    1909             :             END DO
    1910           0 :             cij = 0.5_dp*cij/twopi/twopi
    1911           0 :             cij = MATMUL(MATMUL(cell%hmat, cij), TRANSPOSE(cell%hmat))
    1912           0 :             DO k = 4, 9
    1913           0 :                ix = indco(1, k + 1)
    1914           0 :                iy = indco(2, k + 1)
    1915           0 :                iz = indco(3, k + 1)
    1916           0 :                IF (ix == 0) THEN
    1917           0 :                   rmom(k + 1, 2) = cij(iy, iz)
    1918           0 :                ELSE IF (iy == 0) THEN
    1919           0 :                   rmom(k + 1, 2) = cij(ix, iz)
    1920           0 :                ELSE IF (iz == 0) THEN
    1921           0 :                   rmom(k + 1, 2) = cij(ix, iy)
    1922             :                END IF
    1923             :             END DO
    1924             :          CASE (3)
    1925             :             ! Octapole
    1926           0 :             CPABORT("Berry phase moments bigger than 2 not implemented")
    1927             :          CASE (4)
    1928             :             ! Hexadecapole
    1929           0 :             CPABORT("Berry phase moments bigger than 3 not implemented")
    1930             :          CASE DEFAULT
    1931         340 :             CPABORT("Berry phase moments bigger than 4 not implemented")
    1932             :          END SELECT
    1933             :       END DO
    1934             : 
    1935             :       ! electronic contribution
    1936             : 
    1937        5440 :       ria = twopi*REAL(nmotot, dp)*occ*MATMUL(cell%h_inv, rcc)
    1938        1360 :       xphase = CMPLX(COS(ria), SIN(ria), dp)
    1939             : 
    1940             :       ! charge
    1941         340 :       trace = 0.0_dp
    1942         702 :       DO ispin = 1, dft_control%nspins
    1943         362 :          CALL dbcsr_dot(rho_ao(ispin)%matrix, matrix_s(1)%matrix, trace)
    1944         702 :          rmom(1, 1) = rmom(1, 1) + trace
    1945             :       END DO
    1946             : 
    1947         340 :       zi = 0._dp
    1948         340 :       zij = 0._dp
    1949             :       zijk = 0._dp
    1950             :       zijkl = 0._dp
    1951             : 
    1952         680 :       DO l = 1, nmom
    1953         340 :          SELECT CASE (l)
    1954             :          CASE (1)
    1955             :             ! Dipole
    1956        1360 :             DO i = 1, 3
    1957        4080 :                kvec(:) = twopi*cell%h_inv(i, :)
    1958        1020 :                CALL build_berry_moment_matrix(qs_env, cosmat, sinmat, kvec)
    1959        1020 :                IF (qs_env%run_rtp) THEN
    1960          48 :                   CALL get_qs_env(qs_env, rtp=rtp)
    1961          48 :                   CALL get_rtp(rtp, mos_new=mos_new)
    1962          48 :                   CALL op_orbbas_rtp(cosmat, sinmat, mos, op_fm_set, mos_new)
    1963             :                ELSE
    1964         972 :                   CALL op_orbbas(cosmat, sinmat, mos, op_fm_set, opvec)
    1965             :                END IF
    1966        1020 :                zdet = CMPLX(1._dp, 0._dp, dp)
    1967        2106 :                DO ispin = 1, dft_control%nspins
    1968        1086 :                   CALL cp_cfm_get_info(eigrmat(ispin), ncol_local=tmp_dim)
    1969        6252 :                   DO idim = 1, tmp_dim
    1970             :                      eigrmat(ispin)%local_data(:, idim) = &
    1971             :                         CMPLX(op_fm_set(1, ispin)%local_data(:, idim), &
    1972       38586 :                               -op_fm_set(2, ispin)%local_data(:, idim), dp)
    1973             :                   END DO
    1974             :                   ! CALL cp_cfm_lu_decompose(eigrmat(ispin), zdeta)
    1975        1086 :                   CALL cp_cfm_det(eigrmat(ispin), zdeta)
    1976        1086 :                   zdet = zdet*zdeta
    1977        3192 :                   IF (dft_control%nspins == 1) THEN
    1978         954 :                      zdet = zdet*zdeta
    1979             :                   END IF
    1980             :                END DO
    1981        1360 :                zi(i) = zdet
    1982             :             END DO
    1983        1360 :             zi = zi*xphase
    1984             :          CASE (2)
    1985             :             ! Quadrupole
    1986           0 :             CPABORT("Berry phase moments bigger than 1 not implemented")
    1987           0 :             DO i = 1, 3
    1988           0 :                DO j = i, 3
    1989           0 :                   kvec(:) = twopi*(cell%h_inv(i, :) + cell%h_inv(j, :))
    1990           0 :                   CALL build_berry_moment_matrix(qs_env, cosmat, sinmat, kvec)
    1991           0 :                   IF (qs_env%run_rtp) THEN
    1992           0 :                      CALL get_qs_env(qs_env, rtp=rtp)
    1993           0 :                      CALL get_rtp(rtp, mos_new=mos_new)
    1994           0 :                      CALL op_orbbas_rtp(cosmat, sinmat, mos, op_fm_set, mos_new)
    1995             :                   ELSE
    1996           0 :                      CALL op_orbbas(cosmat, sinmat, mos, op_fm_set, opvec)
    1997             :                   END IF
    1998           0 :                   zdet = CMPLX(1._dp, 0._dp, dp)
    1999           0 :                   DO ispin = 1, dft_control%nspins
    2000           0 :                      CALL cp_cfm_get_info(eigrmat(ispin), ncol_local=tmp_dim)
    2001           0 :                      DO idim = 1, tmp_dim
    2002             :                         eigrmat(ispin)%local_data(:, idim) = &
    2003             :                            CMPLX(op_fm_set(1, ispin)%local_data(:, idim), &
    2004           0 :                                  -op_fm_set(2, ispin)%local_data(:, idim), dp)
    2005             :                      END DO
    2006             :                      ! CALL cp_cfm_lu_decompose(eigrmat(ispin), zdeta)
    2007           0 :                      CALL cp_cfm_det(eigrmat(ispin), zdeta)
    2008           0 :                      zdet = zdet*zdeta
    2009           0 :                      IF (dft_control%nspins == 1) THEN
    2010           0 :                         zdet = zdet*zdeta
    2011             :                      END IF
    2012             :                   END DO
    2013           0 :                   zij(i, j) = zdet*xphase(i)*xphase(j)
    2014           0 :                   zij(j, i) = zdet*xphase(i)*xphase(j)
    2015             :                END DO
    2016             :             END DO
    2017             :          CASE (3)
    2018             :             ! Octapole
    2019           0 :             CPABORT("Berry phase moments bigger than 2 not implemented")
    2020             :          CASE (4)
    2021             :             ! Hexadecapole
    2022           0 :             CPABORT("Berry phase moments bigger than 3 not implemented")
    2023             :          CASE DEFAULT
    2024         340 :             CPABORT("Berry phase moments bigger than 4 not implemented")
    2025             :          END SELECT
    2026             :       END DO
    2027         680 :       DO l = 1, nmom
    2028         340 :          SELECT CASE (l)
    2029             :          CASE (1)
    2030             :             ! Dipole (apply periodic (2 Pi) boundary conditions)
    2031        1360 :             ci = AIMAG(LOG(zi))
    2032        1360 :             DO i = 1, 3
    2033        1020 :                IF (qq(i) + ci(i) > pi) ci(i) = ci(i) - twopi
    2034        1360 :                IF (qq(i) + ci(i) < -pi) ci(i) = ci(i) + twopi
    2035             :             END DO
    2036        6460 :             rmom(2:4, 1) = MATMUL(cell%hmat, ci)/twopi
    2037             :          CASE (2)
    2038             :             ! Quadrupole
    2039           0 :             CPABORT("Berry phase moments bigger than 1 not implemented")
    2040           0 :             DO i = 1, 3
    2041           0 :                DO j = 1, 3
    2042           0 :                   zz = zij(i, j)/zi(i)/zi(j)
    2043           0 :                   cij(i, j) = AIMAG(LOG(zz))/twopi
    2044             :                END DO
    2045             :             END DO
    2046           0 :             cij = 0.5_dp*cij/twopi/twopi
    2047           0 :             cij = MATMUL(MATMUL(cell%hmat, cij), TRANSPOSE(cell%hmat))
    2048           0 :             DO k = 4, 9
    2049           0 :                ix = indco(1, k + 1)
    2050           0 :                iy = indco(2, k + 1)
    2051           0 :                iz = indco(3, k + 1)
    2052           0 :                IF (ix == 0) THEN
    2053           0 :                   rmom(k + 1, 1) = cij(iy, iz)
    2054           0 :                ELSE IF (iy == 0) THEN
    2055           0 :                   rmom(k + 1, 1) = cij(ix, iz)
    2056           0 :                ELSE IF (iz == 0) THEN
    2057           0 :                   rmom(k + 1, 1) = cij(ix, iy)
    2058             :                END IF
    2059             :             END DO
    2060             :          CASE (3)
    2061             :             ! Octapole
    2062           0 :             CPABORT("Berry phase moments bigger than 2 not implemented")
    2063             :          CASE (4)
    2064             :             ! Hexadecapole
    2065           0 :             CPABORT("Berry phase moments bigger than 3 not implemented")
    2066             :          CASE DEFAULT
    2067         340 :             CPABORT("Berry phase moments bigger than 4 not implemented")
    2068             :          END SELECT
    2069             :       END DO
    2070             : 
    2071        1700 :       rmom(:, 3) = rmom(:, 1) + rmom(:, 2)
    2072         340 :       description = "[DIPOLE]"
    2073         340 :       CALL cp_results_erase(results=results, description=description)
    2074             :       CALL put_results(results=results, description=description, &
    2075         340 :                        values=rmom(2:4, 3))
    2076         340 :       IF (magnetic) THEN
    2077           0 :          CALL print_moments(unit_number, nmom, rmom, rlab, rcc, cell, periodic=.TRUE., mmom=mmom)
    2078             :       ELSE
    2079         340 :          CALL print_moments(unit_number, nmom, rmom, rlab, rcc, cell, periodic=.TRUE.)
    2080             :       END IF
    2081             : 
    2082         340 :       DEALLOCATE (rmom)
    2083         340 :       DEALLOCATE (rlab)
    2084         340 :       IF (magnetic) THEN
    2085           0 :          DEALLOCATE (mmom)
    2086             :       END IF
    2087             : 
    2088         340 :       CALL dbcsr_deallocate_matrix(cosmat)
    2089         340 :       CALL dbcsr_deallocate_matrix(sinmat)
    2090             : 
    2091         340 :       CALL cp_fm_release(opvec)
    2092         340 :       CALL cp_fm_release(op_fm_set)
    2093         702 :       DO ispin = 1, dft_control%nspins
    2094         702 :          CALL cp_cfm_release(eigrmat(ispin))
    2095             :       END DO
    2096         340 :       DEALLOCATE (eigrmat)
    2097             : 
    2098         340 :       CALL timestop(handle)
    2099             : 
    2100        1020 :    END SUBROUTINE qs_moment_berry_phase
    2101             : 
    2102             : ! **************************************************************************************************
    2103             : !> \brief ...
    2104             : !> \param cosmat ...
    2105             : !> \param sinmat ...
    2106             : !> \param mos ...
    2107             : !> \param op_fm_set ...
    2108             : !> \param opvec ...
    2109             : ! **************************************************************************************************
    2110         972 :    SUBROUTINE op_orbbas(cosmat, sinmat, mos, op_fm_set, opvec)
    2111             : 
    2112             :       TYPE(dbcsr_type), POINTER                          :: cosmat, sinmat
    2113             :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mos
    2114             :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN)      :: op_fm_set
    2115             :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: opvec
    2116             : 
    2117             :       INTEGER                                            :: i, nao, nmo
    2118             :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    2119             : 
    2120        1986 :       DO i = 1, SIZE(op_fm_set, 2) ! spin
    2121        1014 :          CALL get_mo_set(mo_set=mos(i), nao=nao, mo_coeff=mo_coeff, nmo=nmo)
    2122        1014 :          CALL cp_dbcsr_sm_fm_multiply(cosmat, mo_coeff, opvec(i), ncol=nmo)
    2123             :          CALL parallel_gemm("T", "N", nmo, nmo, nao, 1.0_dp, mo_coeff, opvec(i), 0.0_dp, &
    2124        1014 :                             op_fm_set(1, i))
    2125        1014 :          CALL cp_dbcsr_sm_fm_multiply(sinmat, mo_coeff, opvec(i), ncol=nmo)
    2126             :          CALL parallel_gemm("T", "N", nmo, nmo, nao, 1.0_dp, mo_coeff, opvec(i), 0.0_dp, &
    2127        3000 :                             op_fm_set(2, i))
    2128             :       END DO
    2129             : 
    2130         972 :    END SUBROUTINE op_orbbas
    2131             : 
    2132             : ! **************************************************************************************************
    2133             : !> \brief ...
    2134             : !> \param cosmat ...
    2135             : !> \param sinmat ...
    2136             : !> \param mos ...
    2137             : !> \param op_fm_set ...
    2138             : !> \param mos_new ...
    2139             : ! **************************************************************************************************
    2140          48 :    SUBROUTINE op_orbbas_rtp(cosmat, sinmat, mos, op_fm_set, mos_new)
    2141             : 
    2142             :       TYPE(dbcsr_type), POINTER                          :: cosmat, sinmat
    2143             :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mos
    2144             :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN)      :: op_fm_set
    2145             :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: mos_new
    2146             : 
    2147             :       INTEGER                                            :: i, icol, lcol, nao, newdim, nmo
    2148             :       LOGICAL                                            :: double_col, double_row
    2149             :       TYPE(cp_fm_struct_type), POINTER                   :: newstruct, newstruct1
    2150             :       TYPE(cp_fm_type)                                   :: work, work1, work2
    2151             :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    2152             : 
    2153         120 :       DO i = 1, SIZE(op_fm_set, 2) ! spin
    2154          72 :          CALL get_mo_set(mo_set=mos(i), nao=nao, mo_coeff=mo_coeff, nmo=nmo)
    2155          72 :          CALL cp_fm_get_info(mos_new(2*i), ncol_local=lcol, ncol_global=nmo)
    2156          72 :          double_col = .TRUE.
    2157          72 :          double_row = .FALSE.
    2158             :          CALL cp_fm_struct_double(newstruct, &
    2159             :                                   mos_new(2*i)%matrix_struct, &
    2160             :                                   mos_new(2*i)%matrix_struct%context, &
    2161             :                                   double_col, &
    2162          72 :                                   double_row)
    2163             : 
    2164          72 :          CALL cp_fm_create(work, matrix_struct=newstruct)
    2165          72 :          CALL cp_fm_create(work1, matrix_struct=newstruct)
    2166          72 :          CALL cp_fm_create(work2, matrix_struct=newstruct)
    2167          72 :          CALL cp_fm_get_info(work, ncol_global=newdim)
    2168             : 
    2169          72 :          CALL cp_fm_set_all(work, 0.0_dp, 0.0_dp)
    2170         336 :          DO icol = 1, lcol
    2171        3432 :             work%local_data(:, icol) = mos_new(2*i - 1)%local_data(:, icol)
    2172        3504 :             work%local_data(:, icol + lcol) = mos_new(2*i)%local_data(:, icol)
    2173             :          END DO
    2174             : 
    2175          72 :          CALL cp_dbcsr_sm_fm_multiply(cosmat, work, work1, ncol=newdim)
    2176          72 :          CALL cp_dbcsr_sm_fm_multiply(sinmat, work, work2, ncol=newdim)
    2177             : 
    2178         336 :          DO icol = 1, lcol
    2179        3432 :             work%local_data(:, icol) = work1%local_data(:, icol) - work2%local_data(:, icol + lcol)
    2180        3504 :             work%local_data(:, icol + lcol) = work1%local_data(:, icol + lcol) + work2%local_data(:, icol)
    2181             :          END DO
    2182             : 
    2183          72 :          CALL cp_fm_release(work1)
    2184          72 :          CALL cp_fm_release(work2)
    2185             : 
    2186             :          CALL cp_fm_struct_double(newstruct1, &
    2187             :                                   op_fm_set(1, i)%matrix_struct, &
    2188             :                                   op_fm_set(1, i)%matrix_struct%context, &
    2189             :                                   double_col, &
    2190          72 :                                   double_row)
    2191             : 
    2192          72 :          CALL cp_fm_create(work1, matrix_struct=newstruct1)
    2193             : 
    2194             :          CALL parallel_gemm("T", "N", nmo, newdim, nao, 1.0_dp, mos_new(2*i - 1), &
    2195          72 :                             work, 0.0_dp, work1)
    2196             : 
    2197         336 :          DO icol = 1, lcol
    2198         756 :             op_fm_set(1, i)%local_data(:, icol) = work1%local_data(:, icol)
    2199         828 :             op_fm_set(2, i)%local_data(:, icol) = work1%local_data(:, icol + lcol)
    2200             :          END DO
    2201             : 
    2202             :          CALL parallel_gemm("T", "N", nmo, newdim, nao, 1.0_dp, mos_new(2*i), &
    2203          72 :                             work, 0.0_dp, work1)
    2204             : 
    2205         336 :          DO icol = 1, lcol
    2206             :             op_fm_set(1, i)%local_data(:, icol) = &
    2207         756 :                op_fm_set(1, i)%local_data(:, icol) + work1%local_data(:, icol + lcol)
    2208             :             op_fm_set(2, i)%local_data(:, icol) = &
    2209         828 :                op_fm_set(2, i)%local_data(:, icol) - work1%local_data(:, icol)
    2210             :          END DO
    2211             : 
    2212          72 :          CALL cp_fm_release(work)
    2213          72 :          CALL cp_fm_release(work1)
    2214          72 :          CALL cp_fm_struct_release(newstruct)
    2215         336 :          CALL cp_fm_struct_release(newstruct1)
    2216             : 
    2217             :       END DO
    2218             : 
    2219          48 :    END SUBROUTINE op_orbbas_rtp
    2220             : 
    2221             : ! **************************************************************************************************
    2222             : !> \brief ...
    2223             : !> \param qs_env ...
    2224             : !> \param magnetic ...
    2225             : !> \param nmoments ...
    2226             : !> \param reference ...
    2227             : !> \param ref_point ...
    2228             : !> \param unit_number ...
    2229             : !> \param vel_reprs ...
    2230             : !> \param com_nl ...
    2231             : ! **************************************************************************************************
    2232         796 :    SUBROUTINE qs_moment_locop(qs_env, magnetic, nmoments, reference, ref_point, unit_number, vel_reprs, com_nl)
    2233             : 
    2234             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2235             :       LOGICAL, INTENT(IN)                                :: magnetic
    2236             :       INTEGER, INTENT(IN)                                :: nmoments, reference
    2237             :       REAL(dp), DIMENSION(:), INTENT(IN), POINTER        :: ref_point
    2238             :       INTEGER, INTENT(IN)                                :: unit_number
    2239             :       LOGICAL, INTENT(IN), OPTIONAL                      :: vel_reprs, com_nl
    2240             : 
    2241             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'qs_moment_locop'
    2242             : 
    2243         796 :       CHARACTER(LEN=8), ALLOCATABLE, DIMENSION(:)        :: rlab
    2244             :       CHARACTER(LEN=default_string_length)               :: description
    2245             :       INTEGER                                            :: akind, handle, i, ia, iatom, idir, &
    2246             :                                                             ikind, ispin, ix, iy, iz, l, nm, nmom, &
    2247             :                                                             order
    2248             :       LOGICAL                                            :: my_com_nl, my_velreprs
    2249             :       REAL(dp)                                           :: charge, dd, strace, trace
    2250         796 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: mmom, nlcom_rrv, nlcom_rrv_vrr, &
    2251         796 :                                                             nlcom_rv, nlcom_rvr, nlcom_rxrv, &
    2252         796 :                                                             qupole_der, rmom_vel
    2253         796 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: rmom
    2254             :       REAL(dp), DIMENSION(3)                             :: rcc, ria
    2255             :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
    2256             :       TYPE(cell_type), POINTER                           :: cell
    2257             :       TYPE(cp_result_type), POINTER                      :: results
    2258         796 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: magmom, matrix_s, moments, momentum, &
    2259         796 :                                                             rho_ao
    2260         796 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: moments_der
    2261             :       TYPE(dbcsr_type), POINTER                          :: tmp_ao
    2262             :       TYPE(dft_control_type), POINTER                    :: dft_control
    2263             :       TYPE(distribution_1d_type), POINTER                :: local_particles
    2264             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2265             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    2266         796 :          POINTER                                         :: sab_all, sab_orb
    2267         796 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    2268         796 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    2269             :       TYPE(qs_rho_type), POINTER                         :: rho
    2270             : 
    2271           0 :       CPASSERT(ASSOCIATED(qs_env))
    2272             : 
    2273         796 :       CALL timeset(routineN, handle)
    2274             : 
    2275         796 :       my_velreprs = .FALSE.
    2276         796 :       IF (PRESENT(vel_reprs)) my_velreprs = vel_reprs
    2277         796 :       IF (PRESENT(com_nl)) my_com_nl = com_nl
    2278         796 :       IF (my_velreprs) CALL cite_reference(Mattiat2019)
    2279             : 
    2280             :       ! reference point
    2281         796 :       CALL get_reference_point(rcc, qs_env=qs_env, reference=reference, ref_point=ref_point)
    2282             : 
    2283             :       ! only allow for moments up to maxl set by basis
    2284         796 :       nmom = MIN(nmoments, current_maxl)
    2285             :       ! electronic contribution
    2286         796 :       NULLIFY (dft_control, rho, cell, particle_set, qs_kind_set, results, para_env, matrix_s, rho_ao, sab_all, sab_orb)
    2287             :       CALL get_qs_env(qs_env, &
    2288             :                       dft_control=dft_control, &
    2289             :                       rho=rho, &
    2290             :                       cell=cell, &
    2291             :                       results=results, &
    2292             :                       particle_set=particle_set, &
    2293             :                       qs_kind_set=qs_kind_set, &
    2294             :                       para_env=para_env, &
    2295             :                       matrix_s=matrix_s, &
    2296             :                       sab_all=sab_all, &
    2297         796 :                       sab_orb=sab_orb)
    2298             : 
    2299         796 :       IF (my_com_nl) THEN
    2300          28 :          IF ((nmom >= 1) .AND. my_velreprs) THEN
    2301          28 :             ALLOCATE (nlcom_rv(3))
    2302         112 :             nlcom_rv(:) = 0._dp
    2303             :          END IF
    2304          28 :          IF ((nmom >= 2) .AND. my_velreprs) THEN
    2305          28 :             ALLOCATE (nlcom_rrv(6))
    2306         196 :             nlcom_rrv(:) = 0._dp
    2307          28 :             ALLOCATE (nlcom_rvr(6))
    2308         196 :             nlcom_rvr(:) = 0._dp
    2309          28 :             ALLOCATE (nlcom_rrv_vrr(6))
    2310         196 :             nlcom_rrv_vrr(:) = 0._dp
    2311             :          END IF
    2312          28 :          IF (magnetic) THEN
    2313           6 :             ALLOCATE (nlcom_rxrv(3))
    2314          24 :             nlcom_rxrv = 0._dp
    2315             :          END IF
    2316             :          ! Calculate non local correction terms
    2317          28 :          CALL calculate_commutator_nl_terms(qs_env, nlcom_rv, nlcom_rxrv, nlcom_rrv, nlcom_rvr, nlcom_rrv_vrr, rcc)
    2318             :       END IF
    2319             : 
    2320         796 :       NULLIFY (moments)
    2321         796 :       nm = (6 + 11*nmom + 6*nmom**2 + nmom**3)/6 - 1
    2322         796 :       CALL dbcsr_allocate_matrix_set(moments, nm)
    2323        3414 :       DO i = 1, nm
    2324        2618 :          ALLOCATE (moments(i)%matrix)
    2325        2618 :          IF (my_velreprs .AND. (nmom >= 2)) THEN
    2326             :             CALL dbcsr_create(moments(i)%matrix, template=matrix_s(1)%matrix, &
    2327         252 :                               matrix_type=dbcsr_type_symmetric)
    2328         252 :             CALL cp_dbcsr_alloc_block_from_nbl(moments(i)%matrix, sab_orb)
    2329             :          ELSE
    2330        2366 :             CALL dbcsr_copy(moments(i)%matrix, matrix_s(1)%matrix, "Moments")
    2331             :          END IF
    2332        3414 :          CALL dbcsr_set(moments(i)%matrix, 0.0_dp)
    2333             :       END DO
    2334             : 
    2335             :       ! calculate derivatives if quadrupole in vel. reprs. is requested
    2336         796 :       IF (my_velreprs .AND. (nmom >= 2)) THEN
    2337          28 :          NULLIFY (moments_der)
    2338          28 :          CALL dbcsr_allocate_matrix_set(moments_der, 3, 3)
    2339         112 :          DO i = 1, 3 ! x, y, z
    2340         364 :             DO idir = 1, 3 ! d/dx, d/dy, d/dz
    2341         252 :                CALL dbcsr_init_p(moments_der(i, idir)%matrix)
    2342             :                CALL dbcsr_create(moments_der(i, idir)%matrix, template=matrix_s(1)%matrix, &
    2343         252 :                                  matrix_type=dbcsr_type_antisymmetric)
    2344         252 :                CALL cp_dbcsr_alloc_block_from_nbl(moments_der(i, idir)%matrix, sab_orb)
    2345         336 :                CALL dbcsr_set(moments_der(i, idir)%matrix, 0.0_dp)
    2346             :             END DO
    2347             :          END DO
    2348          28 :          CALL build_local_moments_der_matrix(qs_env, moments_der, 1, 2, ref_point=rcc, moments=moments)
    2349             :       ELSE
    2350         768 :          CALL build_local_moment_matrix(qs_env, moments, nmom, ref_point=rcc)
    2351             :       END IF
    2352             : 
    2353         796 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
    2354             : 
    2355        3184 :       ALLOCATE (rmom(nm + 1, 3))
    2356        2388 :       ALLOCATE (rlab(nm + 1))
    2357       13426 :       rmom = 0.0_dp
    2358        4210 :       rlab = ""
    2359             : 
    2360         796 :       IF ((my_velreprs .AND. (nmoments >= 1)) .OR. magnetic) THEN
    2361             :          ! Allocate matrix to store the matrix product to be traced (dbcsr_dot only works for products of
    2362             :          ! symmetric matrices)
    2363          30 :          NULLIFY (tmp_ao)
    2364          30 :          CALL dbcsr_init_p(tmp_ao)
    2365          30 :          CALL dbcsr_create(tmp_ao, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry, name="tmp")
    2366          30 :          CALL cp_dbcsr_alloc_block_from_nbl(tmp_ao, sab_all)
    2367          30 :          CALL dbcsr_set(tmp_ao, 0.0_dp)
    2368             :       END IF
    2369             : 
    2370         796 :       trace = 0.0_dp
    2371        1664 :       DO ispin = 1, dft_control%nspins
    2372         868 :          CALL dbcsr_dot(rho_ao(ispin)%matrix, matrix_s(1)%matrix, trace)
    2373        1664 :          rmom(1, 1) = rmom(1, 1) + trace
    2374             :       END DO
    2375             : 
    2376        3414 :       DO i = 1, SIZE(moments)
    2377        2618 :          strace = 0._dp
    2378        5452 :          DO ispin = 1, dft_control%nspins
    2379        2834 :             IF (my_velreprs .AND. nmoments >= 2) THEN
    2380             :                CALL dbcsr_multiply("T", "N", 1.0_dp, rho_ao(ispin)%matrix, moments(i)%matrix, &
    2381         252 :                                    0.0_dp, tmp_ao)
    2382         252 :                CALL dbcsr_trace(tmp_ao, trace)
    2383             :             ELSE
    2384        2582 :                CALL dbcsr_dot(rho_ao(ispin)%matrix, moments(i)%matrix, trace)
    2385             :             END IF
    2386        5452 :             strace = strace + trace
    2387             :          END DO
    2388        3414 :          rmom(i + 1, 1) = strace
    2389             :       END DO
    2390             : 
    2391         796 :       CALL dbcsr_deallocate_matrix_set(moments)
    2392             : 
    2393             :       ! nuclear contribution
    2394             :       CALL get_qs_env(qs_env=qs_env, &
    2395         796 :                       local_particles=local_particles)
    2396        2488 :       DO ikind = 1, SIZE(local_particles%n_el)
    2397        3726 :          DO ia = 1, local_particles%n_el(ikind)
    2398        1238 :             iatom = local_particles%list(ikind)%array(ia)
    2399             :             ! fold atomic positions back into unit cell
    2400        9904 :             ria = pbc(particle_set(iatom)%r - rcc, cell) + rcc
    2401        4952 :             ria = ria - rcc
    2402        1238 :             atomic_kind => particle_set(iatom)%atomic_kind
    2403        1238 :             CALL get_atomic_kind(atomic_kind, kind_number=akind)
    2404        1238 :             CALL get_qs_kind(qs_kind_set(akind), core_charge=charge)
    2405        1238 :             rmom(1, 2) = rmom(1, 2) - charge
    2406        6923 :             DO l = 1, nm
    2407        3993 :                ix = indco(1, l + 1)
    2408        3993 :                iy = indco(2, l + 1)
    2409        3993 :                iz = indco(3, l + 1)
    2410        3993 :                dd = 1._dp
    2411        3993 :                IF (ix > 0) dd = dd*ria(1)**ix
    2412        3993 :                IF (iy > 0) dd = dd*ria(2)**iy
    2413        3993 :                IF (iz > 0) dd = dd*ria(3)**iz
    2414        3993 :                rmom(l + 1, 2) = rmom(l + 1, 2) - charge*dd
    2415        5231 :                CALL set_label(rlab(l + 1), ix, iy, iz)
    2416             :             END DO
    2417             :          END DO
    2418             :       END DO
    2419         796 :       CALL para_env%sum(rmom(:, 2))
    2420       13426 :       rmom(:, :) = -rmom(:, :)
    2421        4210 :       rmom(:, 3) = rmom(:, 1) + rmom(:, 2)
    2422             : 
    2423             :       ! magnetic moments
    2424         796 :       IF (magnetic) THEN
    2425           8 :          NULLIFY (magmom)
    2426           8 :          CALL dbcsr_allocate_matrix_set(magmom, 3)
    2427          32 :          DO i = 1, SIZE(magmom)
    2428          24 :             CALL dbcsr_init_p(magmom(i)%matrix)
    2429             :             CALL dbcsr_create(magmom(i)%matrix, template=matrix_s(1)%matrix, &
    2430          24 :                               matrix_type=dbcsr_type_antisymmetric)
    2431          24 :             CALL cp_dbcsr_alloc_block_from_nbl(magmom(i)%matrix, sab_orb)
    2432          32 :             CALL dbcsr_set(magmom(i)%matrix, 0.0_dp)
    2433             :          END DO
    2434             : 
    2435           8 :          CALL build_local_magmom_matrix(qs_env, magmom, nmom, ref_point=rcc)
    2436             : 
    2437          24 :          ALLOCATE (mmom(SIZE(magmom)))
    2438          32 :          mmom(:) = 0.0_dp
    2439           8 :          IF (qs_env%run_rtp) THEN
    2440             :             ! get imaginary part of the density in rho_ao (the real part is not needed since the trace of the product
    2441             :             ! of a symmetric (REAL(rho_ao)) and an anti-symmetric (L_AO) matrix is zero)
    2442             :             ! There may be other cases, where the imaginary part of the density is relevant
    2443           4 :             NULLIFY (rho_ao)
    2444           4 :             CALL qs_rho_get(rho, rho_ao_im=rho_ao)
    2445             :          END IF
    2446             :          ! if the density is purely real this is an expensive way to calculate zero
    2447          32 :          DO i = 1, SIZE(magmom)
    2448          24 :             strace = 0._dp
    2449          48 :             DO ispin = 1, dft_control%nspins
    2450          24 :                CALL dbcsr_set(tmp_ao, 0.0_dp)
    2451             :                CALL dbcsr_multiply("T", "N", 1.0_dp, rho_ao(ispin)%matrix, magmom(i)%matrix, &
    2452          24 :                                    0.0_dp, tmp_ao)
    2453          24 :                CALL dbcsr_trace(tmp_ao, trace)
    2454          48 :                strace = strace + trace
    2455             :             END DO
    2456          32 :             mmom(i) = strace
    2457             :          END DO
    2458             : 
    2459           8 :          CALL dbcsr_deallocate_matrix_set(magmom)
    2460             :       END IF
    2461             : 
    2462             :       ! velocity representations
    2463         796 :       IF (my_velreprs) THEN
    2464          84 :          ALLOCATE (rmom_vel(nm))
    2465         280 :          rmom_vel = 0.0_dp
    2466             : 
    2467          84 :          DO order = 1, nmom
    2468          28 :             SELECT CASE (order)
    2469             : 
    2470             :             CASE (1) ! expectation value of momentum
    2471          28 :                NULLIFY (momentum)
    2472          28 :                CALL dbcsr_allocate_matrix_set(momentum, 3)
    2473         112 :                DO i = 1, 3
    2474          84 :                   CALL dbcsr_init_p(momentum(i)%matrix)
    2475             :                   CALL dbcsr_create(momentum(i)%matrix, template=matrix_s(1)%matrix, &
    2476          84 :                                     matrix_type=dbcsr_type_antisymmetric)
    2477          84 :                   CALL cp_dbcsr_alloc_block_from_nbl(momentum(i)%matrix, sab_orb)
    2478         112 :                   CALL dbcsr_set(momentum(i)%matrix, 0.0_dp)
    2479             :                END DO
    2480          28 :                CALL build_lin_mom_matrix(qs_env, momentum)
    2481             : 
    2482             :                ! imaginary part of the density for RTP, real part gives 0 since momentum is antisymmetric
    2483          28 :                IF (qs_env%run_rtp) THEN
    2484          22 :                   NULLIFY (rho_ao)
    2485          22 :                   CALL qs_rho_get(rho, rho_ao_im=rho_ao)
    2486          88 :                   DO idir = 1, SIZE(momentum)
    2487          66 :                      strace = 0._dp
    2488         132 :                      DO ispin = 1, dft_control%nspins
    2489          66 :                         CALL dbcsr_set(tmp_ao, 0.0_dp)
    2490             :                         CALL dbcsr_multiply("T", "N", 1.0_dp, rho_ao(ispin)%matrix, momentum(idir)%matrix, &
    2491          66 :                                             0.0_dp, tmp_ao)
    2492          66 :                         CALL dbcsr_trace(tmp_ao, trace)
    2493         132 :                         strace = strace + trace
    2494             :                      END DO
    2495          88 :                      rmom_vel(idir) = rmom_vel(idir) + strace
    2496             :                   END DO
    2497             :                END IF
    2498             : 
    2499          28 :                CALL dbcsr_deallocate_matrix_set(momentum)
    2500             : 
    2501             :             CASE (2) ! expectation value of quadrupole moment in vel. reprs.
    2502          28 :                ALLOCATE (qupole_der(9)) ! will contain the expectation values of r_\alpha * d/d r_\beta
    2503         280 :                qupole_der = 0._dp
    2504             : 
    2505          28 :                NULLIFY (rho_ao)
    2506          28 :                CALL qs_rho_get(rho, rho_ao=rho_ao)
    2507             : 
    2508             :                ! Calculate expectation value over real part
    2509          28 :                trace = 0._dp
    2510         112 :                DO i = 1, 3
    2511         364 :                   DO idir = 1, 3
    2512         252 :                      strace = 0._dp
    2513         504 :                      DO ispin = 1, dft_control%nspins
    2514         252 :                         CALL dbcsr_set(tmp_ao, 0._dp)
    2515         252 :                         CALL dbcsr_multiply("T", "N", 1._dp, rho_ao(ispin)%matrix, moments_der(i, idir)%matrix, 0._dp, tmp_ao)
    2516         252 :                         CALL dbcsr_trace(tmp_ao, trace)
    2517         504 :                         strace = strace + trace
    2518             :                      END DO
    2519         336 :                      qupole_der((i - 1)*3 + idir) = qupole_der((i - 1)*3 + idir) + strace
    2520             :                   END DO
    2521             :                END DO
    2522             : 
    2523          28 :                IF (qs_env%run_rtp) THEN
    2524          22 :                   NULLIFY (rho_ao)
    2525          22 :                   CALL qs_rho_get(rho, rho_ao_im=rho_ao)
    2526             : 
    2527             :                   ! Calculate expectation value over imaginary part
    2528          22 :                   trace = 0._dp
    2529          88 :                   DO i = 1, 3
    2530         286 :                      DO idir = 1, 3
    2531         198 :                         strace = 0._dp
    2532         396 :                         DO ispin = 1, dft_control%nspins
    2533         198 :                            CALL dbcsr_set(tmp_ao, 0._dp)
    2534         198 :                            CALL dbcsr_multiply("T", "N", 1._dp, rho_ao(ispin)%matrix, moments_der(i, idir)%matrix, 0._dp, tmp_ao)
    2535         198 :                            CALL dbcsr_trace(tmp_ao, trace)
    2536         396 :                            strace = strace + trace
    2537             :                         END DO
    2538         264 :                         qupole_der((i - 1)*3 + idir) = qupole_der((i - 1)*3 + idir) + strace
    2539             :                      END DO
    2540             :                   END DO
    2541             :                END IF
    2542             : 
    2543             :                ! calculate vel. reprs. of quadrupole moment from derivatives
    2544          28 :                rmom_vel(4) = -2*qupole_der(1) - rmom(1, 1)
    2545          28 :                rmom_vel(5) = -qupole_der(2) - qupole_der(4)
    2546          28 :                rmom_vel(6) = -qupole_der(3) - qupole_der(7)
    2547          28 :                rmom_vel(7) = -2*qupole_der(5) - rmom(1, 1)
    2548          28 :                rmom_vel(8) = -qupole_der(6) - qupole_der(8)
    2549          28 :                rmom_vel(9) = -2*qupole_der(9) - rmom(1, 1)
    2550             : 
    2551          84 :                DEALLOCATE (qupole_der)
    2552             :             CASE DEFAULT
    2553             :             END SELECT
    2554             :          END DO
    2555             :       END IF
    2556             : 
    2557         796 :       IF ((my_velreprs .AND. (nmoments >= 1)) .OR. magnetic) THEN
    2558          30 :          CALL dbcsr_deallocate_matrix(tmp_ao)
    2559             :       END IF
    2560         796 :       IF (my_velreprs .AND. (nmoments >= 2)) THEN
    2561          28 :          CALL dbcsr_deallocate_matrix_set(moments_der)
    2562             :       END IF
    2563             : 
    2564         796 :       description = "[DIPOLE]"
    2565         796 :       CALL cp_results_erase(results=results, description=description)
    2566             :       CALL put_results(results=results, description=description, &
    2567         796 :                        values=rmom(2:4, 3))
    2568             : 
    2569         796 :       IF (magnetic .AND. my_velreprs) THEN
    2570           6 :          CALL print_moments(unit_number, nmom, rmom, rlab, rcc, cell, periodic=.FALSE., mmom=mmom, rmom_vel=rmom_vel)
    2571         790 :       ELSE IF (magnetic .AND. .NOT. my_velreprs) THEN
    2572           2 :          CALL print_moments(unit_number, nmom, rmom, rlab, rcc, cell, periodic=.FALSE., mmom=mmom)
    2573         788 :       ELSE IF (my_velreprs .AND. .NOT. magnetic) THEN
    2574          22 :          CALL print_moments(unit_number, nmom, rmom, rlab, rcc, cell, periodic=.FALSE., rmom_vel=rmom_vel)
    2575             :       ELSE
    2576         766 :          CALL print_moments(unit_number, nmom, rmom, rlab, rcc, cell, periodic=.FALSE.)
    2577             :       END IF
    2578             : 
    2579         796 :       IF (my_com_nl) THEN
    2580          28 :          IF (magnetic) THEN
    2581          24 :             mmom(:) = nlcom_rxrv(:)
    2582             :          END IF
    2583          28 :          IF (my_velreprs .AND. (nmom >= 1)) THEN
    2584          28 :             DEALLOCATE (rmom_vel)
    2585          28 :             ALLOCATE (rmom_vel(21))
    2586         112 :             rmom_vel(1:3) = nlcom_rv
    2587             :          END IF
    2588          28 :          IF (my_velreprs .AND. (nmom >= 2)) THEN
    2589         196 :             rmom_vel(4:9) = nlcom_rrv
    2590         196 :             rmom_vel(10:15) = nlcom_rvr
    2591         196 :             rmom_vel(16:21) = nlcom_rrv_vrr
    2592             :          END IF
    2593          28 :          IF (magnetic .AND. .NOT. my_velreprs) THEN
    2594           0 :             CALL print_moments_nl(unit_number, nmom, rlab, mmom=mmom)
    2595          28 :          ELSE IF (my_velreprs .AND. .NOT. magnetic) THEN
    2596          22 :             CALL print_moments_nl(unit_number, nmom, rlab, rmom_vel=rmom_vel)
    2597           6 :          ELSE IF (my_velreprs .AND. magnetic) THEN
    2598           6 :             CALL print_moments_nl(unit_number, nmom, rlab, mmom=mmom, rmom_vel=rmom_vel)
    2599             :          END IF
    2600             : 
    2601             :       END IF
    2602             : 
    2603             :       IF (my_com_nl) THEN
    2604          28 :          IF (nmom >= 1 .AND. my_velreprs) DEALLOCATE (nlcom_rv)
    2605          28 :          IF (nmom >= 2 .AND. my_velreprs) THEN
    2606          28 :             DEALLOCATE (nlcom_rrv)
    2607          28 :             DEALLOCATE (nlcom_rvr)
    2608          28 :             DEALLOCATE (nlcom_rrv_vrr)
    2609             :          END IF
    2610          28 :          IF (magnetic) DEALLOCATE (nlcom_rxrv)
    2611             :       END IF
    2612             : 
    2613         796 :       DEALLOCATE (rmom)
    2614         796 :       DEALLOCATE (rlab)
    2615         796 :       IF (magnetic) THEN
    2616           8 :          DEALLOCATE (mmom)
    2617             :       END IF
    2618         796 :       IF (my_velreprs) THEN
    2619          28 :          DEALLOCATE (rmom_vel)
    2620             :       END IF
    2621             : 
    2622         796 :       CALL timestop(handle)
    2623             : 
    2624        1592 :    END SUBROUTINE qs_moment_locop
    2625             : 
    2626             : ! **************************************************************************************************
    2627             : !> \brief ...
    2628             : !> \param label ...
    2629             : !> \param ix ...
    2630             : !> \param iy ...
    2631             : !> \param iz ...
    2632             : ! **************************************************************************************************
    2633        5013 :    SUBROUTINE set_label(label, ix, iy, iz)
    2634             :       CHARACTER(LEN=*), INTENT(OUT)                      :: label
    2635             :       INTEGER, INTENT(IN)                                :: ix, iy, iz
    2636             : 
    2637             :       INTEGER                                            :: i
    2638             : 
    2639        5013 :       label = ""
    2640        6817 :       DO i = 1, ix
    2641        6817 :          WRITE (label(i:), "(A1)") "X"
    2642             :       END DO
    2643        6817 :       DO i = ix + 1, ix + iy
    2644        6817 :          WRITE (label(i:), "(A1)") "Y"
    2645             :       END DO
    2646        6817 :       DO i = ix + iy + 1, ix + iy + iz
    2647        6817 :          WRITE (label(i:), "(A1)") "Z"
    2648             :       END DO
    2649             : 
    2650        5013 :    END SUBROUTINE set_label
    2651             : 
    2652             : ! **************************************************************************************************
    2653             : !> \brief ...
    2654             : !> \param unit_number ...
    2655             : !> \param nmom ...
    2656             : !> \param rmom ...
    2657             : !> \param rlab ...
    2658             : !> \param rcc ...
    2659             : !> \param cell ...
    2660             : !> \param periodic ...
    2661             : !> \param mmom ...
    2662             : !> \param rmom_vel ...
    2663             : ! **************************************************************************************************
    2664        1136 :    SUBROUTINE print_moments(unit_number, nmom, rmom, rlab, rcc, cell, periodic, mmom, rmom_vel)
    2665             :       INTEGER, INTENT(IN)                                :: unit_number, nmom
    2666             :       REAL(dp), DIMENSION(:, :), INTENT(IN)              :: rmom
    2667             :       CHARACTER(LEN=8), DIMENSION(:)                     :: rlab
    2668             :       REAL(dp), DIMENSION(3), INTENT(IN)                 :: rcc
    2669             :       TYPE(cell_type), POINTER                           :: cell
    2670             :       LOGICAL                                            :: periodic
    2671             :       REAL(dp), DIMENSION(:), INTENT(IN), OPTIONAL       :: mmom, rmom_vel
    2672             : 
    2673             :       INTEGER                                            :: i, i0, i1, j, l
    2674             :       REAL(dp)                                           :: dd
    2675             : 
    2676        1136 :       IF (unit_number > 0) THEN
    2677        1751 :          DO l = 0, nmom
    2678         578 :             SELECT CASE (l)
    2679             :             CASE (0)
    2680         578 :                WRITE (unit_number, "(T3,A,T33,3F16.8)") "Reference Point [Bohr]", rcc
    2681         578 :                WRITE (unit_number, "(T3,A)") "Charges"
    2682             :                WRITE (unit_number, "(T5,A,T18,F14.8,T36,A,T42,F14.8,T60,A,T67,F14.8)") &
    2683         578 :                   "Electronic=", rmom(1, 1), "Core=", rmom(1, 2), "Total=", rmom(1, 3)
    2684             :             CASE (1)
    2685         578 :                IF (periodic) THEN
    2686         180 :                   WRITE (unit_number, "(T3,A)") "Dipole vectors are based on the periodic (Berry phase) operator."
    2687         180 :                   WRITE (unit_number, "(T3,A)") "They are defined modulo integer multiples of the cell matrix [Debye]."
    2688         720 :                   WRITE (unit_number, "(T3,A,3(F14.8,1X),A)") "[X] [", cell%hmat(1, :)*debye, "] [i]"
    2689         720 :                   WRITE (unit_number, "(T3,A,3(F14.8,1X),A)") "[Y]=[", cell%hmat(2, :)*debye, "]*[j]"
    2690         720 :                   WRITE (unit_number, "(T3,A,3(F14.8,1X),A)") "[Z] [", cell%hmat(3, :)*debye, "] [k]"
    2691             :                ELSE
    2692         398 :                   WRITE (unit_number, "(T3,A)") "Dipoles are based on the traditional operator."
    2693             :                END IF
    2694        2312 :                dd = SQRT(SUM(rmom(2:4, 3)**2))*debye
    2695         578 :                WRITE (unit_number, "(T3,A)") "Dipole moment [Debye]"
    2696             :                WRITE (unit_number, "(T5,3(A,A,E15.7,1X),T60,A,T68,F13.7)") &
    2697        2312 :                   (TRIM(rlab(i)), "=", rmom(i, 3)*debye, i=2, 4), "Total=", dd
    2698             :             CASE (2)
    2699          15 :                WRITE (unit_number, "(T3,A)") "Quadrupole moment [Debye*Angstrom]"
    2700             :                WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
    2701          60 :                   (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr, i=5, 7)
    2702             :                WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
    2703          60 :                   (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr, i=8, 10)
    2704             :             CASE (3)
    2705           1 :                WRITE (unit_number, "(T3,A)") "Octapole moment [Debye*Angstrom**2]"
    2706             :                WRITE (unit_number, "(T7,4(A,A,F14.8,3X))") &
    2707           5 :                   (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr/bohr, i=11, 14)
    2708             :                WRITE (unit_number, "(T7,4(A,A,F14.8,3X))") &
    2709           5 :                   (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr/bohr, i=15, 18)
    2710             :                WRITE (unit_number, "(T7,4(A,A,F14.8,3X))") &
    2711           3 :                   (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr/bohr, i=19, 20)
    2712             :             CASE (4)
    2713           1 :                WRITE (unit_number, "(T3,A)") "Hexadecapole moment [Debye*Angstrom**3]"
    2714             :                WRITE (unit_number, "(T6,4(A,A,F14.8,2X))") &
    2715           5 :                   (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr/bohr/bohr, i=21, 24)
    2716             :                WRITE (unit_number, "(T6,4(A,A,F14.8,2X))") &
    2717           5 :                   (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr/bohr/bohr, i=25, 28)
    2718             :                WRITE (unit_number, "(T6,4(A,A,F14.8,2X))") &
    2719           5 :                   (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr/bohr/bohr, i=29, 32)
    2720             :                WRITE (unit_number, "(T6,4(A,A,F14.8,2X))") &
    2721           5 :                   (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr/bohr/bohr, i=32, 35)
    2722             :             CASE DEFAULT
    2723           0 :                WRITE (unit_number, "(T3,A,A,I2)") "Higher moment [Debye*Angstrom**(L-1)]", &
    2724           0 :                   "  L=", l
    2725           0 :                i0 = (6 + 11*(l - 1) + 6*(l - 1)**2 + (l - 1)**3)/6
    2726           0 :                i1 = (6 + 11*l + 6*l**2 + l**3)/6 - 1
    2727           0 :                dd = debye/(bohr)**(l - 1)
    2728        1173 :                DO i = i0, i1, 3
    2729             :                   WRITE (unit_number, "(T18,3(A,A,F14.8,4X))") &
    2730           0 :                      (TRIM(rlab(j + 1)), "=", rmom(j + 1, 3)*dd, j=i, MIN(i1, i + 2))
    2731             :                END DO
    2732             :             END SELECT
    2733             :          END DO
    2734         578 :          IF (PRESENT(mmom)) THEN
    2735           4 :             IF (nmom >= 1) THEN
    2736          16 :                dd = SQRT(SUM(mmom(1:3)**2))
    2737           4 :                WRITE (unit_number, "(T3,A)") "Orbital angular momentum [a. u.]"
    2738             :                WRITE (unit_number, "(T5,3(A,A,E16.8,1X),T64,A,T71,F14.8)") &
    2739          16 :                   (TRIM(rlab(i + 1)), "=", mmom(i), i=1, 3), "Total=", dd
    2740             :             END IF
    2741             :          END IF
    2742         578 :          IF (PRESENT(rmom_vel)) THEN
    2743          42 :             DO l = 1, nmom
    2744          14 :                SELECT CASE (l)
    2745             :                CASE (1)
    2746          56 :                   dd = SQRT(SUM(rmom_vel(1:3)**2))
    2747          14 :                   WRITE (unit_number, "(T3,A)") "Expectation value of momentum operator [a. u.]"
    2748             :                   WRITE (unit_number, "(T5,3(A,A,E16.8,1X),T64,A,T71,F14.8)") &
    2749          56 :                      (TRIM(rlab(i + 1)), "=", rmom_vel(i), i=1, 3), "Total=", dd
    2750             :                CASE (2)
    2751          14 :                   WRITE (unit_number, "(T3,A)") "Expectation value of quadrupole operator in vel. repr. [a. u.]"
    2752             :                   WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
    2753          56 :                      (TRIM(rlab(i + 1)), "=", rmom_vel(i), i=4, 6)
    2754             :                   WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
    2755          84 :                      (TRIM(rlab(i + 1)), "=", rmom_vel(i), i=7, 9)
    2756             :                CASE DEFAULT
    2757             :                END SELECT
    2758             :             END DO
    2759             :          END IF
    2760             :       END IF
    2761             : 
    2762        1136 :    END SUBROUTINE print_moments
    2763             : 
    2764             : ! **************************************************************************************************
    2765             : !> \brief ...
    2766             : !> \param unit_number ...
    2767             : !> \param nmom ...
    2768             : !> \param rlab ...
    2769             : !> \param mmom ...
    2770             : !> \param rmom_vel ...
    2771             : ! **************************************************************************************************
    2772          28 :    SUBROUTINE print_moments_nl(unit_number, nmom, rlab, mmom, rmom_vel)
    2773             :       INTEGER, INTENT(IN)                                :: unit_number, nmom
    2774             :       CHARACTER(LEN=8), DIMENSION(:)                     :: rlab
    2775             :       REAL(dp), DIMENSION(:), INTENT(IN), OPTIONAL       :: mmom, rmom_vel
    2776             : 
    2777             :       INTEGER                                            :: i, l
    2778             :       REAL(dp)                                           :: dd
    2779             : 
    2780          28 :       IF (unit_number > 0) THEN
    2781          14 :          IF (PRESENT(mmom)) THEN
    2782           3 :             IF (nmom >= 1) THEN
    2783          12 :                dd = SQRT(SUM(mmom(1:3)**2))
    2784           3 :                WRITE (unit_number, "(T3,A)") "Expectation value of rx[r,V_nl] [a. u.]"
    2785             :                WRITE (unit_number, "(T5,3(A,A,E16.8,1X),T64,A,T71,F14.8)") &
    2786          12 :                   (TRIM(rlab(i + 1)), "=", mmom(i), i=1, 3), "Total=", dd
    2787             :             END IF
    2788             :          END IF
    2789          14 :          IF (PRESENT(rmom_vel)) THEN
    2790          42 :             DO l = 1, nmom
    2791          14 :                SELECT CASE (l)
    2792             :                CASE (1)
    2793          56 :                   dd = SQRT(SUM(rmom_vel(1:3)**2))
    2794          14 :                   WRITE (unit_number, "(T3,A)") "Expectation value of [r,V_nl] [a. u.]"
    2795             :                   WRITE (unit_number, "(T5,3(A,A,E16.8,1X),T64,A,T71,F14.8)") &
    2796          56 :                      (TRIM(rlab(i + 1)), "=", rmom_vel(i), i=1, 3), "Total=", dd
    2797             :                CASE (2)
    2798          14 :                   WRITE (unit_number, "(T3,A)") "Expectation value of [rr,V_nl] [a. u.]"
    2799             :                   WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
    2800          56 :                      (TRIM(rlab(i + 1)), "=", rmom_vel(i), i=4, 6)
    2801             :                   WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
    2802          56 :                      (TRIM(rlab(i + 1)), "=", rmom_vel(i), i=7, 9)
    2803          14 :                   WRITE (unit_number, "(T3,A)") "Expectation value of r x V_nl x r [a. u.]"
    2804             :                   WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
    2805          56 :                      (TRIM(rlab(i + 1 - 6)), "=", rmom_vel(i), i=10, 12)
    2806             :                   WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
    2807          56 :                      (TRIM(rlab(i + 1 - 6)), "=", rmom_vel(i), i=13, 15)
    2808          14 :                   WRITE (unit_number, "(T3,A)") "Expectation value of r x r x V_nl + V_nl x r x r [a. u.]"
    2809             :                   WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
    2810          56 :                      (TRIM(rlab(i + 1 - 12)), "=", rmom_vel(i), i=16, 18)
    2811             :                   WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
    2812          84 :                      (TRIM(rlab(i + 1 - 12)), "=", rmom_vel(i), i=19, 21)
    2813             :                CASE DEFAULT
    2814             :                END SELECT
    2815             :             END DO
    2816             :          END IF
    2817             :       END IF
    2818             : 
    2819          28 :    END SUBROUTINE print_moments_nl
    2820             : 
    2821             : ! **************************************************************************************************
    2822             : !> \brief Calculate the expectation value of operators related to non-local potential:
    2823             : !>        [r, Vnl], noted rv
    2824             : !>        r x [r,Vnl], noted rxrv
    2825             : !>        [rr,Vnl], noted rrv
    2826             : !>        r x Vnl x r, noted rvr
    2827             : !>        r x r x Vnl + Vnl x r x r, noted rrv_vrr
    2828             : !>        Note that the 3 first operator are commutator while the 2 last
    2829             : !>        are not. For reading clarity the same notation is used for all 5
    2830             : !>        operators.
    2831             : !> \param qs_env ...
    2832             : !> \param nlcom_rv ...
    2833             : !> \param nlcom_rxrv ...
    2834             : !> \param nlcom_rrv ...
    2835             : !> \param nlcom_rvr ...
    2836             : !> \param nlcom_rrv_vrr ...
    2837             : !> \param ref_point ...
    2838             : ! **************************************************************************************************
    2839          28 :    SUBROUTINE calculate_commutator_nl_terms(qs_env, nlcom_rv, nlcom_rxrv, nlcom_rrv, nlcom_rvr, &
    2840             :                                             nlcom_rrv_vrr, ref_point)
    2841             : 
    2842             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2843             :       REAL(dp), ALLOCATABLE, DIMENSION(:), OPTIONAL      :: nlcom_rv, nlcom_rxrv, nlcom_rrv, &
    2844             :                                                             nlcom_rvr, nlcom_rrv_vrr
    2845             :       REAL(dp), DIMENSION(3)                             :: ref_point
    2846             : 
    2847             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_commutator_nl_terms'
    2848             : 
    2849             :       INTEGER                                            :: handle, ind, ispin
    2850             :       LOGICAL                                            :: calc_rrv, calc_rrv_vrr, calc_rv, &
    2851             :                                                             calc_rvr, calc_rxrv
    2852             :       REAL(dp)                                           :: eps_ppnl, strace, trace
    2853             :       TYPE(cell_type), POINTER                           :: cell
    2854          28 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_rrv, matrix_rrv_vrr, matrix_rv, &
    2855          28 :                                                             matrix_rvr, matrix_rxrv, matrix_s, &
    2856          28 :                                                             rho_ao
    2857             :       TYPE(dbcsr_type), POINTER                          :: tmp_ao
    2858             :       TYPE(dft_control_type), POINTER                    :: dft_control
    2859             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    2860          28 :          POINTER                                         :: sab_all, sab_orb, sap_ppnl
    2861          28 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    2862          28 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    2863             :       TYPE(qs_rho_type), POINTER                         :: rho
    2864             : 
    2865          28 :       CALL timeset(routineN, handle)
    2866             : 
    2867          28 :       calc_rv = .FALSE.
    2868          28 :       calc_rxrv = .FALSE.
    2869          28 :       calc_rrv = .FALSE.
    2870          28 :       calc_rvr = .FALSE.
    2871          28 :       calc_rrv_vrr = .FALSE.
    2872             : 
    2873             :       ! rv, rxrv and rrv are commutator matrices: anti-symmetric.
    2874             :       ! The real part of the density matrix rho_ao is symmetric so that
    2875             :       ! the expectation value of real density matrix is zero. Hence, if
    2876             :       ! the density matrix is real, no need to compute these quantities.
    2877             :       ! This is not the case for rvr and rrv_vrr which are symmetric.
    2878             : 
    2879          28 :       IF (ALLOCATED(nlcom_rv)) THEN
    2880         112 :          nlcom_rv(:) = 0._dp
    2881          28 :          IF (qs_env%run_rtp) calc_rv = .TRUE.
    2882             :       END IF
    2883          28 :       IF (ALLOCATED(nlcom_rxrv)) THEN
    2884          24 :          nlcom_rxrv(:) = 0._dp
    2885           6 :          IF (qs_env%run_rtp) calc_rxrv = .TRUE.
    2886             :       END IF
    2887          28 :       IF (ALLOCATED(nlcom_rrv)) THEN
    2888         196 :          nlcom_rrv(:) = 0._dp
    2889          28 :          IF (qs_env%run_rtp) calc_rrv = .TRUE.
    2890             :       END IF
    2891          28 :       IF (ALLOCATED(nlcom_rvr)) THEN
    2892         196 :          nlcom_rvr(:) = 0._dp
    2893             :          calc_rvr = .TRUE.
    2894             :       END IF
    2895          28 :       IF (ALLOCATED(nlcom_rrv_vrr)) THEN
    2896         196 :          nlcom_rrv_vrr(:) = 0._dp
    2897             :          calc_rrv_vrr = .TRUE.
    2898             :       END IF
    2899             : 
    2900          28 :       IF (.NOT. (calc_rv .OR. calc_rrv .OR. calc_rxrv &
    2901           0 :                  .OR. calc_rvr .OR. calc_rrv_vrr)) RETURN
    2902             : 
    2903          28 :       NULLIFY (cell, matrix_s, particle_set, qs_kind_set, rho, sab_all, sab_orb, sap_ppnl)
    2904             :       CALL get_qs_env(qs_env, &
    2905             :                       cell=cell, &
    2906             :                       dft_control=dft_control, &
    2907             :                       matrix_s=matrix_s, &
    2908             :                       particle_set=particle_set, &
    2909             :                       qs_kind_set=qs_kind_set, &
    2910             :                       rho=rho, &
    2911             :                       sab_orb=sab_orb, &
    2912             :                       sab_all=sab_all, &
    2913          28 :                       sap_ppnl=sap_ppnl)
    2914             : 
    2915          28 :       eps_ppnl = dft_control%qs_control%eps_ppnl
    2916             : 
    2917             :       ! Allocate storage
    2918          28 :       NULLIFY (matrix_rv, matrix_rxrv, matrix_rrv, matrix_rvr, matrix_rrv_vrr)
    2919          28 :       IF (calc_rv) THEN
    2920          22 :          CALL dbcsr_allocate_matrix_set(matrix_rv, 3)
    2921          88 :          DO ind = 1, 3
    2922          66 :             CALL dbcsr_init_p(matrix_rv(ind)%matrix)
    2923             :             CALL dbcsr_create(matrix_rv(ind)%matrix, template=matrix_s(1)%matrix, &
    2924          66 :                               matrix_type=dbcsr_type_antisymmetric)
    2925          66 :             CALL cp_dbcsr_alloc_block_from_nbl(matrix_rv(ind)%matrix, sab_orb)
    2926          88 :             CALL dbcsr_set(matrix_rv(ind)%matrix, 0._dp)
    2927             :          END DO
    2928             :       END IF
    2929             : 
    2930          28 :       IF (calc_rxrv) THEN
    2931           4 :          CALL dbcsr_allocate_matrix_set(matrix_rxrv, 3)
    2932          16 :          DO ind = 1, 3
    2933          12 :             CALL dbcsr_init_p(matrix_rxrv(ind)%matrix)
    2934             :             CALL dbcsr_create(matrix_rxrv(ind)%matrix, template=matrix_s(1)%matrix, &
    2935          12 :                               matrix_type=dbcsr_type_antisymmetric)
    2936          12 :             CALL cp_dbcsr_alloc_block_from_nbl(matrix_rxrv(ind)%matrix, sab_orb)
    2937          16 :             CALL dbcsr_set(matrix_rxrv(ind)%matrix, 0._dp)
    2938             :          END DO
    2939             :       END IF
    2940             : 
    2941          28 :       IF (calc_rrv) THEN
    2942          22 :          CALL dbcsr_allocate_matrix_set(matrix_rrv, 6)
    2943         154 :          DO ind = 1, 6
    2944         132 :             CALL dbcsr_init_p(matrix_rrv(ind)%matrix)
    2945             :             CALL dbcsr_create(matrix_rrv(ind)%matrix, template=matrix_s(1)%matrix, &
    2946         132 :                               matrix_type=dbcsr_type_antisymmetric)
    2947         132 :             CALL cp_dbcsr_alloc_block_from_nbl(matrix_rrv(ind)%matrix, sab_orb)
    2948         154 :             CALL dbcsr_set(matrix_rrv(ind)%matrix, 0._dp)
    2949             :          END DO
    2950             :       END IF
    2951             : 
    2952          28 :       IF (calc_rvr) THEN
    2953          28 :          CALL dbcsr_allocate_matrix_set(matrix_rvr, 6)
    2954         196 :          DO ind = 1, 6
    2955         168 :             CALL dbcsr_init_p(matrix_rvr(ind)%matrix)
    2956             :             CALL dbcsr_create(matrix_rvr(ind)%matrix, template=matrix_s(1)%matrix, &
    2957         168 :                               matrix_type=dbcsr_type_symmetric)
    2958         168 :             CALL cp_dbcsr_alloc_block_from_nbl(matrix_rvr(ind)%matrix, sab_orb)
    2959         196 :             CALL dbcsr_set(matrix_rvr(ind)%matrix, 0._dp)
    2960             :          END DO
    2961             :       END IF
    2962          28 :       IF (calc_rrv_vrr) THEN
    2963          28 :          CALL dbcsr_allocate_matrix_set(matrix_rrv_vrr, 6)
    2964         196 :          DO ind = 1, 6
    2965         168 :             CALL dbcsr_init_p(matrix_rrv_vrr(ind)%matrix)
    2966             :             CALL dbcsr_create(matrix_rrv_vrr(ind)%matrix, template=matrix_s(1)%matrix, &
    2967         168 :                               matrix_type=dbcsr_type_symmetric)
    2968         168 :             CALL cp_dbcsr_alloc_block_from_nbl(matrix_rrv_vrr(ind)%matrix, sab_orb)
    2969         196 :             CALL dbcsr_set(matrix_rrv_vrr(ind)%matrix, 0._dp)
    2970             :          END DO
    2971             :       END IF
    2972             : 
    2973             :       ! calculate evaluation of operators in AO basis set
    2974             :       CALL build_com_mom_nl(qs_kind_set, sab_orb, sap_ppnl, eps_ppnl, particle_set, cell, matrix_rv=matrix_rv, &
    2975             :                             matrix_rxrv=matrix_rxrv, matrix_rrv=matrix_rrv, matrix_rvr=matrix_rvr, &
    2976          28 :                             matrix_rrv_vrr=matrix_rrv_vrr, ref_point=ref_point)
    2977             : 
    2978             :       ! Calculate expectation values
    2979             :       ! Real part
    2980          28 :       NULLIFY (tmp_ao)
    2981          28 :       CALL dbcsr_init_p(tmp_ao)
    2982          28 :       CALL dbcsr_create(tmp_ao, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry, name="tmp")
    2983          28 :       CALL cp_dbcsr_alloc_block_from_nbl(tmp_ao, sab_all)
    2984          28 :       CALL dbcsr_set(tmp_ao, 0.0_dp)
    2985             : 
    2986          28 :       IF (calc_rvr .OR. calc_rrv_vrr) THEN
    2987          28 :          NULLIFY (rho_ao)
    2988          28 :          CALL qs_rho_get(rho, rho_ao=rho_ao)
    2989             : 
    2990          28 :          IF (calc_rvr) THEN
    2991          28 :             trace = 0._dp
    2992         196 :             DO ind = 1, SIZE(matrix_rvr)
    2993         168 :                strace = 0._dp
    2994         336 :                DO ispin = 1, dft_control%nspins
    2995         168 :                   CALL dbcsr_set(tmp_ao, 0.0_dp)
    2996             :                   CALL dbcsr_multiply("T", "N", 1.0_dp, rho_ao(ispin)%matrix, matrix_rvr(ind)%matrix, &
    2997         168 :                                       0.0_dp, tmp_ao)
    2998         168 :                   CALL dbcsr_trace(tmp_ao, trace)
    2999         336 :                   strace = strace + trace
    3000             :                END DO
    3001         196 :                nlcom_rvr(ind) = nlcom_rvr(ind) + strace
    3002             :             END DO
    3003             :          END IF
    3004             : 
    3005          28 :          IF (calc_rrv_vrr) THEN
    3006          28 :             trace = 0._dp
    3007         196 :             DO ind = 1, SIZE(matrix_rrv_vrr)
    3008         168 :                strace = 0._dp
    3009         336 :                DO ispin = 1, dft_control%nspins
    3010         168 :                   CALL dbcsr_set(tmp_ao, 0.0_dp)
    3011             :                   CALL dbcsr_multiply("T", "N", 1.0_dp, rho_ao(ispin)%matrix, matrix_rrv_vrr(ind)%matrix, &
    3012         168 :                                       0.0_dp, tmp_ao)
    3013         168 :                   CALL dbcsr_trace(tmp_ao, trace)
    3014         336 :                   strace = strace + trace
    3015             :                END DO
    3016         196 :                nlcom_rrv_vrr(ind) = nlcom_rrv_vrr(ind) + strace
    3017             :             END DO
    3018             :          END IF
    3019             :       END IF
    3020             : 
    3021             :       ! imagninary part of the density matrix
    3022          28 :       NULLIFY (rho_ao)
    3023          28 :       CALL qs_rho_get(rho, rho_ao_im=rho_ao)
    3024             : 
    3025          28 :       IF (calc_rv) THEN
    3026          22 :          trace = 0._dp
    3027          88 :          DO ind = 1, SIZE(matrix_rv)
    3028          66 :             strace = 0._dp
    3029         132 :             DO ispin = 1, dft_control%nspins
    3030          66 :                CALL dbcsr_set(tmp_ao, 0.0_dp)
    3031             :                CALL dbcsr_multiply("T", "N", 1.0_dp, rho_ao(ispin)%matrix, matrix_rv(ind)%matrix, &
    3032          66 :                                    0.0_dp, tmp_ao)
    3033          66 :                CALL dbcsr_trace(tmp_ao, trace)
    3034         132 :                strace = strace + trace
    3035             :             END DO
    3036          88 :             nlcom_rv(ind) = nlcom_rv(ind) + strace
    3037             :          END DO
    3038             :       END IF
    3039             : 
    3040          28 :       IF (calc_rrv) THEN
    3041          22 :          trace = 0._dp
    3042         154 :          DO ind = 1, SIZE(matrix_rrv)
    3043         132 :             strace = 0._dp
    3044         264 :             DO ispin = 1, dft_control%nspins
    3045         132 :                CALL dbcsr_set(tmp_ao, 0.0_dp)
    3046             :                CALL dbcsr_multiply("T", "N", 1.0_dp, rho_ao(ispin)%matrix, matrix_rrv(ind)%matrix, &
    3047         132 :                                    0.0_dp, tmp_ao)
    3048         132 :                CALL dbcsr_trace(tmp_ao, trace)
    3049         264 :                strace = strace + trace
    3050             :             END DO
    3051         154 :             nlcom_rrv(ind) = nlcom_rrv(ind) + strace
    3052             :          END DO
    3053             :       END IF
    3054             : 
    3055          28 :       IF (calc_rxrv) THEN
    3056           4 :          trace = 0._dp
    3057          16 :          DO ind = 1, SIZE(matrix_rxrv)
    3058          12 :             strace = 0._dp
    3059          24 :             DO ispin = 1, dft_control%nspins
    3060          12 :                CALL dbcsr_set(tmp_ao, 0.0_dp)
    3061             :                CALL dbcsr_multiply("T", "N", 1.0_dp, rho_ao(ispin)%matrix, matrix_rxrv(ind)%matrix, &
    3062          12 :                                    0.0_dp, tmp_ao)
    3063          12 :                CALL dbcsr_trace(tmp_ao, trace)
    3064          24 :                strace = strace + trace
    3065             :             END DO
    3066          16 :             nlcom_rxrv(ind) = nlcom_rxrv(ind) + strace
    3067             :          END DO
    3068             :       END IF
    3069          28 :       CALL dbcsr_deallocate_matrix(tmp_ao)
    3070          28 :       IF (calc_rv) CALL dbcsr_deallocate_matrix_set(matrix_rv)
    3071          28 :       IF (calc_rxrv) CALL dbcsr_deallocate_matrix_set(matrix_rxrv)
    3072          28 :       IF (calc_rrv) CALL dbcsr_deallocate_matrix_set(matrix_rrv)
    3073          28 :       IF (calc_rvr) CALL dbcsr_deallocate_matrix_set(matrix_rvr)
    3074          28 :       IF (calc_rrv_vrr) CALL dbcsr_deallocate_matrix_set(matrix_rrv_vrr)
    3075             : 
    3076          28 :       CALL timestop(handle)
    3077          28 :    END SUBROUTINE calculate_commutator_nl_terms
    3078             : 
    3079             : ! *****************************************************************************
    3080             : !> \brief ...
    3081             : !> \param qs_env ...
    3082             : !> \param difdip ...
    3083             : !> \param deltaR ...
    3084             : !> \param order ...
    3085             : !> \param rcc ...
    3086             : !> \note calculate matrix elements <a|r_beta |db/dR_alpha > + <da/dR_alpha | r_beta | b >
    3087             : !> be aware: < a | r_beta| db/dR_alpha > = - < da/dR_alpha | r_beta | b > only valid
    3088             : !>           if alpha .neq.beta
    3089             : !> if alpha=beta: < a | r_beta| db/dR_alpha > = - < da/dR_alpha | r_beta | b > - < a | b >
    3090             : !> modified from qs_efield_mo_derivatives
    3091             : !> SL July 2015
    3092             : ! **************************************************************************************************
    3093         504 :    SUBROUTINE dipole_deriv_ao(qs_env, difdip, deltaR, order, rcc)
    3094             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3095             :       TYPE(dbcsr_p_type), DIMENSION(:, :), &
    3096             :          INTENT(INOUT), POINTER                          :: difdip
    3097             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN), &
    3098             :          POINTER                                         :: deltaR
    3099             :       INTEGER, INTENT(IN)                                :: order
    3100             :       REAL(KIND=dp), DIMENSION(3), OPTIONAL              :: rcc
    3101             : 
    3102             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'dipole_deriv_ao'
    3103             : 
    3104             :       INTEGER :: handle, i, iatom, icol, idir, ikind, inode, irow, iset, j, jatom, jkind, jset, &
    3105             :          last_jatom, lda, ldab, ldb, M_dim, maxsgf, natom, ncoa, ncob, nkind, nseta, nsetb, sgfa, &
    3106             :          sgfb
    3107         504 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, lb_min, npgfa, &
    3108         504 :                                                             npgfb, nsgfa, nsgfb
    3109         504 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
    3110             :       LOGICAL                                            :: found
    3111             :       REAL(dp)                                           :: dab
    3112             :       REAL(dp), DIMENSION(3)                             :: ra, rab, rac, rb, rbc, rc
    3113         504 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: work
    3114         504 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :, :)  :: difmab
    3115         504 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a, set_radius_b
    3116         504 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb
    3117         504 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: mab
    3118         504 :       REAL(KIND=dp), DIMENSION(:, :, :, :), POINTER      :: difmab2
    3119         504 :       TYPE(block_p_type), ALLOCATABLE, DIMENSION(:, :)   :: mint, mint2
    3120             :       TYPE(cell_type), POINTER                           :: cell
    3121         504 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
    3122             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
    3123             :       TYPE(neighbor_list_iterator_p_type), &
    3124         504 :          DIMENSION(:), POINTER                           :: nl_iterator
    3125             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    3126         504 :          POINTER                                         :: sab_all, sab_orb
    3127         504 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    3128         504 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    3129             :       TYPE(qs_kind_type), POINTER                        :: qs_kind
    3130             : 
    3131         504 :       CALL timeset(routineN, handle)
    3132             : 
    3133         504 :       NULLIFY (cell, particle_set, qs_kind_set, sab_orb, sab_all)
    3134             :       CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set, &
    3135         504 :                       qs_kind_set=qs_kind_set, sab_orb=sab_orb, sab_all=sab_all)
    3136             :       CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
    3137         504 :                            maxco=ldab, maxsgf=maxsgf)
    3138             : 
    3139         504 :       nkind = SIZE(qs_kind_set)
    3140         504 :       natom = SIZE(particle_set)
    3141             : 
    3142         504 :       M_dim = ncoset(order) - 1
    3143             : 
    3144         504 :       IF (PRESENT(rcc)) THEN
    3145         504 :          rc = rcc
    3146             :       ELSE
    3147           0 :          rc = 0._dp
    3148             :       END IF
    3149             : 
    3150        2520 :       ALLOCATE (basis_set_list(nkind))
    3151             : 
    3152        2520 :       ALLOCATE (mab(ldab, ldab, M_dim))
    3153        3024 :       ALLOCATE (difmab2(ldab, ldab, M_dim, 3))
    3154        2016 :       ALLOCATE (work(ldab, maxsgf))
    3155        6552 :       ALLOCATE (mint(3, 3))
    3156        6552 :       ALLOCATE (mint2(3, 3))
    3157             : 
    3158      413280 :       mab(1:ldab, 1:ldab, 1:M_dim) = 0.0_dp
    3159     1240344 :       difmab2(1:ldab, 1:ldab, 1:M_dim, 1:3) = 0.0_dp
    3160       34776 :       work(1:ldab, 1:maxsgf) = 0.0_dp
    3161             : 
    3162        2016 :       DO i = 1, 3
    3163        6552 :       DO j = 1, 3
    3164        4536 :          NULLIFY (mint(i, j)%block)
    3165        6048 :          NULLIFY (mint2(i, j)%block)
    3166             :       END DO
    3167             :       END DO
    3168             : 
    3169             :       ! Set the basis_set_list(nkind) to point to the corresponding basis sets
    3170        1512 :       DO ikind = 1, nkind
    3171        1008 :          qs_kind => qs_kind_set(ikind)
    3172        1008 :          CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a)
    3173        1512 :          IF (ASSOCIATED(basis_set_a)) THEN
    3174        1008 :             basis_set_list(ikind)%gto_basis_set => basis_set_a
    3175             :          ELSE
    3176           0 :             NULLIFY (basis_set_list(ikind)%gto_basis_set)
    3177             :          END IF
    3178             :       END DO
    3179             : 
    3180         504 :       CALL neighbor_list_iterator_create(nl_iterator, sab_all)
    3181       20784 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
    3182             :          CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
    3183       20280 :                                 iatom=iatom, jatom=jatom, r=rab)
    3184             : 
    3185       20280 :          basis_set_a => basis_set_list(ikind)%gto_basis_set
    3186       20280 :          basis_set_b => basis_set_list(jkind)%gto_basis_set
    3187       20280 :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
    3188       20280 :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
    3189             : 
    3190             :          ! basis ikind
    3191       20280 :          first_sgfa => basis_set_a%first_sgf
    3192       20280 :          la_max => basis_set_a%lmax
    3193       20280 :          la_min => basis_set_a%lmin
    3194       20280 :          npgfa => basis_set_a%npgf
    3195       20280 :          nseta = basis_set_a%nset
    3196       20280 :          nsgfa => basis_set_a%nsgf_set
    3197       20280 :          rpgfa => basis_set_a%pgf_radius
    3198       20280 :          set_radius_a => basis_set_a%set_radius
    3199       20280 :          sphi_a => basis_set_a%sphi
    3200       20280 :          zeta => basis_set_a%zet
    3201             :          ! basis jkind
    3202       20280 :          first_sgfb => basis_set_b%first_sgf
    3203       20280 :          lb_max => basis_set_b%lmax
    3204       20280 :          lb_min => basis_set_b%lmin
    3205       20280 :          npgfb => basis_set_b%npgf
    3206       20280 :          nsetb = basis_set_b%nset
    3207       20280 :          nsgfb => basis_set_b%nsgf_set
    3208       20280 :          rpgfb => basis_set_b%pgf_radius
    3209       20280 :          set_radius_b => basis_set_b%set_radius
    3210       20280 :          sphi_b => basis_set_b%sphi
    3211       20280 :          zetb => basis_set_b%zet
    3212             : 
    3213       20280 :          IF (inode == 1) last_jatom = 0
    3214             : 
    3215             :          ! this guarentees minimum image convention
    3216             :          ! anything else would not make sense
    3217       20280 :          IF (jatom == last_jatom) THEN
    3218             :             CYCLE
    3219             :          END IF
    3220             : 
    3221        2268 :          last_jatom = jatom
    3222             : 
    3223        2268 :          irow = iatom
    3224        2268 :          icol = jatom
    3225             : 
    3226        9072 :          DO i = 1, 3
    3227       29484 :          DO j = 1, 3
    3228       20412 :             NULLIFY (mint(i, j)%block)
    3229             :             CALL dbcsr_get_block_p(matrix=difdip(i, j)%matrix, &
    3230             :                                    row=irow, col=icol, BLOCK=mint(i, j)%block, &
    3231       20412 :                                    found=found)
    3232       27216 :             CPASSERT(found)
    3233             :          END DO
    3234             :          END DO
    3235             : 
    3236        9072 :          ra(:) = particle_set(iatom)%r(:)
    3237        9072 :          rb(:) = particle_set(jatom)%r(:)
    3238        2268 :          rab(:) = pbc(rb, ra, cell)
    3239        9072 :          rac(:) = pbc(ra - rc, cell)
    3240        9072 :          rbc(:) = pbc(rb - rc, cell)
    3241        2268 :          dab = SQRT(rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3))
    3242             : 
    3243        5040 :          DO iset = 1, nseta
    3244        2268 :             ncoa = npgfa(iset)*ncoset(la_max(iset))
    3245        2268 :             sgfa = first_sgfa(1, iset)
    3246       24816 :             DO jset = 1, nsetb
    3247        2268 :                IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
    3248        2268 :                ncob = npgfb(jset)*ncoset(lb_max(jset))
    3249        2268 :                sgfb = first_sgfb(1, jset)
    3250        2268 :                ldab = MAX(ncoa, ncob)
    3251        2268 :                lda = ncoset(la_max(iset))*npgfa(iset)
    3252        2268 :                ldb = ncoset(lb_max(jset))*npgfb(jset)
    3253       13608 :                ALLOCATE (difmab(lda, ldb, M_dim, 3))
    3254             : 
    3255             :                ! Calculate integral (da|r|b)
    3256             :                CALL diff_momop2(la_max(iset), npgfa(iset), zeta(:, iset), &
    3257             :                                 rpgfa(:, iset), la_min(iset), lb_max(jset), npgfb(jset), &
    3258             :                                 zetb(:, jset), rpgfb(:, jset), lb_min(jset), order, rac, rbc, &
    3259        2268 :                                 difmab, deltaR=deltaR, iatom=iatom, jatom=jatom)
    3260             : 
    3261             : !                  *** Contraction step ***
    3262             : 
    3263        9072 :                DO idir = 1, 3 ! derivative of AO function
    3264       29484 :                DO j = 1, 3     ! position operator r_j
    3265             :                   CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
    3266             :                              1.0_dp, difmab(1, 1, j, idir), SIZE(difmab, 1), &
    3267             :                              sphi_b(1, sgfb), SIZE(sphi_b, 1), &
    3268       20412 :                              0.0_dp, work(1, 1), SIZE(work, 1))
    3269             : 
    3270             :                   CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
    3271             :                              1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
    3272             :                              work(1, 1), SIZE(work, 1), &
    3273             :                              1.0_dp, mint(j, idir)%block(sgfa, sgfb), &
    3274       27216 :                              SIZE(mint(j, idir)%block, 1))
    3275             :                END DO !j
    3276             :                END DO !idir
    3277        4536 :                DEALLOCATE (difmab)
    3278             :             END DO !jset
    3279             :          END DO !iset
    3280             :       END DO!iterator
    3281             : 
    3282         504 :       CALL neighbor_list_iterator_release(nl_iterator)
    3283             : 
    3284        2016 :       DO i = 1, 3
    3285        6552 :       DO j = 1, 3
    3286        6048 :          NULLIFY (mint(i, j)%block)
    3287             :       END DO
    3288             :       END DO
    3289             : 
    3290         504 :       DEALLOCATE (mab, difmab2, basis_set_list, work, mint, mint2)
    3291             : 
    3292         504 :       CALL timestop(handle)
    3293        1512 :    END SUBROUTINE dipole_deriv_ao
    3294             : 
    3295             : END MODULE qs_moments

Generated by: LCOV version 1.15