LCOV - code coverage report
Current view: top level - src - rpa_main.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:21ef868) Lines: 96.9 % 609 590
Test Date: 2026-08-14 07:04:57 Functions: 100.0 % 4 4

            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 to calculate RI-RPA energy
      10              : !> \par History
      11              : !>      06.2012 created [Mauro Del Ben]
      12              : !>      04.2015 GW routines added [Jan Wilhelm]
      13              : !>      10.2015 Cubic-scaling RPA routines added [Jan Wilhelm]
      14              : !>      10.2018 Cubic-scaling SOS-MP2 added [Frederick Stein]
      15              : !>      03.2019 Refactoring [Frederick Stein]
      16              : ! **************************************************************************************************
      17              : MODULE rpa_main
      18              :    USE bibliography,                    ONLY: &
      19              :         Bates2013, DelBen2013, DelBen2015, Freeman1977, Gruneis2009, Ren2011, Ren2013, &
      20              :         Wilhelm2016a, Wilhelm2016b, Wilhelm2017, Wilhelm2018, cite_reference
      21              :    USE bse_main,                        ONLY: start_bse_calculation
      22              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_create,&
      23              :                                               cp_blacs_env_release,&
      24              :                                               cp_blacs_env_type
      25              :    USE cp_cfm_types,                    ONLY: cp_cfm_type
      26              :    USE cp_dbcsr_api,                    ONLY: dbcsr_add,&
      27              :                                               dbcsr_clear,&
      28              :                                               dbcsr_get_info,&
      29              :                                               dbcsr_p_type,&
      30              :                                               dbcsr_type
      31              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_scale_and_add
      32              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      33              :                                               cp_fm_struct_release,&
      34              :                                               cp_fm_struct_type
      35              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      36              :                                               cp_fm_release,&
      37              :                                               cp_fm_set_all,&
      38              :                                               cp_fm_to_fm,&
      39              :                                               cp_fm_type
      40              :    USE dbt_api,                         ONLY: dbt_type
      41              :    USE dgemm_counter_types,             ONLY: dgemm_counter_init,&
      42              :                                               dgemm_counter_type,&
      43              :                                               dgemm_counter_write
      44              :    USE group_dist_types,                ONLY: create_group_dist,&
      45              :                                               get_group_dist,&
      46              :                                               group_dist_d1_type,&
      47              :                                               maxsize,&
      48              :                                               release_group_dist
      49              :    USE hfx_types,                       ONLY: block_ind_type,&
      50              :                                               hfx_compression_type
      51              :    USE input_constants,                 ONLY: rpa_exchange_axk,&
      52              :                                               rpa_exchange_none,&
      53              :                                               rpa_exchange_sosex,&
      54              :                                               sigma_none,&
      55              :                                               wfc_mm_style_gemm
      56              :    USE kinds,                           ONLY: dp,&
      57              :                                               int_8
      58              :    USE kpoint_types,                    ONLY: kpoint_type
      59              :    USE machine,                         ONLY: m_flush,&
      60              :                                               m_memory
      61              :    USE mathconstants,                   ONLY: pi,&
      62              :                                               z_zero
      63              :    USE message_passing,                 ONLY: mp_comm_type,&
      64              :                                               mp_para_env_release,&
      65              :                                               mp_para_env_type
      66              :    USE minimax_exp,                     ONLY: check_exp_minimax_range
      67              :    USE mp2_grids,                       ONLY: get_clenshaw_grid,&
      68              :                                               get_minimax_grid
      69              :    USE mp2_laplace,                     ONLY: SOS_MP2_postprocessing
      70              :    USE mp2_ri_grad_util,                ONLY: array2fm
      71              :    USE mp2_types,                       ONLY: mp2_type,&
      72              :                                               three_dim_real_array,&
      73              :                                               two_dim_int_array,&
      74              :                                               two_dim_real_array
      75              :    USE qs_environment_types,            ONLY: get_qs_env,&
      76              :                                               qs_environment_type
      77              :    USE rpa_exchange,                    ONLY: rpa_exchange_needed_mem,&
      78              :                                               rpa_exchange_work_type
      79              :    USE rpa_grad,                        ONLY: rpa_grad_copy_Q,&
      80              :                                               rpa_grad_create,&
      81              :                                               rpa_grad_finalize,&
      82              :                                               rpa_grad_matrix_operations,&
      83              :                                               rpa_grad_needed_mem,&
      84              :                                               rpa_grad_type
      85              :    USE rpa_gw,                          ONLY: allocate_matrices_gw,&
      86              :                                               allocate_matrices_gw_im_time,&
      87              :                                               compute_GW_self_energy,&
      88              :                                               compute_QP_energies,&
      89              :                                               compute_W_cubic_GW,&
      90              :                                               deallocate_matrices_gw,&
      91              :                                               deallocate_matrices_gw_im_time,&
      92              :                                               get_fermi_level_offset
      93              :    USE rpa_gw_ic,                       ONLY: calculate_ic_correction
      94              :    USE rpa_gw_kpoints_util,             ONLY: get_bandstruc_and_k_dependent_MOs,&
      95              :                                               invert_eps_compute_W_and_Erpa_kp
      96              :    USE rpa_im_time,                     ONLY: compute_mat_P_omega,&
      97              :                                               zero_mat_P_omega
      98              :    USE rpa_im_time_force_methods,       ONLY: calc_laplace_loop_forces,&
      99              :                                               calc_post_loop_forces,&
     100              :                                               calc_rpa_loop_forces,&
     101              :                                               init_im_time_forces,&
     102              :                                               keep_initial_quad
     103              :    USE rpa_im_time_force_types,         ONLY: im_time_force_release,&
     104              :                                               im_time_force_type
     105              :    USE rpa_sigma_functional,            ONLY: finalize_rpa_sigma,&
     106              :                                               rpa_sigma_create,&
     107              :                                               rpa_sigma_matrix_spectral,&
     108              :                                               rpa_sigma_type
     109              :    USE rpa_util,                        ONLY: Q_trace_and_add_unit_matrix,&
     110              :                                               alloc_im_time,&
     111              :                                               calc_mat_Q,&
     112              :                                               compute_Erpa_by_freq_int,&
     113              :                                               contract_P_omega_with_mat_L,&
     114              :                                               dealloc_im_time,&
     115              :                                               remove_scaling_factor_rpa
     116              :    USE util,                            ONLY: get_limit
     117              : #include "./base/base_uses.f90"
     118              : 
     119              :    IMPLICIT NONE
     120              : 
     121              :    PRIVATE
     122              : 
     123              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'rpa_main'
     124              : 
     125              :    PUBLIC :: rpa_ri_compute_en
     126              : 
     127              : CONTAINS
     128              : 
     129              : ! **************************************************************************************************
     130              : !> \brief ...
     131              : !> \param qs_env ...
     132              : !> \param Erpa ...
     133              : !> \param mp2_env ...
     134              : !> \param BIb_C ...
     135              : !> \param BIb_C_gw ...
     136              : !> \param BIb_C_bse_ij ...
     137              : !> \param BIb_C_bse_ab ...
     138              : !> \param para_env ...
     139              : !> \param para_env_sub ...
     140              : !> \param color_sub ...
     141              : !> \param gd_array ...
     142              : !> \param gd_B_virtual ...
     143              : !> \param gd_B_all ...
     144              : !> \param gd_B_occ_bse ...
     145              : !> \param gd_B_virt_bse ...
     146              : !> \param mo_coeff ...
     147              : !> \param fm_matrix_PQ ...
     148              : !> \param fm_matrix_L_kpoints ...
     149              : !> \param fm_matrix_Minv_L_kpoints ...
     150              : !> \param fm_matrix_Minv ...
     151              : !> \param fm_matrix_Minv_Vtrunc_Minv ...
     152              : !> \param kpoints ...
     153              : !> \param Eigenval ...
     154              : !> \param nmo ...
     155              : !> \param homo ...
     156              : !> \param dimen_RI ...
     157              : !> \param dimen_RI_red ...
     158              : !> \param gw_corr_lev_occ ...
     159              : !> \param gw_corr_lev_virt ...
     160              : !> \param bse_lev_virt ...
     161              : !> \param unit_nr ...
     162              : !> \param do_ri_sos_laplace_mp2 ...
     163              : !> \param my_do_gw ...
     164              : !> \param do_im_time ...
     165              : !> \param do_bse ...
     166              : !> \param matrix_s ...
     167              : !> \param mat_munu ...
     168              : !> \param mat_P_global ...
     169              : !> \param t_3c_M ...
     170              : !> \param t_3c_O ...
     171              : !> \param t_3c_O_compressed ...
     172              : !> \param t_3c_O_ind ...
     173              : !> \param starts_array_mc ...
     174              : !> \param ends_array_mc ...
     175              : !> \param starts_array_mc_block ...
     176              : !> \param ends_array_mc_block ...
     177              : !> \param calc_forces ...
     178              : ! **************************************************************************************************
     179          314 :    SUBROUTINE rpa_ri_compute_en(qs_env, Erpa, mp2_env, BIb_C, BIb_C_gw, BIb_C_bse_ij, BIb_C_bse_ab, &
     180              :                                 para_env, para_env_sub, color_sub, &
     181          942 :                                 gd_array, gd_B_virtual, gd_B_all, gd_B_occ_bse, gd_B_virt_bse, &
     182          314 :                                 mo_coeff, fm_matrix_PQ, fm_matrix_L_kpoints, fm_matrix_Minv_L_kpoints, &
     183              :                                 fm_matrix_Minv, fm_matrix_Minv_Vtrunc_Minv, kpoints, &
     184          628 :                                 Eigenval, nmo, homo, dimen_RI, dimen_RI_red, gw_corr_lev_occ, gw_corr_lev_virt, &
     185          314 :                                 bse_lev_virt, &
     186              :                                 unit_nr, do_ri_sos_laplace_mp2, my_do_gw, do_im_time, do_bse, matrix_s, &
     187              :                                 mat_munu, mat_P_global, t_3c_M, t_3c_O, t_3c_O_compressed, t_3c_O_ind, &
     188              :                                 starts_array_mc, ends_array_mc, &
     189              :                                 starts_array_mc_block, ends_array_mc_block, calc_forces)
     190              : 
     191              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     192              :       REAL(KIND=dp), INTENT(OUT)                         :: Erpa
     193              :       TYPE(mp2_type), INTENT(INOUT)                      :: mp2_env
     194              :       TYPE(three_dim_real_array), DIMENSION(:), &
     195              :          INTENT(INOUT)                                   :: BIb_C, BIb_C_gw, BIb_C_bse_ij, &
     196              :                                                             BIb_C_bse_ab
     197              :       TYPE(mp_para_env_type), POINTER                    :: para_env, para_env_sub
     198              :       INTEGER, INTENT(INOUT)                             :: color_sub
     199              :       TYPE(group_dist_d1_type), INTENT(INOUT)            :: gd_array
     200              :       TYPE(group_dist_d1_type), DIMENSION(:), &
     201              :          INTENT(INOUT)                                   :: gd_B_virtual
     202              :       TYPE(group_dist_d1_type), INTENT(INOUT)            :: gd_B_all
     203              :       TYPE(group_dist_d1_type), DIMENSION(:), &
     204              :          INTENT(INOUT)                                   :: gd_B_occ_bse, gd_B_virt_bse
     205              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: mo_coeff
     206              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_matrix_PQ
     207              :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: fm_matrix_L_kpoints, &
     208              :                                                             fm_matrix_Minv_L_kpoints, &
     209              :                                                             fm_matrix_Minv, &
     210              :                                                             fm_matrix_Minv_Vtrunc_Minv
     211              :       TYPE(kpoint_type), POINTER                         :: kpoints
     212              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :), &
     213              :          INTENT(INOUT)                                   :: Eigenval
     214              :       INTEGER, INTENT(IN)                                :: nmo
     215              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: homo
     216              :       INTEGER, INTENT(IN)                                :: dimen_RI, dimen_RI_red
     217              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: gw_corr_lev_occ, gw_corr_lev_virt, &
     218              :                                                             bse_lev_virt
     219              :       INTEGER, INTENT(IN)                                :: unit_nr
     220              :       LOGICAL, INTENT(IN)                                :: do_ri_sos_laplace_mp2, my_do_gw, &
     221              :                                                             do_im_time, do_bse
     222              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
     223              :       TYPE(dbcsr_p_type), INTENT(IN)                     :: mat_munu
     224              :       TYPE(dbcsr_p_type), INTENT(INOUT)                  :: mat_P_global
     225              :       TYPE(dbt_type)                                     :: t_3c_M
     226              :       TYPE(dbt_type), ALLOCATABLE, DIMENSION(:, :)       :: t_3c_O
     227              :       TYPE(hfx_compression_type), ALLOCATABLE, &
     228              :          DIMENSION(:, :, :), INTENT(INOUT)               :: t_3c_O_compressed
     229              :       TYPE(block_ind_type), ALLOCATABLE, &
     230              :          DIMENSION(:, :, :), INTENT(INOUT)               :: t_3c_O_ind
     231              :       INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(IN)     :: starts_array_mc, ends_array_mc, &
     232              :                                                             starts_array_mc_block, &
     233              :                                                             ends_array_mc_block
     234              :       LOGICAL, INTENT(IN)                                :: calc_forces
     235              : 
     236              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'rpa_ri_compute_en'
     237              : 
     238              :       INTEGER :: best_integ_group_size, best_num_integ_point, color_rpa_group, dimen_nm_gw, &
     239              :          dimen_virt_square, handle, handle2, handle3, ierr, iiB, input_num_integ_groups, &
     240              :          integ_group_size, ispin, jjB, min_integ_group_size, my_group_L_end, my_group_L_size, &
     241              :          my_group_L_start, my_nm_gw_end, my_nm_gw_size, my_nm_gw_start, ncol_block_mat, ngroup, &
     242              :          nrow_block_mat, nspins, num_integ_group, num_integ_points, pos_integ_group
     243              :       INTEGER(KIND=int_8)                                :: mem
     244          628 :       INTEGER, ALLOCATABLE, DIMENSION(:) :: dimen_homo_square, dimen_ia, my_ab_comb_bse_end, &
     245          314 :          my_ab_comb_bse_size, my_ab_comb_bse_start, my_ia_end, my_ia_size, my_ia_start, &
     246          314 :          my_ij_comb_bse_end, my_ij_comb_bse_size, my_ij_comb_bse_start, virtual
     247              :       LOGICAL                                            :: do_kpoints_from_Gamma, do_minimax_quad, &
     248              :                                                             my_open_shell, skip_integ_group_opt
     249              :       REAL(KIND=dp) :: allowed_memory, avail_mem, E_Range, Emax, Emin, mem_for_iaK, mem_for_QK, &
     250              :          mem_min, mem_per_group, mem_per_rank, mem_per_repl, mem_real
     251          314 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: Eigenval_kp
     252          628 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_mat_Q, fm_mat_Q_gemm, fm_mat_S, &
     253          314 :                                                             fm_mat_S_ab_bse, fm_mat_S_gw, &
     254          314 :                                                             fm_mat_S_ij_bse
     255          628 :       TYPE(cp_fm_type), DIMENSION(1)                     :: fm_mat_R_gw
     256              :       TYPE(mp_para_env_type), POINTER                    :: para_env_RPA
     257              :       TYPE(two_dim_real_array), ALLOCATABLE, &
     258          314 :          DIMENSION(:)                                    :: BIb_C_2D, BIb_C_2D_bse_ab, &
     259          314 :                                                             BIb_C_2D_bse_ij, BIb_C_2D_gw
     260              : 
     261          314 :       CALL timeset(routineN, handle)
     262              : 
     263          314 :       CALL cite_reference(DelBen2013)
     264          314 :       CALL cite_reference(DelBen2015)
     265              : 
     266          314 :       IF (mp2_env%ri_rpa%exchange_correction == rpa_exchange_axk) THEN
     267           10 :          CALL cite_reference(Bates2013)
     268          304 :       ELSE IF (mp2_env%ri_rpa%exchange_correction == rpa_exchange_sosex) THEN
     269            2 :          CALL cite_reference(Freeman1977)
     270            2 :          CALL cite_reference(Gruneis2009)
     271              :       END IF
     272          314 :       IF (mp2_env%ri_rpa%do_rse) THEN
     273            6 :          CALL cite_reference(Ren2011)
     274            6 :          CALL cite_reference(Ren2013)
     275              :       END IF
     276              : 
     277          314 :       IF (my_do_gw) THEN
     278          116 :          CALL cite_reference(Wilhelm2016a)
     279          116 :          CALL cite_reference(Wilhelm2017)
     280          116 :          CALL cite_reference(Wilhelm2018)
     281              :       END IF
     282              : 
     283          314 :       IF (do_im_time) THEN
     284          136 :          CALL cite_reference(Wilhelm2016b)
     285              :       END IF
     286              : 
     287          314 :       nspins = SIZE(homo)
     288          314 :       my_open_shell = (nspins == 2)
     289         2198 :       ALLOCATE (virtual(nspins), dimen_ia(nspins), my_ia_end(nspins), my_ia_start(nspins), my_ia_size(nspins))
     290          694 :       virtual(:) = nmo - homo(:)
     291          694 :       dimen_ia(:) = virtual(:)*homo(:)
     292              : 
     293         1256 :       ALLOCATE (Eigenval_kp(nmo, 1, nspins))
     294         9770 :       Eigenval_kp(:, 1, :) = Eigenval(:, :)
     295              : 
     296          314 :       IF (do_im_time) mp2_env%ri_rpa%minimax_quad = .TRUE.
     297          314 :       do_minimax_quad = mp2_env%ri_rpa%minimax_quad
     298              : 
     299          314 :       IF (do_ri_sos_laplace_mp2) THEN
     300           58 :          num_integ_points = mp2_env%ri_laplace%n_quadrature
     301           58 :          input_num_integ_groups = mp2_env%ri_laplace%num_integ_groups
     302              : 
     303              :          ! check the range for the minimax approximation
     304           58 :          E_Range = mp2_env%e_range
     305           58 :          IF (mp2_env%e_range <= 1.0_dp .OR. mp2_env%e_gap <= 0.0_dp) THEN
     306              :             Emin = HUGE(dp)
     307              :             Emax = 0.0_dp
     308           88 :             DO ispin = 1, nspins
     309           88 :                IF (homo(ispin) > 0) THEN
     310           50 :                   Emin = MIN(Emin, 2.0_dp*(Eigenval(homo(ispin) + 1, ispin) - Eigenval(homo(ispin), ispin)))
     311         2640 :                   Emax = MAX(Emax, 2.0_dp*(MAXVAL(Eigenval(:, ispin)) - MINVAL(Eigenval(:, ispin))))
     312              :                END IF
     313              :             END DO
     314           38 :             E_Range = Emax/Emin
     315              :          END IF
     316           58 :          IF (E_Range < 2.0_dp) E_Range = 2.0_dp
     317              :          ierr = 0
     318           58 :          CALL check_exp_minimax_range(num_integ_points, E_Range, ierr)
     319           58 :          IF (ierr /= 0) THEN
     320              :             jjB = num_integ_points - 1
     321            0 :             DO iiB = 1, jjB
     322            0 :                num_integ_points = num_integ_points - 1
     323              :                ierr = 0
     324            0 :                CALL check_exp_minimax_range(num_integ_points, E_Range, ierr)
     325            0 :                IF (ierr == 0) EXIT
     326              :             END DO
     327              :          END IF
     328           58 :          CPASSERT(num_integ_points >= 1)
     329              :       ELSE
     330          256 :          num_integ_points = mp2_env%ri_rpa%rpa_num_quad_points
     331          256 :          input_num_integ_groups = mp2_env%ri_rpa%rpa_num_integ_groups
     332          256 :          IF (my_do_gw .AND. do_minimax_quad) THEN
     333           46 :             IF (num_integ_points > 34) THEN
     334            0 :                IF (unit_nr > 0) THEN
     335              :                   CALL cp_warn(__LOCATION__, &
     336              :                                "The required number of quadrature point exceeds the maximum possible in the "// &
     337            0 :                                "Minimax quadrature scheme. The number of quadrature point has been reset to 30.")
     338              :                END IF
     339            0 :                num_integ_points = 30
     340              :             END IF
     341              :          ELSE
     342          210 :             IF (do_minimax_quad .AND. num_integ_points > 20) THEN
     343            0 :                IF (unit_nr > 0) THEN
     344              :                   CALL cp_warn(__LOCATION__, &
     345              :                                "The required number of quadrature point exceeds the maximum possible in the "// &
     346            0 :                                "Minimax quadrature scheme. The number of quadrature point has been reset to 20.")
     347              :                END IF
     348            0 :                num_integ_points = 20
     349              :             END IF
     350              :          END IF
     351              :       END IF
     352          314 :       allowed_memory = mp2_env%mp2_memory
     353              : 
     354          314 :       CALL get_group_dist(gd_array, color_sub, my_group_L_start, my_group_L_end, my_group_L_size)
     355              : 
     356          314 :       ngroup = para_env%num_pe/para_env_sub%num_pe
     357              : 
     358              :       ! for imaginary time or periodic GW or BSE, we use all processors for a single frequency/time point
     359          314 :       IF (do_im_time .OR. mp2_env%ri_g0w0%do_periodic .OR. do_bse) THEN
     360              : 
     361          180 :          integ_group_size = ngroup
     362          180 :          best_num_integ_point = num_integ_points
     363              : 
     364              :       ELSE
     365              : 
     366              :          ! Calculate available memory and create integral group according to that
     367              :          ! mem_for_iaK is the memory needed for storing the 3 centre integrals
     368          298 :          mem_for_iaK = REAL(SUM(dimen_ia), KIND=dp)*dimen_RI_red*8.0_dp/(1024_dp**2)
     369          134 :          mem_for_QK = REAL(dimen_RI_red, KIND=dp)*nspins*dimen_RI_red*8.0_dp/(1024_dp**2)
     370              : 
     371          134 :          CALL m_memory(mem)
     372          134 :          mem_real = (mem + 1024*1024 - 1)/(1024*1024)
     373          134 :          CALL para_env%min(mem_real)
     374              : 
     375          134 :          mem_per_rank = 0.0_dp
     376              : 
     377              :          ! B_ia_P
     378              :          mem_per_repl = mem_for_iaK
     379              :          ! Q (regular and for dgemm)
     380          134 :          mem_per_repl = mem_per_repl + 2.0_dp*mem_for_QK
     381              : 
     382          134 :          IF (calc_forces) CALL rpa_grad_needed_mem(homo, virtual, dimen_RI_red, mem_per_rank, mem_per_repl, do_ri_sos_laplace_mp2)
     383          134 :          CALL rpa_exchange_needed_mem(mp2_env, homo, virtual, dimen_RI_red, para_env, mem_per_rank, mem_per_repl)
     384              : 
     385          134 :          mem_min = mem_per_repl/para_env%num_pe + mem_per_rank
     386              : 
     387          134 :          IF (unit_nr > 0) THEN
     388           67 :             WRITE (unit_nr, '(T3,A,T68,F9.2,A4)') 'RI_INFO| Minimum required memory per MPI process:', mem_min, ' MiB'
     389           67 :             WRITE (unit_nr, '(T3,A,T68,F9.2,A4)') 'RI_INFO| Available memory per MPI process:', mem_real, ' MiB'
     390              :          END IF
     391              : 
     392              :          ! Use only the allowed amount of memory
     393          134 :          mem_real = MIN(mem_real, allowed_memory)
     394              :          ! For the memory estimate, we require the amount of required memory per replication group and the available memory
     395          134 :          mem_real = mem_real - mem_per_rank
     396              : 
     397          134 :          mem_per_group = mem_real*para_env_sub%num_pe
     398              : 
     399              :          ! here we try to find the best rpa/laplace group size
     400          134 :          skip_integ_group_opt = .FALSE.
     401              : 
     402              :          ! Check the input number of integration groups
     403          134 :          IF (input_num_integ_groups > 0) THEN
     404            2 :             IF (num_integ_points < input_num_integ_groups) THEN
     405            0 :                IF (MOD(ngroup, input_num_integ_groups) == 0) THEN
     406            0 :                   best_integ_group_size = ngroup/input_num_integ_groups
     407            0 :                   best_num_integ_point = (num_integ_points + input_num_integ_groups - 1)/input_num_integ_groups
     408              :                   skip_integ_group_opt = .TRUE.
     409              :                ELSE
     410            0 :                   IF (unit_nr > 0) WRITE (unit_nr, '(T3,A)') 'Total number of groups not multiple of NUM_INTEG_GROUPS'
     411              :                END IF
     412              :             ELSE
     413            2 :                IF (unit_nr > 0) WRITE (unit_nr, '(T3,A)') 'Too many integration groups for the given number of quadrature points'
     414              :             END IF
     415              :          END IF
     416              : 
     417              :          IF (.NOT. skip_integ_group_opt) THEN
     418          134 :             best_integ_group_size = ngroup
     419          134 :             best_num_integ_point = num_integ_points
     420              : 
     421          134 :             min_integ_group_size = MAX(1, ngroup/num_integ_points)
     422              : 
     423          134 :             integ_group_size = min_integ_group_size - 1
     424          134 :             DO iiB = min_integ_group_size + 1, ngroup
     425          112 :                integ_group_size = integ_group_size + 1
     426              : 
     427              :                ! check that the ngroup is a multiple of integ_group_size
     428          112 :                IF (MOD(ngroup, integ_group_size) /= 0) CYCLE
     429              : 
     430              :                ! check for memory
     431          112 :                avail_mem = integ_group_size*mem_per_group
     432          112 :                IF (avail_mem < mem_per_repl) CYCLE
     433              : 
     434              :                ! check that the integration groups have the same size
     435          112 :                num_integ_group = ngroup/integ_group_size
     436              : 
     437          112 :                best_num_integ_point = (num_integ_points + num_integ_group - 1)/num_integ_group
     438          112 :                best_integ_group_size = integ_group_size
     439              : 
     440          134 :                EXIT
     441              : 
     442              :             END DO
     443              :          END IF
     444              : 
     445          134 :          integ_group_size = best_integ_group_size
     446              : 
     447              :       END IF
     448              : 
     449          314 :       IF (unit_nr > 0 .AND. .NOT. do_im_time) THEN
     450           89 :          IF (do_ri_sos_laplace_mp2) THEN
     451              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T75,i6)") &
     452           14 :                "RI_INFO| Group size for laplace numerical integration:", integ_group_size*para_env_sub%num_pe
     453              :             WRITE (UNIT=unit_nr, FMT="(T3,A)") &
     454           14 :                "INTEG_INFO| MINIMAX approximation"
     455              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T75,i6)") &
     456           14 :                "INTEG_INFO| Number of integration points:", num_integ_points
     457              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T75,i6)") &
     458           14 :                "INTEG_INFO| Max. number of integration points per Laplace group:", best_num_integ_point
     459              :          ELSE
     460              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T75,i6)") &
     461           75 :                "RI_INFO| Group size for frequency integration:", integ_group_size*para_env_sub%num_pe
     462           75 :             IF (do_minimax_quad) THEN
     463              :                WRITE (UNIT=unit_nr, FMT="(T3,A)") &
     464           21 :                   "INTEG_INFO| MINIMAX quadrature"
     465              :             ELSE
     466              :                WRITE (UNIT=unit_nr, FMT="(T3,A)") &
     467           54 :                   "INTEG_INFO| Clenshaw-Curtius quadrature"
     468              :             END IF
     469              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T75,i6)") &
     470           75 :                "INTEG_INFO| Number of integration points:", num_integ_points
     471              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T75,i6)") &
     472           75 :                "INTEG_INFO| Max. number of integration points per RPA group:", best_num_integ_point
     473              :          END IF
     474           89 :          CALL m_flush(unit_nr)
     475              :       END IF
     476              : 
     477          314 :       num_integ_group = ngroup/integ_group_size
     478              : 
     479          314 :       pos_integ_group = MOD(color_sub, integ_group_size)
     480          314 :       color_rpa_group = color_sub/integ_group_size
     481              : 
     482          314 :       CALL timeset(routineN//"_reorder", handle2)
     483              : 
     484              :       ! not necessary for imaginary time
     485              : 
     486         1322 :       ALLOCATE (BIb_C_2D(nspins))
     487              : 
     488          314 :       IF (.NOT. do_im_time) THEN
     489              : 
     490              :          ! reorder the local data in such a way to help the next stage of matrix creation
     491              :          ! now the data inside the group are divided into a ia x K matrix
     492          394 :          DO ispin = 1, nspins
     493              :             CALL calculate_BIb_C_2D(BIb_C_2D(ispin)%array, BIb_C(ispin)%array, para_env_sub, dimen_ia(ispin), &
     494              :                                     homo(ispin), virtual(ispin), gd_B_virtual(ispin), &
     495          216 :                                     my_ia_size(ispin), my_ia_start(ispin), my_ia_end(ispin), my_group_L_size)
     496              : 
     497          216 :             DEALLOCATE (BIb_C(ispin)%array)
     498          394 :             CALL release_group_dist(gd_B_virtual(ispin))
     499              : 
     500              :          END DO
     501              : 
     502              :          ! in the GW case, BIb_C_2D_gw is an nm x K matrix, with n: number of corr GW levels, m=nmo
     503          178 :          IF (my_do_gw) THEN
     504          222 :             ALLOCATE (BIb_C_2D_gw(nspins))
     505              : 
     506           70 :             CALL timeset(routineN//"_reorder_gw", handle3)
     507              : 
     508           70 :             dimen_nm_gw = nmo*(gw_corr_lev_occ(1) + gw_corr_lev_virt(1))
     509              : 
     510              :             ! The same for open shell
     511          152 :             DO ispin = 1, nspins
     512              :                CALL calculate_BIb_C_2D(BIb_C_2D_gw(ispin)%array, BIb_C_gw(ispin)%array, para_env_sub, dimen_nm_gw, &
     513              :                                        gw_corr_lev_occ(ispin) + gw_corr_lev_virt(ispin), nmo, gd_B_all, &
     514           82 :                                        my_nm_gw_size, my_nm_gw_start, my_nm_gw_end, my_group_L_size)
     515          152 :                DEALLOCATE (BIb_C_gw(ispin)%array)
     516              :             END DO
     517              : 
     518           70 :             CALL release_group_dist(gd_B_all)
     519              : 
     520          140 :             CALL timestop(handle3)
     521              : 
     522              :          END IF
     523              :       END IF
     524              : 
     525          314 :       IF (do_bse) THEN
     526              : 
     527           42 :          CALL timeset(routineN//"_reorder_bse1", handle3)
     528              : 
     529          226 :          ALLOCATE (BIb_C_2D_bse_ij(nspins), BIb_C_2D_bse_ab(nspins))
     530           84 :          ALLOCATE (dimen_homo_square(nspins))
     531          168 :          ALLOCATE (my_ij_comb_bse_size(nspins), my_ij_comb_bse_start(nspins), my_ij_comb_bse_end(nspins))
     532          168 :          ALLOCATE (my_ab_comb_bse_size(nspins), my_ab_comb_bse_start(nspins), my_ab_comb_bse_end(nspins))
     533              : 
     534              :          ! We do not implement an explicit bse_lev_occ different to homo here, because the small number of occupied levels
     535              :          ! does not critically influence the memory
     536           92 :          DO ispin = 1, nspins
     537           50 :             dimen_homo_square(ispin) = homo(ispin)**2
     538              :             CALL calculate_BIb_C_2D(BIb_C_2D_bse_ij(ispin)%array, BIb_C_bse_ij(ispin)%array, para_env_sub, &
     539              :                                     dimen_homo_square(ispin), homo(ispin), homo(ispin), gd_B_occ_bse(ispin), &
     540              :                                     my_ij_comb_bse_size(ispin), my_ij_comb_bse_start(ispin), &
     541           50 :                                     my_ij_comb_bse_end(ispin), my_group_L_size)
     542           50 :             DEALLOCATE (BIb_C_bse_ij(ispin)%array)
     543           92 :             CALL release_group_dist(gd_B_occ_bse(ispin))
     544              :          END DO
     545              : 
     546           42 :          CALL timestop(handle3)
     547              : 
     548           42 :          CALL timeset(routineN//"_reorder_bse2", handle3)
     549              : 
     550              :          ! bse_lev_virt(ispin) (hence dimen_virt_square) and gd_B_virt_bse(ispin) are per-spin
     551           92 :          DO ispin = 1, nspins
     552           50 :             dimen_virt_square = bse_lev_virt(ispin)**2
     553              :             CALL calculate_BIb_C_2D(BIb_C_2D_bse_ab(ispin)%array, BIb_C_bse_ab(ispin)%array, para_env_sub, &
     554              :                                     dimen_virt_square, bse_lev_virt(ispin), bse_lev_virt(ispin), gd_B_virt_bse(ispin), &
     555              :                                     my_ab_comb_bse_size(ispin), my_ab_comb_bse_start(ispin), &
     556           50 :                                     my_ab_comb_bse_end(ispin), my_group_L_size)
     557           50 :             DEALLOCATE (BIb_C_bse_ab(ispin)%array)
     558           92 :             CALL release_group_dist(gd_B_virt_bse(ispin))
     559              :          END DO
     560              : 
     561          126 :          CALL timestop(handle3)
     562              : 
     563              :       END IF
     564              : 
     565          314 :       CALL timestop(handle2)
     566              : 
     567          314 :       IF (num_integ_group > 1) THEN
     568          112 :          ALLOCATE (para_env_RPA)
     569          112 :          CALL para_env_RPA%from_split(para_env, color_rpa_group)
     570              :       ELSE
     571          202 :          para_env_RPA => para_env
     572              :       END IF
     573              : 
     574              :       ! now create the matrices needed for the calculation, Q, S and G
     575              :       ! Q and G will have omega dependence
     576              : 
     577          314 :       IF (do_im_time) THEN
     578          844 :          ALLOCATE (fm_mat_Q(nspins), fm_mat_Q_gemm(1), fm_mat_S(1))
     579              :       ELSE
     580         1538 :          ALLOCATE (fm_mat_Q(nspins), fm_mat_Q_gemm(nspins), fm_mat_S(nspins))
     581              :       END IF
     582              : 
     583              :       CALL create_integ_mat(BIb_C_2D, para_env, para_env_sub, color_sub, ngroup, integ_group_size, &
     584              :                             dimen_RI_red, dimen_ia, color_rpa_group, &
     585              :                             mp2_env%block_size_row, mp2_env%block_size_col, unit_nr, &
     586              :                             my_ia_size, my_ia_start, my_ia_end, &
     587              :                             my_group_L_size, my_group_L_start, my_group_L_end, &
     588              :                             para_env_RPA, fm_mat_S, nrow_block_mat, ncol_block_mat, &
     589              :                             dimen_ia_for_block_size=dimen_ia(1), &
     590          314 :                             do_im_time=do_im_time, fm_mat_Q_gemm=fm_mat_Q_gemm, fm_mat_Q=fm_mat_Q, qs_env=qs_env)
     591              : 
     592          694 :       DEALLOCATE (BIb_C_2D, my_ia_end, my_ia_size, my_ia_start)
     593              : 
     594              :       ! for GW, we need other matrix fm_mat_S, always allocate the container to prevent crying compilers
     595         1322 :       ALLOCATE (fm_mat_S_gw(nspins))
     596          314 :       IF (my_do_gw .AND. .NOT. do_im_time) THEN
     597              : 
     598              :          CALL create_integ_mat(BIb_C_2D_gw, para_env, para_env_sub, color_sub, ngroup, integ_group_size, &
     599              :                                dimen_RI_red, [dimen_nm_gw, dimen_nm_gw], color_rpa_group, &
     600              :                                mp2_env%block_size_row, mp2_env%block_size_col, unit_nr, &
     601              :                                [my_nm_gw_size, my_nm_gw_size], [my_nm_gw_start, my_nm_gw_start], [my_nm_gw_end, my_nm_gw_end], &
     602              :                                my_group_L_size, my_group_L_start, my_group_L_end, &
     603              :                                para_env_RPA, fm_mat_S_gw, nrow_block_mat, ncol_block_mat, &
     604              :                                fm_mat_Q(1)%matrix_struct%context, fm_mat_Q(1)%matrix_struct%context, &
     605          630 :                                fm_mat_Q=fm_mat_R_gw)
     606          152 :          DEALLOCATE (BIb_C_2D_gw)
     607              : 
     608              :       END IF
     609              : 
     610              :       ! for Bethe-Salpeter, we need other matrix fm_mat_S (per spin; the ab slab dimension is spin-independent)
     611          314 :       IF (do_bse) THEN
     612          226 :          ALLOCATE (fm_mat_S_ij_bse(nspins), fm_mat_S_ab_bse(nspins))
     613              :          CALL create_integ_mat(BIb_C_2D_bse_ij, para_env, para_env_sub, color_sub, ngroup, integ_group_size, &
     614              :                                dimen_RI_red, dimen_homo_square, color_rpa_group, &
     615              :                                mp2_env%block_size_row, mp2_env%block_size_col, unit_nr, &
     616              :                                my_ij_comb_bse_size, my_ij_comb_bse_start, my_ij_comb_bse_end, &
     617              :                                my_group_L_size, my_group_L_start, my_group_L_end, &
     618              :                                para_env_RPA, fm_mat_S_ij_bse, nrow_block_mat, ncol_block_mat, &
     619           42 :                                fm_mat_Q(1)%matrix_struct%context, fm_mat_Q(1)%matrix_struct%context)
     620              : 
     621              :          CALL create_integ_mat(BIb_C_2D_bse_ab, para_env, para_env_sub, color_sub, ngroup, integ_group_size, &
     622              :                                dimen_RI_red, [(bse_lev_virt(ispin)**2, ispin=1, nspins)], color_rpa_group, &
     623              :                                mp2_env%block_size_row, mp2_env%block_size_col, unit_nr, &
     624              :                                my_ab_comb_bse_size, my_ab_comb_bse_start, my_ab_comb_bse_end, &
     625              :                                my_group_L_size, my_group_L_start, my_group_L_end, &
     626              :                                para_env_RPA, fm_mat_S_ab_bse, nrow_block_mat, ncol_block_mat, &
     627          184 :                                fm_mat_Q(1)%matrix_struct%context, fm_mat_Q(1)%matrix_struct%context)
     628              : 
     629              :       END IF
     630              : 
     631          314 :       do_kpoints_from_Gamma = qs_env%mp2_env%ri_rpa_im_time%do_kpoints_from_Gamma
     632          314 :       IF (do_kpoints_from_Gamma) THEN
     633           16 :          CALL get_bandstruc_and_k_dependent_MOs(qs_env, Eigenval_kp)
     634              :       END IF
     635              : 
     636              :       ! Now start the RPA calculation
     637              :       ! fm_mo_coeff_occ, fm_mo_coeff_virt will be deallocated here
     638              :       CALL rpa_num_int(qs_env, Erpa, mp2_env, para_env, para_env_RPA, para_env_sub, unit_nr, &
     639              :                        homo, virtual, dimen_RI, dimen_RI_red, dimen_ia, dimen_nm_gw, &
     640              :                        Eigenval_kp, num_integ_points, num_integ_group, color_rpa_group, &
     641              :                        fm_matrix_PQ, fm_mat_S, fm_mat_Q_gemm, fm_mat_Q, fm_mat_S_gw, fm_mat_R_gw(1), &
     642              :                        fm_mat_S_ij_bse, fm_mat_S_ab_bse, &
     643              :                        my_do_gw, do_bse, gw_corr_lev_occ, gw_corr_lev_virt, &
     644              :                        bse_lev_virt, &
     645              :                        do_minimax_quad, &
     646              :                        do_im_time, mo_coeff, &
     647              :                        fm_matrix_L_kpoints, fm_matrix_Minv_L_kpoints, &
     648              :                        fm_matrix_Minv, fm_matrix_Minv_Vtrunc_Minv, mat_munu, mat_P_global, &
     649              :                        t_3c_M, t_3c_O, t_3c_O_compressed, t_3c_O_ind, &
     650              :                        starts_array_mc, ends_array_mc, &
     651              :                        starts_array_mc_block, ends_array_mc_block, &
     652              :                        matrix_s, do_kpoints_from_Gamma, kpoints, gd_array, color_sub, &
     653          314 :                        do_ri_sos_laplace_mp2=do_ri_sos_laplace_mp2, calc_forces=calc_forces)
     654              : 
     655          314 :       CALL release_group_dist(gd_array)
     656              : 
     657          314 :       IF (num_integ_group > 1) CALL mp_para_env_release(para_env_RPA)
     658              : 
     659          314 :       IF (.NOT. do_im_time) THEN
     660          178 :          CALL cp_fm_release(fm_mat_Q_gemm)
     661          178 :          CALL cp_fm_release(fm_mat_S)
     662              :       END IF
     663          314 :       CALL cp_fm_release(fm_mat_Q)
     664              : 
     665          314 :       IF (my_do_gw .AND. .NOT. do_im_time) THEN
     666           70 :          CALL cp_fm_release(fm_mat_S_gw)
     667           70 :          CALL cp_fm_release(fm_mat_R_gw(1))
     668              :       END IF
     669              : 
     670          314 :       IF (do_bse) THEN
     671           92 :          DO ispin = 1, nspins
     672           50 :             CALL cp_fm_release(fm_mat_S_ij_bse(ispin))
     673           92 :             CALL cp_fm_release(fm_mat_S_ab_bse(ispin))
     674              :          END DO
     675           42 :          DEALLOCATE (fm_mat_S_ij_bse, fm_mat_S_ab_bse)
     676              :       END IF
     677              : 
     678          314 :       CALL timestop(handle)
     679              : 
     680         1356 :    END SUBROUTINE rpa_ri_compute_en
     681              : 
     682              : ! **************************************************************************************************
     683              : !> \brief reorder the local data in such a way to help the next stage of matrix creation;
     684              : !>        now the data inside the group are divided into a ia x K matrix (BIb_C_2D);
     685              : !>        Subroutine created to avoid massive double coding
     686              : !> \param BIb_C_2D ...
     687              : !> \param BIb_C ...
     688              : !> \param para_env_sub ...
     689              : !> \param dimen_ia ...
     690              : !> \param homo ...
     691              : !> \param virtual ...
     692              : !> \param gd_B_virtual ...
     693              : !> \param my_ia_size ...
     694              : !> \param my_ia_start ...
     695              : !> \param my_ia_end ...
     696              : !> \param my_group_L_size ...
     697              : !> \author Jan Wilhelm, 03/2015
     698              : ! **************************************************************************************************
     699          398 :    SUBROUTINE calculate_BIb_C_2D(BIb_C_2D, BIb_C, para_env_sub, dimen_ia, homo, virtual, &
     700              :                                  gd_B_virtual, &
     701              :                                  my_ia_size, my_ia_start, my_ia_end, my_group_L_size)
     702              : 
     703              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :), &
     704              :          INTENT(OUT)                                     :: BIb_C_2D
     705              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
     706              :          INTENT(IN)                                      :: BIb_C
     707              :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env_sub
     708              :       INTEGER, INTENT(IN)                                :: dimen_ia, homo, virtual
     709              :       TYPE(group_dist_d1_type), INTENT(INOUT)            :: gd_B_virtual
     710              :       INTEGER                                            :: my_ia_size, my_ia_start, my_ia_end, &
     711              :                                                             my_group_L_size
     712              : 
     713              :       INTEGER, PARAMETER                                 :: occ_chunk = 128
     714              : 
     715              :       INTEGER :: ia_global, iiB, itmp(2), jjB, my_B_size, my_B_virtual_start, occ_high, occ_low, &
     716              :          proc_receive, proc_send, proc_shift, rec_B_size, rec_B_virtual_end, rec_B_virtual_start
     717          398 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), TARGET   :: BIb_C_rec_1D
     718          398 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: BIb_C_rec
     719              : 
     720          398 :       itmp = get_limit(dimen_ia, para_env_sub%num_pe, para_env_sub%mepos)
     721          398 :       my_ia_start = itmp(1)
     722          398 :       my_ia_end = itmp(2)
     723          398 :       my_ia_size = my_ia_end - my_ia_start + 1
     724              : 
     725          398 :       CALL get_group_dist(gd_B_virtual, para_env_sub%mepos, sizes=my_B_size, starts=my_B_virtual_start)
     726              : 
     727              :       ! reorder data
     728         1586 :       ALLOCATE (BIb_C_2D(my_group_L_size, my_ia_size))
     729              : 
     730              : !$OMP     PARALLEL DO DEFAULT(NONE) PRIVATE(jjB,ia_global) &
     731              : !$OMP              SHARED(homo,my_B_size,virtual,my_B_virtual_start,my_ia_start,my_ia_end,BIb_C,BIb_C_2D,&
     732          398 : !$OMP              my_group_L_size)
     733              :       DO iiB = 1, homo
     734              :          DO jjB = 1, my_B_size
     735              :             ia_global = (iiB - 1)*virtual + my_B_virtual_start + jjB - 1
     736              :             IF (ia_global >= my_ia_start .AND. ia_global <= my_ia_end) THEN
     737              :                BIb_C_2D(1:my_group_L_size, ia_global - my_ia_start + 1) = BIb_C(1:my_group_L_size, jjB, iiB)
     738              :             END IF
     739              :          END DO
     740              :       END DO
     741              : 
     742          398 :       IF (para_env_sub%num_pe > 1) THEN
     743           30 :          ALLOCATE (BIb_C_rec_1D(INT(my_group_L_size, int_8)*maxsize(gd_B_virtual)*MIN(homo, occ_chunk)))
     744           20 :          DO proc_shift = 1, para_env_sub%num_pe - 1
     745           10 :             proc_send = MODULO(para_env_sub%mepos + proc_shift, para_env_sub%num_pe)
     746           10 :             proc_receive = MODULO(para_env_sub%mepos - proc_shift, para_env_sub%num_pe)
     747              : 
     748           10 :             CALL get_group_dist(gd_B_virtual, proc_receive, rec_B_virtual_start, rec_B_virtual_end, rec_B_size)
     749              : 
     750              :             ! do this in chunks to avoid high memory overhead
     751           20 :             DO occ_low = 1, homo, occ_chunk
     752           10 :                occ_high = MIN(homo, occ_low + occ_chunk - 1)
     753              :                BIb_C_rec(1:my_group_L_size, 1:rec_B_size, 1:occ_high - occ_low + 1) => &
     754           10 :                   BIb_C_rec_1D(1:INT(my_group_L_size, int_8)*rec_B_size*(occ_high - occ_low + 1))
     755              :                CALL para_env_sub%sendrecv(BIb_C(:, :, occ_low:occ_high), proc_send, &
     756        31970 :                                           BIb_C_rec(:, :, 1:occ_high - occ_low + 1), proc_receive)
     757              : !$OMP          PARALLEL DO DEFAULT(NONE) PRIVATE(jjB,ia_global) &
     758              : !$OMP                   SHARED(occ_low,occ_high,rec_B_size,virtual,rec_B_virtual_start,my_ia_start,my_ia_end,BIb_C_rec,BIb_C_2D,&
     759           10 : !$OMP                          my_group_L_size)
     760              :                DO iiB = occ_low, occ_high
     761              :                   DO jjB = 1, rec_B_size
     762              :                      ia_global = (iiB - 1)*virtual + rec_B_virtual_start + jjB - 1
     763              :                      IF (ia_global >= my_ia_start .AND. ia_global <= my_ia_end) THEN
     764              :                      BIb_C_2D(1:my_group_L_size, ia_global - my_ia_start + 1) = BIb_C_rec(1:my_group_L_size, jjB, iiB - occ_low + 1)
     765              :                      END IF
     766              :                   END DO
     767              :                END DO
     768              :             END DO
     769              : 
     770              :          END DO
     771           10 :          DEALLOCATE (BIb_C_rec_1D)
     772              :       END IF
     773              : 
     774          398 :    END SUBROUTINE calculate_BIb_C_2D
     775              : 
     776              : ! **************************************************************************************************
     777              : !> \brief ...
     778              : !> \param BIb_C_2D ...
     779              : !> \param para_env ...
     780              : !> \param para_env_sub ...
     781              : !> \param color_sub ...
     782              : !> \param ngroup ...
     783              : !> \param integ_group_size ...
     784              : !> \param dimen_RI ...
     785              : !> \param dimen_ia ...
     786              : !> \param color_rpa_group ...
     787              : !> \param ext_row_block_size ...
     788              : !> \param ext_col_block_size ...
     789              : !> \param unit_nr ...
     790              : !> \param my_ia_size ...
     791              : !> \param my_ia_start ...
     792              : !> \param my_ia_end ...
     793              : !> \param my_group_L_size ...
     794              : !> \param my_group_L_start ...
     795              : !> \param my_group_L_end ...
     796              : !> \param para_env_RPA ...
     797              : !> \param fm_mat_S ...
     798              : !> \param nrow_block_mat ...
     799              : !> \param ncol_block_mat ...
     800              : !> \param blacs_env_ext ...
     801              : !> \param blacs_env_ext_S ...
     802              : !> \param dimen_ia_for_block_size ...
     803              : !> \param do_im_time ...
     804              : !> \param fm_mat_Q_gemm ...
     805              : !> \param fm_mat_Q ...
     806              : !> \param qs_env ...
     807              : ! **************************************************************************************************
     808          468 :    SUBROUTINE create_integ_mat(BIb_C_2D, para_env, para_env_sub, color_sub, ngroup, integ_group_size, &
     809          468 :                                dimen_RI, dimen_ia, color_rpa_group, &
     810              :                                ext_row_block_size, ext_col_block_size, unit_nr, &
     811          468 :                                my_ia_size, my_ia_start, my_ia_end, &
     812              :                                my_group_L_size, my_group_L_start, my_group_L_end, &
     813          468 :                                para_env_RPA, fm_mat_S, nrow_block_mat, ncol_block_mat, &
     814              :                                blacs_env_ext, blacs_env_ext_S, dimen_ia_for_block_size, &
     815          468 :                                do_im_time, fm_mat_Q_gemm, fm_mat_Q, qs_env)
     816              : 
     817              :       TYPE(two_dim_real_array), DIMENSION(:), &
     818              :          INTENT(INOUT)                                   :: BIb_C_2D
     819              :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env, para_env_sub
     820              :       INTEGER, INTENT(IN)                                :: color_sub, ngroup, integ_group_size, &
     821              :                                                             dimen_RI
     822              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: dimen_ia
     823              :       INTEGER, INTENT(IN)                                :: color_rpa_group, ext_row_block_size, &
     824              :                                                             ext_col_block_size, unit_nr
     825              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: my_ia_size, my_ia_start, my_ia_end
     826              :       INTEGER, INTENT(IN)                                :: my_group_L_size, my_group_L_start, &
     827              :                                                             my_group_L_end
     828              :       TYPE(mp_para_env_type), INTENT(IN), POINTER        :: para_env_RPA
     829              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT)      :: fm_mat_S
     830              :       INTEGER, INTENT(INOUT)                             :: nrow_block_mat, ncol_block_mat
     831              :       TYPE(cp_blacs_env_type), OPTIONAL, POINTER         :: blacs_env_ext, blacs_env_ext_S
     832              :       INTEGER, INTENT(IN), OPTIONAL                      :: dimen_ia_for_block_size
     833              :       LOGICAL, INTENT(IN), OPTIONAL                      :: do_im_time
     834              :       TYPE(cp_fm_type), DIMENSION(:), OPTIONAL           :: fm_mat_Q_gemm, fm_mat_Q
     835              :       TYPE(qs_environment_type), INTENT(IN), OPTIONAL, &
     836              :          POINTER                                         :: qs_env
     837              : 
     838              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'create_integ_mat'
     839              : 
     840              :       INTEGER                                            :: col_row_proc_ratio, grid_2D(2), handle, &
     841              :                                                             iproc, iproc_col, iproc_row, ispin, &
     842              :                                                             mepos_in_RPA_group
     843          468 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: group_grid_2_mepos
     844              :       LOGICAL                                            :: my_blacs_ext, my_blacs_S_ext, &
     845              :                                                             my_do_im_time
     846              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env, blacs_env_Q
     847              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
     848          468 :       TYPE(group_dist_d1_type)                           :: gd_ia, gd_L
     849              : 
     850          468 :       CALL timeset(routineN, handle)
     851              : 
     852          468 :       CPASSERT(PRESENT(blacs_env_ext) .OR. PRESENT(dimen_ia_for_block_size))
     853              : 
     854          468 :       my_blacs_ext = .FALSE.
     855          468 :       IF (PRESENT(blacs_env_ext)) my_blacs_ext = .TRUE.
     856              : 
     857          468 :       my_blacs_S_ext = .FALSE.
     858          468 :       IF (PRESENT(blacs_env_ext_S)) my_blacs_S_ext = .TRUE.
     859              : 
     860          468 :       my_do_im_time = .FALSE.
     861          468 :       IF (PRESENT(do_im_time)) my_do_im_time = do_im_time
     862              : 
     863          468 :       NULLIFY (blacs_env)
     864              :       ! create the RPA blacs env
     865          468 :       IF (my_blacs_S_ext) THEN
     866          154 :          blacs_env => blacs_env_ext_S
     867              :       ELSE
     868          314 :          IF (para_env_RPA%num_pe > 1) THEN
     869          202 :             col_row_proc_ratio = MAX(1, dimen_ia_for_block_size/dimen_RI)
     870              : 
     871          202 :             iproc_col = MIN(MAX(INT(SQRT(REAL(para_env_RPA%num_pe*col_row_proc_ratio, KIND=dp))), 1), para_env_RPA%num_pe) + 1
     872          202 :             DO iproc = 1, para_env_RPA%num_pe
     873          202 :                iproc_col = iproc_col - 1
     874          202 :                IF (MOD(para_env_RPA%num_pe, iproc_col) == 0) EXIT
     875              :             END DO
     876              : 
     877          202 :             iproc_row = para_env_RPA%num_pe/iproc_col
     878          202 :             grid_2D(1) = iproc_row
     879          202 :             grid_2D(2) = iproc_col
     880              :          ELSE
     881          336 :             grid_2D = 1
     882              :          END IF
     883          314 :          CALL cp_blacs_env_create(blacs_env=blacs_env, para_env=para_env_RPA, grid_2d=grid_2D)
     884              : 
     885          314 :          IF (unit_nr > 0 .AND. .NOT. my_do_im_time) THEN
     886              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T75,i6)") &
     887           89 :                "MATRIX_INFO| Number row processes:", grid_2D(1)
     888              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T75,i6)") &
     889           89 :                "MATRIX_INFO| Number column processes:", grid_2D(2)
     890              :          END IF
     891              : 
     892              :          ! define the block_size for the row
     893          314 :          IF (ext_row_block_size > 0) THEN
     894            0 :             nrow_block_mat = ext_row_block_size
     895              :          ELSE
     896          314 :             nrow_block_mat = MAX(1, dimen_RI/grid_2D(1)/2)
     897              :          END IF
     898              : 
     899              :          ! define the block_size for the column
     900          314 :          IF (ext_col_block_size > 0) THEN
     901            0 :             ncol_block_mat = ext_col_block_size
     902              :          ELSE
     903          314 :             ncol_block_mat = MAX(1, dimen_ia_for_block_size/grid_2D(2)/2)
     904              :          END IF
     905              : 
     906          314 :          IF (unit_nr > 0 .AND. .NOT. my_do_im_time) THEN
     907              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T75,i6)") &
     908           89 :                "MATRIX_INFO| Row block size:", nrow_block_mat
     909              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T75,i6)") &
     910           89 :                "MATRIX_INFO| Column block size:", ncol_block_mat
     911              :          END IF
     912              :       END IF
     913              : 
     914          400 :       IF (.NOT. my_do_im_time) THEN
     915          730 :          DO ispin = 1, SIZE(BIb_C_2D)
     916          398 :             NULLIFY (fm_struct)
     917          398 :             IF (my_blacs_ext) THEN
     918              :                CALL cp_fm_struct_create(fm_struct, context=blacs_env, nrow_global=dimen_RI, &
     919          182 :                                         ncol_global=dimen_ia(ispin), para_env=para_env_RPA)
     920              :             ELSE
     921              :                CALL cp_fm_struct_create(fm_struct, context=blacs_env, nrow_global=dimen_RI, &
     922              :                                         ncol_global=dimen_ia(ispin), para_env=para_env_RPA, &
     923          216 :                                         nrow_block=nrow_block_mat, ncol_block=ncol_block_mat, force_block=.TRUE.)
     924              : 
     925              :             END IF ! external blacs_env
     926              : 
     927          398 :             CALL create_group_dist(gd_ia, my_ia_start(ispin), my_ia_end(ispin), my_ia_size(ispin), para_env_RPA)
     928          398 :             CALL create_group_dist(gd_L, my_group_L_start, my_group_L_end, my_group_L_size, para_env_RPA)
     929              : 
     930              :             ! create the info array
     931              : 
     932          398 :             mepos_in_RPA_group = MOD(color_sub, integ_group_size)
     933         1592 :             ALLOCATE (group_grid_2_mepos(0:integ_group_size - 1, 0:para_env_sub%num_pe - 1))
     934          398 :             group_grid_2_mepos = 0
     935          398 :             group_grid_2_mepos(mepos_in_RPA_group, para_env_sub%mepos) = para_env_RPA%mepos
     936          398 :             CALL para_env_RPA%sum(group_grid_2_mepos)
     937              : 
     938              :             CALL array2fm(BIb_C_2D(ispin)%array, fm_struct, my_group_L_start, my_group_L_end, &
     939              :                           my_ia_start(ispin), my_ia_end(ispin), gd_L, gd_ia, &
     940              :                           group_grid_2_mepos, ngroup, para_env_sub%num_pe, fm_mat_S(ispin), &
     941          398 :                           integ_group_size, color_rpa_group)
     942              : 
     943          398 :             DEALLOCATE (group_grid_2_mepos)
     944          398 :             CALL cp_fm_struct_release(fm_struct)
     945              : 
     946              :             ! deallocate the info array
     947          398 :             CALL release_group_dist(gd_L)
     948          398 :             CALL release_group_dist(gd_ia)
     949              : 
     950              :             ! sum the local data across processes belonging to different RPA group.
     951          730 :             IF (para_env_RPA%num_pe /= para_env%num_pe) THEN
     952              :                BLOCK
     953              :                   TYPE(mp_comm_type) :: comm_exchange
     954          170 :                   comm_exchange = fm_mat_S(ispin)%matrix_struct%context%interconnect(para_env)
     955          170 :                   CALL comm_exchange%sum(fm_mat_S(ispin)%local_data)
     956          340 :                   CALL comm_exchange%free()
     957              :                END BLOCK
     958              :             END IF
     959              :          END DO
     960              :       END IF
     961              : 
     962          468 :       IF (PRESENT(fm_mat_Q_gemm) .AND. .NOT. my_do_im_time) THEN
     963              :          ! create the Q matrix dimen_RIxdimen_RI where the result of the mat-mat-mult will be stored
     964          178 :          NULLIFY (fm_struct)
     965              :          CALL cp_fm_struct_create(fm_struct, context=blacs_env, nrow_global=dimen_RI, &
     966              :                                   ncol_global=dimen_RI, para_env=para_env_RPA, &
     967          178 :                                   nrow_block=nrow_block_mat, ncol_block=ncol_block_mat, force_block=.TRUE.)
     968          394 :          DO ispin = 1, SIZE(fm_mat_Q_gemm)
     969          394 :             CALL cp_fm_create(fm_mat_Q_gemm(ispin), fm_struct, name="fm_mat_Q_gemm")
     970              :          END DO
     971          178 :          CALL cp_fm_struct_release(fm_struct)
     972              :       END IF
     973              : 
     974          468 :       IF (PRESENT(fm_mat_Q)) THEN
     975          384 :          NULLIFY (blacs_env_Q)
     976          384 :          IF (my_blacs_ext) THEN
     977           70 :             blacs_env_Q => blacs_env_ext
     978          314 :          ELSE IF (para_env_RPA%num_pe == para_env%num_pe .AND. PRESENT(qs_env)) THEN
     979          202 :             CALL get_qs_env(qs_env, blacs_env=blacs_env_Q)
     980              :          ELSE
     981          112 :             CALL cp_blacs_env_create(blacs_env=blacs_env_Q, para_env=para_env_RPA)
     982              :          END IF
     983          384 :          NULLIFY (fm_struct)
     984              :          CALL cp_fm_struct_create(fm_struct, context=blacs_env_Q, nrow_global=dimen_RI, &
     985          384 :                                   ncol_global=dimen_RI, para_env=para_env_RPA)
     986          834 :          DO ispin = 1, SIZE(fm_mat_Q)
     987          834 :             CALL cp_fm_create(fm_mat_Q(ispin), fm_struct, name="fm_mat_Q", set_zero=.TRUE.)
     988              :          END DO
     989              : 
     990          384 :          CALL cp_fm_struct_release(fm_struct)
     991              : 
     992          384 :          IF (.NOT. (my_blacs_ext .OR. (para_env_RPA%num_pe == para_env%num_pe .AND. PRESENT(qs_env)))) THEN
     993          112 :             CALL cp_blacs_env_release(blacs_env_Q)
     994              :          END IF
     995              :       END IF
     996              : 
     997              :       ! release blacs_env
     998          468 :       IF (.NOT. my_blacs_S_ext) THEN
     999          314 :          CALL cp_blacs_env_release(blacs_env)
    1000              :       ELSE
    1001          154 :          NULLIFY (blacs_env)
    1002              :       END IF
    1003              : 
    1004          468 :       CALL timestop(handle)
    1005              : 
    1006          468 :    END SUBROUTINE create_integ_mat
    1007              : 
    1008              : ! **************************************************************************************************
    1009              : !> \brief ...
    1010              : !> \param qs_env ...
    1011              : !> \param Erpa ...
    1012              : !> \param mp2_env ...
    1013              : !> \param para_env ...
    1014              : !> \param para_env_RPA ...
    1015              : !> \param para_env_sub ...
    1016              : !> \param unit_nr ...
    1017              : !> \param homo ...
    1018              : !> \param virtual ...
    1019              : !> \param dimen_RI ...
    1020              : !> \param dimen_RI_red ...
    1021              : !> \param dimen_ia ...
    1022              : !> \param dimen_nm_gw ...
    1023              : !> \param Eigenval ...
    1024              : !> \param num_integ_points ...
    1025              : !> \param num_integ_group ...
    1026              : !> \param color_rpa_group ...
    1027              : !> \param fm_matrix_PQ ...
    1028              : !> \param fm_mat_S ...
    1029              : !> \param fm_mat_Q_gemm ...
    1030              : !> \param fm_mat_Q ...
    1031              : !> \param fm_mat_S_gw ...
    1032              : !> \param fm_mat_R_gw ...
    1033              : !> \param fm_mat_S_ij_bse ...
    1034              : !> \param fm_mat_S_ab_bse ...
    1035              : !> \param my_do_gw ...
    1036              : !> \param do_bse ...
    1037              : !> \param gw_corr_lev_occ ...
    1038              : !> \param gw_corr_lev_virt ...
    1039              : !> \param bse_lev_virt ...
    1040              : !> \param do_minimax_quad ...
    1041              : !> \param do_im_time ...
    1042              : !> \param mo_coeff ...
    1043              : !> \param fm_matrix_L_kpoints ...
    1044              : !> \param fm_matrix_Minv_L_kpoints ...
    1045              : !> \param fm_matrix_Minv ...
    1046              : !> \param fm_matrix_Minv_Vtrunc_Minv ...
    1047              : !> \param mat_munu ...
    1048              : !> \param mat_P_global ...
    1049              : !> \param t_3c_M ...
    1050              : !> \param t_3c_O ...
    1051              : !> \param t_3c_O_compressed ...
    1052              : !> \param t_3c_O_ind ...
    1053              : !> \param starts_array_mc ...
    1054              : !> \param ends_array_mc ...
    1055              : !> \param starts_array_mc_block ...
    1056              : !> \param ends_array_mc_block ...
    1057              : !> \param matrix_s ...
    1058              : !> \param do_kpoints_from_Gamma ...
    1059              : !> \param kpoints ...
    1060              : !> \param gd_array ...
    1061              : !> \param color_sub ...
    1062              : !> \param do_ri_sos_laplace_mp2 ...
    1063              : !> \param calc_forces ...
    1064              : ! **************************************************************************************************
    1065          314 :    SUBROUTINE rpa_num_int(qs_env, Erpa, mp2_env, para_env, para_env_RPA, para_env_sub, unit_nr, &
    1066          314 :                           homo, virtual, dimen_RI, dimen_RI_red, dimen_ia, dimen_nm_gw, &
    1067              :                           Eigenval, num_integ_points, num_integ_group, color_rpa_group, &
    1068          628 :                           fm_matrix_PQ, fm_mat_S, fm_mat_Q_gemm, fm_mat_Q, fm_mat_S_gw, fm_mat_R_gw, &
    1069          350 :                           fm_mat_S_ij_bse, fm_mat_S_ab_bse, &
    1070          314 :                           my_do_gw, do_bse, gw_corr_lev_occ, gw_corr_lev_virt, &
    1071          314 :                           bse_lev_virt, &
    1072          314 :                           do_minimax_quad, do_im_time, mo_coeff, &
    1073              :                           fm_matrix_L_kpoints, fm_matrix_Minv_L_kpoints, &
    1074              :                           fm_matrix_Minv, fm_matrix_Minv_Vtrunc_Minv, mat_munu, mat_P_global, &
    1075              :                           t_3c_M, t_3c_O, t_3c_O_compressed, t_3c_O_ind, &
    1076              :                           starts_array_mc, ends_array_mc, &
    1077              :                           starts_array_mc_block, ends_array_mc_block, &
    1078              :                           matrix_s, do_kpoints_from_Gamma, kpoints, gd_array, color_sub, &
    1079              :                           do_ri_sos_laplace_mp2, calc_forces)
    1080              : 
    1081              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1082              :       REAL(KIND=dp), INTENT(OUT)                         :: Erpa
    1083              :       TYPE(mp2_type)                                     :: mp2_env
    1084              :       TYPE(mp_para_env_type), POINTER                    :: para_env, para_env_RPA, para_env_sub
    1085              :       INTEGER, INTENT(IN)                                :: unit_nr
    1086              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: homo, virtual
    1087              :       INTEGER, INTENT(IN)                                :: dimen_RI, dimen_RI_red
    1088              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: dimen_ia
    1089              :       INTEGER, INTENT(IN)                                :: dimen_nm_gw
    1090              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
    1091              :          INTENT(INOUT)                                   :: Eigenval
    1092              :       INTEGER, INTENT(IN)                                :: num_integ_points, num_integ_group, &
    1093              :                                                             color_rpa_group
    1094              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_matrix_PQ
    1095              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT)      :: fm_mat_S
    1096              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: fm_mat_Q_gemm, fm_mat_Q, fm_mat_S_gw
    1097              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_mat_R_gw
    1098              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: fm_mat_S_ij_bse, fm_mat_S_ab_bse
    1099              :       LOGICAL, INTENT(IN)                                :: my_do_gw, do_bse
    1100              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: gw_corr_lev_occ, gw_corr_lev_virt, &
    1101              :                                                             bse_lev_virt
    1102              :       LOGICAL, INTENT(IN)                                :: do_minimax_quad, do_im_time
    1103              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: mo_coeff
    1104              :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: fm_matrix_L_kpoints, &
    1105              :                                                             fm_matrix_Minv_L_kpoints, &
    1106              :                                                             fm_matrix_Minv, &
    1107              :                                                             fm_matrix_Minv_Vtrunc_Minv
    1108              :       TYPE(dbcsr_p_type), INTENT(IN)                     :: mat_munu
    1109              :       TYPE(dbcsr_p_type), INTENT(INOUT)                  :: mat_P_global
    1110              :       TYPE(dbt_type), INTENT(INOUT)                      :: t_3c_M
    1111              :       TYPE(dbt_type), ALLOCATABLE, DIMENSION(:, :), &
    1112              :          INTENT(INOUT)                                   :: t_3c_O
    1113              :       TYPE(hfx_compression_type), ALLOCATABLE, &
    1114              :          DIMENSION(:, :, :), INTENT(INOUT)               :: t_3c_O_compressed
    1115              :       TYPE(block_ind_type), ALLOCATABLE, &
    1116              :          DIMENSION(:, :, :), INTENT(INOUT)               :: t_3c_O_ind
    1117              :       INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(IN)     :: starts_array_mc, ends_array_mc, &
    1118              :                                                             starts_array_mc_block, &
    1119              :                                                             ends_array_mc_block
    1120              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
    1121              :       LOGICAL                                            :: do_kpoints_from_Gamma
    1122              :       TYPE(kpoint_type), POINTER                         :: kpoints
    1123              :       TYPE(group_dist_d1_type), INTENT(IN)               :: gd_array
    1124              :       INTEGER, INTENT(IN)                                :: color_sub
    1125              :       LOGICAL, INTENT(IN)                                :: do_ri_sos_laplace_mp2, calc_forces
    1126              : 
    1127              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'rpa_num_int'
    1128              : 
    1129              :       COMPLEX(KIND=dp), ALLOCATABLE, &
    1130          314 :          DIMENSION(:, :, :, :)                           :: vec_Sigma_c_gw
    1131              :       INTEGER :: count_ev_sc_GW, cut_memory, group_size_P, gw_corr_lev_tot, handle, handle3, i, &
    1132              :          ikp_local, ispin, iter_evGW, iter_sc_GW0, j, jquad, min_bsize, mm_style, nkp, &
    1133              :          nkp_self_energy, nmo, nspins, num_3c_repl, num_cells_dm, num_fit_points, Pspin, Qspin, &
    1134              :          size_P
    1135              :       INTEGER(int_8)                                     :: dbcsr_nflop
    1136          314 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: index_to_cell_3c
    1137          314 :       INTEGER, ALLOCATABLE, DIMENSION(:, :, :)           :: cell_to_index_3c
    1138          628 :       INTEGER, DIMENSION(:), POINTER                     :: col_blk_size, prim_blk_sizes, &
    1139          314 :                                                             RI_blk_sizes
    1140              :       LOGICAL :: do_apply_ic_corr_to_gw, do_gw_im_time, do_ic_model, do_kpoints_cubic_RPA, &
    1141              :          do_periodic, do_print, do_ri_Sigma_x, exit_ev_gw, first_cycle, &
    1142              :          first_cycle_periodic_correction, my_open_shell, print_ic_values
    1143          314 :       LOGICAL, ALLOCATABLE, DIMENSION(:, :, :, :, :)     :: has_mat_P_blocks
    1144              :       REAL(KIND=dp) :: a_scaling, alpha, dbcsr_time, e_exchange, e_exchange_corr, eps_filter, &
    1145              :          eps_filter_im_time, ext_scaling, fermi_level_offset, fermi_level_offset_input, &
    1146              :          my_flop_rate, omega, omega_max_fit, omega_old, tau, tau_old
    1147          628 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: delta_corr, e_fermi, tau_tj, tau_wj, tj, &
    1148          314 :                                                             trace_Qomega, vec_omega_fit_gw, wj, &
    1149          314 :                                                             wkp_W
    1150          314 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: vec_W_gw, weights_cos_tf_t_to_w, &
    1151          314 :                                                             weights_cos_tf_w_to_t, &
    1152          314 :                                                             weights_sin_tf_t_to_w
    1153          314 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: Eigenval_last, Eigenval_scf, &
    1154          314 :                                                             vec_Sigma_x_gw
    1155              :       TYPE(cp_cfm_type)                                  :: cfm_mat_Q
    1156              :       TYPE(cp_fm_type) :: fm_mat_Q_static_bse_gemm, fm_mat_RI_global_work, fm_mat_work, &
    1157              :          fm_mo_coeff_occ_scaled, fm_mo_coeff_virt_scaled, fm_scaled_dm_occ_tau, &
    1158              :          fm_scaled_dm_virt_tau
    1159          314 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_mat_S_gw_work, fm_mat_S_ia_bse, &
    1160          314 :                                                             fm_mat_W, fm_mo_coeff_occ, &
    1161          314 :                                                             fm_mo_coeff_virt
    1162          314 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: fm_mat_L_kpoints, fm_mat_Minv_L_kpoints
    1163              :       TYPE(dbcsr_p_type)                                 :: mat_dm, mat_L, mat_M_P_munu_occ, &
    1164              :                                                             mat_M_P_munu_virt, mat_MinvVMinv
    1165              :       TYPE(dbcsr_p_type), ALLOCATABLE, &
    1166          314 :          DIMENSION(:, :, :)                              :: mat_P_omega
    1167          314 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_berry_im_mo_mo, &
    1168          314 :                                                             matrix_berry_re_mo_mo
    1169          314 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_P_omega_kp
    1170              :       TYPE(dbcsr_type), POINTER                          :: mat_W, mat_work
    1171         2198 :       TYPE(dbt_type)                                     :: t_3c_overl_int_ao_mo
    1172          314 :       TYPE(dbt_type), ALLOCATABLE, DIMENSION(:)          :: t_3c_overl_int_gw_AO, &
    1173          314 :                                                             t_3c_overl_int_gw_RI, &
    1174          314 :                                                             t_3c_overl_nnP_ic, &
    1175          314 :                                                             t_3c_overl_nnP_ic_reflected
    1176              :       TYPE(dgemm_counter_type)                           :: dgemm_counter
    1177              :       TYPE(hfx_compression_type), ALLOCATABLE, &
    1178          314 :          DIMENSION(:)                                    :: t_3c_O_mo_compressed
    1179        23236 :       TYPE(im_time_force_type)                           :: force_data
    1180          314 :       TYPE(rpa_exchange_work_type)                       :: exchange_work
    1181         1570 :       TYPE(rpa_grad_type)                                :: rpa_grad
    1182          314 :       TYPE(rpa_sigma_type)                               :: rpa_sigma
    1183          314 :       TYPE(two_dim_int_array), ALLOCATABLE, DIMENSION(:) :: t_3c_O_mo_ind
    1184              : 
    1185          314 :       CALL timeset(routineN, handle)
    1186              : 
    1187          314 :       nspins = SIZE(homo)
    1188          314 :       nmo = homo(1) + virtual(1)
    1189              : 
    1190          314 :       my_open_shell = (nspins == 2)
    1191              : 
    1192          314 :       do_gw_im_time = my_do_gw .AND. do_im_time
    1193          314 :       do_ri_Sigma_x = mp2_env%ri_g0w0%do_ri_Sigma_x
    1194          314 :       do_ic_model = mp2_env%ri_g0w0%do_ic_model
    1195          314 :       print_ic_values = mp2_env%ri_g0w0%print_ic_values
    1196          314 :       do_periodic = mp2_env%ri_g0w0%do_periodic
    1197          314 :       do_kpoints_cubic_RPA = mp2_env%ri_rpa_im_time%do_im_time_kpoints
    1198              : 
    1199              :       ! For SOS-MP2 only gemm is implemented
    1200          314 :       mm_style = wfc_mm_style_gemm
    1201          314 :       IF (.NOT. do_ri_sos_laplace_mp2) mm_style = mp2_env%ri_rpa%mm_style
    1202              : 
    1203          314 :       IF (my_do_gw) THEN
    1204          116 :          ext_scaling = 0.2_dp
    1205          116 :          omega_max_fit = mp2_env%ri_g0w0%omega_max_fit
    1206          116 :          fermi_level_offset_input = mp2_env%ri_g0w0%fermi_level_offset
    1207          116 :          iter_evGW = mp2_env%ri_g0w0%iter_evGW
    1208          116 :          iter_sc_GW0 = mp2_env%ri_g0w0%iter_sc_GW0
    1209          116 :          IF ((.NOT. do_im_time)) THEN
    1210           70 :             IF (iter_sc_GW0 /= 1 .AND. iter_evGW /= 1) CPABORT("Mixed scGW0/evGW not implemented.")
    1211              :             ! in case of scGW0 with the N^4 algorithm, we use the evGW code but use the DFT eigenvalues for W
    1212           70 :             IF (iter_sc_GW0 /= 1) iter_evGW = iter_sc_GW0
    1213              :          END IF
    1214              :       ELSE
    1215          198 :          ext_scaling = 0.0_dp
    1216          198 :          iter_evGW = 1
    1217          198 :          iter_sc_GW0 = 1
    1218              :       END IF
    1219              : 
    1220          314 :       IF (do_kpoints_cubic_RPA .AND. do_ri_sos_laplace_mp2) THEN
    1221            0 :          CPABORT("RI-SOS-Laplace-MP2 with k-point-sampling is not implemented.")
    1222              :       END IF
    1223              : 
    1224          314 :       do_apply_ic_corr_to_gw = .FALSE.
    1225          314 :       IF (mp2_env%ri_g0w0%ic_corr_list(1)%array(1) > 0.0_dp) do_apply_ic_corr_to_gw = .TRUE.
    1226              : 
    1227          314 :       IF (do_im_time) THEN
    1228          136 :          CPASSERT(do_minimax_quad .OR. do_ri_sos_laplace_mp2)
    1229              : 
    1230          136 :          group_size_P = mp2_env%ri_rpa_im_time%group_size_P
    1231          136 :          cut_memory = mp2_env%ri_rpa_im_time%cut_memory
    1232          136 :          eps_filter = mp2_env%ri_rpa_im_time%eps_filter
    1233              :          eps_filter_im_time = mp2_env%ri_rpa_im_time%eps_filter* &
    1234          136 :                               mp2_env%ri_rpa_im_time%eps_filter_factor
    1235              : 
    1236          136 :          min_bsize = mp2_env%ri_rpa_im_time%min_bsize
    1237              : 
    1238              :          CALL alloc_im_time(qs_env, para_env, dimen_RI, dimen_RI_red, &
    1239              :                             num_integ_points, nspins, fm_mat_Q(1), fm_mo_coeff_occ, fm_mo_coeff_virt, &
    1240              :                             fm_matrix_Minv_L_kpoints, fm_matrix_L_kpoints, mat_P_global, &
    1241              :                             t_3c_O, matrix_s, kpoints, eps_filter_im_time, &
    1242              :                             cut_memory, nkp, num_cells_dm, num_3c_repl, &
    1243              :                             size_P, ikp_local, &
    1244              :                             index_to_cell_3c, &
    1245              :                             cell_to_index_3c, &
    1246              :                             col_blk_size, &
    1247              :                             do_ic_model, do_kpoints_cubic_RPA, &
    1248              :                             do_kpoints_from_Gamma, do_ri_Sigma_x, my_open_shell, &
    1249              :                             has_mat_P_blocks, wkp_W, &
    1250              :                             cfm_mat_Q, fm_mat_Minv_L_kpoints, fm_mat_L_kpoints, &
    1251              :                             fm_mat_RI_global_work, fm_mat_work, fm_mo_coeff_occ_scaled, &
    1252              :                             fm_mo_coeff_virt_scaled, mat_dm, mat_L, mat_M_P_munu_occ, mat_M_P_munu_virt, &
    1253              :                             mat_MinvVMinv, mat_P_omega, mat_P_omega_kp, mat_work, mo_coeff, &
    1254          136 :                             fm_scaled_dm_occ_tau, fm_scaled_dm_virt_tau, homo, nmo)
    1255              : 
    1256          136 :          IF (calc_forces) CALL init_im_time_forces(force_data, fm_matrix_PQ, t_3c_M, unit_nr, mp2_env, qs_env)
    1257              : 
    1258          136 :          IF (my_do_gw) THEN
    1259              : 
    1260              :             CALL dbcsr_get_info(mat_P_global%matrix, &
    1261           46 :                                 row_blk_size=RI_blk_sizes)
    1262              : 
    1263              :             CALL dbcsr_get_info(matrix_s(1)%matrix, &
    1264           46 :                                 row_blk_size=prim_blk_sizes)
    1265              : 
    1266           46 :             gw_corr_lev_tot = gw_corr_lev_occ(1) + gw_corr_lev_virt(1)
    1267              : 
    1268           46 :             IF (.NOT. do_kpoints_cubic_RPA) THEN
    1269              :                CALL allocate_matrices_gw_im_time(gw_corr_lev_occ, gw_corr_lev_virt, homo, nmo, &
    1270              :                                                  num_integ_points, unit_nr, &
    1271              :                                                  RI_blk_sizes, do_ic_model, &
    1272              :                                                  para_env, fm_mat_W, fm_mat_Q(1), &
    1273              :                                                  mo_coeff, &
    1274              :                                                  t_3c_overl_int_ao_mo, t_3c_O_mo_compressed, t_3c_O_mo_ind, &
    1275              :                                                  t_3c_overl_int_gw_RI, t_3c_overl_int_gw_AO, &
    1276              :                                                  starts_array_mc, ends_array_mc, &
    1277              :                                                  t_3c_overl_nnP_ic, t_3c_overl_nnP_ic_reflected, &
    1278              :                                                  matrix_s, mat_W, t_3c_O, &
    1279              :                                                  t_3c_O_compressed, t_3c_O_ind, &
    1280           46 :                                                  qs_env)
    1281              : 
    1282              :             END IF
    1283              :          END IF
    1284              : 
    1285              :       END IF
    1286          314 :       IF (do_ic_model) THEN
    1287              :          ! image charge model only implemented for cubic scaling GW
    1288            2 :          CPASSERT(do_gw_im_time)
    1289            2 :          CPASSERT(.NOT. do_periodic)
    1290            2 :          IF (cut_memory /= 1) CPABORT("For IC, use MEMORY_CUT 1 in the LOW_SCALING section.")
    1291              :       END IF
    1292              : 
    1293          942 :       ALLOCATE (e_fermi(nspins))
    1294          314 :       IF (do_minimax_quad .OR. do_ri_sos_laplace_mp2) THEN
    1295          206 :          do_print = .NOT. do_ic_model
    1296              :          CALL get_minimax_grid(para_env, unit_nr, homo, Eigenval, num_integ_points, do_im_time, &
    1297              :                                do_ri_sos_laplace_mp2, do_print, &
    1298              :                                tau_tj, tau_wj, qs_env, do_gw_im_time, &
    1299              :                                do_kpoints_cubic_RPA, e_fermi(1), tj, wj, &
    1300              :                                weights_cos_tf_t_to_w, weights_cos_tf_w_to_t, weights_sin_tf_t_to_w, &
    1301          206 :                                qs_env%mp2_env%ri_g0w0%regularization_minimax)
    1302              : 
    1303              :          !For sos_laplace_mp2 and low-scaling RPA, potentially need to store/retrieve the initial weights
    1304          206 :          IF (qs_env%mp2_env%ri_rpa_im_time%keep_quad) THEN
    1305              :             CALL keep_initial_quad(tj, wj, tau_tj, tau_wj, weights_cos_tf_t_to_w, &
    1306              :                                    weights_cos_tf_w_to_t, do_ri_sos_laplace_mp2, do_im_time, &
    1307          206 :                                    num_integ_points, unit_nr, qs_env)
    1308              :          END IF
    1309              :       ELSE
    1310          108 :          IF (calc_forces) CPABORT("Forces with Clenshaw-Curtis grid not implemented.")
    1311              :          CALL get_clenshaw_grid(para_env, para_env_RPA, unit_nr, homo, virtual, Eigenval, num_integ_points, &
    1312              :                                 num_integ_group, color_rpa_group, fm_mat_S, my_do_gw, &
    1313          108 :                                 ext_scaling, a_scaling, tj, wj)
    1314              :       END IF
    1315              : 
    1316              :       ! This array is needed for RPA
    1317          314 :       IF (.NOT. do_ri_sos_laplace_mp2) THEN
    1318          768 :          ALLOCATE (trace_Qomega(dimen_RI_red))
    1319              :       END IF
    1320              : 
    1321          314 :       IF (do_ri_sos_laplace_mp2 .AND. .NOT. do_im_time) THEN
    1322           28 :          alpha = 1.0_dp
    1323          286 :       ELSE IF (my_open_shell .OR. do_ri_sos_laplace_mp2) THEN
    1324           80 :          alpha = 2.0_dp
    1325              :       ELSE
    1326          206 :          alpha = 4.0_dp
    1327              :       END IF
    1328          314 :       IF (my_do_gw) THEN
    1329              :          CALL allocate_matrices_gw(vec_Sigma_c_gw, color_rpa_group, dimen_nm_gw, &
    1330              :                                    gw_corr_lev_occ, gw_corr_lev_virt, homo, &
    1331              :                                    nmo, num_integ_group, num_integ_points, unit_nr, &
    1332              :                                    gw_corr_lev_tot, num_fit_points, omega_max_fit, &
    1333              :                                    do_minimax_quad, do_periodic, do_ri_Sigma_x,.NOT. do_im_time, &
    1334              :                                    first_cycle_periodic_correction, &
    1335              :                                    a_scaling, Eigenval, tj, vec_omega_fit_gw, vec_Sigma_x_gw, &
    1336              :                                    delta_corr, Eigenval_last, Eigenval_scf, vec_W_gw, &
    1337              :                                    fm_mat_S_gw, fm_mat_S_gw_work, &
    1338              :                                    para_env, mp2_env, kpoints, nkp, nkp_self_energy, &
    1339          116 :                                    do_kpoints_cubic_RPA, do_kpoints_from_Gamma)
    1340              : 
    1341          116 :          IF (do_bse) THEN
    1342              : 
    1343           42 :             CALL cp_fm_create(fm_mat_Q_static_bse_gemm, fm_mat_Q_gemm(1)%matrix_struct)
    1344           42 :             CALL cp_fm_to_fm(fm_mat_Q_gemm(1), fm_mat_Q_static_bse_gemm)
    1345           42 :             CALL cp_fm_set_all(fm_mat_Q_static_bse_gemm, 0.0_dp)
    1346              : 
    1347              :          END IF
    1348              : 
    1349              :       END IF
    1350              : 
    1351          314 :       IF (calc_forces .AND. .NOT. do_im_time) CALL rpa_grad_create(rpa_grad, fm_mat_Q(1), &
    1352              :                                                                    fm_mat_S, homo, virtual, mp2_env, Eigenval(:, 1, :), &
    1353           44 :                                                                    unit_nr, do_ri_sos_laplace_mp2)
    1354          314 :       IF (.NOT. do_im_time .AND. .NOT. do_ri_sos_laplace_mp2) THEN
    1355              :          CALL exchange_work%create(qs_env, para_env_sub, mat_munu, dimen_RI_red, &
    1356          150 :                                    fm_mat_S, fm_mat_Q(1), fm_mat_Q_gemm(1), homo, virtual)
    1357              :       END IF
    1358          314 :       Erpa = 0.0_dp
    1359          314 :       IF (mp2_env%ri_rpa%exchange_correction /= rpa_exchange_none) e_exchange = 0.0_dp
    1360          314 :       first_cycle = .TRUE.
    1361          314 :       omega_old = 0.0_dp
    1362          314 :       CALL dgemm_counter_init(dgemm_counter, unit_nr, mp2_env%ri_rpa%print_dgemm_info)
    1363              : 
    1364          738 :       DO count_ev_sc_GW = 1, iter_evGW
    1365          444 :          dbcsr_time = 0.0_dp
    1366          444 :          dbcsr_nflop = 0
    1367              : 
    1368          444 :          IF (do_ic_model) CYCLE
    1369              : 
    1370              :          ! reset some values, important when doing eigenvalue self-consistent GW
    1371          442 :          IF (my_do_gw) THEN
    1372          244 :             Erpa = 0.0_dp
    1373          244 :             vec_Sigma_c_gw = z_zero
    1374          244 :             first_cycle = .TRUE.
    1375              :          END IF
    1376              : 
    1377              :          ! calculate Q_PQ(it)
    1378          442 :          IF (do_im_time) THEN ! not using Imaginary time
    1379              : 
    1380          148 :             IF (.NOT. do_kpoints_cubic_RPA) THEN
    1381          312 :                DO ispin = 1, nspins
    1382          312 :                   e_fermi(ispin) = (Eigenval(homo(ispin), 1, ispin) + Eigenval(homo(ispin) + 1, 1, ispin))*0.5_dp
    1383              :                END DO
    1384              :             END IF
    1385              : 
    1386          148 :             tau = 0.0_dp
    1387          148 :             tau_old = 0.0_dp
    1388              : 
    1389          148 :             IF (unit_nr > 0) WRITE (UNIT=unit_nr, FMT="(/T3,A,T66,i15)") &
    1390           74 :                "MEMORY_INFO| Memory cut:", cut_memory
    1391          148 :             IF (unit_nr > 0) WRITE (UNIT=unit_nr, FMT="(T3,A,T66,ES15.2)") &
    1392           74 :                "SPARSITY_INFO| Eps filter for M virt/occ tensors:", eps_filter
    1393          148 :             IF (unit_nr > 0) WRITE (UNIT=unit_nr, FMT="(T3,A,T66,ES15.2)") &
    1394           74 :                "SPARSITY_INFO| Eps filter for P matrix:", eps_filter_im_time
    1395          148 :             IF (unit_nr > 0) WRITE (UNIT=unit_nr, FMT="(T3,A,T66,i15)") &
    1396           74 :                "SPARSITY_INFO| Minimum tensor block size:", min_bsize
    1397              : 
    1398              :             ! for evGW, we have to ensure that mat_P_omega is zero
    1399          148 :             CALL zero_mat_P_omega(mat_P_omega(:, :, 1))
    1400              : 
    1401              :             ! compute the matrix Q(it) and Fourier transform it directly to mat_P_omega(iw)
    1402              :             CALL compute_mat_P_omega(mat_P_omega(:, :, 1), fm_scaled_dm_occ_tau, &
    1403              :                                      fm_scaled_dm_virt_tau, fm_mo_coeff_occ(1), fm_mo_coeff_virt(1), &
    1404              :                                      fm_mo_coeff_occ_scaled, fm_mo_coeff_virt_scaled, &
    1405              :                                      mat_P_global, matrix_s, 1, &
    1406              :                                      t_3c_M, t_3c_O, t_3c_O_compressed, t_3c_O_ind, &
    1407              :                                      starts_array_mc, ends_array_mc, &
    1408              :                                      starts_array_mc_block, ends_array_mc_block, &
    1409              :                                      weights_cos_tf_t_to_w, tj, tau_tj, e_fermi(1), eps_filter, alpha, &
    1410              :                                      eps_filter_im_time, Eigenval(:, 1, 1), nmo, &
    1411              :                                      num_integ_points, cut_memory, &
    1412              :                                      unit_nr, mp2_env, para_env, &
    1413              :                                      qs_env, do_kpoints_from_Gamma, &
    1414              :                                      index_to_cell_3c, cell_to_index_3c, &
    1415              :                                      has_mat_P_blocks, do_ri_sos_laplace_mp2, &
    1416          148 :                                      dbcsr_time, dbcsr_nflop)
    1417              : 
    1418              :             ! the same for open shell, use fm_mo_coeff_occ_beta and fm_mo_coeff_virt_beta
    1419          148 :             IF (my_open_shell) THEN
    1420           28 :                CALL zero_mat_P_omega(mat_P_omega(:, :, 2))
    1421              :                CALL compute_mat_P_omega(mat_P_omega(:, :, 2), fm_scaled_dm_occ_tau, &
    1422              :                                         fm_scaled_dm_virt_tau, fm_mo_coeff_occ(2), &
    1423              :                                         fm_mo_coeff_virt(2), &
    1424              :                                         fm_mo_coeff_occ_scaled, fm_mo_coeff_virt_scaled, &
    1425              :                                         mat_P_global, matrix_s, 2, &
    1426              :                                         t_3c_M, t_3c_O, t_3c_O_compressed, t_3c_O_ind, &
    1427              :                                         starts_array_mc, ends_array_mc, &
    1428              :                                         starts_array_mc_block, ends_array_mc_block, &
    1429              :                                         weights_cos_tf_t_to_w, tj, tau_tj, e_fermi(2), eps_filter, alpha, &
    1430              :                                         eps_filter_im_time, Eigenval(:, 1, 2), nmo, &
    1431              :                                         num_integ_points, cut_memory, &
    1432              :                                         unit_nr, mp2_env, para_env, &
    1433              :                                         qs_env, do_kpoints_from_Gamma, &
    1434              :                                         index_to_cell_3c, cell_to_index_3c, &
    1435              :                                         has_mat_P_blocks, do_ri_sos_laplace_mp2, &
    1436           28 :                                         dbcsr_time, dbcsr_nflop)
    1437              : 
    1438              :                !For RPA, we sum up the P matrices. If no force needed, can clean-up the beta spin one
    1439           28 :                IF (.NOT. do_ri_sos_laplace_mp2) THEN
    1440           90 :                   DO j = 1, SIZE(mat_P_omega, 2)
    1441          598 :                      DO i = 1, SIZE(mat_P_omega, 1)
    1442          508 :                         CALL dbcsr_add(mat_P_omega(i, j, 1)%matrix, mat_P_omega(i, j, 2)%matrix, 1.0_dp, 1.0_dp)
    1443          578 :                         IF (.NOT. calc_forces) CALL dbcsr_clear(mat_P_omega(i, j, 2)%matrix)
    1444              :                      END DO
    1445              :                   END DO
    1446              :                END IF
    1447              :             END IF ! my_open_shell
    1448              : 
    1449              :          END IF ! do im time
    1450              : 
    1451          442 :          IF (mp2_env%ri_rpa%sigma_param /= sigma_none) THEN
    1452           10 :             CALL rpa_sigma_create(rpa_sigma, mp2_env%ri_rpa%sigma_param, fm_mat_Q(1), unit_nr, para_env)
    1453              :          END IF
    1454              : 
    1455        13392 :          DO jquad = 1, num_integ_points
    1456        12950 :             IF (MODULO(jquad, num_integ_group) /= color_rpa_group) CYCLE
    1457              : 
    1458        12217 :             CALL timeset(routineN//"_RPA_matrix_operations", handle3)
    1459              : 
    1460        12217 :             IF (do_ri_sos_laplace_mp2) THEN
    1461          176 :                omega = tau_tj(jquad)
    1462              :             ELSE
    1463        12041 :                IF (do_minimax_quad) THEN
    1464         1191 :                   omega = tj(jquad)
    1465              :                ELSE
    1466        10850 :                   omega = a_scaling/TAN(tj(jquad))
    1467              :                END IF
    1468              :             END IF ! do_ri_sos_laplace_mp2
    1469              : 
    1470        12217 :             IF (do_im_time) THEN
    1471              :                ! in case we do imag time, we already calculated fm_mat_Q by a Fourier transform from im. time
    1472              : 
    1473         1180 :                IF (.NOT. (do_kpoints_cubic_RPA .OR. do_kpoints_from_Gamma)) THEN
    1474              : 
    1475         2324 :                   DO ispin = 1, SIZE(mat_P_omega, 3)
    1476              :                      CALL contract_P_omega_with_mat_L(mat_P_omega(jquad, 1, ispin)%matrix, mat_L%matrix, mat_work, &
    1477              :                                                       eps_filter_im_time, fm_mat_work, dimen_RI, dimen_RI_red, &
    1478         2324 :                                                       fm_mat_Minv_L_kpoints(1, 1), fm_mat_Q(ispin))
    1479              :                   END DO
    1480              :                END IF
    1481              : 
    1482              :             ELSE
    1483        11037 :                IF (unit_nr > 0) WRITE (UNIT=unit_nr, FMT="(T3, A, 1X, I3, 1X, A, 1X, I3)") &
    1484         5515 :                   "INTEG_INFO| Started with Integration point", jquad, "of", num_integ_points
    1485              : 
    1486        11037 :                IF (first_cycle .AND. count_ev_sc_gw > 1) THEN
    1487          116 :                   IF (iter_sc_gw0 == 1) THEN
    1488          124 :                      DO ispin = 1, nspins
    1489              :                         CALL remove_scaling_factor_rpa(fm_mat_S(ispin), virtual(ispin), &
    1490          124 :                                                        Eigenval_last(:, 1, ispin), homo(ispin), omega_old)
    1491              :                      END DO
    1492              :                   ELSE
    1493          116 :                      DO ispin = 1, nspins
    1494              :                         CALL remove_scaling_factor_rpa(fm_mat_S(ispin), virtual(ispin), &
    1495          116 :                                                        Eigenval_scf(:, 1, ispin), homo(ispin), omega_old)
    1496              :                      END DO
    1497              :                   END IF
    1498              :                END IF
    1499              : 
    1500        11037 :                IF (iter_sc_GW0 > 1) THEN
    1501        12140 :                DO ispin = 1, nspins
    1502              :                   CALL calc_mat_Q(fm_mat_S(ispin), do_ri_sos_laplace_mp2, first_cycle, virtual(ispin), &
    1503              :                                   Eigenval_scf(:, 1, ispin), homo(ispin), omega, omega_old, jquad, mm_style, &
    1504              :                                   dimen_RI_red, dimen_ia(ispin), alpha, fm_mat_Q(ispin), &
    1505              :                                   fm_mat_Q_gemm(ispin), do_bse, fm_mat_Q_static_bse_gemm, dgemm_counter, &
    1506        12140 :                                   num_integ_points, count_ev_sc_GW)
    1507              :                END DO
    1508              : 
    1509              :                ! For SOS-MP2 we need both matrices separately
    1510         6070 :                IF (.NOT. do_ri_sos_laplace_mp2) THEN
    1511         6070 :                DO ispin = 2, nspins
    1512         6070 :                   CALL cp_fm_scale_and_add(alpha=1.0_dp, matrix_a=fm_mat_Q(1), beta=1.0_dp, matrix_b=fm_mat_Q(ispin))
    1513              :                END DO
    1514              :                END IF
    1515              :                ELSE
    1516        10448 :                DO ispin = 1, nspins
    1517              :                   CALL calc_mat_Q(fm_mat_S(ispin), do_ri_sos_laplace_mp2, first_cycle, virtual(ispin), &
    1518              :                                   Eigenval(:, 1, ispin), homo(ispin), omega, omega_old, jquad, mm_style, &
    1519              :                                   dimen_RI_red, dimen_ia(ispin), alpha, fm_mat_Q(ispin), &
    1520              :                                   fm_mat_Q_gemm(ispin), do_bse, fm_mat_Q_static_bse_gemm, dgemm_counter, &
    1521        10448 :                                   num_integ_points, count_ev_sc_GW)
    1522              :                END DO
    1523              :                ! For open-shell BSE: the static screened-Coulomb polarizability is the
    1524              :                ! sum over both spin channels. calc_mat_Q overwrites fm_mat_Q_static_bse_gemm
    1525              :                ! per spin, so rebuild it here as the explicit spin sum at omega=0.
    1526         4967 :                IF (do_bse .AND. nspins > 1 .AND. jquad == num_integ_points .AND. &
    1527              :                    count_ev_sc_GW == 1) THEN
    1528            8 :                   CALL cp_fm_set_all(fm_mat_Q_static_bse_gemm, 0.0_dp)
    1529           24 :                   DO ispin = 1, nspins
    1530              :                      CALL cp_fm_scale_and_add(1.0_dp, fm_mat_Q_static_bse_gemm, &
    1531           24 :                                               1.0_dp, fm_mat_Q_gemm(ispin))
    1532              :                   END DO
    1533              :                END IF
    1534              : 
    1535              :                ! For SOS-MP2 we need both matrices separately
    1536         4967 :                IF (.NOT. do_ri_sos_laplace_mp2) THEN
    1537         5393 :                DO ispin = 2, nspins
    1538         5393 :                   CALL cp_fm_scale_and_add(alpha=1.0_dp, matrix_a=fm_mat_Q(1), beta=1.0_dp, matrix_b=fm_mat_Q(ispin))
    1539              :                END DO
    1540              :                END IF
    1541              : 
    1542              :                END IF
    1543              : 
    1544              :             END IF ! im time
    1545              : 
    1546              :             ! Calculate RPA exchange energy correction
    1547        12217 :             IF (mp2_env%ri_rpa%exchange_correction /= rpa_exchange_none) THEN
    1548           12 :                e_exchange_corr = 0.0_dp
    1549           12 :                CALL exchange_work%compute(fm_mat_Q(1), Eigenval(:, 1, :), fm_mat_S, omega, e_exchange_corr, mp2_env)
    1550              : 
    1551              :                ! Evaluate the final exchange energy correction
    1552           12 :                e_exchange = e_exchange + e_exchange_corr*wj(jquad)
    1553              :             END IF
    1554              : 
    1555              :             ! for developing Sigma functional  closed and open shell are taken cared for
    1556        12217 :             IF (mp2_env%ri_rpa%sigma_param /= sigma_none) THEN
    1557           30 :                CALL rpa_sigma_matrix_spectral(rpa_sigma, fm_mat_Q(1), wj(jquad), para_env_RPA)
    1558              :             END IF
    1559              : 
    1560        12217 :             IF (do_ri_sos_laplace_mp2) THEN
    1561              : 
    1562          176 :                CALL SOS_MP2_postprocessing(fm_mat_Q, Erpa, tau_wj(jquad))
    1563              : 
    1564          176 :                IF (calc_forces .AND. .NOT. do_im_time) CALL rpa_grad_matrix_operations(mp2_env, rpa_grad, do_ri_sos_laplace_mp2, &
    1565              :                                                            fm_mat_Q, fm_mat_Q_gemm, dgemm_counter, fm_mat_S, omega, homo, virtual, &
    1566           50 :                                                                                        Eigenval(:, 1, :), tau_wj(jquad), unit_nr)
    1567              :             ELSE
    1568        12041 :                IF (calc_forces .AND. .NOT. do_im_time) CALL rpa_grad_copy_Q(fm_mat_Q(1), rpa_grad)
    1569              : 
    1570        12041 :                CALL Q_trace_and_add_unit_matrix(dimen_RI_red, trace_Qomega, fm_mat_Q(1))
    1571              : 
    1572        12041 :                IF (do_kpoints_cubic_RPA .OR. do_kpoints_from_Gamma) THEN
    1573              :                   CALL invert_eps_compute_W_and_Erpa_kp(dimen_RI, num_integ_points, jquad, nkp, count_ev_sc_GW, para_env, &
    1574              :                                                         Erpa, tau_tj, tj, wj, weights_cos_tf_w_to_t, &
    1575              :                                                         wkp_W, do_gw_im_time, do_ri_Sigma_x, do_kpoints_from_Gamma, &
    1576              :                                                         cfm_mat_Q, ikp_local, &
    1577              :                                                         mat_P_omega(:, :, 1), mat_P_omega_kp, qs_env, eps_filter_im_time, unit_nr, &
    1578              :                                                         kpoints, fm_mat_Minv_L_kpoints, fm_mat_L_kpoints, &
    1579              :                                                         fm_mat_W, fm_mat_RI_global_work, mat_MinvVMinv, &
    1580          132 :                                                         fm_matrix_Minv, fm_matrix_Minv_Vtrunc_Minv)
    1581              :                ELSE
    1582        11909 :                   CALL compute_Erpa_by_freq_int(dimen_RI_red, trace_Qomega, fm_mat_Q(1), para_env_RPA, Erpa, wj(jquad))
    1583              :                END IF
    1584              : 
    1585        12041 :                IF (calc_forces .AND. .NOT. do_im_time) CALL rpa_grad_matrix_operations(mp2_env, rpa_grad, do_ri_sos_laplace_mp2, &
    1586              :                                                            fm_mat_Q, fm_mat_Q_gemm, dgemm_counter, fm_mat_S, omega, homo, virtual, &
    1587           56 :                                                                                        Eigenval(:, 1, :), wj(jquad), unit_nr)
    1588              :             END IF ! do_ri_sos_laplace_mp2
    1589              : 
    1590              :             ! save omega and reset the first_cycle flag
    1591        12217 :             first_cycle = .FALSE.
    1592        12217 :             omega_old = omega
    1593              : 
    1594        12217 :             CALL timestop(handle3)
    1595              : 
    1596        12217 :             IF (my_do_gw) THEN
    1597              : 
    1598        11428 :                CALL get_fermi_level_offset(fermi_level_offset, fermi_level_offset_input, Eigenval(:, 1, :), homo)
    1599              : 
    1600              :                ! do_im_time = TRUE means low-scaling calculation
    1601        11428 :                IF (do_im_time) THEN
    1602              :                   ! only for molecules
    1603          818 :                   IF (.NOT. (do_kpoints_cubic_RPA .OR. do_kpoints_from_Gamma)) THEN
    1604              :                     CALL compute_W_cubic_GW(fm_mat_W, fm_mat_Q(1), fm_mat_work, dimen_RI, fm_mat_Minv_L_kpoints, num_integ_points, &
    1605          722 :                                              tj, tau_tj, weights_cos_tf_w_to_t, jquad, omega)
    1606              :                   END IF
    1607              :                ELSE
    1608              :                   CALL compute_GW_self_energy(vec_Sigma_c_gw, dimen_nm_gw, dimen_RI_red, gw_corr_lev_occ, &
    1609              :                                               gw_corr_lev_virt, homo, jquad, nmo, num_fit_points, &
    1610              :                                               do_im_time, do_periodic, first_cycle_periodic_correction, &
    1611              :                                               fermi_level_offset, &
    1612              :                                               omega, Eigenval(:, 1, :), delta_corr, vec_omega_fit_gw, vec_W_gw, wj, &
    1613              :                                               fm_mat_Q(1), fm_mat_R_gw, fm_mat_S_gw, &
    1614              :                                               fm_mat_S_gw_work, mo_coeff(1), para_env, &
    1615              :                                               para_env_RPA, matrix_berry_im_mo_mo, matrix_berry_re_mo_mo, &
    1616        10610 :                                               kpoints, qs_env, mp2_env)
    1617              :                END IF
    1618              :             END IF
    1619              : 
    1620        12217 :             IF (unit_nr > 0) CALL m_flush(unit_nr)
    1621        25609 :             CALL para_env_RPA%sync() ! sync to see output
    1622              : 
    1623              :          END DO ! jquad
    1624              : 
    1625          442 :          IF (mp2_env%ri_rpa%sigma_param /= sigma_none) THEN
    1626           10 :             CALL finalize_rpa_sigma(rpa_sigma, unit_nr, mp2_env%ri_rpa%e_sigma_corr, para_env, do_minimax_quad)
    1627           10 :             IF (do_minimax_quad) mp2_env%ri_rpa%e_sigma_corr = mp2_env%ri_rpa%e_sigma_corr/2.0_dp
    1628           10 :             CALL para_env%sum(mp2_env%ri_rpa%e_sigma_corr)
    1629              :          END IF
    1630              : 
    1631          442 :          CALL para_env%sum(Erpa)
    1632              : 
    1633          442 :          IF (.NOT. (do_ri_sos_laplace_mp2)) THEN
    1634          384 :             Erpa = Erpa/(pi*2.0_dp)
    1635          384 :             IF (do_minimax_quad) Erpa = Erpa/2.0_dp
    1636              :          END IF
    1637              : 
    1638          442 :          IF (mp2_env%ri_rpa%exchange_correction /= rpa_exchange_none) THEN
    1639           12 :             CALL para_env%sum(E_exchange)
    1640           12 :             E_exchange = E_exchange/(pi*2.0_dp)
    1641           12 :             IF (do_minimax_quad) E_exchange = E_exchange/2.0_dp
    1642           12 :             mp2_env%ri_rpa%ener_exchange = E_exchange
    1643              :          END IF
    1644              : 
    1645          442 :          IF (calc_forces .AND. do_ri_sos_laplace_mp2 .AND. do_im_time) THEN
    1646           22 :             IF (my_open_shell) THEN
    1647            4 :                Pspin = 1
    1648            4 :                Qspin = 2
    1649              :                CALL calc_laplace_loop_forces(force_data, mat_P_omega(:, 1, :), t_3c_M, t_3c_O(1, 1), &
    1650              :                                              t_3c_O_compressed(1, 1, :), t_3c_O_ind(1, 1, :), fm_scaled_dm_occ_tau, &
    1651              :                                              fm_scaled_dm_virt_tau, fm_mo_coeff_occ, fm_mo_coeff_virt, &
    1652              :                                              fm_mo_coeff_occ_scaled, fm_mo_coeff_virt_scaled, &
    1653              :                                              starts_array_mc, ends_array_mc, starts_array_mc_block, &
    1654              :                                              ends_array_mc_block, num_integ_points, nmo, Eigenval(:, 1, :), &
    1655              :                                              tau_tj, tau_wj, cut_memory, Pspin, Qspin, my_open_shell, &
    1656            4 :                                              unit_nr, dbcsr_time, dbcsr_nflop, mp2_env, qs_env)
    1657            4 :                Pspin = 2
    1658            4 :                Qspin = 1
    1659              :                CALL calc_laplace_loop_forces(force_data, mat_P_omega(:, 1, :), t_3c_M, t_3c_O(1, 1), &
    1660              :                                              t_3c_O_compressed(1, 1, :), t_3c_O_ind(1, 1, :), fm_scaled_dm_occ_tau, &
    1661              :                                              fm_scaled_dm_virt_tau, fm_mo_coeff_occ, fm_mo_coeff_virt, &
    1662              :                                              fm_mo_coeff_occ_scaled, fm_mo_coeff_virt_scaled, &
    1663              :                                              starts_array_mc, ends_array_mc, starts_array_mc_block, &
    1664              :                                              ends_array_mc_block, num_integ_points, nmo, Eigenval(:, 1, :), &
    1665              :                                              tau_tj, tau_wj, cut_memory, Pspin, Qspin, my_open_shell, &
    1666            4 :                                              unit_nr, dbcsr_time, dbcsr_nflop, mp2_env, qs_env)
    1667              : 
    1668              :             ELSE
    1669           18 :                Pspin = 1
    1670           18 :                Qspin = 1
    1671              :                CALL calc_laplace_loop_forces(force_data, mat_P_omega(:, 1, :), t_3c_M, t_3c_O(1, 1), &
    1672              :                                              t_3c_O_compressed(1, 1, :), t_3c_O_ind(1, 1, :), fm_scaled_dm_occ_tau, &
    1673              :                                              fm_scaled_dm_virt_tau, fm_mo_coeff_occ, fm_mo_coeff_virt, &
    1674              :                                              fm_mo_coeff_occ_scaled, fm_mo_coeff_virt_scaled, &
    1675              :                                              starts_array_mc, ends_array_mc, starts_array_mc_block, &
    1676              :                                              ends_array_mc_block, num_integ_points, nmo, Eigenval(:, 1, :), &
    1677              :                                              tau_tj, tau_wj, cut_memory, Pspin, Qspin, my_open_shell, &
    1678           18 :                                              unit_nr, dbcsr_time, dbcsr_nflop, mp2_env, qs_env)
    1679              :             END IF
    1680           22 :             CALL calc_post_loop_forces(force_data, unit_nr, qs_env)
    1681              :          END IF !laplace SOS-MP2
    1682              : 
    1683          442 :          IF (calc_forces .AND. do_im_time .AND. .NOT. do_ri_sos_laplace_mp2) THEN
    1684           64 :             DO ispin = 1, nspins
    1685              :                CALL calc_rpa_loop_forces(force_data, mat_P_omega(:, 1, :), t_3c_M, t_3c_O(1, 1), &
    1686              :                                          t_3c_O_compressed(1, 1, :), t_3c_O_ind(1, 1, :), fm_scaled_dm_occ_tau, &
    1687              :                                          fm_scaled_dm_virt_tau, fm_mo_coeff_occ, fm_mo_coeff_virt, &
    1688              :                                          fm_mo_coeff_occ_scaled, fm_mo_coeff_virt_scaled, &
    1689              :                                          starts_array_mc, ends_array_mc, starts_array_mc_block, &
    1690              :                                          ends_array_mc_block, num_integ_points, nmo, Eigenval(:, 1, :), &
    1691              :                                          e_fermi(ispin), weights_cos_tf_t_to_w, weights_cos_tf_w_to_t, tj, &
    1692              :                                          wj, tau_tj, cut_memory, ispin, my_open_shell, unit_nr, dbcsr_time, &
    1693           64 :                                          dbcsr_nflop, mp2_env, qs_env)
    1694              :             END DO
    1695           28 :             CALL calc_post_loop_forces(force_data, unit_nr, qs_env)
    1696              :          END IF
    1697              : 
    1698          442 :          IF (do_im_time) THEN
    1699              : 
    1700          148 :             my_flop_rate = REAL(dbcsr_nflop, dp)/(1.0E09_dp*dbcsr_time)
    1701          148 :             IF (unit_nr > 0) WRITE (UNIT=unit_nr, FMT="(/T3,A,T73,ES8.2)") &
    1702           74 :                "PERFORMANCE| DBCSR total number of flops:", REAL(dbcsr_nflop*para_env%num_pe, dp)
    1703          148 :             IF (unit_nr > 0) WRITE (UNIT=unit_nr, FMT="(T3,A,T66,F15.2)") &
    1704           74 :                "PERFORMANCE| DBCSR total execution time:", dbcsr_time
    1705          148 :             IF (unit_nr > 0) WRITE (UNIT=unit_nr, FMT="(T3,A,T66,F15.2)") &
    1706           74 :                "PERFORMANCE| DBCSR flop rate (Gflops / MPI rank):", my_flop_rate
    1707              : 
    1708              :          ELSE
    1709              : 
    1710          294 :             CALL dgemm_counter_write(dgemm_counter, para_env)
    1711              : 
    1712              :          END IF
    1713              : 
    1714              :          ! GW: for low-scaling calculation: Compute self-energy Sigma(i*tau), Sigma(i*omega)
    1715              :          ! for low-scaling and ordinary-scaling: analytic continuation from Sigma(iw) -> Sigma(w)
    1716              :          !                                       and correction of quasiparticle energies e_n^GW
    1717          756 :          IF (my_do_gw) THEN
    1718              : 
    1719              :             CALL compute_QP_energies(vec_Sigma_c_gw, count_ev_sc_GW, gw_corr_lev_occ, &
    1720              :                                      gw_corr_lev_tot, gw_corr_lev_virt, homo, &
    1721              :                                      nmo, num_fit_points, num_integ_points, &
    1722              :                                      unit_nr, do_apply_ic_corr_to_gw, do_im_time, &
    1723              :                                      do_periodic, do_ri_Sigma_x, first_cycle_periodic_correction, &
    1724              :                                      e_fermi, eps_filter, fermi_level_offset, &
    1725              :                                      delta_corr, Eigenval, &
    1726              :                                      Eigenval_last, Eigenval_scf, iter_sc_GW0, exit_ev_gw, tau_tj, tj, &
    1727              :                                      vec_omega_fit_gw, vec_Sigma_x_gw, mp2_env%ri_g0w0%ic_corr_list, &
    1728              :                                      weights_cos_tf_t_to_w, weights_sin_tf_t_to_w, &
    1729              :                                      fm_mo_coeff_occ_scaled, fm_mo_coeff_virt_scaled, fm_mo_coeff_occ, &
    1730              :                                      fm_mo_coeff_virt, fm_scaled_dm_occ_tau, fm_scaled_dm_virt_tau, &
    1731              :                                      mo_coeff(1), fm_mat_W, para_env, para_env_RPA, mat_dm, mat_MinvVMinv, &
    1732              :                                      t_3c_O, t_3c_M, t_3c_overl_int_ao_mo, t_3c_O_compressed, t_3c_O_mo_compressed, &
    1733              :                                      t_3c_O_ind, t_3c_O_mo_ind, &
    1734              :                                      t_3c_overl_int_gw_RI, t_3c_overl_int_gw_AO, &
    1735              :                                      matrix_berry_im_mo_mo, matrix_berry_re_mo_mo, mat_W, matrix_s, &
    1736              :                                      kpoints, mp2_env, qs_env, nkp_self_energy, do_kpoints_cubic_RPA, &
    1737          244 :                                      starts_array_mc, ends_array_mc)
    1738              : 
    1739              :             ! if HOMO-LUMO gap differs by less than mp2_env%ri_g0w0%eps_ev_sc_iter, exit ev sc GW loop
    1740          244 :             IF (exit_ev_gw) EXIT
    1741              : 
    1742              :          END IF ! my_do_gw if
    1743              : 
    1744              :       END DO ! evGW loop
    1745              : 
    1746          314 :       IF (do_ic_model) THEN
    1747              : 
    1748            2 :          IF (my_open_shell) THEN
    1749              : 
    1750              :             CALL calculate_ic_correction(Eigenval(:, 1, 1), mat_MinvVMinv%matrix, &
    1751              :                                          t_3c_overl_nnP_ic(1), t_3c_overl_nnP_ic_reflected(1), &
    1752              :                                          gw_corr_lev_tot, &
    1753              :                                          gw_corr_lev_occ(1), gw_corr_lev_virt(1), homo(1), unit_nr, &
    1754            0 :                                          print_ic_values, para_env, do_alpha=.TRUE.)
    1755              : 
    1756              :             CALL calculate_ic_correction(Eigenval(:, 1, 2), mat_MinvVMinv%matrix, &
    1757              :                                          t_3c_overl_nnP_ic(2), t_3c_overl_nnP_ic_reflected(2), &
    1758              :                                          gw_corr_lev_tot, &
    1759              :                                          gw_corr_lev_occ(2), gw_corr_lev_virt(2), homo(2), unit_nr, &
    1760            0 :                                          print_ic_values, para_env, do_beta=.TRUE.)
    1761              : 
    1762              :          ELSE
    1763              : 
    1764              :             CALL calculate_ic_correction(Eigenval(:, 1, 1), mat_MinvVMinv%matrix, &
    1765              :                                          t_3c_overl_nnP_ic(1), t_3c_overl_nnP_ic_reflected(1), &
    1766              :                                          gw_corr_lev_tot, &
    1767              :                                          gw_corr_lev_occ(1), gw_corr_lev_virt(1), homo(1), unit_nr, &
    1768            2 :                                          print_ic_values, para_env)
    1769              : 
    1770              :          END IF
    1771              : 
    1772              :       END IF
    1773              : 
    1774              :       ! postprocessing after GW for Bethe-Salpeter
    1775          314 :       IF (do_bse) THEN
    1776              :          ! Check used GW flavor; in Case of evGW we use W0 for BSE
    1777              :          ! Use environment variable, since local iter_evGW is overwritten if evGW0 is invoked
    1778           42 :          IF (mp2_env%ri_g0w0%iter_evGW > 1) THEN
    1779            4 :             IF (unit_nr > 0) THEN
    1780              :                CALL cp_warn(__LOCATION__, &
    1781            2 :                             "BSE@evGW applies W0, i.e. screening with DFT energies to the BSE!")
    1782              :             END IF
    1783              :          END IF
    1784              :          ! Create a per-spin copy of fm_mat_S for usage in BSE
    1785          176 :          ALLOCATE (fm_mat_S_ia_bse(nspins))
    1786           92 :          DO ispin = 1, nspins
    1787           50 :             CALL cp_fm_create(fm_mat_S_ia_bse(ispin), fm_mat_S(ispin)%matrix_struct)
    1788           50 :             CALL cp_fm_to_fm(fm_mat_S(ispin), fm_mat_S_ia_bse(ispin))
    1789              :             ! Remove energy/frequency factor from 3c-Integral for BSE
    1790           92 :             IF (iter_sc_gw0 == 1) THEN
    1791              :                CALL remove_scaling_factor_rpa(fm_mat_S_ia_bse(ispin), virtual(ispin), &
    1792           38 :                                               Eigenval_last(:, 1, ispin), homo(ispin), omega)
    1793              :             ELSE
    1794              :                CALL remove_scaling_factor_rpa(fm_mat_S_ia_bse(ispin), virtual(ispin), &
    1795           12 :                                               Eigenval_scf(:, 1, ispin), homo(ispin), omega)
    1796              :             END IF
    1797              :          END DO
    1798              :          ! Main routine for all BSE postprocessing
    1799              :          CALL start_bse_calculation(fm_mat_S_ia_bse, fm_mat_S_ij_bse, fm_mat_S_ab_bse, &
    1800              :                                     fm_mat_Q_static_bse_gemm, &
    1801              :                                     Eigenval, Eigenval_scf, &
    1802              :                                     homo, virtual, dimen_RI, dimen_RI_red, bse_lev_virt, &
    1803           42 :                                     gd_array, color_sub, mp2_env, qs_env, mo_coeff, unit_nr)
    1804              :          ! Release per-spin BSE-copy of fm_mat_S
    1805           92 :          DO ispin = 1, nspins
    1806           92 :             CALL cp_fm_release(fm_mat_S_ia_bse(ispin))
    1807              :          END DO
    1808           42 :          DEALLOCATE (fm_mat_S_ia_bse)
    1809              :       END IF
    1810              : 
    1811          314 :       IF (my_do_gw) THEN
    1812              :          CALL deallocate_matrices_gw(fm_mat_S_gw_work, vec_W_gw, vec_Sigma_c_gw, vec_omega_fit_gw, &
    1813              :                                      mp2_env%ri_g0w0%vec_Sigma_x_minus_vxc_gw, &
    1814              :                                      Eigenval_last, Eigenval_scf, do_periodic, matrix_berry_re_mo_mo, matrix_berry_im_mo_mo, &
    1815          116 :                                      kpoints, vec_Sigma_x_gw,.NOT. do_im_time)
    1816              :       END IF
    1817              : 
    1818          314 :       IF (do_im_time) THEN
    1819              : 
    1820              :          CALL dealloc_im_time(fm_mo_coeff_occ, fm_mo_coeff_virt, &
    1821              :                               fm_scaled_dm_occ_tau, fm_scaled_dm_virt_tau, index_to_cell_3c, &
    1822              :                               cell_to_index_3c, do_ic_model, &
    1823              :                               do_kpoints_cubic_RPA, do_kpoints_from_Gamma, do_ri_Sigma_x, &
    1824              :                               has_mat_P_blocks, &
    1825              :                               wkp_W, cfm_mat_Q, fm_mat_Minv_L_kpoints, fm_mat_L_kpoints, &
    1826              :                               fm_matrix_Minv, fm_matrix_Minv_Vtrunc_Minv, fm_mat_RI_global_work, fm_mat_work, &
    1827              :                               fm_mo_coeff_occ_scaled, fm_mo_coeff_virt_scaled, mat_dm, mat_L, &
    1828              :                               mat_MinvVMinv, mat_P_omega, mat_P_omega_kp, &
    1829          136 :                               t_3c_M, t_3c_O, t_3c_O_compressed, t_3c_O_ind, mat_work, qs_env)
    1830              : 
    1831          136 :          IF (my_do_gw) THEN
    1832              :             CALL deallocate_matrices_gw_im_time(weights_cos_tf_w_to_t, weights_sin_tf_t_to_w, do_ic_model, &
    1833              :                                                 do_kpoints_cubic_RPA, fm_mat_W, &
    1834              :                                                 t_3c_overl_int_ao_mo, t_3c_O_mo_compressed, t_3c_O_mo_ind, &
    1835              :                                                 t_3c_overl_int_gw_RI, t_3c_overl_int_gw_AO, &
    1836              :                                                 t_3c_overl_nnP_ic, t_3c_overl_nnP_ic_reflected, &
    1837           46 :                                                 mat_W, qs_env)
    1838              :          END IF
    1839              : 
    1840              :       END IF
    1841              : 
    1842          314 :       IF (.NOT. do_im_time .AND. .NOT. do_ri_sos_laplace_mp2) CALL exchange_work%release()
    1843              : 
    1844          314 :       IF (.NOT. do_ri_sos_laplace_mp2) THEN
    1845          256 :          DEALLOCATE (tj)
    1846          256 :          DEALLOCATE (wj)
    1847          256 :          DEALLOCATE (trace_Qomega)
    1848              :       END IF
    1849              : 
    1850          314 :       IF (do_im_time .OR. do_ri_sos_laplace_mp2) THEN
    1851          164 :          DEALLOCATE (tau_tj)
    1852          164 :          DEALLOCATE (tau_wj)
    1853              :       END IF
    1854              : 
    1855          314 :       IF (do_im_time .AND. calc_forces) THEN
    1856           50 :          CALL im_time_force_release(force_data)
    1857              :       END IF
    1858              : 
    1859          314 :       IF (calc_forces .AND. .NOT. do_im_time) CALL rpa_grad_finalize(rpa_grad, mp2_env, para_env_sub, para_env, &
    1860              :                                                                      qs_env, gd_array, color_sub, do_ri_sos_laplace_mp2, &
    1861           44 :                                                                      homo, virtual)
    1862              : 
    1863          314 :       CALL timestop(handle)
    1864              : 
    1865         6402 :    END SUBROUTINE rpa_num_int
    1866              : 
    1867              : END MODULE rpa_main
        

Generated by: LCOV version 2.0-1