LCOV - code coverage report
Current view: top level - src - qs_operators_ao.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:4dc10b3) Lines: 675 682 99.0 %
Date: 2024-11-21 06:45:46 Functions: 7 7 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \par History
      10             : !>      created 07.2005
      11             : !> \author MI (07.2005)
      12             : ! **************************************************************************************************
      13             : MODULE qs_operators_ao
      14             :    USE ai_moments,                      ONLY: diff_momop,&
      15             :                                               diffop,&
      16             :                                               moment
      17             :    USE ai_os_rr,                        ONLY: os_rr_ovlp
      18             :    USE basis_set_types,                 ONLY: gto_basis_set_p_type,&
      19             :                                               gto_basis_set_type
      20             :    USE block_p_types,                   ONLY: block_p_type
      21             :    USE cell_types,                      ONLY: cell_type,&
      22             :                                               pbc
      23             :    USE cp_dbcsr_api,                    ONLY: dbcsr_get_block_p,&
      24             :                                               dbcsr_get_matrix_type,&
      25             :                                               dbcsr_has_symmetry,&
      26             :                                               dbcsr_p_type,&
      27             :                                               dbcsr_type_antisymmetric,&
      28             :                                               dbcsr_type_no_symmetry
      29             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      30             :                                               cp_logger_type
      31             :    USE kinds,                           ONLY: default_string_length,&
      32             :                                               dp
      33             :    USE mathconstants,                   ONLY: pi
      34             :    USE message_passing,                 ONLY: mp_para_env_type
      35             :    USE orbital_pointers,                ONLY: coset,&
      36             :                                               init_orbital_pointers,&
      37             :                                               ncoset
      38             :    USE particle_types,                  ONLY: particle_type
      39             :    USE qs_environment_types,            ONLY: get_qs_env,&
      40             :                                               qs_environment_type
      41             :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      42             :                                               get_qs_kind_set,&
      43             :                                               qs_kind_type
      44             :    USE qs_neighbor_list_types,          ONLY: get_iterator_info,&
      45             :                                               neighbor_list_iterate,&
      46             :                                               neighbor_list_iterator_create,&
      47             :                                               neighbor_list_iterator_p_type,&
      48             :                                               neighbor_list_iterator_release,&
      49             :                                               neighbor_list_set_p_type
      50             : #include "./base/base_uses.f90"
      51             : 
      52             :    IMPLICIT NONE
      53             :    PRIVATE
      54             : 
      55             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_operators_ao'
      56             : 
      57             : ! *** Public subroutines ***
      58             : 
      59             :    PUBLIC :: p_xyz_ao, rRc_xyz_ao, rRc_xyz_der_ao
      60             :    PUBLIC :: build_lin_mom_matrix, build_ang_mom_matrix
      61             : 
      62             : CONTAINS
      63             : 
      64             : ! **************************************************************************************************
      65             : !> \brief   Calculation of the linear momentum matrix <mu|∂|nu> over
      66             : !>          Cartesian Gaussian functions.
      67             : !> \param qs_env ...
      68             : !> \param matrix ...
      69             : !> \date    27.02.2009
      70             : !> \author  VW
      71             : !> \version 1.0
      72             : ! **************************************************************************************************
      73         930 :    SUBROUTINE build_lin_mom_matrix(qs_env, matrix)
      74             : 
      75             :       TYPE(qs_environment_type), POINTER                 :: qs_env
      76             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix
      77             : 
      78             :       CHARACTER(len=*), PARAMETER :: routineN = 'build_lin_mom_matrix'
      79             : 
      80             :       INTEGER :: handle, i, iatom, icol, ikind, inode, irow, iset, jatom, jkind, jset, last_jatom, &
      81             :          ldai, maxco, maxlgto, maxsgf, natom, ncoa, ncob, neighbor_list_id, nkind, nseta, nsetb, &
      82             :          sgfa, sgfb
      83         930 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, lb_min, npgfa, &
      84         930 :                                                             npgfb, nsgfa, nsgfb
      85         930 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
      86             :       LOGICAL                                            :: do_symmetric, found, new_atom_b
      87             :       REAL(KIND=dp)                                      :: dab, rab2
      88         930 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: work
      89         930 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: intab, rr_work
      90             :       REAL(KIND=dp), DIMENSION(3)                        :: rab
      91         930 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a, set_radius_b
      92         930 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb
      93         930 :       TYPE(block_p_type), ALLOCATABLE, DIMENSION(:)      :: integral
      94             :       TYPE(cell_type), POINTER                           :: cell
      95             :       TYPE(cp_logger_type), POINTER                      :: logger
      96         930 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
      97             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
      98             :       TYPE(mp_para_env_type), POINTER                    :: para_env
      99             :       TYPE(neighbor_list_iterator_p_type), &
     100         930 :          DIMENSION(:), POINTER                           :: nl_iterator
     101             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     102         930 :          POINTER                                         :: sab_nl
     103         930 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     104         930 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     105             :       TYPE(qs_kind_type), POINTER                        :: qs_kind
     106             : 
     107         930 :       CALL timeset(routineN, handle)
     108             : 
     109         930 :       NULLIFY (cell, sab_nl, qs_kind_set, particle_set, para_env)
     110         930 :       NULLIFY (logger)
     111             : 
     112         930 :       logger => cp_get_default_logger()
     113             : 
     114             :       CALL get_qs_env(qs_env=qs_env, &
     115             :                       qs_kind_set=qs_kind_set, &
     116             :                       particle_set=particle_set, &
     117             :                       neighbor_list_id=neighbor_list_id, &
     118             :                       para_env=para_env, &
     119         930 :                       cell=cell)
     120             : 
     121         930 :       nkind = SIZE(qs_kind_set)
     122         930 :       natom = SIZE(particle_set)
     123             : 
     124             :       ! Take into account the symmetry of the input matrix
     125         930 :       do_symmetric = dbcsr_has_symmetry(matrix(1)%matrix)
     126         930 :       IF (do_symmetric) THEN
     127         928 :          CALL get_qs_env(qs_env=qs_env, sab_orb=sab_nl)
     128             :       ELSE
     129           2 :          CALL get_qs_env(qs_env=qs_env, sab_all=sab_nl)
     130             :       END IF
     131             : !   *** Allocate work storage ***
     132             : 
     133             :       CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
     134             :                            maxco=maxco, &
     135             :                            maxlgto=maxlgto, &
     136         930 :                            maxsgf=maxsgf)
     137             : 
     138         930 :       ldai = ncoset(maxlgto + 1)
     139         930 :       CALL init_orbital_pointers(ldai)
     140             : 
     141       13950 :       ALLOCATE (rr_work(ldai, ldai, 3), intab(maxco, maxco, 3), work(maxco, maxsgf), integral(3))
     142      789900 :       rr_work(:, :, :) = 0.0_dp
     143      649476 :       intab(:, :, :) = 0.0_dp
     144      149076 :       work(:, :) = 0.0_dp
     145             : 
     146        4402 :       ALLOCATE (basis_set_list(nkind))
     147        2542 :       DO ikind = 1, nkind
     148        1612 :          qs_kind => qs_kind_set(ikind)
     149        1612 :          CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a)
     150        2542 :          IF (ASSOCIATED(basis_set_a)) THEN
     151        1612 :             basis_set_list(ikind)%gto_basis_set => basis_set_a
     152             :          ELSE
     153           0 :             NULLIFY (basis_set_list(ikind)%gto_basis_set)
     154             :          END IF
     155             :       END DO
     156         930 :       CALL neighbor_list_iterator_create(nl_iterator, sab_nl)
     157       53301 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     158             :          CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
     159       52371 :                                 iatom=iatom, jatom=jatom, r=rab)
     160       52371 :          basis_set_a => basis_set_list(ikind)%gto_basis_set
     161       52371 :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
     162       52371 :          basis_set_b => basis_set_list(jkind)%gto_basis_set
     163       52371 :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
     164             :          ! basis ikind
     165       52371 :          first_sgfa => basis_set_a%first_sgf
     166       52371 :          la_max => basis_set_a%lmax
     167       52371 :          la_min => basis_set_a%lmin
     168       52371 :          npgfa => basis_set_a%npgf
     169       52371 :          nseta = basis_set_a%nset
     170       52371 :          nsgfa => basis_set_a%nsgf_set
     171       52371 :          rpgfa => basis_set_a%pgf_radius
     172       52371 :          set_radius_a => basis_set_a%set_radius
     173       52371 :          sphi_a => basis_set_a%sphi
     174       52371 :          zeta => basis_set_a%zet
     175             :          ! basis jkind
     176       52371 :          first_sgfb => basis_set_b%first_sgf
     177       52371 :          lb_max => basis_set_b%lmax
     178       52371 :          lb_min => basis_set_b%lmin
     179       52371 :          npgfb => basis_set_b%npgf
     180       52371 :          nsetb = basis_set_b%nset
     181       52371 :          nsgfb => basis_set_b%nsgf_set
     182       52371 :          rpgfb => basis_set_b%pgf_radius
     183       52371 :          set_radius_b => basis_set_b%set_radius
     184       52371 :          sphi_b => basis_set_b%sphi
     185       52371 :          zetb => basis_set_b%zet
     186             : 
     187       52371 :          IF (inode == 1) last_jatom = 0
     188       52371 :          IF (jatom /= last_jatom) THEN
     189             :             new_atom_b = .TRUE.
     190             :             last_jatom = jatom
     191             :          ELSE
     192             :             new_atom_b = .FALSE.
     193             :          END IF
     194             : 
     195             :          IF (new_atom_b) THEN
     196        3208 :             IF (do_symmetric) THEN
     197        3199 :                IF (iatom <= jatom) THEN
     198        2014 :                   irow = iatom
     199        2014 :                   icol = jatom
     200             :                ELSE
     201        1185 :                   irow = jatom
     202        1185 :                   icol = iatom
     203             :                END IF
     204             :             ELSE
     205           9 :                irow = iatom
     206           9 :                icol = jatom
     207             :             END IF
     208             : 
     209       12832 :             DO i = 1, 3
     210        9624 :                NULLIFY (integral(i)%block)
     211             :                CALL dbcsr_get_block_p(matrix=matrix(i)%matrix, &
     212        9624 :                                       row=irow, col=icol, BLOCK=integral(i)%block, found=found)
     213       12832 :                CPASSERT(ASSOCIATED(INTEGRAL(i)%block))
     214             :             END DO
     215             :          END IF
     216             : 
     217       52371 :          rab2 = rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3)
     218       52371 :          dab = SQRT(rab2)
     219             : 
     220      170837 :          DO iset = 1, nseta
     221             : 
     222      117536 :             ncoa = npgfa(iset)*ncoset(la_max(iset))
     223      117536 :             sgfa = first_sgfa(1, iset)
     224             : 
     225      444053 :             DO jset = 1, nsetb
     226             : 
     227      274146 :                IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
     228             : 
     229      109994 :                ncob = npgfb(jset)*ncoset(lb_max(jset))
     230      109994 :                sgfb = first_sgfb(1, jset)
     231             : 
     232             :                ! *** Calculate the primitive fermi contact integrals ***
     233             : 
     234             :                CALL lin_mom(la_max(iset), la_min(iset), npgfa(iset), &
     235             :                             rpgfa(:, iset), zeta(:, iset), &
     236             :                             lb_max(jset), lb_min(jset), npgfb(jset), &
     237             :                             rpgfb(:, jset), zetb(:, jset), &
     238      109994 :                             rab, intab, SIZE(rr_work, 1), rr_work)
     239             : 
     240             :                ! *** Contraction step ***
     241             : 
     242      557512 :                DO i = 1, 3
     243             : 
     244             :                   CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
     245             :                              1.0_dp, intab(1, 1, i), SIZE(intab, 1), &
     246             :                              sphi_b(1, sgfb), SIZE(sphi_b, 1), &
     247      329982 :                              0.0_dp, work(1, 1), SIZE(work, 1))
     248             : 
     249      604128 :                   IF (do_symmetric) THEN
     250      329955 :                      IF (iatom <= jatom) THEN
     251             : 
     252             :                         CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
     253             :                                    1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
     254             :                                    work(1, 1), SIZE(work, 1), &
     255             :                                    1.0_dp, integral(i)%block(sgfa, sgfb), &
     256      207738 :                                    SIZE(integral(i)%block, 1))
     257             : 
     258             :                      ELSE
     259             : 
     260             :                         CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
     261             :                                    -1.0_dp, work(1, 1), SIZE(work, 1), &
     262             :                                    sphi_a(1, sgfa), SIZE(sphi_a, 1), &
     263             :                                    1.0_dp, integral(i)%block(sgfb, sgfa), &
     264      122217 :                                    SIZE(integral(i)%block, 1))
     265             : 
     266             :                      END IF
     267             :                   ELSE
     268             :                      CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
     269             :                                 1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
     270             :                                 work(1, 1), SIZE(work, 1), &
     271             :                                 1.0_dp, integral(i)%block(sgfa, sgfb), &
     272          27 :                                 SIZE(integral(i)%block, 1))
     273             :                   END IF
     274             : 
     275             :                END DO
     276             : 
     277             :             END DO
     278             : 
     279             :          END DO
     280             : 
     281             :       END DO
     282         930 :       CALL neighbor_list_iterator_release(nl_iterator)
     283             : 
     284             :       ! *** Release work storage ***
     285             : 
     286         930 :       DEALLOCATE (intab, work, integral, basis_set_list)
     287             : 
     288             : !   *** Print the spin orbit matrix, if requested ***
     289             : 
     290             :       !IF (BTEST(cp_print_key_should_output(logger%iter_info,&
     291             :       !     qs_env%input,"DFT%PRINT%AO_MATRICES/LINEAR_MOMENTUM"),cp_p_file)) THEN
     292             :       !   iw = cp_print_key_unit_nr(logger,qs_env%input,"DFT%PRINT%AO_MATRICES/LINEA_MOMENTUM",&
     293             :       !        extension=".Log")
     294             :       !   CALL cp_dbcsr_write_sparse_matrix(matrix(1)%matrix,4,6,qs_env,para_env,output_unit=iw)
     295             :       !   CALL cp_dbcsr_write_sparse_matrix(matrix(2)%matrix,4,6,qs_env,para_env,output_unit=iw)
     296             :       !   CALL cp_dbcsr_write_sparse_matrix(matrix(3)%matrix,4,6,qs_env,para_env,output_unit=iw)
     297             :       !   CALL cp_print_key_finished_output(iw,logger,qs_env%input,&
     298             :       !        "DFT%PRINT%AO_MATRICES/LINEAR_MOMENTUM")
     299             :       !END IF
     300             : 
     301         930 :       CALL timestop(handle)
     302             : 
     303        2790 :    END SUBROUTINE build_lin_mom_matrix
     304             : 
     305             : ! **************************************************************************************************
     306             : !> \brief   Calculation of the primitive paramagnetic spin orbit integrals over
     307             : !>          Cartesian Gaussian-type functions.
     308             : !> \param la_max ...
     309             : !> \param la_min ...
     310             : !> \param npgfa ...
     311             : !> \param rpgfa ...
     312             : !> \param zeta ...
     313             : !> \param lb_max ...
     314             : !> \param lb_min ...
     315             : !> \param npgfb ...
     316             : !> \param rpgfb ...
     317             : !> \param zetb ...
     318             : !> \param rab ...
     319             : !> \param intab ...
     320             : !> \param ldrr ...
     321             : !> \param rr ...
     322             : !> \date    02.03.2009
     323             : !> \author  VW
     324             : !> \version 1.0
     325             : ! **************************************************************************************************
     326      219988 :    SUBROUTINE lin_mom(la_max, la_min, npgfa, rpgfa, zeta, lb_max, lb_min, npgfb, rpgfb, zetb, &
     327      109994 :                       rab, intab, ldrr, rr)
     328             :       INTEGER, INTENT(IN)                                :: la_max, la_min, npgfa
     329             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rpgfa, zeta
     330             :       INTEGER, INTENT(IN)                                :: lb_max, lb_min, npgfb
     331             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rpgfb, zetb
     332             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rab
     333             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT)   :: intab
     334             :       INTEGER, INTENT(IN)                                :: ldrr
     335             :       REAL(dp), DIMENSION(0:ldrr-1, 0:ldrr-1, 3), &
     336             :          INTENT(INOUT)                                   :: rr
     337             : 
     338             :       INTEGER                                            :: ax, ay, az, bx, by, bz, coa, cob, i, &
     339             :                                                             ipgf, j, jpgf, la, lb, ma, mb, na, nb
     340             :       REAL(dp)                                           :: dab, dumx, dumy, dumz, f0, rab2, xhi, zet
     341             :       REAL(dp), DIMENSION(3)                             :: rap, rbp
     342             : 
     343             : ! *** Calculate the distance of the centers a and c ***
     344             : 
     345      109994 :       rab2 = rab(1)**2 + rab(2)**2 + rab(3)**2
     346      109994 :       dab = SQRT(rab2)
     347             : 
     348             :       ! *** Loop over all pairs of primitive Gaussian-type functions ***
     349             : 
     350      109994 :       na = 0
     351             : 
     352      354886 :       DO ipgf = 1, npgfa
     353             : 
     354      244892 :          nb = 0
     355             : 
     356      873734 :          DO jpgf = 1, npgfb
     357             : 
     358             :             ! *** Screening ***
     359             : 
     360      628842 :             IF (rpgfa(ipgf) + rpgfb(jpgf) < dab) THEN
     361     1508461 :                DO j = nb + 1, nb + ncoset(lb_max)
     362     5166579 :                   DO i = na + 1, na + ncoset(la_max)
     363     3658118 :                      intab(i, j, 1) = 0.0_dp
     364     3658118 :                      intab(i, j, 2) = 0.0_dp
     365     4763494 :                      intab(i, j, 3) = 0.0_dp
     366             :                   END DO
     367             :                END DO
     368      403085 :                nb = nb + ncoset(lb_max)
     369      403085 :                CYCLE
     370             :             END IF
     371             : 
     372             :             ! *** Calculate some prefactors ***
     373      225757 :             zet = zeta(ipgf) + zetb(jpgf)
     374      225757 :             xhi = zeta(ipgf)*zetb(jpgf)/zet
     375      903028 :             rap = zetb(jpgf)*rab/zet
     376      903028 :             rbp = -zeta(ipgf)*rab/zet
     377             : 
     378      225757 :             f0 = (pi/zet)**(1.5_dp)*EXP(-xhi*rab2)
     379             : 
     380             :             ! *** Calculate the recurrence relation ***
     381             : 
     382      225757 :             CALL os_rr_ovlp(rap, la_max + 1, rbp, lb_max, zet, ldrr, rr)
     383             : 
     384             :             ! *** Calculate the primitive linear momentum integrals ***
     385      538526 :             DO lb = lb_min, lb_max
     386      972225 :             DO bx = 0, lb
     387     1313015 :             DO by = 0, lb - bx
     388      566547 :                bz = lb - bx - by
     389      566547 :                cob = coset(bx, by, bz)
     390      566547 :                mb = nb + cob
     391     1862245 :                DO la = la_min, la_max
     392     2688722 :                DO ax = 0, la
     393     3824563 :                DO ay = 0, la - ax
     394     1702388 :                   az = la - ax - ay
     395     1702388 :                   coa = coset(ax, ay, az)
     396     1702388 :                   ma = na + coa
     397             :                   !
     398             :                   !
     399             :                   ! (a|p_x|b) = 2*a*(a+1x|b) - N_x(a)*(a-1_x|b)
     400     1702388 :                   dumx = 2.0_dp*zeta(ipgf)*rr(ax + 1, bx, 1)
     401     1702388 :                   IF (ax .GT. 0) dumx = dumx - REAL(ax, dp)*rr(ax - 1, bx, 1)
     402     1702388 :                   intab(ma, mb, 1) = f0*dumx*rr(ay, by, 2)*rr(az, bz, 3)
     403             :                   !
     404             :                   ! (a|p_y|b)
     405     1702388 :                   dumy = 2.0_dp*zeta(ipgf)*rr(ay + 1, by, 2)
     406     1702388 :                   IF (ay .GT. 0) dumy = dumy - REAL(ay, dp)*rr(ay - 1, by, 2)
     407     1702388 :                   intab(ma, mb, 2) = f0*rr(ax, bx, 1)*dumy*rr(az, bz, 3)
     408             :                   !
     409             :                   ! (a|p_z|b)
     410     1702388 :                   dumz = 2.0_dp*zeta(ipgf)*rr(az + 1, bz, 3)
     411     1702388 :                   IF (az .GT. 0) dumz = dumz - REAL(az, dp)*rr(az - 1, bz, 3)
     412     2962564 :                   intab(ma, mb, 3) = f0*rr(ax, bx, 1)*rr(ay, by, 2)*dumz
     413             :                   !
     414             :                END DO
     415             :                END DO
     416             :                END DO !la
     417             : 
     418             :             END DO
     419             :             END DO
     420             :             END DO !lb
     421             : 
     422      470649 :             nb = nb + ncoset(lb_max)
     423             : 
     424             :          END DO
     425             : 
     426      354886 :          na = na + ncoset(la_max)
     427             : 
     428             :       END DO
     429             : 
     430      109994 :    END SUBROUTINE lin_mom
     431             : 
     432             : ! **************************************************************************************************
     433             : !> \brief   Calculation of the angular momentum matrix over
     434             : !>          Cartesian Gaussian functions.
     435             : !> \param qs_env ...
     436             : !> \param matrix ...
     437             : !> \param rc ...
     438             : !> \date    27.02.2009
     439             : !> \author  VW
     440             : !> \version 1.0
     441             : ! **************************************************************************************************
     442             : 
     443        1250 :    SUBROUTINE build_ang_mom_matrix(qs_env, matrix, rc)
     444             : 
     445             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     446             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix
     447             :       REAL(dp), DIMENSION(:), INTENT(IN)                 :: rc
     448             : 
     449             :       CHARACTER(len=*), PARAMETER :: routineN = 'build_ang_mom_matrix'
     450             : 
     451             :       INTEGER :: handle, i, iatom, icol, ikind, inode, irow, iset, jatom, jkind, jset, last_jatom, &
     452             :          ldai, maxco, maxlgto, maxsgf, natom, ncoa, ncob, neighbor_list_id, nkind, nseta, nsetb, &
     453             :          sgfa, sgfb
     454        1250 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, lb_min, npgfa, &
     455        1250 :                                                             npgfb, nsgfa, nsgfb
     456        1250 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
     457             :       LOGICAL                                            :: found, new_atom_b
     458             :       REAL(KIND=dp)                                      :: dab, rab2
     459        1250 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: work
     460        1250 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: intab, rr_work
     461             :       REAL(KIND=dp), DIMENSION(3)                        :: ra, rab, rac, rbc
     462        1250 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a, set_radius_b
     463        1250 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb
     464        1250 :       TYPE(block_p_type), ALLOCATABLE, DIMENSION(:)      :: integral
     465             :       TYPE(cell_type), POINTER                           :: cell
     466             :       TYPE(cp_logger_type), POINTER                      :: logger
     467        1250 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
     468             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
     469             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     470             :       TYPE(neighbor_list_iterator_p_type), &
     471        1250 :          DIMENSION(:), POINTER                           :: nl_iterator
     472             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     473        1250 :          POINTER                                         :: sab_all
     474        1250 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     475        1250 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     476             :       TYPE(qs_kind_type), POINTER                        :: qs_kind
     477             : 
     478        1250 :       CALL timeset(routineN, handle)
     479             : 
     480        1250 :       NULLIFY (cell, sab_all, qs_kind_set, particle_set, para_env)
     481        1250 :       NULLIFY (logger)
     482             : 
     483        1250 :       logger => cp_get_default_logger()
     484             : 
     485             :       CALL get_qs_env(qs_env=qs_env, &
     486             :                       qs_kind_set=qs_kind_set, &
     487             :                       particle_set=particle_set, &
     488             :                       neighbor_list_id=neighbor_list_id, &
     489             :                       para_env=para_env, &
     490             :                       sab_all=sab_all, &
     491        1250 :                       cell=cell)
     492             : 
     493        1250 :       nkind = SIZE(qs_kind_set)
     494        1250 :       natom = SIZE(particle_set)
     495             : 
     496             : !   *** Allocate work storage ***
     497             : 
     498             :       CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
     499             :                            maxco=maxco, &
     500             :                            maxlgto=maxlgto, &
     501        1250 :                            maxsgf=maxsgf)
     502             : 
     503        1250 :       ldai = ncoset(maxlgto + 1)
     504        1250 :       CALL init_orbital_pointers(ldai)
     505             : 
     506       18750 :       ALLOCATE (rr_work(ldai, ldai, 3), intab(maxco, maxco, 3), work(maxco, maxsgf), integral(3))
     507     1130660 :       rr_work(:, :, :) = 0.0_dp
     508      673460 :       intab(:, :, :) = 0.0_dp
     509      201912 :       work(:, :) = 0.0_dp
     510             : 
     511        5796 :       ALLOCATE (basis_set_list(nkind))
     512        3296 :       DO ikind = 1, nkind
     513        2046 :          qs_kind => qs_kind_set(ikind)
     514        2046 :          CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a)
     515        3296 :          IF (ASSOCIATED(basis_set_a)) THEN
     516        2046 :             basis_set_list(ikind)%gto_basis_set => basis_set_a
     517             :          ELSE
     518           0 :             NULLIFY (basis_set_list(ikind)%gto_basis_set)
     519             :          END IF
     520             :       END DO
     521        1250 :       CALL neighbor_list_iterator_create(nl_iterator, sab_all)
     522       94981 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     523             :          CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
     524       93731 :                                 iatom=iatom, jatom=jatom, r=rab)
     525       93731 :          basis_set_a => basis_set_list(ikind)%gto_basis_set
     526       93731 :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
     527       93731 :          basis_set_b => basis_set_list(jkind)%gto_basis_set
     528       93731 :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
     529       93731 :          ra = pbc(particle_set(iatom)%r, cell)
     530             :          ! basis ikind
     531       93731 :          first_sgfa => basis_set_a%first_sgf
     532       93731 :          la_max => basis_set_a%lmax
     533       93731 :          la_min => basis_set_a%lmin
     534       93731 :          npgfa => basis_set_a%npgf
     535       93731 :          nseta = basis_set_a%nset
     536       93731 :          nsgfa => basis_set_a%nsgf_set
     537       93731 :          rpgfa => basis_set_a%pgf_radius
     538       93731 :          set_radius_a => basis_set_a%set_radius
     539       93731 :          sphi_a => basis_set_a%sphi
     540       93731 :          zeta => basis_set_a%zet
     541             :          ! basis jkind
     542       93731 :          first_sgfb => basis_set_b%first_sgf
     543       93731 :          lb_max => basis_set_b%lmax
     544       93731 :          lb_min => basis_set_b%lmin
     545       93731 :          npgfb => basis_set_b%npgf
     546       93731 :          nsetb = basis_set_b%nset
     547       93731 :          nsgfb => basis_set_b%nsgf_set
     548       93731 :          rpgfb => basis_set_b%pgf_radius
     549       93731 :          set_radius_b => basis_set_b%set_radius
     550       93731 :          sphi_b => basis_set_b%sphi
     551       93731 :          zetb => basis_set_b%zet
     552             : 
     553       93731 :          IF (inode == 1) last_jatom = 0
     554             : 
     555       93731 :          IF (jatom /= last_jatom) THEN
     556             :             new_atom_b = .TRUE.
     557             :             last_jatom = jatom
     558             :          ELSE
     559             :             new_atom_b = .FALSE.
     560             :          END IF
     561             : 
     562             :          IF (new_atom_b) THEN
     563             :             !IF (iatom <= jatom) THEN
     564        5987 :             irow = iatom
     565        5987 :             icol = jatom
     566             :             !ELSE
     567             :             !   irow = jatom
     568             :             !   icol = iatom
     569             :             !END IF
     570             : 
     571       23948 :             DO i = 1, 3
     572       17961 :                NULLIFY (INTEGRAL(i)%block)
     573             :                CALL dbcsr_get_block_p(matrix=matrix(i)%matrix, &
     574       17961 :                                       row=irow, col=icol, BLOCK=INTEGRAL(i)%block, found=found)
     575       23948 :                CPASSERT(ASSOCIATED(INTEGRAL(i)%block))
     576             :             END DO
     577             :          END IF
     578             : 
     579       93731 :          rab2 = rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3)
     580       93731 :          dab = SQRT(rab2)
     581             : 
     582      312058 :          DO iset = 1, nseta
     583             : 
     584      217077 :             ncoa = npgfa(iset)*ncoset(la_max(iset))
     585      217077 :             sgfa = first_sgfa(1, iset)
     586             : 
     587      837307 :             DO jset = 1, nsetb
     588             : 
     589      526499 :                IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
     590             : 
     591             :                !IF(PRESENT(wancen)) THEN
     592             :                !   rc = wancen
     593      201893 :                rac = pbc(rc, ra, cell)
     594      807572 :                rbc = rac + rab
     595             :                !ELSE
     596             :                !   rc(1:3) = rb(1:3)
     597             :                !   rac(1:3) = -rab(1:3)
     598             :                !   rbc(1:3) = 0.0_dp
     599             :                !ENDIF
     600             : 
     601      201893 :                ncob = npgfb(jset)*ncoset(lb_max(jset))
     602      201893 :                sgfb = first_sgfb(1, jset)
     603             : 
     604             :                ! *** Calculate the primitive angular momentum integrals ***
     605             : 
     606             :                CALL ang_mom(la_max(iset), la_min(iset), npgfa(iset), &
     607             :                             rpgfa(:, iset), zeta(:, iset), &
     608             :                             lb_max(jset), lb_min(jset), npgfb(jset), &
     609             :                             rpgfb(:, jset), zetb(:, jset), &
     610      201893 :                             rab, rac, intab, SIZE(rr_work, 1), rr_work)
     611             : 
     612             :                ! *** Contraction step ***
     613             : 
     614     1024649 :                DO i = 1, 3
     615             : 
     616             :                   CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
     617             :                              1.0_dp, intab(1, 1, i), SIZE(intab, 1), &
     618             :                              sphi_b(1, sgfb), SIZE(sphi_b, 1), &
     619      605679 :                              0.0_dp, work(1, 1), SIZE(work, 1))
     620             : 
     621             :                   !IF (iatom <= jatom) THEN
     622             : 
     623             :                   CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
     624             :                              1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
     625             :                              work(1, 1), SIZE(work, 1), &
     626             :                              1.0_dp, integral(i)%block(sgfa, sgfb), &
     627     1132178 :                              SIZE(integral(i)%block, 1))
     628             : 
     629             :                   !ELSE
     630             :                   !
     631             :                   !   CALL dgemm("T","N",nsgfb(jset),nsgfa(iset),ncoa,&
     632             :                   !              -1.0_dp,work(1,1),SIZE(work,1),&
     633             :                   !              sphi_a(1,sgfa),SIZE(sphi_a,1),&
     634             :                   !              1.0_dp,integral(i)%block(sgfb,sgfa),&
     635             :                   !              SIZE(integral(i)%block,1))
     636             :                   !
     637             :                   !ENDIF
     638             : 
     639             :                END DO
     640             : 
     641             :             END DO
     642             : 
     643             :          END DO
     644             : 
     645             :       END DO
     646        1250 :       CALL neighbor_list_iterator_release(nl_iterator)
     647             : 
     648             :       ! *** Release work storage ***
     649             : 
     650        1250 :       DEALLOCATE (intab, work, integral, basis_set_list)
     651             : 
     652             : !   *** Print the spin orbit matrix, if requested ***
     653             : 
     654             :       !IF (BTEST(cp_print_key_should_output(logger%iter_info,&
     655             :       !     qs_env%input,"DFT%PRINT%AO_MATRICES/ANGULAR_MOMENTUM"),cp_p_file)) THEN
     656             :       !   iw = cp_print_key_unit_nr(logger,qs_env%input,"DFT%PRINT%AO_MATRICES/ANGULAR_MOMENTUM",&
     657             :       !        extension=".Log")
     658             :       !   CALL cp_dbcsr_write_sparse_matrix(matrix(1)%matrix,4,6,qs_env,para_env,output_unit=iw)
     659             :       !   CALL cp_dbcsr_write_sparse_matrix(matrix(2)%matrix,4,6,qs_env,para_env,output_unit=iw)
     660             :       !   CALL cp_dbcsr_write_sparse_matrix(matrix(3)%matrix,4,6,qs_env,para_env,output_unit=iw)
     661             :       !   CALL cp_print_key_finished_output(iw,logger,qs_env%input,&
     662             :       !        "DFT%PRINT%AO_MATRICES/ANGULAR_MOMENTUM")
     663             :       !END IF
     664             : 
     665        1250 :       CALL timestop(handle)
     666             : 
     667        3750 :    END SUBROUTINE build_ang_mom_matrix
     668             : 
     669             : ! **************************************************************************************************
     670             : !> \brief   Calculation of the primitive paramagnetic spin orbit integrals over
     671             : !>          Cartesian Gaussian-type functions.
     672             : !> \param la_max ...
     673             : !> \param la_min ...
     674             : !> \param npgfa ...
     675             : !> \param rpgfa ...
     676             : !> \param zeta ...
     677             : !> \param lb_max ...
     678             : !> \param lb_min ...
     679             : !> \param npgfb ...
     680             : !> \param rpgfb ...
     681             : !> \param zetb ...
     682             : !> \param rab ...
     683             : !> \param rac ...
     684             : !> \param intab ...
     685             : !> \param ldrr ...
     686             : !> \param rr ...
     687             : !> \date    02.03.2009
     688             : !> \author  VW
     689             : !> \version 1.0
     690             : ! **************************************************************************************************
     691      403786 :    SUBROUTINE ang_mom(la_max, la_min, npgfa, rpgfa, zeta, lb_max, lb_min, npgfb, rpgfb, zetb, &
     692      201893 :                       rab, rac, intab, ldrr, rr)
     693             :       INTEGER, INTENT(IN)                                :: la_max, la_min, npgfa
     694             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rpgfa, zeta
     695             :       INTEGER, INTENT(IN)                                :: lb_max, lb_min, npgfb
     696             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rpgfb, zetb
     697             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rab, rac
     698             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT)   :: intab
     699             :       INTEGER, INTENT(IN)                                :: ldrr
     700             :       REAL(dp), DIMENSION(0:ldrr-1, 0:ldrr-1, 3), &
     701             :          INTENT(INOUT)                                   :: rr
     702             : 
     703             :       INTEGER                                            :: ax, ay, az, bx, by, bz, coa, cob, i, &
     704             :                                                             ipgf, j, jpgf, la, lb, ma, mb, na, nb
     705             :       REAL(dp)                                           :: dab, dumx, dumy, dumz, f0, rab2, xhi, zet
     706             :       REAL(dp), DIMENSION(3)                             :: rap, rbp
     707             : 
     708             : ! *** Calculate the distance of the centers a and c ***
     709             : 
     710      201893 :       rab2 = rab(1)**2 + rab(2)**2 + rab(3)**2
     711      201893 :       dab = SQRT(rab2)
     712             : 
     713             :       ! *** Loop over all pairs of primitive Gaussian-type functions ***
     714             : 
     715      201893 :       na = 0
     716             : 
     717      676304 :       DO ipgf = 1, npgfa
     718             : 
     719      474411 :          nb = 0
     720             : 
     721     1742562 :          DO jpgf = 1, npgfb
     722             : 
     723             :             ! *** Screening ***
     724             : 
     725     1268151 :             IF (rpgfa(ipgf) + rpgfb(jpgf) < dab) THEN
     726     3336529 :                DO j = nb + 1, nb + ncoset(lb_max)
     727    12446889 :                   DO i = na + 1, na + ncoset(la_max)
     728     9110360 :                      intab(i, j, 1) = 0.0_dp
     729     9110360 :                      intab(i, j, 2) = 0.0_dp
     730    11620957 :                      intab(i, j, 3) = 0.0_dp
     731             :                   END DO
     732             :                END DO
     733      825932 :                nb = nb + ncoset(lb_max)
     734      825932 :                CYCLE
     735             :             END IF
     736             : 
     737             :             ! *** Calculate some prefactors ***
     738      442219 :             zet = zeta(ipgf) + zetb(jpgf)
     739      442219 :             xhi = zeta(ipgf)*zetb(jpgf)/zet
     740     1768876 :             rap = zetb(jpgf)*rab/zet
     741     1768876 :             rbp = -zeta(ipgf)*rab/zet
     742             : 
     743      442219 :             f0 = (pi/zet)**(1.5_dp)*EXP(-xhi*rab2)
     744             : 
     745             :             ! *** Calculate the recurrence relation ***
     746             : 
     747      442219 :             CALL os_rr_ovlp(rap, la_max + 1, rbp, lb_max, zet, ldrr, rr)
     748             : 
     749             :             ! *** Calculate the primitive Fermi contact integrals ***
     750             : 
     751     1087122 :             DO lb = lb_min, lb_max
     752     2011607 :             DO bx = 0, lb
     753     2802912 :             DO by = 0, lb - bx
     754     1233524 :                bz = lb - bx - by
     755     1233524 :                cob = coset(bx, by, bz)
     756     1233524 :                mb = nb + cob
     757     4112005 :                DO la = la_min, la_max
     758     6109494 :                DO ax = 0, la
     759     8873886 :                DO ay = 0, la - ax
     760     3997916 :                   az = la - ax - ay
     761     3997916 :                   coa = coset(ax, ay, az)
     762     3997916 :                   ma = na + coa
     763             :                   !
     764     3997916 :                   dumx = -2.0_dp*zeta(ipgf)*rr(ax + 1, bx, 1)
     765     3997916 :                   dumy = -2.0_dp*zeta(ipgf)*rr(ay + 1, by, 2)
     766     3997916 :                   dumz = -2.0_dp*zeta(ipgf)*rr(az + 1, bz, 3)
     767     3997916 :                   IF (ax .GT. 0) dumx = dumx + REAL(ax, dp)*rr(ax - 1, bx, 1)
     768     3997916 :                   IF (ay .GT. 0) dumy = dumy + REAL(ay, dp)*rr(ay - 1, by, 2)
     769     3997916 :                   IF (az .GT. 0) dumz = dumz + REAL(az, dp)*rr(az - 1, bz, 3)
     770             :                   !
     771             :                   ! (a|l_z|b)
     772             :                   intab(ma, mb, 1) = -f0*rr(ax, bx, 1)*( &
     773             :                        &  (rr(ay + 1, by, 2) + rac(2)*rr(ay, by, 2))*dumz &
     774     3997916 :                        & - (rr(az + 1, bz, 3) + rac(3)*rr(az, bz, 3))*dumy)
     775             :                   !
     776             :                   ! (a|l_y|b)
     777             :                   intab(ma, mb, 2) = -f0*rr(ay, by, 2)*( &
     778             :                        &  (rr(az + 1, bz, 3) + rac(3)*rr(az, bz, 3))*dumx &
     779     3997916 :                        & - (rr(ax + 1, bx, 1) + rac(1)*rr(ax, bx, 1))*dumz)
     780             :                   !
     781             :                   ! (a|l_z|b)
     782             :                   intab(ma, mb, 3) = -f0*rr(az, bz, 3)*( &
     783             :                        &  (rr(ax + 1, bx, 1) + rac(1)*rr(ax, bx, 1))*dumy &
     784     6919890 :                        & - (rr(ay + 1, by, 2) + rac(2)*rr(ay, by, 2))*dumx)
     785             :                   !
     786             :                END DO
     787             :                END DO
     788             :                END DO !la
     789             : 
     790             :             END DO
     791             :             END DO
     792             :             END DO !lb
     793             : 
     794      916630 :             nb = nb + ncoset(lb_max)
     795             : 
     796             :          END DO
     797             : 
     798      676304 :          na = na + ncoset(la_max)
     799             : 
     800             :       END DO
     801             : 
     802      201893 :    END SUBROUTINE ang_mom
     803             : 
     804             : ! **************************************************************************************************
     805             : !> \brief Calculation of the components of the dipole operator in the velocity form
     806             : !>      The elements of the  sparse matrices are the integrals in the
     807             : !>      basis functions
     808             : !> \param op matrix representation of the p operator
     809             : !>               calculated in terms of the contracted basis functions
     810             : !> \param qs_env environment for the lists and the basis sets
     811             : !> \param minimum_image take into account only the first neighbors in the lists
     812             : !> \par History
     813             : !>      06.2005 created [MI]
     814             : !> \author MI
     815             : ! **************************************************************************************************
     816             : 
     817          74 :    SUBROUTINE p_xyz_ao(op, qs_env, minimum_image)
     818             : 
     819             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: op
     820             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     821             :       LOGICAL, INTENT(IN), OPTIONAL                      :: minimum_image
     822             : 
     823             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'p_xyz_ao'
     824             : 
     825             :       INTEGER :: handle, i, iatom, icol, ikind, inode, irow, iset, jatom, jkind, jset, last_jatom, &
     826             :          ldab, ldsa, ldsb, ldwork, maxl, ncoa, ncob, nkind, nseta, nsetb, sgfa, sgfb
     827          74 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, lb_min, npgfa, &
     828          74 :                                                             npgfb, nsgfa, nsgfb
     829          74 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
     830             :       LOGICAL                                            :: found, my_minimum_image, new_atom_b
     831             :       REAL(KIND=dp)                                      :: alpha, dab, Lxo2, Lyo2, Lzo2, rab2
     832             :       REAL(KIND=dp), DIMENSION(3)                        :: ra, rab
     833          74 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a, set_radius_b
     834          74 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: rpgfa, rpgfb, sphi_a, sphi_b, work, &
     835          74 :                                                             zeta, zetb
     836             :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: difab
     837          74 :       TYPE(block_p_type), DIMENSION(:), POINTER          :: op_dip
     838             :       TYPE(cell_type), POINTER                           :: cell
     839          74 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
     840             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
     841             :       TYPE(neighbor_list_iterator_p_type), &
     842          74 :          DIMENSION(:), POINTER                           :: nl_iterator
     843             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     844          74 :          POINTER                                         :: sab_orb
     845          74 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     846          74 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     847             :       TYPE(qs_kind_type), POINTER                        :: qs_kind
     848             : 
     849          74 :       CALL timeset(routineN, handle)
     850             : 
     851          74 :       NULLIFY (qs_kind, qs_kind_set)
     852          74 :       NULLIFY (cell, particle_set)
     853          74 :       NULLIFY (sab_orb)
     854          74 :       NULLIFY (difab, op_dip, work)
     855          74 :       NULLIFY (la_max, la_min, lb_max, lb_min, npgfa, npgfb, nsgfa, nsgfb)
     856          74 :       NULLIFY (set_radius_a, set_radius_b, rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb)
     857             : 
     858             :       CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, &
     859             :                       cell=cell, particle_set=particle_set, &
     860          74 :                       sab_orb=sab_orb)
     861             : 
     862          74 :       nkind = SIZE(qs_kind_set)
     863             : 
     864             :       CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
     865          74 :                            maxco=ldwork, maxlgto=maxl)
     866             : 
     867          74 :       my_minimum_image = .FALSE.
     868          74 :       IF (PRESENT(minimum_image)) THEN
     869          32 :          my_minimum_image = minimum_image
     870         128 :          Lxo2 = SQRT(SUM(cell%hmat(:, 1)**2))/2.0_dp
     871         128 :          Lyo2 = SQRT(SUM(cell%hmat(:, 2)**2))/2.0_dp
     872         128 :          Lzo2 = SQRT(SUM(cell%hmat(:, 3)**2))/2.0_dp
     873             :       END IF
     874             : 
     875          74 :       ldab = ldwork
     876             : 
     877         370 :       ALLOCATE (difab(ldab, ldab, 3))
     878       73952 :       difab(1:ldab, 1:ldab, 1:3) = 0.0_dp
     879         296 :       ALLOCATE (work(ldwork, ldwork))
     880       24626 :       work(1:ldwork, 1:ldwork) = 0.0_dp
     881         296 :       ALLOCATE (op_dip(3))
     882             : 
     883         296 :       DO i = 1, 3
     884         296 :          NULLIFY (op_dip(i)%block)
     885             :       END DO
     886             : 
     887         342 :       ALLOCATE (basis_set_list(nkind))
     888         194 :       DO ikind = 1, nkind
     889         120 :          qs_kind => qs_kind_set(ikind)
     890         120 :          CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a)
     891         194 :          IF (ASSOCIATED(basis_set_a)) THEN
     892         120 :             basis_set_list(ikind)%gto_basis_set => basis_set_a
     893             :          ELSE
     894           0 :             NULLIFY (basis_set_list(ikind)%gto_basis_set)
     895             :          END IF
     896             :       END DO
     897          74 :       CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
     898        9841 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     899             :          CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
     900        9767 :                                 iatom=iatom, jatom=jatom, r=rab)
     901        9767 :          basis_set_a => basis_set_list(ikind)%gto_basis_set
     902        9767 :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
     903        9767 :          basis_set_b => basis_set_list(jkind)%gto_basis_set
     904        9767 :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
     905        9767 :          ra = pbc(particle_set(iatom)%r, cell)
     906             :          ! basis ikind
     907        9767 :          first_sgfa => basis_set_a%first_sgf
     908        9767 :          la_max => basis_set_a%lmax
     909        9767 :          la_min => basis_set_a%lmin
     910        9767 :          npgfa => basis_set_a%npgf
     911        9767 :          nseta = basis_set_a%nset
     912        9767 :          nsgfa => basis_set_a%nsgf_set
     913        9767 :          rpgfa => basis_set_a%pgf_radius
     914        9767 :          set_radius_a => basis_set_a%set_radius
     915        9767 :          sphi_a => basis_set_a%sphi
     916        9767 :          zeta => basis_set_a%zet
     917             :          ! basis jkind
     918        9767 :          first_sgfb => basis_set_b%first_sgf
     919        9767 :          lb_max => basis_set_b%lmax
     920        9767 :          lb_min => basis_set_b%lmin
     921        9767 :          npgfb => basis_set_b%npgf
     922        9767 :          nsetb = basis_set_b%nset
     923        9767 :          nsgfb => basis_set_b%nsgf_set
     924        9767 :          rpgfb => basis_set_b%pgf_radius
     925        9767 :          set_radius_b => basis_set_b%set_radius
     926        9767 :          sphi_b => basis_set_b%sphi
     927        9767 :          zetb => basis_set_b%zet
     928             : 
     929        9767 :          IF (inode == 1) THEN
     930         363 :             last_jatom = 0
     931         363 :             alpha = 1.0_dp
     932             :          END IF
     933        9767 :          ldsa = SIZE(sphi_a, 1)
     934        9767 :          ldsb = SIZE(sphi_b, 1)
     935             : 
     936        9767 :          IF (my_minimum_image) THEN
     937        8345 :             IF (ABS(rab(1)) > Lxo2 .OR. ABS(rab(2)) > Lyo2 .OR. ABS(rab(3)) > Lzo2) CYCLE
     938             :          END IF
     939             : 
     940        6303 :          IF (jatom /= last_jatom) THEN
     941             :             new_atom_b = .TRUE.
     942             :             last_jatom = jatom
     943             :          ELSE
     944             :             new_atom_b = .FALSE.
     945             :          END IF
     946             : 
     947             :          IF (new_atom_b) THEN
     948        4921 :             IF (iatom <= jatom) THEN
     949        2532 :                irow = iatom
     950        2532 :                icol = jatom
     951        2532 :                alpha = 1.0_dp
     952             :             ELSE
     953        2389 :                irow = jatom
     954        2389 :                icol = iatom
     955        2389 :                IF (dbcsr_get_matrix_type(op(1)%matrix) == dbcsr_type_antisymmetric) THEN
     956             :                   !IF(op(1)%matrix%symmetry=="antisymmetric") THEN
     957        4778 :                   alpha = -1.0_dp
     958             :                END IF
     959             :             END IF
     960             : 
     961       19684 :             DO i = 1, 3
     962       14763 :                NULLIFY (op_dip(i)%block)
     963             :                CALL dbcsr_get_block_p(matrix=op(i)%matrix, &
     964       14763 :                                       row=irow, col=icol, block=op_dip(i)%block, found=found)
     965       19684 :                CPASSERT(ASSOCIATED(op_dip(i)%block))
     966             :             END DO
     967             :          END IF ! new_atom_b
     968        6303 :          rab2 = rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3)
     969        6303 :          dab = SQRT(rab2)
     970             : 
     971       23726 :          DO iset = 1, nseta
     972             : 
     973       17349 :             ncoa = npgfa(iset)*ncoset(la_max(iset))
     974       17349 :             sgfa = first_sgfa(1, iset)
     975             : 
     976       78981 :             DO jset = 1, nsetb
     977             : 
     978       51865 :                ncob = npgfb(jset)*ncoset(lb_max(jset))
     979       51865 :                sgfb = first_sgfb(1, jset)
     980             : 
     981       69214 :                IF (set_radius_a(iset) + set_radius_b(jset) >= dab) THEN
     982             : 
     983             : !            *** Calculate the primitive overlap integrals ***
     984             :                   CALL diffop(la_max(iset), npgfa(iset), zeta(:, iset), &
     985             :                               rpgfa(:, iset), la_min(iset), lb_max(jset), npgfb(jset), &
     986       22848 :                               zetb(:, jset), rpgfb(:, jset), lb_min(jset), rab, difab)
     987             : 
     988             : !            *** Contraction ***
     989             :                   CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
     990             :                              alpha, difab(1, 1, 1), ldab, sphi_b(1, sgfb), ldsb, &
     991       22848 :                              0.0_dp, work(1, 1), ldwork)
     992       22848 :                   IF (iatom <= jatom) THEN
     993             :                      CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
     994             :                                 1.0_dp, sphi_a(1, sgfa), ldsa, &
     995             :                                 work(1, 1), ldwork, &
     996             :                                 1.0_dp, op_dip(1)%block(sgfa, sgfb), &
     997       12802 :                                 SIZE(op_dip(1)%block, 1))
     998             : 
     999             :                   ELSE
    1000             :                      CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
    1001             :                                 1.0_dp, work(1, 1), ldwork, &
    1002             :                                 sphi_a(1, sgfa), ldsa, &
    1003             :                                 1.0_dp, op_dip(1)%block(sgfb, sgfa), &
    1004       10046 :                                 SIZE(op_dip(1)%block, 1))
    1005             : 
    1006             :                   END IF
    1007             : 
    1008             : !             *** Contraction ***
    1009             :                   CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
    1010             :                              alpha, difab(1, 1, 2), ldab, sphi_b(1, sgfb), ldsb, &
    1011       22848 :                              0.0_dp, work(1, 1), ldwork)
    1012       22848 :                   IF (iatom <= jatom) THEN
    1013             :                      CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
    1014             :                                 1.0_dp, sphi_a(1, sgfa), ldsa, &
    1015             :                                 work(1, 1), ldwork, &
    1016             :                                 1.0_dp, op_dip(2)%block(sgfa, sgfb), &
    1017       12802 :                                 SIZE(op_dip(2)%block, 1))
    1018             :                   ELSE
    1019             :                      CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
    1020             :                                 1.0_dp, work(1, 1), ldwork, &
    1021             :                                 sphi_a(1, sgfa), ldsa, &
    1022             :                                 1.0_dp, op_dip(2)%block(sgfb, sgfa), &
    1023       10046 :                                 SIZE(op_dip(2)%block, 1))
    1024             :                   END IF
    1025             : 
    1026             : !            *** Contraction ***
    1027             :                   CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
    1028             :                              alpha, difab(1, 1, 3), ldab, sphi_b(1, sgfb), ldsb, &
    1029       22848 :                              0.0_dp, work(1, 1), ldwork)
    1030       22848 :                   IF (iatom <= jatom) THEN
    1031             :                      CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
    1032             :                                 1.0_dp, sphi_a(1, sgfa), ldsa, &
    1033             :                                 work(1, 1), ldwork, &
    1034             :                                 1.0_dp, op_dip(3)%block(sgfa, sgfb), &
    1035       12802 :                                 SIZE(op_dip(3)%block, 1))
    1036             :                   ELSE
    1037             :                      CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
    1038             :                                 1.0_dp, work(1, 1), ldwork, &
    1039             :                                 sphi_a(1, sgfa), ldsa, &
    1040             :                                 1.0_dp, op_dip(3)%block(sgfb, sgfa), &
    1041       10046 :                                 SIZE(op_dip(3)%block, 1))
    1042             :                   END IF
    1043             :                END IF !  >= dab
    1044             : 
    1045             :             END DO ! jset
    1046             : 
    1047             :          END DO ! iset
    1048             : 
    1049             :       END DO
    1050          74 :       CALL neighbor_list_iterator_release(nl_iterator)
    1051             : 
    1052         296 :       DO i = 1, 3
    1053         296 :          NULLIFY (op_dip(i)%block)
    1054             :       END DO
    1055          74 :       DEALLOCATE (op_dip)
    1056             : 
    1057          74 :       DEALLOCATE (difab, work, basis_set_list)
    1058             : 
    1059          74 :       CALL timestop(handle)
    1060             : 
    1061         148 :    END SUBROUTINE p_xyz_ao
    1062             : 
    1063             : ! **************************************************************************************************
    1064             : !> \brief Calculation of the components of the dipole operator in the length form
    1065             : !>      by taking the relative position operator r-Rc, with respect a reference point Rc
    1066             : !>      Probably it does not work for PBC, or maybe yes if the wfn are
    1067             : !>      sufficiently localized
    1068             : !>      The elements of the  sparse matrices are the integrals in the
    1069             : !>      basis functions
    1070             : !> \param op matrix representation of the p operator
    1071             : !>               calculated in terms of the contracted basis functions
    1072             : !> \param qs_env environment for the lists and the basis sets
    1073             : !> \param rc reference vector position
    1074             : !> \param order maximum order of the momentum, for the dipole order = 1, order = -2 for quad only
    1075             : !> \param minimum_image take into account only the first neighbors in the lists
    1076             : !> \param soft ...
    1077             : !> \par History
    1078             : !>      03.2006 created [MI]
    1079             : !>      06.2019 added quarupole only option (A.Bussy)
    1080             : !> \author MI
    1081             : ! **************************************************************************************************
    1082             : 
    1083          40 :    SUBROUTINE rRc_xyz_ao(op, qs_env, rc, order, minimum_image, soft)
    1084             : 
    1085             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: op
    1086             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1087             :       REAL(dp)                                           :: Rc(3)
    1088             :       INTEGER, INTENT(IN)                                :: order
    1089             :       LOGICAL, INTENT(IN), OPTIONAL                      :: minimum_image, soft
    1090             : 
    1091             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'rRc_xyz_ao'
    1092             : 
    1093             :       CHARACTER(LEN=default_string_length)               :: basis_type
    1094             :       INTEGER :: handle, iatom, icol, ikind, imom, inode, irow, iset, jatom, jkind, jset, &
    1095             :          last_jatom, ldab, ldsa, ldsb, ldwork, M_dim, maxl, ncoa, ncob, nkind, nseta, nsetb, sgfa, &
    1096             :          sgfb, smom
    1097          40 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, npgfa, npgfb, &
    1098          40 :                                                             nsgfa, nsgfb
    1099          40 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
    1100             :       LOGICAL                                            :: found, my_minimum_image, my_soft, &
    1101             :                                                             new_atom_b
    1102             :       REAL(KIND=dp)                                      :: dab, Lxo2, Lyo2, Lzo2, rab2
    1103             :       REAL(KIND=dp), DIMENSION(3)                        :: ra, rab, rac, rb, rbc
    1104          40 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a, set_radius_b
    1105          40 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: rpgfa, rpgfb, sphi_a, sphi_b, work, &
    1106          40 :                                                             zeta, zetb
    1107          40 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: mab
    1108          40 :       TYPE(block_p_type), DIMENSION(:), POINTER          :: op_dip
    1109             :       TYPE(cell_type), POINTER                           :: cell
    1110          40 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
    1111             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
    1112             :       TYPE(neighbor_list_iterator_p_type), &
    1113          40 :          DIMENSION(:), POINTER                           :: nl_iterator
    1114             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1115          40 :          POINTER                                         :: sab_orb
    1116          40 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1117          40 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1118             :       TYPE(qs_kind_type), POINTER                        :: qs_kind
    1119             : 
    1120          40 :       CALL timeset(routineN, handle)
    1121             : 
    1122          40 :       NULLIFY (qs_kind, qs_kind_set)
    1123          40 :       NULLIFY (cell, particle_set)
    1124          40 :       NULLIFY (sab_orb)
    1125          40 :       NULLIFY (mab, op_dip, work)
    1126          40 :       NULLIFY (la_max, la_min, lb_max, npgfa, npgfb, nsgfa, nsgfb)
    1127          40 :       NULLIFY (set_radius_a, set_radius_b, rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb)
    1128             : 
    1129          40 :       my_soft = .FALSE.
    1130          40 :       IF (PRESENT(soft)) my_soft = soft
    1131          14 :       IF (my_soft) THEN
    1132           0 :          basis_type = "ORB_SOFT"
    1133             :       ELSE
    1134          40 :          basis_type = "ORB"
    1135             :       END IF
    1136             : 
    1137             :       CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, &
    1138          40 :                       cell=cell, particle_set=particle_set, sab_orb=sab_orb)
    1139             : 
    1140          40 :       nkind = SIZE(qs_kind_set)
    1141             : 
    1142             :       CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
    1143          40 :                            maxco=ldwork, maxlgto=maxl)
    1144             : 
    1145          40 :       my_minimum_image = .FALSE.
    1146          40 :       IF (PRESENT(minimum_image)) THEN
    1147          38 :          my_minimum_image = minimum_image
    1148         152 :          Lxo2 = SQRT(SUM(cell%hmat(:, 1)**2))/2.0_dp
    1149         152 :          Lyo2 = SQRT(SUM(cell%hmat(:, 2)**2))/2.0_dp
    1150         152 :          Lzo2 = SQRT(SUM(cell%hmat(:, 3)**2))/2.0_dp
    1151             :       END IF
    1152             : 
    1153          40 :       ldab = ldwork
    1154             : 
    1155          40 :       smom = 1
    1156          40 :       IF (order == -2) smom = 4
    1157          40 :       M_dim = ncoset(ABS(order)) - 1
    1158          40 :       CPASSERT(M_dim <= SIZE(op, 1))
    1159             : 
    1160         200 :       ALLOCATE (mab(ldab, ldab, 1:M_dim))
    1161       29872 :       mab(1:ldab, 1:ldab, 1:M_dim) = 0.0_dp
    1162         160 :       ALLOCATE (work(ldwork, ldwork))
    1163        9944 :       work(1:ldwork, 1:ldwork) = 0.0_dp
    1164         240 :       ALLOCATE (op_dip(smom:M_dim))
    1165             : 
    1166         160 :       DO imom = smom, M_dim
    1167         160 :          NULLIFY (op_dip(imom)%block)
    1168             :       END DO
    1169             : 
    1170         188 :       ALLOCATE (basis_set_list(nkind))
    1171         108 :       DO ikind = 1, nkind
    1172          68 :          qs_kind => qs_kind_set(ikind)
    1173          68 :          CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a, basis_type=basis_type)
    1174         108 :          IF (ASSOCIATED(basis_set_a)) THEN
    1175          68 :             basis_set_list(ikind)%gto_basis_set => basis_set_a
    1176             :          ELSE
    1177           0 :             NULLIFY (basis_set_list(ikind)%gto_basis_set)
    1178             :          END IF
    1179             :       END DO
    1180          40 :       CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
    1181         157 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
    1182             :          CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
    1183         117 :                                 iatom=iatom, jatom=jatom, r=rab)
    1184         117 :          basis_set_a => basis_set_list(ikind)%gto_basis_set
    1185         117 :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
    1186         117 :          basis_set_b => basis_set_list(jkind)%gto_basis_set
    1187         117 :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
    1188         117 :          ra = pbc(particle_set(iatom)%r, cell)
    1189             :          ! basis ikind
    1190         117 :          first_sgfa => basis_set_a%first_sgf
    1191         117 :          la_max => basis_set_a%lmax
    1192         117 :          la_min => basis_set_a%lmin
    1193         117 :          npgfa => basis_set_a%npgf
    1194         117 :          nseta = basis_set_a%nset
    1195         117 :          nsgfa => basis_set_a%nsgf_set
    1196         117 :          rpgfa => basis_set_a%pgf_radius
    1197         117 :          set_radius_a => basis_set_a%set_radius
    1198         117 :          sphi_a => basis_set_a%sphi
    1199         117 :          zeta => basis_set_a%zet
    1200             :          ! basis jkind
    1201         117 :          first_sgfb => basis_set_b%first_sgf
    1202         117 :          lb_max => basis_set_b%lmax
    1203         117 :          npgfb => basis_set_b%npgf
    1204         117 :          nsetb = basis_set_b%nset
    1205         117 :          nsgfb => basis_set_b%nsgf_set
    1206         117 :          rpgfb => basis_set_b%pgf_radius
    1207         117 :          set_radius_b => basis_set_b%set_radius
    1208         117 :          sphi_b => basis_set_b%sphi
    1209         117 :          zetb => basis_set_b%zet
    1210             : 
    1211         117 :          ldsa = SIZE(sphi_a, 1)
    1212         117 :          ldsb = SIZE(sphi_b, 1)
    1213         117 :          IF (inode == 1) last_jatom = 0
    1214             : 
    1215         117 :          IF (my_minimum_image) THEN
    1216          91 :             IF (ABS(rab(1)) > Lxo2 .OR. ABS(rab(2)) > Lyo2 .OR. ABS(rab(3)) > Lzo2) CYCLE
    1217             :          END IF
    1218             : 
    1219         460 :          rb = rab + ra
    1220             : 
    1221         115 :          IF (jatom /= last_jatom) THEN
    1222             :             new_atom_b = .TRUE.
    1223             :             last_jatom = jatom
    1224             :          ELSE
    1225             :             new_atom_b = .FALSE.
    1226             :          END IF
    1227             : 
    1228             :          IF (new_atom_b) THEN
    1229          97 :             IF (iatom <= jatom) THEN
    1230          65 :                irow = iatom
    1231          65 :                icol = jatom
    1232             :             ELSE
    1233          32 :                irow = jatom
    1234          32 :                icol = iatom
    1235             :             END IF
    1236             : 
    1237         388 :             DO imom = smom, M_dim
    1238         291 :                NULLIFY (op_dip(imom)%block)
    1239             :                CALL dbcsr_get_block_p(matrix=op(imom)%matrix, &
    1240         291 :                                       row=irow, col=icol, block=op_dip(imom)%block, found=found)
    1241         388 :                CPASSERT(ASSOCIATED(op_dip(imom)%block))
    1242             :             END DO ! imom
    1243             :          END IF ! new_atom_b
    1244             : 
    1245         115 :          rab2 = rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3)
    1246         115 :          dab = SQRT(rab2)
    1247             : 
    1248         503 :          DO iset = 1, nseta
    1249             : 
    1250         348 :             ncoa = npgfa(iset)*ncoset(la_max(iset))
    1251         348 :             sgfa = first_sgfa(1, iset)
    1252             : 
    1253        1621 :             DO jset = 1, nsetb
    1254             : 
    1255        1156 :                ncob = npgfb(jset)*ncoset(lb_max(jset))
    1256        1156 :                sgfb = first_sgfb(1, jset)
    1257             : 
    1258        1504 :                IF (set_radius_a(iset) + set_radius_b(jset) >= dab) THEN
    1259             : 
    1260        1036 :                   rac = pbc(rc, ra, cell)
    1261        1036 :                   rbc = pbc(rc, rb, cell)
    1262             : 
    1263             : !            *** Calculate the primitive overlap integrals ***
    1264             :                   CALL moment(la_max(iset), npgfa(iset), zeta(:, iset), &
    1265             :                               rpgfa(:, iset), la_min(iset), &
    1266             :                               lb_max(jset), npgfb(jset), zetb(:, jset), rpgfb(:, jset), &
    1267        1036 :                               ABS(order), rac, rbc, mab)
    1268             : 
    1269        4144 :                   DO imom = smom, M_dim
    1270             : !                 *** Contraction ***
    1271             :                      CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
    1272             :                                 1.0_dp, mab(1, 1, imom), ldab, sphi_b(1, sgfb), ldsb, &
    1273        3108 :                                 0.0_dp, work(1, 1), ldwork)
    1274        4144 :                      IF (iatom <= jatom) THEN
    1275             :                         CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
    1276             :                                    1.0_dp, sphi_a(1, sgfa), ldsa, &
    1277             :                                    work(1, 1), ldwork, &
    1278             :                                    1.0_dp, op_dip(imom)%block(sgfa, sgfb), &
    1279        2385 :                                    SIZE(op_dip(imom)%block, 1))
    1280             :                      ELSE
    1281             :                         CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
    1282             :                                    1.0_dp, work(1, 1), ldwork, &
    1283             :                                    sphi_a(1, sgfa), ldsa, &
    1284             :                                    1.0_dp, op_dip(imom)%block(sgfb, sgfa), &
    1285         723 :                                    SIZE(op_dip(imom)%block, 1))
    1286             :                      END IF
    1287             : 
    1288             :                   END DO ! imom
    1289             :                END IF !  >= dab
    1290             : 
    1291             :             END DO ! jset
    1292             : 
    1293             :          END DO ! iset
    1294             : 
    1295             :       END DO
    1296          40 :       CALL neighbor_list_iterator_release(nl_iterator)
    1297             : 
    1298         160 :       DO imom = smom, M_dim
    1299         160 :          NULLIFY (op_dip(imom)%block)
    1300             :       END DO
    1301          40 :       DEALLOCATE (op_dip)
    1302             : 
    1303          40 :       DEALLOCATE (mab, work, basis_set_list)
    1304             : 
    1305          40 :       CALL timestop(handle)
    1306             : 
    1307          80 :    END SUBROUTINE rRc_xyz_ao
    1308             : 
    1309             : ! **************************************************************************************************
    1310             : !> \brief Calculation of the  multipole operators integrals
    1311             : !>      and of its derivatives of the type
    1312             : !>      [\mu | op | d(\nu)/dR(\nu)]-[d(\mu)/dR(\mu)| op | \nu]
    1313             : !>      by taking the relative position operator r-Rc, with respect a reference point Rc
    1314             : !>      The derivative are with respect to the primitive position,
    1315             : !>      The multipole operator is symmetric and if it does not depend on R(\mu) or R(\nu)
    1316             : !>      therefore  [\mu | op | d(\nu)/dR(\nu)] = -[d(\mu)/dR(\mu)| op | \nu]
    1317             : !>        [\mu|op|d(\nu)/dR]-[d(\mu)/dR|op|\nu]=2[\mu|op|d(\nu)/dR]
    1318             : !>      When it is not the case a correction term is needed
    1319             : !>
    1320             : !>     The momentum operator [\mu|M|\nu] is symmetric, the number of components is
    1321             : !>     determined by the order: 3 for order 1 (x,y,x), 9 for order 2(xx,xy,xz,yy,yz,zz)
    1322             : !>     The derivative of the type [\mu | op | d(\nu)/dR_i(\nu)], where
    1323             : !>     i indicates the cartesian direction, is antisymmetric only when
    1324             : !>     the no component M =(r_i) or (r_i r_j) is in the same cartesian
    1325             : !>     direction of the derivative,  indeed
    1326             : !>   d([\mu|M|\nu])/dr_i = [d(\mu)/dr_i|M|\nu] + [\mu|M|d(\nu)/dr_i] + [\mu |d(M)/dr_i|\nu]
    1327             : !>   d([\mu|M|\nu])/dr_i = -[d(\mu)/dR_i(\mu)|M|\nu] -[\mu|M|d(\nu)/dR_i(\nu)] + [\mu |d(M)/dr_i|\nu]
    1328             : !>     Therefore we cannot use an antisymmetric matrix
    1329             : !>
    1330             : !>     The same holds for the derivative with respect to the electronic position r
    1331             : !>     taking into account that [\mu|op|d(\nu)/dR] = -[\mu|op|d(\nu)/dr]
    1332             : !> \param op matrix representation of the p operator
    1333             : !>               calculated in terms of the contracted basis functions
    1334             : !> \param op_der ...
    1335             : !> \param qs_env environment for the lists and the basis sets
    1336             : !> \param rc reference vector position
    1337             : !> \param order maximum order of the momentum, for the dipole order = 1
    1338             : !> \param minimum_image take into account only the first neighbors in the lists
    1339             : !> \param soft ...
    1340             : !> \par History
    1341             : !>      03.2006 created [MI]
    1342             : !> \author MI
    1343             : !> \note
    1344             : !>      Probably it does not work for PBC, or maybe yes if the wfn are
    1345             : !>      sufficiently localized
    1346             : !>      The elements of the  sparse matrices are the integrals in the
    1347             : !>      basis functions
    1348             : ! **************************************************************************************************
    1349        3750 :    SUBROUTINE rRc_xyz_der_ao(op, op_der, qs_env, rc, order, minimum_image, soft)
    1350             : 
    1351             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: op
    1352             :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: op_der
    1353             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1354             :       REAL(dp)                                           :: Rc(3)
    1355             :       INTEGER, INTENT(IN)                                :: order
    1356             :       LOGICAL, INTENT(IN), OPTIONAL                      :: minimum_image, soft
    1357             : 
    1358             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'rRc_xyz_der_ao'
    1359             : 
    1360             :       CHARACTER(LEN=default_string_length)               :: basis_type
    1361             :       INTEGER :: handle, i, iatom, icol, idir, ikind, imom, inode, ipgf, irow, iset, j, jatom, &
    1362             :          jkind, jpgf, jset, last_jatom, lda_min, ldab, ldb_min, ldsa, ldsb, ldwork, M_dim, maxl, &
    1363             :          na, nb, ncoa, ncob, nda, ndb, nkind, nseta, nsetb, sgfa, sgfb
    1364        3750 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, lb_min, npgfa, &
    1365        3750 :                                                             npgfb, nsgfa, nsgfb
    1366        3750 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
    1367             :       LOGICAL                                            :: my_minimum_image, my_soft, new_atom_b, &
    1368             :                                                             op_der_found, op_found
    1369             :       REAL(KIND=dp)                                      :: alpha, alpha_der, dab, Lxo2, Lyo2, Lzo2, &
    1370             :                                                             rab2
    1371             :       REAL(KIND=dp), DIMENSION(3)                        :: ra, rab, rac, rb, rbc
    1372        3750 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a, set_radius_b
    1373        3750 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: rpgfa, rpgfb, sphi_a, sphi_b, work, &
    1374        3750 :                                                             zeta, zetb
    1375        3750 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: mab, mab_tmp
    1376        3750 :       REAL(KIND=dp), DIMENSION(:, :, :, :), POINTER      :: difmab
    1377        3750 :       TYPE(block_p_type), DIMENSION(:), POINTER          :: op_dip
    1378        3750 :       TYPE(block_p_type), DIMENSION(:, :), POINTER       :: op_dip_der
    1379             :       TYPE(cell_type), POINTER                           :: cell
    1380        3750 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
    1381             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
    1382             :       TYPE(neighbor_list_iterator_p_type), &
    1383        3750 :          DIMENSION(:), POINTER                           :: nl_iterator
    1384             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1385        3750 :          POINTER                                         :: sab_all
    1386        3750 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1387        3750 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1388             :       TYPE(qs_kind_type), POINTER                        :: qs_kind
    1389             : 
    1390        3750 :       CALL timeset(routineN, handle)
    1391             : 
    1392        3750 :       CPASSERT(ASSOCIATED(op))
    1393        3750 :       CPASSERT(ASSOCIATED(op_der))
    1394             :       !IF(.NOT.op_sm_der(1,1)%matrix%symmetry=="none") THEN
    1395        3750 :       IF (.NOT. dbcsr_get_matrix_type(op_der(1, 1)%matrix) .EQ. dbcsr_type_no_symmetry) THEN
    1396        3750 :          CPABORT("")
    1397             :       END IF
    1398             : 
    1399        3750 :       NULLIFY (qs_kind, qs_kind_set)
    1400        3750 :       NULLIFY (cell, particle_set)
    1401        3750 :       NULLIFY (sab_all)
    1402        3750 :       NULLIFY (difmab, mab, mab_tmp)
    1403        3750 :       NULLIFY (op_dip, op_dip_der, work)
    1404        3750 :       NULLIFY (la_max, la_min, lb_max, lb_min, npgfa, npgfb, nsgfa, nsgfb)
    1405        3750 :       NULLIFY (set_radius_a, set_radius_b, rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb)
    1406             : 
    1407        3750 :       my_soft = .FALSE.
    1408        3750 :       IF (PRESENT(soft)) my_soft = soft
    1409        3750 :       IF (my_soft) THEN
    1410        2022 :          basis_type = "ORB_SOFT"
    1411             :       ELSE
    1412        1728 :          basis_type = "ORB"
    1413             :       END IF
    1414             : 
    1415             :       CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, &
    1416             :                       cell=cell, particle_set=particle_set, &
    1417        3750 :                       sab_all=sab_all)
    1418             : 
    1419        3750 :       nkind = SIZE(qs_kind_set)
    1420             : 
    1421             :       CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
    1422        3750 :                            maxco=ldwork, maxlgto=maxl)
    1423             : 
    1424        3750 :       my_minimum_image = .FALSE.
    1425        3750 :       IF (PRESENT(minimum_image)) THEN
    1426        3750 :          my_minimum_image = minimum_image
    1427       15000 :          Lxo2 = SQRT(SUM(cell%hmat(:, 1)**2))/2.0_dp
    1428       15000 :          Lyo2 = SQRT(SUM(cell%hmat(:, 2)**2))/2.0_dp
    1429       15000 :          Lzo2 = SQRT(SUM(cell%hmat(:, 3)**2))/2.0_dp
    1430             :       END IF
    1431             : 
    1432        3750 :       ldab = ldwork
    1433             : 
    1434        3750 :       M_dim = ncoset(order) - 1
    1435        3750 :       CPASSERT(M_dim <= SIZE(op, 1))
    1436             : 
    1437       18750 :       ALLOCATE (mab(ldab, ldab, M_dim))
    1438     6053640 :       mab(1:ldab, 1:ldab, 1:M_dim) = 0.0_dp
    1439       22500 :       ALLOCATE (difmab(ldab, ldab, M_dim, 3))
    1440    18164670 :       difmab(1:ldab, 1:ldab, 1:M_dim, 1:3) = 0.0_dp
    1441             : 
    1442       15000 :       ALLOCATE (work(ldwork, ldwork))
    1443      672210 :       work(1:ldwork, 1:ldwork) = 0.0_dp
    1444       45000 :       ALLOCATE (op_dip(M_dim))
    1445      123750 :       ALLOCATE (op_dip_der(M_dim, 3))
    1446             : 
    1447       37500 :       DO imom = 1, M_dim
    1448       33750 :          NULLIFY (op_dip(imom)%block)
    1449      138750 :          DO i = 1, 3
    1450      135000 :             NULLIFY (op_dip_der(imom, i)%block)
    1451             :          END DO
    1452             :       END DO
    1453             : 
    1454       17388 :       ALLOCATE (basis_set_list(nkind))
    1455        9888 :       DO ikind = 1, nkind
    1456        6138 :          qs_kind => qs_kind_set(ikind)
    1457        6138 :          CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a, basis_type=basis_type)
    1458        9888 :          IF (ASSOCIATED(basis_set_a)) THEN
    1459        6138 :             basis_set_list(ikind)%gto_basis_set => basis_set_a
    1460             :          ELSE
    1461           0 :             NULLIFY (basis_set_list(ikind)%gto_basis_set)
    1462             :          END IF
    1463             :       END DO
    1464        3750 :       CALL neighbor_list_iterator_create(nl_iterator, sab_all)
    1465      284943 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
    1466             :          CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
    1467      281193 :                                 iatom=iatom, jatom=jatom, r=rab)
    1468      281193 :          basis_set_a => basis_set_list(ikind)%gto_basis_set
    1469      281193 :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
    1470      281193 :          basis_set_b => basis_set_list(jkind)%gto_basis_set
    1471      281193 :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
    1472      281193 :          ra = pbc(particle_set(iatom)%r, cell)
    1473             :          ! basis ikind
    1474      281193 :          first_sgfa => basis_set_a%first_sgf
    1475      281193 :          la_max => basis_set_a%lmax
    1476      281193 :          la_min => basis_set_a%lmin
    1477      281193 :          npgfa => basis_set_a%npgf
    1478      281193 :          nseta = basis_set_a%nset
    1479      281193 :          nsgfa => basis_set_a%nsgf_set
    1480      281193 :          rpgfa => basis_set_a%pgf_radius
    1481      281193 :          set_radius_a => basis_set_a%set_radius
    1482      281193 :          sphi_a => basis_set_a%sphi
    1483      281193 :          zeta => basis_set_a%zet
    1484             :          ! basis jkind
    1485      281193 :          first_sgfb => basis_set_b%first_sgf
    1486      281193 :          lb_max => basis_set_b%lmax
    1487      281193 :          lb_min => basis_set_b%lmin
    1488      281193 :          npgfb => basis_set_b%npgf
    1489      281193 :          nsetb = basis_set_b%nset
    1490      281193 :          nsgfb => basis_set_b%nsgf_set
    1491      281193 :          rpgfb => basis_set_b%pgf_radius
    1492      281193 :          set_radius_b => basis_set_b%set_radius
    1493      281193 :          sphi_b => basis_set_b%sphi
    1494      281193 :          zetb => basis_set_b%zet
    1495             : 
    1496      281193 :          ldsa = SIZE(sphi_a, 1)
    1497      281193 :          IF (ldsa .EQ. 0) CYCLE
    1498      281172 :          ldsb = SIZE(sphi_b, 1)
    1499      281172 :          IF (ldsb .EQ. 0) CYCLE
    1500      281172 :          IF (inode == 1) last_jatom = 0
    1501             : 
    1502      281172 :          IF (my_minimum_image) THEN
    1503           0 :             IF (ABS(rab(1)) > Lxo2 .OR. ABS(rab(2)) > Lyo2 .OR. ABS(rab(3)) > Lzo2) CYCLE
    1504             :          END IF
    1505             : 
    1506     1124688 :          rb = rab + ra
    1507             : 
    1508      281172 :          IF (jatom /= last_jatom) THEN
    1509             :             new_atom_b = .TRUE.
    1510             :             last_jatom = jatom
    1511             :          ELSE
    1512             :             new_atom_b = .FALSE.
    1513             :          END IF
    1514             : 
    1515             :          IF (new_atom_b) THEN
    1516       17958 :             irow = iatom
    1517       17958 :             icol = jatom
    1518       17958 :             alpha_der = 2.0_dp
    1519             : 
    1520      179580 :             DO imom = 1, M_dim
    1521      161622 :                NULLIFY (op_dip(imom)%block)
    1522             :                CALL dbcsr_get_block_p(matrix=op(imom)%matrix, &
    1523             :                                       row=irow, col=icol, &
    1524             :                                       block=op_dip(imom)%block, &
    1525      161622 :                                       found=op_found)
    1526      161622 :                CPASSERT(op_found .AND. ASSOCIATED(op_dip(imom)%block))
    1527      826068 :                DO idir = 1, 3
    1528      484866 :                   NULLIFY (op_dip_der(imom, idir)%block)
    1529             :                   CALL dbcsr_get_block_p(matrix=op_der(imom, idir)%matrix, &
    1530             :                                          row=irow, col=icol, &
    1531             :                                          block=op_dip_der(imom, idir)%block, &
    1532      484866 :                                          found=op_der_found)
    1533      646488 :                   CPASSERT(op_der_found .AND. ASSOCIATED(op_dip_der(imom, idir)%block))
    1534             :                END DO ! idir
    1535             :             END DO ! imom
    1536             :          END IF ! new_atom_b
    1537             : 
    1538      281172 :          rab2 = rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3)
    1539      281172 :          dab = SQRT(rab2)
    1540             : 
    1541      936090 :          DO iset = 1, nseta
    1542             : 
    1543      651168 :             ncoa = npgfa(iset)*ncoset(la_max(iset))
    1544      651168 :             sgfa = first_sgfa(1, iset)
    1545             : 
    1546     2511669 :             DO jset = 1, nsetb
    1547             : 
    1548     1579308 :                ncob = npgfb(jset)*ncoset(lb_max(jset))
    1549     1579308 :                sgfb = first_sgfb(1, jset)
    1550             : 
    1551     2230476 :                IF (set_radius_a(iset) + set_radius_b(jset) >= dab) THEN
    1552             : 
    1553      596982 :                   rac = pbc(rc, ra, cell)
    1554     2387928 :                   rbc = rac + rab
    1555             : !                  rac = pbc(rc,ra,cell)
    1556             : !                  rbc = pbc(rc,rb,cell)
    1557             : 
    1558             :                   ALLOCATE (mab_tmp(npgfa(iset)*ncoset(la_max(iset) + 1), &
    1559     2958078 :                                     npgfb(jset)*ncoset(lb_max(jset) + 1), ncoset(order) - 1))
    1560             : 
    1561      596982 :                   lda_min = MAX(0, la_min(iset) - 1)
    1562      596982 :                   ldb_min = MAX(0, lb_min(jset) - 1)
    1563             : !            *** Calculate the primitive overlap integrals ***
    1564             :                   CALL moment(la_max(iset) + 1, npgfa(iset), zeta(:, iset), &
    1565             :                               rpgfa(:, iset), lda_min, &
    1566             :                               lb_max(jset) + 1, npgfb(jset), zetb(:, jset), rpgfb(:, jset), &
    1567      596982 :                               order, rac, rbc, mab_tmp)
    1568             : 
    1569             : !            *** Calculate the derivatives
    1570             :                   CALL diff_momop(la_max(iset), npgfa(iset), zeta(:, iset), &
    1571             :                                   rpgfa(:, iset), la_min(iset), lb_max(jset), npgfb(jset), &
    1572             :                                   zetb(:, jset), rpgfb(:, jset), lb_min(jset), order, rac, rbc, &
    1573      596982 :                                   difmab, mab_ext=mab_tmp)
    1574             : 
    1575             : ! Contract and copy in the sparse matrix
    1576   874316388 :                   mab = 0.0_dp
    1577     5969820 :                   DO imom = 1, M_dim
    1578     5372838 :                      na = 0
    1579     5372838 :                      nda = 0
    1580    17098830 :                      DO ipgf = 1, npgfa(iset)
    1581    11725992 :                         nb = 0
    1582    11725992 :                         ndb = 0
    1583    42864039 :                         DO jpgf = 1, npgfb(jset)
    1584   127844055 :                            DO j = 1, ncoset(lb_max(jset))
    1585   486284148 :                               DO i = 1, ncoset(la_max(iset))
    1586   455146101 :                                  mab(i + na, j + nb, imom) = mab_tmp(i + nda, j + ndb, imom)
    1587             :                               END DO ! i
    1588             :                            END DO ! j
    1589    31138047 :                            nb = nb + ncoset(lb_max(jset))
    1590    42864039 :                            ndb = ndb + ncoset(lb_max(jset) + 1)
    1591             :                         END DO ! jpgf
    1592    11725992 :                         na = na + ncoset(la_max(iset))
    1593    17098830 :                         nda = nda + ncoset(la_max(iset) + 1)
    1594             :                      END DO ! ipgf
    1595             : 
    1596             : !                 *** Contraction ***
    1597             :                      CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
    1598             :                                 1.0_dp, mab(1, 1, imom), ldab, sphi_b(1, sgfb), ldsb, &
    1599     5372838 :                                 0.0_dp, work(1, 1), ldwork)
    1600             :                      CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
    1601             :                                 1.0_dp, sphi_a(1, sgfa), ldsa, &
    1602             :                                 work(1, 1), ldwork, &
    1603             :                                 1.0_dp, op_dip(imom)%block(sgfa, sgfb), &
    1604     5372838 :                                 SIZE(op_dip(imom)%block, 1))
    1605             : 
    1606     5372838 :                      alpha = -1.0_dp !-alpha_der
    1607    22088334 :                      DO idir = 1, 3
    1608             :                         CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
    1609             :                                    alpha, difmab(1, 1, imom, idir), ldab, sphi_b(1, sgfb), ldsb, &
    1610    16118514 :                                    0.0_dp, work(1, 1), ldwork)
    1611             :                         CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
    1612             :                                    1.0_dp, sphi_a(1, sgfa), ldsa, &
    1613             :                                    work(1, 1), ldwork, &
    1614             :                                    1.0_dp, op_dip_der(imom, idir)%block(sgfa, sgfb), &
    1615    21491352 :                                    SIZE(op_dip_der(imom, idir)%block, 1))
    1616             : 
    1617             :                      END DO ! idir
    1618             : 
    1619             :                   END DO ! imom
    1620             : 
    1621      596982 :                   DEALLOCATE (mab_tmp)
    1622             :                END IF !  >= dab
    1623             : 
    1624             :             END DO ! jset
    1625             : 
    1626             :          END DO ! iset
    1627             : 
    1628             :       END DO
    1629        3750 :       CALL neighbor_list_iterator_release(nl_iterator)
    1630             : 
    1631       15000 :       DO i = 1, 3
    1632       15000 :          NULLIFY (op_dip(i)%block)
    1633             :       END DO
    1634        3750 :       DEALLOCATE (op_dip, op_dip_der)
    1635             : 
    1636        3750 :       DEALLOCATE (mab, difmab, work, basis_set_list)
    1637             : 
    1638        3750 :       CALL timestop(handle)
    1639             : 
    1640        7500 :    END SUBROUTINE rRc_xyz_der_ao
    1641             : 
    1642             : END MODULE qs_operators_ao
    1643             : 

Generated by: LCOV version 1.15