LCOV - code coverage report
Current view: top level - src - rpa_gw_kpoints_util.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:62906da) Lines: 87.3 % 511 446
Test Date: 2026-10-24 01:17:15 Functions: 100.0 % 19 19

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Routines treating GW and RPA calculations with kpoints
      10              : !> \par History
      11              : !>      since 2018 continuous development [J. Wilhelm]
      12              : ! **************************************************************************************************
      13              : MODULE rpa_gw_kpoints_util
      14              :    USE cell_types,                      ONLY: cell_type,&
      15              :                                               get_cell,&
      16              :                                               minimum_image_weights
      17              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      18              :    USE cp_cfm_basic_linalg,             ONLY: cp_cfm_add_on_diag,&
      19              :                                               cp_cfm_get_diag,&
      20              :                                               cp_cfm_scale_and_add_fm,&
      21              :                                               cp_cfm_uplo_to_full
      22              :    USE cp_cfm_cholesky,                 ONLY: cp_cfm_cholesky_decompose,&
      23              :                                               cp_cfm_cholesky_invert
      24              :    USE cp_cfm_diag,                     ONLY: cp_cfm_geeig,&
      25              :                                               cp_cfm_geeig_canon,&
      26              :                                               cp_cfm_power
      27              :    USE cp_cfm_types,                    ONLY: cp_cfm_copy_general,&
      28              :                                               cp_cfm_create,&
      29              :                                               cp_cfm_get_info,&
      30              :                                               cp_cfm_release,&
      31              :                                               cp_cfm_set_all,&
      32              :                                               cp_cfm_to_cfm,&
      33              :                                               cp_cfm_type,&
      34              :                                               cp_fm_to_cfm
      35              :    USE cp_control_types,                ONLY: dft_control_type
      36              :    USE cp_dbcsr_api,                    ONLY: &
      37              :         dbcsr_copy, dbcsr_create, dbcsr_deallocate_matrix, dbcsr_desymmetrize, dbcsr_filter, &
      38              :         dbcsr_get_block_p, dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, &
      39              :         dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_p_type, &
      40              :         dbcsr_release, dbcsr_set, dbcsr_transposed, dbcsr_type, dbcsr_type_no_symmetry
      41              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_reserve_all_blocks
      42              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      43              :                                               copy_fm_to_dbcsr,&
      44              :                                               dbcsr_allocate_matrix_set
      45              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_scale_and_add
      46              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_type
      47              :    USE cp_fm_types,                     ONLY: cp_fm_copy_general,&
      48              :                                               cp_fm_create,&
      49              :                                               cp_fm_release,&
      50              :                                               cp_fm_set_all,&
      51              :                                               cp_fm_type
      52              :    USE gw_utils_fm,                     ONLY: cfm_contract_ABA
      53              :    USE hfx_types,                       ONLY: hfx_release
      54              :    USE input_constants,                 ONLY: cholesky_off,&
      55              :                                               kp_weights_W_auto,&
      56              :                                               kp_weights_W_tailored,&
      57              :                                               kp_weights_W_uniform
      58              :    USE kinds,                           ONLY: dp
      59              :    USE kpoint_methods,                  ONLY: kpoint_env_initialize,&
      60              :                                               kpoint_initialize_mo_set,&
      61              :                                               kpoint_initialize_mos
      62              :    USE kpoint_types,                    ONLY: get_kpoint_info,&
      63              :                                               kpoint_env_type,&
      64              :                                               kpoint_type
      65              :    USE machine,                         ONLY: m_walltime
      66              :    USE mathconstants,                   ONLY: gaussi,&
      67              :                                               twopi,&
      68              :                                               z_one,&
      69              :                                               z_zero
      70              :    USE mathlib,                         ONLY: invmat
      71              :    USE message_passing,                 ONLY: mp_para_env_type
      72              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      73              :    USE particle_types,                  ONLY: particle_type
      74              :    USE qs_band_structure,               ONLY: calculate_kpoints_for_bs
      75              :    USE qs_environment_types,            ONLY: get_qs_env,&
      76              :                                               qs_environment_type
      77              :    USE qs_mo_types,                     ONLY: get_mo_set
      78              :    USE qs_scf_types,                    ONLY: qs_scf_env_type
      79              :    USE rpa_gw_im_time_util,             ONLY: compute_weight_re_im,&
      80              :                                               get_atom_index_from_basis_function_index
      81              :    USE rpa_im_time,                     ONLY: init_cell_index_rpa
      82              :    USE scf_control_types,               ONLY: scf_control_type
      83              :    USE time_frequency_grids,            ONLY: time_frequency_grid_type
      84              : #include "./base/base_uses.f90"
      85              : 
      86              :    IMPLICIT NONE
      87              : 
      88              :    PRIVATE
      89              : 
      90              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'rpa_gw_kpoints_util'
      91              : 
      92              :    PUBLIC :: invert_eps_compute_W_and_Erpa_kp, real_space_to_kpoint_transform_rpa, &
      93              :              get_mat_cell_T_from_mat_gamma, get_bandstruc_and_k_dependent_MOs, &
      94              :              compute_wkp_W, mat_kp_from_mat_gamma, cfm_screened_interaction_from_eps_cholesky
      95              : 
      96              : CONTAINS
      97              : 
      98              : ! **************************************************************************************************
      99              : !> \brief Form the screened interaction from a Cholesky-factorized dielectric matrix.
     100              : !> \param eps_chol input Cholesky factor; overwritten by epsilon^-1-Id or Wc
     101              : !> \param B Coulomb factor satisfying V=B^H B
     102              : !> \param Wc optional separate output; if absent, eps_chol is overwritten by Wc
     103              : !> \param n_active optional number of physical rows/columns
     104              : ! **************************************************************************************************
     105         5842 :    SUBROUTINE cfm_screened_interaction_from_eps_cholesky(eps_chol, B, Wc, n_active)
     106              :       TYPE(cp_cfm_type), INTENT(INOUT)                   :: eps_chol
     107              :       TYPE(cp_cfm_type), INTENT(IN)                      :: B
     108              :       TYPE(cp_cfm_type), INTENT(INOUT), OPTIONAL         :: Wc
     109              :       INTEGER, INTENT(IN), OPTIONAL                      :: n_active
     110              : 
     111         5842 :       CALL cp_cfm_cholesky_invert(eps_chol)
     112         5842 :       CALL cp_cfm_uplo_to_full(eps_chol)
     113         5842 :       CALL cp_cfm_add_on_diag(eps_chol, -z_one, n_active)
     114         5842 :       CALL cfm_contract_ABA(B, eps_chol, Wc)
     115              : 
     116         5842 :    END SUBROUTINE cfm_screened_interaction_from_eps_cholesky
     117              : 
     118              : ! **************************************************************************************************
     119              : !> \brief ...
     120              : !> \param dimen_RI ...
     121              : !> \param jquad ...
     122              : !> \param nkp ...
     123              : !> \param count_ev_sc_GW ...
     124              : !> \param para_env ...
     125              : !> \param Erpa ...
     126              : !> \param grid ...
     127              : !> \param wkp_W ...
     128              : !> \param do_gw_im_time ...
     129              : !> \param do_ri_Sigma_x ...
     130              : !> \param do_kpoints_from_Gamma ...
     131              : !> \param cfm_mat_Q ...
     132              : !> \param ikp_local ...
     133              : !> \param mat_P_omega ...
     134              : !> \param mat_P_omega_kp ...
     135              : !> \param qs_env ...
     136              : !> \param eps_filter_im_time ...
     137              : !> \param unit_nr ...
     138              : !> \param kpoints ...
     139              : !> \param cfm_mat_Minv_L_kpoints ...
     140              : !> \param cfm_matrix_L_kpoints ...
     141              : !> \param fm_mat_W ...
     142              : !> \param cfm_mat_RI_global_work ...
     143              : !> \param mat_MinvVMinv ...
     144              : !> \param fm_matrix_Minv ...
     145              : !> \param fm_matrix_Minv_Vtrunc_Minv ...
     146              : ! **************************************************************************************************
     147          132 :    SUBROUTINE invert_eps_compute_W_and_Erpa_kp(dimen_RI, jquad, nkp, count_ev_sc_GW, para_env, &
     148          264 :                                                Erpa, grid, wkp_W, do_gw_im_time, &
     149              :                                                do_ri_Sigma_x, do_kpoints_from_Gamma, &
     150          132 :                                                cfm_mat_Q, ikp_local, mat_P_omega, mat_P_omega_kp, &
     151              :                                                qs_env, eps_filter_im_time, unit_nr, kpoints, cfm_mat_Minv_L_kpoints, &
     152          168 :                                                cfm_matrix_L_kpoints, fm_mat_W, &
     153              :                                                cfm_mat_RI_global_work, mat_MinvVMinv, fm_matrix_Minv, &
     154              :                                                fm_matrix_Minv_Vtrunc_Minv)
     155              : 
     156              :       INTEGER, INTENT(IN)                                :: dimen_RI, jquad, nkp, count_ev_sc_GW
     157              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     158              :       REAL(KIND=dp), INTENT(INOUT)                       :: Erpa
     159              :       TYPE(time_frequency_grid_type), INTENT(IN)         :: grid
     160              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: wkp_W
     161              :       LOGICAL, INTENT(IN)                                :: do_gw_im_time, do_ri_Sigma_x, &
     162              :                                                             do_kpoints_from_Gamma
     163              :       TYPE(cp_cfm_type), INTENT(INOUT)                   :: cfm_mat_Q
     164              :       INTEGER, INTENT(IN)                                :: ikp_local
     165              :       TYPE(dbcsr_p_type), DIMENSION(:, :), INTENT(INOUT) :: mat_P_omega, mat_P_omega_kp
     166              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     167              :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter_im_time
     168              :       INTEGER, INTENT(IN)                                :: unit_nr
     169              :       TYPE(kpoint_type), POINTER                         :: kpoints
     170              :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:)       :: cfm_mat_Minv_L_kpoints, &
     171              :                                                             cfm_matrix_L_kpoints
     172              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: fm_mat_W
     173              :       TYPE(cp_cfm_type)                                  :: cfm_mat_RI_global_work
     174              :       TYPE(dbcsr_p_type), INTENT(IN)                     :: mat_MinvVMinv
     175              :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: fm_matrix_Minv, &
     176              :                                                             fm_matrix_Minv_Vtrunc_Minv
     177              : 
     178              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'invert_eps_compute_W_and_Erpa_kp'
     179              : 
     180              :       INTEGER                                            :: handle, ikp, num_integ_points
     181              :       LOGICAL                                            :: do_this_ikp
     182              :       REAL(KIND=dp)                                      :: t1, t2
     183          132 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: diag_Qomega
     184              : 
     185          132 :       CALL timeset(routineN, handle)
     186              : 
     187          132 :       num_integ_points = SIZE(grid%frequency)
     188              : 
     189          132 :       t1 = m_walltime()
     190              : 
     191          132 :       IF (do_kpoints_from_Gamma) THEN
     192           96 :          CALL get_mat_cell_T_from_mat_gamma(mat_P_omega(jquad, :), qs_env, kpoints, jquad, unit_nr)
     193              :       END IF
     194              : 
     195              :       CALL transform_P_from_real_space_to_kpoints(mat_P_omega, mat_P_omega_kp, &
     196          132 :                                                   kpoints, eps_filter_im_time, jquad)
     197              : 
     198          396 :       ALLOCATE (diag_Qomega(dimen_RI))
     199              : 
     200          132 :       IF (unit_nr > 0) WRITE (unit_nr, '(/T3,A,1X,I3)') &
     201           66 :          'GW_INFO| Computing chi and W frequency point', jquad
     202              : 
     203         2700 :       DO ikp = 1, nkp
     204              : 
     205              :          ! parallization, we either have all kpoints on all processors or a single kpoint per group
     206         2568 :          do_this_ikp = (ikp_local == -1) .OR. (ikp_local == 0 .AND. ikp == 1) .OR. (ikp_local == ikp)
     207              :          IF (.NOT. do_this_ikp) CYCLE
     208              : 
     209              :          ! 1. remove all spurious negative eigenvalues from P(iw,k), multiplication Q(iw,k) = K^H(k)P(iw,k)K(k)
     210              :          CALL compute_Q_kp_RPA(cfm_mat_Q, &
     211              :                                mat_P_omega_kp, &
     212              :                                cfm_mat_Minv_L_kpoints(ikp), &
     213              :                                cfm_mat_RI_global_work, &
     214              :                                ikp, nkp, ikp_local, para_env, &
     215         2568 :                                qs_env%mp2_env%ri_rpa_im_time%make_chi_pos_definite)
     216              : 
     217              :          ! 2. Cholesky decomposition of Id + Q(iw,k)
     218         2568 :          CALL cholesky_decomp_Q(cfm_mat_Q, diag_Qomega, dimen_RI)
     219              : 
     220              :          ! 3. Computing E_c^RPA = E_c^RPA + a_w/N_k*sum_k ln[det(1+Q(iw,k))-Tr(Q(iw,k))]
     221              :          CALL frequency_and_kpoint_integration(Erpa, cfm_mat_Q, para_env, diag_Qomega, &
     222         2568 :                                                dimen_RI, grid%frequency_weights(jquad), kpoints%wkp(ikp))
     223              : 
     224         2700 :          IF (do_gw_im_time) THEN
     225              : 
     226              :             ! compute S^-1*V*S^-1 for exchange part of the self-energy in real space as W in real space
     227         2496 :             IF (do_ri_Sigma_x .AND. jquad == 1 .AND. count_ev_sc_GW == 1 .AND. do_kpoints_from_Gamma) THEN
     228              : 
     229          312 :                CALL dbcsr_set(mat_MinvVMinv%matrix, 0.0_dp)
     230          312 :                CALL copy_fm_to_dbcsr(fm_matrix_Minv_Vtrunc_Minv(1, 1), mat_MinvVMinv%matrix, keep_sparsity=.FALSE.)
     231              : 
     232              :             END IF
     233         2496 :             IF (do_kpoints_from_Gamma) THEN
     234              :                CALL compute_Wc_real_space_tau_GW(fm_mat_W, cfm_mat_Q, cfm_matrix_L_kpoints(ikp), &
     235              :                                                  dimen_RI, jquad, &
     236              :                                                  ikp, grid, &
     237         2496 :                                                  ikp_local, para_env, kpoints, qs_env, wkp_W)
     238              :             END IF
     239              : 
     240              :          END IF
     241              :       END DO
     242              : 
     243              :       ! after the transform of (eps(iw)-1)^-1 from iw to it is done, multiply with V^1/2 to obtain W(it)
     244          132 :       IF (do_gw_im_time .AND. do_kpoints_from_Gamma .AND. jquad == num_integ_points) THEN
     245           16 :          CALL Wc_to_Minv_Wc_Minv(fm_mat_W, fm_matrix_Minv, para_env, dimen_RI, num_integ_points)
     246           16 :          CALL deallocate_kp_matrices(cfm_matrix_L_kpoints, cfm_mat_Minv_L_kpoints)
     247              :       END IF
     248              : 
     249          132 :       DEALLOCATE (diag_Qomega)
     250              : 
     251          132 :       t2 = m_walltime()
     252              : 
     253          132 :       IF (unit_nr > 0) WRITE (unit_nr, '(T6,A,T56,F25.1)') 'Execution time (s):', t2 - t1
     254              : 
     255          132 :       CALL timestop(handle)
     256              : 
     257          132 :    END SUBROUTINE invert_eps_compute_W_and_Erpa_kp
     258              : 
     259              : ! **************************************************************************************************
     260              : !> \brief ...
     261              : !> \param cfm_matrix_L_kpoints ...
     262              : !> \param cfm_mat_Minv_L_kpoints ...
     263              : ! **************************************************************************************************
     264           16 :    SUBROUTINE deallocate_kp_matrices(cfm_matrix_L_kpoints, cfm_mat_Minv_L_kpoints)
     265              : 
     266              :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:)       :: cfm_matrix_L_kpoints, &
     267              :                                                             cfm_mat_Minv_L_kpoints
     268              : 
     269              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'deallocate_kp_matrices'
     270              : 
     271              :       INTEGER                                            :: handle, ikp
     272              : 
     273           16 :       CALL timeset(routineN, handle)
     274              : 
     275           16 :       IF (ALLOCATED(cfm_mat_Minv_L_kpoints)) THEN
     276          432 :          DO ikp = 1, SIZE(cfm_mat_Minv_L_kpoints)
     277          432 :             IF (ASSOCIATED(cfm_mat_Minv_L_kpoints(ikp)%matrix_struct)) CALL cp_cfm_release(cfm_mat_Minv_L_kpoints(ikp))
     278              :          END DO
     279           16 :          DEALLOCATE (cfm_mat_Minv_L_kpoints)
     280              :       END IF
     281           16 :       IF (ALLOCATED(cfm_matrix_L_kpoints)) THEN
     282          432 :          DO ikp = 1, SIZE(cfm_matrix_L_kpoints)
     283          432 :             IF (ASSOCIATED(cfm_matrix_L_kpoints(ikp)%matrix_struct)) CALL cp_cfm_release(cfm_matrix_L_kpoints(ikp))
     284              :          END DO
     285           16 :          DEALLOCATE (cfm_matrix_L_kpoints)
     286              :       END IF
     287              : 
     288           16 :       CALL timestop(handle)
     289              : 
     290           16 :    END SUBROUTINE deallocate_kp_matrices
     291              : 
     292              : ! **************************************************************************************************
     293              : !> \brief ...
     294              : !> \param cfm_mat_Q ...
     295              : !> \param mat_P_omega_kp ...
     296              : !> \param cfm_mat_L ...
     297              : !> \param cfm_mat_RI_global_work ...
     298              : !> \param ikp ...
     299              : !> \param nkp ...
     300              : !> \param ikp_local ...
     301              : !> \param para_env ...
     302              : !> \param make_chi_pos_definite ...
     303              : ! **************************************************************************************************
     304         2568 :    SUBROUTINE compute_Q_kp_RPA(cfm_mat_Q, mat_P_omega_kp, cfm_mat_L, &
     305              :                                cfm_mat_RI_global_work, ikp, nkp, ikp_local, para_env, &
     306              :                                make_chi_pos_definite)
     307              : 
     308              :       TYPE(cp_cfm_type)                                  :: cfm_mat_Q
     309              :       TYPE(dbcsr_p_type), DIMENSION(:, :), INTENT(INOUT) :: mat_P_omega_kp
     310              :       TYPE(cp_cfm_type)                                  :: cfm_mat_L, cfm_mat_RI_global_work
     311              :       INTEGER, INTENT(IN)                                :: ikp, nkp, ikp_local
     312              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     313              :       LOGICAL, INTENT(IN)                                :: make_chi_pos_definite
     314              : 
     315              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'compute_Q_kp_RPA'
     316              : 
     317              :       INTEGER                                            :: handle
     318              : 
     319         2568 :       CALL timeset(routineN, handle)
     320              : 
     321              :       ! 1. Convert the dbcsr matrix mat_P_omega_kp (that is chi(k,iw)) to a full matrix and
     322              :       !    distribute it to subgroups
     323         2568 :       CALL mat_P_to_subgroup(mat_P_omega_kp, cfm_mat_RI_global_work, cfm_mat_Q, ikp, nkp, ikp_local, para_env)
     324              : 
     325              :       ! 2. Remove all negative eigenvalues from chi(k,iw)
     326         2568 :       IF (make_chi_pos_definite) THEN
     327         2568 :          CALL cp_cfm_power(cfm_mat_Q, threshold=0.0_dp, exponent=1.0_dp)
     328              :       END IF
     329              : 
     330              :       ! Q(iw,k) = L^H(k)*P(iw,k)*L(k)
     331         2568 :       CALL cfm_contract_ABA(cfm_mat_L, cfm_mat_Q)
     332              : 
     333         2568 :       CALL timestop(handle)
     334              : 
     335         2568 :    END SUBROUTINE compute_Q_kp_RPA
     336              : 
     337              : ! **************************************************************************************************
     338              : !> \brief ...
     339              : !> \param mat_P_omega_kp ...
     340              : !> \param cfm_mat_RI_global_work ...
     341              : !> \param cfm_mat_Q ...
     342              : !> \param ikp ...
     343              : !> \param nkp ...
     344              : !> \param ikp_local ...
     345              : !> \param para_env ...
     346              : ! **************************************************************************************************
     347         2568 :    SUBROUTINE mat_P_to_subgroup(mat_P_omega_kp, cfm_mat_RI_global_work, cfm_mat_Q, ikp, nkp, ikp_local, para_env)
     348              : 
     349              :       TYPE(dbcsr_p_type), DIMENSION(:, :), INTENT(INOUT) :: mat_P_omega_kp
     350              :       TYPE(cp_cfm_type), INTENT(INOUT)                   :: cfm_mat_RI_global_work, cfm_mat_Q
     351              :       INTEGER, INTENT(IN)                                :: ikp, nkp, ikp_local
     352              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     353              : 
     354              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'mat_P_to_subgroup'
     355              : 
     356              :       INTEGER                                            :: handle, jkp
     357              :       TYPE(cp_cfm_type)                                  :: cfm_dummy
     358              :       TYPE(cp_fm_type)                                   :: fm_mat_work
     359              :       TYPE(dbcsr_type), POINTER                          :: mat_P_omega_im, mat_P_omega_re
     360              : 
     361         2568 :       CALL timeset(routineN, handle)
     362              : 
     363         2568 :       CALL cp_fm_create(fm_mat_work, cfm_mat_RI_global_work%matrix_struct)
     364              : 
     365        67608 :       DO jkp = 1, nkp
     366        65040 :          IF (ikp_local == -1 .AND. jkp /= ikp) CYCLE
     367              : 
     368         2568 :          mat_P_omega_re => mat_P_omega_kp(1, jkp)%matrix
     369         2568 :          CALL cp_fm_set_all(fm_mat_work, 0.0_dp)
     370         2568 :          CALL copy_dbcsr_to_fm(mat_P_omega_re, fm_mat_work)
     371         2568 :          CALL cp_fm_to_cfm(msourcer=fm_mat_work, mtarget=cfm_mat_RI_global_work)
     372              : 
     373         2568 :          mat_P_omega_im => mat_P_omega_kp(2, jkp)%matrix
     374         2568 :          CALL cp_fm_set_all(fm_mat_work, 0.0_dp)
     375         2568 :          CALL copy_dbcsr_to_fm(mat_P_omega_im, fm_mat_work)
     376         2568 :          CALL cp_cfm_scale_and_add_fm(z_one, cfm_mat_RI_global_work, gaussi, fm_mat_work)
     377              : 
     378         2568 :          IF (ikp_local /= -1) CALL para_env%sync()
     379              : 
     380         2568 :          IF (ikp_local == -1 .OR. ikp_local == jkp) THEN
     381         2568 :             CALL cp_cfm_copy_general(cfm_mat_RI_global_work, cfm_mat_Q, para_env)
     382              :          ELSE
     383            0 :             CALL cp_cfm_copy_general(cfm_mat_RI_global_work, cfm_dummy, para_env)
     384              :          END IF
     385              : 
     386         5136 :          IF (ikp_local /= -1) CALL para_env%sync()
     387              :       END DO
     388              : 
     389         2568 :       CALL cp_fm_release(fm_mat_work)
     390         2568 :       CALL para_env%sync()
     391              : 
     392         2568 :       CALL timestop(handle)
     393              : 
     394         2568 :    END SUBROUTINE mat_P_to_subgroup
     395              : 
     396              : ! **************************************************************************************************
     397              : !> \brief ...
     398              : !> \param cfm_mat_Q ...
     399              : !> \param diag_Qomega ...
     400              : !> \param dimen_RI ...
     401              : ! **************************************************************************************************
     402         2568 :    SUBROUTINE cholesky_decomp_Q(cfm_mat_Q, diag_Qomega, dimen_RI)
     403              : 
     404              :       TYPE(cp_cfm_type), INTENT(INOUT)                   :: cfm_mat_Q
     405              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: diag_Qomega
     406              :       INTEGER, INTENT(IN)                                :: dimen_RI
     407              : 
     408              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'cholesky_decomp_Q'
     409              : 
     410              :       INTEGER                                            :: handle, info_chol
     411         5136 :       COMPLEX(KIND=dp), DIMENSION(dimen_RI)              :: diag_Q
     412              : 
     413         2568 :       CALL timeset(routineN, handle)
     414              : 
     415              :       ! epsilon = I + Q; the Hermitian Q has a real diagonal for the RPA energy.
     416         2568 :       CALL cp_cfm_get_diag(cfm_mat_Q, diag_Q, n_active=dimen_RI)
     417       182640 :       diag_Qomega = REAL(diag_Q, KIND=dp)
     418         2568 :       CALL cp_cfm_add_on_diag(cfm_mat_Q, z_one, n_active=dimen_RI)
     419              : 
     420         2568 :       CALL cp_cfm_cholesky_decompose(matrix=cfm_mat_Q, n=dimen_RI, info_out=info_chol)
     421              : 
     422         2568 :       CPASSERT(info_chol == 0)
     423              : 
     424         2568 :       CALL timestop(handle)
     425              : 
     426         2568 :    END SUBROUTINE cholesky_decomp_Q
     427              : 
     428              : ! **************************************************************************************************
     429              : !> \brief ...
     430              : !> \param Erpa ...
     431              : !> \param cfm_mat_Q ...
     432              : !> \param para_env ...
     433              : !> \param diag_Qomega ...
     434              : !> \param dimen_RI ...
     435              : !> \param freq_weight ...
     436              : !> \param kp_weight ...
     437              : ! **************************************************************************************************
     438         2568 :    SUBROUTINE frequency_and_kpoint_integration(Erpa, cfm_mat_Q, para_env, diag_Qomega, &
     439              :                                                dimen_RI, freq_weight, kp_weight)
     440              : 
     441              :       REAL(KIND=dp), INTENT(INOUT)                       :: Erpa
     442              :       TYPE(cp_cfm_type), INTENT(IN)                      :: cfm_mat_Q
     443              :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env
     444              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: diag_Qomega
     445              :       INTEGER, INTENT(IN)                                :: dimen_RI
     446              :       REAL(KIND=dp), INTENT(IN)                          :: freq_weight, kp_weight
     447              : 
     448              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'frequency_and_kpoint_integration'
     449              : 
     450              :       INTEGER                                            :: handle, iiB
     451         5136 :       COMPLEX(KIND=dp), DIMENSION(dimen_RI)              :: diag_chol
     452              :       REAL(KIND=dp)                                      :: FComega
     453         2568 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: Q_log
     454              : 
     455         2568 :       CALL timeset(routineN, handle)
     456              : 
     457         7704 :       ALLOCATE (Q_log(dimen_RI))
     458              :       ! epsilon = U^H U; log(det(epsilon)) = 2*sum(log(real(U_ii))).
     459         2568 :       CALL cp_cfm_get_diag(cfm_mat_Q, diag_chol, n_active=dimen_RI)
     460       182640 :       Q_log(:) = 2.0_dp*LOG(REAL(diag_chol, KIND=dp))
     461              : 
     462              :       FComega = 0.0_dp
     463       182640 :       DO iiB = 1, dimen_RI
     464       180072 :          IF (MODULO(iiB, para_env%num_pe) /= para_env%mepos) CYCLE
     465       182640 :          FComega = FComega + (Q_log(iiB) - diag_Qomega(iiB))/2.0_dp
     466              :       END DO
     467              : 
     468         2568 :       Erpa = Erpa + FComega*freq_weight*kp_weight
     469              : 
     470         2568 :       DEALLOCATE (Q_log)
     471              : 
     472         2568 :       CALL timestop(handle)
     473              : 
     474         2568 :    END SUBROUTINE frequency_and_kpoint_integration
     475              : 
     476              : ! **************************************************************************************************
     477              : !> \brief Split a real Gamma matrix among nearest images using normalized equal weights.
     478              : !> \param mat_P_omega ...
     479              : !> \param qs_env ...
     480              : !> \param kpoints ...
     481              : !> \param jquad ...
     482              : !> \param unit_nr ...
     483              : ! **************************************************************************************************
     484          210 :    SUBROUTINE get_mat_cell_T_from_mat_gamma(mat_P_omega, qs_env, kpoints, jquad, unit_nr)
     485              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN)       :: mat_P_omega
     486              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     487              :       TYPE(kpoint_type), POINTER                         :: kpoints
     488              :       INTEGER, INTENT(IN)                                :: jquad, unit_nr
     489              : 
     490              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'get_mat_cell_T_from_mat_gamma'
     491              : 
     492              :       INTEGER                                            :: col, handle, i_cell, num_cells_P, row
     493              :       INTEGER, DIMENSION(3)                              :: periodic
     494              :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell_P
     495              :       LOGICAL                                            :: found
     496              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: weights
     497          210 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: data_block, image_block
     498              :       TYPE(cell_type), POINTER                           :: cell
     499              :       TYPE(dbcsr_iterator_type)                          :: iter
     500          210 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     501              : 
     502          210 :       CALL timeset(routineN, handle)
     503              : 
     504          210 :       NULLIFY (cell, particle_set)
     505          210 :       CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
     506          210 :       CALL get_cell(cell=cell, periodic=periodic)
     507              : 
     508              :       ! Nearest-neighbour candidate cells depend on periodicity, not on the target k-point mesh.
     509          840 :       CALL init_cell_index_rpa(2*periodic + 1, kpoints%cell_to_index, kpoints%index_to_cell, cell)
     510          210 :       index_to_cell_P => kpoints%index_to_cell
     511          210 :       num_cells_P = SIZE(index_to_cell_P, 2)
     512          210 :       CPASSERT(SIZE(mat_P_omega) >= num_cells_P)
     513          630 :       ALLOCATE (weights(num_cells_P))
     514              : 
     515         1890 :       DO i_cell = 2, num_cells_P
     516         1890 :          CALL dbcsr_copy(mat_P_omega(i_cell)%matrix, mat_P_omega(1)%matrix)
     517              :       END DO
     518              : 
     519          210 :       IF (jquad == 1 .AND. unit_nr > 0) THEN
     520            8 :          WRITE (unit_nr, '(T3,A,T66,ES15.2)') 'GW_INFO| RI regularization parameter: ', &
     521           16 :             qs_env%mp2_env%ri_rpa_im_time%regularization_RI
     522            8 :          WRITE (unit_nr, '(T3,A,T66,ES15.2)') 'GW_INFO| eps_eigval_S: ', &
     523           16 :             qs_env%mp2_env%ri_rpa_im_time%eps_eigval_S
     524            8 :          IF (qs_env%mp2_env%ri_rpa_im_time%make_chi_pos_definite) THEN
     525              :             WRITE (unit_nr, '(T3,A,T81)') &
     526            8 :                'GW_INFO| Make chi(iw,k) positive definite?                                TRUE'
     527              :          ELSE
     528              :             WRITE (unit_nr, '(T3,A,T81)') &
     529            0 :                'GW_INFO| Make chi(iw,k) positive definite?                               FALSE'
     530              :          END IF
     531              :       END IF
     532              : 
     533          210 :       CALL dbcsr_iterator_start(iter, mat_P_omega(1)%matrix)
     534         1065 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     535          855 :          CALL dbcsr_iterator_next_block(iter, row, col, data_block)
     536              :          CALL minimum_image_weights(particle_set(row)%r, particle_set(col)%r, &
     537          855 :                                     cell, index_to_cell_P, weights)
     538              :          ! Keep the Gamma block unchanged until its contributions to all other images are copied.
     539         8760 :          DO i_cell = num_cells_P, 1, -1
     540              :             CALL dbcsr_get_block_p(matrix=mat_P_omega(i_cell)%matrix, row=row, col=col, &
     541         7695 :                                    block=image_block, found=found)
     542         7695 :             CPASSERT(found)
     543      5344992 :             image_block = weights(i_cell)*data_block
     544              :          END DO
     545              :       END DO
     546          210 :       CALL dbcsr_iterator_stop(iter)
     547              : 
     548          210 :       CALL timestop(handle)
     549              : 
     550          630 :    END SUBROUTINE get_mat_cell_T_from_mat_gamma
     551              : 
     552              : ! **************************************************************************************************
     553              : !> \brief ...
     554              : !> \param mat_P_omega ...
     555              : !> \param mat_P_omega_kp ...
     556              : !> \param kpoints ...
     557              : !> \param eps_filter_im_time ...
     558              : !> \param jquad ...
     559              : ! **************************************************************************************************
     560          132 :    SUBROUTINE transform_P_from_real_space_to_kpoints(mat_P_omega, mat_P_omega_kp, &
     561              :                                                      kpoints, eps_filter_im_time, jquad)
     562              : 
     563              :       TYPE(dbcsr_p_type), DIMENSION(:, :), INTENT(INOUT) :: mat_P_omega, mat_P_omega_kp
     564              :       TYPE(kpoint_type), POINTER                         :: kpoints
     565              :       REAL(kind=dp), INTENT(IN)                          :: eps_filter_im_time
     566              :       INTEGER, INTENT(IN)                                :: jquad
     567              : 
     568              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'transform_P_from_real_space_to_kpoints'
     569              : 
     570              :       INTEGER                                            :: handle, icell, nkp, num_integ_points
     571              : 
     572          132 :       CALL timeset(routineN, handle)
     573              : 
     574          132 :       num_integ_points = SIZE(mat_P_omega, 1)
     575          132 :       nkp = SIZE(mat_P_omega, 2)
     576              : 
     577              :       CALL real_space_to_kpoint_transform_rpa(mat_P_omega_kp(1, :), mat_P_omega_kp(2, :), mat_P_omega(jquad, :), &
     578          132 :                                               kpoints, eps_filter_im_time)
     579              : 
     580         2700 :       DO icell = 1, SIZE(mat_P_omega, 2)
     581         2568 :          CALL dbcsr_set(mat_P_omega(jquad, icell)%matrix, 0.0_dp)
     582         2700 :          CALL dbcsr_filter(mat_P_omega(jquad, icell)%matrix, 1.0_dp)
     583              :       END DO
     584              : 
     585          132 :       CALL timestop(handle)
     586              : 
     587          132 :    END SUBROUTINE transform_P_from_real_space_to_kpoints
     588              : 
     589              : ! **************************************************************************************************
     590              : !> \brief ...
     591              : !> \param real_mat_kp ...
     592              : !> \param imag_mat_kp ...
     593              : !> \param mat_real_space ...
     594              : !> \param kpoints ...
     595              : !> \param eps_filter_im_time ...
     596              : !> \param real_mat_real_space ...
     597              : ! **************************************************************************************************
     598          246 :    SUBROUTINE real_space_to_kpoint_transform_rpa(real_mat_kp, imag_mat_kp, mat_real_space, &
     599              :                                                  kpoints, eps_filter_im_time, real_mat_real_space)
     600              : 
     601              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT)    :: real_mat_kp, imag_mat_kp, mat_real_space
     602              :       TYPE(kpoint_type), POINTER                         :: kpoints
     603              :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter_im_time
     604              :       LOGICAL, INTENT(IN), OPTIONAL                      :: real_mat_real_space
     605              : 
     606              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'real_space_to_kpoint_transform_rpa'
     607              : 
     608              :       INTEGER                                            :: handle, i_cell, ik, nkp, num_cells
     609              :       INTEGER, DIMENSION(3)                              :: cell
     610          246 :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell
     611              :       LOGICAL                                            :: my_real_mat_real_space
     612              :       REAL(KIND=dp)                                      :: arg, coskl, sinkl
     613          246 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
     614              :       TYPE(dbcsr_type)                                   :: mat_work
     615              : 
     616          246 :       CALL timeset(routineN, handle)
     617              : 
     618          246 :       my_real_mat_real_space = .TRUE.
     619          246 :       IF (PRESENT(real_mat_real_space)) my_real_mat_real_space = real_mat_real_space
     620              : 
     621              :       CALL dbcsr_create(matrix=mat_work, &
     622              :                         template=real_mat_kp(1)%matrix, &
     623          246 :                         matrix_type=dbcsr_type_no_symmetry)
     624          246 :       CALL dbcsr_reserve_all_blocks(mat_work)
     625          246 :       CALL dbcsr_set(mat_work, 0.0_dp)
     626              : 
     627              :       ! this kpoint environme t should be the kpoints for D(it) and X(it) created in init_cell_index_rpa
     628          246 :       CALL get_kpoint_info(kpoints, nkp=nkp, xkp=xkp)
     629              : 
     630          246 :       NULLIFY (index_to_cell)
     631          246 :       index_to_cell => kpoints%index_to_cell
     632              : 
     633          246 :       num_cells = SIZE(index_to_cell, 2)
     634              : 
     635          246 :       CPASSERT(SIZE(mat_real_space) >= num_cells/2 + 1)
     636              : 
     637         3408 :       DO ik = 1, nkp
     638              : 
     639         3162 :          CALL dbcsr_reserve_all_blocks(real_mat_kp(ik)%matrix)
     640         3162 :          CALL dbcsr_reserve_all_blocks(imag_mat_kp(ik)%matrix)
     641              : 
     642         3162 :          CALL dbcsr_set(real_mat_kp(ik)%matrix, 0.0_dp)
     643         3162 :          CALL dbcsr_set(imag_mat_kp(ik)%matrix, 0.0_dp)
     644              : 
     645        18756 :          DO i_cell = 1, num_cells/2 + 1
     646              : 
     647        62376 :             cell(:) = index_to_cell(:, i_cell)
     648              : 
     649        15594 :             arg = REAL(cell(1), dp)*xkp(1, ik) + REAL(cell(2), dp)*xkp(2, ik) + REAL(cell(3), dp)*xkp(3, ik)
     650        15594 :             coskl = COS(twopi*arg)
     651        15594 :             sinkl = SIN(twopi*arg)
     652              : 
     653        15594 :             IF (my_real_mat_real_space) THEN
     654        15354 :                CALL dbcsr_add_local(real_mat_kp(ik)%matrix, mat_real_space(i_cell)%matrix, 1.0_dp, coskl)
     655        15354 :                CALL dbcsr_add_local(imag_mat_kp(ik)%matrix, mat_real_space(i_cell)%matrix, 1.0_dp, sinkl)
     656              :             ELSE
     657          240 :                CALL dbcsr_add_local(real_mat_kp(ik)%matrix, mat_real_space(i_cell)%matrix, 1.0_dp, -sinkl)
     658          240 :                CALL dbcsr_add_local(imag_mat_kp(ik)%matrix, mat_real_space(i_cell)%matrix, 1.0_dp, coskl)
     659              :             END IF
     660              : 
     661        18756 :             IF (.NOT. (cell(1) == 0 .AND. cell(2) == 0 .AND. cell(3) == 0)) THEN
     662              : 
     663        12432 :                CALL dbcsr_transposed(mat_work, mat_real_space(i_cell)%matrix)
     664              : 
     665        12432 :                IF (my_real_mat_real_space) THEN
     666        12240 :                   CALL dbcsr_add_local(real_mat_kp(ik)%matrix, mat_work, 1.0_dp, coskl)
     667        12240 :                   CALL dbcsr_add_local(imag_mat_kp(ik)%matrix, mat_work, 1.0_dp, -sinkl)
     668              :                ELSE
     669              :                   ! for an imaginary real-space matrix, we need to consider the imaginary unit
     670              :                   ! and we need to take into account that the transposed gives an extra "-" sign
     671              :                   ! because the transposed is actually Hermitian conjugate
     672          192 :                   CALL dbcsr_add_local(real_mat_kp(ik)%matrix, mat_work, 1.0_dp, -sinkl)
     673          192 :                   CALL dbcsr_add_local(imag_mat_kp(ik)%matrix, mat_work, 1.0_dp, -coskl)
     674              :                END IF
     675              : 
     676        12432 :                CALL dbcsr_set(mat_work, 0.0_dp)
     677              : 
     678              :             END IF
     679              : 
     680              :          END DO
     681              : 
     682         3162 :          CALL dbcsr_filter(real_mat_kp(ik)%matrix, eps_filter_im_time)
     683         3408 :          CALL dbcsr_filter(imag_mat_kp(ik)%matrix, eps_filter_im_time)
     684              : 
     685              :       END DO
     686              : 
     687          246 :       CALL dbcsr_release(mat_work)
     688              : 
     689          246 :       CALL timestop(handle)
     690              : 
     691          246 :    END SUBROUTINE real_space_to_kpoint_transform_rpa
     692              : 
     693              : ! **************************************************************************************************
     694              : !> \brief ...
     695              : !> \param mat_a ...
     696              : !> \param mat_b ...
     697              : !> \param alpha ...
     698              : !> \param beta ...
     699              : ! **************************************************************************************************
     700        56052 :    SUBROUTINE dbcsr_add_local(mat_a, mat_b, alpha, beta)
     701              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: mat_a, mat_b
     702              :       REAL(kind=dp), INTENT(IN)                          :: alpha, beta
     703              : 
     704              :       INTEGER                                            :: col, row
     705              :       LOGICAL                                            :: found
     706        56052 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block_to_compute, data_block
     707              :       TYPE(dbcsr_iterator_type)                          :: iter
     708              : 
     709        56052 :       CALL dbcsr_iterator_start(iter, mat_b)
     710       289170 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     711       233118 :          CALL dbcsr_iterator_next_block(iter, row, col, data_block)
     712              : 
     713       233118 :          NULLIFY (block_to_compute)
     714              :          CALL dbcsr_get_block_p(matrix=mat_a, &
     715       233118 :                                 row=row, col=col, block=block_to_compute, found=found)
     716              : 
     717       233118 :          CPASSERT(found)
     718              : 
     719    259745328 :          block_to_compute(:, :) = alpha*block_to_compute(:, :) + beta*data_block(:, :)
     720              : 
     721              :       END DO
     722        56052 :       CALL dbcsr_iterator_stop(iter)
     723              : 
     724        56052 :    END SUBROUTINE dbcsr_add_local
     725              : 
     726              : ! **************************************************************************************************
     727              : !> \brief ...
     728              : !> \param fm_mat_W_tau ...
     729              : !> \param cfm_mat_Q ...
     730              : !> \param cfm_mat_L ...
     731              : !> \param dimen_RI ...
     732              : !> \param jquad ...
     733              : !> \param ikp ...
     734              : !> \param grid ...
     735              : !> \param ikp_local ...
     736              : !> \param para_env ...
     737              : !> \param kpoints ...
     738              : !> \param qs_env ...
     739              : !> \param wkp_W ...
     740              : ! **************************************************************************************************
     741         2496 :    SUBROUTINE compute_Wc_real_space_tau_GW(fm_mat_W_tau, cfm_mat_Q, cfm_mat_L, &
     742              :                                            dimen_RI, jquad, &
     743              :                                            ikp, grid, ikp_local, &
     744         2496 :                                            para_env, kpoints, qs_env, wkp_W)
     745              : 
     746              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: fm_mat_W_tau
     747              :       TYPE(cp_cfm_type), INTENT(INOUT)                   :: cfm_mat_Q
     748              :       TYPE(cp_cfm_type), INTENT(IN)                      :: cfm_mat_L
     749              :       INTEGER, INTENT(IN)                                :: dimen_RI, jquad, ikp
     750              :       TYPE(time_frequency_grid_type), INTENT(IN)         :: grid
     751              :       INTEGER, INTENT(IN)                                :: ikp_local
     752              :       TYPE(mp_para_env_type), INTENT(IN), POINTER        :: para_env
     753              :       TYPE(kpoint_type), INTENT(IN), POINTER             :: kpoints
     754              :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
     755              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: wkp_W
     756              : 
     757              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_Wc_real_space_tau_GW'
     758              : 
     759              :       INTEGER :: handle, handle2, iatom, iatom_old, iquad, irow, jatom, jatom_old, jcol, jkp, &
     760              :          ncol_local, nkp, nrow_local, num_cells, num_integ_points
     761              :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_from_RI_index
     762         2496 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
     763         2496 :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell
     764              :       REAL(KIND=dp)                                      :: contribution, weight, weight_im, &
     765              :                                                             weight_re
     766              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: hmat
     767         2496 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: wkp
     768         2496 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
     769              :       TYPE(cell_type), POINTER                           :: cell
     770              :       TYPE(cp_cfm_type)                                  :: cfm_mat_work_2
     771              :       TYPE(cp_fm_type)                                   :: fm_dummy, fm_mat_work_global, &
     772              :                                                             fm_mat_work_local
     773         2496 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     774              : 
     775         2496 :       CALL timeset(routineN, handle)
     776              : 
     777         2496 :       num_integ_points = SIZE(grid%imaginary_time)
     778              : 
     779         2496 :       CALL timeset(routineN//"_1", handle2)
     780              : 
     781         2496 :       CALL cp_cfm_create(cfm_mat_work_2, cfm_mat_Q%matrix_struct)
     782         2496 :       CALL cp_cfm_set_all(cfm_mat_work_2, z_zero)
     783              : 
     784         2496 :       CALL cp_fm_create(fm_mat_work_global, fm_mat_W_tau(1)%matrix_struct)
     785         2496 :       CALL cp_fm_set_all(fm_mat_work_global, 0.0_dp)
     786              : 
     787         2496 :       CALL cp_fm_create(fm_mat_work_local, cfm_mat_Q%matrix_struct)
     788         2496 :       CALL cp_fm_set_all(fm_mat_work_local, 0.0_dp)
     789              : 
     790         2496 :       CALL timestop(handle2)
     791              : 
     792         2496 :       CALL timeset(routineN//"_2", handle2)
     793              : 
     794         2496 :       CALL cfm_screened_interaction_from_eps_cholesky(cfm_mat_Q, cfm_mat_L, cfm_mat_work_2, dimen_RI)
     795              : 
     796         2496 :       CALL timestop(handle2)
     797              : 
     798         2496 :       CALL timeset(routineN//"_4", handle2)
     799              : 
     800         2496 :       CALL get_kpoint_info(kpoints, xkp=xkp, wkp=wkp, nkp=nkp)
     801         2496 :       index_to_cell => kpoints%index_to_cell
     802         2496 :       num_cells = SIZE(index_to_cell, 2)
     803              : 
     804         7488 :       ALLOCATE (atom_from_RI_index(dimen_RI))
     805              : 
     806         2496 :       CALL get_atom_index_from_basis_function_index(qs_env, atom_from_RI_index, dimen_RI, "RI_AUX")
     807              : 
     808         2496 :       NULLIFY (cell, particle_set)
     809         2496 :       CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
     810         2496 :       CALL get_cell(cell=cell, h=hmat)
     811         2496 :       iatom_old = 0
     812         2496 :       jatom_old = 0
     813              : 
     814              :       CALL cp_cfm_get_info(matrix=cfm_mat_Q, &
     815              :                            nrow_local=nrow_local, &
     816              :                            ncol_local=ncol_local, &
     817              :                            row_indices=row_indices, &
     818         2496 :                            col_indices=col_indices)
     819              : 
     820        89544 :       DO irow = 1, nrow_local
     821      6863376 :          DO jcol = 1, ncol_local
     822              : 
     823      6773832 :             iatom = atom_from_RI_index(row_indices(irow))
     824      6773832 :             jatom = atom_from_RI_index(col_indices(jcol))
     825              : 
     826      6773832 :             IF (iatom /= iatom_old .OR. jatom /= jatom_old) THEN
     827              : 
     828              :                ! symmetrize=.FALSE. necessary since we already have a symmetrized index_to_cell
     829              :                CALL compute_weight_re_im(weight_re, weight_im, &
     830              :                                          num_cells, iatom, jatom, xkp(1:3, ikp), wkp_W(ikp), &
     831       258336 :                                          cell, index_to_cell, hmat, particle_set)
     832              : 
     833       258336 :                iatom_old = iatom
     834       258336 :                jatom_old = jatom
     835              : 
     836              :             END IF
     837              : 
     838              :             contribution = weight_re*REAL(cfm_mat_work_2%local_data(irow, jcol)) + &
     839      6773832 :                            weight_im*AIMAG(cfm_mat_work_2%local_data(irow, jcol))
     840              : 
     841      6860880 :             fm_mat_work_local%local_data(irow, jcol) = fm_mat_work_local%local_data(irow, jcol) + contribution
     842              : 
     843              :          END DO
     844              :       END DO
     845              : 
     846         2496 :       CALL timestop(handle2)
     847              : 
     848         2496 :       CALL timeset(routineN//"_5", handle2)
     849              : 
     850         2496 :       IF (ikp_local == -1) THEN
     851              : 
     852         2496 :          CALL cp_fm_copy_general(fm_mat_work_local, fm_mat_work_global, para_env)
     853              : 
     854        17472 :          DO iquad = 1, num_integ_points
     855              : 
     856        14976 :             weight = grid%cosine_frequency_to_time(iquad, jquad)
     857              : 
     858        14976 :             IF (jquad == 1 .AND. ikp == 1) THEN
     859           96 :                CALL cp_fm_set_all(matrix=fm_mat_W_tau(iquad), alpha=0.0_dp)
     860              :             END IF
     861              : 
     862        17472 :             CALL cp_fm_scale_and_add(alpha=1.0_dp, matrix_a=fm_mat_W_tau(iquad), beta=weight, matrix_b=fm_mat_work_global)
     863              : 
     864              :          END DO
     865              : 
     866              :       ELSE
     867              : 
     868            0 :          DO jkp = 1, nkp
     869              : 
     870            0 :             CALL para_env%sync()
     871              : 
     872            0 :             IF (ikp_local == jkp) THEN
     873            0 :                CALL cp_fm_copy_general(fm_mat_work_local, fm_mat_work_global, para_env)
     874              :             ELSE
     875            0 :                CALL cp_fm_copy_general(fm_dummy, fm_mat_work_global, para_env)
     876              :             END IF
     877              : 
     878            0 :             CALL para_env%sync()
     879              : 
     880            0 :             DO iquad = 1, num_integ_points
     881              : 
     882            0 :                weight = grid%cosine_frequency_to_time(iquad, jquad)
     883              : 
     884            0 :                IF (jquad == 1 .AND. jkp == 1) THEN
     885            0 :                   CALL cp_fm_set_all(matrix=fm_mat_W_tau(iquad), alpha=0.0_dp)
     886              :                END IF
     887              : 
     888              :                CALL cp_fm_scale_and_add(alpha=1.0_dp, matrix_a=fm_mat_W_tau(iquad), beta=weight, &
     889            0 :                                         matrix_b=fm_mat_work_global)
     890              : 
     891              :             END DO
     892              : 
     893              :          END DO
     894              : 
     895              :       END IF
     896              : 
     897         2496 :       CALL cp_cfm_release(cfm_mat_work_2)
     898         2496 :       CALL cp_fm_release(fm_mat_work_global)
     899         2496 :       CALL cp_fm_release(fm_mat_work_local)
     900              : 
     901         2496 :       DEALLOCATE (atom_from_RI_index)
     902              : 
     903         2496 :       CALL timestop(handle2)
     904              : 
     905         2496 :       CALL timestop(handle)
     906              : 
     907        17472 :    END SUBROUTINE compute_Wc_real_space_tau_GW
     908              : 
     909              : ! **************************************************************************************************
     910              : !> \brief ...
     911              : !> \param fm_mat_W ...
     912              : !> \param fm_matrix_Minv ...
     913              : !> \param para_env ...
     914              : !> \param dimen_RI ...
     915              : !> \param num_integ_points ...
     916              : ! **************************************************************************************************
     917           16 :    SUBROUTINE Wc_to_Minv_Wc_Minv(fm_mat_W, fm_matrix_Minv, para_env, dimen_RI, num_integ_points)
     918              :       TYPE(cp_fm_type), DIMENSION(:)                     :: fm_mat_W
     919              :       TYPE(cp_fm_type), DIMENSION(:, :)                  :: fm_matrix_Minv
     920              :       TYPE(mp_para_env_type), INTENT(IN), POINTER        :: para_env
     921              :       INTEGER                                            :: dimen_RI, num_integ_points
     922              : 
     923              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'Wc_to_Minv_Wc_Minv'
     924              : 
     925              :       INTEGER                                            :: handle, jquad
     926              :       TYPE(cp_fm_type)                                   :: fm_work_Minv, fm_work_Minv_W
     927              : 
     928           16 :       CALL timeset(routineN, handle)
     929              : 
     930           16 :       CALL cp_fm_create(fm_work_Minv, fm_mat_W(1)%matrix_struct)
     931           16 :       CALL cp_fm_copy_general(fm_matrix_Minv(1, 1), fm_work_Minv, para_env)
     932              : 
     933           16 :       CALL cp_fm_create(fm_work_Minv_W, fm_mat_W(1)%matrix_struct)
     934              : 
     935          112 :       DO jquad = 1, num_integ_points
     936              : 
     937              :          CALL parallel_gemm('N', 'N', dimen_RI, dimen_RI, dimen_RI, 1.0_dp, fm_work_Minv, fm_mat_W(jquad), &
     938           96 :                             0.0_dp, fm_work_Minv_W)
     939              :          CALL parallel_gemm('N', 'N', dimen_RI, dimen_RI, dimen_RI, 1.0_dp, fm_work_Minv_W, fm_work_Minv, &
     940          112 :                             0.0_dp, fm_mat_W(jquad))
     941              : 
     942              :       END DO
     943              : 
     944           16 :       CALL cp_fm_release(fm_work_Minv)
     945              : 
     946           16 :       CALL cp_fm_release(fm_work_Minv_W)
     947              : 
     948           16 :       CALL timestop(handle)
     949              : 
     950           16 :    END SUBROUTINE Wc_to_Minv_Wc_Minv
     951              : 
     952              : ! **************************************************************************************************
     953              : !> \brief ...
     954              : !> \param qs_env ...
     955              : !> \param wkp_W ...
     956              : !> \param wkp_V ...
     957              : !> \param kpoints ...
     958              : !> \param h_inv ...
     959              : !> \param periodic ...
     960              : ! **************************************************************************************************
     961           22 :    SUBROUTINE compute_wkp_W(qs_env, wkp_W, wkp_V, kpoints, h_inv, periodic)
     962              : 
     963              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     964              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
     965              :          INTENT(OUT)                                     :: wkp_W, wkp_V
     966              :       TYPE(kpoint_type), POINTER                         :: kpoints
     967              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: h_inv
     968              :       INTEGER, DIMENSION(3)                              :: periodic
     969              : 
     970              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'compute_wkp_W'
     971              : 
     972              :       INTEGER                                            :: handle, i_x, ikp, info, j_y, k_z, &
     973              :                                                             kpoint_weights_W_method, n_x, n_y, &
     974              :                                                             n_z, nkp, nsuperfine, num_lin_eqs
     975              :       REAL(KIND=dp)                                      :: exp_kpoints, integral, k_sq, weight
     976              :       REAL(KIND=dp), DIMENSION(3)                        :: k_vec, x_vec
     977           22 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: right_side, wkp, wkp_tmp
     978           22 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: matrix_lin_eqs, xkp
     979              : 
     980           22 :       CALL timeset(routineN, handle)
     981              : 
     982           22 :       kpoint_weights_W_method = qs_env%mp2_env%ri_rpa_im_time%kpoint_weights_W_method
     983              : 
     984           22 :       CALL get_kpoint_info(kpoints, xkp=xkp, wkp=wkp, nkp=nkp)
     985              : 
     986              :       ! we determine the kpoint weights of the Monkhors Pack mesh new
     987              :       ! such that the functions 1/k^2, 1/k and const are integrated exactly
     988              :       ! in the Brillouin zone
     989              :       ! this is done by minimizing sum_i |w_i|^2 where w_i are the weights of
     990              :       ! the i-th kpoint under the following constraints:
     991              :       ! 1) 1/k^2, 1/k and const are integrated exactly
     992              :       ! 2) the kpoint weights of kpoints with identical absolute value are
     993              :       !    the same, of e.g. (1/8,3/8,3/8) same weight as for (3/8,1/8,3/8)
     994              :       ! for 1d and 2d materials: we use ordinary Monkhorst-Pack weights, checked
     995              :       ! by SUM(periodic) == 3
     996           88 :       ALLOCATE (wkp_V(nkp), wkp_W(nkp))
     997              : 
     998              :       ! for exchange part of self-energy, we use truncated Coulomb operator that should be fine
     999              :       ! with uniform weights (without k-point extrapolation)
    1000           22 :       IF (ALLOCATED(qs_env%mp2_env%ri_rpa_im_time%wkp_V)) THEN
    1001          432 :          wkp_V(:) = qs_env%mp2_env%ri_rpa_im_time%wkp_V(:)
    1002              :       ELSE
    1003           18 :          wkp_V(:) = wkp(:)
    1004              :       END IF
    1005              : 
    1006           22 :       IF (kpoint_weights_W_method == kp_weights_W_uniform) THEN
    1007              : 
    1008              :          !  in the k-point weights wkp, there might be k-point extrapolation included
    1009          450 :          wkp_W(:) = wkp(:)
    1010              : 
    1011            0 :       ELSE IF (kpoint_weights_W_method == kp_weights_W_tailored .OR. &
    1012              :                kpoint_weights_W_method == kp_weights_W_auto) THEN
    1013              : 
    1014            0 :          IF (kpoint_weights_W_method == kp_weights_W_tailored) THEN
    1015            0 :             exp_kpoints = qs_env%mp2_env%ri_rpa_im_time%exp_tailored_weights
    1016              :          END IF
    1017              : 
    1018            0 :          IF (kpoint_weights_W_method == kp_weights_W_auto) THEN
    1019            0 :             IF (SUM(periodic) == 2) exp_kpoints = -1.0_dp
    1020              :          END IF
    1021              : 
    1022              :          ! first, compute the integral of f(k)=1/k^2 and 1/k on super fine grid
    1023            0 :          nsuperfine = 500
    1024            0 :          integral = 0.0_dp
    1025              : 
    1026            0 :          IF (periodic(1) == 1) THEN
    1027              :             n_x = nsuperfine
    1028              :          ELSE
    1029            0 :             n_x = 1
    1030              :          END IF
    1031            0 :          IF (periodic(2) == 1) THEN
    1032              :             n_y = nsuperfine
    1033              :          ELSE
    1034            0 :             n_y = 1
    1035              :          END IF
    1036            0 :          IF (periodic(3) == 1) THEN
    1037              :             n_z = nsuperfine
    1038              :          ELSE
    1039            0 :             n_z = 1
    1040              :          END IF
    1041              : 
    1042              :          ! actually, there is the factor *det_3x3(h_inv) missing to account for the
    1043              :          ! integration volume but for wkp det_3x3(h_inv) is needed
    1044            0 :          weight = 1.0_dp/(REAL(n_x, dp)*REAL(n_y, dp)*REAL(n_z, dp))
    1045            0 :          DO i_x = 1, n_x
    1046            0 :             DO j_y = 1, n_y
    1047            0 :                DO k_z = 1, n_z
    1048              : 
    1049            0 :                   IF (periodic(1) == 1) THEN
    1050            0 :                      x_vec(1) = (REAL(i_x - nsuperfine/2, dp) - 0.5_dp)/REAL(nsuperfine, dp)
    1051              :                   ELSE
    1052            0 :                      x_vec(1) = 0.0_dp
    1053              :                   END IF
    1054            0 :                   IF (periodic(2) == 1) THEN
    1055            0 :                      x_vec(2) = (REAL(j_y - nsuperfine/2, dp) - 0.5_dp)/REAL(nsuperfine, dp)
    1056              :                   ELSE
    1057            0 :                      x_vec(2) = 0.0_dp
    1058              :                   END IF
    1059            0 :                   IF (periodic(3) == 1) THEN
    1060            0 :                      x_vec(3) = (REAL(k_z - nsuperfine/2, dp) - 0.5_dp)/REAL(nsuperfine, dp)
    1061              :                   ELSE
    1062            0 :                      x_vec(3) = 0.0_dp
    1063              :                   END IF
    1064              : 
    1065            0 :                   k_vec = MATMUL(h_inv(1:3, 1:3), x_vec)
    1066            0 :                   k_sq = k_vec(1)**2 + k_vec(2)**2 + k_vec(3)**2
    1067            0 :                   integral = integral + weight*k_sq**(exp_kpoints*0.5_dp)
    1068              : 
    1069              :                END DO
    1070              :             END DO
    1071              :          END DO
    1072              : 
    1073            0 :          num_lin_eqs = nkp + 2
    1074              : 
    1075            0 :          ALLOCATE (matrix_lin_eqs(num_lin_eqs, num_lin_eqs))
    1076            0 :          matrix_lin_eqs(:, :) = 0.0_dp
    1077              : 
    1078            0 :          DO ikp = 1, nkp
    1079              : 
    1080            0 :             k_vec = MATMUL(h_inv(1:3, 1:3), xkp(1:3, ikp))
    1081            0 :             k_sq = k_vec(1)**2 + k_vec(2)**2 + k_vec(3)**2
    1082              : 
    1083            0 :             matrix_lin_eqs(ikp, ikp) = 2.0_dp
    1084            0 :             matrix_lin_eqs(ikp, nkp + 1) = 1.0_dp
    1085            0 :             matrix_lin_eqs(nkp + 1, ikp) = 1.0_dp
    1086              : 
    1087            0 :             matrix_lin_eqs(ikp, nkp + 2) = k_sq**(exp_kpoints*0.5_dp)
    1088            0 :             matrix_lin_eqs(nkp + 2, ikp) = k_sq**(exp_kpoints*0.5_dp)
    1089              : 
    1090              :          END DO
    1091              : 
    1092            0 :          CALL invmat(matrix_lin_eqs, info)
    1093              :          ! check whether inversion was successful
    1094            0 :          CPASSERT(info == 0)
    1095              : 
    1096            0 :          ALLOCATE (right_side(num_lin_eqs))
    1097            0 :          right_side = 0.0_dp
    1098            0 :          right_side(nkp + 1) = 1.0_dp
    1099              :          ! divide integral by two because CP2K k-mesh already considers symmetry k <-> -k
    1100            0 :          right_side(nkp + 2) = integral
    1101              : 
    1102            0 :          ALLOCATE (wkp_tmp(num_lin_eqs))
    1103              : 
    1104            0 :          wkp_tmp(1:num_lin_eqs) = MATMUL(matrix_lin_eqs, right_side)
    1105              : 
    1106            0 :          wkp_W(1:nkp) = wkp_tmp(1:nkp)
    1107              : 
    1108            0 :          DEALLOCATE (matrix_lin_eqs, right_side, wkp_tmp)
    1109              : 
    1110              :       END IF
    1111              : 
    1112           22 :       CALL timestop(handle)
    1113              : 
    1114           22 :    END SUBROUTINE compute_wkp_W
    1115              : 
    1116              : ! **************************************************************************************************
    1117              : !> \brief ...
    1118              : !> \param qs_env ...
    1119              : !> \param Eigenval_kp ...
    1120              : ! **************************************************************************************************
    1121           16 :    SUBROUTINE get_bandstruc_and_k_dependent_MOs(qs_env, Eigenval_kp)
    1122              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1123              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: Eigenval_kp
    1124              : 
    1125              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'get_bandstruc_and_k_dependent_MOs'
    1126              : 
    1127              :       INTEGER                                            :: handle, ikp, ispin, nmo, nspins
    1128              :       INTEGER, DIMENSION(3)                              :: nkp_grid_G
    1129           16 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: ev
    1130           16 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: kpgeneral
    1131              :       TYPE(kpoint_type), POINTER                         :: kpoints_Sigma
    1132              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1133              : 
    1134           16 :       CALL timeset(routineN, handle)
    1135              : 
    1136              :       NULLIFY (qs_env%mp2_env%ri_rpa_im_time%kpoints_G, &
    1137           16 :                qs_env%mp2_env%ri_rpa_im_time%kpoints_Sigma, &
    1138           16 :                qs_env%mp2_env%ri_rpa_im_time%kpoints_Sigma_no_xc, &
    1139           16 :                para_env)
    1140              : 
    1141           16 :       nkp_grid_G(1:3) = [1, 1, 1]
    1142              : 
    1143           16 :       CALL get_qs_env(qs_env=qs_env, para_env=para_env)
    1144              : 
    1145              :       CALL create_kp_and_calc_kp_orbitals(qs_env, qs_env%mp2_env%ri_rpa_im_time%kpoints_G, &
    1146              :                                           "MONKHORST-PACK", para_env%num_pe, &
    1147           16 :                                           mp_grid=nkp_grid_G(1:3))
    1148              : 
    1149           16 :       IF (qs_env%mp2_env%ri_g0w0%do_kpoints_Sigma) THEN
    1150              : 
    1151              :          ! set up k-points for GW band structure calculation, will be completed later
    1152           16 :          CALL get_kpgeneral_for_Sigma_kpoints(qs_env, kpgeneral)
    1153              : 
    1154              :          CALL create_kp_and_calc_kp_orbitals(qs_env, qs_env%mp2_env%ri_rpa_im_time%kpoints_Sigma, &
    1155              :                                              "GENERAL", para_env%num_pe, &
    1156           16 :                                              kpgeneral=kpgeneral)
    1157              : 
    1158              :          CALL create_kp_and_calc_kp_orbitals(qs_env, qs_env%mp2_env%ri_rpa_im_time%kpoints_Sigma_no_xc, &
    1159              :                                              "GENERAL", para_env%num_pe, &
    1160           16 :                                              kpgeneral=kpgeneral, with_xc_terms=.FALSE.)
    1161              : 
    1162           16 :          kpoints_Sigma => qs_env%mp2_env%ri_rpa_im_time%kpoints_Sigma
    1163           16 :          nmo = SIZE(Eigenval_kp, 1)
    1164           16 :          nspins = SIZE(Eigenval_kp, 3)
    1165              : 
    1166           48 :          ALLOCATE (qs_env%mp2_env%ri_rpa_im_time%Eigenval_Gamma(nmo))
    1167          340 :          qs_env%mp2_env%ri_rpa_im_time%Eigenval_Gamma(:) = Eigenval_kp(:, 1, 1)
    1168              : 
    1169           16 :          DEALLOCATE (Eigenval_kp)
    1170              : 
    1171           80 :          ALLOCATE (Eigenval_kp(nmo, kpoints_Sigma%nkp, nspins))
    1172              : 
    1173          136 :          DO ikp = 1, kpoints_Sigma%nkp
    1174              : 
    1175          272 :             DO ispin = 1, nspins
    1176              : 
    1177          136 :                ev => kpoints_Sigma%kp_env(ikp)%kpoint_env%mos(ispin)%eigenvalues
    1178              : 
    1179         3016 :                Eigenval_kp(:, ikp, ispin) = ev(:)
    1180              : 
    1181              :             END DO
    1182              : 
    1183              :          END DO
    1184              : 
    1185           16 :          DEALLOCATE (kpgeneral)
    1186              : 
    1187              :       END IF
    1188              : 
    1189           16 :       CALL release_hfx_stuff(qs_env)
    1190              : 
    1191           16 :       CALL timestop(handle)
    1192              : 
    1193           16 :    END SUBROUTINE get_bandstruc_and_k_dependent_MOs
    1194              : 
    1195              : ! **************************************************************************************************
    1196              : !> \brief releases part of the given qs_env in order to save memory
    1197              : !> \param qs_env the object to release
    1198              : ! **************************************************************************************************
    1199           16 :    SUBROUTINE release_hfx_stuff(qs_env)
    1200              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1201              : 
    1202           16 :       IF (ASSOCIATED(qs_env%x_data) .AND. .NOT. qs_env%mp2_env%ri_g0w0%do_ri_Sigma_x) THEN
    1203            2 :          CALL hfx_release(qs_env%x_data)
    1204              :       END IF
    1205              : 
    1206           16 :    END SUBROUTINE release_hfx_stuff
    1207              : 
    1208              : ! **************************************************************************************************
    1209              : !> \brief ...
    1210              : !> \param qs_env ...
    1211              : !> \param kpoints ...
    1212              : !> \param scheme ...
    1213              : !> \param group_size_ext ...
    1214              : !> \param mp_grid ...
    1215              : !> \param kpgeneral ...
    1216              : !> \param with_xc_terms ...
    1217              : !> \param kp_shift ...
    1218              : !> \param gamma_centered ...
    1219              : ! **************************************************************************************************
    1220          336 :    SUBROUTINE create_kp_and_calc_kp_orbitals(qs_env, kpoints, scheme, &
    1221           48 :                                              group_size_ext, mp_grid, kpgeneral, with_xc_terms, &
    1222              :                                              kp_shift, gamma_centered)
    1223              : 
    1224              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1225              :       TYPE(kpoint_type), POINTER                         :: kpoints
    1226              :       CHARACTER(LEN=*), INTENT(IN)                       :: scheme
    1227              :       INTEGER                                            :: group_size_ext
    1228              :       INTEGER, DIMENSION(3), INTENT(IN), OPTIONAL        :: mp_grid
    1229              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN), &
    1230              :          OPTIONAL                                        :: kpgeneral
    1231              :       LOGICAL, OPTIONAL                                  :: with_xc_terms
    1232              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN), OPTIONAL  :: kp_shift
    1233              :       LOGICAL, INTENT(IN), OPTIONAL                      :: gamma_centered
    1234              : 
    1235              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'create_kp_and_calc_kp_orbitals'
    1236              : 
    1237              :       INTEGER                                            :: handle, i_re_im, ikp, ispin, nkp, nspins
    1238              :       INTEGER, DIMENSION(3)                              :: periodic
    1239              :       LOGICAL                                            :: my_with_xc_terms
    1240           48 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues
    1241              :       TYPE(cell_type), POINTER                           :: cell
    1242              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1243              :       TYPE(cp_cfm_type)                                  :: cksmat, cmos, csmat, cwork
    1244              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
    1245              :       TYPE(cp_fm_type)                                   :: fm_work
    1246           48 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s, matrix_s_desymm
    1247           48 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_ks_kp, mat_s_kp
    1248              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1249              :       TYPE(kpoint_env_type), POINTER                     :: kp
    1250              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1251              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    1252              :       TYPE(scf_control_type), POINTER                    :: scf_control
    1253              : 
    1254           48 :       CALL timeset(routineN, handle)
    1255              : 
    1256           48 :       my_with_xc_terms = .TRUE.
    1257           48 :       IF (PRESENT(with_xc_terms)) my_with_xc_terms = with_xc_terms
    1258              : 
    1259              :       CALL get_qs_env(qs_env, &
    1260              :                       para_env=para_env, &
    1261              :                       blacs_env=blacs_env, &
    1262              :                       matrix_s=matrix_s, &
    1263              :                       scf_env=scf_env, &
    1264              :                       scf_control=scf_control, &
    1265           48 :                       cell=cell)
    1266              : 
    1267              :       ! get kpoints
    1268              :       CALL calculate_kpoints_for_bs(kpoints, scheme, kpgeneral=kpgeneral, mp_grid=mp_grid, &
    1269              :                                     group_size_ext=group_size_ext, kp_shift=kp_shift, &
    1270           64 :                                     gamma_centered=gamma_centered)
    1271              : 
    1272           48 :       CALL kpoint_env_initialize(kpoints, para_env, blacs_env)
    1273              : 
    1274              :       ! calculate all MOs that are accessible in the given
    1275              :       ! Gaussian AO basis, therefore nadd=1E10
    1276           48 :       CALL kpoint_initialize_mos(kpoints, qs_env%mos, 2000000000)
    1277           48 :       CALL kpoint_initialize_mo_set(kpoints)
    1278              : 
    1279           48 :       CALL get_cell(cell=cell, periodic=periodic)
    1280              : 
    1281          192 :       CALL init_cell_index_rpa(2*periodic + 1, kpoints%cell_to_index, kpoints%index_to_cell, cell)
    1282              : 
    1283              :       ! get S(k)
    1284           48 :       CALL get_qs_env(qs_env, matrix_s=matrix_s, scf_env=scf_env, scf_control=scf_control, dft_control=dft_control)
    1285              : 
    1286           48 :       NULLIFY (matrix_s_desymm)
    1287           48 :       CALL dbcsr_allocate_matrix_set(matrix_s_desymm, 1)
    1288           48 :       ALLOCATE (matrix_s_desymm(1)%matrix)
    1289              :       CALL dbcsr_create(matrix=matrix_s_desymm(1)%matrix, template=matrix_s(1)%matrix, &
    1290           48 :                         matrix_type=dbcsr_type_no_symmetry)
    1291           48 :       CALL dbcsr_desymmetrize(matrix_s(1)%matrix, matrix_s_desymm(1)%matrix)
    1292              : 
    1293           48 :       CALL mat_kp_from_mat_gamma(qs_env, mat_s_kp, matrix_s_desymm(1)%matrix, kpoints, 1)
    1294              : 
    1295           48 :       CALL get_kpoint_info(kpoints, nkp=nkp)
    1296              : 
    1297           48 :       matrix_struct => kpoints%kp_env(1)%kpoint_env%wmat(1, 1)%matrix_struct
    1298              : 
    1299           48 :       CALL cp_cfm_create(cksmat, matrix_struct)
    1300           48 :       CALL cp_cfm_create(csmat, matrix_struct)
    1301           48 :       CALL cp_cfm_create(cmos, matrix_struct)
    1302           48 :       CALL cp_cfm_create(cwork, matrix_struct)
    1303           48 :       CALL cp_fm_create(fm_work, matrix_struct)
    1304              : 
    1305           48 :       nspins = dft_control%nspins
    1306              : 
    1307          102 :       DO ispin = 1, nspins
    1308              : 
    1309              :          ! get H(k)
    1310           54 :          IF (my_with_xc_terms) THEN
    1311           36 :             CALL mat_kp_from_mat_gamma(qs_env, mat_ks_kp, qs_env%mp2_env%ri_g0w0%matrix_ks(ispin)%matrix, kpoints, ispin)
    1312              :          ELSE
    1313              :             CALL mat_kp_from_mat_gamma(qs_env, mat_ks_kp, qs_env%mp2_env%ri_g0w0%matrix_sigma_x_minus_vxc(ispin)%matrix, &
    1314           18 :                                        kpoints, ispin)
    1315              :          END IF
    1316              : 
    1317          392 :          DO ikp = 1, nkp
    1318              : 
    1319          290 :             CALL copy_dbcsr_to_fm(mat_ks_kp(ikp, 1)%matrix, kpoints%kp_env(ikp)%kpoint_env%wmat(1, ispin))
    1320          290 :             CALL cp_cfm_scale_and_add_fm(z_zero, cksmat, z_one, kpoints%kp_env(ikp)%kpoint_env%wmat(1, ispin))
    1321              : 
    1322          290 :             CALL copy_dbcsr_to_fm(mat_ks_kp(ikp, 2)%matrix, kpoints%kp_env(ikp)%kpoint_env%wmat(2, ispin))
    1323          290 :             CALL cp_cfm_scale_and_add_fm(z_one, cksmat, gaussi, kpoints%kp_env(ikp)%kpoint_env%wmat(2, ispin))
    1324              : 
    1325          290 :             CALL copy_dbcsr_to_fm(mat_s_kp(ikp, 1)%matrix, fm_work)
    1326          290 :             CALL cp_cfm_scale_and_add_fm(z_zero, csmat, z_one, fm_work)
    1327              : 
    1328          290 :             CALL copy_dbcsr_to_fm(mat_s_kp(ikp, 2)%matrix, fm_work)
    1329          290 :             CALL cp_cfm_scale_and_add_fm(z_one, csmat, gaussi, fm_work)
    1330              : 
    1331          290 :             kp => kpoints%kp_env(ikp)%kpoint_env
    1332              : 
    1333          290 :             CALL get_mo_set(kp%mos(ispin), eigenvalues=eigenvalues)
    1334              : 
    1335          290 :             IF (scf_env%cholesky_method == cholesky_off .OR. &
    1336              :                 qs_env%mp2_env%ri_rpa_im_time%make_overlap_mat_ao_pos_definite) THEN
    1337            0 :                CALL cp_cfm_geeig_canon(cksmat, csmat, cmos, eigenvalues, cwork, scf_control%eps_eigval)
    1338              :             ELSE
    1339          290 :                CALL cp_cfm_geeig(cksmat, csmat, cmos, eigenvalues, cwork)
    1340              :             END IF
    1341              : 
    1342          290 :             CALL cp_cfm_to_cfm(cmos, kp%mos(ispin)%cmo_coeff)
    1343              : 
    1344        12382 :             kp%mos(ispin)%eigenvalues = eigenvalues
    1345              : 
    1346              :          END DO
    1347              : 
    1348              :       END DO
    1349              : 
    1350          304 :       DO ikp = 1, nkp
    1351          816 :          DO i_re_im = 1, 2
    1352          768 :             CALL dbcsr_deallocate_matrix(mat_ks_kp(ikp, i_re_im)%matrix)
    1353              :          END DO
    1354              :       END DO
    1355           48 :       DEALLOCATE (mat_ks_kp)
    1356              : 
    1357          304 :       DO ikp = 1, nkp
    1358          816 :          DO i_re_im = 1, 2
    1359          768 :             CALL dbcsr_deallocate_matrix(mat_s_kp(ikp, i_re_im)%matrix)
    1360              :          END DO
    1361              :       END DO
    1362           48 :       DEALLOCATE (mat_s_kp)
    1363              : 
    1364           48 :       CALL dbcsr_deallocate_matrix(matrix_s_desymm(1)%matrix)
    1365           48 :       DEALLOCATE (matrix_s_desymm)
    1366              : 
    1367           48 :       CALL cp_cfm_release(cksmat)
    1368           48 :       CALL cp_cfm_release(csmat)
    1369           48 :       CALL cp_cfm_release(cwork)
    1370           48 :       CALL cp_cfm_release(cmos)
    1371           48 :       CALL cp_fm_release(fm_work)
    1372              : 
    1373           48 :       CALL timestop(handle)
    1374              : 
    1375           48 :    END SUBROUTINE create_kp_and_calc_kp_orbitals
    1376              : 
    1377              : ! **************************************************************************************************
    1378              : !> \brief ...
    1379              : !> \param qs_env ...
    1380              : !> \param mat_kp ...
    1381              : !> \param mat_gamma ...
    1382              : !> \param kpoints ...
    1383              : !> \param ispin ...
    1384              : !> \param real_mat_real_space ...
    1385              : ! **************************************************************************************************
    1386          114 :    SUBROUTINE mat_kp_from_mat_gamma(qs_env, mat_kp, mat_gamma, kpoints, ispin, real_mat_real_space)
    1387              : 
    1388              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1389              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_kp
    1390              :       TYPE(dbcsr_type)                                   :: mat_gamma
    1391              :       TYPE(kpoint_type), POINTER                         :: kpoints
    1392              :       INTEGER                                            :: ispin
    1393              :       LOGICAL, INTENT(IN), OPTIONAL                      :: real_mat_real_space
    1394              : 
    1395              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'mat_kp_from_mat_gamma'
    1396              : 
    1397              :       INTEGER                                            :: handle, i_cell, i_re_im, ikp, nkp, &
    1398              :                                                             num_cells
    1399              :       INTEGER, DIMENSION(3)                              :: periodic
    1400          114 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    1401          114 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
    1402              :       TYPE(cell_type), POINTER                           :: cell
    1403          114 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mat_real_space
    1404              : 
    1405          114 :       CALL timeset(routineN, handle)
    1406              : 
    1407          114 :       CALL get_qs_env(qs_env, cell=cell)
    1408          114 :       CALL get_cell(cell=cell, periodic=periodic)
    1409          114 :       num_cells = 3**(periodic(1) + periodic(2) + periodic(3))
    1410              : 
    1411          114 :       NULLIFY (mat_real_space)
    1412          114 :       CALL dbcsr_allocate_matrix_set(mat_real_space, num_cells)
    1413         1140 :       DO i_cell = 1, num_cells
    1414         1026 :          ALLOCATE (mat_real_space(i_cell)%matrix)
    1415              :          CALL dbcsr_create(matrix=mat_real_space(i_cell)%matrix, &
    1416         1026 :                            template=mat_gamma)
    1417         1026 :          CALL dbcsr_reserve_all_blocks(mat_real_space(i_cell)%matrix)
    1418         1140 :          CALL dbcsr_set(mat_real_space(i_cell)%matrix, 0.0_dp)
    1419              :       END DO
    1420              : 
    1421          114 :       CALL dbcsr_copy(mat_real_space(1)%matrix, mat_gamma)
    1422              : 
    1423          114 :       CALL get_mat_cell_T_from_mat_gamma(mat_real_space, qs_env, kpoints, 2, 0)
    1424              : 
    1425          114 :       NULLIFY (xkp, cell_to_index)
    1426          114 :       CALL get_kpoint_info(kpoints, nkp=nkp, xkp=xkp, cell_to_index=cell_to_index)
    1427              : 
    1428          114 :       IF (ispin == 1) THEN
    1429          108 :          NULLIFY (mat_kp)
    1430          108 :          CALL dbcsr_allocate_matrix_set(mat_kp, nkp, 2)
    1431          668 :          DO ikp = 1, nkp
    1432         1788 :             DO i_re_im = 1, 2
    1433         1120 :                ALLOCATE (mat_kp(ikp, i_re_im)%matrix)
    1434         1120 :                CALL dbcsr_create(matrix=mat_kp(ikp, i_re_im)%matrix, template=mat_gamma)
    1435         1120 :                CALL dbcsr_reserve_all_blocks(mat_kp(ikp, i_re_im)%matrix)
    1436         1680 :                CALL dbcsr_set(mat_kp(ikp, i_re_im)%matrix, 0.0_dp)
    1437              :             END DO
    1438              :          END DO
    1439              :       END IF
    1440              : 
    1441          114 :       IF (PRESENT(real_mat_real_space)) THEN
    1442              :          CALL real_space_to_kpoint_transform_rpa(mat_kp(:, 1), mat_kp(:, 2), mat_real_space, kpoints, 0.0_dp, &
    1443           12 :                                                  real_mat_real_space)
    1444              :       ELSE
    1445          102 :          CALL real_space_to_kpoint_transform_rpa(mat_kp(:, 1), mat_kp(:, 2), mat_real_space, kpoints, 0.0_dp)
    1446              :       END IF
    1447              : 
    1448         1140 :       DO i_cell = 1, num_cells
    1449         1140 :          CALL dbcsr_deallocate_matrix(mat_real_space(i_cell)%matrix)
    1450              :       END DO
    1451          114 :       DEALLOCATE (mat_real_space)
    1452              : 
    1453          114 :       CALL timestop(handle)
    1454              : 
    1455          114 :    END SUBROUTINE mat_kp_from_mat_gamma
    1456              : 
    1457              : ! **************************************************************************************************
    1458              : !> \brief ...
    1459              : !> \param qs_env ...
    1460              : !> \param kpgeneral ...
    1461              : ! **************************************************************************************************
    1462           16 :    SUBROUTINE get_kpgeneral_for_Sigma_kpoints(qs_env, kpgeneral)
    1463              :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
    1464              :       REAL(kind=dp), DIMENSION(:, :), POINTER            :: kpgeneral
    1465              : 
    1466              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'get_kpgeneral_for_Sigma_kpoints'
    1467              : 
    1468              :       INTEGER                                            :: handle, i_kp_in_kp_line, i_special_kp, &
    1469              :                                                             i_x, ikk, j_y, k_z, n_kp_in_kp_line, &
    1470              :                                                             n_special_kp
    1471           16 :       INTEGER, DIMENSION(:), POINTER                     :: nkp_grid
    1472              : 
    1473           16 :       CALL timeset(routineN, handle)
    1474              : 
    1475           16 :       n_special_kp = qs_env%mp2_env%ri_g0w0%n_special_kp
    1476           16 :       n_kp_in_kp_line = qs_env%mp2_env%ri_g0w0%n_kp_in_kp_line
    1477           16 :       IF (n_special_kp > 0) THEN
    1478           14 :          qs_env%mp2_env%ri_g0w0%nkp_self_energy_special_kp = n_kp_in_kp_line*(n_special_kp - 1) + 1
    1479              :       ELSE
    1480            2 :          qs_env%mp2_env%ri_g0w0%nkp_self_energy_special_kp = 0
    1481              :       END IF
    1482              : 
    1483              :       qs_env%mp2_env%ri_g0w0%nkp_self_energy_monkh_pack = qs_env%mp2_env%ri_g0w0%kp_grid_Sigma(1)* &
    1484              :                                                           qs_env%mp2_env%ri_g0w0%kp_grid_Sigma(2)* &
    1485           16 :                                                           qs_env%mp2_env%ri_g0w0%kp_grid_Sigma(3)
    1486              : 
    1487              :       qs_env%mp2_env%ri_g0w0%nkp_self_energy = qs_env%mp2_env%ri_g0w0%nkp_self_energy_special_kp + &
    1488           16 :                                                qs_env%mp2_env%ri_g0w0%nkp_self_energy_monkh_pack
    1489              : 
    1490           48 :       ALLOCATE (kpgeneral(3, qs_env%mp2_env%ri_g0w0%nkp_self_energy))
    1491              : 
    1492           16 :       IF (n_special_kp > 0) THEN
    1493              : 
    1494          112 :          kpgeneral(1:3, 1) = qs_env%mp2_env%ri_g0w0%xkp_special_kp(1:3, 1)
    1495              : 
    1496           14 :          ikk = 1
    1497              : 
    1498           28 :          DO i_special_kp = 2, n_special_kp
    1499           70 :             DO i_kp_in_kp_line = 1, n_kp_in_kp_line
    1500              : 
    1501           42 :                ikk = ikk + 1
    1502              :                kpgeneral(1:3, ikk) = qs_env%mp2_env%ri_g0w0%xkp_special_kp(1:3, i_special_kp - 1) + &
    1503              :                                      REAL(i_kp_in_kp_line, KIND=dp)/REAL(n_kp_in_kp_line, KIND=dp)* &
    1504              :                                      (qs_env%mp2_env%ri_g0w0%xkp_special_kp(1:3, i_special_kp) - &
    1505          350 :                                       qs_env%mp2_env%ri_g0w0%xkp_special_kp(1:3, i_special_kp - 1))
    1506              : 
    1507              :             END DO
    1508              :          END DO
    1509              : 
    1510              :       ELSE
    1511              : 
    1512              :          ikk = 0
    1513              : 
    1514              :       END IF
    1515              : 
    1516           16 :       nkp_grid => qs_env%mp2_env%ri_g0w0%kp_grid_Sigma
    1517              : 
    1518           48 :       DO i_x = 1, nkp_grid(1)
    1519          112 :          DO j_y = 1, nkp_grid(2)
    1520          160 :             DO k_z = 1, nkp_grid(3)
    1521           64 :                ikk = ikk + 1
    1522           64 :                kpgeneral(1, ikk) = REAL(2*i_x - nkp_grid(1) - 1, KIND=dp)/(2._dp*REAL(nkp_grid(1), KIND=dp))
    1523           64 :                kpgeneral(2, ikk) = REAL(2*j_y - nkp_grid(2) - 1, KIND=dp)/(2._dp*REAL(nkp_grid(2), KIND=dp))
    1524          128 :                kpgeneral(3, ikk) = REAL(2*k_z - nkp_grid(3) - 1, KIND=dp)/(2._dp*REAL(nkp_grid(3), KIND=dp))
    1525              :             END DO
    1526              :          END DO
    1527              :       END DO
    1528              : 
    1529           16 :       CALL timestop(handle)
    1530              : 
    1531           16 :    END SUBROUTINE get_kpgeneral_for_Sigma_kpoints
    1532              : 
    1533            0 : END MODULE rpa_gw_kpoints_util
        

Generated by: LCOV version 2.0-1