LCOV - code coverage report
Current view: top level - src - qs_tddfpt2_operators.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:24d69ee) Lines: 96.6 % 203 196
Test Date: 2026-09-03 07:32:15 Functions: 100.0 % 6 6

            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              : MODULE qs_tddfpt2_operators
       9              :    USE admm_types,                      ONLY: admm_type
      10              :    USE cell_types,                      ONLY: cell_type,&
      11              :                                               pbc
      12              :    USE cp_control_types,                ONLY: tddfpt2_control_type
      13              :    USE cp_dbcsr_api,                    ONLY: &
      14              :         dbcsr_create, dbcsr_filter, dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, &
      15              :         dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_p_type, &
      16              :         dbcsr_release, dbcsr_set, dbcsr_type, dbcsr_type_no_symmetry
      17              :    USE cp_dbcsr_operations,             ONLY: copy_fm_to_dbcsr,&
      18              :                                               cp_dbcsr_plus_fm_fm_t,&
      19              :                                               cp_dbcsr_sm_fm_multiply
      20              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale,&
      21              :                                               cp_fm_scale_and_add
      22              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_type
      23              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      24              :                                               cp_fm_get_info,&
      25              :                                               cp_fm_release,&
      26              :                                               cp_fm_to_fm,&
      27              :                                               cp_fm_type
      28              :    USE hartree_local_methods,           ONLY: Vh_1c_gg_integrals
      29              :    USE hartree_local_types,             ONLY: hartree_local_type
      30              :    USE hfx_admm_utils,                  ONLY: tddft_hfx_matrix
      31              :    USE hfx_types,                       ONLY: hfx_type
      32              :    USE input_constants,                 ONLY: no_sf_tddfpt
      33              :    USE input_section_types,             ONLY: section_vals_get,&
      34              :                                               section_vals_get_subs_vals,&
      35              :                                               section_vals_type
      36              :    USE kinds,                           ONLY: dp
      37              :    USE message_passing,                 ONLY: mp_para_env_type
      38              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      39              :    USE particle_types,                  ONLY: particle_type
      40              :    USE pw_env_types,                    ONLY: pw_env_get,&
      41              :                                               pw_env_type
      42              :    USE pw_methods,                      ONLY: pw_axpy,&
      43              :                                               pw_multiply,&
      44              :                                               pw_scale,&
      45              :                                               pw_transfer
      46              :    USE pw_poisson_methods,              ONLY: pw_poisson_solve
      47              :    USE pw_poisson_types,                ONLY: pw_poisson_type
      48              :    USE pw_pool_types,                   ONLY: pw_pool_p_type
      49              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      50              :                                               pw_r3d_rs_type
      51              :    USE qs_environment_types,            ONLY: get_qs_env,&
      52              :                                               qs_environment_type
      53              :    USE qs_local_rho_types,              ONLY: local_rho_type
      54              :    USE qs_rho0_ggrid,                   ONLY: integrate_vhg0_rspace
      55              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      56              :                                               qs_rho_type
      57              :    USE qs_tddfpt2_stda_utils,           ONLY: get_lowdin_x
      58              :    USE qs_tddfpt2_subgroups,            ONLY: tddfpt_subgroup_env_type
      59              :    USE qs_tddfpt2_types,                ONLY: tddfpt_ground_state_mos,&
      60              :                                               tddfpt_work_matrices
      61              :    USE realspace_grid_types,            ONLY: realspace_grid_desc_p_type,&
      62              :                                               realspace_grid_type
      63              : #include "./base/base_uses.f90"
      64              : 
      65              :    IMPLICIT NONE
      66              : 
      67              :    PRIVATE
      68              : 
      69              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_tddfpt2_operators'
      70              : 
      71              :    LOGICAL, PARAMETER, PRIVATE          :: debug_this_module = .FALSE.
      72              :    ! number of first derivative components (3: d/dx, d/dy, d/dz)
      73              :    INTEGER, PARAMETER, PRIVATE          :: nderivs = 3
      74              :    INTEGER, PARAMETER, PRIVATE          :: maxspins = 2
      75              : 
      76              :    PUBLIC :: tddfpt_apply_energy_diff, tddfpt_apply_coulomb, tddfpt_apply_hfx, &
      77              :              tddfpt_apply_xc_potential, tddfpt_apply_hfxlr_kernel, tddfpt_apply_hfxsr_kernel
      78              : 
      79              : ! **************************************************************************************************
      80              : 
      81              : CONTAINS
      82              : 
      83              : ! **************************************************************************************************
      84              : !> \brief Apply orbital energy difference term:
      85              : !>        Aop_evects(spin,state) += KS(spin) * evects(spin,state) -
      86              : !>                                  S * evects(spin,state) * diag(evals_occ(spin))
      87              : !> \param Aop_evects  action of TDDFPT operator on trial vectors (modified on exit)
      88              : !> \param evects      trial vectors C_{1,i}
      89              : !> \param S_evects    S * C_{1,i}
      90              : !> \param gs_mos      molecular orbitals optimised for the ground state (only occupied orbital
      91              : !>                    energies [component %evals_occ] are needed)
      92              : !> \param matrix_ks   Kohn-Sham matrix
      93              : !> \param tddfpt_control ...
      94              : !> \par History
      95              : !>    * 05.2016 initialise all matrix elements in one go [Sergey Chulkov]
      96              : !>    * 03.2017 renamed from tddfpt_init_energy_diff(), altered prototype [Sergey Chulkov]
      97              : !> \note Based on the subroutine p_op_l1() which was originally created by
      98              : !>       Thomas Chassaing on 08.2002.
      99              : ! **************************************************************************************************
     100         6814 :    SUBROUTINE tddfpt_apply_energy_diff(Aop_evects, evects, S_evects, gs_mos, matrix_ks, tddfpt_control)
     101              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(INOUT)   :: Aop_evects
     102              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN)      :: evects, S_evects
     103              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
     104              :          INTENT(in)                                      :: gs_mos
     105              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(in)       :: matrix_ks
     106              :       TYPE(tddfpt2_control_type), INTENT(in), POINTER    :: tddfpt_control
     107              : 
     108              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_apply_energy_diff'
     109              : 
     110              :       INTEGER                                            :: handle, i, ispin, ivect, j, nactive, &
     111              :                                                             nao, nspins, nvects, spin2
     112         6814 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: evals_active
     113              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
     114              :       TYPE(cp_fm_type)                                   :: hevec
     115              : 
     116         6814 :       CALL timeset(routineN, handle)
     117              : 
     118         6814 :       nspins = SIZE(evects, 1)
     119         6814 :       nvects = SIZE(evects, 2)
     120              : 
     121        14644 :       DO ispin = 1, SIZE(evects, 1)
     122              :          CALL cp_fm_get_info(matrix=evects(ispin, 1), matrix_struct=matrix_struct, &
     123         7830 :                              nrow_global=nao, ncol_global=nactive)
     124         7830 :          CALL cp_fm_create(hevec, matrix_struct)
     125        23490 :          ALLOCATE (evals_active(nactive))
     126        87326 :          DO i = 1, nactive
     127        79496 :             j = gs_mos(ispin)%index_active(i)
     128        87326 :             evals_active(i) = gs_mos(ispin)%evals_occ(j)
     129              :          END DO
     130              : 
     131         7830 :          IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
     132              :             spin2 = ispin
     133              :          ELSE
     134           96 :             spin2 = 2
     135              :          END IF
     136              : 
     137        28308 :          DO ivect = 1, nvects
     138              :             CALL cp_dbcsr_sm_fm_multiply(matrix_ks(spin2)%matrix, evects(ispin, ivect), &
     139              :                                          Aop_evects(ispin, ivect), ncol=nactive, &
     140        20478 :                                          alpha=1.0_dp, beta=1.0_dp)
     141              : 
     142        20478 :             IF (ASSOCIATED(gs_mos(ispin)%evals_occ_matrix)) THEN
     143              :                ! orbital energy correction: evals_occ_matrix is not a diagonal matrix
     144              :                CALL parallel_gemm('N', 'N', nao, nactive, nactive, 1.0_dp, &
     145              :                                   S_evects(ispin, ivect), gs_mos(ispin)%evals_occ_matrix, &
     146          762 :                                   0.0_dp, hevec)
     147              :             ELSE
     148        19716 :                CALL cp_fm_to_fm(S_evects(ispin, ivect), hevec)
     149        19716 :                CALL cp_fm_column_scale(hevec, evals_active)
     150              :             END IF
     151              : 
     152              :             ! KS * C1 - S * C1 * occupied_orbital_energies
     153        28308 :             CALL cp_fm_scale_and_add(1.0_dp, Aop_evects(ispin, ivect), -1.0_dp, hevec)
     154              :          END DO
     155         7830 :          DEALLOCATE (evals_active)
     156        22474 :          CALL cp_fm_release(hevec)
     157              :       END DO
     158              : 
     159         6814 :       CALL timestop(handle)
     160              : 
     161        13628 :    END SUBROUTINE tddfpt_apply_energy_diff
     162              : 
     163              : ! **************************************************************************************************
     164              : !> \brief Update v_rspace by adding coulomb term.
     165              : !> \param A_ia_rspace    action of TDDFPT operator on the trial vector expressed in a plane wave
     166              : !>                       representation (modified on exit)
     167              : !> \param rho_ia_g       response density in reciprocal space for the given trial vector
     168              : !> \param local_rho_set ...
     169              : !> \param hartree_local ...
     170              : !> \param qs_env ...
     171              : !> \param sub_env        the full sub_environment needed for calculation
     172              : !> \param gapw           Flag indicating GAPW cacluation
     173              : !> \param work_v_gspace  work reciprocal-space grid to store Coulomb potential (modified on exit)
     174              : !> \param work_v_rspace  work real-space grid to store Coulomb potential (modified on exit)
     175              : !> \param tddfpt_mgrid ...
     176              : !> \par History
     177              : !>    * 05.2016 compute all coulomb terms in one go [Sergey Chulkov]
     178              : !>    * 03.2017 proceed excited states sequentially; minimise the number of conversions between
     179              : !>              DBCSR and FM matrices [Sergey Chulkov]
     180              : !>    * 06.2018 return the action expressed in the plane wave representation instead of the one
     181              : !>              in the atomic basis set representation
     182              : !> \note Based on the subroutine kpp1_calc_k_p_p1() which was originally created by
     183              : !>       Mohamed Fawzi on 10.2002.
     184              : ! **************************************************************************************************
     185         8078 :    SUBROUTINE tddfpt_apply_coulomb(A_ia_rspace, rho_ia_g, local_rho_set, hartree_local, &
     186              :                                    qs_env, sub_env, gapw, work_v_gspace, work_v_rspace, tddfpt_mgrid)
     187              :       TYPE(pw_r3d_rs_type), DIMENSION(:), INTENT(INOUT)  :: A_ia_rspace
     188              :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: rho_ia_g
     189              :       TYPE(local_rho_type), POINTER                      :: local_rho_set
     190              :       TYPE(hartree_local_type), POINTER                  :: hartree_local
     191              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     192              :       TYPE(tddfpt_subgroup_env_type), INTENT(in)         :: sub_env
     193              :       LOGICAL, INTENT(IN)                                :: gapw
     194              :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: work_v_gspace
     195              :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: work_v_rspace
     196              :       LOGICAL, INTENT(IN)                                :: tddfpt_mgrid
     197              : 
     198              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_apply_coulomb'
     199              : 
     200              :       INTEGER                                            :: handle, ispin, nspins
     201              :       REAL(kind=dp)                                      :: alpha, pair_energy
     202              :       TYPE(pw_env_type), POINTER                         :: pw_env
     203              :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     204         8078 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: my_pools
     205              :       TYPE(realspace_grid_desc_p_type), DIMENSION(:), &
     206         8078 :          POINTER                                         :: my_rs_descs
     207         8078 :       TYPE(realspace_grid_type), DIMENSION(:), POINTER   :: my_rs_grids
     208              : 
     209         8078 :       CALL timeset(routineN, handle)
     210              : 
     211         8078 :       nspins = SIZE(A_ia_rspace)
     212         8078 :       pw_env => sub_env%pw_env
     213         8078 :       IF (tddfpt_mgrid) THEN
     214              :          CALL pw_env_get(pw_env, poisson_env=poisson_env, rs_grids=my_rs_grids, &
     215           86 :                          rs_descs=my_rs_descs, pw_pools=my_pools)
     216              :       ELSE
     217         7992 :          CALL pw_env_get(pw_env, poisson_env=poisson_env)
     218              :       END IF
     219              : 
     220         8078 :       IF (nspins > 1) THEN
     221         1822 :          alpha = 1.0_dp
     222              :       ELSE
     223              :          ! spin-restricted case: alpha == 2 due to singlet state.
     224              :          ! In case of triplet states alpha == 0, so we should not call this subroutine at all.
     225         6256 :          alpha = 2.0_dp
     226              :       END IF
     227              : 
     228         8078 :       IF (gapw) THEN
     229         1922 :          CPASSERT(ASSOCIATED(local_rho_set))
     230         1922 :          CALL pw_axpy(local_rho_set%rho0_mpole%rho0_s_gs, rho_ia_g)
     231         1922 :          IF (ASSOCIATED(local_rho_set%rho0_mpole%rhoz_cneo_s_gs)) THEN
     232            0 :             CALL pw_axpy(local_rho_set%rho0_mpole%rhoz_cneo_s_gs, rho_ia_g)
     233              :          END IF
     234              :       END IF
     235              : 
     236         8078 :       CALL pw_poisson_solve(poisson_env, rho_ia_g, pair_energy, work_v_gspace)
     237         8078 :       CALL pw_transfer(work_v_gspace, work_v_rspace)
     238              : 
     239              :       ! (i a || j b) = ( i_alpha a_alpha + i_beta a_beta || j_alpha b_alpha + j_beta b_beta) =
     240              :       !                tr (Cj_alpha^T * [J_i{alpha}a{alpha}_munu + J_i{beta}a{beta}_munu] * Cb_alpha) +
     241              :       !                tr (Cj_beta^T * [J_i{alpha}a{alpha}_munu + J_i{beta}a{beta}_munu] * Cb_beta)
     242        17978 :       DO ispin = 1, nspins
     243        17978 :          CALL pw_axpy(work_v_rspace, A_ia_rspace(ispin), alpha)
     244              :       END DO
     245              : 
     246         8078 :       IF (gapw) THEN
     247              :          CALL Vh_1c_gg_integrals(qs_env, pair_energy, &
     248              :                                  hartree_local%ecoul_1c, &
     249              :                                  local_rho_set, &
     250         1922 :                                  sub_env%para_env, tddft=.TRUE., core_2nd=.TRUE.)
     251         1922 :          CALL pw_scale(work_v_rspace, work_v_rspace%pw_grid%dvol)
     252         1922 :          IF (tddfpt_mgrid) THEN
     253              :             CALL integrate_vhg0_rspace(qs_env, work_v_rspace, sub_env%para_env, &
     254              :                                        calculate_forces=.FALSE., &
     255              :                                        local_rho_set=local_rho_set, my_pools=my_pools, &
     256           50 :                                        my_rs_descs=my_rs_descs)
     257              :          ELSE
     258              :             CALL integrate_vhg0_rspace(qs_env, work_v_rspace, sub_env%para_env, &
     259              :                                        calculate_forces=.FALSE., &
     260         1872 :                                        local_rho_set=local_rho_set)
     261              :          END IF
     262              :       END IF
     263              : 
     264         8078 :       CALL timestop(handle)
     265              : 
     266         8078 :    END SUBROUTINE tddfpt_apply_coulomb
     267              : 
     268              : ! **************************************************************************************************
     269              : !> \brief Routine for applying fxc potential
     270              : !> \param A_ia_rspace      action of TDDFPT operator on trial vectors expressed in a plane wave
     271              : !>                         representation (modified on exit)
     272              : !> \param fxc_rspace ...
     273              : !> \param rho_ia_struct    response density for the given trial vector
     274              : !> \param is_rks_triplets ...
     275              : ! **************************************************************************************************
     276          156 :    SUBROUTINE tddfpt_apply_xc_potential(A_ia_rspace, fxc_rspace, rho_ia_struct, is_rks_triplets)
     277              : 
     278              :       TYPE(pw_r3d_rs_type), DIMENSION(:), INTENT(INOUT)  :: A_ia_rspace
     279              :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: fxc_rspace
     280              :       TYPE(qs_rho_type), POINTER                         :: rho_ia_struct
     281              :       LOGICAL, INTENT(in)                                :: is_rks_triplets
     282              : 
     283              :       INTEGER                                            :: nspins
     284              :       REAL(KIND=dp)                                      :: alpha
     285          156 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho1_r
     286              : 
     287          156 :       nspins = SIZE(A_ia_rspace)
     288              : 
     289          156 :       alpha = 1.0_dp
     290              : 
     291          156 :       CALL qs_rho_get(rho_ia_struct, rho_r=rho1_r)
     292              : 
     293          156 :       IF (nspins == 2) THEN
     294            0 :          CALL pw_multiply(A_ia_rspace(1), fxc_rspace(1), rho1_r(1), alpha)
     295            0 :          CALL pw_multiply(A_ia_rspace(1), fxc_rspace(2), rho1_r(2), alpha)
     296            0 :          CALL pw_multiply(A_ia_rspace(2), fxc_rspace(3), rho1_r(2), alpha)
     297            0 :          CALL pw_multiply(A_ia_rspace(2), fxc_rspace(2), rho1_r(1), alpha)
     298          156 :       ELSE IF (is_rks_triplets) THEN
     299            0 :          CALL pw_multiply(A_ia_rspace(1), fxc_rspace(1), rho1_r(1), alpha)
     300            0 :          CALL pw_multiply(A_ia_rspace(1), fxc_rspace(2), rho1_r(1), -alpha)
     301              :       ELSE
     302          156 :          CALL pw_multiply(A_ia_rspace(1), fxc_rspace(1), rho1_r(1), alpha)
     303          156 :          CALL pw_multiply(A_ia_rspace(1), fxc_rspace(2), rho1_r(1), alpha)
     304              :       END IF
     305              : 
     306          156 :    END SUBROUTINE tddfpt_apply_xc_potential
     307              : 
     308              : ! **************************************************************************************************
     309              : !> \brief Update action of TDDFPT operator on trial vectors by adding exact-exchange term.
     310              : !> \param Aop_evects      action of TDDFPT operator on trial vectors (modified on exit)
     311              : !> \param evects          trial vectors
     312              : !> \param gs_mos          molecular orbitals optimised for the ground state (only occupied
     313              : !>                        molecular orbitals [component %mos_occ] are needed)
     314              : !> \param do_admm         perform auxiliary density matrix method calculations
     315              : !> \param qs_env          Quickstep environment
     316              : !> \param work_rho_ia_ao_symm ...
     317              : !> \param work_hmat_symm ...
     318              : !> \param work_rho_ia_ao_asymm ...
     319              : !> \param work_hmat_asymm ...
     320              : !> \param wfm_rho_orb ...
     321              : !> \par History
     322              : !>    * 05.2016 compute all exact-exchange terms in one go [Sergey Chulkov]
     323              : !>    * 03.2017 code related to ADMM correction is now moved to tddfpt_apply_admm_correction()
     324              : !>              in order to compute this correction within parallel groups [Sergey Chulkov]
     325              : !> \note Based on the subroutine kpp1_calc_k_p_p1() which was originally created by
     326              : !>       Mohamed Fawzi on 10.2002.
     327              : ! **************************************************************************************************
     328         1572 :    SUBROUTINE tddfpt_apply_hfx(Aop_evects, evects, gs_mos, do_admm, qs_env, &
     329         1572 :                                work_rho_ia_ao_symm, work_hmat_symm, work_rho_ia_ao_asymm, &
     330         1572 :                                work_hmat_asymm, wfm_rho_orb)
     331              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(INOUT)   :: Aop_evects
     332              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN)      :: evects
     333              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
     334              :          INTENT(in)                                      :: gs_mos
     335              :       LOGICAL, INTENT(in)                                :: do_admm
     336              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     337              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT)    :: work_rho_ia_ao_symm
     338              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT), &
     339              :          TARGET                                          :: work_hmat_symm
     340              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT)    :: work_rho_ia_ao_asymm
     341              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT), &
     342              :          TARGET                                          :: work_hmat_asymm
     343              :       TYPE(cp_fm_type), INTENT(IN)                       :: wfm_rho_orb
     344              : 
     345              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'tddfpt_apply_hfx'
     346              : 
     347              :       INTEGER                                            :: handle, ispin, ivect, nao, nao_aux, &
     348              :                                                             nspins, nvects
     349              :       INTEGER, DIMENSION(maxspins)                       :: nactive
     350              :       LOGICAL                                            :: do_hfx
     351              :       REAL(kind=dp)                                      :: alpha
     352              :       TYPE(admm_type), POINTER                           :: admm_env
     353              :       TYPE(section_vals_type), POINTER                   :: hfx_section, input
     354              : 
     355         1572 :       CALL timeset(routineN, handle)
     356              : 
     357              :       ! Check for hfx section
     358         1572 :       CALL get_qs_env(qs_env, input=input)
     359         1572 :       hfx_section => section_vals_get_subs_vals(input, "DFT%XC%HF")
     360         1572 :       CALL section_vals_get(hfx_section, explicit=do_hfx)
     361              : 
     362         1572 :       IF (do_hfx) THEN
     363         1572 :          nspins = SIZE(evects, 1)
     364         1572 :          nvects = SIZE(evects, 2)
     365              : 
     366         1572 :          IF (SIZE(gs_mos) > 1) THEN
     367           98 :             alpha = 1.0_dp
     368              :          ELSE
     369         1474 :             alpha = 2.0_dp
     370              :          END IF
     371              : 
     372         1572 :          CALL cp_fm_get_info(evects(1, 1), nrow_global=nao)
     373         3222 :          DO ispin = 1, nspins
     374         3222 :             CALL cp_fm_get_info(evects(ispin, 1), ncol_global=nactive(ispin))
     375              :          END DO
     376              : 
     377         1572 :          IF (do_admm) THEN
     378          880 :             CALL get_qs_env(qs_env, admm_env=admm_env)
     379          880 :             CALL cp_fm_get_info(admm_env%A, nrow_global=nao_aux)
     380              :          END IF
     381              : 
     382              :          !Note: the symmetrized transition density matrix is P = 0.5*(C*evect^T + evect*C^T)
     383              :          !      in the end, we only want evect*C^T for consistency with the MO formulation of TDDFT
     384              :          !      therefore, we go in 2 steps: with the symmetric 0.5*(C*evect^T + evect*C^T) and
     385              :          !      the antisymemtric 0.5*(C*evect^T - evect*C^T)
     386              : 
     387              :          ! some stuff from qs_ks_build_kohn_sham_matrix
     388              :          ! TO DO: add SIC support
     389         4552 :          DO ivect = 1, nvects
     390         6088 :             DO ispin = 1, nspins
     391              : 
     392              :                !The symmetric density matrix
     393              :                CALL parallel_gemm('N', 'T', nao, nao, nactive(ispin), 0.5_dp, evects(ispin, ivect), &
     394         3108 :                                   gs_mos(ispin)%mos_active, 0.0_dp, wfm_rho_orb)
     395              :                CALL parallel_gemm('N', 'T', nao, nao, nactive(ispin), 0.5_dp, gs_mos(ispin)%mos_active, &
     396         3108 :                                   evects(ispin, ivect), 1.0_dp, wfm_rho_orb)
     397              : 
     398         3108 :                CALL dbcsr_set(work_hmat_symm(ispin)%matrix, 0.0_dp)
     399         6088 :                IF (do_admm) THEN
     400              :                   CALL parallel_gemm('N', 'N', nao_aux, nao, nao, 1.0_dp, admm_env%A, &
     401         1622 :                                      wfm_rho_orb, 0.0_dp, admm_env%work_aux_orb)
     402              :                   CALL parallel_gemm('N', 'T', nao_aux, nao_aux, nao, 1.0_dp, admm_env%work_aux_orb, admm_env%A, &
     403         1622 :                                      0.0_dp, admm_env%work_aux_aux)
     404         1622 :                   CALL copy_fm_to_dbcsr(admm_env%work_aux_aux, work_rho_ia_ao_symm(ispin)%matrix, keep_sparsity=.TRUE.)
     405              :                ELSE
     406         1486 :                   CALL copy_fm_to_dbcsr(wfm_rho_orb, work_rho_ia_ao_symm(ispin)%matrix, keep_sparsity=.TRUE.)
     407              :                END IF
     408              :             END DO
     409              : 
     410         2980 :             CALL tddft_hfx_matrix(work_hmat_symm, work_rho_ia_ao_symm, qs_env)
     411              : 
     412         2980 :             IF (do_admm) THEN
     413         3216 :                DO ispin = 1, nspins
     414              :                   CALL cp_dbcsr_sm_fm_multiply(work_hmat_symm(ispin)%matrix, admm_env%A, admm_env%work_aux_orb, &
     415         1622 :                                                ncol=nao, alpha=1.0_dp, beta=0.0_dp)
     416              : 
     417              :                   CALL parallel_gemm('T', 'N', nao, nao, nao_aux, 1.0_dp, admm_env%A, &
     418         1622 :                                      admm_env%work_aux_orb, 0.0_dp, wfm_rho_orb)
     419              : 
     420              :                   CALL parallel_gemm('N', 'N', nao, nactive(ispin), nao, alpha, wfm_rho_orb, &
     421         3216 :                                      gs_mos(ispin)%mos_active, 1.0_dp, Aop_evects(ispin, ivect))
     422              :                END DO
     423              :             ELSE
     424         2872 :                DO ispin = 1, nspins
     425              :                   CALL cp_dbcsr_sm_fm_multiply(work_hmat_symm(ispin)%matrix, gs_mos(ispin)%mos_active, &
     426              :                                                Aop_evects(ispin, ivect), ncol=nactive(ispin), &
     427         2872 :                                                alpha=alpha, beta=1.0_dp)
     428              :                END DO
     429              :             END IF
     430              : 
     431              :             !The anti-symmetric density matrix
     432         6088 :             DO ispin = 1, nspins
     433              : 
     434              :                !The symmetric density matrix
     435              :                CALL parallel_gemm('N', 'T', nao, nao, nactive(ispin), 0.5_dp, evects(ispin, ivect), &
     436         3108 :                                   gs_mos(ispin)%mos_active, 0.0_dp, wfm_rho_orb)
     437              :                CALL parallel_gemm('N', 'T', nao, nao, nactive(ispin), -0.5_dp, gs_mos(ispin)%mos_active, &
     438         3108 :                                   evects(ispin, ivect), 1.0_dp, wfm_rho_orb)
     439              : 
     440         3108 :                CALL dbcsr_set(work_hmat_asymm(ispin)%matrix, 0.0_dp)
     441         6088 :                IF (do_admm) THEN
     442              :                   CALL parallel_gemm('N', 'N', nao_aux, nao, nao, 1.0_dp, admm_env%A, &
     443         1622 :                                      wfm_rho_orb, 0.0_dp, admm_env%work_aux_orb)
     444              :                   CALL parallel_gemm('N', 'T', nao_aux, nao_aux, nao, 1.0_dp, admm_env%work_aux_orb, admm_env%A, &
     445         1622 :                                      0.0_dp, admm_env%work_aux_aux)
     446         1622 :                   CALL copy_fm_to_dbcsr(admm_env%work_aux_aux, work_rho_ia_ao_asymm(ispin)%matrix, keep_sparsity=.TRUE.)
     447              :                ELSE
     448         1486 :                   CALL copy_fm_to_dbcsr(wfm_rho_orb, work_rho_ia_ao_asymm(ispin)%matrix, keep_sparsity=.TRUE.)
     449              :                END IF
     450              :             END DO
     451              : 
     452         2980 :             CALL tddft_hfx_matrix(work_hmat_asymm, work_rho_ia_ao_asymm, qs_env)
     453              : 
     454         4552 :             IF (do_admm) THEN
     455         3216 :                DO ispin = 1, nspins
     456              :                   CALL cp_dbcsr_sm_fm_multiply(work_hmat_asymm(ispin)%matrix, admm_env%A, admm_env%work_aux_orb, &
     457         1622 :                                                ncol=nao, alpha=1.0_dp, beta=0.0_dp)
     458              : 
     459              :                   CALL parallel_gemm('T', 'N', nao, nao, nao_aux, 1.0_dp, admm_env%A, &
     460         1622 :                                      admm_env%work_aux_orb, 0.0_dp, wfm_rho_orb)
     461              : 
     462              :                   CALL parallel_gemm('N', 'N', nao, nactive(ispin), nao, alpha, wfm_rho_orb, &
     463         3216 :                                      gs_mos(ispin)%mos_active, 1.0_dp, Aop_evects(ispin, ivect))
     464              :                END DO
     465              :             ELSE
     466         2872 :                DO ispin = 1, nspins
     467              :                   CALL cp_dbcsr_sm_fm_multiply(work_hmat_asymm(ispin)%matrix, gs_mos(ispin)%mos_active, &
     468              :                                                Aop_evects(ispin, ivect), ncol=nactive(ispin), &
     469         2872 :                                                alpha=alpha, beta=1.0_dp)
     470              :                END DO
     471              :             END IF
     472              :          END DO
     473              :       END IF
     474              : 
     475         1572 :       CALL timestop(handle)
     476              : 
     477         1572 :    END SUBROUTINE tddfpt_apply_hfx
     478              : 
     479              : ! **************************************************************************************************
     480              : !> \brief Update action of TDDFPT operator on trial vectors by adding exact-exchange term.
     481              : !> \param Aop_evects      action of TDDFPT operator on trial vectors (modified on exit)
     482              : !> \param evects          trial vectors
     483              : !> \param gs_mos          molecular orbitals optimised for the ground state (only occupied
     484              : !>                        molecular orbitals [component %mos_occ] are needed)
     485              : !> \param qs_env          Quickstep environment
     486              : !> \param admm_env ...
     487              : !> \param hfx_section ...
     488              : !> \param x_data ...
     489              : !> \param symmetry ...
     490              : !> \param recalc_integrals ...
     491              : !> \param work_rho_ia_ao ...
     492              : !> \param work_hmat ...
     493              : !> \param wfm_rho_orb ...
     494              : ! **************************************************************************************************
     495           44 :    SUBROUTINE tddfpt_apply_hfxsr_kernel(Aop_evects, evects, gs_mos, qs_env, admm_env, &
     496              :                                         hfx_section, x_data, symmetry, recalc_integrals, &
     497           44 :                                         work_rho_ia_ao, work_hmat, wfm_rho_orb)
     498              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in)      :: Aop_evects, evects
     499              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
     500              :          INTENT(in)                                      :: gs_mos
     501              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     502              :       TYPE(admm_type), POINTER                           :: admm_env
     503              :       TYPE(section_vals_type), POINTER                   :: hfx_section
     504              :       TYPE(hfx_type), DIMENSION(:, :), POINTER           :: x_data
     505              :       INTEGER, INTENT(IN)                                :: symmetry
     506              :       LOGICAL, INTENT(IN)                                :: recalc_integrals
     507              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT)    :: work_rho_ia_ao
     508              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT), &
     509              :          TARGET                                          :: work_hmat
     510              :       TYPE(cp_fm_type), INTENT(IN)                       :: wfm_rho_orb
     511              : 
     512              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_apply_hfxsr_kernel'
     513              : 
     514              :       INTEGER                                            :: handle, ispin, ivect, nao, nao_aux, &
     515              :                                                             nspins, nvects
     516              :       INTEGER, DIMENSION(maxspins)                       :: nactive
     517              :       LOGICAL                                            :: reint
     518              :       REAL(kind=dp)                                      :: alpha
     519              : 
     520           44 :       CALL timeset(routineN, handle)
     521              : 
     522           44 :       nspins = SIZE(evects, 1)
     523           44 :       nvects = SIZE(evects, 2)
     524              : 
     525           44 :       alpha = 2.0_dp
     526           44 :       IF (nspins > 1) alpha = 1.0_dp
     527              : 
     528           44 :       CALL cp_fm_get_info(evects(1, 1), nrow_global=nao)
     529           44 :       CALL cp_fm_get_info(admm_env%A, nrow_global=nao_aux)
     530           88 :       DO ispin = 1, nspins
     531           88 :          CALL cp_fm_get_info(evects(ispin, 1), ncol_global=nactive(ispin))
     532              :       END DO
     533              : 
     534           44 :       reint = recalc_integrals
     535              : 
     536          132 :       DO ivect = 1, nvects
     537          176 :          DO ispin = 1, nspins
     538              :             CALL parallel_gemm('N', 'T', nao, nao, nactive(ispin), 0.5_dp, evects(ispin, ivect), &
     539           88 :                                gs_mos(ispin)%mos_active, 0.0_dp, wfm_rho_orb)
     540              :             CALL parallel_gemm('N', 'T', nao, nao, nactive(ispin), 0.5_dp*symmetry, gs_mos(ispin)%mos_active, &
     541           88 :                                evects(ispin, ivect), 1.0_dp, wfm_rho_orb)
     542           88 :             CALL dbcsr_set(work_hmat(ispin)%matrix, 0.0_dp)
     543              :             CALL parallel_gemm('N', 'N', nao_aux, nao, nao, 1.0_dp, admm_env%A, &
     544           88 :                                wfm_rho_orb, 0.0_dp, admm_env%work_aux_orb)
     545              :             CALL parallel_gemm('N', 'T', nao_aux, nao_aux, nao, 1.0_dp, admm_env%work_aux_orb, admm_env%A, &
     546           88 :                                0.0_dp, admm_env%work_aux_aux)
     547          176 :             CALL copy_fm_to_dbcsr(admm_env%work_aux_aux, work_rho_ia_ao(ispin)%matrix, keep_sparsity=.TRUE.)
     548              :          END DO
     549              : 
     550           88 :          CALL tddft_hfx_matrix(work_hmat, work_rho_ia_ao, qs_env, .FALSE., reint, hfx_section, x_data)
     551           88 :          reint = .FALSE.
     552              : 
     553          220 :          DO ispin = 1, nspins
     554              :             CALL cp_dbcsr_sm_fm_multiply(work_hmat(ispin)%matrix, admm_env%A, admm_env%work_aux_orb, &
     555           88 :                                          ncol=nao, alpha=1.0_dp, beta=0.0_dp)
     556              :             CALL parallel_gemm('T', 'N', nao, nao, nao_aux, 1.0_dp, admm_env%A, &
     557           88 :                                admm_env%work_aux_orb, 0.0_dp, wfm_rho_orb)
     558              :             CALL parallel_gemm('N', 'N', nao, nactive(ispin), nao, alpha, wfm_rho_orb, &
     559          176 :                                gs_mos(ispin)%mos_active, 1.0_dp, Aop_evects(ispin, ivect))
     560              :          END DO
     561              :       END DO
     562              : 
     563           44 :       CALL timestop(handle)
     564              : 
     565           44 :    END SUBROUTINE tddfpt_apply_hfxsr_kernel
     566              : 
     567              : ! **************************************************************************************************
     568              : !> \brief ...Calculate the HFXLR kernel contribution by contracting the Lowdin MO coefficients --
     569              : !>           transition charges with the exchange-type integrals using the sTDA approximation
     570              : !> \param qs_env ...
     571              : !> \param sub_env ...
     572              : !> \param rcut ...
     573              : !> \param hfx_scale ...
     574              : !> \param work ...
     575              : !> \param X ...
     576              : !> \param res ... vector AX with A being the sTDA matrix and X the Davidson trial vector of the
     577              : !>                eigenvalue problem A*X = omega*X
     578              : ! **************************************************************************************************
     579           72 :    SUBROUTINE tddfpt_apply_hfxlr_kernel(qs_env, sub_env, rcut, hfx_scale, work, X, res)
     580              : 
     581              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     582              :       TYPE(tddfpt_subgroup_env_type)                     :: sub_env
     583              :       REAL(KIND=dp), INTENT(IN)                          :: rcut, hfx_scale
     584              :       TYPE(tddfpt_work_matrices)                         :: work
     585              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: X
     586              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT)      :: res
     587              : 
     588              :       CHARACTER(len=*), PARAMETER :: routineN = 'tddfpt_apply_hfxlr_kernel'
     589              : 
     590              :       INTEGER                                            :: handle, iatom, ispin, jatom, natom, &
     591              :                                                             nsgf, nspins
     592              :       INTEGER, DIMENSION(2)                              :: nactive
     593              :       REAL(KIND=dp)                                      :: dr, eps_filter, fcut, gabr
     594              :       REAL(KIND=dp), DIMENSION(3)                        :: rij
     595           72 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: pblock
     596              :       TYPE(cell_type), POINTER                           :: cell
     597              :       TYPE(cp_fm_struct_type), POINTER                   :: fmstruct
     598              :       TYPE(cp_fm_type)                                   :: cvec
     599           72 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: xtransformed
     600              :       TYPE(cp_fm_type), POINTER                          :: ct
     601              :       TYPE(dbcsr_iterator_type)                          :: iter
     602              :       TYPE(dbcsr_type)                                   :: pdens
     603              :       TYPE(dbcsr_type), POINTER                          :: tempmat
     604              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     605           72 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     606              : 
     607           72 :       CALL timeset(routineN, handle)
     608              : 
     609              :       ! parameters
     610           72 :       eps_filter = 1.E-08_dp
     611              : 
     612           72 :       nspins = SIZE(X)
     613          144 :       DO ispin = 1, nspins
     614          144 :          CALL cp_fm_get_info(X(ispin), ncol_global=nactive(ispin))
     615              :       END DO
     616              : 
     617           72 :       para_env => sub_env%para_env
     618              : 
     619           72 :       CALL get_qs_env(qs_env, natom=natom, cell=cell, particle_set=particle_set)
     620              : 
     621              :       ! calculate Loewdin transformed Davidson trial vector tilde(X)=S^1/2*X
     622              :       ! and tilde(tilde(X))=S^1/2_A*tilde(X)_A
     623          288 :       ALLOCATE (xtransformed(nspins))
     624          144 :       DO ispin = 1, nspins
     625           72 :          NULLIFY (fmstruct)
     626           72 :          ct => work%ctransformed(ispin)
     627           72 :          CALL cp_fm_get_info(ct, matrix_struct=fmstruct)
     628          144 :          CALL cp_fm_create(matrix=xtransformed(ispin), matrix_struct=fmstruct, name="XTRANSFORMED")
     629              :       END DO
     630           72 :       CALL get_lowdin_x(work%shalf, X, xtransformed)
     631              : 
     632          144 :       DO ispin = 1, nspins
     633           72 :          ct => work%ctransformed(ispin)
     634           72 :          CALL cp_fm_get_info(ct, matrix_struct=fmstruct, nrow_global=nsgf)
     635           72 :          CALL cp_fm_create(cvec, fmstruct)
     636              :          !
     637           72 :          tempmat => work%shalf
     638           72 :          CALL dbcsr_create(pdens, template=tempmat, matrix_type=dbcsr_type_no_symmetry)
     639              :          ! P(nu,mu) = SUM_j XT(nu,j)*CT(mu,j)
     640           72 :          ct => work%ctransformed(ispin)
     641           72 :          CALL dbcsr_set(pdens, 0.0_dp)
     642              :          CALL cp_dbcsr_plus_fm_fm_t(pdens, xtransformed(ispin), ct, nactive(ispin), &
     643           72 :                                     1.0_dp, keep_sparsity=.FALSE.)
     644           72 :          CALL dbcsr_filter(pdens, eps_filter)
     645              :          ! Apply PP*gab -> PP; gab = gamma_coulomb
     646              :          ! P(nu,mu) = P(nu,mu)*g(a of nu,b of mu)
     647           72 :          CALL dbcsr_iterator_start(iter, pdens)
     648          396 :          DO WHILE (dbcsr_iterator_blocks_left(iter))
     649          324 :             CALL dbcsr_iterator_next_block(iter, iatom, jatom, pblock)
     650         1296 :             rij = particle_set(iatom)%r - particle_set(jatom)%r
     651         1296 :             rij = pbc(rij, cell)
     652         1296 :             dr = SQRT(SUM(rij(:)**2))
     653          324 :             gabr = 1._dp/rcut
     654          324 :             IF (dr < 1.e-6) THEN
     655          108 :                gabr = 2._dp*gabr/SQRT(3.1415926_dp)
     656              :             ELSE
     657          216 :                gabr = ERF(gabr*dr)/dr
     658              :                fcut = EXP(dr - 4._dp*rcut)
     659          216 :                fcut = fcut/(fcut + 1._dp)
     660              :             END IF
     661        21924 :             pblock = hfx_scale*gabr*pblock
     662              :          END DO
     663           72 :          CALL dbcsr_iterator_stop(iter)
     664              :          ! CV(mu,i) = P(nu,mu)*CT(mu,i)
     665           72 :          CALL cp_dbcsr_sm_fm_multiply(pdens, ct, cvec, nactive(ispin), 1.0_dp, 0.0_dp)
     666              :          ! rho(nu,i) = rho(nu,i) + ShalfP(nu,mu)*CV(mu,i)
     667              :          CALL cp_dbcsr_sm_fm_multiply(work%shalf, cvec, res(ispin), nactive(ispin), &
     668           72 :                                       -1.0_dp, 1.0_dp)
     669              :          !
     670           72 :          CALL dbcsr_release(pdens)
     671              :          !
     672          288 :          CALL cp_fm_release(cvec)
     673              :       END DO
     674              : 
     675           72 :       CALL cp_fm_release(xtransformed)
     676              : 
     677           72 :       CALL timestop(handle)
     678              : 
     679          144 :    END SUBROUTINE tddfpt_apply_hfxlr_kernel
     680              : 
     681              : ! **************************************************************************************************
     682              : 
     683              : END MODULE qs_tddfpt2_operators
        

Generated by: LCOV version 2.0-1