LCOV - code coverage report
Current view: top level - src - mp2_integrals.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:9ccafda) Lines: 95.7 % 557 533
Test Date: 2026-10-15 00:55:44 Functions: 77.8 % 9 7

            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 and distribute 2c- and 3c- integrals for RI
      10              : !> \par History
      11              : !>      06.2012 created [Mauro Del Ben]
      12              : !>      03.2019 separated from mp2_ri_gpw [Frederick Stein]
      13              : ! **************************************************************************************************
      14              : MODULE mp2_integrals
      15              :    USE OMP_LIB,                         ONLY: omp_get_num_threads,&
      16              :                                               omp_get_thread_num
      17              :    USE atomic_kind_types,               ONLY: atomic_kind_type
      18              :    USE basis_set_types,                 ONLY: gto_basis_set_p_type,&
      19              :                                               gto_basis_set_type
      20              :    USE bibliography,                    ONLY: DelBen2013,&
      21              :                                               cite_reference
      22              :    USE cell_types,                      ONLY: cell_type,&
      23              :                                               get_cell
      24              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      25              :    USE cp_cfm_types,                    ONLY: cp_cfm_type
      26              :    USE cp_control_types,                ONLY: dft_control_type
      27              :    USE cp_dbcsr_api,                    ONLY: &
      28              :         dbcsr_copy, dbcsr_create, dbcsr_get_info, dbcsr_multiply, dbcsr_p_type, dbcsr_release, &
      29              :         dbcsr_release_p, dbcsr_set, dbcsr_type, dbcsr_type_no_symmetry
      30              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      31              :                                               cp_dbcsr_m_by_n_from_template
      32              :    USE cp_eri_mme_interface,            ONLY: cp_eri_mme_param,&
      33              :                                               cp_eri_mme_set_params
      34              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      35              :                                               cp_fm_struct_release,&
      36              :                                               cp_fm_struct_type
      37              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      38              :                                               cp_fm_get_info,&
      39              :                                               cp_fm_release,&
      40              :                                               cp_fm_type
      41              :    USE cp_log_handling,                 ONLY: cp_to_string
      42              :    USE cp_units,                        ONLY: cp_unit_from_cp2k
      43              :    USE dbt_api,                         ONLY: &
      44              :         dbt_clear, dbt_contract, dbt_copy, dbt_create, dbt_destroy, dbt_distribution_destroy, &
      45              :         dbt_distribution_new, dbt_distribution_type, dbt_filter, dbt_get_block, dbt_get_info, &
      46              :         dbt_get_stored_coordinates, dbt_mp_environ_pgrid, dbt_pgrid_create, dbt_pgrid_destroy, &
      47              :         dbt_pgrid_type, dbt_put_block, dbt_reserve_blocks, dbt_scale, dbt_split_blocks, dbt_type
      48              :    USE group_dist_types,                ONLY: create_group_dist,&
      49              :                                               get_group_dist,&
      50              :                                               group_dist_d1_type
      51              :    USE hfx_types,                       ONLY: alloc_containers,&
      52              :                                               block_ind_type,&
      53              :                                               hfx_compression_type
      54              :    USE input_constants,                 ONLY: &
      55              :         do_eri_gpw, do_eri_mme, do_eri_os, do_potential_coulomb, do_potential_id, &
      56              :         do_potential_long, do_potential_short, do_potential_truncated, kp_weights_W_auto, &
      57              :         kp_weights_W_tailored, kp_weights_W_uniform
      58              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      59              :                                               section_vals_type,&
      60              :                                               section_vals_val_get
      61              :    USE kinds,                           ONLY: default_string_length,&
      62              :                                               dp,&
      63              :                                               int_8
      64              :    USE kpoint_methods,                  ONLY: kpoint_init_cell_index
      65              :    USE kpoint_types,                    ONLY: kpoint_type
      66              :    USE libint_2c_3c,                    ONLY: compare_potential_types,&
      67              :                                               libint_potential_type
      68              :    USE machine,                         ONLY: m_flush
      69              :    USE message_passing,                 ONLY: mp_cart_type,&
      70              :                                               mp_comm_type,&
      71              :                                               mp_para_env_type
      72              :    USE mp2_eri,                         ONLY: mp2_eri_3c_integrate
      73              :    USE mp2_eri_gpw,                     ONLY: cleanup_gpw,&
      74              :                                               mp2_eri_3c_integrate_gpw,&
      75              :                                               prepare_gpw
      76              :    USE mp2_ri_2c,                       ONLY: get_2c_integrals
      77              :    USE mp2_types,                       ONLY: three_dim_real_array
      78              :    USE particle_methods,                ONLY: get_particle_set
      79              :    USE particle_types,                  ONLY: particle_type
      80              :    USE pw_env_types,                    ONLY: pw_env_type
      81              :    USE pw_poisson_types,                ONLY: pw_poisson_type
      82              :    USE pw_pool_types,                   ONLY: pw_pool_type
      83              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      84              :                                               pw_r3d_rs_type
      85              :    USE qs_environment_types,            ONLY: get_qs_env,&
      86              :                                               qs_environment_type,&
      87              :                                               set_qs_env
      88              :    USE qs_integral_utils,               ONLY: basis_set_list_setup
      89              :    USE qs_interactions,                 ONLY: init_interaction_radii_orb_basis
      90              :    USE qs_kind_types,                   ONLY: qs_kind_type
      91              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      92              :    USE qs_tensors,                      ONLY: build_3c_integrals,&
      93              :                                               build_3c_neighbor_lists,&
      94              :                                               compress_tensor,&
      95              :                                               get_tensor_occupancy,&
      96              :                                               neighbor_list_3c_destroy
      97              :    USE qs_tensors_types,                ONLY: create_3c_tensor,&
      98              :                                               create_tensor_batches,&
      99              :                                               distribution_3d_create,&
     100              :                                               distribution_3d_type,&
     101              :                                               neighbor_list_3c_type,&
     102              :                                               pgf_block_sizes
     103              :    USE task_list_types,                 ONLY: task_list_type
     104              :    USE util,                            ONLY: get_limit
     105              : #include "./base/base_uses.f90"
     106              : 
     107              :    IMPLICIT NONE
     108              : 
     109              :    PRIVATE
     110              : 
     111              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mp2_integrals'
     112              : 
     113              :    PUBLIC :: mp2_ri_gpw_compute_in, compute_kpoints
     114              : 
     115              :    TYPE intermediate_matrix_type
     116              :       TYPE(dbcsr_type) :: matrix_ia_jnu, matrix_ia_jb
     117              :       INTEGER :: max_row_col_local = 0
     118              :       INTEGER, ALLOCATABLE, DIMENSION(:, :) :: local_col_row_info
     119              :       TYPE(cp_fm_type) :: fm_BIb_jb = cp_fm_type()
     120              :       CHARACTER(LEN=default_string_length) :: descr = ""
     121              :    END TYPE intermediate_matrix_type
     122              : 
     123              : CONTAINS
     124              : 
     125              : ! **************************************************************************************************
     126              : !> \brief with ri mp2 gpw
     127              : !> \param BIb_C ...
     128              : !> \param BIb_C_gw ...
     129              : !> \param BIb_C_bse_ij ...
     130              : !> \param BIb_C_bse_ab ...
     131              : !> \param gd_array ...
     132              : !> \param gd_B_virtual ...
     133              : !> \param dimen_RI ...
     134              : !> \param dimen_RI_red ...
     135              : !> \param qs_env ...
     136              : !> \param para_env ...
     137              : !> \param para_env_sub ...
     138              : !> \param color_sub ...
     139              : !> \param cell ...
     140              : !> \param particle_set ...
     141              : !> \param atomic_kind_set ...
     142              : !> \param qs_kind_set ...
     143              : !> \param fm_matrix_PQ ...
     144              : !> \param cfm_matrix_L_kpoints ...
     145              : !> \param cfm_matrix_Minv_L_kpoints ...
     146              : !> \param fm_matrix_Minv_L_gamma real Gamma-point factor used by the real-valued RPA path
     147              : !> \param fm_matrix_Minv ...
     148              : !> \param fm_matrix_Minv_Vtrunc_Minv ...
     149              : !> \param nmo ...
     150              : !> \param homo ...
     151              : !> \param mat_munu ...
     152              : !> \param sab_orb_sub ...
     153              : !> \param mo_coeff_o ...
     154              : !> \param mo_coeff_v ...
     155              : !> \param mo_coeff_all ...
     156              : !> \param mo_coeff_gw ...
     157              : !> \param mo_coeff_o_bse ...
     158              : !> \param mo_coeff_v_bse ...
     159              : !> \param eps_filter ...
     160              : !> \param unit_nr ...
     161              : !> \param mp2_memory ...
     162              : !> \param calc_PQ_cond_num ...
     163              : !> \param calc_forces ...
     164              : !> \param blacs_env_sub ...
     165              : !> \param my_do_gw ...
     166              : !> \param do_bse ...
     167              : !> \param gd_B_all ...
     168              : !> \param starts_array_mc ...
     169              : !> \param ends_array_mc ...
     170              : !> \param starts_array_mc_block ...
     171              : !> \param ends_array_mc_block ...
     172              : !> \param gw_corr_lev_occ ...
     173              : !> \param gw_corr_lev_virt ...
     174              : !> \param bse_lev_virt ...
     175              : !> \param do_im_time ...
     176              : !> \param do_kpoints_cubic_RPA ...
     177              : !> \param kpoints ...
     178              : !> \param t_3c_M ...
     179              : !> \param t_3c_O ...
     180              : !> \param t_3c_O_compressed ...
     181              : !> \param t_3c_O_ind ...
     182              : !> \param ri_metric ...
     183              : !> \param gd_B_occ_bse ...
     184              : !> \param gd_B_virt_bse ...
     185              : !> \author Mauro Del Ben
     186              : ! **************************************************************************************************
     187         5568 :    SUBROUTINE mp2_ri_gpw_compute_in(BIb_C, BIb_C_gw, BIb_C_bse_ij, BIb_C_bse_ab, gd_array, gd_B_virtual, &
     188              :                                     dimen_RI, dimen_RI_red, qs_env, para_env, para_env_sub, color_sub, &
     189              :                                     cell, particle_set, atomic_kind_set, qs_kind_set, &
     190              :                                     fm_matrix_PQ, cfm_matrix_L_kpoints, cfm_matrix_Minv_L_kpoints, fm_matrix_Minv_L_gamma, &
     191              :                                     fm_matrix_Minv, fm_matrix_Minv_Vtrunc_Minv, &
     192          696 :                                     nmo, homo, mat_munu, &
     193          696 :                                     sab_orb_sub, mo_coeff_o, mo_coeff_v, mo_coeff_all, &
     194          696 :                                     mo_coeff_gw, mo_coeff_o_bse, mo_coeff_v_bse, eps_filter, unit_nr, &
     195              :                                     mp2_memory, calc_PQ_cond_num, calc_forces, blacs_env_sub, my_do_gw, do_bse, &
     196              :                                     gd_B_all, starts_array_mc, ends_array_mc, &
     197              :                                     starts_array_mc_block, ends_array_mc_block, &
     198              :                                     gw_corr_lev_occ, gw_corr_lev_virt, &
     199          696 :                                     bse_lev_virt, &
     200              :                                     do_im_time, do_kpoints_cubic_RPA, kpoints, &
     201              :                                     t_3c_M, t_3c_O, t_3c_O_compressed, t_3c_O_ind, &
     202              :                                     ri_metric, gd_B_occ_bse, gd_B_virt_bse)
     203              : 
     204              :       TYPE(three_dim_real_array), ALLOCATABLE, &
     205              :          DIMENSION(:), INTENT(OUT)                       :: BIb_C, BIb_C_gw, BIb_C_bse_ij, &
     206              :                                                             BIb_C_bse_ab
     207              :       TYPE(group_dist_d1_type), INTENT(OUT)              :: gd_array
     208              :       TYPE(group_dist_d1_type), ALLOCATABLE, &
     209              :          DIMENSION(:), INTENT(OUT)                       :: gd_B_virtual
     210              :       INTEGER, INTENT(OUT)                               :: dimen_RI, dimen_RI_red
     211              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     212              :       TYPE(mp_para_env_type), POINTER                    :: para_env, para_env_sub
     213              :       INTEGER, INTENT(IN)                                :: color_sub
     214              :       TYPE(cell_type), POINTER                           :: cell
     215              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     216              :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     217              :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     218              :       TYPE(cp_fm_type), INTENT(OUT)                      :: fm_matrix_PQ
     219              :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:)       :: cfm_matrix_L_kpoints, &
     220              :                                                             cfm_matrix_Minv_L_kpoints
     221              :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: fm_matrix_Minv_L_gamma, fm_matrix_Minv, &
     222              :                                                             fm_matrix_Minv_Vtrunc_Minv
     223              :       INTEGER, INTENT(IN)                                :: nmo
     224              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: homo
     225              :       TYPE(dbcsr_p_type), INTENT(INOUT)                  :: mat_munu
     226              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     227              :          INTENT(IN), POINTER                             :: sab_orb_sub
     228              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN)       :: mo_coeff_o, mo_coeff_v, mo_coeff_all, &
     229              :                                                             mo_coeff_gw, mo_coeff_o_bse, &
     230              :                                                             mo_coeff_v_bse
     231              :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter
     232              :       INTEGER, INTENT(IN)                                :: unit_nr
     233              :       REAL(KIND=dp), INTENT(IN)                          :: mp2_memory
     234              :       LOGICAL, INTENT(IN)                                :: calc_PQ_cond_num, calc_forces
     235              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env_sub
     236              :       LOGICAL, INTENT(IN)                                :: my_do_gw, do_bse
     237              :       TYPE(group_dist_d1_type), INTENT(OUT)              :: gd_B_all
     238              :       INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(OUT)    :: starts_array_mc, ends_array_mc, &
     239              :                                                             starts_array_mc_block, &
     240              :                                                             ends_array_mc_block
     241              :       INTEGER, INTENT(IN)                                :: gw_corr_lev_occ, gw_corr_lev_virt
     242              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: bse_lev_virt
     243              :       LOGICAL, INTENT(IN)                                :: do_im_time, do_kpoints_cubic_RPA
     244              :       TYPE(kpoint_type), POINTER                         :: kpoints
     245              :       TYPE(dbt_type), INTENT(OUT)                        :: t_3c_M
     246              :       TYPE(dbt_type), ALLOCATABLE, DIMENSION(:, :), &
     247              :          INTENT(OUT)                                     :: t_3c_O
     248              :       TYPE(hfx_compression_type), ALLOCATABLE, &
     249              :          DIMENSION(:, :, :), INTENT(INOUT)               :: t_3c_O_compressed
     250              :       TYPE(block_ind_type), ALLOCATABLE, &
     251              :          DIMENSION(:, :, :)                              :: t_3c_O_ind
     252              :       TYPE(libint_potential_type), INTENT(IN)            :: ri_metric
     253              :       TYPE(group_dist_d1_type), ALLOCATABLE, &
     254              :          DIMENSION(:), INTENT(OUT)                       :: gd_B_occ_bse, gd_B_virt_bse
     255              : 
     256              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'mp2_ri_gpw_compute_in'
     257              : 
     258              :       INTEGER :: cm, cut_memory, cut_memory_int, eri_method, gw_corr_lev_total, handle, handle2, &
     259              :          handle4, i, i_counter, i_mem, ibasis, ispin, itmp(2), j, jcell, kcell, LLL, min_bsize, &
     260              :          my_B_all_end, my_B_all_size, my_B_all_start, my_group_L_end, my_group_L_size, &
     261              :          my_group_L_start, n_rep, natom, ngroup, nimg, nkind, nspins, potential_type, &
     262              :          ri_metric_type
     263              :       INTEGER(int_8)                                     :: nze
     264          696 :       INTEGER, ALLOCATABLE, DIMENSION(:) :: dist_AO_1, dist_AO_2, dist_RI, &
     265          696 :          ends_array_mc_block_int, ends_array_mc_int, my_B_occ_bse_end, my_B_occ_bse_size, &
     266          696 :          my_B_occ_bse_start, my_B_size, my_B_virt_bse_end, my_B_virt_bse_size, &
     267         1392 :          my_B_virt_bse_start, my_B_virtual_end, my_B_virtual_start, sizes_AO, sizes_AO_split, &
     268         1392 :          sizes_RI, sizes_RI_split, starts_array_mc_block_int, starts_array_mc_int, virtual
     269              :       INTEGER, DIMENSION(2, 3)                           :: bounds
     270              :       INTEGER, DIMENSION(3)                              :: bounds_3c, pcoord, pdims, pdims_t3c, &
     271              :                                                             periodic
     272              :       LOGICAL                                            :: do_gpw, do_kpoints_from_Gamma, do_svd, &
     273              :                                                             memory_info
     274              :       REAL(KIND=dp) :: compression_factor, cutoff_old, eps_pgf_orb, eps_pgf_orb_old, eps_svd, &
     275              :          mem_for_abK, mem_for_iaK, mem_for_ijK, memory_3c, occ, omega_pot, rc_ang, &
     276              :          relative_cutoff_old
     277          696 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: e_cutoff_old
     278          696 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: my_Lrows, my_Vrows
     279              :       TYPE(cp_eri_mme_param), POINTER                    :: eri_param
     280          696 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mat_munu_local_L
     281         3480 :       TYPE(dbt_pgrid_type)                               :: pgrid_t3c_M, pgrid_t3c_overl
     282         9048 :       TYPE(dbt_type)                                     :: t_3c_overl_int_template, t_3c_tmp
     283          696 :       TYPE(dbt_type), ALLOCATABLE, DIMENSION(:, :)       :: t_3c_overl_int
     284              :       TYPE(dft_control_type), POINTER                    :: dft_control
     285              :       TYPE(distribution_3d_type)                         :: dist_3d
     286          696 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_ao, basis_set_ri_aux
     287              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis, ri_basis
     288              :       TYPE(intermediate_matrix_type), ALLOCATABLE, &
     289          696 :          DIMENSION(:)                                    :: intermed_mat, intermed_mat_bse_ab, &
     290          696 :                                                             intermed_mat_bse_ij, intermed_mat_gw
     291          696 :       TYPE(mp_cart_type)                                 :: mp_comm_t3c_2
     292              :       TYPE(neighbor_list_3c_type)                        :: nl_3c
     293              :       TYPE(pw_c1d_gs_type)                               :: pot_g, rho_g
     294              :       TYPE(pw_env_type), POINTER                         :: pw_env_sub
     295              :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     296              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     297              :       TYPE(pw_r3d_rs_type)                               :: psi_L, rho_r
     298              :       TYPE(section_vals_type), POINTER                   :: qs_section
     299              :       TYPE(task_list_type), POINTER                      :: task_list_sub
     300              : 
     301          696 :       CALL timeset(routineN, handle)
     302              : 
     303          696 :       CALL cite_reference(DelBen2013)
     304              : 
     305          696 :       nspins = SIZE(homo)
     306              : 
     307         2088 :       ALLOCATE (virtual(nspins))
     308         1554 :       virtual(:) = nmo - homo(:)
     309          696 :       gw_corr_lev_total = gw_corr_lev_virt + gw_corr_lev_occ
     310              : 
     311          696 :       eri_method = qs_env%mp2_env%eri_method
     312          696 :       eri_param => qs_env%mp2_env%eri_mme_param
     313          696 :       do_svd = qs_env%mp2_env%do_svd
     314          696 :       eps_svd = qs_env%mp2_env%eps_svd
     315          696 :       potential_type = qs_env%mp2_env%potential_parameter%potential_type
     316          696 :       ri_metric_type = ri_metric%potential_type
     317          696 :       omega_pot = qs_env%mp2_env%potential_parameter%omega
     318              : 
     319              :       ! whether we need gpw integrals (plus pw stuff)
     320              :       do_gpw = (eri_method == do_eri_gpw) .OR. &
     321              :                ((potential_type == do_potential_long .OR. ri_metric_type == do_potential_long) &
     322              :                 .AND. qs_env%mp2_env%eri_method == do_eri_os) &
     323          696 :                .OR. (ri_metric_type == do_potential_id .AND. qs_env%mp2_env%eri_method == do_eri_mme)
     324              : 
     325          696 :       IF (do_svd .AND. calc_forces) THEN
     326            0 :          CPABORT("SVD not implemented for forces.!")
     327              :       END IF
     328              : 
     329          696 :       do_kpoints_from_Gamma = qs_env%mp2_env%ri_rpa_im_time%do_kpoints_from_Gamma
     330          696 :       IF (do_kpoints_cubic_RPA .OR. do_kpoints_from_Gamma) THEN
     331              :          CALL get_qs_env(qs_env=qs_env, &
     332           22 :                          kpoints=kpoints)
     333              :       END IF
     334           22 :       IF (do_kpoints_from_Gamma) THEN
     335           16 :          CALL compute_kpoints(qs_env, kpoints, unit_nr)
     336              :       END IF
     337              : 
     338          696 :       IF (do_bse) THEN
     339           56 :          IF (.NOT. my_do_gw) THEN
     340            0 :             CALL cp_abort(__LOCATION__, "BSE calculations require prior GW calculations.")
     341              :          END IF
     342           56 :          IF (do_im_time) THEN
     343            0 :             CALL cp_abort(__LOCATION__, "BSE calculations are not implemented for low-scaling GW.")
     344              :          END IF
     345              :          ! GPW integrals have to be implemented later
     346           56 :          IF (eri_method == do_eri_gpw) THEN
     347              :             CALL cp_abort(__LOCATION__, &
     348              :                           "BSE calculations are not implemented for GPW integrals. "// &
     349              :                           "This is probably caused by invoking a periodic calculation. "// &
     350            0 :                           "Use PERIODIC NONE for BSE calculations.")
     351              :          END IF
     352              :       END IF
     353              : 
     354          696 :       ngroup = para_env%num_pe/para_env_sub%num_pe
     355              : 
     356              :       ! Preparations for MME method to compute ERIs
     357          696 :       IF (qs_env%mp2_env%eri_method == do_eri_mme) THEN
     358              :          ! cell might have changed, so we need to reset parameters
     359          126 :          CALL cp_eri_mme_set_params(eri_param, cell, qs_kind_set, basis_type_1="ORB", basis_type_2="RI_AUX", para_env=para_env)
     360              :       END IF
     361              : 
     362          696 :       CALL get_cell(cell=cell, periodic=periodic)
     363              :       ! for minimax Ewald summation, full periodicity is required
     364          696 :       IF (eri_method == do_eri_mme) THEN
     365          126 :          CPASSERT(periodic(1) == 1 .AND. periodic(2) == 1 .AND. periodic(3) == 1)
     366              :       END IF
     367              : 
     368          696 :       IF (do_svd .AND. (do_kpoints_from_Gamma .OR. do_kpoints_cubic_RPA)) THEN
     369            0 :          CPABORT("SVD with kpoints not implemented yet!")
     370              :       END IF
     371              : 
     372              :       CALL get_2c_integrals(qs_env, eri_method, eri_param, para_env, para_env_sub, mp2_memory, &
     373              :                             my_Lrows, my_Vrows, fm_matrix_PQ, ngroup, color_sub, dimen_RI, dimen_RI_red, &
     374              :                             kpoints, my_group_L_size, my_group_L_start, my_group_L_end, &
     375              :                             gd_array, calc_PQ_cond_num .AND. .NOT. do_svd, do_svd, eps_svd, &
     376              :                             qs_env%mp2_env%potential_parameter, ri_metric, &
     377              :                             cfm_matrix_L_kpoints, cfm_matrix_Minv_L_kpoints, fm_matrix_Minv_L_gamma, &
     378              :                             fm_matrix_Minv, fm_matrix_Minv_Vtrunc_Minv, &
     379              :                             do_im_time, do_kpoints_from_Gamma .OR. do_kpoints_cubic_RPA, qs_env%mp2_env%mp2_gpw%eps_pgf_orb_S, &
     380         2066 :                             qs_kind_set, sab_orb_sub, calc_forces, unit_nr)
     381              : 
     382          696 :       IF (unit_nr > 0) THEN
     383              :          ASSOCIATE (ri_metric => qs_env%mp2_env%ri_metric)
     384          612 :             SELECT CASE (ri_metric%potential_type)
     385              :             CASE (do_potential_coulomb)
     386              :                WRITE (unit_nr, FMT="(/T3,A,T74,A)") &
     387          264 :                   "RI_INFO| RI metric: ", "COULOMB"
     388              :             CASE (do_potential_short)
     389              :                WRITE (unit_nr, FMT="(T3,A,T71,A)") &
     390            0 :                   "RI_INFO| RI metric: ", "SHORTRANGE"
     391              :                WRITE (unit_nr, '(T3,A,T61,F20.10)') &
     392            0 :                   "RI_INFO| Omega:     ", ri_metric%omega
     393            0 :                rc_ang = cp_unit_from_cp2k(ri_metric%cutoff_radius, "angstrom")
     394              :                WRITE (unit_nr, '(T3,A,T61,F20.10)') &
     395            0 :                   "RI_INFO| Cutoff Radius [angstrom]:     ", rc_ang
     396              :             CASE (do_potential_long)
     397              :                WRITE (unit_nr, FMT="(T3,A,T72,A)") &
     398            8 :                   "RI_INFO| RI metric: ", "LONGRANGE"
     399              :                WRITE (unit_nr, '(T3,A,T61,F20.10)') &
     400            8 :                   "RI_INFO| Omega:     ", ri_metric%omega
     401              :             CASE (do_potential_id)
     402              :                WRITE (unit_nr, FMT="(T3,A,T74,A)") &
     403           45 :                   "RI_INFO| RI metric: ", "OVERLAP"
     404              :             CASE (do_potential_truncated)
     405              :                WRITE (unit_nr, FMT="(T3,A,T64,A)") &
     406           31 :                   "RI_INFO| RI metric: ", "TRUNCATED COULOMB"
     407           31 :                rc_ang = cp_unit_from_cp2k(ri_metric%cutoff_radius, "angstrom")
     408              :                WRITE (unit_nr, '(T3,A,T61,F20.2)') &
     409          379 :                   "RI_INFO| Cutoff Radius [angstrom]:     ", rc_ang
     410              :             END SELECT
     411              :          END ASSOCIATE
     412              :       END IF
     413              : 
     414          696 :       IF (calc_forces .AND. .NOT. do_im_time) THEN
     415              :          ! we need (P|Q)^(-1/2) for future use, just save it
     416              :          ! in a fully (home made) distributed way
     417          272 :          itmp = get_limit(dimen_RI, para_env_sub%num_pe, para_env_sub%mepos)
     418          272 :          lll = itmp(2) - itmp(1) + 1
     419         1088 :          ALLOCATE (qs_env%mp2_env%ri_grad%PQ_half(lll, my_group_L_size))
     420       972108 :          qs_env%mp2_env%ri_grad%PQ_half(:, :) = my_Lrows(itmp(1):itmp(2), 1:my_group_L_size)
     421          272 :          IF (.NOT. compare_potential_types(qs_env%mp2_env%ri_metric, qs_env%mp2_env%potential_parameter)) THEN
     422           36 :             ALLOCATE (qs_env%mp2_env%ri_grad%operator_half(lll, my_group_L_size))
     423        41844 :             qs_env%mp2_env%ri_grad%operator_half(:, :) = my_Vrows(itmp(1):itmp(2), 1:my_group_L_size)
     424           12 :             DEALLOCATE (my_Vrows)
     425              :          END IF
     426              :       END IF
     427              : 
     428          696 :       IF (unit_nr > 0) THEN
     429              :          WRITE (UNIT=unit_nr, FMT="(T3,A,T75,i6)") &
     430          348 :             "RI_INFO| Number of auxiliary basis functions:", dimen_RI, &
     431          348 :             "GENERAL_INFO| Number of basis functions:", nmo, &
     432          348 :             "GENERAL_INFO| Number of occupied orbitals:", homo(1), &
     433          696 :             "GENERAL_INFO| Number of virtual orbitals:", virtual(1)
     434          348 :          IF (do_svd) THEN
     435              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T75,i6)") &
     436           23 :                "RI_INFO| Reduced auxiliary basis set size:", dimen_RI_red
     437              :          END IF
     438              : 
     439          777 :          mem_for_iaK = dimen_RI*REAL(SUM(homo*virtual), KIND=dp)*8.0_dp/(1024_dp**2)
     440          777 :          mem_for_ijK = dimen_RI*REAL(SUM(homo(1:nspins)**2), KIND=dp)*8.0_dp/(1024_dp**2)
     441          777 :          mem_for_abK = dimen_RI*REAL(SUM(bse_lev_virt(1:nspins)**2), KIND=dp)*8.0_dp/(1024_dp**2)
     442              : 
     443          348 :          IF (.NOT. do_im_time) THEN
     444          276 :             WRITE (unit_nr, '(T3,A,T66,F11.2,A4)') 'RI_INFO| Total memory for (ia|K) integrals:', &
     445          552 :                mem_for_iaK, ' MiB'
     446          276 :             IF (my_do_gw .AND. .NOT. do_im_time) THEN
     447           44 :                mem_for_iaK = dimen_RI*REAL(nmo, KIND=dp)*gw_corr_lev_total*8.0_dp/(1024_dp**2)
     448              : 
     449           44 :                WRITE (unit_nr, '(T3,A,T66,F11.2,A4)') 'RI_INFO| Total memory for G0W0-(nm|K) integrals:', &
     450           88 :                   mem_for_iaK, ' MiB'
     451              :             END IF
     452              :          END IF
     453          348 :          IF (do_bse) THEN
     454           28 :             WRITE (unit_nr, '(T3,A,T66,F11.2,A4)') 'RI_INFO| Total memory for (ij|K) integrals:', &
     455           56 :                mem_for_ijK, ' MiB'
     456           28 :             WRITE (unit_nr, '(T3,A,T66,F11.2,A4)') 'RI_INFO| Total memory for (ab|K) integrals:', &
     457           56 :                mem_for_abK, ' MiB'
     458              :          END IF
     459          348 :          CALL m_flush(unit_nr)
     460              :       END IF
     461              : 
     462          696 :       CALL para_env%sync() ! sync to see memory output
     463              : 
     464              :       ! in case we do imaginary time, we need the overlap tensor (alpha beta P) or trunc. Coulomb tensor
     465          696 :       IF (.NOT. do_im_time) THEN
     466              : 
     467         4124 :          ALLOCATE (gd_B_virtual(nspins), intermed_mat(nspins))
     468         2208 :          ALLOCATE (my_B_virtual_start(nspins), my_B_virtual_end(nspins), my_B_size(nspins))
     469         1234 :          DO ispin = 1, nspins
     470              : 
     471              :             CALL create_intermediate_matrices(intermed_mat(ispin), mo_coeff_o(ispin)%matrix, virtual(ispin), homo(ispin), &
     472          682 :                                               TRIM(ADJUSTL(cp_to_string(ispin))), blacs_env_sub, para_env_sub)
     473              : 
     474          682 :             CALL create_group_dist(gd_B_virtual(ispin), para_env_sub%num_pe, virtual(ispin))
     475              :             CALL get_group_dist(gd_B_virtual(ispin), para_env_sub%mepos, my_B_virtual_start(ispin), my_B_virtual_end(ispin), &
     476         1234 :                                 my_B_size(ispin))
     477              : 
     478              :          END DO
     479              : 
     480              :          ! in the case of G0W0, we need (K|nm), n,m may be occ or virt (m restricted to corrected levels)
     481          552 :          IF (my_do_gw) THEN
     482              : 
     483          280 :             ALLOCATE (intermed_mat_gw(nspins))
     484          192 :             DO ispin = 1, nspins
     485              :                CALL create_intermediate_matrices(intermed_mat_gw(ispin), mo_coeff_gw(ispin)%matrix, &
     486              :                                                  nmo, gw_corr_lev_total, &
     487              :                                                  "gw_"//TRIM(ADJUSTL(cp_to_string(ispin))), &
     488          192 :                                                  blacs_env_sub, para_env_sub)
     489              : 
     490              :             END DO
     491              : 
     492           88 :             CALL create_group_dist(gd_B_all, para_env_sub%num_pe, nmo)
     493           88 :             CALL get_group_dist(gd_B_all, para_env_sub%mepos, my_B_all_start, my_B_all_end, my_B_all_size)
     494              : 
     495           88 :             IF (do_bse) THEN
     496              :                ! virt x virt slab size bse_lev_virt(ispin) is per-spin, so gd_B_virt_bse is an array;
     497              :                ! the occupied count homo(ispin) is per-spin, so gd_B_occ_bse and the bse intermediates are arrays
     498          552 :                ALLOCATE (intermed_mat_bse_ab(nspins), intermed_mat_bse_ij(nspins), gd_B_occ_bse(nspins), gd_B_virt_bse(nspins))
     499          224 :                ALLOCATE (my_B_occ_bse_start(nspins), my_B_occ_bse_end(nspins), my_B_occ_bse_size(nspins))
     500          224 :                ALLOCATE (my_B_virt_bse_start(nspins), my_B_virt_bse_end(nspins), my_B_virt_bse_size(nspins))
     501          124 :                DO ispin = 1, nspins
     502           68 :                   CALL create_group_dist(gd_B_virt_bse(ispin), para_env_sub%num_pe, bse_lev_virt(ispin))
     503              :                   CALL get_group_dist(gd_B_virt_bse(ispin), para_env_sub%mepos, my_B_virt_bse_start(ispin), &
     504           68 :                                       my_B_virt_bse_end(ispin), my_B_virt_bse_size(ispin))
     505              :                   ! virt x virt matrices
     506              :                   CALL create_intermediate_matrices(intermed_mat_bse_ab(ispin), mo_coeff_v_bse(ispin)%matrix, &
     507              :                                                     bse_lev_virt(ispin), bse_lev_virt(ispin), &
     508           68 :                                                     "bse_ab_"//TRIM(ADJUSTL(cp_to_string(ispin))), blacs_env_sub, para_env_sub)
     509              : 
     510              :                   ! occ x occ matrices
     511              :                   ! We do not implement bse_lev_occ here, because the small number of occupied levels
     512              :                   ! does not critically influence the memory
     513              :                   CALL create_intermediate_matrices(intermed_mat_bse_ij(ispin), mo_coeff_o_bse(ispin)%matrix, &
     514              :                                                     homo(ispin), homo(ispin), &
     515           68 :                                                     "bse_ij_"//TRIM(ADJUSTL(cp_to_string(ispin))), blacs_env_sub, para_env_sub)
     516              : 
     517           68 :                   CALL create_group_dist(gd_B_occ_bse(ispin), para_env_sub%num_pe, homo(ispin))
     518              :                   CALL get_group_dist(gd_B_occ_bse(ispin), para_env_sub%mepos, my_B_occ_bse_start(ispin), &
     519          124 :                                       my_B_occ_bse_end(ispin), my_B_occ_bse_size(ispin))
     520              :                END DO
     521              : 
     522              :             END IF
     523              :          END IF
     524              : 
     525              :          ! array that will store the (ia|K) integrals
     526         2338 :          ALLOCATE (BIb_C(nspins))
     527         1234 :          DO ispin = 1, nspins
     528         3404 :             ALLOCATE (BIb_C(ispin)%array(my_group_L_size, my_B_size(ispin), homo(ispin)))
     529      2080612 :             BIb_C(ispin)%array = 0.0_dp
     530              :          END DO
     531              : 
     532              :          ! in the case of GW, we also need (nm|K)
     533          552 :          IF (my_do_gw) THEN
     534              : 
     535          280 :             ALLOCATE (BIb_C_gw(nspins))
     536          192 :             DO ispin = 1, nspins
     537          520 :                ALLOCATE (BIb_C_gw(ispin)%array(my_group_L_size, my_B_all_size, gw_corr_lev_total))
     538      5914529 :                BIb_C_gw(ispin)%array = 0.0_dp
     539              :             END DO
     540              : 
     541              :          END IF
     542              : 
     543          552 :          IF (do_bse) THEN
     544              : 
     545          304 :             ALLOCATE (BIb_C_bse_ij(nspins), BIb_C_bse_ab(nspins))
     546          124 :             DO ispin = 1, nspins
     547          340 :                ALLOCATE (BIb_C_bse_ij(ispin)%array(my_group_L_size, my_B_occ_bse_size(ispin), homo(ispin)))
     548       109254 :                BIb_C_bse_ij(ispin)%array = 0.0_dp
     549              : 
     550          340 :                ALLOCATE (BIb_C_bse_ab(ispin)%array(my_group_L_size, my_B_virt_bse_size(ispin), bse_lev_virt(ispin)))
     551      3948480 :                BIb_C_bse_ab(ispin)%array = 0.0_dp
     552              :             END DO
     553              : 
     554              :          END IF
     555              : 
     556          552 :          CALL timeset(routineN//"_loop", handle2)
     557              : 
     558              :          IF (eri_method == do_eri_mme .AND. &
     559          552 :              (ri_metric%potential_type == do_potential_coulomb .OR. ri_metric%potential_type == do_potential_long) .OR. &
     560              :              eri_method == do_eri_os .AND. ri_metric%potential_type == do_potential_coulomb) THEN
     561              : 
     562              :             ! Add a warning for automatically generated RI_AUX basis sets
     563              :             ! Tend to be not sufficiently converged
     564          202 :             IF (qs_env%mp2_env%ri_aux_auto_generated) THEN
     565              :                CALL cp_warn(__LOCATION__, &
     566              :                             "At least one RI_AUX basis set was not explicitly invoked in &KIND-section. "// &
     567              :                             "Automatically RI-basis sets and ERI_METHOD OS tend to be not converged. "// &
     568            0 :                             "Consider specifying BASIS_SET RI_AUX explicitly with a sufficiently large basis.")
     569              :             END IF
     570              : 
     571          202 :             NULLIFY (mat_munu_local_L)
     572         7531 :             ALLOCATE (mat_munu_local_L(my_group_L_size))
     573         7127 :             DO LLL = 1, my_group_L_size
     574         6925 :                NULLIFY (mat_munu_local_L(LLL)%matrix)
     575         6925 :                ALLOCATE (mat_munu_local_L(LLL)%matrix)
     576         6925 :                CALL dbcsr_copy(mat_munu_local_L(LLL)%matrix, mat_munu%matrix)
     577         7127 :                CALL dbcsr_set(mat_munu_local_L(LLL)%matrix, 0.0_dp)
     578              :             END DO
     579              :             CALL mp2_eri_3c_integrate(eri_param, ri_metric, para_env_sub, qs_env, &
     580              :                                       first_c=my_group_L_start, last_c=my_group_L_end, &
     581              :                                       mat_ab=mat_munu_local_L, &
     582              :                                       basis_type_a="ORB", basis_type_b="ORB", &
     583              :                                       basis_type_c="RI_AUX", &
     584          202 :                                       sab_nl=sab_orb_sub, eri_method=eri_method)
     585              : 
     586          422 :             DO ispin = 1, nspins
     587         8203 :                DO LLL = 1, my_group_L_size
     588              :                   CALL ao_to_mo_and_store_B(para_env_sub, mat_munu_local_L(LLL), intermed_mat(ispin), &
     589              :                                             BIb_C(ispin)%array(LLL, :, :), &
     590              :                                             mo_coeff_o(ispin)%matrix, mo_coeff_v(ispin)%matrix, &
     591              :                                             eps_filter, &
     592         8203 :                                             my_B_virtual_end(ispin), my_B_virtual_start(ispin))
     593              :                END DO
     594              :                CALL contract_B_L(BIb_C(ispin)%array, my_Lrows, gd_B_virtual(ispin)%sizes, &
     595              :                                  gd_array%sizes, qs_env%mp2_env%eri_blksize, &
     596          422 :                                  ngroup, color_sub, para_env, para_env_sub)
     597              :             END DO
     598              : 
     599          202 :             IF (my_do_gw) THEN
     600              : 
     601          192 :                DO ispin = 1, nspins
     602         4731 :                   DO LLL = 1, my_group_L_size
     603              :                      CALL ao_to_mo_and_store_B(para_env_sub, mat_munu_local_L(LLL), intermed_mat_gw(ispin), &
     604              :                                                BIb_C_gw(ispin)%array(LLL, :, :), &
     605              :                                                mo_coeff_gw(ispin)%matrix, mo_coeff_all(ispin)%matrix, eps_filter, &
     606         4731 :                                                my_B_all_end, my_B_all_start)
     607              :                   END DO
     608              :                   CALL contract_B_L(BIb_C_gw(ispin)%array, my_Lrows, gd_B_all%sizes, gd_array%sizes, qs_env%mp2_env%eri_blksize, &
     609          192 :                                     ngroup, color_sub, para_env, para_env_sub)
     610              :                END DO
     611              :             END IF
     612              : 
     613          202 :             IF (do_bse) THEN
     614              : 
     615          124 :                DO ispin = 1, nspins
     616              :                   ! B^ab_P matrix elements for BSE
     617         3257 :                   DO LLL = 1, my_group_L_size
     618              :                      CALL ao_to_mo_and_store_B(para_env_sub, mat_munu_local_L(LLL), intermed_mat_bse_ab(ispin), &
     619              :                                                BIb_C_bse_ab(ispin)%array(LLL, :, :), &
     620              :                                                mo_coeff_v_bse(ispin)%matrix, mo_coeff_v_bse(ispin)%matrix, eps_filter, &
     621         3257 :                                                my_B_all_end, my_B_all_start)
     622              :                   END DO
     623              :                   CALL contract_B_L(BIb_C_bse_ab(ispin)%array, my_Lrows, gd_B_virt_bse(ispin)%sizes, gd_array%sizes, &
     624           68 :                                     qs_env%mp2_env%eri_blksize, ngroup, color_sub, para_env, para_env_sub)
     625              : 
     626              :                   ! B^ij_P matrix elements for BSE
     627         3257 :                   DO LLL = 1, my_group_L_size
     628              :                      CALL ao_to_mo_and_store_B(para_env_sub, mat_munu_local_L(LLL), intermed_mat_bse_ij(ispin), &
     629              :                                                BIb_C_bse_ij(ispin)%array(LLL, :, :), &
     630              :                                                mo_coeff_o(ispin)%matrix, mo_coeff_o(ispin)%matrix, eps_filter, &
     631         3257 :                                                my_B_occ_bse_end(ispin), my_B_occ_bse_start(ispin))
     632              :                   END DO
     633              :                   CALL contract_B_L(BIb_C_bse_ij(ispin)%array, my_Lrows, gd_B_occ_bse(ispin)%sizes, gd_array%sizes, &
     634          124 :                                     qs_env%mp2_env%eri_blksize, ngroup, color_sub, para_env, para_env_sub)
     635              :                END DO
     636              : 
     637              :             END IF
     638              : 
     639         7127 :             DO LLL = 1, my_group_L_size
     640         7127 :                CALL dbcsr_release_p(mat_munu_local_L(LLL)%matrix)
     641              :             END DO
     642          202 :             DEALLOCATE (mat_munu_local_L)
     643              : 
     644          350 :          ELSE IF (do_gpw) THEN
     645              : 
     646              :             CALL prepare_gpw(qs_env, dft_control, e_cutoff_old, cutoff_old, relative_cutoff_old, para_env_sub, pw_env_sub, &
     647          350 :                              auxbas_pw_pool, poisson_env, task_list_sub, rho_r, rho_g, pot_g, psi_L, sab_orb_sub)
     648              : 
     649        15109 :             DO i_counter = 1, my_group_L_size
     650              : 
     651              :                CALL mp2_eri_3c_integrate_gpw(psi_L, rho_g, atomic_kind_set, qs_kind_set, cell, dft_control, &
     652              :                                              particle_set, pw_env_sub, my_Lrows(:, i_counter), poisson_env, rho_r, pot_g, &
     653        14759 :                                              ri_metric, mat_munu, qs_env, task_list_sub)
     654              : 
     655        34272 :                DO ispin = 1, nspins
     656              :                   CALL ao_to_mo_and_store_B(para_env_sub, mat_munu, intermed_mat(ispin), &
     657              :                                             BIb_C(ispin)%array(i_counter, :, :), &
     658              :                                             mo_coeff_o(ispin)%matrix, mo_coeff_v(ispin)%matrix, eps_filter, &
     659        34272 :                                             my_B_virtual_end(ispin), my_B_virtual_start(ispin))
     660              : 
     661              :                END DO
     662              : 
     663        15109 :                IF (my_do_gw) THEN
     664              :                   ! transform (K|mu nu) to (K|nm), n corresponds to corrected GW levels, m is in nmo
     665            0 :                   DO ispin = 1, nspins
     666              :                      CALL ao_to_mo_and_store_B(para_env_sub, mat_munu, intermed_mat_gw(ispin), &
     667              :                                                BIb_C_gw(ispin)%array(i_counter, :, :), &
     668              :                                                mo_coeff_gw(ispin)%matrix, mo_coeff_all(ispin)%matrix, eps_filter, &
     669            0 :                                                my_B_all_end, my_B_all_start)
     670              : 
     671              :                   END DO
     672              :                END IF
     673              : 
     674              :             END DO
     675              : 
     676              :             CALL cleanup_gpw(qs_env, e_cutoff_old, cutoff_old, relative_cutoff_old, para_env_sub, pw_env_sub, &
     677          350 :                              task_list_sub, auxbas_pw_pool, rho_r, rho_g, pot_g, psi_L)
     678              :          ELSE
     679            0 :             CPABORT("Integration method not implemented!")
     680              :          END IF
     681              : 
     682          552 :          CALL timestop(handle2)
     683              : 
     684          552 :          DEALLOCATE (my_Lrows)
     685              : 
     686         1234 :          DO ispin = 1, nspins
     687         1234 :             CALL release_intermediate_matrices(intermed_mat(ispin))
     688              :          END DO
     689         1234 :          DEALLOCATE (intermed_mat)
     690              : 
     691          552 :          IF (my_do_gw) THEN
     692          192 :             DO ispin = 1, nspins
     693          192 :                CALL release_intermediate_matrices(intermed_mat_gw(ispin))
     694              :             END DO
     695          192 :             DEALLOCATE (intermed_mat_gw)
     696              :          END IF
     697              : 
     698         1104 :          IF (do_bse) THEN
     699          124 :             DO ispin = 1, nspins
     700           68 :                CALL release_intermediate_matrices(intermed_mat_bse_ab(ispin))
     701          124 :                CALL release_intermediate_matrices(intermed_mat_bse_ij(ispin))
     702              :             END DO
     703          192 :             DEALLOCATE (intermed_mat_bse_ab, intermed_mat_bse_ij)
     704              :          END IF
     705              : 
     706              :          ! imag. time = low-scaling SOS-MP2, RPA, GW
     707              :       ELSE
     708              : 
     709          144 :          memory_info = qs_env%mp2_env%ri_rpa_im_time%memory_info
     710              : 
     711              :          ! we need 3 tensors:
     712              :          ! 1) t_3c_overl_int: 3c overlap integrals, optimized for easy access to integral blocks
     713              :          !                   (atomic blocks)
     714              :          ! 2) t_3c_O: 3c overlap integrals, optimized for contraction (split blocks)
     715              :          ! 3) t_3c_M: tensor M, optimized for contraction
     716              : 
     717          144 :          CALL get_qs_env(qs_env, natom=natom, nkind=nkind, dft_control=dft_control)
     718              : 
     719          144 :          pdims_t3c = 0
     720          144 :          CALL dbt_pgrid_create(para_env, pdims_t3c, pgrid_t3c_overl)
     721              : 
     722              :          ! set up basis
     723          576 :          ALLOCATE (sizes_RI(natom), sizes_AO(natom))
     724         1144 :          ALLOCATE (basis_set_ri_aux(nkind), basis_set_ao(nkind))
     725          144 :          CALL basis_set_list_setup(basis_set_ri_aux, "RI_AUX", qs_kind_set)
     726          144 :          CALL get_particle_set(particle_set, qs_kind_set, nsgf=sizes_RI, basis=basis_set_ri_aux)
     727          144 :          CALL basis_set_list_setup(basis_set_ao, "ORB", qs_kind_set)
     728          144 :          CALL get_particle_set(particle_set, qs_kind_set, nsgf=sizes_AO, basis=basis_set_ao)
     729              : 
     730              :          ! make sure we use the QS%EPS_PGF_ORB
     731          144 :          qs_section => section_vals_get_subs_vals(qs_env%input, "DFT%QS")
     732          144 :          CALL section_vals_val_get(qs_section, "EPS_PGF_ORB", n_rep_val=n_rep)
     733          144 :          IF (n_rep /= 0) THEN
     734           90 :             CALL section_vals_val_get(qs_section, "EPS_PGF_ORB", r_val=eps_pgf_orb)
     735              :          ELSE
     736           54 :             CALL section_vals_val_get(qs_section, "EPS_DEFAULT", r_val=eps_pgf_orb)
     737           54 :             eps_pgf_orb = SQRT(eps_pgf_orb)
     738              :          END IF
     739          144 :          eps_pgf_orb_old = dft_control%qs_control%eps_pgf_orb
     740              : 
     741          428 :          DO ibasis = 1, SIZE(basis_set_ao)
     742          284 :             orb_basis => basis_set_ao(ibasis)%gto_basis_set
     743          284 :             CALL init_interaction_radii_orb_basis(orb_basis, eps_pgf_orb)
     744          284 :             ri_basis => basis_set_ri_aux(ibasis)%gto_basis_set
     745          428 :             CALL init_interaction_radii_orb_basis(ri_basis, eps_pgf_orb)
     746              :          END DO
     747              : 
     748          144 :          cut_memory_int = qs_env%mp2_env%ri_rpa_im_time%cut_memory
     749              :          CALL create_tensor_batches(sizes_RI, cut_memory_int, starts_array_mc_int, ends_array_mc_int, &
     750          144 :                                     starts_array_mc_block_int, ends_array_mc_block_int)
     751              : 
     752          144 :          DEALLOCATE (starts_array_mc_int, ends_array_mc_int)
     753              : 
     754              :          CALL create_3c_tensor(t_3c_overl_int_template, dist_RI, dist_AO_1, dist_AO_2, pgrid_t3c_overl, &
     755              :                                sizes_RI, sizes_AO, sizes_AO, map1=[1, 2], map2=[3], &
     756          144 :                                name="O (RI AO | AO)")
     757              : 
     758          144 :          CALL get_qs_env(qs_env, nkind=nkind, particle_set=particle_set)
     759          144 :          CALL dbt_mp_environ_pgrid(pgrid_t3c_overl, pdims, pcoord)
     760          144 :          CALL mp_comm_t3c_2%create(pgrid_t3c_overl%mp_comm_2d, 3, pdims)
     761              :          CALL distribution_3d_create(dist_3d, dist_RI, dist_AO_1, dist_AO_2, &
     762          144 :                                      nkind, particle_set, mp_comm_t3c_2, own_comm=.TRUE.)
     763          144 :          DEALLOCATE (dist_RI, dist_AO_1, dist_AO_2)
     764              : 
     765              :          CALL build_3c_neighbor_lists(nl_3c, basis_set_ri_aux, basis_set_ao, basis_set_ao, &
     766              :                                       dist_3d, ri_metric, "RPA_3c_nl", qs_env, &
     767          144 :                                       sym_jk=.NOT. do_kpoints_cubic_RPA, own_dist=.TRUE.)
     768              : 
     769              :          ! init k points
     770          144 :          IF (do_kpoints_cubic_RPA) THEN
     771              :             ! set up new kpoint type with periodic images according to eps_grid from MP2 section
     772              :             ! instead of eps_pgf_orb from QS section
     773            6 :             CALL kpoint_init_cell_index(kpoints, nl_3c%jk_list, para_env, dft_control%nimages)
     774            6 :             IF (unit_nr > 0) WRITE (UNIT=unit_nr, FMT="(T3,A,T75,i6)") &
     775            3 :                "3C_OVERLAP_INTEGRALS_INFO| Number of periodic images considered:", dft_control%nimages
     776              : 
     777            6 :             nimg = dft_control%nimages
     778              :          ELSE
     779              :             nimg = 1
     780              :          END IF
     781              : 
     782         1896 :          ALLOCATE (t_3c_overl_int(nimg, nimg))
     783              : 
     784          312 :          DO i = 1, SIZE(t_3c_overl_int, 1)
     785          600 :             DO j = 1, SIZE(t_3c_overl_int, 2)
     786          456 :                CALL dbt_create(t_3c_overl_int_template, t_3c_overl_int(i, j))
     787              :             END DO
     788              :          END DO
     789              : 
     790          144 :          CALL dbt_destroy(t_3c_overl_int_template)
     791              : 
     792              :          ! split blocks to improve load balancing for tensor contraction
     793          144 :          min_bsize = qs_env%mp2_env%ri_rpa_im_time%min_bsize
     794              : 
     795          144 :          CALL pgf_block_sizes(atomic_kind_set, basis_set_ao, min_bsize, sizes_AO_split)
     796          144 :          CALL pgf_block_sizes(atomic_kind_set, basis_set_ri_aux, min_bsize, sizes_RI_split)
     797              : 
     798          144 :          pdims_t3c = 0
     799          144 :          CALL dbt_pgrid_create(para_env, pdims_t3c, pgrid_t3c_M)
     800              : 
     801              :          ASSOCIATE (cut_memory => qs_env%mp2_env%ri_rpa_im_time%cut_memory)
     802              :             CALL create_tensor_batches(sizes_AO_split, cut_memory, starts_array_mc, ends_array_mc, &
     803          144 :                                        starts_array_mc_block, ends_array_mc_block)
     804              :             CALL create_tensor_batches(sizes_RI_split, cut_memory, &
     805              :                                        qs_env%mp2_env%ri_rpa_im_time%starts_array_mc_RI, &
     806              :                                        qs_env%mp2_env%ri_rpa_im_time%ends_array_mc_RI, &
     807              :                                        qs_env%mp2_env%ri_rpa_im_time%starts_array_mc_block_RI, &
     808          288 :                                        qs_env%mp2_env%ri_rpa_im_time%ends_array_mc_block_RI)
     809              : 
     810              :          END ASSOCIATE
     811          144 :          cut_memory = qs_env%mp2_env%ri_rpa_im_time%cut_memory
     812              : 
     813              :          CALL create_3c_tensor(t_3c_M, dist_RI, dist_AO_1, dist_AO_2, pgrid_t3c_M, &
     814              :                                sizes_RI_split, sizes_AO_split, sizes_AO_split, &
     815              :                                map1=[1], map2=[2, 3], &
     816          144 :                                name="M (RI | AO AO)")
     817          144 :          DEALLOCATE (dist_RI, dist_AO_1, dist_AO_2)
     818          144 :          CALL dbt_pgrid_destroy(pgrid_t3c_M)
     819              : 
     820         1896 :          ALLOCATE (t_3c_O(SIZE(t_3c_overl_int, 1), SIZE(t_3c_overl_int, 2)))
     821       305924 :          ALLOCATE (t_3c_O_compressed(SIZE(t_3c_overl_int, 1), SIZE(t_3c_overl_int, 2), cut_memory))
     822         1796 :          ALLOCATE (t_3c_O_ind(SIZE(t_3c_overl_int, 1), SIZE(t_3c_overl_int, 2), cut_memory))
     823              :          CALL create_3c_tensor(t_3c_O(1, 1), dist_RI, dist_AO_1, dist_AO_2, pgrid_t3c_overl, &
     824              :                                sizes_RI_split, sizes_AO_split, sizes_AO_split, &
     825              :                                map1=[1, 2], map2=[3], &
     826          144 :                                name="O (RI AO | AO)")
     827          144 :          DEALLOCATE (dist_RI, dist_AO_1, dist_AO_2)
     828          144 :          CALL dbt_pgrid_destroy(pgrid_t3c_overl)
     829              : 
     830          312 :          DO i = 1, SIZE(t_3c_O, 1)
     831          600 :             DO j = 1, SIZE(t_3c_O, 2)
     832          456 :                IF (i > 1 .OR. j > 1) CALL dbt_create(t_3c_O(1, 1), t_3c_O(i, j))
     833              :             END DO
     834              :          END DO
     835              : 
     836              :          ! build integrals in batches and copy to optimized format
     837              :          ! note: integrals are stored in terms of atomic blocks. To avoid a memory bottleneck,
     838              :          ! integrals are calculated in batches and copied to optimized format with subatomic blocks
     839              : 
     840          396 :          DO cm = 1, cut_memory_int
     841              :             CALL build_3c_integrals(t_3c_overl_int, &
     842              :                                     qs_env%mp2_env%ri_rpa_im_time%eps_filter/2, &
     843              :                                     qs_env, &
     844              :                                     nl_3c, &
     845              :                                     int_eps=qs_env%mp2_env%ri_rpa_im_time%eps_filter/2, &
     846              :                                     basis_i=basis_set_ri_aux, &
     847              :                                     basis_j=basis_set_ao, basis_k=basis_set_ao, &
     848              :                                     potential_parameter=ri_metric, &
     849              :                                     do_kpoints=do_kpoints_cubic_RPA, &
     850          756 :                                     bounds_i=[starts_array_mc_block_int(cm), ends_array_mc_block_int(cm)], desymmetrize=.FALSE.)
     851          252 :             CALL timeset(routineN//"_copy_3c", handle4)
     852              :             ! copy integral tensor t_3c_overl_int to t_3c_O tensor optimized for contraction
     853          536 :             DO i = 1, SIZE(t_3c_overl_int, 1)
     854          980 :                DO j = 1, SIZE(t_3c_overl_int, 2)
     855              : 
     856              :                   CALL dbt_copy(t_3c_overl_int(i, j), t_3c_O(i, j), order=[1, 3, 2], &
     857          444 :                                 summation=.TRUE., move_data=.TRUE.)
     858          444 :                   CALL dbt_clear(t_3c_overl_int(i, j))
     859          444 :                   CALL dbt_filter(t_3c_O(i, j), qs_env%mp2_env%ri_rpa_im_time%eps_filter/2)
     860              :                   ! rescaling, probably because of neighbor list
     861          728 :                   IF (do_kpoints_cubic_RPA .AND. cm == cut_memory_int) THEN
     862          150 :                      CALL dbt_scale(t_3c_O(i, j), 0.5_dp)
     863              :                   END IF
     864              :                END DO
     865              :             END DO
     866          648 :             CALL timestop(handle4)
     867              :          END DO
     868              : 
     869          312 :          DO i = 1, SIZE(t_3c_overl_int, 1)
     870          600 :             DO j = 1, SIZE(t_3c_overl_int, 2)
     871          456 :                CALL dbt_destroy(t_3c_overl_int(i, j))
     872              :             END DO
     873              :          END DO
     874          432 :          DEALLOCATE (t_3c_overl_int)
     875              : 
     876          144 :          CALL timeset(routineN//"_copy_3c", handle4)
     877              :          ! desymmetrize
     878          144 :          CALL dbt_create(t_3c_O(1, 1), t_3c_tmp)
     879          312 :          DO jcell = 1, nimg
     880          540 :             DO kcell = 1, jcell
     881          228 :                CALL dbt_copy(t_3c_O(jcell, kcell), t_3c_tmp)
     882          228 :                CALL dbt_copy(t_3c_tmp, t_3c_O(kcell, jcell), order=[1, 3, 2], summation=.TRUE., move_data=.TRUE.)
     883          396 :                CALL dbt_filter(t_3c_O(kcell, jcell), qs_env%mp2_env%ri_rpa_im_time%eps_filter)
     884              :             END DO
     885              :          END DO
     886          312 :          DO jcell = 1, nimg
     887          372 :             DO kcell = jcell + 1, nimg
     888           60 :                CALL dbt_copy(t_3c_O(jcell, kcell), t_3c_tmp)
     889           60 :                CALL dbt_copy(t_3c_tmp, t_3c_O(kcell, jcell), order=[1, 3, 2], summation=.FALSE., move_data=.TRUE.)
     890          228 :                CALL dbt_filter(t_3c_O(kcell, jcell), qs_env%mp2_env%ri_rpa_im_time%eps_filter)
     891              :             END DO
     892              :          END DO
     893              : 
     894          144 :          CALL dbt_get_info(t_3c_O(1, 1), nfull_total=bounds_3c)
     895          144 :          CALL get_tensor_occupancy(t_3c_O(1, 1), nze, occ)
     896          144 :          memory_3c = 0.0_dp
     897              : 
     898          432 :          bounds(:, 1) = [1, bounds_3c(1)]
     899          432 :          bounds(:, 3) = [1, bounds_3c(3)]
     900          312 :          DO i = 1, SIZE(t_3c_O, 1)
     901          600 :             DO j = 1, SIZE(t_3c_O, 2)
     902          764 :                DO i_mem = 1, cut_memory
     903         1428 :                   bounds(:, 2) = [starts_array_mc(i_mem), ends_array_mc(i_mem)]
     904          476 :                   CALL dbt_copy(t_3c_O(i, j), t_3c_tmp, bounds=bounds)
     905              : 
     906          476 :                   CALL alloc_containers(t_3c_O_compressed(i, j, i_mem), 1)
     907              :                   CALL compress_tensor(t_3c_tmp, t_3c_O_ind(i, j, i_mem)%ind, &
     908              :                                        t_3c_O_compressed(i, j, i_mem), &
     909          764 :                                        qs_env%mp2_env%ri_rpa_im_time%eps_compress, memory_3c)
     910              :                END DO
     911          456 :                CALL dbt_clear(t_3c_O(i, j))
     912              :             END DO
     913              :          END DO
     914              : 
     915          144 :          CALL para_env%sum(memory_3c)
     916              : 
     917          144 :          compression_factor = REAL(nze, dp)*1.0E-06_dp*8.0_dp/memory_3c
     918              : 
     919          144 :          IF (unit_nr > 0) THEN
     920              :             WRITE (UNIT=unit_nr, FMT="((T3,A,T66,F11.2,A4))") &
     921           72 :                "MEMORY_INFO| Memory for 3-center integrals (compressed):", memory_3c, ' MiB'
     922              : 
     923              :             WRITE (UNIT=unit_nr, FMT="((T3,A,T60,F21.2))") &
     924           72 :                "MEMORY_INFO| Compression factor:                  ", compression_factor
     925              :          END IF
     926              : 
     927          144 :          CALL dbt_destroy(t_3c_tmp)
     928              : 
     929          144 :          CALL timestop(handle4)
     930              : 
     931          428 :          DO ibasis = 1, SIZE(basis_set_ao)
     932          284 :             orb_basis => basis_set_ao(ibasis)%gto_basis_set
     933          284 :             CALL init_interaction_radii_orb_basis(orb_basis, eps_pgf_orb_old)
     934          284 :             ri_basis => basis_set_ri_aux(ibasis)%gto_basis_set
     935          428 :             CALL init_interaction_radii_orb_basis(ri_basis, eps_pgf_orb_old)
     936              :          END DO
     937              : 
     938          144 :          DEALLOCATE (basis_set_ri_aux, basis_set_ao)
     939              : 
     940          576 :          CALL neighbor_list_3c_destroy(nl_3c)
     941              : 
     942              :       END IF
     943              : 
     944          696 :       CALL timestop(handle)
     945              : 
     946         2784 :    END SUBROUTINE mp2_ri_gpw_compute_in
     947              : 
     948              : ! **************************************************************************************************
     949              : !> \brief Contract (P|ai) = (R|P) x (R|ai)
     950              : !> \param BIb_C (R|ai)
     951              : !> \param my_Lrows (R|P)
     952              : !> \param sizes_B number of a (virtual) indices per subgroup process
     953              : !> \param sizes_L number of P / R (auxiliary) indices per subgroup
     954              : !> \param blk_size ...
     955              : !> \param ngroup how many subgroups (NG)
     956              : !> \param igroup subgroup color
     957              : !> \param mp_comm communicator
     958              : !> \param para_env_sub ...
     959              : ! **************************************************************************************************
     960          460 :    SUBROUTINE contract_B_L(BIb_C, my_Lrows, sizes_B, sizes_L, blk_size, ngroup, igroup, mp_comm, para_env_sub)
     961              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT)   :: BIb_C
     962              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: my_Lrows
     963              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: sizes_B, sizes_L
     964              :       INTEGER, DIMENSION(2), INTENT(IN)                  :: blk_size
     965              :       INTEGER, INTENT(IN)                                :: ngroup, igroup
     966              : 
     967              :       CLASS(mp_comm_type), INTENT(IN)                    :: mp_comm
     968              :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env_sub
     969              : 
     970              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'contract_B_L'
     971              :       LOGICAL, PARAMETER                                 :: debug = .FALSE.
     972              : 
     973              :       INTEGER                                            :: check_proc, handle, i, iend, ii, ioff, &
     974              :                                                             istart, loc_a, loc_P, nblk_per_thread
     975          460 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: block_ind_L_P, block_ind_L_R
     976              :       INTEGER, DIMENSION(1)                              :: dist_B_i, map_B_1, map_L_1, map_L_2, &
     977              :                                                             sizes_i
     978              :       INTEGER, DIMENSION(2)                              :: map_B_2, pdims_L
     979              :       INTEGER, DIMENSION(3)                              :: pdims_B
     980              :       LOGICAL                                            :: found
     981          920 :       INTEGER, DIMENSION(ngroup)                         :: dist_L_P, dist_L_R
     982          920 :       INTEGER, DIMENSION(para_env_sub%num_pe)            :: dist_B_a
     983         7820 :       TYPE(dbt_distribution_type)                        :: dist_B, dist_L
     984         2300 :       TYPE(dbt_pgrid_type)                               :: mp_comm_B, mp_comm_L
     985        11500 :       TYPE(dbt_type)                                     :: tB_in, tB_in_split, tB_out, &
     986        11500 :                                                             tB_out_split, tL, tL_split
     987              : 
     988          460 :       CALL timeset(routineN, handle)
     989              : 
     990          460 :       sizes_i(1) = SIZE(BIb_C, 3)
     991              : 
     992              :       ASSOCIATE (nproc => para_env_sub%num_pe, iproc => para_env_sub%mepos, iproc_glob => mp_comm%mepos)
     993              : 
     994              :          ! local block index for R/P and a
     995          460 :          loc_P = igroup + 1; loc_a = iproc + 1
     996              : 
     997            0 :          CPASSERT(SIZE(sizes_L) == ngroup)
     998          460 :          CPASSERT(SIZE(sizes_B) == nproc)
     999          460 :          CPASSERT(sizes_L(loc_P) == SIZE(BIb_C, 1))
    1000          460 :          CPASSERT(sizes_L(loc_P) == SIZE(my_Lrows, 2))
    1001          460 :          CPASSERT(sizes_B(loc_a) == SIZE(BIb_C, 2))
    1002              : 
    1003              :          ! Tensor distributions as follows:
    1004              :          ! Process grid NG x Nw
    1005              :          ! Each process has coordinates (np, nw)
    1006              :          ! tB_in: (R|ai): R distributed (np), a distributed (nw)
    1007              :          ! tB_out: (P|ai): P distributed (np), a distributed (nw)
    1008              :          ! tL: (R|P): R distributed (nw), P distributed (np)
    1009              : 
    1010              :          ! define mappings between tensor index and matrix index:
    1011              :          ! (R|ai) and (P|ai):
    1012          460 :          map_B_1 = [1] ! index 1 (R or P) maps to 1st matrix index (np distributed)
    1013          460 :          map_B_2 = [2, 3] ! indices 2, 3 (a, i) map to 2nd matrix index (nw distributed)
    1014              :          ! (R|P):
    1015          460 :          map_L_1 = [2] ! index 2 (P) maps to 1st matrix index (np distributed)
    1016          460 :          map_L_2 = [1] ! index 1 (R) maps to 2nd matrix index (nw distributed)
    1017              : 
    1018              :          ! derive nd process grid that is compatible with distributions and 2d process grid
    1019              :          ! (R|ai) / (P|ai) on process grid NG x Nw x 1
    1020              :          ! (R|P) on process grid NG x Nw
    1021         1840 :          pdims_B = [ngroup, nproc, 1]
    1022         1380 :          pdims_L = [nproc, ngroup]
    1023              : 
    1024          460 :          CALL dbt_pgrid_create(mp_comm, pdims_B, mp_comm_B)
    1025          460 :          CALL dbt_pgrid_create(mp_comm, pdims_L, mp_comm_L)
    1026              : 
    1027              :          ! setup distribution vectors such that distribution matches parallel data layout of BIb_C and my_Lrows
    1028          460 :          dist_B_i = [0]
    1029         1852 :          dist_B_a = [(i, i=0, nproc - 1)]
    1030         2748 :          dist_L_R = [(MODULO(i, nproc), i=0, ngroup - 1)] ! R index is replicated in my_Lrows, we impose a cyclic distribution
    1031         2748 :          dist_L_P = [(i, i=0, ngroup - 1)]
    1032              : 
    1033              :          ! create distributions and tensors
    1034          460 :          CALL dbt_distribution_new(dist_B, mp_comm_B, dist_L_P, dist_B_a, dist_B_i)
    1035          460 :          CALL dbt_distribution_new(dist_L, mp_comm_L, dist_L_R, dist_L_P)
    1036              : 
    1037          460 :          CALL dbt_create(tB_in, "(R|ai)", dist_B, map_B_1, map_B_2, sizes_L, sizes_B, sizes_i)
    1038          460 :          CALL dbt_create(tB_out, "(P|ai)", dist_B, map_B_1, map_B_2, sizes_L, sizes_B, sizes_i)
    1039          460 :          CALL dbt_create(tL, "(R|P)", dist_L, map_L_1, map_L_2, sizes_L, sizes_L)
    1040              : 
    1041              :          IF (debug) THEN
    1042              :             ! check that tensor distribution is correct
    1043              :             CALL dbt_get_stored_coordinates(tB_in, [loc_P, loc_a, 1], check_proc)
    1044              :             CPASSERT(check_proc == iproc_glob)
    1045              :          END IF
    1046              : 
    1047              :          ! reserve (R|ai) block
    1048          460 : !$OMP PARALLEL DEFAULT(NONE) SHARED(tB_in,loc_P,loc_a)
    1049              :          CALL dbt_reserve_blocks(tB_in, [loc_P], [loc_a], [1])
    1050              : !$OMP END PARALLEL
    1051              : 
    1052              :          ! reserve (R|P) blocks
    1053              :          ! in my_Lrows, R index is replicated. For (R|P), we distribute quadratic blocks cyclically over
    1054              :          ! the processes in a subgroup.
    1055              :          ! There are NG blocks, so each process holds at most NG/Nw+1 blocks.
    1056         1380 :          ALLOCATE (block_ind_L_R(ngroup/nproc + 1))
    1057          920 :          ALLOCATE (block_ind_L_P(ngroup/nproc + 1))
    1058          460 :          block_ind_L_R(:) = 0; block_ind_L_P(:) = 0
    1059          460 :          ii = 0
    1060         1374 :          DO i = 1, ngroup
    1061         2742 :             CALL dbt_get_stored_coordinates(tL, [i, loc_P], check_proc)
    1062         1374 :             IF (check_proc == iproc_glob) THEN
    1063          911 :                ii = ii + 1
    1064          911 :                block_ind_L_R(ii) = i
    1065          911 :                block_ind_L_P(ii) = loc_P
    1066              :             END IF
    1067              :          END DO
    1068              : 
    1069              : !TODO: Parallelize creation of block list.
    1070              : !$OMP PARALLEL DEFAULT(NONE) SHARED(tL,block_ind_L_R,block_ind_L_P,ii) &
    1071          460 : !$OMP PRIVATE(nblk_per_thread,istart,iend)
    1072              :          nblk_per_thread = ii/omp_get_num_threads() + 1
    1073              :          istart = omp_get_thread_num()*nblk_per_thread + 1
    1074              :          iend = MIN(istart + nblk_per_thread, ii)
    1075              :          CALL dbt_reserve_blocks(tL, block_ind_L_R(istart:iend), block_ind_L_P(istart:iend))
    1076              : !$OMP END PARALLEL
    1077              : 
    1078              :          ! insert (R|ai) block
    1079         3220 :          CALL dbt_put_block(tB_in, [loc_P, loc_a, 1], SHAPE(BIb_C), BIb_C)
    1080              : 
    1081              :          ! insert (R|P) blocks
    1082          460 :          ioff = 0
    1083         1834 :          DO i = 1, ngroup
    1084          914 :             istart = ioff + 1; iend = ioff + sizes_L(i)
    1085          914 :             ioff = ioff + sizes_L(i)
    1086         2742 :             CALL dbt_get_stored_coordinates(tL, [i, loc_P], check_proc)
    1087         1374 :             IF (check_proc == iproc_glob) THEN
    1088      1810053 :                CALL dbt_put_block(tL, [i, loc_P], [sizes_L(i), sizes_L(loc_P)], my_Lrows(istart:iend, :))
    1089              :             END IF
    1090              :          END DO
    1091              :       END ASSOCIATE
    1092              : 
    1093         1840 :       CALL dbt_split_blocks(tB_in, tB_in_split, [blk_size(2), blk_size(1), blk_size(1)])
    1094         1380 :       CALL dbt_split_blocks(tL, tL_split, [blk_size(2), blk_size(2)])
    1095         1840 :       CALL dbt_split_blocks(tB_out, tB_out_split, [blk_size(2), blk_size(1), blk_size(1)])
    1096              : 
    1097              :       ! contract
    1098              :       CALL dbt_contract(alpha=1.0_dp, tensor_1=tB_in_split, tensor_2=tL_split, &
    1099              :                         beta=0.0_dp, tensor_3=tB_out_split, &
    1100              :                         contract_1=[1], notcontract_1=[2, 3], &
    1101              :                         contract_2=[1], notcontract_2=[2], &
    1102          460 :                         map_1=[2, 3], map_2=[1], optimize_dist=.TRUE.)
    1103              : 
    1104              :       ! retrieve local block of contraction result (P|ai)
    1105          460 :       CALL dbt_copy(tB_out_split, tB_out)
    1106              : 
    1107         3220 :       CALL dbt_get_block(tB_out, [loc_P, loc_a, 1], SHAPE(BIb_C), BIb_C, found)
    1108          460 :       CPASSERT(found)
    1109              : 
    1110              :       ! cleanup
    1111          460 :       CALL dbt_destroy(tB_in)
    1112          460 :       CALL dbt_destroy(tB_in_split)
    1113          460 :       CALL dbt_destroy(tB_out)
    1114          460 :       CALL dbt_destroy(tB_out_split)
    1115          460 :       CALL dbt_destroy(tL)
    1116          460 :       CALL dbt_destroy(tL_split)
    1117              : 
    1118          460 :       CALL dbt_distribution_destroy(dist_B)
    1119          460 :       CALL dbt_distribution_destroy(dist_L)
    1120              : 
    1121          460 :       CALL dbt_pgrid_destroy(mp_comm_B)
    1122          460 :       CALL dbt_pgrid_destroy(mp_comm_L)
    1123              : 
    1124          460 :       CALL timestop(handle)
    1125              : 
    1126          920 :    END SUBROUTINE contract_B_L
    1127              : 
    1128              : ! **************************************************************************************************
    1129              : !> \brief Encapsulate building of intermediate matrices matrix_ia_jnu(_beta
    1130              : !>         matrix_ia_jb(_beta),fm_BIb_jb(_beta),matrix_in_jnu(for G0W0) and
    1131              : !>         fm_BIb_all(for G0W0)
    1132              : !> \param intermed_mat ...
    1133              : !> \param mo_coeff_templ ...
    1134              : !> \param size_1 ...
    1135              : !> \param size_2 ...
    1136              : !> \param matrix_name_2 ...
    1137              : !> \param blacs_env_sub ...
    1138              : !> \param para_env_sub ...
    1139              : !> \author Jan Wilhelm
    1140              : ! **************************************************************************************************
    1141            0 :    SUBROUTINE create_intermediate_matrices(intermed_mat, mo_coeff_templ, size_1, size_2, &
    1142              :                                            matrix_name_2, blacs_env_sub, para_env_sub)
    1143              : 
    1144              :       TYPE(intermediate_matrix_type), INTENT(OUT)        :: intermed_mat
    1145              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: mo_coeff_templ
    1146              :       INTEGER, INTENT(IN)                                :: size_1, size_2
    1147              :       CHARACTER(LEN=*), INTENT(IN)                       :: matrix_name_2
    1148              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env_sub
    1149              :       TYPE(mp_para_env_type), POINTER                    :: para_env_sub
    1150              : 
    1151              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'create_intermediate_matrices'
    1152              : 
    1153              :       INTEGER                                            :: handle, ncol_local, nfullcols_total, &
    1154              :                                                             nfullrows_total, nrow_local
    1155          922 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
    1156              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    1157              : 
    1158          922 :       CALL timeset(routineN, handle)
    1159              : 
    1160              :       ! initialize and create the matrix (K|jnu)
    1161          922 :       CALL dbcsr_create(intermed_mat%matrix_ia_jnu, template=mo_coeff_templ)
    1162              : 
    1163              :       ! Allocate Sparse matrices: (K|jb)
    1164              :       CALL cp_dbcsr_m_by_n_from_template(intermed_mat%matrix_ia_jb, template=mo_coeff_templ, m=size_2, n=size_1, &
    1165          922 :                                          sym=dbcsr_type_no_symmetry)
    1166              : 
    1167              :       ! set all to zero in such a way that the memory is actually allocated
    1168          922 :       CALL dbcsr_set(intermed_mat%matrix_ia_jnu, 0.0_dp)
    1169          922 :       CALL dbcsr_set(intermed_mat%matrix_ia_jb, 0.0_dp)
    1170              : 
    1171              :       ! create the analogous of matrix_ia_jb in fm type
    1172          922 :       NULLIFY (fm_struct)
    1173          922 :       CALL dbcsr_get_info(intermed_mat%matrix_ia_jb, nfullrows_total=nfullrows_total, nfullcols_total=nfullcols_total)
    1174              :       CALL cp_fm_struct_create(fm_struct, context=blacs_env_sub, nrow_global=nfullrows_total, &
    1175          922 :                                ncol_global=nfullcols_total, para_env=para_env_sub)
    1176          922 :       CALL cp_fm_create(intermed_mat%fm_BIb_jb, fm_struct, name="fm_BIb_jb_"//matrix_name_2)
    1177              : 
    1178          922 :       CALL copy_dbcsr_to_fm(intermed_mat%matrix_ia_jb, intermed_mat%fm_BIb_jb)
    1179          922 :       CALL cp_fm_struct_release(fm_struct)
    1180              : 
    1181              :       CALL cp_fm_get_info(matrix=intermed_mat%fm_BIb_jb, &
    1182              :                           nrow_local=nrow_local, &
    1183              :                           ncol_local=ncol_local, &
    1184              :                           row_indices=row_indices, &
    1185          922 :                           col_indices=col_indices)
    1186              : 
    1187          922 :       intermed_mat%max_row_col_local = MAX(nrow_local, ncol_local)
    1188          922 :       CALL para_env_sub%max(intermed_mat%max_row_col_local)
    1189              : 
    1190         3688 :       ALLOCATE (intermed_mat%local_col_row_info(0:intermed_mat%max_row_col_local, 2))
    1191        36570 :       intermed_mat%local_col_row_info = 0
    1192              :       ! 0,1 nrows
    1193          922 :       intermed_mat%local_col_row_info(0, 1) = nrow_local
    1194         7321 :       intermed_mat%local_col_row_info(1:nrow_local, 1) = row_indices(1:nrow_local)
    1195              :       ! 0,2 ncols
    1196          922 :       intermed_mat%local_col_row_info(0, 2) = ncol_local
    1197        16794 :       intermed_mat%local_col_row_info(1:ncol_local, 2) = col_indices(1:ncol_local)
    1198              : 
    1199          922 :       intermed_mat%descr = matrix_name_2
    1200              : 
    1201          922 :       CALL timestop(handle)
    1202              : 
    1203         2766 :    END SUBROUTINE create_intermediate_matrices
    1204              : 
    1205              : ! **************************************************************************************************
    1206              : !> \brief Encapsulate ERI postprocessing: AO to MO transformation and store in B matrix.
    1207              : !> \param para_env ...
    1208              : !> \param mat_munu ...
    1209              : !> \param intermed_mat ...
    1210              : !> \param BIb_jb ...
    1211              : !> \param mo_coeff_o ...
    1212              : !> \param mo_coeff_v ...
    1213              : !> \param eps_filter ...
    1214              : !> \param my_B_end ...
    1215              : !> \param my_B_start ...
    1216              : ! **************************************************************************************************
    1217        38501 :    SUBROUTINE ao_to_mo_and_store_B(para_env, mat_munu, intermed_mat, BIb_jb, &
    1218              :                                    mo_coeff_o, mo_coeff_v, eps_filter, &
    1219              :                                    my_B_end, my_B_start)
    1220              :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env
    1221              :       TYPE(dbcsr_p_type), INTENT(IN)                     :: mat_munu
    1222              :       TYPE(intermediate_matrix_type), INTENT(INOUT)      :: intermed_mat
    1223              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: BIb_jb
    1224              :       TYPE(dbcsr_type), POINTER                          :: mo_coeff_o, mo_coeff_v
    1225              :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter
    1226              :       INTEGER, INTENT(IN)                                :: my_B_end, my_B_start
    1227              : 
    1228              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'ao_to_mo_and_store_B'
    1229              : 
    1230              :       INTEGER                                            :: handle
    1231              : 
    1232        38501 :       CALL timeset(routineN//"_mult_"//TRIM(intermed_mat%descr), handle)
    1233              : 
    1234              :       CALL dbcsr_multiply("N", "N", 1.0_dp, mat_munu%matrix, mo_coeff_o, &
    1235        38501 :                           0.0_dp, intermed_mat%matrix_ia_jnu, filter_eps=eps_filter)
    1236              :       CALL dbcsr_multiply("T", "N", 1.0_dp, intermed_mat%matrix_ia_jnu, mo_coeff_v, &
    1237        38501 :                           0.0_dp, intermed_mat%matrix_ia_jb, filter_eps=eps_filter)
    1238        38501 :       CALL timestop(handle)
    1239              : 
    1240        38501 :       CALL timeset(routineN//"_E_Ex_"//TRIM(intermed_mat%descr), handle)
    1241        38501 :       CALL copy_dbcsr_to_fm(intermed_mat%matrix_ia_jb, intermed_mat%fm_BIb_jb)
    1242              : 
    1243              :       CALL grep_my_integrals(para_env, intermed_mat%fm_BIb_jb, BIb_jb, intermed_mat%max_row_col_local, &
    1244              :                              intermed_mat%local_col_row_info, &
    1245        38501 :                              my_B_end, my_B_start)
    1246              : 
    1247        38501 :       CALL timestop(handle)
    1248        38501 :    END SUBROUTINE ao_to_mo_and_store_B
    1249              : 
    1250              : ! **************************************************************************************************
    1251              : !> \brief ...
    1252              : !> \param intermed_mat ...
    1253              : ! **************************************************************************************************
    1254          922 :    SUBROUTINE release_intermediate_matrices(intermed_mat)
    1255              :       TYPE(intermediate_matrix_type), INTENT(INOUT)      :: intermed_mat
    1256              : 
    1257          922 :       CALL dbcsr_release(intermed_mat%matrix_ia_jnu)
    1258          922 :       CALL dbcsr_release(intermed_mat%matrix_ia_jb)
    1259          922 :       CALL cp_fm_release(intermed_mat%fm_BIb_jb)
    1260          922 :       DEALLOCATE (intermed_mat%local_col_row_info)
    1261              : 
    1262          922 :    END SUBROUTINE release_intermediate_matrices
    1263              : 
    1264              : ! **************************************************************************************************
    1265              : !> \brief ...
    1266              : !> \param qs_env ...
    1267              : !> \param kpoints ...
    1268              : !> \param unit_nr ...
    1269              : ! **************************************************************************************************
    1270           16 :    SUBROUTINE compute_kpoints(qs_env, kpoints, unit_nr)
    1271              : 
    1272              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1273              :       TYPE(kpoint_type), POINTER                         :: kpoints
    1274              :       INTEGER                                            :: unit_nr
    1275              : 
    1276              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'compute_kpoints'
    1277              : 
    1278              :       INTEGER                                            :: handle, i, i_dim, ix, iy, iz, nkp, &
    1279              :                                                             nkp_extra, nkp_orig
    1280              :       INTEGER, DIMENSION(3)                              :: nkp_grid, nkp_grid_extra, periodic
    1281              :       LOGICAL                                            :: do_extrapolate_kpoints
    1282              :       TYPE(cell_type), POINTER                           :: cell
    1283              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1284              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1285              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1286           16 :          POINTER                                         :: sab_orb
    1287              : 
    1288           16 :       CALL timeset(routineN, handle)
    1289              : 
    1290           16 :       NULLIFY (cell, dft_control, para_env)
    1291           16 :       CALL get_qs_env(qs_env=qs_env, cell=cell, para_env=para_env, dft_control=dft_control, sab_orb=sab_orb)
    1292           16 :       CALL get_cell(cell=cell, periodic=periodic)
    1293              : 
    1294              :       ! general because we augment a Monkhorst-Pack mesh by additional points in the BZ
    1295           16 :       kpoints%kp_scheme = "GENERAL"
    1296           16 :       kpoints%symmetry = .FALSE.
    1297           16 :       kpoints%verbose = .FALSE.
    1298           16 :       kpoints%full_grid = .TRUE.
    1299           16 :       kpoints%use_real_wfn = .FALSE.
    1300           16 :       kpoints%eps_geo = 1.e-6_dp
    1301           64 :       nkp_grid(1:3) = qs_env%mp2_env%ri_rpa_im_time%kp_grid(1:3)
    1302           16 :       do_extrapolate_kpoints = qs_env%mp2_env%ri_rpa_im_time%do_extrapolate_kpoints
    1303              : 
    1304           64 :       DO i_dim = 1, 3
    1305           48 :          IF (periodic(i_dim) == 1) THEN
    1306           32 :             CPASSERT(MODULO(nkp_grid(i_dim), 2) == 0)
    1307              :          END IF
    1308           64 :          IF (periodic(i_dim) == 0) THEN
    1309           16 :             CPASSERT(nkp_grid(i_dim) == 1)
    1310              :          END IF
    1311              :       END DO
    1312              : 
    1313           16 :       nkp_orig = nkp_grid(1)*nkp_grid(2)*nkp_grid(3)/2
    1314              : 
    1315           16 :       IF (do_extrapolate_kpoints) THEN
    1316              : 
    1317           16 :          CPASSERT(qs_env%mp2_env%ri_rpa_im_time%kpoint_weights_W_method == kp_weights_W_uniform)
    1318              : 
    1319           64 :          DO i_dim = 1, 3
    1320           48 :             IF (periodic(i_dim) == 1) nkp_grid_extra(i_dim) = nkp_grid(i_dim) + 2
    1321           64 :             IF (periodic(i_dim) == 0) nkp_grid_extra(i_dim) = 1
    1322              :          END DO
    1323              : 
    1324           64 :          qs_env%mp2_env%ri_rpa_im_time%kp_grid_extra(1:3) = nkp_grid_extra(1:3)
    1325              : 
    1326           16 :          nkp_extra = nkp_grid_extra(1)*nkp_grid_extra(2)*nkp_grid_extra(3)/2
    1327              : 
    1328              :       ELSE
    1329              : 
    1330            0 :          nkp_grid_extra(1:3) = 0
    1331            0 :          nkp_extra = 0
    1332              : 
    1333              :       END IF
    1334              : 
    1335           16 :       nkp = nkp_orig + nkp_extra
    1336              : 
    1337           16 :       qs_env%mp2_env%ri_rpa_im_time%nkp_orig = nkp_orig
    1338           16 :       qs_env%mp2_env%ri_rpa_im_time%nkp_extra = nkp_extra
    1339              : 
    1340           80 :       ALLOCATE (kpoints%xkp(3, nkp), kpoints%wkp(nkp))
    1341              : 
    1342           64 :       kpoints%nkp_grid(1:3) = nkp_grid(1:3)
    1343           16 :       kpoints%nkp = nkp
    1344              : 
    1345           32 :       ALLOCATE (qs_env%mp2_env%ri_rpa_im_time%wkp_V(nkp))
    1346           16 :       IF (do_extrapolate_kpoints) THEN
    1347              :          kpoints%wkp(1:nkp_orig) = 1.0_dp/REAL(nkp_orig, KIND=dp) &
    1348          144 :                                    /(1.0_dp - SQRT(REAL(nkp_extra, KIND=dp)/REAL(nkp_orig, KIND=dp)))
    1349              :          kpoints%wkp(nkp_orig + 1:nkp) = 1.0_dp/REAL(nkp_extra, KIND=dp) &
    1350          304 :                                          /(1.0_dp - SQRT(REAL(nkp_orig, KIND=dp)/REAL(nkp_extra, KIND=dp)))
    1351          144 :          qs_env%mp2_env%ri_rpa_im_time%wkp_V(1:nkp_orig) = 0.0_dp
    1352          304 :          qs_env%mp2_env%ri_rpa_im_time%wkp_V(nkp_orig + 1:nkp) = 1.0_dp/REAL(nkp_extra, KIND=dp)
    1353              :       ELSE
    1354            0 :          kpoints%wkp(:) = 1.0_dp/REAL(nkp, KIND=dp)
    1355            0 :          qs_env%mp2_env%ri_rpa_im_time%wkp_V(:) = kpoints%wkp(:)
    1356              :       END IF
    1357              : 
    1358           16 :       i = 0
    1359           44 :       DO ix = 1, nkp_grid(1)
    1360          108 :          DO iy = 1, nkp_grid(2)
    1361          348 :             DO iz = 1, nkp_grid(3)
    1362              : 
    1363          256 :                IF (i == nkp_orig) CYCLE
    1364          128 :                i = i + 1
    1365              : 
    1366          128 :                kpoints%xkp(1, i) = REAL(2*ix - nkp_grid(1) - 1, KIND=dp)/(2._dp*REAL(nkp_grid(1), KIND=dp))
    1367          128 :                kpoints%xkp(2, i) = REAL(2*iy - nkp_grid(2) - 1, KIND=dp)/(2._dp*REAL(nkp_grid(2), KIND=dp))
    1368          320 :                kpoints%xkp(3, i) = REAL(2*iz - nkp_grid(3) - 1, KIND=dp)/(2._dp*REAL(nkp_grid(3), KIND=dp))
    1369              : 
    1370              :             END DO
    1371              :          END DO
    1372              :       END DO
    1373              : 
    1374           52 :       DO ix = 1, nkp_grid_extra(1)
    1375          148 :          DO iy = 1, nkp_grid_extra(2)
    1376          708 :             DO iz = 1, nkp_grid_extra(3)
    1377              : 
    1378          576 :                i = i + 1
    1379          576 :                IF (i > nkp) CYCLE
    1380              : 
    1381          288 :                kpoints%xkp(1, i) = REAL(2*ix - nkp_grid_extra(1) - 1, KIND=dp)/(2._dp*REAL(nkp_grid_extra(1), KIND=dp))
    1382          288 :                kpoints%xkp(2, i) = REAL(2*iy - nkp_grid_extra(2) - 1, KIND=dp)/(2._dp*REAL(nkp_grid_extra(2), KIND=dp))
    1383          672 :                kpoints%xkp(3, i) = REAL(2*iz - nkp_grid_extra(3) - 1, KIND=dp)/(2._dp*REAL(nkp_grid_extra(3), KIND=dp))
    1384              : 
    1385              :             END DO
    1386              :          END DO
    1387              :       END DO
    1388              : 
    1389           16 :       CALL kpoint_init_cell_index(kpoints, sab_orb, para_env, dft_control%nimages)
    1390              : 
    1391           16 :       CALL set_qs_env(qs_env, kpoints=kpoints)
    1392              : 
    1393           16 :       IF (unit_nr > 0) THEN
    1394              : 
    1395            8 :          IF (do_extrapolate_kpoints) THEN
    1396            8 :             WRITE (UNIT=unit_nr, FMT="(T3,A,T69,3I4)") "KPOINT_INFO| K-point mesh for V (leading to Sigma^x):", nkp_grid(1:3)
    1397            8 :             WRITE (UNIT=unit_nr, FMT="(T3,A,T69)") "KPOINT_INFO| K-point extrapolation for W^c is used (W^c leads to Sigma^c):"
    1398            8 :             WRITE (UNIT=unit_nr, FMT="(T3,A,T69,3I4)") "KPOINT_INFO| K-point mesh 1 for W^c:", nkp_grid(1:3)
    1399            8 :             WRITE (UNIT=unit_nr, FMT="(T3,A,T69,3I4)") "KPOINT_INFO| K-point mesh 2 for W^c:", nkp_grid_extra(1:3)
    1400              :          ELSE
    1401            0 :             WRITE (UNIT=unit_nr, FMT="(T3,A,T69,3I4)") "KPOINT_INFO| K-point mesh for V and W:", nkp_grid(1:3)
    1402            0 :             WRITE (UNIT=unit_nr, FMT="(T3,A,T75,I6)") "KPOINT_INFO| Number of kpoints for V and W:", nkp
    1403              :          END IF
    1404              : 
    1405            8 :          SELECT CASE (qs_env%mp2_env%ri_rpa_im_time%kpoint_weights_W_method)
    1406              :          CASE (kp_weights_W_tailored)
    1407              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T81)") &
    1408            0 :                "KPOINT_INFO| K-point weights for W:                                   TAILORED"
    1409              :          CASE (kp_weights_W_auto)
    1410              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T81)") &
    1411            0 :                "KPOINT_INFO| K-point weights for W:                                       AUTO"
    1412              :          CASE (kp_weights_W_uniform)
    1413              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T81)") &
    1414            8 :                "KPOINT_INFO| K-point weights for W:                                    UNIFORM"
    1415              :          END SELECT
    1416              : 
    1417              :       END IF
    1418              : 
    1419           16 :       CALL timestop(handle)
    1420              : 
    1421           16 :    END SUBROUTINE compute_kpoints
    1422              : 
    1423              : ! **************************************************************************************************
    1424              : !> \brief ...
    1425              : !> \param para_env_sub ...
    1426              : !> \param fm_BIb_jb ...
    1427              : !> \param BIb_jb ...
    1428              : !> \param max_row_col_local ...
    1429              : !> \param local_col_row_info ...
    1430              : !> \param my_B_virtual_end ...
    1431              : !> \param my_B_virtual_start ...
    1432              : ! **************************************************************************************************
    1433        38501 :    SUBROUTINE grep_my_integrals(para_env_sub, fm_BIb_jb, BIb_jb, max_row_col_local, &
    1434              :                                 local_col_row_info, &
    1435              :                                 my_B_virtual_end, my_B_virtual_start)
    1436              :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env_sub
    1437              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_BIb_jb
    1438              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: BIb_jb
    1439              :       INTEGER, INTENT(IN)                                :: max_row_col_local
    1440              :       INTEGER, ALLOCATABLE, DIMENSION(:, :), INTENT(IN)  :: local_col_row_info
    1441              :       INTEGER, INTENT(IN)                                :: my_B_virtual_end, my_B_virtual_start
    1442              : 
    1443              :       INTEGER                                            :: i_global, iiB, j_global, jjB, ncol_rec, &
    1444              :                                                             nrow_rec, proc_receive, proc_send, &
    1445              :                                                             proc_shift
    1446        38501 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: rec_col_row_info
    1447        38501 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices_rec, row_indices_rec
    1448        38501 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: local_BI, rec_BI
    1449              : 
    1450       154004 :       ALLOCATE (rec_col_row_info(0:max_row_col_local, 2))
    1451              : 
    1452      1720273 :       rec_col_row_info(:, :) = local_col_row_info
    1453              : 
    1454        38501 :       nrow_rec = rec_col_row_info(0, 1)
    1455        38501 :       ncol_rec = rec_col_row_info(0, 2)
    1456              : 
    1457       115461 :       ALLOCATE (row_indices_rec(nrow_rec))
    1458       373917 :       row_indices_rec = rec_col_row_info(1:nrow_rec, 1)
    1459              : 
    1460       115503 :       ALLOCATE (col_indices_rec(ncol_rec))
    1461       797791 :       col_indices_rec = rec_col_row_info(1:ncol_rec, 2)
    1462              : 
    1463              :       ! accumulate data on BIb_jb buffer starting from myself
    1464       797791 :       DO jjB = 1, ncol_rec
    1465       759290 :          j_global = col_indices_rec(jjB)
    1466       797791 :          IF (j_global >= my_B_virtual_start .AND. j_global <= my_B_virtual_end) THEN
    1467     12537885 :             DO iiB = 1, nrow_rec
    1468     11803195 :                i_global = row_indices_rec(iiB)
    1469     12537885 :                BIb_jb(j_global - my_B_virtual_start + 1, i_global) = fm_BIb_jb%local_data(iiB, jjB)
    1470              :             END DO
    1471              :          END IF
    1472              :       END DO
    1473              : 
    1474        38501 :       DEALLOCATE (row_indices_rec)
    1475        38501 :       DEALLOCATE (col_indices_rec)
    1476              : 
    1477        38501 :       IF (para_env_sub%num_pe > 1) THEN
    1478         9816 :          ALLOCATE (local_BI(nrow_rec, ncol_rec))
    1479       156209 :          local_BI(1:nrow_rec, 1:ncol_rec) = fm_BIb_jb%local_data(1:nrow_rec, 1:ncol_rec)
    1480              : 
    1481         4908 :          DO proc_shift = 1, para_env_sub%num_pe - 1
    1482         2454 :             proc_send = MODULO(para_env_sub%mepos + proc_shift, para_env_sub%num_pe)
    1483         2454 :             proc_receive = MODULO(para_env_sub%mepos - proc_shift, para_env_sub%num_pe)
    1484              : 
    1485              :             ! first exchange information on the local data
    1486         2454 :             rec_col_row_info = 0
    1487         2454 :             CALL para_env_sub%sendrecv(local_col_row_info, proc_send, rec_col_row_info, proc_receive)
    1488         2454 :             nrow_rec = rec_col_row_info(0, 1)
    1489         2454 :             ncol_rec = rec_col_row_info(0, 2)
    1490              : 
    1491         7362 :             ALLOCATE (row_indices_rec(nrow_rec))
    1492         7705 :             row_indices_rec = rec_col_row_info(1:nrow_rec, 1)
    1493              : 
    1494         7362 :             ALLOCATE (col_indices_rec(ncol_rec))
    1495        51654 :             col_indices_rec = rec_col_row_info(1:ncol_rec, 2)
    1496              : 
    1497         9816 :             ALLOCATE (rec_BI(nrow_rec, ncol_rec))
    1498       156209 :             rec_BI = 0.0_dp
    1499              : 
    1500              :             ! then send and receive the real data
    1501       309964 :             CALL para_env_sub%sendrecv(local_BI, proc_send, rec_BI, proc_receive)
    1502              : 
    1503              :             ! accumulate the received data on BIb_jb buffer
    1504        51654 :             DO jjB = 1, ncol_rec
    1505        49200 :                j_global = col_indices_rec(jjB)
    1506        51654 :                IF (j_global >= my_B_virtual_start .AND. j_global <= my_B_virtual_end) THEN
    1507        76719 :                   DO iiB = 1, nrow_rec
    1508        52119 :                      i_global = row_indices_rec(iiB)
    1509        76719 :                      BIb_jb(j_global - my_B_virtual_start + 1, i_global) = rec_BI(iiB, jjB)
    1510              :                   END DO
    1511              :                END IF
    1512              :             END DO
    1513              : 
    1514         2454 :             DEALLOCATE (col_indices_rec)
    1515         2454 :             DEALLOCATE (row_indices_rec)
    1516         4908 :             DEALLOCATE (rec_BI)
    1517              :          END DO
    1518              : 
    1519         2454 :          DEALLOCATE (local_BI)
    1520              :       END IF
    1521              : 
    1522        38501 :       DEALLOCATE (rec_col_row_info)
    1523              : 
    1524        38501 :    END SUBROUTINE grep_my_integrals
    1525              : 
    1526            0 : END MODULE mp2_integrals
        

Generated by: LCOV version 2.0-1