LCOV - code coverage report
Current view: top level - src - rpa_im_time.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:71c3ab0) Lines: 98.7 % 599 591
Test Date: 2026-07-25 06:35:44 Functions: 100.0 % 12 12

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

Generated by: LCOV version 2.0-1