LCOV - code coverage report
Current view: top level - src - rpa_gw_im_time_util.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:9ccafda) Lines: 99.6 % 266 265
Test Date: 2026-10-15 00:55:44 Functions: 100.0 % 4 4

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Utility routines for GW with imaginary time
      10              : !> \par History
      11              : !>      06.2019 split from rpa_im_time.F [Frederick Stein]
      12              : ! **************************************************************************************************
      13              : MODULE rpa_gw_im_time_util
      14              : 
      15              :    USE atomic_kind_types,               ONLY: atomic_kind_type
      16              :    USE basis_set_types,                 ONLY: gto_basis_set_p_type
      17              :    USE cell_types,                      ONLY: cell_type,&
      18              :                                               pbc
      19              :    USE cp_dbcsr_api,                    ONLY: &
      20              :         dbcsr_create, dbcsr_distribution_get, dbcsr_distribution_new, dbcsr_distribution_release, &
      21              :         dbcsr_distribution_type, dbcsr_filter, dbcsr_get_info, dbcsr_init_p, dbcsr_multiply, &
      22              :         dbcsr_p_type, dbcsr_release, dbcsr_release_p, dbcsr_type, dbcsr_type_no_symmetry
      23              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_add_on_diag,&
      24              :                                               dbcsr_get_diag,&
      25              :                                               dbcsr_reserve_all_blocks,&
      26              :                                               dbcsr_set_diag
      27              :    USE cp_dbcsr_operations,             ONLY: copy_fm_to_dbcsr,&
      28              :                                               cp_dbcsr_m_by_n_from_row_template
      29              :    USE cp_dbcsr_redistribution,         ONLY: cp_dbcsr_from_subgroups
      30              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      31              :                                               cp_fm_release,&
      32              :                                               cp_fm_set_element,&
      33              :                                               cp_fm_to_fm,&
      34              :                                               cp_fm_type
      35              :    USE dbt_api,                         ONLY: &
      36              :         dbt_contract, dbt_copy, dbt_copy_matrix_to_tensor, dbt_create, dbt_default_distvec, &
      37              :         dbt_destroy, dbt_get_info, dbt_pgrid_create, dbt_pgrid_destroy, dbt_pgrid_type, dbt_type
      38              :    USE hfx_types,                       ONLY: alloc_containers,&
      39              :                                               block_ind_type,&
      40              :                                               hfx_compression_type
      41              :    USE kinds,                           ONLY: dp,&
      42              :                                               int_8
      43              :    USE mathconstants,                   ONLY: twopi
      44              :    USE message_passing,                 ONLY: mp_dims_create,&
      45              :                                               mp_para_env_type
      46              :    USE particle_methods,                ONLY: get_particle_set
      47              :    USE particle_types,                  ONLY: particle_type
      48              :    USE qs_environment_types,            ONLY: get_qs_env,&
      49              :                                               qs_environment_type
      50              :    USE qs_integral_utils,               ONLY: basis_set_list_setup
      51              :    USE qs_kind_types,                   ONLY: qs_kind_type
      52              :    USE qs_tensors,                      ONLY: compress_tensor,&
      53              :                                               decompress_tensor,&
      54              :                                               get_tensor_occupancy
      55              :    USE qs_tensors_types,                ONLY: create_2c_tensor,&
      56              :                                               create_3c_tensor,&
      57              :                                               pgf_block_sizes,&
      58              :                                               split_block_sizes
      59              : #include "./base/base_uses.f90"
      60              : 
      61              :    IMPLICIT NONE
      62              : 
      63              :    PRIVATE
      64              : 
      65              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'rpa_gw_im_time_util'
      66              : 
      67              :    PUBLIC :: get_tensor_3c_overl_int_gw, compute_weight_re_im, get_atom_index_from_basis_function_index
      68              : 
      69              : CONTAINS
      70              : 
      71              : ! **************************************************************************************************
      72              : !> \brief ...
      73              : !> \param t_3c_overl_int ...
      74              : !> \param t_3c_O_compressed ...
      75              : !> \param t_3c_O_ind ...
      76              : !> \param t_3c_overl_int_ao_mo ...
      77              : !> \param t_3c_O_mo_compressed ...
      78              : !> \param t_3c_O_mo_ind ...
      79              : !> \param t_3c_overl_int_gw_RI ...
      80              : !> \param t_3c_overl_int_gw_AO ...
      81              : !> \param starts_array_mc ...
      82              : !> \param ends_array_mc ...
      83              : !> \param mo_coeff ...
      84              : !> \param matrix_s ...
      85              : !> \param gw_corr_lev_occ ...
      86              : !> \param gw_corr_lev_virt ...
      87              : !> \param homo ...
      88              : !> \param nmo ...
      89              : !> \param para_env ...
      90              : !> \param do_ic_model ...
      91              : !> \param t_3c_overl_nnP_ic ...
      92              : !> \param t_3c_overl_nnP_ic_reflected ...
      93              : !> \param qs_env ...
      94              : !> \param unit_nr ...
      95              : !> \param do_alpha ...
      96              : ! **************************************************************************************************
      97           54 :    SUBROUTINE get_tensor_3c_overl_int_gw(t_3c_overl_int, t_3c_O_compressed, t_3c_O_ind, &
      98              :                                          t_3c_overl_int_ao_mo, t_3c_O_mo_compressed, t_3c_O_mo_ind, &
      99              :                                          t_3c_overl_int_gw_RI, t_3c_overl_int_gw_AO, &
     100          108 :                                          starts_array_mc, ends_array_mc, &
     101              :                                          mo_coeff, matrix_s, &
     102              :                                          gw_corr_lev_occ, gw_corr_lev_virt, homo, nmo, &
     103              :                                          para_env, &
     104              :                                          do_ic_model, &
     105              :                                          t_3c_overl_nnP_ic, t_3c_overl_nnP_ic_reflected, &
     106              :                                          qs_env, unit_nr, do_alpha)
     107              : 
     108              :       TYPE(dbt_type), DIMENSION(:, :)                    :: t_3c_overl_int
     109              :       TYPE(hfx_compression_type), DIMENSION(:, :, :)     :: t_3c_O_compressed
     110              :       TYPE(block_ind_type), DIMENSION(:, :, :)           :: t_3c_O_ind
     111              :       TYPE(dbt_type)                                     :: t_3c_overl_int_ao_mo
     112              :       TYPE(hfx_compression_type)                         :: t_3c_O_mo_compressed
     113              :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: t_3c_O_mo_ind
     114              :       TYPE(dbt_type)                                     :: t_3c_overl_int_gw_RI, &
     115              :                                                             t_3c_overl_int_gw_AO
     116              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: starts_array_mc, ends_array_mc
     117              :       TYPE(cp_fm_type), INTENT(IN)                       :: mo_coeff
     118              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
     119              :       INTEGER, INTENT(IN)                                :: gw_corr_lev_occ, gw_corr_lev_virt, homo, &
     120              :                                                             nmo
     121              :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env
     122              :       LOGICAL, INTENT(IN)                                :: do_ic_model
     123              :       TYPE(dbt_type)                                     :: t_3c_overl_nnP_ic, &
     124              :                                                             t_3c_overl_nnP_ic_reflected
     125              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     126              :       INTEGER, INTENT(IN)                                :: unit_nr
     127              :       LOGICAL, INTENT(IN), OPTIONAL                      :: do_alpha
     128              : 
     129              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'get_tensor_3c_overl_int_gw'
     130              : 
     131              :       INTEGER :: cut_memory, handle, i_mem, icol_global, imo, irow_global, min_bsize, &
     132              :          min_bsize_mo, nkind, nmo_blk_gw, npcols, nprows, size_MO, unit_nr_prv
     133              :       INTEGER(int_8)                                     :: nze
     134          108 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: dist1, dist2, dist3, sizes_AO, &
     135           54 :                                                             sizes_AO_split, sizes_MO, sizes_MO_1, &
     136          108 :                                                             sizes_RI, sizes_RI_split, tmp
     137              :       INTEGER, DIMENSION(2)                              :: pdims_2d
     138              :       INTEGER, DIMENSION(2, 1)                           :: bounds
     139              :       INTEGER, DIMENSION(2, 3)                           :: ibounds
     140              :       INTEGER, DIMENSION(3)                              :: bounds_3c, pdims
     141          108 :       INTEGER, DIMENSION(:), POINTER                     :: distp_1, distp_2, sizes_MO_blocked, &
     142           54 :                                                             sizes_MO_p1, sizes_MO_p2
     143              :       LOGICAL                                            :: memory_info, my_do_alpha
     144              :       REAL(dp)                                           :: compression_factor, memory_3c, occ
     145           54 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: norm
     146           54 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     147              :       TYPE(cp_fm_type)                                   :: fm_mat_mo_coeff_gw
     148              :       TYPE(dbcsr_distribution_type)                      :: dist, dist_templ
     149              :       TYPE(dbcsr_type)                                   :: mat_mo_coeff_gw_reflected_norm, &
     150              :                                                             mat_norm, mat_norm_diag, mat_work
     151              :       TYPE(dbcsr_type), POINTER                          :: mat_mo_coeff_gw, &
     152              :                                                             mat_mo_coeff_gw_reflected
     153          486 :       TYPE(dbt_pgrid_type)                               :: pgrid_2d, pgrid_AO, pgrid_ic, pgrid_MO
     154          702 :       TYPE(dbt_type)                                     :: mo_coeff_gw_t, mo_coeff_gw_t_tmp, &
     155          378 :                                                             t_3c_overl_int_ao_ao, &
     156          378 :                                                             t_3c_overl_int_mo_ao, &
     157          378 :                                                             t_3c_overl_int_mo_mo
     158           54 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_ao, basis_set_ri_aux
     159           54 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     160           54 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     161              : 
     162           54 :       memory_info = qs_env%mp2_env%ri_rpa_im_time%memory_info
     163           54 :       IF (memory_info) THEN
     164            0 :          unit_nr_prv = unit_nr
     165              :       ELSE
     166           54 :          unit_nr_prv = 0
     167              :       END IF
     168              : 
     169           54 :       my_do_alpha = .FALSE.
     170           54 :       IF (PRESENT(do_alpha)) my_do_alpha = do_alpha
     171              : 
     172           54 :       CALL timeset(routineN, handle)
     173              : 
     174           54 :       CALL get_qs_env(qs_env, nkind=nkind, qs_kind_set=qs_kind_set, particle_set=particle_set, atomic_kind_set=atomic_kind_set)
     175              : 
     176           54 :       CALL cp_fm_create(fm_mat_mo_coeff_gw, mo_coeff%matrix_struct)
     177           54 :       CALL cp_fm_to_fm(mo_coeff, fm_mat_mo_coeff_gw)
     178              : 
     179              :       ! set MO coeffs to zero where
     180         1396 :       DO irow_global = 1, nmo
     181         3094 :          DO icol_global = 1, homo - gw_corr_lev_occ
     182         3094 :             CALL cp_fm_set_element(fm_mat_mo_coeff_gw, irow_global, icol_global, 0.0_dp)
     183              :          END DO
     184        32506 :          DO icol_global = homo + gw_corr_lev_virt + 1, nmo
     185        32452 :             CALL cp_fm_set_element(fm_mat_mo_coeff_gw, irow_global, icol_global, 0.0_dp)
     186              :          END DO
     187              :       END DO
     188              : 
     189           54 :       NULLIFY (mat_mo_coeff_gw)
     190           54 :       CALL dbcsr_init_p(mat_mo_coeff_gw)
     191              : 
     192              :       CALL cp_dbcsr_m_by_n_from_row_template(mat_mo_coeff_gw, template=matrix_s(1)%matrix, n=nmo, &
     193           54 :                                              sym=dbcsr_type_no_symmetry)
     194              : 
     195              :       CALL copy_fm_to_dbcsr(fm_mat_mo_coeff_gw, &
     196              :                             mat_mo_coeff_gw, &
     197           54 :                             keep_sparsity=.FALSE.)
     198              : 
     199              :       ! just remove the blocks which have been set to zero
     200           54 :       CALL dbcsr_filter(mat_mo_coeff_gw, 1.0E-20_dp)
     201              : 
     202           54 :       min_bsize = qs_env%mp2_env%ri_rpa_im_time%min_bsize
     203           54 :       min_bsize_mo = qs_env%mp2_env%ri_rpa_im_time%min_bsize_mo
     204              : 
     205          108 :       CALL split_block_sizes([gw_corr_lev_occ + gw_corr_lev_virt], sizes_MO, min_bsize_mo)
     206          162 :       ALLOCATE (sizes_MO_1(nmo))
     207         1396 :       sizes_MO_1(:) = 1
     208              : 
     209           54 :       nmo_blk_gw = SIZE(sizes_MO)
     210           54 :       CALL move_alloc(sizes_MO, tmp)
     211          162 :       ALLOCATE (sizes_MO(nmo_blk_gw + 2))
     212           54 :       sizes_MO(1) = homo - gw_corr_lev_occ
     213          108 :       sizes_MO(2:SIZE(tmp) + 1) = tmp(:)
     214           54 :       sizes_MO(SIZE(tmp) + 2) = nmo - (homo + gw_corr_lev_virt)
     215              : 
     216          432 :       ALLOCATE (basis_set_ri_aux(nkind), basis_set_ao(nkind))
     217           54 :       CALL basis_set_list_setup(basis_set_ri_aux, "RI_AUX", qs_kind_set)
     218           54 :       CALL get_particle_set(particle_set, qs_kind_set, nsgf=sizes_RI, basis=basis_set_ri_aux)
     219           54 :       CALL basis_set_list_setup(basis_set_ao, "ORB", qs_kind_set)
     220           54 :       CALL get_particle_set(particle_set, qs_kind_set, nsgf=sizes_AO, basis=basis_set_ao)
     221              : 
     222           54 :       CALL pgf_block_sizes(atomic_kind_set, basis_set_ao, min_bsize, sizes_AO_split)
     223           54 :       CALL pgf_block_sizes(atomic_kind_set, basis_set_ri_aux, min_bsize, sizes_RI_split)
     224              : 
     225           54 :       DEALLOCATE (basis_set_ao, basis_set_ri_aux)
     226              : 
     227           54 :       pdims = 0
     228              :       CALL dbt_pgrid_create(para_env, pdims, pgrid_AO, &
     229          216 :                             tensor_dims=[SIZE(sizes_RI_split), SIZE(sizes_AO_split), SIZE(sizes_AO_split)])
     230              : 
     231           54 :       pdims_2d = 0
     232           54 :       CALL mp_dims_create(para_env%num_pe, pdims_2d)
     233              : 
     234              :       ! we iterate over MO blocks for saving memory during contraction, thus we should not parallelize over MO dimension
     235          216 :       pdims = [pdims_2d(1), pdims_2d(2), 1]
     236              :       CALL dbt_pgrid_create(para_env, pdims, pgrid_MO, &
     237          216 :                             tensor_dims=[SIZE(sizes_RI_split), SIZE(sizes_AO_split), 1])
     238              : 
     239           54 :       pdims_2d = 0
     240              :       CALL dbt_pgrid_create(para_env, pdims_2d, pgrid_2d, &
     241          162 :                             tensor_dims=[SIZE(sizes_AO_split), nmo])
     242              : 
     243              :       CALL create_3c_tensor(t_3c_overl_int_ao_ao, dist1, dist2, dist3, pgrid_AO, &
     244           54 :                             sizes_RI_split, sizes_AO_split, sizes_AO_split, [1, 2], [3], name="(RI AO | AO)")
     245           54 :       DEALLOCATE (dist1, dist2, dist3)
     246              : 
     247           54 :       IF (.NOT. qs_env%mp2_env%ri_g0w0%do_kpoints_Sigma) THEN
     248              :          CALL create_3c_tensor(t_3c_overl_int_ao_mo, dist1, dist2, dist3, pgrid_AO, &
     249           36 :                                sizes_RI_split, sizes_AO_split, sizes_MO_1, [1, 2], [3], name="(RI AO | MO)")
     250           36 :          DEALLOCATE (dist1, dist2, dist3)
     251              :       END IF
     252              : 
     253              :       CALL create_3c_tensor(t_3c_overl_int_gw_RI, dist1, dist2, dist3, pgrid_MO, &
     254           54 :                             sizes_RI_split, sizes_AO_split, sizes_MO, [1], [2, 3], name="(RI | AO MO)")
     255           54 :       DEALLOCATE (dist1, dist2, dist3)
     256              : 
     257              :       CALL create_3c_tensor(t_3c_overl_int_gw_AO, dist1, dist2, dist3, pgrid_MO, &
     258           54 :                             sizes_AO_split, sizes_RI_split, sizes_MO, [1], [2, 3], name="(AO | RI MO)")
     259           54 :       DEALLOCATE (dist1, dist2, dist3)
     260              : 
     261           54 :       CALL dbt_pgrid_destroy(pgrid_AO)
     262           54 :       CALL dbt_pgrid_destroy(pgrid_MO)
     263              : 
     264           54 :       CALL create_2c_tensor(mo_coeff_gw_t, dist1, dist2, pgrid_2d, sizes_AO_split, sizes_MO_1, name="(AO|MO)")
     265           54 :       DEALLOCATE (dist1, dist2)
     266           54 :       CALL dbt_pgrid_destroy(pgrid_2d)
     267              : 
     268           54 :       CALL dbt_create(mat_mo_coeff_gw, mo_coeff_gw_t_tmp, name="MO coeffs")
     269           54 :       CALL dbt_copy_matrix_to_tensor(mat_mo_coeff_gw, mo_coeff_gw_t_tmp)
     270              : 
     271           54 :       CALL dbt_copy(mo_coeff_gw_t_tmp, mo_coeff_gw_t)
     272              : 
     273           54 :       bounds(1, 1) = homo - gw_corr_lev_occ + 1
     274           54 :       bounds(2, 1) = homo + gw_corr_lev_virt
     275              : 
     276           54 :       CALL dbt_get_info(t_3c_overl_int_ao_ao, nfull_total=bounds_3c)
     277              : 
     278          162 :       ibounds(:, 1) = [1, bounds_3c(1)]
     279          162 :       ibounds(:, 3) = [1, bounds_3c(3)]
     280              : 
     281           54 :       cut_memory = SIZE(starts_array_mc)
     282              : 
     283           54 :       IF (.NOT. qs_env%mp2_env%ri_g0w0%do_kpoints_Sigma) THEN
     284           72 :          DO i_mem = 1, cut_memory
     285              :             CALL decompress_tensor(t_3c_overl_int(1, 1), t_3c_O_ind(1, 1, i_mem)%ind, t_3c_O_compressed(1, 1, i_mem), &
     286           36 :                                    qs_env%mp2_env%ri_rpa_im_time%eps_compress)
     287              : 
     288          108 :             ibounds(:, 2) = [starts_array_mc(i_mem), ends_array_mc(i_mem)]
     289              : 
     290           36 :             CALL dbt_copy(t_3c_overl_int(1, 1), t_3c_overl_int_ao_ao, move_data=.TRUE.)
     291              : 
     292              :             CALL dbt_contract(1.0_dp, mo_coeff_gw_t, t_3c_overl_int_ao_ao, 1.0_dp, &
     293              :                               t_3c_overl_int_ao_mo, contract_1=[1], notcontract_1=[2], &
     294              :                               contract_2=[3], notcontract_2=[1, 2], map_1=[3], map_2=[1, 2], &
     295           72 :                               bounds_2=ibounds, move_data=.FALSE., unit_nr=unit_nr_prv)
     296              : 
     297              :          END DO
     298              :       END IF
     299              : 
     300           54 :       CALL cp_fm_release(fm_mat_mo_coeff_gw)
     301              : 
     302           54 :       IF (do_ic_model) THEN
     303            2 :          pdims = 0
     304              :          CALL dbt_pgrid_create(para_env, pdims, pgrid_ic, &
     305            8 :                                tensor_dims=[SIZE(sizes_RI_split), nmo, nmo])
     306              : 
     307              :          CALL create_3c_tensor(t_3c_overl_int_mo_ao, dist1, dist2, dist3, pgrid_ic, &
     308            2 :                                sizes_RI_split, sizes_MO_1, sizes_AO_split, [1, 2], [3], name="(RI MO | AO)")
     309            2 :          DEALLOCATE (dist1, dist2, dist3)
     310              :          CALL create_3c_tensor(t_3c_overl_int_mo_mo, dist1, dist2, dist3, pgrid_ic, &
     311            2 :                                sizes_RI_split, sizes_MO_1, sizes_MO_1, [1, 2], [3], name="(RI MO | MO)")
     312            2 :          DEALLOCATE (dist1, dist2, dist3)
     313            2 :          CALL dbt_create(t_3c_overl_int_mo_mo, t_3c_overl_nnP_ic)
     314              :          CALL create_3c_tensor(t_3c_overl_nnP_ic_reflected, dist1, dist2, dist3, pgrid_ic, &
     315            2 :                                sizes_RI_split, sizes_MO_1, sizes_MO_1, [1], [2, 3], name="(RI | MO MO)")
     316            2 :          DEALLOCATE (dist1, dist2, dist3)
     317              : 
     318            2 :          CALL dbt_pgrid_destroy(pgrid_ic)
     319              : 
     320            2 :          CALL dbt_copy(t_3c_overl_int_ao_mo, t_3c_overl_int_mo_ao, order=[1, 3, 2])
     321              :          CALL dbt_contract(1.0_dp, mo_coeff_gw_t, t_3c_overl_int_mo_ao, 0.0_dp, &
     322              :                            t_3c_overl_int_mo_mo, contract_1=[1], notcontract_1=[2], &
     323              :                            contract_2=[3], notcontract_2=[1, 2], map_1=[3], map_2=[1, 2], &
     324            2 :                            bounds_2=bounds, move_data=.FALSE., unit_nr=unit_nr_prv)
     325            2 :          CALL dbt_copy(t_3c_overl_int_mo_mo, t_3c_overl_nnP_ic)
     326              : 
     327            2 :          NULLIFY (mat_mo_coeff_gw_reflected)
     328            2 :          CALL dbcsr_init_p(mat_mo_coeff_gw_reflected)
     329              : 
     330              :          CALL cp_dbcsr_m_by_n_from_row_template(mat_mo_coeff_gw_reflected, template=matrix_s(1)%matrix, n=nmo, &
     331            2 :                                                 sym=dbcsr_type_no_symmetry)
     332              : 
     333            2 :          CALL reflect_mat_row(mat_mo_coeff_gw_reflected, mat_mo_coeff_gw, para_env, qs_env, unit_nr, do_alpha=my_do_alpha)
     334              : 
     335              :          ! normalize reflected MOs (they are not properly normalized since high angular momentum basis functions
     336              :          ! of the image molecule are not exactly reflected at the image plane (sign problem in p_z function)
     337            2 :          CALL dbcsr_create(matrix=mat_work, template=mat_mo_coeff_gw_reflected, matrix_type=dbcsr_type_no_symmetry)
     338              : 
     339            2 :          CALL dbcsr_get_info(mat_work, distribution=dist_templ, nblkcols_total=size_MO, col_blk_size=sizes_MO_blocked)
     340              : 
     341            2 :          CALL dbcsr_distribution_get(dist_templ, nprows=nprows, npcols=npcols)
     342              : 
     343            8 :          ALLOCATE (distp_1(size_MO), distp_2(size_MO))
     344            2 :          CALL dbt_default_distvec(size_MO, nprows, sizes_MO_blocked, distp_1)
     345            2 :          CALL dbt_default_distvec(size_MO, npcols, sizes_MO_blocked, distp_2)
     346            2 :          CALL dbcsr_distribution_new(dist, template=dist_templ, row_dist=distp_1, col_dist=distp_2, reuse_arrays=.TRUE.)
     347              : 
     348            4 :          ALLOCATE (sizes_MO_p1(size_MO))
     349            4 :          ALLOCATE (sizes_MO_p2(size_MO))
     350           14 :          sizes_MO_p1(:) = sizes_MO_blocked
     351           14 :          sizes_MO_p2(:) = sizes_MO_blocked
     352              :          CALL dbcsr_create(mat_norm, "mo norm", dist, dbcsr_type_no_symmetry, sizes_MO_p1, sizes_MO_p2, &
     353            2 :                            reuse_arrays=.TRUE.)
     354            2 :          CALL dbcsr_distribution_release(dist)
     355              : 
     356            2 :          CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_s(1)%matrix, mat_mo_coeff_gw_reflected, 0.0_dp, mat_work)
     357            2 :          CALL dbcsr_multiply("T", "N", 1.0_dp, mat_mo_coeff_gw_reflected, mat_work, 0.0_dp, mat_norm)
     358              : 
     359            2 :          CALL dbcsr_release(mat_work)
     360              : 
     361            6 :          ALLOCATE (norm(nmo))
     362            2 :          norm = 0.0_dp
     363              : 
     364            2 :          CALL dbcsr_get_diag(mat_norm, norm)
     365            2 :          CALL para_env%sum(norm)
     366              : 
     367           14 :          DO imo = bounds(1, 1), bounds(2, 1)
     368           14 :             norm(imo) = 1.0_dp/SQRT(norm(imo))
     369              :          END DO
     370              : 
     371            2 :          CALL dbcsr_create(mat_norm_diag, template=mat_norm)
     372            2 :          CALL dbcsr_release(mat_norm)
     373              : 
     374            2 :          CALL dbcsr_add_on_diag(mat_norm_diag, 1.0_dp)
     375              : 
     376            2 :          CALL dbcsr_set_diag(mat_norm_diag, norm)
     377              : 
     378            2 :          CALL dbcsr_create(mat_mo_coeff_gw_reflected_norm, template=mat_mo_coeff_gw_reflected)
     379            2 :          CALL dbcsr_multiply("N", "N", 1.0_dp, mat_mo_coeff_gw_reflected, mat_norm_diag, 0.0_dp, mat_mo_coeff_gw_reflected_norm)
     380            2 :          CALL dbcsr_release(mat_norm_diag)
     381              : 
     382            2 :          CALL dbcsr_filter(mat_mo_coeff_gw_reflected_norm, 1.0E-20_dp)
     383              : 
     384            2 :          CALL dbt_copy_matrix_to_tensor(mat_mo_coeff_gw_reflected_norm, mo_coeff_gw_t_tmp)
     385            2 :          CALL dbcsr_release(mat_mo_coeff_gw_reflected_norm)
     386            2 :          CALL dbt_copy(mo_coeff_gw_t_tmp, mo_coeff_gw_t)
     387              : 
     388              :          CALL dbt_contract(1.0_dp, mo_coeff_gw_t, t_3c_overl_int_ao_ao, 0.0_dp, &
     389              :                            t_3c_overl_int_ao_mo, contract_1=[1], notcontract_1=[2], &
     390              :                            contract_2=[3], notcontract_2=[1, 2], map_1=[3], map_2=[1, 2], &
     391            2 :                            bounds_2=bounds, move_data=.FALSE., unit_nr=unit_nr_prv)
     392              : 
     393            2 :          CALL dbt_copy(t_3c_overl_int_ao_mo, t_3c_overl_int_mo_ao, order=[1, 3, 2])
     394              :          CALL dbt_contract(1.0_dp, mo_coeff_gw_t, t_3c_overl_int_mo_ao, 0.0_dp, &
     395              :                            t_3c_overl_int_mo_mo, contract_1=[1], notcontract_1=[2], &
     396              :                            contract_2=[3], notcontract_2=[1, 2], map_1=[3], map_2=[1, 2], &
     397            2 :                            bounds_2=bounds, move_data=.FALSE., unit_nr=unit_nr_prv)
     398            2 :          CALL dbt_copy(t_3c_overl_int_mo_mo, t_3c_overl_nnP_ic_reflected)
     399            2 :          CALL dbt_destroy(t_3c_overl_int_mo_ao)
     400            2 :          CALL dbt_destroy(t_3c_overl_int_mo_mo)
     401              : 
     402            4 :          CALL dbcsr_release_p(mat_mo_coeff_gw_reflected)
     403              : 
     404              :       END IF
     405              : 
     406           54 :       IF (.NOT. qs_env%mp2_env%ri_g0w0%do_kpoints_Sigma) THEN
     407           36 :          CALL alloc_containers(t_3c_O_mo_compressed, 1)
     408           36 :          CALL get_tensor_occupancy(t_3c_overl_int_ao_mo, nze, occ)
     409           36 :          memory_3c = 0.0_dp
     410              : 
     411              :          CALL compress_tensor(t_3c_overl_int_ao_mo, t_3c_O_mo_ind, t_3c_O_mo_compressed, &
     412           36 :                               qs_env%mp2_env%ri_rpa_im_time%eps_compress, memory_3c)
     413              : 
     414           36 :          CALL para_env%sum(memory_3c)
     415           36 :          compression_factor = REAL(nze, dp)*1.0E-06_dp*8.0_dp/memory_3c
     416              : 
     417           36 :          IF (unit_nr > 0) THEN
     418              :             WRITE (UNIT=unit_nr, FMT="((T3,A,T66,F11.2,A4))") &
     419           18 :                "MEMORY_INFO| Memory of MO-contracted tensor (compressed):", memory_3c, ' MiB'
     420              : 
     421              :             WRITE (UNIT=unit_nr, FMT="((T3,A,T60,F21.2))") &
     422           18 :                "MEMORY_INFO| Compression factor:                  ", compression_factor
     423              :          END IF
     424              :       END IF
     425              : 
     426           54 :       CALL dbcsr_release_p(mat_mo_coeff_gw)
     427              : 
     428           54 :       CALL dbt_destroy(t_3c_overl_int_ao_ao)
     429           54 :       CALL dbt_destroy(mo_coeff_gw_t)
     430           54 :       CALL dbt_destroy(mo_coeff_gw_t_tmp)
     431              : 
     432           54 :       CALL timestop(handle)
     433              : 
     434          324 :    END SUBROUTINE get_tensor_3c_overl_int_gw
     435              : 
     436              : ! **************************************************************************************************
     437              : !> \brief reflect from V = (A,B|B,A) to V_reflected = (B,A|A,B) where A belongs to the block of the molecule
     438              : !>        and B to the off diagonal block between molecule and image of the molecule
     439              : !> \param mat_reflected ...
     440              : !> \param mat_orig ...
     441              : !> \param para_env ...
     442              : !> \param qs_env ...
     443              : !> \param unit_nr ...
     444              : !> \param do_alpha ...
     445              : ! **************************************************************************************************
     446            2 :    SUBROUTINE reflect_mat_row(mat_reflected, mat_orig, para_env, qs_env, unit_nr, do_alpha)
     447              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: mat_reflected
     448              :       TYPE(dbcsr_type), INTENT(IN)                       :: mat_orig
     449              :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env
     450              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     451              :       INTEGER, INTENT(IN)                                :: unit_nr
     452              :       LOGICAL, INTENT(IN)                                :: do_alpha
     453              : 
     454              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'reflect_mat_row'
     455              : 
     456              :       INTEGER                                            :: handle, i_atom, j_atom, natom, &
     457              :                                                             nblkcols_total, nblkrows_total
     458            2 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: image_atom
     459            2 :       INTEGER, DIMENSION(:), POINTER                     :: col_blk_sizes, row_blk_sizes
     460              :       LOGICAL                                            :: found_image_atom
     461              :       REAL(KIND=dp)                                      :: avg_z_dist, delta, eps_dist2, &
     462              :                                                             min_z_dist, ra(3), rb(3), sum_z, &
     463              :                                                             z_reflection
     464              :       TYPE(cell_type), POINTER                           :: cell
     465            2 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     466              : 
     467            2 :       CALL timeset(routineN, handle)
     468              : 
     469            2 :       CALL dbcsr_reserve_all_blocks(mat_reflected)
     470              : 
     471              :       CALL get_qs_env(qs_env, cell=cell, &
     472            2 :                       particle_set=particle_set)
     473              : 
     474              :       ! first check, whether we have an image molecule
     475              :       CALL dbcsr_get_info(mat_orig, &
     476              :                           nblkrows_total=nblkrows_total, &
     477              :                           nblkcols_total=nblkcols_total, &
     478              :                           row_blk_size=row_blk_sizes, &
     479            2 :                           col_blk_size=col_blk_sizes)
     480              : 
     481            2 :       natom = SIZE(particle_set)
     482            2 :       CPASSERT(natom == nblkrows_total)
     483              : 
     484            2 :       eps_dist2 = qs_env%mp2_env%ri_g0w0%eps_dist
     485            2 :       eps_dist2 = eps_dist2*eps_dist2
     486              : 
     487            2 :       sum_z = 0.0_dp
     488              : 
     489           18 :       DO i_atom = 1, natom
     490              : 
     491           16 :          ra(:) = pbc(particle_set(i_atom)%r, cell)
     492              : 
     493           18 :          sum_z = sum_z + ra(3)
     494              : 
     495              :       END DO
     496              : 
     497            2 :       z_reflection = sum_z/REAL(natom, KIND=dp)
     498              : 
     499            2 :       sum_z = 0.0_dp
     500              : 
     501           18 :       DO i_atom = 1, natom
     502              : 
     503           16 :          ra(:) = pbc(particle_set(i_atom)%r, cell)
     504              : 
     505           18 :          sum_z = sum_z + ABS(ra(3) - z_reflection)
     506              : 
     507              :       END DO
     508              : 
     509            2 :       avg_z_dist = sum_z/REAL(natom, KIND=dp)
     510              : 
     511            2 :       min_z_dist = avg_z_dist
     512              : 
     513           18 :       DO i_atom = 1, natom
     514              : 
     515           16 :          ra(:) = pbc(particle_set(i_atom)%r, cell)
     516              : 
     517           18 :          IF (ABS(ra(3) - z_reflection) < min_z_dist) THEN
     518              :             min_z_dist = ABS(ra(3) - z_reflection)
     519              :          END IF
     520              : 
     521              :       END DO
     522              : 
     523            2 :       IF (unit_nr > 0 .AND. do_alpha) THEN
     524            1 :          WRITE (unit_nr, '(T3,A,T70,F9.2,A2)') 'IC_MODEL| Average distance of the molecule to the image plane:', &
     525            2 :             avg_z_dist*0.529_dp, ' A'
     526            1 :          WRITE (unit_nr, '(T3,A,T70,F9.2,A2)') 'IC_MODEL| Minimum distance of the molecule to the image plane:', &
     527            2 :             min_z_dist*0.529_dp, ' A'
     528              :       END IF
     529              : 
     530            6 :       ALLOCATE (image_atom(nblkrows_total))
     531            2 :       image_atom = 0
     532              : 
     533           18 :       DO i_atom = 1, natom
     534              : 
     535           16 :          found_image_atom = .FALSE.
     536              : 
     537           16 :          ra(:) = pbc(particle_set(i_atom)%r, cell)
     538              : 
     539          144 :          DO j_atom = 1, natom
     540              : 
     541          128 :             rb(:) = pbc(particle_set(j_atom)%r, cell)
     542              : 
     543          128 :             delta = (ra(1) - rb(1))**2 + (ra(2) - rb(2))**2 + (ra(3) + rb(3) - 2.0_dp*z_reflection)**2
     544              : 
     545              :             ! SQRT(delta) < eps_dist
     546          144 :             IF (delta < eps_dist2) THEN
     547              :                ! this CPASSERT ensures that there is at most one image atom for each atom
     548           16 :                CPASSERT(.NOT. found_image_atom)
     549           16 :                image_atom(i_atom) = j_atom
     550           16 :                found_image_atom = .TRUE.
     551              :                ! check whether we have the same basis at the image atom
     552              :                ! if this is wrong, check whether you have the same basis sets for the molecule and the image
     553           16 :                CPASSERT(row_blk_sizes(i_atom) == row_blk_sizes(j_atom))
     554              :             END IF
     555              : 
     556              :          END DO
     557              : 
     558              :          ! this CPASSERT ensures that there is at least one image atom for each atom
     559           18 :          CPASSERT(found_image_atom)
     560              : 
     561              :       END DO
     562              : 
     563            2 :       CALL cp_dbcsr_from_subgroups(mat_orig, mat_reflected, para_env, row_mapping=image_atom, copy_only=.TRUE.)
     564              : 
     565            2 :       CALL timestop(handle)
     566              : 
     567            6 :    END SUBROUTINE reflect_mat_row
     568              : 
     569              : ! **************************************************************************************************
     570              : !> \brief ...
     571              : !> \param qs_env ...
     572              : !> \param atom_from_basis_index ...
     573              : !> \param basis_size ...
     574              : !> \param basis_type ...
     575              : !> \param first_bf_from_atom ...
     576              : ! **************************************************************************************************
     577        14898 :    SUBROUTINE get_atom_index_from_basis_function_index(qs_env, atom_from_basis_index, basis_size, &
     578              :                                                        basis_type, first_bf_from_atom)
     579              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     580              :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_from_basis_index
     581              :       INTEGER                                            :: basis_size
     582              :       CHARACTER(LEN=*)                                   :: basis_type
     583              :       INTEGER, ALLOCATABLE, DIMENSION(:), OPTIONAL       :: first_bf_from_atom
     584              : 
     585              :       INTEGER                                            :: iatom, LLL, natom, nkind
     586              :       INTEGER, DIMENSION(:), POINTER                     :: row_blk_end, row_blk_start
     587        14898 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set
     588        14898 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     589        14898 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     590              : 
     591        14898 :       NULLIFY (qs_kind_set, particle_set)
     592              :       CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set, natom=natom, nkind=nkind, &
     593        14898 :                       particle_set=particle_set)
     594              : 
     595        44694 :       ALLOCATE (row_blk_start(natom))
     596        29796 :       ALLOCATE (row_blk_end(natom))
     597        68512 :       ALLOCATE (basis_set(nkind))
     598        14898 :       CALL basis_set_list_setup(basis_set, basis_type, qs_kind_set)
     599              :       CALL get_particle_set(particle_set, qs_kind_set, first_sgf=row_blk_start, last_sgf=row_blk_end, &
     600        14898 :                             basis=basis_set)
     601       399746 :       DO LLL = 1, basis_size
     602      1401550 :          DO iatom = 1, natom
     603      1386652 :             IF (LLL >= row_blk_start(iatom) .AND. LLL <= row_blk_end(iatom)) THEN
     604       384848 :                atom_from_basis_index(LLL) = iatom
     605              :             END IF
     606              :          END DO
     607              :       END DO
     608              : 
     609        14898 :       IF (PRESENT(first_bf_from_atom)) first_bf_from_atom(1:natom) = row_blk_start(:)
     610              : 
     611        14898 :       DEALLOCATE (basis_set)
     612        14898 :       DEALLOCATE (row_blk_start)
     613        14898 :       DEALLOCATE (row_blk_end)
     614              : 
     615        14898 :    END SUBROUTINE get_atom_index_from_basis_function_index
     616              : 
     617              : ! **************************************************************************************************
     618              : !> \brief ...
     619              : !> \param weight_re ...
     620              : !> \param weight_im ...
     621              : !> \param num_cells ...
     622              : !> \param iatom ...
     623              : !> \param jatom ...
     624              : !> \param xkp ...
     625              : !> \param wkp_W ...
     626              : !> \param cell ...
     627              : !> \param index_to_cell ...
     628              : !> \param hmat ...
     629              : !> \param particle_set ...
     630              : ! **************************************************************************************************
     631       409772 :    SUBROUTINE compute_weight_re_im(weight_re, weight_im, &
     632              :                                    num_cells, iatom, jatom, xkp, wkp_W, &
     633              :                                    cell, index_to_cell, hmat, particle_set)
     634              : 
     635              :       REAL(KIND=dp)                                      :: weight_re, weight_im
     636              :       INTEGER                                            :: num_cells, iatom, jatom
     637              :       REAL(KIND=dp), DIMENSION(3)                        :: xkp
     638              :       REAL(KIND=dp)                                      :: wkp_W
     639              :       TYPE(cell_type), POINTER                           :: cell
     640              :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell
     641              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: hmat
     642              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     643              : 
     644              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_weight_re_im'
     645              : 
     646              :       INTEGER                                            :: handle, icell, n_equidistant_cells, &
     647              :                                                             xcell, ycell, zcell
     648              :       REAL(KIND=dp)                                      :: abs_rab_cell, abs_rab_cell_min, arg
     649              :       REAL(KIND=dp), DIMENSION(3)                        :: cell_vector, rab_cell_i
     650              : 
     651       409772 :       CALL timeset(routineN, handle)
     652              : 
     653       409772 :       weight_re = 0.0_dp
     654       409772 :       weight_im = 0.0_dp
     655              : 
     656       409772 :       abs_rab_cell_min = 1.0E10_dp
     657              : 
     658       409772 :       n_equidistant_cells = 0
     659              : 
     660      3087532 :       DO icell = 1, num_cells
     661              : 
     662      2677760 :          xcell = index_to_cell(1, icell)
     663      2677760 :          ycell = index_to_cell(2, icell)
     664      2677760 :          zcell = index_to_cell(3, icell)
     665              : 
     666     42844160 :          cell_vector(1:3) = MATMUL(hmat, REAL([xcell, ycell, zcell], dp))
     667              : 
     668              :          rab_cell_i(1:3) = pbc(particle_set(iatom)%r(1:3), cell) - &
     669     10711040 :                            (pbc(particle_set(jatom)%r(1:3), cell) + cell_vector(1:3))
     670              : 
     671      2677760 :          abs_rab_cell = SQRT(rab_cell_i(1)**2 + rab_cell_i(2)**2 + rab_cell_i(3)**2)
     672              : 
     673       409772 :          IF (abs_rab_cell < abs_rab_cell_min) THEN
     674              :             abs_rab_cell_min = abs_rab_cell
     675              :          END IF
     676              : 
     677              :       END DO
     678              : 
     679      3087532 :       DO icell = 1, num_cells
     680              : 
     681      2677760 :          xcell = index_to_cell(1, icell)
     682      2677760 :          ycell = index_to_cell(2, icell)
     683      2677760 :          zcell = index_to_cell(3, icell)
     684              : 
     685     42844160 :          cell_vector(1:3) = MATMUL(hmat, REAL([xcell, ycell, zcell], dp))
     686              : 
     687              :          rab_cell_i(1:3) = pbc(particle_set(iatom)%r(1:3), cell) - &
     688     10711040 :                            (pbc(particle_set(jatom)%r(1:3), cell) + cell_vector(1:3))
     689              : 
     690      2677760 :          abs_rab_cell = SQRT(rab_cell_i(1)**2 + rab_cell_i(2)**2 + rab_cell_i(3)**2)
     691              : 
     692      3087532 :          IF (abs_rab_cell < abs_rab_cell_min + 0.1_dp) THEN
     693              : 
     694       409932 :             arg = REAL(xcell, dp)*xkp(1) + REAL(ycell, dp)*xkp(2) + REAL(zcell, dp)*xkp(3)
     695              : 
     696       409932 :             weight_re = weight_re + wkp_W*COS(twopi*arg)
     697       409932 :             weight_im = weight_im + wkp_W*SIN(twopi*arg)
     698              : 
     699       409932 :             n_equidistant_cells = n_equidistant_cells + 1
     700              : 
     701              :          END IF
     702              : 
     703              :       END DO
     704              : 
     705       409772 :       weight_re = weight_re/REAL(n_equidistant_cells, KIND=dp)
     706       409772 :       weight_im = weight_im/REAL(n_equidistant_cells, KIND=dp)
     707              : 
     708       409772 :       CALL timestop(handle)
     709              : 
     710       409772 :    END SUBROUTINE compute_weight_re_im
     711              : 
     712              : END MODULE rpa_gw_im_time_util
        

Generated by: LCOV version 2.0-1