LCOV - code coverage report
Current view: top level - src - gw_tensor_large_cell_gamma_static_cohsex.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:123285f) Lines: 77.5 % 275 213
Test Date: 2026-11-04 00:58:17 Functions: 87.5 % 8 7

            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 Static COHSEX band structure in the tensor-based large-cell Gamma GW code:
      10              : !>        COHSEX DIAGONAL (diagonal energies) or COHSEX QP_UPDATE (canonical energies and MOs)
      11              : !> \author Ritaj Tyagi
      12              : !> \date Jan 2025
      13              : ! **************************************************************************************************
      14              : MODULE gw_tensor_large_cell_Gamma_static_cohsex
      15              :    USE atomic_kind_types,               ONLY: atomic_kind_type
      16              :    USE bibliography,                    ONLY: Hedin1965,&
      17              :                                               Hybertsen1986,&
      18              :                                               Tyagi2024,&
      19              :                                               Tyagi2026,&
      20              :                                               cite_reference
      21              :    USE cell_types,                      ONLY: cell_type
      22              :    USE cp_cfm_diag,                     ONLY: cp_cfm_geeig
      23              :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      24              :                                               cp_cfm_release,&
      25              :                                               cp_cfm_to_fm,&
      26              :                                               cp_cfm_type
      27              :    USE cp_control_types,                ONLY: dft_control_type
      28              :    USE cp_dbcsr_api,                    ONLY: dbcsr_add,&
      29              :                                               dbcsr_p_type,&
      30              :                                               dbcsr_set
      31              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      32              :                                               dbcsr_deallocate_matrix_set
      33              :    USE cp_files,                        ONLY: close_file,&
      34              :                                               open_file
      35              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_scale_and_add,&
      36              :                                               cp_fm_transpose
      37              :    USE cp_fm_diag,                      ONLY: cp_fm_syevx
      38              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      39              :                                               cp_fm_get_diag,&
      40              :                                               cp_fm_get_info,&
      41              :                                               cp_fm_release,&
      42              :                                               cp_fm_set_all,&
      43              :                                               cp_fm_to_fm,&
      44              :                                               cp_fm_type,&
      45              :                                               cp_fm_write_formatted
      46              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      47              :                                               cp_logger_type
      48              :    USE cp_output_handling,              ONLY: cp_p_file,&
      49              :                                               cp_print_key_finished_output,&
      50              :                                               cp_print_key_should_output,&
      51              :                                               cp_print_key_unit_nr
      52              :    USE cp_realspace_grid_cube,          ONLY: cp_pw_to_cube
      53              :    USE dbt_api,                         ONLY: dbt_type
      54              :    USE gw_compute_V_and_W,              ONLY: apply_extrapol_factor,&
      55              :                                               compute_MinvVsqrt_Vsqrt,&
      56              :                                               compute_V_k_by_lattice_sum,&
      57              :                                               compute_fm_W_MIC_freq_j_from_chi,&
      58              :                                               fm_read,&
      59              :                                               fm_write
      60              :    USE gw_tensor_large_cell_Gamma,      ONLY: compute_Sigma_c_occ_vir,&
      61              :                                               create_mat_for_Sigma_c,&
      62              :                                               delete_unnecessary_files,&
      63              :                                               destroy_mat_Sigma_c,&
      64              :                                               get_Sigma_x,&
      65              :                                               get_mat_chi_Gamma_tau,&
      66              :                                               print_skipping
      67              :    USE gw_utils,                        ONLY: de_init_bs_env
      68              :    USE gw_utils_fm,                     ONLY: cfm_contract_ABA,&
      69              :                                               fm_contract_ABA
      70              :    USE input_constants,                 ONLY: cohsex_qp_update
      71              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      72              :                                               section_vals_type,&
      73              :                                               section_vals_val_get
      74              :    USE kinds,                           ONLY: default_path_length,&
      75              :                                               default_string_length,&
      76              :                                               dp
      77              :    USE machine,                         ONLY: m_walltime
      78              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      79              :    USE particle_list_types,             ONLY: particle_list_type
      80              :    USE particle_types,                  ONLY: particle_type
      81              :    USE physcon,                         ONLY: evolt
      82              :    USE post_scf_bandstructure_types,    ONLY: post_scf_bandstructure_type
      83              :    USE post_scf_bandstructure_utils,    ONLY: cfm_ikp_from_fm_Gamma,&
      84              :                                               get_all_VBM_CBM_bandgaps
      85              :    USE pw_env_types,                    ONLY: pw_env_get,&
      86              :                                               pw_env_type
      87              :    USE pw_pool_types,                   ONLY: pw_pool_type
      88              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      89              :                                               pw_r3d_rs_type
      90              :    USE qs_collocate_density,            ONLY: calculate_wavefunction
      91              :    USE qs_environment_types,            ONLY: get_qs_env,&
      92              :                                               qs_environment_type
      93              :    USE qs_kind_types,                   ONLY: qs_kind_type
      94              :    USE qs_mo_io,                        ONLY: write_mo_set_to_output_unit
      95              :    USE qs_mo_types,                     ONLY: allocate_mo_set,&
      96              :                                               deallocate_mo_set,&
      97              :                                               init_mo_set,&
      98              :                                               mo_set_type
      99              :    USE qs_subsys_types,                 ONLY: qs_subsys_get,&
     100              :                                               qs_subsys_type
     101              : #include "./base/base_uses.f90"
     102              : 
     103              :    IMPLICIT NONE
     104              : 
     105              :    PRIVATE
     106              : 
     107              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'gw_tensor_large_cell_Gamma_static_cohsex'
     108              : 
     109              :    PUBLIC :: gw_calc_tensor_large_cell_Gamma_static_cohsex
     110              : 
     111              : CONTAINS
     112              : 
     113              : ! **************************************************************************************************
     114              : !> \brief Perform static COHSEX band structure calculation
     115              : !> \param qs_env ...
     116              : !> \param bs_env ...
     117              : !> \par History
     118              : !>    * 12.2024 created [Ritaj Tyagi]
     119              : ! **************************************************************************************************
     120            8 :    SUBROUTINE gw_calc_tensor_large_cell_Gamma_static_cohsex(qs_env, bs_env)
     121              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     122              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     123              : 
     124              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'gw_calc_tensor_large_cell_Gamma_static_cohsex'
     125              : 
     126              :       INTEGER                                            :: handle
     127            8 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_Sigma_c_Gamma, fm_Sigma_x_Gamma, &
     128            8 :                                                             fm_W_MIC_freq_zero
     129              : 
     130            8 :       CALL timeset(routineN, handle)
     131              : 
     132              :       ! static COHSEX; with QP_UPDATE the quasiparticle update; scaled self-energy if requested
     133            8 :       CALL cite_reference(Hedin1965)
     134            8 :       CALL cite_reference(Hybertsen1986)
     135            8 :       IF (bs_env%cohsex_flavor == cohsex_qp_update) CALL cite_reference(Tyagi2024)
     136            8 :       IF (bs_env%cohsex_scale_occ /= 1.0_dp .OR. bs_env%cohsex_scale_virt /= 1.0_dp) THEN
     137            8 :          CALL cite_reference(Tyagi2026)
     138              :       END IF
     139              : 
     140            8 :       IF (bs_env%Sigma_c_freq_zero_exists) THEN
     141              : 
     142              :          ! restart: Σ^c_λσ(iω=0,k=0) from file; χ and W are not needed
     143            0 :          CALL read_Sigma_c_freq_zero(bs_env, fm_Sigma_c_Gamma)
     144              : 
     145              :       ELSE
     146              : 
     147              :          ! G^occ_µλ(i|τ|,k=0) = sum_n^occ C_µn(k=0) e^(-|(ϵ_nk=0-ϵ_F)τ|) C_λn(k=0)
     148              :          ! G^vir_µλ(i|τ|,k=0) = sum_n^vir C_µn(k=0) e^(-|(ϵ_nk=0-ϵ_F)τ|) C_λn(k=0)
     149              :          ! χ_PQ(iτ,k=0) = sum_λν [sum_µ (µν|P) G^occ_µλ(i|τ|)] [sum_σ (σλ|Q) G^vir_σν(i|τ|)]
     150            8 :          CALL get_mat_chi_Gamma_tau(bs_env, qs_env, bs_env%mat_chi_Gamma_tau)
     151              : 
     152              :          ! χ_PQ(iτ,k=0) -> χ_PQ(iω=0,k=0) -> χ_PQ(iω=0,k) -> ε_PQ(iω=0,k) -> W_PQ(iω=0,k)
     153              :          ! -> W^MIC_PQ(iω=0) -> M^-1*W^MIC(iω=0)*M^-1
     154            8 :          CALL get_W_MIC_freq_zero(bs_env, qs_env, bs_env%mat_chi_Gamma_tau, fm_W_MIC_freq_zero)
     155              : 
     156              :          ! Σ^c_λσ(iω=0,k=0) = 1/2 sum_n sgn(ϵ_n - ϵ_F) sum_νQ [sum_P (νσ|P) W^MIC_PQ(iω=0)]
     157              :          !                    [sum_µ (λµ|Q) C_µn C_νn]; written to the Σ^c(iω=0) restart file
     158            8 :          CALL get_Sigma_c(bs_env, qs_env, fm_W_MIC_freq_zero, fm_Sigma_c_Gamma)
     159              : 
     160              :       END IF
     161              : 
     162              :       ! D_µν = sum_n^occ C_µn(k=0) C_νn(k=0), V^trunc_PQ = sum_cell_R <phi_P,0|V^trunc|phi_Q,R>
     163              :       ! Σ^x_λσ(k=0) = sum_νQ [sum_P (νσ|P) V^trunc_PQ] [sum_µ (λµ|Q) D_µν)]
     164            8 :       CALL get_Sigma_x(bs_env, qs_env, fm_Sigma_x_Gamma)
     165              : 
     166              :       ! Σ^c_λσ(k=0) -> Σ^c_nn(ϵ,k); ϵ_nk^GW = ϵ_nk^DFT + Σ^c_nn(ϵ,k) + Σ^x_nn(k) - v^xc_nn(k)
     167            8 :       CALL compute_QP_energies(bs_env, qs_env, fm_Sigma_x_Gamma, fm_Sigma_c_Gamma)
     168              : 
     169            8 :       CALL de_init_bs_env(qs_env, bs_env)
     170              : 
     171            8 :       CALL timestop(handle)
     172              : 
     173            8 :    END SUBROUTINE gw_calc_tensor_large_cell_Gamma_static_cohsex
     174              : 
     175              : ! **************************************************************************************************
     176              : !> \brief Static screened Coulomb interaction at iω = 0:
     177              : !>          χ_PQ(iω=0,k=0) = sum_i w^0_i χ_PQ(iτ_i,k=0)   (w^0: time weights at zero frequency)
     178              : !>          χ_PQ(iω=0,k=0) -> χ_PQ(iω=0,k) -> ε_PQ(iω=0,k) -> W_PQ(iω=0,k) -> W^MIC_PQ(iω=0)
     179              : !>        as for one frequency point of G0W0 (compute_fm_W_MIC_freq_j_from_chi); then the
     180              : !>        k-point extrapolation factor and M^-1(k=0) W^MIC(iω=0) M^-1(k=0)
     181              : !> \param bs_env ...
     182              : !> \param qs_env ...
     183              : !> \param mat_chi_Gamma_tau ...
     184              : !> \param fm_W_MIC_freq_zero ...
     185              : ! **************************************************************************************************
     186            8 :    SUBROUTINE get_W_MIC_freq_zero(bs_env, qs_env, mat_chi_Gamma_tau, fm_W_MIC_freq_zero)
     187              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     188              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     189              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mat_chi_Gamma_tau
     190              :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_W_MIC_freq_zero
     191              : 
     192              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'get_W_MIC_freq_zero'
     193              : 
     194              :       INTEGER                                            :: handle, i_t, ikp, ikp_batch, ikp_in_batch
     195              :       REAL(KIND=dp)                                      :: t1
     196              :       TYPE(cp_cfm_type)                                  :: cfm_M_inv_V_sqrt_ikp, cfm_V_sqrt_ikp
     197            8 :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:)       :: cfm_V_kp
     198              : 
     199            8 :       CALL timeset(routineN, handle)
     200              : 
     201              :       ! χ_PQ(iω=0,k=0) = sum_i w^0_i χ_PQ(iτ_i,k=0) -> bs_env%fm_chi_Gamma_freq
     202            8 :       CALL dbcsr_set(bs_env%mat_RI_RI%matrix, 0.0_dp)
     203           60 :       DO i_t = 1, bs_env%num_time_freq_points
     204              :          CALL dbcsr_add(bs_env%mat_RI_RI%matrix, mat_chi_Gamma_tau(i_t)%matrix, 1.0_dp, &
     205           60 :                         bs_env%time_frequency_grid%time_weights_at_zero_frequency(i_t))
     206              :       END DO
     207            8 :       CALL copy_dbcsr_to_fm(bs_env%mat_RI_RI%matrix, bs_env%fm_chi_Gamma_freq)
     208            8 :       CALL dbcsr_deallocate_matrix_set(mat_chi_Gamma_tau)
     209              : 
     210           16 :       ALLOCATE (fm_W_MIC_freq_zero(1))
     211            8 :       CALL cp_fm_create(fm_W_MIC_freq_zero(1), bs_env%fm_RI_RI%matrix_struct)
     212            8 :       CALL cp_fm_set_all(fm_W_MIC_freq_zero(1), 0.0_dp)
     213              : 
     214           62 :       DO ikp_batch = 1, bs_env%num_chi_eps_W_batches
     215              : 
     216           54 :          t1 = m_walltime()
     217              : 
     218              :          ! V_PQ(k) = sum_R e^(ikR) <phi_P, cell 0 | 1/r | phi_Q, cell R>
     219           54 :          CALL compute_V_k_by_lattice_sum(bs_env, qs_env, cfm_V_kp, ikp_batch)
     220              : 
     221          270 :          DO ikp_in_batch = 1, bs_env%nkp_chi_eps_W_batch
     222              : 
     223          216 :             ikp = (ikp_batch - 1)*bs_env%nkp_chi_eps_W_batch + ikp_in_batch
     224              : 
     225          216 :             IF (ikp > bs_env%nkp_chi_eps_W_orig_plus_extra) CYCLE
     226              : 
     227              :             CALL compute_MinvVsqrt_Vsqrt(bs_env, qs_env, cfm_V_kp, &
     228          206 :                                          cfm_V_sqrt_ikp, cfm_M_inv_V_sqrt_ikp, ikp)
     229              : 
     230          206 :             CALL bs_env%para_env%sync()
     231          206 :             CALL cp_cfm_release(cfm_V_kp(ikp))
     232              : 
     233              :             ! W^MIC contribution of k-point ikp at iω = 0 (j_w = 1: first frequency point for the
     234              :             ! approximate k-point extrapolation)
     235              :             CALL compute_fm_W_MIC_freq_j_from_chi(bs_env, qs_env, bs_env%fm_W_MIC_freq, 1, ikp, &
     236          206 :                                                   cfm_M_inv_V_sqrt_ikp, cfm_V_sqrt_ikp)
     237              : 
     238          270 :             CALL cp_fm_scale_and_add(1.0_dp, fm_W_MIC_freq_zero(1), 1.0_dp, bs_env%fm_W_MIC_freq)
     239              : 
     240              :          END DO ! ikp_in_batch
     241              : 
     242           54 :          DEALLOCATE (cfm_V_kp)
     243              : 
     244           62 :          IF (bs_env%unit_nr > 0) THEN
     245              :             WRITE (bs_env%unit_nr, '(T2,A,I10,A,I3,A,F10.1,A)') &
     246           27 :                'Computed W(iω=0,k) for k-point batch', &
     247           27 :                ikp_batch, ' /', bs_env%num_chi_eps_W_batches, &
     248           54 :                ', Execution time', m_walltime() - t1, ' s'
     249              :          END IF
     250              : 
     251              :       END DO ! ikp_batch
     252              : 
     253            8 :       IF (bs_env%approx_kp_extrapol) THEN
     254            0 :          CALL apply_extrapol_factor(bs_env, fm_W_MIC_freq_zero)
     255              :       END IF
     256              : 
     257              :       ! M^-1(k=0) W^MIC(iω=0) M^-1(k=0)
     258            8 :       CALL fm_contract_ABA(bs_env%fm_Minv_Gamma, fm_W_MIC_freq_zero(1))
     259              : 
     260            8 :       CALL cp_cfm_release(cfm_M_inv_V_sqrt_ikp)
     261            8 :       CALL cp_cfm_release(cfm_V_sqrt_ikp)
     262              : 
     263            8 :       IF (bs_env%unit_nr > 0) WRITE (bs_env%unit_nr, '(A)') ' '
     264              : 
     265            8 :       CALL timestop(handle)
     266              : 
     267           16 :    END SUBROUTINE get_W_MIC_freq_zero
     268              : 
     269              : ! **************************************************************************************************
     270              : !> \brief Static COHSEX correlation self-energy at the Γ point in the AO basis,
     271              : !>          Σ^c_λσ = 1/2 sum_n sgn(ϵ_n - ϵ_F) sum_νQ [sum_P (νσ|P) W^MIC_PQ(iω=0)] [sum_µ (λµ|Q) C_µn C_νn]
     272              : !>                 = 1/2 (Σ^neg_λσ(iτ=0) + Σ^pos_λσ(iτ=0))   with W = W^MIC(iω=0),
     273              : !>        i.e. the occupied and virtual self-energy parts of G0W0 at τ = 0 (compute_Sigma_c_occ_vir),
     274              : !>        symmetrized
     275              : !> \param bs_env ...
     276              : !> \param qs_env ...
     277              : !> \param fm_W_MIC_freq_zero ...
     278              : !> \param fm_Sigma_c_Gamma ...
     279              : ! **************************************************************************************************
     280            8 :    SUBROUTINE get_Sigma_c(bs_env, qs_env, fm_W_MIC_freq_zero, fm_Sigma_c_Gamma)
     281              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     282              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     283              :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_W_MIC_freq_zero, fm_Sigma_c_Gamma
     284              : 
     285              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'get_Sigma_c'
     286              : 
     287              :       INTEGER                                            :: handle, ispin
     288              :       REAL(KIND=dp)                                      :: t1
     289            8 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_Sigma_neg, mat_Sigma_pos
     290          200 :       TYPE(dbt_type)                                     :: t_2c_Gocc, t_2c_Gvir, t_2c_Sigma_neg, &
     291          200 :                                                             t_2c_Sigma_pos, t_2c_W, t_3c_x_W
     292              : 
     293            8 :       CALL timeset(routineN, handle)
     294              : 
     295              :       CALL create_mat_for_Sigma_c(bs_env, t_2c_Gocc, t_2c_Gvir, t_2c_W, t_2c_Sigma_neg, &
     296            8 :                                   t_2c_Sigma_pos, t_3c_x_W, mat_Sigma_neg, mat_Sigma_pos)
     297              : 
     298           32 :       ALLOCATE (fm_Sigma_c_Gamma(bs_env%n_spin))
     299           16 :       DO ispin = 1, bs_env%n_spin
     300              : 
     301            8 :          t1 = m_walltime()
     302              : 
     303              :          ! Σ^neg(iτ=0) = -G^occ(0) W^MIC(iω=0),  Σ^pos(iτ=0) = G^vir(0) W^MIC(iω=0)
     304              :          CALL compute_Sigma_c_occ_vir(bs_env, qs_env, 0.0_dp, ispin, fm_W_MIC_freq_zero(1), &
     305              :                                       t_2c_Gocc, t_2c_Gvir, t_2c_W, t_2c_Sigma_neg, &
     306              :                                       t_2c_Sigma_pos, t_3c_x_W, mat_Sigma_neg(1, ispin)%matrix, &
     307            8 :                                       mat_Sigma_pos(1, ispin)%matrix, count_skipped=.FALSE.)
     308              : 
     309              :          ! Σ^c = 1/2 (Σ^neg + Σ^pos), symmetrized
     310            8 :          CALL cp_fm_create(fm_Sigma_c_Gamma(ispin), bs_env%fm_s_Gamma%matrix_struct)
     311            8 :          CALL copy_dbcsr_to_fm(mat_Sigma_neg(1, ispin)%matrix, fm_Sigma_c_Gamma(ispin))
     312            8 :          CALL copy_dbcsr_to_fm(mat_Sigma_pos(1, ispin)%matrix, bs_env%fm_work_mo(1))
     313            8 :          CALL cp_fm_scale_and_add(0.5_dp, fm_Sigma_c_Gamma(ispin), 0.5_dp, bs_env%fm_work_mo(1))
     314            8 :          CALL cp_fm_transpose(fm_Sigma_c_Gamma(ispin), bs_env%fm_work_mo(1))
     315            8 :          CALL cp_fm_scale_and_add(0.5_dp, fm_Sigma_c_Gamma(ispin), 0.5_dp, bs_env%fm_work_mo(1))
     316              : 
     317              :          ! restart file of Σ^c(iω=0,k=0), one per spin
     318            8 :          CALL fm_write(fm_Sigma_c_Gamma(ispin), ispin, bs_env%Sigma_c_freq_zero_name, qs_env)
     319              : 
     320           16 :          IF (bs_env%unit_nr > 0) THEN
     321              :             WRITE (bs_env%unit_nr, '(T2,A,T55,A,F10.1,A)') &
     322            4 :                'Computed Σ^c(k=0),', ' Execution time', m_walltime() - t1, ' s'
     323              :          END IF
     324              : 
     325              :       END DO
     326              : 
     327            8 :       IF (bs_env%unit_nr > 0) WRITE (bs_env%unit_nr, '(A)') ' '
     328              : 
     329            8 :       CALL print_skipping(bs_env)
     330              : 
     331              :       CALL destroy_mat_Sigma_c(t_2c_Gocc, t_2c_Gvir, t_2c_W, t_2c_Sigma_neg, t_2c_Sigma_pos, &
     332            8 :                                t_3c_x_W, fm_W_MIC_freq_zero, mat_Sigma_neg, mat_Sigma_pos)
     333              : 
     334            8 :       CALL delete_unnecessary_files(bs_env)
     335              : 
     336            8 :       CALL timestop(handle)
     337              : 
     338           24 :    END SUBROUTINE get_Sigma_c
     339              : 
     340              : ! **************************************************************************************************
     341              : !> \brief Read the static COHSEX restart file Σ^c_λσ(iω=0,k=0), one per spin
     342              : !> \param bs_env ...
     343              : !> \param fm_Sigma_c_Gamma Σ^c_λσ(iω=0,k=0) per spin, created here
     344              : ! **************************************************************************************************
     345            0 :    SUBROUTINE read_Sigma_c_freq_zero(bs_env, fm_Sigma_c_Gamma)
     346              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     347              :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_Sigma_c_Gamma
     348              : 
     349              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'read_Sigma_c_freq_zero'
     350              : 
     351              :       INTEGER                                            :: handle, ispin
     352              :       REAL(KIND=dp)                                      :: t1
     353              : 
     354            0 :       CALL timeset(routineN, handle)
     355              : 
     356            0 :       ALLOCATE (fm_Sigma_c_Gamma(bs_env%n_spin))
     357            0 :       DO ispin = 1, bs_env%n_spin
     358            0 :          t1 = m_walltime()
     359            0 :          CALL cp_fm_create(fm_Sigma_c_Gamma(ispin), bs_env%fm_s_Gamma%matrix_struct)
     360            0 :          CALL fm_read(fm_Sigma_c_Gamma(ispin), bs_env, bs_env%Sigma_c_freq_zero_name, ispin)
     361            0 :          IF (bs_env%unit_nr > 0) THEN
     362              :             WRITE (bs_env%unit_nr, '(T2,A,T55,A,F10.1,A)') &
     363            0 :                'Read Σ^c(k=0) from file,', ' Execution time', m_walltime() - t1, ' s'
     364              :          END IF
     365              :       END DO
     366              : 
     367            0 :       IF (bs_env%unit_nr > 0) WRITE (bs_env%unit_nr, '(A)') ' '
     368              : 
     369            0 :       CALL timestop(handle)
     370              : 
     371            0 :    END SUBROUTINE read_Sigma_c_freq_zero
     372              : 
     373              : ! **************************************************************************************************
     374              : !> \brief ...
     375              : !> \param bs_env ...
     376              : !> \param qs_env ...
     377              : !> \param fm_Sigma_x_Gamma ...
     378              : !> \param fm_Sigma_c_Gamma ...
     379              : ! **************************************************************************************************
     380           48 :    SUBROUTINE compute_QP_energies(bs_env, qs_env, fm_Sigma_x_Gamma, fm_Sigma_c_Gamma)
     381              : 
     382              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     383              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     384              :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fm_Sigma_x_Gamma, fm_Sigma_c_Gamma
     385              : 
     386              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_QP_energies'
     387              : 
     388              :       INTEGER                                            :: handle, ikp, ispin
     389              :       TYPE(cp_cfm_type)                                  :: cfm_ks_ikp, cfm_mos_ikp, cfm_s_ikp, &
     390              :                                                             cfm_work_ikp
     391              :       TYPE(cp_fm_type)                                   :: fm_Sigma_c_ikp_mo, fm_Sigma_x_ikp_mo, &
     392              :                                                             fm_V_xc_ikp_mo
     393              : 
     394            8 :       CALL timeset(routineN, handle)
     395              : 
     396            8 :       CALL cp_cfm_create(cfm_mos_ikp, bs_env%fm_s_Gamma%matrix_struct)
     397            8 :       CALL cp_cfm_create(cfm_work_ikp, bs_env%fm_s_Gamma%matrix_struct)
     398              : 
     399              :       ! MO-basis operator matrices at k_i (n_ao x n_ao), reused for every k-point
     400            8 :       CALL cp_fm_create(fm_V_xc_ikp_mo, bs_env%fm_s_Gamma%matrix_struct)
     401            8 :       CALL cp_fm_create(fm_Sigma_x_ikp_mo, bs_env%fm_s_Gamma%matrix_struct)
     402            8 :       CALL cp_fm_create(fm_Sigma_c_ikp_mo, bs_env%fm_s_Gamma%matrix_struct)
     403              : 
     404           16 :       DO ispin = 1, bs_env%n_spin
     405              : 
     406           34 :          DO ikp = 1, bs_env%nkp_bs_and_DOS
     407              : 
     408              :             ! 1. get H^KS_µν(k_i) from H^KS_µν(k=0)
     409              :             CALL cfm_ikp_from_fm_Gamma(cfm_ks_ikp, bs_env%fm_ks_Gamma(ispin), &
     410           18 :                                        ikp, qs_env, bs_env%kpoints_DOS, "ORB")
     411              : 
     412              :             ! 2. get S_µν(k_i) from S_µν(k=0)
     413              :             CALL cfm_ikp_from_fm_Gamma(cfm_s_ikp, bs_env%fm_s_Gamma, &
     414           18 :                                        ikp, qs_env, bs_env%kpoints_DOS, "ORB")
     415              : 
     416              :             ! 3. Diagonalize (Roothaan-Hall): H_KS(k_i)*C(k_i) = S(k_i)*C(k_i)*ϵ(k_i)
     417              :             CALL cp_cfm_geeig(cfm_ks_ikp, cfm_s_ikp, cfm_mos_ikp, &
     418           18 :                               bs_env%eigenval_scf(:, ikp, ispin), cfm_work_ikp)
     419              : 
     420              :             ! Reuse the KS buffer for the full MO operators. Retain their real parts
     421              :             ! at the existing real COHSEX Hamiltonian boundary.
     422              :             ! 4. V^xc_µν(k=0) -> V^xc_µν(k_i) -> V^xc_mn(k_i)
     423              :             CALL cfm_ikp_from_fm_Gamma(cfm_ks_ikp, bs_env%fm_V_xc_Gamma(ispin), &
     424           18 :                                        ikp, qs_env, bs_env%kpoints_DOS, "ORB")
     425           18 :             CALL cfm_contract_ABA(cfm_mos_ikp, cfm_ks_ikp, workspace=cfm_work_ikp)
     426           18 :             CALL cp_cfm_to_fm(cfm_ks_ikp, fm_V_xc_ikp_mo)
     427              : 
     428              :             ! 5. Σ^x_µν(k=0) -> Σ^x_µν(k_i) -> Σ^x_mn(k_i)
     429              :             CALL cfm_ikp_from_fm_Gamma(cfm_ks_ikp, fm_Sigma_x_Gamma(ispin), &
     430           18 :                                        ikp, qs_env, bs_env%kpoints_DOS, "ORB")
     431           18 :             CALL cfm_contract_ABA(cfm_mos_ikp, cfm_ks_ikp, workspace=cfm_work_ikp)
     432           18 :             CALL cp_cfm_to_fm(cfm_ks_ikp, fm_Sigma_x_ikp_mo)
     433              : 
     434              :             ! 6. Σ^c_µν(k=0) -> Σ^c_µν(k_i) -> Σ^c_mn(k_i)
     435              :             CALL cfm_ikp_from_fm_Gamma(cfm_ks_ikp, fm_Sigma_c_Gamma(ispin), &
     436           18 :                                        ikp, qs_env, bs_env%kpoints_DOS, "ORB")
     437           18 :             CALL cfm_contract_ABA(cfm_mos_ikp, cfm_ks_ikp, workspace=cfm_work_ikp)
     438           18 :             CALL cp_cfm_to_fm(cfm_ks_ikp, fm_Sigma_c_ikp_mo)
     439              : 
     440              :             ! 7. build static COHSEX QP Hamiltonian, diagonalize, and print
     441              :             CALL diagonalize_and_print(bs_env, qs_env, fm_Sigma_x_ikp_mo, fm_V_xc_ikp_mo, &
     442           26 :                                        fm_Sigma_c_ikp_mo, ikp, ispin)
     443              : 
     444              :          END DO ! ikp_DOS
     445              : 
     446              :       END DO ! ispin
     447              : 
     448            8 :       CALL get_all_VBM_CBM_bandgaps(bs_env)
     449              : 
     450            8 :       CALL cp_fm_release(fm_Sigma_x_Gamma)
     451            8 :       CALL cp_fm_release(fm_Sigma_c_Gamma)
     452            8 :       CALL cp_fm_release(fm_V_xc_ikp_mo)
     453            8 :       CALL cp_fm_release(fm_Sigma_x_ikp_mo)
     454            8 :       CALL cp_fm_release(fm_Sigma_c_ikp_mo)
     455            8 :       CALL cp_cfm_release(cfm_ks_ikp)
     456            8 :       CALL cp_cfm_release(cfm_s_ikp)
     457            8 :       CALL cp_cfm_release(cfm_mos_ikp)
     458            8 :       CALL cp_cfm_release(cfm_work_ikp)
     459              : 
     460            8 :       CALL timestop(handle)
     461              : 
     462            8 :    END SUBROUTINE compute_QP_energies
     463              : 
     464              : ! **************************************************************************************************
     465              : !> \brief Build the static COHSEX quasiparticle Hamiltonian H^QP at k-point ikp and print the
     466              : !>        diagonal energies ϵ^DG = H^QP_nn (COHSEX DIAGONAL); with COHSEX QP_UPDATE also
     467              : !>        diagonalize H^QP and print the canonical energies ϵ^CN and the canonical MOs
     468              : !> \param bs_env ...
     469              : !> \param qs_env ...
     470              : !> \param fm_Sigma_x_ikp_mo ...
     471              : !> \param fm_V_xc_ikp_mo ...
     472              : !> \param fm_Sigma_c_ikp_mo ...
     473              : !> \param ikp ...
     474              : !> \param ispin ...
     475              : ! **************************************************************************************************
     476           18 :    SUBROUTINE diagonalize_and_print(bs_env, qs_env, fm_Sigma_x_ikp_mo, fm_V_xc_ikp_mo, &
     477              :                                     fm_Sigma_c_ikp_mo, ikp, ispin)
     478              : 
     479              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     480              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     481              :       TYPE(cp_fm_type)                                   :: fm_Sigma_x_ikp_mo, fm_V_xc_ikp_mo, &
     482              :                                                             fm_Sigma_c_ikp_mo
     483              :       INTEGER                                            :: ikp, ispin
     484              : 
     485              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'diagonalize_and_print'
     486              : 
     487              :       CHARACTER(len=3)                                   :: occ_vir
     488              :       CHARACTER(len=default_string_length)               :: fname
     489              :       INTEGER                                            :: handle, i_col, i_row, ikp_for_print, &
     490              :                                                             iunit, j_col, j_row, m, n_mo, &
     491              :                                                             ncol_local, nrow_local
     492           18 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
     493              :       LOGICAL                                            :: is_bandstruc_kpoint, print_DOS_kpoints, &
     494              :                                                             print_ikp, qp_update
     495              :       REAL(KIND=dp)                                      :: val
     496              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: diag_Sigma_c, diag_Sigma_x, diag_SP, &
     497              :                                                             diag_V_xc, SP_eigval
     498              :       TYPE(cp_fm_type)                                   :: fm_SP_mat, SP_eigvec, SP_eigvec_ao
     499              : 
     500           18 :       CALL timeset(routineN, handle)
     501              : 
     502           18 :       n_mo = bs_env%n_ao
     503              :       ! COHSEX QP_UPDATE: diagonalize H^QP (canonical energies and MOs); DIAGONAL: ϵ^DG only
     504           18 :       qp_update = (bs_env%cohsex_flavor == cohsex_qp_update)
     505              : 
     506           18 :       CALL cp_fm_create(fm_SP_mat, bs_env%fm_s_Gamma%matrix_struct)
     507              : 
     508           54 :       ALLOCATE (SP_eigval(n_mo))
     509           18 :       SP_eigval(:) = 0.0_dp
     510              : 
     511              :       ! Build the static COHSEX QP Hamiltonian directly in the distributed fm by looping
     512              :       ! over local elements only (global indices from row_indices/col_indices):
     513              :       !   occ-occ block : Σ^x - v^xc + α Σ^c   (α = COHSEX_SCALE_OCC)
     514              :       !   vir-vir block : Σ^x - v^xc + α Σ^c   (α = COHSEX_SCALE_VIRT)
     515              :       !   occ-vir / vir-occ : 0, i.e. occupied and virtual states are not mixed
     516              :       !   diagonal additionally gets + ϵ^DFT_nk
     517              :       CALL cp_fm_get_info(fm_SP_mat, nrow_local=nrow_local, ncol_local=ncol_local, &
     518           18 :                           row_indices=row_indices, col_indices=col_indices)
     519              : 
     520              : !$OMP PARALLEL DO COLLAPSE(2) DEFAULT(NONE) &
     521              : !$OMP             SHARED(ncol_local, nrow_local, col_indices, row_indices, bs_env, ispin, ikp, &
     522              : !$OMP                    fm_Sigma_x_ikp_mo, fm_V_xc_ikp_mo, fm_Sigma_c_ikp_mo, fm_SP_mat) &
     523           18 : !$OMP             PRIVATE(i_col, i_row, j_col, j_row, val)
     524              :       DO i_col = 1, ncol_local
     525              :          DO i_row = 1, nrow_local
     526              :             j_col = col_indices(i_col)
     527              :             j_row = row_indices(i_row)
     528              :             IF (j_row <= bs_env%n_occ(ispin) .AND. j_col <= bs_env%n_occ(ispin)) THEN
     529              :                val = fm_Sigma_x_ikp_mo%local_data(i_row, i_col) &
     530              :                      - fm_V_xc_ikp_mo%local_data(i_row, i_col) &
     531              :                      + bs_env%cohsex_scale_occ*fm_Sigma_c_ikp_mo%local_data(i_row, i_col)
     532              :             ELSE IF (j_row > bs_env%n_occ(ispin) .AND. j_col > bs_env%n_occ(ispin)) THEN
     533              :                val = fm_Sigma_x_ikp_mo%local_data(i_row, i_col) &
     534              :                      - fm_V_xc_ikp_mo%local_data(i_row, i_col) &
     535              :                      + bs_env%cohsex_scale_virt*fm_Sigma_c_ikp_mo%local_data(i_row, i_col)
     536              :             ELSE
     537              :                val = 0.0_dp
     538              :             END IF
     539              :             IF (j_row == j_col) val = val + bs_env%eigenval_scf(j_row, ikp, ispin)
     540              :             fm_SP_mat%local_data(i_row, i_col) = val
     541              :          END DO
     542              :       END DO
     543              : !$OMP END PARALLEL DO
     544              : 
     545              :       ! diagonal elements (for the per-MO QP printout) before diagonalization
     546           90 :       ALLOCATE (diag_SP(n_mo), diag_Sigma_c(n_mo), diag_Sigma_x(n_mo), diag_V_xc(n_mo))
     547           18 :       CALL cp_fm_get_diag(fm_SP_mat, diag_SP)
     548           18 :       CALL cp_fm_get_diag(fm_Sigma_c_ikp_mo, diag_Sigma_c)
     549           18 :       CALL cp_fm_get_diag(fm_Sigma_x_ikp_mo, diag_Sigma_x)
     550           18 :       CALL cp_fm_get_diag(fm_V_xc_ikp_mo, diag_V_xc)
     551              : 
     552           18 :       IF (qp_update) THEN
     553              :          ! canonical static COHSEX: H^QP U = U ϵ^CN (the occ-virt blocks are zero)
     554           14 :          CALL cp_fm_create(SP_eigvec, bs_env%fm_s_Gamma%matrix_struct)
     555           14 :          CALL cp_fm_create(SP_eigvec_ao, bs_env%fm_s_Gamma%matrix_struct)
     556           14 :          CALL cp_fm_syevx(matrix=fm_SP_mat, eigenvectors=SP_eigvec, eigenvalues=SP_eigval)
     557           14 :          IF (ikp == bs_env%nkp_bs_and_DOS) THEN
     558            6 :             CALL fm_write_formatted(SP_eigvec, 0, "Singlepole_Eigenvector_Gamma", qs_env)
     559              :          END IF
     560              : 
     561              :          ! transform QP eigenvectors from the KS-MO basis to the AO basis
     562              :          CALL parallel_gemm(transa="N", transb="N", m=n_mo, n=n_mo, k=n_mo, alpha=1.0_dp, &
     563              :                             matrix_a=bs_env%fm_mo_coeff_Gamma(ispin), matrix_b=SP_eigvec, &
     564           14 :                             beta=0.0_dp, matrix_c=SP_eigvec_ao)
     565              :       ELSE
     566              :          ! diagonal static COHSEX: ϵ^DG = H^QP_nn, no diagonalization
     567           96 :          SP_eigval(:) = diag_SP(:)
     568              :       END IF
     569              : 
     570          412 :       bs_env%eigenval_GW(:, ikp, ispin) = SP_eigval(:)
     571           18 :       IF (ALLOCATED(bs_env%eigenval_G0W0)) THEN
     572          412 :          bs_env%eigenval_G0W0(:, ikp, ispin) = SP_eigval(:)
     573              :       END IF
     574          412 :       DO m = 1, n_mo
     575              :          bs_env%eigenval_HF(m, ikp, ispin) = bs_env%eigenval_scf(m, ikp, ispin) + &
     576          412 :                                              diag_Sigma_x(m) - diag_V_xc(m)
     577              :       END DO
     578              : 
     579              :       ! only print eigenvalues of DOS k-points in case no bandstructure path has been given;
     580              :       ! in kpoints_DOS the last nkp_only_bs entries are the bandstructure-path k-points
     581           18 :       print_DOS_kpoints = (bs_env%nkp_only_bs <= 0)
     582           18 :       is_bandstruc_kpoint = (ikp > bs_env%nkp_only_DOS)
     583           18 :       print_ikp = print_DOS_kpoints .OR. is_bandstruc_kpoint
     584              : 
     585              :       !! Printing Quasiparticle energies to a file
     586           18 :       IF (bs_env%para_env%is_source() .AND. print_ikp) THEN
     587              : 
     588            9 :          IF (print_DOS_kpoints) THEN
     589            9 :             ikp_for_print = ikp
     590              :          ELSE
     591            0 :             ikp_for_print = ikp - bs_env%nkp_only_DOS
     592              :          END IF
     593              : 
     594            9 :          fname = "Quasiparticle_energies_singlepole"
     595            9 :          IF (ikp_for_print == 1 .AND. ispin == 1) THEN
     596            4 :             CALL open_file(TRIM(fname), unit_number=iunit, file_status="REPLACE", file_action="WRITE")
     597              :          ELSE
     598              :             CALL open_file(TRIM(fname), unit_number=iunit, file_status="OLD", file_action="WRITE", &
     599            5 :                            file_position="APPEND")
     600              :          END IF
     601              : 
     602            9 :          WRITE (iunit, "(A)") " "
     603            9 :          WRITE (iunit, "(A10,I7,A25,3F10.4)") "kpoint: ", ikp_for_print, "coordinate: ", &
     604           45 :             bs_env%kpoints_DOS%xkp(:, ikp)
     605            9 :          WRITE (iunit, "(A)") " "
     606            9 :          IF (qp_update) THEN
     607            7 :             WRITE (iunit, "(A5,A24,2A17,A16,A18,A18)") "n", "ϵ_nk^DFT (eV)", "Σ^c_nk (eV)", &
     608           14 :                "Σ^x_nk (eV)", "v_nk^xc (eV)", "ϵ_nk^DG (eV)", "ϵ_nk^CN (eV)"
     609              :          ELSE
     610            2 :             WRITE (iunit, "(A5,A24,2A17,A16,A18)") "n", "ϵ_nk^DFT (eV)", "Σ^c_nk (eV)", &
     611            4 :                "Σ^x_nk (eV)", "v_nk^xc (eV)", "ϵ_nk^DG (eV)"
     612              :          END IF
     613            9 :          WRITE (iunit, "(A)") " "
     614              : 
     615          206 :          DO m = 1, n_mo
     616          197 :             IF (m <= bs_env%n_occ(ispin)) occ_vir = 'occ'
     617          197 :             IF (m > bs_env%n_occ(ispin)) occ_vir = 'vir'
     618          206 :             IF (qp_update) THEN
     619          151 :                WRITE (iunit, "(I5,3A,4F16.3,F17.3,F17.3)") m, ' (', occ_vir, ') ', &
     620          151 :                   bs_env%eigenval_scf(m, ikp, ispin)*evolt, &
     621          151 :                   diag_Sigma_c(m)*evolt, &
     622          151 :                   diag_Sigma_x(m)*evolt, &
     623          151 :                   diag_V_xc(m)*evolt, &
     624          151 :                   diag_SP(m)*evolt, &
     625          302 :                   SP_eigval(m)*evolt
     626              :             ELSE
     627           46 :                WRITE (iunit, "(I5,3A,4F16.3,F17.3)") m, ' (', occ_vir, ') ', &
     628           46 :                   bs_env%eigenval_scf(m, ikp, ispin)*evolt, &
     629           46 :                   diag_Sigma_c(m)*evolt, &
     630           46 :                   diag_Sigma_x(m)*evolt, &
     631           46 :                   diag_V_xc(m)*evolt, &
     632           92 :                   diag_SP(m)*evolt
     633              :             END IF
     634              :          END DO
     635              : 
     636            9 :          WRITE (iunit, "(A)") " "
     637              : 
     638            9 :          CALL close_file(iunit)
     639              :       END IF
     640              : 
     641           18 :       IF (qp_update) THEN
     642              :          ! canonical MO energies/coefficients and MO cubes (DFT%PRINT%MO, DFT%PRINT%MO_CUBES),
     643              :          ! Gamma point only
     644           14 :          IF (ikp == 1) THEN
     645            6 :             CALL print_static_cohsex_mos(bs_env, qs_env, SP_eigvec_ao, SP_eigval, ispin)
     646              :          END IF
     647           14 :          CALL cp_fm_release(SP_eigvec)
     648           14 :          CALL cp_fm_release(SP_eigvec_ao)
     649              :       END IF
     650              : 
     651           18 :       CALL cp_fm_release(fm_SP_mat)
     652           18 :       DEALLOCATE (SP_eigval, diag_SP, diag_Sigma_c, diag_Sigma_x, diag_V_xc)
     653              : 
     654           18 :       CALL timestop(handle)
     655              : 
     656           36 :    END SUBROUTINE diagonalize_and_print
     657              : 
     658              : ! **************************************************************************************************
     659              : !> \brief Print static COHSEX QP MO energies/occupations/coefficients and MO cubes at the Gamma point,
     660              : !>        reusing the standard DFT%PRINT%MO / DFT%PRINT%MO_CUBES print keys.
     661              : !> \param bs_env ...
     662              : !> \param qs_env ...
     663              : !> \param fm_qp_mo_ao ...
     664              : !> \param qp_eigval ...
     665              : !> \param ispin ...
     666              : ! **************************************************************************************************
     667            6 :    SUBROUTINE print_static_cohsex_mos(bs_env, qs_env, fm_qp_mo_ao, qp_eigval, ispin)
     668              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     669              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     670              :       TYPE(cp_fm_type)                                   :: fm_qp_mo_ao
     671              :       REAL(KIND=dp), DIMENSION(:)                        :: qp_eigval
     672              :       INTEGER                                            :: ispin
     673              : 
     674              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'print_static_cohsex_mos'
     675              : 
     676              :       CHARACTER(LEN=5)                                   :: spin_label
     677              :       CHARACTER(LEN=default_path_length)                 :: fname, title
     678              :       INTEGER                                            :: first_mo, handle, ivector, last_mo, &
     679              :                                                             n_mo, nelectron, nhomo, nlumo, unit_nr
     680            6 :       INTEGER, DIMENSION(:), POINTER                     :: stride
     681              :       LOGICAL                                            :: print_coeff, print_cubes, &
     682              :                                                             print_energies, print_mo, print_occ
     683              :       REAL(KIND=dp)                                      :: maxocc
     684            6 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     685              :       TYPE(cell_type), POINTER                           :: cell
     686              :       TYPE(cp_logger_type), POINTER                      :: logger
     687              :       TYPE(dft_control_type), POINTER                    :: dft_control
     688              :       TYPE(mo_set_type)                                  :: qp_mo_set
     689              :       TYPE(particle_list_type), POINTER                  :: particles
     690            6 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     691              :       TYPE(pw_c1d_gs_type)                               :: wf_g
     692              :       TYPE(pw_env_type), POINTER                         :: pw_env
     693              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     694              :       TYPE(pw_r3d_rs_type)                               :: wf_r
     695            6 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     696              :       TYPE(qs_subsys_type), POINTER                      :: subsys
     697              :       TYPE(section_vals_type), POINTER                   :: dft_section, input
     698              : 
     699            6 :       CALL timeset(routineN, handle)
     700              : 
     701            6 :       n_mo = bs_env%n_ao
     702              : 
     703            6 :       CALL get_qs_env(qs_env, input=input)
     704            6 :       dft_section => section_vals_get_subs_vals(input, "DFT")
     705            6 :       logger => cp_get_default_logger()
     706              : 
     707              :       ! ---------------------------------------------------------------------------------------
     708              :       ! MO energies / occupation numbers / coefficients
     709              :       ! ---------------------------------------------------------------------------------------
     710            6 :       CALL section_vals_val_get(dft_section, "PRINT%MO%ENERGIES", l_val=print_energies)
     711            6 :       CALL section_vals_val_get(dft_section, "PRINT%MO%COEFFICIENTS", l_val=print_coeff)
     712            6 :       CALL section_vals_val_get(dft_section, "PRINT%MO%OCCUPATION_NUMBERS", l_val=print_occ)
     713            6 :       print_mo = (cp_print_key_should_output(logger%iter_info, dft_section, "PRINT%MO") /= 0)
     714              : 
     715            6 :       IF (print_mo .AND. (print_energies .OR. print_occ .OR. print_coeff)) THEN
     716              : 
     717              :          ! occupation numbers of the QP states: the lowest n_occ are occupied
     718            0 :          IF (bs_env%n_spin == 1) THEN
     719            0 :             maxocc = 2.0_dp
     720              :          ELSE
     721            0 :             maxocc = 1.0_dp
     722              :          END IF
     723            0 :          nelectron = NINT(maxocc*REAL(bs_env%n_occ(ispin), KIND=dp))
     724              : 
     725              :          CALL allocate_mo_set(qp_mo_set, nao=n_mo, nmo=n_mo, nelectron=nelectron, &
     726              :                               n_el_f=REAL(nelectron, KIND=dp), maxocc=maxocc, &
     727            0 :                               flexible_electron_count=0.0_dp)
     728            0 :          CALL init_mo_set(qp_mo_set, fm_struct=fm_qp_mo_ao%matrix_struct, name="static_cohsex")
     729            0 :          qp_mo_set%eigenvalues(:) = qp_eigval(:)
     730            0 :          CALL cp_fm_to_fm(fm_qp_mo_ao, qp_mo_set%mo_coeff)
     731              : 
     732            0 :          CALL get_qs_env(qs_env, particle_set=particle_set, qs_kind_set=qs_kind_set)
     733              : 
     734            0 :          IF (bs_env%n_spin == 1) THEN
     735              :             CALL write_mo_set_to_output_unit(qp_mo_set, qs_kind_set, particle_set, dft_section, &
     736            0 :                                              4, 0, final_mos=.TRUE.)
     737              :          ELSE
     738            0 :             IF (ispin == 1) THEN
     739            0 :                spin_label = "ALPHA"
     740              :             ELSE
     741            0 :                spin_label = "BETA"
     742              :             END IF
     743              :             CALL write_mo_set_to_output_unit(qp_mo_set, qs_kind_set, particle_set, dft_section, &
     744            0 :                                              4, 0, final_mos=.TRUE., spin=TRIM(spin_label))
     745              :          END IF
     746              : 
     747            0 :          CALL deallocate_mo_set(qp_mo_set)
     748              :       END IF
     749              : 
     750              :       ! ---------------------------------------------------------------------------------------
     751              :       ! MO cubes
     752              :       ! ---------------------------------------------------------------------------------------
     753            6 :       print_cubes = (cp_print_key_should_output(logger%iter_info, dft_section, "PRINT%MO_CUBES") /= 0)
     754              : 
     755            6 :       IF (print_cubes) THEN
     756            0 :          CALL section_vals_val_get(dft_section, "PRINT%MO_CUBES%NHOMO", i_val=nhomo)
     757            0 :          CALL section_vals_val_get(dft_section, "PRINT%MO_CUBES%NLUMO", i_val=nlumo)
     758            0 :          CALL section_vals_val_get(dft_section, "PRINT%MO_CUBES%STRIDE", i_vals=stride)
     759              : 
     760            0 :          IF (nhomo == -1) nhomo = bs_env%n_occ(ispin)
     761            0 :          IF (nlumo == -1) nlumo = n_mo - bs_env%n_occ(ispin)
     762            0 :          first_mo = MAX(1, bs_env%n_occ(ispin) - nhomo + 1)
     763            0 :          last_mo = MIN(n_mo, bs_env%n_occ(ispin) + nlumo)
     764              : 
     765              :          CALL get_qs_env(qs_env, &
     766              :                          atomic_kind_set=atomic_kind_set, &
     767              :                          qs_kind_set=qs_kind_set, &
     768              :                          cell=cell, &
     769              :                          dft_control=dft_control, &
     770              :                          particle_set=particle_set, &
     771              :                          pw_env=pw_env, &
     772            0 :                          subsys=subsys)
     773            0 :          CALL qs_subsys_get(subsys, particles=particles)
     774              : 
     775            0 :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
     776            0 :          CALL auxbas_pw_pool%create_pw(wf_r)
     777            0 :          CALL auxbas_pw_pool%create_pw(wf_g)
     778              : 
     779            0 :          DO ivector = first_mo, last_mo
     780              :             CALL calculate_wavefunction(fm_qp_mo_ao, ivector, wf_r, wf_g, atomic_kind_set, &
     781            0 :                                         qs_kind_set, cell, dft_control, particle_set, pw_env)
     782              : 
     783            0 :             WRITE (fname, '(A,I5.5,A,I1)') "static_cohsex_WFN_", ivector, "_", ispin
     784              :             unit_nr = cp_print_key_unit_nr(logger, dft_section, "PRINT%MO_CUBES", &
     785              :                                            extension=".cube", middle_name=TRIM(fname), &
     786            0 :                                            file_position="REWIND", log_filename=.FALSE.)
     787            0 :             WRITE (title, *) "static COHSEX WAVEFUNCTION ", ivector, " spin ", ispin, &
     788            0 :                " i.e. HOMO ", ivector - bs_env%n_occ(ispin)
     789            0 :             CALL cp_pw_to_cube(wf_r, unit_nr, title, particles, stride=stride)
     790            0 :             CALL cp_print_key_finished_output(unit_nr, logger, dft_section, "PRINT%MO_CUBES")
     791              :          END DO
     792              : 
     793            0 :          CALL auxbas_pw_pool%give_back_pw(wf_r)
     794            0 :          CALL auxbas_pw_pool%give_back_pw(wf_g)
     795              :       END IF
     796              : 
     797            6 :       CALL timestop(handle)
     798              : 
     799            6 :    END SUBROUTINE print_static_cohsex_mos
     800              : 
     801              : ! **************************************************************************************************
     802              : !> \brief ...
     803              : !> \param fm ...
     804              : !> \param matrix_index ...
     805              : !> \param matrix_name ...
     806              : !> \param qs_env ...
     807              : ! **************************************************************************************************
     808            6 :    SUBROUTINE fm_write_formatted(fm, matrix_index, matrix_name, qs_env)
     809              :       TYPE(cp_fm_type)                                   :: fm
     810              :       INTEGER                                            :: matrix_index
     811              :       CHARACTER(LEN=*)                                   :: matrix_name
     812              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     813              : 
     814              :       CHARACTER(LEN=*), PARAMETER :: key = 'PROPERTIES%BANDSTRUCTURE%GW%PRINT%RESTART', &
     815              :          routineN = 'fm_write_formatted'
     816              : 
     817              :       CHARACTER(LEN=default_string_length)               :: filename
     818              :       INTEGER                                            :: handle, unit_nr
     819              :       TYPE(cp_logger_type), POINTER                      :: logger
     820              :       TYPE(section_vals_type), POINTER                   :: input
     821              : 
     822            6 :       CALL timeset(routineN, handle)
     823              : 
     824            6 :       CALL get_qs_env(qs_env, input=input)
     825              : 
     826            6 :       logger => cp_get_default_logger()
     827              : 
     828            6 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, key), cp_p_file)) THEN
     829              : 
     830            0 :          IF (matrix_index < 10) THEN
     831            0 :             WRITE (filename, '(3A,I1)') "RESTART_", matrix_name, "_0", matrix_index
     832            0 :          ELSE IF (matrix_index < 100) THEN
     833            0 :             WRITE (filename, '(3A,I2)') "RESTART_", matrix_name, "_", matrix_index
     834              :          ELSE
     835            0 :             CPABORT('Please implement more than 99 time/frequency points.')
     836              :          END IF
     837              : 
     838              :          unit_nr = cp_print_key_unit_nr(logger, input, key, extension=".matrix", &
     839              :                                         file_form="FORMATTED", middle_name=TRIM(filename), &
     840            0 :                                         file_position="REWIND", file_action="WRITE")
     841              : 
     842            0 :          CALL cp_fm_write_formatted(fm, unit_nr)
     843            0 :          IF (unit_nr > 0) THEN
     844            0 :             CALL close_file(unit_nr)
     845              :          END IF
     846              :       END IF
     847              : 
     848            6 :       CALL timestop(handle)
     849              : 
     850            6 :    END SUBROUTINE fm_write_formatted
     851              : 
     852              : END MODULE gw_tensor_large_cell_Gamma_static_cohsex
        

Generated by: LCOV version 2.0-1