LCOV - code coverage report
Current view: top level - src - rpa_gw.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:123285f) Lines: 95.8 % 2465 2361
Test Date: 2026-11-04 00:58:17 Functions: 95.1 % 61 58

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

Generated by: LCOV version 2.0-1