LCOV - code coverage report
Current view: top level - src - rpa_gw.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:5c1df3d) Lines: 93.7 % 2436 2282
Test Date: 2026-09-14 06:34:43 Functions: 100.0 % 49 49

            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 GW, continuous development [Jan Wilhelm]
      10              : !> \par History
      11              : !>      03.2019 created [Frederick Stein]
      12              : !>      12.2022 added periodic GW routines [Jan Wilhelm]
      13              : ! **************************************************************************************************
      14              : MODULE rpa_gw
      15              :    USE atomic_kind_types,               ONLY: atomic_kind_type
      16              :    USE basis_set_types,                 ONLY: gto_basis_set_p_type,&
      17              :                                               gto_basis_set_type
      18              :    USE cell_types,                      ONLY: cell_type,&
      19              :                                               get_cell
      20              :    USE core_ppnl,                       ONLY: build_core_ppnl
      21              :    USE cp_cfm_basic_linalg,             ONLY: cp_cfm_scale,&
      22              :                                               cp_cfm_scale_and_add,&
      23              :                                               cp_cfm_scale_and_add_fm,&
      24              :                                               cp_cfm_transpose
      25              :    USE cp_cfm_diag,                     ONLY: cp_cfm_geeig_canon
      26              :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      27              :                                               cp_cfm_get_info,&
      28              :                                               cp_cfm_release,&
      29              :                                               cp_cfm_set_all,&
      30              :                                               cp_cfm_to_fm,&
      31              :                                               cp_cfm_type,&
      32              :                                               cp_fm_to_cfm
      33              :    USE cp_control_types,                ONLY: dft_control_type
      34              :    USE cp_dbcsr_api,                    ONLY: &
      35              :         dbcsr_copy, dbcsr_create, dbcsr_desymmetrize, dbcsr_filter, dbcsr_get_info, dbcsr_init_p, &
      36              :         dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, dbcsr_iterator_start, &
      37              :         dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_multiply, dbcsr_p_type, dbcsr_release, &
      38              :         dbcsr_release_p, dbcsr_scale, dbcsr_set, dbcsr_type, dbcsr_type_antisymmetric, &
      39              :         dbcsr_type_no_symmetry
      40              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_add_on_diag
      41              :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      42              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      43              :                                               copy_fm_to_dbcsr,&
      44              :                                               dbcsr_allocate_matrix_set,&
      45              :                                               dbcsr_deallocate_matrix_set
      46              :    USE cp_files,                        ONLY: close_file,&
      47              :                                               open_file
      48              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_scale_and_add,&
      49              :                                               cp_fm_uplo_to_full
      50              :    USE cp_fm_cholesky,                  ONLY: cp_fm_cholesky_decompose,&
      51              :                                               cp_fm_cholesky_invert
      52              :    USE cp_fm_diag,                      ONLY: cp_fm_syevd
      53              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      54              :                                               cp_fm_struct_release,&
      55              :                                               cp_fm_struct_type
      56              :    USE cp_fm_types,                     ONLY: &
      57              :         cp_fm_copy_general, cp_fm_create, cp_fm_get_diag, cp_fm_get_info, cp_fm_release, &
      58              :         cp_fm_set_all, cp_fm_to_fm, cp_fm_to_fm_submat, cp_fm_type
      59              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      60              :                                               cp_logger_get_default_unit_nr,&
      61              :                                               cp_logger_type
      62              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      63              :                                               cp_print_key_unit_nr
      64              :    USE cp_realspace_grid_cube,          ONLY: cp_pw_to_cube
      65              :    USE dbt_api,                         ONLY: &
      66              :         dbt_batched_contract_finalize, dbt_batched_contract_init, dbt_clear, dbt_contract, &
      67              :         dbt_copy, dbt_copy_matrix_to_tensor, dbt_copy_tensor_to_matrix, dbt_create, dbt_destroy, &
      68              :         dbt_get_block, dbt_get_info, dbt_iterator_blocks_left, dbt_iterator_next_block, &
      69              :         dbt_iterator_start, dbt_iterator_stop, dbt_iterator_type, dbt_nblks_total, &
      70              :         dbt_pgrid_create, dbt_pgrid_destroy, dbt_pgrid_type, dbt_type
      71              :    USE hfx_types,                       ONLY: block_ind_type,&
      72              :                                               dealloc_containers,&
      73              :                                               hfx_compression_type
      74              :    USE input_constants,                 ONLY: gw_pade_approx,&
      75              :                                               gw_two_pole_model,&
      76              :                                               ri_rpa_g0w0_crossing_bisection,&
      77              :                                               ri_rpa_g0w0_crossing_newton,&
      78              :                                               ri_rpa_g0w0_crossing_z_shot,&
      79              :                                               soc_none
      80              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      81              :                                               section_vals_type
      82              :    USE kinds,                           ONLY: default_path_length,&
      83              :                                               dp
      84              :    USE kpoint_methods,                  ONLY: kpoint_density_matrices,&
      85              :                                               kpoint_density_transform,&
      86              :                                               kpoint_init_cell_index
      87              :    USE kpoint_types,                    ONLY: get_kpoint_info,&
      88              :                                               kpoint_create,&
      89              :                                               kpoint_release,&
      90              :                                               kpoint_sym_create,&
      91              :                                               kpoint_type
      92              :    USE machine,                         ONLY: m_walltime
      93              :    USE mathconstants,                   ONLY: fourpi,&
      94              :                                               gaussi,&
      95              :                                               pi,&
      96              :                                               twopi,&
      97              :                                               z_one,&
      98              :                                               z_zero
      99              :    USE message_passing,                 ONLY: mp_para_env_type
     100              :    USE mp2_types,                       ONLY: mp2_type,&
     101              :                                               one_dim_real_array,&
     102              :                                               two_dim_int_array
     103              :    USE parallel_gemm_api,               ONLY: parallel_gemm
     104              :    USE particle_list_types,             ONLY: particle_list_type
     105              :    USE particle_types,                  ONLY: particle_type
     106              :    USE physcon,                         ONLY: evolt
     107              :    USE pw_env_types,                    ONLY: pw_env_get,&
     108              :                                               pw_env_type
     109              :    USE pw_methods,                      ONLY: pw_axpy,&
     110              :                                               pw_copy,&
     111              :                                               pw_scale,&
     112              :                                               pw_zero
     113              :    USE pw_pool_types,                   ONLY: pw_pool_type
     114              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
     115              :                                               pw_r3d_rs_type
     116              :    USE qs_band_structure,               ONLY: calculate_kp_orbitals
     117              :    USE qs_collocate_density,            ONLY: calculate_rho_elec
     118              :    USE qs_environment_types,            ONLY: get_qs_env,&
     119              :                                               qs_env_release,&
     120              :                                               qs_environment_type
     121              :    USE qs_force_types,                  ONLY: qs_force_type
     122              :    USE qs_gamma2kp,                     ONLY: create_kp_from_gamma
     123              :    USE qs_integral_utils,               ONLY: basis_set_list_setup
     124              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
     125              :                                               qs_kind_type
     126              :    USE qs_ks_types,                     ONLY: qs_ks_env_type
     127              :    USE qs_mo_types,                     ONLY: get_mo_set
     128              :    USE qs_moments,                      ONLY: build_berry_moment_matrix
     129              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type,&
     130              :                                               release_neighbor_list_sets
     131              :    USE qs_neighbor_lists,               ONLY: setup_neighbor_list
     132              :    USE qs_overlap,                      ONLY: build_overlap_matrix_simple
     133              :    USE qs_scf_types,                    ONLY: qs_scf_env_type
     134              :    USE qs_subsys_types,                 ONLY: qs_subsys_get,&
     135              :                                               qs_subsys_type
     136              :    USE qs_tensors,                      ONLY: decompress_tensor
     137              :    USE qs_tensors_types,                ONLY: create_2c_tensor
     138              :    USE rpa_gw_ic,                       ONLY: apply_ic_corr
     139              :    USE rpa_gw_im_time_util,             ONLY: get_tensor_3c_overl_int_gw
     140              :    USE rpa_gw_kpoints_util,             ONLY: get_mat_cell_T_from_mat_gamma,&
     141              :                                               mat_kp_from_mat_gamma,&
     142              :                                               real_space_to_kpoint_transform_rpa
     143              :    USE rpa_im_time,                     ONLY: compute_gamma_propagator,&
     144              :                                               compute_periodic_dm,&
     145              :                                               create_propagator_matrix_set,&
     146              :                                               propagator_sector_occupied,&
     147              :                                               propagator_sector_virtual
     148              :    USE scf_control_types,               ONLY: scf_control_type
     149              :    USE util,                            ONLY: sort
     150              :    USE virial_types,                    ONLY: virial_type
     151              : #include "./base/base_uses.f90"
     152              : 
     153              :    IMPLICIT NONE
     154              : 
     155              :    PRIVATE
     156              : 
     157              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'rpa_gw'
     158              : 
     159              :    PUBLIC :: allocate_matrices_gw_im_time, allocate_matrices_gw, compute_GW_self_energy, compute_QP_energies, &
     160              :              deallocate_matrices_gw_im_time, deallocate_matrices_gw, compute_minus_vxc_kpoints, trafo_to_mo_and_kpoints, &
     161              :              get_fermi_level_offset, compute_W_cubic_GW, continuation_pade
     162              : 
     163              : CONTAINS
     164              : 
     165              : ! **************************************************************************************************
     166              : !> \brief ...
     167              : !> \param gw_corr_lev_occ ...
     168              : !> \param gw_corr_lev_virt ...
     169              : !> \param homo ...
     170              : !> \param nmo ...
     171              : !> \param num_integ_points ...
     172              : !> \param unit_nr ...
     173              : !> \param RI_blk_sizes ...
     174              : !> \param do_ic_model ...
     175              : !> \param para_env ...
     176              : !> \param fm_mat_W ...
     177              : !> \param fm_mat_Q ...
     178              : !> \param mo_coeff ...
     179              : !> \param t_3c_overl_int_ao_mo ...
     180              : !> \param t_3c_O_mo_compressed ...
     181              : !> \param t_3c_O_mo_ind ...
     182              : !> \param t_3c_overl_int_gw_RI ...
     183              : !> \param t_3c_overl_int_gw_AO ...
     184              : !> \param starts_array_mc ...
     185              : !> \param ends_array_mc ...
     186              : !> \param t_3c_overl_nnP_ic ...
     187              : !> \param t_3c_overl_nnP_ic_reflected ...
     188              : !> \param matrix_s ...
     189              : !> \param mat_W ...
     190              : !> \param t_3c_overl_int ...
     191              : !> \param t_3c_O_compressed ...
     192              : !> \param t_3c_O_ind ...
     193              : !> \param qs_env ...
     194              : ! **************************************************************************************************
     195           92 :    SUBROUTINE allocate_matrices_gw_im_time(gw_corr_lev_occ, gw_corr_lev_virt, homo, nmo, &
     196              :                                            num_integ_points, unit_nr, &
     197              :                                            RI_blk_sizes, do_ic_model, &
     198              :                                            para_env, fm_mat_W, fm_mat_Q, &
     199           46 :                                            mo_coeff, &
     200              :                                            t_3c_overl_int_ao_mo, t_3c_O_mo_compressed, t_3c_O_mo_ind, &
     201              :                                            t_3c_overl_int_gw_RI, t_3c_overl_int_gw_AO, &
     202           46 :                                            starts_array_mc, ends_array_mc, &
     203              :                                            t_3c_overl_nnP_ic, t_3c_overl_nnP_ic_reflected, &
     204           46 :                                            matrix_s, mat_W, t_3c_overl_int, &
     205           46 :                                            t_3c_O_compressed, t_3c_O_ind, &
     206              :                                            qs_env)
     207              : 
     208              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: gw_corr_lev_occ, gw_corr_lev_virt, homo
     209              :       INTEGER, INTENT(IN)                                :: nmo, num_integ_points, unit_nr
     210              :       INTEGER, DIMENSION(:), POINTER                     :: RI_blk_sizes
     211              :       LOGICAL, INTENT(IN)                                :: do_ic_model
     212              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     213              :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:), &
     214              :          INTENT(OUT)                                     :: fm_mat_W
     215              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_mat_Q
     216              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: mo_coeff
     217              :       TYPE(dbt_type)                                     :: t_3c_overl_int_ao_mo
     218              :       TYPE(hfx_compression_type), ALLOCATABLE, &
     219              :          DIMENSION(:)                                    :: t_3c_O_mo_compressed
     220              :       TYPE(two_dim_int_array), ALLOCATABLE, &
     221              :          DIMENSION(:), INTENT(OUT)                       :: t_3c_O_mo_ind
     222              :       TYPE(dbt_type), ALLOCATABLE, DIMENSION(:), &
     223              :          INTENT(INOUT)                                   :: t_3c_overl_int_gw_RI, &
     224              :                                                             t_3c_overl_int_gw_AO
     225              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: starts_array_mc, ends_array_mc
     226              :       TYPE(dbt_type), ALLOCATABLE, DIMENSION(:), &
     227              :          INTENT(INOUT)                                   :: t_3c_overl_nnP_ic, &
     228              :                                                             t_3c_overl_nnP_ic_reflected
     229              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
     230              :       TYPE(dbcsr_type), POINTER                          :: mat_W
     231              :       TYPE(dbt_type), DIMENSION(:, :)                    :: t_3c_overl_int
     232              :       TYPE(hfx_compression_type), DIMENSION(:, :, :)     :: t_3c_O_compressed
     233              :       TYPE(block_ind_type), DIMENSION(:, :, :)           :: t_3c_O_ind
     234              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     235              : 
     236              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'allocate_matrices_gw_im_time'
     237              : 
     238              :       INTEGER                                            :: handle, jquad, nspins
     239              :       LOGICAL                                            :: my_open_shell
     240          414 :       TYPE(dbt_type)                                     :: t_3c_overl_int_ao_mo_beta
     241              : 
     242           46 :       CALL timeset(routineN, handle)
     243              : 
     244           46 :       nspins = SIZE(homo)
     245           46 :       my_open_shell = (nspins == 2)
     246              : 
     247            0 :       ALLOCATE (t_3c_O_mo_ind(nspins), t_3c_overl_int_gw_AO(nspins), t_3c_overl_int_gw_RI(nspins), &
     248        99454 :                 t_3c_overl_nnP_ic(nspins), t_3c_overl_nnP_ic_reflected(nspins), t_3c_O_mo_compressed(nspins))
     249              :       CALL get_tensor_3c_overl_int_gw(t_3c_overl_int, &
     250              :                                       t_3c_O_compressed, t_3c_O_ind, &
     251              :                                       t_3c_overl_int_ao_mo, t_3c_O_mo_compressed(1), t_3c_O_mo_ind(1)%array, &
     252              :                                       t_3c_overl_int_gw_RI(1), t_3c_overl_int_gw_AO(1), &
     253              :                                       starts_array_mc, ends_array_mc, &
     254              :                                       mo_coeff(1), matrix_s, &
     255              :                                       gw_corr_lev_occ(1), gw_corr_lev_virt(1), homo(1), nmo, &
     256              :                                       para_env, &
     257              :                                       do_ic_model, &
     258              :                                       t_3c_overl_nnP_ic(1), t_3c_overl_nnP_ic_reflected(1), &
     259           46 :                                       qs_env, unit_nr, do_alpha=.TRUE.)
     260              : 
     261           46 :       IF (my_open_shell) THEN
     262              : 
     263              :          CALL get_tensor_3c_overl_int_gw(t_3c_overl_int, &
     264              :                                          t_3c_O_compressed, t_3c_O_ind, &
     265              :                                          t_3c_overl_int_ao_mo_beta, t_3c_O_mo_compressed(2), t_3c_O_mo_ind(2)%array, &
     266              :                                          t_3c_overl_int_gw_RI(2), t_3c_overl_int_gw_AO(2), &
     267              :                                          starts_array_mc, ends_array_mc, &
     268              :                                          mo_coeff(2), matrix_s, &
     269              :                                          gw_corr_lev_occ(2), gw_corr_lev_virt(2), homo(2), nmo, &
     270              :                                          para_env, &
     271              :                                          do_ic_model, &
     272              :                                          t_3c_overl_nnP_ic(2), t_3c_overl_nnP_ic_reflected(2), &
     273            8 :                                          qs_env, unit_nr, do_alpha=.FALSE.)
     274              : 
     275            8 :          IF (.NOT. qs_env%mp2_env%ri_g0w0%do_kpoints_Sigma) THEN
     276            6 :             CALL dbt_destroy(t_3c_overl_int_ao_mo_beta)
     277              :          END IF
     278              : 
     279              :       END IF
     280              : 
     281          728 :       ALLOCATE (fm_mat_W(num_integ_points))
     282              : 
     283          636 :       DO jquad = 1, num_integ_points
     284              : 
     285          636 :          CALL cp_fm_create(fm_mat_W(jquad), fm_mat_Q%matrix_struct, set_zero=.TRUE.)
     286              : 
     287              :       END DO
     288              : 
     289           46 :       NULLIFY (mat_W)
     290           46 :       CALL dbcsr_init_p(mat_W)
     291              :       CALL dbcsr_create(matrix=mat_W, &
     292              :                         template=matrix_s(1)%matrix, &
     293              :                         matrix_type=dbcsr_type_no_symmetry, &
     294              :                         row_blk_size=RI_blk_sizes, &
     295           46 :                         col_blk_size=RI_blk_sizes)
     296              : 
     297           46 :       CALL timestop(handle)
     298              : 
     299           92 :    END SUBROUTINE allocate_matrices_gw_im_time
     300              : 
     301              : ! **************************************************************************************************
     302              : !> \brief ...
     303              : !> \param vec_Sigma_c_gw ...
     304              : !> \param color_rpa_group ...
     305              : !> \param dimen_nm_gw ...
     306              : !> \param gw_corr_lev_occ ...
     307              : !> \param gw_corr_lev_virt ...
     308              : !> \param homo ...
     309              : !> \param nmo ...
     310              : !> \param num_integ_group ...
     311              : !> \param num_integ_points ...
     312              : !> \param unit_nr ...
     313              : !> \param gw_corr_lev_tot ...
     314              : !> \param num_fit_points ...
     315              : !> \param omega_max_fit ...
     316              : !> \param do_minimax_quad ...
     317              : !> \param do_periodic ...
     318              : !> \param do_ri_Sigma_x ...
     319              : !> \param my_do_gw ...
     320              : !> \param first_cycle_periodic_correction ...
     321              : !> \param a_scaling ...
     322              : !> \param Eigenval ...
     323              : !> \param tj ...
     324              : !> \param vec_omega_fit_gw ...
     325              : !> \param vec_Sigma_x_gw ...
     326              : !> \param delta_corr ...
     327              : !> \param Eigenval_last ...
     328              : !> \param Eigenval_scf ...
     329              : !> \param vec_W_gw ...
     330              : !> \param fm_mat_S_gw ...
     331              : !> \param fm_mat_S_gw_work ...
     332              : !> \param para_env ...
     333              : !> \param mp2_env ...
     334              : !> \param kpoints ...
     335              : !> \param nkp ...
     336              : !> \param nkp_self_energy ...
     337              : !> \param do_kpoints_cubic_RPA ...
     338              : !> \param do_kpoints_from_Gamma ...
     339              : ! **************************************************************************************************
     340          116 :    SUBROUTINE allocate_matrices_gw(vec_Sigma_c_gw, color_rpa_group, dimen_nm_gw, &
     341          116 :                                    gw_corr_lev_occ, gw_corr_lev_virt, homo, &
     342              :                                    nmo, num_integ_group, num_integ_points, unit_nr, &
     343              :                                    gw_corr_lev_tot, num_fit_points, omega_max_fit, &
     344              :                                    do_minimax_quad, do_periodic, do_ri_Sigma_x, my_do_gw, &
     345              :                                    first_cycle_periodic_correction, &
     346              :                                    a_scaling, Eigenval, tj, vec_omega_fit_gw, vec_Sigma_x_gw, &
     347              :                                    delta_corr, Eigenval_last, Eigenval_scf, vec_W_gw, &
     348          116 :                                    fm_mat_S_gw, fm_mat_S_gw_work, &
     349              :                                    para_env, mp2_env, kpoints, nkp, nkp_self_energy, &
     350              :                                    do_kpoints_cubic_RPA, do_kpoints_from_Gamma)
     351              : 
     352              :       COMPLEX(KIND=dp), ALLOCATABLE, &
     353              :          DIMENSION(:, :, :, :), INTENT(OUT)              :: vec_Sigma_c_gw
     354              :       INTEGER, INTENT(IN)                                :: color_rpa_group, dimen_nm_gw
     355              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: gw_corr_lev_occ, gw_corr_lev_virt, homo
     356              :       INTEGER, INTENT(IN)                                :: nmo, num_integ_group, num_integ_points, &
     357              :                                                             unit_nr
     358              :       INTEGER, INTENT(INOUT)                             :: gw_corr_lev_tot, num_fit_points
     359              :       REAL(KIND=dp)                                      :: omega_max_fit
     360              :       LOGICAL, INTENT(IN)                                :: do_minimax_quad, do_periodic, &
     361              :                                                             do_ri_Sigma_x, my_do_gw
     362              :       LOGICAL, INTENT(OUT) :: first_cycle_periodic_correction
     363              :       REAL(KIND=dp), INTENT(IN)                          :: a_scaling
     364              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
     365              :          INTENT(INOUT)                                   :: Eigenval
     366              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
     367              :          INTENT(IN)                                      :: tj
     368              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
     369              :          INTENT(OUT)                                     :: vec_omega_fit_gw
     370              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
     371              :          INTENT(OUT)                                     :: vec_Sigma_x_gw
     372              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
     373              :          INTENT(INOUT)                                   :: delta_corr
     374              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
     375              :          INTENT(OUT)                                     :: Eigenval_last, Eigenval_scf
     376              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :), &
     377              :          INTENT(OUT)                                     :: vec_W_gw
     378              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: fm_mat_S_gw
     379              :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:), &
     380              :          INTENT(INOUT)                                   :: fm_mat_S_gw_work
     381              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     382              :       TYPE(mp2_type)                                     :: mp2_env
     383              :       TYPE(kpoint_type), POINTER                         :: kpoints
     384              :       INTEGER, INTENT(OUT)                               :: nkp, nkp_self_energy
     385              :       LOGICAL, INTENT(IN)                                :: do_kpoints_cubic_RPA, &
     386              :                                                             do_kpoints_from_Gamma
     387              : 
     388              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'allocate_matrices_gw'
     389              : 
     390              :       INTEGER                                            :: handle, iquad, ispin, jquad, nspins
     391              :       LOGICAL                                            :: my_open_shell
     392              :       REAL(KIND=dp)                                      :: omega
     393          116 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: vec_omega_gw
     394              : 
     395          116 :       CALL timeset(routineN, handle)
     396              : 
     397          116 :       nspins = SIZE(Eigenval, 3)
     398          116 :       my_open_shell = (nspins == 2)
     399              : 
     400          116 :       gw_corr_lev_tot = gw_corr_lev_occ(1) + gw_corr_lev_virt(1)
     401              : 
     402              :       ! fill the omega_frequency vector
     403          348 :       ALLOCATE (vec_omega_gw(num_integ_points))
     404          116 :       vec_omega_gw = 0.0_dp
     405              : 
     406         4646 :       DO jquad = 1, num_integ_points
     407         4530 :          IF (do_minimax_quad) THEN
     408          590 :             omega = tj(jquad)
     409              :          ELSE
     410         3940 :             omega = a_scaling/TAN(tj(jquad))
     411              :          END IF
     412         4646 :          vec_omega_gw(jquad) = omega
     413              :       END DO
     414              : 
     415              :       ! determine number of fit points in the interval [0,w_max] for virt, or [-w_max,0] for occ
     416          116 :       num_fit_points = 0
     417              : 
     418         4646 :       DO jquad = 1, num_integ_points
     419         4646 :          IF (vec_omega_gw(jquad) < omega_max_fit) THEN
     420         3668 :             num_fit_points = num_fit_points + 1
     421              :          END IF
     422              :       END DO
     423              : 
     424          116 :       IF (mp2_env%ri_g0w0%analytic_continuation == gw_pade_approx) THEN
     425           80 :          IF (mp2_env%ri_g0w0%nparam_pade > num_fit_points) THEN
     426           32 :             IF (unit_nr > 0) WRITE (UNIT=unit_nr, FMT="(T3,A)") &
     427           16 :                "Pade approximation: more parameters than data points. Reset # of parameters."
     428           32 :             mp2_env%ri_g0w0%nparam_pade = num_fit_points
     429           32 :             IF (unit_nr > 0) WRITE (UNIT=unit_nr, FMT="(T3,A,T74,I7)") &
     430           16 :                "Number of pade parameters:", mp2_env%ri_g0w0%nparam_pade
     431              :          END IF
     432              :       END IF
     433              : 
     434              :       ! create new arrays containing omega values at which we calculate vec_Sigma_c_gw
     435          348 :       ALLOCATE (vec_omega_fit_gw(num_fit_points))
     436              : 
     437              :       ! fill the omega vector with frequencies, where we calculate the self-energy
     438          116 :       iquad = 0
     439         4646 :       DO jquad = 1, num_integ_points
     440         4646 :          IF (vec_omega_gw(jquad) < omega_max_fit) THEN
     441         3668 :             iquad = iquad + 1
     442         3668 :             vec_omega_fit_gw(iquad) = vec_omega_gw(jquad)
     443              :          END IF
     444              :       END DO
     445              : 
     446          116 :       DEALLOCATE (vec_omega_gw)
     447              : 
     448          116 :       IF (do_kpoints_cubic_RPA) THEN
     449            0 :          CALL get_kpoint_info(kpoints, nkp=nkp)
     450            0 :          IF (mp2_env%ri_g0w0%do_gamma_only_sigma) THEN
     451            0 :             nkp_self_energy = 1
     452              :          ELSE
     453            0 :             nkp_self_energy = nkp
     454              :          END IF
     455          116 :       ELSE IF (do_kpoints_from_Gamma) THEN
     456           16 :          CALL get_kpoint_info(kpoints, nkp=nkp)
     457           16 :          IF (mp2_env%ri_g0w0%do_kpoints_Sigma) THEN
     458           16 :             nkp_self_energy = mp2_env%ri_g0w0%nkp_self_energy
     459              :          ELSE
     460            0 :             nkp_self_energy = 1
     461              :          END IF
     462              :       ELSE
     463          100 :          nkp = 1
     464          100 :          nkp_self_energy = 1
     465              :       END IF
     466          696 :       ALLOCATE (vec_Sigma_c_gw(gw_corr_lev_tot, num_fit_points, nkp_self_energy, nspins))
     467          116 :       vec_Sigma_c_gw = z_zero
     468              : 
     469          580 :       ALLOCATE (Eigenval_scf(nmo, nkp_self_energy, nspins))
     470         6374 :       Eigenval_scf(:, :, :) = Eigenval(:, :, :)
     471              : 
     472          464 :       ALLOCATE (Eigenval_last(nmo, nkp_self_energy, nspins))
     473         6374 :       Eigenval_last(:, :, :) = Eigenval(:, :, :)
     474              : 
     475          116 :       IF (do_periodic) THEN
     476              : 
     477           18 :          ALLOCATE (delta_corr(1 + homo(1) - gw_corr_lev_occ(1):homo(1) + gw_corr_lev_virt(1)))
     478            6 :          delta_corr(:) = 0.0_dp
     479              : 
     480            6 :          first_cycle_periodic_correction = .TRUE.
     481              : 
     482              :       END IF
     483              : 
     484          464 :       ALLOCATE (vec_Sigma_x_gw(nmo, nkp_self_energy, nspins))
     485          116 :       vec_Sigma_x_gw = 0.0_dp
     486              : 
     487          116 :       IF (my_do_gw) THEN
     488              : 
     489              :          ! minimax grids not implemented for O(N^4) GW
     490           70 :          CPASSERT(.NOT. do_minimax_quad)
     491              : 
     492              :          ! create temporary matrix to store B*([1+Q(iw')]^-1-1), has the same size as B
     493          292 :          ALLOCATE (fm_mat_S_gw_work(nspins))
     494          152 :          DO ispin = 1, nspins
     495           82 :             CALL cp_fm_create(fm_mat_S_gw_work(ispin), fm_mat_S_gw(ispin)%matrix_struct)
     496          152 :             CALL cp_fm_set_all(matrix=fm_mat_S_gw_work(ispin), alpha=0.0_dp)
     497              :          END DO
     498              : 
     499          280 :          ALLOCATE (vec_W_gw(dimen_nm_gw, nspins))
     500           70 :          vec_W_gw = 0.0_dp
     501              : 
     502              :          ! in case we do RI for Sigma_x, we calculate Sigma_x right here
     503           70 :          IF (do_ri_Sigma_x) THEN
     504              : 
     505              :             CALL get_vec_sigma_x(vec_Sigma_x_gw(:, :, 1), nmo, fm_mat_S_gw(1), para_env, num_integ_group, color_rpa_group, &
     506           52 :                                  homo(1), gw_corr_lev_occ(1), mp2_env%ri_g0w0%vec_Sigma_x_minus_vxc_gw(:, 1, 1))
     507              : 
     508           52 :             IF (my_open_shell) THEN
     509              :                CALL get_vec_sigma_x(vec_Sigma_x_gw(:, :, 2), nmo, fm_mat_S_gw(2), para_env, num_integ_group, &
     510              :                                     color_rpa_group, homo(2), gw_corr_lev_occ(2), &
     511            8 :                                     mp2_env%ri_g0w0%vec_Sigma_x_minus_vxc_gw(:, 2, 1))
     512              :             END IF
     513              : 
     514              :          END IF
     515              : 
     516              :       END IF
     517              : 
     518          116 :       CALL timestop(handle)
     519              : 
     520          116 :    END SUBROUTINE allocate_matrices_gw
     521              : 
     522              : ! **************************************************************************************************
     523              : !> \brief ...
     524              : !> \param vec_Sigma_x_gw ...
     525              : !> \param nmo ...
     526              : !> \param fm_mat_S_gw ...
     527              : !> \param para_env ...
     528              : !> \param num_integ_group ...
     529              : !> \param color_rpa_group ...
     530              : !> \param homo ...
     531              : !> \param gw_corr_lev_occ ...
     532              : !> \param vec_Sigma_x_minus_vxc_gw11 ...
     533              : ! **************************************************************************************************
     534           60 :    SUBROUTINE get_vec_sigma_x(vec_Sigma_x_gw, nmo, fm_mat_S_gw, para_env, num_integ_group, color_rpa_group, homo, &
     535           60 :                               gw_corr_lev_occ, vec_Sigma_x_minus_vxc_gw11)
     536              : 
     537              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: vec_Sigma_x_gw
     538              :       INTEGER, INTENT(IN)                                :: nmo
     539              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_mat_S_gw
     540              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     541              :       INTEGER, INTENT(IN)                                :: num_integ_group, color_rpa_group, homo, &
     542              :                                                             gw_corr_lev_occ
     543              :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: vec_Sigma_x_minus_vxc_gw11
     544              : 
     545              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'get_vec_sigma_x'
     546              : 
     547              :       INTEGER                                            :: handle, iiB, m_global, n_global, &
     548              :                                                             ncol_local, nm_global, nrow_local
     549           60 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices
     550              : 
     551           60 :       CALL timeset(routineN, handle)
     552              : 
     553              :       CALL cp_fm_get_info(matrix=fm_mat_S_gw, &
     554              :                           nrow_local=nrow_local, &
     555              :                           ncol_local=ncol_local, &
     556           60 :                           col_indices=col_indices)
     557              : 
     558           60 :       CALL para_env%sync()
     559              : 
     560              :       ! loop over (nm) index
     561        48112 :       DO iiB = 1, ncol_local
     562              : 
     563              :          ! this is needed for correct values within parallelization
     564        48052 :          IF (MODULO(1, num_integ_group) /= color_rpa_group) CYCLE
     565              : 
     566        46442 :          nm_global = col_indices(iiB)
     567              : 
     568              :          ! transform the index nm to n and m, formulae copied from Mauro's code
     569        46442 :          n_global = MAX(1, nm_global - 1)/nmo + 1
     570        46442 :          m_global = nm_global - (n_global - 1)*nmo
     571        46442 :          n_global = n_global + homo - gw_corr_lev_occ
     572              : 
     573        46502 :          IF (m_global <= homo) THEN
     574              : 
     575              :             ! Sigma_x_n = -sum_m^occ sum_P (B_(nm)^P)^2
     576              :             vec_Sigma_x_gw(n_global, 1) = &
     577              :                vec_Sigma_x_gw(n_global, 1) - &
     578       423400 :                DOT_PRODUCT(fm_mat_S_gw%local_data(:, iiB), fm_mat_S_gw%local_data(:, iiB))
     579              : 
     580              :          END IF
     581              : 
     582              :       END DO
     583              : 
     584           60 :       CALL para_env%sync()
     585              : 
     586         3416 :       CALL para_env%sum(vec_Sigma_x_gw)
     587              : 
     588              :       vec_Sigma_x_minus_vxc_gw11(:) = &
     589              :          vec_Sigma_x_minus_vxc_gw11(:) + &
     590         1678 :          vec_Sigma_x_gw(:, 1)
     591              : 
     592           60 :       CALL timestop(handle)
     593              : 
     594           60 :    END SUBROUTINE get_vec_sigma_x
     595              : 
     596              : ! **************************************************************************************************
     597              : !> \brief ...
     598              : !> \param fm_mat_S_gw_work ...
     599              : !> \param vec_W_gw ...
     600              : !> \param vec_Sigma_c_gw ...
     601              : !> \param vec_omega_fit_gw ...
     602              : !> \param vec_Sigma_x_minus_vxc_gw ...
     603              : !> \param Eigenval_last ...
     604              : !> \param Eigenval_scf ...
     605              : !> \param do_periodic ...
     606              : !> \param matrix_berry_re_mo_mo ...
     607              : !> \param matrix_berry_im_mo_mo ...
     608              : !> \param kpoints ...
     609              : !> \param vec_Sigma_x_gw ...
     610              : !> \param my_do_gw ...
     611              : ! **************************************************************************************************
     612          116 :    SUBROUTINE deallocate_matrices_gw(fm_mat_S_gw_work, vec_W_gw, vec_Sigma_c_gw, vec_omega_fit_gw, &
     613              :                                      vec_Sigma_x_minus_vxc_gw, Eigenval_last, &
     614              :                                      Eigenval_scf, do_periodic, matrix_berry_re_mo_mo, matrix_berry_im_mo_mo, kpoints, &
     615              :                                      vec_Sigma_x_gw, my_do_gw)
     616              : 
     617              :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:), &
     618              :          INTENT(INOUT)                                   :: fm_mat_S_gw_work
     619              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :), &
     620              :          INTENT(INOUT)                                   :: vec_W_gw
     621              :       COMPLEX(KIND=dp), ALLOCATABLE, &
     622              :          DIMENSION(:, :, :, :), INTENT(INOUT)            :: vec_Sigma_c_gw
     623              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
     624              :          INTENT(INOUT)                                   :: vec_omega_fit_gw
     625              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
     626              :          INTENT(INOUT)                                   :: vec_Sigma_x_minus_vxc_gw, Eigenval_last, &
     627              :                                                             Eigenval_scf
     628              :       LOGICAL, INTENT(IN)                                :: do_periodic
     629              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_berry_re_mo_mo, &
     630              :                                                             matrix_berry_im_mo_mo
     631              :       TYPE(kpoint_type), POINTER                         :: kpoints
     632              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
     633              :          INTENT(INOUT)                                   :: vec_Sigma_x_gw
     634              :       LOGICAL, INTENT(IN)                                :: my_do_gw
     635              : 
     636              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'deallocate_matrices_gw'
     637              : 
     638              :       INTEGER                                            :: handle, nspins
     639              :       LOGICAL                                            :: my_open_shell
     640              : 
     641          116 :       CALL timeset(routineN, handle)
     642              : 
     643          116 :       nspins = SIZE(Eigenval_last, 3)
     644          116 :       my_open_shell = (nspins == 2)
     645              : 
     646          116 :       IF (my_do_gw) THEN
     647           70 :          CALL cp_fm_release(fm_mat_S_gw_work)
     648           70 :          DEALLOCATE (vec_Sigma_x_minus_vxc_gw)
     649           70 :          DEALLOCATE (vec_W_gw)
     650              :       END IF
     651              : 
     652          116 :       DEALLOCATE (vec_Sigma_c_gw)
     653          116 :       DEALLOCATE (vec_Sigma_x_gw)
     654          116 :       DEALLOCATE (vec_omega_fit_gw)
     655          116 :       DEALLOCATE (Eigenval_last)
     656          116 :       DEALLOCATE (Eigenval_scf)
     657              : 
     658          116 :       IF (do_periodic) THEN
     659            6 :          CALL dbcsr_deallocate_matrix_set(matrix_berry_re_mo_mo)
     660            6 :          CALL dbcsr_deallocate_matrix_set(matrix_berry_im_mo_mo)
     661            6 :          CALL kpoint_release(kpoints)
     662              :       END IF
     663              : 
     664          116 :       CALL timestop(handle)
     665              : 
     666          116 :    END SUBROUTINE deallocate_matrices_gw
     667              : 
     668              : ! **************************************************************************************************
     669              : !> \brief ...
     670              : !> \param weights_cos_tf_w_to_t ...
     671              : !> \param weights_sin_tf_t_to_w ...
     672              : !> \param do_ic_model ...
     673              : !> \param do_kpoints_cubic_RPA ...
     674              : !> \param fm_mat_W ...
     675              : !> \param t_3c_overl_int_ao_mo ...
     676              : !> \param t_3c_O_mo_compressed ...
     677              : !> \param t_3c_O_mo_ind ...
     678              : !> \param t_3c_overl_int_gw_RI ...
     679              : !> \param t_3c_overl_int_gw_AO ...
     680              : !> \param t_3c_overl_nnP_ic ...
     681              : !> \param t_3c_overl_nnP_ic_reflected ...
     682              : !> \param mat_W ...
     683              : !> \param qs_env ...
     684              : ! **************************************************************************************************
     685           46 :    SUBROUTINE deallocate_matrices_gw_im_time(weights_cos_tf_w_to_t, weights_sin_tf_t_to_w, do_ic_model, do_kpoints_cubic_RPA, &
     686              :                                              fm_mat_W, &
     687              :                                              t_3c_overl_int_ao_mo, t_3c_O_mo_compressed, t_3c_O_mo_ind, &
     688              :                                              t_3c_overl_int_gw_RI, t_3c_overl_int_gw_AO, &
     689              :                                              t_3c_overl_nnP_ic, t_3c_overl_nnP_ic_reflected, mat_W, &
     690              :                                              qs_env)
     691              : 
     692              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :), &
     693              :          INTENT(INOUT)                                   :: weights_cos_tf_w_to_t, &
     694              :                                                             weights_sin_tf_t_to_w
     695              :       LOGICAL, INTENT(IN)                                :: do_ic_model, do_kpoints_cubic_RPA
     696              :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:), &
     697              :          INTENT(INOUT)                                   :: fm_mat_W
     698              :       TYPE(dbt_type), INTENT(INOUT)                      :: t_3c_overl_int_ao_mo
     699              :       TYPE(hfx_compression_type), ALLOCATABLE, &
     700              :          DIMENSION(:)                                    :: t_3c_O_mo_compressed
     701              :       TYPE(two_dim_int_array), ALLOCATABLE, DIMENSION(:) :: t_3c_O_mo_ind
     702              :       TYPE(dbt_type), ALLOCATABLE, DIMENSION(:), &
     703              :          INTENT(INOUT)                                   :: t_3c_overl_int_gw_RI, &
     704              :                                                             t_3c_overl_int_gw_AO, &
     705              :                                                             t_3c_overl_nnP_ic, &
     706              :                                                             t_3c_overl_nnP_ic_reflected
     707              :       TYPE(dbcsr_type), POINTER                          :: mat_W
     708              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     709              : 
     710              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'deallocate_matrices_gw_im_time'
     711              : 
     712              :       INTEGER                                            :: handle, ispin, nspins, unused
     713              :       LOGICAL                                            :: my_open_shell
     714              : 
     715           46 :       CALL timeset(routineN, handle)
     716              : 
     717           46 :       nspins = SIZE(t_3c_overl_int_gw_RI)
     718           46 :       my_open_shell = (nspins == 2)
     719              : 
     720           46 :       IF (ALLOCATED(weights_cos_tf_w_to_t)) DEALLOCATE (weights_cos_tf_w_to_t)
     721           46 :       IF (ALLOCATED(weights_sin_tf_t_to_w)) DEALLOCATE (weights_sin_tf_t_to_w)
     722              : 
     723           46 :       IF (.NOT. do_kpoints_cubic_RPA) THEN
     724           46 :          CALL cp_fm_release(fm_mat_W)
     725           46 :          CALL dbcsr_release_P(mat_W)
     726              :       END IF
     727              : 
     728          100 :       DO ispin = 1, nspins
     729           54 :          CALL dbt_destroy(t_3c_overl_int_gw_RI(ispin))
     730          100 :          CALL dbt_destroy(t_3c_overl_int_gw_AO(ispin))
     731              :       END DO
     732          154 :       DEALLOCATE (t_3c_overl_int_gw_AO, t_3c_overl_int_gw_RI)
     733           46 :       IF (do_ic_model) THEN
     734            4 :          DO ispin = 1, nspins
     735            2 :             CALL dbt_destroy(t_3c_overl_nnP_ic(ispin))
     736            4 :             CALL dbt_destroy(t_3c_overl_nnP_ic_reflected(ispin))
     737              :          END DO
     738            6 :          DEALLOCATE (t_3c_overl_nnP_ic, t_3c_overl_nnP_ic_reflected)
     739              :       END IF
     740              : 
     741           46 :       IF (.NOT. qs_env%mp2_env%ri_g0w0%do_kpoints_Sigma) THEN
     742           66 :          DO ispin = 1, nspins
     743           36 :             DEALLOCATE (t_3c_O_mo_ind(ispin)%array)
     744           66 :             CALL dealloc_containers(t_3c_O_mo_compressed(ispin), unused)
     745              :          END DO
     746           66 :          DEALLOCATE (t_3c_O_mo_ind, t_3c_O_mo_compressed)
     747              : 
     748           30 :          CALL dbt_destroy(t_3c_overl_int_ao_mo)
     749              :       END IF
     750              : 
     751           46 :       IF (qs_env%mp2_env%ri_g0w0%do_kpoints_Sigma) THEN
     752           34 :          DO ispin = 1, nspins
     753           18 :             CALL dbcsr_release(qs_env%mp2_env%ri_g0w0%matrix_sigma_x_minus_vxc(ispin)%matrix)
     754           18 :             DEALLOCATE (qs_env%mp2_env%ri_g0w0%matrix_sigma_x_minus_vxc(ispin)%matrix)
     755              : 
     756           18 :             CALL dbcsr_release(qs_env%mp2_env%ri_g0w0%matrix_ks(ispin)%matrix)
     757           34 :             DEALLOCATE (qs_env%mp2_env%ri_g0w0%matrix_ks(ispin)%matrix)
     758              :          END DO
     759           16 :          DEALLOCATE (qs_env%mp2_env%ri_g0w0%matrix_sigma_x_minus_vxc)
     760           16 :          DEALLOCATE (qs_env%mp2_env%ri_g0w0%matrix_ks)
     761              :       END IF
     762              : 
     763           46 :       CALL timestop(handle)
     764              : 
     765           46 :    END SUBROUTINE deallocate_matrices_gw_im_time
     766              : 
     767              : ! **************************************************************************************************
     768              : !> \brief ...
     769              : !> \param vec_Sigma_c_gw ...
     770              : !> \param dimen_nm_gw ...
     771              : !> \param dimen_RI ...
     772              : !> \param gw_corr_lev_occ ...
     773              : !> \param gw_corr_lev_virt ...
     774              : !> \param homo ...
     775              : !> \param jquad ...
     776              : !> \param nmo ...
     777              : !> \param num_fit_points ...
     778              : !> \param do_im_time ...
     779              : !> \param do_periodic ...
     780              : !> \param first_cycle_periodic_correction ...
     781              : !> \param fermi_level_offset ...
     782              : !> \param omega ...
     783              : !> \param Eigenval ...
     784              : !> \param delta_corr ...
     785              : !> \param vec_omega_fit_gw ...
     786              : !> \param vec_W_gw ...
     787              : !> \param wj ...
     788              : !> \param fm_mat_Q ...
     789              : !> \param fm_mat_R_gw ...
     790              : !> \param fm_mat_S_gw ...
     791              : !> \param fm_mat_S_gw_work ...
     792              : !> \param mo_coeff ...
     793              : !> \param para_env ...
     794              : !> \param para_env_RPA ...
     795              : !> \param matrix_berry_im_mo_mo ...
     796              : !> \param matrix_berry_re_mo_mo ...
     797              : !> \param kpoints ...
     798              : !> \param qs_env ...
     799              : !> \param mp2_env ...
     800              : ! **************************************************************************************************
     801        53050 :    SUBROUTINE compute_GW_self_energy(vec_Sigma_c_gw, dimen_nm_gw, dimen_RI, gw_corr_lev_occ, &
     802        10610 :                                      gw_corr_lev_virt, homo, jquad, nmo, num_fit_points, &
     803              :                                      do_im_time, do_periodic, &
     804              :                                      first_cycle_periodic_correction, fermi_level_offset, &
     805        10610 :                                      omega, Eigenval, delta_corr, vec_omega_fit_gw, vec_W_gw, wj, &
     806        10610 :                                      fm_mat_Q, fm_mat_R_gw, fm_mat_S_gw, &
     807        10610 :                                      fm_mat_S_gw_work, mo_coeff, para_env, &
     808              :                                      para_env_RPA, matrix_berry_im_mo_mo, matrix_berry_re_mo_mo, &
     809              :                                      kpoints, qs_env, mp2_env)
     810              : 
     811              :       COMPLEX(KIND=dp), ALLOCATABLE, &
     812              :          DIMENSION(:, :, :, :), INTENT(INOUT)            :: vec_Sigma_c_gw
     813              :       INTEGER, INTENT(IN)                                :: dimen_nm_gw, dimen_RI
     814              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: gw_corr_lev_occ, gw_corr_lev_virt, homo
     815              :       INTEGER, INTENT(IN)                                :: jquad, nmo, num_fit_points
     816              :       LOGICAL, INTENT(IN)                                :: do_im_time, do_periodic
     817              :       LOGICAL, INTENT(INOUT) :: first_cycle_periodic_correction
     818              :       REAL(KIND=dp), INTENT(INOUT)                       :: fermi_level_offset, omega
     819              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: Eigenval
     820              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
     821              :          INTENT(INOUT)                                   :: delta_corr
     822              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
     823              :          INTENT(IN)                                      :: vec_omega_fit_gw
     824              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :), &
     825              :          INTENT(INOUT)                                   :: vec_W_gw
     826              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
     827              :          INTENT(IN)                                      :: wj
     828              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_mat_Q, fm_mat_R_gw
     829              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: fm_mat_S_gw, fm_mat_S_gw_work
     830              :       TYPE(cp_fm_type), INTENT(IN)                       :: mo_coeff
     831              :       TYPE(mp_para_env_type), POINTER                    :: para_env, para_env_RPA
     832              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_berry_im_mo_mo, &
     833              :                                                             matrix_berry_re_mo_mo
     834              :       TYPE(kpoint_type), POINTER                         :: kpoints
     835              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     836              :       TYPE(mp2_type)                                     :: mp2_env
     837              : 
     838              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_GW_self_energy'
     839              : 
     840              :       INTEGER                                            :: handle, i_global, iiB, ispin, j_global, &
     841              :                                                             jjB, ncol_local, nrow_local, nspins
     842        10610 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
     843              : 
     844        10610 :       CALL timeset(routineN, handle)
     845              : 
     846        10610 :       nspins = SIZE(fm_mat_S_gw)
     847              : 
     848              :       CALL cp_fm_get_info(matrix=fm_mat_Q, &
     849              :                           nrow_local=nrow_local, &
     850              :                           ncol_local=ncol_local, &
     851              :                           row_indices=row_indices, &
     852        10610 :                           col_indices=col_indices)
     853              : 
     854        10610 :       IF (.NOT. do_im_time) THEN
     855              :          ! calculate [1+Q(iw')]^-1
     856        10610 :          CALL cp_fm_cholesky_invert(fm_mat_Q)
     857              :          ! symmetrize the result, fm_mat_R_gw is only temporary work matrix
     858        10610 :          CALL cp_fm_uplo_to_full(fm_mat_Q, fm_mat_R_gw)
     859              : 
     860              :          ! periodic correction for GW (paper Phys. Rev. B 95, 235123 (2017))
     861        10610 :          IF (do_periodic) THEN
     862              :             CALL calc_periodic_correction(delta_corr, qs_env, para_env, para_env_RPA, &
     863              :                                           mp2_env%ri_g0w0%kp_grid, homo(1), nmo, gw_corr_lev_occ(1), &
     864              :                                           gw_corr_lev_virt(1), omega, mo_coeff, Eigenval(:, 1), &
     865              :                                           matrix_berry_re_mo_mo, matrix_berry_im_mo_mo, &
     866              :                                           first_cycle_periodic_correction, kpoints, &
     867              :                                           mp2_env%ri_g0w0%do_mo_coeff_gamma, &
     868              :                                           mp2_env%ri_g0w0%num_kp_grids, mp2_env%ri_g0w0%eps_kpoint, &
     869              :                                           mp2_env%ri_g0w0%do_extra_kpoints, &
     870          240 :                                           mp2_env%ri_g0w0%do_aux_bas_gw, mp2_env%ri_g0w0%frac_aux_mos)
     871              :          END IF
     872              : 
     873        10610 :          CALL para_env_RPA%sync()
     874              : 
     875              :          ! subtract 1 from the diagonal to get rid of exchange self-energy
     876              : !$OMP           PARALLEL DO DEFAULT(NONE) PRIVATE(jjB,iiB,i_global,j_global) &
     877        10610 : !$OMP                       SHARED(ncol_local,nrow_local,col_indices,row_indices,fm_mat_Q,dimen_RI)
     878              :          DO jjB = 1, ncol_local
     879              :             j_global = col_indices(jjB)
     880              :             DO iiB = 1, nrow_local
     881              :                i_global = row_indices(iiB)
     882              :                IF (j_global == i_global .AND. i_global <= dimen_RI) THEN
     883              :                   fm_mat_Q%local_data(iiB, jjB) = fm_mat_Q%local_data(iiB, jjB) - 1.0_dp
     884              :                END IF
     885              :             END DO
     886              :          END DO
     887              : 
     888        10610 :          CALL para_env_RPA%sync()
     889              : 
     890        21600 :          DO ispin = 1, nspins
     891              :             CALL compute_GW_self_energy_deep(vec_Sigma_c_gw(:, :, :, ispin), dimen_nm_gw, dimen_RI, &
     892              :                                              gw_corr_lev_occ(ispin), gw_corr_lev_virt(ispin), &
     893              :                                              homo(ispin), jquad, nmo, &
     894              :                                              num_fit_points, do_periodic, fermi_level_offset, omega, &
     895              :                                              Eigenval(:, ispin), delta_corr, &
     896              :                                              vec_omega_fit_gw, vec_W_gw(:, ispin), wj, fm_mat_Q, &
     897        21600 :                                              fm_mat_S_gw(ispin), fm_mat_S_gw_work(ispin))
     898              :          END DO
     899              : 
     900              :       END IF ! GW
     901              : 
     902        10610 :       CALL timestop(handle)
     903              : 
     904        10610 :    END SUBROUTINE compute_GW_self_energy
     905              : 
     906              : ! **************************************************************************************************
     907              : !> \brief ...
     908              : !> \param fermi_level_offset ...
     909              : !> \param fermi_level_offset_input ...
     910              : !> \param Eigenval ...
     911              : !> \param homo ...
     912              : ! **************************************************************************************************
     913        11428 :    SUBROUTINE get_fermi_level_offset(fermi_level_offset, fermi_level_offset_input, Eigenval, homo)
     914              : 
     915              :       REAL(KIND=dp), INTENT(INOUT)                       :: fermi_level_offset
     916              :       REAL(KIND=dp), INTENT(IN)                          :: fermi_level_offset_input
     917              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: Eigenval
     918              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: homo
     919              : 
     920              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'get_fermi_level_offset'
     921              : 
     922              :       INTEGER                                            :: handle, ispin, nspins
     923              : 
     924        11428 :       CALL timeset(routineN, handle)
     925              : 
     926        11428 :       nspins = SIZE(Eigenval, 2)
     927              : 
     928              :       ! Fermi level offset should have a maximum such that the Fermi level of occupied orbitals
     929              :       ! is always closer to occupied orbitals than to virtual orbitals and vice versa
     930              :       ! that means, the Fermi level offset is at most as big as half the bandgap
     931        11428 :       fermi_level_offset = fermi_level_offset_input
     932        23404 :       DO ispin = 1, nspins
     933        23404 :          fermi_level_offset = MIN(fermi_level_offset, (Eigenval(homo(ispin) + 1, ispin) - Eigenval(homo(ispin), ispin))*0.5_dp)
     934              :       END DO
     935              : 
     936        11428 :       CALL timestop(handle)
     937              : 
     938        11428 :    END SUBROUTINE get_fermi_level_offset
     939              : 
     940              : ! **************************************************************************************************
     941              : !> \brief ...
     942              : !> \param fm_mat_W ...
     943              : !> \param fm_mat_Q ...
     944              : !> \param fm_mat_work ...
     945              : !> \param dimen_RI ...
     946              : !> \param fm_mat_L ...
     947              : !> \param num_integ_points ...
     948              : !> \param tj ...
     949              : !> \param tau_tj ...
     950              : !> \param weights_cos_tf_w_to_t ...
     951              : !> \param jquad ...
     952              : !> \param omega ...
     953              : ! **************************************************************************************************
     954          722 :    SUBROUTINE compute_W_cubic_GW(fm_mat_W, fm_mat_Q, fm_mat_work, dimen_RI, fm_mat_L, num_integ_points, &
     955              :                                  tj, tau_tj, weights_cos_tf_w_to_t, jquad, omega)
     956              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: fm_mat_W
     957              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_mat_Q, fm_mat_work
     958              :       INTEGER, INTENT(IN)                                :: dimen_RI
     959              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN)      :: fm_mat_L
     960              :       INTEGER, INTENT(IN)                                :: num_integ_points
     961              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
     962              :          INTENT(IN)                                      :: tj, tau_tj
     963              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :), &
     964              :          INTENT(IN)                                      :: weights_cos_tf_w_to_t
     965              :       INTEGER, INTENT(IN)                                :: jquad
     966              :       REAL(KIND=dp), INTENT(INOUT)                       :: omega
     967              : 
     968              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_W_cubic_GW'
     969              : 
     970              :       INTEGER                                            :: handle, i_global, iiB, iquad, j_global, &
     971              :                                                             jjB, ncol_local, nrow_local
     972          722 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
     973              :       REAL(KIND=dp)                                      :: tau, weight
     974              : 
     975          722 :       CALL timeset(routineN, handle)
     976              : 
     977              :       CALL cp_fm_get_info(matrix=fm_mat_Q, &
     978              :                           nrow_local=nrow_local, &
     979              :                           ncol_local=ncol_local, &
     980              :                           row_indices=row_indices, &
     981          722 :                           col_indices=col_indices)
     982              :       ! calculate [1+Q(iw')]^-1
     983          722 :       CALL cp_fm_cholesky_invert(fm_mat_Q)
     984              : 
     985              :       ! symmetrize the result
     986          722 :       CALL cp_fm_uplo_to_full(fm_mat_Q, fm_mat_work)
     987              : 
     988              :       ! subtract 1 from the diagonal to get rid of exchange self-energy
     989              : !$OMP           PARALLEL DO DEFAULT(NONE) PRIVATE(jjB,iiB,i_global,j_global) &
     990          722 : !$OMP                       SHARED(ncol_local,nrow_local,col_indices,row_indices,fm_mat_Q,dimen_RI)
     991              :       DO jjB = 1, ncol_local
     992              :          j_global = col_indices(jjB)
     993              :          DO iiB = 1, nrow_local
     994              :             i_global = row_indices(iiB)
     995              :             IF (j_global == i_global .AND. i_global <= dimen_RI) THEN
     996              :                fm_mat_Q%local_data(iiB, jjB) = fm_mat_Q%local_data(iiB, jjB) - 1.0_dp
     997              :             END IF
     998              :          END DO
     999              :       END DO
    1000              : 
    1001              :       ! multiply with L from the left and the right to get the screened Coulomb interaction
    1002              :       CALL parallel_gemm('T', 'N', dimen_RI, dimen_RI, dimen_RI, 1.0_dp, fm_mat_L(1, 1), fm_mat_Q, &
    1003          722 :                          0.0_dp, fm_mat_work)
    1004              : 
    1005              :       CALL parallel_gemm('N', 'N', dimen_RI, dimen_RI, dimen_RI, 1.0_dp, fm_mat_work, fm_mat_L(1, 1), &
    1006          722 :                          0.0_dp, fm_mat_Q)
    1007              : 
    1008              :       ! Fourier transform from w to t
    1009        17528 :       DO iquad = 1, num_integ_points
    1010              : 
    1011        16806 :          omega = tj(jquad)
    1012        16806 :          tau = tau_tj(iquad)
    1013        16806 :          weight = weights_cos_tf_w_to_t(iquad, jquad)*COS(tau*omega)
    1014              : 
    1015        16806 :          IF (jquad == 1) THEN
    1016              : 
    1017          722 :             CALL cp_fm_set_all(matrix=fm_mat_W(iquad), alpha=0.0_dp)
    1018              : 
    1019              :          END IF
    1020              : 
    1021        17528 :          CALL cp_fm_scale_and_add(alpha=1.0_dp, matrix_a=fm_mat_W(iquad), beta=weight, matrix_b=fm_mat_Q)
    1022              : 
    1023              :       END DO
    1024              : 
    1025          722 :       CALL timestop(handle)
    1026          722 :    END SUBROUTINE compute_W_cubic_GW
    1027              : 
    1028              : ! **************************************************************************************************
    1029              : !> \brief ...
    1030              : !> \param vec_Sigma_c_gw ...
    1031              : !> \param dimen_nm_gw ...
    1032              : !> \param dimen_RI ...
    1033              : !> \param gw_corr_lev_occ ...
    1034              : !> \param gw_corr_lev_virt ...
    1035              : !> \param homo ...
    1036              : !> \param jquad ...
    1037              : !> \param nmo ...
    1038              : !> \param num_fit_points ...
    1039              : !> \param do_periodic ...
    1040              : !> \param fermi_level_offset ...
    1041              : !> \param omega ...
    1042              : !> \param Eigenval ...
    1043              : !> \param delta_corr ...
    1044              : !> \param vec_omega_fit_gw ...
    1045              : !> \param vec_W_gw ...
    1046              : !> \param wj ...
    1047              : !> \param fm_mat_Q ...
    1048              : !> \param fm_mat_S_gw ...
    1049              : !> \param fm_mat_S_gw_work ...
    1050              : ! **************************************************************************************************
    1051        54950 :    SUBROUTINE compute_GW_self_energy_deep(vec_Sigma_c_gw, dimen_nm_gw, dimen_RI, &
    1052              :                                           gw_corr_lev_occ, gw_corr_lev_virt, &
    1053              :                                           homo, jquad, nmo, num_fit_points, &
    1054        21980 :                                           do_periodic, fermi_level_offset, omega, Eigenval, &
    1055        16365 :                                           delta_corr, vec_omega_fit_gw, vec_W_gw, &
    1056        10990 :                                           wj, fm_mat_Q, fm_mat_S_gw, fm_mat_S_gw_work)
    1057              : 
    1058              :       COMPLEX(KIND=dp), DIMENSION(:, :, :), &
    1059              :          INTENT(INOUT)                                   :: vec_Sigma_c_gw
    1060              :       INTEGER, INTENT(IN)                                :: dimen_nm_gw, dimen_RI, gw_corr_lev_occ, &
    1061              :                                                             gw_corr_lev_virt, homo, jquad, nmo, &
    1062              :                                                             num_fit_points
    1063              :       LOGICAL, INTENT(IN)                                :: do_periodic
    1064              :       REAL(KIND=dp), INTENT(IN)                          :: fermi_level_offset
    1065              :       REAL(KIND=dp), INTENT(INOUT)                       :: omega
    1066              :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: Eigenval
    1067              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: delta_corr, vec_omega_fit_gw
    1068              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: vec_W_gw
    1069              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: wj
    1070              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_mat_Q, fm_mat_S_gw, fm_mat_S_gw_work
    1071              : 
    1072              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_GW_self_energy_deep'
    1073              : 
    1074              :       INTEGER                                            :: handle, iiB, iquad, m_global, n_global, &
    1075              :                                                             ncol_local, nm_global
    1076        10990 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
    1077              :       REAL(KIND=dp)                                      :: delta_corr_nn, e_fermi, omega_i, &
    1078              :                                                             sign_occ_virt
    1079              : 
    1080        10990 :       CALL timeset(routineN, handle)
    1081              : 
    1082              :       ! S_work_(nm)Q = B_(nm)P * ([1+Q]^-1-1)_PQ
    1083              :       CALL parallel_gemm(transa="N", transb="N", m=dimen_RI, n=dimen_nm_gw, k=dimen_RI, alpha=1.0_dp, &
    1084              :                          matrix_a=fm_mat_Q, matrix_b=fm_mat_S_gw, beta=0.0_dp, &
    1085        10990 :                          matrix_c=fm_mat_S_gw_work)
    1086              : 
    1087              :       CALL cp_fm_get_info(matrix=fm_mat_S_gw, &
    1088              :                           ncol_local=ncol_local, &
    1089              :                           row_indices=row_indices, &
    1090        10990 :                           col_indices=col_indices)
    1091              : 
    1092              :       ! vector W_(nm) = S_work_(nm)Q * [B_(nm)Q]^T
    1093              : 
    1094      5172490 :       vec_W_gw = 0.0_dp
    1095              : 
    1096      5172490 :       DO iiB = 1, ncol_local
    1097      5161500 :          nm_global = col_indices(iiB)
    1098              :          vec_W_gw(nm_global) = vec_W_gw(nm_global) + &
    1099    265547240 :                                DOT_PRODUCT(fm_mat_S_gw_work%local_data(:, iiB), fm_mat_S_gw%local_data(:, iiB))
    1100              : 
    1101              :          ! transform the index nm of vec_W_gw back to n and m, formulae copied from Mauro's code
    1102      5161500 :          n_global = MAX(1, nm_global - 1)/nmo + 1
    1103      5161500 :          m_global = nm_global - (n_global - 1)*nmo
    1104      5161500 :          n_global = n_global + homo - gw_corr_lev_occ
    1105              : 
    1106              :          ! compute self-energy for imaginary frequencies
    1107    357271990 :          DO iquad = 1, num_fit_points
    1108              : 
    1109              :             ! for occ orbitals, we compute the self-energy for negative frequencies
    1110    352099500 :             IF (n_global <= homo) THEN
    1111              :                sign_occ_virt = -1.0_dp
    1112              :             ELSE
    1113    270639100 :                sign_occ_virt = 1.0_dp
    1114              :             END IF
    1115              : 
    1116    352099500 :             omega_i = vec_omega_fit_gw(iquad)*sign_occ_virt
    1117              : 
    1118              :             ! set the Fermi energy for occ orbitals slightly above the HOMO and
    1119              :             ! for virt orbitals slightly below the LUMO
    1120    352099500 :             IF (n_global <= homo) THEN
    1121    428896840 :                e_fermi = MAXVAL(Eigenval(homo - gw_corr_lev_occ + 1:homo)) + fermi_level_offset
    1122              :             ELSE
    1123   5138691260 :                e_fermi = MINVAL(Eigenval(homo + 1:homo + gw_corr_lev_virt)) - fermi_level_offset
    1124              :             END IF
    1125              : 
    1126              :             ! add here the periodic correction
    1127    352099500 :             IF (do_periodic .AND. row_indices(1) == 1 .AND. n_global == m_global) THEN
    1128        57120 :                delta_corr_nn = delta_corr(n_global)
    1129              :             ELSE
    1130              :                delta_corr_nn = 0.0_dp
    1131              :             END IF
    1132              : 
    1133              :             ! update the self-energy (use that vec_W_gw(iw) is symmetric), divide the integration
    1134              :             ! weight by 2, because the integration is from -infty to +infty and not just 0 to +infty
    1135              :             ! as for RPA, also we need for virtual orbitals a complex conjugate
    1136              :             vec_Sigma_c_gw(n_global - homo + gw_corr_lev_occ, iquad, 1) = &
    1137              :                vec_Sigma_c_gw(n_global - homo + gw_corr_lev_occ, iquad, 1) - &
    1138              :                0.5_dp/pi*wj(jquad)/2.0_dp*(vec_W_gw(nm_global) + delta_corr_nn)* &
    1139              :                (1.0_dp/(gaussi*(omega + omega_i) + e_fermi - Eigenval(m_global)) + &
    1140    357261000 :                 1.0_dp/(gaussi*(-omega + omega_i) + e_fermi - Eigenval(m_global)))
    1141              :          END DO
    1142              : 
    1143              :       END DO
    1144              : 
    1145        10990 :       CALL timestop(handle)
    1146              : 
    1147        10990 :    END SUBROUTINE compute_GW_self_energy_deep
    1148              : 
    1149              : ! **************************************************************************************************
    1150              : !> \brief ...
    1151              : !> \param vec_Sigma_c_gw ...
    1152              : !> \param count_ev_sc_GW ...
    1153              : !> \param gw_corr_lev_occ ...
    1154              : !> \param gw_corr_lev_tot ...
    1155              : !> \param gw_corr_lev_virt ...
    1156              : !> \param homo ...
    1157              : !> \param nmo ...
    1158              : !> \param num_fit_points ...
    1159              : !> \param num_integ_points ...
    1160              : !> \param unit_nr ...
    1161              : !> \param do_apply_ic_corr_to_gw ...
    1162              : !> \param do_im_time ...
    1163              : !> \param do_periodic ...
    1164              : !> \param do_ri_Sigma_x ...
    1165              : !> \param first_cycle_periodic_correction ...
    1166              : !> \param e_fermi ...
    1167              : !> \param eps_filter ...
    1168              : !> \param fermi_level_offset ...
    1169              : !> \param delta_corr ...
    1170              : !> \param Eigenval ...
    1171              : !> \param Eigenval_last ...
    1172              : !> \param Eigenval_scf ...
    1173              : !> \param iter_sc_GW0 ...
    1174              : !> \param exit_ev_gw ...
    1175              : !> \param tau_tj ...
    1176              : !> \param tj ...
    1177              : !> \param vec_omega_fit_gw ...
    1178              : !> \param vec_Sigma_x_gw ...
    1179              : !> \param ic_corr_list ...
    1180              : !> \param weights_cos_tf_t_to_w ...
    1181              : !> \param weights_sin_tf_t_to_w ...
    1182              : !> \param cfm_mo_coeff ...
    1183              : !> \param mo_coeff ...
    1184              : !> \param fm_mat_W ...
    1185              : !> \param para_env ...
    1186              : !> \param para_env_RPA ...
    1187              : !> \param mat_dm ...
    1188              : !> \param mat_MinvVMinv ...
    1189              : !> \param t_3c_O ...
    1190              : !> \param t_3c_M ...
    1191              : !> \param t_3c_overl_int_ao_mo ...
    1192              : !> \param t_3c_O_compressed ...
    1193              : !> \param t_3c_O_mo_compressed ...
    1194              : !> \param t_3c_O_ind ...
    1195              : !> \param t_3c_O_mo_ind ...
    1196              : !> \param t_3c_overl_int_gw_RI ...
    1197              : !> \param t_3c_overl_int_gw_AO ...
    1198              : !> \param matrix_berry_im_mo_mo ...
    1199              : !> \param matrix_berry_re_mo_mo ...
    1200              : !> \param mat_W ...
    1201              : !> \param matrix_s ...
    1202              : !> \param kpoints ...
    1203              : !> \param mp2_env ...
    1204              : !> \param qs_env ...
    1205              : !> \param nkp_self_energy ...
    1206              : !> \param do_kpoints_cubic_RPA ...
    1207              : !> \param starts_array_mc ...
    1208              : !> \param ends_array_mc ...
    1209              : ! **************************************************************************************************
    1210         1220 :    SUBROUTINE compute_QP_energies(vec_Sigma_c_gw, count_ev_sc_GW, gw_corr_lev_occ, &
    1211          488 :                                   gw_corr_lev_tot, gw_corr_lev_virt, homo, &
    1212              :                                   nmo, num_fit_points, num_integ_points, &
    1213              :                                   unit_nr, do_apply_ic_corr_to_gw, do_im_time, &
    1214              :                                   do_periodic, do_ri_Sigma_x, &
    1215          244 :                                   first_cycle_periodic_correction, e_fermi, eps_filter, &
    1216          244 :                                   fermi_level_offset, delta_corr, Eigenval, &
    1217              :                                   Eigenval_last, Eigenval_scf, iter_sc_GW0, exit_ev_gw, tau_tj, tj, &
    1218              :                                   vec_omega_fit_gw, vec_Sigma_x_gw, ic_corr_list, &
    1219          244 :                                   weights_cos_tf_t_to_w, weights_sin_tf_t_to_w, cfm_mo_coeff, mo_coeff, fm_mat_W, &
    1220              :                                   para_env, para_env_RPA, mat_dm, mat_MinvVMinv, &
    1221              :                                   t_3c_O, t_3c_M, t_3c_overl_int_ao_mo, &
    1222          244 :                                   t_3c_O_compressed, t_3c_O_mo_compressed, &
    1223          244 :                                   t_3c_O_ind, t_3c_O_mo_ind, &
    1224          400 :                                   t_3c_overl_int_gw_RI, t_3c_overl_int_gw_AO, matrix_berry_im_mo_mo, &
    1225              :                                   matrix_berry_re_mo_mo, mat_W, matrix_s, &
    1226              :                                   kpoints, mp2_env, qs_env, nkp_self_energy, do_kpoints_cubic_RPA, &
    1227          246 :                                   starts_array_mc, ends_array_mc)
    1228              : 
    1229              :       COMPLEX(KIND=dp), DIMENSION(:, :, :, :), &
    1230              :          INTENT(OUT)                                     :: vec_Sigma_c_gw
    1231              :       INTEGER, INTENT(IN)                                :: count_ev_sc_GW
    1232              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: gw_corr_lev_occ
    1233              :       INTEGER, INTENT(IN)                                :: gw_corr_lev_tot
    1234              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: gw_corr_lev_virt, homo
    1235              :       INTEGER, INTENT(IN)                                :: nmo, num_fit_points, num_integ_points, &
    1236              :                                                             unit_nr
    1237              :       LOGICAL, INTENT(IN)                                :: do_apply_ic_corr_to_gw, do_im_time, &
    1238              :                                                             do_periodic, do_ri_Sigma_x
    1239              :       LOGICAL, INTENT(INOUT) :: first_cycle_periodic_correction
    1240              :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: e_fermi
    1241              :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter, fermi_level_offset
    1242              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
    1243              :          INTENT(INOUT)                                   :: delta_corr
    1244              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT)   :: Eigenval
    1245              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
    1246              :          INTENT(INOUT)                                   :: Eigenval_last, Eigenval_scf
    1247              :       INTEGER, INTENT(IN)                                :: iter_sc_GW0
    1248              :       LOGICAL, INTENT(INOUT)                             :: exit_ev_gw
    1249              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
    1250              :          INTENT(INOUT)                                   :: tau_tj, tj, vec_omega_fit_gw
    1251              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
    1252              :          INTENT(INOUT)                                   :: vec_Sigma_x_gw
    1253              :       TYPE(one_dim_real_array), DIMENSION(2), INTENT(IN) :: ic_corr_list
    1254              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :), &
    1255              :          INTENT(IN)                                      :: weights_cos_tf_t_to_w, &
    1256              :                                                             weights_sin_tf_t_to_w
    1257              :       TYPE(cp_cfm_type), DIMENSION(:), INTENT(IN)        :: cfm_mo_coeff
    1258              :       TYPE(cp_fm_type), INTENT(IN)                       :: mo_coeff
    1259              :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:), &
    1260              :          INTENT(IN)                                      :: fm_mat_W
    1261              :       TYPE(mp_para_env_type), POINTER                    :: para_env, para_env_RPA
    1262              :       TYPE(dbcsr_p_type), INTENT(IN)                     :: mat_dm, mat_MinvVMinv
    1263              :       TYPE(dbt_type), ALLOCATABLE, DIMENSION(:, :)       :: t_3c_O
    1264              :       TYPE(dbt_type)                                     :: t_3c_M, t_3c_overl_int_ao_mo
    1265              :       TYPE(hfx_compression_type), ALLOCATABLE, &
    1266              :          DIMENSION(:, :, :), INTENT(INOUT)               :: t_3c_O_compressed
    1267              :       TYPE(hfx_compression_type), DIMENSION(:)           :: t_3c_O_mo_compressed
    1268              :       TYPE(block_ind_type), ALLOCATABLE, &
    1269              :          DIMENSION(:, :, :), INTENT(INOUT)               :: t_3c_O_ind
    1270              :       TYPE(two_dim_int_array), DIMENSION(:)              :: t_3c_O_mo_ind
    1271              :       TYPE(dbt_type), DIMENSION(:)                       :: t_3c_overl_int_gw_RI, &
    1272              :                                                             t_3c_overl_int_gw_AO
    1273              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_berry_im_mo_mo, &
    1274              :                                                             matrix_berry_re_mo_mo
    1275              :       TYPE(dbcsr_type), POINTER                          :: mat_W
    1276              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
    1277              :       TYPE(kpoint_type), POINTER                         :: kpoints
    1278              :       TYPE(mp2_type)                                     :: mp2_env
    1279              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1280              :       INTEGER, INTENT(IN)                                :: nkp_self_energy
    1281              :       LOGICAL, INTENT(IN)                                :: do_kpoints_cubic_RPA
    1282              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: starts_array_mc, ends_array_mc
    1283              : 
    1284              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_QP_energies'
    1285              : 
    1286              :       INTEGER :: count_ev_sc_GW_print, count_sc_GW0, count_sc_GW0_print, crossing_search, handle, &
    1287              :          idos, ikp, ispin, iunit, n_level_gw, ndos, nspins, num_points_corr, num_poles
    1288              :       LOGICAL                                            :: do_kpoints_Sigma, my_open_shell
    1289              :       REAL(KIND=dp) :: dos_lower_bound, dos_precision, dos_upper_bound, E_CBM_GW, E_CBM_GW_beta, &
    1290              :          E_CBM_SCF, E_CBM_SCF_beta, E_VBM_GW, E_VBM_GW_beta, E_VBM_SCF, E_VBM_SCF_beta, stop_crit
    1291          244 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: vec_gw_dos
    1292          244 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: m_value, vec_gw_energ, z_value
    1293              :       TYPE(cp_logger_type), POINTER                      :: logger
    1294              :       TYPE(kpoint_type), POINTER                         :: kpoints_Sigma
    1295              : 
    1296          244 :       CALL timeset(routineN, handle)
    1297              : 
    1298          244 :       nspins = SIZE(homo)
    1299          244 :       my_open_shell = (nspins == 2)
    1300              : 
    1301          244 :       do_kpoints_Sigma = mp2_env%ri_g0w0%do_kpoints_Sigma
    1302              : 
    1303          312 :       DO count_sc_GW0 = 1, iter_sc_GW0
    1304              : 
    1305              :          ! postprocessing for cubic scaling GW calculation
    1306          258 :          IF (do_im_time .AND. .NOT. do_kpoints_cubic_RPA .AND. .NOT. do_kpoints_Sigma) THEN
    1307           56 :             num_points_corr = mp2_env%ri_g0w0%num_omega_points
    1308              : 
    1309          118 :             DO ispin = 1, nspins
    1310              :                CALL compute_self_energy_cubic_gw(num_integ_points, nmo, tau_tj, tj, &
    1311              :                                                  matrix_s, cfm_mo_coeff(ispin), Eigenval(:, 1, ispin), eps_filter, &
    1312              :                                                  e_fermi(ispin), fm_mat_W, &
    1313              :                                                  gw_corr_lev_tot, gw_corr_lev_occ(ispin), gw_corr_lev_virt(ispin), homo(ispin), &
    1314              :                                                  count_ev_sc_GW, count_sc_GW0, &
    1315              :                                                  t_3c_overl_int_ao_mo, t_3c_O_mo_compressed(ispin), &
    1316              :                                                  t_3c_O_mo_ind(ispin)%array, &
    1317              :                                                  t_3c_overl_int_gw_RI(ispin), t_3c_overl_int_gw_AO(ispin), &
    1318              :                                                  mat_W, mat_MinvVMinv, mat_dm, &
    1319              :                                                  weights_cos_tf_t_to_w, weights_sin_tf_t_to_w, vec_Sigma_c_gw(:, :, :, ispin), &
    1320              :                                                  do_periodic, num_points_corr, delta_corr, qs_env, para_env, para_env_RPA, &
    1321              :                                                  mp2_env, matrix_berry_re_mo_mo, matrix_berry_im_mo_mo, &
    1322              :                                                  first_cycle_periodic_correction, kpoints, num_fit_points, mo_coeff, &
    1323          118 :                                                  do_ri_Sigma_x, vec_Sigma_x_gw(:, :, ispin), unit_nr, ispin)
    1324              :             END DO
    1325              : 
    1326              :          END IF
    1327              : 
    1328          242 :          IF (do_kpoints_Sigma) THEN
    1329              :             CALL compute_self_energy_cubic_gw_kpoints(num_integ_points, tau_tj, tj, &
    1330              :                                                       matrix_s, Eigenval(:, :, :), e_fermi, fm_mat_W, &
    1331              :                                                       gw_corr_lev_tot, gw_corr_lev_occ, gw_corr_lev_virt, homo, &
    1332              :                                                       count_ev_sc_GW, count_sc_GW0, &
    1333              :                                                       t_3c_O, t_3c_M, t_3c_O_compressed, t_3c_O_ind, &
    1334              :                                                       mat_W, mat_MinvVMinv, &
    1335              :                                                       weights_cos_tf_t_to_w, weights_sin_tf_t_to_w, vec_Sigma_c_gw(:, :, :, :), &
    1336              :                                                       qs_env, para_env, &
    1337              :                                                       mp2_env, num_fit_points, mo_coeff, &
    1338              :                                                       do_ri_Sigma_x, vec_Sigma_x_gw(:, :, :), unit_nr, nspins, &
    1339           16 :                                                       starts_array_mc, ends_array_mc, eps_filter)
    1340              : 
    1341              :          END IF
    1342              : 
    1343          258 :          IF (do_periodic .AND. mp2_env%ri_g0w0%do_average_deg_levels) THEN
    1344              : 
    1345           20 :             DO ispin = 1, nspins
    1346              :                CALL average_degenerate_levels(vec_Sigma_c_gw(:, :, :, ispin), &
    1347              :                                               Eigenval(1 + homo(ispin) - gw_corr_lev_occ(ispin): &
    1348              :                                                        homo(ispin) + gw_corr_lev_virt(ispin), 1, ispin), &
    1349           20 :                                               mp2_env%ri_g0w0%eps_eigenval)
    1350              :             END DO
    1351              :          END IF
    1352              : 
    1353          258 :          IF (.NOT. do_im_time) THEN
    1354       351390 :             CALL para_env%sum(vec_Sigma_c_gw)
    1355              :          END IF
    1356              : 
    1357          258 :          CALL para_env%sync()
    1358              : 
    1359          258 :          stop_crit = 1.0e-7
    1360          258 :          num_poles = mp2_env%ri_g0w0%num_poles
    1361          258 :          crossing_search = mp2_env%ri_g0w0%crossing_search
    1362              : 
    1363              :          ! arrays storing the correlation self-energy, stat. error and z-shot value
    1364         1290 :          ALLOCATE (vec_gw_energ(gw_corr_lev_tot, nkp_self_energy, nspins))
    1365          258 :          vec_gw_energ = 0.0_dp
    1366         1032 :          ALLOCATE (z_value(gw_corr_lev_tot, nkp_self_energy, nspins))
    1367          258 :          z_value = 0.0_dp
    1368         1032 :          ALLOCATE (m_value(gw_corr_lev_tot, nkp_self_energy, nspins))
    1369          258 :          m_value = 0.0_dp
    1370          258 :          E_VBM_GW = -1.0E3
    1371          258 :          E_CBM_GW = 1.0E3
    1372          258 :          E_VBM_SCF = -1.0E3
    1373          258 :          E_CBM_SCF = 1.0E3
    1374          258 :          E_VBM_GW_beta = -1.0E3
    1375          258 :          E_CBM_GW_beta = 1.0E3
    1376          258 :          E_VBM_SCF_beta = -1.0E3
    1377          258 :          E_CBM_SCF_beta = 1.0E3
    1378              : 
    1379          258 :          ndos = 0
    1380          258 :          dos_precision = mp2_env%ri_g0w0%dos_prec
    1381          258 :          dos_upper_bound = mp2_env%ri_g0w0%dos_upper
    1382          258 :          dos_lower_bound = mp2_env%ri_g0w0%dos_lower
    1383              : 
    1384          258 :          IF (dos_lower_bound >= dos_upper_bound) THEN
    1385            0 :             CALL cp_abort(__LOCATION__, "Invalid settings for GW_DOS calculation!")
    1386              :          END IF
    1387              : 
    1388          258 :          IF (dos_precision /= 0) THEN
    1389            0 :             ndos = INT((dos_upper_bound - dos_lower_bound)/dos_precision)
    1390            0 :             ALLOCATE (vec_gw_dos(ndos))
    1391            0 :             vec_gw_dos = 0.0_dp
    1392              :          END IF
    1393              : 
    1394              :          ! for the normal code for molecules or Gamma only: nkp = 1
    1395          620 :          DO ikp = 1, nkp_self_energy
    1396              : 
    1397          362 :             kpoints_Sigma => qs_env%mp2_env%ri_rpa_im_time%kpoints_Sigma
    1398              : 
    1399              :             ! fit the self-energy on imaginary frequency axis and evaluate the fit on the MO energy of the SCF
    1400         4024 :             DO n_level_gw = 1, gw_corr_lev_tot
    1401              :                ! processes perform different fits
    1402         3662 :                IF (MODULO(n_level_gw, para_env%num_pe) /= para_env%mepos) CYCLE
    1403              : 
    1404         2273 :                SELECT CASE (mp2_env%ri_g0w0%analytic_continuation)
    1405              :                CASE (gw_two_pole_model)
    1406              :                   CALL fit_and_continuation_2pole(vec_gw_energ(:, ikp, 1), vec_omega_fit_gw, &
    1407              :                                                   z_value(:, ikp, 1), m_value(:, ikp, 1), vec_Sigma_c_gw(:, :, ikp, 1), &
    1408              :                                                   mp2_env%ri_g0w0%vec_Sigma_x_minus_vxc_gw(:, 1, ikp), &
    1409              :                                                   Eigenval(:, ikp, 1), Eigenval_scf(:, ikp, 1), n_level_gw, &
    1410              :                                                   gw_corr_lev_occ(1), gw_corr_lev_virt(1), num_poles, &
    1411              :                                                   num_fit_points, crossing_search, homo(1), stop_crit, &
    1412          442 :                                                   fermi_level_offset, do_im_time)
    1413              : 
    1414              :                CASE (gw_pade_approx)
    1415              :                   CALL continuation_pade(vec_gw_energ(:, ikp, 1), vec_omega_fit_gw, &
    1416              :                                          z_value(:, ikp, 1), m_value(:, ikp, 1), vec_Sigma_c_gw(:, :, ikp, 1), &
    1417              :                                          mp2_env%ri_g0w0%vec_Sigma_x_minus_vxc_gw(:, 1, ikp), &
    1418              :                                          Eigenval(:, ikp, 1), Eigenval_scf(:, ikp, 1), &
    1419              :                                          mp2_env%ri_g0w0%do_hedin_shift, n_level_gw, &
    1420              :                                          gw_corr_lev_occ(1), gw_corr_lev_virt(1), mp2_env%ri_g0w0%nparam_pade, &
    1421              :                                          num_fit_points, crossing_search, homo(1), fermi_level_offset, &
    1422              :                                          do_im_time, mp2_env%ri_g0w0%print_self_energy, count_ev_sc_GW, &
    1423              :                                          vec_gw_dos, dos_lower_bound, dos_precision, ndos, &
    1424              :                                          mp2_env%ri_g0w0%min_level_self_energy, &
    1425              :                                          mp2_env%ri_g0w0%max_level_self_energy, mp2_env%ri_g0w0%dos_eta, &
    1426         1389 :                                          mp2_env%ri_g0w0%dos_min, mp2_env%ri_g0w0%dos_max)
    1427              :                CASE DEFAULT
    1428         1831 :                   CPABORT("Only two-model and Pade approximation are implemented.")
    1429              :                END SELECT
    1430              : 
    1431         2193 :                IF (my_open_shell) THEN
    1432          414 :                   SELECT CASE (mp2_env%ri_g0w0%analytic_continuation)
    1433              :                   CASE (gw_two_pole_model)
    1434              :                      CALL fit_and_continuation_2pole( &
    1435              :                         vec_gw_energ(:, ikp, 2), vec_omega_fit_gw, &
    1436              :                         z_value(:, ikp, 2), m_value(:, ikp, 2), vec_Sigma_c_gw(:, :, ikp, 2), &
    1437              :                         mp2_env%ri_g0w0%vec_Sigma_x_minus_vxc_gw(:, 2, ikp), &
    1438              :                         Eigenval(:, ikp, 2), Eigenval_scf(:, ikp, 2), n_level_gw, &
    1439              :                         gw_corr_lev_occ(2), gw_corr_lev_virt(2), num_poles, &
    1440              :                         num_fit_points, crossing_search, homo(2), stop_crit, &
    1441          126 :                         fermi_level_offset, do_im_time)
    1442              :                   CASE (gw_pade_approx)
    1443              :                      CALL continuation_pade(vec_gw_energ(:, ikp, 2), vec_omega_fit_gw, &
    1444              :                                             z_value(:, ikp, 2), m_value(:, ikp, 2), vec_Sigma_c_gw(:, :, ikp, 2), &
    1445              :                                             mp2_env%ri_g0w0%vec_Sigma_x_minus_vxc_gw(:, 2, ikp), &
    1446              :                                             Eigenval(:, ikp, 2), Eigenval_scf(:, ikp, 2), &
    1447              :                                             mp2_env%ri_g0w0%do_hedin_shift, n_level_gw, &
    1448              :                                             gw_corr_lev_occ(2), gw_corr_lev_virt(2), mp2_env%ri_g0w0%nparam_pade, &
    1449              :                                             num_fit_points, crossing_search, homo(2), &
    1450              :                                             fermi_level_offset, do_im_time, &
    1451              :                                             mp2_env%ri_g0w0%print_self_energy, count_ev_sc_GW, &
    1452              :                                             vec_gw_dos, dos_lower_bound, dos_precision, ndos, &
    1453              :                                             mp2_env%ri_g0w0%min_level_self_energy, &
    1454              :                                             mp2_env%ri_g0w0%max_level_self_energy, mp2_env%ri_g0w0%dos_eta, &
    1455          162 :                                             mp2_env%ri_g0w0%dos_min, mp2_env%ri_g0w0%dos_max)
    1456              :                   CASE DEFAULT
    1457          288 :                      CPABORT("Only two-pole model and Pade approximation are implemented.")
    1458              :                   END SELECT
    1459              : 
    1460              :                END IF
    1461              : 
    1462              :             END DO ! n_level_gw
    1463              : 
    1464          362 :             CALL para_env%sum(vec_gw_energ)
    1465          362 :             CALL para_env%sum(z_value)
    1466          362 :             CALL para_env%sum(m_value)
    1467              : 
    1468          362 :             IF (dos_precision /= 0.0_dp) THEN
    1469            0 :                CALL para_env%sum(vec_gw_dos)
    1470              :             END IF
    1471              : 
    1472          362 :             CALL check_NaN(vec_gw_energ, 0.0_dp)
    1473          362 :             CALL check_NaN(z_value, 1.0_dp)
    1474          362 :             CALL check_NaN(m_value, 0.0_dp)
    1475              : 
    1476          362 :             IF (do_im_time .OR. mp2_env%ri_g0w0%iter_sc_GW0 == 1) THEN
    1477          288 :                count_ev_sc_GW_print = count_ev_sc_GW
    1478          288 :                count_sc_GW0_print = count_sc_GW0
    1479              :             ELSE
    1480           74 :                count_ev_sc_GW_print = count_sc_GW0
    1481           74 :                count_sc_GW0_print = count_ev_sc_GW
    1482              :             END IF
    1483              : 
    1484              :             ! print the quasiparticle energies and update Eigenval in case you do eigenvalue self-consistent GW
    1485          620 :             IF (my_open_shell) THEN
    1486              : 
    1487              :                CALL print_and_update_for_ev_sc( &
    1488              :                   vec_gw_energ(:, ikp, 1), &
    1489              :                   z_value(:, ikp, 1), m_value(:, ikp, 1), mp2_env%ri_g0w0%vec_Sigma_x_minus_vxc_gw(:, 1, ikp), &
    1490              :                   Eigenval(:, ikp, 1), Eigenval_last(:, ikp, 1), Eigenval_scf(:, ikp, 1), &
    1491              :                   gw_corr_lev_occ(1), gw_corr_lev_virt(1), gw_corr_lev_tot, &
    1492              :                   crossing_search, homo(1), unit_nr, count_ev_sc_GW_print, count_sc_GW0_print, &
    1493           42 :                   ikp, nkp_self_energy, kpoints_Sigma, 1, E_VBM_GW, E_CBM_GW, E_VBM_SCF, E_CBM_SCF)
    1494              : 
    1495              :                CALL print_and_update_for_ev_sc( &
    1496              :                   vec_gw_energ(:, ikp, 2), &
    1497              :                   z_value(:, ikp, 2), m_value(:, ikp, 2), mp2_env%ri_g0w0%vec_Sigma_x_minus_vxc_gw(:, 2, ikp), &
    1498              :                   Eigenval(:, ikp, 2), Eigenval_last(:, ikp, 2), Eigenval_scf(:, ikp, 2), &
    1499              :                   gw_corr_lev_occ(2), gw_corr_lev_virt(2), gw_corr_lev_tot, &
    1500              :                   crossing_search, homo(2), unit_nr, count_ev_sc_GW_print, count_sc_GW0_print, &
    1501           42 :                   ikp, nkp_self_energy, kpoints_Sigma, 2, E_VBM_GW_beta, E_CBM_GW_beta, E_VBM_SCF_beta, E_CBM_SCF_beta)
    1502              : 
    1503           42 :                IF (do_apply_ic_corr_to_gw .AND. count_ev_sc_GW == 1) THEN
    1504              : 
    1505              :                   CALL apply_ic_corr(Eigenval(:, ikp, 1), Eigenval_scf(:, ikp, 1), ic_corr_list(1)%array, &
    1506              :                                      gw_corr_lev_occ(1), gw_corr_lev_virt(1), gw_corr_lev_tot, &
    1507            0 :                                      homo(1), nmo, unit_nr, do_alpha=.TRUE.)
    1508              : 
    1509              :                   CALL apply_ic_corr(Eigenval(:, ikp, 2), Eigenval_scf(:, ikp, 2), ic_corr_list(2)%array, &
    1510              :                                      gw_corr_lev_occ(2), gw_corr_lev_virt(2), gw_corr_lev_tot, &
    1511            0 :                                      homo(2), nmo, unit_nr, do_beta=.TRUE.)
    1512              : 
    1513              :                END IF
    1514              : 
    1515              :             ELSE
    1516              : 
    1517              :                CALL print_and_update_for_ev_sc( &
    1518              :                   vec_gw_energ(:, ikp, 1), &
    1519              :                   z_value(:, ikp, 1), m_value(:, ikp, 1), mp2_env%ri_g0w0%vec_Sigma_x_minus_vxc_gw(:, 1, ikp), &
    1520              :                   Eigenval(:, ikp, 1), Eigenval_last(:, ikp, 1), Eigenval_scf(:, ikp, 1), &
    1521              :                   gw_corr_lev_occ(1), gw_corr_lev_virt(1), gw_corr_lev_tot, &
    1522              :                   crossing_search, homo(1), unit_nr, count_ev_sc_GW_print, count_sc_GW0_print, &
    1523          320 :                   ikp, nkp_self_energy, kpoints_Sigma, 0, E_VBM_GW, E_CBM_GW, E_VBM_SCF, E_CBM_SCF)
    1524              : 
    1525          320 :                IF (do_apply_ic_corr_to_gw .AND. count_ev_sc_GW == 1) THEN
    1526              : 
    1527              :                   CALL apply_ic_corr(Eigenval(:, ikp, 1), Eigenval_scf(:, ikp, 1), ic_corr_list(1)%array, &
    1528              :                                      gw_corr_lev_occ(1), gw_corr_lev_virt(1), gw_corr_lev_tot, &
    1529            0 :                                      homo(1), nmo, unit_nr)
    1530              : 
    1531              :                END IF
    1532              : 
    1533              :             END IF
    1534              : 
    1535              :          END DO ! ikp
    1536              : 
    1537          258 :          IF (nkp_self_energy > 1 .AND. unit_nr > 0) THEN
    1538              : 
    1539              :             CALL print_gaps(E_VBM_SCF, E_CBM_SCF, E_VBM_SCF_beta, E_CBM_SCF_beta, &
    1540            8 :                             E_VBM_GW, E_CBM_GW, E_VBM_GW_beta, E_CBM_GW_beta, my_open_shell, unit_nr)
    1541              : 
    1542              :          END IF
    1543              : 
    1544              :          ! Decide whether to add spin-orbit splitting of bands, spin-orbit coupling strength comes from
    1545              :          ! Hartwigsen parametrization (1999) of GTH pseudopotentials
    1546          258 :          IF (mp2_env%ri_g0w0%soc_type /= soc_none) THEN
    1547              :             CALL calculate_and_print_soc(qs_env, Eigenval_scf, Eigenval_scf, gw_corr_lev_occ, gw_corr_lev_virt, &
    1548            2 :                                          homo, unit_nr, do_soc_gw=.FALSE., do_soc_scf=.TRUE.)
    1549              :             CALL calculate_and_print_soc(qs_env, Eigenval, Eigenval_scf, gw_corr_lev_occ, gw_corr_lev_virt, &
    1550            2 :                                          homo, unit_nr, do_soc_gw=.TRUE., do_soc_scf=.FALSE.)
    1551              :          END IF
    1552              : 
    1553          258 :          logger => cp_get_default_logger()
    1554          258 :          IF (logger%para_env%is_source()) THEN
    1555          255 :             iunit = cp_logger_get_default_unit_nr()
    1556              :          ELSE
    1557            3 :             iunit = -1
    1558              :          END IF
    1559              : 
    1560          258 :          IF (dos_precision /= 0.0_dp) THEN
    1561            0 :             IF (iunit > 0) THEN
    1562            0 :                CALL open_file('spectral.dat', unit_number=iunit, file_status="UNKNOWN", file_action="WRITE")
    1563            0 :                DO idos = 1, ndos
    1564              :                   ! 1/pi
    1565              :                   ! [1/Hartree] -> [1/evolt]
    1566            0 :                   WRITE (iunit, '(E17.10, E17.10)') (dos_lower_bound + REAL(idos - 1, KIND=dp)*dos_precision)*evolt, &
    1567            0 :                      vec_gw_dos(idos)/evolt/pi
    1568              :                END DO
    1569            0 :                CALL close_file(iunit)
    1570              :             END IF
    1571            0 :             DEALLOCATE (vec_gw_dos)
    1572              :          END IF
    1573              : 
    1574          258 :          DEALLOCATE (z_value)
    1575          258 :          DEALLOCATE (m_value)
    1576          258 :          DEALLOCATE (vec_gw_energ)
    1577              : 
    1578          258 :          exit_ev_gw = .FALSE.
    1579              : 
    1580              :          ! if HOMO-LUMO gap differs by less than mp2_env%ri_g0w0%eps_sc_iter, exit ev sc GW loop
    1581          258 :          IF (ABS(Eigenval(homo(1), 1, 1) - Eigenval_last(homo(1), 1, 1) - &
    1582              :                  Eigenval(homo(1) + 1, 1, 1) + Eigenval_last(homo(1) + 1, 1, 1)) &
    1583              :              < mp2_env%ri_g0w0%eps_iter) THEN
    1584           22 :             IF (count_sc_GW0 == 1) exit_ev_gw = .TRUE.
    1585              :             EXIT
    1586              :          END IF
    1587              : 
    1588          500 :          DO ispin = 1, nspins
    1589              :             CALL shift_unshifted_levels(Eigenval(:, 1, ispin), Eigenval_last(:, 1, ispin), gw_corr_lev_occ(ispin), &
    1590          500 :                                         gw_corr_lev_virt(ispin), homo(ispin), nmo)
    1591              :          END DO
    1592              : 
    1593          236 :          IF (do_im_time .AND. do_kpoints_Sigma .AND. mp2_env%ri_g0w0%print_local_bandgap) THEN
    1594            2 :             CALL print_local_bandgap(qs_env, Eigenval, gw_corr_lev_occ(1), gw_corr_lev_virt(1), homo(1), "GW")
    1595            2 :             CALL print_local_bandgap(qs_env, Eigenval_scf, gw_corr_lev_occ(1), gw_corr_lev_virt(1), homo(1), "DFT")
    1596              :          END IF
    1597              : 
    1598              :          ! in case of N^4 scaling GW, the scGW0 cycle is the eigenvalue sc cycle
    1599          290 :          IF (.NOT. do_im_time) EXIT
    1600              : 
    1601              :       END DO ! scGW0
    1602              : 
    1603          244 :       CALL timestop(handle)
    1604              : 
    1605          244 :    END SUBROUTINE compute_QP_energies
    1606              : 
    1607              : ! **************************************************************************************************
    1608              : !> \brief ...
    1609              : !> \param qs_env ...
    1610              : !> \param Eigenval ...
    1611              : !> \param Eigenval_scf ...
    1612              : !> \param gw_corr_lev_occ ...
    1613              : !> \param gw_corr_lev_virt ...
    1614              : !> \param homo ...
    1615              : !> \param unit_nr ...
    1616              : !> \param do_soc_gw ...
    1617              : !> \param do_soc_scf ...
    1618              : ! **************************************************************************************************
    1619            4 :    SUBROUTINE calculate_and_print_soc(qs_env, Eigenval, Eigenval_scf, gw_corr_lev_occ, gw_corr_lev_virt, &
    1620            4 :                                       homo, unit_nr, do_soc_gw, do_soc_scf)
    1621              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1622              :       REAL(KIND=dp), DIMENSION(:, :, :)                  :: Eigenval, Eigenval_scf
    1623              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: gw_corr_lev_occ, gw_corr_lev_virt, homo
    1624              :       INTEGER                                            :: unit_nr
    1625              :       LOGICAL                                            :: do_soc_gw, do_soc_scf
    1626              : 
    1627              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_and_print_soc'
    1628              : 
    1629              :       INTEGER :: handle, i_dim, i_glob, i_row, ikp, j_col, j_glob, n_level_gw, nao, ncol_local, &
    1630              :          nder, nkind, nkp_self_energy, nrow_local, periodic(3), size_real_space
    1631            4 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: index0
    1632            4 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
    1633              :       LOGICAL                                            :: calculate_forces, use_virial
    1634              :       REAL(KIND=dp) :: avg_occ_QP_shift, avg_virt_QP_shift, E_CBM_GW_SOC, E_GAP_GW_SOC, E_HOMO, &
    1635              :          E_HOMO_GW_SOC, E_i, E_j, E_LUMO, E_LUMO_GW_SOC, E_VBM_GW_SOC, E_window, eps_ppnl
    1636            4 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigenvalues_without_soc_sorted
    1637            4 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues
    1638            4 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1639              :       TYPE(cell_type), POINTER                           :: cell
    1640              :       TYPE(cp_cfm_type)                                  :: cfm_mat_h_double, cfm_mat_h_ks, &
    1641              :                                                             cfm_mat_s_double, cfm_mat_work_double, &
    1642              :                                                             cfm_mo_coeff, cfm_mo_coeff_double
    1643              :       TYPE(cp_fm_type), POINTER                          :: imos, rmos
    1644            4 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s, matrix_s_desymm
    1645            4 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_VSOC_l_nosymm, mat_VSOC_lx_kp, &
    1646            4 :                                                             mat_VSOC_ly_kp, mat_VSOC_lz_kp, &
    1647            4 :                                                             matrix_dummy, matrix_l, &
    1648            4 :                                                             matrix_pot_dummy
    1649              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1650              :       TYPE(kpoint_type), POINTER                         :: kpoints_Sigma
    1651              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1652              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1653            4 :          POINTER                                         :: sab_orb, sap_ppnl
    1654            4 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1655            4 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
    1656            4 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1657              :       TYPE(scf_control_type), POINTER                    :: scf_control
    1658              :       TYPE(virial_type), POINTER                         :: virial
    1659              : 
    1660            4 :       CALL timeset(routineN, handle)
    1661              : 
    1662            4 :       CPASSERT(do_soc_gw .NEQV. do_soc_scf)
    1663              : 
    1664              :       CALL get_qs_env(qs_env=qs_env, &
    1665              :                       matrix_s=matrix_s, &
    1666              :                       para_env=para_env, &
    1667              :                       qs_kind_set=qs_kind_set, &
    1668              :                       sab_orb=sab_orb, &
    1669              :                       atomic_kind_set=atomic_kind_set, &
    1670              :                       particle_set=particle_set, &
    1671              :                       sap_ppnl=sap_ppnl, &
    1672              :                       dft_control=dft_control, &
    1673              :                       cell=cell, &
    1674              :                       nkind=nkind, &
    1675            4 :                       scf_control=scf_control)
    1676              : 
    1677            4 :       calculate_forces = .FALSE.
    1678            4 :       use_virial = .FALSE.
    1679            4 :       nder = 0
    1680            4 :       eps_ppnl = dft_control%qs_control%eps_ppnl
    1681              : 
    1682            4 :       CALL get_cell(cell=cell, periodic=periodic)
    1683              : 
    1684            4 :       size_real_space = 3**(periodic(1) + periodic(2) + periodic(3))
    1685              : 
    1686            4 :       NULLIFY (matrix_l)
    1687            4 :       CALL dbcsr_allocate_matrix_set(matrix_l, 3, 1)
    1688           16 :       DO i_dim = 1, 3
    1689           12 :          ALLOCATE (matrix_l(i_dim, 1)%matrix)
    1690              :          CALL dbcsr_create(matrix_l(i_dim, 1)%matrix, template=matrix_s(1)%matrix, &
    1691           12 :                            matrix_type=dbcsr_type_antisymmetric)
    1692           12 :          CALL cp_dbcsr_alloc_block_from_nbl(matrix_l(i_dim, 1)%matrix, sab_orb)
    1693           16 :          CALL dbcsr_set(matrix_l(i_dim, 1)%matrix, 0.0_dp)
    1694              :       END DO
    1695              : 
    1696            4 :       NULLIFY (matrix_pot_dummy)
    1697            4 :       CALL dbcsr_allocate_matrix_set(matrix_pot_dummy, 1, 1)
    1698            4 :       ALLOCATE (matrix_pot_dummy(1, 1)%matrix)
    1699            4 :       CALL dbcsr_create(matrix_pot_dummy(1, 1)%matrix, template=matrix_s(1)%matrix)
    1700            4 :       CALL cp_dbcsr_alloc_block_from_nbl(matrix_pot_dummy(1, 1)%matrix, sab_orb)
    1701            4 :       CALL dbcsr_set(matrix_pot_dummy(1, 1)%matrix, 0.0_dp)
    1702              : 
    1703              :       CALL build_core_ppnl(matrix_pot_dummy, matrix_dummy, force, virial, calculate_forces, use_virial, nder, &
    1704              :                            qs_kind_set, atomic_kind_set, particle_set, sab_orb, sap_ppnl, eps_ppnl, &
    1705            4 :                            nimages=1, basis_type="ORB", matrix_l=matrix_l)
    1706              : 
    1707            4 :       CALL alloc_mat_set_2d(mat_VSOC_l_nosymm, 3, size_real_space, matrix_s(1)%matrix, explicitly_no_symmetry=.TRUE.)
    1708           16 :       DO i_dim = 1, 3
    1709           16 :          CALL dbcsr_desymmetrize(matrix_l(i_dim, 1)%matrix, mat_VSOC_l_nosymm(i_dim, 1)%matrix)
    1710              :       END DO
    1711              : 
    1712            4 :       kpoints_Sigma => qs_env%mp2_env%ri_rpa_im_time%kpoints_Sigma
    1713              : 
    1714            4 :       CALL mat_kp_from_mat_gamma(qs_env, mat_VSOC_lx_kp, mat_VSOC_l_nosymm(1, 1)%matrix, kpoints_Sigma, 1, .FALSE.)
    1715            4 :       CALL mat_kp_from_mat_gamma(qs_env, mat_VSOC_ly_kp, mat_VSOC_l_nosymm(2, 1)%matrix, kpoints_Sigma, 1, .FALSE.)
    1716            4 :       CALL mat_kp_from_mat_gamma(qs_env, mat_VSOC_lz_kp, mat_VSOC_l_nosymm(3, 1)%matrix, kpoints_Sigma, 1, .FALSE.)
    1717              : 
    1718            4 :       nkp_self_energy = kpoints_Sigma%nkp
    1719              : 
    1720            4 :       CALL get_mo_set(kpoints_Sigma%kp_env(1)%kpoint_env%mos(1, 1), mo_coeff=rmos)
    1721              : 
    1722            4 :       CALL create_cfm_double_row_col_size(rmos, cfm_mat_h_double)
    1723            4 :       CALL create_cfm_double_row_col_size(rmos, cfm_mat_s_double)
    1724            4 :       CALL create_cfm_double_row_col_size(rmos, cfm_mo_coeff_double)
    1725            4 :       CALL create_cfm_double_row_col_size(rmos, cfm_mat_work_double)
    1726              : 
    1727            4 :       CALL cp_cfm_set_all(cfm_mo_coeff_double, z_zero)
    1728              : 
    1729            4 :       CALL cp_cfm_create(cfm_mo_coeff, rmos%matrix_struct)
    1730            4 :       CALL cp_cfm_create(cfm_mat_h_ks, rmos%matrix_struct)
    1731              : 
    1732            4 :       CALL cp_fm_get_info(matrix=rmos, nrow_global=nao)
    1733              : 
    1734            4 :       NULLIFY (matrix_s_desymm)
    1735            4 :       CALL dbcsr_allocate_matrix_set(matrix_s_desymm, 1)
    1736            4 :       ALLOCATE (matrix_s_desymm(1)%matrix)
    1737              :       CALL dbcsr_create(matrix=matrix_s_desymm(1)%matrix, template=matrix_s(1)%matrix, &
    1738            4 :                         matrix_type=dbcsr_type_no_symmetry)
    1739            4 :       CALL dbcsr_desymmetrize(matrix_s(1)%matrix, matrix_s_desymm(1)%matrix)
    1740              : 
    1741           12 :       ALLOCATE (eigenvalues(2*nao))
    1742           76 :       eigenvalues = 0.0_dp
    1743            8 :       ALLOCATE (eigenvalues_without_soc_sorted(2*nao))
    1744              : 
    1745            4 :       E_window = qs_env%mp2_env%ri_g0w0%soc_energy_window
    1746            4 :       IF (unit_nr > 0) THEN
    1747            2 :          WRITE (unit_nr, '(T3,A)') ' '
    1748            2 :          WRITE (unit_nr, '(T3,A)') '------------------------------------------------------------------------------'
    1749            2 :          WRITE (unit_nr, '(T3,A)') ' '
    1750            2 :          WRITE (unit_nr, '(T3,A,F42.1)') 'GW_SOC_INFO | SOC energy window (eV)', E_window*evolt
    1751              :       END IF
    1752              : 
    1753            4 :       E_VBM_GW_SOC = -1000.0_dp
    1754            4 :       E_CBM_GW_SOC = 1000.0_dp
    1755              : 
    1756           20 :       DO ikp = 1, nkp_self_energy
    1757              : 
    1758           16 :          CALL get_mo_set(kpoints_Sigma%kp_env(ikp)%kpoint_env%mos(1, 1), mo_coeff=rmos)
    1759           16 :          CALL get_mo_set(kpoints_Sigma%kp_env(ikp)%kpoint_env%mos(2, 1), mo_coeff=imos)
    1760           16 :          CALL cp_fm_to_cfm(rmos, imos, cfm_mo_coeff)
    1761              : 
    1762              :          ! ispin = 1
    1763              :          avg_occ_QP_shift = SUM(Eigenval(homo(1) - gw_corr_lev_occ(1) + 1:homo(1), ikp, 1) - &
    1764           32 :                                 Eigenval_scf(homo(1) - gw_corr_lev_occ(1) + 1:homo(1), ikp, 1))/gw_corr_lev_occ(1)
    1765              :          avg_virt_QP_shift = SUM(Eigenval(homo(1):homo(1) + gw_corr_lev_virt(1), ikp, 1) - &
    1766           48 :                                  Eigenval_scf(homo(1):homo(1) + gw_corr_lev_virt(1), ikp, 1))/gw_corr_lev_virt(1)
    1767              : 
    1768           16 :          IF (gw_corr_lev_occ(1) < homo(1)) THEN
    1769              :             Eigenval(1:homo(1) - gw_corr_lev_occ(1), ikp, 1) = Eigenval_scf(1:homo(1) - gw_corr_lev_occ(1), ikp, 1) &
    1770           64 :                                                                + avg_occ_QP_shift
    1771              :          END IF
    1772           16 :          IF (gw_corr_lev_virt(1) < nao - homo(1) + 1) THEN
    1773              :             Eigenval(homo(1) + gw_corr_lev_virt(1) + 1:nao, ikp, 1) = Eigenval_scf(homo(1) + gw_corr_lev_virt(1) + 1:nao, ikp, 1) &
    1774           80 :                                                                       + avg_virt_QP_shift
    1775              :          END IF
    1776              : 
    1777           16 :          CALL cp_cfm_set_all(cfm_mat_h_double, z_zero)
    1778           16 :          CALL add_dbcsr_submatrix(cfm_mat_h_double, mat_VSOC_lx_kp(ikp, 1:2), cfm_mat_h_ks, nao + 1, 1, z_one, .TRUE.)
    1779           16 :          CALL add_dbcsr_submatrix(cfm_mat_h_double, mat_VSOC_ly_kp(ikp, 1:2), cfm_mat_h_ks, nao + 1, 1, gaussi, .TRUE.)
    1780           16 :          CALL add_dbcsr_submatrix(cfm_mat_h_double, mat_VSOC_lz_kp(ikp, 1:2), cfm_mat_h_ks, 1, 1, z_one, .FALSE.)
    1781           16 :          CALL add_dbcsr_submatrix(cfm_mat_h_double, mat_VSOC_lz_kp(ikp, 1:2), cfm_mat_h_ks, nao + 1, nao + 1, -z_one, .FALSE.)
    1782              : 
    1783              :          ! trafo to MO basis
    1784         2896 :          cfm_mo_coeff_double%local_data = z_zero
    1785           16 :          CALL add_cfm_submatrix(cfm_mo_coeff_double, cfm_mo_coeff, 1, 1)
    1786           16 :          CALL add_cfm_submatrix(cfm_mo_coeff_double, cfm_mo_coeff, nao + 1, nao + 1)
    1787              : 
    1788              :          CALL cp_cfm_get_info(matrix=cfm_mat_h_double, &
    1789              :                               nrow_local=nrow_local, &
    1790              :                               ncol_local=ncol_local, &
    1791              :                               row_indices=row_indices, &
    1792           16 :                               col_indices=col_indices)
    1793              : 
    1794              :          CALL parallel_gemm(transa="N", transb="N", m=2*nao, n=2*nao, k=2*nao, alpha=z_one, &
    1795              :                             matrix_a=cfm_mat_h_double, matrix_b=cfm_mo_coeff_double, beta=z_zero, &
    1796           16 :                             matrix_c=cfm_mat_work_double)
    1797              : 
    1798              :          CALL parallel_gemm(transa="C", transb="N", m=2*nao, n=2*nao, k=2*nao, alpha=z_one, &
    1799              :                             matrix_a=cfm_mo_coeff_double, matrix_b=cfm_mat_work_double, beta=z_zero, &
    1800           16 :                             matrix_c=cfm_mat_h_double)
    1801              : 
    1802              :          CALL cp_cfm_get_info(matrix=cfm_mat_h_double, &
    1803              :                               nrow_local=nrow_local, &
    1804              :                               ncol_local=ncol_local, &
    1805              :                               row_indices=row_indices, &
    1806           16 :                               col_indices=col_indices)
    1807              : 
    1808           16 :          CALL cp_cfm_set_all(cfm_mat_s_double, z_zero)
    1809              : 
    1810           16 :          E_HOMO = Eigenval(homo(1), ikp, 1)
    1811           16 :          E_LUMO = Eigenval(homo(1) + 1, ikp, 1)
    1812              : 
    1813           16 :          CALL para_env%sync()
    1814              : 
    1815          160 :          DO i_row = 1, nrow_local
    1816         2752 :          DO j_col = 1, ncol_local
    1817         2592 :             i_glob = row_indices(i_row)
    1818         2592 :             j_glob = col_indices(j_col)
    1819         2592 :             IF (i_glob <= nao) THEN
    1820         1296 :                E_i = Eigenval(i_glob, ikp, 1)
    1821              :             ELSE
    1822         1296 :                E_i = Eigenval(i_glob - nao, ikp, 1)
    1823              :             END IF
    1824         2592 :             IF (j_glob <= nao) THEN
    1825         1296 :                E_j = Eigenval(j_glob, ikp, 1)
    1826              :             ELSE
    1827         1296 :                E_j = Eigenval(j_glob - nao, ikp, 1)
    1828              :             END IF
    1829              : 
    1830              :             ! add eigenvalues to diagonal entries
    1831         2736 :             IF (i_glob == j_glob) THEN
    1832          144 :                cfm_mat_h_double%local_data(i_row, j_col) = cfm_mat_h_double%local_data(i_row, j_col) + E_i*z_one
    1833          144 :                cfm_mat_s_double%local_data(i_row, j_col) = z_one
    1834              :             ELSE
    1835              :                IF (E_i < E_HOMO - 0.5_dp*E_window .OR. E_i > E_LUMO + 0.5_dp*E_window .OR. &
    1836         2448 :                    E_j < E_HOMO - 0.5_dp*E_window .OR. E_j > E_LUMO + 0.5_dp*E_window) THEN
    1837         2000 :                   cfm_mat_h_double%local_data(i_row, j_col) = z_zero
    1838              :                END IF
    1839              :             END IF
    1840              : 
    1841              :          END DO
    1842              :          END DO
    1843              : 
    1844           16 :          CALL para_env%sync()
    1845              : 
    1846          304 :          eigenvalues = 0.0_dp
    1847              :          CALL cp_cfm_geeig_canon(cfm_mat_h_double, cfm_mat_s_double, cfm_mo_coeff_double, eigenvalues, &
    1848           16 :                                  cfm_mat_work_double, scf_control%eps_eigval)
    1849              : 
    1850          160 :          eigenvalues_without_soc_sorted(1:nao) = Eigenval(:, ikp, 1)
    1851          160 :          eigenvalues_without_soc_sorted(nao + 1:2*nao) = Eigenval(:, ikp, 1)
    1852           48 :          ALLOCATE (index0(2*nao))
    1853           16 :          CALL sort(eigenvalues_without_soc_sorted, 2*nao, index0)
    1854           16 :          DEALLOCATE (index0)
    1855              : 
    1856           48 :          E_HOMO_GW_SOC = MAXVAL(eigenvalues(2*homo(1) - 2*gw_corr_lev_occ(1) + 1:2*homo(1)))
    1857           48 :          E_LUMO_GW_SOC = MINVAL(eigenvalues(2*homo(1) + 1:2*homo(1) + 2*gw_corr_lev_virt(1)))
    1858           16 :          E_GAP_GW_SOC = E_LUMO_GW_SOC - E_HOMO_GW_SOC
    1859              :          IF (E_HOMO_GW_SOC > E_VBM_GW_SOC) E_VBM_GW_SOC = E_HOMO_GW_SOC
    1860              :          IF (E_LUMO_GW_SOC < E_CBM_GW_SOC) E_CBM_GW_SOC = E_LUMO_GW_SOC
    1861              : 
    1862           52 :          IF (unit_nr > 0) THEN
    1863            8 :             WRITE (unit_nr, '(T3,A)') ' '
    1864            8 :             WRITE (unit_nr, '(T3,A7,I3,A3,I3,A8,3F7.3,A12,3F7.3)') 'Kpoint ', ikp, '  /', nkp_self_energy, &
    1865            8 :                '   xkp =', kpoints_Sigma%xkp(1, ikp), kpoints_Sigma%xkp(2, ikp), kpoints_Sigma%xkp(3, ikp), &
    1866           16 :                '  and  xkp =', -kpoints_Sigma%xkp(1, ikp), -kpoints_Sigma%xkp(2, ikp), -kpoints_Sigma%xkp(3, ikp)
    1867            8 :             WRITE (unit_nr, '(T3,A)') ' '
    1868            8 :             IF (do_soc_gw) THEN
    1869            4 :                WRITE (unit_nr, '(T3,A)') ' '
    1870            4 :                WRITE (unit_nr, '(T3,A,F13.4)') 'GW_SOC_INFO | Average GW shift of occupied levels compared to SCF', &
    1871            8 :                   avg_occ_QP_shift*evolt
    1872            4 :                WRITE (unit_nr, '(T3,A,F11.4)') 'GW_SOC_INFO | Average GW shift of unoccupied levels compared to SCF', &
    1873            8 :                   avg_virt_QP_shift*evolt
    1874            4 :                WRITE (unit_nr, '(T3,A)') ' '
    1875            4 :                WRITE (unit_nr, '(T3,2A)') 'Molecular orbital   E_GW with SOC (eV)   E_GW without SOC (eV)  SOC shift (eV)'
    1876              :             ELSE
    1877            4 :                WRITE (unit_nr, '(T3,2A)') 'Molecular orbital  E_SCF with SOC (eV)  E_SCF without SOC (eV)  SOC shift (eV)'
    1878              :             END IF
    1879              : 
    1880           24 :             DO n_level_gw = 2*(homo(1) - gw_corr_lev_occ(1)) + 1, 2*homo(1)
    1881           16 :                WRITE (unit_nr, '(T3,I4,A,3F21.4)') n_level_gw, ' ( occ )   ', eigenvalues(n_level_gw)*evolt, &
    1882           16 :                   eigenvalues_without_soc_sorted(n_level_gw)*evolt, &
    1883           40 :                   (eigenvalues(n_level_gw) - eigenvalues_without_soc_sorted(n_level_gw))*evolt
    1884              :             END DO
    1885           24 :             DO n_level_gw = 2*homo(1) + 1, 2*(homo(1) + gw_corr_lev_virt(1))
    1886           16 :                WRITE (unit_nr, '(T3,I4,A,3F21.4)') n_level_gw, ' ( vir )   ', eigenvalues(n_level_gw)*evolt, &
    1887           16 :                   eigenvalues_without_soc_sorted(n_level_gw)*evolt, &
    1888           40 :                   (eigenvalues(n_level_gw) - eigenvalues_without_soc_sorted(n_level_gw))*evolt
    1889              :             END DO
    1890            8 :             WRITE (unit_nr, '(T3,A)') ' '
    1891            8 :             IF (do_soc_gw) THEN
    1892            4 :                WRITE (unit_nr, '(T3,A,F38.4)') 'GW+SOC direct gap at current kpoint (eV)', E_GAP_GW_SOC*evolt
    1893              :             ELSE
    1894            4 :                WRITE (unit_nr, '(T3,A,F37.4)') 'SCF+SOC direct gap at current kpoint (eV)', E_GAP_GW_SOC*evolt
    1895              :             END IF
    1896            8 :             WRITE (unit_nr, '(T3,A)') ' '
    1897            8 :             WRITE (unit_nr, '(T3,A)') '------------------------------------------------------------------------------'
    1898              :          END IF
    1899              : 
    1900              :       END DO
    1901              : 
    1902            4 :       IF (unit_nr > 0) THEN
    1903            2 :          WRITE (unit_nr, '(T3,A)') ' '
    1904            2 :          IF (do_soc_gw) THEN
    1905            1 :             WRITE (unit_nr, '(T3,A,F46.4)') 'GW+SOC valence band maximum (eV)', E_VBM_GW_SOC*evolt
    1906            1 :             WRITE (unit_nr, '(T3,A,F43.4)') 'GW+SOC conduction band minimum (eV)', E_CBM_GW_SOC*evolt
    1907            1 :             WRITE (unit_nr, '(T3,A,F59.4)') 'GW+SOC bandgap (eV)', (E_CBM_GW_SOC - E_VBM_GW_SOC)*evolt
    1908              :          ELSE
    1909            1 :             WRITE (unit_nr, '(T3,A,F45.4)') 'SCF+SOC valence band maximum (eV)', E_VBM_GW_SOC*evolt
    1910            1 :             WRITE (unit_nr, '(T3,A,F42.4)') 'SCF+SOC conduction band minimum (eV)', E_CBM_GW_SOC*evolt
    1911            1 :             WRITE (unit_nr, '(T3,A,F58.4)') 'SCF+SOC bandgap (eV)', (E_CBM_GW_SOC - E_VBM_GW_SOC)*evolt
    1912              :          END IF
    1913              :       END IF
    1914              : 
    1915            4 :       CALL dbcsr_deallocate_matrix_set(matrix_l)
    1916            4 :       CALL dbcsr_deallocate_matrix_set(mat_VSOC_l_nosymm)
    1917            4 :       CALL dbcsr_deallocate_matrix_set(matrix_pot_dummy)
    1918            4 :       CALL dbcsr_deallocate_matrix_set(mat_VSOC_lx_kp)
    1919            4 :       CALL dbcsr_deallocate_matrix_set(mat_VSOC_ly_kp)
    1920            4 :       CALL dbcsr_deallocate_matrix_set(mat_VSOC_lz_kp)
    1921            4 :       CALL dbcsr_deallocate_matrix_set(matrix_s_desymm)
    1922              : 
    1923            4 :       CALL cp_cfm_release(cfm_mat_h_double)
    1924            4 :       CALL cp_cfm_release(cfm_mat_s_double)
    1925            4 :       CALL cp_cfm_release(cfm_mo_coeff_double)
    1926            4 :       CALL cp_cfm_release(cfm_mo_coeff)
    1927            4 :       CALL cp_cfm_release(cfm_mat_h_ks)
    1928            4 :       CALL cp_cfm_release(cfm_mat_work_double)
    1929            4 :       DEALLOCATE (eigenvalues)
    1930              : 
    1931            4 :       CALL timestop(handle)
    1932              : 
    1933           12 :    END SUBROUTINE calculate_and_print_soc
    1934              : 
    1935              : ! **************************************************************************************************
    1936              : !> \brief ...
    1937              : !> \param cfm_mat_target ...
    1938              : !> \param mat_source ...
    1939              : !> \param cfm_source_template ...
    1940              : !> \param nstart_row ...
    1941              : !> \param nstart_col ...
    1942              : !> \param factor ...
    1943              : !> \param add_also_herm_conj ...
    1944              : ! **************************************************************************************************
    1945           64 :    SUBROUTINE add_dbcsr_submatrix(cfm_mat_target, mat_source, cfm_source_template, &
    1946              :                                   nstart_row, nstart_col, factor, add_also_herm_conj)
    1947              :       TYPE(cp_cfm_type)                                  :: cfm_mat_target
    1948              :       TYPE(dbcsr_p_type), DIMENSION(:)                   :: mat_source
    1949              :       TYPE(cp_cfm_type)                                  :: cfm_source_template
    1950              :       INTEGER                                            :: nstart_row, nstart_col
    1951              :       COMPLEX(KIND=dp)                                   :: factor
    1952              :       LOGICAL                                            :: add_also_herm_conj
    1953              : 
    1954              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'add_dbcsr_submatrix'
    1955              : 
    1956              :       INTEGER                                            :: handle, nao
    1957              :       TYPE(cp_cfm_type)                                  :: cfm_mat_work_double, &
    1958              :                                                             cfm_mat_work_double_2
    1959              :       TYPE(cp_fm_type)                                   :: fm_mat_work_double_im, &
    1960              :                                                             fm_mat_work_double_re, fm_mat_work_im, &
    1961              :                                                             fm_mat_work_re
    1962              : 
    1963           64 :       CALL timeset(routineN, handle)
    1964              : 
    1965           64 :       CALL cp_fm_create(fm_mat_work_double_re, cfm_mat_target%matrix_struct)
    1966           64 :       CALL cp_fm_create(fm_mat_work_double_im, cfm_mat_target%matrix_struct)
    1967           64 :       CALL cp_fm_set_all(fm_mat_work_double_re, 0.0_dp)
    1968           64 :       CALL cp_fm_set_all(fm_mat_work_double_im, 0.0_dp)
    1969              : 
    1970           64 :       CALL cp_cfm_create(cfm_mat_work_double, cfm_mat_target%matrix_struct)
    1971           64 :       CALL cp_cfm_create(cfm_mat_work_double_2, cfm_mat_target%matrix_struct)
    1972           64 :       CALL cp_cfm_set_all(cfm_mat_work_double, z_zero)
    1973           64 :       CALL cp_cfm_set_all(cfm_mat_work_double_2, z_zero)
    1974              : 
    1975           64 :       CALL cp_fm_create(fm_mat_work_re, cfm_source_template%matrix_struct)
    1976           64 :       CALL cp_fm_create(fm_mat_work_im, cfm_source_template%matrix_struct)
    1977              : 
    1978           64 :       CALL copy_dbcsr_to_fm(mat_source(1)%matrix, fm_mat_work_re)
    1979           64 :       CALL copy_dbcsr_to_fm(mat_source(2)%matrix, fm_mat_work_im)
    1980              : 
    1981           64 :       CALL cp_cfm_get_info(cfm_source_template, nrow_global=nao)
    1982              : 
    1983              :       CALL cp_fm_to_fm_submat(msource=fm_mat_work_re, mtarget=fm_mat_work_double_re, &
    1984              :                               nrow=nao, ncol=nao, &
    1985              :                               s_firstrow=1, s_firstcol=1, &
    1986           64 :                               t_firstrow=nstart_row, t_firstcol=nstart_col)
    1987              : 
    1988              :       CALL cp_fm_to_fm_submat(msource=fm_mat_work_im, mtarget=fm_mat_work_double_im, &
    1989              :                               nrow=nao, ncol=nao, &
    1990              :                               s_firstrow=1, s_firstcol=1, &
    1991           64 :                               t_firstrow=nstart_row, t_firstcol=nstart_col)
    1992              : 
    1993           64 :       CALL cp_cfm_scale_and_add_fm(z_one, cfm_mat_work_double, z_one, fm_mat_work_double_re)
    1994           64 :       CALL cp_cfm_scale_and_add_fm(z_one, cfm_mat_work_double, gaussi, fm_mat_work_double_im)
    1995              : 
    1996           64 :       CALL cp_cfm_scale(factor, cfm_mat_work_double)
    1997              : 
    1998           64 :       CALL cp_cfm_scale_and_add(z_one, cfm_mat_target, z_one, cfm_mat_work_double)
    1999              : 
    2000           64 :       IF (add_also_herm_conj) THEN
    2001           32 :          CALL cp_cfm_transpose(cfm_mat_work_double, 'C', cfm_mat_work_double_2)
    2002           32 :          CALL cp_cfm_scale_and_add(z_one, cfm_mat_target, z_one, cfm_mat_work_double_2)
    2003              :       END IF
    2004              : 
    2005           64 :       CALL cp_fm_release(fm_mat_work_double_re)
    2006           64 :       CALL cp_fm_release(fm_mat_work_double_im)
    2007           64 :       CALL cp_cfm_release(cfm_mat_work_double)
    2008           64 :       CALL cp_cfm_release(cfm_mat_work_double_2)
    2009           64 :       CALL cp_fm_release(fm_mat_work_re)
    2010           64 :       CALL cp_fm_release(fm_mat_work_im)
    2011              : 
    2012           64 :       CALL timestop(handle)
    2013              : 
    2014           64 :    END SUBROUTINE add_dbcsr_submatrix
    2015              : 
    2016              : ! **************************************************************************************************
    2017              : !> \brief ...
    2018              : !> \param cfm_mat_target ...
    2019              : !> \param cfm_mat_source ...
    2020              : !> \param nstart_row ...
    2021              : !> \param nstart_col ...
    2022              : ! **************************************************************************************************
    2023          192 :    SUBROUTINE add_cfm_submatrix(cfm_mat_target, cfm_mat_source, nstart_row, nstart_col)
    2024              : 
    2025              :       TYPE(cp_cfm_type)                                  :: cfm_mat_target, cfm_mat_source
    2026              :       INTEGER                                            :: nstart_row, nstart_col
    2027              : 
    2028              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'add_cfm_submatrix'
    2029              : 
    2030              :       INTEGER                                            :: handle, nao
    2031              :       TYPE(cp_fm_type)                                   :: fm_mat_work_double_im, &
    2032              :                                                             fm_mat_work_double_re, fm_mat_work_im, &
    2033              :                                                             fm_mat_work_re
    2034              : 
    2035           32 :       CALL timeset(routineN, handle)
    2036              : 
    2037           32 :       CALL cp_fm_create(fm_mat_work_double_re, cfm_mat_target%matrix_struct)
    2038           32 :       CALL cp_fm_create(fm_mat_work_double_im, cfm_mat_target%matrix_struct)
    2039           32 :       CALL cp_fm_set_all(fm_mat_work_double_re, 0.0_dp)
    2040           32 :       CALL cp_fm_set_all(fm_mat_work_double_im, 0.0_dp)
    2041              : 
    2042           32 :       CALL cp_fm_create(fm_mat_work_re, cfm_mat_source%matrix_struct)
    2043           32 :       CALL cp_fm_create(fm_mat_work_im, cfm_mat_source%matrix_struct)
    2044           32 :       CALL cp_cfm_to_fm(cfm_mat_source, fm_mat_work_re, fm_mat_work_im)
    2045              : 
    2046           32 :       CALL cp_cfm_get_info(cfm_mat_source, nrow_global=nao)
    2047              : 
    2048              :       CALL cp_fm_to_fm_submat(msource=fm_mat_work_re, mtarget=fm_mat_work_double_re, &
    2049              :                               nrow=nao, ncol=nao, &
    2050              :                               s_firstrow=1, s_firstcol=1, &
    2051           32 :                               t_firstrow=nstart_row, t_firstcol=nstart_col)
    2052              : 
    2053              :       CALL cp_fm_to_fm_submat(msource=fm_mat_work_im, mtarget=fm_mat_work_double_im, &
    2054              :                               nrow=nao, ncol=nao, &
    2055              :                               s_firstrow=1, s_firstcol=1, &
    2056           32 :                               t_firstrow=nstart_row, t_firstcol=nstart_col)
    2057              : 
    2058           32 :       CALL cp_cfm_scale_and_add_fm(z_one, cfm_mat_target, z_one, fm_mat_work_double_re)
    2059           32 :       CALL cp_cfm_scale_and_add_fm(z_one, cfm_mat_target, gaussi, fm_mat_work_double_im)
    2060              : 
    2061           32 :       CALL cp_fm_release(fm_mat_work_double_re)
    2062           32 :       CALL cp_fm_release(fm_mat_work_double_im)
    2063           32 :       CALL cp_fm_release(fm_mat_work_re)
    2064           32 :       CALL cp_fm_release(fm_mat_work_im)
    2065              : 
    2066           32 :       CALL timestop(handle)
    2067              : 
    2068           32 :    END SUBROUTINE add_cfm_submatrix
    2069              : 
    2070              : ! **************************************************************************************************
    2071              : !> \brief ...
    2072              : !> \param fm_orig ...
    2073              : !> \param cfm_double ...
    2074              : ! **************************************************************************************************
    2075           48 :    SUBROUTINE create_cfm_double_row_col_size(fm_orig, cfm_double)
    2076              :       TYPE(cp_fm_type)                                   :: fm_orig
    2077              :       TYPE(cp_cfm_type)                                  :: cfm_double
    2078              : 
    2079              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'create_cfm_double_row_col_size'
    2080              : 
    2081              :       INTEGER                                            :: handle, ncol_global_orig, &
    2082              :                                                             nrow_global_orig
    2083              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_double
    2084              : 
    2085           16 :       CALL timeset(routineN, handle)
    2086              : 
    2087           16 :       CALL cp_fm_get_info(matrix=fm_orig, nrow_global=nrow_global_orig, ncol_global=ncol_global_orig)
    2088              : 
    2089              :       CALL cp_fm_struct_create(fm_struct_double, &
    2090              :                                nrow_global=2*nrow_global_orig, &
    2091              :                                ncol_global=2*ncol_global_orig, &
    2092           16 :                                template_fmstruct=fm_orig%matrix_struct)
    2093              : 
    2094           16 :       CALL cp_cfm_create(cfm_double, fm_struct_double)
    2095              : 
    2096           16 :       CALL cp_fm_struct_release(fm_struct_double)
    2097              : 
    2098           16 :       CALL timestop(handle)
    2099              : 
    2100           16 :    END SUBROUTINE create_cfm_double_row_col_size
    2101              : 
    2102              : ! **************************************************************************************************
    2103              : !> \brief ...
    2104              : !> \param E_VBM_SCF ...
    2105              : !> \param E_CBM_SCF ...
    2106              : !> \param E_VBM_SCF_beta ...
    2107              : !> \param E_CBM_SCF_beta ...
    2108              : !> \param E_VBM_GW ...
    2109              : !> \param E_CBM_GW ...
    2110              : !> \param E_VBM_GW_beta ...
    2111              : !> \param E_CBM_GW_beta ...
    2112              : !> \param my_open_shell ...
    2113              : !> \param unit_nr ...
    2114              : ! **************************************************************************************************
    2115            8 :    SUBROUTINE print_gaps(E_VBM_SCF, E_CBM_SCF, E_VBM_SCF_beta, E_CBM_SCF_beta, &
    2116              :                          E_VBM_GW, E_CBM_GW, E_VBM_GW_beta, E_CBM_GW_beta, my_open_shell, unit_nr)
    2117              : 
    2118              :       REAL(KIND=dp)                                      :: E_VBM_SCF, E_CBM_SCF, E_VBM_SCF_beta, &
    2119              :                                                             E_CBM_SCF_beta, E_VBM_GW, E_CBM_GW, &
    2120              :                                                             E_VBM_GW_beta, E_CBM_GW_beta
    2121              :       LOGICAL                                            :: my_open_shell
    2122              :       INTEGER                                            :: unit_nr
    2123              : 
    2124            8 :       IF (my_open_shell) THEN
    2125            1 :          WRITE (unit_nr, '(T3,A)') ' '
    2126            1 :          WRITE (unit_nr, '(T3,A,F43.4)') 'Alpha SCF valence band maximum (eV)', E_VBM_SCF*evolt
    2127            1 :          WRITE (unit_nr, '(T3,A,F40.4)') 'Alpha SCF conduction band minimum (eV)', E_CBM_SCF*evolt
    2128            1 :          WRITE (unit_nr, '(T3,A,F56.4)') 'Alpha SCF bandgap (eV)', (E_CBM_SCF - E_VBM_SCF)*evolt
    2129            1 :          WRITE (unit_nr, '(T3,A)') ' '
    2130            1 :          WRITE (unit_nr, '(T3,A,F44.4)') 'Beta SCF valence band maximum (eV)', E_VBM_SCF_beta*evolt
    2131            1 :          WRITE (unit_nr, '(T3,A,F41.4)') 'Beta SCF conduction band minimum (eV)', E_CBM_SCF_beta*evolt
    2132            1 :          WRITE (unit_nr, '(T3,A,F57.4)') 'Beta SCF bandgap (eV)', (E_CBM_SCF_beta - E_VBM_SCF_beta)*evolt
    2133            1 :          WRITE (unit_nr, '(T3,A)') ' '
    2134            1 :          WRITE (unit_nr, '(T3,A,F44.4)') 'Alpha GW valence band maximum (eV)', E_VBM_GW*evolt
    2135            1 :          WRITE (unit_nr, '(T3,A,F41.4)') 'Alpha GW conduction band minimum (eV)', E_CBM_GW*evolt
    2136            1 :          WRITE (unit_nr, '(T3,A,F57.4)') 'Alpha GW bandgap (eV)', (E_CBM_GW - E_VBM_GW)*evolt
    2137            1 :          WRITE (unit_nr, '(T3,A)') ' '
    2138            1 :          WRITE (unit_nr, '(T3,A,F45.4)') 'Beta GW valence band maximum (eV)', E_VBM_GW_beta*evolt
    2139            1 :          WRITE (unit_nr, '(T3,A,F42.4)') 'Beta GW conduction band minimum (eV)', E_CBM_GW_beta*evolt
    2140            1 :          WRITE (unit_nr, '(T3,A,F58.4)') 'Beta GW bandgap (eV)', (E_CBM_GW_beta - E_VBM_GW_beta)*evolt
    2141              :       ELSE
    2142            7 :          WRITE (unit_nr, '(T3,A)') ' '
    2143            7 :          WRITE (unit_nr, '(T3,A,F49.4)') 'SCF valence band maximum (eV)', E_VBM_SCF*evolt
    2144            7 :          WRITE (unit_nr, '(T3,A,F46.4)') 'SCF conduction band minimum (eV)', E_CBM_SCF*evolt
    2145            7 :          WRITE (unit_nr, '(T3,A,F62.4)') 'SCF bandgap (eV)', (E_CBM_SCF - E_VBM_SCF)*evolt
    2146            7 :          WRITE (unit_nr, '(T3,A)') ' '
    2147            7 :          WRITE (unit_nr, '(T3,A,F50.4)') 'GW valence band maximum (eV)', E_VBM_GW*evolt
    2148            7 :          WRITE (unit_nr, '(T3,A,F47.4)') 'GW conduction band minimum (eV)', E_CBM_GW*evolt
    2149            7 :          WRITE (unit_nr, '(T3,A,F63.4)') 'GW bandgap (eV)', (E_CBM_GW - E_VBM_GW)*evolt
    2150              :       END IF
    2151              : 
    2152            8 :    END SUBROUTINE print_gaps
    2153              : 
    2154              : ! **************************************************************************************************
    2155              : !> \brief ...
    2156              : !> \param array ...
    2157              : !> \param real_value ...
    2158              : ! **************************************************************************************************
    2159         1086 :    SUBROUTINE check_NaN(array, real_value)
    2160              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
    2161              :          INTENT(INOUT)                                   :: array
    2162              :       REAL(KIND=dp), INTENT(IN)                          :: real_value
    2163              : 
    2164              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'check_NaN'
    2165              : 
    2166              :       INTEGER                                            :: handle, i, j, k
    2167              : 
    2168         1086 :       CALL timeset(routineN, handle)
    2169              : 
    2170        12072 :       DO i = 1, SIZE(array, 1)
    2171        27906 :       DO j = 1, SIZE(array, 2)
    2172        45054 :       DO k = 1, SIZE(array, 3)
    2173              : 
    2174              :          ! check for NaN
    2175        34068 :          IF (array(i, j, k) /= array(i, j, k)) array(i, j, k) = real_value
    2176              : 
    2177              :       END DO
    2178              :       END DO
    2179              :       END DO
    2180              : 
    2181         1086 :       CALL timestop(handle)
    2182              : 
    2183         1086 :    END SUBROUTINE check_NaN
    2184              : 
    2185              : ! **************************************************************************************************
    2186              : !> \brief ...
    2187              : !> \param qs_env ...
    2188              : !> \param Eigenval ...
    2189              : !> \param gw_corr_lev_occ ...
    2190              : !> \param gw_corr_lev_virt ...
    2191              : !> \param homo ...
    2192              : !> \param dft_gw_char ...
    2193              : ! **************************************************************************************************
    2194            4 :    SUBROUTINE print_local_bandgap(qs_env, Eigenval, gw_corr_lev_occ, gw_corr_lev_virt, homo, dft_gw_char)
    2195              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2196              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: Eigenval
    2197              :       INTEGER                                            :: gw_corr_lev_occ, gw_corr_lev_virt, homo
    2198              :       CHARACTER(len=*)                                   :: dft_gw_char
    2199              : 
    2200              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'print_local_bandgap'
    2201              : 
    2202              :       INTEGER                                            :: handle, i_E
    2203              :       TYPE(pw_c1d_gs_type)                               :: rho_g_dummy
    2204              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    2205              :       TYPE(pw_r3d_rs_type)                               :: E_CBM_rspace, E_gap_rspace, E_VBM_rspace
    2206            4 :       TYPE(pw_r3d_rs_type), ALLOCATABLE, DIMENSION(:)    :: LDOS
    2207              : 
    2208            4 :       CALL timeset(routineN, handle)
    2209              : 
    2210            4 :       CALL create_real_space_grids(E_gap_rspace, E_VBM_rspace, E_CBM_rspace, rho_g_dummy, LDOS, auxbas_pw_pool, qs_env)
    2211              : 
    2212              :       CALL calculate_E_gap_rspace(E_gap_rspace, E_VBM_rspace, E_CBM_rspace, rho_g_dummy, &
    2213            4 :                                   LDOS, qs_env, Eigenval, gw_corr_lev_occ, gw_corr_lev_virt, homo, dft_gw_char)
    2214              : 
    2215            4 :       CALL auxbas_pw_pool%give_back_pw(E_gap_rspace)
    2216            4 :       CALL auxbas_pw_pool%give_back_pw(E_VBM_rspace)
    2217            4 :       CALL auxbas_pw_pool%give_back_pw(E_CBM_rspace)
    2218            4 :       CALL auxbas_pw_pool%give_back_pw(rho_g_dummy)
    2219           20 :       DO i_E = 1, SIZE(LDOS)
    2220           20 :          CALL auxbas_pw_pool%give_back_pw(LDOS(i_E))
    2221              :       END DO
    2222            4 :       DEALLOCATE (LDOS)
    2223              : 
    2224            4 :       CALL timestop(handle)
    2225              : 
    2226            4 :    END SUBROUTINE print_local_bandgap
    2227              : 
    2228              : ! **************************************************************************************************
    2229              : !> \brief ...
    2230              : !> \param E_gap_rspace ...
    2231              : !> \param E_VBM_rspace ...
    2232              : !> \param E_CBM_rspace ...
    2233              : !> \param rho_g_dummy ...
    2234              : !> \param LDOS ...
    2235              : !> \param qs_env ...
    2236              : !> \param Eigenval ...
    2237              : !> \param gw_corr_lev_occ ...
    2238              : !> \param gw_corr_lev_virt ...
    2239              : !> \param homo ...
    2240              : !> \param dft_gw_char ...
    2241              : ! **************************************************************************************************
    2242            4 :    SUBROUTINE calculate_E_gap_rspace(E_gap_rspace, E_VBM_rspace, E_CBM_rspace, rho_g_dummy, &
    2243            4 :                                      LDOS, qs_env, Eigenval, gw_corr_lev_occ, gw_corr_lev_virt, homo, dft_gw_char)
    2244              :       TYPE(pw_r3d_rs_type)                               :: E_gap_rspace, E_VBM_rspace, E_CBM_rspace
    2245              :       TYPE(pw_c1d_gs_type)                               :: rho_g_dummy
    2246              :       TYPE(pw_r3d_rs_type), ALLOCATABLE, DIMENSION(:)    :: LDOS
    2247              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2248              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: Eigenval
    2249              :       INTEGER                                            :: gw_corr_lev_occ, gw_corr_lev_virt, homo
    2250              :       CHARACTER(len=*)                                   :: dft_gw_char
    2251              : 
    2252              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_E_gap_rspace'
    2253              : 
    2254              :       INTEGER :: handle, i_E, i_img, i_spin, i_x, i_y, i_z, ikp, imo, n_E, n_E_occ, n_x_end, &
    2255              :          n_x_start, n_y_end, n_y_start, n_z_end, n_z_start, nimg, nkp, nkp_self_energy
    2256              :       REAL(KIND=dp)                                      :: avg_LDOS_occ, avg_LDOS_virt, d_E, E_CBM, &
    2257              :                                                             E_CBM_at_k, E_diff, E_VBM, E_VBM_at_k
    2258            4 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: E_array
    2259            4 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: occupation
    2260              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
    2261            4 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_work
    2262            4 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s, rho_ao
    2263            4 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rho_ao_weighted
    2264              :       TYPE(dft_control_type), POINTER                    :: dft_control
    2265              :       TYPE(kpoint_type), POINTER                         :: kpoints_Sigma
    2266              :       TYPE(mp2_type), POINTER                            :: mp2_env
    2267              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2268              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    2269            4 :          POINTER                                         :: sab_orb
    2270              :       TYPE(particle_list_type), POINTER                  :: particles
    2271              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
    2272              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    2273              :       TYPE(qs_subsys_type), POINTER                      :: subsys
    2274              :       TYPE(section_vals_type), POINTER                   :: gw_section
    2275              : 
    2276            4 :       CALL timeset(routineN, handle)
    2277              : 
    2278              :       CALL get_qs_env(qs_env=qs_env, para_env=para_env, mp2_env=mp2_env, ks_env=ks_env, matrix_s=matrix_s, &
    2279            4 :                       scf_env=scf_env, sab_orb=sab_orb, dft_control=dft_control, subsys=subsys)
    2280              : 
    2281              :       ! compute valence band maximum (VBM) and conduction band minimum (CBM)
    2282            4 :       nkp = SIZE(Eigenval, 2)
    2283            4 :       E_VBM = -1.0E3_dp
    2284            4 :       E_CBM = 1.0E3_dp
    2285              : 
    2286           36 :       DO ikp = 1, nkp
    2287              : 
    2288           64 :          E_VBM_at_k = MAXVAL(Eigenval(homo - gw_corr_lev_occ + 1:homo, ikp, 1))
    2289              :          IF (E_VBM_at_k > E_VBM) E_VBM = E_VBM_at_k
    2290              : 
    2291           64 :          E_CBM_at_k = MINVAL(Eigenval(homo + 1:homo + gw_corr_lev_virt, ikp, 1))
    2292            4 :          IF (E_CBM_at_k < E_CBM) E_CBM = E_CBM_at_k
    2293              : 
    2294              :       END DO
    2295              : 
    2296            4 :       d_E = mp2_env%ri_g0w0%energy_spacing_print_loc_bandgap
    2297              : 
    2298            4 :       n_E = INT(mp2_env%ri_g0w0%energy_window_print_loc_bandgap/d_E)
    2299              : 
    2300            4 :       n_E_occ = n_E/2
    2301           12 :       ALLOCATE (E_array(n_E))
    2302           12 :       DO i_E = 1, n_E_occ
    2303           12 :          E_array(i_E) = E_VBM - REAL(n_E_occ - i_E, KIND=dp)*d_E
    2304              :       END DO
    2305           12 :       DO i_E = n_E_occ + 1, n_E
    2306           12 :          E_array(i_E) = E_CBM + REAL(i_E - n_E_occ - 1, KIND=dp)*d_E
    2307              :       END DO
    2308              : 
    2309            4 :       kpoints_Sigma => qs_env%mp2_env%ri_rpa_im_time%kpoints_Sigma
    2310              : 
    2311            4 :       nkp_self_energy = kpoints_Sigma%nkp
    2312            4 :       CPASSERT(nkp == nkp_self_energy)
    2313              : 
    2314            4 :       kpoints_Sigma%sab_nl => sab_orb
    2315              : 
    2316            4 :       DEALLOCATE (kpoints_Sigma%cell_to_index)
    2317              :       NULLIFY (kpoints_Sigma%cell_to_index)
    2318            4 :       CALL kpoint_init_cell_index(kpoints_Sigma, sab_orb, para_env, dft_control%nimages)
    2319              : 
    2320          424 :       nimg = MAXVAL(kpoints_Sigma%cell_to_index)
    2321              : 
    2322            4 :       NULLIFY (rho_ao_weighted)
    2323            4 :       CALL dbcsr_allocate_matrix_set(rho_ao_weighted, 2, nimg)
    2324              : 
    2325           12 :       DO i_spin = 1, 2
    2326          236 :          DO i_img = 1, nimg
    2327          224 :             ALLOCATE (rho_ao_weighted(i_spin, i_img)%matrix)
    2328          224 :             CALL dbcsr_create(matrix=rho_ao_weighted(i_spin, i_img)%matrix, template=matrix_s(1)%matrix)
    2329          224 :             CALL cp_dbcsr_alloc_block_from_nbl(rho_ao_weighted(i_spin, i_img)%matrix, sab_orb)
    2330          232 :             CALL dbcsr_set(rho_ao_weighted(i_spin, i_img)%matrix, 0.0_dp)
    2331              :          END DO
    2332              :       END DO
    2333              : 
    2334          124 :       ALLOCATE (fm_work(nimg))
    2335            4 :       matrix_struct => kpoints_Sigma%kp_env(1)%kpoint_env%mos(1, 1)%mo_coeff%matrix_struct
    2336          116 :       DO i_img = 1, nimg
    2337          116 :          CALL cp_fm_create(fm_work(i_img), matrix_struct)
    2338              :       END DO
    2339              : 
    2340           20 :       DO i_E = 1, n_E
    2341              : 
    2342              :          ! occupation = weight factor for computing LDOS
    2343          144 :          DO ikp = 1, nkp
    2344              :             CALL get_mo_set(kpoints_Sigma%kp_env(ikp)%kpoint_env%mos(1, 1), &
    2345          128 :                             occupation_numbers=occupation)
    2346              : 
    2347         3072 :             occupation(:) = 0.0_dp
    2348          400 :             DO imo = homo - gw_corr_lev_occ + 1, homo + gw_corr_lev_virt
    2349          256 :                E_diff = E_array(i_E) - Eigenval(imo, ikp, 1)
    2350          384 :                occupation(imo) = EXP(-(E_diff/d_E)**2)
    2351              :             END DO
    2352              : 
    2353              :          END DO
    2354              : 
    2355              :          CALL get_mo_set(kpoints_Sigma%kp_env(1)%kpoint_env%mos(1, 1), &
    2356           16 :                          occupation_numbers=occupation)
    2357              : 
    2358              :          ! density matrices
    2359           16 :          CALL kpoint_density_matrices(kpoints_Sigma)
    2360              : 
    2361              :          ! density matrices in real space
    2362              :          CALL kpoint_density_transform(kpoints_Sigma, rho_ao_weighted, .FALSE., &
    2363           16 :                                        matrix_s(1)%matrix, sab_orb, fm_work)
    2364              : 
    2365           16 :          rho_ao => rho_ao_weighted(1, :)
    2366              : 
    2367              :          CALL calculate_rho_elec(matrix_p_kp=rho_ao, &
    2368              :                                  rho=LDOS(i_E), &
    2369              :                                  rho_gspace=rho_g_dummy, &
    2370           16 :                                  ks_env=ks_env)
    2371              : 
    2372           52 :          DO i_spin = 1, 2
    2373          944 :             DO i_img = 1, nimg
    2374          928 :                CALL dbcsr_set(rho_ao_weighted(i_spin, i_img)%matrix, 0.0_dp)
    2375              :             END DO
    2376              :          END DO
    2377              : 
    2378              :       END DO
    2379              : 
    2380            4 :       n_x_start = LBOUND(LDOS(1)%array, 1)
    2381            4 :       n_x_end = UBOUND(LDOS(1)%array, 1)
    2382            4 :       n_y_start = LBOUND(LDOS(1)%array, 2)
    2383            4 :       n_y_end = UBOUND(LDOS(1)%array, 2)
    2384            4 :       n_z_start = LBOUND(LDOS(1)%array, 3)
    2385            4 :       n_z_end = UBOUND(LDOS(1)%array, 3)
    2386              : 
    2387            4 :       CALL pw_zero(E_VBM_rspace)
    2388            4 :       CALL pw_zero(E_CBM_rspace)
    2389              : 
    2390           68 :       DO i_x = n_x_start, n_x_end
    2391         2116 :          DO i_y = n_y_start, n_y_end
    2392        94272 :             DO i_z = n_z_start, n_z_end
    2393              :                ! compute average occ and virt LDOS
    2394              :                avg_LDOS_occ = 0.0_dp
    2395       276480 :                DO i_E = 1, n_E_occ
    2396       276480 :                   avg_LDOS_occ = avg_LDOS_occ + LDOS(i_E)%array(i_x, i_y, i_z)
    2397              :                END DO
    2398        92160 :                avg_LDOS_occ = avg_LDOS_occ/REAL(n_E_occ, KIND=dp)
    2399              : 
    2400        92160 :                avg_LDOS_virt = 0.0_dp
    2401       276480 :                DO i_E = n_E_occ + 1, n_E
    2402       276480 :                   avg_LDOS_virt = avg_LDOS_virt + LDOS(i_E)%array(i_x, i_y, i_z)
    2403              :                END DO
    2404        92160 :                avg_LDOS_virt = avg_LDOS_virt/REAL(n_E - n_E_occ, KIND=dp)
    2405              : 
    2406              :                ! compute local valence band maximum (VBM)
    2407       117590 :                DO i_E = n_E_occ, 1, -1
    2408       117590 :                   IF (LDOS(i_E)%array(i_x, i_y, i_z) > mp2_env%ri_g0w0%ldos_thresh_print_loc_bandgap*avg_LDOS_occ) THEN
    2409        79734 :                      E_VBM_rspace%array(i_x, i_y, i_z) = E_array(i_E)
    2410        79734 :                      EXIT
    2411              :                   END IF
    2412              :                END DO
    2413              : 
    2414              :                ! compute local valence band maximum (VBM)
    2415        94304 :                DO i_E = n_E_occ + 1, n_E
    2416        92256 :                   IF (LDOS(i_E)%array(i_x, i_y, i_z) > mp2_env%ri_g0w0%ldos_thresh_print_loc_bandgap*avg_LDOS_virt) THEN
    2417        92112 :                      E_CBM_rspace%array(i_x, i_y, i_z) = E_array(i_E)
    2418        92112 :                      EXIT
    2419              :                   END IF
    2420              :                END DO
    2421              : 
    2422              :             END DO
    2423              :          END DO
    2424              :       END DO
    2425              : 
    2426            4 :       CALL pw_scale(E_VBM_rspace, evolt)
    2427            4 :       CALL pw_scale(E_CBM_rspace, evolt)
    2428              : 
    2429            4 :       CALL pw_copy(E_CBM_rspace, E_gap_rspace)
    2430            4 :       CALL pw_axpy(E_VBM_rspace, E_gap_rspace, -1.0_dp)
    2431              : 
    2432            4 :       gw_section => section_vals_get_subs_vals(qs_env%input, "DFT%XC%WF_CORRELATION%RI_RPA%GW")
    2433            4 :       CALL qs_subsys_get(subsys, particles=particles)
    2434              : 
    2435            4 :       CALL print_file(E_gap_rspace, dft_gw_char//"_Gap_in_eV", gw_section, particles, mp2_env)
    2436            4 :       CALL print_file(E_VBM_rspace, dft_gw_char//"_VBM_in_eV", gw_section, particles, mp2_env)
    2437            4 :       CALL print_file(E_CBM_rspace, dft_gw_char//"_CBM_in_eV", gw_section, particles, mp2_env)
    2438            4 :       CALL print_file(LDOS(n_E_occ), dft_gw_char//"_LDOS_VBM_in_eV", gw_section, particles, mp2_env)
    2439            4 :       CALL print_file(LDOS(n_E_occ + 1), dft_gw_char//"_LDOS_CBM_in_eV", gw_section, particles, mp2_env)
    2440              : 
    2441            4 :       CALL dbcsr_deallocate_matrix_set(rho_ao_weighted)
    2442              : 
    2443            4 :       CALL cp_fm_release(fm_work)
    2444              : 
    2445            4 :       DEALLOCATE (E_array)
    2446              : 
    2447            4 :       NULLIFY (kpoints_Sigma%sab_nl)
    2448              : 
    2449            4 :       CALL timestop(handle)
    2450              : 
    2451            8 :    END SUBROUTINE calculate_E_gap_rspace
    2452              : 
    2453              : ! **************************************************************************************************
    2454              : !> \brief ...
    2455              : !> \param pw_print ...
    2456              : !> \param middle_name ...
    2457              : !> \param gw_section ...
    2458              : !> \param particles ...
    2459              : !> \param mp2_env ...
    2460              : ! **************************************************************************************************
    2461           20 :    SUBROUTINE print_file(pw_print, middle_name, gw_section, particles, mp2_env)
    2462              :       TYPE(pw_r3d_rs_type)                               :: pw_print
    2463              :       CHARACTER(len=*)                                   :: middle_name
    2464              :       TYPE(section_vals_type), POINTER                   :: gw_section
    2465              :       TYPE(particle_list_type), POINTER                  :: particles
    2466              :       TYPE(mp2_type), POINTER                            :: mp2_env
    2467              : 
    2468              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'print_file'
    2469              : 
    2470              :       INTEGER                                            :: handle, unit_nr_cube
    2471              :       LOGICAL                                            :: mpi_io
    2472              :       TYPE(cp_logger_type), POINTER                      :: logger
    2473              : 
    2474           20 :       CALL timeset(routineN, handle)
    2475              : 
    2476           20 :       NULLIFY (logger)
    2477           20 :       logger => cp_get_default_logger()
    2478           20 :       mpi_io = .TRUE.
    2479              :       unit_nr_cube = cp_print_key_unit_nr(logger, gw_section, "PRINT%LOCAL_BANDGAP", extension=".cube", &
    2480           20 :                                           middle_name=middle_name, file_form="FORMATTED", mpi_io=mpi_io)
    2481              :       CALL cp_pw_to_cube(pw_print, unit_nr_cube, middle_name, particles=particles, &
    2482           20 :                          stride=mp2_env%ri_g0w0%stride_loc_bandgap, mpi_io=mpi_io)
    2483              :       CALL cp_print_key_finished_output(unit_nr_cube, logger, gw_section, &
    2484           20 :                                         "PRINT%LOCAL_BANDGAP", mpi_io=mpi_io)
    2485              : 
    2486           20 :       CALL timestop(handle)
    2487              : 
    2488           20 :    END SUBROUTINE print_file
    2489              : 
    2490              : ! **************************************************************************************************
    2491              : !> \brief ...
    2492              : !> \param E_gap_rspace ...
    2493              : !> \param E_VBM_rspace ...
    2494              : !> \param E_CBM_rspace ...
    2495              : !> \param rho_g_dummy ...
    2496              : !> \param LDOS ...
    2497              : !> \param auxbas_pw_pool ...
    2498              : !> \param qs_env ...
    2499              : ! **************************************************************************************************
    2500            4 :    SUBROUTINE create_real_space_grids(E_gap_rspace, E_VBM_rspace, E_CBM_rspace, rho_g_dummy, LDOS, auxbas_pw_pool, qs_env)
    2501              :       TYPE(pw_r3d_rs_type)                               :: E_gap_rspace, E_VBM_rspace, E_CBM_rspace
    2502              :       TYPE(pw_c1d_gs_type)                               :: rho_g_dummy
    2503              :       TYPE(pw_r3d_rs_type), ALLOCATABLE, DIMENSION(:)    :: LDOS
    2504              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    2505              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2506              : 
    2507              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'create_real_space_grids'
    2508              : 
    2509              :       INTEGER                                            :: handle, i_E, n_E
    2510              :       TYPE(mp2_type), POINTER                            :: mp2_env
    2511              :       TYPE(pw_env_type), POINTER                         :: pw_env
    2512              : 
    2513            4 :       CALL timeset(routineN, handle)
    2514              : 
    2515            4 :       CALL get_qs_env(qs_env=qs_env, mp2_env=mp2_env, pw_env=pw_env)
    2516              : 
    2517            4 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    2518              : 
    2519            4 :       CALL auxbas_pw_pool%create_pw(E_gap_rspace)
    2520            4 :       CALL auxbas_pw_pool%create_pw(E_VBM_rspace)
    2521            4 :       CALL auxbas_pw_pool%create_pw(E_CBM_rspace)
    2522            4 :       CALL auxbas_pw_pool%create_pw(rho_g_dummy)
    2523              : 
    2524              :       n_E = INT(mp2_env%ri_g0w0%energy_window_print_loc_bandgap/ &
    2525            4 :                 mp2_env%ri_g0w0%energy_spacing_print_loc_bandgap)
    2526              : 
    2527           28 :       ALLOCATE (LDOS(n_E))
    2528              : 
    2529           20 :       DO i_E = 1, n_E
    2530           20 :          CALL auxbas_pw_pool%create_pw(LDOS(i_E))
    2531              :       END DO
    2532              : 
    2533            4 :       CALL timestop(handle)
    2534              : 
    2535            4 :    END SUBROUTINE create_real_space_grids
    2536              : 
    2537              : ! **************************************************************************************************
    2538              : !> \brief ...
    2539              : !> \param delta_corr ...
    2540              : !> \param qs_env ...
    2541              : !> \param para_env ...
    2542              : !> \param para_env_RPA ...
    2543              : !> \param kp_grid ...
    2544              : !> \param homo ...
    2545              : !> \param nmo ...
    2546              : !> \param gw_corr_lev_occ ...
    2547              : !> \param gw_corr_lev_virt ...
    2548              : !> \param omega ...
    2549              : !> \param fm_mo_coeff ...
    2550              : !> \param Eigenval ...
    2551              : !> \param matrix_berry_re_mo_mo ...
    2552              : !> \param matrix_berry_im_mo_mo ...
    2553              : !> \param first_cycle_periodic_correction ...
    2554              : !> \param kpoints ...
    2555              : !> \param do_mo_coeff_Gamma_only ...
    2556              : !> \param num_kp_grids ...
    2557              : !> \param eps_kpoint ...
    2558              : !> \param do_extra_kpoints ...
    2559              : !> \param do_aux_bas ...
    2560              : !> \param frac_aux_mos ...
    2561              : ! **************************************************************************************************
    2562          260 :    SUBROUTINE calc_periodic_correction(delta_corr, qs_env, para_env, para_env_RPA, kp_grid, homo, nmo, &
    2563          260 :                                        gw_corr_lev_occ, gw_corr_lev_virt, omega, fm_mo_coeff, Eigenval, &
    2564              :                                        matrix_berry_re_mo_mo, matrix_berry_im_mo_mo, &
    2565              :                                        first_cycle_periodic_correction, kpoints, do_mo_coeff_Gamma_only, &
    2566              :                                        num_kp_grids, eps_kpoint, do_extra_kpoints, do_aux_bas, frac_aux_mos)
    2567              : 
    2568              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
    2569              :          INTENT(INOUT)                                   :: delta_corr
    2570              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2571              :       TYPE(mp_para_env_type), POINTER                    :: para_env, para_env_RPA
    2572              :       INTEGER, DIMENSION(:), POINTER                     :: kp_grid
    2573              :       INTEGER, INTENT(IN)                                :: homo, nmo, gw_corr_lev_occ, &
    2574              :                                                             gw_corr_lev_virt
    2575              :       REAL(KIND=dp), INTENT(IN)                          :: omega
    2576              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_mo_coeff
    2577              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: Eigenval
    2578              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_berry_re_mo_mo, &
    2579              :                                                             matrix_berry_im_mo_mo
    2580              :       LOGICAL, INTENT(INOUT) :: first_cycle_periodic_correction
    2581              :       TYPE(kpoint_type), POINTER                         :: kpoints
    2582              :       LOGICAL, INTENT(IN)                                :: do_mo_coeff_Gamma_only
    2583              :       INTEGER, INTENT(IN)                                :: num_kp_grids
    2584              :       REAL(KIND=dp), INTENT(IN)                          :: eps_kpoint
    2585              :       LOGICAL, INTENT(IN)                                :: do_extra_kpoints, do_aux_bas
    2586              :       REAL(KIND=dp), INTENT(IN)                          :: frac_aux_mos
    2587              : 
    2588              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calc_periodic_correction'
    2589              : 
    2590              :       INTEGER                                            :: handle
    2591          260 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eps_head, eps_inv_head
    2592              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: h_inv
    2593              : 
    2594          260 :       CALL timeset(routineN, handle)
    2595              : 
    2596          260 :       IF (first_cycle_periodic_correction) THEN
    2597              : 
    2598              :          CALL get_kpoints(qs_env, kpoints, kp_grid, num_kp_grids, para_env, h_inv, nmo, do_mo_coeff_Gamma_only, &
    2599            6 :                           do_extra_kpoints)
    2600              : 
    2601              :          CALL get_berry_phase(qs_env, kpoints, matrix_berry_re_mo_mo, matrix_berry_im_mo_mo, fm_mo_coeff, &
    2602              :                               para_env, do_mo_coeff_Gamma_only, homo, nmo, gw_corr_lev_virt, eps_kpoint, do_aux_bas, &
    2603            6 :                               frac_aux_mos)
    2604              : 
    2605              :       END IF
    2606              : 
    2607              :       CALL compute_eps_head_Berry(eps_head, kpoints, matrix_berry_re_mo_mo, matrix_berry_im_mo_mo, para_env_RPA, &
    2608          260 :                                   qs_env, homo, Eigenval, omega)
    2609              : 
    2610          260 :       CALL compute_eps_inv_head(eps_inv_head, eps_head, kpoints)
    2611              : 
    2612              :       CALL kpoint_sum_for_eps_inv_head_Berry(delta_corr, eps_inv_head, kpoints, qs_env, &
    2613              :                                              matrix_berry_re_mo_mo, matrix_berry_im_mo_mo, &
    2614              :                                              homo, gw_corr_lev_occ, gw_corr_lev_virt, para_env_RPA, &
    2615          260 :                                              do_extra_kpoints)
    2616              : 
    2617          260 :       DEALLOCATE (eps_head, eps_inv_head)
    2618              : 
    2619          260 :       first_cycle_periodic_correction = .FALSE.
    2620              : 
    2621          260 :       CALL timestop(handle)
    2622              : 
    2623          260 :    END SUBROUTINE calc_periodic_correction
    2624              : 
    2625              : ! **************************************************************************************************
    2626              : !> \brief ...
    2627              : !> \param eps_head ...
    2628              : !> \param kpoints ...
    2629              : !> \param matrix_berry_re_mo_mo ...
    2630              : !> \param matrix_berry_im_mo_mo ...
    2631              : !> \param para_env_RPA ...
    2632              : !> \param qs_env ...
    2633              : !> \param homo ...
    2634              : !> \param Eigenval ...
    2635              : !> \param omega ...
    2636              : ! **************************************************************************************************
    2637          260 :    SUBROUTINE compute_eps_head_Berry(eps_head, kpoints, matrix_berry_re_mo_mo, matrix_berry_im_mo_mo, para_env_RPA, &
    2638          260 :                                      qs_env, homo, Eigenval, omega)
    2639              : 
    2640              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
    2641              :          INTENT(OUT)                                     :: eps_head
    2642              :       TYPE(kpoint_type), POINTER                         :: kpoints
    2643              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN)       :: matrix_berry_re_mo_mo, &
    2644              :                                                             matrix_berry_im_mo_mo
    2645              :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env_RPA
    2646              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2647              :       INTEGER, INTENT(IN)                                :: homo
    2648              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: Eigenval
    2649              :       REAL(KIND=dp), INTENT(IN)                          :: omega
    2650              : 
    2651              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_eps_head_Berry'
    2652              : 
    2653              :       INTEGER :: col, col_end_in_block, col_offset, col_size, handle, i_col, i_row, ikp, nkp, nmo, &
    2654              :          row, row_offset, row_size, row_start_in_block
    2655              :       REAL(KIND=dp)                                      :: abs_k_square, cell_volume, &
    2656              :                                                             correct_kpoint(3), cos_square, &
    2657              :                                                             eigen_diff, relative_kpoint(3), &
    2658              :                                                             sin_square
    2659              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: P_head
    2660          260 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: data_block
    2661              :       TYPE(cell_type), POINTER                           :: cell
    2662              :       TYPE(dbcsr_iterator_type)                          :: iter
    2663              : 
    2664          260 :       CALL timeset(routineN, handle)
    2665              : 
    2666          260 :       CALL get_qs_env(qs_env=qs_env, cell=cell)
    2667          260 :       CALL get_cell(cell=cell, deth=cell_volume)
    2668              : 
    2669          260 :       NULLIFY (data_block)
    2670              : 
    2671          260 :       nkp = kpoints%nkp
    2672              : 
    2673          260 :       nmo = SIZE(Eigenval)
    2674              : 
    2675          780 :       ALLOCATE (P_head(nkp))
    2676          260 :       P_head(:) = 0.0_dp
    2677              : 
    2678          520 :       ALLOCATE (eps_head(nkp))
    2679          260 :       eps_head(:) = 0.0_dp
    2680              : 
    2681       279620 :       DO ikp = 1, nkp
    2682              : 
    2683      3631680 :          relative_kpoint(1:3) = MATMUL(cell%hmat, kpoints%xkp(1:3, ikp))
    2684              : 
    2685      1117440 :          correct_kpoint(1:3) = twopi*kpoints%xkp(1:3, ikp)
    2686              : 
    2687       279360 :          abs_k_square = (correct_kpoint(1))**2 + (correct_kpoint(2))**2 + (correct_kpoint(3))**2
    2688              : 
    2689              :          ! real part of the Berry phase
    2690       279360 :          CALL dbcsr_iterator_start(iter, matrix_berry_re_mo_mo(ikp)%matrix)
    2691       465120 :          DO WHILE (dbcsr_iterator_blocks_left(iter))
    2692              : 
    2693              :             CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
    2694              :                                            row_size=row_size, col_size=col_size, &
    2695       185760 :                                            row_offset=row_offset, col_offset=col_offset)
    2696              : 
    2697       185760 :             IF (row_offset + row_size <= homo .OR. col_offset > homo) CYCLE
    2698              : 
    2699       185760 :             IF (row_offset <= homo) THEN
    2700       139680 :                row_start_in_block = homo - row_offset + 2
    2701              :             ELSE
    2702              :                row_start_in_block = 1
    2703              :             END IF
    2704              : 
    2705       185760 :             IF (col_offset + col_size - 1 > homo) THEN
    2706       185760 :                col_end_in_block = homo - col_offset + 1
    2707              :             ELSE
    2708              :                col_end_in_block = col_size
    2709              :             END IF
    2710              : 
    2711      1929600 :             DO i_row = row_start_in_block, MIN(row_size, nmo - row_offset + 1)
    2712              : 
    2713      7508160 :                DO i_col = 1, MIN(col_end_in_block, nmo - col_offset + 1)
    2714              : 
    2715      5857920 :                   eigen_diff = Eigenval(i_col + col_offset - 1) - Eigenval(i_row + row_offset - 1)
    2716              : 
    2717      5857920 :                   cos_square = (data_block(i_row, i_col))**2
    2718              : 
    2719      7322400 :                   P_head(ikp) = P_head(ikp) + 2.0_dp*eigen_diff/(omega**2 + eigen_diff**2)*cos_square/abs_k_square
    2720              : 
    2721              :                END DO
    2722              : 
    2723              :             END DO
    2724              : 
    2725              :          END DO
    2726              : 
    2727       279360 :          CALL dbcsr_iterator_stop(iter)
    2728              : 
    2729              :          ! imaginary part of the Berry phase
    2730       279360 :          CALL dbcsr_iterator_start(iter, matrix_berry_im_mo_mo(ikp)%matrix)
    2731       465120 :          DO WHILE (dbcsr_iterator_blocks_left(iter))
    2732              : 
    2733              :             CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
    2734              :                                            row_size=row_size, col_size=col_size, &
    2735       185760 :                                            row_offset=row_offset, col_offset=col_offset)
    2736              : 
    2737       185760 :             IF (row_offset + row_size <= homo .OR. col_offset > homo) CYCLE
    2738              : 
    2739       185760 :             IF (row_offset <= homo) THEN
    2740       139680 :                row_start_in_block = homo - row_offset + 2
    2741              :             ELSE
    2742              :                row_start_in_block = 1
    2743              :             END IF
    2744              : 
    2745       185760 :             IF (col_offset + col_size - 1 > homo) THEN
    2746       185760 :                col_end_in_block = homo - col_offset + 1
    2747              :             ELSE
    2748              :                col_end_in_block = col_size
    2749              :             END IF
    2750              : 
    2751      1929600 :             DO i_row = row_start_in_block, MIN(row_size, nmo - row_offset + 1)
    2752              : 
    2753      7508160 :                DO i_col = 1, MIN(col_end_in_block, nmo - col_offset + 1)
    2754              : 
    2755      5857920 :                   eigen_diff = Eigenval(i_col + col_offset - 1) - Eigenval(i_row + row_offset - 1)
    2756              : 
    2757      5857920 :                   sin_square = (data_block(i_row, i_col))**2
    2758              : 
    2759      7322400 :                   P_head(ikp) = P_head(ikp) + 2.0_dp*eigen_diff/(omega**2 + eigen_diff**2)*sin_square/abs_k_square
    2760              : 
    2761              :                END DO
    2762              : 
    2763              :             END DO
    2764              : 
    2765              :          END DO
    2766              : 
    2767       838340 :          CALL dbcsr_iterator_stop(iter)
    2768              : 
    2769              :       END DO
    2770              : 
    2771          260 :       CALL para_env_RPA%sum(P_head)
    2772              : 
    2773              :       ! normalize eps_head
    2774              :       ! 2.0_dp due to closed shell
    2775       279620 :       eps_head(:) = 1.0_dp - 2.0_dp*P_head(:)/cell_volume*fourpi
    2776              : 
    2777          260 :       DEALLOCATE (P_head)
    2778              : 
    2779          260 :       CALL timestop(handle)
    2780              : 
    2781          520 :    END SUBROUTINE compute_eps_head_Berry
    2782              : 
    2783              : ! **************************************************************************************************
    2784              : !> \brief ...
    2785              : !> \param qs_env ...
    2786              : !> \param kpoints ...
    2787              : !> \param matrix_berry_re_mo_mo ...
    2788              : !> \param matrix_berry_im_mo_mo ...
    2789              : !> \param fm_mo_coeff ...
    2790              : !> \param para_env ...
    2791              : !> \param do_mo_coeff_Gamma_only ...
    2792              : !> \param homo ...
    2793              : !> \param nmo ...
    2794              : !> \param gw_corr_lev_virt ...
    2795              : !> \param eps_kpoint ...
    2796              : !> \param do_aux_bas ...
    2797              : !> \param frac_aux_mos ...
    2798              : ! **************************************************************************************************
    2799            6 :    SUBROUTINE get_berry_phase(qs_env, kpoints, matrix_berry_re_mo_mo, matrix_berry_im_mo_mo, fm_mo_coeff, para_env, &
    2800              :                               do_mo_coeff_Gamma_only, homo, nmo, gw_corr_lev_virt, eps_kpoint, do_aux_bas, &
    2801              :                               frac_aux_mos)
    2802              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2803              :       TYPE(kpoint_type), POINTER                         :: kpoints
    2804              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_berry_re_mo_mo, &
    2805              :                                                             matrix_berry_im_mo_mo
    2806              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_mo_coeff
    2807              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2808              :       LOGICAL, INTENT(IN)                                :: do_mo_coeff_Gamma_only
    2809              :       INTEGER, INTENT(IN)                                :: homo, nmo, gw_corr_lev_virt
    2810              :       REAL(KIND=dp), INTENT(IN)                          :: eps_kpoint
    2811              :       LOGICAL, INTENT(IN)                                :: do_aux_bas
    2812              :       REAL(KIND=dp), INTENT(IN)                          :: frac_aux_mos
    2813              : 
    2814              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'get_berry_phase'
    2815              : 
    2816              :       INTEGER                                            :: col_index, handle, i_col_local, ikind, &
    2817              :                                                             ikp, nao_aux, ncol_local, nkind, nkp, &
    2818              :                                                             nmo_for_aux_bas
    2819            6 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices
    2820              :       REAL(dp)                                           :: abs_kpoint, correct_kpoint(3), &
    2821              :                                                             scale_kpoint
    2822            6 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: evals_P, evals_P_sqrt_inv
    2823              :       TYPE(cell_type), POINTER                           :: cell
    2824              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_aux_aux
    2825              :       TYPE(cp_fm_type) :: fm_mat_eigv_P, fm_mat_P, fm_mat_P_sqrt_inv, fm_mat_s_aux_aux_inv, &
    2826              :          fm_mat_scaled_eigv_P, fm_mat_work_aux_aux
    2827            6 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s, matrix_s_aux_aux, &
    2828            6 :                                                             matrix_s_aux_orb
    2829              :       TYPE(dbcsr_type), POINTER :: cosmat, cosmat_desymm, mat_mo_coeff_aux, mat_mo_coeff_aux_2, &
    2830              :          mat_mo_coeff_Gamma_all, mat_mo_coeff_Gamma_occ_and_GW, mat_mo_coeff_im, mat_mo_coeff_re, &
    2831              :          mat_work_aux_orb, mat_work_aux_orb_2, matrix_P, matrix_P_sqrt, matrix_P_sqrt_inv, &
    2832              :          matrix_s_inv_aux_aux, sinmat, sinmat_desymm, tmp
    2833            6 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: gw_aux_basis_set_list, orb_basis_set_list
    2834              :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_gw_aux
    2835              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    2836            6 :          POINTER                                         :: sab_orb, sab_orb_mic, sgwgw_list, &
    2837            6 :                                                             sgworb_list
    2838            6 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    2839              :       TYPE(qs_kind_type), POINTER                        :: qs_kind
    2840              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
    2841              : 
    2842            6 :       CALL timeset(routineN, handle)
    2843              : 
    2844            6 :       nkp = kpoints%nkp
    2845              : 
    2846            6 :       NULLIFY (matrix_berry_re_mo_mo, matrix_s, cell, matrix_berry_im_mo_mo, sinmat, cosmat, tmp, &
    2847            6 :                cosmat_desymm, sinmat_desymm, qs_kind_set, orb_basis_set_list, sab_orb_mic)
    2848              : 
    2849              :       CALL get_qs_env(qs_env=qs_env, &
    2850              :                       cell=cell, &
    2851              :                       matrix_s=matrix_s, &
    2852              :                       qs_kind_set=qs_kind_set, &
    2853              :                       nkind=nkind, &
    2854              :                       ks_env=ks_env, &
    2855            6 :                       sab_orb=sab_orb)
    2856              : 
    2857           30 :       ALLOCATE (orb_basis_set_list(nkind))
    2858            6 :       CALL basis_set_list_setup(orb_basis_set_list, "ORB", qs_kind_set)
    2859              : 
    2860            6 :       CALL setup_neighbor_list(sab_orb_mic, orb_basis_set_list, qs_env=qs_env, mic=.FALSE.)
    2861              : 
    2862              :       ! create dbcsr matrix of mo_coeff for multiplcation
    2863            6 :       NULLIFY (mat_mo_coeff_re)
    2864            6 :       CALL dbcsr_init_p(mat_mo_coeff_re)
    2865              :       CALL dbcsr_create(matrix=mat_mo_coeff_re, &
    2866              :                         template=matrix_s(1)%matrix, &
    2867            6 :                         matrix_type=dbcsr_type_no_symmetry)
    2868              : 
    2869            6 :       NULLIFY (mat_mo_coeff_im)
    2870            6 :       CALL dbcsr_init_p(mat_mo_coeff_im)
    2871              :       CALL dbcsr_create(matrix=mat_mo_coeff_im, &
    2872              :                         template=matrix_s(1)%matrix, &
    2873            6 :                         matrix_type=dbcsr_type_no_symmetry)
    2874              : 
    2875            6 :       NULLIFY (mat_mo_coeff_Gamma_all)
    2876            6 :       CALL dbcsr_init_p(mat_mo_coeff_Gamma_all)
    2877              :       CALL dbcsr_create(matrix=mat_mo_coeff_Gamma_all, &
    2878              :                         template=matrix_s(1)%matrix, &
    2879            6 :                         matrix_type=dbcsr_type_no_symmetry)
    2880              : 
    2881            6 :       CALL copy_fm_to_dbcsr(fm_mo_coeff, mat_mo_coeff_Gamma_all, keep_sparsity=.FALSE.)
    2882              : 
    2883            6 :       NULLIFY (mat_mo_coeff_Gamma_occ_and_GW)
    2884            6 :       CALL dbcsr_init_p(mat_mo_coeff_Gamma_occ_and_GW)
    2885              :       CALL dbcsr_create(matrix=mat_mo_coeff_Gamma_occ_and_GW, &
    2886              :                         template=matrix_s(1)%matrix, &
    2887            6 :                         matrix_type=dbcsr_type_no_symmetry)
    2888              : 
    2889            6 :       CALL copy_fm_to_dbcsr(fm_mo_coeff, mat_mo_coeff_Gamma_occ_and_GW, keep_sparsity=.FALSE.)
    2890              : 
    2891            6 :       IF (.NOT. do_aux_bas) THEN
    2892              : 
    2893              :          ! allocate intermediate matrices
    2894            4 :          CALL dbcsr_init_p(cosmat)
    2895            4 :          CALL dbcsr_init_p(sinmat)
    2896            4 :          CALL dbcsr_init_p(tmp)
    2897            4 :          CALL dbcsr_init_p(cosmat_desymm)
    2898            4 :          CALL dbcsr_init_p(sinmat_desymm)
    2899            4 :          CALL dbcsr_create(matrix=cosmat, template=matrix_s(1)%matrix)
    2900            4 :          CALL dbcsr_create(matrix=sinmat, template=matrix_s(1)%matrix)
    2901              :          CALL dbcsr_create(matrix=tmp, &
    2902              :                            template=matrix_s(1)%matrix, &
    2903            4 :                            matrix_type=dbcsr_type_no_symmetry)
    2904              :          CALL dbcsr_create(matrix=cosmat_desymm, &
    2905              :                            template=matrix_s(1)%matrix, &
    2906            4 :                            matrix_type=dbcsr_type_no_symmetry)
    2907              :          CALL dbcsr_create(matrix=sinmat_desymm, &
    2908              :                            template=matrix_s(1)%matrix, &
    2909            4 :                            matrix_type=dbcsr_type_no_symmetry)
    2910            4 :          CALL dbcsr_copy(cosmat, matrix_s(1)%matrix)
    2911            4 :          CALL dbcsr_copy(sinmat, matrix_s(1)%matrix)
    2912              : 
    2913            4 :          CALL dbcsr_allocate_matrix_set(matrix_berry_re_mo_mo, nkp)
    2914            4 :          CALL dbcsr_allocate_matrix_set(matrix_berry_im_mo_mo, nkp)
    2915              : 
    2916              :       ELSE
    2917              : 
    2918            2 :          NULLIFY (gw_aux_basis_set_list)
    2919           10 :          ALLOCATE (gw_aux_basis_set_list(nkind))
    2920              : 
    2921            6 :          DO ikind = 1, nkind
    2922              : 
    2923            4 :             NULLIFY (gw_aux_basis_set_list(ikind)%gto_basis_set)
    2924              : 
    2925            4 :             NULLIFY (basis_set_gw_aux)
    2926              : 
    2927            4 :             qs_kind => qs_kind_set(ikind)
    2928            4 :             CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_gw_aux, basis_type="AUX_GW")
    2929            4 :             CPASSERT(ASSOCIATED(basis_set_gw_aux))
    2930              : 
    2931            4 :             basis_set_gw_aux%kind_radius = orb_basis_set_list(ikind)%gto_basis_set%kind_radius
    2932              : 
    2933            6 :             gw_aux_basis_set_list(ikind)%gto_basis_set => basis_set_gw_aux
    2934              : 
    2935              :          END DO
    2936              : 
    2937              :          ! neighbor lists
    2938            2 :          NULLIFY (sgwgw_list, sgworb_list)
    2939            2 :          CALL setup_neighbor_list(sgwgw_list, gw_aux_basis_set_list, qs_env=qs_env)
    2940            2 :          CALL setup_neighbor_list(sgworb_list, gw_aux_basis_set_list, orb_basis_set_list, qs_env=qs_env)
    2941              : 
    2942            2 :          NULLIFY (matrix_s_aux_aux, matrix_s_aux_orb)
    2943              : 
    2944              :          ! build overlap matrix in gw aux basis and the mixed gw aux basis-orb basis
    2945              :          CALL build_overlap_matrix_simple(ks_env, matrix_s_aux_aux, &
    2946            2 :                                           gw_aux_basis_set_list, gw_aux_basis_set_list, sgwgw_list)
    2947              : 
    2948              :          CALL build_overlap_matrix_simple(ks_env, matrix_s_aux_orb, &
    2949            2 :                                           gw_aux_basis_set_list, orb_basis_set_list, sgworb_list)
    2950              : 
    2951            2 :          CALL dbcsr_get_info(matrix_s_aux_aux(1)%matrix, nfullrows_total=nao_aux)
    2952              : 
    2953            2 :          nmo_for_aux_bas = FLOOR(frac_aux_mos*REAL(nao_aux, KIND=dp))
    2954              : 
    2955              :          CALL cp_fm_struct_create(fm_struct_aux_aux, &
    2956              :                                   context=fm_mo_coeff%matrix_struct%context, &
    2957              :                                   nrow_global=nao_aux, &
    2958              :                                   ncol_global=nao_aux, &
    2959            2 :                                   para_env=para_env)
    2960              : 
    2961            2 :          NULLIFY (mat_work_aux_orb)
    2962            2 :          CALL dbcsr_init_p(mat_work_aux_orb)
    2963              :          CALL dbcsr_create(matrix=mat_work_aux_orb, &
    2964              :                            template=matrix_s_aux_orb(1)%matrix, &
    2965            2 :                            matrix_type=dbcsr_type_no_symmetry)
    2966              : 
    2967            2 :          NULLIFY (mat_work_aux_orb_2)
    2968            2 :          CALL dbcsr_init_p(mat_work_aux_orb_2)
    2969              :          CALL dbcsr_create(matrix=mat_work_aux_orb_2, &
    2970              :                            template=matrix_s_aux_orb(1)%matrix, &
    2971            2 :                            matrix_type=dbcsr_type_no_symmetry)
    2972              : 
    2973            2 :          NULLIFY (mat_mo_coeff_aux)
    2974            2 :          CALL dbcsr_init_p(mat_mo_coeff_aux)
    2975              :          CALL dbcsr_create(matrix=mat_mo_coeff_aux, &
    2976              :                            template=matrix_s_aux_orb(1)%matrix, &
    2977            2 :                            matrix_type=dbcsr_type_no_symmetry)
    2978              : 
    2979            2 :          NULLIFY (mat_mo_coeff_aux_2)
    2980            2 :          CALL dbcsr_init_p(mat_mo_coeff_aux_2)
    2981              :          CALL dbcsr_create(matrix=mat_mo_coeff_aux_2, &
    2982              :                            template=matrix_s_aux_orb(1)%matrix, &
    2983            2 :                            matrix_type=dbcsr_type_no_symmetry)
    2984              : 
    2985            2 :          NULLIFY (matrix_s_inv_aux_aux)
    2986            2 :          CALL dbcsr_init_p(matrix_s_inv_aux_aux)
    2987              :          CALL dbcsr_create(matrix=matrix_s_inv_aux_aux, &
    2988              :                            template=matrix_s_aux_aux(1)%matrix, &
    2989            2 :                            matrix_type=dbcsr_type_no_symmetry)
    2990              : 
    2991            2 :          NULLIFY (matrix_P)
    2992            2 :          CALL dbcsr_init_p(matrix_P)
    2993              :          CALL dbcsr_create(matrix=matrix_P, &
    2994              :                            template=matrix_s(1)%matrix, &
    2995            2 :                            matrix_type=dbcsr_type_no_symmetry)
    2996              : 
    2997            2 :          NULLIFY (matrix_P_sqrt)
    2998            2 :          CALL dbcsr_init_p(matrix_P_sqrt)
    2999              :          CALL dbcsr_create(matrix=matrix_P_sqrt, &
    3000              :                            template=matrix_s(1)%matrix, &
    3001            2 :                            matrix_type=dbcsr_type_no_symmetry)
    3002              : 
    3003            2 :          NULLIFY (matrix_P_sqrt_inv)
    3004            2 :          CALL dbcsr_init_p(matrix_P_sqrt_inv)
    3005              :          CALL dbcsr_create(matrix=matrix_P_sqrt_inv, &
    3006              :                            template=matrix_s(1)%matrix, &
    3007            2 :                            matrix_type=dbcsr_type_no_symmetry)
    3008              : 
    3009            2 :          CALL cp_fm_create(fm_mat_s_aux_aux_inv, fm_struct_aux_aux, name="inverse overlap mat")
    3010            2 :          CALL cp_fm_create(fm_mat_work_aux_aux, fm_struct_aux_aux, name="work mat")
    3011            2 :          CALL cp_fm_create(fm_mat_P, fm_mo_coeff%matrix_struct)
    3012            2 :          CALL cp_fm_create(fm_mat_eigv_P, fm_mo_coeff%matrix_struct)
    3013            2 :          CALL cp_fm_create(fm_mat_scaled_eigv_P, fm_mo_coeff%matrix_struct)
    3014            2 :          CALL cp_fm_create(fm_mat_P_sqrt_inv, fm_mo_coeff%matrix_struct)
    3015              : 
    3016              :          NULLIFY (evals_P)
    3017            6 :          ALLOCATE (evals_P(nmo))
    3018              : 
    3019            2 :          NULLIFY (evals_P_sqrt_inv)
    3020            4 :          ALLOCATE (evals_P_sqrt_inv(nmo))
    3021              : 
    3022            2 :          CALL copy_dbcsr_to_fm(matrix_s_aux_aux(1)%matrix, fm_mat_s_aux_aux_inv)
    3023              :          ! Calculate S_inverse
    3024            2 :          CALL cp_fm_cholesky_decompose(fm_mat_s_aux_aux_inv)
    3025            2 :          CALL cp_fm_cholesky_invert(fm_mat_s_aux_aux_inv)
    3026              :          ! Symmetrize the guy
    3027            2 :          CALL cp_fm_uplo_to_full(fm_mat_s_aux_aux_inv, fm_mat_work_aux_aux)
    3028              : 
    3029            2 :          CALL copy_fm_to_dbcsr(fm_mat_s_aux_aux_inv, matrix_s_inv_aux_aux, keep_sparsity=.FALSE.)
    3030              : 
    3031              :          CALL dbcsr_multiply('N', 'N', 1.0_dp, matrix_s_inv_aux_aux, matrix_s_aux_orb(1)%matrix, 0.0_dp, mat_work_aux_orb, &
    3032            2 :                              filter_eps=1.0E-15_dp)
    3033              : 
    3034              :          CALL dbcsr_multiply('N', 'N', 1.0_dp, mat_work_aux_orb, mat_mo_coeff_Gamma_all, 0.0_dp, mat_mo_coeff_aux_2, &
    3035            2 :                              last_column=nmo_for_aux_bas, filter_eps=1.0E-15_dp)
    3036              : 
    3037              :          CALL dbcsr_multiply('N', 'N', 1.0_dp, matrix_s_aux_aux(1)%matrix, mat_mo_coeff_aux_2, 0.0_dp, mat_work_aux_orb, &
    3038            2 :                              filter_eps=1.0E-15_dp)
    3039              : 
    3040              :          CALL dbcsr_multiply('T', 'N', 1.0_dp, mat_mo_coeff_aux_2, mat_work_aux_orb, 0.0_dp, matrix_P, &
    3041            2 :                              filter_eps=1.0E-15_dp)
    3042              : 
    3043            2 :          CALL copy_dbcsr_to_fm(matrix_P, fm_mat_P)
    3044              : 
    3045            2 :          CALL cp_fm_syevd(fm_mat_P, fm_mat_eigv_P, evals_P)
    3046              : 
    3047              :          ! only invert the eigenvalues which correspond to the MOs used in the aux. basis
    3048           62 :          evals_P_sqrt_inv(1:nmo - nmo_for_aux_bas) = 0.0_dp
    3049           46 :          evals_P_sqrt_inv(nmo - nmo_for_aux_bas + 1:nmo) = 1.0_dp/SQRT(evals_P(nmo - nmo_for_aux_bas + 1:nmo))
    3050              : 
    3051            2 :          CALL cp_fm_to_fm(fm_mat_eigv_P, fm_mat_scaled_eigv_P)
    3052              : 
    3053              :          CALL cp_fm_get_info(matrix=fm_mat_scaled_eigv_P, &
    3054              :                              ncol_local=ncol_local, &
    3055            2 :                              col_indices=col_indices)
    3056              : 
    3057            2 :          CALL para_env%sync()
    3058              : 
    3059              :          ! multiply eigenvectors with inverse sqrt of eigenvalues
    3060           84 :          DO i_col_local = 1, ncol_local
    3061              : 
    3062           82 :             col_index = col_indices(i_col_local)
    3063              : 
    3064              :             fm_mat_scaled_eigv_P%local_data(:, i_col_local) = &
    3065         1765 :                fm_mat_scaled_eigv_P%local_data(:, i_col_local)*evals_P_sqrt_inv(col_index)
    3066              : 
    3067              :          END DO
    3068              : 
    3069            2 :          CALL para_env%sync()
    3070              : 
    3071              :          CALL parallel_gemm(transa="N", transb="T", m=nmo, n=nmo, k=nmo, alpha=1.0_dp, &
    3072              :                             matrix_a=fm_mat_eigv_P, matrix_b=fm_mat_scaled_eigv_P, beta=0.0_dp, &
    3073            2 :                             matrix_c=fm_mat_P_sqrt_inv)
    3074              : 
    3075            2 :          CALL copy_fm_to_dbcsr(fm_mat_P_sqrt_inv, matrix_P_sqrt_inv, keep_sparsity=.FALSE.)
    3076              : 
    3077              :          CALL dbcsr_multiply('N', 'N', 1.0_dp, mat_mo_coeff_aux_2, matrix_P_sqrt_inv, 0.0_dp, mat_mo_coeff_aux, &
    3078            2 :                              filter_eps=1.0E-15_dp)
    3079              : 
    3080              :          ! allocate intermediate matrices
    3081            2 :          CALL dbcsr_init_p(cosmat)
    3082            2 :          CALL dbcsr_init_p(sinmat)
    3083            2 :          CALL dbcsr_init_p(tmp)
    3084            2 :          CALL dbcsr_init_p(cosmat_desymm)
    3085            2 :          CALL dbcsr_init_p(sinmat_desymm)
    3086            2 :          CALL dbcsr_create(matrix=cosmat, template=matrix_s_aux_aux(1)%matrix)
    3087            2 :          CALL dbcsr_create(matrix=sinmat, template=matrix_s_aux_aux(1)%matrix)
    3088              :          CALL dbcsr_create(matrix=tmp, &
    3089              :                            template=matrix_s_aux_orb(1)%matrix, &
    3090            2 :                            matrix_type=dbcsr_type_no_symmetry)
    3091              :          CALL dbcsr_create(matrix=cosmat_desymm, &
    3092              :                            template=matrix_s_aux_aux(1)%matrix, &
    3093            2 :                            matrix_type=dbcsr_type_no_symmetry)
    3094              :          CALL dbcsr_create(matrix=sinmat_desymm, &
    3095              :                            template=matrix_s_aux_aux(1)%matrix, &
    3096            2 :                            matrix_type=dbcsr_type_no_symmetry)
    3097            2 :          CALL dbcsr_copy(cosmat, matrix_s_aux_aux(1)%matrix)
    3098            2 :          CALL dbcsr_copy(sinmat, matrix_s_aux_aux(1)%matrix)
    3099              : 
    3100            2 :          CALL dbcsr_allocate_matrix_set(matrix_berry_re_mo_mo, nkp)
    3101            2 :          CALL dbcsr_allocate_matrix_set(matrix_berry_im_mo_mo, nkp)
    3102              : 
    3103              :          ! allocate the new MO coefficients in the aux basis
    3104            2 :          CALL dbcsr_release_p(mat_mo_coeff_Gamma_all)
    3105            2 :          CALL dbcsr_release_p(mat_mo_coeff_Gamma_occ_and_GW)
    3106              : 
    3107            2 :          NULLIFY (mat_mo_coeff_Gamma_all)
    3108            2 :          CALL dbcsr_init_p(mat_mo_coeff_Gamma_all)
    3109              :          CALL dbcsr_create(matrix=mat_mo_coeff_Gamma_all, &
    3110              :                            template=matrix_s_aux_orb(1)%matrix, &
    3111            2 :                            matrix_type=dbcsr_type_no_symmetry)
    3112              : 
    3113            2 :          CALL dbcsr_copy(mat_mo_coeff_Gamma_all, mat_mo_coeff_aux)
    3114              : 
    3115            2 :          NULLIFY (mat_mo_coeff_Gamma_occ_and_GW)
    3116            2 :          CALL dbcsr_init_p(mat_mo_coeff_Gamma_occ_and_GW)
    3117              :          CALL dbcsr_create(matrix=mat_mo_coeff_Gamma_occ_and_GW, &
    3118              :                            template=matrix_s_aux_orb(1)%matrix, &
    3119            2 :                            matrix_type=dbcsr_type_no_symmetry)
    3120              : 
    3121            2 :          CALL dbcsr_copy(mat_mo_coeff_Gamma_occ_and_GW, mat_mo_coeff_aux)
    3122              : 
    3123            8 :          DEALLOCATE (evals_P, evals_P_sqrt_inv)
    3124              : 
    3125              :       END IF
    3126              : 
    3127            6 :       CALL remove_unnecessary_blocks(mat_mo_coeff_Gamma_occ_and_GW, homo, gw_corr_lev_virt)
    3128              : 
    3129        11166 :       DO ikp = 1, nkp
    3130              : 
    3131        11160 :          ALLOCATE (matrix_berry_re_mo_mo(ikp)%matrix)
    3132        11160 :          CALL dbcsr_init_p(matrix_berry_re_mo_mo(ikp)%matrix)
    3133              :          CALL dbcsr_create(matrix_berry_re_mo_mo(ikp)%matrix, &
    3134              :                            template=matrix_s(1)%matrix, &
    3135        11160 :                            matrix_type=dbcsr_type_no_symmetry)
    3136        11160 :          CALL dbcsr_desymmetrize(matrix_s(1)%matrix, matrix_berry_re_mo_mo(ikp)%matrix)
    3137        11160 :          CALL dbcsr_set(matrix_berry_re_mo_mo(ikp)%matrix, 0.0_dp)
    3138              : 
    3139        11160 :          ALLOCATE (matrix_berry_im_mo_mo(ikp)%matrix)
    3140        11160 :          CALL dbcsr_init_p(matrix_berry_im_mo_mo(ikp)%matrix)
    3141              :          CALL dbcsr_create(matrix_berry_im_mo_mo(ikp)%matrix, &
    3142              :                            template=matrix_s(1)%matrix, &
    3143        11160 :                            matrix_type=dbcsr_type_no_symmetry)
    3144        11160 :          CALL dbcsr_desymmetrize(matrix_s(1)%matrix, matrix_berry_im_mo_mo(ikp)%matrix)
    3145        11160 :          CALL dbcsr_set(matrix_berry_im_mo_mo(ikp)%matrix, 0.0_dp)
    3146              : 
    3147        44640 :          correct_kpoint(1:3) = -twopi*kpoints%xkp(1:3, ikp)
    3148              : 
    3149        11160 :          abs_kpoint = SQRT(correct_kpoint(1)**2 + correct_kpoint(2)**2 + correct_kpoint(3)**2)
    3150              : 
    3151        11160 :          IF (abs_kpoint < eps_kpoint) THEN
    3152              : 
    3153            0 :             scale_kpoint = eps_kpoint/abs_kpoint
    3154            0 :             correct_kpoint(:) = correct_kpoint(:)*scale_kpoint
    3155              : 
    3156              :          END IF
    3157              : 
    3158              :          ! get the Berry phase
    3159        11160 :          IF (do_aux_bas) THEN
    3160              :             CALL build_berry_moment_matrix(qs_env, cosmat, sinmat, correct_kpoint, sab_orb_external=sab_orb_mic, &
    3161         1944 :                                            basis_type="AUX_GW")
    3162              :          ELSE
    3163              :             CALL build_berry_moment_matrix(qs_env, cosmat, sinmat, correct_kpoint, sab_orb_external=sab_orb_mic, &
    3164         9216 :                                            basis_type="ORB")
    3165              :          END IF
    3166              : 
    3167        11160 :          IF (do_mo_coeff_Gamma_only) THEN
    3168              : 
    3169        11160 :             CALL dbcsr_desymmetrize(cosmat, cosmat_desymm)
    3170              : 
    3171              :             CALL dbcsr_multiply('N', 'N', 1.0_dp, cosmat_desymm, mat_mo_coeff_Gamma_occ_and_GW, 0.0_dp, tmp, &
    3172        11160 :                                 filter_eps=1.0E-15_dp)
    3173              : 
    3174              :             CALL dbcsr_multiply('T', 'N', 1.0_dp, mat_mo_coeff_Gamma_all, tmp, 0.0_dp, &
    3175        11160 :                                 matrix_berry_re_mo_mo(ikp)%matrix, filter_eps=1.0E-15_dp)
    3176              : 
    3177        11160 :             CALL dbcsr_desymmetrize(sinmat, sinmat_desymm)
    3178              : 
    3179              :             CALL dbcsr_multiply('N', 'N', 1.0_dp, sinmat_desymm, mat_mo_coeff_Gamma_occ_and_GW, 0.0_dp, tmp, &
    3180        11160 :                                 filter_eps=1.0E-15_dp)
    3181              : 
    3182              :             CALL dbcsr_multiply('T', 'N', 1.0_dp, mat_mo_coeff_Gamma_all, tmp, 0.0_dp, &
    3183        11160 :                                 matrix_berry_im_mo_mo(ikp)%matrix, filter_eps=1.0E-15_dp)
    3184              : 
    3185              :          ELSE
    3186              : 
    3187              :             ! get mo coeff at the ikp
    3188              :             CALL copy_fm_to_dbcsr(kpoints%kp_env(ikp)%kpoint_env%mos(1, 1)%mo_coeff, &
    3189            0 :                                   mat_mo_coeff_re, keep_sparsity=.FALSE.)
    3190              : 
    3191              :             CALL copy_fm_to_dbcsr(kpoints%kp_env(ikp)%kpoint_env%mos(2, 1)%mo_coeff, &
    3192            0 :                                   mat_mo_coeff_im, keep_sparsity=.FALSE.)
    3193              : 
    3194            0 :             CALL dbcsr_desymmetrize(cosmat, cosmat_desymm)
    3195              : 
    3196            0 :             CALL dbcsr_desymmetrize(sinmat, sinmat_desymm)
    3197              : 
    3198              :             ! I.
    3199            0 :             CALL dbcsr_multiply('N', 'N', 1.0_dp, cosmat_desymm, mat_mo_coeff_re, 0.0_dp, tmp)
    3200              : 
    3201              :             ! I.1
    3202              :             CALL dbcsr_multiply('T', 'N', 1.0_dp, mat_mo_coeff_Gamma_all, tmp, 0.0_dp, &
    3203            0 :                                 matrix_berry_re_mo_mo(ikp)%matrix)
    3204              : 
    3205              :             ! II.
    3206            0 :             CALL dbcsr_multiply('N', 'N', 1.0_dp, sinmat_desymm, mat_mo_coeff_re, 0.0_dp, tmp)
    3207              : 
    3208              :             ! II.5
    3209              :             CALL dbcsr_multiply('T', 'N', 1.0_dp, mat_mo_coeff_Gamma_all, tmp, 0.0_dp, &
    3210            0 :                                 matrix_berry_im_mo_mo(ikp)%matrix)
    3211              : 
    3212              :             ! III.
    3213            0 :             CALL dbcsr_multiply('N', 'N', 1.0_dp, cosmat_desymm, mat_mo_coeff_im, 0.0_dp, tmp)
    3214              : 
    3215              :             ! III.7
    3216              :             CALL dbcsr_multiply('T', 'N', 1.0_dp, mat_mo_coeff_Gamma_all, tmp, 1.0_dp, &
    3217            0 :                                 matrix_berry_im_mo_mo(ikp)%matrix)
    3218              : 
    3219              :             ! IV.
    3220            0 :             CALL dbcsr_multiply('N', 'N', 1.0_dp, sinmat_desymm, mat_mo_coeff_im, 0.0_dp, tmp)
    3221              : 
    3222              :             ! IV.3
    3223              :             CALL dbcsr_multiply('T', 'N', -1.0_dp, mat_mo_coeff_Gamma_all, tmp, 1.0_dp, &
    3224            0 :                                 matrix_berry_re_mo_mo(ikp)%matrix)
    3225              : 
    3226              :          END IF
    3227              : 
    3228        11166 :          IF (abs_kpoint < eps_kpoint) THEN
    3229              : 
    3230            0 :             CALL dbcsr_scale(matrix_berry_im_mo_mo(ikp)%matrix, 1.0_dp/scale_kpoint)
    3231            0 :             CALL dbcsr_set(matrix_berry_re_mo_mo(ikp)%matrix, 0.0_dp)
    3232            0 :             CALL dbcsr_add_on_diag(matrix_berry_re_mo_mo(ikp)%matrix, 1.0_dp)
    3233              : 
    3234              :          END IF
    3235              : 
    3236              :       END DO
    3237              : 
    3238            6 :       CALL dbcsr_release_p(cosmat)
    3239            6 :       CALL dbcsr_release_p(sinmat)
    3240            6 :       CALL dbcsr_release_p(mat_mo_coeff_re)
    3241            6 :       CALL dbcsr_release_p(mat_mo_coeff_im)
    3242            6 :       CALL dbcsr_release_p(mat_mo_coeff_Gamma_all)
    3243            6 :       CALL dbcsr_release_p(mat_mo_coeff_Gamma_occ_and_GW)
    3244            6 :       CALL dbcsr_release_p(tmp)
    3245            6 :       CALL dbcsr_release_p(cosmat_desymm)
    3246            6 :       CALL dbcsr_release_p(sinmat_desymm)
    3247            6 :       DEALLOCATE (orb_basis_set_list)
    3248              : 
    3249            6 :       CALL release_neighbor_list_sets(sab_orb_mic)
    3250              : 
    3251            6 :       IF (do_aux_bas) THEN
    3252              : 
    3253            2 :          DEALLOCATE (gw_aux_basis_set_list)
    3254            2 :          CALL dbcsr_deallocate_matrix_set(matrix_s_aux_aux)
    3255            2 :          CALL dbcsr_deallocate_matrix_set(matrix_s_aux_orb)
    3256            2 :          CALL dbcsr_release_p(mat_work_aux_orb)
    3257            2 :          CALL dbcsr_release_p(mat_work_aux_orb_2)
    3258            2 :          CALL dbcsr_release_p(mat_mo_coeff_aux)
    3259            2 :          CALL dbcsr_release_p(mat_mo_coeff_aux_2)
    3260            2 :          CALL dbcsr_release_p(matrix_s_inv_aux_aux)
    3261            2 :          CALL dbcsr_release_p(matrix_P)
    3262            2 :          CALL dbcsr_release_p(matrix_P_sqrt)
    3263            2 :          CALL dbcsr_release_p(matrix_P_sqrt_inv)
    3264              : 
    3265            2 :          CALL cp_fm_struct_release(fm_struct_aux_aux)
    3266              : 
    3267            2 :          CALL cp_fm_release(fm_mat_s_aux_aux_inv)
    3268            2 :          CALL cp_fm_release(fm_mat_work_aux_aux)
    3269            2 :          CALL cp_fm_release(fm_mat_P)
    3270            2 :          CALL cp_fm_release(fm_mat_eigv_P)
    3271            2 :          CALL cp_fm_release(fm_mat_scaled_eigv_P)
    3272            2 :          CALL cp_fm_release(fm_mat_P_sqrt_inv)
    3273              : 
    3274              :          ! Deallocate the neighbor list structure
    3275            2 :          CALL release_neighbor_list_sets(sgwgw_list)
    3276            2 :          CALL release_neighbor_list_sets(sgworb_list)
    3277              : 
    3278              :       END IF
    3279              : 
    3280            6 :       CALL timestop(handle)
    3281              : 
    3282            6 :    END SUBROUTINE get_berry_phase
    3283              : 
    3284              : ! **************************************************************************************************
    3285              : !> \brief ...
    3286              : !> \param mat_mo_coeff_Gamma_occ_and_GW ...
    3287              : !> \param homo ...
    3288              : !> \param gw_corr_lev_virt ...
    3289              : ! **************************************************************************************************
    3290            6 :    SUBROUTINE remove_unnecessary_blocks(mat_mo_coeff_Gamma_occ_and_GW, homo, gw_corr_lev_virt)
    3291              : 
    3292              :       TYPE(dbcsr_type), POINTER                          :: mat_mo_coeff_Gamma_occ_and_GW
    3293              :       INTEGER, INTENT(IN)                                :: homo, gw_corr_lev_virt
    3294              : 
    3295              :       INTEGER                                            :: col, col_offset, row
    3296            6 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: data_block
    3297              :       TYPE(dbcsr_iterator_type)                          :: iter
    3298              : 
    3299            6 :       CALL dbcsr_iterator_start(iter, mat_mo_coeff_Gamma_occ_and_GW)
    3300              : 
    3301           27 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
    3302              : 
    3303              :          CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
    3304           21 :                                         col_offset=col_offset)
    3305              : 
    3306           27 :          IF (col_offset > homo + gw_corr_lev_virt) THEN
    3307              : 
    3308          532 :             data_block = 0.0_dp
    3309              : 
    3310              :          END IF
    3311              : 
    3312              :       END DO
    3313              : 
    3314            6 :       CALL dbcsr_iterator_stop(iter)
    3315              : 
    3316            6 :       CALL dbcsr_filter(mat_mo_coeff_Gamma_occ_and_GW, 1.0E-15_dp)
    3317              : 
    3318            6 :    END SUBROUTINE remove_unnecessary_blocks
    3319              : 
    3320              : ! **************************************************************************************************
    3321              : !> \brief ...
    3322              : !> \param delta_corr ...
    3323              : !> \param eps_inv_head ...
    3324              : !> \param kpoints ...
    3325              : !> \param qs_env ...
    3326              : !> \param matrix_berry_re_mo_mo ...
    3327              : !> \param matrix_berry_im_mo_mo ...
    3328              : !> \param homo ...
    3329              : !> \param gw_corr_lev_occ ...
    3330              : !> \param gw_corr_lev_virt ...
    3331              : !> \param para_env_RPA ...
    3332              : !> \param do_extra_kpoints ...
    3333              : ! **************************************************************************************************
    3334          260 :    SUBROUTINE kpoint_sum_for_eps_inv_head_Berry(delta_corr, eps_inv_head, kpoints, qs_env, matrix_berry_re_mo_mo, &
    3335          260 :                                                 matrix_berry_im_mo_mo, homo, gw_corr_lev_occ, gw_corr_lev_virt, &
    3336              :                                                 para_env_RPA, do_extra_kpoints)
    3337              : 
    3338              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
    3339              :          INTENT(INOUT)                                   :: delta_corr
    3340              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: eps_inv_head
    3341              :       TYPE(kpoint_type), POINTER                         :: kpoints
    3342              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3343              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN)       :: matrix_berry_re_mo_mo, &
    3344              :                                                             matrix_berry_im_mo_mo
    3345              :       INTEGER, INTENT(IN)                                :: homo, gw_corr_lev_occ, gw_corr_lev_virt
    3346              :       TYPE(mp_para_env_type), INTENT(IN), OPTIONAL       :: para_env_RPA
    3347              :       LOGICAL, INTENT(IN)                                :: do_extra_kpoints
    3348              : 
    3349              :       INTEGER                                            :: col, col_offset, col_size, i_col, i_row, &
    3350              :                                                             ikp, m_level, n_level_gw, nkp, row, &
    3351              :                                                             row_offset, row_size
    3352              :       REAL(KIND=dp)                                      :: abs_k_square, cell_volume, &
    3353              :                                                             check_int_one_over_ksq, contribution, &
    3354              :                                                             weight
    3355              :       REAL(KIND=dp), DIMENSION(3)                        :: correct_kpoint
    3356          260 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: delta_corr_extra
    3357          260 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: data_block
    3358              :       TYPE(cell_type), POINTER                           :: cell
    3359              :       TYPE(dbcsr_iterator_type)                          :: iter, iter_new
    3360              : 
    3361          260 :       CALL get_qs_env(qs_env=qs_env, cell=cell)
    3362              : 
    3363          260 :       CALL get_cell(cell=cell, deth=cell_volume)
    3364              : 
    3365          260 :       nkp = kpoints%nkp
    3366              : 
    3367          260 :       delta_corr = 0.0_dp
    3368              : 
    3369          260 :       IF (do_extra_kpoints) THEN
    3370          260 :          NULLIFY (delta_corr_extra)
    3371          780 :          ALLOCATE (delta_corr_extra(1 + homo - gw_corr_lev_occ:homo + gw_corr_lev_virt))
    3372         3800 :          delta_corr_extra = 0.0_dp
    3373              :       END IF
    3374              : 
    3375          260 :       check_int_one_over_ksq = 0.0_dp
    3376              : 
    3377       279620 :       DO ikp = 1, nkp
    3378              : 
    3379       279360 :          weight = kpoints%wkp(ikp)
    3380              : 
    3381      1117440 :          correct_kpoint(1:3) = twopi*kpoints%xkp(1:3, ikp)
    3382              : 
    3383       279360 :          abs_k_square = (correct_kpoint(1))**2 + (correct_kpoint(2))**2 + (correct_kpoint(3))**2
    3384              : 
    3385              :          ! cos part of the Berry phase
    3386       279360 :          CALL dbcsr_iterator_start(iter, matrix_berry_re_mo_mo(ikp)%matrix)
    3387       465120 :          DO WHILE (dbcsr_iterator_blocks_left(iter))
    3388              : 
    3389              :             CALL dbcsr_iterator_next_block(iter, row, col, data_block, &
    3390              :                                            row_size=row_size, col_size=col_size, &
    3391       185760 :                                            row_offset=row_offset, col_offset=col_offset)
    3392              : 
    3393      2880000 :             DO i_col = 1, col_size
    3394              : 
    3395     31916160 :                DO n_level_gw = 1 + homo - gw_corr_lev_occ, homo + gw_corr_lev_virt
    3396              : 
    3397     31730400 :                   IF (n_level_gw == i_col + col_offset - 1) THEN
    3398              : 
    3399     26619840 :                      DO i_row = 1, row_size
    3400              : 
    3401     24481440 :                         contribution = weight*(eps_inv_head(ikp) - 1.0_dp)/abs_k_square*(data_block(i_row, i_col))**2
    3402              : 
    3403     24481440 :                         m_level = i_row + row_offset - 1
    3404              : 
    3405              :                         ! we only compute the correction for n=m
    3406     24481440 :                         IF (m_level /= n_level_gw) CYCLE
    3407              : 
    3408      3862080 :                         IF (.NOT. do_extra_kpoints) THEN
    3409              : 
    3410            0 :                            delta_corr(n_level_gw) = delta_corr(n_level_gw) + contribution
    3411              : 
    3412              :                         ELSE
    3413              : 
    3414      1723680 :                            IF (ikp <= nkp*8/9) THEN
    3415              : 
    3416      1532160 :                               delta_corr(n_level_gw) = delta_corr(n_level_gw) + contribution
    3417              : 
    3418              :                            ELSE
    3419              : 
    3420       191520 :                               delta_corr_extra(n_level_gw) = delta_corr_extra(n_level_gw) + contribution
    3421              : 
    3422              :                            END IF
    3423              : 
    3424              :                         END IF
    3425              : 
    3426              :                      END DO
    3427              : 
    3428              :                   END IF
    3429              : 
    3430              :                END DO
    3431              : 
    3432              :             END DO
    3433              : 
    3434              :          END DO
    3435              : 
    3436       279360 :          CALL dbcsr_iterator_stop(iter)
    3437              : 
    3438              :          ! the same for the im. part of the Berry phase
    3439       279360 :          CALL dbcsr_iterator_start(iter_new, matrix_berry_im_mo_mo(ikp)%matrix)
    3440       465120 :          DO WHILE (dbcsr_iterator_blocks_left(iter_new))
    3441              : 
    3442              :             CALL dbcsr_iterator_next_block(iter_new, row, col, data_block, &
    3443              :                                            row_size=row_size, col_size=col_size, &
    3444       185760 :                                            row_offset=row_offset, col_offset=col_offset)
    3445              : 
    3446      2880000 :             DO i_col = 1, col_size
    3447              : 
    3448     31916160 :                DO n_level_gw = 1 + homo - gw_corr_lev_occ, homo + gw_corr_lev_virt
    3449              : 
    3450     31730400 :                   IF (n_level_gw == i_col + col_offset - 1) THEN
    3451              : 
    3452     26619840 :                      DO i_row = 1, row_size
    3453              : 
    3454     24481440 :                         m_level = i_row + row_offset - 1
    3455              : 
    3456     24481440 :                         contribution = weight*(eps_inv_head(ikp) - 1.0_dp)/abs_k_square*(data_block(i_row, i_col))**2
    3457              : 
    3458              :                         ! we only compute the correction for n=m
    3459     24481440 :                         IF (m_level /= n_level_gw) CYCLE
    3460              : 
    3461      3862080 :                         IF (.NOT. do_extra_kpoints) THEN
    3462              : 
    3463            0 :                            delta_corr(n_level_gw) = delta_corr(n_level_gw) + contribution
    3464              : 
    3465              :                         ELSE
    3466              : 
    3467      1723680 :                            IF (ikp <= nkp*8/9) THEN
    3468              : 
    3469      1532160 :                               delta_corr(n_level_gw) = delta_corr(n_level_gw) + contribution
    3470              : 
    3471              :                            ELSE
    3472              : 
    3473       191520 :                               delta_corr_extra(n_level_gw) = delta_corr_extra(n_level_gw) + contribution
    3474              : 
    3475              :                            END IF
    3476              : 
    3477              :                         END IF
    3478              : 
    3479              :                      END DO
    3480              : 
    3481              :                   END IF
    3482              : 
    3483              :                END DO
    3484              : 
    3485              :             END DO
    3486              : 
    3487              :          END DO
    3488              : 
    3489       279360 :          CALL dbcsr_iterator_stop(iter_new)
    3490              : 
    3491       838340 :          check_int_one_over_ksq = check_int_one_over_ksq + weight/abs_k_square
    3492              : 
    3493              :       END DO
    3494              : 
    3495              :       ! normalize by the cell volume
    3496         3800 :       delta_corr = delta_corr/cell_volume*fourpi
    3497              : 
    3498          260 :       check_int_one_over_ksq = check_int_one_over_ksq/cell_volume
    3499              : 
    3500          260 :       CALL para_env_RPA%sum(delta_corr)
    3501              : 
    3502          260 :       IF (do_extra_kpoints) THEN
    3503              : 
    3504         3800 :          delta_corr_extra = delta_corr_extra/cell_volume*fourpi
    3505              : 
    3506         7340 :          CALL para_env_RPA%sum(delta_corr_extra)
    3507              : 
    3508         3800 :          delta_corr(:) = delta_corr(:) + (delta_corr(:) - delta_corr_extra(:))
    3509              : 
    3510          260 :          DEALLOCATE (delta_corr_extra)
    3511              : 
    3512              :       END IF
    3513              : 
    3514          260 :    END SUBROUTINE kpoint_sum_for_eps_inv_head_Berry
    3515              : 
    3516              : ! **************************************************************************************************
    3517              : !> \brief ...
    3518              : !> \param eps_inv_head ...
    3519              : !> \param eps_head ...
    3520              : !> \param kpoints ...
    3521              : ! **************************************************************************************************
    3522          260 :    SUBROUTINE compute_eps_inv_head(eps_inv_head, eps_head, kpoints)
    3523              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
    3524              :          INTENT(OUT)                                     :: eps_inv_head
    3525              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: eps_head
    3526              :       TYPE(kpoint_type), POINTER                         :: kpoints
    3527              : 
    3528              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_eps_inv_head'
    3529              : 
    3530              :       INTEGER                                            :: handle, ikp, nkp
    3531              : 
    3532          260 :       CALL timeset(routineN, handle)
    3533              : 
    3534          260 :       nkp = kpoints%nkp
    3535              : 
    3536          780 :       ALLOCATE (eps_inv_head(nkp))
    3537              : 
    3538       279620 :       DO ikp = 1, nkp
    3539              : 
    3540       279620 :          eps_inv_head(ikp) = 1.0_dp/eps_head(ikp)
    3541              : 
    3542              :       END DO
    3543              : 
    3544          260 :       CALL timestop(handle)
    3545              : 
    3546          260 :    END SUBROUTINE compute_eps_inv_head
    3547              : 
    3548              : ! **************************************************************************************************
    3549              : !> \brief ...
    3550              : !> \param qs_env ...
    3551              : !> \param kpoints ...
    3552              : !> \param kp_grid ...
    3553              : !> \param num_kp_grids ...
    3554              : !> \param para_env ...
    3555              : !> \param h_inv ...
    3556              : !> \param nmo ...
    3557              : !> \param do_mo_coeff_Gamma_only ...
    3558              : !> \param do_extra_kpoints ...
    3559              : ! **************************************************************************************************
    3560            6 :    SUBROUTINE get_kpoints(qs_env, kpoints, kp_grid, num_kp_grids, para_env, h_inv, nmo, &
    3561              :                           do_mo_coeff_Gamma_only, do_extra_kpoints)
    3562              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3563              :       TYPE(kpoint_type), POINTER                         :: kpoints
    3564              :       INTEGER, DIMENSION(:), POINTER                     :: kp_grid
    3565              :       INTEGER, INTENT(IN)                                :: num_kp_grids
    3566              :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env
    3567              :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(INOUT)      :: h_inv
    3568              :       INTEGER, INTENT(IN)                                :: nmo
    3569              :       LOGICAL, INTENT(IN)                                :: do_mo_coeff_Gamma_only, do_extra_kpoints
    3570              : 
    3571              :       INTEGER                                            :: end_kp, i, i_grid_level, ix, iy, iz, &
    3572              :                                                             nkp_inner_grid, nkp_outer_grid, &
    3573              :                                                             npoints, start_kp
    3574              :       INTEGER, DIMENSION(3)                              :: outer_kp_grid
    3575              :       REAL(KIND=dp)                                      :: kpoint_weight_left, single_weight
    3576              :       REAL(KIND=dp), DIMENSION(3)                        :: kpt_latt, reducing_factor
    3577              :       TYPE(cell_type), POINTER                           :: cell
    3578            6 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    3579              : 
    3580            6 :       NULLIFY (kpoints, cell, particle_set)
    3581              : 
    3582              :       ! check whether kp_grid includes the Gamma point. If so, abort.
    3583            6 :       CPASSERT(MOD(kp_grid(1)*kp_grid(2)*kp_grid(3), 2) == 0)
    3584            6 :       IF (do_extra_kpoints) THEN
    3585            6 :          CPASSERT(do_mo_coeff_Gamma_only)
    3586              :       END IF
    3587              : 
    3588            6 :       IF (do_mo_coeff_Gamma_only) THEN
    3589              : 
    3590            6 :          outer_kp_grid(1) = kp_grid(1) - 1
    3591            6 :          outer_kp_grid(2) = kp_grid(2) - 1
    3592            6 :          outer_kp_grid(3) = kp_grid(3) - 1
    3593              : 
    3594            6 :          CALL get_qs_env(qs_env=qs_env, cell=cell, particle_set=particle_set)
    3595              : 
    3596            6 :          CALL get_cell(cell, h_inv=h_inv)
    3597              : 
    3598            6 :          CALL kpoint_create(kpoints)
    3599              : 
    3600            6 :          kpoints%kp_scheme = "GENERAL"
    3601            6 :          kpoints%symmetry = .FALSE.
    3602            6 :          kpoints%verbose = .FALSE.
    3603            6 :          kpoints%full_grid = .FALSE.
    3604            6 :          kpoints%use_real_wfn = .FALSE.
    3605            6 :          kpoints%eps_geo = 1.e-6_dp
    3606              :          npoints = kp_grid(1)*kp_grid(2)*kp_grid(3)/2 + &
    3607            6 :                    (num_kp_grids - 1)*((outer_kp_grid(1) + 1)/2*outer_kp_grid(2)*outer_kp_grid(3) - 1)
    3608              : 
    3609            6 :          IF (do_extra_kpoints) THEN
    3610              : 
    3611            6 :             CPASSERT(num_kp_grids == 1)
    3612            6 :             CPASSERT(MOD(kp_grid(1), 4) == 0)
    3613            6 :             CPASSERT(MOD(kp_grid(2), 4) == 0)
    3614            6 :             CPASSERT(MOD(kp_grid(3), 4) == 0)
    3615              : 
    3616              :          END IF
    3617              : 
    3618            6 :          IF (do_extra_kpoints) THEN
    3619              : 
    3620            6 :             npoints = kp_grid(1)*kp_grid(2)*kp_grid(3)/2 + kp_grid(1)*kp_grid(2)*kp_grid(3)/2/8
    3621              : 
    3622              :          END IF
    3623              : 
    3624            6 :          kpoints%full_grid = .TRUE.
    3625            6 :          kpoints%nkp = npoints
    3626           30 :          ALLOCATE (kpoints%xkp(3, npoints), kpoints%wkp(npoints))
    3627        44646 :          kpoints%xkp = 0.0_dp
    3628        11166 :          kpoints%wkp = 0.0_dp
    3629              : 
    3630            6 :          nkp_outer_grid = outer_kp_grid(1)*outer_kp_grid(2)*outer_kp_grid(3)
    3631            6 :          nkp_inner_grid = kp_grid(1)*kp_grid(2)*kp_grid(3)
    3632              : 
    3633            6 :          i = 0
    3634           24 :          reducing_factor(:) = 1.0_dp
    3635              :          kpoint_weight_left = 1.0_dp
    3636              : 
    3637              :          ! the outer grids
    3638            6 :          DO i_grid_level = 1, num_kp_grids - 1
    3639              : 
    3640            0 :             single_weight = kpoint_weight_left/REAL(nkp_outer_grid, KIND=dp)
    3641              : 
    3642            0 :             start_kp = i + 1
    3643              : 
    3644            0 :             DO ix = 1, outer_kp_grid(1)
    3645            0 :                DO iy = 1, outer_kp_grid(2)
    3646            0 :                   DO iz = 1, outer_kp_grid(3)
    3647              : 
    3648              :                      ! exclude Gamma
    3649            0 :                      IF (2*ix - outer_kp_grid(1) - 1 == 0 .AND. 2*iy - outer_kp_grid(2) - 1 == 0 .AND. &
    3650              :                          2*iz - outer_kp_grid(3) - 1 == 0) CYCLE
    3651              : 
    3652              :                      ! use time reversal symmetry k<->-k
    3653            0 :                      IF (2*ix - outer_kp_grid(1) - 1 < 0) CYCLE
    3654              : 
    3655            0 :                      i = i + 1
    3656              :                      kpt_latt(1) = REAL(2*ix - outer_kp_grid(1) - 1, KIND=dp)/(2._dp*REAL(outer_kp_grid(1), KIND=dp)) &
    3657            0 :                                    *reducing_factor(1)
    3658              :                      kpt_latt(2) = REAL(2*iy - outer_kp_grid(2) - 1, KIND=dp)/(2._dp*REAL(outer_kp_grid(2), KIND=dp)) &
    3659            0 :                                    *reducing_factor(2)
    3660              :                      kpt_latt(3) = REAL(2*iz - outer_kp_grid(3) - 1, KIND=dp)/(2._dp*REAL(outer_kp_grid(3), KIND=dp)) &
    3661            0 :                                    *reducing_factor(3)
    3662            0 :                      kpoints%xkp(1:3, i) = MATMUL(TRANSPOSE(h_inv), kpt_latt(:))
    3663              : 
    3664            0 :                      IF (2*ix - outer_kp_grid(1) - 1 == 0) THEN
    3665            0 :                         kpoints%wkp(i) = single_weight
    3666              :                      ELSE
    3667            0 :                         kpoints%wkp(i) = 2._dp*single_weight
    3668              :                      END IF
    3669              : 
    3670              :                   END DO
    3671              :                END DO
    3672              :             END DO
    3673              : 
    3674            0 :             end_kp = i
    3675              : 
    3676            0 :             kpoint_weight_left = kpoint_weight_left - SUM(kpoints%wkp(start_kp:end_kp))
    3677              : 
    3678            0 :             reducing_factor(1) = reducing_factor(1)/REAL(outer_kp_grid(1), KIND=dp)
    3679            0 :             reducing_factor(2) = reducing_factor(2)/REAL(outer_kp_grid(2), KIND=dp)
    3680            6 :             reducing_factor(3) = reducing_factor(3)/REAL(outer_kp_grid(3), KIND=dp)
    3681              : 
    3682              :          END DO
    3683              : 
    3684            6 :          single_weight = kpoint_weight_left/REAL(nkp_inner_grid, KIND=dp)
    3685              : 
    3686              :          ! the inner grid
    3687           94 :          DO ix = 1, kp_grid(1)
    3688         1406 :             DO iy = 1, kp_grid(2)
    3689        21240 :                DO iz = 1, kp_grid(3)
    3690              : 
    3691              :                   ! use time reversal symmetry k<->-k
    3692        19840 :                   IF (2*ix - kp_grid(1) - 1 < 0) CYCLE
    3693              : 
    3694         9920 :                   i = i + 1
    3695         9920 :                   kpt_latt(1) = REAL(2*ix - kp_grid(1) - 1, KIND=dp)/(2._dp*REAL(kp_grid(1), KIND=dp))*reducing_factor(1)
    3696         9920 :                   kpt_latt(2) = REAL(2*iy - kp_grid(2) - 1, KIND=dp)/(2._dp*REAL(kp_grid(2), KIND=dp))*reducing_factor(2)
    3697         9920 :                   kpt_latt(3) = REAL(2*iz - kp_grid(3) - 1, KIND=dp)/(2._dp*REAL(kp_grid(3), KIND=dp))*reducing_factor(3)
    3698              : 
    3699        39680 :                   kpoints%xkp(1:3, i) = MATMUL(TRANSPOSE(h_inv), kpt_latt(:))
    3700              : 
    3701        21152 :                   kpoints%wkp(i) = 2._dp*single_weight
    3702              : 
    3703              :                END DO
    3704              :             END DO
    3705              :          END DO
    3706              : 
    3707            6 :          IF (do_extra_kpoints) THEN
    3708              : 
    3709            6 :             single_weight = kpoint_weight_left/REAL(kp_grid(1)*kp_grid(2)*kp_grid(3)/8, KIND=dp)
    3710              : 
    3711           50 :             DO ix = 1, kp_grid(1)/2
    3712          378 :                DO iy = 1, kp_grid(2)/2
    3713         2852 :                   DO iz = 1, kp_grid(3)/2
    3714              : 
    3715              :                      ! use time reversal symmetry k<->-k
    3716         2480 :                      IF (2*ix - kp_grid(1)/2 - 1 < 0) CYCLE
    3717              : 
    3718         1240 :                      i = i + 1
    3719         1240 :                      kpt_latt(1) = REAL(2*ix - kp_grid(1)/2 - 1, KIND=dp)/(REAL(kp_grid(1), KIND=dp))
    3720         1240 :                      kpt_latt(2) = REAL(2*iy - kp_grid(2)/2 - 1, KIND=dp)/(REAL(kp_grid(2), KIND=dp))
    3721         1240 :                      kpt_latt(3) = REAL(2*iz - kp_grid(3)/2 - 1, KIND=dp)/(REAL(kp_grid(3), KIND=dp))
    3722              : 
    3723         4960 :                      kpoints%xkp(1:3, i) = MATMUL(TRANSPOSE(h_inv), kpt_latt(:))
    3724              : 
    3725         2808 :                      kpoints%wkp(i) = 2._dp*single_weight
    3726              : 
    3727              :                   END DO
    3728              :                END DO
    3729              :             END DO
    3730              : 
    3731              :          END IF
    3732              : 
    3733              :          ! default: no symmetry settings
    3734        11178 :          ALLOCATE (kpoints%kp_sym(kpoints%nkp))
    3735        11166 :          DO i = 1, kpoints%nkp
    3736        11160 :             NULLIFY (kpoints%kp_sym(i)%kpoint_sym)
    3737        11166 :             CALL kpoint_sym_create(kpoints%kp_sym(i)%kpoint_sym)
    3738              :          END DO
    3739              : 
    3740              :       ELSE
    3741              : 
    3742              :          BLOCK
    3743              :             TYPE(qs_environment_type), POINTER :: qs_env_kp_Gamma_only
    3744            0 :             CALL create_kp_from_gamma(qs_env, qs_env_kp_Gamma_only)
    3745              : 
    3746            0 :             CALL get_qs_env(qs_env=qs_env, cell=cell, particle_set=particle_set)
    3747              : 
    3748              :             CALL calculate_kp_orbitals(qs_env_kp_Gamma_only, kpoints, "MONKHORST-PACK", nadd=nmo, mp_grid=kp_grid(1:3), &
    3749            0 :                                        group_size_ext=para_env%num_pe)
    3750              : 
    3751            0 :             CALL qs_env_release(qs_env_kp_Gamma_only)
    3752            0 :             DEALLOCATE (qs_env_kp_Gamma_only)
    3753              :          END BLOCK
    3754              : 
    3755              :       END IF
    3756              : 
    3757            6 :    END SUBROUTINE get_kpoints
    3758              : 
    3759              : ! **************************************************************************************************
    3760              : !> \brief ...
    3761              : !> \param vec_Sigma_c_gw ...
    3762              : !> \param Eigenval_DFT ...
    3763              : !> \param eps_eigenval ...
    3764              : ! **************************************************************************************************
    3765           10 :    PURE SUBROUTINE average_degenerate_levels(vec_Sigma_c_gw, Eigenval_DFT, eps_eigenval)
    3766              :       COMPLEX(KIND=dp), DIMENSION(:, :, :), &
    3767              :          INTENT(INOUT)                                   :: vec_Sigma_c_gw
    3768              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: Eigenval_DFT
    3769              :       REAL(KIND=dp), INTENT(IN)                          :: eps_eigenval
    3770              : 
    3771           10 :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:)        :: avg_self_energy
    3772              :       INTEGER :: degeneracy, first_degenerate_level, i_deg_level, i_level_gw, j_deg_level, jquad, &
    3773              :          num_deg_levels, num_integ_points, num_levels_gw
    3774           10 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: list_degenerate_levels
    3775              : 
    3776           10 :       num_levels_gw = SIZE(vec_Sigma_c_gw, 1)
    3777              : 
    3778           30 :       ALLOCATE (list_degenerate_levels(num_levels_gw))
    3779          130 :       list_degenerate_levels = 1
    3780              : 
    3781           10 :       num_integ_points = SIZE(vec_Sigma_c_gw, 2)
    3782              : 
    3783           30 :       ALLOCATE (avg_self_energy(num_integ_points))
    3784              : 
    3785          120 :       DO i_level_gw = 2, num_levels_gw
    3786              : 
    3787          120 :          IF (ABS(Eigenval_DFT(i_level_gw) - Eigenval_DFT(i_level_gw - 1)) < eps_eigenval) THEN
    3788              : 
    3789            0 :             list_degenerate_levels(i_level_gw) = list_degenerate_levels(i_level_gw - 1)
    3790              : 
    3791              :          ELSE
    3792              : 
    3793          110 :             list_degenerate_levels(i_level_gw) = list_degenerate_levels(i_level_gw - 1) + 1
    3794              : 
    3795              :          END IF
    3796              : 
    3797              :       END DO
    3798              : 
    3799           10 :       num_deg_levels = list_degenerate_levels(num_levels_gw)
    3800              : 
    3801          130 :       DO i_deg_level = 1, num_deg_levels
    3802              : 
    3803              :          degeneracy = 0
    3804              : 
    3805         1624 :          DO i_level_gw = 1, num_levels_gw
    3806              : 
    3807         1504 :             IF (degeneracy == 0 .AND. i_deg_level == list_degenerate_levels(i_level_gw)) THEN
    3808              : 
    3809          120 :                first_degenerate_level = i_level_gw
    3810              : 
    3811              :             END IF
    3812              : 
    3813         1624 :             IF (i_deg_level == list_degenerate_levels(i_level_gw)) THEN
    3814              : 
    3815          120 :                degeneracy = degeneracy + 1
    3816              : 
    3817              :             END IF
    3818              : 
    3819              :          END DO
    3820              : 
    3821         3136 :          DO jquad = 1, num_integ_points
    3822              : 
    3823              :             avg_self_energy(jquad) = SUM(vec_Sigma_c_gw(first_degenerate_level:first_degenerate_level + degeneracy - 1, jquad, 1)) &
    3824         6152 :                                      /REAL(degeneracy, KIND=dp)
    3825              : 
    3826              :          END DO
    3827              : 
    3828          250 :          DO j_deg_level = 0, degeneracy - 1
    3829              : 
    3830         3256 :             vec_Sigma_c_gw(first_degenerate_level + j_deg_level, :, 1) = avg_self_energy(:)
    3831              : 
    3832              :          END DO
    3833              : 
    3834              :       END DO
    3835              : 
    3836           10 :    END SUBROUTINE average_degenerate_levels
    3837              : 
    3838              : ! **************************************************************************************************
    3839              : !> \brief ...
    3840              : !> \param vec_gw_energ ...
    3841              : !> \param vec_omega_fit_gw ...
    3842              : !> \param z_value ...
    3843              : !> \param m_value ...
    3844              : !> \param vec_Sigma_c_gw ...
    3845              : !> \param vec_Sigma_x_minus_vxc_gw ...
    3846              : !> \param Eigenval ...
    3847              : !> \param Eigenval_scf ...
    3848              : !> \param n_level_gw ...
    3849              : !> \param gw_corr_lev_occ ...
    3850              : !> \param gw_corr_lev_vir ...
    3851              : !> \param num_poles ...
    3852              : !> \param num_fit_points ...
    3853              : !> \param crossing_search ...
    3854              : !> \param homo ...
    3855              : !> \param stop_crit ...
    3856              : !> \param fermi_level_offset ...
    3857              : !> \param do_gw_im_time ...
    3858              : ! **************************************************************************************************
    3859          568 :    SUBROUTINE fit_and_continuation_2pole(vec_gw_energ, vec_omega_fit_gw, &
    3860         1136 :                                          z_value, m_value, vec_Sigma_c_gw, vec_Sigma_x_minus_vxc_gw, &
    3861         1136 :                                          Eigenval, Eigenval_scf, n_level_gw, &
    3862              :                                          gw_corr_lev_occ, gw_corr_lev_vir, num_poles, &
    3863              :                                          num_fit_points, crossing_search, homo, stop_crit, &
    3864              :                                          fermi_level_offset, do_gw_im_time)
    3865              : 
    3866              :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: vec_gw_energ, vec_omega_fit_gw, z_value, &
    3867              :                                                             m_value
    3868              :       COMPLEX(KIND=dp), DIMENSION(:, :), INTENT(IN)      :: vec_Sigma_c_gw
    3869              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: vec_Sigma_x_minus_vxc_gw, Eigenval, &
    3870              :                                                             Eigenval_scf
    3871              :       INTEGER, INTENT(IN)                                :: n_level_gw, gw_corr_lev_occ, &
    3872              :                                                             gw_corr_lev_vir, num_poles, &
    3873              :                                                             num_fit_points, crossing_search, homo
    3874              :       REAL(KIND=dp), INTENT(IN)                          :: stop_crit, fermi_level_offset
    3875              :       LOGICAL, INTENT(IN)                                :: do_gw_im_time
    3876              : 
    3877              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'fit_and_continuation_2pole'
    3878              : 
    3879              :       COMPLEX(KIND=dp)                                   :: func_val, rho1
    3880          568 :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:)        :: dLambda, dLambda_2, Lambda, &
    3881          568 :                                                             Lambda_without_offset, vec_b_gw, &
    3882          568 :                                                             vec_b_gw_copy
    3883          568 :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :)     :: mat_A_gw, mat_B_gw
    3884              :       INTEGER                                            :: handle4, ierr, iii, iiter, info, &
    3885              :                                                             integ_range, jjj, jquad, kkk, &
    3886              :                                                             max_iter_fit, n_level_gw_ref, num_var, &
    3887              :                                                             xpos
    3888          568 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: ipiv
    3889              :       LOGICAL                                            :: could_exit
    3890              :       REAL(KIND=dp) :: chi2, chi2_old, delta, deriv_val_real, e_fermi, gw_energ, Ldown, &
    3891              :          level_energ_GW, Lup, range_step, ScalParam, sign_occ_virt, stat_error
    3892          568 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: Lambda_Im, Lambda_Re, stat_errors, &
    3893          568 :                                                             vec_N_gw, vec_omega_fit_gw_sign
    3894          568 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: mat_N_gw
    3895              : 
    3896          568 :       max_iter_fit = 10000
    3897              : 
    3898          568 :       num_var = 2*num_poles + 1
    3899         1704 :       ALLOCATE (Lambda(num_var))
    3900          568 :       Lambda = z_zero
    3901         1136 :       ALLOCATE (Lambda_without_offset(num_var))
    3902          568 :       Lambda_without_offset = z_zero
    3903         1704 :       ALLOCATE (Lambda_Re(num_var))
    3904          568 :       Lambda_Re = 0.0_dp
    3905         1136 :       ALLOCATE (Lambda_Im(num_var))
    3906          568 :       Lambda_Im = 0.0_dp
    3907              : 
    3908         1704 :       ALLOCATE (vec_omega_fit_gw_sign(num_fit_points))
    3909              : 
    3910          568 :       IF (n_level_gw <= gw_corr_lev_occ) THEN
    3911              :          sign_occ_virt = -1.0_dp
    3912              :       ELSE
    3913          405 :          sign_occ_virt = 1.0_dp
    3914              :       END IF
    3915              : 
    3916          568 :       n_level_gw_ref = n_level_gw + homo - gw_corr_lev_occ
    3917              : 
    3918         7324 :       DO jquad = 1, num_fit_points
    3919         7324 :          vec_omega_fit_gw_sign(jquad) = ABS(vec_omega_fit_gw(jquad))*sign_occ_virt
    3920              :       END DO
    3921              : 
    3922              :       ! initial guess
    3923          568 :       range_step = (vec_omega_fit_gw_sign(num_fit_points) - vec_omega_fit_gw_sign(1))/(num_poles - 1)
    3924         1704 :       DO iii = 1, num_poles
    3925         1704 :          Lambda_Im(2*iii + 1) = vec_omega_fit_gw_sign(1) + (iii - 1)*range_step
    3926              :       END DO
    3927          568 :       range_step = (vec_omega_fit_gw_sign(num_fit_points) - vec_omega_fit_gw_sign(1))/num_poles
    3928         1704 :       DO iii = 1, num_poles
    3929         1704 :          Lambda_Re(2*iii + 1) = ABS(vec_omega_fit_gw_sign(1) + (iii - 0.5_dp)*range_step)
    3930              :       END DO
    3931              : 
    3932         3408 :       DO iii = 1, num_var
    3933         3408 :          Lambda(iii) = Lambda_Re(iii) + gaussi*Lambda_Im(iii)
    3934              :       END DO
    3935              : 
    3936              :       CALL calc_chi2(chi2_old, Lambda, vec_Sigma_c_gw, vec_omega_fit_gw_sign, num_poles, &
    3937          568 :                      num_fit_points, n_level_gw)
    3938              : 
    3939         2272 :       ALLOCATE (mat_A_gw(num_poles + 1, num_poles + 1))
    3940         1704 :       ALLOCATE (vec_b_gw(num_poles + 1))
    3941         1704 :       ALLOCATE (ipiv(num_poles + 1))
    3942          568 :       mat_A_gw = z_zero
    3943          568 :       vec_b_gw = 0.0_dp
    3944              : 
    3945         2272 :       mat_A_gw(1:num_poles + 1, 1) = z_one
    3946          568 :       integ_range = num_fit_points/num_poles
    3947         2272 :       DO kkk = 1, num_poles + 1
    3948         1704 :          xpos = (kkk - 1)*integ_range + 1
    3949         1704 :          xpos = MIN(xpos, num_fit_points)
    3950              :          ! calculate coefficient at this point
    3951         5112 :          DO iii = 1, num_poles
    3952         3408 :             jjj = iii*2
    3953              :             func_val = z_one/(gaussi*vec_omega_fit_gw_sign(xpos) - &
    3954         3408 :                               CMPLX(Lambda_Re(jjj + 1), Lambda_Im(jjj + 1), KIND=dp))
    3955         5112 :             mat_A_gw(kkk, iii + 1) = func_val
    3956              :          END DO
    3957         2272 :          vec_b_gw(kkk) = vec_Sigma_c_gw(n_level_gw, xpos)
    3958              :       END DO
    3959              : 
    3960              :       ! Solve system of linear equations
    3961          568 :       CALL ZGETRF(num_poles + 1, num_poles + 1, mat_A_gw, num_poles + 1, ipiv, info)
    3962              : 
    3963          568 :       CALL ZGETRS('N', num_poles + 1, 1, mat_A_gw, num_poles + 1, ipiv, vec_b_gw, num_poles + 1, info)
    3964              : 
    3965          568 :       Lambda_Re(1) = REAL(vec_b_gw(1))
    3966          568 :       Lambda_Im(1) = AIMAG(vec_b_gw(1))
    3967         1704 :       DO iii = 1, num_poles
    3968         1136 :          jjj = iii*2
    3969         1136 :          Lambda_Re(jjj) = REAL(vec_b_gw(iii + 1))
    3970         1704 :          Lambda_Im(jjj) = AIMAG(vec_b_gw(iii + 1))
    3971              :       END DO
    3972              : 
    3973          568 :       DEALLOCATE (mat_A_gw)
    3974          568 :       DEALLOCATE (vec_b_gw)
    3975          568 :       DEALLOCATE (ipiv)
    3976              : 
    3977         2272 :       ALLOCATE (mat_A_gw(num_var*2, num_var*2))
    3978         2272 :       ALLOCATE (mat_B_gw(num_fit_points, num_var*2))
    3979         1704 :       ALLOCATE (dLambda(num_fit_points))
    3980         1136 :       ALLOCATE (dLambda_2(num_fit_points))
    3981         1704 :       ALLOCATE (vec_b_gw(num_var*2))
    3982         1136 :       ALLOCATE (vec_b_gw_copy(num_var*2))
    3983         1704 :       ALLOCATE (ipiv(num_var*2))
    3984              : 
    3985              :       ScalParam = 0.01_dp
    3986              :       Ldown = 1.5_dp
    3987              :       Lup = 10.0_dp
    3988              :       could_exit = .FALSE.
    3989              : 
    3990              :       ! iteration loop for fitting
    3991      1163654 :       DO iiter = 1, max_iter_fit
    3992              : 
    3993      1163619 :          CALL timeset(routineN//"_fit_loop_1", handle4)
    3994              : 
    3995              :          ! calc delta lambda
    3996      6981714 :          DO iii = 1, num_var
    3997      6981714 :             Lambda(iii) = Lambda_Re(iii) + gaussi*Lambda_Im(iii)
    3998              :          END DO
    3999      1163619 :          dLambda = z_zero
    4000              : 
    4001     14961560 :          DO kkk = 1, num_fit_points
    4002     13797941 :             func_val = Lambda(1)
    4003     41393823 :             DO iii = 1, num_poles
    4004     27595882 :                jjj = iii*2
    4005     41393823 :                func_val = func_val + Lambda(jjj)/(vec_omega_fit_gw_sign(kkk)*gaussi - Lambda(jjj + 1))
    4006              :             END DO
    4007     14961560 :             dLambda(kkk) = vec_Sigma_c_gw(n_level_gw, kkk) - func_val
    4008              :          END DO
    4009     14961560 :          rho1 = SUM(dLambda*dLambda)
    4010              : 
    4011              :          ! fill matrix
    4012      1163619 :          mat_B_gw = z_zero
    4013     14961560 :          DO iii = 1, num_fit_points
    4014     13797941 :             mat_B_gw(iii, 1) = 1.0_dp
    4015     14961560 :             mat_B_gw(iii, num_var + 1) = gaussi
    4016              :          END DO
    4017      3490857 :          DO iii = 1, num_poles
    4018      2327238 :             jjj = iii*2
    4019     31086739 :             DO kkk = 1, num_fit_points
    4020     27595882 :                mat_B_gw(kkk, jjj) = 1.0_dp/(gaussi*vec_omega_fit_gw_sign(kkk) - Lambda(jjj + 1))
    4021     27595882 :                mat_B_gw(kkk, jjj + num_var) = gaussi/(gaussi*vec_omega_fit_gw_sign(kkk) - Lambda(jjj + 1))
    4022     27595882 :                mat_B_gw(kkk, jjj + 1) = Lambda(jjj)/(gaussi*vec_omega_fit_gw_sign(kkk) - Lambda(jjj + 1))**2
    4023              :                mat_B_gw(kkk, jjj + 1 + num_var) = (-Lambda_Im(jjj) + gaussi*Lambda_Re(jjj))/ &
    4024     29923120 :                                                   (gaussi*vec_omega_fit_gw_sign(kkk) - Lambda(jjj + 1))**2
    4025              :             END DO
    4026              :          END DO
    4027              : 
    4028      1163619 :          CALL timestop(handle4)
    4029              : 
    4030      1163619 :          CALL timeset(routineN//"_fit_matmul_1", handle4)
    4031              : 
    4032              :          CALL zgemm('C', 'N', num_var*2, num_var*2, num_fit_points, z_one, mat_B_gw, num_fit_points, mat_B_gw, num_fit_points, &
    4033      1163619 :                     z_zero, mat_A_gw, num_var*2)
    4034      1163619 :          CALL timestop(handle4)
    4035              : 
    4036      1163619 :          CALL timeset(routineN//"_fit_zgemv_1", handle4)
    4037              :          CALL zgemv('C', num_fit_points, num_var*2, z_one, mat_B_gw, num_fit_points, dLambda, 1, &
    4038      1163619 :                     z_zero, vec_b_gw, 1)
    4039              : 
    4040      1163619 :          CALL timestop(handle4)
    4041              : 
    4042              :          ! scale diagonal elements of a_mat
    4043     12799809 :          DO iii = 1, num_var*2
    4044     12799809 :             mat_A_gw(iii, iii) = mat_A_gw(iii, iii) + ScalParam*mat_A_gw(iii, iii)
    4045              :          END DO
    4046              : 
    4047              :          ! solve linear system
    4048      1163619 :          ierr = 0
    4049      1163619 :          ipiv = 0
    4050              : 
    4051      1163619 :          CALL timeset(routineN//"_fit_lin_eq_2", handle4)
    4052              : 
    4053      1163619 :          CALL ZGETRF(2*num_var, 2*num_var, mat_A_gw, 2*num_var, ipiv, info)
    4054              : 
    4055      1163619 :          CALL ZGETRS('N', 2*num_var, 1, mat_A_gw, 2*num_var, ipiv, vec_b_gw, 2*num_var, info)
    4056              : 
    4057      1163619 :          CALL timestop(handle4)
    4058              : 
    4059      6981714 :          DO iii = 1, num_var
    4060      6981714 :             Lambda(iii) = Lambda_Re(iii) + gaussi*Lambda_Im(iii) + vec_b_gw(iii) + vec_b_gw(iii + num_var)
    4061              :          END DO
    4062              : 
    4063              :          ! calculate chi2
    4064              :          CALL calc_chi2(chi2, Lambda, vec_Sigma_c_gw, vec_omega_fit_gw_sign, num_poles, &
    4065      1163619 :                         num_fit_points, n_level_gw)
    4066              : 
    4067              :          ! if the fit is already super accurate, exit. otherwise maybe issues when dividing by 0
    4068      1163619 :          IF (chi2 < 1.0E-30_dp) EXIT
    4069              : 
    4070      1163573 :          IF (chi2 < chi2_old) THEN
    4071       987924 :             ScalParam = MAX(ScalParam/Ldown, 1E-12_dp)
    4072      5927544 :             DO iii = 1, num_var
    4073      4939620 :                Lambda_Re(iii) = Lambda_Re(iii) + REAL(vec_b_gw(iii) + vec_b_gw(iii + num_var))
    4074      5927544 :                Lambda_Im(iii) = Lambda_Im(iii) + AIMAG(vec_b_gw(iii) + vec_b_gw(iii + num_var))
    4075              :             END DO
    4076       987924 :             IF (chi2_old/chi2 - 1.0_dp < stop_crit) could_exit = .TRUE.
    4077       987924 :             chi2_old = chi2
    4078              :          ELSE
    4079       175649 :             ScalParam = ScalParam*Lup
    4080              :          END IF
    4081      1163573 :          IF (ScalParam > 100.0_dp .AND. could_exit) EXIT
    4082              : 
    4083      4655044 :          IF (ScalParam > 1E+10_dp) ScalParam = 1E-4_dp
    4084              : 
    4085              :       END DO
    4086              : 
    4087          568 :       IF (.NOT. do_gw_im_time) THEN
    4088              : 
    4089              :          ! change a_0 [Lambda(1)], so that Sigma(i0) = Fit(i0)
    4090              :          ! do not do this for imaginary time since we do not have many fit points and the fit should be perfect
    4091          420 :          func_val = Lambda(1)
    4092         1260 :          DO iii = 1, num_poles
    4093          840 :             jjj = iii*2
    4094              :             ! calculate value of the fit function
    4095         1260 :             func_val = func_val + Lambda(jjj)/(-Lambda(jjj + 1))
    4096              :          END DO
    4097              : 
    4098          420 :          Lambda_Re(1) = Lambda_Re(1) - REAL(func_val) + REAL(vec_Sigma_c_gw(n_level_gw, num_fit_points))
    4099          420 :          Lambda_Im(1) = Lambda_Im(1) - AIMAG(func_val) + AIMAG(vec_Sigma_c_gw(n_level_gw, num_fit_points))
    4100              : 
    4101              :       END IF
    4102              : 
    4103         3408 :       Lambda_without_offset(:) = Lambda(:)
    4104              : 
    4105         3408 :       DO iii = 1, num_var
    4106         3408 :          Lambda(iii) = CMPLX(Lambda_Re(iii), Lambda_Im(iii), KIND=dp)
    4107              :       END DO
    4108              : 
    4109          568 :       IF (do_gw_im_time) THEN
    4110              :          ! for cubic-scaling GW, we have one Green's function for occ and virt states with the Fermi level
    4111              :          ! in the middle of homo and lumo
    4112          148 :          e_fermi = 0.5_dp*(Eigenval(homo) + Eigenval(homo + 1))
    4113              :       ELSE
    4114              :          ! in case of O(N^4) GW, we have the Fermi level differently for occ and virt states, see
    4115              :          ! Fig. 1 in JCTC 12, 3623-3635 (2016)
    4116          420 :          IF (n_level_gw <= gw_corr_lev_occ) THEN
    4117          552 :             e_fermi = MAXVAL(Eigenval(homo - gw_corr_lev_occ + 1:homo)) + fermi_level_offset
    4118              :          ELSE
    4119         3432 :             e_fermi = MINVAL(Eigenval(homo + 1:homo + gw_corr_lev_vir)) - fermi_level_offset
    4120              :          END IF
    4121              :       END IF
    4122              : 
    4123              :       ! either Z-shot or Newton/bisection crossing search for evaluating Sigma_c
    4124          568 :       IF (crossing_search == ri_rpa_g0w0_crossing_z_shot .OR. &
    4125              :           crossing_search == ri_rpa_g0w0_crossing_newton) THEN
    4126              : 
    4127              :          ! calculate Sigma_c_fit(e_n) and Z
    4128          568 :          func_val = Lambda(1)
    4129          568 :          z_value(n_level_gw) = 1.0_dp
    4130         1704 :          DO iii = 1, num_poles
    4131         1136 :             jjj = iii*2
    4132              :             z_value(n_level_gw) = z_value(n_level_gw) + REAL(Lambda(jjj)/ &
    4133         1136 :                                                              (Eigenval(n_level_gw_ref) - e_fermi - Lambda(jjj + 1))**2)
    4134         1704 :             func_val = func_val + Lambda(jjj)/(Eigenval(n_level_gw_ref) - e_fermi - Lambda(jjj + 1))
    4135              :          END DO
    4136              :          ! m is the slope of the correl self-energy
    4137          568 :          m_value(n_level_gw) = 1.0_dp - z_value(n_level_gw)
    4138          568 :          z_value(n_level_gw) = 1.0_dp/z_value(n_level_gw)
    4139          568 :          gw_energ = REAL(func_val)
    4140          568 :          vec_gw_energ(n_level_gw) = gw_energ
    4141              : 
    4142              :          ! in case one wants to do Newton-Raphson on top of the Z-shot
    4143          568 :          IF (crossing_search == ri_rpa_g0w0_crossing_newton) THEN
    4144              : 
    4145              :             level_energ_GW = (Eigenval_scf(n_level_gw_ref) - &
    4146              :                               m_value(n_level_gw)*Eigenval(n_level_gw_ref) + &
    4147              :                               vec_gw_energ(n_level_gw) + &
    4148              :                               vec_Sigma_x_minus_vxc_gw(n_level_gw_ref))* &
    4149           32 :                              z_value(n_level_gw)
    4150              : 
    4151              :             ! Newton-Raphson iteration
    4152          272 :             DO kkk = 1, 1000
    4153              : 
    4154              :                ! calculate the value of the fit function for level_energ_GW
    4155          272 :                func_val = Lambda(1)
    4156          272 :                z_value(n_level_gw) = 1.0_dp
    4157          816 :                DO iii = 1, num_poles
    4158          544 :                   jjj = iii*2
    4159          816 :                   func_val = func_val + Lambda(jjj)/(level_energ_GW - e_fermi - Lambda(jjj + 1))
    4160              :                END DO
    4161              : 
    4162              :                ! calculate the derivative of the fit function for level_energ_GW
    4163          272 :                deriv_val_real = -1.0_dp
    4164          816 :                DO iii = 1, num_poles
    4165          544 :                   jjj = iii*2
    4166              :                   deriv_val_real = deriv_val_real + REAL(Lambda(jjj))/((ABS(level_energ_GW - e_fermi - Lambda(jjj + 1)))**2) &
    4167              :                                    - (REAL(Lambda(jjj))*(level_energ_GW - e_fermi) - REAL(Lambda(jjj)*CONJG(Lambda(jjj + 1))))* &
    4168              :                                    2.0_dp*(level_energ_GW - e_fermi - REAL(Lambda(jjj + 1)))/ &
    4169          816 :                                    ((ABS(level_energ_GW - e_fermi - Lambda(jjj + 1)))**2)
    4170              : 
    4171              :                END DO
    4172              : 
    4173              :               delta = (Eigenval_scf(n_level_gw_ref) + vec_Sigma_x_minus_vxc_gw(n_level_gw_ref) + REAL(func_val) - level_energ_GW)/ &
    4174          272 :                        deriv_val_real
    4175              : 
    4176          272 :                level_energ_GW = level_energ_GW - delta
    4177              : 
    4178          272 :                IF (ABS(delta) < 1.0E-08) EXIT
    4179              : 
    4180              :             END DO
    4181              : 
    4182              :             ! update the GW-energy by Newton-Raphson and set the Z-value to 1
    4183              : 
    4184           32 :             vec_gw_energ(n_level_gw) = REAL(func_val)
    4185           32 :             z_value(n_level_gw) = 1.0_dp
    4186           32 :             m_value(n_level_gw) = 0.0_dp
    4187              : 
    4188              :          END IF ! Newton-Raphson on top of Z-shot
    4189              : 
    4190              :       ELSE
    4191            0 :          CPABORT("Only NONE, ZSHOT and NEWTON implemented for 2-pole model")
    4192              :       END IF ! decision crossing search none, Z-shot
    4193              : 
    4194              :       !   --------------------------------------------
    4195              :       !  | calculate statistical error due to fitting |
    4196              :       !   --------------------------------------------
    4197              : 
    4198              :       ! estimate the statistical error of the calculated Sigma_c(i*omega)
    4199              :       ! by sqrt(chi2/n), where n is the number of fit points
    4200              : 
    4201              :       CALL calc_chi2(chi2, Lambda_without_offset, vec_Sigma_c_gw, vec_omega_fit_gw_sign, num_poles, &
    4202          568 :                      num_fit_points, n_level_gw)
    4203              : 
    4204              :       ! Estimate the statistical error of every fit point
    4205          568 :       stat_error = SQRT(chi2/num_fit_points)
    4206              : 
    4207              :       ! allocate N array containing the second derivatives of chi^2
    4208         1704 :       ALLOCATE (vec_N_gw(num_var*2))
    4209          568 :       vec_N_gw = 0.0_dp
    4210              : 
    4211         2272 :       ALLOCATE (mat_N_gw(num_var*2, num_var*2))
    4212          568 :       mat_N_gw = 0.0_dp
    4213              : 
    4214         6248 :       DO iii = 1, num_var*2
    4215              :          CALL calc_mat_N(vec_N_gw(iii), Lambda_without_offset, vec_Sigma_c_gw, vec_omega_fit_gw_sign, &
    4216         6248 :                          iii, iii, num_poles, num_fit_points, n_level_gw, 0.001_dp)
    4217              :       END DO
    4218              : 
    4219         6248 :       DO iii = 1, num_var*2
    4220        63048 :          DO jjj = 1, num_var*2
    4221              :             CALL calc_mat_N(mat_N_gw(iii, jjj), Lambda_without_offset, vec_Sigma_c_gw, vec_omega_fit_gw_sign, &
    4222        62480 :                             iii, jjj, num_poles, num_fit_points, n_level_gw, 0.001_dp)
    4223              :          END DO
    4224              :       END DO
    4225              : 
    4226          568 :       CALL DGETRF(2*num_var, 2*num_var, mat_N_gw, 2*num_var, ipiv, info)
    4227              : 
    4228              :       ! vec_b_gw is only working array
    4229          568 :       CALL DGETRI(2*num_var, mat_N_gw, 2*num_var, ipiv, vec_b_gw, 2*num_var, info)
    4230              : 
    4231         1136 :       ALLOCATE (stat_errors(2*num_var))
    4232              :       stat_errors = 0.0_dp
    4233              : 
    4234         6248 :       DO iii = 1, 2*num_var
    4235         6248 :          stat_errors(iii) = SQRT(ABS(mat_N_gw(iii, iii)))*stat_error
    4236              :       END DO
    4237              : 
    4238          568 :       DEALLOCATE (mat_N_gw)
    4239          568 :       DEALLOCATE (vec_N_gw)
    4240          568 :       DEALLOCATE (mat_A_gw)
    4241          568 :       DEALLOCATE (mat_B_gw)
    4242          568 :       DEALLOCATE (stat_errors)
    4243          568 :       DEALLOCATE (dLambda)
    4244          568 :       DEALLOCATE (dLambda_2)
    4245          568 :       DEALLOCATE (vec_b_gw)
    4246          568 :       DEALLOCATE (vec_b_gw_copy)
    4247          568 :       DEALLOCATE (ipiv)
    4248          568 :       DEALLOCATE (vec_omega_fit_gw_sign)
    4249          568 :       DEALLOCATE (Lambda)
    4250          568 :       DEALLOCATE (Lambda_without_offset)
    4251          568 :       DEALLOCATE (Lambda_Re)
    4252          568 :       DEALLOCATE (Lambda_Im)
    4253              : 
    4254          568 :    END SUBROUTINE fit_and_continuation_2pole
    4255              : 
    4256              : ! **************************************************************************************************
    4257              : !> \brief perform analytic continuation with pade approximation
    4258              : !> \param vec_gw_energ real Sigma_c
    4259              : !> \param vec_omega_fit_gw frequency points for Sigma_c(iomega)
    4260              : !> \param z_value 1/(1-dev)
    4261              : !> \param m_value derivative of real Sigma_c
    4262              : !> \param vec_Sigma_c_gw complex Sigma_c(iomega)
    4263              : !> \param vec_Sigma_x_minus_vxc_gw ...
    4264              : !> \param Eigenval quasiparticle energy during ev self-consistent GW
    4265              : !> \param Eigenval_scf KS/HF eigenvalue
    4266              : !> \param do_hedin_shift ...
    4267              : !> \param n_level_gw ...
    4268              : !> \param gw_corr_lev_occ ...
    4269              : !> \param gw_corr_lev_vir ...
    4270              : !> \param nparam_pade number of pade parameters
    4271              : !> \param num_fit_points number of fit points for Sigma_c(iomega)
    4272              : !> \param crossing_search type ofr cross search to find quasiparticle energies
    4273              : !> \param homo ...
    4274              : !> \param fermi_level_offset ...
    4275              : !> \param do_gw_im_time ...
    4276              : !> \param print_self_energy ...
    4277              : !> \param count_ev_sc_GW ...
    4278              : !> \param vec_gw_dos ...
    4279              : !> \param dos_lower_bound ...
    4280              : !> \param dos_precision ...
    4281              : !> \param ndos ...
    4282              : !> \param min_level_self_energy ...
    4283              : !> \param max_level_self_energy ...
    4284              : !> \param dos_eta ...
    4285              : !> \param dos_min ...
    4286              : !> \param dos_max ...
    4287              : !> \param e_fermi_ext ...
    4288              : ! **************************************************************************************************
    4289         4323 :    SUBROUTINE continuation_pade(vec_gw_energ, vec_omega_fit_gw, &
    4290         8646 :                                 z_value, m_value, vec_Sigma_c_gw, vec_Sigma_x_minus_vxc_gw, &
    4291         8646 :                                 Eigenval, Eigenval_scf, do_hedin_shift, n_level_gw, &
    4292              :                                 gw_corr_lev_occ, gw_corr_lev_vir, &
    4293              :                                 nparam_pade, num_fit_points, crossing_search, homo, &
    4294              :                                 fermi_level_offset, do_gw_im_time, print_self_energy, count_ev_sc_GW, &
    4295              :                                 vec_gw_dos, dos_lower_bound, dos_precision, ndos, &
    4296              :                                 min_level_self_energy, max_level_self_energy, &
    4297              :                                 dos_eta, dos_min, dos_max, e_fermi_ext)
    4298              : 
    4299              :       ! Optional arguments for spectral function
    4300              :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: vec_gw_energ
    4301              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: vec_omega_fit_gw
    4302              :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: z_value, m_value
    4303              :       COMPLEX(KIND=dp), DIMENSION(:, :), INTENT(IN)      :: vec_Sigma_c_gw
    4304              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: vec_Sigma_x_minus_vxc_gw, Eigenval, &
    4305              :                                                             Eigenval_scf
    4306              :       LOGICAL, INTENT(IN)                                :: do_hedin_shift
    4307              :       INTEGER, INTENT(IN)                                :: n_level_gw, gw_corr_lev_occ, &
    4308              :                                                             gw_corr_lev_vir, nparam_pade, &
    4309              :                                                             num_fit_points, crossing_search, homo
    4310              :       REAL(KIND=dp), INTENT(IN)                          :: fermi_level_offset
    4311              :       LOGICAL, INTENT(IN)                                :: do_gw_im_time, print_self_energy
    4312              :       INTEGER, INTENT(IN)                                :: count_ev_sc_GW
    4313              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), OPTIONAL :: vec_gw_dos
    4314              :       REAL(KIND=dp), OPTIONAL                            :: dos_lower_bound, dos_precision
    4315              :       INTEGER, INTENT(IN), OPTIONAL                      :: ndos, min_level_self_energy, &
    4316              :                                                             max_level_self_energy
    4317              :       REAL(KIND=dp), OPTIONAL                            :: dos_eta
    4318              :       INTEGER, INTENT(IN), OPTIONAL                      :: dos_min, dos_max
    4319              :       REAL(KIND=dp), OPTIONAL                            :: e_fermi_ext
    4320              : 
    4321              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'continuation_pade'
    4322              : 
    4323              :       CHARACTER(LEN=5)                                   :: string_level
    4324              :       CHARACTER(len=default_path_length)                 :: filename
    4325              :       COMPLEX(KIND=dp)                                   :: sigma_c_pade, sigma_c_pade_im_freq
    4326         4323 :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:)        :: coeff_pade, omega_points_pade, &
    4327         4323 :                                                             Sigma_c_gw_reorder
    4328              :       INTEGER                                            :: handle, i_omega, idos, iunit, jquad, &
    4329              :                                                             n_level_gw_ref, num_omega
    4330              :       REAL(KIND=dp)                                      :: e_fermi, energy_val, hedin_shift, &
    4331              :                                                             level_energ_GW_start, omega, &
    4332              :                                                             omega_dos, omega_dos_pade_eval, &
    4333              :                                                             sign_occ_virt
    4334         4323 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: vec_omega_fit_gw_sign, &
    4335         4323 :                                                             vec_omega_fit_gw_sign_reorder, &
    4336         4323 :                                                             vec_sigma_imag, vec_sigma_real
    4337              :       TYPE(cp_logger_type), POINTER                      :: logger
    4338              : 
    4339         4323 :       CALL timeset(routineN, handle)
    4340              : 
    4341        12969 :       ALLOCATE (vec_omega_fit_gw_sign(num_fit_points))
    4342              : 
    4343         4323 :       IF (n_level_gw <= gw_corr_lev_occ) THEN
    4344              :          sign_occ_virt = -1.0_dp
    4345              :       ELSE
    4346         3065 :          sign_occ_virt = 1.0_dp
    4347              :       END IF
    4348              : 
    4349        94166 :       DO jquad = 1, num_fit_points
    4350        94166 :          vec_omega_fit_gw_sign(jquad) = ABS(vec_omega_fit_gw(jquad))*sign_occ_virt
    4351              :       END DO
    4352              : 
    4353         4323 :       IF (do_gw_im_time) THEN
    4354              :          ! for cubic-scaling GW, we have one Green's function for occ and virt states
    4355              :          ! with the Fermi level in the middle of homo and lumo
    4356         3016 :          e_fermi = 0.5_dp*(Eigenval(homo) + Eigenval(homo + 1))
    4357              :       ELSE
    4358              :          ! in case of O(N^4) GW, we have the Fermi level differently for occ and virt states, see
    4359              :          ! Fig. 1 in JCTC 12, 3623-3635 (2016)
    4360         1307 :          IF (n_level_gw <= gw_corr_lev_occ) THEN
    4361         1582 :             e_fermi = MAXVAL(Eigenval(homo - gw_corr_lev_occ + 1:homo)) + fermi_level_offset
    4362              :          ELSE
    4363        22092 :             e_fermi = MINVAL(Eigenval(homo + 1:homo + gw_corr_lev_vir)) - fermi_level_offset
    4364              :          END IF
    4365              :       END IF
    4366              : 
    4367         4323 :       IF (PRESENT(e_fermi_ext)) e_fermi = e_fermi_ext
    4368              : 
    4369         4323 :       n_level_gw_ref = n_level_gw + homo - gw_corr_lev_occ
    4370              : 
    4371              :       !*** reorder, such that omega=i*0 is first entry
    4372        12969 :       ALLOCATE (Sigma_c_gw_reorder(num_fit_points))
    4373         8646 :       ALLOCATE (vec_omega_fit_gw_sign_reorder(num_fit_points))
    4374              :       ! for cubic scaling GW fit points are ordered differently than in N^4 GW
    4375         4323 :       IF (do_gw_im_time) THEN
    4376        14921 :          DO jquad = 1, num_fit_points
    4377        11905 :             Sigma_c_gw_reorder(jquad) = vec_Sigma_c_gw(n_level_gw, jquad)
    4378        14921 :             vec_omega_fit_gw_sign_reorder(jquad) = vec_omega_fit_gw_sign(jquad)
    4379              :          END DO
    4380              :       ELSE
    4381        79245 :          DO jquad = 1, num_fit_points
    4382        77938 :             Sigma_c_gw_reorder(jquad) = vec_Sigma_c_gw(n_level_gw, num_fit_points - jquad + 1)
    4383        79245 :             vec_omega_fit_gw_sign_reorder(jquad) = vec_omega_fit_gw_sign(num_fit_points - jquad + 1)
    4384              :          END DO
    4385              :       END IF
    4386              : 
    4387              :       !*** evaluate parameters for pade approximation
    4388        12969 :       ALLOCATE (coeff_pade(nparam_pade))
    4389         8646 :       ALLOCATE (omega_points_pade(nparam_pade))
    4390         4323 :       coeff_pade = 0.0_dp
    4391              :       CALL get_pade_parameters(Sigma_c_gw_reorder, vec_omega_fit_gw_sign_reorder, &
    4392         4323 :                                num_fit_points, nparam_pade, omega_points_pade, coeff_pade)
    4393              : 
    4394              :       !*** calculate start_value for iterative cross-searching methods
    4395         4323 :       IF ((crossing_search == ri_rpa_g0w0_crossing_bisection) .OR. &
    4396              :           (crossing_search == ri_rpa_g0w0_crossing_newton)) THEN
    4397         4323 :          energy_val = Eigenval(n_level_gw_ref) - e_fermi
    4398              :          CALL evaluate_pade_function(energy_val, nparam_pade, omega_points_pade, &
    4399         4323 :                                      coeff_pade, sigma_c_pade)
    4400              :          CALL get_z_and_m_value_pade(energy_val, nparam_pade, omega_points_pade, &
    4401         4323 :                                      coeff_pade, z_value(n_level_gw), m_value(n_level_gw))
    4402              :          level_energ_GW_start = (Eigenval_scf(n_level_gw_ref) - &
    4403              :                                  m_value(n_level_gw)*Eigenval(n_level_gw_ref) + &
    4404              :                                  REAL(sigma_c_pade) + &
    4405              :                                  vec_Sigma_x_minus_vxc_gw(n_level_gw_ref))* &
    4406         4323 :                                 z_value(n_level_gw)
    4407              : 
    4408              :          ! calculate Hedin shift; the last line is for evGW0 and evGW
    4409         4323 :          hedin_shift = 0.0_dp
    4410         4323 :          IF (do_hedin_shift) hedin_shift = REAL(sigma_c_pade) + &
    4411              :                                            vec_Sigma_x_minus_vxc_gw(n_level_gw_ref) &
    4412           60 :                                            - Eigenval(n_level_gw_ref) + Eigenval_scf(n_level_gw_ref)
    4413              :       END IF
    4414              : 
    4415         4323 :       IF (PRESENT(min_level_self_energy) .AND. PRESENT(max_level_self_energy)) THEN
    4416         1551 :          IF (n_level_gw_ref >= min_level_self_energy .AND. &
    4417              :              n_level_gw_ref <= max_level_self_energy) THEN
    4418            0 :             ALLOCATE (vec_sigma_real(ndos))
    4419            0 :             ALLOCATE (vec_sigma_imag(ndos))
    4420            0 :             WRITE (string_level, "(I4)") n_level_gw_ref
    4421            0 :             string_level = ADJUSTL(string_level)
    4422              :          END IF
    4423              :       END IF
    4424              : 
    4425              :       !*** Calculate spectral function
    4426              :       !***         1   \‾‾                    |Im 𝚺ₘ(ω)|+η
    4427              :       !*** A(ω) = ---   |    ---------------------------------------------------
    4428              :       !***         π   /__   [ω - eₘ^DFT - (Re 𝚺ₘ(ω) - vₘ^xc)]² + (|Im 𝚺ₘ(ω)|+η)²
    4429              : 
    4430         4323 :       IF (PRESENT(ndos)) THEN
    4431         1551 :       IF (ndos /= 0) THEN
    4432              :          ! Hedin shift not implemented
    4433            0 :          CPASSERT(.NOT. do_hedin_shift)
    4434            0 :          logger => cp_get_default_logger()
    4435            0 :          IF (logger%para_env%is_source()) THEN
    4436            0 :             iunit = cp_logger_get_default_unit_nr()
    4437              :          ELSE
    4438            0 :             iunit = -1
    4439              :          END IF
    4440            0 :          DO idos = 1, ndos
    4441            0 :             omega_dos = dos_lower_bound + REAL(idos - 1, KIND=dp)*dos_precision
    4442            0 :             omega_dos_pade_eval = omega_dos - e_fermi
    4443              :             CALL evaluate_pade_function(omega_dos_pade_eval, nparam_pade, omega_points_pade, &
    4444            0 :                                         coeff_pade, sigma_c_pade)
    4445              : 
    4446              :             IF (n_level_gw_ref >= min_level_self_energy .AND. &
    4447            0 :                 n_level_gw_ref <= max_level_self_energy .AND. iunit > 0) THEN
    4448              : 
    4449            0 :                vec_sigma_real(idos) = (REAL(sigma_c_pade))
    4450            0 :                vec_sigma_imag(idos) = (AIMAG(sigma_c_pade))
    4451              : 
    4452              :             END IF
    4453              : 
    4454            0 :             IF (n_level_gw_ref >= dos_min .AND. &
    4455            0 :                 (n_level_gw_ref <= dos_max .OR. dos_max == 0)) THEN
    4456              :                vec_gw_dos(idos) = vec_gw_dos(idos) + &
    4457              :                                   (ABS(AIMAG(sigma_c_pade)) + dos_eta) &
    4458              :                                   /( &
    4459              :                                   (omega_dos - Eigenval_scf(n_level_gw_ref) - &
    4460              :                                    (REAL(sigma_c_pade) + vec_Sigma_x_minus_vxc_gw(n_level_gw_ref)) &
    4461              :                                    )**2 &
    4462              :                                   + (ABS(AIMAG(sigma_c_pade)) + dos_eta)**2 &
    4463            0 :                                   )
    4464              :             END IF
    4465              : 
    4466              :          END DO
    4467              :       END IF
    4468              :       END IF
    4469              : 
    4470         4323 :       IF (PRESENT(min_level_self_energy) .AND. PRESENT(max_level_self_energy)) THEN
    4471         1551 :          logger => cp_get_default_logger()
    4472         1551 :          IF (logger%para_env%is_source()) THEN
    4473         1527 :             iunit = cp_logger_get_default_unit_nr()
    4474              :          ELSE
    4475           24 :             iunit = -1
    4476              :          END IF
    4477              :          IF (n_level_gw_ref >= min_level_self_energy .AND. &
    4478         1551 :              n_level_gw_ref <= max_level_self_energy .AND. iunit > 0) THEN
    4479              : 
    4480              :             CALL open_file('self_energy_re_'//TRIM(string_level)//'.dat', unit_number=iunit, &
    4481            0 :                            file_status="UNKNOWN", file_action="WRITE")
    4482            0 :             DO idos = 1, ndos
    4483            0 :                omega_dos = dos_lower_bound + REAL(idos - 1, KIND=dp)*dos_precision
    4484            0 :                WRITE (iunit, '(F17.10, F17.10)') omega_dos*evolt, vec_sigma_real(idos)*evolt
    4485              :             END DO
    4486              : 
    4487            0 :             CALL close_file(iunit)
    4488              : 
    4489              :             CALL open_file('self_energy_im_'//TRIM(string_level)//'.dat', unit_number=iunit, &
    4490            0 :                            file_status="UNKNOWN", file_action="WRITE")
    4491            0 :             DO idos = 1, ndos
    4492            0 :                omega_dos = dos_lower_bound + REAL(idos - 1, KIND=dp)*dos_precision
    4493            0 :                WRITE (iunit, '(F17.10, F17.10)') omega_dos*evolt, vec_sigma_imag(idos)*evolt
    4494              :             END DO
    4495              : 
    4496            0 :             CALL close_file(iunit)
    4497              : 
    4498            0 :             DEALLOCATE (vec_sigma_real)
    4499            0 :             DEALLOCATE (vec_sigma_imag)
    4500              :          END IF
    4501              :       END IF
    4502              : 
    4503              :       !*** perform crossing search
    4504            0 :       SELECT CASE (crossing_search)
    4505              :       CASE (ri_rpa_g0w0_crossing_z_shot)
    4506              :          ! Hedin shift not implemented
    4507            0 :          CPASSERT(.NOT. do_hedin_shift)
    4508            0 :          energy_val = Eigenval(n_level_gw_ref) - e_fermi
    4509              :          CALL evaluate_pade_function(energy_val, nparam_pade, omega_points_pade, &
    4510            0 :                                      coeff_pade, sigma_c_pade)
    4511            0 :          vec_gw_energ(n_level_gw) = REAL(sigma_c_pade)
    4512              : 
    4513              :          CALL get_z_and_m_value_pade(energy_val, nparam_pade, omega_points_pade, &
    4514            0 :                                      coeff_pade, z_value(n_level_gw), m_value(n_level_gw))
    4515              : 
    4516              :       CASE (ri_rpa_g0w0_crossing_bisection)
    4517              :          CALL get_sigma_c_bisection_pade(vec_gw_energ(n_level_gw), Eigenval_scf(n_level_gw_ref), &
    4518              :                                          vec_Sigma_x_minus_vxc_gw(n_level_gw_ref), e_fermi, &
    4519              :                                          nparam_pade, omega_points_pade, coeff_pade, &
    4520            8 :                                          level_energ_GW_start, hedin_shift)
    4521            8 :          z_value(n_level_gw) = 1.0_dp
    4522            8 :          m_value(n_level_gw) = 0.0_dp
    4523              : 
    4524              :       CASE (ri_rpa_g0w0_crossing_newton)
    4525              :          CALL get_sigma_c_newton_pade(vec_gw_energ(n_level_gw), Eigenval_scf(n_level_gw_ref), &
    4526              :                                       vec_Sigma_x_minus_vxc_gw(n_level_gw_ref), e_fermi, &
    4527              :                                       nparam_pade, omega_points_pade, coeff_pade, &
    4528         4315 :                                       level_energ_GW_start, hedin_shift)
    4529         4315 :          z_value(n_level_gw) = 1.0_dp
    4530         4315 :          m_value(n_level_gw) = 0.0_dp
    4531              : 
    4532              :       CASE DEFAULT
    4533         4323 :          CPABORT("Only Z_SHOT, NEWTON, and BISECTION crossing search implemented.")
    4534              :       END SELECT
    4535              : 
    4536         4323 :       IF (print_self_energy) THEN
    4537              : 
    4538            0 :          IF (count_ev_sc_GW == 1) THEN
    4539              : 
    4540            0 :             IF (n_level_gw_ref < 10) THEN
    4541            0 :                WRITE (filename, "(A26,I1)") "G0W0_self_energy_level_000", n_level_gw_ref
    4542            0 :             ELSE IF (n_level_gw_ref < 100) THEN
    4543            0 :                WRITE (filename, "(A25,I2)") "G0W0_self_energy_level_00", n_level_gw_ref
    4544            0 :             ELSE IF (n_level_gw_ref < 1000) THEN
    4545            0 :                WRITE (filename, "(A24,I3)") "G0W0_self_energy_level_0", n_level_gw_ref
    4546              :             ELSE
    4547            0 :                WRITE (filename, "(A23,I4)") "G0W0_self_energy_level_", n_level_gw_ref
    4548              :             END IF
    4549              : 
    4550              :          ELSE
    4551              : 
    4552            0 :             IF (n_level_gw_ref < 10) THEN
    4553            0 :                WRITE (filename, "(A11,I1,A22,I1)") "evGW_cycle_", count_ev_sc_GW, &
    4554            0 :                   "_self_energy_level_000", n_level_gw_ref
    4555            0 :             ELSE IF (n_level_gw_ref < 100) THEN
    4556            0 :                WRITE (filename, "(A11,I1,A21,I2)") "evGW_cycle_", count_ev_sc_GW, &
    4557            0 :                   "_self_energy_level_00", n_level_gw_ref
    4558            0 :             ELSE IF (n_level_gw_ref < 1000) THEN
    4559            0 :                WRITE (filename, "(A11,I1,A20,I3)") "evGW_cycle_", count_ev_sc_GW, &
    4560            0 :                   "_self_energy_level_0", n_level_gw_ref
    4561              :             ELSE
    4562            0 :                WRITE (filename, "(A11,I1,A19,I4)") "evGW_cycle_", count_ev_sc_GW, &
    4563            0 :                   "_self_energy_level_", n_level_gw_ref
    4564              :             END IF
    4565              : 
    4566              :          END IF
    4567              : 
    4568            0 :          logger => cp_get_default_logger()
    4569            0 :          IF (logger%para_env%is_source()) THEN
    4570            0 :             iunit = cp_logger_get_default_unit_nr()
    4571              :          ELSE
    4572            0 :             iunit = -1
    4573              :          END IF
    4574            0 :          CALL open_file(TRIM(filename), unit_number=iunit, file_status="UNKNOWN", file_action="WRITE")
    4575              : 
    4576            0 :          num_omega = 10000
    4577              : 
    4578            0 :          WRITE (iunit, "(2A42)") " omega (eV)     Sigma(omega) (eV)  ", &
    4579            0 :             "  omega - e_n^DFT - Sigma_n^x - v_n^xc (eV)"
    4580              : 
    4581            0 :          DO i_omega = 0, num_omega
    4582              : 
    4583            0 :             omega = -50.0_dp/evolt + REAL(i_omega, KIND=dp)/REAL(num_omega, KIND=dp)*100.0_dp/evolt
    4584              : 
    4585              :             CALL evaluate_pade_function(omega - e_fermi, nparam_pade, omega_points_pade, &
    4586            0 :                                         coeff_pade, sigma_c_pade)
    4587              : 
    4588            0 :             WRITE (iunit, "(F12.2,2F17.5)") omega*evolt, REAL(sigma_c_pade)*evolt, &
    4589            0 :                (omega - Eigenval_scf(n_level_gw_ref) - vec_Sigma_x_minus_vxc_gw(n_level_gw_ref))*evolt
    4590              : 
    4591              :          END DO
    4592              : 
    4593            0 :          WRITE (iunit, "(A51,A39)") " w (eV)  Re(Sigma(i*w)) (eV)   Im(Sigma(i*w)) (eV) ", &
    4594            0 :             "  Re(Fit(i*w)) (eV)    Im(Fit(iw)) (eV)"
    4595              : 
    4596            0 :          DO jquad = 1, num_fit_points
    4597              : 
    4598              :             CALL evaluate_pade_function(vec_omega_fit_gw_sign_reorder(jquad), &
    4599              :                                         nparam_pade, omega_points_pade, &
    4600            0 :                                         coeff_pade, sigma_c_pade_im_freq, do_imag_freq=.TRUE.)
    4601              : 
    4602            0 :             WRITE (iunit, "(F12.2,4F17.5)") vec_omega_fit_gw_sign_reorder(jquad)*evolt, &
    4603            0 :                REAL(Sigma_c_gw_reorder(jquad)*evolt), &
    4604            0 :                AIMAG(Sigma_c_gw_reorder(jquad)*evolt), &
    4605            0 :                REAL(sigma_c_pade_im_freq*evolt), &
    4606            0 :                AIMAG(sigma_c_pade_im_freq*evolt)
    4607              : 
    4608              :          END DO
    4609              : 
    4610            0 :          CALL close_file(iunit)
    4611              : 
    4612              :       END IF
    4613              : 
    4614         4323 :       DEALLOCATE (vec_omega_fit_gw_sign)
    4615         4323 :       DEALLOCATE (Sigma_c_gw_reorder)
    4616         4323 :       DEALLOCATE (vec_omega_fit_gw_sign_reorder)
    4617         4323 :       DEALLOCATE (coeff_pade, omega_points_pade)
    4618              : 
    4619         4323 :       CALL timestop(handle)
    4620              : 
    4621         8646 :    END SUBROUTINE continuation_pade
    4622              : 
    4623              : ! **************************************************************************************************
    4624              : !> \brief calculate pade parameter recursively as in  Eq. (A2) in J. Low Temp. Phys., Vol. 29,
    4625              : !>          1977, pp. 179
    4626              : !> \param y f(x), here: Sigma_c(iomega)
    4627              : !> \param x the frequency points omega
    4628              : !> \param num_fit_points ...
    4629              : !> \param nparam number of pade parameters
    4630              : !> \param xpoints set of points used in pade approximation, selection of x
    4631              : !> \param coeff pade coefficients
    4632              : ! **************************************************************************************************
    4633         4323 :    PURE SUBROUTINE get_pade_parameters(y, x, num_fit_points, nparam, xpoints, coeff)
    4634              : 
    4635              :       COMPLEX(KIND=dp), DIMENSION(:), INTENT(IN)         :: y
    4636              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: x
    4637              :       INTEGER, INTENT(IN)                                :: num_fit_points, nparam
    4638              :       COMPLEX(KIND=dp), DIMENSION(:), INTENT(INOUT)      :: xpoints, coeff
    4639              : 
    4640         4323 :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:)        :: ypoints
    4641         4323 :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :)     :: g_mat
    4642              :       INTEGER                                            :: idat, iparam, nstep
    4643              : 
    4644         4323 :       nstep = INT(num_fit_points/(nparam - 1))
    4645              : 
    4646        12969 :       ALLOCATE (ypoints(nparam))
    4647              :       !omega=i0 is in element x(1)
    4648         4323 :       idat = 1
    4649        31123 :       DO iparam = 1, nparam - 1
    4650        26800 :          xpoints(iparam) = gaussi*x(idat)
    4651        26800 :          ypoints(iparam) = y(idat)
    4652        31123 :          idat = idat + nstep
    4653              :       END DO
    4654         4323 :       xpoints(nparam) = gaussi*x(num_fit_points)
    4655         4323 :       ypoints(nparam) = y(num_fit_points)
    4656              : 
    4657              :       !*** generate parameters recursively
    4658              : 
    4659        17292 :       ALLOCATE (g_mat(nparam, nparam))
    4660        35446 :       g_mat(:, 1) = ypoints(:)
    4661        31123 :       DO iparam = 2, nparam
    4662       195985 :          DO idat = iparam, nparam
    4663              :             g_mat(idat, iparam) = (g_mat(iparam - 1, iparam - 1) - g_mat(idat, iparam - 1))/ &
    4664       191662 :                                   ((xpoints(idat) - xpoints(iparam - 1))*g_mat(idat, iparam - 1))
    4665              :          END DO
    4666              :       END DO
    4667              : 
    4668        35446 :       DO iparam = 1, nparam
    4669        35446 :          coeff(iparam) = g_mat(iparam, iparam)
    4670              :       END DO
    4671              : 
    4672         4323 :       DEALLOCATE (ypoints)
    4673         4323 :       DEALLOCATE (g_mat)
    4674              : 
    4675         4323 :    END SUBROUTINE get_pade_parameters
    4676              : 
    4677              : ! **************************************************************************************************
    4678              : !> \brief evaluate pade function for a real value x_val
    4679              : !> \param x_val real value
    4680              : !> \param nparam number of pade parameters
    4681              : !> \param xpoints selection of points of the original complex function, i.e. here of Sigma_c(iomega)
    4682              : !> \param coeff pade coefficients
    4683              : !> \param func_val function value
    4684              : !> \param do_imag_freq ...
    4685              : ! **************************************************************************************************
    4686        21198 :    PURE SUBROUTINE evaluate_pade_function(x_val, nparam, xpoints, coeff, func_val, do_imag_freq)
    4687              : 
    4688              :       REAL(KIND=dp), INTENT(IN)                          :: x_val
    4689              :       INTEGER, INTENT(IN)                                :: nparam
    4690              :       COMPLEX(KIND=dp), DIMENSION(:), INTENT(IN)         :: xpoints, coeff
    4691              :       COMPLEX(KIND=dp), INTENT(OUT)                      :: func_val
    4692              :       LOGICAL, INTENT(IN), OPTIONAL                      :: do_imag_freq
    4693              : 
    4694              :       INTEGER                                            :: iparam
    4695              :       LOGICAL                                            :: my_do_imag_freq
    4696              : 
    4697        21198 :       my_do_imag_freq = .FALSE.
    4698        21198 :       IF (PRESENT(do_imag_freq)) my_do_imag_freq = do_imag_freq
    4699              : 
    4700        21198 :       func_val = z_one
    4701       148946 :       DO iparam = nparam, 2, -1
    4702       148946 :          IF (my_do_imag_freq) THEN
    4703            0 :             func_val = z_one + coeff(iparam)*(gaussi*x_val - xpoints(iparam - 1))/func_val
    4704              :          ELSE
    4705       127748 :             func_val = z_one + coeff(iparam)*(x_val*z_one - xpoints(iparam - 1))/func_val
    4706              :          END IF
    4707              :       END DO
    4708              : 
    4709        21198 :       func_val = coeff(1)/func_val
    4710              : 
    4711        21198 :    END SUBROUTINE evaluate_pade_function
    4712              : 
    4713              : ! **************************************************************************************************
    4714              : !> \brief get the z-value and the m-value (derivative) of the pade function
    4715              : !> \param x_val real value
    4716              : !> \param nparam number of pade parameters
    4717              : !> \param xpoints selection of points of the original complex function, i.e. here of Sigma_c(iomega)
    4718              : !> \param coeff pade coefficients
    4719              : !> \param z_value 1/(1-dev)
    4720              : !> \param m_value derivative
    4721              : ! **************************************************************************************************
    4722        21090 :    PURE SUBROUTINE get_z_and_m_value_pade(x_val, nparam, xpoints, coeff, z_value, m_value)
    4723              : 
    4724              :       REAL(KIND=dp), INTENT(IN)                          :: x_val
    4725              :       INTEGER, INTENT(IN)                                :: nparam
    4726              :       COMPLEX(KIND=dp), DIMENSION(:), INTENT(IN)         :: xpoints, coeff
    4727              :       REAL(KIND=dp), INTENT(OUT), OPTIONAL               :: z_value, m_value
    4728              : 
    4729              :       COMPLEX(KIND=dp)                                   :: denominator, dev_denominator, &
    4730              :                                                             dev_numerator, dev_val, func_val, &
    4731              :                                                             numerator
    4732              :       INTEGER                                            :: iparam
    4733              : 
    4734        21090 :       func_val = z_one
    4735        21090 :       dev_val = z_zero
    4736       148730 :       DO iparam = nparam, 2, -1
    4737       127640 :          numerator = coeff(iparam)*(x_val*z_one - xpoints(iparam - 1))
    4738       127640 :          dev_numerator = coeff(iparam)*z_one
    4739       127640 :          denominator = func_val
    4740       127640 :          dev_denominator = dev_val
    4741       127640 :          dev_val = dev_numerator/denominator - (numerator*dev_denominator)/(denominator**2)
    4742       148730 :          func_val = z_one + coeff(iparam)*(x_val*z_one - xpoints(iparam - 1))/func_val
    4743              :       END DO
    4744              : 
    4745        21090 :       dev_val = -1.0_dp*coeff(1)/(func_val**2)*dev_val
    4746        21090 :       func_val = coeff(1)/func_val
    4747              : 
    4748        21090 :       IF (PRESENT(z_value)) THEN
    4749         4323 :          z_value = 1.0_dp - REAL(dev_val)
    4750         4323 :          z_value = 1.0_dp/z_value
    4751              :       END IF
    4752        21090 :       IF (PRESENT(m_value)) m_value = REAL(dev_val)
    4753              : 
    4754        21090 :    END SUBROUTINE get_z_and_m_value_pade
    4755              : 
    4756              : ! **************************************************************************************************
    4757              : !> \brief crossing search using the bisection method to find the quasiparticle energy
    4758              : !> \param gw_energ real Sigma_c
    4759              : !> \param Eigenval_scf Eigenvalue from the SCF
    4760              : !> \param Sigma_x_minus_vxc_gw ...
    4761              : !> \param e_fermi fermi level
    4762              : !> \param nparam_pade number of pade parameters
    4763              : !> \param omega_points_pade selection of frequency points of Sigma_c(iomega)
    4764              : !> \param coeff_pade pade coefficients
    4765              : !> \param start_val start value for the quasiparticle iteration
    4766              : !> \param hedin_shift ...
    4767              : ! **************************************************************************************************
    4768           16 :    SUBROUTINE get_sigma_c_bisection_pade(gw_energ, Eigenval_scf, Sigma_x_minus_vxc_gw, e_fermi, &
    4769            8 :                                          nparam_pade, omega_points_pade, coeff_pade, start_val, &
    4770              :                                          hedin_shift)
    4771              : 
    4772              :       REAL(KIND=dp), INTENT(OUT)                         :: gw_energ
    4773              :       REAL(KIND=dp), INTENT(IN)                          :: Eigenval_scf, Sigma_x_minus_vxc_gw, &
    4774              :                                                             e_fermi
    4775              :       INTEGER, INTENT(IN)                                :: nparam_pade
    4776              :       COMPLEX(KIND=dp), DIMENSION(:), INTENT(IN)         :: omega_points_pade, coeff_pade
    4777              :       REAL(KIND=dp), INTENT(IN)                          :: start_val, hedin_shift
    4778              : 
    4779              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'get_sigma_c_bisection_pade'
    4780              : 
    4781              :       COMPLEX(KIND=dp)                                   :: sigma_c
    4782              :       INTEGER                                            :: handle, icount
    4783              :       REAL(KIND=dp)                                      :: delta, energy_val, qp_energy, &
    4784              :                                                             qp_energy_old, threshold
    4785              : 
    4786            8 :       CALL timeset(routineN, handle)
    4787              : 
    4788            8 :       threshold = 1.0E-7_dp
    4789              : 
    4790            8 :       qp_energy = start_val
    4791            8 :       qp_energy_old = start_val
    4792            8 :       delta = 1.0E-3_dp
    4793              : 
    4794            8 :       icount = 0
    4795          116 :       DO WHILE (ABS(delta) > threshold)
    4796          108 :          icount = icount + 1
    4797          108 :          qp_energy = qp_energy_old + 0.5_dp*delta
    4798          108 :          qp_energy_old = qp_energy
    4799          108 :          energy_val = qp_energy - e_fermi - hedin_shift
    4800              :          CALL evaluate_pade_function(energy_val, nparam_pade, omega_points_pade, &
    4801          108 :                                      coeff_pade, sigma_c)
    4802          108 :          qp_energy = Eigenval_scf + REAL(sigma_c) + Sigma_x_minus_vxc_gw
    4803          108 :          delta = qp_energy - qp_energy_old
    4804              :          ! Self-consistent quasi-particle solution has not been found
    4805          116 :          IF (icount > 500) EXIT
    4806              :       END DO
    4807              : 
    4808            8 :       gw_energ = REAL(sigma_c)
    4809              : 
    4810            8 :       CALL timestop(handle)
    4811              : 
    4812            8 :    END SUBROUTINE get_sigma_c_bisection_pade
    4813              : 
    4814              : ! **************************************************************************************************
    4815              : !> \brief crossing search using the Newton method to find the quasiparticle energy
    4816              : !> \param gw_energ real Sigma_c
    4817              : !> \param Eigenval_scf Eigenvalue from the SCF
    4818              : !> \param Sigma_x_minus_vxc_gw ...
    4819              : !> \param e_fermi fermi level
    4820              : !> \param nparam_pade number of pade parameters
    4821              : !> \param omega_points_pade selection of frequency points of Sigma_c(iomega)
    4822              : !> \param coeff_pade pade coefficients
    4823              : !> \param start_val start value for the quasiparticle iteration
    4824              : !> \param hedin_shift ...
    4825              : ! **************************************************************************************************
    4826         8630 :    SUBROUTINE get_sigma_c_newton_pade(gw_energ, Eigenval_scf, Sigma_x_minus_vxc_gw, e_fermi, &
    4827         4315 :                                       nparam_pade, omega_points_pade, coeff_pade, start_val, &
    4828              :                                       hedin_shift)
    4829              : 
    4830              :       REAL(KIND=dp), INTENT(OUT)                         :: gw_energ
    4831              :       REAL(KIND=dp), INTENT(IN)                          :: Eigenval_scf, Sigma_x_minus_vxc_gw, &
    4832              :                                                             e_fermi
    4833              :       INTEGER, INTENT(IN)                                :: nparam_pade
    4834              :       COMPLEX(KIND=dp), DIMENSION(:), INTENT(IN)         :: omega_points_pade, coeff_pade
    4835              :       REAL(KIND=dp), INTENT(IN)                          :: start_val, hedin_shift
    4836              : 
    4837              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'get_sigma_c_newton_pade'
    4838              : 
    4839              :       COMPLEX(KIND=dp)                                   :: sigma_c
    4840              :       INTEGER                                            :: handle, icount
    4841              :       REAL(KIND=dp)                                      :: delta, energy_val, m_value, qp_energy, &
    4842              :                                                             qp_energy_old, threshold
    4843              : 
    4844         4315 :       CALL timeset(routineN, handle)
    4845              : 
    4846         4315 :       threshold = 1.0E-7_dp
    4847              : 
    4848         4315 :       qp_energy = start_val
    4849         4315 :       qp_energy_old = start_val
    4850         4315 :       delta = 1.0E-3_dp
    4851              : 
    4852         4315 :       icount = 0
    4853        21078 :       DO WHILE (ABS(delta) > threshold)
    4854        16767 :          icount = icount + 1
    4855        16767 :          energy_val = qp_energy - e_fermi - hedin_shift
    4856              :          CALL evaluate_pade_function(energy_val, nparam_pade, omega_points_pade, &
    4857        16767 :                                      coeff_pade, sigma_c)
    4858              :          !get m_value --> derivative of function
    4859              :          CALL get_z_and_m_value_pade(energy_val, nparam_pade, omega_points_pade, &
    4860        16767 :                                      coeff_pade, m_value=m_value)
    4861        16767 :          qp_energy_old = qp_energy
    4862              :          qp_energy = qp_energy - (Eigenval_scf + Sigma_x_minus_vxc_gw + REAL(sigma_c) - qp_energy)/ &
    4863        16767 :                      (m_value - 1.0_dp)
    4864        16767 :          delta = qp_energy - qp_energy_old
    4865              :          ! Self-consistent quasi-particle solution has not been found
    4866        21078 :          IF (icount > 500) EXIT
    4867              :       END DO
    4868              : 
    4869         4315 :       gw_energ = REAL(sigma_c)
    4870              : 
    4871         4315 :       CALL timestop(handle)
    4872              : 
    4873         4315 :    END SUBROUTINE get_sigma_c_newton_pade
    4874              : 
    4875              : ! **************************************************************************************************
    4876              : !> \brief Prints the GW stuff to the output and optinally to an external file.
    4877              : !>        Also updates the eigenvalues for eigenvalue-self-consistent GW
    4878              : !> \param vec_gw_energ ...
    4879              : !> \param z_value ...
    4880              : !> \param m_value ...
    4881              : !> \param vec_Sigma_x_minus_vxc_gw ...
    4882              : !> \param Eigenval ...
    4883              : !> \param Eigenval_last ...
    4884              : !> \param Eigenval_scf ...
    4885              : !> \param gw_corr_lev_occ ...
    4886              : !> \param gw_corr_lev_virt ...
    4887              : !> \param gw_corr_lev_tot ...
    4888              : !> \param crossing_search ...
    4889              : !> \param homo ...
    4890              : !> \param unit_nr ...
    4891              : !> \param count_ev_sc_GW ...
    4892              : !> \param count_sc_GW0 ...
    4893              : !> \param ikp ...
    4894              : !> \param nkp_self_energy ...
    4895              : !> \param kpoints ...
    4896              : !> \param ispin requested spin-state (1 for alpha, 2 for beta, else closed-shell)
    4897              : !> \param E_VBM_GW ...
    4898              : !> \param E_CBM_GW ...
    4899              : !> \param E_VBM_SCF ...
    4900              : !> \param E_CBM_SCF ...
    4901              : ! **************************************************************************************************
    4902         1616 :    SUBROUTINE print_and_update_for_ev_sc(vec_gw_energ, &
    4903          404 :                                          z_value, m_value, vec_Sigma_x_minus_vxc_gw, Eigenval, &
    4904          404 :                                          Eigenval_last, Eigenval_scf, &
    4905              :                                          gw_corr_lev_occ, gw_corr_lev_virt, gw_corr_lev_tot, &
    4906              :                                          crossing_search, homo, unit_nr, count_ev_sc_GW, count_sc_GW0, &
    4907              :                                          ikp, nkp_self_energy, kpoints, ispin, E_VBM_GW, E_CBM_GW, &
    4908              :                                          E_VBM_SCF, E_CBM_SCF)
    4909              : 
    4910              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: vec_gw_energ, z_value, m_value
    4911              :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: vec_Sigma_x_minus_vxc_gw, Eigenval, &
    4912              :                                                             Eigenval_last, Eigenval_scf
    4913              :       INTEGER, INTENT(IN) :: gw_corr_lev_occ, gw_corr_lev_virt, gw_corr_lev_tot, crossing_search, &
    4914              :          homo, unit_nr, count_ev_sc_GW, count_sc_GW0, ikp, nkp_self_energy
    4915              :       TYPE(kpoint_type), INTENT(IN), POINTER             :: kpoints
    4916              :       INTEGER, INTENT(IN)                                :: ispin
    4917              :       REAL(KIND=dp), INTENT(INOUT), OPTIONAL             :: E_VBM_GW, E_CBM_GW, E_VBM_SCF, E_CBM_SCF
    4918              : 
    4919              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'print_and_update_for_ev_sc'
    4920              : 
    4921              :       CHARACTER(4)                                       :: occ_virt
    4922              :       INTEGER                                            :: handle, n_level_gw, n_level_gw_ref
    4923              :       LOGICAL                                            :: do_alpha, do_beta, do_closed_shell, &
    4924              :                                                             do_kpoints, is_energy_okay
    4925              :       REAL(KIND=dp)                                      :: E_GAP_GW, E_HOMO_GW, E_HOMO_SCF, &
    4926              :                                                             E_LUMO_GW, E_LUMO_SCF, new_energy
    4927              : 
    4928          404 :       CALL timeset(routineN, handle)
    4929              : 
    4930          404 :       do_alpha = (ispin == 1)
    4931          404 :       do_beta = (ispin == 2)
    4932          404 :       do_closed_shell = .NOT. (do_alpha .OR. do_beta)
    4933          404 :       do_kpoints = (nkp_self_energy > 1)
    4934              : 
    4935         9616 :       Eigenval_last(:) = Eigenval(:)
    4936              : 
    4937          404 :       IF (unit_nr > 0) THEN
    4938              : 
    4939          202 :          IF (count_ev_sc_GW == 1 .AND. count_sc_GW0 == 1 .AND. ikp == 1) THEN
    4940              : 
    4941           67 :             WRITE (unit_nr, *) ' '
    4942              : 
    4943           67 :             IF (do_alpha .OR. do_closed_shell) THEN
    4944           57 :                WRITE (unit_nr, *) ' '
    4945           57 :                WRITE (unit_nr, '(T3,A)') '******************************************************************************'
    4946           57 :                WRITE (unit_nr, '(T3,A)') '**                                                                          **'
    4947           57 :                WRITE (unit_nr, '(T3,A)') '**                        GW QUASIPARTICLE ENERGIES                         **'
    4948           57 :                WRITE (unit_nr, '(T3,A)') '**                                                                          **'
    4949           57 :                WRITE (unit_nr, '(T3,A)') '******************************************************************************'
    4950           57 :                WRITE (unit_nr, '(T3,A)') ' '
    4951           57 :                WRITE (unit_nr, '(T3,A)') ' '
    4952           57 :                WRITE (unit_nr, '(T3,A)') 'The GW quasiparticle energies are calculated according to: '
    4953              : 
    4954           57 :                IF (crossing_search == ri_rpa_g0w0_crossing_z_shot) THEN
    4955           16 :                   WRITE (unit_nr, '(T3,A)') 'E_GW = E_SCF + Z * ( Sigc(E_SCF) + Sigx - vxc )'
    4956              :                ELSE
    4957           41 :                   WRITE (unit_nr, '(T3,A)') ' '
    4958           41 :                   WRITE (unit_nr, '(T3,A)') '                    E_GW = E_SCF + Sigc(E_GW) + Sigx - vxc '
    4959           41 :                   WRITE (unit_nr, '(T3,A)') ' '
    4960           41 :                   WRITE (unit_nr, '(T3,A)') 'Upper equation is solved self-consistently for E_GW, see Eq. (12) in J. Phys.'
    4961           41 :                   WRITE (unit_nr, '(T3,A)') 'Chem. Lett. 9, 306 (2018), doi: 10.1021/acs.jpclett.7b02740'
    4962              :                END IF
    4963           57 :                WRITE (unit_nr, *) ' '
    4964           57 :                WRITE (unit_nr, *) ' '
    4965           57 :                WRITE (unit_nr, '(T3,A)') '------------'
    4966           57 :                WRITE (unit_nr, '(T3,A)') 'G0W0 results'
    4967           57 :                WRITE (unit_nr, '(T3,A)') '------------'
    4968              : 
    4969              :             END IF
    4970              : 
    4971           67 :             IF (.NOT. do_kpoints) THEN
    4972           58 :                IF (do_alpha) THEN
    4973            9 :                   WRITE (unit_nr, *) ' '
    4974            9 :                   WRITE (unit_nr, '(T3,A)') '---------------------------------------'
    4975            9 :                   WRITE (unit_nr, '(T3,A)') 'GW quasiparticle energies of alpha spins'
    4976            9 :                   WRITE (unit_nr, '(T3,A)') '----------------------------------------'
    4977           49 :                ELSE IF (do_beta) THEN
    4978            9 :                   WRITE (unit_nr, *) ' '
    4979            9 :                   WRITE (unit_nr, '(T3,A)') '---------------------------------------'
    4980            9 :                   WRITE (unit_nr, '(T3,A)') 'GW quasiparticle energies of beta spins'
    4981            9 :                   WRITE (unit_nr, '(T3,A)') '---------------------------------------'
    4982              :                END IF
    4983              :             END IF
    4984              : 
    4985              :          END IF
    4986              : 
    4987          202 :          IF (count_ev_sc_GW > 1) THEN
    4988           41 :             WRITE (unit_nr, *) ' '
    4989           41 :             WRITE (unit_nr, '(T3,A)') '---------------------------------------'
    4990           41 :             WRITE (unit_nr, '(T3,A,I4)') 'Eigenvalue-selfconsistency cycle: ', count_ev_sc_GW
    4991           41 :             WRITE (unit_nr, '(T3,A)') '---------------------------------------'
    4992              :          END IF
    4993              : 
    4994          202 :          IF (count_sc_GW0 > 1) THEN
    4995           36 :             WRITE (unit_nr, '(T3,A)') '----------------------------------'
    4996           36 :             WRITE (unit_nr, '(T3,A,I4)') 'scGW0 selfconsistency cycle: ', count_sc_GW0
    4997           36 :             WRITE (unit_nr, '(T3,A)') '----------------------------------'
    4998              :          END IF
    4999              : 
    5000          202 :          IF (do_kpoints) THEN
    5001           68 :             WRITE (unit_nr, *) ' '
    5002           68 :             WRITE (unit_nr, '(T3,A7,I3,A3,I3,A8,3F7.3,A12,3F7.3)') 'Kpoint ', ikp, '  /', nkp_self_energy, &
    5003           68 :                '   xkp =', kpoints%xkp(1, ikp), kpoints%xkp(2, ikp), kpoints%xkp(3, ikp), &
    5004          136 :                '  and  xkp =', -kpoints%xkp(1, ikp), -kpoints%xkp(2, ikp), -kpoints%xkp(3, ikp)
    5005           68 :             WRITE (unit_nr, '(T3,A72)') '(Relative Brillouin zone size: [-0.5, 0.5] x [-0.5, 0.5] x [-0.5, 0.5])'
    5006           68 :             WRITE (unit_nr, *) ' '
    5007           68 :             IF (do_alpha) THEN
    5008            8 :                WRITE (unit_nr, '(T3,A)') 'GW quasiparticle energies of alpha spins:'
    5009           60 :             ELSE IF (do_beta) THEN
    5010            8 :                WRITE (unit_nr, '(T3,A)') 'GW quasiparticle energies of beta spins:'
    5011              :             END IF
    5012              :          END IF
    5013              : 
    5014              :       END IF
    5015              : 
    5016         4642 :       DO n_level_gw = 1, gw_corr_lev_tot
    5017              : 
    5018         4238 :          n_level_gw_ref = n_level_gw + homo - gw_corr_lev_occ
    5019              : 
    5020              :          new_energy = (Eigenval_scf(n_level_gw_ref) - &
    5021              :                        m_value(n_level_gw)*Eigenval(n_level_gw_ref) + &
    5022              :                        vec_gw_energ(n_level_gw) + &
    5023              :                        vec_Sigma_x_minus_vxc_gw(n_level_gw_ref))* &
    5024         4238 :                       z_value(n_level_gw)
    5025              : 
    5026         4238 :          is_energy_okay = .TRUE.
    5027              : 
    5028         4238 :          IF (n_level_gw_ref > homo .AND. new_energy < Eigenval(homo)) THEN
    5029              :             is_energy_okay = .FALSE.
    5030              :          END IF
    5031              : 
    5032          404 :          IF (is_energy_okay) THEN
    5033         4238 :             Eigenval(n_level_gw_ref) = new_energy
    5034              :          END IF
    5035              : 
    5036              :       END DO
    5037              : 
    5038          404 :       IF (unit_nr > 0) THEN
    5039          202 :          WRITE (unit_nr, '(T3,A)') ' '
    5040          202 :          IF (crossing_search == ri_rpa_g0w0_crossing_z_shot) THEN
    5041           39 :             WRITE (unit_nr, '(T13,2A)') 'MO    E_SCF (eV)    Sigc (eV)   Sigx-vxc (eV)    Z         E_GW (eV)'
    5042              :          ELSE
    5043          163 :             WRITE (unit_nr, '(T3,2A)') 'Molecular orbital   E_SCF (eV)       Sigc (eV)   Sigx-vxc (eV)       E_GW (eV)'
    5044              :          END IF
    5045              :       END IF
    5046              : 
    5047         4642 :       DO n_level_gw = 1, gw_corr_lev_tot
    5048         4238 :          n_level_gw_ref = n_level_gw + homo - gw_corr_lev_occ
    5049         4238 :          IF (n_level_gw <= gw_corr_lev_occ) THEN
    5050         1108 :             occ_virt = 'occ'
    5051              :          ELSE
    5052         3130 :             occ_virt = 'vir'
    5053              :          END IF
    5054              : 
    5055         4642 :          IF (unit_nr > 0) THEN
    5056         2119 :             IF (crossing_search == ri_rpa_g0w0_crossing_z_shot) THEN
    5057              :                WRITE (unit_nr, '(T3,I4,3A,5F13.4)') &
    5058          536 :                   n_level_gw_ref, ' ( ', occ_virt, ') ', &
    5059          536 :                   Eigenval_last(n_level_gw_ref)*evolt, &
    5060          536 :                   vec_gw_energ(n_level_gw)*evolt, &
    5061          536 :                   vec_Sigma_x_minus_vxc_gw(n_level_gw_ref)*evolt, &
    5062          536 :                   z_value(n_level_gw), &
    5063         1072 :                   Eigenval(n_level_gw_ref)*evolt
    5064              :             ELSE
    5065              :                WRITE (unit_nr, '(T3,I4,3A,4F16.4)') &
    5066         1583 :                   n_level_gw_ref, ' ( ', occ_virt, ')  ', &
    5067         1583 :                   Eigenval_last(n_level_gw_ref)*evolt, &
    5068         1583 :                   vec_gw_energ(n_level_gw)*evolt, &
    5069         1583 :                   vec_Sigma_x_minus_vxc_gw(n_level_gw_ref)*evolt, &
    5070         3166 :                   Eigenval(n_level_gw_ref)*evolt
    5071              :             END IF
    5072              :          END IF
    5073              :       END DO
    5074              : 
    5075         1512 :       E_HOMO_SCF = MAXVAL(Eigenval_last(homo - gw_corr_lev_occ + 1:homo))
    5076         3534 :       E_LUMO_SCF = MINVAL(Eigenval_last(homo + 1:homo + gw_corr_lev_virt))
    5077              : 
    5078         1512 :       E_HOMO_GW = MAXVAL(Eigenval(homo - gw_corr_lev_occ + 1:homo))
    5079         3534 :       E_LUMO_GW = MINVAL(Eigenval(homo + 1:homo + gw_corr_lev_virt))
    5080          404 :       E_GAP_GW = E_LUMO_GW - E_HOMO_GW
    5081              : 
    5082              :       IF (PRESENT(E_VBM_SCF) .AND. PRESENT(E_CBM_SCF) .AND. &
    5083          404 :           PRESENT(E_VBM_GW) .AND. PRESENT(E_CBM_GW)) THEN
    5084          404 :          IF (E_HOMO_SCF > E_VBM_SCF) E_VBM_SCF = E_HOMO_SCF
    5085          404 :          IF (E_LUMO_SCF < E_CBM_SCF) E_CBM_SCF = E_LUMO_SCF
    5086          404 :          IF (E_HOMO_GW > E_VBM_GW) E_VBM_GW = E_HOMO_GW
    5087          404 :          IF (E_LUMO_GW < E_CBM_GW) E_CBM_GW = E_LUMO_GW
    5088              :       END IF
    5089              : 
    5090          404 :       IF (unit_nr > 0) THEN
    5091              : 
    5092          202 :          IF (do_kpoints) THEN
    5093           68 :             IF (do_closed_shell) THEN
    5094           52 :                WRITE (unit_nr, '(T3,A)') ' '
    5095           52 :                WRITE (unit_nr, '(T3,A,F42.4)') 'GW direct gap at current kpoint (eV)', E_GAP_GW*evolt
    5096           16 :             ELSE IF (do_alpha) THEN
    5097            8 :                WRITE (unit_nr, '(T3,A)') ' '
    5098            8 :                WRITE (unit_nr, '(T3,A,F36.4)') 'Alpha GW direct gap at current kpoint (eV)', &
    5099           16 :                   E_GAP_GW*evolt
    5100            8 :             ELSE IF (do_beta) THEN
    5101            8 :                WRITE (unit_nr, '(T3,A)') ' '
    5102            8 :                WRITE (unit_nr, '(T3,A,F37.4)') 'Beta GW direct gap at current kpoint (eV)', &
    5103           16 :                   E_GAP_GW*evolt
    5104              :             END IF
    5105              :          ELSE
    5106          134 :             IF (do_closed_shell) THEN
    5107          108 :                WRITE (unit_nr, '(T3,A)') ' '
    5108          108 :                IF (count_ev_sc_GW > 1) THEN
    5109           33 :                   WRITE (unit_nr, '(T3,A,I3,A,F39.4)') 'HOMO-LUMO gap in evGW iteration', &
    5110           66 :                      count_ev_sc_GW, ' (eV)', E_GAP_GW*evolt
    5111           75 :                ELSE IF (count_sc_GW0 > 1) THEN
    5112           35 :                   WRITE (unit_nr, '(T3,A,I3,A,F38.4)') 'HOMO-LUMO gap in evGW0 iteration', &
    5113           70 :                      count_sc_GW0, ' (eV)', E_GAP_GW*evolt
    5114              :                ELSE
    5115           40 :                   WRITE (unit_nr, '(T3,A,F55.4)') 'G0W0 HOMO-LUMO gap (eV)', E_GAP_GW*evolt
    5116              :                END IF
    5117           26 :             ELSE IF (do_alpha) THEN
    5118           13 :                WRITE (unit_nr, '(T3,A)') ' '
    5119           13 :                WRITE (unit_nr, '(T3,A,F51.4)') 'Alpha GW HOMO-LUMO gap (eV)', E_GAP_GW*evolt
    5120           13 :             ELSE IF (do_beta) THEN
    5121           13 :                WRITE (unit_nr, '(T3,A)') ' '
    5122           13 :                WRITE (unit_nr, '(T3,A,F52.4)') 'Beta GW HOMO-LUMO gap (eV)', E_GAP_GW*evolt
    5123              :             END IF
    5124              :          END IF
    5125              :       END IF
    5126              : 
    5127          404 :       IF (unit_nr > 0) THEN
    5128          202 :          WRITE (unit_nr, *) ' '
    5129          202 :          WRITE (unit_nr, '(T3,A)') '------------------------------------------------------------------------------'
    5130              :       END IF
    5131              : 
    5132          404 :       CALL timestop(handle)
    5133              : 
    5134          404 :    END SUBROUTINE print_and_update_for_ev_sc
    5135              : 
    5136              : ! **************************************************************************************************
    5137              : !> \brief ...
    5138              : !> \param Eigenval ...
    5139              : !> \param Eigenval_last ...
    5140              : !> \param gw_corr_lev_occ ...
    5141              : !> \param gw_corr_lev_virt ...
    5142              : !> \param homo ...
    5143              : !> \param nmo ...
    5144              : ! **************************************************************************************************
    5145          264 :    PURE SUBROUTINE shift_unshifted_levels(Eigenval, Eigenval_last, gw_corr_lev_occ, gw_corr_lev_virt, &
    5146              :                                           homo, nmo)
    5147              : 
    5148              :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: Eigenval, Eigenval_last
    5149              :       INTEGER, INTENT(IN)                                :: gw_corr_lev_occ, gw_corr_lev_virt, homo, &
    5150              :                                                             nmo
    5151              : 
    5152              :       INTEGER                                            :: n_level_gw, n_level_gw_ref
    5153              :       REAL(KIND=dp)                                      :: eigen_diff
    5154              : 
    5155              :       ! for eigenvalue self-consistent GW, all eigenvalues have to be corrected
    5156              :       ! 1) the occupied; check if there are occupied MOs not being corrected by GW
    5157          264 :       IF (gw_corr_lev_occ < homo .AND. gw_corr_lev_occ > 0) THEN
    5158              : 
    5159              :          ! calculate average GW correction for occupied orbitals
    5160              :          eigen_diff = 0.0_dp
    5161              : 
    5162           84 :          DO n_level_gw = 1, gw_corr_lev_occ
    5163           42 :             n_level_gw_ref = n_level_gw + homo - gw_corr_lev_occ
    5164           84 :             eigen_diff = eigen_diff + Eigenval(n_level_gw_ref) - Eigenval_last(n_level_gw_ref)
    5165              :          END DO
    5166           42 :          eigen_diff = eigen_diff/gw_corr_lev_occ
    5167              : 
    5168              :          ! correct the eigenvalues of the occupied orbitals which have not been corrected by GW
    5169          164 :          DO n_level_gw = 1, homo - gw_corr_lev_occ
    5170          164 :             Eigenval(n_level_gw) = Eigenval(n_level_gw) + eigen_diff
    5171              :          END DO
    5172              : 
    5173              :       END IF
    5174              : 
    5175              :       ! 2) the virtual: check if there are virtual orbitals not being corrected by GW
    5176          264 :       IF (gw_corr_lev_virt < nmo - homo .AND. gw_corr_lev_virt > 0) THEN
    5177              : 
    5178              :          ! calculate average GW correction for virtual orbitals
    5179              :          eigen_diff = 0.0_dp
    5180         2522 :          DO n_level_gw = 1, gw_corr_lev_virt
    5181         2270 :             n_level_gw_ref = n_level_gw + homo
    5182         2522 :             eigen_diff = eigen_diff + Eigenval(n_level_gw_ref) - Eigenval_last(n_level_gw_ref)
    5183              :          END DO
    5184          252 :          eigen_diff = eigen_diff/gw_corr_lev_virt
    5185              : 
    5186              :          ! correct the eigenvalues of the virtual orbitals which have not been corrected by GW
    5187         2744 :          DO n_level_gw = homo + gw_corr_lev_virt + 1, nmo
    5188         2744 :             Eigenval(n_level_gw) = Eigenval(n_level_gw) + eigen_diff
    5189              :          END DO
    5190              : 
    5191              :       END IF
    5192              : 
    5193          264 :    END SUBROUTINE shift_unshifted_levels
    5194              : 
    5195              : ! **************************************************************************************************
    5196              : !> \brief Calculate the matrix mat_N_gw containing the second derivatives
    5197              : !>        with respect to the fitting parameters. The second derivatives are
    5198              : !>        calculated numerically by finite differences.
    5199              : !> \param N_ij matrix element
    5200              : !> \param Lambda fitting parameters
    5201              : !> \param Sigma_c ...
    5202              : !> \param vec_omega_fit_gw ...
    5203              : !> \param i ...
    5204              : !> \param j ...
    5205              : !> \param num_poles ...
    5206              : !> \param num_fit_points ...
    5207              : !> \param n_level_gw ...
    5208              : !> \param h  ...
    5209              : ! **************************************************************************************************
    5210        62480 :    SUBROUTINE calc_mat_N(N_ij, Lambda, Sigma_c, vec_omega_fit_gw, i, j, &
    5211              :                          num_poles, num_fit_points, n_level_gw, h)
    5212              :       REAL(KIND=dp), INTENT(OUT)                         :: N_ij
    5213              :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:), &
    5214              :          INTENT(IN)                                      :: Lambda
    5215              :       COMPLEX(KIND=dp), DIMENSION(:, :), INTENT(IN)      :: Sigma_c
    5216              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
    5217              :          INTENT(IN)                                      :: vec_omega_fit_gw
    5218              :       INTEGER, INTENT(IN)                                :: i, j, num_poles, num_fit_points, &
    5219              :                                                             n_level_gw
    5220              :       REAL(KIND=dp), INTENT(IN)                          :: h
    5221              : 
    5222              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'calc_mat_N'
    5223              : 
    5224              :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:)        :: Lambda_tmp
    5225              :       INTEGER                                            :: handle, num_var
    5226              :       REAL(KIND=dp)                                      :: chi2, chi2_sum
    5227              : 
    5228        62480 :       CALL timeset(routineN, handle)
    5229              : 
    5230        62480 :       num_var = 2*num_poles + 1
    5231       187440 :       ALLOCATE (Lambda_tmp(num_var))
    5232        62480 :       Lambda_tmp = z_zero
    5233        62480 :       chi2_sum = 0.0_dp
    5234              : 
    5235              :       !test
    5236       374880 :       Lambda_tmp(:) = Lambda(:)
    5237              :       CALL calc_chi2(chi2, Lambda_tmp, Sigma_c, vec_omega_fit_gw, num_poles, &
    5238        62480 :                      num_fit_points, n_level_gw)
    5239              : 
    5240              :       ! Fitting parameters with offset h
    5241       374880 :       Lambda_tmp(:) = Lambda(:)
    5242        62480 :       IF (MODULO(i, 2) == 0) THEN
    5243        31240 :          Lambda_tmp(i/2) = Lambda_tmp(i/2) + h*z_one
    5244              :       ELSE
    5245        31240 :          Lambda_tmp((i + 1)/2) = Lambda_tmp((i + 1)/2) + h*gaussi
    5246              :       END IF
    5247        62480 :       IF (MODULO(j, 2) == 0) THEN
    5248        31240 :          Lambda_tmp(j/2) = Lambda_tmp(j/2) + h*z_one
    5249              :       ELSE
    5250        31240 :          Lambda_tmp((j + 1)/2) = Lambda_tmp((j + 1)/2) + h*gaussi
    5251              :       END IF
    5252              :       CALL calc_chi2(chi2, Lambda_tmp, Sigma_c, vec_omega_fit_gw, num_poles, &
    5253        62480 :                      num_fit_points, n_level_gw)
    5254        62480 :       chi2_sum = chi2_sum + chi2
    5255              : 
    5256        62480 :       IF (MODULO(i, 2) == 0) THEN
    5257        31240 :          Lambda_tmp(i/2) = Lambda_tmp(i/2) - 2.0_dp*h*z_one
    5258              :       ELSE
    5259        31240 :          Lambda_tmp((i + 1)/2) = Lambda_tmp((i + 1)/2) - 2.0_dp*h*gaussi
    5260              :       END IF
    5261              :       CALL calc_chi2(chi2, Lambda_tmp, Sigma_c, vec_omega_fit_gw, num_poles, &
    5262        62480 :                      num_fit_points, n_level_gw)
    5263        62480 :       chi2_sum = chi2_sum - chi2
    5264              : 
    5265        62480 :       IF (MODULO(j, 2) == 0) THEN
    5266        31240 :          Lambda_tmp(j/2) = Lambda_tmp(j/2) - 2.0_dp*h*z_one
    5267              :       ELSE
    5268        31240 :          Lambda_tmp((j + 1)/2) = Lambda_tmp((j + 1)/2) - 2.0_dp*h*gaussi
    5269              :       END IF
    5270              :       CALL calc_chi2(chi2, Lambda_tmp, Sigma_c, vec_omega_fit_gw, num_poles, &
    5271        62480 :                      num_fit_points, n_level_gw)
    5272        62480 :       chi2_sum = chi2_sum + chi2
    5273              : 
    5274        62480 :       IF (MODULO(i, 2) == 0) THEN
    5275        31240 :          Lambda_tmp(i/2) = Lambda_tmp(i/2) + 2.0_dp*h*z_one
    5276              :       ELSE
    5277        31240 :          Lambda_tmp((i + 1)/2) = Lambda_tmp((i + 1)/2) + 2.0_dp*h*gaussi
    5278              :       END IF
    5279              :       CALL calc_chi2(chi2, Lambda_tmp, Sigma_c, vec_omega_fit_gw, num_poles, &
    5280        62480 :                      num_fit_points, n_level_gw)
    5281        62480 :       chi2_sum = chi2_sum - chi2
    5282              : 
    5283              :       ! Second derivative with symmetric difference quotient
    5284        62480 :       N_ij = 1.0_dp/2.0_dp*chi2_sum/(4.0_dp*h*h)
    5285              : 
    5286        62480 :       DEALLOCATE (Lambda_tmp)
    5287              : 
    5288        62480 :       CALL timestop(handle)
    5289              : 
    5290        62480 :    END SUBROUTINE calc_mat_N
    5291              : 
    5292              : ! **************************************************************************************************
    5293              : !> \brief Calculate chi2
    5294              : !> \param chi2 ...
    5295              : !> \param Lambda fitting parameters
    5296              : !> \param Sigma_c ...
    5297              : !> \param vec_omega_fit_gw ...
    5298              : !> \param num_poles ...
    5299              : !> \param num_fit_points ...
    5300              : !> \param n_level_gw ...
    5301              : ! **************************************************************************************************
    5302      1414675 :    PURE SUBROUTINE calc_chi2(chi2, Lambda, Sigma_c, vec_omega_fit_gw, num_poles, &
    5303              :                              num_fit_points, n_level_gw)
    5304              :       REAL(KIND=dp), INTENT(OUT)                         :: chi2
    5305              :       COMPLEX(KIND=dp), DIMENSION(:), INTENT(IN)         :: Lambda
    5306              :       COMPLEX(KIND=dp), DIMENSION(:, :), INTENT(IN)      :: Sigma_c
    5307              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: vec_omega_fit_gw
    5308              :       INTEGER, INTENT(IN)                                :: num_poles, num_fit_points, n_level_gw
    5309              : 
    5310              :       COMPLEX(KIND=dp)                                   :: func_val
    5311              :       INTEGER                                            :: iii, jjj, kkk
    5312              : 
    5313      1414675 :       chi2 = 0.0_dp
    5314     18198768 :       DO kkk = 1, num_fit_points
    5315     16784093 :          func_val = Lambda(1)
    5316     50352279 :          DO iii = 1, num_poles
    5317     33568186 :             jjj = iii*2
    5318              :             ! calculate value of the fit function
    5319     50352279 :             func_val = func_val + Lambda(jjj)/(gaussi*vec_omega_fit_gw(kkk) - Lambda(jjj + 1))
    5320              :          END DO
    5321     18198768 :          chi2 = chi2 + (ABS(Sigma_c(n_level_gw, kkk) - func_val))**2
    5322              :       END DO
    5323              : 
    5324      1414675 :    END SUBROUTINE calc_chi2
    5325              : 
    5326              : ! **************************************************************************************************
    5327              : !> \brief ...
    5328              : !> \param num_integ_points ...
    5329              : !> \param nmo ...
    5330              : !> \param tau_tj ...
    5331              : !> \param tj ...
    5332              : !> \param matrix_s ...
    5333              : !> \param cfm_mo_coeff ...
    5334              : !> \param Eigenval ...
    5335              : !> \param eps_filter ...
    5336              : !> \param e_fermi ...
    5337              : !> \param fm_mat_W ...
    5338              : !> \param gw_corr_lev_tot ...
    5339              : !> \param gw_corr_lev_occ ...
    5340              : !> \param gw_corr_lev_virt ...
    5341              : !> \param homo ...
    5342              : !> \param count_ev_sc_GW ...
    5343              : !> \param count_sc_GW0 ...
    5344              : !> \param t_3c_overl_int_ao_mo ...
    5345              : !> \param t_3c_O_mo_compressed ...
    5346              : !> \param t_3c_O_mo_ind ...
    5347              : !> \param t_3c_overl_int_gw_RI ...
    5348              : !> \param t_3c_overl_int_gw_AO ...
    5349              : !> \param mat_W ...
    5350              : !> \param mat_MinvVMinv ...
    5351              : !> \param mat_dm ...
    5352              : !> \param weights_cos_tf_t_to_w ...
    5353              : !> \param weights_sin_tf_t_to_w ...
    5354              : !> \param vec_Sigma_c_gw ...
    5355              : !> \param do_periodic ...
    5356              : !> \param num_points_corr ...
    5357              : !> \param delta_corr ...
    5358              : !> \param qs_env ...
    5359              : !> \param para_env ...
    5360              : !> \param para_env_RPA ...
    5361              : !> \param mp2_env ...
    5362              : !> \param matrix_berry_re_mo_mo ...
    5363              : !> \param matrix_berry_im_mo_mo ...
    5364              : !> \param first_cycle_periodic_correction ...
    5365              : !> \param kpoints ...
    5366              : !> \param num_fit_points ...
    5367              : !> \param fm_mo_coeff ...
    5368              : !> \param do_ri_Sigma_x ...
    5369              : !> \param vec_Sigma_x_gw ...
    5370              : !> \param unit_nr ...
    5371              : !> \param ispin ...
    5372              : ! **************************************************************************************************
    5373           62 :    SUBROUTINE compute_self_energy_cubic_gw(num_integ_points, nmo, tau_tj, tj, &
    5374          124 :                                            matrix_s, cfm_mo_coeff, Eigenval, eps_filter, &
    5375           62 :                                            e_fermi, fm_mat_W, &
    5376              :                                            gw_corr_lev_tot, gw_corr_lev_occ, gw_corr_lev_virt, homo, &
    5377              :                                            count_ev_sc_GW, count_sc_GW0, &
    5378           62 :                                            t_3c_overl_int_ao_mo, t_3c_O_mo_compressed, t_3c_O_mo_ind, &
    5379              :                                            t_3c_overl_int_gw_RI, t_3c_overl_int_gw_AO, &
    5380              :                                            mat_W, mat_MinvVMinv, mat_dm, &
    5381          124 :                                            weights_cos_tf_t_to_w, weights_sin_tf_t_to_w, vec_Sigma_c_gw, &
    5382              :                                            do_periodic, num_points_corr, delta_corr, qs_env, para_env, para_env_RPA, &
    5383              :                                            mp2_env, matrix_berry_re_mo_mo, matrix_berry_im_mo_mo, &
    5384              :                                            first_cycle_periodic_correction, kpoints, num_fit_points, fm_mo_coeff, &
    5385           62 :                                            do_ri_Sigma_x, vec_Sigma_x_gw, unit_nr, ispin)
    5386              :       INTEGER, INTENT(IN)                                :: num_integ_points, nmo
    5387              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
    5388              :          INTENT(IN)                                      :: tau_tj, tj
    5389              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN)       :: matrix_s
    5390              :       TYPE(cp_cfm_type), INTENT(IN)                      :: cfm_mo_coeff
    5391              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: Eigenval
    5392              :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter
    5393              :       REAL(KIND=dp), INTENT(INOUT)                       :: e_fermi
    5394              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: fm_mat_W
    5395              :       INTEGER, INTENT(IN)                                :: gw_corr_lev_tot, gw_corr_lev_occ, &
    5396              :                                                             gw_corr_lev_virt, homo, &
    5397              :                                                             count_ev_sc_GW, count_sc_GW0
    5398              :       TYPE(dbt_type)                                     :: t_3c_overl_int_ao_mo
    5399              :       TYPE(hfx_compression_type)                         :: t_3c_O_mo_compressed
    5400              :       INTEGER, DIMENSION(:, :)                           :: t_3c_O_mo_ind
    5401              :       TYPE(dbt_type)                                     :: t_3c_overl_int_gw_RI, &
    5402              :                                                             t_3c_overl_int_gw_AO
    5403              :       TYPE(dbcsr_type), INTENT(INOUT), TARGET            :: mat_W
    5404              :       TYPE(dbcsr_p_type)                                 :: mat_MinvVMinv, mat_dm
    5405              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: weights_cos_tf_t_to_w, &
    5406              :                                                             weights_sin_tf_t_to_w
    5407              :       COMPLEX(KIND=dp), DIMENSION(:, :, :), INTENT(OUT)  :: vec_Sigma_c_gw
    5408              :       LOGICAL, INTENT(IN)                                :: do_periodic
    5409              :       INTEGER, INTENT(IN)                                :: num_points_corr
    5410              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
    5411              :          INTENT(INOUT)                                   :: delta_corr
    5412              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    5413              :       TYPE(mp_para_env_type), POINTER                    :: para_env, para_env_RPA
    5414              :       TYPE(mp2_type), INTENT(INOUT)                      :: mp2_env
    5415              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_berry_re_mo_mo, &
    5416              :                                                             matrix_berry_im_mo_mo
    5417              :       LOGICAL, INTENT(INOUT) :: first_cycle_periodic_correction
    5418              :       TYPE(kpoint_type), POINTER                         :: kpoints
    5419              :       INTEGER, INTENT(IN)                                :: num_fit_points
    5420              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_mo_coeff
    5421              :       LOGICAL, INTENT(IN)                                :: do_ri_Sigma_x
    5422              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: vec_Sigma_x_gw
    5423              :       INTEGER, INTENT(IN)                                :: unit_nr, ispin
    5424              : 
    5425              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_self_energy_cubic_gw'
    5426              : 
    5427           62 :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :)     :: delta_corr_omega
    5428              :       INTEGER :: gw_lev_end, gw_lev_start, handle, handle3, i, iblk_mo, iquad, jquad, mo_end, &
    5429              :          mo_start, n_level_gw, n_level_gw_ref, nao, nblk_mo, unit_nr_prv
    5430           62 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: batch_range_mo, dist1, dist2, mo_bsizes, &
    5431          124 :                                                             mo_offsets, sizes_AO, sizes_RI
    5432              :       INTEGER, DIMENSION(2)                              :: mo_bounds, pdims_2d
    5433              :       INTEGER, DIMENSION(3, 1)                           :: index_to_cell_zero
    5434              :       LOGICAL                                            :: memory_info
    5435              :       REAL(KIND=dp)                                      :: ext_scaling, omega, omega_i, omega_sign, &
    5436              :                                                             sign_occ_virt, t_i_Clenshaw, tau, &
    5437              :                                                             weight_cos, weight_i, weight_sin
    5438           62 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: vec_Sigma_c_gw_cos_omega, &
    5439           62 :          vec_Sigma_c_gw_cos_tau, vec_Sigma_c_gw_neg_tau, vec_Sigma_c_gw_pos_tau, &
    5440           62 :          vec_Sigma_c_gw_sin_omega, vec_Sigma_c_gw_sin_tau
    5441              :       TYPE(cp_cfm_type)                                  :: cfm_scaled_dm_occ_tau
    5442              :       TYPE(cp_fm_type)                                   :: fm_scaled_dm_occ_tau
    5443           62 :       TYPE(dbcsr_p_type), DIMENSION(:, :, :), POINTER    :: greens_fct
    5444              :       TYPE(dbcsr_type), POINTER                          :: mat_greens_fct_occ, mat_greens_fct_virt
    5445          186 :       TYPE(dbt_pgrid_type)                               :: pgrid_2d
    5446         1178 :       TYPE(dbt_type)                                     :: t_3c_ctr_AO, t_3c_ctr_RI, t_AO_tmp, &
    5447          806 :                                                             t_dm, t_greens_fct_occ, &
    5448          806 :                                                             t_greens_fct_virt, t_RI_tmp, &
    5449          806 :                                                             t_SinvVSinv, t_W
    5450              : 
    5451           62 :       CALL timeset(routineN, handle)
    5452              : 
    5453           62 :       CALL cp_cfm_get_info(cfm_mo_coeff, nrow_global=nao)
    5454              : 
    5455              :       CALL decompress_tensor(t_3c_overl_int_ao_mo, t_3c_O_mo_ind, t_3c_O_mo_compressed, &
    5456           62 :                              mp2_env%ri_rpa_im_time%eps_compress)
    5457              : 
    5458           62 :       CALL dbt_copy(t_3c_overl_int_ao_mo, t_3c_overl_int_gw_RI)
    5459           62 :       CALL dbt_copy(t_3c_overl_int_ao_mo, t_3c_overl_int_gw_AO, order=[2, 1, 3], move_data=.TRUE.)
    5460              : 
    5461           62 :       memory_info = mp2_env%ri_rpa_im_time%memory_info
    5462           62 :       IF (memory_info) THEN
    5463            0 :          unit_nr_prv = unit_nr
    5464              :       ELSE
    5465           62 :          unit_nr_prv = 0
    5466              :       END IF
    5467              : 
    5468           62 :       mo_start = homo - gw_corr_lev_occ + 1
    5469           62 :       mo_end = homo + gw_corr_lev_virt
    5470           62 :       CPASSERT(mo_end - mo_start + 1 == gw_corr_lev_tot)
    5471              : 
    5472         7940 :       vec_Sigma_c_gw = z_zero
    5473          248 :       ALLOCATE (vec_Sigma_c_gw_pos_tau(gw_corr_lev_tot, num_integ_points))
    5474           62 :       vec_Sigma_c_gw_pos_tau = 0.0_dp
    5475          186 :       ALLOCATE (vec_Sigma_c_gw_neg_tau(gw_corr_lev_tot, num_integ_points))
    5476           62 :       vec_Sigma_c_gw_neg_tau = 0.0_dp
    5477          186 :       ALLOCATE (vec_Sigma_c_gw_cos_tau(gw_corr_lev_tot, num_integ_points))
    5478           62 :       vec_Sigma_c_gw_cos_tau = 0.0_dp
    5479          186 :       ALLOCATE (vec_Sigma_c_gw_sin_tau(gw_corr_lev_tot, num_integ_points))
    5480           62 :       vec_Sigma_c_gw_sin_tau = 0.0_dp
    5481              : 
    5482          186 :       ALLOCATE (vec_Sigma_c_gw_cos_omega(gw_corr_lev_tot, num_integ_points))
    5483           62 :       vec_Sigma_c_gw_cos_omega = 0.0_dp
    5484          186 :       ALLOCATE (vec_Sigma_c_gw_sin_omega(gw_corr_lev_tot, num_integ_points))
    5485           62 :       vec_Sigma_c_gw_sin_omega = 0.0_dp
    5486              : 
    5487          248 :       ALLOCATE (delta_corr_omega(1 + homo - gw_corr_lev_occ:homo + gw_corr_lev_virt, num_integ_points))
    5488           62 :       delta_corr_omega(:, :) = z_zero
    5489              : 
    5490           62 :       e_fermi = 0.5_dp*(Eigenval(homo) + Eigenval(homo + 1))
    5491              : 
    5492           62 :       index_to_cell_zero = 0
    5493           62 :       NULLIFY (greens_fct)
    5494           62 :       CALL create_propagator_matrix_set(greens_fct, 1, matrix_s(1)%matrix, index_to_cell_zero)
    5495           62 :       mat_greens_fct_occ => greens_fct(propagator_sector_occupied, 1, 1)%matrix
    5496           62 :       mat_greens_fct_virt => greens_fct(propagator_sector_virtual, 1, 1)%matrix
    5497              : 
    5498           62 :       nblk_mo = dbt_nblks_total(t_3c_overl_int_gw_AO, 3)
    5499          186 :       ALLOCATE (mo_offsets(nblk_mo))
    5500          124 :       ALLOCATE (mo_bsizes(nblk_mo))
    5501          186 :       ALLOCATE (batch_range_mo(nblk_mo - 1))
    5502           62 :       CALL dbt_get_info(t_3c_overl_int_gw_AO, blk_offset_3=mo_offsets, blk_size_3=mo_bsizes)
    5503              : 
    5504           62 :       pdims_2d = 0
    5505           62 :       CALL dbt_pgrid_create(para_env, pdims_2d, pgrid_2d)
    5506          186 :       ALLOCATE (sizes_RI(dbt_nblks_total(t_3c_overl_int_gw_RI, 1)))
    5507           62 :       CALL dbt_get_info(t_3c_overl_int_gw_RI, blk_size_1=sizes_RI)
    5508              : 
    5509           62 :       CALL create_2c_tensor(t_W, dist1, dist2, pgrid_2d, sizes_RI, sizes_RI, name="(RI|RI)")
    5510              : 
    5511           62 :       DEALLOCATE (dist1, dist2)
    5512              : 
    5513           62 :       CALL dbt_create(mat_W, t_RI_tmp, name="(RI|RI)")
    5514              : 
    5515           62 :       CALL dbt_create(t_3c_overl_int_gw_RI, t_3c_ctr_RI)
    5516           62 :       CALL dbt_create(t_3c_overl_int_gw_AO, t_3c_ctr_AO)
    5517              : 
    5518          186 :       ALLOCATE (sizes_AO(dbt_nblks_total(t_3c_overl_int_gw_AO, 1)))
    5519           62 :       CALL dbt_get_info(t_3c_overl_int_gw_AO, blk_size_1=sizes_AO)
    5520           62 :       CALL create_2c_tensor(t_greens_fct_occ, dist1, dist2, pgrid_2d, sizes_AO, sizes_AO, name="(AO|AO)")
    5521           62 :       DEALLOCATE (dist1, dist2)
    5522           62 :       CALL create_2c_tensor(t_greens_fct_virt, dist1, dist2, pgrid_2d, sizes_AO, sizes_AO, name="(AO|AO)")
    5523           62 :       DEALLOCATE (dist1, dist2)
    5524              : 
    5525         1010 :       DO jquad = 1, num_integ_points
    5526              : 
    5527              :          CALL compute_gamma_propagator(greens_fct, 1, cfm_mo_coeff, homo, Eigenval, nmo, &
    5528          948 :                                        eps_filter, e_fermi, tau_tj(jquad), para_env)
    5529              : 
    5530          948 :          CALL dbcsr_set(mat_W, 0.0_dp)
    5531          948 :          CALL copy_fm_to_dbcsr(fm_mat_W(jquad), mat_W, keep_sparsity=.FALSE.)
    5532              : 
    5533          948 :          IF (jquad == 1) CALL dbt_create(mat_greens_fct_occ, t_AO_tmp, name="(AO|AO)")
    5534              : 
    5535          948 :          CALL dbt_copy_matrix_to_tensor(mat_W, t_RI_tmp)
    5536          948 :          CALL dbt_copy(t_RI_tmp, t_W)
    5537          948 :          CALL dbt_copy_matrix_to_tensor(mat_greens_fct_occ, t_AO_tmp)
    5538          948 :          CALL dbt_copy(t_AO_tmp, t_greens_fct_occ)
    5539          948 :          CALL dbt_copy_matrix_to_tensor(mat_greens_fct_virt, t_AO_tmp)
    5540          948 :          CALL dbt_copy(t_AO_tmp, t_greens_fct_virt)
    5541              : 
    5542         4740 :          batch_range_mo(:) = [(i, i=2, nblk_mo)]
    5543          948 :          CALL dbt_batched_contract_init(t_3c_overl_int_gw_AO, batch_range_3=batch_range_mo)
    5544          948 :          CALL dbt_batched_contract_init(t_3c_overl_int_gw_RI, batch_range_3=batch_range_mo)
    5545          948 :          CALL dbt_batched_contract_init(t_3c_ctr_AO, batch_range_3=batch_range_mo)
    5546          948 :          CALL dbt_batched_contract_init(t_3c_ctr_RI, batch_range_3=batch_range_mo)
    5547          948 :          CALL dbt_batched_contract_init(t_W)
    5548          948 :          CALL dbt_batched_contract_init(t_greens_fct_occ)
    5549          948 :          CALL dbt_batched_contract_init(t_greens_fct_virt)
    5550              : 
    5551              :          ! in iteration over MO blocks skip first and last block because they correspond to the MO s
    5552              :          ! outside of the GW range of required MOs
    5553         1896 :          DO iblk_mo = 2, nblk_mo - 1
    5554         2844 :             mo_bounds = [mo_offsets(iblk_mo), mo_offsets(iblk_mo) + mo_bsizes(iblk_mo) - 1]
    5555              :             CALL contract_cubic_gw(t_3c_overl_int_gw_AO, t_3c_overl_int_gw_RI, &
    5556              :                                    t_greens_fct_occ, t_W, [1.0_dp, -1.0_dp], &
    5557              :                                    mo_bounds, unit_nr_prv, &
    5558          948 :                                    t_3c_ctr_RI, t_3c_ctr_AO, calculate_ctr_ri=.TRUE.)
    5559          948 :             CALL trace_sigma_gw(t_3c_ctr_AO, t_3c_ctr_RI, vec_Sigma_c_gw_neg_tau(:, jquad), mo_start, mo_bounds, para_env)
    5560              : 
    5561              :             CALL contract_cubic_gw(t_3c_overl_int_gw_AO, t_3c_overl_int_gw_RI, &
    5562              :                                    t_greens_fct_virt, t_W, [1.0_dp, 1.0_dp], &
    5563              :                                    mo_bounds, unit_nr_prv, &
    5564          948 :                                    t_3c_ctr_RI, t_3c_ctr_AO, calculate_ctr_ri=.FALSE.)
    5565              : 
    5566         1896 :             CALL trace_sigma_gw(t_3c_ctr_AO, t_3c_ctr_RI, vec_Sigma_c_gw_pos_tau(:, jquad), mo_start, mo_bounds, para_env)
    5567              :          END DO
    5568          948 :          CALL dbt_batched_contract_finalize(t_3c_overl_int_gw_AO)
    5569          948 :          CALL dbt_batched_contract_finalize(t_3c_overl_int_gw_RI)
    5570          948 :          CALL dbt_batched_contract_finalize(t_3c_ctr_AO)
    5571          948 :          CALL dbt_batched_contract_finalize(t_3c_ctr_RI)
    5572          948 :          CALL dbt_batched_contract_finalize(t_W)
    5573          948 :          CALL dbt_batched_contract_finalize(t_greens_fct_occ)
    5574          948 :          CALL dbt_batched_contract_finalize(t_greens_fct_virt)
    5575              : 
    5576          948 :          CALL dbt_clear(t_3c_ctr_AO)
    5577          948 :          CALL dbt_clear(t_3c_ctr_RI)
    5578              : 
    5579              :          vec_Sigma_c_gw_cos_tau(:, jquad) = 0.5_dp*(vec_Sigma_c_gw_pos_tau(:, jquad) + &
    5580        12316 :                                                     vec_Sigma_c_gw_neg_tau(:, jquad))
    5581              : 
    5582              :          vec_Sigma_c_gw_sin_tau(:, jquad) = 0.5_dp*(vec_Sigma_c_gw_pos_tau(:, jquad) - &
    5583        12378 :                                                     vec_Sigma_c_gw_neg_tau(:, jquad))
    5584              : 
    5585              :       END DO ! jquad (tau)
    5586           62 :       CALL dbt_destroy(t_W)
    5587              : 
    5588           62 :       CALL dbt_destroy(t_greens_fct_occ)
    5589           62 :       CALL dbt_destroy(t_greens_fct_virt)
    5590              : 
    5591              :       ! Fourier transform from time to frequency
    5592          634 :       DO jquad = 1, num_fit_points
    5593              : 
    5594        14254 :          DO iquad = 1, num_integ_points
    5595              : 
    5596        13620 :             omega = tj(jquad)
    5597        13620 :             tau = tau_tj(iquad)
    5598        13620 :             weight_cos = weights_cos_tf_t_to_w(jquad, iquad)*COS(omega*tau)
    5599        13620 :             weight_sin = weights_sin_tf_t_to_w(jquad, iquad)*SIN(omega*tau)
    5600              : 
    5601              :             vec_Sigma_c_gw_cos_omega(:, jquad) = vec_Sigma_c_gw_cos_omega(:, jquad) + &
    5602       199900 :                                                  weight_cos*vec_Sigma_c_gw_cos_tau(:, iquad)
    5603              : 
    5604              :             vec_Sigma_c_gw_sin_omega(:, jquad) = vec_Sigma_c_gw_sin_omega(:, jquad) + &
    5605       200472 :                                                  weight_sin*vec_Sigma_c_gw_sin_tau(:, iquad)
    5606              : 
    5607              :          END DO
    5608              : 
    5609              :       END DO
    5610              : 
    5611              :       ! for occupied levels, we need the correlation self-energy for negative omega. Therefore, weight_sin
    5612              :       ! should be computed with -omega, which results in an additional minus for vec_Sigma_c_gw_sin_omega:
    5613         4226 :       vec_Sigma_c_gw_sin_omega(1:gw_corr_lev_occ, :) = -vec_Sigma_c_gw_sin_omega(1:gw_corr_lev_occ, :)
    5614              : 
    5615              :       vec_Sigma_c_gw(:, 1:num_fit_points, 1) = vec_Sigma_c_gw_cos_omega(:, 1:num_fit_points) + &
    5616         7878 :                                                gaussi*vec_Sigma_c_gw_sin_omega(:, 1:num_fit_points)
    5617              : 
    5618           62 :       CALL dbcsr_deallocate_matrix_set(greens_fct)
    5619              : 
    5620           62 :       IF (do_ri_Sigma_x .AND. count_ev_sc_GW == 1 .AND. count_sc_GW0 == 1) THEN
    5621              : 
    5622            2 :          CALL timeset(routineN//"_RI_HFX_operation_1", handle3)
    5623              : 
    5624            2 :          CALL cp_cfm_create(cfm_scaled_dm_occ_tau, cfm_mo_coeff%matrix_struct, nrow=nao, ncol=nao)
    5625              : 
    5626              :          ! get density matrix
    5627              :          CALL parallel_gemm(transa="N", transb="C", m=nao, n=nao, k=homo, alpha=(1.0_dp, 0.0_dp), &
    5628              :                             matrix_a=cfm_mo_coeff, matrix_b=cfm_mo_coeff, beta=(0.0_dp, 0.0_dp), &
    5629            2 :                             matrix_c=cfm_scaled_dm_occ_tau)
    5630              : 
    5631            2 :          CALL cp_fm_create(fm_scaled_dm_occ_tau, cfm_scaled_dm_occ_tau%matrix_struct)
    5632            2 :          CALL cp_cfm_to_fm(cfm_scaled_dm_occ_tau, fm_scaled_dm_occ_tau)
    5633              : 
    5634            2 :          CALL timestop(handle3)
    5635              : 
    5636            2 :          CALL timeset(routineN//"_RI_HFX_operation_2", handle3)
    5637              : 
    5638              :          CALL copy_fm_to_dbcsr(fm_scaled_dm_occ_tau, &
    5639              :                                mat_dm%matrix, &
    5640            2 :                                keep_sparsity=.FALSE.)
    5641              : 
    5642            2 :          CALL cp_fm_release(fm_scaled_dm_occ_tau)
    5643            2 :          CALL cp_cfm_release(cfm_scaled_dm_occ_tau)
    5644              : 
    5645            2 :          CALL timestop(handle3)
    5646              : 
    5647            2 :          CALL create_2c_tensor(t_dm, dist1, dist2, pgrid_2d, sizes_AO, sizes_AO, name="(AO|AO)")
    5648            2 :          DEALLOCATE (dist1, dist2)
    5649              : 
    5650            2 :          CALL dbt_copy_matrix_to_tensor(mat_dm%matrix, t_AO_tmp)
    5651            2 :          CALL dbt_copy(t_AO_tmp, t_dm)
    5652              : 
    5653            2 :          CALL create_2c_tensor(t_SinvVSinv, dist1, dist2, pgrid_2d, sizes_RI, sizes_RI, name="(RI|RI)")
    5654            2 :          DEALLOCATE (dist1, dist2)
    5655              : 
    5656            2 :          CALL dbt_copy_matrix_to_tensor(mat_MinvVMinv%matrix, t_RI_tmp)
    5657            2 :          CALL dbt_copy(t_RI_tmp, t_SinvVSinv)
    5658              : 
    5659            2 :          CALL dbt_batched_contract_init(t_3c_overl_int_gw_AO, batch_range_3=batch_range_mo)
    5660            2 :          CALL dbt_batched_contract_init(t_3c_overl_int_gw_RI, batch_range_3=batch_range_mo)
    5661            2 :          CALL dbt_batched_contract_init(t_3c_ctr_RI, batch_range_3=batch_range_mo)
    5662            2 :          CALL dbt_batched_contract_init(t_3c_ctr_AO, batch_range_3=batch_range_mo)
    5663            2 :          CALL dbt_batched_contract_init(t_dm)
    5664            2 :          CALL dbt_batched_contract_init(t_SinvVSinv)
    5665              : 
    5666            4 :          DO iblk_mo = 2, nblk_mo - 1
    5667            6 :             mo_bounds = [mo_offsets(iblk_mo), mo_offsets(iblk_mo) + mo_bsizes(iblk_mo) - 1]
    5668              : 
    5669              :             CALL contract_cubic_gw(t_3c_overl_int_gw_AO, t_3c_overl_int_gw_RI, &
    5670              :                                    t_dm, t_SinvVSinv, [1.0_dp, -1.0_dp], &
    5671              :                                    mo_bounds, unit_nr_prv, &
    5672            2 :                                    t_3c_ctr_RI, t_3c_ctr_AO, calculate_ctr_ri=.TRUE.)
    5673              : 
    5674            4 :             CALL trace_sigma_gw(t_3c_ctr_AO, t_3c_ctr_RI, vec_Sigma_x_gw(mo_start:mo_end, 1), mo_start, mo_bounds, para_env)
    5675              :          END DO
    5676            2 :          CALL dbt_batched_contract_finalize(t_3c_overl_int_gw_AO)
    5677            2 :          CALL dbt_batched_contract_finalize(t_3c_overl_int_gw_RI)
    5678            2 :          CALL dbt_batched_contract_finalize(t_dm)
    5679            2 :          CALL dbt_batched_contract_finalize(t_SinvVSinv)
    5680            2 :          CALL dbt_batched_contract_finalize(t_3c_ctr_RI)
    5681            2 :          CALL dbt_batched_contract_finalize(t_3c_ctr_AO)
    5682              : 
    5683            2 :          CALL dbt_destroy(t_dm)
    5684            2 :          CALL dbt_destroy(t_SinvVSinv)
    5685              : 
    5686              :          mp2_env%ri_g0w0%vec_Sigma_x_minus_vxc_gw(:, ispin, 1) = &
    5687              :             mp2_env%ri_g0w0%vec_Sigma_x_minus_vxc_gw(:, ispin, 1) + &
    5688           48 :             vec_Sigma_x_gw(:, 1)
    5689              : 
    5690              :       END IF
    5691              : 
    5692           62 :       CALL dbt_pgrid_destroy(pgrid_2d)
    5693              : 
    5694           62 :       CALL dbt_destroy(t_3c_ctr_RI)
    5695           62 :       CALL dbt_destroy(t_3c_ctr_AO)
    5696           62 :       CALL dbt_destroy(t_AO_tmp)
    5697           62 :       CALL dbt_destroy(t_RI_tmp)
    5698              : 
    5699              :       ! compute and add the periodic correction
    5700           62 :       IF (do_periodic) THEN
    5701              : 
    5702            4 :          ext_scaling = 0.2_dp
    5703              : 
    5704              :          ! loop over omega' (integration)
    5705           24 :          DO iquad = 1, num_points_corr
    5706              : 
    5707              :             ! use the Clenshaw-grid
    5708           20 :             t_i_Clenshaw = iquad*pi/(2.0_dp*num_points_corr)
    5709           20 :             omega_i = ext_scaling/TAN(t_i_Clenshaw)
    5710              : 
    5711           20 :             IF (iquad < num_points_corr) THEN
    5712           16 :                weight_i = ext_scaling*pi/(num_points_corr*SIN(t_i_Clenshaw)**2)
    5713              :             ELSE
    5714            4 :                weight_i = ext_scaling*pi/(2.0_dp*num_points_corr*SIN(t_i_Clenshaw)**2)
    5715              :             END IF
    5716              : 
    5717              :             CALL calc_periodic_correction(delta_corr, qs_env, para_env, para_env_RPA, &
    5718              :                                           mp2_env%ri_g0w0%kp_grid, homo, nmo, gw_corr_lev_occ, &
    5719              :                                           gw_corr_lev_virt, omega_i, fm_mo_coeff, Eigenval, &
    5720              :                                           matrix_berry_re_mo_mo, matrix_berry_im_mo_mo, &
    5721              :                                           first_cycle_periodic_correction, kpoints, &
    5722              :                                           mp2_env%ri_g0w0%do_mo_coeff_gamma, &
    5723              :                                           mp2_env%ri_g0w0%num_kp_grids, mp2_env%ri_g0w0%eps_kpoint, &
    5724              :                                           mp2_env%ri_g0w0%do_extra_kpoints, &
    5725           20 :                                           mp2_env%ri_g0w0%do_aux_bas_gw, mp2_env%ri_g0w0%frac_aux_mos)
    5726              : 
    5727          204 :             DO n_level_gw = 1, gw_corr_lev_tot
    5728              : 
    5729          180 :                n_level_gw_ref = n_level_gw + homo - gw_corr_lev_occ
    5730              : 
    5731          180 :                IF (n_level_gw <= gw_corr_lev_occ) THEN
    5732              :                   sign_occ_virt = -1.0_dp
    5733              :                ELSE
    5734          100 :                   sign_occ_virt = 1.0_dp
    5735              :                END IF
    5736              : 
    5737         2160 :                DO jquad = 1, num_integ_points
    5738              : 
    5739         1960 :                   omega_sign = tj(jquad)*sign_occ_virt
    5740              : 
    5741              :                   delta_corr_omega(n_level_gw_ref, jquad) = &
    5742              :                      delta_corr_omega(n_level_gw_ref, jquad) - &
    5743              :                      0.5_dp/pi*weight_i/2.0_dp*delta_corr(n_level_gw_ref)* &
    5744              :                      (1.0_dp/(gaussi*(omega_i + omega_sign) + e_fermi - Eigenval(n_level_gw_ref)) + &
    5745         2140 :                       1.0_dp/(gaussi*(-omega_i + omega_sign) + e_fermi - Eigenval(n_level_gw_ref)))
    5746              : 
    5747              :                END DO
    5748              : 
    5749              :             END DO
    5750              : 
    5751              :          END DO
    5752              : 
    5753            4 :          gw_lev_start = 1 + homo - gw_corr_lev_occ
    5754            4 :          gw_lev_end = homo + gw_corr_lev_virt
    5755              : 
    5756              :          ! add the periodic correction
    5757              :          vec_Sigma_c_gw(1:gw_corr_lev_tot, :, 1) = vec_Sigma_c_gw(1:gw_corr_lev_tot, :, 1) + &
    5758          182 :                                                    delta_corr_omega(gw_lev_start:gw_lev_end, 1:num_fit_points)
    5759              : 
    5760              :       END IF
    5761              : 
    5762           62 :       DEALLOCATE (vec_Sigma_c_gw_pos_tau)
    5763           62 :       DEALLOCATE (vec_Sigma_c_gw_neg_tau)
    5764           62 :       DEALLOCATE (vec_Sigma_c_gw_cos_tau)
    5765           62 :       DEALLOCATE (vec_Sigma_c_gw_sin_tau)
    5766           62 :       DEALLOCATE (vec_Sigma_c_gw_cos_omega)
    5767           62 :       DEALLOCATE (vec_Sigma_c_gw_sin_omega)
    5768           62 :       DEALLOCATE (delta_corr_omega)
    5769              : 
    5770           62 :       CALL timestop(handle)
    5771              : 
    5772          186 :    END SUBROUTINE compute_self_energy_cubic_gw
    5773              : 
    5774              : ! **************************************************************************************************
    5775              : !> \brief ...
    5776              : !> \param num_integ_points ...
    5777              : !> \param tau_tj ...
    5778              : !> \param tj ...
    5779              : !> \param matrix_s ...
    5780              : !> \param Eigenval ...
    5781              : !> \param e_fermi ...
    5782              : !> \param fm_mat_W ...
    5783              : !> \param gw_corr_lev_tot ...
    5784              : !> \param gw_corr_lev_occ ...
    5785              : !> \param gw_corr_lev_virt ...
    5786              : !> \param homo ...
    5787              : !> \param count_ev_sc_GW ...
    5788              : !> \param count_sc_GW0 ...
    5789              : !> \param t_3c_O ...
    5790              : !> \param t_3c_M ...
    5791              : !> \param t_3c_O_compressed ...
    5792              : !> \param t_3c_O_ind ...
    5793              : !> \param mat_W ...
    5794              : !> \param mat_MinvVMinv ...
    5795              : !> \param weights_cos_tf_t_to_w ...
    5796              : !> \param weights_sin_tf_t_to_w ...
    5797              : !> \param vec_Sigma_c_gw ...
    5798              : !> \param qs_env ...
    5799              : !> \param para_env ...
    5800              : !> \param mp2_env ...
    5801              : !> \param num_fit_points ...
    5802              : !> \param fm_mo_coeff ...
    5803              : !> \param do_ri_Sigma_x ...
    5804              : !> \param vec_Sigma_x_gw ...
    5805              : !> \param unit_nr ...
    5806              : !> \param nspins ...
    5807              : !> \param starts_array_mc ...
    5808              : !> \param ends_array_mc ...
    5809              : !> \param eps_filter ...
    5810              : ! **************************************************************************************************
    5811           16 :    SUBROUTINE compute_self_energy_cubic_gw_kpoints(num_integ_points, tau_tj, tj, &
    5812           16 :                                                    matrix_s, Eigenval, e_fermi, fm_mat_W, &
    5813           16 :                                                    gw_corr_lev_tot, gw_corr_lev_occ, gw_corr_lev_virt, homo, &
    5814              :                                                    count_ev_sc_GW, count_sc_GW0, &
    5815              :                                                    t_3c_O, t_3c_M, t_3c_O_compressed, t_3c_O_ind, &
    5816              :                                                    mat_W, mat_MinvVMinv, &
    5817           32 :                                                    weights_cos_tf_t_to_w, weights_sin_tf_t_to_w, vec_Sigma_c_gw, &
    5818              :                                                    qs_env, para_env, &
    5819              :                                                    mp2_env, num_fit_points, fm_mo_coeff, &
    5820           16 :                                                    do_ri_Sigma_x, vec_Sigma_x_gw, unit_nr, nspins, &
    5821           16 :                                                    starts_array_mc, ends_array_mc, eps_filter)
    5822              : 
    5823              :       INTEGER, INTENT(IN)                                :: num_integ_points
    5824              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
    5825              :          INTENT(IN)                                      :: tau_tj, tj
    5826              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN)       :: matrix_s
    5827              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: Eigenval
    5828              :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: e_fermi
    5829              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: fm_mat_W
    5830              :       INTEGER, INTENT(IN)                                :: gw_corr_lev_tot
    5831              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: gw_corr_lev_occ, gw_corr_lev_virt, homo
    5832              :       INTEGER, INTENT(IN)                                :: count_ev_sc_GW, count_sc_GW0
    5833              :       TYPE(dbt_type), ALLOCATABLE, DIMENSION(:, :)       :: t_3c_O
    5834              :       TYPE(dbt_type)                                     :: t_3c_M
    5835              :       TYPE(hfx_compression_type), ALLOCATABLE, &
    5836              :          DIMENSION(:, :, :)                              :: t_3c_O_compressed
    5837              :       TYPE(block_ind_type), ALLOCATABLE, &
    5838              :          DIMENSION(:, :, :), INTENT(INOUT)               :: t_3c_O_ind
    5839              :       TYPE(dbcsr_type), INTENT(INOUT), TARGET            :: mat_W
    5840              :       TYPE(dbcsr_p_type)                                 :: mat_MinvVMinv
    5841              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: weights_cos_tf_t_to_w, &
    5842              :                                                             weights_sin_tf_t_to_w
    5843              :       COMPLEX(KIND=dp), DIMENSION(:, :, :, :), &
    5844              :          INTENT(OUT)                                     :: vec_Sigma_c_gw
    5845              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    5846              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    5847              :       TYPE(mp2_type), INTENT(INOUT)                      :: mp2_env
    5848              :       INTEGER, INTENT(IN)                                :: num_fit_points
    5849              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_mo_coeff
    5850              :       LOGICAL, INTENT(IN)                                :: do_ri_Sigma_x
    5851              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT)   :: vec_Sigma_x_gw
    5852              :       INTEGER, INTENT(IN)                                :: unit_nr, nspins
    5853              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: starts_array_mc, ends_array_mc
    5854              :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter
    5855              : 
    5856              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_self_energy_cubic_gw_kpoints'
    5857              : 
    5858              :       INTEGER                                            :: cut_memory, handle, handle2, i_mem, &
    5859              :                                                             iquad, ispin, j_mem, jquad, &
    5860              :                                                             nkp_self_energy, num_points, &
    5861              :                                                             unit_nr_prv
    5862           32 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: dist1, dist2, sizes_AO, sizes_RI
    5863              :       INTEGER, DIMENSION(2)                              :: mo_end, mo_start, pdims_2d
    5864              :       INTEGER, DIMENSION(2, 1)                           :: bounds_RI_i
    5865              :       INTEGER, DIMENSION(2, 2)                           :: bounds_ao_ao_j
    5866              :       INTEGER, DIMENSION(3)                              :: dims_3c
    5867              :       LOGICAL                                            :: memory_info
    5868              :       REAL(KIND=dp)                                      :: omega, t1, t2, tau, weight_cos, &
    5869              :                                                             weight_sin
    5870           16 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :, :) :: vec_Sigma_c_gw_cos_omega, &
    5871           16 :          vec_Sigma_c_gw_cos_tau, vec_Sigma_c_gw_neg_tau, vec_Sigma_c_gw_pos_tau, &
    5872           16 :          vec_Sigma_c_gw_sin_omega, vec_Sigma_c_gw_sin_tau
    5873           16 :       TYPE(dbcsr_p_type), DIMENSION(:, :, :), POINTER    :: propagator
    5874              :       TYPE(dbcsr_type), TARGET :: mat_greens_fct_occ, mat_greens_fct_virt, mat_mo_coeff, &
    5875              :          mat_self_energy_ao_ao_neg_tau, mat_self_energy_ao_ao_pos_tau
    5876           48 :       TYPE(dbt_pgrid_type)                               :: pgrid_2d
    5877          304 :       TYPE(dbt_type)                                     :: t_3c_M_W_tmp, t_3c_O_all, t_3c_O_W, &
    5878          208 :                                                             t_AO_tmp, t_greens_fct_occ, &
    5879          304 :                                                             t_greens_fct_virt, t_RI_tmp, t_W
    5880              : 
    5881           16 :       CALL timeset(routineN, handle)
    5882              : 
    5883           16 :       NULLIFY (propagator)
    5884              : 
    5885           16 :       memory_info = mp2_env%ri_rpa_im_time%memory_info
    5886           16 :       IF (memory_info) THEN
    5887            0 :          unit_nr_prv = unit_nr
    5888              :       ELSE
    5889           16 :          unit_nr_prv = 0
    5890              :       END IF
    5891              : 
    5892           16 :       cut_memory = mp2_env%ri_rpa_im_time%cut_memory
    5893              : 
    5894           34 :       DO ispin = 1, nspins
    5895           18 :          mo_start(ispin) = homo(ispin) - gw_corr_lev_occ(ispin) + 1
    5896           18 :          mo_end(ispin) = homo(ispin) + gw_corr_lev_virt(ispin)
    5897           34 :          CPASSERT(mo_end(ispin) - mo_start(ispin) + 1 == gw_corr_lev_tot)
    5898              :       END DO
    5899              : 
    5900           16 :       nkp_self_energy = mp2_env%ri_g0w0%nkp_self_energy
    5901              : 
    5902         1346 :       vec_Sigma_c_gw = z_zero
    5903           96 :       ALLOCATE (vec_Sigma_c_gw_pos_tau(gw_corr_lev_tot, num_integ_points, nkp_self_energy, nspins))
    5904           16 :       vec_Sigma_c_gw_pos_tau = 0.0_dp
    5905           80 :       ALLOCATE (vec_Sigma_c_gw_neg_tau(gw_corr_lev_tot, num_integ_points, nkp_self_energy, nspins))
    5906           16 :       vec_Sigma_c_gw_neg_tau = 0.0_dp
    5907           80 :       ALLOCATE (vec_Sigma_c_gw_cos_tau(gw_corr_lev_tot, num_integ_points, nkp_self_energy, nspins))
    5908           16 :       vec_Sigma_c_gw_cos_tau = 0.0_dp
    5909           80 :       ALLOCATE (vec_Sigma_c_gw_sin_tau(gw_corr_lev_tot, num_integ_points, nkp_self_energy, nspins))
    5910           16 :       vec_Sigma_c_gw_sin_tau = 0.0_dp
    5911              : 
    5912           80 :       ALLOCATE (vec_Sigma_c_gw_cos_omega(gw_corr_lev_tot, num_integ_points, nkp_self_energy, nspins))
    5913           16 :       vec_Sigma_c_gw_cos_omega = 0.0_dp
    5914           80 :       ALLOCATE (vec_Sigma_c_gw_sin_omega(gw_corr_lev_tot, num_integ_points, nkp_self_energy, nspins))
    5915           16 :       vec_Sigma_c_gw_sin_omega = 0.0_dp
    5916              : 
    5917              :       CALL dbcsr_create(matrix=mat_greens_fct_occ, &
    5918              :                         template=matrix_s(1)%matrix, &
    5919           16 :                         matrix_type=dbcsr_type_no_symmetry)
    5920              : 
    5921              :       CALL dbcsr_create(matrix=mat_greens_fct_virt, &
    5922              :                         template=matrix_s(1)%matrix, &
    5923           16 :                         matrix_type=dbcsr_type_no_symmetry)
    5924              : 
    5925              :       CALL dbcsr_create(matrix=mat_self_energy_ao_ao_neg_tau, &
    5926              :                         template=matrix_s(1)%matrix, &
    5927           16 :                         matrix_type=dbcsr_type_no_symmetry)
    5928              : 
    5929              :       CALL dbcsr_create(matrix=mat_self_energy_ao_ao_pos_tau, &
    5930              :                         template=matrix_s(1)%matrix, &
    5931           16 :                         matrix_type=dbcsr_type_no_symmetry)
    5932              : 
    5933              :       CALL dbcsr_create(matrix=mat_mo_coeff, &
    5934              :                         template=matrix_s(1)%matrix, &
    5935           16 :                         matrix_type=dbcsr_type_no_symmetry)
    5936              : 
    5937           16 :       CALL copy_fm_to_dbcsr(fm_mo_coeff, mat_mo_coeff, keep_sparsity=.FALSE.)
    5938              : 
    5939           34 :       DO ispin = 1, nspins
    5940          664 :          e_fermi(ispin) = 0.5_dp*(MAXVAL(Eigenval(homo, :, ispin)) + MINVAL(Eigenval(homo + 1, :, ispin)))
    5941              :       END DO
    5942              : 
    5943           16 :       pdims_2d = 0
    5944           16 :       CALL dbt_pgrid_create(para_env, pdims_2d, pgrid_2d)
    5945           48 :       ALLOCATE (sizes_RI(dbt_nblks_total(t_3c_O(1, 1), 1)))
    5946           16 :       CALL dbt_get_info(t_3c_O(1, 1), blk_size_1=sizes_RI)
    5947              : 
    5948           16 :       CALL create_2c_tensor(t_W, dist1, dist2, pgrid_2d, sizes_RI, sizes_RI, name="(RI|RI)")
    5949           16 :       DEALLOCATE (dist1, dist2)
    5950              : 
    5951           16 :       CALL dbt_create(mat_W, t_RI_tmp, name="(RI|RI)")
    5952              : 
    5953           48 :       ALLOCATE (sizes_AO(dbt_nblks_total(t_3c_O(1, 1), 2)))
    5954           16 :       CALL dbt_get_info(t_3c_O(1, 1), blk_size_2=sizes_AO)
    5955           16 :       CALL create_2c_tensor(t_greens_fct_occ, dist1, dist2, pgrid_2d, sizes_AO, sizes_AO, name="(AO|AO)")
    5956              : 
    5957           16 :       DEALLOCATE (dist1, dist2)
    5958           16 :       CALL create_2c_tensor(t_greens_fct_virt, dist1, dist2, pgrid_2d, sizes_AO, sizes_AO, name="(AO|AO)")
    5959           16 :       DEALLOCATE (dist1, dist2)
    5960              : 
    5961           16 :       CALL dbt_get_info(t_3c_M, nfull_total=dims_3c)
    5962              : 
    5963           16 :       CALL dbt_create(t_3c_O(1, 1), t_3c_O_all, name="O (RI AO | AO)")
    5964              : 
    5965              :       ! get full 3c tensor
    5966           74 :       DO i_mem = 1, cut_memory
    5967              :          CALL decompress_tensor(t_3c_O(1, 1), &
    5968              :                                 t_3c_O_ind(1, 1, i_mem)%ind, &
    5969              :                                 t_3c_O_compressed(1, 1, i_mem), &
    5970           58 :                                 mp2_env%ri_rpa_im_time%eps_compress)
    5971           74 :          CALL dbt_copy(t_3c_O(1, 1), t_3c_O_all, summation=.TRUE., move_data=.TRUE.)
    5972              :       END DO
    5973              : 
    5974           16 :       CALL dbt_create(t_3c_M, t_3c_M_W_tmp, name="M W (RI | AO AO)")
    5975           16 :       CALL dbt_create(t_3c_O(1, 1), t_3c_O_W, name="M W (RI AO | AO)")
    5976              : 
    5977           16 :       CALL dbt_create(mat_greens_fct_occ, t_AO_tmp, name="(AO|AO)")
    5978              : 
    5979           16 :       IF (count_ev_sc_GW == 1 .AND. count_sc_GW0 == 1 .AND. do_ri_Sigma_x) THEN
    5980           12 :          num_points = num_integ_points + 1
    5981              :       ELSE
    5982            4 :          num_points = num_integ_points
    5983              :       END IF
    5984              : 
    5985          124 :       DO jquad = 1, num_points
    5986              : 
    5987          108 :          t1 = m_walltime()
    5988              : 
    5989          108 :          IF (jquad <= num_integ_points) THEN
    5990           96 :             tau = tau_tj(jquad)
    5991              : 
    5992           96 :             IF (unit_nr > 0) WRITE (unit_nr, '(/T3,A,1X,I3)') &
    5993           48 :                'GW_INFO| Computing self-energy time point', jquad
    5994              :          ELSE
    5995           12 :             tau = 0.0_dp
    5996              : 
    5997           12 :             IF (unit_nr > 0) WRITE (unit_nr, '(/T3,A,1X,I3)') &
    5998            6 :                'GW_INFO| Computing exchange self-energy'
    5999              :          END IF
    6000              : 
    6001          108 :          IF (jquad <= num_integ_points) THEN
    6002           96 :             CALL dbcsr_set(mat_W, 0.0_dp)
    6003           96 :             CALL copy_fm_to_dbcsr(fm_mat_W(jquad), mat_W, keep_sparsity=.FALSE.)
    6004           96 :             CALL dbt_copy_matrix_to_tensor(mat_W, t_RI_tmp)
    6005              :          ELSE
    6006           12 :             CALL dbt_copy_matrix_to_tensor(mat_MinvVMinv%matrix, t_RI_tmp)
    6007              :          END IF
    6008              : 
    6009          108 :          CALL dbt_copy(t_RI_tmp, t_W)
    6010              : 
    6011          230 :          DO ispin = 1, nspins
    6012              : 
    6013              :             CALL compute_periodic_dm(propagator, qs_env, &
    6014              :                                      ispin, num_points, jquad, e_fermi(ispin), tau, &
    6015          122 :                                      sector=propagator_sector_occupied)
    6016              : 
    6017              :             CALL compute_periodic_dm(propagator, qs_env, &
    6018              :                                      ispin, num_points, jquad, e_fermi(ispin), tau, &
    6019          122 :                                      sector=propagator_sector_virtual)
    6020              : 
    6021          122 :             CALL dbcsr_set(mat_greens_fct_occ, 0.0_dp)
    6022              :             CALL dbcsr_copy(mat_greens_fct_occ, &
    6023          122 :                             propagator(propagator_sector_occupied, jquad, 1)%matrix)
    6024              : 
    6025          122 :             CALL dbcsr_set(mat_greens_fct_virt, 0.0_dp)
    6026              :             CALL dbcsr_copy(mat_greens_fct_virt, &
    6027          122 :                             propagator(propagator_sector_virtual, jquad, 1)%matrix)
    6028              : 
    6029          122 :             CALL dbt_copy_matrix_to_tensor(mat_greens_fct_occ, t_AO_tmp)
    6030          122 :             CALL dbt_copy(t_AO_tmp, t_greens_fct_occ)
    6031              : 
    6032          122 :             CALL dbt_copy_matrix_to_tensor(mat_greens_fct_virt, t_AO_tmp)
    6033          122 :             CALL dbt_copy(t_AO_tmp, t_greens_fct_virt)
    6034              : 
    6035          122 :             CALL dbcsr_set(mat_self_energy_ao_ao_neg_tau, 0.0_dp)
    6036          122 :             CALL dbcsr_set(mat_self_energy_ao_ao_pos_tau, 0.0_dp)
    6037              : 
    6038          122 :             CALL dbt_copy(t_3c_O_all, t_3c_M)
    6039              : 
    6040          122 :             CALL dbt_batched_contract_init(t_3c_O_W)
    6041              :             !         CALL dbt_batched_contract_init(t_3c_O_G)
    6042              :             !         CALL dbt_batched_contract_init(t_self_energy)
    6043              : 
    6044          554 :             DO i_mem = 1, cut_memory ! memory cut for RI index
    6045              : 
    6046              :                !            CALL dbt_batched_contract_init(t_W)
    6047              :                !            CALL dbt_batched_contract_init(t_3c_M)
    6048              :                !            CALL dbt_batched_contract_init(t_3c_M_W_tmp)
    6049              : 
    6050              :                bounds_RI_i(:, 1) = [qs_env%mp2_env%ri_rpa_im_time%starts_array_mc_RI(i_mem), &
    6051         1296 :                                     qs_env%mp2_env%ri_rpa_im_time%ends_array_mc_RI(i_mem)]
    6052              : 
    6053         2142 :                DO j_mem = 1, cut_memory ! memory cut for ao index
    6054              : 
    6055         4764 :                   bounds_ao_ao_j(:, 1) = [starts_array_mc(j_mem), ends_array_mc(j_mem)]
    6056         4764 :                   bounds_ao_ao_j(:, 2) = [1, dims_3c(3)]
    6057              : 
    6058         1588 :                   CALL timeset("tensor_operation_3c_W", handle2)
    6059              : 
    6060              :                   CALL dbt_contract(1.0_dp, t_W, t_3c_M, 0.0_dp, &
    6061              :                                     t_3c_M_W_tmp, &
    6062              :                                     contract_1=[2], notcontract_1=[1], &
    6063              :                                     contract_2=[1], notcontract_2=[2, 3], &
    6064              :                                     map_1=[1], map_2=[2, 3], &
    6065              :                                     bounds_2=bounds_RI_i, &
    6066              :                                     bounds_3=bounds_ao_ao_j, &
    6067              :                                     filter_eps=eps_filter, &
    6068         1588 :                                     unit_nr=unit_nr_prv)
    6069              : 
    6070         1588 :                   CALL dbt_copy(t_3c_M_W_tmp, t_3c_O_W, order=[1, 2, 3], move_data=.TRUE.)
    6071              : 
    6072         1588 :                   CALL timestop(handle2)
    6073              : 
    6074              :                   CALL contract_to_self_energy(t_3c_O_all, t_greens_fct_occ, t_3c_O_W, &
    6075              :                                                mat_self_energy_ao_ao_neg_tau, &
    6076              :                                                bounds_ao_ao_j, bounds_RI_i, unit_nr_prv, &
    6077         1588 :                                                eps_filter, do_occ=.TRUE., do_virt=.FALSE.)
    6078              : 
    6079              :                   CALL contract_to_self_energy(t_3c_O_all, t_greens_fct_virt, t_3c_O_W, &
    6080              :                                                mat_self_energy_ao_ao_pos_tau, &
    6081              :                                                bounds_ao_ao_j, bounds_RI_i, unit_nr_prv, &
    6082         3608 :                                                eps_filter, do_occ=.FALSE., do_virt=.TRUE.)
    6083              : 
    6084              :                END DO ! j_mem
    6085              : 
    6086              :                !            CALL dbt_batched_contract_finalize(t_W)
    6087              :                !            CALL dbt_batched_contract_finalize(t_3c_M)
    6088              :                !            CALL dbt_batched_contract_finalize(t_3c_M_W_tmp)
    6089              : 
    6090              :             END DO ! i_mem
    6091              : 
    6092          122 :             CALL dbt_batched_contract_finalize(t_3c_O_W)
    6093              :             !         CALL dbt_batched_contract_finalize(t_3c_O_G)
    6094              :             !         CALL dbt_batched_contract_finalize(t_self_energy)
    6095              : 
    6096          230 :             IF (jquad <= num_integ_points) THEN
    6097              : 
    6098              :                CALL trafo_to_mo_and_kpoints(qs_env, mat_self_energy_ao_ao_neg_tau, vec_Sigma_c_gw_neg_tau(:, jquad, :, ispin), &
    6099          108 :                                             homo(ispin), gw_corr_lev_occ(ispin), gw_corr_lev_virt(ispin), ispin)
    6100              : 
    6101              :                CALL trafo_to_mo_and_kpoints(qs_env, mat_self_energy_ao_ao_pos_tau, vec_Sigma_c_gw_pos_tau(:, jquad, :, ispin), &
    6102          108 :                                             homo(ispin), gw_corr_lev_occ(ispin), gw_corr_lev_virt(ispin), ispin)
    6103              : 
    6104              :                vec_Sigma_c_gw_cos_tau(:, jquad, :, ispin) = 0.5_dp*(vec_Sigma_c_gw_pos_tau(:, jquad, :, ispin) + &
    6105         2556 :                                                                     vec_Sigma_c_gw_neg_tau(:, jquad, :, ispin))
    6106              : 
    6107              :                vec_Sigma_c_gw_sin_tau(:, jquad, :, ispin) = 0.5_dp*(vec_Sigma_c_gw_pos_tau(:, jquad, :, ispin) - &
    6108         2556 :                                                                     vec_Sigma_c_gw_neg_tau(:, jquad, :, ispin))
    6109              :             ELSE
    6110              : 
    6111              :                CALL trafo_to_mo_and_kpoints(qs_env, mat_self_energy_ao_ao_neg_tau, &
    6112              :                                             vec_Sigma_x_gw(mo_start(ispin):mo_end(ispin), :, ispin), &
    6113           14 :                                             homo(ispin), gw_corr_lev_occ(ispin), gw_corr_lev_virt(ispin), ispin)
    6114              : 
    6115              :             END IF
    6116              : 
    6117              :          END DO ! spins
    6118              : 
    6119          108 :          t2 = m_walltime()
    6120              : 
    6121          124 :          IF (unit_nr > 0) WRITE (unit_nr, '(T6,A,T56,F25.1)') 'Execution time (s):', t2 - t1
    6122              : 
    6123              :       END DO ! jquad (tau)
    6124              : 
    6125           16 :       IF (count_ev_sc_GW == 1 .AND. count_sc_GW0 == 1) THEN
    6126              : 
    6127           16 :          CALL compute_minus_vxc_kpoints(qs_env)
    6128              : 
    6129           16 :          IF (do_ri_Sigma_x) THEN
    6130           26 :             DO ispin = 1, nspins
    6131              :                mp2_env%ri_g0w0%vec_Sigma_x_minus_vxc_gw(:, ispin, :) = mp2_env%ri_g0w0%vec_Sigma_x_minus_vxc_gw(:, ispin, :) + &
    6132         2154 :                                                                        vec_Sigma_x_gw(:, :, ispin)
    6133              :             END DO
    6134              :          END IF
    6135              : 
    6136              :       END IF
    6137              : 
    6138              :       ! Fourier transform from time to frequency
    6139           62 :       DO jquad = 1, num_fit_points
    6140              : 
    6141          338 :          DO iquad = 1, num_integ_points
    6142              : 
    6143          276 :             omega = tj(jquad)
    6144          276 :             tau = tau_tj(iquad)
    6145          276 :             weight_cos = weights_cos_tf_t_to_w(jquad, iquad)*COS(omega*tau)
    6146          276 :             weight_sin = weights_sin_tf_t_to_w(jquad, iquad)*SIN(omega*tau)
    6147              : 
    6148              :             vec_Sigma_c_gw_cos_omega(:, jquad, :, :) = vec_Sigma_c_gw_cos_omega(:, jquad, :, :) + &
    6149         7644 :                                                        weight_cos*vec_Sigma_c_gw_cos_tau(:, iquad, :, :)
    6150              : 
    6151              :             vec_Sigma_c_gw_sin_omega(:, jquad, :, :) = vec_Sigma_c_gw_sin_omega(:, jquad, :, :) + &
    6152         7690 :                                                        weight_sin*vec_Sigma_c_gw_sin_tau(:, iquad, :, :)
    6153              : 
    6154              :          END DO
    6155              : 
    6156              :       END DO
    6157              : 
    6158              :       ! for occupied levels, we need the correlation self-energy for negative omega. Therefore, weight_sin
    6159              :       ! should be computed with -omega, which results in an additional minus for vec_Sigma_c_gw_sin_omega:
    6160           34 :       DO ispin = 1, nspins
    6161              :          vec_Sigma_c_gw_sin_omega(1:gw_corr_lev_occ(ispin), :, :, ispin) = &
    6162         1802 :             -vec_Sigma_c_gw_sin_omega(1:gw_corr_lev_occ(ispin), :, :, ispin)
    6163              :       END DO
    6164              : 
    6165              :       vec_Sigma_c_gw(:, 1:num_fit_points, :, :) = vec_Sigma_c_gw_cos_omega(:, 1:num_fit_points, :, :) + &
    6166         1346 :                                                   gaussi*vec_Sigma_c_gw_sin_omega(:, 1:num_fit_points, :, :)
    6167              : 
    6168           16 :       CALL dbt_pgrid_destroy(pgrid_2d)
    6169              : 
    6170           16 :       CALL dbcsr_release(mat_greens_fct_occ)
    6171           16 :       CALL dbcsr_release(mat_greens_fct_virt)
    6172           16 :       CALL dbcsr_release(mat_self_energy_ao_ao_neg_tau)
    6173           16 :       CALL dbcsr_release(mat_self_energy_ao_ao_pos_tau)
    6174           16 :       CALL dbcsr_release(mat_mo_coeff)
    6175              : 
    6176           16 :       CALL dbcsr_deallocate_matrix_set(propagator)
    6177              : 
    6178           16 :       CALL dbt_destroy(t_W)
    6179           16 :       CALL dbt_destroy(t_RI_tmp)
    6180           16 :       CALL dbt_destroy(t_greens_fct_occ)
    6181           16 :       CALL dbt_destroy(t_greens_fct_virt)
    6182           16 :       CALL dbt_destroy(t_AO_tmp)
    6183           16 :       CALL dbt_destroy(t_3c_O_all)
    6184           16 :       CALL dbt_destroy(t_3c_M_W_tmp)
    6185           16 :       CALL dbt_destroy(t_3c_O_W)
    6186              : 
    6187           16 :       DEALLOCATE (vec_Sigma_c_gw_pos_tau)
    6188           16 :       DEALLOCATE (vec_Sigma_c_gw_neg_tau)
    6189           16 :       DEALLOCATE (vec_Sigma_c_gw_cos_tau)
    6190           16 :       DEALLOCATE (vec_Sigma_c_gw_sin_tau)
    6191           16 :       DEALLOCATE (vec_Sigma_c_gw_cos_omega)
    6192           16 :       DEALLOCATE (vec_Sigma_c_gw_sin_omega)
    6193              : 
    6194           16 :       CALL timestop(handle)
    6195              : 
    6196           64 :    END SUBROUTINE compute_self_energy_cubic_gw_kpoints
    6197              : 
    6198              : ! **************************************************************************************************
    6199              : !> \brief ...
    6200              : !> \param qs_env ...
    6201              : ! **************************************************************************************************
    6202           16 :    SUBROUTINE compute_minus_vxc_kpoints(qs_env)
    6203              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    6204              : 
    6205              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_minus_vxc_kpoints'
    6206              : 
    6207              :       INTEGER                                            :: handle, ikp, ispin, nkp_self_energy, &
    6208              :                                                             nmo, nspins
    6209              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: diag_Sigma_x_minus_vxc_mo_mo
    6210              :       TYPE(cp_cfm_type)                                  :: cfm_mo_coeff, ks_mat_ao_ao, &
    6211              :                                                             ks_mat_no_xc_ao_ao, vxc_ao_ao, &
    6212              :                                                             vxc_ao_mo, vxc_mo_mo
    6213              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
    6214              :       TYPE(cp_fm_type)                                   :: fm_dummy, fm_Sigma_x_minus_vxc_mo_mo, &
    6215              :                                                             fm_tmp_im, fm_tmp_re
    6216              :       TYPE(dft_control_type), POINTER                    :: dft_control
    6217              :       TYPE(kpoint_type), POINTER                         :: kpoints_Sigma, kpoints_Sigma_no_xc
    6218              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    6219              : 
    6220           16 :       CALL timeset(routineN, handle)
    6221              : 
    6222           16 :       CALL get_qs_env(qs_env, para_env=para_env, dft_control=dft_control)
    6223              : 
    6224           16 :       kpoints_Sigma => qs_env%mp2_env%ri_rpa_im_time%kpoints_Sigma
    6225              : 
    6226           16 :       kpoints_Sigma_no_xc => qs_env%mp2_env%ri_rpa_im_time%kpoints_Sigma_no_xc
    6227              : 
    6228           16 :       nkp_self_energy = kpoints_Sigma%nkp
    6229              : 
    6230           16 :       nspins = dft_control%nspins
    6231              : 
    6232           16 :       matrix_struct => kpoints_Sigma%kp_env(1)%kpoint_env%wmat(1, 1)%matrix_struct
    6233              : 
    6234           16 :       CALL cp_cfm_create(ks_mat_ao_ao, matrix_struct)
    6235           16 :       CALL cp_cfm_create(ks_mat_no_xc_ao_ao, matrix_struct)
    6236           16 :       CALL cp_cfm_create(vxc_ao_ao, matrix_struct)
    6237           16 :       CALL cp_cfm_create(vxc_ao_mo, matrix_struct)
    6238           16 :       CALL cp_cfm_create(vxc_mo_mo, matrix_struct)
    6239           16 :       CALL cp_cfm_create(cfm_mo_coeff, matrix_struct)
    6240           16 :       CALL cp_fm_create(fm_Sigma_x_minus_vxc_mo_mo, matrix_struct)
    6241           16 :       CALL cp_fm_create(fm_tmp_re, matrix_struct)
    6242           16 :       CALL cp_fm_create(fm_tmp_im, matrix_struct)
    6243              : 
    6244           16 :       CALL cp_cfm_get_info(cfm_mo_coeff, nrow_global=nmo)
    6245           48 :       ALLOCATE (diag_Sigma_x_minus_vxc_mo_mo(nmo))
    6246              : 
    6247           16 :       DEALLOCATE (qs_env%mp2_env%ri_g0w0%vec_Sigma_x_minus_vxc_gw)
    6248              : 
    6249           64 :       ALLOCATE (qs_env%mp2_env%ri_g0w0%vec_Sigma_x_minus_vxc_gw(nmo, 2, nkp_self_energy))
    6250              : 
    6251          136 :       DO ikp = 1, nkp_self_energy
    6252              : 
    6253          272 :          DO ispin = 1, nspins
    6254              : 
    6255              :             ASSOCIATE (mos => kpoints_Sigma%kp_env(ikp)%kpoint_env%mos)
    6256          136 :             IF (ASSOCIATED(mos(1, ispin)%mo_coeff)) THEN
    6257          136 :                CALL cp_fm_copy_general(mos(1, ispin)%mo_coeff, fm_tmp_re, para_env)
    6258              :             ELSE
    6259            0 :                CALL cp_fm_copy_general(fm_dummy, fm_tmp_re, para_env)
    6260              :             END IF
    6261          272 :             IF (ASSOCIATED(mos(2, ispin)%mo_coeff)) THEN
    6262          136 :                CALL cp_fm_copy_general(mos(2, ispin)%mo_coeff, fm_tmp_im, para_env)
    6263              :             ELSE
    6264            0 :                CALL cp_fm_copy_general(fm_dummy, fm_tmp_im, para_env)
    6265              :             END IF
    6266              :             END ASSOCIATE
    6267              : 
    6268          136 :             CALL cp_fm_to_cfm(fm_tmp_re, fm_tmp_im, cfm_mo_coeff)
    6269              : 
    6270              :             CALL cp_fm_to_cfm(kpoints_Sigma%kp_env(ikp)%kpoint_env%wmat(1, ispin), &
    6271          136 :                               kpoints_Sigma%kp_env(ikp)%kpoint_env%wmat(2, ispin), ks_mat_ao_ao)
    6272              :             ASSOCIATE (wmat => kpoints_Sigma_no_xc%kp_env(ikp)%kpoint_env%wmat)
    6273          136 :             IF (ASSOCIATED(wmat(1, ispin)%matrix_struct)) THEN
    6274          136 :                CALL cp_fm_copy_general(wmat(1, ispin), fm_tmp_re, para_env)
    6275              :             ELSE
    6276            0 :                CALL cp_fm_copy_general(fm_dummy, fm_tmp_re, para_env)
    6277              :             END IF
    6278          272 :             IF (ASSOCIATED(wmat(2, ispin)%matrix_struct)) THEN
    6279          136 :                CALL cp_fm_copy_general(wmat(2, ispin), fm_tmp_im, para_env)
    6280              :             ELSE
    6281            0 :                CALL cp_fm_copy_general(fm_dummy, fm_tmp_im, para_env)
    6282              :             END IF
    6283              :             END ASSOCIATE
    6284              : 
    6285          136 :             CALL cp_fm_to_cfm(fm_tmp_re, fm_tmp_im, vxc_ao_ao)
    6286              : 
    6287          136 :             CALL parallel_gemm('N', 'N', nmo, nmo, nmo, z_one, vxc_ao_ao, cfm_mo_coeff, z_zero, vxc_ao_mo)
    6288          136 :             CALL parallel_gemm('C', 'N', nmo, nmo, nmo, z_one, cfm_mo_coeff, vxc_ao_mo, z_zero, vxc_mo_mo)
    6289              : 
    6290          136 :             CALL cp_cfm_to_fm(vxc_mo_mo, fm_Sigma_x_minus_vxc_mo_mo)
    6291              : 
    6292          136 :             CALL cp_fm_get_diag(fm_Sigma_x_minus_vxc_mo_mo, diag_Sigma_x_minus_vxc_mo_mo)
    6293              : 
    6294         3016 :             qs_env%mp2_env%ri_g0w0%vec_Sigma_x_minus_vxc_gw(:, ispin, ikp) = diag_Sigma_x_minus_vxc_mo_mo(:)
    6295              : 
    6296              :          END DO
    6297              : 
    6298              :       END DO
    6299              : 
    6300           16 :       CALL cp_cfm_release(ks_mat_ao_ao)
    6301           16 :       CALL cp_cfm_release(ks_mat_no_xc_ao_ao)
    6302           16 :       CALL cp_cfm_release(vxc_ao_ao)
    6303           16 :       CALL cp_cfm_release(vxc_ao_mo)
    6304           16 :       CALL cp_cfm_release(vxc_mo_mo)
    6305           16 :       CALL cp_cfm_release(cfm_mo_coeff)
    6306           16 :       CALL cp_fm_release(fm_Sigma_x_minus_vxc_mo_mo)
    6307           16 :       CALL cp_fm_release(fm_tmp_re)
    6308           16 :       CALL cp_fm_release(fm_tmp_im)
    6309              : 
    6310           16 :       DEALLOCATE (diag_Sigma_x_minus_vxc_mo_mo)
    6311              : 
    6312           16 :       CALL timestop(handle)
    6313              : 
    6314           32 :    END SUBROUTINE compute_minus_vxc_kpoints
    6315              : 
    6316              : ! **************************************************************************************************
    6317              : !> \brief ...
    6318              : !> \param qs_env ...
    6319              : !> \param mat_self_energy_ao_ao ...
    6320              : !> \param vec_Sigma ...
    6321              : !> \param homo ...
    6322              : !> \param gw_corr_lev_occ ...
    6323              : !> \param gw_corr_lev_virt ...
    6324              : !> \param ispin ...
    6325              : ! **************************************************************************************************
    6326          230 :    SUBROUTINE trafo_to_mo_and_kpoints(qs_env, mat_self_energy_ao_ao, vec_Sigma, &
    6327              :                                       homo, gw_corr_lev_occ, gw_corr_lev_virt, ispin)
    6328              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    6329              :       TYPE(dbcsr_type), TARGET                           :: mat_self_energy_ao_ao
    6330              :       REAL(KIND=dp), DIMENSION(:, :)                     :: vec_Sigma
    6331              :       INTEGER                                            :: homo, gw_corr_lev_occ, gw_corr_lev_virt, &
    6332              :                                                             ispin
    6333              : 
    6334              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'trafo_to_mo_and_kpoints'
    6335              : 
    6336              :       INTEGER                                            :: handle, ikp, nkp_self_energy, nmo, &
    6337              :                                                             periodic(3), size_real_space
    6338              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: diag_self_energy
    6339              :       TYPE(cell_type), POINTER                           :: cell
    6340              :       TYPE(cp_cfm_type)                                  :: cfm_mo_coeff, cfm_self_energy_ao_ao, &
    6341              :                                                             cfm_self_energy_ao_mo, &
    6342              :                                                             cfm_self_energy_mo_mo
    6343              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
    6344              :       TYPE(cp_fm_type)                                   :: fm_self_energy_mo_mo
    6345          230 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_self_energy_ao_ao_kp_im, &
    6346          230 :          mat_self_energy_ao_ao_kp_re, mat_self_energy_ao_ao_real_space
    6347              :       TYPE(kpoint_type), POINTER                         :: kpoints_Sigma
    6348              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    6349              : 
    6350          230 :       CALL timeset(routineN, handle)
    6351              : 
    6352          230 :       CALL get_qs_env(qs_env, cell=cell, para_env=para_env)
    6353          230 :       CALL get_cell(cell=cell, periodic=periodic)
    6354              : 
    6355          230 :       size_real_space = 3**(periodic(1) + periodic(2) + periodic(3))
    6356              : 
    6357          230 :       CALL alloc_mat_set(mat_self_energy_ao_ao_real_space, size_real_space, mat_self_energy_ao_ao)
    6358              : 
    6359          230 :       CALL dbcsr_copy(mat_self_energy_ao_ao_real_space(1)%matrix, mat_self_energy_ao_ao)
    6360              : 
    6361          230 :       kpoints_Sigma => qs_env%mp2_env%ri_rpa_im_time%kpoints_Sigma
    6362              : 
    6363          230 :       CALL get_mat_cell_T_from_mat_gamma(mat_self_energy_ao_ao_real_space, qs_env, kpoints_Sigma, 0, 0)
    6364              : 
    6365          230 :       nkp_self_energy = kpoints_Sigma%nkp
    6366              : 
    6367          230 :       CALL alloc_mat_set(mat_self_energy_ao_ao_kp_re, nkp_self_energy, mat_self_energy_ao_ao)
    6368          230 :       CALL alloc_mat_set(mat_self_energy_ao_ao_kp_im, nkp_self_energy, mat_self_energy_ao_ao)
    6369              : 
    6370              :       CALL real_space_to_kpoint_transform_rpa(mat_self_energy_ao_ao_kp_re, mat_self_energy_ao_ao_kp_im, &
    6371          230 :                                               mat_self_energy_ao_ao_real_space, kpoints_Sigma, 1.0E-50_dp)
    6372              : 
    6373          230 :       CALL dbcsr_get_info(mat_self_energy_ao_ao, nfullrows_total=nmo)
    6374          690 :       ALLOCATE (diag_self_energy(nmo))
    6375              : 
    6376          230 :       matrix_struct => kpoints_Sigma%kp_env(1)%kpoint_env%mos(1, 1)%mo_coeff%matrix_struct
    6377              : 
    6378          230 :       CALL cp_cfm_create(cfm_self_energy_ao_ao, matrix_struct)
    6379          230 :       CALL cp_cfm_create(cfm_self_energy_ao_mo, matrix_struct)
    6380          230 :       CALL cp_cfm_create(cfm_self_energy_mo_mo, matrix_struct)
    6381          230 :       CALL cp_cfm_set_all(cfm_self_energy_ao_ao, z_zero)
    6382          230 :       CALL cp_cfm_set_all(cfm_self_energy_ao_mo, z_zero)
    6383          230 :       CALL cp_cfm_set_all(cfm_self_energy_mo_mo, z_zero)
    6384              : 
    6385          230 :       CALL cp_fm_create(fm_self_energy_mo_mo, matrix_struct)
    6386          230 :       CALL cp_cfm_create(cfm_mo_coeff, matrix_struct)
    6387              : 
    6388         1966 :       DO ikp = 1, nkp_self_energy
    6389              : 
    6390              :          CALL dbcsr_to_cfm(mat_self_energy_ao_ao_kp_re(ikp)%matrix, &
    6391         1736 :                            mat_self_energy_ao_ao_kp_im(ikp)%matrix, cfm_self_energy_ao_ao)
    6392              : 
    6393              :          CALL cp_fm_to_cfm(kpoints_Sigma%kp_env(ikp)%kpoint_env%mos(1, ispin)%mo_coeff, &
    6394         1736 :                            kpoints_Sigma%kp_env(ikp)%kpoint_env%mos(2, ispin)%mo_coeff, cfm_mo_coeff)
    6395              : 
    6396              :          CALL parallel_gemm('N', 'N', nmo, nmo, nmo, z_one, cfm_self_energy_ao_ao, cfm_mo_coeff, &
    6397         1736 :                             z_zero, cfm_self_energy_ao_mo)
    6398              : 
    6399              :          CALL parallel_gemm('C', 'N', nmo, nmo, nmo, z_one, cfm_mo_coeff, cfm_self_energy_ao_mo, &
    6400         1736 :                             z_zero, cfm_self_energy_mo_mo)
    6401              : 
    6402         1736 :          CALL cp_cfm_to_fm(cfm_self_energy_mo_mo, fm_self_energy_mo_mo)
    6403              : 
    6404         1736 :          CALL cp_fm_get_diag(fm_self_energy_mo_mo, diag_self_energy)
    6405              : 
    6406         5438 :          vec_Sigma(:, ikp) = diag_self_energy(homo - gw_corr_lev_occ + 1:homo + gw_corr_lev_virt)
    6407              : 
    6408              :       END DO
    6409              : 
    6410          230 :       CALL dbcsr_deallocate_matrix_set(mat_self_energy_ao_ao_real_space)
    6411          230 :       CALL dbcsr_deallocate_matrix_set(mat_self_energy_ao_ao_kp_re)
    6412          230 :       CALL dbcsr_deallocate_matrix_set(mat_self_energy_ao_ao_kp_im)
    6413              : 
    6414          230 :       CALL cp_cfm_release(cfm_self_energy_ao_ao)
    6415          230 :       CALL cp_cfm_release(cfm_self_energy_ao_mo)
    6416          230 :       CALL cp_cfm_release(cfm_self_energy_mo_mo)
    6417          230 :       CALL cp_cfm_release(cfm_mo_coeff)
    6418          230 :       CALL cp_fm_release(fm_self_energy_mo_mo)
    6419              : 
    6420          230 :       DEALLOCATE (diag_self_energy)
    6421              : 
    6422          230 :       CALL timestop(handle)
    6423              : 
    6424          920 :    END SUBROUTINE trafo_to_mo_and_kpoints
    6425              : 
    6426              : ! **************************************************************************************************
    6427              : !> \brief ...
    6428              : !> \param dbcsr_re ...
    6429              : !> \param dbcsr_im ...
    6430              : !> \param cfm_mat ...
    6431              : ! **************************************************************************************************
    6432         5208 :    SUBROUTINE dbcsr_to_cfm(dbcsr_re, dbcsr_im, cfm_mat)
    6433              : 
    6434              :       TYPE(dbcsr_type), POINTER                          :: dbcsr_re, dbcsr_im
    6435              :       TYPE(cp_cfm_type), INTENT(IN)                      :: cfm_mat
    6436              : 
    6437              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'dbcsr_to_cfm'
    6438              : 
    6439              :       INTEGER                                            :: handle
    6440              :       TYPE(cp_fm_type)                                   :: fm_mat_im, fm_mat_re
    6441              : 
    6442         1736 :       CALL timeset(routineN, handle)
    6443              : 
    6444         1736 :       CALL cp_fm_create(fm_mat_re, cfm_mat%matrix_struct)
    6445         1736 :       CALL cp_fm_create(fm_mat_im, cfm_mat%matrix_struct)
    6446              : 
    6447         1736 :       CALL copy_dbcsr_to_fm(dbcsr_re, fm_mat_re)
    6448         1736 :       CALL copy_dbcsr_to_fm(dbcsr_im, fm_mat_im)
    6449              : 
    6450         1736 :       CALL cp_fm_to_cfm(fm_mat_re, fm_mat_im, cfm_mat)
    6451              : 
    6452         1736 :       CALL cp_fm_release(fm_mat_re)
    6453         1736 :       CALL cp_fm_release(fm_mat_im)
    6454              : 
    6455         1736 :       CALL timestop(handle)
    6456              : 
    6457         1736 :    END SUBROUTINE dbcsr_to_cfm
    6458              : 
    6459              : ! **************************************************************************************************
    6460              : !> \brief ...
    6461              : !> \param mat_set ...
    6462              : !> \param mat_size ...
    6463              : !> \param template ...
    6464              : !> \param explicitly_no_symmetry ...
    6465              : ! **************************************************************************************************
    6466          690 :    SUBROUTINE alloc_mat_set(mat_set, mat_size, template, explicitly_no_symmetry)
    6467              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mat_set
    6468              :       INTEGER, INTENT(IN)                                :: mat_size
    6469              :       TYPE(dbcsr_type), TARGET                           :: template
    6470              :       LOGICAL, OPTIONAL                                  :: explicitly_no_symmetry
    6471              : 
    6472              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'alloc_mat_set'
    6473              : 
    6474              :       INTEGER                                            :: handle, i_size
    6475              :       LOGICAL                                            :: my_explicitly_no_symmetry
    6476              : 
    6477          690 :       CALL timeset(routineN, handle)
    6478              : 
    6479          690 :       my_explicitly_no_symmetry = .FALSE.
    6480          690 :       IF (PRESENT(explicitly_no_symmetry)) my_explicitly_no_symmetry = explicitly_no_symmetry
    6481              : 
    6482          690 :       NULLIFY (mat_set)
    6483          690 :       CALL dbcsr_allocate_matrix_set(mat_set, mat_size)
    6484         6232 :       DO i_size = 1, mat_size
    6485         5542 :          ALLOCATE (mat_set(i_size)%matrix)
    6486         5542 :          IF (my_explicitly_no_symmetry) THEN
    6487              :             CALL dbcsr_create(matrix=mat_set(i_size)%matrix, template=template, &
    6488            0 :                               matrix_type=dbcsr_type_no_symmetry)
    6489              :          ELSE
    6490         5542 :             CALL dbcsr_create(matrix=mat_set(i_size)%matrix, template=template)
    6491              :          END IF
    6492         5542 :          CALL dbcsr_copy(mat_set(i_size)%matrix, template)
    6493         6232 :          CALL dbcsr_set(mat_set(i_size)%matrix, 0.0_dp)
    6494              :       END DO
    6495              : 
    6496          690 :       CALL timestop(handle)
    6497              : 
    6498          690 :    END SUBROUTINE alloc_mat_set
    6499              : 
    6500              : ! **************************************************************************************************
    6501              : !> \brief ...
    6502              : !> \param mat_set ...
    6503              : !> \param mat_size_1 ...
    6504              : !> \param mat_size_2 ...
    6505              : !> \param template ...
    6506              : !> \param explicitly_no_symmetry ...
    6507              : ! **************************************************************************************************
    6508            4 :    SUBROUTINE alloc_mat_set_2d(mat_set, mat_size_1, mat_size_2, template, explicitly_no_symmetry)
    6509              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_set
    6510              :       INTEGER, INTENT(IN)                                :: mat_size_1, mat_size_2
    6511              :       TYPE(dbcsr_type), TARGET                           :: template
    6512              :       LOGICAL, OPTIONAL                                  :: explicitly_no_symmetry
    6513              : 
    6514              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'alloc_mat_set_2d'
    6515              : 
    6516              :       INTEGER                                            :: handle, i_size, j_size
    6517              :       LOGICAL                                            :: my_explicitly_no_symmetry
    6518              : 
    6519            4 :       CALL timeset(routineN, handle)
    6520              : 
    6521            4 :       my_explicitly_no_symmetry = .FALSE.
    6522            4 :       IF (PRESENT(explicitly_no_symmetry)) my_explicitly_no_symmetry = explicitly_no_symmetry
    6523              : 
    6524            4 :       NULLIFY (mat_set)
    6525            4 :       CALL dbcsr_allocate_matrix_set(mat_set, mat_size_1, mat_size_2)
    6526           16 :       DO i_size = 1, mat_size_1
    6527          124 :          DO j_size = 1, mat_size_2
    6528          108 :             ALLOCATE (mat_set(i_size, j_size)%matrix)
    6529          108 :             IF (my_explicitly_no_symmetry) THEN
    6530              :                CALL dbcsr_create(matrix=mat_set(i_size, j_size)%matrix, template=template, &
    6531          108 :                                  matrix_type=dbcsr_type_no_symmetry)
    6532              :             ELSE
    6533            0 :                CALL dbcsr_create(matrix=mat_set(i_size, j_size)%matrix, template=template)
    6534              :             END IF
    6535          108 :             CALL dbcsr_copy(mat_set(i_size, j_size)%matrix, template)
    6536          120 :             CALL dbcsr_set(mat_set(i_size, j_size)%matrix, 0.0_dp)
    6537              :          END DO
    6538              :       END DO
    6539              : 
    6540            4 :       CALL timestop(handle)
    6541              : 
    6542            4 :    END SUBROUTINE alloc_mat_set_2d
    6543              : 
    6544              : ! **************************************************************************************************
    6545              : !> \brief ...
    6546              : !> \param t_3c_O_all ...
    6547              : !> \param t_greens_fct ...
    6548              : !> \param t_3c_O_W ...
    6549              : !> \param mat_self_energy_ao_ao ...
    6550              : !> \param bounds_ao_ao_j ...
    6551              : !> \param bounds_RI_i ...
    6552              : !> \param unit_nr ...
    6553              : !> \param eps_filter ...
    6554              : !> \param do_occ ...
    6555              : !> \param do_virt ...
    6556              : ! **************************************************************************************************
    6557         3176 :    SUBROUTINE contract_to_self_energy(t_3c_O_all, t_greens_fct, t_3c_O_W, &
    6558              :                                       mat_self_energy_ao_ao, bounds_ao_ao_j, bounds_RI_i, &
    6559              :                                       unit_nr, eps_filter, do_occ, do_virt)
    6560              : 
    6561              :       TYPE(dbt_type)                                     :: t_3c_O_all, t_greens_fct, t_3c_O_W
    6562              :       TYPE(dbcsr_type), TARGET                           :: mat_self_energy_ao_ao
    6563              :       INTEGER, DIMENSION(2, 2)                           :: bounds_ao_ao_j
    6564              :       INTEGER, DIMENSION(2, 1)                           :: bounds_RI_i
    6565              :       INTEGER                                            :: unit_nr
    6566              :       REAL(KIND=dp)                                      :: eps_filter
    6567              :       LOGICAL                                            :: do_occ, do_virt
    6568              : 
    6569              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'contract_to_self_energy'
    6570              : 
    6571              :       INTEGER                                            :: handle
    6572              :       INTEGER, DIMENSION(2, 1)                           :: bounds_ao_j
    6573              :       INTEGER, DIMENSION(2, 2)                           :: bounds_ao_all_RI_i, bounds_RI_i_ao_j
    6574              :       REAL(KIND=dp)                                      :: sign_self_energy
    6575        79400 :       TYPE(dbt_type)                                     :: t_3c_O_G, t_3c_O_G_tmp, t_self_energy, &
    6576        28584 :                                                             t_self_energy_tmp
    6577              : 
    6578         3176 :       CALL timeset(routineN, handle)
    6579              : 
    6580         3176 :       CPASSERT(do_occ .EQV. (.NOT. do_virt))
    6581              : 
    6582         3176 :       CALL dbt_create(t_3c_O_all, t_3c_O_G, name="M occ (RI AO | AO)")
    6583         3176 :       CALL dbt_create(t_3c_O_all, t_3c_O_G_tmp, name="M occ (RI AO | AO)")
    6584         3176 :       CALL dbt_create(t_greens_fct, t_self_energy, name="(AO|AO)")
    6585         3176 :       CALL dbt_create(mat_self_energy_ao_ao, t_self_energy_tmp)
    6586              : 
    6587         9528 :       bounds_ao_j(:, 1) = bounds_ao_ao_j(:, 1)
    6588         9528 :       bounds_ao_all_RI_i(:, 1) = bounds_RI_i(:, 1)
    6589         9528 :       bounds_ao_all_RI_i(:, 2) = bounds_ao_ao_j(:, 2)
    6590              : 
    6591              :       CALL dbt_contract(1.0_dp, t_greens_fct, t_3c_O_all, 0.0_dp, &
    6592              :                         t_3c_O_G_tmp, &
    6593              :                         contract_1=[2], notcontract_1=[1], &
    6594              :                         contract_2=[3], notcontract_2=[1, 2], &
    6595              :                         map_1=[3], map_2=[1, 2], &
    6596              :                         bounds_2=bounds_ao_j, &
    6597              :                         bounds_3=bounds_ao_all_RI_i, &
    6598              :                         filter_eps=eps_filter, &
    6599         3176 :                         unit_nr=unit_nr)
    6600              : 
    6601         3176 :       CALL dbt_copy(t_3c_O_G_tmp, t_3c_O_G, order=[1, 3, 2], move_data=.TRUE.)
    6602              : 
    6603         3176 :       IF (do_occ) sign_self_energy = -1.0_dp
    6604         3176 :       IF (do_virt) sign_self_energy = 1.0_dp
    6605              : 
    6606         9528 :       bounds_RI_i_ao_j(:, 1) = bounds_RI_i(:, 1)
    6607         9528 :       bounds_RI_i_ao_j(:, 2) = bounds_ao_ao_j(:, 1)
    6608              : 
    6609              :       CALL dbt_contract(sign_self_energy, t_3c_O_W, t_3c_O_G, 0.0_dp, &
    6610              :                         t_self_energy, &
    6611              :                         contract_1=[1, 2], notcontract_1=[3], &
    6612              :                         contract_2=[1, 2], notcontract_2=[3], &
    6613              :                         map_1=[1], map_2=[2], &
    6614              :                         bounds_1=bounds_RI_i_ao_j, &
    6615              :                         filter_eps=eps_filter, &
    6616         3176 :                         unit_nr=unit_nr)
    6617              : 
    6618         3176 :       CALL dbt_copy(t_self_energy, t_self_energy_tmp)
    6619         3176 :       CALL dbt_clear(t_self_energy)
    6620              : 
    6621         3176 :       CALL dbt_copy_tensor_to_matrix(t_self_energy_tmp, mat_self_energy_ao_ao, summation=.TRUE.)
    6622              : 
    6623         3176 :       CALL dbt_destroy(t_3c_O_G)
    6624         3176 :       CALL dbt_destroy(t_3c_O_G_tmp)
    6625         3176 :       CALL dbt_destroy(t_self_energy)
    6626         3176 :       CALL dbt_destroy(t_self_energy_tmp)
    6627              : 
    6628         3176 :       CALL timestop(handle)
    6629              : 
    6630         3176 :    END SUBROUTINE contract_to_self_energy
    6631              : 
    6632              : ! **************************************************************************************************
    6633              : !> \brief ...
    6634              : !> \param t_3c_overl_int_gw_AO ...
    6635              : !> \param t_3c_overl_int_gw_RI ...
    6636              : !> \param t_AO ...
    6637              : !> \param t_RI ...
    6638              : !> \param prefac ...
    6639              : !> \param mo_bounds ...
    6640              : !> \param unit_nr ...
    6641              : !> \param t_3c_ctr_RI ...
    6642              : !> \param t_3c_ctr_AO ...
    6643              : !> \param calculate_ctr_RI ...
    6644              : ! **************************************************************************************************
    6645         1898 :    SUBROUTINE contract_cubic_gw(t_3c_overl_int_gw_AO, t_3c_overl_int_gw_RI, &
    6646              :                                 t_AO, t_RI, prefac, &
    6647              :                                 mo_bounds, unit_nr, &
    6648              :                                 t_3c_ctr_RI, t_3c_ctr_AO, calculate_ctr_RI)
    6649              :       TYPE(dbt_type), INTENT(INOUT)                      :: t_3c_overl_int_gw_AO, &
    6650              :                                                             t_3c_overl_int_gw_RI, t_AO, t_RI
    6651              :       REAL(dp), DIMENSION(2), INTENT(IN)                 :: prefac
    6652              :       INTEGER, DIMENSION(2), INTENT(IN)                  :: mo_bounds
    6653              :       INTEGER, INTENT(IN)                                :: unit_nr
    6654              :       TYPE(dbt_type), INTENT(INOUT)                      :: t_3c_ctr_RI, t_3c_ctr_AO
    6655              :       LOGICAL, INTENT(IN)                                :: calculate_ctr_RI
    6656              : 
    6657              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'contract_cubic_gw'
    6658              : 
    6659              :       INTEGER                                            :: handle
    6660              :       INTEGER, DIMENSION(2, 2)                           :: ctr_bounds_mo
    6661              :       INTEGER, DIMENSION(3)                              :: bounds_3c
    6662              : 
    6663         1898 :       CALL timeset(routineN, handle)
    6664              : 
    6665         1898 :       IF (calculate_ctr_RI) THEN
    6666          950 :          CALL dbt_get_info(t_3c_overl_int_gw_RI, nfull_total=bounds_3c)
    6667         2850 :          ctr_bounds_mo(:, 1) = [1, bounds_3c(2)]
    6668         2850 :          ctr_bounds_mo(:, 2) = mo_bounds
    6669              : 
    6670              :          CALL dbt_contract(prefac(1), t_RI, t_3c_overl_int_gw_RI, 0.0_dp, &
    6671              :                            t_3c_ctr_RI, &
    6672              :                            contract_1=[2], notcontract_1=[1], &
    6673              :                            contract_2=[1], notcontract_2=[2, 3], &
    6674              :                            map_1=[1], map_2=[2, 3], &
    6675              :                            bounds_3=ctr_bounds_mo, &
    6676          950 :                            unit_nr=unit_nr)
    6677              : 
    6678              :       END IF
    6679              : 
    6680         1898 :       CALL dbt_get_info(t_3c_overl_int_gw_AO, nfull_total=bounds_3c)
    6681         5694 :       ctr_bounds_mo(:, 1) = [1, bounds_3c(2)]
    6682         5694 :       ctr_bounds_mo(:, 2) = mo_bounds
    6683              : 
    6684              :       CALL dbt_contract(prefac(2), t_AO, t_3c_overl_int_gw_AO, 0.0_dp, &
    6685              :                         t_3c_ctr_AO, &
    6686              :                         contract_1=[2], notcontract_1=[1], &
    6687              :                         contract_2=[1], notcontract_2=[2, 3], &
    6688              :                         map_1=[1], map_2=[2, 3], &
    6689              :                         bounds_3=ctr_bounds_mo, &
    6690         1898 :                         unit_nr=unit_nr)
    6691              : 
    6692         1898 :       CALL timestop(handle)
    6693              : 
    6694         1898 :    END SUBROUTINE contract_cubic_gw
    6695              : 
    6696              : ! **************************************************************************************************
    6697              : !> \brief ...
    6698              : !> \param t3c_1 ...
    6699              : !> \param t3c_2 ...
    6700              : !> \param vec_sigma ...
    6701              : !> \param mo_offset ...
    6702              : !> \param mo_bounds ...
    6703              : !> \param para_env ...
    6704              : ! **************************************************************************************************
    6705         1898 :    SUBROUTINE trace_sigma_gw(t3c_1, t3c_2, vec_sigma, mo_offset, mo_bounds, para_env)
    6706              :       TYPE(dbt_type), INTENT(INOUT)                      :: t3c_1, t3c_2
    6707              :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: vec_Sigma
    6708              :       INTEGER, INTENT(IN)                                :: mo_offset
    6709              :       INTEGER, DIMENSION(2), INTENT(IN)                  :: mo_bounds
    6710              :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env
    6711              : 
    6712              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'trace_sigma_gw'
    6713              : 
    6714              :       INTEGER                                            :: handle, n, n_end, n_end_block, n_start, &
    6715              :                                                             n_start_block
    6716              :       INTEGER, DIMENSION(1)                              :: trace_shape
    6717              :       INTEGER, DIMENSION(2)                              :: mo_bounds_off
    6718              :       INTEGER, DIMENSION(3)                              :: boff, bsize, ind
    6719              :       LOGICAL                                            :: found
    6720         1898 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: block_1, block_2
    6721              :       REAL(KIND=dp), &
    6722         3796 :          DIMENSION(mo_bounds(2)-mo_bounds(1)+1)          :: vec_Sigma_prv
    6723              :       TYPE(dbt_iterator_type)                            :: iter
    6724        17082 :       TYPE(dbt_type)                                     :: t3c_1_redist
    6725              : 
    6726         1898 :       CALL timeset(routineN, handle)
    6727              : 
    6728         1898 :       CALL dbt_create(t3c_2, t3c_1_redist)
    6729         1898 :       CALL dbt_copy(t3c_1, t3c_1_redist, order=[2, 1, 3], move_data=.TRUE.)
    6730              : 
    6731        24638 :       vec_Sigma_prv = 0.0_dp
    6732              : 
    6733              : !$OMP PARALLEL DEFAULT(NONE) REDUCTION(+:vec_Sigma_prv) &
    6734              : !$OMP SHARED(t3c_1_redist,t3c_2,mo_bounds) &
    6735              : !$OMP PRIVATE(iter,ind,bsize,boff,block_1,block_2,found) &
    6736         1898 : !$OMP PRIVATE(n_start_block,n_start,n_end_block,n_end,trace_shape)
    6737              :       CALL dbt_iterator_start(iter, t3c_1_redist)
    6738              :       DO WHILE (dbt_iterator_blocks_left(iter))
    6739              :          CALL dbt_iterator_next_block(iter, ind, blk_size=bsize, blk_offset=boff)
    6740              :          CALL dbt_get_block(t3c_1_redist, ind, block_1, found)
    6741              :          CPASSERT(found)
    6742              :          CALL dbt_get_block(t3c_2, ind, block_2, found)
    6743              :          IF (.NOT. found) CYCLE
    6744              : 
    6745              :          IF (boff(3) < mo_bounds(1)) THEN
    6746              :             n_start_block = mo_bounds(1) - boff(3) + 1
    6747              :             n_start = 1
    6748              :          ELSE
    6749              :             n_start_block = 1
    6750              :             n_start = boff(3) - mo_bounds(1) + 1
    6751              :          END IF
    6752              : 
    6753              :          IF (boff(3) + bsize(3) - 1 > mo_bounds(2)) THEN
    6754              :             n_end_block = mo_bounds(2) - boff(3) + 1
    6755              :             n_end = mo_bounds(2) - mo_bounds(1) + 1
    6756              :          ELSE
    6757              :             n_end_block = bsize(3)
    6758              :             n_end = boff(3) + bsize(3) - mo_bounds(1)
    6759              :          END IF
    6760              : 
    6761              :          trace_shape(1) = SIZE(block_1, 1)*SIZE(block_1, 2)
    6762              :          vec_Sigma_prv(n_start:n_end) = &
    6763              :             vec_Sigma_prv(n_start:n_end) + &
    6764              :             [(DOT_PRODUCT(RESHAPE(block_1(:, :, n), trace_shape), &
    6765              :                           RESHAPE(block_2(:, :, n), trace_shape)), &
    6766              :               n=n_start_block, n_end_block)]
    6767              :          DEALLOCATE (block_1, block_2)
    6768              :       END DO
    6769              :       CALL dbt_iterator_stop(iter)
    6770              : !$OMP END PARALLEL
    6771              : 
    6772         1898 :       CALL dbt_destroy(t3c_1_redist)
    6773              : 
    6774         1898 :       CALL para_env%sum(vec_Sigma_prv)
    6775              : 
    6776         5694 :       mo_bounds_off = mo_bounds - mo_offset + 1
    6777              :       vec_Sigma(mo_bounds_off(1):mo_bounds_off(2)) = &
    6778        24638 :          vec_Sigma(mo_bounds_off(1):mo_bounds_off(2)) + vec_Sigma_prv
    6779              : 
    6780         1898 :       CALL timestop(handle)
    6781         3796 :    END SUBROUTINE trace_sigma_gw
    6782              : 
    6783              : END MODULE rpa_gw
        

Generated by: LCOV version 2.0-1