LCOV - code coverage report
Current view: top level - src - qs_linres_op.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:24d69ee) Lines: 85.0 % 514 437
Test Date: 2026-09-03 07:32:15 Functions: 92.3 % 13 12

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

Generated by: LCOV version 2.0-1