LCOV - code coverage report
Current view: top level - src - rpa_im_time.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:591cf04) Lines: 98.8 % 592 585
Test Date: 2026-09-21 02:17:57 Functions: 100.0 % 13 13

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

Generated by: LCOV version 2.0-1