LCOV - code coverage report
Current view: top level - src - gw_large_cell_gamma.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:51fc4cd) Lines: 92.5 % 782 723
Test Date: 2026-02-04 06:28:27 Functions: 97.6 % 41 40

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

Generated by: LCOV version 2.0-1