LCOV - code coverage report
Current view: top level - src - rpa_im_time.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 590 598 98.7 %
Date: 2024-12-21 06:28:57 Functions: 12 12 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief Routines for low-scaling RPA/GW with imaginary time
      10             : !> \par History
      11             : !>      10.2015 created [Jan Wilhelm]
      12             : ! **************************************************************************************************
      13             : MODULE rpa_im_time
      14             :    USE cell_types,                      ONLY: cell_type,&
      15             :                                               get_cell
      16             :    USE cp_dbcsr_api,                    ONLY: &
      17             :         dbcsr_add, dbcsr_clear, dbcsr_copy, dbcsr_create, dbcsr_distribution_get, &
      18             :         dbcsr_distribution_type, dbcsr_filter, dbcsr_get_info, dbcsr_init_p, dbcsr_p_type, &
      19             :         dbcsr_release_p, dbcsr_reserve_all_blocks, dbcsr_scale, dbcsr_set, dbcsr_type, &
      20             :         dbcsr_type_no_symmetry
      21             :    USE cp_dbcsr_operations,             ONLY: copy_fm_to_dbcsr,&
      22             :                                               dbcsr_allocate_matrix_set,&
      23             :                                               dbcsr_deallocate_matrix_set
      24             :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale,&
      25             :                                               cp_fm_scale
      26             :    USE cp_fm_struct,                    ONLY: cp_fm_struct_type
      27             :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      28             :                                               cp_fm_get_info,&
      29             :                                               cp_fm_release,&
      30             :                                               cp_fm_set_all,&
      31             :                                               cp_fm_to_fm,&
      32             :                                               cp_fm_type
      33             :    USE dbt_api,                         ONLY: &
      34             :         dbt_batched_contract_finalize, dbt_batched_contract_init, dbt_contract, dbt_copy, &
      35             :         dbt_copy_matrix_to_tensor, dbt_copy_tensor_to_matrix, dbt_create, dbt_destroy, dbt_filter, &
      36             :         dbt_get_info, dbt_nblks_total, dbt_nd_mp_comm, dbt_pgrid_destroy, dbt_pgrid_type, dbt_type
      37             :    USE hfx_types,                       ONLY: block_ind_type,&
      38             :                                               hfx_compression_type
      39             :    USE kinds,                           ONLY: dp,&
      40             :                                               int_8
      41             :    USE kpoint_types,                    ONLY: get_kpoint_info,&
      42             :                                               kpoint_env_type,&
      43             :                                               kpoint_type
      44             :    USE machine,                         ONLY: m_flush,&
      45             :                                               m_walltime
      46             :    USE mathconstants,                   ONLY: twopi
      47             :    USE message_passing,                 ONLY: mp_comm_type,&
      48             :                                               mp_para_env_type
      49             :    USE mp2_types,                       ONLY: mp2_type
      50             :    USE parallel_gemm_api,               ONLY: parallel_gemm
      51             :    USE particle_types,                  ONLY: particle_type
      52             :    USE qs_environment_types,            ONLY: get_qs_env,&
      53             :                                               qs_environment_type
      54             :    USE qs_mo_types,                     ONLY: get_mo_set,&
      55             :                                               mo_set_type
      56             :    USE qs_tensors,                      ONLY: decompress_tensor,&
      57             :                                               get_tensor_occupancy
      58             :    USE qs_tensors_types,                ONLY: create_2c_tensor
      59             :    USE rpa_gw_im_time_util,             ONLY: compute_weight_re_im,&
      60             :                                               get_atom_index_from_basis_function_index
      61             : #include "./base/base_uses.f90"
      62             : 
      63             :    IMPLICIT NONE
      64             : 
      65             :    PRIVATE
      66             : 
      67             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'rpa_im_time'
      68             : 
      69             :    PUBLIC :: compute_mat_P_omega, &
      70             :              compute_transl_dm, &
      71             :              init_cell_index_rpa, &
      72             :              zero_mat_P_omega, &
      73             :              compute_periodic_dm, &
      74             :              compute_mat_dm_global
      75             : 
      76             : CONTAINS
      77             : 
      78             : ! **************************************************************************************************
      79             : !> \brief ...
      80             : !> \param mat_P_omega ...
      81             : !> \param fm_scaled_dm_occ_tau ...
      82             : !> \param fm_scaled_dm_virt_tau ...
      83             : !> \param fm_mo_coeff_occ ...
      84             : !> \param fm_mo_coeff_virt ...
      85             : !> \param fm_mo_coeff_occ_scaled ...
      86             : !> \param fm_mo_coeff_virt_scaled ...
      87             : !> \param mat_P_global ...
      88             : !> \param matrix_s ...
      89             : !> \param ispin ...
      90             : !> \param t_3c_M ...
      91             : !> \param t_3c_O ...
      92             : !> \param t_3c_O_compressed ...
      93             : !> \param t_3c_O_ind ...
      94             : !> \param starts_array_mc ...
      95             : !> \param ends_array_mc ...
      96             : !> \param starts_array_mc_block ...
      97             : !> \param ends_array_mc_block ...
      98             : !> \param weights_cos_tf_t_to_w ...
      99             : !> \param tj ...
     100             : !> \param tau_tj ...
     101             : !> \param e_fermi ...
     102             : !> \param eps_filter ...
     103             : !> \param alpha ...
     104             : !> \param eps_filter_im_time ...
     105             : !> \param Eigenval ...
     106             : !> \param nmo ...
     107             : !> \param num_integ_points ...
     108             : !> \param cut_memory ...
     109             : !> \param unit_nr ...
     110             : !> \param mp2_env ...
     111             : !> \param para_env ...
     112             : !> \param qs_env ...
     113             : !> \param do_kpoints_from_Gamma ...
     114             : !> \param index_to_cell_3c ...
     115             : !> \param cell_to_index_3c ...
     116             : !> \param has_mat_P_blocks ...
     117             : !> \param do_ri_sos_laplace_mp2 ...
     118             : !> \param dbcsr_time ...
     119             : !> \param dbcsr_nflop ...
     120             : ! **************************************************************************************************
     121         528 :    SUBROUTINE compute_mat_P_omega(mat_P_omega, fm_scaled_dm_occ_tau, &
     122             :                                   fm_scaled_dm_virt_tau, fm_mo_coeff_occ, fm_mo_coeff_virt, &
     123             :                                   fm_mo_coeff_occ_scaled, fm_mo_coeff_virt_scaled, &
     124             :                                   mat_P_global, &
     125             :                                   matrix_s, &
     126             :                                   ispin, &
     127         352 :                                   t_3c_M, t_3c_O, t_3c_O_compressed, t_3c_O_ind, &
     128         176 :                                   starts_array_mc, ends_array_mc, &
     129         176 :                                   starts_array_mc_block, ends_array_mc_block, &
     130             :                                   weights_cos_tf_t_to_w, &
     131         176 :                                   tj, tau_tj, e_fermi, eps_filter, &
     132         176 :                                   alpha, eps_filter_im_time, Eigenval, nmo, &
     133             :                                   num_integ_points, cut_memory, unit_nr, &
     134             :                                   mp2_env, para_env, &
     135             :                                   qs_env, do_kpoints_from_Gamma, &
     136             :                                   index_to_cell_3c, cell_to_index_3c, &
     137         176 :                                   has_mat_P_blocks, do_ri_sos_laplace_mp2, &
     138             :                                   dbcsr_time, dbcsr_nflop)
     139             :       TYPE(dbcsr_p_type), DIMENSION(:, :), INTENT(IN)    :: mat_P_omega
     140             :       TYPE(cp_fm_type), INTENT(IN) :: fm_scaled_dm_occ_tau, fm_scaled_dm_virt_tau, &
     141             :          fm_mo_coeff_occ, fm_mo_coeff_virt, fm_mo_coeff_occ_scaled, fm_mo_coeff_virt_scaled
     142             :       TYPE(dbcsr_p_type), INTENT(INOUT)                  :: mat_P_global
     143             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
     144             :       INTEGER, INTENT(IN)                                :: ispin
     145             :       TYPE(dbt_type), INTENT(INOUT)                      :: t_3c_M
     146             :       TYPE(dbt_type), DIMENSION(:, :), INTENT(INOUT)     :: t_3c_O
     147             :       TYPE(hfx_compression_type), DIMENSION(:, :, :), &
     148             :          INTENT(INOUT)                                   :: t_3c_O_compressed
     149             :       TYPE(block_ind_type), DIMENSION(:, :, :), &
     150             :          INTENT(INOUT)                                   :: t_3c_O_ind
     151             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: starts_array_mc, ends_array_mc, &
     152             :                                                             starts_array_mc_block, &
     153             :                                                             ends_array_mc_block
     154             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :), &
     155             :          INTENT(IN)                                      :: weights_cos_tf_t_to_w
     156             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
     157             :          INTENT(IN)                                      :: tj
     158             :       INTEGER, INTENT(IN)                                :: num_integ_points, nmo
     159             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: Eigenval
     160             :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter_im_time, alpha, eps_filter, &
     161             :                                                             e_fermi
     162             :       REAL(KIND=dp), DIMENSION(0:num_integ_points), &
     163             :          INTENT(IN)                                      :: tau_tj
     164             :       INTEGER, INTENT(IN)                                :: cut_memory, unit_nr
     165             :       TYPE(mp2_type)                                     :: mp2_env
     166             :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env
     167             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     168             :       LOGICAL, INTENT(IN)                                :: do_kpoints_from_Gamma
     169             :       INTEGER, ALLOCATABLE, DIMENSION(:, :), INTENT(IN)  :: index_to_cell_3c
     170             :       INTEGER, ALLOCATABLE, DIMENSION(:, :, :), &
     171             :          INTENT(IN)                                      :: cell_to_index_3c
     172             :       LOGICAL, DIMENSION(:, :, :, :, :), INTENT(INOUT)   :: has_mat_P_blocks
     173             :       LOGICAL, INTENT(IN)                                :: do_ri_sos_laplace_mp2
     174             :       REAL(dp), INTENT(INOUT)                            :: dbcsr_time
     175             :       INTEGER(int_8), INTENT(INOUT)                      :: dbcsr_nflop
     176             : 
     177             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_mat_P_omega'
     178             : 
     179             :       INTEGER :: comm_2d_handle, handle, handle2, handle3, i, i_cell, i_cell_R_1, &
     180             :          i_cell_R_1_minus_S, i_cell_R_1_minus_T, i_cell_R_2, i_cell_R_2_minus_S_minus_T, i_cell_S, &
     181             :          i_cell_T, i_mem, iquad, j, j_mem, jquad, num_3c_repl, num_cells_dm, unit_nr_dbcsr
     182             :       INTEGER(int_8)                                     :: nze, nze_dm_occ, nze_dm_virt, nze_M_occ, &
     183             :                                                             nze_M_virt, nze_O
     184             :       INTEGER(KIND=int_8)                                :: flops_1_occ, flops_1_virt, flops_2
     185         352 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: dist_1, dist_2, mc_ranges, size_dm, &
     186         176 :                                                             size_P
     187             :       INTEGER, DIMENSION(2)                              :: pdims_2d
     188             :       INTEGER, DIMENSION(2, 1)                           :: ibounds_2, jbounds_2
     189             :       INTEGER, DIMENSION(2, 2)                           :: ibounds_1, jbounds_1
     190             :       INTEGER, DIMENSION(3)                              :: bounds_3c
     191         176 :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell_dm
     192             :       LOGICAL :: do_Gamma_RPA, do_kpoints_cubic_RPA, first_cycle_im_time, first_cycle_omega_loop, &
     193             :          memory_info, R_1_minus_S_needed, R_1_minus_T_needed, R_2_minus_S_minus_T_needed
     194             :       REAL(dp)                                           :: occ, occ_dm_occ, occ_dm_virt, occ_M_occ, &
     195             :                                                             occ_M_virt, occ_O, t1_flop
     196             :       REAL(KIND=dp)                                      :: omega, omega_old, t1, t2, tau, weight, &
     197             :                                                             weight_old
     198             :       TYPE(dbcsr_distribution_type)                      :: dist_P
     199         176 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_dm_occ_global, mat_dm_virt_global
     200         528 :       TYPE(dbt_pgrid_type)                               :: pgrid_2d
     201        3344 :       TYPE(dbt_type)                                     :: t_3c_M_occ, t_3c_M_occ_tmp, t_3c_M_virt, &
     202        4928 :                                                             t_3c_M_virt_tmp, t_dm, t_dm_tmp, t_P, &
     203        1232 :                                                             t_P_tmp
     204         352 :       TYPE(dbt_type), ALLOCATABLE, DIMENSION(:)          :: t_dm_occ, t_dm_virt
     205         176 :       TYPE(dbt_type), ALLOCATABLE, DIMENSION(:, :)       :: t_3c_O_occ, t_3c_O_virt
     206             :       TYPE(mp_comm_type)                                 :: comm_2d
     207             : 
     208         176 :       CALL timeset(routineN, handle)
     209             : 
     210         176 :       memory_info = mp2_env%ri_rpa_im_time%memory_info
     211         176 :       IF (memory_info) THEN
     212           0 :          unit_nr_dbcsr = unit_nr
     213             :       ELSE
     214         176 :          unit_nr_dbcsr = 0
     215             :       END IF
     216             : 
     217         176 :       do_kpoints_cubic_RPA = qs_env%mp2_env%ri_rpa_im_time%do_im_time_kpoints
     218         176 :       do_Gamma_RPA = .NOT. do_kpoints_cubic_RPA
     219         752 :       num_3c_repl = MAXVAL(cell_to_index_3c)
     220             : 
     221         176 :       first_cycle_im_time = .TRUE.
     222        4096 :       ALLOCATE (t_3c_O_occ(SIZE(t_3c_O, 1), SIZE(t_3c_O, 2)), t_3c_O_virt(SIZE(t_3c_O, 1), SIZE(t_3c_O, 2)))
     223         368 :       DO i = 1, SIZE(t_3c_O, 1)
     224         640 :          DO j = 1, SIZE(t_3c_O, 2)
     225         272 :             CALL dbt_create(t_3c_O(i, j), t_3c_O_occ(i, j))
     226         464 :             CALL dbt_create(t_3c_O(i, j), t_3c_O_virt(i, j))
     227             :          END DO
     228             :       END DO
     229             : 
     230         176 :       CALL dbt_create(t_3c_M, t_3c_M_occ, name="M occ (RI | AO AO)")
     231         176 :       CALL dbt_create(t_3c_M, t_3c_M_virt, name="M virt (RI | AO AO)")
     232             : 
     233         528 :       ALLOCATE (mc_ranges(cut_memory + 1))
     234         514 :       mc_ranges(:cut_memory) = starts_array_mc_block(:)
     235         176 :       mc_ranges(cut_memory + 1) = ends_array_mc_block(cut_memory) + 1
     236             : 
     237        1320 :       DO jquad = 1, num_integ_points
     238             : 
     239        1144 :          CALL para_env%sync()
     240        1144 :          t1 = m_walltime()
     241             : 
     242             :          CALL compute_mat_dm_global(fm_scaled_dm_occ_tau, fm_scaled_dm_virt_tau, tau_tj, num_integ_points, nmo, &
     243             :                                     fm_mo_coeff_occ, fm_mo_coeff_virt, fm_mo_coeff_occ_scaled, &
     244             :                                     fm_mo_coeff_virt_scaled, mat_dm_occ_global, mat_dm_virt_global, &
     245             :                                     matrix_s, ispin, &
     246             :                                     Eigenval, e_fermi, eps_filter, memory_info, unit_nr, &
     247             :                                     jquad, do_kpoints_cubic_RPA, do_kpoints_from_Gamma, qs_env, &
     248        1144 :                                     num_cells_dm, index_to_cell_dm, para_env)
     249             : 
     250       11488 :          ALLOCATE (t_dm_virt(num_cells_dm))
     251       10344 :          ALLOCATE (t_dm_occ(num_cells_dm))
     252        1144 :          CALL dbcsr_get_info(mat_P_global%matrix, distribution=dist_P)
     253        1144 :          CALL dbcsr_distribution_get(dist_P, group=comm_2d_handle, nprows=pdims_2d(1), npcols=pdims_2d(2))
     254        1144 :          CALL comm_2d%set_handle(comm_2d_handle)
     255             : 
     256        1144 :          pgrid_2d = dbt_nd_mp_comm(comm_2d, [1], [2], pdims_2d=pdims_2d)
     257        3432 :          ALLOCATE (size_P(dbt_nblks_total(t_3c_M, 1)))
     258        1144 :          CALL dbt_get_info(t_3c_M, blk_size_1=size_P)
     259             : 
     260        3432 :          ALLOCATE (size_dm(dbt_nblks_total(t_3c_O(1, 1), 3)))
     261        1144 :          CALL dbt_get_info(t_3c_O(1, 1), blk_size_3=size_dm)
     262        1144 :          CALL create_2c_tensor(t_dm, dist_1, dist_2, pgrid_2d, size_dm, size_dm, name="D (AO | AO)")
     263        1144 :          DEALLOCATE (size_dm)
     264        1144 :          DEALLOCATE (dist_1, dist_2)
     265             :          CALL create_2c_tensor(t_P, dist_1, dist_2, pgrid_2d, size_P, size_P, name="P (RI | RI)")
     266        1144 :          DEALLOCATE (size_P)
     267        1144 :          DEALLOCATE (dist_1, dist_2)
     268        1144 :          CALL dbt_pgrid_destroy(pgrid_2d)
     269             : 
     270        2336 :          DO i_cell = 1, num_cells_dm
     271        1192 :             CALL dbt_create(t_dm, t_dm_virt(i_cell), name="D virt (AO | AO)")
     272        1192 :             CALL dbt_create(mat_dm_virt_global(jquad, i_cell)%matrix, t_dm_tmp)
     273        1192 :             CALL dbt_copy_matrix_to_tensor(mat_dm_virt_global(jquad, i_cell)%matrix, t_dm_tmp)
     274        1192 :             CALL dbt_copy(t_dm_tmp, t_dm_virt(i_cell), move_data=.TRUE.)
     275        1192 :             CALL dbcsr_clear(mat_dm_virt_global(jquad, i_cell)%matrix)
     276             : 
     277        1192 :             CALL dbt_create(t_dm, t_dm_occ(i_cell), name="D occ (AO | AO)")
     278        1192 :             CALL dbt_copy_matrix_to_tensor(mat_dm_occ_global(jquad, i_cell)%matrix, t_dm_tmp)
     279        1192 :             CALL dbt_copy(t_dm_tmp, t_dm_occ(i_cell), move_data=.TRUE.)
     280        1192 :             CALL dbt_destroy(t_dm_tmp)
     281        2336 :             CALL dbcsr_clear(mat_dm_occ_global(jquad, i_cell)%matrix)
     282             :          END DO
     283             : 
     284        1144 :          CALL get_tensor_occupancy(t_dm_occ(1), nze_dm_occ, occ_dm_occ)
     285        1144 :          CALL get_tensor_occupancy(t_dm_virt(1), nze_dm_virt, occ_dm_virt)
     286             : 
     287        1144 :          CALL dbt_destroy(t_dm)
     288             : 
     289        1144 :          CALL dbt_create(t_3c_O_occ(1, 1), t_3c_M_occ_tmp, name="M (RI AO | AO)")
     290        1144 :          CALL dbt_create(t_3c_O_virt(1, 1), t_3c_M_virt_tmp, name="M (RI AO | AO)")
     291             : 
     292        1144 :          CALL timeset(routineN//"_contract", handle2)
     293             : 
     294        1144 :          CALL para_env%sync()
     295        1144 :          t1_flop = m_walltime()
     296             : 
     297        2384 :          DO i = 1, SIZE(t_3c_O_occ, 1)
     298        4104 :             DO j = 1, SIZE(t_3c_O_occ, 2)
     299        2960 :                CALL dbt_batched_contract_init(t_3c_O_occ(i, j), batch_range_2=mc_ranges, batch_range_3=mc_ranges)
     300             :             END DO
     301             :          END DO
     302        2384 :          DO i = 1, SIZE(t_3c_O_virt, 1)
     303        4104 :             DO j = 1, SIZE(t_3c_O_virt, 2)
     304        2960 :                CALL dbt_batched_contract_init(t_3c_O_virt(i, j), batch_range_2=mc_ranges, batch_range_3=mc_ranges)
     305             :             END DO
     306             :          END DO
     307        1144 :          CALL dbt_batched_contract_init(t_3c_M_occ_tmp, batch_range_2=mc_ranges, batch_range_3=mc_ranges)
     308        1144 :          CALL dbt_batched_contract_init(t_3c_M_virt_tmp, batch_range_2=mc_ranges, batch_range_3=mc_ranges)
     309        1144 :          CALL dbt_batched_contract_init(t_3c_M_occ, batch_range_2=mc_ranges, batch_range_3=mc_ranges)
     310        1144 :          CALL dbt_batched_contract_init(t_3c_M_virt, batch_range_2=mc_ranges, batch_range_3=mc_ranges)
     311             : 
     312        2312 :          DO i_cell_T = 1, num_cells_dm/2 + 1
     313             : 
     314        1168 :             IF (.NOT. ANY(has_mat_P_blocks(i_cell_T, :, :, :, :))) CYCLE
     315             : 
     316        1168 :             CALL dbt_batched_contract_init(t_P)
     317             : 
     318        1168 :             IF (do_Gamma_RPA) THEN
     319        1120 :                nze_O = 0
     320        1120 :                nze_M_virt = 0
     321        1120 :                nze_M_occ = 0
     322        1120 :                occ_M_virt = 0.0_dp
     323        1120 :                occ_M_occ = 0.0_dp
     324        1120 :                occ_O = 0.0_dp
     325             :             END IF
     326             : 
     327        3096 :             DO j_mem = 1, cut_memory
     328             : 
     329        1928 :                CALL dbt_get_info(t_3c_O_occ(1, 1), nfull_total=bounds_3c)
     330             : 
     331        5784 :                jbounds_1(:, 1) = [1, bounds_3c(1)]
     332        5784 :                jbounds_1(:, 2) = [starts_array_mc(j_mem), ends_array_mc(j_mem)]
     333             : 
     334        5784 :                jbounds_2(:, 1) = [starts_array_mc(j_mem), ends_array_mc(j_mem)]
     335             : 
     336        1928 :                IF (do_Gamma_RPA) CALL dbt_batched_contract_init(t_dm_virt(1))
     337             : 
     338        6264 :                DO i_mem = 1, cut_memory
     339             : 
     340        4496 :                   IF (.NOT. ANY(has_mat_P_blocks(i_cell_T, i_mem, j_mem, :, :))) CYCLE
     341             : 
     342       12768 :                   ibounds_1(:, 1) = [1, bounds_3c(1)]
     343       12768 :                   ibounds_1(:, 2) = [starts_array_mc(i_mem), ends_array_mc(i_mem)]
     344             : 
     345       12768 :                   ibounds_2(:, 1) = [starts_array_mc(i_mem), ends_array_mc(i_mem)]
     346             : 
     347        4256 :                   IF (unit_nr_dbcsr > 0) WRITE (UNIT=unit_nr_dbcsr, FMT="(T3,A,I3,1X,I3)") &
     348           0 :                      "RPA_LOW_SCALING_INFO| Memory Cut iteration", i_mem, j_mem
     349             : 
     350       10920 :                   DO i_cell_R_1 = 1, num_3c_repl
     351             : 
     352       16208 :                      DO i_cell_R_2 = 1, num_3c_repl
     353             : 
     354        7136 :                         IF (.NOT. has_mat_P_blocks(i_cell_T, i_mem, j_mem, i_cell_R_1, i_cell_R_2)) CYCLE
     355             : 
     356             :                         CALL get_diff_index_3c(i_cell_R_1, i_cell_T, i_cell_R_1_minus_T, &
     357             :                                                index_to_cell_3c, cell_to_index_3c, index_to_cell_dm, &
     358        5186 :                                                R_1_minus_T_needed, do_kpoints_cubic_RPA)
     359             : 
     360        5186 :                         IF (do_Gamma_RPA) CALL dbt_batched_contract_init(t_dm_occ(1))
     361       12472 :                         DO i_cell_S = 1, num_cells_dm
     362             :                            CALL get_diff_index_3c(i_cell_R_1, i_cell_S, i_cell_R_1_minus_S, index_to_cell_3c, &
     363             :                                                   cell_to_index_3c, index_to_cell_dm, R_1_minus_S_needed, &
     364        7286 :                                                   do_kpoints_cubic_RPA)
     365       12472 :                            IF (R_1_minus_S_needed) THEN
     366             : 
     367        7086 :                               CALL timeset(routineN//"_calc_M_occ_t", handle3)
     368             :                               CALL decompress_tensor(t_3c_O(i_cell_R_1_minus_S, i_cell_R_2), &
     369             :                                                      t_3c_O_ind(i_cell_R_1_minus_S, i_cell_R_2, j_mem)%ind, &
     370             :                                                      t_3c_O_compressed(i_cell_R_1_minus_S, i_cell_R_2, j_mem), &
     371        7086 :                                                      qs_env%mp2_env%ri_rpa_im_time%eps_compress)
     372             : 
     373        7086 :                               IF (do_Gamma_RPA .AND. i_mem == 1) THEN
     374        1836 :                                  CALL get_tensor_occupancy(t_3c_O(1, 1), nze, occ)
     375        1836 :                                  nze_O = nze_O + nze
     376        1836 :                                  occ_O = occ_O + occ
     377             :                               END IF
     378             : 
     379             :                               CALL dbt_copy(t_3c_O(i_cell_R_1_minus_S, i_cell_R_2), &
     380        7086 :                                             t_3c_O_occ(i_cell_R_1_minus_S, i_cell_R_2), move_data=.TRUE.)
     381             : 
     382             :                               CALL dbt_contract(alpha=1.0_dp, &
     383             :                                                 tensor_1=t_3c_O_occ(i_cell_R_1_minus_S, i_cell_R_2), &
     384             :                                                 tensor_2=t_dm_occ(i_cell_S), &
     385             :                                                 beta=1.0_dp, &
     386             :                                                 tensor_3=t_3c_M_occ_tmp, &
     387             :                                                 contract_1=[3], notcontract_1=[1, 2], &
     388             :                                                 contract_2=[2], notcontract_2=[1], &
     389             :                                                 map_1=[1, 2], map_2=[3], &
     390             :                                                 bounds_2=jbounds_1, bounds_3=ibounds_2, &
     391             :                                                 filter_eps=eps_filter, unit_nr=unit_nr_dbcsr, &
     392        7086 :                                                 flop=flops_1_occ)
     393        7086 :                               CALL timestop(handle3)
     394             : 
     395        7086 :                               dbcsr_nflop = dbcsr_nflop + flops_1_occ
     396             : 
     397             :                            END IF
     398             :                         END DO
     399             : 
     400        5186 :                         IF (do_Gamma_RPA) CALL dbt_batched_contract_finalize(t_dm_occ(1))
     401             : 
     402             :                         ! copy matrix to optimal contraction layout - copy is done manually in order
     403             :                         ! to better control memory allocations (we can release data of previous
     404             :                         ! representation)
     405        5186 :                         CALL timeset(routineN//"_copy_M_occ_t", handle3)
     406        5186 :                         CALL dbt_copy(t_3c_M_occ_tmp, t_3c_M_occ, order=[1, 3, 2], move_data=.TRUE.)
     407        5186 :                         CALL dbt_filter(t_3c_M_occ, eps_filter)
     408        5186 :                         CALL timestop(handle3)
     409             : 
     410        5186 :                         IF (do_Gamma_RPA) THEN
     411        4136 :                            CALL get_tensor_occupancy(t_3c_M_occ, nze, occ)
     412        4136 :                            nze_M_occ = nze_M_occ + nze
     413        4136 :                            occ_M_occ = occ_M_occ + occ
     414             :                         END IF
     415             : 
     416       12472 :                         DO i_cell_S = 1, num_cells_dm
     417             :                            CALL get_diff_diff_index_3c(i_cell_R_2, i_cell_S, i_cell_T, i_cell_R_2_minus_S_minus_T, &
     418             :                                                        index_to_cell_3c, cell_to_index_3c, index_to_cell_dm, &
     419        7286 :                                                        R_2_minus_S_minus_T_needed, do_kpoints_cubic_RPA)
     420             : 
     421       12472 :                            IF (R_1_minus_T_needed .AND. R_2_minus_S_minus_T_needed) THEN
     422             :                               CALL decompress_tensor(t_3c_O(i_cell_R_2_minus_S_minus_T, i_cell_R_1_minus_T), &
     423             :                                                      t_3c_O_ind(i_cell_R_2_minus_S_minus_T, i_cell_R_1_minus_T, i_mem)%ind, &
     424             :                                                      t_3c_O_compressed(i_cell_R_2_minus_S_minus_T, i_cell_R_1_minus_T, i_mem), &
     425        6916 :                                                      qs_env%mp2_env%ri_rpa_im_time%eps_compress)
     426             : 
     427             :                               CALL dbt_copy(t_3c_O(i_cell_R_2_minus_S_minus_T, i_cell_R_1_minus_T), &
     428        6916 :                                             t_3c_O_virt(i_cell_R_2_minus_S_minus_T, i_cell_R_1_minus_T), move_data=.TRUE.)
     429             : 
     430        6916 :                               CALL timeset(routineN//"_calc_M_virt_t", handle3)
     431             :                               CALL dbt_contract(alpha=alpha/2.0_dp, &
     432             :                                                 tensor_1=t_3c_O_virt( &
     433             :                                                 i_cell_R_2_minus_S_minus_T, i_cell_R_1_minus_T), &
     434             :                                                 tensor_2=t_dm_virt(i_cell_S), &
     435             :                                                 beta=1.0_dp, &
     436             :                                                 tensor_3=t_3c_M_virt_tmp, &
     437             :                                                 contract_1=[3], notcontract_1=[1, 2], &
     438             :                                                 contract_2=[2], notcontract_2=[1], &
     439             :                                                 map_1=[1, 2], map_2=[3], &
     440             :                                                 bounds_2=ibounds_1, bounds_3=jbounds_2, &
     441             :                                                 filter_eps=eps_filter, unit_nr=unit_nr_dbcsr, &
     442        6916 :                                                 flop=flops_1_virt)
     443        6916 :                               CALL timestop(handle3)
     444             : 
     445        6916 :                               dbcsr_nflop = dbcsr_nflop + flops_1_virt
     446             : 
     447             :                            END IF
     448             :                         END DO
     449             : 
     450        5186 :                         CALL timeset(routineN//"_copy_M_virt_t", handle3)
     451        5186 :                         CALL dbt_copy(t_3c_M_virt_tmp, t_3c_M_virt, move_data=.TRUE.)
     452        5186 :                         CALL dbt_filter(t_3c_M_virt, eps_filter)
     453        5186 :                         CALL timestop(handle3)
     454             : 
     455        5186 :                         IF (do_Gamma_RPA) THEN
     456        4136 :                            CALL get_tensor_occupancy(t_3c_M_virt, nze, occ)
     457        4136 :                            nze_M_virt = nze_M_virt + nze
     458        4136 :                            occ_M_virt = occ_M_virt + occ
     459             :                         END IF
     460             : 
     461             :                         flops_2 = 0
     462             : 
     463        5186 :                         CALL timeset(routineN//"_calc_P_t", handle3)
     464             : 
     465             :                         CALL dbt_contract(alpha=1.0_dp, tensor_1=t_3c_M_occ, &
     466             :                                           tensor_2=t_3c_M_virt, &
     467             :                                           beta=1.0_dp, &
     468             :                                           tensor_3=t_P, &
     469             :                                           contract_1=[2, 3], notcontract_1=[1], &
     470             :                                           contract_2=[2, 3], notcontract_2=[1], &
     471             :                                           map_1=[1], map_2=[2], &
     472             :                                           filter_eps=eps_filter_im_time/REAL(cut_memory**2, KIND=dp), &
     473             :                                           flop=flops_2, &
     474             :                                           move_data=.TRUE., &
     475        5186 :                                           unit_nr=unit_nr_dbcsr)
     476             : 
     477        5186 :                         CALL timestop(handle3)
     478             : 
     479        5186 :                         first_cycle_im_time = .FALSE.
     480             : 
     481        5186 :                         IF (jquad == 1 .AND. flops_2 == 0) &
     482       25886 :                            has_mat_P_blocks(i_cell_T, i_mem, j_mem, i_cell_R_1, i_cell_R_2) = .FALSE.
     483             : 
     484             :                      END DO
     485             :                   END DO
     486             :                END DO
     487        3096 :                IF (do_Gamma_RPA) CALL dbt_batched_contract_finalize(t_dm_virt(1))
     488             :             END DO
     489             : 
     490        1168 :             CALL dbt_batched_contract_finalize(t_P, unit_nr=unit_nr_dbcsr)
     491             : 
     492        1168 :             CALL dbt_create(mat_P_global%matrix, t_P_tmp)
     493        1168 :             CALL dbt_copy(t_P, t_P_tmp, move_data=.TRUE.)
     494        1168 :             CALL dbt_copy_tensor_to_matrix(t_P_tmp, mat_P_global%matrix)
     495        1168 :             CALL dbt_destroy(t_P_tmp)
     496             : 
     497        2312 :             IF (do_ri_sos_laplace_mp2) THEN
     498             :                ! For RI-SOS-Laplace-MP2 we do not perform a cosine transform,
     499             :                ! but we have to copy P_local to the output matrix
     500             : 
     501         138 :                CALL dbcsr_add(mat_P_omega(jquad, i_cell_T)%matrix, mat_P_global%matrix, 1.0_dp, 1.0_dp)
     502             :             ELSE
     503        1030 :                CALL timeset(routineN//"_Fourier_transform", handle3)
     504             : 
     505             :                ! Fourier transform of P(it) to P(iw)
     506        1030 :                first_cycle_omega_loop = .TRUE.
     507             : 
     508        1030 :                tau = tau_tj(jquad)
     509             : 
     510       13676 :                DO iquad = 1, num_integ_points
     511             : 
     512       12646 :                   omega = tj(iquad)
     513       12646 :                   weight = weights_cos_tf_t_to_w(iquad, jquad)
     514             : 
     515       12646 :                   IF (first_cycle_omega_loop) THEN
     516             :                      ! no multiplication with 2.0 as in Kresses paper (Kaltak, JCTC 10, 2498 (2014), Eq. 12)
     517             :                      ! because this factor is already absorbed in the weight w_j
     518        1030 :                      CALL dbcsr_scale(mat_P_global%matrix, COS(omega*tau)*weight)
     519             :                   ELSE
     520       11616 :                      CALL dbcsr_scale(mat_P_global%matrix, COS(omega*tau)/COS(omega_old*tau)*weight/weight_old)
     521             :                   END IF
     522             : 
     523       12646 :                   CALL dbcsr_add(mat_P_omega(iquad, i_cell_T)%matrix, mat_P_global%matrix, 1.0_dp, 1.0_dp)
     524             : 
     525       12646 :                   first_cycle_omega_loop = .FALSE.
     526             : 
     527       12646 :                   omega_old = omega
     528       13676 :                   weight_old = weight
     529             : 
     530             :                END DO
     531             : 
     532        1030 :                CALL timestop(handle3)
     533             :             END IF
     534             : 
     535             :          END DO
     536             : 
     537        1144 :          CALL timestop(handle2)
     538             : 
     539        1144 :          CALL dbt_batched_contract_finalize(t_3c_M_occ_tmp)
     540        1144 :          CALL dbt_batched_contract_finalize(t_3c_M_virt_tmp)
     541        1144 :          CALL dbt_batched_contract_finalize(t_3c_M_occ)
     542        1144 :          CALL dbt_batched_contract_finalize(t_3c_M_virt)
     543             : 
     544        2384 :          DO i = 1, SIZE(t_3c_O_occ, 1)
     545        4104 :             DO j = 1, SIZE(t_3c_O_occ, 2)
     546        2960 :                CALL dbt_batched_contract_finalize(t_3c_O_occ(i, j))
     547             :             END DO
     548             :          END DO
     549             : 
     550        2384 :          DO i = 1, SIZE(t_3c_O_virt, 1)
     551        4104 :             DO j = 1, SIZE(t_3c_O_virt, 2)
     552        2960 :                CALL dbt_batched_contract_finalize(t_3c_O_virt(i, j))
     553             :             END DO
     554             :          END DO
     555             : 
     556        1144 :          CALL dbt_destroy(t_P)
     557        2336 :          DO i_cell = 1, num_cells_dm
     558        1192 :             CALL dbt_destroy(t_dm_virt(i_cell))
     559        2336 :             CALL dbt_destroy(t_dm_occ(i_cell))
     560             :          END DO
     561             : 
     562        1144 :          CALL dbt_destroy(t_3c_M_occ_tmp)
     563        1144 :          CALL dbt_destroy(t_3c_M_virt_tmp)
     564        2336 :          DEALLOCATE (t_dm_virt)
     565        2336 :          DEALLOCATE (t_dm_occ)
     566             : 
     567        1144 :          CALL para_env%sync()
     568        1144 :          t2 = m_walltime()
     569             : 
     570        1144 :          dbcsr_time = dbcsr_time + t2 - t1_flop
     571             : 
     572        7040 :          IF (unit_nr > 0) THEN
     573             :             WRITE (unit_nr, '(/T3,A,1X,I3)') &
     574         572 :                'RPA_LOW_SCALING_INFO| Info for time point', jquad
     575             :             WRITE (unit_nr, '(T6,A,T56,F25.1)') &
     576         572 :                'Execution time (s):', t2 - t1
     577             :             WRITE (unit_nr, '(T6,A,T63,ES7.1,1X,A1,1X,F7.3,A1)') &
     578         572 :                'Occupancy of D occ:', REAL(nze_dm_occ, dp), '/', occ_dm_occ*100, '%'
     579             :             WRITE (unit_nr, '(T6,A,T63,ES7.1,1X,A1,1X,F7.3,A1)') &
     580         572 :                'Occupancy of D virt:', REAL(nze_dm_virt, dp), '/', occ_dm_virt*100, '%'
     581         572 :             IF (do_Gamma_RPA) THEN
     582             :                WRITE (unit_nr, '(T6,A,T63,ES7.1,1X,A1,1X,F7.3,A1)') &
     583         560 :                   'Occupancy of 3c ints:', REAL(nze_O, dp), '/', occ_O*100, '%'
     584             :                WRITE (unit_nr, '(T6,A,T63,ES7.1,1X,A1,1X,F7.3,A1)') &
     585         560 :                   'Occupancy of M occ:', REAL(nze_M_occ, dp), '/', occ_M_occ*100, '%'
     586             :                WRITE (unit_nr, '(T6,A,T63,ES7.1,1X,A1,1X,F7.3,A1)') &
     587         560 :                   'Occupancy of M virt:', REAL(nze_M_virt, dp), '/', occ_M_virt*100, '%'
     588             :             END IF
     589         572 :             WRITE (unit_nr, *)
     590         572 :             CALL m_flush(unit_nr)
     591             :          END IF
     592             : 
     593             :       END DO ! time points
     594             : 
     595         176 :       CALL dbt_destroy(t_3c_M_occ)
     596         176 :       CALL dbt_destroy(t_3c_M_virt)
     597             : 
     598         368 :       DO i = 1, SIZE(t_3c_O, 1)
     599         640 :          DO j = 1, SIZE(t_3c_O, 2)
     600         272 :             CALL dbt_destroy(t_3c_O_occ(i, j))
     601         464 :             CALL dbt_destroy(t_3c_O_virt(i, j))
     602             :          END DO
     603             :       END DO
     604             : 
     605         176 :       CALL clean_up(mat_dm_occ_global, mat_dm_virt_global)
     606             : 
     607         176 :       CALL timestop(handle)
     608             : 
     609        1072 :    END SUBROUTINE compute_mat_P_omega
     610             : 
     611             : ! **************************************************************************************************
     612             : !> \brief ...
     613             : !> \param mat_P_omega ...
     614             : ! **************************************************************************************************
     615         176 :    SUBROUTINE zero_mat_P_omega(mat_P_omega)
     616             :       TYPE(dbcsr_p_type), DIMENSION(:, :), INTENT(IN)    :: mat_P_omega
     617             : 
     618             :       INTEGER                                            :: i_kp, jquad
     619             : 
     620        1320 :       DO jquad = 1, SIZE(mat_P_omega, 1)
     621        5788 :          DO i_kp = 1, SIZE(mat_P_omega, 2)
     622             : 
     623        5612 :             CALL dbcsr_set(mat_P_omega(jquad, i_kp)%matrix, 0.0_dp)
     624             : 
     625             :          END DO
     626             :       END DO
     627             : 
     628         176 :    END SUBROUTINE zero_mat_P_omega
     629             : 
     630             : ! **************************************************************************************************
     631             : !> \brief ...
     632             : !> \param fm_scaled_dm_occ_tau ...
     633             : !> \param fm_scaled_dm_virt_tau ...
     634             : !> \param tau_tj ...
     635             : !> \param num_integ_points ...
     636             : !> \param nmo ...
     637             : !> \param fm_mo_coeff_occ ...
     638             : !> \param fm_mo_coeff_virt ...
     639             : !> \param fm_mo_coeff_occ_scaled ...
     640             : !> \param fm_mo_coeff_virt_scaled ...
     641             : !> \param mat_dm_occ_global ...
     642             : !> \param mat_dm_virt_global ...
     643             : !> \param matrix_s ...
     644             : !> \param ispin ...
     645             : !> \param Eigenval ...
     646             : !> \param e_fermi ...
     647             : !> \param eps_filter ...
     648             : !> \param memory_info ...
     649             : !> \param unit_nr ...
     650             : !> \param jquad ...
     651             : !> \param do_kpoints_cubic_RPA ...
     652             : !> \param do_kpoints_from_Gamma ...
     653             : !> \param qs_env ...
     654             : !> \param num_cells_dm ...
     655             : !> \param index_to_cell_dm ...
     656             : !> \param para_env ...
     657             : ! **************************************************************************************************
     658        2628 :    SUBROUTINE compute_mat_dm_global(fm_scaled_dm_occ_tau, fm_scaled_dm_virt_tau, tau_tj, num_integ_points, nmo, &
     659             :                                     fm_mo_coeff_occ, fm_mo_coeff_virt, fm_mo_coeff_occ_scaled, &
     660             :                                     fm_mo_coeff_virt_scaled, mat_dm_occ_global, mat_dm_virt_global, &
     661        1314 :                                     matrix_s, ispin, &
     662        1314 :                                     Eigenval, e_fermi, eps_filter, memory_info, unit_nr, &
     663             :                                     jquad, do_kpoints_cubic_RPA, do_kpoints_from_Gamma, qs_env, &
     664             :                                     num_cells_dm, index_to_cell_dm, para_env)
     665             : 
     666             :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_scaled_dm_occ_tau, &
     667             :                                                             fm_scaled_dm_virt_tau
     668             :       INTEGER, INTENT(IN)                                :: num_integ_points
     669             :       REAL(KIND=dp), DIMENSION(0:num_integ_points), &
     670             :          INTENT(IN)                                      :: tau_tj
     671             :       INTEGER, INTENT(IN)                                :: nmo
     672             :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_mo_coeff_occ, fm_mo_coeff_virt, &
     673             :                                                             fm_mo_coeff_occ_scaled, &
     674             :                                                             fm_mo_coeff_virt_scaled
     675             :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_dm_occ_global, mat_dm_virt_global
     676             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN)       :: matrix_s
     677             :       INTEGER, INTENT(IN)                                :: ispin
     678             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: Eigenval
     679             :       REAL(KIND=dp), INTENT(IN)                          :: e_fermi, eps_filter
     680             :       LOGICAL, INTENT(IN)                                :: memory_info
     681             :       INTEGER, INTENT(IN)                                :: unit_nr, jquad
     682             :       LOGICAL, INTENT(IN)                                :: do_kpoints_cubic_RPA, &
     683             :                                                             do_kpoints_from_Gamma
     684             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     685             :       INTEGER, INTENT(OUT)                               :: num_cells_dm
     686             :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell_dm
     687             :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env
     688             : 
     689             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_mat_dm_global'
     690             :       REAL(KIND=dp), PARAMETER                           :: stabilize_exp = 70.0_dp
     691             : 
     692             :       INTEGER                                            :: handle, i_global, iiB, iquad, jjB, &
     693             :                                                             ncol_local, nrow_local, size_dm_occ, &
     694             :                                                             size_dm_virt
     695        1314 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
     696             :       REAL(KIND=dp)                                      :: tau
     697             : 
     698        1314 :       CALL timeset(routineN, handle)
     699             : 
     700        1314 :       IF (memory_info .AND. unit_nr > 0) WRITE (UNIT=unit_nr, FMT="(T3,A,T75,i6)") &
     701           0 :          "RPA_LOW_SCALING_INFO| Started with time point: ", jquad
     702             : 
     703        1314 :       tau = tau_tj(jquad)
     704             : 
     705        1314 :       IF (do_kpoints_cubic_RPA) THEN
     706             : 
     707             :          CALL compute_transl_dm(mat_dm_occ_global, qs_env, &
     708             :                                 ispin, num_integ_points, jquad, e_fermi, tau, &
     709             :                                 eps_filter, num_cells_dm, index_to_cell_dm, &
     710          24 :                                 remove_occ=.FALSE., remove_virt=.TRUE., first_jquad=1)
     711             : 
     712             :          CALL compute_transl_dm(mat_dm_virt_global, qs_env, &
     713             :                                 ispin, num_integ_points, jquad, e_fermi, tau, &
     714             :                                 eps_filter, num_cells_dm, index_to_cell_dm, &
     715          24 :                                 remove_occ=.TRUE., remove_virt=.FALSE., first_jquad=1)
     716             : 
     717        1290 :       ELSE IF (do_kpoints_from_Gamma) THEN
     718             : 
     719             :          CALL compute_periodic_dm(mat_dm_occ_global, qs_env, &
     720             :                                   ispin, num_integ_points, jquad, e_fermi, tau, &
     721             :                                   remove_occ=.FALSE., remove_virt=.TRUE., &
     722         132 :                                   alloc_dm=(jquad == 1))
     723             : 
     724             :          CALL compute_periodic_dm(mat_dm_virt_global, qs_env, &
     725             :                                   ispin, num_integ_points, jquad, e_fermi, tau, &
     726             :                                   remove_occ=.TRUE., remove_virt=.FALSE., &
     727         132 :                                   alloc_dm=(jquad == 1))
     728             : 
     729         132 :          num_cells_dm = 1
     730             : 
     731             :       ELSE
     732             : 
     733        1158 :          num_cells_dm = 1
     734             : 
     735        1158 :          CALL para_env%sync()
     736             : 
     737             :          ! get info of fm_mo_coeff_occ
     738             :          CALL cp_fm_get_info(matrix=fm_mo_coeff_occ, &
     739             :                              nrow_local=nrow_local, &
     740             :                              ncol_local=ncol_local, &
     741             :                              row_indices=row_indices, &
     742        1158 :                              col_indices=col_indices)
     743             : 
     744             :          ! Multiply the occupied and the virtual MO coefficients with the factor exp((-e_i-e_F)*tau/2).
     745             :          ! Then, we simply get the sum over all occ states and virt. states by a simple matrix-matrix
     746             :          ! multiplication.
     747             : 
     748             :          ! first, the occ
     749       16269 :          DO jjB = 1, nrow_local
     750      481262 :             DO iiB = 1, ncol_local
     751      464993 :                i_global = col_indices(iiB)
     752             : 
     753             :                ! hard coded: exponential function gets NaN if argument is negative with large absolute value
     754             :                ! use 69, since e^(-69) = 10^(-30) which should be sufficiently small that it does not matter
     755      480104 :                IF (ABS(tau*0.5_dp*(Eigenval(i_global) - e_fermi)) < stabilize_exp) THEN
     756             :                   fm_mo_coeff_occ_scaled%local_data(jjB, iiB) = &
     757      398777 :                      fm_mo_coeff_occ%local_data(jjB, iiB)*EXP(tau*0.5_dp*(Eigenval(i_global) - e_fermi))
     758             :                ELSE
     759       66216 :                   fm_mo_coeff_occ_scaled%local_data(jjB, iiB) = 0.0_dp
     760             :                END IF
     761             : 
     762             :             END DO
     763             :          END DO
     764             : 
     765             :          ! get info of fm_mo_coeff_virt
     766             :          CALL cp_fm_get_info(matrix=fm_mo_coeff_virt, &
     767             :                              nrow_local=nrow_local, &
     768             :                              ncol_local=ncol_local, &
     769             :                              row_indices=row_indices, &
     770        1158 :                              col_indices=col_indices)
     771             : 
     772             :          ! the same for virt
     773       16269 :          DO jjB = 1, nrow_local
     774      481262 :             DO iiB = 1, ncol_local
     775      464993 :                i_global = col_indices(iiB)
     776             : 
     777      480104 :                IF (ABS(tau*0.5_dp*(Eigenval(i_global) - e_fermi)) < stabilize_exp) THEN
     778             :                   fm_mo_coeff_virt_scaled%local_data(jjB, iiB) = &
     779      398777 :                      fm_mo_coeff_virt%local_data(jjB, iiB)*EXP(-tau*0.5_dp*(Eigenval(i_global) - e_fermi))
     780             :                ELSE
     781       66216 :                   fm_mo_coeff_virt_scaled%local_data(jjB, iiB) = 0.0_dp
     782             :                END IF
     783             : 
     784             :             END DO
     785             :          END DO
     786             : 
     787        1158 :          CALL para_env%sync()
     788             : 
     789        1158 :          size_dm_occ = nmo
     790        1158 :          size_dm_virt = nmo
     791             : 
     792             :          CALL parallel_gemm(transa="N", transb="T", m=size_dm_occ, n=size_dm_occ, k=nmo, alpha=1.0_dp, &
     793             :                             matrix_a=fm_mo_coeff_occ_scaled, matrix_b=fm_mo_coeff_occ_scaled, beta=0.0_dp, &
     794        1158 :                             matrix_c=fm_scaled_dm_occ_tau)
     795             : 
     796             :          CALL parallel_gemm(transa="N", transb="T", m=size_dm_virt, n=size_dm_virt, k=nmo, alpha=1.0_dp, &
     797             :                             matrix_a=fm_mo_coeff_virt_scaled, matrix_b=fm_mo_coeff_virt_scaled, beta=0.0_dp, &
     798        1158 :                             matrix_c=fm_scaled_dm_virt_tau)
     799             : 
     800        1158 :          IF (jquad == 1) THEN
     801             : 
     802             :             ! transfer fm density matrices to dbcsr matrix
     803         212 :             NULLIFY (mat_dm_occ_global)
     804         212 :             CALL dbcsr_allocate_matrix_set(mat_dm_occ_global, num_integ_points, 1)
     805             : 
     806        1370 :             DO iquad = 1, num_integ_points
     807             : 
     808        1158 :                ALLOCATE (mat_dm_occ_global(iquad, 1)%matrix)
     809             :                CALL dbcsr_create(matrix=mat_dm_occ_global(iquad, 1)%matrix, &
     810             :                                  template=matrix_s(1)%matrix, &
     811        1370 :                                  matrix_type=dbcsr_type_no_symmetry)
     812             : 
     813             :             END DO
     814             : 
     815             :          END IF
     816             : 
     817             :          CALL copy_fm_to_dbcsr(fm_scaled_dm_occ_tau, &
     818             :                                mat_dm_occ_global(jquad, 1)%matrix, &
     819        1158 :                                keep_sparsity=.FALSE.)
     820             : 
     821        1158 :          CALL dbcsr_filter(mat_dm_occ_global(jquad, 1)%matrix, eps_filter)
     822             : 
     823        1158 :          IF (jquad == 1) THEN
     824             : 
     825         212 :             NULLIFY (mat_dm_virt_global)
     826         212 :             CALL dbcsr_allocate_matrix_set(mat_dm_virt_global, num_integ_points, 1)
     827             : 
     828             :          END IF
     829             : 
     830        1158 :          ALLOCATE (mat_dm_virt_global(jquad, 1)%matrix)
     831             :          CALL dbcsr_create(matrix=mat_dm_virt_global(jquad, 1)%matrix, &
     832             :                            template=matrix_s(1)%matrix, &
     833        1158 :                            matrix_type=dbcsr_type_no_symmetry)
     834             :          CALL copy_fm_to_dbcsr(fm_scaled_dm_virt_tau, &
     835             :                                mat_dm_virt_global(jquad, 1)%matrix, &
     836        1158 :                                keep_sparsity=.FALSE.)
     837             : 
     838        1158 :          CALL dbcsr_filter(mat_dm_virt_global(jquad, 1)%matrix, eps_filter)
     839             : 
     840             :          ! release memory
     841        1158 :          IF (jquad > 1) THEN
     842         946 :             CALL dbcsr_set(mat_dm_occ_global(jquad - 1, 1)%matrix, 0.0_dp)
     843         946 :             CALL dbcsr_set(mat_dm_virt_global(jquad - 1, 1)%matrix, 0.0_dp)
     844         946 :             CALL dbcsr_filter(mat_dm_occ_global(jquad - 1, 1)%matrix, 0.0_dp)
     845         946 :             CALL dbcsr_filter(mat_dm_virt_global(jquad - 1, 1)%matrix, 0.0_dp)
     846             :          END IF
     847             : 
     848             :       END IF ! do kpoints
     849             : 
     850        1314 :       CALL timestop(handle)
     851             : 
     852        1314 :    END SUBROUTINE compute_mat_dm_global
     853             : 
     854             : ! **************************************************************************************************
     855             : !> \brief ...
     856             : !> \param mat_dm_occ_global ...
     857             : !> \param mat_dm_virt_global ...
     858             : ! **************************************************************************************************
     859         176 :    SUBROUTINE clean_up(mat_dm_occ_global, mat_dm_virt_global)
     860             :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_dm_occ_global, mat_dm_virt_global
     861             : 
     862         176 :       CALL dbcsr_deallocate_matrix_set(mat_dm_occ_global)
     863         176 :       CALL dbcsr_deallocate_matrix_set(mat_dm_virt_global)
     864             : 
     865         176 :    END SUBROUTINE clean_up
     866             : 
     867             : ! **************************************************************************************************
     868             : !> \brief Calculate kpoint density matrices (rho(k), owned by kpoint groups)
     869             : !> \param kpoint    kpoint environment
     870             : !> \param tau ...
     871             : !> \param e_fermi ...
     872             : !> \param remove_occ ...
     873             : !> \param remove_virt ...
     874             : ! **************************************************************************************************
     875         612 :    SUBROUTINE kpoint_density_matrices_rpa(kpoint, tau, e_fermi, remove_occ, remove_virt)
     876             : 
     877             :       TYPE(kpoint_type), POINTER                         :: kpoint
     878             :       REAL(KIND=dp), INTENT(IN)                          :: tau, e_fermi
     879             :       LOGICAL, INTENT(IN)                                :: remove_occ, remove_virt
     880             : 
     881             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_density_matrices_rpa'
     882             :       REAL(KIND=dp), PARAMETER                           :: stabilize_exp = 70.0_dp
     883             : 
     884             :       INTEGER                                            :: handle, i_mo, ikpgr, ispin, kplocal, &
     885             :                                                             nao, nmo, nspin
     886             :       INTEGER, DIMENSION(2)                              :: kp_range
     887         612 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues, exp_scaling, occupation
     888             :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
     889             :       TYPE(cp_fm_type)                                   :: fwork
     890             :       TYPE(cp_fm_type), POINTER                          :: cpmat, rpmat
     891             :       TYPE(kpoint_env_type), POINTER                     :: kp
     892             :       TYPE(mo_set_type), POINTER                         :: mo_set
     893             : 
     894         612 :       CALL timeset(routineN, handle)
     895             : 
     896             :       ! only imaginary wavefunctions supported in kpoint cubic scaling RPA
     897         612 :       CPASSERT(kpoint%use_real_wfn .EQV. .FALSE.)
     898             : 
     899             :       ! work matrix
     900         612 :       mo_set => kpoint%kp_env(1)%kpoint_env%mos(1, 1)
     901         612 :       CALL get_mo_set(mo_set, nao=nao, nmo=nmo)
     902             : 
     903             :       ! if this CPASSERT is triggered, please add all virtual MOs to SCF section,
     904             :       ! e.g. ADDED_MOS 1000000
     905         612 :       CPASSERT(nao == nmo)
     906             : 
     907        1836 :       ALLOCATE (exp_scaling(nmo))
     908             : 
     909         612 :       CALL cp_fm_get_info(mo_set%mo_coeff, matrix_struct=matrix_struct)
     910         612 :       CALL cp_fm_create(fwork, matrix_struct)
     911             : 
     912         612 :       CALL get_kpoint_info(kpoint, kp_range=kp_range)
     913         612 :       kplocal = kp_range(2) - kp_range(1) + 1
     914             : 
     915        1272 :       DO ikpgr = 1, kplocal
     916         660 :          kp => kpoint%kp_env(ikpgr)%kpoint_env
     917         660 :          nspin = SIZE(kp%mos, 2)
     918        2140 :          DO ispin = 1, nspin
     919         868 :             mo_set => kp%mos(1, ispin)
     920         868 :             CALL get_mo_set(mo_set, eigenvalues=eigenvalues)
     921         868 :             rpmat => kp%wmat(1, ispin)
     922         868 :             cpmat => kp%wmat(2, ispin)
     923         868 :             CALL get_mo_set(mo_set, occupation_numbers=occupation)
     924         868 :             CALL cp_fm_to_fm(mo_set%mo_coeff, fwork)
     925             : 
     926         868 :             IF (remove_virt) THEN
     927         434 :                CALL cp_fm_column_scale(fwork, occupation)
     928             :             END IF
     929         868 :             IF (remove_occ) THEN
     930        8388 :                CALL cp_fm_column_scale(fwork, 2.0_dp/REAL(nspin, KIND=dp) - occupation)
     931             :             END IF
     932             : 
     933             :             ! proper spin
     934         868 :             IF (nspin == 1) THEN
     935         452 :                CALL cp_fm_scale(0.5_dp, fwork)
     936             :             END IF
     937             : 
     938       16776 :             DO i_mo = 1, nmo
     939             : 
     940       16776 :                IF (ABS(tau*0.5_dp*(eigenvalues(i_mo) - e_fermi)) < stabilize_exp) THEN
     941       15908 :                   exp_scaling(i_mo) = EXP(-ABS(tau*(eigenvalues(i_mo) - e_fermi)))
     942             :                ELSE
     943           0 :                   exp_scaling(i_mo) = 0.0_dp
     944             :                END IF
     945             :             END DO
     946             : 
     947         868 :             CALL cp_fm_column_scale(fwork, exp_scaling)
     948             : 
     949             :             ! Re(c)*Re(c)
     950         868 :             CALL parallel_gemm("N", "T", nao, nao, nmo, 1.0_dp, mo_set%mo_coeff, fwork, 0.0_dp, rpmat)
     951         868 :             mo_set => kp%mos(2, ispin)
     952             :             ! Im(c)*Re(c)
     953         868 :             CALL parallel_gemm("N", "T", nao, nao, nmo, -1.0_dp, mo_set%mo_coeff, fwork, 0.0_dp, cpmat)
     954             :             ! Re(c)*Im(c)
     955         868 :             CALL parallel_gemm("N", "T", nao, nao, nmo, 1.0_dp, fwork, mo_set%mo_coeff, 1.0_dp, cpmat)
     956             : 
     957         868 :             CALL cp_fm_to_fm(mo_set%mo_coeff, fwork)
     958             : 
     959         868 :             IF (remove_virt) THEN
     960         434 :                CALL cp_fm_column_scale(fwork, occupation)
     961             :             END IF
     962         868 :             IF (remove_occ) THEN
     963        8388 :                CALL cp_fm_column_scale(fwork, 2.0_dp/REAL(nspin, KIND=dp) - occupation)
     964             :             END IF
     965             : 
     966             :             ! proper spin
     967         868 :             IF (nspin == 1) THEN
     968         452 :                CALL cp_fm_scale(0.5_dp, fwork)
     969             :             END IF
     970             : 
     971       16776 :             DO i_mo = 1, nmo
     972       16776 :                IF (ABS(tau*0.5_dp*(eigenvalues(i_mo) - e_fermi)) < stabilize_exp) THEN
     973       15908 :                   exp_scaling(i_mo) = EXP(-ABS(tau*(eigenvalues(i_mo) - e_fermi)))
     974             :                ELSE
     975           0 :                   exp_scaling(i_mo) = 0.0_dp
     976             :                END IF
     977             :             END DO
     978             : 
     979         868 :             CALL cp_fm_column_scale(fwork, exp_scaling)
     980             :             ! Im(c)*Im(c)
     981        1528 :             CALL parallel_gemm("N", "T", nao, nao, nmo, 1.0_dp, mo_set%mo_coeff, fwork, 1.0_dp, rpmat)
     982             : 
     983             :          END DO
     984             : 
     985             :       END DO
     986             : 
     987         612 :       CALL cp_fm_release(fwork)
     988         612 :       DEALLOCATE (exp_scaling)
     989             : 
     990         612 :       CALL timestop(handle)
     991             : 
     992        1836 :    END SUBROUTINE kpoint_density_matrices_rpa
     993             : 
     994             : ! **************************************************************************************************
     995             : !> \brief ...
     996             : !> \param mat_dm_global ...
     997             : !> \param qs_env ...
     998             : !> \param ispin ...
     999             : !> \param num_integ_points ...
    1000             : !> \param jquad ...
    1001             : !> \param e_fermi ...
    1002             : !> \param tau ...
    1003             : !> \param eps_filter ...
    1004             : !> \param num_cells_dm ...
    1005             : !> \param index_to_cell_dm ...
    1006             : !> \param remove_occ ...
    1007             : !> \param remove_virt ...
    1008             : !> \param first_jquad ...
    1009             : ! **************************************************************************************************
    1010          48 :    SUBROUTINE compute_transl_dm(mat_dm_global, qs_env, ispin, num_integ_points, jquad, e_fermi, tau, &
    1011             :                                 eps_filter, num_cells_dm, index_to_cell_dm, remove_occ, remove_virt, &
    1012             :                                 first_jquad)
    1013             :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_dm_global
    1014             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1015             :       INTEGER, INTENT(IN)                                :: ispin, num_integ_points, jquad
    1016             :       REAL(KIND=dp), INTENT(IN)                          :: e_fermi, tau, eps_filter
    1017             :       INTEGER, INTENT(OUT)                               :: num_cells_dm
    1018             :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell_dm
    1019             :       LOGICAL, INTENT(IN)                                :: remove_occ, remove_virt
    1020             :       INTEGER, INTENT(IN)                                :: first_jquad
    1021             : 
    1022             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'compute_transl_dm'
    1023             : 
    1024             :       INTEGER                                            :: handle, i_dim, i_img, iquad, jspin, nspin
    1025             :       INTEGER, DIMENSION(3)                              :: cell_grid_dm
    1026             :       TYPE(cell_type), POINTER                           :: cell
    1027          48 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_dm_global_work, matrix_s_kp
    1028             :       TYPE(kpoint_type), POINTER                         :: kpoints
    1029          48 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    1030             : 
    1031          48 :       CALL timeset(routineN, handle)
    1032             : 
    1033             :       CALL get_qs_env(qs_env, &
    1034             :                       matrix_s_kp=matrix_s_kp, &
    1035             :                       mos=mos, &
    1036             :                       kpoints=kpoints, &
    1037          48 :                       cell=cell)
    1038             : 
    1039          48 :       nspin = SIZE(mos)
    1040             : 
    1041             :       ! we always use an odd number of image cells
    1042             :       ! CAUTION: also at another point, cell_grid_dm is defined, these definitions have to be identical
    1043         192 :       DO i_dim = 1, 3
    1044         192 :          cell_grid_dm(i_dim) = (kpoints%nkp_grid(i_dim)/2)*2 - 1
    1045             :       END DO
    1046             : 
    1047          48 :       num_cells_dm = cell_grid_dm(1)*cell_grid_dm(2)*cell_grid_dm(3)
    1048             : 
    1049          48 :       NULLIFY (mat_dm_global_work)
    1050          48 :       CALL dbcsr_allocate_matrix_set(mat_dm_global_work, nspin, num_cells_dm)
    1051             : 
    1052          96 :       DO jspin = 1, nspin
    1053             : 
    1054         240 :          DO i_img = 1, num_cells_dm
    1055             : 
    1056         144 :             ALLOCATE (mat_dm_global_work(jspin, i_img)%matrix)
    1057             :             CALL dbcsr_create(matrix=mat_dm_global_work(jspin, i_img)%matrix, &
    1058             :                               template=matrix_s_kp(1, 1)%matrix, &
    1059             :                               !                              matrix_type=dbcsr_type_symmetric)
    1060         144 :                               matrix_type=dbcsr_type_no_symmetry)
    1061             : 
    1062         144 :             CALL dbcsr_reserve_all_blocks(mat_dm_global_work(jspin, i_img)%matrix)
    1063             : 
    1064         192 :             CALL dbcsr_set(mat_dm_global_work(ispin, i_img)%matrix, 0.0_dp)
    1065             : 
    1066             :          END DO
    1067             : 
    1068             :       END DO
    1069             : 
    1070             :       ! density matrices in k-space weighted with EXP(-|e_i-e_F|*t) for occupied orbitals
    1071             :       CALL kpoint_density_matrices_rpa(kpoints, tau, e_fermi, &
    1072          48 :                                        remove_occ=remove_occ, remove_virt=remove_virt)
    1073             : 
    1074             :       ! overwrite the cell indices in kpoints
    1075          48 :       CALL init_cell_index_rpa(cell_grid_dm, kpoints%cell_to_index, kpoints%index_to_cell, cell)
    1076             : 
    1077             :       ! density matrices in real space, the cell vectors T for transforming are taken from kpoints%index_to_cell
    1078             :       ! (custom made for RPA) and not from sab_nl (which is symmetric and from SCF)
    1079          48 :       CALL density_matrix_from_kp_to_transl(kpoints, mat_dm_global_work, kpoints%index_to_cell)
    1080             : 
    1081             :       ! we need the index to cell for the density matrices later
    1082          48 :       index_to_cell_dm => kpoints%index_to_cell
    1083             : 
    1084             :       ! normally, jquad = 1 to allocate the matrix set, but for GW jquad = 0 is the exchange self-energy
    1085          48 :       IF (jquad == first_jquad) THEN
    1086             : 
    1087           8 :          NULLIFY (mat_dm_global)
    1088         200 :          ALLOCATE (mat_dm_global(first_jquad:num_integ_points, num_cells_dm))
    1089             : 
    1090          56 :          DO iquad = first_jquad, num_integ_points
    1091         200 :             DO i_img = 1, num_cells_dm
    1092         144 :                NULLIFY (mat_dm_global(iquad, i_img)%matrix)
    1093         144 :                ALLOCATE (mat_dm_global(iquad, i_img)%matrix)
    1094             :                CALL dbcsr_create(matrix=mat_dm_global(iquad, i_img)%matrix, &
    1095             :                                  template=matrix_s_kp(1, 1)%matrix, &
    1096         192 :                                  matrix_type=dbcsr_type_no_symmetry)
    1097             : 
    1098             :             END DO
    1099             :          END DO
    1100             : 
    1101             :       END IF
    1102             : 
    1103         192 :       DO i_img = 1, num_cells_dm
    1104             : 
    1105             :          ! filter to get rid of the blocks full with zeros on the lower half, otherwise blocks doubled
    1106         144 :          CALL dbcsr_filter(mat_dm_global_work(ispin, i_img)%matrix, eps_filter)
    1107             : 
    1108             :          CALL dbcsr_copy(mat_dm_global(jquad, i_img)%matrix, &
    1109         192 :                          mat_dm_global_work(ispin, i_img)%matrix)
    1110             : 
    1111             :       END DO
    1112             : 
    1113          48 :       CALL dbcsr_deallocate_matrix_set(mat_dm_global_work)
    1114             : 
    1115          48 :       CALL timestop(handle)
    1116             : 
    1117          48 :    END SUBROUTINE compute_transl_dm
    1118             : 
    1119             : ! **************************************************************************************************
    1120             : !> \brief ...
    1121             : !> \param mat_dm_global ...
    1122             : !> \param qs_env ...
    1123             : !> \param ispin ...
    1124             : !> \param num_integ_points ...
    1125             : !> \param jquad ...
    1126             : !> \param e_fermi ...
    1127             : !> \param tau ...
    1128             : !> \param remove_occ ...
    1129             : !> \param remove_virt ...
    1130             : !> \param alloc_dm ...
    1131             : ! **************************************************************************************************
    1132         564 :    SUBROUTINE compute_periodic_dm(mat_dm_global, qs_env, ispin, num_integ_points, jquad, e_fermi, tau, &
    1133             :                                   remove_occ, remove_virt, alloc_dm)
    1134             :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_dm_global
    1135             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1136             :       INTEGER, INTENT(IN)                                :: ispin, num_integ_points, jquad
    1137             :       REAL(KIND=dp), INTENT(IN)                          :: e_fermi, tau
    1138             :       LOGICAL, INTENT(IN)                                :: remove_occ, remove_virt, alloc_dm
    1139             : 
    1140             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_periodic_dm'
    1141             : 
    1142             :       INTEGER                                            :: handle, iquad, jspin, nspin, num_cells_dm
    1143         564 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_dm_global_work, matrix_s_kp
    1144             :       TYPE(kpoint_type), POINTER                         :: kpoints_G
    1145         564 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    1146             : 
    1147         564 :       CALL timeset(routineN, handle)
    1148             : 
    1149         564 :       NULLIFY (matrix_s_kp, mos)
    1150             : 
    1151             :       CALL get_qs_env(qs_env, &
    1152             :                       matrix_s_kp=matrix_s_kp, &
    1153         564 :                       mos=mos)
    1154             : 
    1155         564 :       kpoints_G => qs_env%mp2_env%ri_rpa_im_time%kpoints_G
    1156             : 
    1157         564 :       nspin = SIZE(mos)
    1158             : 
    1159         564 :       num_cells_dm = 1
    1160             : 
    1161         564 :       NULLIFY (mat_dm_global_work)
    1162         564 :       CALL dbcsr_allocate_matrix_set(mat_dm_global_work, nspin, num_cells_dm)
    1163             : 
    1164             :       ! if necessaray, allocate mat_dm_global
    1165         564 :       IF (alloc_dm) THEN
    1166             : 
    1167          80 :          NULLIFY (mat_dm_global)
    1168         828 :          ALLOCATE (mat_dm_global(1:num_integ_points, num_cells_dm))
    1169             : 
    1170         588 :          DO iquad = 1, num_integ_points
    1171         508 :             NULLIFY (mat_dm_global(iquad, 1)%matrix)
    1172         508 :             ALLOCATE (mat_dm_global(iquad, 1)%matrix)
    1173             :             CALL dbcsr_create(matrix=mat_dm_global(iquad, 1)%matrix, &
    1174             :                               template=matrix_s_kp(1, 1)%matrix, &
    1175         588 :                               matrix_type=dbcsr_type_no_symmetry)
    1176             : 
    1177             :          END DO
    1178             : 
    1179             :       END IF
    1180             : 
    1181        1336 :       DO jspin = 1, nspin
    1182             : 
    1183         772 :          ALLOCATE (mat_dm_global_work(jspin, 1)%matrix)
    1184             :          CALL dbcsr_create(matrix=mat_dm_global_work(jspin, 1)%matrix, &
    1185             :                            template=matrix_s_kp(1, 1)%matrix, &
    1186         772 :                            matrix_type=dbcsr_type_no_symmetry)
    1187             : 
    1188         772 :          CALL dbcsr_reserve_all_blocks(mat_dm_global_work(jspin, 1)%matrix)
    1189             : 
    1190        1336 :          CALL dbcsr_set(mat_dm_global_work(jspin, 1)%matrix, 0.0_dp)
    1191             : 
    1192             :       END DO
    1193             : 
    1194             :       ! density matrices in k-space weighted with EXP(-|e_i-e_F|*t) for occupied orbitals
    1195             :       CALL kpoint_density_matrices_rpa(kpoints_G, tau, e_fermi, &
    1196         564 :                                        remove_occ=remove_occ, remove_virt=remove_virt)
    1197             : 
    1198         564 :       CALL density_matrix_from_kp_to_mic(kpoints_G, mat_dm_global_work, qs_env)
    1199             : 
    1200             :       CALL dbcsr_copy(mat_dm_global(jquad, 1)%matrix, &
    1201         564 :                       mat_dm_global_work(ispin, 1)%matrix)
    1202             : 
    1203         564 :       CALL dbcsr_deallocate_matrix_set(mat_dm_global_work)
    1204             : 
    1205         564 :       CALL timestop(handle)
    1206             : 
    1207         564 :    END SUBROUTINE compute_periodic_dm
    1208             : 
    1209             :    ! **************************************************************************************************
    1210             : !> \brief ...
    1211             : !> \param kpoints_G ...
    1212             : !> \param mat_dm_global_work ...
    1213             : !> \param qs_env ...
    1214             : ! **************************************************************************************************
    1215         564 :    SUBROUTINE density_matrix_from_kp_to_mic(kpoints_G, mat_dm_global_work, qs_env)
    1216             : 
    1217             :       TYPE(kpoint_type), POINTER                         :: kpoints_G
    1218             :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_dm_global_work
    1219             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1220             : 
    1221             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'density_matrix_from_kp_to_mic'
    1222             : 
    1223             :       INTEGER                                            :: handle, iatom, iatom_old, ik, irow, &
    1224             :                                                             ispin, jatom, jatom_old, jcol, nao, &
    1225             :                                                             ncol_local, nkp, nrow_local, nspin, &
    1226             :                                                             num_cells
    1227             :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_from_ao_index
    1228         564 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
    1229         564 :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell
    1230             :       REAL(KIND=dp)                                      :: contribution, weight_im, weight_re
    1231             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: hmat
    1232         564 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: wkp
    1233         564 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
    1234             :       TYPE(cell_type), POINTER                           :: cell
    1235             :       TYPE(cp_fm_type)                                   :: fm_mat_work
    1236             :       TYPE(cp_fm_type), POINTER                          :: cpmat, rpmat
    1237             :       TYPE(kpoint_env_type), POINTER                     :: kp
    1238             :       TYPE(mo_set_type), POINTER                         :: mo_set
    1239         564 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1240             : 
    1241         564 :       CALL timeset(routineN, handle)
    1242             : 
    1243         564 :       NULLIFY (xkp, wkp)
    1244             : 
    1245         564 :       CALL cp_fm_create(fm_mat_work, kpoints_G%kp_env(1)%kpoint_env%wmat(1, 1)%matrix_struct)
    1246         564 :       CALL cp_fm_set_all(fm_mat_work, 0.0_dp)
    1247             : 
    1248         564 :       CALL get_kpoint_info(kpoints_G, nkp=nkp, xkp=xkp, wkp=wkp)
    1249         564 :       index_to_cell => kpoints_G%index_to_cell
    1250         564 :       num_cells = SIZE(index_to_cell, 2)
    1251             : 
    1252         564 :       nspin = SIZE(mat_dm_global_work, 1)
    1253             : 
    1254         564 :       mo_set => kpoints_G%kp_env(1)%kpoint_env%mos(1, 1)
    1255         564 :       CALL get_mo_set(mo_set, nao=nao)
    1256             : 
    1257        1692 :       ALLOCATE (atom_from_ao_index(nao))
    1258             : 
    1259         564 :       CALL get_atom_index_from_basis_function_index(qs_env, atom_from_ao_index, nao, "ORB")
    1260             : 
    1261             :       CALL cp_fm_get_info(matrix=kpoints_G%kp_env(1)%kpoint_env%wmat(1, 1), &
    1262             :                           nrow_local=nrow_local, &
    1263             :                           ncol_local=ncol_local, &
    1264             :                           row_indices=row_indices, &
    1265         564 :                           col_indices=col_indices)
    1266             : 
    1267         564 :       NULLIFY (cell, particle_set)
    1268         564 :       CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
    1269         564 :       CALL get_cell(cell=cell, h=hmat)
    1270             : 
    1271         564 :       iatom_old = 0
    1272         564 :       jatom_old = 0
    1273             : 
    1274        1336 :       DO ispin = 1, nspin
    1275             : 
    1276         772 :          CALL dbcsr_set(mat_dm_global_work(ispin, 1)%matrix, 0.0_dp)
    1277             : 
    1278        1544 :          DO ik = 1, nkp
    1279             : 
    1280         772 :             kp => kpoints_G%kp_env(ik)%kpoint_env
    1281         772 :             rpmat => kp%wmat(1, ispin)
    1282         772 :             cpmat => kp%wmat(2, ispin)
    1283             : 
    1284        8394 :             DO irow = 1, nrow_local
    1285      136936 :                DO jcol = 1, ncol_local
    1286             : 
    1287      129314 :                   iatom = atom_from_ao_index(row_indices(irow))
    1288      129314 :                   jatom = atom_from_ao_index(col_indices(jcol))
    1289             : 
    1290      129314 :                   IF (iatom .NE. iatom_old .OR. jatom .NE. jatom_old) THEN
    1291             : 
    1292             :                      CALL compute_weight_re_im(weight_re, weight_im, &
    1293             :                                                num_cells, iatom, jatom, xkp(1:3, ik), wkp(ik), &
    1294       20316 :                                                cell, index_to_cell, hmat, particle_set)
    1295             : 
    1296       20316 :                      iatom_old = iatom
    1297       20316 :                      jatom_old = jatom
    1298             : 
    1299             :                   END IF
    1300             : 
    1301             :                   ! minus sign because of i^2 = -1
    1302             :                   contribution = weight_re*rpmat%local_data(irow, jcol) - &
    1303      129314 :                                  weight_im*cpmat%local_data(irow, jcol)
    1304             : 
    1305      136164 :                   fm_mat_work%local_data(irow, jcol) = fm_mat_work%local_data(irow, jcol) + contribution
    1306             : 
    1307             :                END DO
    1308             :             END DO
    1309             : 
    1310             :          END DO ! ik
    1311             : 
    1312         772 :          CALL copy_fm_to_dbcsr(fm_mat_work, mat_dm_global_work(ispin, 1)%matrix, keep_sparsity=.FALSE.)
    1313        1336 :          CALL cp_fm_set_all(fm_mat_work, 0.0_dp)
    1314             : 
    1315             :       END DO
    1316             : 
    1317         564 :       CALL cp_fm_release(fm_mat_work)
    1318         564 :       DEALLOCATE (atom_from_ao_index)
    1319             : 
    1320         564 :       CALL timestop(handle)
    1321             : 
    1322        1692 :    END SUBROUTINE density_matrix_from_kp_to_mic
    1323             : 
    1324             : ! **************************************************************************************************
    1325             : !> \brief ...
    1326             : !> \param kpoints ...
    1327             : !> \param mat_dm_global_work ...
    1328             : !> \param index_to_cell ...
    1329             : ! **************************************************************************************************
    1330          48 :    SUBROUTINE density_matrix_from_kp_to_transl(kpoints, mat_dm_global_work, index_to_cell)
    1331             : 
    1332             :       TYPE(kpoint_type), POINTER                         :: kpoints
    1333             :       TYPE(dbcsr_p_type), DIMENSION(:, :), INTENT(IN)    :: mat_dm_global_work
    1334             :       INTEGER, DIMENSION(:, :), INTENT(IN)               :: index_to_cell
    1335             : 
    1336             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'density_matrix_from_kp_to_transl'
    1337             : 
    1338             :       INTEGER                                            :: handle, icell, ik, ispin, nkp, nspin, &
    1339             :                                                             xcell, ycell, zcell
    1340             :       REAL(KIND=dp)                                      :: arg, coskl, sinkl
    1341          48 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: wkp
    1342          48 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
    1343             :       TYPE(cp_fm_type), POINTER                          :: cpmat, rpmat
    1344             :       TYPE(dbcsr_type), POINTER                          :: mat_work_im, mat_work_re
    1345             :       TYPE(kpoint_env_type), POINTER                     :: kp
    1346             : 
    1347          48 :       CALL timeset(routineN, handle)
    1348             : 
    1349          48 :       NULLIFY (xkp, wkp)
    1350             : 
    1351          48 :       NULLIFY (mat_work_re)
    1352          48 :       CALL dbcsr_init_p(mat_work_re)
    1353             :       CALL dbcsr_create(matrix=mat_work_re, &
    1354             :                         template=mat_dm_global_work(1, 1)%matrix, &
    1355          48 :                         matrix_type=dbcsr_type_no_symmetry)
    1356             : 
    1357          48 :       NULLIFY (mat_work_im)
    1358          48 :       CALL dbcsr_init_p(mat_work_im)
    1359             :       CALL dbcsr_create(matrix=mat_work_im, &
    1360             :                         template=mat_dm_global_work(1, 1)%matrix, &
    1361          48 :                         matrix_type=dbcsr_type_no_symmetry)
    1362             : 
    1363          48 :       CALL get_kpoint_info(kpoints, nkp=nkp, xkp=xkp, wkp=wkp)
    1364             : 
    1365          48 :       nspin = SIZE(mat_dm_global_work, 1)
    1366             : 
    1367          48 :       CPASSERT(SIZE(mat_dm_global_work, 2) == SIZE(index_to_cell, 2))
    1368             : 
    1369          96 :       DO ispin = 1, nspin
    1370             : 
    1371         240 :          DO icell = 1, SIZE(mat_dm_global_work, 2)
    1372             : 
    1373         192 :             CALL dbcsr_set(mat_dm_global_work(ispin, icell)%matrix, 0.0_dp)
    1374             : 
    1375             :          END DO
    1376             : 
    1377             :       END DO
    1378             : 
    1379          96 :       DO ispin = 1, nspin
    1380             : 
    1381         192 :          DO ik = 1, nkp
    1382             : 
    1383          96 :             kp => kpoints%kp_env(ik)%kpoint_env
    1384          96 :             rpmat => kp%wmat(1, ispin)
    1385          96 :             cpmat => kp%wmat(2, ispin)
    1386             : 
    1387          96 :             CALL copy_fm_to_dbcsr(rpmat, mat_work_re, keep_sparsity=.FALSE.)
    1388          96 :             CALL copy_fm_to_dbcsr(cpmat, mat_work_im, keep_sparsity=.FALSE.)
    1389             : 
    1390         432 :             DO icell = 1, SIZE(mat_dm_global_work, 2)
    1391             : 
    1392         288 :                xcell = index_to_cell(1, icell)
    1393         288 :                ycell = index_to_cell(2, icell)
    1394         288 :                zcell = index_to_cell(3, icell)
    1395             : 
    1396         288 :                arg = REAL(xcell, dp)*xkp(1, ik) + REAL(ycell, dp)*xkp(2, ik) + REAL(zcell, dp)*xkp(3, ik)
    1397         288 :                coskl = wkp(ik)*COS(twopi*arg)
    1398         288 :                sinkl = wkp(ik)*SIN(twopi*arg)
    1399             : 
    1400         288 :                CALL dbcsr_add(mat_dm_global_work(ispin, icell)%matrix, mat_work_re, 1.0_dp, coskl)
    1401         384 :                CALL dbcsr_add(mat_dm_global_work(ispin, icell)%matrix, mat_work_im, 1.0_dp, sinkl)
    1402             : 
    1403             :             END DO
    1404             : 
    1405             :          END DO
    1406             :       END DO
    1407             : 
    1408          48 :       CALL dbcsr_release_p(mat_work_re)
    1409          48 :       CALL dbcsr_release_p(mat_work_im)
    1410             : 
    1411          48 :       CALL timestop(handle)
    1412             : 
    1413          48 :    END SUBROUTINE density_matrix_from_kp_to_transl
    1414             : 
    1415             : ! **************************************************************************************************
    1416             : !> \brief ...
    1417             : !> \param cell_grid ...
    1418             : !> \param cell_to_index ...
    1419             : !> \param index_to_cell ...
    1420             : !> \param cell ...
    1421             : ! **************************************************************************************************
    1422         624 :    SUBROUTINE init_cell_index_rpa(cell_grid, cell_to_index, index_to_cell, cell)
    1423             :       INTEGER, DIMENSION(3), INTENT(IN)                  :: cell_grid
    1424             :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    1425             :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell
    1426             :       TYPE(cell_type), INTENT(IN), POINTER               :: cell
    1427             : 
    1428             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'init_cell_index_rpa'
    1429             : 
    1430             :       INTEGER                                            :: cell_counter, handle, i_cell, &
    1431             :                                                             index_min_dist, num_cells, xcell, &
    1432             :                                                             ycell, zcell
    1433             :       INTEGER, DIMENSION(3)                              :: itm
    1434         624 :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell_unsorted
    1435         624 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index_unsorted
    1436         624 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: abs_cell_vectors
    1437             :       REAL(KIND=dp), DIMENSION(3)                        :: cell_vector
    1438             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: hmat
    1439             : 
    1440         624 :       CALL timeset(routineN, handle)
    1441             : 
    1442         624 :       CALL get_cell(cell=cell, h=hmat)
    1443             : 
    1444         624 :       num_cells = cell_grid(1)*cell_grid(2)*cell_grid(3)
    1445        2496 :       itm(:) = cell_grid(:)/2
    1446             : 
    1447             :       ! check that real space super lattice is a (2n+1)x(2m+1)x(2k+1) super lattice with the unit cell
    1448             :       ! in the middle
    1449         624 :       CPASSERT(cell_grid(1) .NE. itm(1)*2)
    1450         624 :       CPASSERT(cell_grid(2) .NE. itm(2)*2)
    1451         624 :       CPASSERT(cell_grid(3) .NE. itm(3)*2)
    1452             : 
    1453         624 :       IF (ASSOCIATED(cell_to_index)) DEALLOCATE (cell_to_index)
    1454         624 :       IF (ASSOCIATED(index_to_cell)) DEALLOCATE (index_to_cell)
    1455             : 
    1456        3120 :       ALLOCATE (cell_to_index_unsorted(-itm(1):itm(1), -itm(2):itm(2), -itm(3):itm(3)))
    1457       12504 :       cell_to_index_unsorted(:, :, :) = 0
    1458             : 
    1459        1872 :       ALLOCATE (index_to_cell_unsorted(3, num_cells))
    1460       21936 :       index_to_cell_unsorted(:, :) = 0
    1461             : 
    1462        2496 :       ALLOCATE (cell_to_index(-itm(1):itm(1), -itm(2):itm(2), -itm(3):itm(3)))
    1463       12504 :       cell_to_index(:, :, :) = 0
    1464             : 
    1465        1248 :       ALLOCATE (index_to_cell(3, num_cells))
    1466       21936 :       index_to_cell(:, :) = 0
    1467             : 
    1468        1872 :       ALLOCATE (abs_cell_vectors(1:num_cells))
    1469             : 
    1470        1464 :       cell_counter = 0
    1471             : 
    1472        1464 :       DO xcell = -itm(1), itm(1)
    1473        3240 :          DO ycell = -itm(2), itm(2)
    1474        7944 :             DO zcell = -itm(3), itm(3)
    1475             : 
    1476        5328 :                cell_counter = cell_counter + 1
    1477        5328 :                cell_to_index_unsorted(xcell, ycell, zcell) = cell_counter
    1478             : 
    1479        5328 :                index_to_cell_unsorted(1, cell_counter) = xcell
    1480        5328 :                index_to_cell_unsorted(2, cell_counter) = ycell
    1481        5328 :                index_to_cell_unsorted(3, cell_counter) = zcell
    1482             : 
    1483       85248 :                cell_vector(1:3) = MATMUL(hmat, REAL(index_to_cell_unsorted(1:3, cell_counter), dp))
    1484             : 
    1485        7104 :                abs_cell_vectors(cell_counter) = SQRT(cell_vector(1)**2 + cell_vector(2)**2 + cell_vector(3)**2)
    1486             : 
    1487             :             END DO
    1488             :          END DO
    1489             :       END DO
    1490             : 
    1491             :       ! first only do all symmetry non-equivalent cells, we need that because chi^T is computed for
    1492             :       ! cell indices T from index_to_cell(:,1:num_cells/2+1)
    1493        3600 :       DO i_cell = 1, num_cells/2 + 1
    1494             : 
    1495       17568 :          index_min_dist = MINLOC(abs_cell_vectors(1:num_cells/2 + 1), DIM=1)
    1496             : 
    1497        2976 :          xcell = index_to_cell_unsorted(1, index_min_dist)
    1498        2976 :          ycell = index_to_cell_unsorted(2, index_min_dist)
    1499        2976 :          zcell = index_to_cell_unsorted(3, index_min_dist)
    1500             : 
    1501        2976 :          index_to_cell(1, i_cell) = xcell
    1502        2976 :          index_to_cell(2, i_cell) = ycell
    1503        2976 :          index_to_cell(3, i_cell) = zcell
    1504             : 
    1505        2976 :          cell_to_index(xcell, ycell, zcell) = i_cell
    1506             : 
    1507        3600 :          abs_cell_vectors(index_min_dist) = 10000000000.0_dp
    1508             : 
    1509             :       END DO
    1510             : 
    1511             :       ! now all the remaining cells
    1512        2976 :       DO i_cell = num_cells/2 + 2, num_cells
    1513             : 
    1514       23232 :          index_min_dist = MINLOC(abs_cell_vectors(1:num_cells), DIM=1)
    1515             : 
    1516        2352 :          xcell = index_to_cell_unsorted(1, index_min_dist)
    1517        2352 :          ycell = index_to_cell_unsorted(2, index_min_dist)
    1518        2352 :          zcell = index_to_cell_unsorted(3, index_min_dist)
    1519             : 
    1520        2352 :          index_to_cell(1, i_cell) = xcell
    1521        2352 :          index_to_cell(2, i_cell) = ycell
    1522        2352 :          index_to_cell(3, i_cell) = zcell
    1523             : 
    1524        2352 :          cell_to_index(xcell, ycell, zcell) = i_cell
    1525             : 
    1526        2976 :          abs_cell_vectors(index_min_dist) = 10000000000.0_dp
    1527             : 
    1528             :       END DO
    1529             : 
    1530         624 :       DEALLOCATE (index_to_cell_unsorted, cell_to_index_unsorted, abs_cell_vectors)
    1531             : 
    1532         624 :       CALL timestop(handle)
    1533             : 
    1534         624 :    END SUBROUTINE init_cell_index_rpa
    1535             : 
    1536             : ! **************************************************************************************************
    1537             : !> \brief ...
    1538             : !> \param i_cell_R ...
    1539             : !> \param i_cell_S ...
    1540             : !> \param i_cell_R_minus_S ...
    1541             : !> \param index_to_cell_3c ...
    1542             : !> \param cell_to_index_3c ...
    1543             : !> \param index_to_cell_dm ...
    1544             : !> \param R_minus_S_needed ...
    1545             : !> \param do_kpoints_cubic_RPA ...
    1546             : ! **************************************************************************************************
    1547       12472 :    SUBROUTINE get_diff_index_3c(i_cell_R, i_cell_S, i_cell_R_minus_S, index_to_cell_3c, &
    1548             :                                 cell_to_index_3c, index_to_cell_dm, R_minus_S_needed, &
    1549             :                                 do_kpoints_cubic_RPA)
    1550             : 
    1551             :       INTEGER, INTENT(IN)                                :: i_cell_R, i_cell_S
    1552             :       INTEGER, INTENT(OUT)                               :: i_cell_R_minus_S
    1553             :       INTEGER, ALLOCATABLE, DIMENSION(:, :), INTENT(IN)  :: index_to_cell_3c
    1554             :       INTEGER, ALLOCATABLE, DIMENSION(:, :, :), &
    1555             :          INTENT(IN)                                      :: cell_to_index_3c
    1556             :       INTEGER, DIMENSION(:, :), INTENT(IN), POINTER      :: index_to_cell_dm
    1557             :       LOGICAL, INTENT(OUT)                               :: R_minus_S_needed
    1558             :       LOGICAL, INTENT(IN)                                :: do_kpoints_cubic_RPA
    1559             : 
    1560             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'get_diff_index_3c'
    1561             : 
    1562             :       INTEGER :: handle, x_cell_R, x_cell_R_minus_S, x_cell_S, y_cell_R, y_cell_R_minus_S, &
    1563             :          y_cell_S, z_cell_R, z_cell_R_minus_S, z_cell_S
    1564             : 
    1565       12472 :       CALL timeset(routineN, handle)
    1566             : 
    1567       12472 :       IF (do_kpoints_cubic_RPA) THEN
    1568             : 
    1569        4200 :          x_cell_R = index_to_cell_3c(1, i_cell_R)
    1570        4200 :          y_cell_R = index_to_cell_3c(2, i_cell_R)
    1571        4200 :          z_cell_R = index_to_cell_3c(3, i_cell_R)
    1572             : 
    1573        4200 :          x_cell_S = index_to_cell_dm(1, i_cell_S)
    1574        4200 :          y_cell_S = index_to_cell_dm(2, i_cell_S)
    1575        4200 :          z_cell_S = index_to_cell_dm(3, i_cell_S)
    1576             : 
    1577        4200 :          x_cell_R_minus_S = x_cell_R - x_cell_S
    1578        4200 :          y_cell_R_minus_S = y_cell_R - y_cell_S
    1579        4200 :          z_cell_R_minus_S = z_cell_R - z_cell_S
    1580             : 
    1581             :          IF (x_cell_R_minus_S .GE. LBOUND(cell_to_index_3c, 1) .AND. &
    1582             :              x_cell_R_minus_S .LE. UBOUND(cell_to_index_3c, 1) .AND. &
    1583             :              y_cell_R_minus_S .GE. LBOUND(cell_to_index_3c, 2) .AND. &
    1584             :              y_cell_R_minus_S .LE. UBOUND(cell_to_index_3c, 2) .AND. &
    1585       29300 :              z_cell_R_minus_S .GE. LBOUND(cell_to_index_3c, 3) .AND. &
    1586             :              z_cell_R_minus_S .LE. UBOUND(cell_to_index_3c, 3)) THEN
    1587             : 
    1588        3950 :             i_cell_R_minus_S = cell_to_index_3c(x_cell_R_minus_S, y_cell_R_minus_S, z_cell_R_minus_S)
    1589             : 
    1590             :             ! 0 means that there is no 3c index with this R-S vector because R-S is too big and the 3c integral is 0
    1591        3950 :             IF (i_cell_R_minus_S == 0) THEN
    1592             : 
    1593           0 :                R_minus_S_needed = .FALSE.
    1594           0 :                i_cell_R_minus_S = 0
    1595             : 
    1596             :             ELSE
    1597             : 
    1598        3950 :                R_minus_S_needed = .TRUE.
    1599             : 
    1600             :             END IF
    1601             : 
    1602             :          ELSE
    1603             : 
    1604         250 :             i_cell_R_minus_S = 0
    1605         250 :             R_minus_S_needed = .FALSE.
    1606             : 
    1607             :          END IF
    1608             : 
    1609             :       ELSE ! no k-points
    1610             : 
    1611        8272 :          R_minus_S_needed = .TRUE.
    1612        8272 :          i_cell_R_minus_S = 1
    1613             : 
    1614             :       END IF
    1615             : 
    1616       12472 :       CALL timestop(handle)
    1617             : 
    1618       12472 :    END SUBROUTINE get_diff_index_3c
    1619             : 
    1620             : ! **************************************************************************************************
    1621             : !> \brief ...
    1622             : !> \param i_cell_R ...
    1623             : !> \param i_cell_S ...
    1624             : !> \param i_cell_T ...
    1625             : !> \param i_cell_R_minus_S_minus_T ...
    1626             : !> \param index_to_cell_3c ...
    1627             : !> \param cell_to_index_3c ...
    1628             : !> \param index_to_cell_dm ...
    1629             : !> \param R_minus_S_minus_T_needed ...
    1630             : !> \param do_kpoints_cubic_RPA ...
    1631             : ! **************************************************************************************************
    1632       14572 :    SUBROUTINE get_diff_diff_index_3c(i_cell_R, i_cell_S, i_cell_T, i_cell_R_minus_S_minus_T, &
    1633        7286 :                                      index_to_cell_3c, cell_to_index_3c, index_to_cell_dm, &
    1634             :                                      R_minus_S_minus_T_needed, &
    1635             :                                      do_kpoints_cubic_RPA)
    1636             : 
    1637             :       INTEGER, INTENT(IN)                                :: i_cell_R, i_cell_S, i_cell_T
    1638             :       INTEGER, INTENT(OUT)                               :: i_cell_R_minus_S_minus_T
    1639             :       INTEGER, DIMENSION(:, :), INTENT(IN)               :: index_to_cell_3c
    1640             :       INTEGER, ALLOCATABLE, DIMENSION(:, :, :), &
    1641             :          INTENT(IN)                                      :: cell_to_index_3c
    1642             :       INTEGER, DIMENSION(:, :), INTENT(IN)               :: index_to_cell_dm
    1643             :       LOGICAL, INTENT(OUT)                               :: R_minus_S_minus_T_needed
    1644             :       LOGICAL, INTENT(IN)                                :: do_kpoints_cubic_RPA
    1645             : 
    1646             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'get_diff_diff_index_3c'
    1647             : 
    1648             :       INTEGER :: handle, x_cell_R, x_cell_R_minus_S_minus_T, x_cell_S, x_cell_T, y_cell_R, &
    1649             :          y_cell_R_minus_S_minus_T, y_cell_S, y_cell_T, z_cell_R, z_cell_R_minus_S_minus_T, &
    1650             :          z_cell_S, z_cell_T
    1651             : 
    1652        7286 :       CALL timeset(routineN, handle)
    1653             : 
    1654        7286 :       IF (do_kpoints_cubic_RPA) THEN
    1655             : 
    1656        3150 :          x_cell_R = index_to_cell_3c(1, i_cell_R)
    1657        3150 :          y_cell_R = index_to_cell_3c(2, i_cell_R)
    1658        3150 :          z_cell_R = index_to_cell_3c(3, i_cell_R)
    1659             : 
    1660        3150 :          x_cell_S = index_to_cell_dm(1, i_cell_S)
    1661        3150 :          y_cell_S = index_to_cell_dm(2, i_cell_S)
    1662        3150 :          z_cell_S = index_to_cell_dm(3, i_cell_S)
    1663             : 
    1664        3150 :          x_cell_T = index_to_cell_dm(1, i_cell_T)
    1665        3150 :          y_cell_T = index_to_cell_dm(2, i_cell_T)
    1666        3150 :          z_cell_T = index_to_cell_dm(3, i_cell_T)
    1667             : 
    1668        3150 :          x_cell_R_minus_S_minus_T = x_cell_R - x_cell_S - x_cell_T
    1669        3150 :          y_cell_R_minus_S_minus_T = y_cell_R - y_cell_S - y_cell_T
    1670        3150 :          z_cell_R_minus_S_minus_T = z_cell_R - z_cell_S - z_cell_T
    1671             : 
    1672             :          IF (x_cell_R_minus_S_minus_T .GE. LBOUND(cell_to_index_3c, 1) .AND. &
    1673             :              x_cell_R_minus_S_minus_T .LE. UBOUND(cell_to_index_3c, 1) .AND. &
    1674             :              y_cell_R_minus_S_minus_T .GE. LBOUND(cell_to_index_3c, 2) .AND. &
    1675             :              y_cell_R_minus_S_minus_T .LE. UBOUND(cell_to_index_3c, 2) .AND. &
    1676       22000 :              z_cell_R_minus_S_minus_T .GE. LBOUND(cell_to_index_3c, 3) .AND. &
    1677             :              z_cell_R_minus_S_minus_T .LE. UBOUND(cell_to_index_3c, 3)) THEN
    1678             : 
    1679             :             i_cell_R_minus_S_minus_T = cell_to_index_3c(x_cell_R_minus_S_minus_T, &
    1680             :                                                         y_cell_R_minus_S_minus_T, &
    1681        2900 :                                                         z_cell_R_minus_S_minus_T)
    1682             : 
    1683             :             ! index 0 means that there are only no 3c matrix elements because R-S-T is too big
    1684        2900 :             IF (i_cell_R_minus_S_minus_T == 0) THEN
    1685             : 
    1686           0 :                R_minus_S_minus_T_needed = .FALSE.
    1687             : 
    1688             :             ELSE
    1689             : 
    1690        2900 :                R_minus_S_minus_T_needed = .TRUE.
    1691             : 
    1692             :             END IF
    1693             : 
    1694             :          ELSE
    1695             : 
    1696         250 :             i_cell_R_minus_S_minus_T = 0
    1697         250 :             R_minus_S_minus_T_needed = .FALSE.
    1698             : 
    1699             :          END IF
    1700             : 
    1701             :          !  no k-kpoints
    1702             :       ELSE
    1703             : 
    1704        4136 :          R_minus_S_minus_T_needed = .TRUE.
    1705        4136 :          i_cell_R_minus_S_minus_T = 1
    1706             : 
    1707             :       END IF
    1708             : 
    1709        7286 :       CALL timestop(handle)
    1710             : 
    1711        7286 :    END SUBROUTINE get_diff_diff_index_3c
    1712             : 
    1713        1144 : END MODULE rpa_im_time

Generated by: LCOV version 1.15