LCOV - code coverage report
Current view: top level - src - qs_tddfpt2_forces.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:cccd2f3) Lines: 90.0 % 697 627
Test Date: 2026-05-06 07:07:47 Functions: 100.0 % 9 9

            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_forces
       9              :    USE admm_types,                      ONLY: admm_type,&
      10              :                                               get_admm_env
      11              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      12              :                                               get_atomic_kind,&
      13              :                                               get_atomic_kind_set
      14              :    USE bibliography,                    ONLY: Hehn2022,&
      15              :                                               Hehn2024,&
      16              :                                               Sertcan2024,&
      17              :                                               cite_reference
      18              :    USE cp_control_types,                ONLY: dft_control_type,&
      19              :                                               tddfpt2_control_type
      20              :    USE cp_dbcsr_api,                    ONLY: &
      21              :         dbcsr_add, dbcsr_complete_redistribute, dbcsr_copy, dbcsr_create, dbcsr_p_type, &
      22              :         dbcsr_release, dbcsr_scale, dbcsr_set, dbcsr_type, dbcsr_type_antisymmetric
      23              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_dot
      24              :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      25              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      26              :                                               copy_fm_to_dbcsr,&
      27              :                                               cp_dbcsr_plus_fm_fm_t,&
      28              :                                               cp_dbcsr_sm_fm_multiply,&
      29              :                                               dbcsr_allocate_matrix_set,&
      30              :                                               dbcsr_deallocate_matrix_set
      31              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      32              :                                               cp_fm_struct_release,&
      33              :                                               cp_fm_struct_type
      34              :    USE cp_fm_types,                     ONLY: cp_fm_copy_general,&
      35              :                                               cp_fm_create,&
      36              :                                               cp_fm_get_info,&
      37              :                                               cp_fm_release,&
      38              :                                               cp_fm_set_all,&
      39              :                                               cp_fm_type
      40              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      41              :                                               cp_logger_get_default_unit_nr,&
      42              :                                               cp_logger_type
      43              :    USE exstates_types,                  ONLY: excited_energy_type,&
      44              :                                               exstate_potential_release
      45              :    USE hartree_local_methods,           ONLY: Vh_1c_gg_integrals,&
      46              :                                               init_coulomb_local
      47              :    USE hartree_local_types,             ONLY: hartree_local_create,&
      48              :                                               hartree_local_release,&
      49              :                                               hartree_local_type
      50              :    USE hfx_energy_potential,            ONLY: integrate_four_center
      51              :    USE hfx_ri,                          ONLY: hfx_ri_update_ks
      52              :    USE hfx_types,                       ONLY: hfx_type
      53              :    USE input_constants,                 ONLY: do_admm_aux_exch_func_none,&
      54              :                                               no_sf_tddfpt,&
      55              :                                               oe_shift,&
      56              :                                               tddfpt_kernel_full,&
      57              :                                               tddfpt_kernel_none,&
      58              :                                               tddfpt_kernel_stda
      59              :    USE input_section_types,             ONLY: section_get_lval,&
      60              :                                               section_vals_get,&
      61              :                                               section_vals_get_subs_vals,&
      62              :                                               section_vals_type,&
      63              :                                               section_vals_val_get
      64              :    USE kinds,                           ONLY: default_string_length,&
      65              :                                               dp
      66              :    USE message_passing,                 ONLY: mp_para_env_type
      67              :    USE mulliken,                        ONLY: ao_charges
      68              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      69              :    USE particle_types,                  ONLY: particle_type
      70              :    USE pw_env_types,                    ONLY: pw_env_get,&
      71              :                                               pw_env_type
      72              :    USE pw_methods,                      ONLY: pw_axpy,&
      73              :                                               pw_scale,&
      74              :                                               pw_transfer,&
      75              :                                               pw_zero
      76              :    USE pw_poisson_methods,              ONLY: pw_poisson_solve
      77              :    USE pw_poisson_types,                ONLY: pw_poisson_type
      78              :    USE pw_pool_types,                   ONLY: pw_pool_type
      79              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      80              :                                               pw_r3d_rs_type
      81              :    USE qs_collocate_density,            ONLY: calculate_rho_elec
      82              :    USE qs_density_matrices,             ONLY: calculate_wx_matrix,&
      83              :                                               calculate_xwx_matrix
      84              :    USE qs_environment_types,            ONLY: get_qs_env,&
      85              :                                               qs_environment_type,&
      86              :                                               set_qs_env
      87              :    USE qs_force_types,                  ONLY: allocate_qs_force,&
      88              :                                               deallocate_qs_force,&
      89              :                                               qs_force_type,&
      90              :                                               sum_qs_force,&
      91              :                                               total_qs_force,&
      92              :                                               zero_qs_force
      93              :    USE qs_fxc,                          ONLY: qs_fxc_analytic,&
      94              :                                               qs_fxc_fdiff
      95              :    USE qs_gapw_densities,               ONLY: prepare_gapw_den
      96              :    USE qs_integrate_potential,          ONLY: integrate_v_rspace
      97              :    USE qs_kernel_types,                 ONLY: kernel_env_type
      98              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      99              :                                               get_qs_kind_set,&
     100              :                                               qs_kind_type
     101              :    USE qs_ks_atom,                      ONLY: update_ks_atom
     102              :    USE qs_ks_reference,                 ONLY: ks_ref_potential,&
     103              :                                               ks_ref_potential_atom
     104              :    USE qs_ks_types,                     ONLY: qs_ks_env_type
     105              :    USE qs_local_rho_types,              ONLY: local_rho_set_create,&
     106              :                                               local_rho_set_release,&
     107              :                                               local_rho_type
     108              :    USE qs_mo_types,                     ONLY: get_mo_set,&
     109              :                                               mo_set_type
     110              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
     111              :    USE qs_oce_types,                    ONLY: oce_matrix_type
     112              :    USE qs_overlap,                      ONLY: build_overlap_matrix
     113              :    USE qs_rho0_ggrid,                   ONLY: integrate_vhg0_rspace,&
     114              :                                               rho0_s_grid_create
     115              :    USE qs_rho0_methods,                 ONLY: init_rho0
     116              :    USE qs_rho0_types,                   ONLY: get_rho0_mpole
     117              :    USE qs_rho_atom_methods,             ONLY: allocate_rho_atom_internals,&
     118              :                                               calculate_rho_atom_coeff
     119              :    USE qs_rho_atom_types,               ONLY: rho_atom_type
     120              :    USE qs_rho_types,                    ONLY: qs_rho_create,&
     121              :                                               qs_rho_get,&
     122              :                                               qs_rho_set,&
     123              :                                               qs_rho_type
     124              :    USE qs_tddfpt2_fhxc_forces,          ONLY: fhxc_force,&
     125              :                                               stda_force
     126              :    USE qs_tddfpt2_subgroups,            ONLY: tddfpt_subgroup_env_type
     127              :    USE qs_tddfpt2_types,                ONLY: tddfpt_ground_state_mos,&
     128              :                                               tddfpt_work_matrices
     129              :    USE qs_vxc_atom,                     ONLY: calculate_xc_2nd_deriv_atom
     130              :    USE task_list_types,                 ONLY: task_list_type
     131              :    USE xc_derivatives,                  ONLY: xc_functionals_get_needs
     132              :    USE xc_rho_cflags_types,             ONLY: xc_rho_cflags_type
     133              :    USE xtb_ehess,                       ONLY: xtb_coulomb_hessian
     134              :    USE xtb_types,                       ONLY: get_xtb_atom_param,&
     135              :                                               xtb_atom_type
     136              : #include "./base/base_uses.f90"
     137              : 
     138              :    IMPLICIT NONE
     139              : 
     140              :    PRIVATE
     141              : 
     142              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_tddfpt2_forces'
     143              : 
     144              :    PUBLIC :: tddfpt_forces_main
     145              : 
     146              : ! **************************************************************************************************
     147              : 
     148              : CONTAINS
     149              : 
     150              : ! **************************************************************************************************
     151              : !> \brief Perform TDDFPT gradient calculation. This routine calculates the response vector R of Eq. 49
     152              : !>        in J. Chem. Theory Comput. 2022, 18, 4186−4202 (https://doi.org/10.1021/acs.jctc.2c00144)
     153              : !>        in ex_env%cpmos and a few contributions to the gradient.
     154              : !> \param qs_env  Quickstep environment
     155              : !> \param gs_mos ...
     156              : !> \param ex_env Holds: Response vector ex_env%cpmos = R
     157              : !>                      Difference density ex_env%matrix_pe = T
     158              : !>                      Matrix ex_env%matrix_hz = H_munu[T]
     159              : !> \param kernel_env ...
     160              : !> \param sub_env ...
     161              : !> \param work_matrices ...
     162              : !> \par History
     163              : !>    * 10.2022 created JHU
     164              : ! **************************************************************************************************
     165          658 :    SUBROUTINE tddfpt_forces_main(qs_env, gs_mos, ex_env, kernel_env, sub_env, work_matrices)
     166              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     167              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
     168              :          POINTER                                         :: gs_mos
     169              :       TYPE(excited_energy_type), POINTER                 :: ex_env
     170              :       TYPE(kernel_env_type)                              :: kernel_env
     171              :       TYPE(tddfpt_subgroup_env_type)                     :: sub_env
     172              :       TYPE(tddfpt_work_matrices)                         :: work_matrices
     173              : 
     174              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_forces_main'
     175              : 
     176              :       INTEGER                                            :: handle, ispin, nspins, spin
     177              :       LOGICAL                                            :: do_sf
     178              :       TYPE(admm_type), POINTER                           :: admm_env
     179              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
     180          658 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_pe_asymm, matrix_pe_symm, &
     181          658 :                                                             matrix_s, matrix_s_aux_fit
     182              :       TYPE(dft_control_type), POINTER                    :: dft_control
     183              :       TYPE(tddfpt2_control_type), POINTER                :: tddfpt_control
     184              : 
     185          658 :       CALL timeset(routineN, handle)
     186              : 
     187          658 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     188              : 
     189          658 :       CALL cite_reference(Hehn2022)
     190          658 :       CALL cite_reference(Hehn2024)
     191          658 :       IF (dft_control%qs_control%gapw .OR. dft_control%qs_control%gapw_xc) CALL cite_reference(Sertcan2024)
     192              : 
     193          658 :       nspins = dft_control%nspins
     194          658 :       tddfpt_control => dft_control%tddfpt2_control
     195          658 :       IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
     196          646 :          do_sf = .FALSE.
     197              :       ELSE
     198           12 :          do_sf = .TRUE.
     199              :       END IF
     200              : 
     201              :       ! disable RES-TDDFPT for now
     202         1424 :       DO ispin = 1, nspins
     203         1424 :          IF (gs_mos(ispin)%nmo_occ /= gs_mos(ispin)%nmo_active) THEN
     204            0 :             CALL cp_abort(__LOCATION__, "RES-TDDFPT Forces NYA")
     205              :          END IF
     206              :       END DO
     207              : 
     208              :       ! rhs of linres equation
     209          658 :       IF (ASSOCIATED(ex_env%cpmos)) THEN
     210          522 :          DO ispin = 1, SIZE(ex_env%cpmos)
     211          522 :             CALL cp_fm_release(ex_env%cpmos(ispin))
     212              :          END DO
     213          236 :          DEALLOCATE (ex_env%cpmos)
     214              :       END IF
     215         2740 :       ALLOCATE (ex_env%cpmos(nspins))
     216              :       ! Create and initialize rectangular matrices of nao*occ dimension for alpha and beta R vectors
     217              :       ! for the Z-vector equation system: AZ=-R
     218         1424 :       DO ispin = 1, nspins
     219          766 :          CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, matrix_struct=matrix_struct)
     220          766 :          CALL cp_fm_create(ex_env%cpmos(ispin), matrix_struct)
     221         1424 :          CALL cp_fm_set_all(ex_env%cpmos(ispin), 0.0_dp)
     222              :       END DO
     223          658 :       CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s)
     224          658 :       NULLIFY (matrix_pe_asymm, matrix_pe_symm)
     225              : 
     226              :       ! Build difference density matrix_pe = X*X^T - (C*X^T*S*X*C^T + (C*X^T*S*X*C^T)^T)/2
     227              :       !
     228          658 :       CALL dbcsr_allocate_matrix_set(ex_env%matrix_pe, nspins)
     229          658 :       CALL dbcsr_allocate_matrix_set(matrix_pe_symm, nspins)
     230          658 :       CALL dbcsr_allocate_matrix_set(matrix_pe_asymm, nspins)
     231         1424 :       DO ispin = 1, nspins
     232              : 
     233              :          ! Initialize matrix_pe as a sparse matrix with zeros
     234          766 :          ALLOCATE (ex_env%matrix_pe(ispin)%matrix)
     235          766 :          CALL dbcsr_create(ex_env%matrix_pe(ispin)%matrix, template=matrix_s(1)%matrix)
     236          766 :          CALL dbcsr_copy(ex_env%matrix_pe(ispin)%matrix, matrix_s(1)%matrix)
     237          766 :          CALL dbcsr_set(ex_env%matrix_pe(ispin)%matrix, 0.0_dp)
     238              : 
     239          766 :          ALLOCATE (matrix_pe_symm(ispin)%matrix)
     240          766 :          CALL dbcsr_create(matrix_pe_symm(ispin)%matrix, template=matrix_s(1)%matrix)
     241          766 :          CALL dbcsr_copy(matrix_pe_symm(ispin)%matrix, ex_env%matrix_pe(ispin)%matrix)
     242              : 
     243          766 :          ALLOCATE (matrix_pe_asymm(ispin)%matrix)
     244              :          CALL dbcsr_create(matrix_pe_asymm(ispin)%matrix, template=matrix_s(1)%matrix, &
     245          766 :                            matrix_type=dbcsr_type_antisymmetric)
     246          766 :          CALL dbcsr_complete_redistribute(ex_env%matrix_pe(ispin)%matrix, matrix_pe_asymm(ispin)%matrix)
     247              : 
     248          766 :          IF (do_sf) THEN
     249              :             spin = 1
     250              :          ELSE
     251          742 :             spin = ispin
     252              :          END IF
     253              :          ! Add difference density to matrix_pe
     254              :          CALL tddfpt_resvec1(ex_env%evect(spin), gs_mos(spin)%mos_active, &
     255         1424 :                              matrix_s(1)%matrix, ex_env%matrix_pe(ispin)%matrix, ispin, do_sf)
     256              :       END DO
     257              :       !
     258              :       ! Project the difference density into auxiliary basis for ADMM
     259          658 :       IF (dft_control%do_admm) THEN
     260          142 :          CALL get_qs_env(qs_env, admm_env=admm_env)
     261          142 :          CALL get_admm_env(admm_env, matrix_s_aux_fit=matrix_s_aux_fit)
     262          142 :          CALL dbcsr_allocate_matrix_set(ex_env%matrix_pe_admm, nspins)
     263          304 :          DO ispin = 1, nspins
     264          162 :             ALLOCATE (ex_env%matrix_pe_admm(ispin)%matrix)
     265          162 :             CALL dbcsr_create(ex_env%matrix_pe_admm(ispin)%matrix, template=matrix_s_aux_fit(1)%matrix)
     266          162 :             CALL dbcsr_copy(ex_env%matrix_pe_admm(ispin)%matrix, matrix_s_aux_fit(1)%matrix)
     267          162 :             CALL dbcsr_set(ex_env%matrix_pe_admm(ispin)%matrix, 0.0_dp)
     268              :             CALL tddfpt_resvec1_admm(ex_env%matrix_pe(ispin)%matrix, &
     269          304 :                                      admm_env, ex_env%matrix_pe_admm(ispin)%matrix)
     270              :          END DO
     271              :       END IF
     272              :       !
     273          658 :       CALL dbcsr_allocate_matrix_set(ex_env%matrix_hz, nspins)
     274         1424 :       DO ispin = 1, nspins
     275          766 :          ALLOCATE (ex_env%matrix_hz(ispin)%matrix)
     276          766 :          CALL dbcsr_create(ex_env%matrix_hz(ispin)%matrix, template=matrix_s(1)%matrix)
     277          766 :          CALL dbcsr_copy(ex_env%matrix_hz(ispin)%matrix, matrix_s(1)%matrix)
     278         1424 :          CALL dbcsr_set(ex_env%matrix_hz(ispin)%matrix, 0.0_dp)
     279              :       END DO
     280              :       ! Calculate first term of R vector: H_{\mu i\sigma}[T]
     281          658 :       IF (dft_control%qs_control%xtb) THEN
     282           16 :          CALL tddfpt_resvec2_xtb(qs_env, ex_env%matrix_pe, gs_mos, ex_env%matrix_hz, ex_env%cpmos)
     283              :       ELSE
     284              :          CALL tddfpt_resvec2(qs_env, ex_env%matrix_pe, ex_env%matrix_pe_admm, &
     285          642 :                              gs_mos, ex_env%matrix_hz, ex_env%cpmos)
     286              :       END IF
     287              :       !
     288          658 :       CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1, SIZE(ex_env%evect, 1))
     289          658 :       CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1_asymm, SIZE(ex_env%evect, 1))
     290         1412 :       DO ispin = 1, SIZE(ex_env%evect, 1)
     291          754 :          ALLOCATE (ex_env%matrix_px1(ispin)%matrix)
     292          754 :          CALL dbcsr_create(ex_env%matrix_px1(ispin)%matrix, template=matrix_s(1)%matrix)
     293          754 :          CALL dbcsr_copy(ex_env%matrix_px1(ispin)%matrix, matrix_s(1)%matrix)
     294          754 :          CALL dbcsr_set(ex_env%matrix_px1(ispin)%matrix, 0.0_dp)
     295              : 
     296          754 :          ALLOCATE (ex_env%matrix_px1_asymm(ispin)%matrix)
     297              :          CALL dbcsr_create(ex_env%matrix_px1_asymm(ispin)%matrix, template=matrix_s(1)%matrix, &
     298          754 :                            matrix_type=dbcsr_type_antisymmetric)
     299         1412 :          CALL dbcsr_complete_redistribute(ex_env%matrix_px1(ispin)%matrix, ex_env%matrix_px1_asymm(ispin)%matrix)
     300              :       END DO
     301              :       ! Kernel ADMM
     302          658 :       IF (tddfpt_control%do_admm) THEN
     303           78 :          CALL get_qs_env(qs_env, admm_env=admm_env)
     304           78 :          CALL get_admm_env(admm_env, matrix_s_aux_fit=matrix_s_aux_fit)
     305           78 :          CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1_admm, SIZE(ex_env%evect, 1))
     306           78 :          CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1_admm_asymm, SIZE(ex_env%evect, 1))
     307          160 :          DO ispin = 1, SIZE(ex_env%evect, 1)
     308           82 :             ALLOCATE (ex_env%matrix_px1_admm(ispin)%matrix)
     309           82 :             CALL dbcsr_create(ex_env%matrix_px1_admm(ispin)%matrix, template=matrix_s_aux_fit(1)%matrix)
     310           82 :             CALL dbcsr_copy(ex_env%matrix_px1_admm(ispin)%matrix, matrix_s_aux_fit(1)%matrix)
     311           82 :             CALL dbcsr_set(ex_env%matrix_px1_admm(ispin)%matrix, 0.0_dp)
     312              : 
     313           82 :             ALLOCATE (ex_env%matrix_px1_admm_asymm(ispin)%matrix)
     314              :             CALL dbcsr_create(ex_env%matrix_px1_admm_asymm(ispin)%matrix, template=matrix_s_aux_fit(1)%matrix, &
     315           82 :                               matrix_type=dbcsr_type_antisymmetric)
     316              :             CALL dbcsr_complete_redistribute(ex_env%matrix_px1_admm(ispin)%matrix, &
     317          160 :                                              ex_env%matrix_px1_admm_asymm(ispin)%matrix)
     318              :          END DO
     319              :       END IF
     320              :       ! TDA forces. Calculates and adds all missing terms for the response vector, Eq. 49.
     321          658 :       CALL tddfpt_forces(qs_env, ex_env, gs_mos, kernel_env, sub_env, work_matrices)
     322              :       ! Rotate res vector cpmos into original frame of occupied orbitals.
     323          658 :       CALL tddfpt_resvec3(qs_env, ex_env%cpmos, work_matrices)
     324              : 
     325          658 :       CALL dbcsr_deallocate_matrix_set(matrix_pe_symm)
     326          658 :       CALL dbcsr_deallocate_matrix_set(matrix_pe_asymm)
     327              : 
     328          658 :       CALL timestop(handle)
     329              : 
     330          658 :    END SUBROUTINE tddfpt_forces_main
     331              : 
     332              : ! **************************************************************************************************
     333              : !> \brief Calculate direct tddft forces
     334              : !> \param qs_env ...
     335              : !> \param ex_env ...
     336              : !> \param gs_mos ...
     337              : !> \param kernel_env ...
     338              : !> \param sub_env ...
     339              : !> \param work_matrices ...
     340              : !> \par History
     341              : !>    * 01.2020 screated [JGH]
     342              : ! **************************************************************************************************
     343          658 :    SUBROUTINE tddfpt_forces(qs_env, ex_env, gs_mos, kernel_env, sub_env, work_matrices)
     344              : 
     345              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     346              :       TYPE(excited_energy_type), POINTER                 :: ex_env
     347              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
     348              :          POINTER                                         :: gs_mos
     349              :       TYPE(kernel_env_type), INTENT(IN)                  :: kernel_env
     350              :       TYPE(tddfpt_subgroup_env_type)                     :: sub_env
     351              :       TYPE(tddfpt_work_matrices)                         :: work_matrices
     352              : 
     353              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'tddfpt_forces'
     354              : 
     355              :       INTEGER                                            :: handle
     356          658 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: natom_of_kind
     357              :       LOGICAL                                            :: debug_forces
     358              :       REAL(KIND=dp)                                      :: ehartree, exc
     359          658 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     360              :       TYPE(dft_control_type), POINTER                    :: dft_control
     361          658 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: ks_force, td_force
     362              : 
     363          658 :       CALL timeset(routineN, handle)
     364              : 
     365              :       ! for extended debug output
     366          658 :       debug_forces = ex_env%debug_forces
     367              :       ! prepare force array
     368              :       CALL get_qs_env(qs_env, dft_control=dft_control, force=ks_force, &
     369          658 :                       atomic_kind_set=atomic_kind_set)
     370          658 :       CALL get_atomic_kind_set(atomic_kind_set=atomic_kind_set, natom_of_kind=natom_of_kind)
     371          658 :       NULLIFY (td_force)
     372          658 :       CALL allocate_qs_force(td_force, natom_of_kind)
     373          658 :       DEALLOCATE (natom_of_kind)
     374          658 :       CALL zero_qs_force(td_force)
     375          658 :       CALL set_qs_env(qs_env, force=td_force)
     376              :       !
     377          658 :       IF (dft_control%qs_control%xtb) THEN
     378              :          CALL tddfpt_force_direct(qs_env, ex_env, gs_mos, kernel_env, sub_env, &
     379           16 :                                   work_matrices, debug_forces)
     380              :       ELSE
     381              :          !
     382          642 :          CALL exstate_potential_release(ex_env)
     383              :          ! Build the values of hartree, fock and exchange-correlation potential on the grid
     384              :          CALL ks_ref_potential(qs_env, ex_env%vh_rspace, ex_env%vxc_rspace, &
     385              :                                ex_env%vtau_rspace, ex_env%vadmm_rspace, ehartree, exc, &
     386          642 :                                vadmm_tau_rspace=ex_env%vadmm_tau_rspace)
     387              :          CALL ks_ref_potential_atom(qs_env, ex_env%local_rho_set, ex_env%local_rho_set_admm, &
     388          642 :                                     ex_env%vh_rspace)
     389              :          CALL tddfpt_force_direct(qs_env, ex_env, gs_mos, kernel_env, sub_env, &
     390          642 :                                   work_matrices, debug_forces)
     391              :       END IF
     392              :       !
     393              :       ! add TD and KS forces
     394          658 :       CALL get_qs_env(qs_env, force=td_force)
     395          658 :       CALL sum_qs_force(ks_force, td_force)
     396          658 :       CALL set_qs_env(qs_env, force=ks_force)
     397          658 :       CALL deallocate_qs_force(td_force)
     398              :       !
     399          658 :       CALL timestop(handle)
     400              : 
     401          658 :    END SUBROUTINE tddfpt_forces
     402              : 
     403              : ! **************************************************************************************************
     404              : !> \brief Calculate direct tddft forces.
     405              : !>  J. Chem. Theory Comput. 2022, 18, 7, 4186–4202 (https://doi.org/10.1021/acs.jctc.2c00144)
     406              : !> \param qs_env ...
     407              : !> \param ex_env Holds on exit
     408              : !>                 cpmos      = R,                     Response vector, Eq. 49.
     409              : !>                 matrix_pe  = T,                     Difference density, Eq. 44.
     410              : !>                 matrix_wx1 = CK[D^X]X^T,            Third term of Eq. 51.
     411              : !>                 matrix_wz  = CX^T(\omegaS - K)XC^T, Last term of Eq. 51.
     412              : !> \param gs_mos ...
     413              : !> \param kernel_env ...
     414              : !> \param sub_env ...
     415              : !> \param work_matrices ...
     416              : !> \param debug_forces ...
     417              : !> \par History
     418              : !>    * 01.2020 screated [JGH]
     419              : ! **************************************************************************************************
     420          658 :    SUBROUTINE tddfpt_force_direct(qs_env, ex_env, gs_mos, kernel_env, sub_env, work_matrices, &
     421              :                                   debug_forces)
     422              : 
     423              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     424              :       TYPE(excited_energy_type), POINTER                 :: ex_env
     425              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
     426              :          POINTER                                         :: gs_mos
     427              :       TYPE(kernel_env_type), INTENT(IN)                  :: kernel_env
     428              :       TYPE(tddfpt_subgroup_env_type)                     :: sub_env
     429              :       TYPE(tddfpt_work_matrices)                         :: work_matrices
     430              :       LOGICAL                                            :: debug_forces
     431              : 
     432              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_force_direct'
     433              : 
     434              :       INTEGER                                            :: handle, iounit, ispin, nact, natom, &
     435              :                                                             nspins, spin
     436              :       LOGICAL                                            :: do_sf
     437              :       REAL(KIND=dp)                                      :: evalue
     438          658 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: ftot1, ftot2
     439              :       REAL(KIND=dp), DIMENSION(3)                        :: fodeb
     440          658 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     441          658 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: evect
     442              :       TYPE(cp_logger_type), POINTER                      :: logger
     443          658 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s, matrix_wx1, &
     444          658 :                                                             matrix_wz, scrm
     445              :       TYPE(dft_control_type), POINTER                    :: dft_control
     446              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     447              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     448          658 :          POINTER                                         :: sab_orb
     449          658 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
     450              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     451              :       TYPE(tddfpt2_control_type), POINTER                :: tddfpt_control
     452              : 
     453          658 :       CALL timeset(routineN, handle)
     454              : 
     455          658 :       logger => cp_get_default_logger()
     456          658 :       IF (logger%para_env%is_source()) THEN
     457          329 :          iounit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     458              :       ELSE
     459              :          iounit = -1
     460              :       END IF
     461              : 
     462          658 :       evect => ex_env%evect
     463              : 
     464              :       CALL get_qs_env(qs_env=qs_env, ks_env=ks_env, para_env=para_env, &
     465          658 :                       sab_orb=sab_orb, dft_control=dft_control, force=force)
     466          658 :       NULLIFY (tddfpt_control)
     467          658 :       tddfpt_control => dft_control%tddfpt2_control
     468          658 :       IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
     469              :          do_sf = .FALSE.
     470              :       ELSE
     471           12 :          do_sf = .TRUE.
     472              :       END IF
     473          658 :       nspins = dft_control%nspins
     474              : 
     475          658 :       IF (debug_forces) THEN
     476          122 :          CALL get_qs_env(qs_env, natom=natom, atomic_kind_set=atomic_kind_set)
     477          366 :          ALLOCATE (ftot1(3, natom))
     478          122 :          CALL total_qs_force(ftot1, force, atomic_kind_set)
     479              :       END IF
     480              : 
     481              :       ! Build last terms of the response vector, Eq. 49, and third term of Lambda_munu, Eq. 51.
     482              :       ! the response vector is in ex_env%cpmos and Lambda is in ex_env%matrix_wx1
     483          658 :       CALL tddfpt_kernel_force(qs_env, ex_env, gs_mos, kernel_env, sub_env, work_matrices, debug_forces)
     484              : 
     485              :       ! Overlap matrix, build the Lambda matrix, Eq. 51.
     486          658 :       NULLIFY (matrix_wx1, matrix_wz)
     487          658 :       CALL dbcsr_allocate_matrix_set(matrix_wz, nspins)
     488          658 :       matrix_wx1 => ex_env%matrix_wx1
     489          658 :       CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s, matrix_ks=matrix_ks)
     490         1424 :       DO ispin = 1, nspins
     491          766 :          IF (do_sf) THEN
     492              :             spin = 1
     493              :          ELSE
     494          742 :             spin = ispin
     495              :          END IF
     496              :          ! Create and initialize the Lambda matrix as a sparse matrix
     497          766 :          ALLOCATE (matrix_wz(ispin)%matrix)
     498          766 :          CALL dbcsr_create(matrix=matrix_wz(ispin)%matrix, template=matrix_s(1)%matrix)
     499          766 :          CALL cp_dbcsr_alloc_block_from_nbl(matrix_wz(ispin)%matrix, sab_orb)
     500          766 :          CALL dbcsr_set(matrix_wz(ispin)%matrix, 0.0_dp)
     501              :          ! For spin-flip excitations only the beta component of the Lambda matrix
     502              :          ! contains the excitation energy term
     503          766 :          IF (.NOT. (do_sf .AND. (ispin == 1))) THEN
     504          754 :             CALL cp_fm_get_info(evect(spin), ncol_global=nact)
     505          754 :             CALL cp_dbcsr_plus_fm_fm_t(matrix_wz(ispin)%matrix, matrix_v=evect(spin), ncol=nact)
     506          754 :             evalue = ex_env%evalue
     507          754 :             IF (tddfpt_control%oe_corr == oe_shift) THEN
     508            4 :                evalue = ex_env%evalue - tddfpt_control%ev_shift
     509              :             END IF
     510          754 :             CALL dbcsr_scale(matrix_wz(ispin)%matrix, evalue)
     511              :          END IF
     512              :          ! For spin-flip excitations only the alpha component of the Lambda matrix
     513              :          ! contains the occupied MO energy term
     514         1424 :          IF (.NOT. (do_sf .AND. (ispin == 2))) THEN
     515              :             CALL calculate_wx_matrix(gs_mos(ispin)%mos_active, evect(spin), matrix_ks(ispin)%matrix, &
     516          754 :                                      matrix_wz(ispin)%matrix)
     517              :          END IF
     518              :       END DO
     519          658 :       IF (nspins == 2) THEN
     520              :          CALL dbcsr_add(matrix_wz(1)%matrix, matrix_wz(2)%matrix, &
     521          108 :                         alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
     522              :       END IF
     523          658 :       NULLIFY (scrm)
     524         1024 :       IF (debug_forces) fodeb(1:3) = force(1)%overlap(1:3, 1)
     525              :       ! Calculate the force contribution of matrix_xz into the force in ks_env.
     526              :       !   force%overlap = Tr(dS*matrix_wz), last term of Eq. 51.
     527              :       CALL build_overlap_matrix(ks_env, matrix_s=scrm, &
     528              :                                 matrix_name="OVERLAP MATRIX", &
     529              :                                 basis_type_a="ORB", basis_type_b="ORB", &
     530              :                                 sab_nl=sab_orb, calculate_forces=.TRUE., &
     531          658 :                                 matrix_p=matrix_wz(1)%matrix)
     532          658 :       CALL dbcsr_deallocate_matrix_set(scrm)
     533          658 :       CALL dbcsr_deallocate_matrix_set(matrix_wz)
     534          658 :       IF (debug_forces) THEN
     535          488 :          fodeb(1:3) = force(1)%overlap(1:3, 1) - fodeb(1:3)
     536          122 :          CALL para_env%sum(fodeb)
     537          122 :          IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Wx*dS ", fodeb
     538              :       END IF
     539              : 
     540              :       ! Overlap matrix. Build a part of the first term of Lamda, Eq. 51, corresponding to
     541              :       ! the second term of Eq. 41. matrix_wz = C*X^T*(omega*S - K)*X*C^T
     542          658 :       CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s, matrix_ks=matrix_ks)
     543          658 :       NULLIFY (matrix_wz)
     544          658 :       CALL dbcsr_allocate_matrix_set(matrix_wz, nspins)
     545         1424 :       DO ispin = 1, nspins
     546          766 :          ALLOCATE (matrix_wz(ispin)%matrix)
     547          766 :          CALL dbcsr_create(matrix=matrix_wz(ispin)%matrix, template=matrix_s(1)%matrix)
     548          766 :          CALL cp_dbcsr_alloc_block_from_nbl(matrix_wz(ispin)%matrix, sab_orb)
     549          766 :          CALL dbcsr_set(matrix_wz(ispin)%matrix, 0.0_dp)
     550              :          ! For spin-flip excitations only the alpha component of Lambda has contributions
     551              :          ! of this term, so skip beta
     552         1424 :          IF (.NOT. (do_sf .AND. (ispin == 2))) THEN
     553          754 :             evalue = ex_env%evalue
     554          754 :             IF (tddfpt_control%oe_corr == oe_shift) THEN
     555            4 :                evalue = ex_env%evalue - tddfpt_control%ev_shift
     556              :             END IF
     557          754 :             IF (do_sf) THEN
     558              :                spin = 2
     559              :             ELSE
     560          742 :                spin = ispin
     561              :             END IF
     562              :             CALL calculate_xwx_matrix(gs_mos(ispin)%mos_active, evect(ispin), matrix_s(1)%matrix, &
     563          754 :                                       matrix_ks(spin)%matrix, matrix_wz(ispin)%matrix, evalue)
     564              :          END IF
     565              :       END DO
     566          658 :       IF (nspins == 2) THEN
     567              :          CALL dbcsr_add(matrix_wz(1)%matrix, matrix_wz(2)%matrix, &
     568          108 :                         alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
     569              :       END IF
     570          658 :       NULLIFY (scrm)
     571         1024 :       IF (debug_forces) fodeb(1:3) = force(1)%overlap(1:3, 1)
     572              :       CALL build_overlap_matrix(ks_env, matrix_s=scrm, &
     573              :                                 matrix_name="OVERLAP MATRIX", &
     574              :                                 basis_type_a="ORB", basis_type_b="ORB", &
     575              :                                 sab_nl=sab_orb, calculate_forces=.TRUE., &
     576          658 :                                 matrix_p=matrix_wz(1)%matrix)
     577          658 :       CALL dbcsr_deallocate_matrix_set(scrm)
     578          658 :       CALL dbcsr_deallocate_matrix_set(matrix_wz)
     579          658 :       IF (debug_forces) THEN
     580          488 :          fodeb(1:3) = force(1)%overlap(1:3, 1) - fodeb(1:3)
     581          122 :          CALL para_env%sum(fodeb)
     582          122 :          IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: xWx*dS ", fodeb
     583              :       END IF
     584              : 
     585              :       ! Compute force contribution of the first term of Eq. 41 in the first term of Eq. 51
     586              :       ! that was calculated in tddfpt_kernel_force,
     587              :       !  force%overlap = 0.5C*H[T]*C^T
     588          658 :       IF (ASSOCIATED(matrix_wx1)) THEN
     589          580 :          IF (nspins == 2 .AND. .NOT. do_sf) THEN
     590              :             CALL dbcsr_add(matrix_wx1(1)%matrix, matrix_wx1(2)%matrix, &
     591           96 :                            alpha_scalar=0.5_dp, beta_scalar=0.5_dp)
     592          484 :          ELSE IF (nspins == 2 .AND. do_sf) THEN
     593              :             CALL dbcsr_add(matrix_wx1(1)%matrix, matrix_wx1(2)%matrix, &
     594           12 :                            alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
     595              :          END IF
     596          580 :          NULLIFY (scrm)
     597          910 :          IF (debug_forces) fodeb(1:3) = force(1)%overlap(1:3, 1)
     598              :          CALL build_overlap_matrix(ks_env, matrix_s=scrm, &
     599              :                                    matrix_name="OVERLAP MATRIX", &
     600              :                                    basis_type_a="ORB", basis_type_b="ORB", &
     601              :                                    sab_nl=sab_orb, calculate_forces=.TRUE., &
     602          580 :                                    matrix_p=matrix_wx1(1)%matrix)
     603          580 :          CALL dbcsr_deallocate_matrix_set(scrm)
     604          580 :          IF (debug_forces) THEN
     605          440 :             fodeb(1:3) = force(1)%overlap(1:3, 1) - fodeb(1:3)
     606          110 :             CALL para_env%sum(fodeb)
     607          110 :             IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: D^XKP*dS ", fodeb
     608              :          END IF
     609              :       END IF
     610              : 
     611          658 :       IF (debug_forces) THEN
     612          366 :          ALLOCATE (ftot2(3, natom))
     613          122 :          CALL total_qs_force(ftot2, force, atomic_kind_set)
     614          488 :          fodeb(1:3) = ftot2(1:3, 1) - ftot1(1:3, 1)
     615          122 :          CALL para_env%sum(fodeb)
     616          122 :          IF (iounit > 0) WRITE (iounit, "(T3,A,T30,3F16.8)") "DEBUG:: Excitation Force", fodeb
     617          122 :          DEALLOCATE (ftot1, ftot2)
     618              :       END IF
     619              : 
     620          658 :       CALL timestop(handle)
     621              : 
     622         1316 :    END SUBROUTINE tddfpt_force_direct
     623              : 
     624              : ! **************************************************************************************************
     625              : !> \brief Build the spin difference density,
     626              : !>           matrix_pe = matrix_pe + X*X^T - (C*X^T*S*X*C^T + (C*X^T*S*X*C^T)^T)/2
     627              : !> \param evect ...
     628              : !> \param mos_active ...
     629              : !> \param matrix_s ...
     630              : !> \param matrix_pe ...
     631              : !> \param spin ...
     632              : !> \param do_sf ...
     633              : ! **************************************************************************************************
     634         3064 :    SUBROUTINE tddfpt_resvec1(evect, mos_active, matrix_s, matrix_pe, spin, do_sf)
     635              : 
     636              :       TYPE(cp_fm_type), INTENT(IN)                       :: evect, mos_active
     637              :       TYPE(dbcsr_type), POINTER                          :: matrix_s, matrix_pe
     638              :       INTEGER, INTENT(IN)                                :: spin
     639              :       LOGICAL, INTENT(IN)                                :: do_sf
     640              : 
     641              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'tddfpt_resvec1'
     642              : 
     643              :       INTEGER                                            :: handle, iounit, nact, nao, norb
     644              :       REAL(KIND=dp)                                      :: tmp
     645              :       TYPE(cp_fm_struct_type), POINTER                   :: fmstruct, fmstruct2
     646              :       TYPE(cp_fm_type)                                   :: cxmat, xxmat
     647              :       TYPE(cp_logger_type), POINTER                      :: logger
     648              : 
     649          766 :       CALL timeset(routineN, handle)
     650          766 :       CALL cp_fm_get_info(mos_active, nrow_global=nao, ncol_global=norb)
     651          766 :       CALL cp_fm_get_info(evect, nrow_global=nao, ncol_global=nact)
     652          766 :       CPASSERT(norb == nact)
     653              : 
     654              :       ! matrix_pe = X*X^T
     655          766 :       IF (.NOT. do_sf .OR. (do_sf .AND. (spin == 2))) THEN
     656          754 :          CALL cp_dbcsr_plus_fm_fm_t(matrix_pe, matrix_v=evect, ncol=norb)
     657              :       END IF
     658              : 
     659              :       ! matrix_pe = matrix_pe - (C*X^T*S*X*C^T + (C*X^T*S*X*C^T)^T)/2
     660          766 :       IF (.NOT. do_sf .OR. (do_sf .AND. (spin == 1))) THEN
     661          754 :          CALL cp_fm_get_info(evect, matrix_struct=fmstruct)
     662          754 :          NULLIFY (fmstruct2)
     663              :          CALL cp_fm_struct_create(fmstruct=fmstruct2, template_fmstruct=fmstruct, &
     664          754 :                                   nrow_global=norb, ncol_global=norb)
     665          754 :          CALL cp_fm_create(xxmat, matrix_struct=fmstruct2)
     666          754 :          CALL cp_fm_struct_release(fmstruct2)
     667          754 :          CALL cp_fm_create(cxmat, matrix_struct=fmstruct)
     668              :          ! S*X
     669          754 :          CALL cp_dbcsr_sm_fm_multiply(matrix_s, evect, cxmat, norb, alpha=1.0_dp, beta=0.0_dp)
     670              :          ! (S*X)^T*X
     671          754 :          CALL parallel_gemm('T', 'N', norb, norb, nao, 1.0_dp, cxmat, evect, 0.0_dp, xxmat)
     672              :          ! C*X^T*S*X
     673          754 :          CALL parallel_gemm('N', 'N', nao, norb, norb, 1.0_dp, mos_active, xxmat, 0.0_dp, cxmat)
     674          754 :          CALL cp_fm_release(xxmat)
     675              :          ! matrix_pe = matrix_pe - (C*(C^T*X^T*S*X)^T + C^T*(C^T*X^T*S*X))/2
     676              :          CALL cp_dbcsr_plus_fm_fm_t(matrix_pe, matrix_v=mos_active, matrix_g=cxmat, &
     677          754 :                                     ncol=norb, alpha=-1.0_dp, symmetry_mode=1)
     678          754 :          CALL cp_fm_release(cxmat)
     679              :       END IF
     680              :       !
     681              :       ! Test for Tr(Pe*S)=0
     682          766 :       CALL dbcsr_dot(matrix_pe, matrix_s, tmp)
     683          766 :       IF (.NOT. do_sf) THEN
     684          742 :          IF (ABS(tmp) > 1.e-08_dp) THEN
     685            0 :             logger => cp_get_default_logger()
     686            0 :             IF (logger%para_env%is_source()) THEN
     687            0 :                iounit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     688              :             ELSE
     689              :                iounit = -1
     690              :             END IF
     691            0 :             CPWARN("Electron count of excitation density matrix is non-zero.")
     692            0 :             IF (iounit > 0) THEN
     693            0 :                WRITE (iounit, "(T2,A,T61,G20.10)") "Measured electron count is ", tmp
     694            0 :                WRITE (iounit, "(T2,A,/)") REPEAT("*", 79)
     695              :             END IF
     696              :          END IF
     697           24 :       ELSE IF (spin == 1) THEN
     698           12 :          IF (ABS(tmp + 1) > 1.e-08_dp) THEN
     699            0 :             logger => cp_get_default_logger()
     700            0 :             IF (logger%para_env%is_source()) THEN
     701            0 :                iounit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     702              :             ELSE
     703              :                iounit = -1
     704              :             END IF
     705            0 :             CPWARN("Count of occupied occupation number change is not -1.")
     706            0 :             IF (iounit > 0) THEN
     707            0 :                WRITE (iounit, "(T2,A,T61,G20.10)") "Measured electron count is ", tmp
     708            0 :                WRITE (iounit, "(T2,A,/)") REPEAT("*", 79)
     709              :             END IF
     710              :          END IF
     711           12 :       ELSE IF (spin == 2) THEN
     712           12 :          IF (ABS(tmp - 1) > 1.e-08_dp) THEN
     713            0 :             logger => cp_get_default_logger()
     714            0 :             IF (logger%para_env%is_source()) THEN
     715            0 :                iounit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     716              :             ELSE
     717              :                iounit = -1
     718              :             END IF
     719            0 :             CPWARN("Count of unoccupied occupation number change is not 1.")
     720            0 :             IF (iounit > 0) THEN
     721            0 :                WRITE (iounit, "(T2,A,T61,G20.10)") "Measured electron count is ", tmp
     722            0 :                WRITE (iounit, "(T2,A,/)") REPEAT("*", 79)
     723              :             END IF
     724              :          END IF
     725              :       END IF
     726              :       !
     727              : 
     728          766 :       CALL timestop(handle)
     729              : 
     730          766 :    END SUBROUTINE tddfpt_resvec1
     731              : 
     732              : ! **************************************************************************************************
     733              : !> \brief PA = A * P * A(T)
     734              : !> \param matrix_pe ...
     735              : !> \param admm_env ...
     736              : !> \param matrix_pe_admm ...
     737              : ! **************************************************************************************************
     738          162 :    SUBROUTINE tddfpt_resvec1_admm(matrix_pe, admm_env, matrix_pe_admm)
     739              : 
     740              :       TYPE(dbcsr_type), POINTER                          :: matrix_pe
     741              :       TYPE(admm_type), POINTER                           :: admm_env
     742              :       TYPE(dbcsr_type), POINTER                          :: matrix_pe_admm
     743              : 
     744              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_resvec1_admm'
     745              : 
     746              :       INTEGER                                            :: handle, nao, nao_aux
     747              : 
     748          162 :       CALL timeset(routineN, handle)
     749              :       !
     750          162 :       nao_aux = admm_env%nao_aux_fit
     751          162 :       nao = admm_env%nao_orb
     752              :       !
     753          162 :       CALL copy_dbcsr_to_fm(matrix_pe, admm_env%work_orb_orb)
     754              :       CALL parallel_gemm('N', 'N', nao_aux, nao, nao, &
     755              :                          1.0_dp, admm_env%A, admm_env%work_orb_orb, 0.0_dp, &
     756          162 :                          admm_env%work_aux_orb)
     757              :       CALL parallel_gemm('N', 'T', nao_aux, nao_aux, nao, &
     758              :                          1.0_dp, admm_env%work_aux_orb, admm_env%A, 0.0_dp, &
     759          162 :                          admm_env%work_aux_aux)
     760          162 :       CALL copy_fm_to_dbcsr(admm_env%work_aux_aux, matrix_pe_admm, keep_sparsity=.TRUE.)
     761              :       !
     762          162 :       CALL timestop(handle)
     763              : 
     764          162 :    END SUBROUTINE tddfpt_resvec1_admm
     765              : 
     766              : ! **************************************************************************************************
     767              : !> \brief Calculates the action of the H operator as in the first term of equation 49 in
     768              : !>        https://doi.org/10.1021/acs.jctc.2c00144 (J. Chem. Theory Comput. 2022, 18, 4186−4202)
     769              : !>          cpmos = H_{\mu i\sigma}[matrix_pe]
     770              : !> \param qs_env ...
     771              : !> \param matrix_pe Input square matrix with the size of the number of atomic orbitals squared nao^2
     772              : !> \param matrix_pe_admm ...
     773              : !> \param gs_mos ...
     774              : !> \param matrix_hz Holds H_{\mu\nu\sigma}[matrix_pe] on exit
     775              : !> \param cpmos ...
     776              : ! **************************************************************************************************
     777          642 :    SUBROUTINE tddfpt_resvec2(qs_env, matrix_pe, matrix_pe_admm, gs_mos, matrix_hz, cpmos)
     778              : 
     779              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     780              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_pe, matrix_pe_admm
     781              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
     782              :          POINTER                                         :: gs_mos
     783              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_hz
     784              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT)      :: cpmos
     785              : 
     786              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'tddfpt_resvec2'
     787              : 
     788              :       CHARACTER(LEN=default_string_length)               :: basis_type
     789              :       INTEGER                                            :: handle, iounit, ispin, mspin, n_rep_hf, &
     790              :                                                             nao, nao_aux, natom, norb, nspins
     791              :       LOGICAL :: deriv2_analytic, distribute_fock_matrix, do_hfx, gapw, gapw_xc, &
     792              :          hfx_treat_lsd_in_core, needs_tau_response, s_mstruct_changed
     793              :       REAL(KIND=dp)                                      :: eh1, focc, rhotot, thartree
     794              :       REAL(KIND=dp), DIMENSION(2)                        :: total_rho
     795          642 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: Qlm_tot
     796              :       TYPE(admm_type), POINTER                           :: admm_env
     797          642 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     798              :       TYPE(cp_fm_type), POINTER                          :: mos
     799              :       TYPE(cp_logger_type), POINTER                      :: logger
     800          642 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: msaux
     801          642 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mhz, mpe
     802              :       TYPE(dbcsr_type), POINTER                          :: dbwork
     803              :       TYPE(dft_control_type), POINTER                    :: dft_control
     804              :       TYPE(hartree_local_type), POINTER                  :: hartree_local
     805          642 :       TYPE(hfx_type), DIMENSION(:, :), POINTER           :: x_data
     806              :       TYPE(local_rho_type), POINTER                      :: local_rho_set, local_rho_set_admm
     807              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     808              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     809          642 :          POINTER                                         :: sab, sab_aux_fit
     810              :       TYPE(oce_matrix_type), POINTER                     :: oce
     811              :       TYPE(pw_c1d_gs_type)                               :: rho_tot_gspace, v_hartree_gspace
     812          642 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rho_g, rho_g_aux, rhoz_g_aux, &
     813          642 :                                                             rhoz_tau_g_aux, trho_g, trho_tau_g, &
     814          642 :                                                             trho_xc_g, trho_xc_tau_g
     815              :       TYPE(pw_env_type), POINTER                         :: pw_env
     816              :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     817              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     818              :       TYPE(pw_r3d_rs_type)                               :: v_hartree_rspace
     819          642 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r, rho_r_aux, rhoz_r_aux, &
     820          642 :                                                             rhoz_tau_r_aux, trho_r, trho_tau_r, &
     821          642 :                                                             trho_xc_r, trho_xc_tau_r, v_xc, &
     822          642 :                                                             v_xc_tau
     823              :       TYPE(pw_r3d_rs_type), POINTER                      :: weights
     824          642 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     825              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     826              :       TYPE(qs_rho_type), POINTER                         :: rho, rho_aux_fit, rho_xc, rhoz_aux, trho
     827          642 :       TYPE(rho_atom_type), DIMENSION(:), POINTER         :: rho1_atom_set, rho_atom_set
     828              :       TYPE(section_vals_type), POINTER                   :: hfx_section, input, xc_fun_section, &
     829              :                                                             xc_section
     830              :       TYPE(task_list_type), POINTER                      :: task_list
     831              :       TYPE(xc_rho_cflags_type)                           :: needs
     832              : 
     833          642 :       CALL timeset(routineN, handle)
     834              : 
     835          642 :       NULLIFY (pw_env)
     836              :       CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, ks_env=ks_env, &
     837          642 :                       dft_control=dft_control, para_env=para_env)
     838          642 :       CPASSERT(ASSOCIATED(pw_env))
     839          642 :       nspins = dft_control%nspins
     840          642 :       gapw = dft_control%qs_control%gapw
     841          642 :       gapw_xc = dft_control%qs_control%gapw_xc
     842              : 
     843          642 :       CPASSERT(.NOT. dft_control%tddfpt2_control%do_exck)
     844          642 :       CPASSERT(.NOT. dft_control%tddfpt2_control%do_hfxsr)
     845          642 :       CPASSERT(.NOT. dft_control%tddfpt2_control%do_hfxlr)
     846              : 
     847          642 :       NULLIFY (auxbas_pw_pool, poisson_env)
     848              :       ! gets the tmp grids
     849              :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
     850          642 :                       poisson_env=poisson_env)
     851              : 
     852          642 :       CALL auxbas_pw_pool%create_pw(v_hartree_gspace)
     853          642 :       CALL auxbas_pw_pool%create_pw(rho_tot_gspace)
     854          642 :       CALL auxbas_pw_pool%create_pw(v_hartree_rspace)
     855              : 
     856          642 :       CALL get_qs_env(qs_env, input=input)
     857          642 :       IF (dft_control%do_admm) THEN
     858          142 :          CALL get_qs_env(qs_env, admm_env=admm_env)
     859          142 :          xc_section => admm_env%xc_section_primary
     860              :       ELSE
     861          500 :          xc_section => section_vals_get_subs_vals(input, "DFT%XC")
     862              :       END IF
     863          642 :       xc_fun_section => section_vals_get_subs_vals(xc_section, "XC_FUNCTIONAL")
     864          642 :       needs = xc_functionals_get_needs(xc_fun_section, (nspins == 2), .TRUE.)
     865          642 :       needs_tau_response = needs%tau .OR. needs%tau_spin
     866              : 
     867          642 :       NULLIFY (trho_tau_r, trho_tau_g, trho_xc_tau_r, trho_xc_tau_g)
     868         4710 :       ALLOCATE (trho_r(nspins), trho_g(nspins))
     869         1392 :       DO ispin = 1, nspins
     870          750 :          CALL auxbas_pw_pool%create_pw(trho_r(ispin))
     871         1392 :          CALL auxbas_pw_pool%create_pw(trho_g(ispin))
     872              :       END DO
     873          642 :       IF (needs_tau_response) THEN
     874            0 :          ALLOCATE (trho_tau_r(nspins), trho_tau_g(nspins))
     875            0 :          DO ispin = 1, nspins
     876            0 :             CALL auxbas_pw_pool%create_pw(trho_tau_r(ispin))
     877            0 :             CALL auxbas_pw_pool%create_pw(trho_tau_g(ispin))
     878              :          END DO
     879              :       END IF
     880          642 :       IF (gapw_xc) THEN
     881          130 :          ALLOCATE (trho_xc_r(nspins), trho_xc_g(nspins))
     882           52 :          DO ispin = 1, nspins
     883           26 :             CALL auxbas_pw_pool%create_pw(trho_xc_r(ispin))
     884           52 :             CALL auxbas_pw_pool%create_pw(trho_xc_g(ispin))
     885              :          END DO
     886           26 :          IF (needs_tau_response) THEN
     887            0 :             ALLOCATE (trho_xc_tau_r(nspins), trho_xc_tau_g(nspins))
     888            0 :             DO ispin = 1, nspins
     889            0 :                CALL auxbas_pw_pool%create_pw(trho_xc_tau_r(ispin))
     890            0 :                CALL auxbas_pw_pool%create_pw(trho_xc_tau_g(ispin))
     891              :             END DO
     892              :          END IF
     893              :       END IF
     894              : 
     895              :       ! GAPW/GAPW_XC initializations
     896          642 :       NULLIFY (hartree_local, local_rho_set)
     897          642 :       IF (gapw) THEN
     898              :          CALL get_qs_env(qs_env, &
     899              :                          atomic_kind_set=atomic_kind_set, &
     900              :                          natom=natom, &
     901          130 :                          qs_kind_set=qs_kind_set)
     902          130 :          CALL local_rho_set_create(local_rho_set)
     903              :          CALL allocate_rho_atom_internals(local_rho_set%rho_atom_set, atomic_kind_set, &
     904          130 :                                           qs_kind_set, dft_control, para_env)
     905              :          CALL init_rho0(local_rho_set, qs_env, dft_control%qs_control%gapw_control, &
     906          130 :                         zcore=0.0_dp)
     907          130 :          CALL rho0_s_grid_create(pw_env, local_rho_set%rho0_mpole)
     908          130 :          CALL hartree_local_create(hartree_local)
     909          130 :          CALL init_coulomb_local(hartree_local, natom)
     910          512 :       ELSEIF (gapw_xc) THEN
     911              :          CALL get_qs_env(qs_env, &
     912              :                          atomic_kind_set=atomic_kind_set, &
     913           26 :                          qs_kind_set=qs_kind_set)
     914           26 :          CALL local_rho_set_create(local_rho_set)
     915              :          CALL allocate_rho_atom_internals(local_rho_set%rho_atom_set, atomic_kind_set, &
     916           26 :                                           qs_kind_set, dft_control, para_env)
     917              :       END IF
     918              : 
     919          642 :       total_rho = 0.0_dp
     920          642 :       CALL pw_zero(rho_tot_gspace)
     921         1392 :       DO ispin = 1, nspins
     922              :          CALL calculate_rho_elec(ks_env=ks_env, matrix_p=matrix_pe(ispin)%matrix, &
     923              :                                  rho=trho_r(ispin), &
     924              :                                  rho_gspace=trho_g(ispin), &
     925              :                                  soft_valid=gapw, &
     926          750 :                                  total_rho=total_rho(ispin))
     927          750 :          IF (needs_tau_response) THEN
     928              :             CALL calculate_rho_elec(ks_env=ks_env, matrix_p=matrix_pe(ispin)%matrix, &
     929              :                                     rho=trho_tau_r(ispin), &
     930              :                                     rho_gspace=trho_tau_g(ispin), &
     931              :                                     soft_valid=gapw, &
     932            0 :                                     compute_tau=.TRUE.)
     933              :          END IF
     934          750 :          CALL pw_axpy(trho_g(ispin), rho_tot_gspace)
     935         1392 :          IF (gapw_xc) THEN
     936              :             CALL calculate_rho_elec(ks_env=ks_env, matrix_p=matrix_pe(ispin)%matrix, &
     937              :                                     rho=trho_xc_r(ispin), &
     938              :                                     rho_gspace=trho_xc_g(ispin), &
     939              :                                     soft_valid=gapw_xc, &
     940           26 :                                     total_rho=rhotot)
     941           26 :             IF (needs_tau_response) THEN
     942              :                CALL calculate_rho_elec(ks_env=ks_env, matrix_p=matrix_pe(ispin)%matrix, &
     943              :                                        rho=trho_xc_tau_r(ispin), &
     944              :                                        rho_gspace=trho_xc_tau_g(ispin), &
     945              :                                        soft_valid=gapw_xc, &
     946            0 :                                        compute_tau=.TRUE.)
     947              :             END IF
     948              :          END IF
     949              :       END DO
     950              : 
     951              :       ! GAPW o GAPW_XC require the calculation of hard and soft local densities
     952          642 :       IF (gapw .OR. gapw_xc) THEN
     953          156 :          CALL get_qs_env(qs_env=qs_env, oce=oce, sab_orb=sab)
     954              :          CALL calculate_rho_atom_coeff(qs_env, matrix_pe, local_rho_set%rho_atom_set, &
     955          156 :                                        qs_kind_set, oce, sab, para_env)
     956          156 :          CALL prepare_gapw_den(qs_env, local_rho_set, do_rho0=gapw)
     957              :       END IF
     958         1926 :       rhotot = SUM(total_rho)
     959          642 :       IF (gapw) THEN
     960          130 :          CALL get_rho0_mpole(local_rho_set%rho0_mpole, Qlm_tot=Qlm_tot)
     961          130 :          rhotot = rhotot + local_rho_set%rho0_mpole%total_rho0_h
     962          130 :          CALL pw_axpy(local_rho_set%rho0_mpole%rho0_s_gs, rho_tot_gspace)
     963          130 :          IF (ASSOCIATED(local_rho_set%rho0_mpole%rhoz_cneo_s_gs)) THEN
     964            0 :             CALL pw_axpy(local_rho_set%rho0_mpole%rhoz_cneo_s_gs, rho_tot_gspace)
     965              :          END IF
     966              :       END IF
     967              : 
     968          642 :       IF (ABS(rhotot) > 1.e-05_dp) THEN
     969           24 :          logger => cp_get_default_logger()
     970           24 :          IF (logger%para_env%is_source()) THEN
     971           12 :             iounit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     972              :          ELSE
     973              :             iounit = -1
     974              :          END IF
     975           24 :          CPWARN("Real space electron count of excitation density is non-zero.")
     976           24 :          IF (iounit > 0) THEN
     977           12 :             WRITE (iounit, "(T2,A,T61,G20.10)") "Measured electron count is ", rhotot
     978           12 :             WRITE (iounit, "(T2,A,/)") REPEAT("*", 79)
     979              :          END IF
     980              :       END IF
     981              : 
     982              :       ! calculate associated hartree potential
     983              :       CALL pw_poisson_solve(poisson_env, rho_tot_gspace, thartree, &
     984          642 :                             v_hartree_gspace)
     985          642 :       CALL pw_transfer(v_hartree_gspace, v_hartree_rspace)
     986          642 :       CALL pw_scale(v_hartree_rspace, v_hartree_rspace%pw_grid%dvol)
     987          642 :       IF (gapw) THEN
     988              :          CALL Vh_1c_gg_integrals(qs_env, thartree, hartree_local%ecoul_1c, &
     989          130 :                                  local_rho_set, para_env, tddft=.TRUE.)
     990              :          CALL integrate_vhg0_rspace(qs_env, v_hartree_rspace, para_env, &
     991              :                                     calculate_forces=.FALSE., &
     992          130 :                                     local_rho_set=local_rho_set)
     993              :       END IF
     994              : 
     995              :       ! Fxc*drho term
     996          642 :       CALL get_qs_env(qs_env, rho=rho)
     997          642 :       CALL qs_rho_get(rho, rho_r=rho_r, rho_g=rho_g)
     998              :       !
     999          642 :       deriv2_analytic = section_get_lval(xc_section, "2ND_DERIV_ANALYTICAL")
    1000          642 :       IF (deriv2_analytic) THEN
    1001          642 :          NULLIFY (v_xc, v_xc_tau)
    1002          642 :          CALL get_qs_env(qs_env=qs_env, xcint_weights=weights)
    1003          642 :          IF (gapw_xc) THEN
    1004           26 :             CALL get_qs_env(qs_env=qs_env, rho_xc=rho_xc)
    1005              :             CALL qs_fxc_analytic(rho_xc, trho_xc_r, trho_xc_tau_r, xc_section, weights, auxbas_pw_pool, &
    1006           26 :                                  .FALSE., v_xc, v_xc_tau)
    1007              :          ELSE
    1008              :             CALL qs_fxc_analytic(rho, trho_r, trho_tau_r, xc_section, weights, auxbas_pw_pool, &
    1009          616 :                                  .FALSE., v_xc, v_xc_tau)
    1010              :          END IF
    1011          642 :          IF (gapw .OR. gapw_xc) THEN
    1012          156 :             CALL get_qs_env(qs_env, rho_atom_set=rho_atom_set)
    1013          156 :             rho1_atom_set => local_rho_set%rho_atom_set
    1014              :             CALL calculate_xc_2nd_deriv_atom(rho_atom_set, rho1_atom_set, qs_env, xc_section, para_env, &
    1015          156 :                                              do_triplet=.FALSE.)
    1016              :          END IF
    1017              :       ELSE
    1018            0 :          CPABORT("NYA 00006")
    1019            0 :          NULLIFY (v_xc, trho)
    1020            0 :          ALLOCATE (trho)
    1021            0 :          CALL qs_rho_create(trho)
    1022            0 :          CALL qs_rho_set(trho, rho_r=trho_r, rho_g=trho_g)
    1023            0 :          CALL qs_fxc_fdiff(ks_env, rho, trho, xc_section, 6, .FALSE., v_xc, v_xc_tau)
    1024            0 :          DEALLOCATE (trho)
    1025              :       END IF
    1026              : 
    1027         1392 :       DO ispin = 1, nspins
    1028          750 :          CALL dbcsr_set(matrix_hz(ispin)%matrix, 0.0_dp)
    1029         1392 :          CALL pw_scale(v_xc(ispin), v_xc(ispin)%pw_grid%dvol)
    1030              :       END DO
    1031          642 :       IF (gapw_xc) THEN
    1032           52 :          DO ispin = 1, nspins
    1033              :             CALL integrate_v_rspace(qs_env=qs_env, v_rspace=v_hartree_rspace, &
    1034              :                                     hmat=matrix_hz(ispin), &
    1035           26 :                                     calculate_forces=.FALSE.)
    1036              :             CALL integrate_v_rspace(qs_env=qs_env, v_rspace=v_xc(ispin), &
    1037              :                                     hmat=matrix_hz(ispin), &
    1038           52 :                                     gapw=gapw_xc, calculate_forces=.FALSE.)
    1039              :          END DO
    1040              :       ELSE
    1041              :          ! vtot = v_xc(ispin) + v_hartree
    1042         1340 :          DO ispin = 1, nspins
    1043              :             CALL integrate_v_rspace(qs_env=qs_env, v_rspace=v_xc(ispin), &
    1044              :                                     hmat=matrix_hz(ispin), &
    1045          724 :                                     gapw=gapw, calculate_forces=.FALSE.)
    1046              :             CALL integrate_v_rspace(qs_env=qs_env, v_rspace=v_hartree_rspace, &
    1047              :                                     hmat=matrix_hz(ispin), &
    1048         1340 :                                     gapw=gapw, calculate_forces=.FALSE.)
    1049              :          END DO
    1050              :       END IF
    1051          642 :       IF (gapw .OR. gapw_xc) THEN
    1052          156 :          mhz(1:nspins, 1:1) => matrix_hz(1:nspins)
    1053          156 :          mpe(1:nspins, 1:1) => matrix_pe(1:nspins)
    1054              :          CALL update_ks_atom(qs_env, mhz, mpe, forces=.FALSE., &
    1055          156 :                              rho_atom_external=local_rho_set%rho_atom_set)
    1056              :       END IF
    1057              : 
    1058          642 :       CALL auxbas_pw_pool%give_back_pw(v_hartree_gspace)
    1059          642 :       CALL auxbas_pw_pool%give_back_pw(v_hartree_rspace)
    1060          642 :       CALL auxbas_pw_pool%give_back_pw(rho_tot_gspace)
    1061         1392 :       DO ispin = 1, nspins
    1062          750 :          CALL auxbas_pw_pool%give_back_pw(trho_r(ispin))
    1063          750 :          CALL auxbas_pw_pool%give_back_pw(trho_g(ispin))
    1064         1392 :          CALL auxbas_pw_pool%give_back_pw(v_xc(ispin))
    1065              :       END DO
    1066          642 :       DEALLOCATE (trho_r, trho_g, v_xc)
    1067          642 :       IF (ASSOCIATED(trho_tau_r)) THEN
    1068            0 :          DO ispin = 1, nspins
    1069            0 :             CALL auxbas_pw_pool%give_back_pw(trho_tau_r(ispin))
    1070            0 :             CALL auxbas_pw_pool%give_back_pw(trho_tau_g(ispin))
    1071              :          END DO
    1072            0 :          DEALLOCATE (trho_tau_r, trho_tau_g)
    1073              :       END IF
    1074          642 :       IF (gapw_xc) THEN
    1075           52 :          DO ispin = 1, nspins
    1076           26 :             CALL auxbas_pw_pool%give_back_pw(trho_xc_r(ispin))
    1077           52 :             CALL auxbas_pw_pool%give_back_pw(trho_xc_g(ispin))
    1078              :          END DO
    1079           26 :          DEALLOCATE (trho_xc_r, trho_xc_g)
    1080           26 :          IF (ASSOCIATED(trho_xc_tau_r)) THEN
    1081            0 :             DO ispin = 1, nspins
    1082            0 :                CALL auxbas_pw_pool%give_back_pw(trho_xc_tau_r(ispin))
    1083            0 :                CALL auxbas_pw_pool%give_back_pw(trho_xc_tau_g(ispin))
    1084              :             END DO
    1085            0 :             DEALLOCATE (trho_xc_tau_r, trho_xc_tau_g)
    1086              :          END IF
    1087              :       END IF
    1088          642 :       IF (ASSOCIATED(v_xc_tau)) THEN
    1089            0 :          DO ispin = 1, nspins
    1090            0 :             CALL auxbas_pw_pool%give_back_pw(v_xc_tau(ispin))
    1091              :          END DO
    1092            0 :          DEALLOCATE (v_xc_tau)
    1093              :       END IF
    1094          642 :       IF (dft_control%do_admm) THEN
    1095          142 :          IF (qs_env%admm_env%aux_exch_func /= do_admm_aux_exch_func_none) THEN
    1096              :             ! add ADMM xc_section_aux terms: f_x[rhoz_ADMM]
    1097           86 :             CALL get_qs_env(qs_env, admm_env=admm_env)
    1098              :             CALL get_admm_env(admm_env, rho_aux_fit=rho_aux_fit, matrix_s_aux_fit=msaux, &
    1099           86 :                               task_list_aux_fit=task_list)
    1100           86 :             basis_type = "AUX_FIT"
    1101              :             !
    1102           86 :             NULLIFY (mpe, mhz)
    1103          438 :             ALLOCATE (mpe(nspins, 1))
    1104           86 :             CALL dbcsr_allocate_matrix_set(mhz, nspins, 1)
    1105          180 :             DO ispin = 1, nspins
    1106           94 :                ALLOCATE (mhz(ispin, 1)%matrix)
    1107           94 :                CALL dbcsr_create(mhz(ispin, 1)%matrix, template=msaux(1)%matrix)
    1108           94 :                CALL dbcsr_copy(mhz(ispin, 1)%matrix, msaux(1)%matrix)
    1109           94 :                CALL dbcsr_set(mhz(ispin, 1)%matrix, 0.0_dp)
    1110          180 :                mpe(ispin, 1)%matrix => matrix_pe_admm(ispin)%matrix
    1111              :             END DO
    1112              :             !
    1113              :             ! GAPW/GAPW_XC initializations
    1114           86 :             NULLIFY (local_rho_set_admm)
    1115           86 :             IF (admm_env%do_gapw) THEN
    1116           12 :                basis_type = "AUX_FIT_SOFT"
    1117           12 :                task_list => admm_env%admm_gapw_env%task_list
    1118           12 :                CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set)
    1119           12 :                CALL get_admm_env(admm_env, sab_aux_fit=sab_aux_fit)
    1120           12 :                CALL local_rho_set_create(local_rho_set_admm)
    1121              :                CALL allocate_rho_atom_internals(local_rho_set_admm%rho_atom_set, atomic_kind_set, &
    1122           12 :                                                 admm_env%admm_gapw_env%admm_kind_set, dft_control, para_env)
    1123              :                CALL calculate_rho_atom_coeff(qs_env, matrix_pe_admm, &
    1124              :                                              rho_atom_set=local_rho_set_admm%rho_atom_set, &
    1125              :                                              qs_kind_set=admm_env%admm_gapw_env%admm_kind_set, &
    1126           12 :                                              oce=admm_env%admm_gapw_env%oce, sab=sab_aux_fit, para_env=para_env)
    1127              :                CALL prepare_gapw_den(qs_env, local_rho_set=local_rho_set_admm, &
    1128           12 :                                      do_rho0=.FALSE., kind_set_external=admm_env%admm_gapw_env%admm_kind_set)
    1129              :             END IF
    1130              :             !
    1131           86 :             xc_section => admm_env%xc_section_aux
    1132           86 :             xc_fun_section => section_vals_get_subs_vals(xc_section, "XC_FUNCTIONAL")
    1133           86 :             needs = xc_functionals_get_needs(xc_fun_section, (nspins == 2), .TRUE.)
    1134           86 :             needs_tau_response = needs%tau .OR. needs%tau_spin
    1135              :             !
    1136           86 :             NULLIFY (rho_g_aux, rho_r_aux, rhoz_g_aux, rhoz_r_aux, rhoz_tau_g_aux, rhoz_tau_r_aux)
    1137           86 :             CALL qs_rho_get(rho_aux_fit, rho_r=rho_r_aux, rho_g=rho_g_aux)
    1138              :             ! rhoz_aux
    1139          446 :             ALLOCATE (rhoz_r_aux(nspins), rhoz_g_aux(nspins))
    1140          180 :             DO ispin = 1, nspins
    1141           94 :                CALL auxbas_pw_pool%create_pw(rhoz_r_aux(ispin))
    1142          180 :                CALL auxbas_pw_pool%create_pw(rhoz_g_aux(ispin))
    1143              :             END DO
    1144           86 :             IF (needs_tau_response) THEN
    1145            0 :                ALLOCATE (rhoz_tau_r_aux(nspins), rhoz_tau_g_aux(nspins))
    1146            0 :                DO ispin = 1, nspins
    1147            0 :                   CALL auxbas_pw_pool%create_pw(rhoz_tau_r_aux(ispin))
    1148            0 :                   CALL auxbas_pw_pool%create_pw(rhoz_tau_g_aux(ispin))
    1149              :                END DO
    1150              :             END IF
    1151          180 :             DO ispin = 1, nspins
    1152              :                CALL calculate_rho_elec(ks_env=ks_env, matrix_p=mpe(ispin, 1)%matrix, &
    1153              :                                        rho=rhoz_r_aux(ispin), rho_gspace=rhoz_g_aux(ispin), &
    1154              :                                        basis_type=basis_type, &
    1155           94 :                                        task_list_external=task_list)
    1156          180 :                IF (needs_tau_response) THEN
    1157              :                   CALL calculate_rho_elec(ks_env=ks_env, matrix_p=mpe(ispin, 1)%matrix, &
    1158              :                                           rho=rhoz_tau_r_aux(ispin), rho_gspace=rhoz_tau_g_aux(ispin), &
    1159              :                                           basis_type=basis_type, task_list_external=task_list, &
    1160            0 :                                           compute_tau=.TRUE.)
    1161              :                END IF
    1162              :             END DO
    1163              :             !
    1164           86 :             NULLIFY (v_xc, v_xc_tau)
    1165           86 :             deriv2_analytic = section_get_lval(xc_section, "2ND_DERIV_ANALYTICAL")
    1166           86 :             IF (deriv2_analytic) THEN
    1167           86 :                CALL get_qs_env(qs_env=qs_env, xcint_weights=weights)
    1168              :                CALL qs_fxc_analytic(rho_aux_fit, rhoz_r_aux, rhoz_tau_r_aux, xc_section, weights, auxbas_pw_pool, &
    1169           86 :                                     .FALSE., v_xc, v_xc_tau)
    1170              :             ELSE
    1171            0 :                CPABORT("NYA 00007")
    1172              :                NULLIFY (rhoz_aux)
    1173            0 :                ALLOCATE (rhoz_aux)
    1174            0 :                CALL qs_rho_create(rhoz_aux)
    1175            0 :                CALL qs_rho_set(rhoz_aux, rho_r=rhoz_r_aux, rho_g=rhoz_g_aux)
    1176            0 :                CALL qs_fxc_fdiff(ks_env, rho_aux_fit, rhoz_aux, xc_section, 6, .FALSE., v_xc, v_xc_tau)
    1177            0 :                DEALLOCATE (rhoz_aux)
    1178              :             END IF
    1179              :             !
    1180          180 :             DO ispin = 1, nspins
    1181           94 :                CALL pw_scale(v_xc(ispin), v_xc(ispin)%pw_grid%dvol)
    1182              :                CALL integrate_v_rspace(qs_env=qs_env, v_rspace=v_xc(ispin), &
    1183              :                                        hmat=mhz(ispin, 1), basis_type=basis_type, &
    1184              :                                        calculate_forces=.FALSE., &
    1185          180 :                                        task_list_external=task_list)
    1186              :             END DO
    1187          180 :             DO ispin = 1, nspins
    1188           94 :                CALL auxbas_pw_pool%give_back_pw(v_xc(ispin))
    1189           94 :                CALL auxbas_pw_pool%give_back_pw(rhoz_r_aux(ispin))
    1190          180 :                CALL auxbas_pw_pool%give_back_pw(rhoz_g_aux(ispin))
    1191              :             END DO
    1192           86 :             DEALLOCATE (v_xc, rhoz_r_aux, rhoz_g_aux)
    1193           86 :             IF (ASSOCIATED(v_xc_tau)) THEN
    1194            0 :                DO ispin = 1, nspins
    1195            0 :                   CALL auxbas_pw_pool%give_back_pw(v_xc_tau(ispin))
    1196              :                END DO
    1197            0 :                DEALLOCATE (v_xc_tau)
    1198              :             END IF
    1199           86 :             IF (ASSOCIATED(rhoz_tau_r_aux)) THEN
    1200            0 :                DO ispin = 1, nspins
    1201            0 :                   CALL auxbas_pw_pool%give_back_pw(rhoz_tau_r_aux(ispin))
    1202            0 :                   CALL auxbas_pw_pool%give_back_pw(rhoz_tau_g_aux(ispin))
    1203              :                END DO
    1204            0 :                DEALLOCATE (rhoz_tau_r_aux, rhoz_tau_g_aux)
    1205              :             END IF
    1206              :             !
    1207           86 :             IF (admm_env%do_gapw) THEN
    1208           12 :                rho_atom_set => admm_env%admm_gapw_env%local_rho_set%rho_atom_set
    1209           12 :                rho1_atom_set => local_rho_set_admm%rho_atom_set
    1210              :                CALL calculate_xc_2nd_deriv_atom(rho_atom_set, rho1_atom_set, qs_env, xc_section, &
    1211           12 :                                                 para_env, kind_set_external=admm_env%admm_gapw_env%admm_kind_set)
    1212              :                CALL update_ks_atom(qs_env, mhz(:, 1), matrix_pe_admm, forces=.FALSE., tddft=.FALSE., &
    1213              :                                    rho_atom_external=rho1_atom_set, &
    1214              :                                    kind_set_external=admm_env%admm_gapw_env%admm_kind_set, &
    1215              :                                    oce_external=admm_env%admm_gapw_env%oce, &
    1216           12 :                                    sab_external=sab_aux_fit)
    1217              :             END IF
    1218              :             !
    1219           86 :             nao = admm_env%nao_orb
    1220           86 :             nao_aux = admm_env%nao_aux_fit
    1221           86 :             ALLOCATE (dbwork)
    1222           86 :             CALL dbcsr_create(dbwork, template=matrix_hz(1)%matrix)
    1223          180 :             DO ispin = 1, nspins
    1224              :                CALL cp_dbcsr_sm_fm_multiply(mhz(ispin, 1)%matrix, admm_env%A, &
    1225           94 :                                             admm_env%work_aux_orb, nao)
    1226              :                CALL parallel_gemm('T', 'N', nao, nao, nao_aux, &
    1227              :                                   1.0_dp, admm_env%A, admm_env%work_aux_orb, 0.0_dp, &
    1228           94 :                                   admm_env%work_orb_orb)
    1229           94 :                CALL dbcsr_copy(dbwork, matrix_hz(1)%matrix)
    1230           94 :                CALL dbcsr_set(dbwork, 0.0_dp)
    1231           94 :                CALL copy_fm_to_dbcsr(admm_env%work_orb_orb, dbwork, keep_sparsity=.TRUE.)
    1232          180 :                CALL dbcsr_add(matrix_hz(ispin)%matrix, dbwork, 1.0_dp, 1.0_dp)
    1233              :             END DO
    1234           86 :             CALL dbcsr_release(dbwork)
    1235           86 :             DEALLOCATE (dbwork)
    1236           86 :             CALL dbcsr_deallocate_matrix_set(mhz)
    1237           86 :             DEALLOCATE (mpe)
    1238           86 :             IF (admm_env%do_gapw) THEN
    1239           12 :                IF (ASSOCIATED(local_rho_set_admm)) CALL local_rho_set_release(local_rho_set_admm)
    1240              :             END IF
    1241              :          END IF
    1242              :       END IF
    1243          642 :       IF (gapw .OR. gapw_xc) THEN
    1244          156 :          IF (ASSOCIATED(local_rho_set)) CALL local_rho_set_release(local_rho_set)
    1245          156 :          IF (ASSOCIATED(hartree_local)) CALL hartree_local_release(hartree_local)
    1246              :       END IF
    1247              : 
    1248              :       ! HFX
    1249          642 :       hfx_section => section_vals_get_subs_vals(xc_section, "HF")
    1250          642 :       CALL section_vals_get(hfx_section, explicit=do_hfx)
    1251          642 :       IF (do_hfx) THEN
    1252          280 :          CALL section_vals_get(hfx_section, n_repetition=n_rep_hf)
    1253          280 :          CPASSERT(n_rep_hf == 1)
    1254              :          CALL section_vals_val_get(hfx_section, "TREAT_LSD_IN_CORE", l_val=hfx_treat_lsd_in_core, &
    1255          280 :                                    i_rep_section=1)
    1256          280 :          mspin = 1
    1257          280 :          IF (hfx_treat_lsd_in_core) mspin = nspins
    1258              :          !
    1259              :          CALL get_qs_env(qs_env=qs_env, rho=rho, x_data=x_data, para_env=para_env, &
    1260          280 :                          s_mstruct_changed=s_mstruct_changed)
    1261          280 :          distribute_fock_matrix = .TRUE.
    1262          280 :          IF (dft_control%do_admm) THEN
    1263          142 :             CALL get_qs_env(qs_env, admm_env=admm_env)
    1264          142 :             CALL get_admm_env(admm_env, matrix_s_aux_fit=msaux)
    1265          142 :             NULLIFY (mpe, mhz)
    1266          730 :             ALLOCATE (mpe(nspins, 1))
    1267          142 :             CALL dbcsr_allocate_matrix_set(mhz, nspins, 1)
    1268          304 :             DO ispin = 1, nspins
    1269          162 :                ALLOCATE (mhz(ispin, 1)%matrix)
    1270          162 :                CALL dbcsr_create(mhz(ispin, 1)%matrix, template=msaux(1)%matrix)
    1271          162 :                CALL dbcsr_copy(mhz(ispin, 1)%matrix, msaux(1)%matrix)
    1272          162 :                CALL dbcsr_set(mhz(ispin, 1)%matrix, 0.0_dp)
    1273          304 :                mpe(ispin, 1)%matrix => matrix_pe_admm(ispin)%matrix
    1274              :             END DO
    1275          142 :             IF (x_data(1, 1)%do_hfx_ri) THEN
    1276              :                eh1 = 0.0_dp
    1277              :                CALL hfx_ri_update_ks(qs_env, x_data(1, 1)%ri_data, mhz, eh1, rho_ao=mpe, &
    1278              :                                      geometry_did_change=s_mstruct_changed, nspins=nspins, &
    1279            6 :                                      hf_fraction=x_data(1, 1)%general_parameter%fraction)
    1280              :             ELSE
    1281          272 :                DO ispin = 1, mspin
    1282              :                   eh1 = 0.0
    1283              :                   CALL integrate_four_center(qs_env, x_data, mhz, eh1, mpe, hfx_section, &
    1284              :                                              para_env, s_mstruct_changed, 1, distribute_fock_matrix, &
    1285          272 :                                              ispin=ispin)
    1286              :                END DO
    1287              :             END IF
    1288              :             !
    1289          142 :             CPASSERT(ASSOCIATED(admm_env%work_aux_orb))
    1290          142 :             CPASSERT(ASSOCIATED(admm_env%work_orb_orb))
    1291          142 :             nao = admm_env%nao_orb
    1292          142 :             nao_aux = admm_env%nao_aux_fit
    1293          142 :             ALLOCATE (dbwork)
    1294          142 :             CALL dbcsr_create(dbwork, template=matrix_hz(1)%matrix)
    1295          304 :             DO ispin = 1, nspins
    1296              :                CALL cp_dbcsr_sm_fm_multiply(mhz(ispin, 1)%matrix, admm_env%A, &
    1297          162 :                                             admm_env%work_aux_orb, nao)
    1298              :                CALL parallel_gemm('T', 'N', nao, nao, nao_aux, &
    1299              :                                   1.0_dp, admm_env%A, admm_env%work_aux_orb, 0.0_dp, &
    1300          162 :                                   admm_env%work_orb_orb)
    1301          162 :                CALL dbcsr_copy(dbwork, matrix_hz(ispin)%matrix)
    1302          162 :                CALL dbcsr_set(dbwork, 0.0_dp)
    1303          162 :                CALL copy_fm_to_dbcsr(admm_env%work_orb_orb, dbwork, keep_sparsity=.TRUE.)
    1304          304 :                CALL dbcsr_add(matrix_hz(ispin)%matrix, dbwork, 1.0_dp, 1.0_dp)
    1305              :             END DO
    1306          142 :             CALL dbcsr_release(dbwork)
    1307          142 :             DEALLOCATE (dbwork)
    1308          142 :             CALL dbcsr_deallocate_matrix_set(mhz)
    1309          142 :             DEALLOCATE (mpe)
    1310              :          ELSE
    1311          138 :             NULLIFY (mpe, mhz)
    1312         1152 :             ALLOCATE (mpe(nspins, 1), mhz(nspins, 1))
    1313          300 :             DO ispin = 1, nspins
    1314          162 :                mhz(ispin, 1)%matrix => matrix_hz(ispin)%matrix
    1315          300 :                mpe(ispin, 1)%matrix => matrix_pe(ispin)%matrix
    1316              :             END DO
    1317          138 :             IF (x_data(1, 1)%do_hfx_ri) THEN
    1318              :                eh1 = 0.0_dp
    1319              :                CALL hfx_ri_update_ks(qs_env, x_data(1, 1)%ri_data, mhz, eh1, rho_ao=mpe, &
    1320              :                                      geometry_did_change=s_mstruct_changed, nspins=nspins, &
    1321           18 :                                      hf_fraction=x_data(1, 1)%general_parameter%fraction)
    1322              :             ELSE
    1323          240 :                DO ispin = 1, mspin
    1324              :                   eh1 = 0.0
    1325              :                   CALL integrate_four_center(qs_env, x_data, mhz, eh1, mpe, hfx_section, &
    1326              :                                              para_env, s_mstruct_changed, 1, distribute_fock_matrix, &
    1327          240 :                                              ispin=ispin)
    1328              :                END DO
    1329              :             END IF
    1330          138 :             DEALLOCATE (mpe, mhz)
    1331              :          END IF
    1332              :       END IF
    1333              : 
    1334          642 :       focc = 4.0_dp
    1335          642 :       IF (nspins == 2) focc = 2.0_dp
    1336         1392 :       DO ispin = 1, nspins
    1337          750 :          mos => gs_mos(ispin)%mos_occ
    1338          750 :          CALL cp_fm_get_info(mos, ncol_global=norb)
    1339              :          CALL cp_dbcsr_sm_fm_multiply(matrix_hz(ispin)%matrix, mos, cpmos(ispin), &
    1340         1392 :                                       norb, alpha=focc, beta=0.0_dp)
    1341              :       END DO
    1342              : 
    1343          642 :       CALL timestop(handle)
    1344              : 
    1345         1926 :    END SUBROUTINE tddfpt_resvec2
    1346              : 
    1347              : ! **************************************************************************************************
    1348              : !> \brief ...
    1349              : !> \param qs_env ...
    1350              : !> \param matrix_pe ...
    1351              : !> \param gs_mos ...
    1352              : !> \param matrix_hz ...
    1353              : !> \param cpmos ...
    1354              : ! **************************************************************************************************
    1355           16 :    SUBROUTINE tddfpt_resvec2_xtb(qs_env, matrix_pe, gs_mos, matrix_hz, cpmos)
    1356              : 
    1357              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1358              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_pe
    1359              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
    1360              :          POINTER                                         :: gs_mos
    1361              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_hz
    1362              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT)      :: cpmos
    1363              : 
    1364              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_resvec2_xtb'
    1365              : 
    1366              :       INTEGER                                            :: atom_a, handle, iatom, ikind, is, ispin, &
    1367              :                                                             na, natom, natorb, nkind, norb, ns, &
    1368              :                                                             nsgf, nspins
    1369              :       INTEGER, DIMENSION(25)                             :: lao
    1370              :       INTEGER, DIMENSION(5)                              :: occ
    1371           16 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: mcharge, mcharge1
    1372           16 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: aocg, aocg1, charges, charges1
    1373              :       REAL(KIND=dp)                                      :: focc
    1374           16 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1375              :       TYPE(cp_fm_type), POINTER                          :: mos
    1376           16 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: p_matrix
    1377           16 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_p, matrix_s
    1378              :       TYPE(dbcsr_type), POINTER                          :: s_matrix
    1379              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1380              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1381           16 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1382           16 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1383              :       TYPE(qs_rho_type), POINTER                         :: rho
    1384              :       TYPE(xtb_atom_type), POINTER                       :: xtb_kind
    1385              : 
    1386           16 :       CALL timeset(routineN, handle)
    1387              : 
    1388           16 :       CPASSERT(ASSOCIATED(matrix_pe))
    1389              : 
    1390           16 :       CALL get_qs_env(qs_env=qs_env, dft_control=dft_control)
    1391           16 :       nspins = dft_control%nspins
    1392              : 
    1393           32 :       DO ispin = 1, nspins
    1394           32 :          CALL dbcsr_set(matrix_hz(ispin)%matrix, 0.0_dp)
    1395              :       END DO
    1396              : 
    1397           16 :       IF (dft_control%qs_control%xtb_control%coulomb_interaction) THEN
    1398              :          ! Mulliken charges
    1399              :          CALL get_qs_env(qs_env, rho=rho, particle_set=particle_set, &
    1400           14 :                          matrix_s_kp=matrix_s, para_env=para_env)
    1401           14 :          natom = SIZE(particle_set)
    1402           14 :          CALL qs_rho_get(rho, rho_ao_kp=matrix_p)
    1403           70 :          ALLOCATE (mcharge(natom), charges(natom, 5))
    1404           42 :          ALLOCATE (mcharge1(natom), charges1(natom, 5))
    1405         1254 :          charges = 0.0_dp
    1406         1254 :          charges1 = 0.0_dp
    1407           14 :          CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, qs_kind_set=qs_kind_set)
    1408           14 :          nkind = SIZE(atomic_kind_set)
    1409           14 :          CALL get_qs_kind_set(qs_kind_set, maxsgf=nsgf)
    1410           56 :          ALLOCATE (aocg(nsgf, natom))
    1411         1184 :          aocg = 0.0_dp
    1412           42 :          ALLOCATE (aocg1(nsgf, natom))
    1413         1184 :          aocg1 = 0.0_dp
    1414           14 :          p_matrix => matrix_p(:, 1)
    1415           14 :          s_matrix => matrix_s(1, 1)%matrix
    1416           14 :          CALL ao_charges(p_matrix, s_matrix, aocg, para_env)
    1417           14 :          CALL ao_charges(matrix_pe, s_matrix, aocg1, para_env)
    1418           48 :          DO ikind = 1, nkind
    1419           34 :             CALL get_atomic_kind(atomic_kind_set(ikind), natom=na)
    1420           34 :             CALL get_qs_kind(qs_kind_set(ikind), xtb_parameter=xtb_kind)
    1421           34 :             CALL get_xtb_atom_param(xtb_kind, natorb=natorb, lao=lao, occupation=occ)
    1422          316 :             DO iatom = 1, na
    1423          234 :                atom_a = atomic_kind_set(ikind)%atom_list(iatom)
    1424         1404 :                charges(atom_a, :) = REAL(occ(:), KIND=dp)
    1425          900 :                DO is = 1, natorb
    1426          632 :                   ns = lao(is) + 1
    1427          632 :                   charges(atom_a, ns) = charges(atom_a, ns) - aocg(is, atom_a)
    1428          866 :                   charges1(atom_a, ns) = charges1(atom_a, ns) - aocg1(is, atom_a)
    1429              :                END DO
    1430              :             END DO
    1431              :          END DO
    1432           14 :          DEALLOCATE (aocg, aocg1)
    1433          248 :          DO iatom = 1, natom
    1434         1404 :             mcharge(iatom) = SUM(charges(iatom, :))
    1435         1418 :             mcharge1(iatom) = SUM(charges1(iatom, :))
    1436              :          END DO
    1437              :          ! Coulomb Kernel
    1438           14 :          CALL xtb_coulomb_hessian(qs_env, matrix_hz, charges1, mcharge1, mcharge)
    1439              :          !
    1440           28 :          DEALLOCATE (charges, mcharge, charges1, mcharge1)
    1441              :       END IF
    1442              : 
    1443           16 :       focc = 2.0_dp
    1444           16 :       IF (nspins == 2) focc = 1.0_dp
    1445           32 :       DO ispin = 1, nspins
    1446           16 :          mos => gs_mos(ispin)%mos_occ
    1447           16 :          CALL cp_fm_get_info(mos, ncol_global=norb)
    1448              :          CALL cp_dbcsr_sm_fm_multiply(matrix_hz(ispin)%matrix, mos, cpmos(ispin), &
    1449           32 :                                       norb, alpha=focc, beta=0.0_dp)
    1450              :       END DO
    1451              : 
    1452           16 :       CALL timestop(handle)
    1453              : 
    1454           32 :    END SUBROUTINE tddfpt_resvec2_xtb
    1455              : 
    1456              : ! **************************************************************************************************
    1457              : !> \brief ...
    1458              : !> \param qs_env ...
    1459              : !> \param cpmos ...
    1460              : !> \param work ...
    1461              : ! **************************************************************************************************
    1462          658 :    SUBROUTINE tddfpt_resvec3(qs_env, cpmos, work)
    1463              : 
    1464              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1465              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: cpmos
    1466              :       TYPE(tddfpt_work_matrices)                         :: work
    1467              : 
    1468              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'tddfpt_resvec3'
    1469              : 
    1470              :       INTEGER                                            :: handle, ispin, nao, norb, nspins
    1471              :       TYPE(cp_fm_struct_type), POINTER                   :: fmstruct
    1472              :       TYPE(cp_fm_type)                                   :: cvec, umat
    1473              :       TYPE(cp_fm_type), POINTER                          :: omos
    1474              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1475          658 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    1476              : 
    1477          658 :       CALL timeset(routineN, handle)
    1478              : 
    1479          658 :       CALL get_qs_env(qs_env, mos=mos, dft_control=dft_control)
    1480          658 :       nspins = dft_control%nspins
    1481              : 
    1482         1424 :       DO ispin = 1, nspins
    1483          766 :          CALL get_mo_set(mos(ispin), mo_coeff=omos)
    1484              :          ASSOCIATE (rvecs => cpmos(ispin))
    1485          766 :             CALL cp_fm_get_info(rvecs, nrow_global=nao, ncol_global=norb)
    1486          766 :             CALL cp_fm_create(cvec, rvecs%matrix_struct, "cvec")
    1487              :             CALL cp_fm_struct_create(fmstruct, context=rvecs%matrix_struct%context, nrow_global=norb, &
    1488          766 :                                      ncol_global=norb, para_env=rvecs%matrix_struct%para_env)
    1489          766 :             CALL cp_fm_create(umat, fmstruct, "umat")
    1490          766 :             CALL cp_fm_struct_release(fmstruct)
    1491              :             !
    1492          766 :             CALL parallel_gemm("T", "N", norb, norb, nao, 1.0_dp, omos, work%S_C0(ispin), 0.0_dp, umat)
    1493          766 :             CALL cp_fm_copy_general(rvecs, cvec, rvecs%matrix_struct%para_env)
    1494          766 :             CALL parallel_gemm("N", "T", nao, norb, norb, 1.0_dp, cvec, umat, 0.0_dp, rvecs)
    1495              :          END ASSOCIATE
    1496          766 :          CALL cp_fm_release(cvec)
    1497         2956 :          CALL cp_fm_release(umat)
    1498              :       END DO
    1499              : 
    1500          658 :       CALL timestop(handle)
    1501              : 
    1502          658 :    END SUBROUTINE tddfpt_resvec3
    1503              : 
    1504              : ! **************************************************************************************************
    1505              : !> \brief Calculate direct tddft forces
    1506              : !> \param qs_env ...
    1507              : !> \param ex_env ...
    1508              : !> \param gs_mos ...
    1509              : !> \param kernel_env ...
    1510              : !> \param sub_env ...
    1511              : !> \param work_matrices ...
    1512              : !> \param debug_forces ...
    1513              : !> \par History
    1514              : !>    * 01.2020 screated [JGH]
    1515              : ! **************************************************************************************************
    1516          658 :    SUBROUTINE tddfpt_kernel_force(qs_env, ex_env, gs_mos, kernel_env, sub_env, work_matrices, debug_forces)
    1517              : 
    1518              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1519              :       TYPE(excited_energy_type), POINTER                 :: ex_env
    1520              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
    1521              :          POINTER                                         :: gs_mos
    1522              :       TYPE(kernel_env_type), INTENT(IN)                  :: kernel_env
    1523              :       TYPE(tddfpt_subgroup_env_type)                     :: sub_env
    1524              :       TYPE(tddfpt_work_matrices)                         :: work_matrices
    1525              :       LOGICAL, INTENT(IN)                                :: debug_forces
    1526              : 
    1527              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_kernel_force'
    1528              : 
    1529              :       INTEGER                                            :: handle
    1530              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1531              :       TYPE(tddfpt2_control_type), POINTER                :: tddfpt_control
    1532              : 
    1533          658 :       CALL timeset(routineN, handle)
    1534              : 
    1535          658 :       CALL get_qs_env(qs_env, dft_control=dft_control)
    1536          658 :       tddfpt_control => dft_control%tddfpt2_control
    1537              : 
    1538          658 :       IF (tddfpt_control%kernel == tddfpt_kernel_full) THEN
    1539              :          ! full Kernel
    1540          420 :          CALL fhxc_force(qs_env, ex_env, gs_mos, kernel_env%full_kernel, debug_forces)
    1541          238 :       ELSE IF (tddfpt_control%kernel == tddfpt_kernel_stda) THEN
    1542              :          ! sTDA Kernel
    1543          160 :          CALL stda_force(qs_env, ex_env, gs_mos, kernel_env%stda_kernel, sub_env, work_matrices, debug_forces)
    1544           78 :       ELSE IF (tddfpt_control%kernel == tddfpt_kernel_none) THEN
    1545              :          ! nothing to be done here
    1546           78 :          ex_env%matrix_wx1 => NULL()
    1547              :       ELSE
    1548            0 :          CPABORT('Unknown kernel type')
    1549              :       END IF
    1550              : 
    1551          658 :       CALL timestop(handle)
    1552              : 
    1553          658 :    END SUBROUTINE tddfpt_kernel_force
    1554              : 
    1555              : END MODULE qs_tddfpt2_forces
        

Generated by: LCOV version 2.0-1