LCOV - code coverage report
Current view: top level - src - qs_linres_op.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:b279b6b) Lines: 445 450 98.9 %
Date: 2024-04-24 07:13:09 Functions: 12 12 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             : !> \brief Calculate the operators p rxp and D needed in the optimization
      10             : !>      of the different contribution of the firs order response orbitals
      11             : !>      in a epr calculation
      12             : !> \note
      13             : !>      The interactions are considered only within the minimum image convention
      14             : !> \par History
      15             : !>       created 07-2005 [MI]
      16             : !> \author MI
      17             : ! **************************************************************************************************
      18             : MODULE qs_linres_op
      19             :    USE cell_types,                      ONLY: cell_type,&
      20             :                                               pbc
      21             :    USE cp_array_utils,                  ONLY: cp_2d_i_p_type,&
      22             :                                               cp_2d_r_p_type
      23             :    USE cp_cfm_basic_linalg,             ONLY: cp_cfm_solve
      24             :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      25             :                                               cp_cfm_get_info,&
      26             :                                               cp_cfm_release,&
      27             :                                               cp_cfm_set_all,&
      28             :                                               cp_cfm_type
      29             :    USE cp_control_types,                ONLY: dft_control_type
      30             :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      31             :    USE cp_dbcsr_operations,             ONLY: cp_dbcsr_sm_fm_multiply,&
      32             :                                               dbcsr_allocate_matrix_set,&
      33             :                                               dbcsr_deallocate_matrix_set
      34             :    USE cp_fm_basic_linalg,              ONLY: cp_fm_scale_and_add
      35             :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      36             :                                               cp_fm_struct_release,&
      37             :                                               cp_fm_struct_type
      38             :    USE cp_fm_types,                     ONLY: &
      39             :         cp_fm_create, cp_fm_get_info, cp_fm_get_submatrix, cp_fm_indxl2g, cp_fm_release, &
      40             :         cp_fm_set_all, cp_fm_set_submatrix, cp_fm_to_fm, cp_fm_type
      41             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      42             :                                               cp_logger_type,&
      43             :                                               cp_to_string
      44             :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      45             :                                               cp_print_key_unit_nr
      46             :    USE dbcsr_api,                       ONLY: &
      47             :         dbcsr_checksum, dbcsr_convert_offsets_to_sizes, dbcsr_copy, dbcsr_create, &
      48             :         dbcsr_deallocate_matrix, dbcsr_distribution_type, dbcsr_get_block_p, &
      49             :         dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, dbcsr_iterator_start, &
      50             :         dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_p_type, dbcsr_set, dbcsr_type, &
      51             :         dbcsr_type_antisymmetric, dbcsr_type_no_symmetry
      52             :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      53             :                                               section_vals_type
      54             :    USE kinds,                           ONLY: dp
      55             :    USE mathconstants,                   ONLY: twopi
      56             :    USE message_passing,                 ONLY: mp_para_env_type
      57             :    USE orbital_pointers,                ONLY: coset
      58             :    USE parallel_gemm_api,               ONLY: parallel_gemm
      59             :    USE particle_methods,                ONLY: get_particle_set
      60             :    USE particle_types,                  ONLY: particle_type
      61             :    USE qs_elec_field,                   ONLY: build_efg_matrix
      62             :    USE qs_environment_types,            ONLY: get_qs_env,&
      63             :                                               qs_environment_type
      64             :    USE qs_fermi_contact,                ONLY: build_fermi_contact_matrix
      65             :    USE qs_kind_types,                   ONLY: get_qs_kind_set,&
      66             :                                               qs_kind_type
      67             :    USE qs_linres_types,                 ONLY: current_env_type,&
      68             :                                               get_current_env,&
      69             :                                               get_issc_env,&
      70             :                                               get_polar_env,&
      71             :                                               issc_env_type,&
      72             :                                               linres_control_type,&
      73             :                                               polar_env_type
      74             :    USE qs_mo_types,                     ONLY: get_mo_set,&
      75             :                                               mo_set_type
      76             :    USE qs_moments,                      ONLY: build_berry_moment_matrix,&
      77             :                                               build_local_moment_matrix
      78             :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      79             :    USE qs_operators_ao,                 ONLY: build_ang_mom_matrix,&
      80             :                                               build_lin_mom_matrix,&
      81             :                                               rRc_xyz_ao
      82             :    USE qs_spin_orbit,                   ONLY: build_pso_matrix
      83             : #include "./base/base_uses.f90"
      84             : 
      85             :    IMPLICIT NONE
      86             : 
      87             :    PRIVATE
      88             :    PUBLIC :: current_operators, issc_operators, fac_vecp, ind_m2, set_vecp, set_vecp_rev, &
      89             :              fm_scale_by_pbc_AC, polar_operators
      90             : 
      91             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_linres_op'
      92             : 
      93             : ! **************************************************************************************************
      94             : 
      95             : CONTAINS
      96             : 
      97             : ! **************************************************************************************************
      98             : !> \brief Calculate the first order hamiltonian applied to the ao
      99             : !>      and then apply them to the ground state orbitals,
     100             : !>      the h1_psi1 full matrices are then ready to solve the
     101             : !>      non-homogeneous linear equations that give the psi1
     102             : !>      linear response orbitals.
     103             : !> \param current_env ...
     104             : !> \param qs_env ...
     105             : !> \par History
     106             : !>      07.2005 created [MI]
     107             : !> \author MI
     108             : !> \note
     109             : !>      For the operators rxp and D the h1 depends on the psi0 to which
     110             : !>      is applied, or better the center of charge of the psi0 is
     111             : !>      used to define the position operator
     112             : !>      The centers of the orbitals result form the orbital localization procedure
     113             : !>      that typically uses the berry phase operator to define the Wannier centers.
     114             : ! **************************************************************************************************
     115         174 :    SUBROUTINE current_operators(current_env, qs_env)
     116             : 
     117             :       TYPE(current_env_type)                             :: current_env
     118             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     119             : 
     120             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'current_operators'
     121             : 
     122             :       INTEGER                                            :: handle, iao, icenter, idir, ii, iii, &
     123             :                                                             ispin, istate, j, nao, natom, &
     124             :                                                             nbr_center(2), nmo, nsgf, nspins, &
     125             :                                                             nstates(2), output_unit
     126         348 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: first_sgf, last_sgf
     127         174 :       INTEGER, DIMENSION(:), POINTER                     :: row_blk_sizes
     128             :       REAL(dp)                                           :: chk(3), ck(3), ckdk(3), dk(3)
     129         348 :       REAL(dp), DIMENSION(:, :), POINTER                 :: basisfun_center, vecbuf_c0
     130             :       TYPE(cell_type), POINTER                           :: cell
     131         174 :       TYPE(cp_2d_i_p_type), DIMENSION(:), POINTER        :: center_list
     132         696 :       TYPE(cp_2d_r_p_type), DIMENSION(3)                 :: vecbuf_RmdC0
     133         174 :       TYPE(cp_2d_r_p_type), DIMENSION(:), POINTER        :: centers_set
     134             :       TYPE(cp_fm_struct_type), POINTER                   :: tmp_fm_struct
     135             :       TYPE(cp_fm_type)                                   :: fm_work1
     136         696 :       TYPE(cp_fm_type), DIMENSION(3)                     :: fm_Rmd_mos
     137         174 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: psi0_order
     138         174 :       TYPE(cp_fm_type), DIMENSION(:, :), POINTER         :: p_psi0, rxp_psi0
     139             :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     140             :       TYPE(cp_logger_type), POINTER                      :: logger
     141             :       TYPE(dbcsr_distribution_type), POINTER             :: dbcsr_dist
     142         174 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: op_ao
     143             :       TYPE(dft_control_type), POINTER                    :: dft_control
     144             :       TYPE(linres_control_type), POINTER                 :: linres_control
     145             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     146             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     147         174 :          POINTER                                         :: sab_all, sab_orb
     148         174 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     149         174 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     150             :       TYPE(section_vals_type), POINTER                   :: lr_section
     151             : 
     152         174 :       CALL timeset(routineN, handle)
     153             : 
     154         174 :       NULLIFY (qs_kind_set, cell, dft_control, linres_control, &
     155         174 :                logger, particle_set, lr_section, &
     156         174 :                basisfun_center, centers_set, center_list, p_psi0, &
     157         174 :                rxp_psi0, vecbuf_c0, psi0_order, &
     158         174 :                mo_coeff, op_ao, sab_all)
     159             : 
     160         174 :       logger => cp_get_default_logger()
     161             :       lr_section => section_vals_get_subs_vals(qs_env%input, &
     162         174 :                                                "PROPERTIES%LINRES")
     163             : 
     164             :       output_unit = cp_print_key_unit_nr(logger, lr_section, "PRINT%PROGRAM_RUN_INFO", &
     165         174 :                                          extension=".linresLog")
     166         174 :       IF (output_unit > 0) THEN
     167             :          WRITE (output_unit, FMT="(T2,A,/)") &
     168          87 :             "CURRENT| Calculation of the p and (r-d)xp operators applied to psi0"
     169             :       END IF
     170             : 
     171             :       CALL get_qs_env(qs_env=qs_env, &
     172             :                       qs_kind_set=qs_kind_set, &
     173             :                       cell=cell, &
     174             :                       dft_control=dft_control, &
     175             :                       linres_control=linres_control, &
     176             :                       para_env=para_env, &
     177             :                       particle_set=particle_set, &
     178             :                       sab_all=sab_all, &
     179             :                       sab_orb=sab_orb, &
     180         174 :                       dbcsr_dist=dbcsr_dist)
     181             : 
     182         174 :       nspins = dft_control%nspins
     183             : 
     184             :       CALL get_current_env(current_env=current_env, nao=nao, centers_set=centers_set, &
     185             :                            center_list=center_list, basisfun_center=basisfun_center, &
     186             :                            nbr_center=nbr_center, p_psi0=p_psi0, rxp_psi0=rxp_psi0, &
     187             :                            psi0_order=psi0_order, &
     188         174 :                            nstates=nstates)
     189             : 
     190         522 :       ALLOCATE (vecbuf_c0(1, nao))
     191         696 :       DO idir = 1, 3
     192         522 :          NULLIFY (vecbuf_Rmdc0(idir)%array)
     193        1740 :          ALLOCATE (vecbuf_Rmdc0(idir)%array(1, nao))
     194             :       END DO
     195             : 
     196         174 :       CALL get_qs_kind_set(qs_kind_set=qs_kind_set, nsgf=nsgf)
     197             : 
     198         174 :       natom = SIZE(particle_set, 1)
     199         522 :       ALLOCATE (first_sgf(natom))
     200         522 :       ALLOCATE (last_sgf(natom))
     201             : 
     202             :       CALL get_particle_set(particle_set, qs_kind_set, &
     203             :                             first_sgf=first_sgf, &
     204         174 :                             last_sgf=last_sgf)
     205             : 
     206             :       ! Calculate the (r - dk)xp operator applied to psi0k
     207             :       ! One possible way to go is to use the distributive property of the vector product and calculatr
     208             :       ! (r-c)xp + (c-d)xp
     209             :       ! where c depends on the contracted functions and not on the states
     210             :       ! d is the center of a specific state and a loop over states is needed
     211             :       ! the second term can be added in a second moment as a correction
     212             :       ! notice: (r-c) and p are operators, whereas (c-d) is a multiplicative factor
     213             : 
     214             :       !    !First term: operator matrix elements
     215             :       !    CALL rmc_x_p_xyz_ao(op_rmd_ao,qs_env,minimum_image=.FALSE.)
     216             :       !************************************************************
     217             :       !
     218             :       ! Since many psi0 vector can have the same center, depending on how the center is selected,
     219             :       ! the (r - dk)xp operator matrix is computed Ncenter times,
     220             :       ! where Ncenter is the total number of different centers
     221             :       ! and each time it is multiplied by all the psi0 with center dk to get the rxp_psi0 matrix
     222             : 
     223             :       !
     224             :       ! prepare for allocation
     225         522 :       ALLOCATE (row_blk_sizes(natom))
     226         174 :       CALL dbcsr_convert_offsets_to_sizes(first_sgf, row_blk_sizes, last_sgf)
     227             :       !
     228             :       !
     229         174 :       CALL dbcsr_allocate_matrix_set(op_ao, 3)
     230         174 :       ALLOCATE (op_ao(1)%matrix, op_ao(2)%matrix, op_ao(3)%matrix)
     231             : 
     232             :       CALL dbcsr_create(matrix=op_ao(1)%matrix, &
     233             :                         name="op_ao", &
     234             :                         dist=dbcsr_dist, matrix_type=dbcsr_type_no_symmetry, &
     235             :                         row_blk_size=row_blk_sizes, col_blk_size=row_blk_sizes, &
     236         174 :                         nze=0, mutable_work=.TRUE.)
     237         174 :       CALL cp_dbcsr_alloc_block_from_nbl(op_ao(1)%matrix, sab_all)
     238         174 :       CALL dbcsr_set(op_ao(1)%matrix, 0.0_dp)
     239             : 
     240         522 :       DO idir = 2, 3
     241             :          CALL dbcsr_copy(op_ao(idir)%matrix, op_ao(1)%matrix, &
     242         348 :                          "op_ao"//"-"//TRIM(ADJUSTL(cp_to_string(idir))))
     243         522 :          CALL dbcsr_set(op_ao(idir)%matrix, 0.0_dp)
     244             :       END DO
     245             : 
     246         174 :       chk(:) = 0.0_dp
     247         424 :       DO ispin = 1, nspins
     248         250 :          mo_coeff => psi0_order(ispin)
     249         250 :          nmo = nstates(ispin)
     250         250 :          CALL cp_fm_set_all(p_psi0(ispin, 1), 0.0_dp)
     251         250 :          CALL cp_fm_set_all(p_psi0(ispin, 2), 0.0_dp)
     252         250 :          CALL cp_fm_set_all(p_psi0(ispin, 3), 0.0_dp)
     253        1500 :          DO icenter = 1, nbr_center(ispin)
     254        1250 :             CALL dbcsr_set(op_ao(1)%matrix, 0.0_dp)
     255        1250 :             CALL dbcsr_set(op_ao(2)%matrix, 0.0_dp)
     256        1250 :             CALL dbcsr_set(op_ao(3)%matrix, 0.0_dp)
     257             :             !CALL rmc_x_p_xyz_ao(op_ao,qs_env,minimum_image=.FALSE.,&
     258             :             !     &              wancen=centers_set(ispin)%array(1:3,icenter))
     259             :             !     &
     260        1250 :             CALL build_ang_mom_matrix(qs_env, op_ao, centers_set(ispin)%array(1:3, icenter))
     261             :             !
     262             :             ! accumulate checksums
     263        1250 :             chk(1) = chk(1) + dbcsr_checksum(op_ao(1)%matrix)
     264        1250 :             chk(2) = chk(2) + dbcsr_checksum(op_ao(2)%matrix)
     265        1250 :             chk(3) = chk(3) + dbcsr_checksum(op_ao(3)%matrix)
     266        5250 :             DO idir = 1, 3
     267        3750 :                CALL cp_fm_set_all(rxp_psi0(ispin, idir), 0.0_dp)
     268             :                CALL cp_dbcsr_sm_fm_multiply(op_ao(idir)%matrix, mo_coeff, &
     269             :                                             rxp_psi0(ispin, idir), ncol=nmo, &
     270        3750 :                                             alpha=-1.0_dp)
     271        9794 :                DO j = center_list(ispin)%array(1, icenter), center_list(ispin)%array(1, icenter + 1) - 1
     272        4794 :                   istate = center_list(ispin)%array(2, j)
     273             :                   ! the p_psi0 fm is used as temporary matrix to store the results for the psi0 centered in dk
     274             :                   CALL cp_fm_to_fm(rxp_psi0(ispin, idir), &
     275        8544 :                                    p_psi0(ispin, idir), 1, istate, istate)
     276             :                END DO
     277             :             END DO
     278             :          END DO
     279         250 :          CALL cp_fm_to_fm(p_psi0(ispin, 1), rxp_psi0(ispin, 1))
     280         250 :          CALL cp_fm_to_fm(p_psi0(ispin, 2), rxp_psi0(ispin, 2))
     281         424 :          CALL cp_fm_to_fm(p_psi0(ispin, 3), rxp_psi0(ispin, 3))
     282             :       END DO
     283             :       !
     284         174 :       CALL dbcsr_deallocate_matrix_set(op_ao)
     285             :       !
     286             :       ! print checksums
     287         174 :       IF (output_unit > 0) THEN
     288          87 :          WRITE (output_unit, '(T2,A,E23.16)') 'CURRENT| current_operators: CheckSum L_x =', chk(1)
     289          87 :          WRITE (output_unit, '(T2,A,E23.16)') 'CURRENT| current_operators: CheckSum L_y =', chk(2)
     290          87 :          WRITE (output_unit, '(T2,A,E23.16)') 'CURRENT| current_operators: CheckSum L_z =', chk(3)
     291             :       END IF
     292             :       !
     293             :       ! Calculate the px py pz operators
     294         174 :       CALL dbcsr_allocate_matrix_set(op_ao, 3)
     295         174 :       ALLOCATE (op_ao(1)%matrix, op_ao(2)%matrix, op_ao(3)%matrix)
     296             : 
     297             :       CALL dbcsr_create(matrix=op_ao(1)%matrix, &
     298             :                         name="op_ao", &
     299             :                         dist=dbcsr_dist, matrix_type=dbcsr_type_antisymmetric, &
     300             :                         row_blk_size=row_blk_sizes, col_blk_size=row_blk_sizes, &
     301         174 :                         nze=0, mutable_work=.TRUE.)
     302         174 :       CALL cp_dbcsr_alloc_block_from_nbl(op_ao(1)%matrix, sab_orb)
     303         174 :       CALL dbcsr_set(op_ao(1)%matrix, 0.0_dp)
     304             : 
     305         522 :       DO idir = 2, 3
     306             :          CALL dbcsr_copy(op_ao(idir)%matrix, op_ao(1)%matrix, &
     307         348 :                          "op_ao"//"-"//TRIM(ADJUSTL(cp_to_string(idir))))
     308         522 :          CALL dbcsr_set(op_ao(idir)%matrix, 0.0_dp)
     309             :       END DO
     310             :       !
     311         174 :       CALL build_lin_mom_matrix(qs_env, op_ao)
     312             :       !CALL p_xyz_ao(op_ao,qs_env,minimum_image=.FALSE.)
     313             :       !
     314             :       ! print checksums
     315         174 :       chk(1) = dbcsr_checksum(op_ao(1)%matrix)
     316         174 :       chk(2) = dbcsr_checksum(op_ao(2)%matrix)
     317         174 :       chk(3) = dbcsr_checksum(op_ao(3)%matrix)
     318         174 :       IF (output_unit > 0) THEN
     319          87 :          WRITE (output_unit, '(T2,A,E23.16)') 'CURRENT| current_operators: CheckSum P_x =', chk(1)
     320          87 :          WRITE (output_unit, '(T2,A,E23.16)') 'CURRENT| current_operators: CheckSum P_y =', chk(2)
     321          87 :          WRITE (output_unit, '(T2,A,E23.16)') 'CURRENT| current_operators: CheckSum P_z =', chk(3)
     322             :       END IF
     323             :       ! Apply the p operator to the psi0
     324         696 :       DO idir = 1, 3
     325        1446 :          DO ispin = 1, nspins
     326         750 :             mo_coeff => psi0_order(ispin)
     327         750 :             nmo = nstates(ispin)
     328         750 :             CALL cp_fm_set_all(p_psi0(ispin, idir), 0.0_dp)
     329             :             CALL cp_dbcsr_sm_fm_multiply(op_ao(idir)%matrix, mo_coeff, &
     330             :                                          p_psi0(ispin, idir), ncol=nmo, &
     331        1272 :                                          alpha=-1.0_dp)
     332             :          END DO
     333             :       END DO
     334             :       !
     335         174 :       CALL dbcsr_deallocate_matrix_set(op_ao)
     336             :       !
     337             :       CALL cp_print_key_finished_output(output_unit, logger, lr_section, &
     338         174 :                                         "PRINT%PROGRAM_RUN_INFO")
     339             : 
     340             : ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     341             :       !  This part is not necessary with the present implementation
     342             :       !  the angular momentum operator is computed directly for each dk independently
     343             :       !  and multiplied by the proper psi0 (i.e. those centered in dk)
     344             :       !  If Wannier centers are used, and no grouping of states with close centers is applied
     345             :       !  the (r-dk)xp operator is computed Nstate times and each time applied to only one vector psi0
     346             :       !
     347             :       ! Apply the (r-c)xp operator to the psi0
     348             :       !DO ispin = 1,nspins
     349             :       !  CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, nmo=nmo, homo=homo)
     350             :       !  DO idir = 1,3
     351             :       !     CALL cp_fm_set_all(rxp_psi0(ispin,idir),0.0_dp)
     352             :       !     CALL cp_sm_fm_multiply(op_rmd_ao(idir)%matrix,mo_coeff,&
     353             :       !            rxp_psi0(ispin,idir),ncol=nmo,alpha=-1.0_dp)
     354             :       !  END DO
     355             :       !END DO
     356             : 
     357             :       !Calculate the second term of the operator state by state
     358             :       !!!! what follows is a way to avoid calculating the L matrix for each centers.
     359             :       !!!! not tested
     360             :       IF (.FALSE.) THEN
     361             :          DO ispin = 1, nspins
     362             :             !   Allocate full matrices as working storage in the calculation
     363             :             !   of the rxp operator matrix. 3 matrices for the 3 Cartesian direction
     364             :             !   plus one to apply the momentum oprator to the modified mos fm
     365             :             mo_coeff => psi0_order(ispin)
     366             :             nmo = nstates(ispin)
     367             :             NULLIFY (tmp_fm_struct)
     368             :             CALL cp_fm_struct_create(tmp_fm_struct, nrow_global=nao, &
     369             :                                      ncol_global=nmo, para_env=para_env, &
     370             :                                      context=mo_coeff%matrix_struct%context)
     371             :             DO idir = 1, 3
     372             :                CALL cp_fm_create(fm_Rmd_mos(idir), tmp_fm_struct)
     373             :             END DO
     374             :             CALL cp_fm_create(fm_work1, tmp_fm_struct)
     375             :             CALL cp_fm_struct_release(tmp_fm_struct)
     376             : 
     377             :             ! This part should be done better, using the full matrix distribution
     378             :             DO istate = 1, nmo
     379             :                CALL cp_fm_get_submatrix(psi0_order(ispin), vecbuf_c0, 1, istate, nao, 1, &
     380             :                                         transpose=.TRUE.)
     381             :                !center of the localized psi0 state istate
     382             :                dk(1:3) = centers_set(ispin)%array(1:3, istate)
     383             :                DO idir = 1, 3
     384             :                   !  This loop should be distributed over the processors
     385             :                   DO iao = 1, nao
     386             :                      ck(1:3) = basisfun_center(1:3, iao)
     387             :                      ckdk = pbc(dk, ck, cell)
     388             :                      vecbuf_Rmdc0(idir)%array(1, iao) = vecbuf_c0(1, iao)*ckdk(idir)
     389             :                   END DO ! iao
     390             :                   CALL cp_fm_set_submatrix(fm_Rmd_mos(idir), vecbuf_Rmdc0(idir)%array, &
     391             :                                            1, istate, nao, 1, transpose=.TRUE.)
     392             :                END DO ! idir
     393             :             END DO ! istate
     394             : 
     395             :             DO idir = 1, 3
     396             :                CALL set_vecp(idir, ii, iii)
     397             : 
     398             :                !Add the second term to the idir component
     399             :                CALL cp_fm_set_all(fm_work1, 0.0_dp)
     400             :                CALL cp_dbcsr_sm_fm_multiply(op_ao(iii)%matrix, fm_Rmd_mos(ii), &
     401             :                                             fm_work1, ncol=nmo, alpha=-1.0_dp)
     402             :                CALL cp_fm_scale_and_add(1.0_dp, rxp_psi0(ispin, idir), &
     403             :                                         1.0_dp, fm_work1)
     404             : 
     405             :                CALL cp_fm_set_all(fm_work1, 0.0_dp)
     406             :                CALL cp_dbcsr_sm_fm_multiply(op_ao(ii)%matrix, fm_Rmd_mos(iii), &
     407             :                                             fm_work1, ncol=nmo, alpha=-1.0_dp)
     408             :                CALL cp_fm_scale_and_add(1.0_dp, rxp_psi0(ispin, idir), &
     409             :                                         -1.0_dp, fm_work1)
     410             : 
     411             :             END DO ! idir
     412             : 
     413             :             DO idir = 1, 3
     414             :                CALL cp_fm_release(fm_Rmd_mos(idir))
     415             :             END DO
     416             :             CALL cp_fm_release(fm_work1)
     417             : 
     418             :          END DO ! ispin
     419             :       END IF
     420             : 
     421         174 :       DEALLOCATE (row_blk_sizes)
     422             : 
     423         174 :       DEALLOCATE (first_sgf, last_sgf)
     424             : 
     425         174 :       DEALLOCATE (vecbuf_c0)
     426         696 :       DO idir = 1, 3
     427         696 :          DEALLOCATE (vecbuf_Rmdc0(idir)%array)
     428             :       END DO
     429             : 
     430         174 :       CALL timestop(handle)
     431             : 
     432         696 :    END SUBROUTINE current_operators
     433             : 
     434             : ! **************************************************************************************************
     435             : !> \brief ...
     436             : !> \param issc_env ...
     437             : !> \param qs_env ...
     438             : !> \param iatom ...
     439             : ! **************************************************************************************************
     440          44 :    SUBROUTINE issc_operators(issc_env, qs_env, iatom)
     441             : 
     442             :       TYPE(issc_env_type)                                :: issc_env
     443             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     444             :       INTEGER, INTENT(IN)                                :: iatom
     445             : 
     446             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'issc_operators'
     447             : 
     448             :       INTEGER                                            :: handle, idir, ispin, nmo, nspins, &
     449             :                                                             output_unit
     450             :       LOGICAL                                            :: do_dso, do_fc, do_pso, do_sd
     451             :       REAL(dp)                                           :: chk(20), r_i(3)
     452             :       TYPE(cell_type), POINTER                           :: cell
     453          44 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: fc_psi0
     454          44 :       TYPE(cp_fm_type), DIMENSION(:, :), POINTER         :: dso_psi0, efg_psi0, pso_psi0
     455             :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     456             :       TYPE(cp_logger_type), POINTER                      :: logger
     457          44 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_dso, matrix_efg, matrix_fc, &
     458          44 :                                                             matrix_pso
     459             :       TYPE(dft_control_type), POINTER                    :: dft_control
     460             :       TYPE(linres_control_type), POINTER                 :: linres_control
     461          44 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     462             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     463          44 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     464          44 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     465             :       TYPE(section_vals_type), POINTER                   :: lr_section
     466             : 
     467          44 :       CALL timeset(routineN, handle)
     468             : 
     469          44 :       NULLIFY (matrix_fc, matrix_pso, matrix_efg)
     470          44 :       NULLIFY (efg_psi0, pso_psi0, fc_psi0)
     471             : 
     472          44 :       logger => cp_get_default_logger()
     473             :       lr_section => section_vals_get_subs_vals(qs_env%input, &
     474          44 :                                                "PROPERTIES%LINRES")
     475             : 
     476             :       output_unit = cp_print_key_unit_nr(logger, lr_section, "PRINT%PROGRAM_RUN_INFO", &
     477          44 :                                          extension=".linresLog")
     478             : 
     479             :       CALL get_qs_env(qs_env=qs_env, &
     480             :                       qs_kind_set=qs_kind_set, &
     481             :                       cell=cell, &
     482             :                       dft_control=dft_control, &
     483             :                       linres_control=linres_control, &
     484             :                       para_env=para_env, &
     485             :                       mos=mos, &
     486          44 :                       particle_set=particle_set)
     487             : 
     488          44 :       nspins = dft_control%nspins
     489             : 
     490             :       CALL get_issc_env(issc_env=issc_env, &
     491             :                         matrix_efg=matrix_efg, & !this is used only here alloc/dealloc here???
     492             :                         matrix_pso=matrix_pso, & !this is used only here alloc/dealloc here???
     493             :                         matrix_fc=matrix_fc, & !this is used only here alloc/dealloc here???
     494             :                         matrix_dso=matrix_dso, & !this is used only here alloc/dealloc here???
     495             :                         efg_psi0=efg_psi0, &
     496             :                         pso_psi0=pso_psi0, &
     497             :                         dso_psi0=dso_psi0, &
     498             :                         fc_psi0=fc_psi0, &
     499             :                         do_fc=do_fc, &
     500             :                         do_sd=do_sd, &
     501             :                         do_pso=do_pso, &
     502          44 :                         do_dso=do_dso)
     503             :       !
     504             :       !
     505         176 :       r_i = particle_set(iatom)%r !pbc(particle_set(iatom)%r,cell)
     506             :       !write(*,*) 'issc_operators iatom=',iatom,' r_i=',r_i
     507          44 :       chk = 0.0_dp
     508             :       !
     509             :       !
     510             :       !
     511             :       ! Fermi contact integral
     512             :       !IF(do_fc) THEN
     513             :       IF (.TRUE.) THEN ! for the moment we build it (regs)
     514          44 :          CALL dbcsr_set(matrix_fc(1)%matrix, 0.0_dp)
     515          44 :          CALL build_fermi_contact_matrix(qs_env, matrix_fc, r_i)
     516             : 
     517          44 :          chk(1) = dbcsr_checksum(matrix_fc(1)%matrix)
     518             : 
     519          44 :          IF (output_unit > 0) THEN
     520          22 :             WRITE (output_unit, '(T2,A,E23.16)') 'ISSC| fermi_contact: CheckSum =', chk(1)
     521             :          END IF
     522             :       END IF
     523             :       !
     524             :       ! spin-orbit integral
     525             :       !IF(do_pso) THEN
     526             :       IF (.TRUE.) THEN ! for the moment we build it (regs)
     527          44 :          CALL dbcsr_set(matrix_pso(1)%matrix, 0.0_dp)
     528          44 :          CALL dbcsr_set(matrix_pso(2)%matrix, 0.0_dp)
     529          44 :          CALL dbcsr_set(matrix_pso(3)%matrix, 0.0_dp)
     530          44 :          CALL build_pso_matrix(qs_env, matrix_pso, r_i)
     531             : 
     532          44 :          chk(2) = dbcsr_checksum(matrix_pso(1)%matrix)
     533          44 :          chk(3) = dbcsr_checksum(matrix_pso(2)%matrix)
     534          44 :          chk(4) = dbcsr_checksum(matrix_pso(3)%matrix)
     535             : 
     536          44 :          IF (output_unit > 0) THEN
     537          22 :             WRITE (output_unit, '(T2,A,E23.16)') 'ISSC| pso_x: CheckSum =', chk(2)
     538          22 :             WRITE (output_unit, '(T2,A,E23.16)') 'ISSC| pso_y: CheckSum =', chk(3)
     539          22 :             WRITE (output_unit, '(T2,A,E23.16)') 'ISSC| pso_z: CheckSum =', chk(4)
     540             :          END IF
     541             :       END IF
     542             :       !
     543             :       ! electric field integral
     544             :       !IF(do_sd) THEN
     545             :       IF (.TRUE.) THEN ! for the moment we build it (regs)
     546          44 :          CALL dbcsr_set(matrix_efg(1)%matrix, 0.0_dp)
     547          44 :          CALL dbcsr_set(matrix_efg(2)%matrix, 0.0_dp)
     548          44 :          CALL dbcsr_set(matrix_efg(3)%matrix, 0.0_dp)
     549          44 :          CALL dbcsr_set(matrix_efg(4)%matrix, 0.0_dp)
     550          44 :          CALL dbcsr_set(matrix_efg(5)%matrix, 0.0_dp)
     551          44 :          CALL dbcsr_set(matrix_efg(6)%matrix, 0.0_dp)
     552          44 :          CALL build_efg_matrix(qs_env, matrix_efg, r_i)
     553             : 
     554          44 :          chk(5) = dbcsr_checksum(matrix_efg(1)%matrix)
     555          44 :          chk(6) = dbcsr_checksum(matrix_efg(2)%matrix)
     556          44 :          chk(7) = dbcsr_checksum(matrix_efg(3)%matrix)
     557          44 :          chk(8) = dbcsr_checksum(matrix_efg(4)%matrix)
     558          44 :          chk(9) = dbcsr_checksum(matrix_efg(5)%matrix)
     559          44 :          chk(10) = dbcsr_checksum(matrix_efg(6)%matrix)
     560             : 
     561          44 :          IF (output_unit > 0) THEN
     562          22 :             WRITE (output_unit, '(T2,A,E23.16)') 'ISSC| efg (3xx-rr)/3: CheckSum =', chk(5)
     563          22 :             WRITE (output_unit, '(T2,A,E23.16)') 'ISSC| efg (3yy-rr)/3: CheckSum =', chk(6)
     564          22 :             WRITE (output_unit, '(T2,A,E23.16)') 'ISSC| efg (3zz-rr)/3: CheckSum =', chk(7)
     565          22 :             WRITE (output_unit, '(T2,A,E23.16)') 'ISSC| efg xy: CheckSum =', chk(8)
     566          22 :             WRITE (output_unit, '(T2,A,E23.16)') 'ISSC| efg xz: CheckSum =', chk(9)
     567          22 :             WRITE (output_unit, '(T2,A,E23.16)') 'ISSC| efg yz: CheckSum =', chk(10)
     568             :          END IF
     569             :       END IF
     570             :       !
     571             :       !
     572          44 :       IF (output_unit > 0) THEN
     573         242 :          WRITE (output_unit, '(T2,A,E23.16)') 'ISSC| all operator: CheckSum =', SUM(chk(1:10))
     574             :       END IF
     575             :       !
     576             :       !>>> debugging only  here we build the dipole matrix... debugging the kernel...
     577          44 :       IF (do_dso) THEN
     578           2 :          CALL dbcsr_set(matrix_dso(1)%matrix, 0.0_dp)
     579           2 :          CALL dbcsr_set(matrix_dso(2)%matrix, 0.0_dp)
     580           2 :          CALL dbcsr_set(matrix_dso(3)%matrix, 0.0_dp)
     581           2 :          CALL rRc_xyz_ao(matrix_dso, qs_env, (/0.0_dp, 0.0_dp, 0.0_dp/), 1)
     582             :       END IF
     583             :       !
     584             :       ! multiply by the mos
     585          92 :       DO ispin = 1, nspins
     586             :          !
     587          48 :          CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff)
     588          48 :          CALL cp_fm_get_info(mo_coeff, ncol_global=nmo)
     589             :          !
     590             :          ! EFG
     591          48 :          IF (do_sd) THEN
     592           0 :             DO idir = 1, 6
     593             :                CALL cp_dbcsr_sm_fm_multiply(matrix_efg(idir)%matrix, mo_coeff, &
     594             :                                             efg_psi0(ispin, idir), ncol=nmo, &
     595           0 :                                             alpha=1.0_dp)
     596             :             END DO
     597             :          END IF
     598             :          !
     599             :          ! PSO
     600          48 :          IF (do_pso) THEN
     601         152 :             DO idir = 1, 3
     602             :                CALL cp_dbcsr_sm_fm_multiply(matrix_pso(idir)%matrix, mo_coeff, &
     603             :                                             pso_psi0(ispin, idir), ncol=nmo, &
     604         152 :                                             alpha=-1.0_dp)
     605             :             END DO
     606             :          END IF
     607             :          !
     608             :          ! FC
     609          48 :          IF (do_fc) THEN
     610             :             CALL cp_dbcsr_sm_fm_multiply(matrix_fc(1)%matrix, mo_coeff, &
     611             :                                          fc_psi0(ispin), ncol=nmo, &
     612           0 :                                          alpha=1.0_dp)
     613             :          END IF
     614             :          !
     615             :          !>>> for debugging only
     616         140 :          IF (do_dso) THEN
     617           8 :             DO idir = 1, 3
     618             :                CALL cp_dbcsr_sm_fm_multiply(matrix_dso(idir)%matrix, mo_coeff, &
     619             :                                             dso_psi0(ispin, idir), ncol=nmo, &
     620           8 :                                             alpha=-1.0_dp)
     621             :             END DO
     622             :          END IF
     623             :          !<<< for debugging only
     624             :       END DO
     625             : 
     626             :       CALL cp_print_key_finished_output(output_unit, logger, lr_section, &
     627          44 :                                         "PRINT%PROGRAM_RUN_INFO")
     628             : 
     629          44 :       CALL timestop(handle)
     630             : 
     631          44 :    END SUBROUTINE issc_operators
     632             : 
     633             : ! **************************************************************************************************
     634             : !> \brief Calculate the dipole operator in the AO basis and its derivative wrt to MOs
     635             : !>
     636             : !> \param qs_env ...
     637             : ! **************************************************************************************************
     638         108 :    SUBROUTINE polar_operators(qs_env)
     639             : 
     640             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     641             : 
     642             :       LOGICAL                                            :: do_periodic
     643             :       TYPE(dft_control_type), POINTER                    :: dft_control
     644             :       TYPE(polar_env_type), POINTER                      :: polar_env
     645             : 
     646         108 :       CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, polar_env=polar_env)
     647         108 :       CALL get_polar_env(polar_env=polar_env, do_periodic=do_periodic)
     648         108 :       IF (dft_control%qs_control%dftb .OR. dft_control%qs_control%xtb) THEN
     649           8 :          IF (do_periodic) THEN
     650           4 :             CALL polar_tb_operators_berry(qs_env)
     651             :          ELSE
     652           4 :             CALL polar_tb_operators_local(qs_env)
     653             :          END IF
     654             :       ELSE
     655         100 :          IF (do_periodic) THEN
     656          14 :             CALL polar_operators_berry(qs_env)
     657             :          ELSE
     658          86 :             CALL polar_operators_local(qs_env)
     659             :          END IF
     660             :       END IF
     661             : 
     662         108 :    END SUBROUTINE polar_operators
     663             : 
     664             : ! **************************************************************************************************
     665             : !> \brief Calculate the Berry phase operator in the AO basis and
     666             : !>         then the derivative of the Berry phase operator with respect to
     667             : !>         the ground state wave function (see paper Putrino et al., JCP, 13, 7102) for the AOs;
     668             : !>        afterwards multiply with the ground state MO coefficients
     669             : !>
     670             : !> \param qs_env ...
     671             : !> \par History
     672             : !>      01.2013 created [SL]
     673             : !>      06.2018 polar_env integrated into qs_env (MK)
     674             : !> \author SL
     675             : ! **************************************************************************************************
     676             : 
     677          14 :    SUBROUTINE polar_operators_berry(qs_env)
     678             : 
     679             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     680             : 
     681             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'polar_operators_berry'
     682             :       COMPLEX(KIND=dp), PARAMETER                        :: one = (1.0_dp, 0.0_dp), &
     683             :                                                             zero = (0.0_dp, 0.0_dp)
     684             : 
     685             :       COMPLEX(DP)                                        :: zdet, zdeta
     686             :       INTEGER                                            :: handle, i, idim, ispin, nao, nmo, &
     687             :                                                             nspins, tmp_dim, z
     688             :       LOGICAL                                            :: do_raman
     689             :       REAL(dp)                                           :: kvec(3), maxocc
     690             :       TYPE(cell_type), POINTER                           :: cell
     691          14 :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:)       :: eigrmat
     692          14 :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:, :)    :: inv_mat
     693             :       TYPE(cp_fm_struct_type), POINTER                   :: tmp_fm_struct
     694          14 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: op_fm_set, opvec
     695          14 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :, :)  :: inv_work
     696          14 :       TYPE(cp_fm_type), DIMENSION(:, :), POINTER         :: dBerry_psi0
     697             :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     698          14 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
     699             :       TYPE(dbcsr_type), POINTER                          :: cosmat, sinmat
     700             :       TYPE(dft_control_type), POINTER                    :: dft_control
     701          14 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     702             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     703             :       TYPE(polar_env_type), POINTER                      :: polar_env
     704             : 
     705          14 :       CALL timeset(routineN, handle)
     706             : 
     707          14 :       NULLIFY (dBerry_psi0, sinmat, cosmat)
     708          14 :       NULLIFY (polar_env)
     709             : 
     710          14 :       NULLIFY (cell, dft_control, mos, matrix_s)
     711             :       CALL get_qs_env(qs_env=qs_env, &
     712             :                       cell=cell, &
     713             :                       dft_control=dft_control, &
     714             :                       para_env=para_env, &
     715             :                       polar_env=polar_env, &
     716             :                       mos=mos, &
     717          14 :                       matrix_s=matrix_s)
     718             : 
     719          14 :       nspins = dft_control%nspins
     720             : 
     721             :       CALL get_polar_env(polar_env=polar_env, &
     722             :                          do_raman=do_raman, &
     723          14 :                          dBerry_psi0=dBerry_psi0)
     724             :       !SL calculate dipole berry phase
     725          14 :       IF (do_raman) THEN
     726             : 
     727          56 :          DO i = 1, 3
     728          98 :             DO ispin = 1, nspins
     729          84 :                CALL cp_fm_set_all(dBerry_psi0(i, ispin), 0.0_dp)
     730             :             END DO
     731             :          END DO
     732             : 
     733             :          ! initialize all work matrices needed
     734          84 :          ALLOCATE (opvec(2, dft_control%nspins))
     735          84 :          ALLOCATE (op_fm_set(2, dft_control%nspins))
     736          56 :          ALLOCATE (eigrmat(dft_control%nspins))
     737          98 :          ALLOCATE (inv_mat(3, dft_control%nspins))
     738         182 :          ALLOCATE (inv_work(2, 3, dft_control%nspins))
     739             : 
     740             :          ! A bit to allocate for the wavefunction
     741          28 :          DO ispin = 1, dft_control%nspins
     742          14 :             NULLIFY (tmp_fm_struct, mo_coeff)
     743          14 :             CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, nao=nao, nmo=nmo)
     744             :             CALL cp_fm_struct_create(tmp_fm_struct, nrow_global=nmo, &
     745          14 :                                      ncol_global=nmo, para_env=para_env, context=mo_coeff%matrix_struct%context)
     746          42 :             DO i = 1, SIZE(op_fm_set, 1)
     747          28 :                CALL cp_fm_create(opvec(i, ispin), mo_coeff%matrix_struct)
     748          42 :                CALL cp_fm_create(op_fm_set(i, ispin), tmp_fm_struct)
     749             :             END DO
     750          14 :             CALL cp_cfm_create(eigrmat(ispin), op_fm_set(1, ispin)%matrix_struct)
     751          14 :             CALL cp_fm_struct_release(tmp_fm_struct)
     752          84 :             DO i = 1, 3
     753          42 :                CALL cp_cfm_create(inv_mat(i, ispin), op_fm_set(1, ispin)%matrix_struct)
     754          42 :                CALL cp_fm_create(inv_work(2, i, ispin), op_fm_set(2, ispin)%matrix_struct)
     755          56 :                CALL cp_fm_create(inv_work(1, i, ispin), op_fm_set(1, ispin)%matrix_struct)
     756             :             END DO
     757             :          END DO
     758             : 
     759          14 :          NULLIFY (cosmat, sinmat)
     760          14 :          ALLOCATE (cosmat, sinmat)
     761          14 :          CALL dbcsr_copy(cosmat, matrix_s(1)%matrix, 'COS MOM')
     762          14 :          CALL dbcsr_copy(sinmat, matrix_s(1)%matrix, 'SIN MOM')
     763             : 
     764          56 :          DO i = 1, 3
     765         168 :             kvec(:) = twopi*cell%h_inv(i, :)
     766          42 :             CALL dbcsr_set(cosmat, 0.0_dp)
     767          42 :             CALL dbcsr_set(sinmat, 0.0_dp)
     768          42 :             CALL build_berry_moment_matrix(qs_env, cosmat, sinmat, kvec)
     769             : 
     770          84 :             DO ispin = 1, dft_control%nspins ! spin
     771          42 :                CALL get_mo_set(mo_set=mos(ispin), nao=nao, mo_coeff=mo_coeff, nmo=nmo)
     772             : 
     773          42 :                CALL cp_dbcsr_sm_fm_multiply(cosmat, mo_coeff, opvec(1, ispin), ncol=nmo)
     774             :                CALL parallel_gemm("T", "N", nmo, nmo, nao, 1.0_dp, mo_coeff, opvec(1, ispin), 0.0_dp, &
     775          42 :                                   op_fm_set(1, ispin))
     776          42 :                CALL cp_dbcsr_sm_fm_multiply(sinmat, mo_coeff, opvec(2, ispin), ncol=nmo)
     777             :                CALL parallel_gemm("T", "N", nmo, nmo, nao, 1.0_dp, mo_coeff, opvec(2, ispin), 0.0_dp, &
     778         126 :                                   op_fm_set(2, ispin))
     779             : 
     780             :             END DO
     781             : 
     782             :             ! Second step invert C^T S_berry C
     783          42 :             zdet = one
     784          84 :             DO ispin = 1, dft_control%nspins
     785          42 :                CALL cp_cfm_get_info(eigrmat(ispin), ncol_local=tmp_dim)
     786         210 :                DO idim = 1, tmp_dim
     787             :                   eigrmat(ispin)%local_data(:, idim) = &
     788             :                      CMPLX(op_fm_set(1, ispin)%local_data(:, idim), &
     789         546 :                            -op_fm_set(2, ispin)%local_data(:, idim), dp)
     790             :                END DO
     791          42 :                CALL cp_cfm_set_all(inv_mat(i, ispin), zero, one)
     792         126 :                CALL cp_cfm_solve(eigrmat(ispin), inv_mat(i, ispin), zdeta)
     793             :             END DO
     794             : 
     795             :             ! Compute the derivative and add the result to mo_derivatives
     796          98 :             DO ispin = 1, dft_control%nspins
     797          42 :                CALL cp_cfm_get_info(eigrmat(ispin), ncol_local=tmp_dim)
     798          42 :                CALL get_mo_set(mo_set=mos(ispin), nao=nao, nmo=nmo, maxocc=maxocc)
     799         210 :                DO z = 1, tmp_dim
     800         504 :                   inv_work(1, i, ispin)%local_data(:, z) = REAL(inv_mat(i, ispin)%local_data(:, z), dp)
     801         546 :                   inv_work(2, i, ispin)%local_data(:, z) = AIMAG(inv_mat(i, ispin)%local_data(:, z))
     802             :                END DO
     803             :                CALL parallel_gemm("N", "N", nao, nmo, nmo, -1.0_dp, opvec(1, ispin), inv_work(2, i, ispin), &
     804          42 :                                   0.0_dp, dBerry_psi0(i, ispin))
     805             :                CALL parallel_gemm("N", "N", nao, nmo, nmo, 1.0_dp, opvec(2, ispin), inv_work(1, i, ispin), &
     806         126 :                                   1.0_dp, dBerry_psi0(i, ispin))
     807             :             END DO
     808             :          END DO !x/y/z-direction
     809             :          !SL we omit here the multiplication with hmat (this scaling back done at the end of the response calc)
     810             : 
     811          28 :          DO ispin = 1, dft_control%nspins
     812          14 :             CALL cp_cfm_release(eigrmat(ispin))
     813          70 :             DO i = 1, 3
     814          56 :                CALL cp_cfm_release(inv_mat(i, ispin))
     815             :             END DO
     816             :          END DO
     817          14 :          DEALLOCATE (inv_mat)
     818          14 :          DEALLOCATE (eigrmat)
     819             : 
     820          14 :          CALL cp_fm_release(inv_work)
     821          14 :          CALL cp_fm_release(opvec)
     822          14 :          CALL cp_fm_release(op_fm_set)
     823             : 
     824          14 :          CALL dbcsr_deallocate_matrix(cosmat)
     825          14 :          CALL dbcsr_deallocate_matrix(sinmat)
     826             : 
     827             :       END IF ! do_raman
     828             : 
     829          14 :       CALL timestop(handle)
     830             : 
     831          28 :    END SUBROUTINE polar_operators_berry
     832             : 
     833             : ! **************************************************************************************************
     834             : !> \brief Calculate the Berry phase operator in the AO basis and
     835             : !>         then the derivative of the Berry phase operator with respect to
     836             : !>         the ground state wave function (see paper Putrino et al., JCP, 13, 7102) for the AOs;
     837             : !>        afterwards multiply with the ground state MO coefficients
     838             : !>
     839             : !> \param qs_env ...
     840             : !> \par History
     841             : !>      01.2013 created [SL]
     842             : !>      06.2018 polar_env integrated into qs_env (MK)
     843             : !>      08.2020 adapt for xTB/DFTB (JHU)
     844             : !> \author SL
     845             : ! **************************************************************************************************
     846             : 
     847           4 :    SUBROUTINE polar_tb_operators_berry(qs_env)
     848             : 
     849             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     850             : 
     851             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'polar_tb_operators_berry'
     852             : 
     853             :       COMPLEX(dp)                                        :: zdeta
     854             :       INTEGER                                            :: blk, handle, i, icol, idir, irow, ispin, &
     855             :                                                             nmo, nspins
     856             :       LOGICAL                                            :: do_raman, found
     857             :       REAL(dp)                                           :: dd, fdir
     858             :       REAL(dp), DIMENSION(3)                             :: kvec, ria, rib
     859             :       REAL(dp), DIMENSION(3, 3)                          :: hmat
     860           4 :       REAL(dp), DIMENSION(:, :), POINTER                 :: d_block, s_block
     861             :       TYPE(cell_type), POINTER                           :: cell
     862           4 :       TYPE(cp_fm_type), DIMENSION(:, :), POINTER         :: dBerry_psi0
     863             :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     864             :       TYPE(dbcsr_iterator_type)                          :: iter
     865           4 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: dipmat, matrix_s
     866             :       TYPE(dft_control_type), POINTER                    :: dft_control
     867           4 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     868           4 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     869             :       TYPE(polar_env_type), POINTER                      :: polar_env
     870             : 
     871           4 :       CALL timeset(routineN, handle)
     872             : 
     873             :       CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, &
     874             :                       cell=cell, particle_set=particle_set, &
     875           4 :                       polar_env=polar_env, mos=mos, matrix_s=matrix_s)
     876             : 
     877           4 :       nspins = dft_control%nspins
     878             : 
     879             :       CALL get_polar_env(polar_env=polar_env, &
     880             :                          do_raman=do_raman, &
     881           4 :                          dBerry_psi0=dBerry_psi0)
     882             : 
     883           4 :       IF (do_raman) THEN
     884             : 
     885          16 :          ALLOCATE (dipmat(3))
     886          16 :          DO i = 1, 3
     887          12 :             ALLOCATE (dipmat(i)%matrix)
     888          12 :             CALL dbcsr_copy(dipmat(i)%matrix, matrix_s(1)%matrix, 'dipole')
     889          16 :             CALL dbcsr_set(dipmat(i)%matrix, 0.0_dp)
     890             :          END DO
     891             : 
     892          52 :          hmat = cell%hmat(:, :)/twopi
     893             : 
     894           4 :          CALL dbcsr_iterator_start(iter, matrix_s(1)%matrix)
     895          20 :          DO WHILE (dbcsr_iterator_blocks_left(iter))
     896          16 :             NULLIFY (s_block, d_block)
     897          16 :             CALL dbcsr_iterator_next_block(iter, irow, icol, s_block, blk)
     898          64 :             ria = particle_set(irow)%r
     899          64 :             rib = particle_set(icol)%r
     900          68 :             DO idir = 1, 3
     901         192 :                kvec(:) = twopi*cell%h_inv(idir, :)
     902         192 :                dd = SUM(kvec(:)*ria(:))
     903          48 :                zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)
     904          48 :                fdir = AIMAG(LOG(zdeta))
     905         192 :                dd = SUM(kvec(:)*rib(:))
     906          48 :                zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)
     907          48 :                fdir = fdir + AIMAG(LOG(zdeta))
     908             :                CALL dbcsr_get_block_p(matrix=dipmat(idir)%matrix, &
     909          48 :                                       row=irow, col=icol, BLOCK=d_block, found=found)
     910          48 :                CPASSERT(found)
     911        1168 :                d_block = d_block + 0.5_dp*fdir*s_block
     912             :             END DO
     913             :          END DO
     914           4 :          CALL dbcsr_iterator_stop(iter)
     915             : 
     916             :          ! Compute the derivative and add the result to mo_derivatives
     917           8 :          DO ispin = 1, dft_control%nspins ! spin
     918           4 :             CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, nmo=nmo)
     919          20 :             DO i = 1, 3
     920             :                CALL cp_dbcsr_sm_fm_multiply(dipmat(i)%matrix, mo_coeff, &
     921          16 :                                             dBerry_psi0(i, ispin), ncol=nmo)
     922             :             END DO !x/y/z-direction
     923             :          END DO
     924             : 
     925          16 :          DO i = 1, 3
     926          16 :             CALL dbcsr_deallocate_matrix(dipmat(i)%matrix)
     927             :          END DO
     928           4 :          DEALLOCATE (dipmat)
     929             : 
     930             :       END IF ! do_raman
     931             : 
     932           4 :       CALL timestop(handle)
     933           4 :    END SUBROUTINE polar_tb_operators_berry
     934             : 
     935             : ! **************************************************************************************************
     936             : !> \brief Calculate the Berry phase operator in the AO basis and
     937             : !>         then the derivative of the Berry phase operator with respect to
     938             : !>         the ground state wave function (see paper Putrino et al., JCP, 13, 7102) for the AOs;
     939             : !>        afterwards multiply with the ground state MO coefficients
     940             : !>
     941             : !> \param qs_env ...
     942             : !> \par History
     943             : !>      01.2013 created [SL]
     944             : !>      06.2018 polar_env integrated into qs_env (MK)
     945             : !> \author SL
     946             : ! **************************************************************************************************
     947          86 :    SUBROUTINE polar_operators_local(qs_env)
     948             : 
     949             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     950             : 
     951             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'polar_operators_local'
     952             : 
     953             :       INTEGER                                            :: handle, i, ispin, nmo, nspins
     954             :       LOGICAL                                            :: do_raman
     955          86 :       TYPE(cp_fm_type), DIMENSION(:, :), POINTER         :: dBerry_psi0
     956             :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     957          86 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: dipmat, matrix_s
     958             :       TYPE(dft_control_type), POINTER                    :: dft_control
     959          86 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     960             :       TYPE(polar_env_type), POINTER                      :: polar_env
     961             : 
     962          86 :       CALL timeset(routineN, handle)
     963             : 
     964             :       CALL get_qs_env(qs_env=qs_env, &
     965             :                       dft_control=dft_control, &
     966             :                       polar_env=polar_env, &
     967             :                       mos=mos, &
     968          86 :                       matrix_s=matrix_s)
     969             : 
     970          86 :       nspins = dft_control%nspins
     971             : 
     972             :       CALL get_polar_env(polar_env=polar_env, &
     973             :                          do_raman=do_raman, &
     974          86 :                          dBerry_psi0=dBerry_psi0)
     975             : 
     976             :       !SL calculate dipole berry phase
     977          86 :       IF (do_raman) THEN
     978             : 
     979         344 :          ALLOCATE (dipmat(3))
     980         344 :          DO i = 1, 3
     981         258 :             ALLOCATE (dipmat(i)%matrix)
     982         258 :             CALL dbcsr_copy(dipmat(i)%matrix, matrix_s(1)%matrix, 'dipole')
     983         344 :             CALL dbcsr_set(dipmat(i)%matrix, 0.0_dp)
     984             :          END DO
     985          86 :          CALL build_local_moment_matrix(qs_env, dipmat, 1)
     986             : 
     987             :          ! Compute the derivative and add the result to mo_derivatives
     988         178 :          DO ispin = 1, dft_control%nspins ! spin
     989          92 :             CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, nmo=nmo)
     990         454 :             DO i = 1, 3
     991             :                CALL cp_dbcsr_sm_fm_multiply(dipmat(i)%matrix, mo_coeff, &
     992         368 :                                             dBerry_psi0(i, ispin), ncol=nmo)
     993             :             END DO !x/y/z-direction
     994             :          END DO
     995             : 
     996         344 :          DO i = 1, 3
     997         344 :             CALL dbcsr_deallocate_matrix(dipmat(i)%matrix)
     998             :          END DO
     999          86 :          DEALLOCATE (dipmat)
    1000             : 
    1001             :       END IF ! do_raman
    1002             : 
    1003          86 :       CALL timestop(handle)
    1004             : 
    1005          86 :    END SUBROUTINE polar_operators_local
    1006             : 
    1007             : ! **************************************************************************************************
    1008             : !> \brief Calculate the local dipole operator in the AO basis
    1009             : !>        afterwards multiply with the ground state MO coefficients
    1010             : !>
    1011             : !> \param qs_env ...
    1012             : !> \par History
    1013             : !>      01.2013 created [SL]
    1014             : !>      06.2018 polar_env integrated into qs_env (MK)
    1015             : !>      08.2020 TB version (JHU)
    1016             : !> \author SL
    1017             : ! **************************************************************************************************
    1018           4 :    SUBROUTINE polar_tb_operators_local(qs_env)
    1019             : 
    1020             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1021             : 
    1022             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'polar_tb_operators_local'
    1023             : 
    1024             :       INTEGER                                            :: blk, handle, i, icol, irow, ispin, nmo, &
    1025             :                                                             nspins
    1026             :       LOGICAL                                            :: do_raman, found
    1027             :       REAL(dp)                                           :: fdir
    1028             :       REAL(dp), DIMENSION(3)                             :: ria, rib
    1029           4 :       REAL(dp), DIMENSION(:, :), POINTER                 :: d_block, s_block
    1030             :       TYPE(cell_type), POINTER                           :: cell
    1031           4 :       TYPE(cp_fm_type), DIMENSION(:, :), POINTER         :: dBerry_psi0
    1032             :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    1033             :       TYPE(dbcsr_iterator_type)                          :: iter
    1034           4 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: dipmat, matrix_s
    1035             :       TYPE(dft_control_type), POINTER                    :: dft_control
    1036           4 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    1037           4 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1038             :       TYPE(polar_env_type), POINTER                      :: polar_env
    1039             : 
    1040           4 :       CALL timeset(routineN, handle)
    1041             : 
    1042             :       CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, &
    1043             :                       cell=cell, particle_set=particle_set, &
    1044           4 :                       polar_env=polar_env, mos=mos, matrix_s=matrix_s)
    1045             : 
    1046           4 :       nspins = dft_control%nspins
    1047             : 
    1048             :       CALL get_polar_env(polar_env=polar_env, &
    1049             :                          do_raman=do_raman, &
    1050           4 :                          dBerry_psi0=dBerry_psi0)
    1051             : 
    1052           4 :       IF (do_raman) THEN
    1053             : 
    1054          16 :          ALLOCATE (dipmat(3))
    1055          16 :          DO i = 1, 3
    1056          12 :             ALLOCATE (dipmat(i)%matrix)
    1057          16 :             CALL dbcsr_copy(dipmat(i)%matrix, matrix_s(1)%matrix, 'dipole')
    1058             :          END DO
    1059             : 
    1060           4 :          CALL dbcsr_iterator_start(iter, matrix_s(1)%matrix)
    1061          20 :          DO WHILE (dbcsr_iterator_blocks_left(iter))
    1062          16 :             NULLIFY (s_block, d_block)
    1063          16 :             CALL dbcsr_iterator_next_block(iter, irow, icol, s_block, blk)
    1064          64 :             ria = particle_set(irow)%r
    1065          64 :             ria = pbc(ria, cell)
    1066          64 :             rib = particle_set(icol)%r
    1067          64 :             rib = pbc(rib, cell)
    1068          68 :             DO i = 1, 3
    1069             :                CALL dbcsr_get_block_p(matrix=dipmat(i)%matrix, &
    1070          48 :                                       row=irow, col=icol, BLOCK=d_block, found=found)
    1071          48 :                CPASSERT(found)
    1072          48 :                fdir = 0.5_dp*(ria(i) + rib(i))
    1073        1168 :                d_block = s_block*fdir
    1074             :             END DO
    1075             :          END DO
    1076           4 :          CALL dbcsr_iterator_stop(iter)
    1077             : 
    1078             :          ! Compute the derivative and add the result to mo_derivatives
    1079           8 :          DO ispin = 1, dft_control%nspins ! spin
    1080           4 :             CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, nmo=nmo)
    1081          20 :             DO i = 1, 3
    1082             :                CALL cp_dbcsr_sm_fm_multiply(dipmat(i)%matrix, mo_coeff, &
    1083          16 :                                             dBerry_psi0(i, ispin), ncol=nmo)
    1084             :             END DO !x/y/z-direction
    1085             :          END DO
    1086             : 
    1087          16 :          DO i = 1, 3
    1088          16 :             CALL dbcsr_deallocate_matrix(dipmat(i)%matrix)
    1089             :          END DO
    1090           4 :          DEALLOCATE (dipmat)
    1091             : 
    1092             :       END IF ! do_raman
    1093             : 
    1094           4 :       CALL timestop(handle)
    1095             : 
    1096           4 :    END SUBROUTINE polar_tb_operators_local
    1097             : 
    1098             : ! **************************************************************************************************
    1099             : !> \brief ...
    1100             : !> \param a ...
    1101             : !> \param b ...
    1102             : !> \param c ...
    1103             : !> \return ...
    1104             : ! **************************************************************************************************
    1105        7656 :    FUNCTION fac_vecp(a, b, c) RESULT(factor)
    1106             : 
    1107             :       INTEGER                                            :: a, b, c
    1108             :       REAL(dp)                                           :: factor
    1109             : 
    1110        7656 :       factor = 0.0_dp
    1111             : 
    1112        7656 :       IF ((b .EQ. a + 1 .OR. b .EQ. a - 2) .AND. (c .EQ. b + 1 .OR. c .EQ. b - 2)) THEN
    1113             :          factor = 1.0_dp
    1114        4215 :       ELSEIF ((b .EQ. a - 1 .OR. b .EQ. a + 2) .AND. (c .EQ. b - 1 .OR. c .EQ. b + 2)) THEN
    1115        4215 :          factor = -1.0_dp
    1116             :       END IF
    1117             : 
    1118        7656 :    END FUNCTION fac_vecp
    1119             : 
    1120             : ! **************************************************************************************************
    1121             : !> \brief ...
    1122             : !> \param ii ...
    1123             : !> \param iii ...
    1124             : !> \return ...
    1125             : ! **************************************************************************************************
    1126      414828 :    FUNCTION ind_m2(ii, iii) RESULT(i)
    1127             : 
    1128             :       INTEGER                                            :: ii, iii, i
    1129             : 
    1130             :       INTEGER                                            :: l(3)
    1131             : 
    1132      414828 :       i = 0
    1133      414828 :       l(1:3) = 0
    1134      414828 :       IF (ii == 0) THEN
    1135           0 :          l(iii) = 1
    1136      414828 :       ELSEIF (iii == 0) THEN
    1137           0 :          l(ii) = 1
    1138      414828 :       ELSEIF (ii == iii) THEN
    1139      138276 :          l(ii) = 2
    1140      138276 :          i = coset(l(1), l(2), l(3)) - 1
    1141             :       ELSE
    1142      276552 :          l(ii) = 1
    1143      276552 :          l(iii) = 1
    1144             :       END IF
    1145      414828 :       i = coset(l(1), l(2), l(3)) - 1
    1146      414828 :    END FUNCTION ind_m2
    1147             : 
    1148             : ! **************************************************************************************************
    1149             : !> \brief ...
    1150             : !> \param i1 ...
    1151             : !> \param i2 ...
    1152             : !> \param i3 ...
    1153             : ! **************************************************************************************************
    1154       44593 :    SUBROUTINE set_vecp(i1, i2, i3)
    1155             : 
    1156             :       INTEGER, INTENT(IN)                                :: i1
    1157             :       INTEGER, INTENT(OUT)                               :: i2, i3
    1158             : 
    1159       44593 :       IF (i1 == 1) THEN
    1160       14031 :          i2 = 2
    1161       14031 :          i3 = 3
    1162       30562 :       ELSEIF (i1 == 2) THEN
    1163       15281 :          i2 = 3
    1164       15281 :          i3 = 1
    1165       15281 :       ELSEIF (i1 == 3) THEN
    1166       15281 :          i2 = 1
    1167       15281 :          i3 = 2
    1168             :       ELSE
    1169             :       END IF
    1170             : 
    1171       44593 :    END SUBROUTINE set_vecp
    1172             : ! **************************************************************************************************
    1173             : !> \brief ...
    1174             : !> \param i1 ...
    1175             : !> \param i2 ...
    1176             : !> \param i3 ...
    1177             : ! **************************************************************************************************
    1178        7458 :    SUBROUTINE set_vecp_rev(i1, i2, i3)
    1179             : 
    1180             :       INTEGER, INTENT(IN)                                :: i1, i2
    1181             :       INTEGER, INTENT(OUT)                               :: i3
    1182             : 
    1183        7458 :       IF ((i1 + i2) == 3) THEN
    1184        2486 :          i3 = 3
    1185        4972 :       ELSEIF ((i1 + i2) == 4) THEN
    1186        2486 :          i3 = 2
    1187        2486 :       ELSEIF ((i1 + i2) == 5) THEN
    1188        2486 :          i3 = 1
    1189             :       ELSE
    1190             :       END IF
    1191             : 
    1192        7458 :    END SUBROUTINE set_vecp_rev
    1193             : 
    1194             : ! **************************************************************************************************
    1195             : !> \brief scale a matrix as a_ij = a_ij * pbc(rc(:,j),ra(:,i))(ixyz)
    1196             : !> \param matrix ...
    1197             : !> \param ra ...
    1198             : !> \param rc ...
    1199             : !> \param cell ...
    1200             : !> \param ixyz ...
    1201             : !> \author vw
    1202             : ! **************************************************************************************************
    1203        1500 :    SUBROUTINE fm_scale_by_pbc_AC(matrix, ra, rc, cell, ixyz)
    1204             :       TYPE(cp_fm_type), INTENT(IN)                       :: matrix
    1205             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(in)         :: ra, rc
    1206             :       TYPE(cell_type), POINTER                           :: cell
    1207             :       INTEGER, INTENT(IN)                                :: ixyz
    1208             : 
    1209             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'fm_scale_by_pbc_AC'
    1210             : 
    1211             :       INTEGER :: handle, icol_global, icol_local, irow_global, irow_local, m, mypcol, myprow, n, &
    1212             :          ncol_block, ncol_global, ncol_local, npcol, nprow, nrow_block, nrow_global, nrow_local
    1213             :       REAL(KIND=dp)                                      :: dist(3), rra(3), rrc(3)
    1214        1500 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: a
    1215             : 
    1216        1500 :       CALL timeset(routineN, handle)
    1217             : 
    1218        1500 :       myprow = matrix%matrix_struct%context%mepos(1)
    1219        1500 :       mypcol = matrix%matrix_struct%context%mepos(2)
    1220        1500 :       nprow = matrix%matrix_struct%context%num_pe(1)
    1221        1500 :       npcol = matrix%matrix_struct%context%num_pe(2)
    1222             : 
    1223        1500 :       nrow_block = matrix%matrix_struct%nrow_block
    1224        1500 :       ncol_block = matrix%matrix_struct%ncol_block
    1225        1500 :       nrow_global = matrix%matrix_struct%nrow_global
    1226        1500 :       ncol_global = matrix%matrix_struct%ncol_global
    1227        1500 :       nrow_local = matrix%matrix_struct%nrow_locals(myprow)
    1228        1500 :       ncol_local = matrix%matrix_struct%ncol_locals(mypcol)
    1229             : 
    1230        1500 :       n = SIZE(rc, 2)
    1231        1500 :       m = SIZE(ra, 2)
    1232             : 
    1233        1500 :       a => matrix%local_data
    1234       11088 :       DO icol_local = 1, ncol_local
    1235             :          icol_global = cp_fm_indxl2g(icol_local, ncol_block, mypcol, &
    1236        9588 :                                      matrix%matrix_struct%first_p_pos(2), npcol)
    1237        9588 :          IF (icol_global .GT. n) CYCLE
    1238       38352 :          rrc = rc(:, icol_global)
    1239      131400 :          DO irow_local = 1, nrow_local
    1240             :             irow_global = cp_fm_indxl2g(irow_local, nrow_block, myprow, &
    1241      120312 :                                         matrix%matrix_struct%first_p_pos(1), nprow)
    1242      120312 :             IF (irow_global .GT. m) CYCLE
    1243      481248 :             rra = ra(:, irow_global)
    1244      120312 :             dist = pbc(rrc, rra, cell)
    1245      129900 :             a(irow_local, icol_local) = a(irow_local, icol_local)*dist(ixyz)
    1246             :          END DO
    1247             :       END DO
    1248             : 
    1249        1500 :       CALL timestop(handle)
    1250             : 
    1251        1500 :    END SUBROUTINE fm_scale_by_pbc_AC
    1252             : 
    1253             : END MODULE qs_linres_op
    1254             : 

Generated by: LCOV version 1.15