LCOV - code coverage report
Current view: top level - src - gw_large_cell_gamma.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 681 735 92.7 %
Date: 2024-12-21 06:28:57 Functions: 39 40 97.5 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief Routines from paper [Graml2024]
      10             : !> \author Jan Wilhelm
      11             : !> \date 07.2023
      12             : ! **************************************************************************************************
      13             : MODULE gw_large_cell_gamma
      14             :    USE atomic_kind_types,               ONLY: atomic_kind_type
      15             :    USE cell_types,                      ONLY: cell_type,&
      16             :                                               get_cell,&
      17             :                                               pbc
      18             :    USE constants_operator,              ONLY: operator_coulomb
      19             :    USE cp_cfm_basic_linalg,             ONLY: cp_cfm_upper_to_full
      20             :    USE cp_cfm_cholesky,                 ONLY: cp_cfm_cholesky_decompose,&
      21             :                                               cp_cfm_cholesky_invert
      22             :    USE cp_cfm_diag,                     ONLY: cp_cfm_geeig
      23             :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      24             :                                               cp_cfm_get_info,&
      25             :                                               cp_cfm_release,&
      26             :                                               cp_cfm_to_cfm,&
      27             :                                               cp_cfm_to_fm,&
      28             :                                               cp_cfm_type,&
      29             :                                               cp_fm_to_cfm
      30             :    USE cp_dbcsr_api,                    ONLY: &
      31             :         dbcsr_add, dbcsr_copy, dbcsr_create, dbcsr_deallocate_matrix, dbcsr_get_block_p, &
      32             :         dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, dbcsr_iterator_start, &
      33             :         dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_p_type, dbcsr_release, &
      34             :         dbcsr_reserve_all_blocks, dbcsr_set, dbcsr_type
      35             :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      36             :                                               copy_fm_to_dbcsr,&
      37             :                                               dbcsr_deallocate_matrix_set
      38             :    USE cp_files,                        ONLY: close_file,&
      39             :                                               open_file
      40             :    USE cp_fm_basic_linalg,              ONLY: cp_fm_scale_and_add
      41             :    USE cp_fm_diag,                      ONLY: cp_fm_power
      42             :    USE cp_fm_types,                     ONLY: &
      43             :         cp_fm_create, cp_fm_get_diag, cp_fm_get_info, cp_fm_read_unformatted, cp_fm_release, &
      44             :         cp_fm_set_all, cp_fm_to_fm, cp_fm_type, cp_fm_write_unformatted
      45             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      46             :                                               cp_logger_type
      47             :    USE cp_output_handling,              ONLY: cp_p_file,&
      48             :                                               cp_print_key_should_output,&
      49             :                                               cp_print_key_unit_nr
      50             :    USE dbt_api,                         ONLY: dbt_clear,&
      51             :                                               dbt_contract,&
      52             :                                               dbt_copy,&
      53             :                                               dbt_create,&
      54             :                                               dbt_destroy,&
      55             :                                               dbt_type
      56             :    USE gw_communication,                ONLY: fm_to_local_tensor,&
      57             :                                               local_dbt_to_global_mat
      58             :    USE gw_utils,                        ONLY: analyt_conti_and_print,&
      59             :                                               de_init_bs_env,&
      60             :                                               time_to_freq
      61             :    USE input_constants,                 ONLY: rtp_method_bse
      62             :    USE input_section_types,             ONLY: section_vals_type
      63             :    USE kinds,                           ONLY: default_string_length,&
      64             :                                               dp,&
      65             :                                               int_8
      66             :    USE kpoint_coulomb_2c,               ONLY: build_2c_coulomb_matrix_kp
      67             :    USE kpoint_types,                    ONLY: kpoint_type
      68             :    USE machine,                         ONLY: m_walltime
      69             :    USE mathconstants,                   ONLY: twopi,&
      70             :                                               z_one,&
      71             :                                               z_zero
      72             :    USE message_passing,                 ONLY: mp_file_delete
      73             :    USE mp2_ri_2c,                       ONLY: RI_2c_integral_mat
      74             :    USE parallel_gemm_api,               ONLY: parallel_gemm
      75             :    USE particle_types,                  ONLY: particle_type
      76             :    USE post_scf_bandstructure_types,    ONLY: post_scf_bandstructure_type
      77             :    USE post_scf_bandstructure_utils,    ONLY: MIC_contribution_from_ikp,&
      78             :                                               cfm_ikp_from_fm_Gamma,&
      79             :                                               get_all_VBM_CBM_bandgaps
      80             :    USE qs_environment_types,            ONLY: get_qs_env,&
      81             :                                               qs_environment_type
      82             :    USE qs_kind_types,                   ONLY: qs_kind_type
      83             :    USE qs_tensors,                      ONLY: build_3c_integrals
      84             :    USE rpa_gw_kpoints_util,             ONLY: cp_cfm_power
      85             : #include "./base/base_uses.f90"
      86             : 
      87             :    IMPLICIT NONE
      88             : 
      89             :    PRIVATE
      90             : 
      91             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'gw_large_cell_gamma'
      92             : 
      93             :    PUBLIC :: gw_calc_large_cell_Gamma, &
      94             :              compute_3c_integrals
      95             : 
      96             : CONTAINS
      97             : 
      98             : ! **************************************************************************************************
      99             : !> \brief Perform GW band structure calculation
     100             : !> \param qs_env ...
     101             : !> \param bs_env ...
     102             : !> \par History
     103             : !>    * 07.2023 created [Jan Wilhelm]
     104             : ! **************************************************************************************************
     105          28 :    SUBROUTINE gw_calc_large_cell_Gamma(qs_env, bs_env)
     106             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     107             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     108             : 
     109             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'gw_calc_large_cell_Gamma'
     110             : 
     111             :       INTEGER                                            :: handle
     112          28 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_Sigma_x_Gamma, fm_W_MIC_time
     113          28 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :, :)  :: fm_Sigma_c_Gamma_time
     114             : 
     115          28 :       CALL timeset(routineN, handle)
     116             : 
     117             :       ! G^occ_µλ(i|τ|,k=0) = sum_n^occ C_µn(k=0) e^(-|(ϵ_nk=0-ϵ_F)τ|) C_λn(k=0)
     118             :       ! G^vir_µλ(i|τ|,k=0) = sum_n^vir C_µn(k=0) e^(-|(ϵ_nk=0-ϵ_F)τ|) C_λn(k=0)
     119             :       ! χ_PQ(iτ,k=0) = sum_λν [sum_µ (µν|P) G^occ_µλ(i|τ|)] [sum_σ (σλ|Q) G^vir_σν(i|τ|)]
     120          28 :       CALL get_mat_chi_Gamma_tau(bs_env, qs_env, bs_env%mat_chi_Gamma_tau)
     121             : 
     122             :       ! χ_PQ(iτ,k=0) -> χ_PQ(iω,k) -> ε_PQ(iω,k) -> W_PQ(iω,k) -> W^MIC_PQ(iτ) -> M^-1*W^MIC*M^-1
     123          28 :       CALL get_W_MIC(bs_env, qs_env, bs_env%mat_chi_Gamma_tau, fm_W_MIC_time)
     124             : 
     125             :       ! D_µν = sum_n^occ C_µn(k=0) C_νn(k=0), V^trunc_PQ = sum_cell_R <phi_P,0|V^trunc|phi_Q,R>
     126             :       ! Σ^x_λσ(k=0) = sum_νQ [sum_P (νσ|P) V^trunc_PQ] [sum_µ (λµ|Q) D_µν)]
     127          28 :       CALL get_Sigma_x(bs_env, qs_env, fm_Sigma_x_Gamma)
     128             : 
     129             :       ! Σ^c_λσ(iτ,k=0) = sum_νQ [sum_P (νσ|P) W^MIC_PQ(iτ)] [sum_µ (λµ|Q) G^occ_µν(i|τ|)], τ < 0
     130             :       ! Σ^c_λσ(iτ,k=0) = sum_νQ [sum_P (νσ|P) W^MIC_PQ(iτ)] [sum_µ (λµ|Q) G^vir_µν(i|τ|)], τ > 0
     131          28 :       CALL get_Sigma_c(bs_env, qs_env, fm_W_MIC_time, fm_Sigma_c_Gamma_time)
     132             : 
     133             :       ! Σ^c_λσ(iτ,k=0) -> Σ^c_nn(ϵ,k); ϵ_nk^GW = ϵ_nk^DFT + Σ^c_nn(ϵ,k) + Σ^x_nn(k) - v^xc_nn(k)
     134          28 :       CALL compute_QP_energies(bs_env, qs_env, fm_Sigma_x_Gamma, fm_Sigma_c_Gamma_time)
     135             : 
     136          28 :       CALL de_init_bs_env(bs_env)
     137             : 
     138          28 :       CALL timestop(handle)
     139             : 
     140          28 :    END SUBROUTINE gw_calc_large_cell_Gamma
     141             : 
     142             : ! **************************************************************************************************
     143             : !> \brief ...
     144             : !> \param bs_env ...
     145             : !> \param qs_env ...
     146             : !> \param mat_chi_Gamma_tau ...
     147             : ! **************************************************************************************************
     148          28 :    SUBROUTINE get_mat_chi_Gamma_tau(bs_env, qs_env, mat_chi_Gamma_tau)
     149             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     150             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     151             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mat_chi_Gamma_tau
     152             : 
     153             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'get_mat_chi_Gamma_tau'
     154             : 
     155             :       INTEGER :: handle, i_intval_idx, i_t, inner_loop_atoms_interval_index, ispin, j_intval_idx
     156             :       INTEGER, DIMENSION(2)                              :: i_atoms, IL_atoms, j_atoms
     157             :       LOGICAL                                            :: dist_too_long_i, dist_too_long_j
     158             :       REAL(KIND=dp)                                      :: t1, tau
     159         700 :       TYPE(dbt_type)                                     :: t_2c_Gocc, t_2c_Gvir, t_3c_for_Gocc, &
     160         476 :                                                             t_3c_for_Gvir, t_3c_x_Gocc, &
     161         476 :                                                             t_3c_x_Gocc_2, t_3c_x_Gvir, &
     162         252 :                                                             t_3c_x_Gvir_2
     163             : 
     164          28 :       CALL timeset(routineN, handle)
     165             : 
     166         412 :       DO i_t = 1, bs_env%num_time_freq_points
     167             : 
     168         384 :          t1 = m_walltime()
     169             : 
     170         384 :          IF (bs_env%read_chi(i_t)) THEN
     171             : 
     172           0 :             CALL fm_read(bs_env%fm_RI_RI, bs_env, bs_env%chi_name, i_t)
     173             : 
     174             :             CALL copy_fm_to_dbcsr(bs_env%fm_RI_RI, mat_chi_Gamma_tau(i_t)%matrix, &
     175           0 :                                   keep_sparsity=.FALSE.)
     176             : 
     177           0 :             IF (bs_env%unit_nr > 0) THEN
     178             :                WRITE (bs_env%unit_nr, '(T2,A,I5,A,I3,A,F7.1,A)') &
     179           0 :                   'Read χ(iτ,k=0) from file for time point  ', i_t, ' /', &
     180           0 :                   bs_env%num_time_freq_points, &
     181           0 :                   ',    Execution time', m_walltime() - t1, ' s'
     182             :             END IF
     183             : 
     184             :             CYCLE
     185             : 
     186             :          END IF
     187             : 
     188         384 :          IF (.NOT. bs_env%calc_chi(i_t)) CYCLE
     189             : 
     190             :          CALL create_tensors_chi(t_2c_Gocc, t_2c_Gvir, t_3c_for_Gocc, t_3c_for_Gvir, &
     191         204 :                                  t_3c_x_Gocc, t_3c_x_Gvir, t_3c_x_Gocc_2, t_3c_x_Gvir_2, bs_env)
     192             : 
     193             :          ! 1. compute G^occ and G^vir
     194             :          !    Background: G^σ(iτ) = G^occ,σ(iτ) * Θ(-τ) + G^vir,σ(iτ) * Θ(τ), σ ∈ {↑,↓}
     195             :          !    G^occ,σ_µλ(i|τ|,k=0) = sum_n^occ C^σ_µn(k=0) e^(-|(ϵ^σ_nk=0-ϵ_F)τ|) C^σ_λn(k=0)
     196             :          !    G^vir,σ_µλ(i|τ|,k=0) = sum_n^vir C^σ_µn(k=0) e^(-|(ϵ^σ_nk=0-ϵ_F)τ|) C^σ_λn(k=0)
     197         204 :          tau = bs_env%imag_time_points(i_t)
     198             : 
     199         428 :          DO ispin = 1, bs_env%n_spin
     200         224 :             CALL G_occ_vir(bs_env, tau, bs_env%fm_Gocc, ispin, occ=.TRUE., vir=.FALSE.)
     201         224 :             CALL G_occ_vir(bs_env, tau, bs_env%fm_Gvir, ispin, occ=.FALSE., vir=.TRUE.)
     202             : 
     203             :             CALL fm_to_local_tensor(bs_env%fm_Gocc, bs_env%mat_ao_ao%matrix, &
     204             :                                     bs_env%mat_ao_ao_tensor%matrix, t_2c_Gocc, bs_env, &
     205         224 :                                     bs_env%atoms_j_t_group)
     206             :             CALL fm_to_local_tensor(bs_env%fm_Gvir, bs_env%mat_ao_ao%matrix, &
     207             :                                     bs_env%mat_ao_ao_tensor%matrix, t_2c_Gvir, bs_env, &
     208         224 :                                     bs_env%atoms_i_t_group)
     209             : 
     210             :             ! every group has its own range of i_atoms and j_atoms; only deal with a
     211             :             ! limited number of i_atom-j_atom pairs simultaneously in a group to save memory
     212         652 :             DO i_intval_idx = 1, bs_env%n_intervals_i
     213         672 :                DO j_intval_idx = 1, bs_env%n_intervals_j
     214         672 :                   i_atoms = bs_env%i_atom_intervals(1:2, i_intval_idx)
     215         672 :                   j_atoms = bs_env%j_atom_intervals(1:2, j_intval_idx)
     216             : 
     217         448 :                   DO inner_loop_atoms_interval_index = 1, bs_env%n_intervals_inner_loop_atoms
     218             : 
     219         672 :                      IL_atoms = bs_env%inner_loop_atom_intervals(1:2, inner_loop_atoms_interval_index)
     220             : 
     221         224 :                      CALL check_dist(i_atoms, IL_atoms, qs_env, bs_env, dist_too_long_i)
     222         224 :                      CALL check_dist(j_atoms, IL_atoms, qs_env, bs_env, dist_too_long_j)
     223         224 :                      IF (dist_too_long_i .OR. dist_too_long_j) CYCLE
     224             : 
     225             :                      ! 2. compute 3-center integrals (µν|P) ("|": truncated Coulomb operator)
     226         224 :                      CALL compute_3c_integrals(qs_env, bs_env, t_3c_for_Gocc, i_atoms, IL_atoms)
     227             : 
     228             :                      ! 3. tensor operation M_λνP(iτ) = sum_µ (µν|P) G^occ_µλ(i|τ|,k=0)
     229             :                      CALL G_times_3c(t_3c_for_Gocc, t_2c_Gocc, t_3c_x_Gocc, bs_env, &
     230         224 :                                      j_atoms, i_atoms, IL_atoms)
     231             : 
     232             :                      ! 4. compute 3-center integrals (σλ|Q) ("|": truncated Coulomb operator)
     233         224 :                      CALL compute_3c_integrals(qs_env, bs_env, t_3c_for_Gvir, j_atoms, IL_atoms)
     234             : 
     235             :                      ! 5. tensor operation N_νλQ(iτ) = sum_σ (σλ|Q) G^vir_σν(i|τ|,k=0)
     236             :                      CALL G_times_3c(t_3c_for_Gvir, t_2c_Gvir, t_3c_x_Gvir, bs_env, &
     237         448 :                                      i_atoms, j_atoms, IL_atoms)
     238             : 
     239             :                   END DO ! IL_atoms
     240             : 
     241             :                   ! 6. reorder tensors
     242         224 :                   CALL dbt_copy(t_3c_x_Gocc, t_3c_x_Gocc_2, move_data=.TRUE., order=[1, 3, 2])
     243         224 :                   CALL dbt_copy(t_3c_x_Gvir, t_3c_x_Gvir_2, move_data=.TRUE.)
     244             : 
     245             :                   ! 7. tensor operation χ_PQ(iτ,k=0) = sum_λν M_λνP(iτ) N_νλQ(iτ),
     246             :                   CALL dbt_contract(alpha=bs_env%spin_degeneracy, &
     247             :                                     tensor_1=t_3c_x_Gocc_2, tensor_2=t_3c_x_Gvir_2, &
     248             :                                     beta=1.0_dp, tensor_3=bs_env%t_chi, &
     249             :                                     contract_1=[2, 3], notcontract_1=[1], map_1=[1], &
     250             :                                     contract_2=[2, 3], notcontract_2=[1], map_2=[2], &
     251         448 :                                     filter_eps=bs_env%eps_filter, move_data=.TRUE.)
     252             : 
     253             :                END DO ! j_atoms
     254             :             END DO ! i_atoms
     255             :          END DO ! ispin
     256             : 
     257             :          ! 8. communicate data of χ_PQ(iτ,k=0) in tensor bs_env%t_chi (which local in the
     258             :          !    subgroup) to the global dbcsr matrix mat_chi_Gamma_tau (which stores
     259             :          !    χ_PQ(iτ,k=0) for all time points)
     260             :          CALL local_dbt_to_global_mat(bs_env%t_chi, bs_env%mat_RI_RI_tensor%matrix, &
     261         204 :                                       mat_chi_Gamma_tau(i_t)%matrix, bs_env%para_env)
     262             : 
     263             :          CALL write_matrix(mat_chi_Gamma_tau(i_t)%matrix, i_t, bs_env%chi_name, &
     264         204 :                            bs_env%fm_RI_RI, qs_env)
     265             : 
     266             :          CALL destroy_tensors_chi(t_2c_Gocc, t_2c_Gvir, t_3c_for_Gocc, t_3c_for_Gvir, &
     267         204 :                                   t_3c_x_Gocc, t_3c_x_Gvir, t_3c_x_Gocc_2, t_3c_x_Gvir_2)
     268             : 
     269         232 :          IF (bs_env%unit_nr > 0) THEN
     270             :             WRITE (bs_env%unit_nr, '(T2,A,I13,A,I3,A,F7.1,A)') &
     271         102 :                'Computed χ(iτ,k=0) for time point', i_t, ' /', bs_env%num_time_freq_points, &
     272         204 :                ',    Execution time', m_walltime() - t1, ' s'
     273             :          END IF
     274             : 
     275             :       END DO ! i_t
     276             : 
     277          28 :       IF (bs_env%unit_nr > 0) WRITE (bs_env%unit_nr, '(A)') ' '
     278             : 
     279          28 :       CALL timestop(handle)
     280             : 
     281          28 :    END SUBROUTINE get_mat_chi_Gamma_tau
     282             : 
     283             : ! **************************************************************************************************
     284             : !> \brief ...
     285             : !> \param fm ...
     286             : !> \param bs_env ...
     287             : !> \param mat_name ...
     288             : !> \param idx ...
     289             : ! **************************************************************************************************
     290         684 :    SUBROUTINE fm_read(fm, bs_env, mat_name, idx)
     291             :       TYPE(cp_fm_type)                                   :: fm
     292             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     293             :       CHARACTER(LEN=*)                                   :: mat_name
     294             :       INTEGER                                            :: idx
     295             : 
     296             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'fm_read'
     297             : 
     298             :       CHARACTER(LEN=default_string_length)               :: f_chi
     299             :       INTEGER                                            :: handle, unit_nr
     300             : 
     301         684 :       CALL timeset(routineN, handle)
     302             : 
     303         684 :       unit_nr = -1
     304         684 :       IF (bs_env%para_env%is_source()) THEN
     305             : 
     306         342 :          IF (idx < 10) THEN
     307         174 :             WRITE (f_chi, '(3A,I1,A)') TRIM(bs_env%prefix), TRIM(mat_name), "_0", idx, ".matrix"
     308         168 :          ELSE IF (idx < 100) THEN
     309         168 :             WRITE (f_chi, '(3A,I2,A)') TRIM(bs_env%prefix), TRIM(mat_name), "_", idx, ".matrix"
     310             :          ELSE
     311           0 :             CPABORT('Please implement more than 99 time/frequency points.')
     312             :          END IF
     313             : 
     314             :          CALL open_file(file_name=TRIM(f_chi), file_action="READ", file_form="UNFORMATTED", &
     315         342 :                         file_position="REWIND", file_status="OLD", unit_number=unit_nr)
     316             : 
     317             :       END IF
     318             : 
     319         684 :       CALL cp_fm_read_unformatted(fm, unit_nr)
     320             : 
     321         684 :       IF (bs_env%para_env%is_source()) CALL close_file(unit_number=unit_nr)
     322             : 
     323         684 :       CALL timestop(handle)
     324             : 
     325         684 :    END SUBROUTINE fm_read
     326             : 
     327             : ! **************************************************************************************************
     328             : !> \brief ...
     329             : !> \param t_2c_Gocc ...
     330             : !> \param t_2c_Gvir ...
     331             : !> \param t_3c_for_Gocc ...
     332             : !> \param t_3c_for_Gvir ...
     333             : !> \param t_3c_x_Gocc ...
     334             : !> \param t_3c_x_Gvir ...
     335             : !> \param t_3c_x_Gocc_2 ...
     336             : !> \param t_3c_x_Gvir_2 ...
     337             : !> \param bs_env ...
     338             : ! **************************************************************************************************
     339         204 :    SUBROUTINE create_tensors_chi(t_2c_Gocc, t_2c_Gvir, t_3c_for_Gocc, t_3c_for_Gvir, &
     340             :                                  t_3c_x_Gocc, t_3c_x_Gvir, t_3c_x_Gocc_2, t_3c_x_Gvir_2, bs_env)
     341             : 
     342             :       TYPE(dbt_type)                                     :: t_2c_Gocc, t_2c_Gvir, t_3c_for_Gocc, &
     343             :                                                             t_3c_for_Gvir, t_3c_x_Gocc, &
     344             :                                                             t_3c_x_Gvir, t_3c_x_Gocc_2, &
     345             :                                                             t_3c_x_Gvir_2
     346             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     347             : 
     348             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'create_tensors_chi'
     349             : 
     350             :       INTEGER                                            :: handle
     351             : 
     352         204 :       CALL timeset(routineN, handle)
     353             : 
     354         204 :       CALL dbt_create(bs_env%t_G, t_2c_Gocc)
     355         204 :       CALL dbt_create(bs_env%t_G, t_2c_Gvir)
     356         204 :       CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_for_Gocc)
     357         204 :       CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_for_Gvir)
     358         204 :       CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_x_Gocc)
     359         204 :       CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_x_Gvir)
     360         204 :       CALL dbt_create(bs_env%t_RI__AO_AO, t_3c_x_Gocc_2)
     361         204 :       CALL dbt_create(bs_env%t_RI__AO_AO, t_3c_x_Gvir_2)
     362             : 
     363         204 :       CALL timestop(handle)
     364             : 
     365         204 :    END SUBROUTINE create_tensors_chi
     366             : 
     367             : ! **************************************************************************************************
     368             : !> \brief ...
     369             : !> \param t_2c_Gocc ...
     370             : !> \param t_2c_Gvir ...
     371             : !> \param t_3c_for_Gocc ...
     372             : !> \param t_3c_for_Gvir ...
     373             : !> \param t_3c_x_Gocc ...
     374             : !> \param t_3c_x_Gvir ...
     375             : !> \param t_3c_x_Gocc_2 ...
     376             : !> \param t_3c_x_Gvir_2 ...
     377             : ! **************************************************************************************************
     378         204 :    SUBROUTINE destroy_tensors_chi(t_2c_Gocc, t_2c_Gvir, t_3c_for_Gocc, t_3c_for_Gvir, &
     379             :                                   t_3c_x_Gocc, t_3c_x_Gvir, t_3c_x_Gocc_2, t_3c_x_Gvir_2)
     380             :       TYPE(dbt_type)                                     :: t_2c_Gocc, t_2c_Gvir, t_3c_for_Gocc, &
     381             :                                                             t_3c_for_Gvir, t_3c_x_Gocc, &
     382             :                                                             t_3c_x_Gvir, t_3c_x_Gocc_2, &
     383             :                                                             t_3c_x_Gvir_2
     384             : 
     385             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'destroy_tensors_chi'
     386             : 
     387             :       INTEGER                                            :: handle
     388             : 
     389         204 :       CALL timeset(routineN, handle)
     390             : 
     391         204 :       CALL dbt_destroy(t_2c_Gocc)
     392         204 :       CALL dbt_destroy(t_2c_Gvir)
     393         204 :       CALL dbt_destroy(t_3c_for_Gocc)
     394         204 :       CALL dbt_destroy(t_3c_for_Gvir)
     395         204 :       CALL dbt_destroy(t_3c_x_Gocc)
     396         204 :       CALL dbt_destroy(t_3c_x_Gvir)
     397         204 :       CALL dbt_destroy(t_3c_x_Gocc_2)
     398         204 :       CALL dbt_destroy(t_3c_x_Gvir_2)
     399             : 
     400         204 :       CALL timestop(handle)
     401             : 
     402         204 :    END SUBROUTINE destroy_tensors_chi
     403             : 
     404             : ! **************************************************************************************************
     405             : !> \brief ...
     406             : !> \param matrix ...
     407             : !> \param matrix_index ...
     408             : !> \param matrix_name ...
     409             : !> \param fm ...
     410             : !> \param qs_env ...
     411             : ! **************************************************************************************************
     412         670 :    SUBROUTINE write_matrix(matrix, matrix_index, matrix_name, fm, qs_env)
     413             :       TYPE(dbcsr_type)                                   :: matrix
     414             :       INTEGER                                            :: matrix_index
     415             :       CHARACTER(LEN=*)                                   :: matrix_name
     416             :       TYPE(cp_fm_type), INTENT(IN), POINTER              :: fm
     417             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     418             : 
     419             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'write_matrix'
     420             : 
     421             :       INTEGER                                            :: handle
     422             : 
     423         670 :       CALL timeset(routineN, handle)
     424             : 
     425         670 :       CALL cp_fm_set_all(fm, 0.0_dp)
     426             : 
     427         670 :       CALL copy_dbcsr_to_fm(matrix, fm)
     428             : 
     429         670 :       CALL fm_write(fm, matrix_index, matrix_name, qs_env)
     430             : 
     431         670 :       CALL timestop(handle)
     432             : 
     433         670 :    END SUBROUTINE write_matrix
     434             : 
     435             : ! **************************************************************************************************
     436             : !> \brief ...
     437             : !> \param fm ...
     438             : !> \param matrix_index ...
     439             : !> \param matrix_name ...
     440             : !> \param qs_env ...
     441             : ! **************************************************************************************************
     442         880 :    SUBROUTINE fm_write(fm, matrix_index, matrix_name, qs_env)
     443             :       TYPE(cp_fm_type)                                   :: fm
     444             :       INTEGER                                            :: matrix_index
     445             :       CHARACTER(LEN=*)                                   :: matrix_name
     446             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     447             : 
     448             :       CHARACTER(LEN=*), PARAMETER :: key = 'PROPERTIES%BANDSTRUCTURE%GW%PRINT%RESTART', &
     449             :          routineN = 'fm_write'
     450             : 
     451             :       CHARACTER(LEN=default_string_length)               :: filename
     452             :       INTEGER                                            :: handle, unit_nr
     453             :       TYPE(cp_logger_type), POINTER                      :: logger
     454             :       TYPE(section_vals_type), POINTER                   :: input
     455             : 
     456         880 :       CALL timeset(routineN, handle)
     457             : 
     458         880 :       CALL get_qs_env(qs_env, input=input)
     459             : 
     460         880 :       logger => cp_get_default_logger()
     461             : 
     462         880 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, key), cp_p_file)) THEN
     463             : 
     464         616 :          IF (matrix_index < 10) THEN
     465         304 :             WRITE (filename, '(3A,I1)') "RESTART_", matrix_name, "_0", matrix_index
     466         312 :          ELSE IF (matrix_index < 100) THEN
     467         312 :             WRITE (filename, '(3A,I2)') "RESTART_", matrix_name, "_", matrix_index
     468             :          ELSE
     469           0 :             CPABORT('Please implement more than 99 time/frequency points.')
     470             :          END IF
     471             : 
     472             :          unit_nr = cp_print_key_unit_nr(logger, input, key, extension=".matrix", &
     473             :                                         file_form="UNFORMATTED", middle_name=TRIM(filename), &
     474         616 :                                         file_position="REWIND", file_action="WRITE")
     475             : 
     476         616 :          CALL cp_fm_write_unformatted(fm, unit_nr)
     477         616 :          IF (unit_nr > 0) THEN
     478         308 :             CALL close_file(unit_nr)
     479             :          END IF
     480             :       END IF
     481             : 
     482         880 :       CALL timestop(handle)
     483             : 
     484         880 :    END SUBROUTINE fm_write
     485             : 
     486             : ! **************************************************************************************************
     487             : !> \brief ...
     488             : !> \param bs_env ...
     489             : !> \param tau ...
     490             : !> \param fm_G_Gamma ...
     491             : !> \param ispin ...
     492             : !> \param occ ...
     493             : !> \param vir ...
     494             : ! **************************************************************************************************
     495        1828 :    SUBROUTINE G_occ_vir(bs_env, tau, fm_G_Gamma, ispin, occ, vir)
     496             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     497             :       REAL(KIND=dp)                                      :: tau
     498             :       TYPE(cp_fm_type)                                   :: fm_G_Gamma
     499             :       INTEGER                                            :: ispin
     500             :       LOGICAL                                            :: occ, vir
     501             : 
     502             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'G_occ_vir'
     503             : 
     504             :       INTEGER                                            :: handle, homo, i_row_local, j_col, &
     505             :                                                             j_col_local, n_mo, ncol_local, &
     506             :                                                             nrow_local
     507         914 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices
     508             :       REAL(KIND=dp)                                      :: tau_E
     509             : 
     510         914 :       CALL timeset(routineN, handle)
     511             : 
     512         914 :       CPASSERT(occ .NEQV. vir)
     513             : 
     514             :       CALL cp_fm_get_info(matrix=bs_env%fm_work_mo(1), &
     515             :                           nrow_local=nrow_local, &
     516             :                           ncol_local=ncol_local, &
     517         914 :                           col_indices=col_indices)
     518             : 
     519         914 :       n_mo = bs_env%n_ao
     520         914 :       homo = bs_env%n_occ(ispin)
     521             : 
     522         914 :       CALL cp_fm_to_fm(bs_env%fm_mo_coeff_Gamma(ispin), bs_env%fm_work_mo(1))
     523             : 
     524        4026 :       DO i_row_local = 1, nrow_local
     525       44732 :          DO j_col_local = 1, ncol_local
     526             : 
     527       40706 :             j_col = col_indices(j_col_local)
     528             : 
     529       40706 :             tau_E = ABS(tau*0.5_dp*(bs_env%eigenval_scf_Gamma(j_col, ispin) - bs_env%e_fermi(ispin)))
     530             : 
     531       40706 :             IF (tau_E < bs_env%stabilize_exp) THEN
     532             :                bs_env%fm_work_mo(1)%local_data(i_row_local, j_col_local) = &
     533       39914 :                   bs_env%fm_work_mo(1)%local_data(i_row_local, j_col_local)*EXP(-tau_E)
     534             :             ELSE
     535         792 :                bs_env%fm_work_mo(1)%local_data(i_row_local, j_col_local) = 0.0_dp
     536             :             END IF
     537             : 
     538       43818 :             IF ((occ .AND. j_col > homo) .OR. (vir .AND. j_col <= homo)) THEN
     539       20725 :                bs_env%fm_work_mo(1)%local_data(i_row_local, j_col_local) = 0.0_dp
     540             :             END IF
     541             : 
     542             :          END DO
     543             :       END DO
     544             : 
     545             :       CALL parallel_gemm(transa="N", transb="T", m=n_mo, n=n_mo, k=n_mo, alpha=1.0_dp, &
     546             :                          matrix_a=bs_env%fm_work_mo(1), matrix_b=bs_env%fm_work_mo(1), &
     547         914 :                          beta=0.0_dp, matrix_c=fm_G_Gamma)
     548             : 
     549         914 :       CALL timestop(handle)
     550             : 
     551         914 :    END SUBROUTINE G_occ_vir
     552             : 
     553             : ! **************************************************************************************************
     554             : !> \brief ...
     555             : !> \param qs_env ...
     556             : !> \param bs_env ...
     557             : !> \param t_3c ...
     558             : !> \param atoms_AO_1 ...
     559             : !> \param atoms_AO_2 ...
     560             : !> \param atoms_RI ...
     561             : ! **************************************************************************************************
     562        1114 :    SUBROUTINE compute_3c_integrals(qs_env, bs_env, t_3c, atoms_AO_1, atoms_AO_2, atoms_RI)
     563             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     564             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     565             :       TYPE(dbt_type)                                     :: t_3c
     566             :       INTEGER, DIMENSION(2), OPTIONAL                    :: atoms_AO_1, atoms_AO_2, atoms_RI
     567             : 
     568             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_3c_integrals'
     569             : 
     570             :       INTEGER                                            :: handle
     571             :       INTEGER, DIMENSION(2)                              :: my_atoms_AO_1, my_atoms_AO_2, my_atoms_RI
     572        1114 :       TYPE(dbt_type), ALLOCATABLE, DIMENSION(:, :)       :: t_3c_array
     573             : 
     574        1114 :       CALL timeset(routineN, handle)
     575             : 
     576             :       ! free memory (not clear whether memory has been freed previously)
     577        1114 :       CALL dbt_clear(t_3c)
     578             : 
     579       12254 :       ALLOCATE (t_3c_array(1, 1))
     580        1114 :       CALL dbt_create(t_3c, t_3c_array(1, 1))
     581             : 
     582        1114 :       IF (PRESENT(atoms_AO_1)) THEN
     583             :          my_atoms_AO_1 = atoms_AO_1
     584             :       ELSE
     585        1326 :          my_atoms_AO_1 = [1, bs_env%n_atom]
     586             :       END IF
     587        1114 :       IF (PRESENT(atoms_AO_2)) THEN
     588             :          my_atoms_AO_2 = atoms_AO_2
     589             :       ELSE
     590         708 :          my_atoms_AO_2 = [1, bs_env%n_atom]
     591             :       END IF
     592        1114 :       IF (PRESENT(atoms_RI)) THEN
     593             :          my_atoms_RI = atoms_RI
     594             :       ELSE
     595        1380 :          my_atoms_RI = [1, bs_env%n_atom]
     596             :       END IF
     597             : 
     598             :       CALL build_3c_integrals(t_3c_array, &
     599             :                               bs_env%eps_filter, &
     600             :                               qs_env, &
     601             :                               bs_env%nl_3c, &
     602             :                               int_eps=bs_env%eps_filter, &
     603             :                               basis_i=bs_env%basis_set_RI, &
     604             :                               basis_j=bs_env%basis_set_AO, &
     605             :                               basis_k=bs_env%basis_set_AO, &
     606             :                               potential_parameter=bs_env%ri_metric, &
     607             :                               bounds_i=atoms_RI, &
     608             :                               bounds_j=atoms_AO_1, &
     609             :                               bounds_k=atoms_AO_2, &
     610        1114 :                               desymmetrize=.FALSE.)
     611             : 
     612        1114 :       CALL dbt_copy(t_3c_array(1, 1), t_3c, move_data=.TRUE.)
     613             : 
     614        1114 :       CALL dbt_destroy(t_3c_array(1, 1))
     615        2228 :       DEALLOCATE (t_3c_array)
     616             : 
     617        1114 :       CALL timestop(handle)
     618             : 
     619        2228 :    END SUBROUTINE compute_3c_integrals
     620             : 
     621             : ! **************************************************************************************************
     622             : !> \brief ...
     623             : !> \param t_3c_for_G ...
     624             : !> \param t_G ...
     625             : !> \param t_M ...
     626             : !> \param bs_env ...
     627             : !> \param atoms_AO_1 ...
     628             : !> \param atoms_AO_2 ...
     629             : !> \param atoms_IL ...
     630             : ! **************************************************************************************************
     631         448 :    SUBROUTINE G_times_3c(t_3c_for_G, t_G, t_M, bs_env, atoms_AO_1, atoms_AO_2, atoms_IL)
     632             :       TYPE(dbt_type)                                     :: t_3c_for_G, t_G, t_M
     633             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     634             :       INTEGER, DIMENSION(2)                              :: atoms_AO_1, atoms_AO_2, atoms_IL
     635             : 
     636             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'G_times_3c'
     637             : 
     638             :       INTEGER                                            :: handle
     639             :       INTEGER, DIMENSION(2)                              :: bounds_IL, bounds_l
     640             :       INTEGER, DIMENSION(2, 2)                           :: bounds_k
     641             : 
     642         448 :       CALL timeset(routineN, handle)
     643             : 
     644             :       ! JW bounds_IL and bounds_k do not safe any operations, but maybe communication
     645             :       !    maybe remove "bounds_1=bounds_IL, &" and "bounds_2=bounds_k, &" later and
     646             :       !    check whether performance improves
     647             : 
     648             :       bounds_IL(1:2) = [bs_env%i_ao_start_from_atom(atoms_IL(1)), &
     649        1344 :                         bs_env%i_ao_end_from_atom(atoms_IL(2))]
     650        1344 :       bounds_k(1:2, 1) = [1, bs_env%n_RI]
     651             :       bounds_k(1:2, 2) = [bs_env%i_ao_start_from_atom(atoms_AO_2(1)), &
     652        1344 :                           bs_env%i_ao_end_from_atom(atoms_AO_2(2))]
     653             :       bounds_l(1:2) = [bs_env%i_ao_start_from_atom(atoms_AO_1(1)), &
     654        1344 :                        bs_env%i_ao_end_from_atom(atoms_AO_1(2))]
     655             : 
     656             :       CALL dbt_contract(alpha=1.0_dp, &
     657             :                         tensor_1=t_3c_for_G, &
     658             :                         tensor_2=t_G, &
     659             :                         beta=1.0_dp, &
     660             :                         tensor_3=t_M, &
     661             :                         contract_1=[3], notcontract_1=[1, 2], map_1=[1, 2], &
     662             :                         contract_2=[2], notcontract_2=[1], map_2=[3], &
     663             :                         bounds_1=bounds_IL, &
     664             :                         bounds_2=bounds_k, &
     665             :                         bounds_3=bounds_l, &
     666         448 :                         filter_eps=bs_env%eps_filter)
     667             : 
     668         448 :       CALL dbt_clear(t_3c_for_G)
     669             : 
     670         448 :       CALL timestop(handle)
     671             : 
     672         448 :    END SUBROUTINE G_times_3c
     673             : 
     674             : ! **************************************************************************************************
     675             : !> \brief ...
     676             : !> \param atoms_1 ...
     677             : !> \param atoms_2 ...
     678             : !> \param qs_env ...
     679             : !> \param bs_env ...
     680             : !> \param dist_too_long ...
     681             : ! **************************************************************************************************
     682         448 :    SUBROUTINE check_dist(atoms_1, atoms_2, qs_env, bs_env, dist_too_long)
     683             :       INTEGER, DIMENSION(2)                              :: atoms_1, atoms_2
     684             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     685             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     686             :       LOGICAL                                            :: dist_too_long
     687             : 
     688             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'check_dist'
     689             : 
     690             :       INTEGER                                            :: atom_1, atom_2, handle
     691             :       REAL(dp)                                           :: abs_rab, min_dist_AO_atoms
     692             :       REAL(KIND=dp), DIMENSION(3)                        :: rab
     693             :       TYPE(cell_type), POINTER                           :: cell
     694         448 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     695             : 
     696         448 :       CALL timeset(routineN, handle)
     697             : 
     698         448 :       CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
     699             : 
     700         448 :       min_dist_AO_atoms = 1.0E5_dp
     701        1392 :       DO atom_1 = atoms_1(1), atoms_1(2)
     702        3424 :          DO atom_2 = atoms_2(1), atoms_2(2)
     703             : 
     704        2032 :             rab = pbc(particle_set(atom_1)%r(1:3), particle_set(atom_2)%r(1:3), cell)
     705             : 
     706        2032 :             abs_rab = SQRT(rab(1)**2 + rab(2)**2 + rab(3)**2)
     707             : 
     708        2976 :             min_dist_AO_atoms = MIN(min_dist_AO_atoms, abs_rab)
     709             : 
     710             :          END DO
     711             :       END DO
     712             : 
     713         448 :       dist_too_long = (min_dist_AO_atoms > bs_env%max_dist_AO_atoms)
     714             : 
     715         448 :       CALL timestop(handle)
     716             : 
     717         448 :    END SUBROUTINE check_dist
     718             : 
     719             : ! **************************************************************************************************
     720             : !> \brief ...
     721             : !> \param bs_env ...
     722             : !> \param qs_env ...
     723             : !> \param mat_chi_Gamma_tau ...
     724             : !> \param fm_W_MIC_time ...
     725             : ! **************************************************************************************************
     726          28 :    SUBROUTINE get_W_MIC(bs_env, qs_env, mat_chi_Gamma_tau, fm_W_MIC_time)
     727             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     728             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     729             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mat_chi_Gamma_tau
     730             :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_W_MIC_time
     731             : 
     732             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'get_W_MIC'
     733             : 
     734             :       INTEGER                                            :: handle
     735             : 
     736          28 :       CALL timeset(routineN, handle)
     737             : 
     738          28 :       IF (bs_env%all_W_exist) THEN
     739          12 :          CALL read_W_MIC_time(bs_env, mat_chi_Gamma_tau, fm_W_MIC_time)
     740             :       ELSE
     741          16 :          CALL compute_W_MIC(bs_env, qs_env, mat_chi_Gamma_tau, fm_W_MIC_time)
     742             :       END IF
     743             : 
     744          28 :       CALL timestop(handle)
     745             : 
     746          28 :    END SUBROUTINE get_W_MIC
     747             : 
     748             : ! **************************************************************************************************
     749             : !> \brief ...
     750             : !> \param bs_env ...
     751             : !> \param qs_env ...
     752             : !> \param fm_V_kp ...
     753             : !> \param ikp_batch ...
     754             : ! **************************************************************************************************
     755          76 :    SUBROUTINE compute_V_k_by_lattice_sum(bs_env, qs_env, fm_V_kp, ikp_batch)
     756             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     757             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     758             :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: fm_V_kp
     759             :       INTEGER                                            :: ikp_batch
     760             : 
     761             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_V_k_by_lattice_sum'
     762             : 
     763             :       INTEGER                                            :: handle, ikp, ikp_end, ikp_start, &
     764             :                                                             nkp_chi_eps_W_batch, re_im
     765          76 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     766             :       TYPE(cell_type), POINTER                           :: cell
     767          76 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_V_kp
     768          76 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     769          76 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     770             : 
     771          76 :       CALL timeset(routineN, handle)
     772             : 
     773          76 :       nkp_chi_eps_W_batch = bs_env%nkp_chi_eps_W_batch
     774             : 
     775          76 :       ikp_start = (ikp_batch - 1)*bs_env%nkp_chi_eps_W_batch + 1
     776          76 :       ikp_end = MIN(ikp_batch*bs_env%nkp_chi_eps_W_batch, bs_env%kpoints_chi_eps_W%nkp)
     777             : 
     778          76 :       NULLIFY (mat_V_kp)
     779         988 :       ALLOCATE (mat_V_kp(ikp_start:ikp_end, 2))
     780             : 
     781         342 :       DO ikp = ikp_start, ikp_end
     782         874 :          DO re_im = 1, 2
     783         532 :             NULLIFY (mat_V_kp(ikp, re_im)%matrix)
     784         532 :             ALLOCATE (mat_V_kp(ikp, re_im)%matrix)
     785         532 :             CALL dbcsr_create(mat_V_kp(ikp, re_im)%matrix, template=bs_env%mat_RI_RI%matrix)
     786         532 :             CALL dbcsr_reserve_all_blocks(mat_V_kp(ikp, re_im)%matrix)
     787         798 :             CALL dbcsr_set(mat_V_kp(ikp, re_im)%matrix, 0.0_dp)
     788             : 
     789             :          END DO ! re_im
     790             :       END DO ! ikp
     791             : 
     792             :       CALL get_qs_env(qs_env=qs_env, &
     793             :                       particle_set=particle_set, &
     794             :                       cell=cell, &
     795             :                       qs_kind_set=qs_kind_set, &
     796          76 :                       atomic_kind_set=atomic_kind_set)
     797             : 
     798          76 :       IF (ikp_end .LE. bs_env%nkp_chi_eps_W_orig) THEN
     799             : 
     800             :          ! 1. 2c Coulomb integrals for the first "original" k-point grid
     801         104 :          bs_env%kpoints_chi_eps_W%nkp_grid = bs_env%nkp_grid_chi_eps_W_orig
     802             : 
     803          50 :       ELSE IF (ikp_start > bs_env%nkp_chi_eps_W_orig .AND. &
     804             :                ikp_end .LE. bs_env%nkp_chi_eps_W_orig_plus_extra) THEN
     805             : 
     806             :          ! 2. 2c Coulomb integrals for the second "extrapolation" k-point grid
     807         200 :          bs_env%kpoints_chi_eps_W%nkp_grid = bs_env%nkp_grid_chi_eps_W_extra
     808             : 
     809             :       ELSE
     810             : 
     811           0 :          CPABORT("Error with k-point parallelization.")
     812             : 
     813             :       END IF
     814             : 
     815             :       CALL build_2c_coulomb_matrix_kp(mat_V_kp, &
     816             :                                       bs_env%kpoints_chi_eps_W, &
     817             :                                       basis_type="RI_AUX", &
     818             :                                       cell=cell, &
     819             :                                       particle_set=particle_set, &
     820             :                                       qs_kind_set=qs_kind_set, &
     821             :                                       atomic_kind_set=atomic_kind_set, &
     822             :                                       size_lattice_sum=bs_env%size_lattice_sum_V, &
     823             :                                       operator_type=operator_coulomb, &
     824             :                                       ikp_start=ikp_start, &
     825          76 :                                       ikp_end=ikp_end)
     826             : 
     827         304 :       bs_env%kpoints_chi_eps_W%nkp_grid = bs_env%nkp_grid_chi_eps_W_orig
     828             : 
     829         988 :       ALLOCATE (fm_V_kp(ikp_start:ikp_end, 2))
     830         342 :       DO ikp = ikp_start, ikp_end
     831         874 :          DO re_im = 1, 2
     832         532 :             CALL cp_fm_create(fm_V_kp(ikp, re_im), bs_env%fm_RI_RI%matrix_struct)
     833         532 :             CALL copy_dbcsr_to_fm(mat_V_kp(ikp, re_im)%matrix, fm_V_kp(ikp, re_im))
     834         798 :             CALL dbcsr_deallocate_matrix(mat_V_kp(ikp, re_im)%matrix)
     835             :          END DO
     836             :       END DO
     837          76 :       DEALLOCATE (mat_V_kp)
     838             : 
     839          76 :       CALL timestop(handle)
     840             : 
     841          76 :    END SUBROUTINE compute_V_k_by_lattice_sum
     842             : 
     843             : ! **************************************************************************************************
     844             : !> \brief ...
     845             : !> \param bs_env ...
     846             : !> \param qs_env ...
     847             : !> \param fm_V_kp ...
     848             : !> \param cfm_V_sqrt_ikp ...
     849             : !> \param cfm_M_inv_V_sqrt_ikp ...
     850             : !> \param ikp ...
     851             : ! **************************************************************************************************
     852         266 :    SUBROUTINE compute_MinvVsqrt_Vsqrt(bs_env, qs_env, fm_V_kp, cfm_V_sqrt_ikp, &
     853             :                                       cfm_M_inv_V_sqrt_ikp, ikp)
     854             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     855             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     856             :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: fm_V_kp
     857             :       TYPE(cp_cfm_type)                                  :: cfm_V_sqrt_ikp, cfm_M_inv_V_sqrt_ikp
     858             :       INTEGER                                            :: ikp
     859             : 
     860             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_MinvVsqrt_Vsqrt'
     861             : 
     862             :       INTEGER                                            :: handle, info, n_RI
     863             :       TYPE(cp_cfm_type)                                  :: cfm_M_inv_ikp, cfm_work
     864         266 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: fm_M_ikp
     865             : 
     866         266 :       CALL timeset(routineN, handle)
     867             : 
     868         266 :       n_RI = bs_env%n_RI
     869             : 
     870             :       ! get here M(k) and write it to fm_M_ikp
     871             :       CALL RI_2c_integral_mat(qs_env, fm_M_ikp, fm_V_kp(ikp, 1), &
     872             :                               n_RI, bs_env%ri_metric, do_kpoints=.TRUE., &
     873             :                               kpoints=bs_env%kpoints_chi_eps_W, &
     874             :                               regularization_RI=bs_env%regularization_RI, ikp_ext=ikp, &
     875         266 :                               do_build_cell_index=(ikp == 1))
     876             : 
     877         266 :       IF (ikp == 1) THEN
     878          16 :          CALL cp_cfm_create(cfm_V_sqrt_ikp, fm_V_kp(ikp, 1)%matrix_struct)
     879          16 :          CALL cp_cfm_create(cfm_M_inv_V_sqrt_ikp, fm_V_kp(ikp, 1)%matrix_struct)
     880             :       END IF
     881         266 :       CALL cp_cfm_create(cfm_M_inv_ikp, fm_V_kp(ikp, 1)%matrix_struct)
     882             : 
     883         266 :       CALL cp_fm_to_cfm(fm_M_ikp(1, 1), fm_M_ikp(1, 2), cfm_M_inv_ikp)
     884         266 :       CALL cp_fm_to_cfm(fm_V_kp(ikp, 1), fm_V_kp(ikp, 2), cfm_V_sqrt_ikp)
     885             : 
     886         266 :       CALL cp_fm_release(fm_M_ikp)
     887             : 
     888         266 :       CALL cp_cfm_create(cfm_work, fm_V_kp(ikp, 1)%matrix_struct)
     889             : 
     890             :       ! M(k) -> M^-1(k)
     891         266 :       CALL cp_cfm_to_cfm(cfm_M_inv_ikp, cfm_work)
     892         266 :       CALL cp_cfm_cholesky_decompose(matrix=cfm_M_inv_ikp, n=n_RI, info_out=info)
     893         266 :       IF (info == 0) THEN
     894             :          ! successful Cholesky decomposition
     895         266 :          CALL cp_cfm_cholesky_invert(cfm_M_inv_ikp)
     896             :          ! symmetrize the result
     897         266 :          CALL cp_cfm_upper_to_full(cfm_M_inv_ikp)
     898             :       ELSE
     899             :          ! Cholesky decomposition not successful: use expensive diagonalization
     900           0 :          CALL cp_cfm_power(cfm_work, threshold=bs_env%eps_eigval_mat_RI, exponent=-1.0_dp)
     901           0 :          CALL cp_cfm_to_cfm(cfm_work, cfm_M_inv_ikp)
     902             :       END IF
     903             : 
     904             :       ! V(k) -> L(k) with L^H(k)*L(k) = V(k) [L(k) can be just considered to be V^0.5(k)]
     905         266 :       CALL cp_cfm_to_cfm(cfm_V_sqrt_ikp, cfm_work)
     906         266 :       CALL cp_cfm_cholesky_decompose(matrix=cfm_V_sqrt_ikp, n=n_RI, info_out=info)
     907         266 :       IF (info == 0) THEN
     908             :          ! successful Cholesky decomposition
     909         266 :          CALL clean_lower_part(cfm_V_sqrt_ikp)
     910             :       ELSE
     911             :          ! Cholesky decomposition not successful: use expensive diagonalization
     912           0 :          CALL cp_cfm_power(cfm_work, threshold=0.0_dp, exponent=0.5_dp)
     913           0 :          CALL cp_cfm_to_cfm(cfm_work, cfm_V_sqrt_ikp)
     914             :       END IF
     915         266 :       CALL cp_cfm_release(cfm_work)
     916             : 
     917             :       ! get M^-1(k)*V^0.5(k)
     918             :       CALL parallel_gemm("N", "C", n_RI, n_RI, n_RI, z_one, cfm_M_inv_ikp, cfm_V_sqrt_ikp, &
     919         266 :                          z_zero, cfm_M_inv_V_sqrt_ikp)
     920             : 
     921         266 :       CALL cp_cfm_release(cfm_M_inv_ikp)
     922             : 
     923         266 :       CALL timestop(handle)
     924             : 
     925         532 :    END SUBROUTINE compute_MinvVsqrt_Vsqrt
     926             : 
     927             : ! **************************************************************************************************
     928             : !> \brief ...
     929             : !> \param bs_env ...
     930             : !> \param mat_chi_Gamma_tau ...
     931             : !> \param fm_W_MIC_time ...
     932             : ! **************************************************************************************************
     933          12 :    SUBROUTINE read_W_MIC_time(bs_env, mat_chi_Gamma_tau, fm_W_MIC_time)
     934             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     935             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mat_chi_Gamma_tau
     936             :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_W_MIC_time
     937             : 
     938             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'read_W_MIC_time'
     939             : 
     940             :       INTEGER                                            :: handle, i_t
     941             :       REAL(KIND=dp)                                      :: t1
     942             : 
     943          12 :       CALL timeset(routineN, handle)
     944             : 
     945          12 :       CALL dbcsr_deallocate_matrix_set(mat_chi_Gamma_tau)
     946          12 :       CALL create_fm_W_MIC_time(bs_env, fm_W_MIC_time)
     947             : 
     948         192 :       DO i_t = 1, bs_env%num_time_freq_points
     949             : 
     950         180 :          t1 = m_walltime()
     951             : 
     952         180 :          CALL fm_read(fm_W_MIC_time(i_t), bs_env, bs_env%W_time_name, i_t)
     953             : 
     954         192 :          IF (bs_env%unit_nr > 0) THEN
     955             :             WRITE (bs_env%unit_nr, '(T2,A,I5,A,I3,A,F7.1,A)') &
     956          90 :                'Read W^MIC(iτ) from file for time point  ', i_t, ' /', bs_env%num_time_freq_points, &
     957         180 :                ',    Execution time', m_walltime() - t1, ' s'
     958             :          END IF
     959             : 
     960             :       END DO
     961             : 
     962          12 :       IF (bs_env%unit_nr > 0) WRITE (bs_env%unit_nr, '(A)') ' '
     963             : 
     964             :       ! Marek : Reading of the W(w=0) potential for RTP
     965             :       ! TODO : is the condition bs_env%all_W_exist sufficient for reading?
     966          12 :       IF (bs_env%rtp_method == rtp_method_bse) THEN
     967           6 :          CALL cp_fm_create(bs_env%fm_W_MIC_freq_zero, bs_env%fm_W_MIC_freq%matrix_struct)
     968           6 :          t1 = m_walltime()
     969           6 :          CALL fm_read(bs_env%fm_W_MIC_freq_zero, bs_env, "W_freq_rtp", 0)
     970           6 :          IF (bs_env%unit_nr > 0) THEN
     971             :             WRITE (bs_env%unit_nr, '(T2,A,I5,A,I3,A,F7.1,A)') &
     972           3 :                'Read W^MIC(w=0) from file for frequency point  ', 1, ' /', 1, &
     973           6 :                ',    Execution time', m_walltime() - t1, ' s'
     974             :          END IF
     975             :       END IF
     976             : 
     977          12 :       CALL timestop(handle)
     978             : 
     979          12 :    END SUBROUTINE read_W_MIC_time
     980             : 
     981             : ! **************************************************************************************************
     982             : !> \brief ...
     983             : !> \param bs_env ...
     984             : !> \param qs_env ...
     985             : !> \param mat_chi_Gamma_tau ...
     986             : !> \param fm_W_MIC_time ...
     987             : ! **************************************************************************************************
     988          16 :    SUBROUTINE compute_W_MIC(bs_env, qs_env, mat_chi_Gamma_tau, fm_W_MIC_time)
     989             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     990             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     991             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mat_chi_Gamma_tau
     992             :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_W_MIC_time
     993             : 
     994             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'compute_W_MIC'
     995             : 
     996             :       INTEGER                                            :: handle, i_t, ikp, ikp_batch, &
     997             :                                                             ikp_in_batch, j_w
     998             :       REAL(KIND=dp)                                      :: t1
     999             :       TYPE(cp_cfm_type)                                  :: cfm_M_inv_V_sqrt_ikp, cfm_V_sqrt_ikp
    1000          16 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: fm_V_kp
    1001             : 
    1002          16 :       CALL timeset(routineN, handle)
    1003             : 
    1004          16 :       CALL create_fm_W_MIC_time(bs_env, fm_W_MIC_time)
    1005             : 
    1006          92 :       DO ikp_batch = 1, bs_env%num_chi_eps_W_batches
    1007             : 
    1008          76 :          t1 = m_walltime()
    1009             : 
    1010             :          ! Compute V_PQ(k) = sum_R e^(ikR) <phi_P, cell 0 | 1/r | phi_Q, cell R>
    1011          76 :          CALL compute_V_k_by_lattice_sum(bs_env, qs_env, fm_V_kp, ikp_batch)
    1012             : 
    1013         380 :          DO ikp_in_batch = 1, bs_env%nkp_chi_eps_W_batch
    1014             : 
    1015         304 :             ikp = (ikp_batch - 1)*bs_env%nkp_chi_eps_W_batch + ikp_in_batch
    1016             : 
    1017         304 :             IF (ikp > bs_env%nkp_chi_eps_W_orig_plus_extra) CYCLE
    1018             : 
    1019             :             CALL compute_MinvVsqrt_Vsqrt(bs_env, qs_env, fm_V_kp, &
    1020         266 :                                          cfm_V_sqrt_ikp, cfm_M_inv_V_sqrt_ikp, ikp)
    1021             : 
    1022         266 :             CALL bs_env%para_env%sync()
    1023             : 
    1024        2570 :             DO j_w = 1, bs_env%num_time_freq_points
    1025             : 
    1026             :                ! check if we need this (ikp, ω_j) combination for approximate k-point extrapolation
    1027        2304 :                IF (bs_env%approx_kp_extrapol .AND. j_w > 1 .AND. &
    1028             :                    ikp > bs_env%nkp_chi_eps_W_orig) CYCLE
    1029             : 
    1030             :                CALL compute_fm_W_MIC_freq_j(bs_env, qs_env, bs_env%fm_W_MIC_freq, j_w, ikp, &
    1031             :                                             mat_chi_Gamma_tau, cfm_M_inv_V_sqrt_ikp, &
    1032        1980 :                                             cfm_V_sqrt_ikp)
    1033             : 
    1034             :                ! Fourier trafo from W_PQ^MIC(iω_j) to W_PQ^MIC(iτ)
    1035        2570 :                CALL Fourier_transform_w_to_t(bs_env, fm_W_MIC_time, bs_env%fm_W_MIC_freq, j_w)
    1036             : 
    1037             :             END DO ! ω_j
    1038             : 
    1039         266 :             CALL cp_fm_release(fm_V_kp(ikp, 1))
    1040         380 :             CALL cp_fm_release(fm_V_kp(ikp, 2))
    1041             : 
    1042             :          END DO ! ikp_in_batch
    1043             : 
    1044          76 :          DEALLOCATE (fm_V_kp)
    1045             : 
    1046          92 :          IF (bs_env%unit_nr > 0) THEN
    1047             :             WRITE (bs_env%unit_nr, '(T2,A,I12,A,I3,A,F7.1,A)') &
    1048          38 :                'Computed W(iτ,k) for k-point batch', &
    1049          38 :                ikp_batch, ' /', bs_env%num_chi_eps_W_batches, &
    1050          76 :                ',    Execution time', m_walltime() - t1, ' s'
    1051             :          END IF
    1052             : 
    1053             :       END DO ! ikp_batch
    1054             : 
    1055          16 :       IF (bs_env%approx_kp_extrapol) THEN
    1056           2 :          CALL apply_extrapol_factor(bs_env, fm_W_MIC_time)
    1057             :       END IF
    1058             : 
    1059             :       ! M^-1(k=0)*W^MIC(iτ)*M^-1(k=0)
    1060          16 :       CALL multiply_fm_W_MIC_time_with_Minv_Gamma(bs_env, qs_env, fm_W_MIC_time)
    1061             : 
    1062         220 :       DO i_t = 1, bs_env%num_time_freq_points
    1063         220 :          CALL fm_write(fm_W_MIC_time(i_t), i_t, bs_env%W_time_name, qs_env)
    1064             :       END DO
    1065             : 
    1066          16 :       CALL cp_cfm_release(cfm_M_inv_V_sqrt_ikp)
    1067          16 :       CALL cp_cfm_release(cfm_V_sqrt_ikp)
    1068          16 :       CALL dbcsr_deallocate_matrix_set(mat_chi_Gamma_tau)
    1069             : 
    1070             :       ! Marek : Fourier transform W^MIC(itau) back to get it at a specific im.frequency point - iomega = 0
    1071             :       ! TODO : Should this be activeted here or somewhere else? Maybe directly in the main (gw) routine?
    1072             :       ! Create the matrix TODO: Add release statement in some well understood place - at destruction of bs_env?
    1073          16 :       IF (bs_env%rtp_method == rtp_method_bse) THEN
    1074           6 :          CALL cp_fm_create(bs_env%fm_W_MIC_freq_zero, bs_env%fm_W_MIC_freq%matrix_struct)
    1075             :          ! Set to zero
    1076           6 :          CALL cp_fm_set_all(bs_env%fm_W_MIC_freq_zero, 0.0_dp)
    1077             :          ! Sum over all times
    1078         126 :          DO i_t = 1, bs_env%num_time_freq_points
    1079             :             ! Add the relevant structure with correct weight
    1080             :             CALL cp_fm_scale_and_add(1.0_dp, bs_env%fm_W_MIC_freq_zero, &
    1081         126 :                                      bs_env%imag_time_weights_freq_zero(i_t), fm_W_MIC_time(i_t))
    1082             :          END DO
    1083             :          ! Done, save to file
    1084           6 :          CALL fm_write(bs_env%fm_W_MIC_freq_zero, 0, "W_freq_rtp", qs_env)
    1085             :       END IF
    1086             : 
    1087          16 :       IF (bs_env%unit_nr > 0) WRITE (bs_env%unit_nr, '(A)') ' '
    1088             : 
    1089          16 :       CALL timestop(handle)
    1090             : 
    1091          32 :    END SUBROUTINE compute_W_MIC
    1092             : 
    1093             : ! **************************************************************************************************
    1094             : !> \brief ...
    1095             : !> \param bs_env ...
    1096             : !> \param qs_env ...
    1097             : !> \param fm_W_MIC_freq_j ...
    1098             : !> \param j_w ...
    1099             : !> \param ikp ...
    1100             : !> \param mat_chi_Gamma_tau ...
    1101             : !> \param cfm_M_inv_V_sqrt_ikp ...
    1102             : !> \param cfm_V_sqrt_ikp ...
    1103             : ! **************************************************************************************************
    1104        1980 :    SUBROUTINE compute_fm_W_MIC_freq_j(bs_env, qs_env, fm_W_MIC_freq_j, j_w, ikp, mat_chi_Gamma_tau, &
    1105             :                                       cfm_M_inv_V_sqrt_ikp, cfm_V_sqrt_ikp)
    1106             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1107             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1108             :       TYPE(cp_fm_type)                                   :: fm_W_MIC_freq_j
    1109             :       INTEGER                                            :: j_w, ikp
    1110             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mat_chi_Gamma_tau
    1111             :       TYPE(cp_cfm_type)                                  :: cfm_M_inv_V_sqrt_ikp, cfm_V_sqrt_ikp
    1112             : 
    1113             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_fm_W_MIC_freq_j'
    1114             : 
    1115             :       INTEGER                                            :: handle
    1116             :       TYPE(cp_cfm_type)                                  :: cfm_chi_ikp_freq_j, cfm_W_ikp_freq_j
    1117             : 
    1118        1980 :       CALL timeset(routineN, handle)
    1119             : 
    1120             :       ! 1. Fourier transformation of χ_PQ(iτ,k=0) to χ_PQ(iω_j,k=0)
    1121        1980 :       CALL compute_fm_chi_Gamma_freq(bs_env, bs_env%fm_chi_Gamma_freq, j_w, mat_chi_Gamma_tau)
    1122             : 
    1123        1980 :       CALL cp_fm_set_all(fm_W_MIC_freq_j, 0.0_dp)
    1124             : 
    1125             :       ! 2. Get χ_PQ(iω_j,k_i) from χ_PQ(iω_j,k=0) using the minimum image convention
    1126             :       CALL cfm_ikp_from_fm_Gamma(cfm_chi_ikp_freq_j, bs_env%fm_chi_Gamma_freq, &
    1127        1980 :                                  ikp, qs_env, bs_env%kpoints_chi_eps_W, "RI_AUX")
    1128             : 
    1129             :       ! 3. Remove all negative eigenvalues from χ_PQ(iω_j,k_i)
    1130        1980 :       CALL cp_cfm_power(cfm_chi_ikp_freq_j, threshold=0.0_dp, exponent=1.0_dp)
    1131             : 
    1132             :       ! 4. ε(iω_j,k_i) = Id - V^0.5(k_i)*M^-1(k_i)*χ(iω_j,k_i)*M^-1(k_i)*V^0.5(k_i)
    1133             :       !    W(iω_j,k_i) = V^0.5(k_i)*(ε^-1(iω_j,k_i)-Id)*V^0.5(k_i)
    1134             :       CALL compute_cfm_W_ikp_freq_j(bs_env, cfm_chi_ikp_freq_j, cfm_V_sqrt_ikp, &
    1135        1980 :                                     cfm_M_inv_V_sqrt_ikp, cfm_W_ikp_freq_j)
    1136             : 
    1137             :       ! 5. k-point integration W_PQ(iω_j, k_i) to W_PQ^MIC(iω_j)
    1138        1980 :       SELECT CASE (bs_env%approx_kp_extrapol)
    1139             :       CASE (.FALSE.)
    1140             :          ! default: standard k-point extrapolation
    1141             :          CALL MIC_contribution_from_ikp(bs_env, qs_env, fm_W_MIC_freq_j, cfm_W_ikp_freq_j, ikp, &
    1142        1980 :                                         bs_env%kpoints_chi_eps_W, "RI_AUX")
    1143             :       CASE (.TRUE.)
    1144             :          ! for approximate kpoint extrapolation: get W_PQ^MIC(iω_1) with and without k-point
    1145             :          ! extrapolation to compute the extrapolation factor f_PQ for every PQ-matrix element,
    1146             :          ! f_PQ = (W_PQ^MIC(iω_1) with extrapolation) / (W_PQ^MIC(iω_1) without extrapolation)
    1147             : 
    1148             :          ! for ω_1, we compute the k-point extrapolated result using all k-points
    1149         196 :          IF (j_w == 1) THEN
    1150             : 
    1151             :             ! k-point extrapolated
    1152             :             CALL MIC_contribution_from_ikp(bs_env, qs_env, bs_env%fm_W_MIC_freq_1_extra, &
    1153             :                                            cfm_W_ikp_freq_j, ikp, bs_env%kpoints_chi_eps_W, &
    1154          52 :                                            "RI_AUX")
    1155             :             ! non-kpoint extrapolated
    1156          52 :             IF (ikp .LE. bs_env%nkp_chi_eps_W_orig) THEN
    1157             :                CALL MIC_contribution_from_ikp(bs_env, qs_env, bs_env%fm_W_MIC_freq_1_no_extra, &
    1158             :                                               cfm_W_ikp_freq_j, ikp, bs_env%kpoints_chi_eps_W, &
    1159          16 :                                               "RI_AUX", wkp_ext=bs_env%wkp_orig)
    1160             :             END IF
    1161             : 
    1162             :          END IF
    1163             : 
    1164             :          ! for all ω_j, we need to compute W^MIC without k-point extrpolation
    1165         196 :          IF (ikp .LE. bs_env%nkp_chi_eps_W_orig) THEN
    1166             :             CALL MIC_contribution_from_ikp(bs_env, qs_env, fm_W_MIC_freq_j, cfm_W_ikp_freq_j, &
    1167             :                                            ikp, bs_env%kpoints_chi_eps_W, "RI_AUX", &
    1168         160 :                                            wkp_ext=bs_env%wkp_orig)
    1169             :          END IF
    1170             :       END SELECT
    1171             : 
    1172        1980 :       CALL cp_cfm_release(cfm_W_ikp_freq_j)
    1173             : 
    1174        1980 :       CALL timestop(handle)
    1175             : 
    1176        1980 :    END SUBROUTINE compute_fm_W_MIC_freq_j
    1177             : 
    1178             : ! **************************************************************************************************
    1179             : !> \brief ...
    1180             : !> \param cfm_mat ...
    1181             : ! **************************************************************************************************
    1182         532 :    SUBROUTINE clean_lower_part(cfm_mat)
    1183             :       TYPE(cp_cfm_type)                                  :: cfm_mat
    1184             : 
    1185             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'clean_lower_part'
    1186             : 
    1187             :       INTEGER                                            :: handle, i_global, i_row, j_col, &
    1188             :                                                             j_global, ncol_local, nrow_local
    1189         266 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
    1190             : 
    1191         266 :       CALL timeset(routineN, handle)
    1192             : 
    1193             :       CALL cp_cfm_get_info(matrix=cfm_mat, &
    1194             :                            nrow_local=nrow_local, ncol_local=ncol_local, &
    1195         266 :                            row_indices=row_indices, col_indices=col_indices)
    1196             : 
    1197        1138 :       DO i_row = 1, nrow_local
    1198        7868 :          DO j_col = 1, ncol_local
    1199        6730 :             i_global = row_indices(i_row)
    1200        6730 :             j_global = col_indices(j_col)
    1201        7602 :             IF (j_global < i_global) cfm_mat%local_data(i_row, j_col) = z_zero
    1202             :          END DO
    1203             :       END DO
    1204             : 
    1205         266 :       CALL timestop(handle)
    1206             : 
    1207         266 :    END SUBROUTINE clean_lower_part
    1208             : 
    1209             : ! **************************************************************************************************
    1210             : !> \brief ...
    1211             : !> \param bs_env ...
    1212             : !> \param fm_W_MIC_time ...
    1213             : ! **************************************************************************************************
    1214           4 :    SUBROUTINE apply_extrapol_factor(bs_env, fm_W_MIC_time)
    1215             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1216             :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_W_MIC_time
    1217             : 
    1218             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'apply_extrapol_factor'
    1219             : 
    1220             :       INTEGER                                            :: handle, i, i_t, j, ncol_local, nrow_local
    1221             :       REAL(KIND=dp)                                      :: extrapol_factor, W_extra_1, W_no_extra_1
    1222             : 
    1223           2 :       CALL timeset(routineN, handle)
    1224             : 
    1225           2 :       CALL cp_fm_get_info(matrix=fm_W_MIC_time(1), nrow_local=nrow_local, ncol_local=ncol_local)
    1226             : 
    1227          22 :       DO i_t = 1, bs_env%num_time_freq_points
    1228          72 :          DO i = 1, nrow_local
    1229         320 :             DO j = 1, ncol_local
    1230             : 
    1231         250 :                W_extra_1 = bs_env%fm_W_MIC_freq_1_extra%local_data(i, j)
    1232         250 :                W_no_extra_1 = bs_env%fm_W_MIC_freq_1_no_extra%local_data(i, j)
    1233             : 
    1234         250 :                IF (ABS(W_no_extra_1) > 1.0E-13) THEN
    1235         190 :                   extrapol_factor = W_extra_1/W_no_extra_1
    1236             :                ELSE
    1237             :                   extrapol_factor = 1.0_dp
    1238             :                END IF
    1239             : 
    1240             :                ! reset extrapolation factor if it is very large
    1241         250 :                IF (ABS(extrapol_factor) > 10.0_dp) extrapol_factor = 1.0_dp
    1242             : 
    1243             :                fm_W_MIC_time(i_t)%local_data(i, j) = fm_W_MIC_time(i_t)%local_data(i, j) &
    1244         300 :                                                      *extrapol_factor
    1245             :             END DO
    1246             :          END DO
    1247             :       END DO
    1248             : 
    1249           2 :       CALL timestop(handle)
    1250             : 
    1251           2 :    END SUBROUTINE apply_extrapol_factor
    1252             : 
    1253             : ! **************************************************************************************************
    1254             : !> \brief ...
    1255             : !> \param bs_env ...
    1256             : !> \param fm_chi_Gamma_freq ...
    1257             : !> \param j_w ...
    1258             : !> \param mat_chi_Gamma_tau ...
    1259             : ! **************************************************************************************************
    1260        1980 :    SUBROUTINE compute_fm_chi_Gamma_freq(bs_env, fm_chi_Gamma_freq, j_w, mat_chi_Gamma_tau)
    1261             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1262             :       TYPE(cp_fm_type)                                   :: fm_chi_Gamma_freq
    1263             :       INTEGER                                            :: j_w
    1264             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mat_chi_Gamma_tau
    1265             : 
    1266             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_fm_chi_Gamma_freq'
    1267             : 
    1268             :       INTEGER                                            :: handle, i_t
    1269             :       REAL(KIND=dp)                                      :: freq_j, time_i, weight_ij
    1270             : 
    1271        1980 :       CALL timeset(routineN, handle)
    1272             : 
    1273        1980 :       CALL dbcsr_set(bs_env%mat_RI_RI%matrix, 0.0_dp)
    1274             : 
    1275        1980 :       freq_j = bs_env%imag_freq_points(j_w)
    1276             : 
    1277       20484 :       DO i_t = 1, bs_env%num_time_freq_points
    1278             : 
    1279       18504 :          time_i = bs_env%imag_time_points(i_t)
    1280       18504 :          weight_ij = bs_env%weights_cos_t_to_w(j_w, i_t)
    1281             : 
    1282             :          ! actual Fourier transform
    1283             :          CALL dbcsr_add(bs_env%mat_RI_RI%matrix, mat_chi_Gamma_tau(i_t)%matrix, &
    1284       20484 :                         1.0_dp, COS(time_i*freq_j)*weight_ij)
    1285             : 
    1286             :       END DO
    1287             : 
    1288        1980 :       CALL copy_dbcsr_to_fm(bs_env%mat_RI_RI%matrix, fm_chi_Gamma_freq)
    1289             : 
    1290        1980 :       CALL timestop(handle)
    1291             : 
    1292        1980 :    END SUBROUTINE compute_fm_chi_Gamma_freq
    1293             : 
    1294             : ! **************************************************************************************************
    1295             : !> \brief ...
    1296             : !> \param mat_ikp_re ...
    1297             : !> \param mat_ikp_im ...
    1298             : !> \param mat_Gamma ...
    1299             : !> \param kpoints ...
    1300             : !> \param ikp ...
    1301             : !> \param qs_env ...
    1302             : ! **************************************************************************************************
    1303           0 :    SUBROUTINE mat_ikp_from_mat_Gamma(mat_ikp_re, mat_ikp_im, mat_Gamma, kpoints, ikp, qs_env)
    1304             :       TYPE(dbcsr_type)                                   :: mat_ikp_re, mat_ikp_im, mat_Gamma
    1305             :       TYPE(kpoint_type), POINTER                         :: kpoints
    1306             :       INTEGER                                            :: ikp
    1307             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1308             : 
    1309             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'mat_ikp_from_mat_Gamma'
    1310             : 
    1311             :       INTEGER                                            :: col, handle, i_cell, j_cell, num_cells, &
    1312             :                                                             row
    1313           0 :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell
    1314             :       LOGICAL :: f, i_cell_is_the_minimum_image_cell
    1315             :       REAL(KIND=dp)                                      :: abs_rab_cell_i, abs_rab_cell_j, arg
    1316             :       REAL(KIND=dp), DIMENSION(3)                        :: cell_vector, cell_vector_j, rab_cell_i, &
    1317             :                                                             rab_cell_j
    1318             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: hmat
    1319           0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block_im, block_re, data_block
    1320             :       TYPE(cell_type), POINTER                           :: cell
    1321             :       TYPE(dbcsr_iterator_type)                          :: iter
    1322           0 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1323             : 
    1324           0 :       CALL timeset(routineN, handle)
    1325             : 
    1326             :       ! get the same blocks in mat_ikp_re and mat_ikp_im as in mat_Gamma
    1327           0 :       CALL dbcsr_copy(mat_ikp_re, mat_Gamma)
    1328           0 :       CALL dbcsr_copy(mat_ikp_im, mat_Gamma)
    1329           0 :       CALL dbcsr_set(mat_ikp_re, 0.0_dp)
    1330           0 :       CALL dbcsr_set(mat_ikp_im, 0.0_dp)
    1331             : 
    1332           0 :       NULLIFY (cell, particle_set)
    1333           0 :       CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
    1334           0 :       CALL get_cell(cell=cell, h=hmat)
    1335             : 
    1336           0 :       index_to_cell => kpoints%index_to_cell
    1337             : 
    1338           0 :       num_cells = SIZE(index_to_cell, 2)
    1339             : 
    1340           0 :       DO i_cell = 1, num_cells
    1341             : 
    1342           0 :          CALL dbcsr_iterator_start(iter, mat_Gamma)
    1343           0 :          DO WHILE (dbcsr_iterator_blocks_left(iter))
    1344           0 :             CALL dbcsr_iterator_next_block(iter, row, col, data_block)
    1345             : 
    1346           0 :             cell_vector(1:3) = MATMUL(hmat, REAL(index_to_cell(1:3, i_cell), dp))
    1347             : 
    1348             :             rab_cell_i(1:3) = pbc(particle_set(row)%r(1:3), cell) - &
    1349           0 :                               (pbc(particle_set(col)%r(1:3), cell) + cell_vector(1:3))
    1350           0 :             abs_rab_cell_i = SQRT(rab_cell_i(1)**2 + rab_cell_i(2)**2 + rab_cell_i(3)**2)
    1351             : 
    1352             :             ! minimum image convention
    1353           0 :             i_cell_is_the_minimum_image_cell = .TRUE.
    1354           0 :             DO j_cell = 1, num_cells
    1355           0 :                cell_vector_j(1:3) = MATMUL(hmat, REAL(index_to_cell(1:3, j_cell), dp))
    1356             :                rab_cell_j(1:3) = pbc(particle_set(row)%r(1:3), cell) - &
    1357           0 :                                  (pbc(particle_set(col)%r(1:3), cell) + cell_vector_j(1:3))
    1358           0 :                abs_rab_cell_j = SQRT(rab_cell_j(1)**2 + rab_cell_j(2)**2 + rab_cell_j(3)**2)
    1359             : 
    1360           0 :                IF (abs_rab_cell_i > abs_rab_cell_j + 1.0E-6_dp) THEN
    1361           0 :                   i_cell_is_the_minimum_image_cell = .FALSE.
    1362             :                END IF
    1363             :             END DO
    1364             : 
    1365           0 :             IF (i_cell_is_the_minimum_image_cell) THEN
    1366           0 :                NULLIFY (block_re, block_im)
    1367           0 :                CALL dbcsr_get_block_p(matrix=mat_ikp_re, row=row, col=col, block=block_re, found=f)
    1368           0 :                CALL dbcsr_get_block_p(matrix=mat_ikp_im, row=row, col=col, block=block_im, found=f)
    1369           0 :                CPASSERT(ALL(ABS(block_re) < 1.0E-10_dp))
    1370           0 :                CPASSERT(ALL(ABS(block_im) < 1.0E-10_dp))
    1371             : 
    1372             :                arg = REAL(index_to_cell(1, i_cell), dp)*kpoints%xkp(1, ikp) + &
    1373             :                      REAL(index_to_cell(2, i_cell), dp)*kpoints%xkp(2, ikp) + &
    1374           0 :                      REAL(index_to_cell(3, i_cell), dp)*kpoints%xkp(3, ikp)
    1375             : 
    1376           0 :                block_re(:, :) = COS(twopi*arg)*data_block(:, :)
    1377           0 :                block_im(:, :) = SIN(twopi*arg)*data_block(:, :)
    1378             :             END IF
    1379             : 
    1380             :          END DO
    1381           0 :          CALL dbcsr_iterator_stop(iter)
    1382             : 
    1383             :       END DO
    1384             : 
    1385           0 :       CALL timestop(handle)
    1386             : 
    1387           0 :    END SUBROUTINE mat_ikp_from_mat_Gamma
    1388             : 
    1389             : ! **************************************************************************************************
    1390             : !> \brief ...
    1391             : !> \param bs_env ...
    1392             : !> \param cfm_chi_ikp_freq_j ...
    1393             : !> \param cfm_V_sqrt_ikp ...
    1394             : !> \param cfm_M_inv_V_sqrt_ikp ...
    1395             : !> \param cfm_W_ikp_freq_j ...
    1396             : ! **************************************************************************************************
    1397        9900 :    SUBROUTINE compute_cfm_W_ikp_freq_j(bs_env, cfm_chi_ikp_freq_j, cfm_V_sqrt_ikp, &
    1398             :                                        cfm_M_inv_V_sqrt_ikp, cfm_W_ikp_freq_j)
    1399             : 
    1400             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1401             :       TYPE(cp_cfm_type)                                  :: cfm_chi_ikp_freq_j, cfm_V_sqrt_ikp, &
    1402             :                                                             cfm_M_inv_V_sqrt_ikp, cfm_W_ikp_freq_j
    1403             : 
    1404             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_cfm_W_ikp_freq_j'
    1405             : 
    1406             :       INTEGER                                            :: handle, info, n_RI
    1407             :       TYPE(cp_cfm_type)                                  :: cfm_eps_ikp_freq_j, cfm_work
    1408             : 
    1409        1980 :       CALL timeset(routineN, handle)
    1410             : 
    1411        1980 :       CALL cp_cfm_create(cfm_work, cfm_chi_ikp_freq_j%matrix_struct)
    1412        1980 :       n_RI = bs_env%n_RI
    1413             : 
    1414             :       ! 1. ε(iω_j,k) = Id - V^0.5(k)*M^-1(k)*χ(iω_j,k)*M^-1(k)*V^0.5(k)
    1415             : 
    1416             :       ! 1. a) work = χ(iω_j,k)*M^-1(k)*V^0.5(k)
    1417             :       CALL parallel_gemm('N', 'N', n_RI, n_RI, n_RI, z_one, &
    1418        1980 :                          cfm_chi_ikp_freq_j, cfm_M_inv_V_sqrt_ikp, z_zero, cfm_work)
    1419        1980 :       CALL cp_cfm_release(cfm_chi_ikp_freq_j)
    1420             : 
    1421             :       ! 1. b) eps_work = V^0.5(k)*M^-1(k)*work
    1422        1980 :       CALL cp_cfm_create(cfm_eps_ikp_freq_j, cfm_work%matrix_struct)
    1423             :       CALL parallel_gemm('C', 'N', n_RI, n_RI, n_RI, z_one, &
    1424        1980 :                          cfm_M_inv_V_sqrt_ikp, cfm_work, z_zero, cfm_eps_ikp_freq_j)
    1425             : 
    1426             :       ! 1. c) ε(iω_j,k) = eps_work - Id
    1427        1980 :       CALL cfm_add_on_diag(cfm_eps_ikp_freq_j, z_one)
    1428             : 
    1429             :       ! 2. W(iω_j,k) = V^0.5(k)*(ε^-1(iω_j,k)-Id)*V^0.5(k)
    1430             : 
    1431             :       ! 2. a) Cholesky decomposition of ε(iω_j,k) as preparation for inversion
    1432        1980 :       CALL cp_cfm_cholesky_decompose(matrix=cfm_eps_ikp_freq_j, n=n_RI, info_out=info)
    1433        1980 :       CPASSERT(info == 0)
    1434             : 
    1435             :       ! 2. b) Inversion of ε(iω_j,k) using its Cholesky decomposition
    1436        1980 :       CALL cp_cfm_cholesky_invert(cfm_eps_ikp_freq_j)
    1437        1980 :       CALL cp_cfm_upper_to_full(cfm_eps_ikp_freq_j)
    1438             : 
    1439             :       ! 2. c) ε^-1(iω_j,k)-Id
    1440        1980 :       CALL cfm_add_on_diag(cfm_eps_ikp_freq_j, -z_one)
    1441             : 
    1442             :       ! 2. d) work = (ε^-1(iω_j,k)-Id)*V^0.5(k)
    1443             :       CALL parallel_gemm('N', 'N', n_RI, n_RI, n_RI, z_one, cfm_eps_ikp_freq_j, cfm_V_sqrt_ikp, &
    1444        1980 :                          z_zero, cfm_work)
    1445             : 
    1446             :       ! 2. e) W(iw,k) = V^0.5(k)*work
    1447        1980 :       CALL cp_cfm_create(cfm_W_ikp_freq_j, cfm_work%matrix_struct)
    1448             :       CALL parallel_gemm('C', 'N', n_RI, n_RI, n_RI, z_one, cfm_V_sqrt_ikp, cfm_work, &
    1449        1980 :                          z_zero, cfm_W_ikp_freq_j)
    1450             : 
    1451        1980 :       CALL cp_cfm_release(cfm_work)
    1452        1980 :       CALL cp_cfm_release(cfm_eps_ikp_freq_j)
    1453             : 
    1454        1980 :       CALL timestop(handle)
    1455             : 
    1456        1980 :    END SUBROUTINE compute_cfm_W_ikp_freq_j
    1457             : 
    1458             : ! **************************************************************************************************
    1459             : !> \brief ...
    1460             : !> \param cfm ...
    1461             : !> \param alpha ...
    1462             : ! **************************************************************************************************
    1463        7920 :    SUBROUTINE cfm_add_on_diag(cfm, alpha)
    1464             : 
    1465             :       TYPE(cp_cfm_type)                                  :: cfm
    1466             :       COMPLEX(KIND=dp)                                   :: alpha
    1467             : 
    1468             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'cfm_add_on_diag'
    1469             : 
    1470             :       INTEGER                                            :: handle, i_global, i_row, j_col, &
    1471             :                                                             j_global, ncol_local, nrow_local
    1472        3960 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
    1473             : 
    1474        3960 :       CALL timeset(routineN, handle)
    1475             : 
    1476             :       CALL cp_cfm_get_info(matrix=cfm, &
    1477             :                            nrow_local=nrow_local, &
    1478             :                            ncol_local=ncol_local, &
    1479             :                            row_indices=row_indices, &
    1480        3960 :                            col_indices=col_indices)
    1481             : 
    1482             :       ! add 1 on the diagonal
    1483       31584 :       DO j_col = 1, ncol_local
    1484       27624 :          j_global = col_indices(j_col)
    1485      160500 :          DO i_row = 1, nrow_local
    1486      128916 :             i_global = row_indices(i_row)
    1487      156540 :             IF (j_global == i_global) THEN
    1488       13812 :                cfm%local_data(i_row, j_col) = cfm%local_data(i_row, j_col) + alpha
    1489             :             END IF
    1490             :          END DO
    1491             :       END DO
    1492             : 
    1493        3960 :       CALL timestop(handle)
    1494             : 
    1495        3960 :    END SUBROUTINE cfm_add_on_diag
    1496             : 
    1497             : ! **************************************************************************************************
    1498             : !> \brief ...
    1499             : !> \param bs_env ...
    1500             : !> \param fm_W_MIC_time ...
    1501             : ! **************************************************************************************************
    1502          28 :    SUBROUTINE create_fm_W_MIC_time(bs_env, fm_W_MIC_time)
    1503             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1504             :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_W_MIC_time
    1505             : 
    1506             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'create_fm_W_MIC_time'
    1507             : 
    1508             :       INTEGER                                            :: handle, i_t
    1509             : 
    1510          28 :       CALL timeset(routineN, handle)
    1511             : 
    1512         468 :       ALLOCATE (fm_W_MIC_time(bs_env%num_time_freq_points))
    1513         412 :       DO i_t = 1, bs_env%num_time_freq_points
    1514         412 :          CALL cp_fm_create(fm_W_MIC_time(i_t), bs_env%fm_RI_RI%matrix_struct)
    1515             :       END DO
    1516             : 
    1517          28 :       CALL timestop(handle)
    1518             : 
    1519          28 :    END SUBROUTINE create_fm_W_MIC_time
    1520             : 
    1521             : ! **************************************************************************************************
    1522             : !> \brief ...
    1523             : !> \param bs_env ...
    1524             : !> \param fm_W_MIC_time ...
    1525             : !> \param fm_W_MIC_freq_j ...
    1526             : !> \param j_w ...
    1527             : ! **************************************************************************************************
    1528        1980 :    SUBROUTINE Fourier_transform_w_to_t(bs_env, fm_W_MIC_time, fm_W_MIC_freq_j, j_w)
    1529             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1530             :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_W_MIC_time
    1531             :       TYPE(cp_fm_type)                                   :: fm_W_MIC_freq_j
    1532             :       INTEGER                                            :: j_w
    1533             : 
    1534             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'Fourier_transform_w_to_t'
    1535             : 
    1536             :       INTEGER                                            :: handle, i_t
    1537             :       REAL(KIND=dp)                                      :: freq_j, time_i, weight_ij
    1538             : 
    1539        1980 :       CALL timeset(routineN, handle)
    1540             : 
    1541        1980 :       freq_j = bs_env%imag_freq_points(j_w)
    1542             : 
    1543       20484 :       DO i_t = 1, bs_env%num_time_freq_points
    1544             : 
    1545       18504 :          time_i = bs_env%imag_time_points(i_t)
    1546       18504 :          weight_ij = bs_env%weights_cos_w_to_t(i_t, j_w)
    1547             : 
    1548             :          ! actual Fourier transform
    1549             :          CALL cp_fm_scale_and_add(alpha=1.0_dp, matrix_a=fm_W_MIC_time(i_t), &
    1550       20484 :                                   beta=weight_ij*COS(time_i*freq_j), matrix_b=fm_W_MIC_freq_j)
    1551             : 
    1552             :       END DO
    1553             : 
    1554        1980 :       CALL timestop(handle)
    1555             : 
    1556        1980 :    END SUBROUTINE Fourier_transform_w_to_t
    1557             : 
    1558             : ! **************************************************************************************************
    1559             : !> \brief ...
    1560             : !> \param bs_env ...
    1561             : !> \param qs_env ...
    1562             : !> \param fm_W_MIC_time ...
    1563             : ! **************************************************************************************************
    1564          32 :    SUBROUTINE multiply_fm_W_MIC_time_with_Minv_Gamma(bs_env, qs_env, fm_W_MIC_time)
    1565             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1566             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1567             :       TYPE(cp_fm_type), DIMENSION(:)                     :: fm_W_MIC_time
    1568             : 
    1569             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'multiply_fm_W_MIC_time_with_Minv_Gamma'
    1570             : 
    1571             :       INTEGER                                            :: handle, i_t, n_RI, ndep
    1572             :       TYPE(cp_fm_type)                                   :: fm_work
    1573          32 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: fm_Minv_Gamma
    1574             : 
    1575          32 :       CALL timeset(routineN, handle)
    1576             : 
    1577          32 :       n_RI = bs_env%n_RI
    1578             : 
    1579          32 :       CALL cp_fm_create(fm_work, fm_W_MIC_time(1)%matrix_struct)
    1580             : 
    1581             :       ! compute Gamma-only RI-metric matrix M(k=0); no regularization
    1582             :       CALL RI_2c_integral_mat(qs_env, fm_Minv_Gamma, fm_W_MIC_time(1), n_RI, &
    1583          32 :                               bs_env%ri_metric, do_kpoints=.FALSE.)
    1584             : 
    1585          32 :       CALL cp_fm_power(fm_Minv_Gamma(1, 1), fm_work, -1.0_dp, 0.0_dp, ndep)
    1586             : 
    1587             :       ! M^-1(k=0)*W^MIC(iτ)*M^-1(k=0)
    1588         252 :       DO i_t = 1, SIZE(fm_W_MIC_time)
    1589             : 
    1590             :          CALL parallel_gemm('N', 'N', n_RI, n_RI, n_RI, 1.0_dp, fm_Minv_Gamma(1, 1), &
    1591         220 :                             fm_W_MIC_time(i_t), 0.0_dp, fm_work)
    1592             : 
    1593             :          CALL parallel_gemm('N', 'N', n_RI, n_RI, n_RI, 1.0_dp, fm_work, &
    1594         252 :                             fm_Minv_Gamma(1, 1), 0.0_dp, fm_W_MIC_time(i_t))
    1595             : 
    1596             :       END DO
    1597             : 
    1598          32 :       CALL cp_fm_release(fm_work)
    1599          32 :       CALL cp_fm_release(fm_Minv_Gamma)
    1600             : 
    1601          32 :       CALL timestop(handle)
    1602             : 
    1603          64 :    END SUBROUTINE multiply_fm_W_MIC_time_with_Minv_Gamma
    1604             : 
    1605             : ! **************************************************************************************************
    1606             : !> \brief ...
    1607             : !> \param bs_env ...
    1608             : !> \param qs_env ...
    1609             : !> \param fm_Sigma_x_Gamma ...
    1610             : ! **************************************************************************************************
    1611          28 :    SUBROUTINE get_Sigma_x(bs_env, qs_env, fm_Sigma_x_Gamma)
    1612             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1613             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1614             :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_Sigma_x_Gamma
    1615             : 
    1616             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'get_Sigma_x'
    1617             : 
    1618             :       INTEGER                                            :: handle, ispin
    1619             : 
    1620          28 :       CALL timeset(routineN, handle)
    1621             : 
    1622         120 :       ALLOCATE (fm_Sigma_x_Gamma(bs_env%n_spin))
    1623          64 :       DO ispin = 1, bs_env%n_spin
    1624          64 :          CALL cp_fm_create(fm_Sigma_x_Gamma(ispin), bs_env%fm_s_Gamma%matrix_struct)
    1625             :       END DO
    1626             : 
    1627          28 :       IF (bs_env%Sigma_x_exists) THEN
    1628          30 :          DO ispin = 1, bs_env%n_spin
    1629          30 :             CALL fm_read(fm_Sigma_x_Gamma(ispin), bs_env, bs_env%Sigma_x_name, ispin)
    1630             :          END DO
    1631             :       ELSE
    1632          16 :          CALL compute_Sigma_x(bs_env, qs_env, fm_Sigma_x_Gamma)
    1633             :       END IF
    1634             : 
    1635          28 :       CALL timestop(handle)
    1636             : 
    1637          28 :    END SUBROUTINE get_Sigma_x
    1638             : 
    1639             : ! **************************************************************************************************
    1640             : !> \brief ...
    1641             : !> \param bs_env ...
    1642             : !> \param qs_env ...
    1643             : !> \param fm_Sigma_x_Gamma ...
    1644             : ! **************************************************************************************************
    1645          16 :    SUBROUTINE compute_Sigma_x(bs_env, qs_env, fm_Sigma_x_Gamma)
    1646             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1647             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1648             :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_Sigma_x_Gamma
    1649             : 
    1650             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'compute_Sigma_x'
    1651             : 
    1652             :       INTEGER                                            :: handle, i_intval_idx, ispin, j_intval_idx
    1653             :       INTEGER, DIMENSION(2)                              :: i_atoms, j_atoms
    1654             :       REAL(KIND=dp)                                      :: t1
    1655          16 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: fm_Vtr_Gamma
    1656             :       TYPE(dbcsr_type)                                   :: mat_Sigma_x_Gamma
    1657         528 :       TYPE(dbt_type)                                     :: t_2c_D, t_2c_Sigma_x, t_2c_V, t_3c_x_V
    1658             : 
    1659          16 :       CALL timeset(routineN, handle)
    1660             : 
    1661          16 :       t1 = m_walltime()
    1662             : 
    1663          16 :       CALL dbt_create(bs_env%t_G, t_2c_D)
    1664          16 :       CALL dbt_create(bs_env%t_W, t_2c_V)
    1665          16 :       CALL dbt_create(bs_env%t_G, t_2c_Sigma_x)
    1666          16 :       CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_x_V)
    1667          16 :       CALL dbcsr_create(mat_Sigma_x_Gamma, template=bs_env%mat_ao_ao%matrix)
    1668             : 
    1669             :       ! 1. Compute truncated Coulomb operator matrix V^tr(k=0) (cutoff rad: cellsize/2)
    1670             :       CALL RI_2c_integral_mat(qs_env, fm_Vtr_Gamma, bs_env%fm_RI_RI, bs_env%n_RI, &
    1671          16 :                               bs_env%trunc_coulomb, do_kpoints=.FALSE.)
    1672             : 
    1673             :       ! 2. Compute M^-1(k=0) and get M^-1(k=0)*V^tr(k=0)*M^-1(k=0)
    1674          16 :       CALL multiply_fm_W_MIC_time_with_Minv_Gamma(bs_env, qs_env, fm_Vtr_Gamma(:, 1))
    1675             : 
    1676          34 :       DO ispin = 1, bs_env%n_spin
    1677             : 
    1678             :          ! 3. Compute density matrix D_µν
    1679          18 :          CALL G_occ_vir(bs_env, 0.0_dp, bs_env%fm_work_mo(2), ispin, occ=.TRUE., vir=.FALSE.)
    1680             : 
    1681             :          CALL fm_to_local_tensor(bs_env%fm_work_mo(2), bs_env%mat_ao_ao%matrix, &
    1682             :                                  bs_env%mat_ao_ao_tensor%matrix, t_2c_D, bs_env, &
    1683          18 :                                  bs_env%atoms_i_t_group)
    1684             : 
    1685             :          CALL fm_to_local_tensor(fm_Vtr_Gamma(1, 1), bs_env%mat_RI_RI%matrix, &
    1686             :                                  bs_env%mat_RI_RI_tensor%matrix, t_2c_V, bs_env, &
    1687          18 :                                  bs_env%atoms_j_t_group)
    1688             : 
    1689             :          ! every group has its own range of i_atoms and j_atoms; only deal with a
    1690             :          ! limited number of i_atom-j_atom pairs simultaneously in a group to save memory
    1691          36 :          DO i_intval_idx = 1, bs_env%n_intervals_i
    1692          54 :             DO j_intval_idx = 1, bs_env%n_intervals_j
    1693          54 :                i_atoms = bs_env%i_atom_intervals(1:2, i_intval_idx)
    1694          54 :                j_atoms = bs_env%j_atom_intervals(1:2, j_intval_idx)
    1695             : 
    1696             :                ! 4. compute 3-center integrals (µν|P) ("|": truncated Coulomb operator)
    1697             :                ! 5. M_νσQ(iτ) = sum_P (νσ|P) (M^-1(k=0)*V^tr(k=0)*M^-1(k=0))_PQ(iτ)
    1698          18 :                CALL compute_3c_and_contract_W(qs_env, bs_env, i_atoms, j_atoms, t_3c_x_V, t_2c_V)
    1699             : 
    1700             :                ! 6. tensor operations with D and computation of Σ^x
    1701             :                !    Σ^x_λσ(k=0) = sum_νQ M_νσQ(iτ) sum_µ (λµ|Q) D_µν
    1702             :                CALL contract_to_Sigma(t_2c_D, t_3c_x_V, t_2c_Sigma_x, i_atoms, j_atoms, &
    1703          36 :                                       qs_env, bs_env, occ=.TRUE., vir=.FALSE., clear_W=.TRUE.)
    1704             : 
    1705             :             END DO ! j_atoms
    1706             :          END DO ! i_atoms
    1707             : 
    1708             :          CALL local_dbt_to_global_mat(t_2c_Sigma_x, bs_env%mat_ao_ao_tensor%matrix, &
    1709          18 :                                       mat_Sigma_x_Gamma, bs_env%para_env)
    1710             : 
    1711             :          CALL write_matrix(mat_Sigma_x_Gamma, ispin, bs_env%Sigma_x_name, &
    1712          18 :                            bs_env%fm_work_mo(1), qs_env)
    1713             : 
    1714          34 :          CALL copy_dbcsr_to_fm(mat_Sigma_x_Gamma, fm_Sigma_x_Gamma(ispin))
    1715             : 
    1716             :       END DO ! ispin
    1717             : 
    1718          16 :       IF (bs_env%unit_nr > 0) THEN
    1719             :          WRITE (bs_env%unit_nr, '(T2,A,T58,A,F7.1,A)') &
    1720           8 :             'Computed Σ^x(k=0),', ' Execution time', m_walltime() - t1, ' s'
    1721           8 :          WRITE (bs_env%unit_nr, '(A)') ' '
    1722             :       END IF
    1723             : 
    1724          16 :       CALL dbcsr_release(mat_Sigma_x_Gamma)
    1725          16 :       CALL dbt_destroy(t_2c_D)
    1726          16 :       CALL dbt_destroy(t_2c_V)
    1727          16 :       CALL dbt_destroy(t_2c_Sigma_x)
    1728          16 :       CALL dbt_destroy(t_3c_x_V)
    1729          16 :       CALL cp_fm_release(fm_Vtr_Gamma)
    1730             : 
    1731          16 :       CALL timestop(handle)
    1732             : 
    1733          32 :    END SUBROUTINE compute_Sigma_x
    1734             : 
    1735             : ! **************************************************************************************************
    1736             : !> \brief ...
    1737             : !> \param bs_env ...
    1738             : !> \param qs_env ...
    1739             : !> \param fm_W_MIC_time ...
    1740             : !> \param fm_Sigma_c_Gamma_time ...
    1741             : ! **************************************************************************************************
    1742          28 :    SUBROUTINE get_Sigma_c(bs_env, qs_env, fm_W_MIC_time, fm_Sigma_c_Gamma_time)
    1743             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1744             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1745             :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_W_MIC_time
    1746             :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :, :)  :: fm_Sigma_c_Gamma_time
    1747             : 
    1748             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'get_Sigma_c'
    1749             : 
    1750             :       INTEGER                                            :: handle, i_intval_idx, i_t, ispin, &
    1751             :                                                             j_intval_idx, read_write_index
    1752             :       INTEGER, DIMENSION(2)                              :: i_atoms, j_atoms
    1753             :       REAL(KIND=dp)                                      :: t1, tau
    1754          28 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_Sigma_neg_tau, mat_Sigma_pos_tau
    1755         476 :       TYPE(dbt_type)                                     :: t_2c_Gocc, t_2c_Gvir, &
    1756         252 :                                                             t_2c_Sigma_neg_tau, &
    1757         700 :                                                             t_2c_Sigma_pos_tau, t_2c_W, t_3c_x_W
    1758             : 
    1759          28 :       CALL timeset(routineN, handle)
    1760             : 
    1761             :       CALL create_mat_for_Sigma_c(bs_env, t_2c_Gocc, t_2c_Gvir, t_2c_W, t_2c_Sigma_neg_tau, &
    1762             :                                   t_2c_Sigma_pos_tau, t_3c_x_W, &
    1763          28 :                                   mat_Sigma_neg_tau, mat_Sigma_pos_tau)
    1764             : 
    1765         412 :       DO i_t = 1, bs_env%num_time_freq_points
    1766             : 
    1767         876 :          DO ispin = 1, bs_env%n_spin
    1768             : 
    1769         464 :             t1 = m_walltime()
    1770             : 
    1771         464 :             read_write_index = i_t + (ispin - 1)*bs_env%num_time_freq_points
    1772             : 
    1773             :             ! read self-energy from restart
    1774         464 :             IF (bs_env%Sigma_c_exists(i_t, ispin)) THEN
    1775         240 :                CALL fm_read(bs_env%fm_work_mo(1), bs_env, bs_env%Sigma_p_name, read_write_index)
    1776             :                CALL copy_fm_to_dbcsr(bs_env%fm_work_mo(1), mat_Sigma_pos_tau(i_t, ispin)%matrix, &
    1777         240 :                                      keep_sparsity=.FALSE.)
    1778         240 :                CALL fm_read(bs_env%fm_work_mo(1), bs_env, bs_env%Sigma_n_name, read_write_index)
    1779             :                CALL copy_fm_to_dbcsr(bs_env%fm_work_mo(1), mat_Sigma_neg_tau(i_t, ispin)%matrix, &
    1780         240 :                                      keep_sparsity=.FALSE.)
    1781         240 :                IF (bs_env%unit_nr > 0) THEN
    1782         120 :                   WRITE (bs_env%unit_nr, '(T2,2A,I3,A,I3,A,F7.1,A)') 'Read Σ^c(iτ,k=0) ', &
    1783         120 :                      'from file for time point  ', i_t, ' /', bs_env%num_time_freq_points, &
    1784         240 :                      ',    Execution time', m_walltime() - t1, ' s'
    1785             :                END IF
    1786             : 
    1787             :                CYCLE
    1788             : 
    1789             :             END IF
    1790             : 
    1791         224 :             tau = bs_env%imag_time_points(i_t)
    1792             : 
    1793         224 :             CALL G_occ_vir(bs_env, tau, bs_env%fm_Gocc, ispin, occ=.TRUE., vir=.FALSE.)
    1794         224 :             CALL G_occ_vir(bs_env, tau, bs_env%fm_Gvir, ispin, occ=.FALSE., vir=.TRUE.)
    1795             : 
    1796             :             ! fm G^occ, G^vir and W to local tensor
    1797             :             CALL fm_to_local_tensor(bs_env%fm_Gocc, bs_env%mat_ao_ao%matrix, &
    1798             :                                     bs_env%mat_ao_ao_tensor%matrix, t_2c_Gocc, bs_env, &
    1799         224 :                                     bs_env%atoms_i_t_group)
    1800             :             CALL fm_to_local_tensor(bs_env%fm_Gvir, bs_env%mat_ao_ao%matrix, &
    1801             :                                     bs_env%mat_ao_ao_tensor%matrix, t_2c_Gvir, bs_env, &
    1802         224 :                                     bs_env%atoms_i_t_group)
    1803             :             CALL fm_to_local_tensor(fm_W_MIC_time(i_t), bs_env%mat_RI_RI%matrix, &
    1804             :                                     bs_env%mat_RI_RI_tensor%matrix, t_2c_W, bs_env, &
    1805         224 :                                     bs_env%atoms_j_t_group)
    1806             : 
    1807             :             ! every group has its own range of i_atoms and j_atoms; only deal with a
    1808             :             ! limited number of i_atom-j_atom pairs simultaneously in a group to save memory
    1809         448 :             DO i_intval_idx = 1, bs_env%n_intervals_i
    1810         672 :                DO j_intval_idx = 1, bs_env%n_intervals_j
    1811         672 :                   i_atoms = bs_env%i_atom_intervals(1:2, i_intval_idx)
    1812         672 :                   j_atoms = bs_env%j_atom_intervals(1:2, j_intval_idx)
    1813             : 
    1814         224 :                   IF (bs_env%skip_Sigma_occ(i_intval_idx, j_intval_idx) .AND. &
    1815             :                       bs_env%skip_Sigma_vir(i_intval_idx, j_intval_idx)) CYCLE
    1816             : 
    1817             :                   ! 1. compute 3-center integrals (µν|P) ("|": truncated Coulomb operator)
    1818             :                   ! 2. tensor operation M_νσQ(iτ) = sum_P (νσ|P) W^MIC_PQ(iτ)
    1819         206 :                   CALL compute_3c_and_contract_W(qs_env, bs_env, i_atoms, j_atoms, t_3c_x_W, t_2c_W)
    1820             : 
    1821             :                   ! 3. Σ_λσ(iτ,k=0) = sum_νQ M_νσQ(iτ) sum_µ (λµ|Q) G^occ_µν(i|τ|) for τ < 0
    1822             :                   !    (recall M_νσQ(iτ) = M_νσQ(-iτ) because W^MIC_PQ(iτ) = W^MIC_PQ(-iτ) )
    1823             :                   CALL contract_to_Sigma(t_2c_Gocc, t_3c_x_W, t_2c_Sigma_neg_tau, i_atoms, j_atoms, &
    1824             :                                          qs_env, bs_env, occ=.TRUE., vir=.FALSE., clear_W=.FALSE., &
    1825         206 :                                          can_skip=bs_env%skip_Sigma_occ(i_intval_idx, j_intval_idx))
    1826             : 
    1827             :                   !    Σ_λσ(iτ,k=0) = sum_νQ M_νσQ(iτ) sum_µ (λµ|Q) G^vir_µν(i|τ|) for τ > 0
    1828             :                   CALL contract_to_Sigma(t_2c_Gvir, t_3c_x_W, t_2c_Sigma_pos_tau, i_atoms, j_atoms, &
    1829             :                                          qs_env, bs_env, occ=.FALSE., vir=.TRUE., clear_W=.TRUE., &
    1830         448 :                                          can_skip=bs_env%skip_Sigma_vir(i_intval_idx, j_intval_idx))
    1831             : 
    1832             :                END DO ! j_atoms
    1833             :             END DO ! i_atoms
    1834             : 
    1835             :             ! 4. communicate data tensor t_2c_Sigma (which is local in the subgroup)
    1836             :             !    to the global dbcsr matrix mat_Sigma_pos/neg_tau (which stores Σ for all iτ)
    1837             :             CALL local_dbt_to_global_mat(t_2c_Sigma_neg_tau, bs_env%mat_ao_ao_tensor%matrix, &
    1838         224 :                                          mat_Sigma_neg_tau(i_t, ispin)%matrix, bs_env%para_env)
    1839             :             CALL local_dbt_to_global_mat(t_2c_Sigma_pos_tau, bs_env%mat_ao_ao_tensor%matrix, &
    1840         224 :                                          mat_Sigma_pos_tau(i_t, ispin)%matrix, bs_env%para_env)
    1841             : 
    1842             :             CALL write_matrix(mat_Sigma_pos_tau(i_t, ispin)%matrix, read_write_index, &
    1843         224 :                               bs_env%Sigma_p_name, bs_env%fm_work_mo(1), qs_env)
    1844             :             CALL write_matrix(mat_Sigma_neg_tau(i_t, ispin)%matrix, read_write_index, &
    1845         224 :                               bs_env%Sigma_n_name, bs_env%fm_work_mo(1), qs_env)
    1846             : 
    1847         608 :             IF (bs_env%unit_nr > 0) THEN
    1848             :                WRITE (bs_env%unit_nr, '(T2,A,I10,A,I3,A,F7.1,A)') &
    1849         112 :                   'Computed Σ^c(iτ,k=0) for time point ', i_t, ' /', bs_env%num_time_freq_points, &
    1850         224 :                   ',    Execution time', m_walltime() - t1, ' s'
    1851             :             END IF
    1852             : 
    1853             :          END DO ! ispin
    1854             : 
    1855             :       END DO ! i_t
    1856             : 
    1857          28 :       IF (bs_env%unit_nr > 0) WRITE (bs_env%unit_nr, '(A)') ' '
    1858             : 
    1859             :       CALL fill_fm_Sigma_c_Gamma_time(fm_Sigma_c_Gamma_time, bs_env, &
    1860          28 :                                       mat_Sigma_pos_tau, mat_Sigma_neg_tau)
    1861             : 
    1862          28 :       CALL print_skipping(bs_env)
    1863             : 
    1864             :       CALL destroy_mat_Sigma_c(t_2c_Gocc, t_2c_Gvir, t_2c_W, t_2c_Sigma_neg_tau, &
    1865             :                                t_2c_Sigma_pos_tau, t_3c_x_W, fm_W_MIC_time, &
    1866          28 :                                mat_Sigma_neg_tau, mat_Sigma_pos_tau)
    1867             : 
    1868          28 :       CALL delete_unnecessary_files(bs_env)
    1869             : 
    1870          28 :       CALL timestop(handle)
    1871             : 
    1872          56 :    END SUBROUTINE get_Sigma_c
    1873             : 
    1874             : ! **************************************************************************************************
    1875             : !> \brief ...
    1876             : !> \param bs_env ...
    1877             : !> \param t_2c_Gocc ...
    1878             : !> \param t_2c_Gvir ...
    1879             : !> \param t_2c_W ...
    1880             : !> \param t_2c_Sigma_neg_tau ...
    1881             : !> \param t_2c_Sigma_pos_tau ...
    1882             : !> \param t_3c_x_W ...
    1883             : !> \param mat_Sigma_neg_tau ...
    1884             : !> \param mat_Sigma_pos_tau ...
    1885             : ! **************************************************************************************************
    1886          28 :    SUBROUTINE create_mat_for_Sigma_c(bs_env, t_2c_Gocc, t_2c_Gvir, t_2c_W, t_2c_Sigma_neg_tau, &
    1887             :                                      t_2c_Sigma_pos_tau, t_3c_x_W, &
    1888             :                                      mat_Sigma_neg_tau, mat_Sigma_pos_tau)
    1889             : 
    1890             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1891             :       TYPE(dbt_type)                                     :: t_2c_Gocc, t_2c_Gvir, t_2c_W, &
    1892             :                                                             t_2c_Sigma_neg_tau, &
    1893             :                                                             t_2c_Sigma_pos_tau, t_3c_x_W
    1894             :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_Sigma_neg_tau, mat_Sigma_pos_tau
    1895             : 
    1896             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'create_mat_for_Sigma_c'
    1897             : 
    1898             :       INTEGER                                            :: handle, i_t, ispin
    1899             : 
    1900          28 :       CALL timeset(routineN, handle)
    1901             : 
    1902          28 :       CALL dbt_create(bs_env%t_G, t_2c_Gocc)
    1903          28 :       CALL dbt_create(bs_env%t_G, t_2c_Gvir)
    1904          28 :       CALL dbt_create(bs_env%t_W, t_2c_W)
    1905          28 :       CALL dbt_create(bs_env%t_G, t_2c_Sigma_neg_tau)
    1906          28 :       CALL dbt_create(bs_env%t_G, t_2c_Sigma_pos_tau)
    1907          28 :       CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_x_W)
    1908             : 
    1909          28 :       NULLIFY (mat_Sigma_neg_tau, mat_Sigma_pos_tau)
    1910         612 :       ALLOCATE (mat_Sigma_neg_tau(bs_env%num_time_freq_points, bs_env%n_spin))
    1911         612 :       ALLOCATE (mat_Sigma_pos_tau(bs_env%num_time_freq_points, bs_env%n_spin))
    1912             : 
    1913         412 :       DO i_t = 1, bs_env%num_time_freq_points
    1914         876 :          DO ispin = 1, bs_env%n_spin
    1915         464 :             ALLOCATE (mat_Sigma_neg_tau(i_t, ispin)%matrix)
    1916         464 :             ALLOCATE (mat_Sigma_pos_tau(i_t, ispin)%matrix)
    1917         464 :             CALL dbcsr_create(mat_Sigma_neg_tau(i_t, ispin)%matrix, template=bs_env%mat_ao_ao%matrix)
    1918         848 :             CALL dbcsr_create(mat_Sigma_pos_tau(i_t, ispin)%matrix, template=bs_env%mat_ao_ao%matrix)
    1919             :          END DO
    1920             :       END DO
    1921             : 
    1922          28 :       CALL timestop(handle)
    1923             : 
    1924          28 :    END SUBROUTINE create_mat_for_Sigma_c
    1925             : 
    1926             : ! **************************************************************************************************
    1927             : !> \brief ...
    1928             : !> \param qs_env ...
    1929             : !> \param bs_env ...
    1930             : !> \param i_atoms ...
    1931             : !> \param j_atoms ...
    1932             : !> \param t_3c_x_W ...
    1933             : !> \param t_2c_W ...
    1934             : ! **************************************************************************************************
    1935         224 :    SUBROUTINE compute_3c_and_contract_W(qs_env, bs_env, i_atoms, j_atoms, t_3c_x_W, t_2c_W)
    1936             : 
    1937             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1938             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1939             :       INTEGER, DIMENSION(2)                              :: i_atoms, j_atoms
    1940             :       TYPE(dbt_type)                                     :: t_3c_x_W, t_2c_W
    1941             : 
    1942             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_3c_and_contract_W'
    1943             : 
    1944             :       INTEGER                                            :: handle, RI_intval_idx
    1945             :       INTEGER, DIMENSION(2)                              :: bounds_j, RI_atoms
    1946        3808 :       TYPE(dbt_type)                                     :: t_3c_for_W, t_3c_x_W_tmp
    1947             : 
    1948         224 :       CALL timeset(routineN, handle)
    1949             : 
    1950         224 :       CALL dbt_create(bs_env%t_RI__AO_AO, t_3c_x_W_tmp)
    1951         224 :       CALL dbt_create(bs_env%t_RI__AO_AO, t_3c_for_W)
    1952             : 
    1953             :       bounds_j(1:2) = [bs_env%i_RI_start_from_atom(j_atoms(1)), &
    1954         672 :                        bs_env%i_RI_end_from_atom(j_atoms(2))]
    1955             : 
    1956         448 :       DO RI_intval_idx = 1, bs_env%n_intervals_inner_loop_atoms
    1957         672 :          RI_atoms = bs_env%inner_loop_atom_intervals(1:2, RI_intval_idx)
    1958             : 
    1959             :          ! 1. compute 3-center integrals (µν|P) ("|": truncated Coulomb operator)
    1960             :          CALL compute_3c_integrals(qs_env, bs_env, t_3c_for_W, &
    1961         224 :                                    atoms_AO_1=i_atoms, atoms_RI=RI_atoms)
    1962             : 
    1963             :          ! 2. tensor operation M_νσQ(iτ) = sum_P (νσ|P) W^MIC_PQ(iτ)
    1964             :          CALL dbt_contract(alpha=1.0_dp, &
    1965             :                            tensor_1=t_2c_W, &
    1966             :                            tensor_2=t_3c_for_W, &
    1967             :                            beta=1.0_dp, &
    1968             :                            tensor_3=t_3c_x_W_tmp, &
    1969             :                            contract_1=[2], notcontract_1=[1], map_1=[1], &
    1970             :                            contract_2=[1], notcontract_2=[2, 3], map_2=[2, 3], &
    1971             :                            bounds_2=bounds_j, &
    1972         448 :                            filter_eps=bs_env%eps_filter)
    1973             : 
    1974             :       END DO ! RI_atoms
    1975             : 
    1976             :       ! 3. reorder tensor
    1977         224 :       CALL dbt_copy(t_3c_x_W_tmp, t_3c_x_W, order=[1, 2, 3], move_data=.TRUE.)
    1978             : 
    1979         224 :       CALL dbt_destroy(t_3c_x_W_tmp)
    1980         224 :       CALL dbt_destroy(t_3c_for_W)
    1981             : 
    1982         224 :       CALL timestop(handle)
    1983             : 
    1984         224 :    END SUBROUTINE compute_3c_and_contract_W
    1985             : 
    1986             : ! **************************************************************************************************
    1987             : !> \brief ...
    1988             : !> \param t_2c_G ...
    1989             : !> \param t_3c_x_W ...
    1990             : !> \param t_2c_Sigma ...
    1991             : !> \param i_atoms ...
    1992             : !> \param j_atoms ...
    1993             : !> \param qs_env ...
    1994             : !> \param bs_env ...
    1995             : !> \param occ ...
    1996             : !> \param vir ...
    1997             : !> \param clear_W ...
    1998             : !> \param can_skip ...
    1999             : ! **************************************************************************************************
    2000         430 :    SUBROUTINE contract_to_Sigma(t_2c_G, t_3c_x_W, t_2c_Sigma, i_atoms, j_atoms, qs_env, bs_env, &
    2001             :                                 occ, vir, clear_W, can_skip)
    2002             :       TYPE(dbt_type)                                     :: t_2c_G, t_3c_x_W, t_2c_Sigma
    2003             :       INTEGER, DIMENSION(2)                              :: i_atoms, j_atoms
    2004             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2005             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    2006             :       LOGICAL                                            :: occ, vir, clear_W
    2007             :       LOGICAL, OPTIONAL                                  :: can_skip
    2008             : 
    2009             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'contract_to_Sigma'
    2010             : 
    2011             :       INTEGER :: handle, inner_loop_atoms_interval_index
    2012             :       INTEGER(KIND=int_8)                                :: flop
    2013             :       INTEGER, DIMENSION(2)                              :: bounds_i, IL_atoms
    2014             :       REAL(KIND=dp)                                      :: sign_Sigma
    2015       10750 :       TYPE(dbt_type)                                     :: t_3c_for_G, t_3c_x_G, t_3c_x_G_2
    2016             : 
    2017         430 :       CALL timeset(routineN, handle)
    2018             : 
    2019         430 :       CPASSERT(occ .EQV. (.NOT. vir))
    2020         430 :       IF (occ) sign_Sigma = -1.0_dp
    2021         430 :       IF (vir) sign_Sigma = 1.0_dp
    2022             : 
    2023         430 :       CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_for_G)
    2024         430 :       CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_x_G)
    2025         430 :       CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_x_G_2)
    2026             : 
    2027             :       bounds_i(1:2) = [bs_env%i_ao_start_from_atom(i_atoms(1)), &
    2028        1290 :                        bs_env%i_ao_end_from_atom(i_atoms(2))]
    2029             : 
    2030         860 :       DO inner_loop_atoms_interval_index = 1, bs_env%n_intervals_inner_loop_atoms
    2031        1290 :          IL_atoms = bs_env%inner_loop_atom_intervals(1:2, inner_loop_atoms_interval_index)
    2032             : 
    2033             :          CALL compute_3c_integrals(qs_env, bs_env, t_3c_for_G, &
    2034         430 :                                    atoms_RI=j_atoms, atoms_AO_2=IL_atoms)
    2035             : 
    2036             :          CALL dbt_contract(alpha=1.0_dp, &
    2037             :                            tensor_1=t_2c_G, &
    2038             :                            tensor_2=t_3c_for_G, &
    2039             :                            beta=1.0_dp, &
    2040             :                            tensor_3=t_3c_x_G, &
    2041             :                            contract_1=[2], notcontract_1=[1], map_1=[3], &
    2042             :                            contract_2=[3], notcontract_2=[1, 2], map_2=[1, 2], &
    2043             :                            bounds_2=bounds_i, &
    2044         860 :                            filter_eps=bs_env%eps_filter)
    2045             : 
    2046             :       END DO ! IL_atoms
    2047             : 
    2048         430 :       CALL dbt_copy(t_3c_x_G, t_3c_x_G_2, order=[1, 3, 2], move_data=.TRUE.)
    2049             : 
    2050             :       CALL dbt_contract(alpha=sign_Sigma, &
    2051             :                         tensor_1=t_3c_x_W, &
    2052             :                         tensor_2=t_3c_x_G_2, &
    2053             :                         beta=1.0_dp, &
    2054             :                         tensor_3=t_2c_Sigma, &
    2055             :                         contract_1=[1, 2], notcontract_1=[3], map_1=[1], &
    2056             :                         contract_2=[1, 2], notcontract_2=[3], map_2=[2], &
    2057         430 :                         filter_eps=bs_env%eps_filter, move_data=clear_W, flop=flop)
    2058             : 
    2059         430 :       IF (PRESENT(can_skip)) THEN
    2060         412 :          IF (flop == 0_int_8) can_skip = .TRUE.
    2061             :       END IF
    2062             : 
    2063         430 :       CALL dbt_destroy(t_3c_for_G)
    2064         430 :       CALL dbt_destroy(t_3c_x_G)
    2065         430 :       CALL dbt_destroy(t_3c_x_G_2)
    2066             : 
    2067         430 :       CALL timestop(handle)
    2068             : 
    2069         430 :    END SUBROUTINE contract_to_Sigma
    2070             : 
    2071             : ! **************************************************************************************************
    2072             : !> \brief ...
    2073             : !> \param fm_Sigma_c_Gamma_time ...
    2074             : !> \param bs_env ...
    2075             : !> \param mat_Sigma_pos_tau ...
    2076             : !> \param mat_Sigma_neg_tau ...
    2077             : ! **************************************************************************************************
    2078          28 :    SUBROUTINE fill_fm_Sigma_c_Gamma_time(fm_Sigma_c_Gamma_time, bs_env, &
    2079             :                                          mat_Sigma_pos_tau, mat_Sigma_neg_tau)
    2080             : 
    2081             :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :, :)  :: fm_Sigma_c_Gamma_time
    2082             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    2083             :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_Sigma_pos_tau, mat_Sigma_neg_tau
    2084             : 
    2085             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'fill_fm_Sigma_c_Gamma_time'
    2086             : 
    2087             :       INTEGER                                            :: handle, i_t, ispin, pos_neg
    2088             : 
    2089          28 :       CALL timeset(routineN, handle)
    2090             : 
    2091        1148 :       ALLOCATE (fm_Sigma_c_Gamma_time(bs_env%num_time_freq_points, 2, bs_env%n_spin))
    2092         412 :       DO i_t = 1, bs_env%num_time_freq_points
    2093         876 :          DO ispin = 1, bs_env%n_spin
    2094        1392 :             DO pos_neg = 1, 2
    2095             :                CALL cp_fm_create(fm_Sigma_c_Gamma_time(i_t, pos_neg, ispin), &
    2096        1392 :                                  bs_env%fm_s_Gamma%matrix_struct)
    2097             :             END DO
    2098             :             CALL copy_dbcsr_to_fm(mat_Sigma_pos_tau(i_t, ispin)%matrix, &
    2099         464 :                                   fm_Sigma_c_Gamma_time(i_t, 1, ispin))
    2100             :             CALL copy_dbcsr_to_fm(mat_Sigma_neg_tau(i_t, ispin)%matrix, &
    2101         848 :                                   fm_Sigma_c_Gamma_time(i_t, 2, ispin))
    2102             :          END DO
    2103             :       END DO
    2104             : 
    2105          28 :       CALL timestop(handle)
    2106             : 
    2107          28 :    END SUBROUTINE fill_fm_Sigma_c_Gamma_time
    2108             : 
    2109             : ! **************************************************************************************************
    2110             : !> \brief ...
    2111             : !> \param bs_env ...
    2112             : ! **************************************************************************************************
    2113          28 :    SUBROUTINE print_skipping(bs_env)
    2114             : 
    2115             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    2116             : 
    2117             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'print_skipping'
    2118             : 
    2119             :       INTEGER                                            :: handle, i_intval_idx, j_intval_idx, &
    2120             :                                                             n_skip
    2121             : 
    2122          28 :       CALL timeset(routineN, handle)
    2123             : 
    2124          28 :       n_skip = 0
    2125             : 
    2126          56 :       DO i_intval_idx = 1, bs_env%n_intervals_i
    2127          84 :          DO j_intval_idx = 1, bs_env%n_intervals_j
    2128          28 :             IF (bs_env%skip_Sigma_occ(i_intval_idx, j_intval_idx) .AND. &
    2129          28 :                 bs_env%skip_Sigma_vir(i_intval_idx, j_intval_idx)) THEN
    2130           2 :                n_skip = n_skip + 1
    2131             :             END IF
    2132             :          END DO
    2133             :       END DO
    2134             : 
    2135          28 :       IF (bs_env%unit_nr > 0) THEN
    2136             :          WRITE (bs_env%unit_nr, '(T2,A,T74,F7.1,A)') &
    2137          14 :             'Sparsity of Σ^c(iτ,k=0): Percentage of skipped atom pairs:', &
    2138          28 :             REAL(100*n_skip, KIND=dp)/REAL(i_intval_idx*j_intval_idx, KIND=dp), ' %'
    2139             :       END IF
    2140             : 
    2141          28 :       CALL timestop(handle)
    2142             : 
    2143          28 :    END SUBROUTINE print_skipping
    2144             : 
    2145             : ! **************************************************************************************************
    2146             : !> \brief ...
    2147             : !> \param t_2c_Gocc ...
    2148             : !> \param t_2c_Gvir ...
    2149             : !> \param t_2c_W ...
    2150             : !> \param t_2c_Sigma_neg_tau ...
    2151             : !> \param t_2c_Sigma_pos_tau ...
    2152             : !> \param t_3c_x_W ...
    2153             : !> \param fm_W_MIC_time ...
    2154             : !> \param mat_Sigma_neg_tau ...
    2155             : !> \param mat_Sigma_pos_tau ...
    2156             : ! **************************************************************************************************
    2157          28 :    SUBROUTINE destroy_mat_Sigma_c(t_2c_Gocc, t_2c_Gvir, t_2c_W, t_2c_Sigma_neg_tau, &
    2158             :                                   t_2c_Sigma_pos_tau, t_3c_x_W, fm_W_MIC_time, &
    2159             :                                   mat_Sigma_neg_tau, mat_Sigma_pos_tau)
    2160             : 
    2161             :       TYPE(dbt_type)                                     :: t_2c_Gocc, t_2c_Gvir, t_2c_W, &
    2162             :                                                             t_2c_Sigma_neg_tau, &
    2163             :                                                             t_2c_Sigma_pos_tau, t_3c_x_W
    2164             :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_W_MIC_time
    2165             :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_Sigma_neg_tau, mat_Sigma_pos_tau
    2166             : 
    2167             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'destroy_mat_Sigma_c'
    2168             : 
    2169             :       INTEGER                                            :: handle
    2170             : 
    2171          28 :       CALL timeset(routineN, handle)
    2172             : 
    2173          28 :       CALL dbt_destroy(t_2c_Gocc)
    2174          28 :       CALL dbt_destroy(t_2c_Gvir)
    2175          28 :       CALL dbt_destroy(t_2c_W)
    2176          28 :       CALL dbt_destroy(t_2c_Sigma_neg_tau)
    2177          28 :       CALL dbt_destroy(t_2c_Sigma_pos_tau)
    2178          28 :       CALL dbt_destroy(t_3c_x_W)
    2179          28 :       CALL cp_fm_release(fm_W_MIC_time)
    2180          28 :       CALL dbcsr_deallocate_matrix_set(mat_Sigma_neg_tau)
    2181          28 :       CALL dbcsr_deallocate_matrix_set(mat_Sigma_pos_tau)
    2182             : 
    2183          28 :       CALL timestop(handle)
    2184             : 
    2185          28 :    END SUBROUTINE destroy_mat_Sigma_c
    2186             : 
    2187             : ! **************************************************************************************************
    2188             : !> \brief ...
    2189             : !> \param bs_env ...
    2190             : ! **************************************************************************************************
    2191          28 :    SUBROUTINE delete_unnecessary_files(bs_env)
    2192             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    2193             : 
    2194             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'delete_unnecessary_files'
    2195             : 
    2196             :       CHARACTER(LEN=default_string_length)               :: f_chi, f_W_t, prefix
    2197             :       INTEGER                                            :: handle, i_t
    2198             : 
    2199          28 :       CALL timeset(routineN, handle)
    2200             : 
    2201          28 :       prefix = bs_env%prefix
    2202             : 
    2203         412 :       DO i_t = 1, bs_env%num_time_freq_points
    2204             : 
    2205         384 :          IF (i_t < 10) THEN
    2206         240 :             WRITE (f_chi, '(3A,I1,A)') TRIM(prefix), bs_env%chi_name, "_00", i_t, ".matrix"
    2207         240 :             WRITE (f_W_t, '(3A,I1,A)') TRIM(prefix), bs_env%W_time_name, "_00", i_t, ".matrix"
    2208         144 :          ELSE IF (i_t < 100) THEN
    2209         144 :             WRITE (f_chi, '(3A,I2,A)') TRIM(prefix), bs_env%chi_name, "_0", i_t, ".matrix"
    2210         144 :             WRITE (f_W_t, '(3A,I2,A)') TRIM(prefix), bs_env%W_time_name, "_0", i_t, ".matrix"
    2211             :          ELSE
    2212           0 :             CPABORT('Please implement more than 99 time/frequency points.')
    2213             :          END IF
    2214             : 
    2215         384 :          CALL safe_delete(f_chi, bs_env)
    2216         412 :          CALL safe_delete(f_W_t, bs_env)
    2217             : 
    2218             :       END DO
    2219             : 
    2220          28 :       CALL timestop(handle)
    2221             : 
    2222          28 :    END SUBROUTINE delete_unnecessary_files
    2223             : 
    2224             : ! **************************************************************************************************
    2225             : !> \brief ...
    2226             : !> \param filename ...
    2227             : !> \param bs_env ...
    2228             : ! **************************************************************************************************
    2229         768 :    SUBROUTINE safe_delete(filename, bs_env)
    2230             :       CHARACTER(LEN=*)                                   :: filename
    2231             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    2232             : 
    2233             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'safe_delete'
    2234             : 
    2235             :       INTEGER                                            :: handle
    2236             :       LOGICAL                                            :: file_exists
    2237             : 
    2238         768 :       CALL timeset(routineN, handle)
    2239             : 
    2240         768 :       IF (bs_env%para_env%mepos == 0) THEN
    2241             : 
    2242         384 :          INQUIRE (file=TRIM(filename), exist=file_exists)
    2243         384 :          IF (file_exists) CALL mp_file_delete(TRIM(filename))
    2244             : 
    2245             :       END IF
    2246             : 
    2247         768 :       CALL timestop(handle)
    2248             : 
    2249         768 :    END SUBROUTINE safe_delete
    2250             : 
    2251             : ! **************************************************************************************************
    2252             : !> \brief ...
    2253             : !> \param bs_env ...
    2254             : !> \param qs_env ...
    2255             : !> \param fm_Sigma_x_Gamma ...
    2256             : !> \param fm_Sigma_c_Gamma_time ...
    2257             : ! **************************************************************************************************
    2258          28 :    SUBROUTINE compute_QP_energies(bs_env, qs_env, fm_Sigma_x_Gamma, fm_Sigma_c_Gamma_time)
    2259             : 
    2260             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    2261             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2262             :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_Sigma_x_Gamma
    2263             :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :, :)  :: fm_Sigma_c_Gamma_time
    2264             : 
    2265             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_QP_energies'
    2266             : 
    2267             :       INTEGER                                            :: handle, ikp, ispin, j_t
    2268             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: Sigma_x_ikp_n, V_xc_ikp_n
    2269             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: Sigma_c_ikp_n_freq, Sigma_c_ikp_n_time
    2270             :       TYPE(cp_cfm_type)                                  :: cfm_ks_ikp, cfm_mos_ikp, cfm_s_ikp, &
    2271             :                                                             cfm_Sigma_x_ikp, cfm_work_ikp
    2272             : 
    2273          28 :       CALL timeset(routineN, handle)
    2274             : 
    2275          28 :       CALL cp_cfm_create(cfm_mos_ikp, bs_env%fm_s_Gamma%matrix_struct)
    2276          28 :       CALL cp_cfm_create(cfm_work_ikp, bs_env%fm_s_Gamma%matrix_struct)
    2277             :       ! JW TODO: fully distribute these arrays at given time; also eigenvalues in bs_env
    2278         140 :       ALLOCATE (V_xc_ikp_n(bs_env%n_ao), Sigma_x_ikp_n(bs_env%n_ao))
    2279         140 :       ALLOCATE (Sigma_c_ikp_n_time(bs_env%n_ao, bs_env%num_time_freq_points, 2))
    2280         112 :       ALLOCATE (Sigma_c_ikp_n_freq(bs_env%n_ao, bs_env%num_time_freq_points, 2))
    2281             : 
    2282          64 :       DO ispin = 1, bs_env%n_spin
    2283             : 
    2284         120 :          DO ikp = 1, bs_env%nkp_bs_and_DOS
    2285             : 
    2286             :             ! 1. get H^KS_µν(k_i) from H^KS_µν(k=0)
    2287             :             CALL cfm_ikp_from_fm_Gamma(cfm_ks_ikp, bs_env%fm_ks_Gamma(ispin), &
    2288          56 :                                        ikp, qs_env, bs_env%kpoints_DOS, "ORB")
    2289             : 
    2290             :             ! 2. get S_µν(k_i) from S_µν(k=0)
    2291             :             CALL cfm_ikp_from_fm_Gamma(cfm_s_ikp, bs_env%fm_s_Gamma, &
    2292          56 :                                        ikp, qs_env, bs_env%kpoints_DOS, "ORB")
    2293             : 
    2294             :             ! 3. Diagonalize (Roothaan-Hall): H_KS(k_i)*C(k_i) = S(k_i)*C(k_i)*ϵ(k_i)
    2295             :             CALL cp_cfm_geeig(cfm_ks_ikp, cfm_s_ikp, cfm_mos_ikp, &
    2296          56 :                               bs_env%eigenval_scf(:, ikp, ispin), cfm_work_ikp)
    2297             : 
    2298             :             ! 4. V^xc_µν(k=0) -> V^xc_µν(k_i) -> V^xc_nn(k_i)
    2299             :             CALL to_ikp_and_mo(V_xc_ikp_n, bs_env%fm_V_xc_Gamma(ispin), &
    2300          56 :                                ikp, qs_env, bs_env, cfm_mos_ikp)
    2301             : 
    2302             :             ! 5. Σ^x_µν(k=0) -> Σ^x_µν(k_i) -> Σ^x_nn(k_i)
    2303             :             CALL to_ikp_and_mo(Sigma_x_ikp_n, fm_Sigma_x_Gamma(ispin), &
    2304          56 :                                ikp, qs_env, bs_env, cfm_mos_ikp)
    2305             : 
    2306             :             ! 6. Σ^c_µν(k=0,+/-i|τ_j|) -> Σ^c_µν(k_i,+/-i|τ_j|) -> Σ^c_nn(k_i,+/-i|τ_j|)
    2307         704 :             DO j_t = 1, bs_env%num_time_freq_points
    2308             :                CALL to_ikp_and_mo(Sigma_c_ikp_n_time(:, j_t, 1), &
    2309             :                                   fm_Sigma_c_Gamma_time(j_t, 1, ispin), &
    2310         648 :                                   ikp, qs_env, bs_env, cfm_mos_ikp)
    2311             :                CALL to_ikp_and_mo(Sigma_c_ikp_n_time(:, j_t, 2), &
    2312             :                                   fm_Sigma_c_Gamma_time(j_t, 2, ispin), &
    2313         704 :                                   ikp, qs_env, bs_env, cfm_mos_ikp)
    2314             :             END DO
    2315             : 
    2316             :             ! 7. Σ^c_nn(k_i,iτ) -> Σ^c_nn(k_i,iω)
    2317          56 :             CALL time_to_freq(bs_env, Sigma_c_ikp_n_time, Sigma_c_ikp_n_freq, ispin)
    2318             : 
    2319             :             ! 8. Analytic continuation Σ^c_nn(k_i,iω) -> Σ^c_nn(k_i,ϵ) and
    2320             :             !    ϵ_nk_i^GW = ϵ_nk_i^DFT + Σ^c_nn(k_i,ϵ) + Σ^x_nn(k_i) - v^xc_nn(k_i)
    2321             :             CALL analyt_conti_and_print(bs_env, Sigma_c_ikp_n_freq, Sigma_x_ikp_n, V_xc_ikp_n, &
    2322          92 :                                         bs_env%eigenval_scf(:, ikp, ispin), ikp, ispin)
    2323             : 
    2324             :          END DO ! ikp_DOS
    2325             : 
    2326             :       END DO ! ispin
    2327             : 
    2328          28 :       CALL get_all_VBM_CBM_bandgaps(bs_env)
    2329             : 
    2330          28 :       CALL cp_fm_release(fm_Sigma_x_Gamma)
    2331          28 :       CALL cp_fm_release(fm_Sigma_c_Gamma_time)
    2332          28 :       CALL cp_cfm_release(cfm_ks_ikp)
    2333          28 :       CALL cp_cfm_release(cfm_s_ikp)
    2334          28 :       CALL cp_cfm_release(cfm_mos_ikp)
    2335          28 :       CALL cp_cfm_release(cfm_work_ikp)
    2336          28 :       CALL cp_cfm_release(cfm_Sigma_x_ikp)
    2337             : 
    2338          28 :       CALL timestop(handle)
    2339             : 
    2340          56 :    END SUBROUTINE compute_QP_energies
    2341             : 
    2342             : ! **************************************************************************************************
    2343             : !> \brief ...
    2344             : !> \param array_ikp_n ...
    2345             : !> \param fm_Gamma ...
    2346             : !> \param ikp ...
    2347             : !> \param qs_env ...
    2348             : !> \param bs_env ...
    2349             : !> \param cfm_mos_ikp ...
    2350             : ! **************************************************************************************************
    2351        1408 :    SUBROUTINE to_ikp_and_mo(array_ikp_n, fm_Gamma, ikp, qs_env, bs_env, cfm_mos_ikp)
    2352             : 
    2353             :       REAL(KIND=dp), DIMENSION(:)                        :: array_ikp_n
    2354             :       TYPE(cp_fm_type)                                   :: fm_Gamma
    2355             :       INTEGER                                            :: ikp
    2356             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2357             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    2358             :       TYPE(cp_cfm_type)                                  :: cfm_mos_ikp
    2359             : 
    2360             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'to_ikp_and_mo'
    2361             : 
    2362             :       INTEGER                                            :: handle
    2363             :       TYPE(cp_fm_type)                                   :: fm_ikp_mo_re
    2364             : 
    2365        1408 :       CALL timeset(routineN, handle)
    2366             : 
    2367        1408 :       CALL cp_fm_create(fm_ikp_mo_re, fm_Gamma%matrix_struct)
    2368             : 
    2369        1408 :       CALL fm_Gamma_ao_to_cfm_ikp_mo(fm_Gamma, fm_ikp_mo_re, ikp, qs_env, bs_env, cfm_mos_ikp)
    2370             : 
    2371        1408 :       CALL cp_fm_get_diag(fm_ikp_mo_re, array_ikp_n)
    2372             : 
    2373        1408 :       CALL cp_fm_release(fm_ikp_mo_re)
    2374             : 
    2375        1408 :       CALL timestop(handle)
    2376             : 
    2377        1408 :    END SUBROUTINE to_ikp_and_mo
    2378             : 
    2379             : ! **************************************************************************************************
    2380             : !> \brief ...
    2381             : !> \param fm_Gamma ...
    2382             : !> \param fm_ikp_mo_re ...
    2383             : !> \param ikp ...
    2384             : !> \param qs_env ...
    2385             : !> \param bs_env ...
    2386             : !> \param cfm_mos_ikp ...
    2387             : ! **************************************************************************************************
    2388        5632 :    SUBROUTINE fm_Gamma_ao_to_cfm_ikp_mo(fm_Gamma, fm_ikp_mo_re, ikp, qs_env, bs_env, cfm_mos_ikp)
    2389             :       TYPE(cp_fm_type)                                   :: fm_Gamma, fm_ikp_mo_re
    2390             :       INTEGER                                            :: ikp
    2391             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2392             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    2393             :       TYPE(cp_cfm_type)                                  :: cfm_mos_ikp
    2394             : 
    2395             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'fm_Gamma_ao_to_cfm_ikp_mo'
    2396             : 
    2397             :       INTEGER                                            :: handle, nmo
    2398             :       TYPE(cp_cfm_type)                                  :: cfm_ikp_ao, cfm_ikp_mo, cfm_tmp
    2399             : 
    2400        1408 :       CALL timeset(routineN, handle)
    2401             : 
    2402        1408 :       CALL cp_cfm_create(cfm_ikp_ao, fm_Gamma%matrix_struct)
    2403        1408 :       CALL cp_cfm_create(cfm_ikp_mo, fm_Gamma%matrix_struct)
    2404        1408 :       CALL cp_cfm_create(cfm_tmp, fm_Gamma%matrix_struct)
    2405             : 
    2406             :       ! get cfm_µν(k_i) from fm_µν(k=0)
    2407        1408 :       CALL cfm_ikp_from_fm_Gamma(cfm_ikp_ao, fm_Gamma, ikp, qs_env, bs_env%kpoints_DOS, "ORB")
    2408             : 
    2409        1408 :       nmo = bs_env%n_ao
    2410        1408 :       CALL parallel_gemm('N', 'N', nmo, nmo, nmo, z_one, cfm_ikp_ao, cfm_mos_ikp, z_zero, cfm_tmp)
    2411        1408 :       CALL parallel_gemm('C', 'N', nmo, nmo, nmo, z_one, cfm_mos_ikp, cfm_tmp, z_zero, cfm_ikp_mo)
    2412             : 
    2413        1408 :       CALL cp_cfm_to_fm(cfm_ikp_mo, fm_ikp_mo_re)
    2414             : 
    2415        1408 :       CALL cp_cfm_release(cfm_ikp_mo)
    2416        1408 :       CALL cp_cfm_release(cfm_ikp_ao)
    2417        1408 :       CALL cp_cfm_release(cfm_tmp)
    2418             : 
    2419        1408 :       CALL timestop(handle)
    2420             : 
    2421        1408 :    END SUBROUTINE fm_Gamma_ao_to_cfm_ikp_mo
    2422             : 
    2423             : END MODULE gw_large_cell_gamma

Generated by: LCOV version 1.15