LCOV - code coverage report
Current view: top level - src - qs_linres_op.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:4dc10b3) Lines: 439 516 85.1 %
Date: 2024-11-21 06:45:46 Functions: 12 13 92.3 %

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

Generated by: LCOV version 1.15