LCOV - code coverage report
Current view: top level - src - post_scf_bandstructure_utils.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:591cf04) Lines: 93.9 % 1262 1185
Test Date: 2026-09-21 02:17:57 Functions: 97.6 % 42 41

            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
      10              : !> \author Jan Wilhelm
      11              : !> \date 07.2023
      12              : ! **************************************************************************************************
      13              : MODULE post_scf_bandstructure_utils
      14              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      15              :                                               get_atomic_kind,&
      16              :                                               get_atomic_kind_set
      17              :    USE cell_types,                      ONLY: cell_type,&
      18              :                                               get_cell,&
      19              :                                               pbc
      20              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      21              :    USE cp_cfm_basic_linalg,             ONLY: cp_cfm_scale
      22              :    USE cp_cfm_cholesky,                 ONLY: cp_cfm_cholesky_decompose
      23              :    USE cp_cfm_diag,                     ONLY: cp_cfm_geeig,&
      24              :                                               cp_cfm_geeig_canon,&
      25              :                                               cp_cfm_heevd
      26              :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      27              :                                               cp_cfm_get_info,&
      28              :                                               cp_cfm_release,&
      29              :                                               cp_cfm_set_all,&
      30              :                                               cp_cfm_to_cfm,&
      31              :                                               cp_cfm_to_fm,&
      32              :                                               cp_cfm_type,&
      33              :                                               cp_fm_to_cfm
      34              :    USE cp_control_types,                ONLY: dft_control_type
      35              :    USE cp_dbcsr_api,                    ONLY: &
      36              :         dbcsr_create, dbcsr_deallocate_matrix, dbcsr_desymmetrize, dbcsr_p_type, dbcsr_set, &
      37              :         dbcsr_type, dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, dbcsr_type_symmetric
      38              :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      39              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      40              :                                               copy_fm_to_dbcsr,&
      41              :                                               dbcsr_allocate_matrix_set,&
      42              :                                               dbcsr_deallocate_matrix_set
      43              :    USE cp_files,                        ONLY: close_file,&
      44              :                                               open_file
      45              :    USE cp_fm_diag,                      ONLY: cp_fm_geeig_canon
      46              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      47              :                                               cp_fm_struct_release,&
      48              :                                               cp_fm_struct_type
      49              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      50              :                                               cp_fm_get_diag,&
      51              :                                               cp_fm_get_info,&
      52              :                                               cp_fm_release,&
      53              :                                               cp_fm_set_all,&
      54              :                                               cp_fm_to_fm,&
      55              :                                               cp_fm_type
      56              :    USE cp_log_handling,                 ONLY: cp_logger_get_default_io_unit,&
      57              :                                               cp_to_string
      58              :    USE cp_parser_methods,               ONLY: read_float_object
      59              :    USE input_constants,                 ONLY: G0W0,&
      60              :                                               evGW0,&
      61              :                                               int_ldos_z,&
      62              :                                               large_cell_Gamma,&
      63              :                                               large_cell_Gamma_ri_rs,&
      64              :                                               non_periodic_ri_rs,&
      65              :                                               small_cell_full_kp
      66              :    USE input_section_types,             ONLY: section_vals_get,&
      67              :                                               section_vals_get_subs_vals,&
      68              :                                               section_vals_type,&
      69              :                                               section_vals_val_get
      70              :    USE kinds,                           ONLY: default_string_length,&
      71              :                                               dp,&
      72              :                                               max_line_length
      73              :    USE kpoint_methods,                  ONLY: kpoint_init_cell_index,&
      74              :                                               rskp_transform
      75              :    USE kpoint_types,                    ONLY: get_kpoint_info,&
      76              :                                               kpoint_create,&
      77              :                                               kpoint_type
      78              :    USE machine,                         ONLY: m_walltime
      79              :    USE mathconstants,                   ONLY: gaussi,&
      80              :                                               twopi,&
      81              :                                               z_one,&
      82              :                                               z_zero
      83              :    USE message_passing,                 ONLY: mp_para_env_type
      84              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      85              :    USE particle_types,                  ONLY: particle_type
      86              :    USE physcon,                         ONLY: angstrom,&
      87              :                                               evolt
      88              :    USE post_scf_bandstructure_types,    ONLY: band_edges_type,&
      89              :                                               eps_qp_gap,&
      90              :                                               max_qp_gap,&
      91              :                                               post_scf_bandstructure_type
      92              :    USE pw_env_types,                    ONLY: pw_env_get,&
      93              :                                               pw_env_type
      94              :    USE pw_pool_types,                   ONLY: pw_pool_type
      95              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      96              :                                               pw_r3d_rs_type
      97              :    USE qs_collocate_density,            ONLY: calculate_rho_elec
      98              :    USE qs_environment_types,            ONLY: get_qs_env,&
      99              :                                               qs_environment_type
     100              :    USE qs_ks_types,                     ONLY: qs_ks_env_type
     101              :    USE qs_mo_types,                     ONLY: get_mo_set,&
     102              :                                               mo_set_type
     103              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
     104              :    USE rpa_gw_im_time_util,             ONLY: compute_weight_re_im,&
     105              :                                               get_atom_index_from_basis_function_index
     106              :    USE scf_control_types,               ONLY: scf_control_type
     107              :    USE soc_pseudopotential_methods,     ONLY: V_SOC_xyz_from_pseudopotential,&
     108              :                                               remove_soc_outside_energy_window_mo
     109              :    USE soc_pseudopotential_utils,       ONLY: add_cfm_submat,&
     110              :                                               add_dbcsr_submat,&
     111              :                                               cfm_add_on_diag,&
     112              :                                               create_cfm_double,&
     113              :                                               get_cfm_submat
     114              :    USE string_utilities,                ONLY: uppercase
     115              : #include "base/base_uses.f90"
     116              : 
     117              :    IMPLICIT NONE
     118              : 
     119              :    PRIVATE
     120              : 
     121              :    PUBLIC :: create_and_init_bs_env, &
     122              :              eval_bandstructure_properties, cfm_ikp_from_fm_Gamma, &
     123              :              MIC_contribution_from_ikp, compute_xkp, kpoint_init_cell_index_simple, &
     124              :              rsmat_to_kp, soc, get_VBM_CBM_bandgaps, get_all_VBM_CBM_bandgaps, &
     125              :              allocate_GW_eigenvalues, gw_flavour_label
     126              : 
     127              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'post_scf_bandstructure_utils'
     128              : 
     129              : CONTAINS
     130              : 
     131              : ! **************************************************************************************************
     132              : !> \brief Allocate the arrays holding the GW quasiparticle energies
     133              : !> \param bs_env ...
     134              : ! **************************************************************************************************
     135          140 :    SUBROUTINE allocate_GW_eigenvalues(bs_env)
     136              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     137              : 
     138              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'allocate_GW_eigenvalues'
     139              : 
     140              :       INTEGER                                            :: handle, n_ao, n_spin, nkp
     141              : 
     142          140 :       CALL timeset(routineN, handle)
     143              : 
     144          140 :       n_ao = bs_env%n_ao
     145          140 :       nkp = bs_env%nkp_bs_and_DOS
     146          140 :       n_spin = bs_env%n_spin
     147              : 
     148          140 :       IF (.NOT. ALLOCATED(bs_env%eigenval_GW)) THEN
     149          620 :          ALLOCATE (bs_env%eigenval_GW(n_ao, nkp, n_spin))
     150              :       END IF
     151          140 :       IF (.NOT. ALLOCATED(bs_env%eigenval_HF)) THEN
     152          620 :          ALLOCATE (bs_env%eigenval_HF(n_ao, nkp, n_spin))
     153              :       END IF
     154              : 
     155          280 :       SELECT CASE (bs_env%gw_flavour)
     156              :       CASE (G0W0, evGW0)
     157          140 :          IF (.NOT. ALLOCATED(bs_env%eigenval_G0W0)) THEN
     158          620 :             ALLOCATE (bs_env%eigenval_G0W0(n_ao, nkp, n_spin))
     159              :          END IF
     160              :       END SELECT
     161              : 
     162          140 :       IF (bs_env%gw_flavour == evGW0 .AND. .NOT. ALLOCATED(bs_env%eigenval_evGW0)) THEN
     163           20 :          ALLOCATE (bs_env%eigenval_evGW0(n_ao, nkp, n_spin))
     164              :       END IF
     165              : 
     166          140 :       CALL timestop(handle)
     167              : 
     168          140 :    END SUBROUTINE allocate_GW_eigenvalues
     169              : 
     170              : ! **************************************************************************************************
     171              : !> \brief Name of the GW flavour that was requested, for printing
     172              : !> \param bs_env ...
     173              : !> \return ...
     174              : ! **************************************************************************************************
     175          635 :    FUNCTION gw_flavour_label(bs_env) RESULT(label)
     176              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     177              :       CHARACTER(LEN=default_string_length)               :: label
     178              : 
     179          690 :       SELECT CASE (bs_env%gw_flavour)
     180              :       CASE (evGW0)
     181           55 :          label = "evGW0"
     182              :       CASE DEFAULT
     183          635 :          label = "G0W0"
     184              :       END SELECT
     185              : 
     186          635 :    END FUNCTION gw_flavour_label
     187              : 
     188              : ! **************************************************************************************************
     189              : !> \brief ...
     190              : !> \param qs_env ...
     191              : !> \param bs_env ...
     192              : !> \param post_scf_bandstructure_section ...
     193              : ! **************************************************************************************************
     194          124 :    SUBROUTINE create_and_init_bs_env(qs_env, bs_env, post_scf_bandstructure_section)
     195              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     196              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     197              :       TYPE(section_vals_type), POINTER                   :: post_scf_bandstructure_section
     198              : 
     199              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'create_and_init_bs_env'
     200              : 
     201              :       INTEGER                                            :: handle
     202              : 
     203          124 :       CALL timeset(routineN, handle)
     204              : 
     205        12152 :       ALLOCATE (bs_env)
     206              : 
     207          124 :       CALL print_header(bs_env)
     208              : 
     209          124 :       CALL read_bandstructure_input_parameters(bs_env, post_scf_bandstructure_section, qs_env)
     210              : 
     211          124 :       CALL get_parameters_from_qs_env(qs_env, bs_env)
     212              : 
     213          124 :       CALL set_heuristic_parameters(bs_env)
     214              : 
     215          230 :       SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
     216              :       CASE (large_cell_Gamma, large_cell_Gamma_ri_rs, non_periodic_ri_rs)
     217              : 
     218          106 :          CALL setup_kpoints_DOS_large_cell_Gamma(qs_env, bs_env, bs_env%kpoints_DOS)
     219              : 
     220          106 :          CALL allocate_and_fill_fm_ks_fm_s(qs_env, bs_env)
     221              : 
     222          106 :          CALL diagonalize_ks_matrix(bs_env)
     223              : 
     224          106 :          CALL check_positive_definite_overlap_mat(bs_env, qs_env)
     225              : 
     226              :       CASE (small_cell_full_kp)
     227              : 
     228           18 :          CALL setup_kpoints_scf_desymm(qs_env, bs_env, bs_env%kpoints_scf_desymm, .TRUE.)
     229           18 :          CALL setup_kpoints_scf_desymm(qs_env, bs_env, bs_env%kpoints_scf_desymm_2, .FALSE.)
     230              : 
     231           18 :          CALL setup_kpoints_DOS_small_cell_full_kp(bs_env, bs_env%kpoints_DOS)
     232              : 
     233           18 :          CALL allocate_and_fill_fm_ks_fm_s(qs_env, bs_env)
     234              : 
     235          142 :          CALL compute_cfm_mo_coeff_kp_and_eigenval_scf_kp(qs_env, bs_env)
     236              : 
     237              :       END SELECT
     238              : 
     239          124 :       CALL timestop(handle)
     240              : 
     241          124 :    END SUBROUTINE create_and_init_bs_env
     242              : 
     243              : ! **************************************************************************************************
     244              : !> \brief ...
     245              : !> \param bs_env ...
     246              : !> \param bs_sec ...
     247              : !> \param qs_env ...
     248              : ! **************************************************************************************************
     249          124 :    SUBROUTINE read_bandstructure_input_parameters(bs_env, bs_sec, qs_env)
     250              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     251              :       TYPE(section_vals_type), POINTER                   :: bs_sec
     252              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     253              : 
     254              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'read_bandstructure_input_parameters'
     255              : 
     256              :       CHARACTER(LEN=default_string_length)               :: ustr
     257              :       CHARACTER(LEN=default_string_length), &
     258          124 :          DIMENSION(:), POINTER                           :: string_ptr
     259              :       CHARACTER(LEN=max_line_length)                     :: error_msg
     260              :       INTEGER                                            :: handle, i, ikp
     261              :       REAL(KIND=dp), DIMENSION(3)                        :: kpptr
     262              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: cart_hmat
     263              :       TYPE(cell_type), POINTER                           :: cell
     264              :       TYPE(section_vals_type), POINTER                   :: dos_pdos_sec, floquet_sec, gw_sec, &
     265              :                                                             kp_bs_sec, ldos_sec, soc_sec
     266              : 
     267          124 :       CALL timeset(routineN, handle)
     268          124 :       NULLIFY (cell)
     269          124 :       CALL get_qs_env(qs_env=qs_env, cell=cell)
     270         1612 :       cart_hmat(:, :) = cell%hmat(:, :)
     271          124 :       IF (cell%input_cell_canonicalized) cart_hmat(:, :) = cell%input_hmat(:, :)
     272              : 
     273          124 :       NULLIFY (gw_sec)
     274          124 :       gw_sec => section_vals_get_subs_vals(bs_sec, "GW")
     275          124 :       CALL section_vals_get(gw_sec, explicit=bs_env%do_gw)
     276          124 :       CALL section_vals_val_get(gw_sec, "RI_RS%_SECTION_PARAMETERS_", l_val=bs_env%do_gw_ri_rs)
     277              : 
     278          124 :       NULLIFY (soc_sec)
     279          124 :       soc_sec => section_vals_get_subs_vals(bs_sec, "SOC")
     280          124 :       CALL section_vals_get(soc_sec, explicit=bs_env%do_soc)
     281              : 
     282          124 :       CALL section_vals_val_get(soc_sec, "SOC_WINDOW_OCC", r_val=bs_env%soc_window_occ)
     283          124 :       CALL section_vals_val_get(soc_sec, "SOC_WINDOW_VIRT", r_val=bs_env%soc_window_virt)
     284          124 :       CALL section_vals_val_get(soc_sec, "SOC_WINDOW_SMEARING", r_val=bs_env%soc_window_smearing)
     285              : 
     286          124 :       NULLIFY (dos_pdos_sec)
     287          124 :       dos_pdos_sec => section_vals_get_subs_vals(bs_sec, "DOS")
     288          124 :       CALL section_vals_get(dos_pdos_sec, explicit=bs_env%do_dos_pdos)
     289              : 
     290          124 :       CALL section_vals_val_get(bs_sec, "DOS%KPOINTS", i_vals=bs_env%nkp_grid_DOS_input)
     291          124 :       CALL section_vals_val_get(bs_sec, "DOS%ENERGY_WINDOW", r_val=bs_env%energy_window_DOS)
     292          124 :       CALL section_vals_val_get(bs_sec, "DOS%ENERGY_STEP", r_val=bs_env%energy_step_DOS)
     293          124 :       CALL section_vals_val_get(bs_sec, "DOS%BROADENING", r_val=bs_env%broadening_DOS)
     294              : 
     295          124 :       NULLIFY (ldos_sec)
     296          124 :       ldos_sec => section_vals_get_subs_vals(bs_sec, "DOS%LDOS")
     297          124 :       CALL section_vals_get(ldos_sec, explicit=bs_env%do_ldos)
     298              : 
     299          124 :       CALL section_vals_val_get(ldos_sec, "INTEGRATION", i_val=bs_env%int_ldos_xyz)
     300          124 :       CALL section_vals_val_get(ldos_sec, "BIN_MESH", i_vals=bs_env%bin_mesh)
     301              : 
     302          124 :       NULLIFY (kp_bs_sec)
     303          124 :       kp_bs_sec => section_vals_get_subs_vals(bs_sec, "BANDSTRUCTURE_PATH")
     304          124 :       CALL section_vals_val_get(kp_bs_sec, "NPOINTS", i_val=bs_env%input_kp_bs_npoints)
     305          124 :       CALL section_vals_val_get(kp_bs_sec, "UNITS", c_val=ustr)
     306          124 :       CALL uppercase(ustr)
     307          124 :       CALL section_vals_val_get(kp_bs_sec, "SPECIAL_POINT", n_rep_val=bs_env%input_kp_bs_n_sp_pts)
     308              : 
     309          124 :       NULLIFY (floquet_sec)
     310          124 :       floquet_sec => section_vals_get_subs_vals(bs_sec, "FLOQUET")
     311          124 :       CALL section_vals_get(floquet_sec, explicit=bs_env%do_floquet)
     312          124 :       CALL section_vals_val_get(floquet_sec, "AMPLITUDE", r_val=bs_env%floquet_amplitude)
     313          124 :       CALL section_vals_val_get(floquet_sec, "FREQUENCY", r_val=bs_env%floquet_omega)
     314          124 :       CALL section_vals_val_get(floquet_sec, "POLARISATION", r_vals=bs_env%floquet_polarisation)
     315          124 :       CALL section_vals_val_get(floquet_sec, "PHASE_OFFSETS", r_vals=bs_env%floquet_phi)
     316          124 :       CALL section_vals_val_get(floquet_sec, "MAX_FLOQUET_INDEX", i_val=bs_env%max_floquet_index)
     317          124 :       CALL section_vals_val_get(floquet_sec, "EPS_FLOQUET", r_val=bs_env%eps_floquet)
     318          124 :       CALL section_vals_val_get(floquet_sec, "ENERGY_WINDOW", r_val=bs_env%energy_window_floquet)
     319          124 :       CALL section_vals_val_get(floquet_sec, "ENERGY_STEP", r_val=bs_env%energy_step_floquet)
     320          124 :       CALL section_vals_val_get(floquet_sec, "BROADENING", r_val=bs_env%broadening_floquet)
     321          124 :       CALL section_vals_val_get(floquet_sec, "MEM_FILL_FRACTION", r_val=bs_env%floquet_mem_fill_fraction)
     322          124 :       CALL section_vals_val_get(floquet_sec, "TEMPERATURE", r_val=bs_env%floquet_temperature)
     323          124 :       CALL section_vals_val_get(floquet_sec, "FLOQUET_DOS_FILE_NAME", c_val=bs_env%floquet_dos_file)
     324          124 :       CALL section_vals_val_get(floquet_sec, "QUASI_ENERGIES_FILE_NAME", c_val=bs_env%floquet_qe_file)
     325          124 :       CALL section_vals_val_get(floquet_sec, "FLOQUET_BS_FILE_NAME", c_val=bs_env%floquet_bs_file)
     326              : 
     327              :       ! read special points for band structure
     328          252 :       ALLOCATE (bs_env%xkp_special(3, bs_env%input_kp_bs_n_sp_pts))
     329          134 :       DO ikp = 1, bs_env%input_kp_bs_n_sp_pts
     330           10 :          CALL section_vals_val_get(kp_bs_sec, "SPECIAL_POINT", i_rep_val=ikp, c_vals=string_ptr)
     331           10 :          CPASSERT(SIZE(string_ptr(:), 1) == 4)
     332           40 :          DO i = 1, 3
     333           30 :             CALL read_float_object(string_ptr(i + 1), kpptr(i), error_msg)
     334           40 :             IF (LEN_TRIM(error_msg) > 0) CPABORT(TRIM(error_msg))
     335              :          END DO
     336          124 :          SELECT CASE (ustr)
     337              :          CASE ("B_VECTOR")
     338           40 :             bs_env%xkp_special(1:3, ikp) = kpptr(1:3)
     339              :          CASE ("CART_ANGSTROM")
     340              :             bs_env%xkp_special(1:3, ikp) = (kpptr(1)*cart_hmat(1, 1:3) + &
     341              :                                             kpptr(2)*cart_hmat(2, 1:3) + &
     342            0 :                                             kpptr(3)*cart_hmat(3, 1:3))/twopi*angstrom
     343              :          CASE ("CART_BOHR")
     344              :             bs_env%xkp_special(1:3, ikp) = (kpptr(1)*cart_hmat(1, 1:3) + &
     345              :                                             kpptr(2)*cart_hmat(2, 1:3) + &
     346            0 :                                             kpptr(3)*cart_hmat(3, 1:3))/twopi
     347              :          CASE DEFAULT
     348           10 :             CPABORT("Unknown unit <"//TRIM(ustr)//"> specified for k-point definition")
     349              :          END SELECT
     350              :       END DO
     351              : 
     352          124 :       CALL timestop(handle)
     353              : 
     354          124 :    END SUBROUTINE read_bandstructure_input_parameters
     355              : 
     356              : ! **************************************************************************************************
     357              : !> \brief ...
     358              : !> \param bs_env ...
     359              : ! **************************************************************************************************
     360          124 :    SUBROUTINE print_header(bs_env)
     361              : 
     362              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     363              : 
     364              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'print_header'
     365              : 
     366              :       INTEGER                                            :: handle, u
     367              : 
     368          124 :       CALL timeset(routineN, handle)
     369              : 
     370          124 :       bs_env%unit_nr = cp_logger_get_default_io_unit()
     371              : 
     372          124 :       u = bs_env%unit_nr
     373              : 
     374          124 :       IF (u > 0) THEN
     375           62 :          WRITE (u, '(T2,A)') ' '
     376           62 :          WRITE (u, '(T2,A)') REPEAT('-', 79)
     377           62 :          WRITE (u, '(T2,A,A78)') '-', '-'
     378           62 :          WRITE (u, '(T2,A,A51,A27)') '-', 'BANDSTRUCTURE CALCULATION', '-'
     379           62 :          WRITE (u, '(T2,A,A78)') '-', '-'
     380           62 :          WRITE (u, '(T2,A)') REPEAT('-', 79)
     381           62 :          WRITE (u, '(T2,A)') ' '
     382              :       END IF
     383              : 
     384          124 :       CALL timestop(handle)
     385              : 
     386          124 :    END SUBROUTINE print_header
     387              : 
     388              : ! **************************************************************************************************
     389              : !> \brief ...
     390              : !> \param qs_env ...
     391              : !> \param bs_env ...
     392              : !> \param kpoints ...
     393              : ! **************************************************************************************************
     394          106 :    SUBROUTINE setup_kpoints_DOS_large_cell_Gamma(qs_env, bs_env, kpoints)
     395              : 
     396              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     397              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     398              :       TYPE(kpoint_type), POINTER                         :: kpoints
     399              : 
     400              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'setup_kpoints_DOS_large_cell_Gamma'
     401              : 
     402              :       INTEGER                                            :: handle, i_dim, i_kp_in_line, &
     403              :                                                             i_special_kp, ikk, n_kp_in_line, &
     404              :                                                             n_special_kp, nkp, nkp_only_bs, &
     405              :                                                             nkp_only_DOS, u
     406              :       INTEGER, DIMENSION(3)                              :: nkp_grid, periodic
     407              : 
     408          106 :       CALL timeset(routineN, handle)
     409              : 
     410              :       ! routine adapted from mp2_integrals.F
     411          106 :       NULLIFY (kpoints)
     412          106 :       CALL kpoint_create(kpoints)
     413              : 
     414          106 :       kpoints%kp_scheme = "GENERAL"
     415              : 
     416          106 :       n_special_kp = bs_env%input_kp_bs_n_sp_pts
     417          106 :       n_kp_in_line = bs_env%input_kp_bs_npoints
     418              : 
     419          424 :       periodic(1:3) = bs_env%periodic(1:3)
     420              : 
     421          424 :       DO i_dim = 1, 3
     422              : 
     423          318 :          CPASSERT(periodic(i_dim) == 0 .OR. periodic(i_dim) == 1)
     424              : 
     425          424 :          IF (bs_env%nkp_grid_DOS_input(i_dim) < 0) THEN
     426          300 :             IF (periodic(i_dim) == 1) nkp_grid(i_dim) = 2
     427          300 :             IF (periodic(i_dim) == 0) nkp_grid(i_dim) = 1
     428              :          ELSE
     429           18 :             nkp_grid(i_dim) = bs_env%nkp_grid_DOS_input(i_dim)
     430              :          END IF
     431              : 
     432              :       END DO
     433              : 
     434              :       ! use the k <-> -k symmetry to reduce the number of kpoints
     435          106 :       IF (nkp_grid(1) > 1) THEN
     436            4 :          nkp_only_DOS = (nkp_grid(1) + 1)/2*nkp_grid(2)*nkp_grid(3)
     437          102 :       ELSE IF (nkp_grid(2) > 1) THEN
     438            4 :          nkp_only_DOS = nkp_grid(1)*(nkp_grid(2) + 1)/2*nkp_grid(3)
     439           98 :       ELSE IF (nkp_grid(3) > 1) THEN
     440            2 :          nkp_only_DOS = nkp_grid(1)*nkp_grid(2)*(nkp_grid(3) + 1)/2
     441              :       ELSE
     442           96 :          nkp_only_DOS = 1
     443              :       END IF
     444              : 
     445              :       ! we will compute the GW QP levels for all k's in the bandstructure path but also
     446              :       ! for all k-points from the SCF (e.g. for DOS or for self-consistent GW)
     447          106 :       IF (n_special_kp > 0) THEN
     448            0 :          nkp_only_bs = n_kp_in_line*(n_special_kp - 1) + 1
     449              :       ELSE
     450              :          nkp_only_bs = 0
     451              :       END IF
     452              : 
     453          106 :       nkp = nkp_only_DOS + nkp_only_bs
     454              : 
     455          424 :       kpoints%nkp_grid(1:3) = nkp_grid(1:3)
     456          106 :       kpoints%nkp = nkp
     457              : 
     458          106 :       bs_env%nkp_bs_and_DOS = nkp
     459          106 :       bs_env%nkp_only_bs = nkp_only_bs
     460          106 :       bs_env%nkp_only_DOS = nkp_only_DOS
     461              : 
     462          530 :       ALLOCATE (kpoints%xkp(3, nkp), kpoints%wkp(nkp))
     463          220 :       kpoints%wkp(1:nkp_only_DOS) = 1.0_dp/REAL(nkp_only_DOS, KIND=dp)
     464              : 
     465          106 :       CALL compute_xkp(kpoints%xkp, 1, nkp_only_DOS, nkp_grid)
     466              : 
     467          106 :       IF (n_special_kp > 0) THEN
     468            0 :          kpoints%xkp(1:3, nkp_only_DOS + 1) = bs_env%xkp_special(1:3, 1)
     469            0 :          ikk = nkp_only_DOS + 1
     470            0 :          DO i_special_kp = 2, n_special_kp
     471            0 :             DO i_kp_in_line = 1, n_kp_in_line
     472            0 :                ikk = ikk + 1
     473              :                kpoints%xkp(1:3, ikk) = bs_env%xkp_special(1:3, i_special_kp - 1) + &
     474              :                                        REAL(i_kp_in_line, KIND=dp)/REAL(n_kp_in_line, KIND=dp)* &
     475              :                                        (bs_env%xkp_special(1:3, i_special_kp) - &
     476            0 :                                         bs_env%xkp_special(1:3, i_special_kp - 1))
     477            0 :                kpoints%wkp(ikk) = 0.0_dp
     478              :             END DO
     479              :          END DO
     480              :       END IF
     481              : 
     482          106 :       CALL kpoint_init_cell_index_simple(kpoints, qs_env)
     483              : 
     484          106 :       u = bs_env%unit_nr
     485              : 
     486          106 :       IF (u > 0 .AND. bs_env%do_periodic) THEN
     487            5 :          IF (nkp_only_bs > 0) THEN
     488              :             WRITE (u, FMT="(T2,1A,T77,I4)") &
     489            0 :                "Number of special k-points for the bandstructure", n_special_kp
     490            0 :             WRITE (u, FMT="(T2,1A,T77,I4)") "Number of k-points for the bandstructure", nkp
     491              :             WRITE (u, FMT="(T2,1A,T69,3I4)") &
     492            0 :                "K-point mesh for the density of states (DOS)", nkp_grid(1:3)
     493              :          ELSE
     494              :             WRITE (u, FMT="(T2,1A,T69,3I4)") &
     495            5 :                "K-point mesh for the density of states (DOS) and the self-energy", nkp_grid(1:3)
     496              :          END IF
     497              :       END IF
     498              : 
     499          106 :       CALL timestop(handle)
     500              : 
     501          106 :    END SUBROUTINE setup_kpoints_DOS_large_cell_Gamma
     502              : 
     503              : ! **************************************************************************************************
     504              : !> \brief ...
     505              : !> \param qs_env ...
     506              : !> \param bs_env ...
     507              : !> \param kpoints ...
     508              : !> \param do_print ...
     509              : ! **************************************************************************************************
     510           36 :    SUBROUTINE setup_kpoints_scf_desymm(qs_env, bs_env, kpoints, do_print)
     511              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     512              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     513              :       TYPE(kpoint_type), POINTER                         :: kpoints
     514              : 
     515              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'setup_kpoints_scf_desymm'
     516              : 
     517              :       INTEGER                                            :: handle, i_cell_x, i_dim, img, j_cell_y, &
     518              :                                                             k_cell_z, nimages, nkp, u
     519              :       INTEGER, DIMENSION(3)                              :: cell_grid, cixd, nkp_grid
     520              :       TYPE(kpoint_type), POINTER                         :: kpoints_scf
     521              : 
     522              :       LOGICAL:: do_print
     523              : 
     524           36 :       CALL timeset(routineN, handle)
     525              : 
     526           36 :       NULLIFY (kpoints)
     527           36 :       CALL kpoint_create(kpoints)
     528              : 
     529           36 :       CALL get_qs_env(qs_env=qs_env, kpoints=kpoints_scf)
     530              : 
     531          144 :       nkp_grid(1:3) = kpoints_scf%nkp_grid(1:3)
     532           36 :       nkp = nkp_grid(1)*nkp_grid(2)*nkp_grid(3)
     533              : 
     534              :       ! we need in periodic directions at least 4 k-points in the SCF
     535          144 :       DO i_dim = 1, 3
     536          144 :          IF (bs_env%periodic(i_dim) == 1) THEN
     537           72 :             CPASSERT(nkp_grid(i_dim) >= 4)
     538              :          END IF
     539              :       END DO
     540              : 
     541           36 :       kpoints%kp_scheme = "GENERAL"
     542          144 :       kpoints%nkp_grid(1:3) = nkp_grid(1:3)
     543           36 :       kpoints%nkp = nkp
     544           36 :       bs_env%nkp_scf_desymm = nkp
     545              : 
     546          108 :       ALLOCATE (kpoints%xkp(1:3, nkp))
     547           36 :       CALL compute_xkp(kpoints%xkp, 1, nkp, nkp_grid)
     548              : 
     549          108 :       ALLOCATE (kpoints%wkp(nkp))
     550          612 :       kpoints%wkp(:) = 1.0_dp/REAL(nkp, KIND=dp)
     551              : 
     552              :       ! for example 4x3x6 kpoint grid -> 3x3x5 cell grid because we need the same number of
     553              :       ! neighbor cells on both sides of the unit cell
     554          144 :       cell_grid(1:3) = nkp_grid(1:3) - MODULO(nkp_grid(1:3) + 1, 2)
     555              : 
     556              :       ! cell index: for example for x: from -n_x/2 to +n_x/2, n_x: number of cells in x direction
     557          144 :       cixd(1:3) = cell_grid(1:3)/2
     558              : 
     559           36 :       nimages = cell_grid(1)*cell_grid(2)*cell_grid(3)
     560              : 
     561           36 :       bs_env%nimages_scf_desymm = nimages
     562          144 :       bs_env%cell_grid_scf_desymm(1:3) = cell_grid(1:3)
     563              : 
     564           36 :       IF (ASSOCIATED(kpoints%index_to_cell)) DEALLOCATE (kpoints%index_to_cell)
     565           36 :       IF (ASSOCIATED(kpoints%cell_to_index)) DEALLOCATE (kpoints%cell_to_index)
     566              : 
     567          180 :       ALLOCATE (kpoints%cell_to_index(-cixd(1):cixd(1), -cixd(2):cixd(2), -cixd(3):cixd(3)))
     568          108 :       ALLOCATE (kpoints%index_to_cell(3, nimages))
     569              : 
     570           36 :       img = 0
     571           88 :       DO i_cell_x = -cixd(1), cixd(1)
     572          244 :          DO j_cell_y = -cixd(2), cixd(2)
     573          532 :             DO k_cell_z = -cixd(3), cixd(3)
     574          324 :                img = img + 1
     575          324 :                kpoints%cell_to_index(i_cell_x, j_cell_y, k_cell_z) = img
     576         1452 :                kpoints%index_to_cell(1:3, img) = [i_cell_x, j_cell_y, k_cell_z]
     577              :             END DO
     578              :          END DO
     579              :       END DO
     580              : 
     581           36 :       u = bs_env%unit_nr
     582           36 :       IF (u > 0 .AND. do_print) THEN
     583            9 :          WRITE (u, FMT="(T2,A,I49)") "Number of cells for G, χ, W, Σ", nimages
     584              :       END IF
     585              : 
     586           36 :       CALL timestop(handle)
     587              : 
     588           36 :    END SUBROUTINE setup_kpoints_scf_desymm
     589              : 
     590              : ! **************************************************************************************************
     591              : !> \brief ...
     592              : !> \param bs_env ...
     593              : !> \param kpoints ...
     594              : ! **************************************************************************************************
     595           18 :    SUBROUTINE setup_kpoints_DOS_small_cell_full_kp(bs_env, kpoints)
     596              : 
     597              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     598              :       TYPE(kpoint_type), POINTER                         :: kpoints
     599              : 
     600              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'setup_kpoints_DOS_small_cell_full_kp'
     601              : 
     602              :       INTEGER                                            :: handle, i_kp_in_line, i_special_kp, ikk, &
     603              :                                                             n_kp_in_line, n_special_kp, nkp, &
     604              :                                                             nkp_only_bs, nkp_scf_desymm, u
     605              : 
     606           18 :       CALL timeset(routineN, handle)
     607              : 
     608              :       ! routine adapted from mp2_integrals.F
     609           18 :       NULLIFY (kpoints)
     610           18 :       CALL kpoint_create(kpoints)
     611              : 
     612           18 :       n_special_kp = bs_env%input_kp_bs_n_sp_pts
     613           18 :       n_kp_in_line = bs_env%input_kp_bs_npoints
     614           18 :       nkp_scf_desymm = bs_env%nkp_scf_desymm
     615              : 
     616              :       ! we will compute the GW QP levels for all k's in the bandstructure path but also
     617              :       ! for all k-points from the SCF (e.g. for DOS or for self-consistent GW)
     618           18 :       IF (n_special_kp > 0) THEN
     619            4 :          nkp_only_bs = n_kp_in_line*(n_special_kp - 1) + 1
     620              :       ELSE
     621              :          nkp_only_bs = 0
     622              :       END IF
     623           18 :       nkp = nkp_only_bs + nkp_scf_desymm
     624              : 
     625           54 :       ALLOCATE (kpoints%xkp(3, nkp))
     626           54 :       ALLOCATE (kpoints%wkp(nkp))
     627              : 
     628           18 :       kpoints%nkp = nkp
     629              : 
     630           18 :       bs_env%nkp_bs_and_DOS = nkp
     631           18 :       bs_env%nkp_only_bs = nkp_only_bs
     632           18 :       bs_env%nkp_only_DOS = nkp_scf_desymm
     633              : 
     634         2340 :       kpoints%xkp(1:3, 1:nkp_scf_desymm) = bs_env%kpoints_scf_desymm%xkp(1:3, 1:nkp_scf_desymm)
     635          306 :       kpoints%wkp(1:nkp_scf_desymm) = 1.0_dp/REAL(nkp_scf_desymm, KIND=dp)
     636              : 
     637           18 :       IF (n_special_kp > 0) THEN
     638           32 :          kpoints%xkp(1:3, nkp_scf_desymm + 1) = bs_env%xkp_special(1:3, 1)
     639            4 :          ikk = nkp_scf_desymm + 1
     640           10 :          DO i_special_kp = 2, n_special_kp
     641           70 :             DO i_kp_in_line = 1, n_kp_in_line
     642           60 :                ikk = ikk + 1
     643              :                kpoints%xkp(1:3, ikk) = bs_env%xkp_special(1:3, i_special_kp - 1) + &
     644              :                                        REAL(i_kp_in_line, KIND=dp)/REAL(n_kp_in_line, KIND=dp)* &
     645              :                                        (bs_env%xkp_special(1:3, i_special_kp) - &
     646          480 :                                         bs_env%xkp_special(1:3, i_special_kp - 1))
     647           66 :                kpoints%wkp(ikk) = 0.0_dp
     648              :             END DO
     649              :          END DO
     650              :       END IF
     651              : 
     652           18 :       IF (ASSOCIATED(kpoints%index_to_cell)) DEALLOCATE (kpoints%index_to_cell)
     653              : 
     654           54 :       ALLOCATE (kpoints%index_to_cell(3, bs_env%nimages_scf_desymm))
     655         1332 :       kpoints%index_to_cell(:, :) = bs_env%kpoints_scf_desymm%index_to_cell(:, :)
     656              : 
     657           18 :       u = bs_env%unit_nr
     658              : 
     659           18 :       IF (u > 0) THEN
     660            9 :          WRITE (u, FMT="(T2,1A,T77,I4)") "Number of special k-points for the bandstructure", &
     661           18 :             n_special_kp
     662            9 :          WRITE (u, FMT="(T2,1A,T77,I4)") "Number of k-points for the bandstructure", nkp
     663              :       END IF
     664              : 
     665           18 :       CALL timestop(handle)
     666              : 
     667           18 :    END SUBROUTINE setup_kpoints_DOS_small_cell_full_kp
     668              : 
     669              : ! **************************************************************************************************
     670              : !> \brief ...
     671              : !> \param qs_env ...
     672              : !> \param bs_env ...
     673              : ! **************************************************************************************************
     674           18 :    SUBROUTINE compute_cfm_mo_coeff_kp_and_eigenval_scf_kp(qs_env, bs_env)
     675              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     676              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     677              : 
     678              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_cfm_mo_coeff_kp_and_eigenval_scf_kp'
     679              : 
     680              :       INTEGER                                            :: handle, ikp, ispin, nkp_bs_and_DOS, &
     681              :                                                             nmo_retained
     682           18 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index_scf
     683              :       REAL(KIND=dp)                                      :: CBM, VBM
     684              :       REAL(KIND=dp), DIMENSION(3)                        :: xkp
     685              :       TYPE(cp_cfm_type)                                  :: cfm_ks, cfm_mos, cfm_s
     686           18 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks, matrix_s
     687              :       TYPE(kpoint_type), POINTER                         :: kpoints_scf
     688              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     689           18 :          POINTER                                         :: sab_nl
     690              : 
     691           18 :       CALL timeset(routineN, handle)
     692              : 
     693              :       CALL get_qs_env(qs_env, &
     694              :                       matrix_ks_kp=matrix_ks, &
     695              :                       matrix_s_kp=matrix_s, &
     696           18 :                       kpoints=kpoints_scf)
     697              : 
     698           18 :       NULLIFY (sab_nl)
     699           18 :       CALL get_kpoint_info(kpoints_scf, sab_nl=sab_nl, cell_to_index=cell_to_index_scf)
     700              : 
     701           18 :       CALL cp_cfm_create(cfm_ks, bs_env%cfm_work_mo%matrix_struct)
     702           18 :       CALL cp_cfm_create(cfm_s, bs_env%cfm_work_mo%matrix_struct)
     703           18 :       CALL cp_cfm_create(cfm_mos, bs_env%cfm_work_mo%matrix_struct)
     704              : 
     705              :       ! nkp_bs_and_DOS contains desymmetrized k-point mesh from SCF and k-points from GW bandstructure
     706           18 :       nkp_bs_and_DOS = bs_env%nkp_bs_and_DOS
     707              : 
     708           18 :       CALL allocate_GW_eigenvalues(bs_env)
     709              : 
     710          442 :       ALLOCATE (bs_env%cfm_mo_coeff_kp(nkp_bs_and_DOS, bs_env%n_spin))
     711          442 :       ALLOCATE (bs_env%cfm_ks_kp(nkp_bs_and_DOS, bs_env%n_spin))
     712          406 :       ALLOCATE (bs_env%cfm_s_kp(nkp_bs_and_DOS))
     713          370 :       DO ikp = 1, nkp_bs_and_DOS
     714          704 :       DO ispin = 1, bs_env%n_spin
     715          352 :          CALL cp_cfm_create(bs_env%cfm_mo_coeff_kp(ikp, ispin), bs_env%cfm_work_mo%matrix_struct)
     716          704 :          CALL cp_cfm_create(bs_env%cfm_ks_kp(ikp, ispin), bs_env%cfm_work_mo%matrix_struct)
     717              :       END DO
     718          370 :       CALL cp_cfm_create(bs_env%cfm_s_kp(ikp), bs_env%cfm_work_mo%matrix_struct)
     719              :       END DO
     720              : 
     721           36 :       DO ispin = 1, bs_env%n_spin
     722          370 :          DO ikp = 1, nkp_bs_and_DOS
     723              : 
     724         1408 :             xkp(1:3) = bs_env%kpoints_DOS%xkp(1:3, ikp)
     725              : 
     726              :             ! h^KS^R -> h^KS(k)
     727          352 :             CALL rsmat_to_kp(matrix_ks, ispin, xkp, cell_to_index_scf, sab_nl, bs_env, cfm_ks)
     728              : 
     729              :             ! S^R -> S(k)
     730          352 :             CALL rsmat_to_kp(matrix_s, 1, xkp, cell_to_index_scf, sab_nl, bs_env, cfm_s)
     731              : 
     732              :             ! we store the complex KS matrix as fm matrix because the infrastructure for fm is
     733              :             ! much nicer compared to cfm
     734          352 :             CALL cp_cfm_to_cfm(cfm_ks, bs_env%cfm_ks_kp(ikp, ispin))
     735          352 :             CALL cp_cfm_to_cfm(cfm_s, bs_env%cfm_s_kp(ikp))
     736              : 
     737              :             ! Diagonalize KS-matrix via Rothaan-Hall equation:
     738              :             ! H^KS(k) C(k) = S(k) C(k) ε(k)
     739              :             CALL cp_cfm_geeig_canon(cfm_ks, cfm_s, cfm_mos, &
     740              :                                     bs_env%eigenval_scf(:, ikp, ispin), &
     741              :                                     bs_env%cfm_work_mo, bs_env%eps_eigval_mat_s, &
     742          352 :                                     nmo_retained=nmo_retained)
     743          352 :             bs_env%n_mo_retained = MIN(bs_env%n_mo_retained, nmo_retained)
     744              : 
     745              :             ! we store the complex MO coeff as fm matrix because the infrastructure for fm is
     746              :             ! much nicer compared to cfm
     747          370 :             CALL cp_cfm_to_cfm(cfm_mos, bs_env%cfm_mo_coeff_kp(ikp, ispin))
     748              : 
     749              :          END DO
     750              : 
     751          370 :          VBM = MAXVAL(bs_env%eigenval_scf(bs_env%n_occ(ispin), :, ispin))
     752          370 :          CBM = MINVAL(bs_env%eigenval_scf(bs_env%n_occ(ispin) + 1, :, ispin))
     753              : 
     754           36 :          bs_env%e_fermi(ispin) = 0.5_dp*(VBM + CBM)
     755              : 
     756              :       END DO
     757              : 
     758           18 :       CALL get_VBM_CBM_bandgaps(bs_env%band_edges_scf, bs_env%eigenval_scf, bs_env)
     759              : 
     760           18 :       CALL cp_cfm_release(cfm_ks)
     761           18 :       CALL cp_cfm_release(cfm_s)
     762           18 :       CALL cp_cfm_release(cfm_mos)
     763              : 
     764           18 :       CALL timestop(handle)
     765              : 
     766           36 :    END SUBROUTINE compute_cfm_mo_coeff_kp_and_eigenval_scf_kp
     767              : 
     768              : ! **************************************************************************************************
     769              : !> \brief ...
     770              : !> \param mat_rs ...
     771              : !> \param ispin ...
     772              : !> \param xkp ...
     773              : !> \param cell_to_index_scf ...
     774              : !> \param sab_nl ...
     775              : !> \param bs_env ...
     776              : !> \param cfm_kp ...
     777              : !> \param imag_rs_mat ...
     778              : ! **************************************************************************************************
     779         1976 :    SUBROUTINE rsmat_to_kp(mat_rs, ispin, xkp, cell_to_index_scf, sab_nl, bs_env, cfm_kp, imag_rs_mat)
     780              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_rs
     781              :       INTEGER                                            :: ispin
     782              :       REAL(KIND=dp), DIMENSION(3)                        :: xkp
     783              :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index_scf
     784              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     785              :          POINTER                                         :: sab_nl
     786              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     787              :       TYPE(cp_cfm_type)                                  :: cfm_kp
     788              :       LOGICAL, OPTIONAL                                  :: imag_rs_mat
     789              : 
     790              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'rsmat_to_kp'
     791              : 
     792              :       INTEGER                                            :: handle
     793              :       LOGICAL                                            :: imag_rs_mat_private
     794              :       TYPE(dbcsr_type), POINTER                          :: cmat, nsmat, rmat
     795              : 
     796         1976 :       CALL timeset(routineN, handle)
     797              : 
     798         1976 :       ALLOCATE (rmat, cmat, nsmat)
     799              : 
     800         1976 :       imag_rs_mat_private = .FALSE.
     801         1976 :       IF (PRESENT(imag_rs_mat)) imag_rs_mat_private = imag_rs_mat
     802              : 
     803          954 :       IF (imag_rs_mat_private) THEN
     804          954 :          CALL dbcsr_create(rmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_antisymmetric)
     805          954 :          CALL dbcsr_create(cmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_symmetric)
     806              :       ELSE
     807         1022 :          CALL dbcsr_create(rmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_symmetric)
     808         1022 :          CALL dbcsr_create(cmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_antisymmetric)
     809              :       END IF
     810         1976 :       CALL dbcsr_create(nsmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_no_symmetry)
     811         1976 :       CALL cp_dbcsr_alloc_block_from_nbl(rmat, sab_nl)
     812         1976 :       CALL cp_dbcsr_alloc_block_from_nbl(cmat, sab_nl)
     813              : 
     814         1976 :       CALL dbcsr_set(rmat, 0.0_dp)
     815         1976 :       CALL dbcsr_set(cmat, 0.0_dp)
     816              :       CALL rskp_transform(rmatrix=rmat, cmatrix=cmat, rsmat=mat_rs, ispin=ispin, &
     817         1976 :                           xkp=xkp, cell_to_index=cell_to_index_scf, sab_nl=sab_nl)
     818              : 
     819         1976 :       CALL dbcsr_desymmetrize(rmat, nsmat)
     820         1976 :       CALL copy_dbcsr_to_fm(nsmat, bs_env%fm_work_mo(1))
     821         1976 :       CALL dbcsr_desymmetrize(cmat, nsmat)
     822         1976 :       CALL copy_dbcsr_to_fm(nsmat, bs_env%fm_work_mo(2))
     823         1976 :       CALL cp_fm_to_cfm(bs_env%fm_work_mo(1), bs_env%fm_work_mo(2), cfm_kp)
     824              : 
     825         1976 :       CALL dbcsr_deallocate_matrix(rmat)
     826         1976 :       CALL dbcsr_deallocate_matrix(cmat)
     827         1976 :       CALL dbcsr_deallocate_matrix(nsmat)
     828              : 
     829         1976 :       CALL timestop(handle)
     830              : 
     831         1976 :    END SUBROUTINE rsmat_to_kp
     832              : 
     833              : ! **************************************************************************************************
     834              : !> \brief ...
     835              : !> \param bs_env ...
     836              : ! **************************************************************************************************
     837          106 :    SUBROUTINE diagonalize_ks_matrix(bs_env)
     838              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     839              : 
     840              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'diagonalize_ks_matrix'
     841              : 
     842              :       INTEGER                                            :: handle, ikp, ispin, nmo_retained
     843              :       REAL(KIND=dp)                                      :: CBM, VBM
     844              : 
     845          106 :       CALL timeset(routineN, handle)
     846              : 
     847          424 :       ALLOCATE (bs_env%eigenval_scf_Gamma(bs_env%n_ao, bs_env%n_spin))
     848              : 
     849          228 :       DO ispin = 1, bs_env%n_spin
     850              : 
     851              :          ! use work matrices because the matrices are overwritten in cp_fm_geeig_canon
     852          122 :          CALL cp_fm_to_fm(bs_env%fm_ks_Gamma(ispin), bs_env%fm_work_mo(1))
     853          122 :          CALL cp_fm_to_fm(bs_env%fm_s_Gamma, bs_env%fm_work_mo(2))
     854              : 
     855              :          ! diagonalize the Kohn-Sham matrix to obtain MO coefficients and SCF eigenvalues
     856              :          ! (at the Gamma-point)
     857              :          CALL cp_fm_geeig_canon(bs_env%fm_work_mo(1), &
     858              :                                 bs_env%fm_work_mo(2), &
     859              :                                 bs_env%fm_mo_coeff_Gamma(ispin), &
     860              :                                 bs_env%eigenval_scf_Gamma(:, ispin), &
     861              :                                 bs_env%fm_work_mo(3), &
     862              :                                 bs_env%eps_eigval_mat_s, &
     863          122 :                                 nmo_retained=nmo_retained)
     864          122 :          bs_env%n_mo_retained = MIN(bs_env%n_mo_retained, nmo_retained)
     865              : 
     866          122 :          VBM = bs_env%eigenval_scf_Gamma(bs_env%n_occ(ispin), ispin)
     867          122 :          CBM = bs_env%eigenval_scf_Gamma(bs_env%n_occ(ispin) + 1, ispin)
     868              : 
     869          122 :          bs_env%band_edges_scf_Gamma(ispin)%VBM = VBM
     870          122 :          bs_env%band_edges_scf_Gamma(ispin)%CBM = CBM
     871          228 :          bs_env%e_fermi(ispin) = 0.5_dp*(VBM + CBM)
     872              : 
     873              :       END DO
     874              : 
     875          106 :       CALL timestop(handle)
     876              : 
     877              :       ! Gamma-only path for molecules: eigenval_scf is filled here from the Gamma eigenvalues
     878          228 :       DO ispin = 1, bs_env%n_spin
     879          362 :          DO ikp = 1, bs_env%nkp_bs_and_DOS
     880         1642 :             bs_env%eigenval_scf(:, ikp, ispin) = bs_env%eigenval_scf_Gamma(:, ispin)
     881              :          END DO
     882              :       END DO
     883              : 
     884          106 :    END SUBROUTINE diagonalize_ks_matrix
     885              : 
     886              : ! **************************************************************************************************
     887              : !> \brief ...
     888              : !> \param bs_env ...
     889              : !> \param qs_env ...
     890              : ! **************************************************************************************************
     891          106 :    SUBROUTINE check_positive_definite_overlap_mat(bs_env, qs_env)
     892              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     893              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     894              : 
     895              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'check_positive_definite_overlap_mat'
     896              : 
     897              :       INTEGER                                            :: handle, ikp, info, u
     898              :       TYPE(cp_cfm_type)                                  :: cfm_s_ikp
     899              : 
     900          106 :       CALL timeset(routineN, handle)
     901              : 
     902          220 :       DO ikp = 1, bs_env%kpoints_DOS%nkp
     903              : 
     904              :          ! get S_µν(k_i) from S_µν(k=0)
     905              :          CALL cfm_ikp_from_fm_Gamma(cfm_s_ikp, bs_env%fm_s_Gamma, &
     906          114 :                                     ikp, qs_env, bs_env%kpoints_DOS, "ORB")
     907              : 
     908              :          ! check whether S_µν(k_i) is positive definite
     909          114 :          CALL cp_cfm_cholesky_decompose(matrix=cfm_s_ikp, n=bs_env%n_ao, info_out=info)
     910              : 
     911              :          ! check if Cholesky decomposition failed (Cholesky decomposition only works for
     912              :          ! positive definite matrices
     913          220 :          IF (info /= 0) THEN
     914            0 :             u = bs_env%unit_nr
     915              : 
     916            0 :             IF (u > 0) THEN
     917            0 :                WRITE (u, FMT="(T2,A)") ""
     918              :                WRITE (u, FMT="(T2,A)") "ERROR: The Cholesky decomposition "// &
     919            0 :                   "of the k-point overlap matrix failed. This is"
     920              :                WRITE (u, FMT="(T2,A)") "because the algorithm is "// &
     921            0 :                   "only correct in the limit of large cells. The cell of "
     922              :                WRITE (u, FMT="(T2,A)") "the calculation is too small. "// &
     923            0 :                   "Use MULTIPLE_UNIT_CELL to create a larger cell "
     924            0 :                WRITE (u, FMT="(T2,A)") "and to prevent this error."
     925              :             END IF
     926              : 
     927            0 :             CALL bs_env%para_env%sync()
     928            0 :             CPABORT("Please see information on the error above.")
     929              : 
     930              :          END IF ! Cholesky decomposition failed
     931              : 
     932              :       END DO ! ikp
     933              : 
     934          106 :       CALL cp_cfm_release(cfm_s_ikp)
     935              : 
     936          106 :       CALL timestop(handle)
     937              : 
     938          106 :    END SUBROUTINE check_positive_definite_overlap_mat
     939              : 
     940              : ! **************************************************************************************************
     941              : !> \brief ...
     942              : !> \param qs_env ...
     943              : !> \param bs_env ...
     944              : ! **************************************************************************************************
     945          248 :    SUBROUTINE get_parameters_from_qs_env(qs_env, bs_env)
     946              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     947              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     948              : 
     949              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'get_parameters_from_qs_env'
     950              : 
     951              :       INTEGER                                            :: color_sub, handle, homo, n_ao, n_atom, u
     952              :       INTEGER, DIMENSION(3)                              :: periodic
     953              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: hmat
     954              :       TYPE(cell_type), POINTER                           :: cell
     955              :       TYPE(dft_control_type), POINTER                    :: dft_control
     956          124 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     957              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     958          124 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     959              :       TYPE(scf_control_type), POINTER                    :: scf_control
     960              :       TYPE(section_vals_type), POINTER                   :: input
     961              : 
     962          124 :       CALL timeset(routineN, handle)
     963              : 
     964              :       CALL get_qs_env(qs_env, &
     965              :                       dft_control=dft_control, &
     966              :                       scf_control=scf_control, &
     967          124 :                       mos=mos)
     968              : 
     969          124 :       bs_env%n_spin = dft_control%nspins
     970          124 :       IF (bs_env%n_spin == 1) bs_env%spin_degeneracy = 2.0_dp
     971          124 :       IF (bs_env%n_spin == 2) bs_env%spin_degeneracy = 1.0_dp
     972              : 
     973          124 :       CALL get_mo_set(mo_set=mos(1), nao=n_ao, homo=homo)
     974          124 :       bs_env%n_ao = n_ao
     975              :       ! lowered by the diagonalization below if the canonical orthogonalization removes modes
     976          124 :       bs_env%n_mo_retained = n_ao
     977          372 :       bs_env%n_occ(1:2) = homo
     978          372 :       bs_env%n_vir(1:2) = n_ao - homo
     979              : 
     980          124 :       IF (bs_env%n_spin == 2) THEN
     981           16 :          CALL get_mo_set(mo_set=mos(2), homo=homo)
     982           16 :          bs_env%n_occ(2) = homo
     983           16 :          bs_env%n_vir(2) = n_ao - homo
     984              :       END IF
     985              : 
     986          124 :       bs_env%eps_eigval_mat_s = scf_control%eps_eigval
     987              : 
     988              :       ! get para_env from qs_env (bs_env%para_env is identical to para_env in qs_env)
     989          124 :       CALL get_qs_env(qs_env, para_env=para_env)
     990          124 :       color_sub = 0
     991          124 :       ALLOCATE (bs_env%para_env)
     992          124 :       CALL bs_env%para_env%from_split(para_env, color_sub)
     993              : 
     994          124 :       CALL get_qs_env(qs_env, particle_set=particle_set)
     995              : 
     996          124 :       n_atom = SIZE(particle_set)
     997          124 :       bs_env%n_atom = n_atom
     998              : 
     999          124 :       CALL get_qs_env(qs_env=qs_env, cell=cell)
    1000          124 :       CALL get_cell(cell=cell, periodic=periodic, h=hmat)
    1001          496 :       bs_env%periodic(1:3) = periodic(1:3)
    1002          432 :       bs_env%do_periodic = ANY(bs_env%periodic /= 0)
    1003         1612 :       bs_env%hmat(1:3, 1:3) = hmat
    1004          124 :       bs_env%nimages_scf = dft_control%nimages
    1005          124 :       IF (dft_control%nimages == 1) THEN
    1006          106 :          IF (bs_env%do_gw_ri_rs) THEN
    1007           38 :             IF (bs_env%do_periodic) THEN
    1008            0 :                bs_env%small_cell_full_kp_or_large_cell_Gamma = large_cell_Gamma_ri_rs
    1009              :             ELSE
    1010           38 :                bs_env%small_cell_full_kp_or_large_cell_Gamma = non_periodic_ri_rs
    1011              :             END IF
    1012              :          ELSE
    1013           68 :             bs_env%small_cell_full_kp_or_large_cell_Gamma = large_cell_Gamma
    1014              :          END IF
    1015           18 :       ELSE IF (dft_control%nimages > 1) THEN
    1016           18 :          IF (bs_env%do_gw_ri_rs) THEN
    1017            0 :             CPABORT("RI-RS Not Implemented for K-point Calculations")
    1018              :          ELSE
    1019           18 :             bs_env%small_cell_full_kp_or_large_cell_Gamma = small_cell_full_kp
    1020              :          END IF
    1021              :       ELSE
    1022            0 :          CPABORT("Wrong number of cells from DFT calculation.")
    1023              :       END IF
    1024              : 
    1025          124 :       u = bs_env%unit_nr
    1026              : 
    1027              :       ! Marek : Get and save the rtp method
    1028          124 :       CALL get_qs_env(qs_env=qs_env, input=input)
    1029          124 :       CALL section_vals_val_get(input, "DFT%REAL_TIME_PROPAGATION%RTBSE%_SECTION_PARAMETERS_", i_val=bs_env%rtp_method)
    1030              : 
    1031          124 :       IF (u > 0) THEN
    1032           62 :          WRITE (u, FMT="(T2,2A,T73,I8)") "Number of occupied molecular orbitals (MOs) ", &
    1033          124 :             "= Number of occupied bands", homo
    1034           62 :          WRITE (u, FMT="(T2,2A,T73,I8)") "Number of unoccupied (= virtual) MOs ", &
    1035          124 :             "= Number of unoccupied bands", n_ao - homo
    1036           62 :          WRITE (u, FMT="(T2,A,T73,I8)") "Number of Gaussian basis functions for MOs", n_ao
    1037           62 :          IF (bs_env%small_cell_full_kp_or_large_cell_Gamma == small_cell_full_kp) THEN
    1038            9 :             WRITE (u, FMT="(T2,2A,T73,I8)") "Number of cells considered in the DFT ", &
    1039           18 :                "calculation", bs_env%nimages_scf
    1040              :          END IF
    1041              :       END IF
    1042              : 
    1043          124 :       CALL timestop(handle)
    1044              : 
    1045          124 :    END SUBROUTINE get_parameters_from_qs_env
    1046              : 
    1047              : ! **************************************************************************************************
    1048              : !> \brief ...
    1049              : !> \param bs_env ...
    1050              : ! **************************************************************************************************
    1051          124 :    SUBROUTINE set_heuristic_parameters(bs_env)
    1052              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1053              : 
    1054              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'set_heuristic_parameters'
    1055              : 
    1056              :       INTEGER                                            :: handle
    1057              : 
    1058          124 :       CALL timeset(routineN, handle)
    1059              : 
    1060          124 :       bs_env%n_bins_max_for_printing = 5000
    1061              : 
    1062          124 :       CALL timestop(handle)
    1063              : 
    1064          124 :    END SUBROUTINE set_heuristic_parameters
    1065              : 
    1066              : ! **************************************************************************************************
    1067              : !> \brief ...
    1068              : !> \param qs_env ...
    1069              : !> \param bs_env ...
    1070              : ! **************************************************************************************************
    1071          124 :    SUBROUTINE allocate_and_fill_fm_ks_fm_s(qs_env, bs_env)
    1072              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1073              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1074              : 
    1075              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'allocate_and_fill_fm_ks_fm_s'
    1076              : 
    1077              :       INTEGER                                            :: handle, i_work, ispin
    1078              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1079              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    1080          124 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks, matrix_s
    1081              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1082              : 
    1083          124 :       CALL timeset(routineN, handle)
    1084              : 
    1085              :       CALL get_qs_env(qs_env, &
    1086              :                       para_env=para_env, &
    1087              :                       blacs_env=blacs_env, &
    1088              :                       matrix_ks_kp=matrix_ks, &
    1089          124 :                       matrix_s_kp=matrix_s)
    1090              : 
    1091          124 :       NULLIFY (fm_struct)
    1092              :       CALL cp_fm_struct_create(fm_struct, context=blacs_env, nrow_global=bs_env%n_ao, &
    1093          124 :                                ncol_global=bs_env%n_ao, para_env=para_env)
    1094              : 
    1095          620 :       DO i_work = 1, SIZE(bs_env%fm_work_mo)
    1096          620 :          CALL cp_fm_create(bs_env%fm_work_mo(i_work), fm_struct)
    1097              :       END DO
    1098              : 
    1099          124 :       CALL cp_cfm_create(bs_env%cfm_work_mo, fm_struct)
    1100          124 :       CALL cp_cfm_create(bs_env%cfm_work_mo_2, fm_struct)
    1101              : 
    1102          124 :       CALL cp_fm_create(bs_env%fm_s_Gamma, fm_struct)
    1103          124 :       CALL copy_dbcsr_to_fm(matrix_s(1, 1)%matrix, bs_env%fm_s_Gamma)
    1104              : 
    1105          264 :       DO ispin = 1, bs_env%n_spin
    1106          140 :          CALL cp_fm_create(bs_env%fm_ks_Gamma(ispin), fm_struct)
    1107          140 :          CALL copy_dbcsr_to_fm(matrix_ks(ispin, 1)%matrix, bs_env%fm_ks_Gamma(ispin))
    1108          264 :          CALL cp_fm_create(bs_env%fm_mo_coeff_Gamma(ispin), fm_struct)
    1109              :       END DO
    1110              : 
    1111          124 :       CALL cp_fm_struct_release(fm_struct)
    1112              : 
    1113          124 :       NULLIFY (bs_env%mat_ao_ao%matrix)
    1114          124 :       ALLOCATE (bs_env%mat_ao_ao%matrix)
    1115              :       CALL dbcsr_create(bs_env%mat_ao_ao%matrix, template=matrix_s(1, 1)%matrix, &
    1116          124 :                         matrix_type=dbcsr_type_no_symmetry)
    1117              : 
    1118          620 :       ALLOCATE (bs_env%eigenval_scf(bs_env%n_ao, bs_env%nkp_bs_and_DOS, bs_env%n_spin))
    1119              : 
    1120          124 :       CALL timestop(handle)
    1121              : 
    1122          124 :    END SUBROUTINE allocate_and_fill_fm_ks_fm_s
    1123              : 
    1124              : ! **************************************************************************************************
    1125              : !> \brief ...
    1126              : !> \param qs_env ...
    1127              : !> \param bs_env ...
    1128              : ! **************************************************************************************************
    1129          124 :    SUBROUTINE eval_bandstructure_properties(qs_env, bs_env)
    1130              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1131              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1132              : 
    1133              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'eval_bandstructure_properties'
    1134              : 
    1135              :       CHARACTER(LEN=default_string_length)               :: gw_label, gw_soc_label
    1136              :       INTEGER                                            :: handle, homo, homo_1, homo_2, &
    1137              :                                                             homo_spinor, ikp, ikp_for_file, ispin, &
    1138              :                                                             n_ao, n_E, nkind, nkp
    1139              :       LOGICAL                                            :: is_bandstruc_kpoint, print_DOS_kpoints, &
    1140              :                                                             print_ikp
    1141              :       REAL(KIND=dp)                                      :: broadening, E_max, E_max_G0W0, E_min, &
    1142              :                                                             E_min_G0W0, E_total_window, &
    1143              :                                                             energy_step_DOS, energy_window_DOS, t1
    1144          124 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: DOS_G0W0, DOS_G0W0_SOC, DOS_scf, DOS_scf_SOC, &
    1145          124 :          eigenval, eigenval_spinor, eigenval_spinor_G0W0, eigenval_spinor_no_SOC
    1146          124 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: PDOS_G0W0, PDOS_G0W0_SOC, PDOS_scf, &
    1147          124 :                                                             PDOS_scf_SOC, proj_mo_on_kind
    1148          124 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: LDOS_G0W0_2d, LDOS_scf_2d, &
    1149          124 :                                                             LDOS_scf_2d_SOC
    1150              :       TYPE(band_edges_type)                              :: band_edges_G0W0, band_edges_G0W0_SOC, &
    1151              :                                                             band_edges_scf, band_edges_scf_guess, &
    1152              :                                                             band_edges_scf_SOC
    1153              :       TYPE(cp_cfm_type) :: cfm_ks_ikp, cfm_ks_ikp_spinor, cfm_mos_ikp_spinor, cfm_s_ikp, &
    1154              :          cfm_s_ikp_copy, cfm_s_ikp_spinor, cfm_s_ikp_spinor_copy, cfm_SOC_ikp_spinor, &
    1155              :          cfm_spinor_wf_ikp, cfm_work_ikp, cfm_work_ikp_spinor
    1156          372 :       TYPE(cp_cfm_type), DIMENSION(2)                    :: cfm_mos_ikp
    1157              : 
    1158          124 :       CALL timeset(routineN, handle)
    1159              : 
    1160          124 :       n_ao = bs_env%n_ao
    1161              : 
    1162          124 :       energy_window_DOS = bs_env%energy_window_DOS
    1163          124 :       energy_step_DOS = bs_env%energy_step_DOS
    1164          124 :       broadening = bs_env%broadening_DOS
    1165              : 
    1166              :       ! if we have done GW or a full kpoint SCF, we already have the band edges
    1167          124 :       IF (bs_env%do_gw .OR. &
    1168              :           bs_env%small_cell_full_kp_or_large_cell_Gamma == small_cell_full_kp) THEN
    1169          124 :          band_edges_scf = bs_env%band_edges_scf
    1170          124 :          band_edges_scf_guess = band_edges_scf
    1171              :       ELSE
    1172              : 
    1173            0 :          IF (bs_env%n_spin == 1) THEN
    1174            0 :             homo = bs_env%n_occ(1)
    1175            0 :             band_edges_scf_guess%VBM = bs_env%eigenval_scf_Gamma(homo, 1)
    1176            0 :             band_edges_scf_guess%CBM = bs_env%eigenval_scf_Gamma(homo + 1, 1)
    1177              :          ELSE
    1178            0 :             homo_1 = bs_env%n_occ(1)
    1179            0 :             homo_2 = bs_env%n_occ(2)
    1180              :             band_edges_scf_guess%VBM = MAX(bs_env%eigenval_scf_Gamma(homo_1, 1), &
    1181            0 :                                            bs_env%eigenval_scf_Gamma(homo_2, 2))
    1182              :             band_edges_scf_guess%CBM = MIN(bs_env%eigenval_scf_Gamma(homo_1 + 1, 1), &
    1183            0 :                                            bs_env%eigenval_scf_Gamma(homo_2 + 1, 2))
    1184              :          END IF
    1185              : 
    1186              :          ! initialization
    1187            0 :          band_edges_scf%VBM = -1000.0_dp
    1188            0 :          band_edges_scf%CBM = 1000.0_dp
    1189            0 :          band_edges_scf%DBG = 1000.0_dp
    1190              :       END IF
    1191              : 
    1192          124 :       E_min = band_edges_scf_guess%VBM - 0.5_dp*energy_window_DOS
    1193          124 :       E_max = band_edges_scf_guess%CBM + 0.5_dp*energy_window_DOS
    1194              : 
    1195          124 :       IF (bs_env%do_gw) THEN
    1196          122 :          band_edges_G0W0 = bs_env%band_edges_GW
    1197          122 :          E_min_G0W0 = band_edges_G0W0%VBM - 0.5_dp*energy_window_DOS
    1198          122 :          E_max_G0W0 = band_edges_G0W0%CBM + 0.5_dp*energy_window_DOS
    1199          122 :          E_min = MIN(E_min, E_min_G0W0)
    1200          122 :          E_max = MAX(E_max, E_max_G0W0)
    1201              :       END IF
    1202              : 
    1203          124 :       E_total_window = E_max - E_min
    1204              : 
    1205          124 :       n_E = INT(E_total_window/energy_step_DOS)
    1206              : 
    1207          124 :       CALL get_qs_env(qs_env, nkind=nkind)
    1208              : 
    1209          496 :       ALLOCATE (proj_mo_on_kind(n_ao, nkind))
    1210          124 :       proj_mo_on_kind(:, :) = 0.0_dp
    1211              : 
    1212          372 :       ALLOCATE (eigenval(n_ao))
    1213          372 :       ALLOCATE (eigenval_spinor(2*n_ao))
    1214          248 :       ALLOCATE (eigenval_spinor_no_SOC(2*n_ao))
    1215          248 :       ALLOCATE (eigenval_spinor_G0W0(2*n_ao))
    1216              : 
    1217          124 :       IF (bs_env%do_dos_pdos) THEN
    1218              : 
    1219           60 :          ALLOCATE (DOS_scf(n_E))
    1220           20 :          DOS_scf(:) = 0.0_dp
    1221           80 :          ALLOCATE (PDOS_scf(n_E, nkind))
    1222           20 :          PDOS_scf(:, :) = 0.0_dp
    1223              : 
    1224           20 :          IF (bs_env%do_soc) THEN
    1225              : 
    1226           32 :             ALLOCATE (DOS_scf_SOC(n_E))
    1227           16 :             DOS_scf_SOC(:) = 0.0_dp
    1228           48 :             ALLOCATE (PDOS_scf_SOC(n_E, nkind))
    1229           16 :             PDOS_scf_SOC(:, :) = 0.0_dp
    1230              : 
    1231              :          END IF
    1232              : 
    1233           20 :          IF (bs_env%do_gw) THEN
    1234              : 
    1235           40 :             ALLOCATE (DOS_G0W0(n_E))
    1236           20 :             DOS_G0W0(:) = 0.0_dp
    1237           60 :             ALLOCATE (PDOS_G0W0(n_E, nkind))
    1238           20 :             PDOS_G0W0(:, :) = 0.0_dp
    1239              : 
    1240           20 :             IF (bs_env%do_soc) THEN
    1241              : 
    1242           32 :                ALLOCATE (DOS_G0W0_SOC(n_E))
    1243           16 :                DOS_G0W0_SOC(:) = 0.0_dp
    1244           48 :                ALLOCATE (PDOS_G0W0_SOC(n_E, nkind))
    1245           16 :                PDOS_G0W0_SOC(:, :) = 0.0_dp
    1246              : 
    1247              :             END IF
    1248              :          END IF
    1249              :       END IF
    1250              : 
    1251          124 :       CALL cp_cfm_create(cfm_mos_ikp(1), bs_env%fm_ks_Gamma(1)%matrix_struct)
    1252          124 :       CALL cp_cfm_create(cfm_mos_ikp(2), bs_env%fm_ks_Gamma(1)%matrix_struct)
    1253          124 :       CALL cp_cfm_create(cfm_work_ikp, bs_env%fm_ks_Gamma(1)%matrix_struct)
    1254          124 :       CALL cp_cfm_create(cfm_s_ikp_copy, bs_env%fm_ks_Gamma(1)%matrix_struct)
    1255              : 
    1256          124 :       IF (bs_env%do_soc) THEN
    1257              : 
    1258           22 :          CALL cp_cfm_create(cfm_mos_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
    1259           22 :          CALL cp_cfm_create(cfm_work_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
    1260           22 :          CALL cp_cfm_create(cfm_s_ikp_spinor_copy, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
    1261           22 :          CALL cp_cfm_create(cfm_ks_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
    1262           22 :          CALL cp_cfm_create(cfm_SOC_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
    1263           22 :          CALL cp_cfm_create(cfm_s_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
    1264           22 :          CALL cp_cfm_create(cfm_spinor_wf_ikp, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
    1265              : 
    1266           22 :          homo_spinor = bs_env%n_occ(1) + bs_env%n_occ(bs_env%n_spin)
    1267              : 
    1268           22 :          band_edges_scf_SOC%VBM = -1000.0_dp
    1269           22 :          band_edges_scf_SOC%CBM = 1000.0_dp
    1270           22 :          band_edges_scf_SOC%DBG = 1000.0_dp
    1271              : 
    1272           22 :          IF (bs_env%do_gw) THEN
    1273           22 :             band_edges_G0W0_SOC%VBM = -1000.0_dp
    1274           22 :             band_edges_G0W0_SOC%CBM = 1000.0_dp
    1275           22 :             band_edges_G0W0_SOC%DBG = 1000.0_dp
    1276              :          END IF
    1277              : 
    1278           22 :          IF (bs_env%unit_nr > 0) THEN
    1279           11 :             WRITE (bs_env%unit_nr, '(A)') ''
    1280           11 :             IF (bs_env%soc_window_occ > 0.0_dp) THEN
    1281            3 :                WRITE (bs_env%unit_nr, '(T2,A,T71,F10.2)') 'SOC requested, SOC energy window occ (eV):', &
    1282            6 :                   bs_env%soc_window_occ*evolt
    1283              :             ELSE
    1284            8 :                WRITE (bs_env%unit_nr, '(T2,A,T71,A10)') 'SOC requested, SOC energy window occ (eV):', &
    1285           16 :                   ' no window'
    1286              :             END IF
    1287           11 :             IF (bs_env%soc_window_virt > 0.0_dp) THEN
    1288            3 :                WRITE (bs_env%unit_nr, '(T2,A,T71,F10.2)') 'SOC requested, SOC energy window virt (eV):', &
    1289            6 :                   bs_env%soc_window_virt*evolt
    1290              :             ELSE
    1291            8 :                WRITE (bs_env%unit_nr, '(T2,A,T71,A10)') 'SOC requested, SOC energy window virt (eV):', &
    1292           16 :                   ' no window'
    1293              :             END IF
    1294           11 :             IF (bs_env%soc_window_occ > 0.0_dp .OR. bs_env%soc_window_virt > 0.0_dp) THEN
    1295            4 :                WRITE (bs_env%unit_nr, '(T2,A,T71,F10.2)') 'SOC requested, SOC window smearing (eV):', &
    1296            8 :                   bs_env%soc_window_smearing*evolt
    1297              :             END IF
    1298              :          END IF
    1299              :       END IF
    1300              : 
    1301          124 :       IF (bs_env%do_ldos) THEN
    1302            2 :          CPASSERT(bs_env%int_ldos_xyz == int_ldos_z)
    1303              :       END IF
    1304              : 
    1305          124 :       IF (bs_env%small_cell_full_kp_or_large_cell_Gamma == small_cell_full_kp) THEN
    1306           18 :          CALL cp_cfm_create(cfm_ks_ikp, bs_env%cfm_ks_kp(1, 1)%matrix_struct)
    1307           18 :          CALL cp_cfm_create(cfm_s_ikp, bs_env%cfm_ks_kp(1, 1)%matrix_struct)
    1308              :       END IF
    1309              : 
    1310          590 :       DO ikp = 1, bs_env%nkp_bs_and_DOS
    1311              : 
    1312          466 :          t1 = m_walltime()
    1313              : 
    1314          952 :          DO ispin = 1, bs_env%n_spin
    1315              : 
    1316          620 :             SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
    1317              :             CASE (large_cell_Gamma, large_cell_Gamma_ri_rs, non_periodic_ri_rs)
    1318              : 
    1319              :                ! 1. get H^KS_µν(k_i) from H^KS_µν(k=0)
    1320              :                CALL cfm_ikp_from_fm_Gamma(cfm_ks_ikp, bs_env%fm_ks_Gamma(ispin), &
    1321          134 :                                           ikp, qs_env, bs_env%kpoints_DOS, "ORB")
    1322              : 
    1323              :                ! 2. get S_µν(k_i) from S_µν(k=0)
    1324              :                CALL cfm_ikp_from_fm_Gamma(cfm_s_ikp, bs_env%fm_s_Gamma, &
    1325          134 :                                           ikp, qs_env, bs_env%kpoints_DOS, "ORB")
    1326          134 :                CALL cp_cfm_to_cfm(cfm_s_ikp, cfm_s_ikp_copy)
    1327              : 
    1328              :                ! 3. Diagonalize (Roothaan-Hall): H_KS(k_i)*C(k_i) = S(k_i)*C(k_i)*ϵ(k_i)
    1329              :                CALL cp_cfm_geeig(cfm_ks_ikp, cfm_s_ikp_copy, cfm_mos_ikp(ispin), &
    1330          134 :                                  eigenval, cfm_work_ikp)
    1331              : 
    1332              :             CASE (small_cell_full_kp)
    1333              : 
    1334              :                ! 1. get H^KS_µν(k_i)
    1335          352 :                CALL cp_cfm_to_cfm(bs_env%cfm_ks_kp(ikp, ispin), cfm_ks_ikp)
    1336              : 
    1337              :                ! 2. get S_µν(k_i)
    1338          352 :                CALL cp_cfm_to_cfm(bs_env%cfm_s_kp(ikp), cfm_s_ikp)
    1339              : 
    1340              :                ! 3. get C_µn(k_i) and ϵ_n(k_i)
    1341          352 :                CALL cp_cfm_to_cfm(bs_env%cfm_mo_coeff_kp(ikp, ispin), cfm_mos_ikp(ispin))
    1342         5092 :                eigenval(:) = bs_env%eigenval_scf(:, ikp, ispin)
    1343              : 
    1344              :             END SELECT
    1345              : 
    1346              :             ! 4. Projection p_nk^A of MO ψ_nk(r) on atom type A (inspired by Mulliken charge)
    1347              :             !    p_nk^A = sum_µ^A,ν C*_µ^A,n(k) S_µ^A,ν(k) C_ν,n(k)
    1348          486 :             CALL compute_proj_mo_on_kind(proj_mo_on_kind, qs_env, cfm_mos_ikp(ispin), cfm_s_ikp)
    1349              : 
    1350              :             ! 5. DOS and PDOS
    1351          486 :             IF (bs_env%do_dos_pdos) THEN
    1352              :                CALL add_to_DOS_PDOS(DOS_scf, PDOS_scf, eigenval, ikp, bs_env, n_E, E_min, &
    1353          234 :                                     proj_mo_on_kind)
    1354              : 
    1355          234 :                IF (bs_env%do_gw) THEN
    1356              :                   CALL add_to_DOS_PDOS(DOS_G0W0, PDOS_G0W0, bs_env%eigenval_GW(:, ikp, ispin), &
    1357          234 :                                        ikp, bs_env, n_E, E_min, proj_mo_on_kind)
    1358              :                END IF
    1359              :             END IF
    1360              : 
    1361          486 :             IF (bs_env%do_ldos) THEN
    1362              :                CALL add_to_LDOS_2d(LDOS_scf_2d, qs_env, ikp, bs_env, cfm_mos_ikp(ispin), &
    1363            2 :                                    eigenval(:), band_edges_scf_guess)
    1364              : 
    1365            2 :                IF (bs_env%do_gw) THEN
    1366              :                   CALL add_to_LDOS_2d(LDOS_G0W0_2d, qs_env, ikp, bs_env, cfm_mos_ikp(ispin), &
    1367            2 :                                       bs_env%eigenval_GW(:, ikp, 1), band_edges_G0W0)
    1368              :                END IF
    1369              : 
    1370              :             END IF
    1371              : 
    1372          486 :             homo = bs_env%n_occ(ispin)
    1373              : 
    1374          486 :             band_edges_scf%VBM = MAX(band_edges_scf%VBM, eigenval(homo))
    1375          486 :             band_edges_scf%CBM = MIN(band_edges_scf%CBM, eigenval(homo + 1))
    1376          952 :             band_edges_scf%DBG = MIN(band_edges_scf%DBG, eigenval(homo + 1) - eigenval(homo))
    1377              : 
    1378              :          END DO ! spin
    1379              : 
    1380              :          ! now the same with spin-orbit coupling
    1381          466 :          IF (bs_env%do_soc) THEN
    1382              : 
    1383              :             ! only print eigenvalues of DOS k-points in case no bandstructure path has been given
    1384          328 :             print_DOS_kpoints = (bs_env%nkp_only_bs <= 0)
    1385              :             ! in kpoints_DOS, the last nkp_only_bs are bandstructure k-points
    1386          328 :             is_bandstruc_kpoint = (ikp > bs_env%nkp_only_DOS)
    1387          328 :             print_ikp = print_DOS_kpoints .OR. is_bandstruc_kpoint
    1388              : 
    1389          328 :             IF (print_DOS_kpoints) THEN
    1390          234 :                nkp = bs_env%nkp_only_DOS
    1391          234 :                ikp_for_file = ikp
    1392              :             ELSE
    1393           94 :                nkp = bs_env%nkp_only_bs
    1394           94 :                ikp_for_file = ikp - bs_env%nkp_only_DOS
    1395              :             END IF
    1396              : 
    1397              :             ! compute DFT+SOC eigenvalues; based on these, compute band edges, DOS and LDOS
    1398              :             CALL SOC_ev(bs_env, qs_env, ikp, bs_env%eigenval_scf, &
    1399              :                         E_min, cfm_mos_ikp, DOS_scf_SOC, PDOS_scf_SOC, &
    1400          328 :                         band_edges_scf_SOC, eigenval_spinor, cfm_spinor_wf_ikp)
    1401              : 
    1402          328 :             IF (.NOT. bs_env%do_gw .AND. print_ikp) THEN
    1403            0 :                CALL write_SOC_eigenvalues(eigenval_spinor, ikp_for_file, ikp, bs_env)
    1404              :             END IF
    1405              : 
    1406          328 :             IF (bs_env%do_ldos) THEN
    1407              :                CALL add_to_LDOS_2d(LDOS_scf_2d_SOC, qs_env, ikp, bs_env, cfm_spinor_wf_ikp, &
    1408            2 :                                    eigenval_spinor, band_edges_scf_guess, .TRUE., cfm_work_ikp)
    1409              :             END IF
    1410              : 
    1411          328 :             IF (bs_env%do_gw) THEN
    1412              : 
    1413              :                ! compute G0W0+SOC eigenvalues; based on these, compute band edges, DOS and LDOS
    1414              :                CALL SOC_ev(bs_env, qs_env, ikp, bs_env%eigenval_GW, &
    1415              :                            E_min, cfm_mos_ikp, DOS_G0W0_SOC, PDOS_G0W0_SOC, &
    1416          328 :                            band_edges_G0W0_SOC, eigenval_spinor_G0W0, cfm_spinor_wf_ikp)
    1417              : 
    1418          328 :                IF (print_ikp) THEN
    1419              :                   ! write SCF+SOC and G0W0+SOC eigenvalues to file
    1420              :                   ! SCF_and_G0W0_band_structure_for_kpoint_<ikp>_+_SOC
    1421              :                   CALL write_SOC_eigenvalues(eigenval_spinor, ikp_for_file, ikp, bs_env, &
    1422          296 :                                              eigenval_spinor_G0W0)
    1423              :                END IF
    1424              : 
    1425              :             END IF ! do_gw
    1426              : 
    1427              :          END IF ! do_soc
    1428              : 
    1429          590 :          IF (bs_env%unit_nr > 0 .AND. m_walltime() - t1 > 20.0_dp) THEN
    1430              :             WRITE (bs_env%unit_nr, '(T2,A,T43,I5,A,I3,A,F7.1,A)') &
    1431            0 :                'Compute DOS, LDOS for k-point ', ikp, ' /', bs_env%nkp_bs_and_DOS, &
    1432            0 :                ',    Execution time', m_walltime() - t1, ' s'
    1433              :          END IF
    1434              : 
    1435              :       END DO ! ikp_DOS
    1436              : 
    1437          124 :       band_edges_scf%IDBG = band_edges_scf%CBM - band_edges_scf%VBM
    1438          124 :       IF (bs_env%do_soc) THEN
    1439           22 :          band_edges_scf_SOC%IDBG = band_edges_scf_SOC%CBM - band_edges_scf_SOC%VBM
    1440           22 :          IF (bs_env%do_gw) THEN
    1441           22 :             band_edges_G0W0_SOC%IDBG = band_edges_G0W0_SOC%CBM - band_edges_G0W0_SOC%VBM
    1442              :          END IF
    1443              :       END IF
    1444              : 
    1445          124 :       CALL write_band_edges(band_edges_scf, "SCF", bs_env)
    1446          124 :       IF (bs_env%do_dos_pdos) THEN
    1447           20 :          CALL write_dos_pdos(DOS_scf, PDOS_scf, bs_env, qs_env, "SCF", E_min, band_edges_scf%VBM)
    1448              :       END IF
    1449          124 :       IF (bs_env%do_ldos) THEN
    1450            2 :          CALL print_LDOS_main(LDOS_scf_2d, bs_env, band_edges_scf, "SCF")
    1451              :       END IF
    1452              : 
    1453          124 :       IF (bs_env%do_soc) THEN
    1454           22 :          CALL write_band_edges(band_edges_scf_SOC, "SCF+SOC", bs_env)
    1455           22 :          IF (bs_env%do_dos_pdos) THEN
    1456              :             CALL write_dos_pdos(DOS_scf_SOC, PDOS_scf_SOC, bs_env, qs_env, "SCF_SOC", &
    1457           16 :                                 E_min, band_edges_scf_SOC%VBM)
    1458              :          END IF
    1459           22 :          IF (bs_env%do_ldos) THEN
    1460              :             ! argument band_edges_scf is actually correct because the non-SOC band edges
    1461              :             ! have been used as reference in add_to_LDOS_2d
    1462              :             CALL print_LDOS_main(LDOS_scf_2d_SOC, bs_env, band_edges_scf, &
    1463            2 :                                  "SCF_SOC")
    1464              :          END IF
    1465              :       END IF
    1466              : 
    1467              :       ! the printed band edges carry the GW flavour that was actually run; the labels handed to
    1468              :       ! write_dos_pdos / print_LDOS_main below become file names and stay as they are
    1469          124 :       gw_label = gw_flavour_label(bs_env)
    1470          124 :       gw_soc_label = TRIM(gw_label)//"+SOC"
    1471              : 
    1472          124 :       IF (bs_env%do_gw) THEN
    1473          122 :          CALL write_band_edges(band_edges_G0W0, TRIM(gw_label), bs_env)
    1474          122 :          CALL write_band_edges(bs_env%band_edges_HF, "Hartree-Fock with SCF orbitals", bs_env)
    1475          122 :          IF (bs_env%do_dos_pdos) THEN
    1476              :             CALL write_dos_pdos(DOS_G0W0, PDOS_G0W0, bs_env, qs_env, "G0W0", E_min, &
    1477           20 :                                 band_edges_G0W0%VBM)
    1478              :          END IF
    1479          122 :          IF (bs_env%do_ldos) THEN
    1480            2 :             CALL print_LDOS_main(LDOS_G0W0_2d, bs_env, band_edges_G0W0, "G0W0")
    1481              :          END IF
    1482              :       END IF
    1483              : 
    1484          124 :       IF (bs_env%do_soc .AND. bs_env%do_gw) THEN
    1485           22 :          CALL write_band_edges(band_edges_G0W0_SOC, TRIM(gw_soc_label), bs_env)
    1486           22 :          IF (bs_env%do_dos_pdos) THEN
    1487              :             CALL write_dos_pdos(DOS_G0W0_SOC, PDOS_G0W0_SOC, bs_env, qs_env, "G0W0_SOC", E_min, &
    1488           16 :                                 band_edges_G0W0_SOC%VBM)
    1489              :          END IF
    1490              :       END IF
    1491              : 
    1492          124 :       CALL cp_cfm_release(cfm_s_ikp)
    1493          124 :       CALL cp_cfm_release(cfm_ks_ikp)
    1494          124 :       CALL cp_cfm_release(cfm_mos_ikp(1))
    1495          124 :       CALL cp_cfm_release(cfm_mos_ikp(2))
    1496          124 :       CALL cp_cfm_release(cfm_work_ikp)
    1497          124 :       CALL cp_cfm_release(cfm_s_ikp_copy)
    1498              : 
    1499          124 :       CALL cp_cfm_release(cfm_s_ikp_spinor)
    1500          124 :       CALL cp_cfm_release(cfm_ks_ikp_spinor)
    1501          124 :       CALL cp_cfm_release(cfm_SOC_ikp_spinor)
    1502          124 :       CALL cp_cfm_release(cfm_mos_ikp_spinor)
    1503          124 :       CALL cp_cfm_release(cfm_work_ikp_spinor)
    1504          124 :       CALL cp_cfm_release(cfm_s_ikp_spinor_copy)
    1505          124 :       CALL cp_cfm_release(cfm_spinor_wf_ikp)
    1506              : 
    1507          124 :       CALL timestop(handle)
    1508              : 
    1509          496 :    END SUBROUTINE eval_bandstructure_properties
    1510              : 
    1511              : ! **************************************************************************************************
    1512              : !> \brief ...
    1513              : !> \param LDOS_2d ...
    1514              : !> \param bs_env ...
    1515              : !> \param band_edges ...
    1516              : !> \param scf_gw_soc ...
    1517              : ! **************************************************************************************************
    1518            6 :    SUBROUTINE print_LDOS_main(LDOS_2d, bs_env, band_edges, scf_gw_soc)
    1519              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: LDOS_2d
    1520              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1521              :       TYPE(band_edges_type)                              :: band_edges
    1522              :       CHARACTER(LEN=*)                                   :: scf_gw_soc
    1523              : 
    1524              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'print_LDOS_main'
    1525              : 
    1526              :       INTEGER :: handle, i_x, i_x_bin, i_x_end, i_x_end_bin, i_x_end_glob, i_x_start, &
    1527              :          i_x_start_bin, i_x_start_glob, i_y, i_y_bin, i_y_end, i_y_end_bin, i_y_end_glob, &
    1528              :          i_y_start, i_y_start_bin, i_y_start_glob, n_E
    1529            6 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: n_sum_for_bins
    1530              :       INTEGER, DIMENSION(2)                              :: bin_mesh
    1531              :       LOGICAL                                            :: do_xy_bins
    1532              :       REAL(KIND=dp)                                      :: E_min, energy_step, energy_window
    1533              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: LDOS_2d_bins
    1534              : 
    1535            6 :       CALL timeset(routineN, handle)
    1536              : 
    1537            6 :       n_E = SIZE(LDOS_2d, 3)
    1538              : 
    1539            6 :       energy_window = bs_env%energy_window_DOS
    1540            6 :       energy_step = bs_env%energy_step_DOS
    1541            6 :       E_min = band_edges%VBM - 0.5_dp*energy_window
    1542              : 
    1543           18 :       bin_mesh(1:2) = bs_env%bin_mesh(1:2)
    1544            6 :       do_xy_bins = (bin_mesh(1) > 0 .AND. bin_mesh(2) > 0)
    1545              : 
    1546            6 :       i_x_start = LBOUND(LDOS_2d, 1)
    1547            6 :       i_x_end = UBOUND(LDOS_2d, 1)
    1548            6 :       i_y_start = LBOUND(LDOS_2d, 2)
    1549            6 :       i_y_end = UBOUND(LDOS_2d, 2)
    1550              : 
    1551            6 :       IF (do_xy_bins) THEN
    1552            6 :          i_x_start_bin = 1
    1553            6 :          i_x_end_bin = bin_mesh(1)
    1554            6 :          i_y_start_bin = 1
    1555            6 :          i_y_end_bin = bin_mesh(2)
    1556              :       ELSE
    1557              :          i_x_start_bin = i_x_start
    1558              :          i_x_end_bin = i_x_end
    1559              :          i_y_start_bin = i_y_start
    1560              :          i_y_end_bin = i_y_end
    1561              :       END IF
    1562              : 
    1563           30 :       ALLOCATE (LDOS_2d_bins(i_x_start_bin:i_x_end_bin, i_y_start_bin:i_y_end_bin, n_E))
    1564            6 :       LDOS_2d_bins(:, :, :) = 0.0_dp
    1565              : 
    1566            6 :       IF (do_xy_bins) THEN
    1567              : 
    1568            6 :          i_x_start_glob = i_x_start
    1569            6 :          i_x_end_glob = i_x_end
    1570            6 :          i_y_start_glob = i_y_start
    1571            6 :          i_y_end_glob = i_y_end
    1572              : 
    1573            6 :          CALL bs_env%para_env%min(i_x_start_glob)
    1574            6 :          CALL bs_env%para_env%max(i_x_end_glob)
    1575            6 :          CALL bs_env%para_env%min(i_y_start_glob)
    1576            6 :          CALL bs_env%para_env%max(i_y_end_glob)
    1577              : 
    1578           24 :          ALLOCATE (n_sum_for_bins(bin_mesh(1), bin_mesh(2)), SOURCE=0)
    1579              : 
    1580              :          ! transform interval [i_x_start, i_x_end] to [1, bin_mesh(1)] (and same for y)
    1581          390 :          DO i_y = i_y_start, i_y_end
    1582         4230 :             DO i_x = i_x_start, i_x_end
    1583         3840 :                i_x_bin = bin_mesh(1)*(i_x - i_x_start_glob)/(i_x_end_glob - i_x_start_glob + 1) + 1
    1584         3840 :                i_y_bin = bin_mesh(2)*(i_y - i_y_start_glob)/(i_y_end_glob - i_y_start_glob + 1) + 1
    1585              :                LDOS_2d_bins(i_x_bin, i_y_bin, :) = LDOS_2d_bins(i_x_bin, i_y_bin, :) + &
    1586      1073920 :                                                    LDOS_2d(i_x, i_y, :)
    1587         4224 :                n_sum_for_bins(i_x_bin, i_y_bin) = n_sum_for_bins(i_x_bin, i_y_bin) + 1
    1588              :             END DO
    1589              :          END DO
    1590              : 
    1591            6 :          CALL bs_env%para_env%sum(LDOS_2d_bins)
    1592            6 :          CALL bs_env%para_env%sum(n_sum_for_bins)
    1593              : 
    1594              :          ! divide by number of terms in the sum so we have the average LDOS(x,y,E)
    1595           30 :          DO i_y_bin = 1, bin_mesh(2)
    1596          126 :             DO i_x_bin = 1, bin_mesh(1)
    1597              :                LDOS_2d_bins(i_x_bin, i_y_bin, :) = LDOS_2d_bins(i_x_bin, i_y_bin, :)/ &
    1598        26872 :                                                    REAL(n_sum_for_bins(i_x_bin, i_y_bin), KIND=dp)
    1599              :             END DO
    1600              :          END DO
    1601              : 
    1602              :       ELSE
    1603              : 
    1604            0 :          LDOS_2d_bins(:, :, :) = LDOS_2d(:, :, :)
    1605              : 
    1606              :       END IF
    1607              : 
    1608            6 :       IF (bin_mesh(1)*bin_mesh(2) < bs_env%n_bins_max_for_printing) THEN
    1609            6 :          CALL print_LDOS_2d_bins(LDOS_2d_bins, bs_env, E_min, scf_gw_soc)
    1610              :       ELSE
    1611            0 :          CPWARN("The number of bins for the LDOS is too large. Decrease BIN_MESH.")
    1612              :       END IF
    1613              : 
    1614            6 :       CALL timestop(handle)
    1615              : 
    1616           12 :    END SUBROUTINE print_LDOS_main
    1617              : 
    1618              : ! **************************************************************************************************
    1619              : !> \brief ...
    1620              : !> \param LDOS_2d_bins ...
    1621              : !> \param bs_env ...
    1622              : !> \param E_min ...
    1623              : !> \param scf_gw_soc ...
    1624              : ! **************************************************************************************************
    1625            6 :    SUBROUTINE print_LDOS_2d_bins(LDOS_2d_bins, bs_env, E_min, scf_gw_soc)
    1626              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: LDOS_2d_bins
    1627              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1628              :       REAL(KIND=dp)                                      :: E_min
    1629              :       CHARACTER(LEN=*)                                   :: scf_gw_soc
    1630              : 
    1631              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'print_LDOS_2d_bins'
    1632              : 
    1633              :       CHARACTER(LEN=18)                                  :: print_format
    1634              :       CHARACTER(LEN=4)                                   :: print_format_1, print_format_2
    1635              :       CHARACTER(len=default_string_length)               :: fname
    1636              :       INTEGER                                            :: handle, i_E, i_x, i_x_end, i_x_start, &
    1637              :                                                             i_y, i_y_end, i_y_start, iunit, n_E, &
    1638              :                                                             n_x, n_y
    1639              :       REAL(KIND=dp)                                      :: energy
    1640              :       REAL(KIND=dp), DIMENSION(3)                        :: coord, idx
    1641              : 
    1642            6 :       CALL timeset(routineN, handle)
    1643              : 
    1644            6 :       i_x_start = LBOUND(LDOS_2d_bins, 1)
    1645            6 :       i_x_end = UBOUND(LDOS_2d_bins, 1)
    1646            6 :       i_y_start = LBOUND(LDOS_2d_bins, 2)
    1647            6 :       i_y_end = UBOUND(LDOS_2d_bins, 2)
    1648            6 :       n_E = SIZE(LDOS_2d_bins, 3)
    1649              : 
    1650            6 :       n_x = i_x_end - i_x_start + 1
    1651            6 :       n_y = i_y_end - i_y_start + 1
    1652              : 
    1653            6 :       IF (bs_env%para_env%is_source()) THEN
    1654              : 
    1655           15 :          DO i_y = i_y_start, i_y_end
    1656           63 :             DO i_x = i_x_start, i_x_end
    1657              : 
    1658           48 :                idx(1) = (REAL(i_x, KIND=dp) - 0.5_dp)/REAL(n_x, KIND=dp)
    1659           48 :                idx(2) = (REAL(i_y, KIND=dp) - 0.5_dp)/REAL(n_y, KIND=dp)
    1660           48 :                idx(3) = 0.0_dp
    1661          624 :                coord(1:3) = MATMUL(bs_env%hmat, idx)
    1662              : 
    1663           48 :                CALL get_print_format(coord(1), print_format_1)
    1664           48 :                CALL get_print_format(coord(2), print_format_2)
    1665              : 
    1666           48 :                print_format = "(3A,"//print_format_1//",A,"//print_format_2//",A)"
    1667              : 
    1668           48 :                WRITE (fname, print_format) "LDOS_", scf_gw_soc, &
    1669           96 :                   "_at_x_", coord(1)*angstrom, '_A_and_y_', coord(2)*angstrom, '_A'
    1670              : 
    1671              :                CALL open_file(TRIM(fname), unit_number=iunit, file_status="REPLACE", &
    1672           48 :                               file_action="WRITE")
    1673              : 
    1674           48 :                WRITE (iunit, "(2A)") "        Energy E (eV)    average LDOS(x,y,E) (1/(eV*Å^2), ", &
    1675           96 :                   "integrated over z, averaged inside bin)"
    1676              : 
    1677        13424 :                DO i_E = 1, n_E
    1678        13376 :                   energy = E_min + i_E*bs_env%energy_step_DOS
    1679        13376 :                   WRITE (iunit, "(2F17.3)") energy*evolt, &
    1680              :                      LDOS_2d_bins(i_x, i_y, i_E)* &
    1681        26800 :                      bs_env%unit_ldos_int_z_inv_Ang2_eV
    1682              :                END DO
    1683              : 
    1684           60 :                CALL close_file(iunit)
    1685              : 
    1686              :             END DO
    1687              :          END DO
    1688              : 
    1689              :       END IF
    1690              : 
    1691            6 :       CALL timestop(handle)
    1692              : 
    1693            6 :    END SUBROUTINE print_LDOS_2d_bins
    1694              : 
    1695              : ! **************************************************************************************************
    1696              : !> \brief ...
    1697              : !> \param coord ...
    1698              : !> \param print_format ...
    1699              : ! **************************************************************************************************
    1700           96 :    SUBROUTINE get_print_format(coord, print_format)
    1701              :       REAL(KIND=dp)                                      :: coord
    1702              :       CHARACTER(LEN=4)                                   :: print_format
    1703              : 
    1704              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'get_print_format'
    1705              : 
    1706              :       INTEGER                                            :: handle
    1707              : 
    1708           96 :       CALL timeset(routineN, handle)
    1709              : 
    1710           96 :       IF (coord < -10000/angstrom) THEN
    1711            0 :          print_format = "F9.2"
    1712           96 :       ELSE IF (coord < -1000/angstrom) THEN
    1713            0 :          print_format = "F8.2"
    1714           96 :       ELSE IF (coord < -100/angstrom) THEN
    1715            0 :          print_format = "F7.2"
    1716           96 :       ELSE IF (coord < -10/angstrom) THEN
    1717            0 :          print_format = "F6.2"
    1718           96 :       ELSE IF (coord < -1/angstrom) THEN
    1719            0 :          print_format = "F5.2"
    1720           96 :       ELSE IF (coord < 10/angstrom) THEN
    1721           96 :          print_format = "F4.2"
    1722            0 :       ELSE IF (coord < 100/angstrom) THEN
    1723            0 :          print_format = "F5.2"
    1724            0 :       ELSE IF (coord < 1000/angstrom) THEN
    1725            0 :          print_format = "F6.2"
    1726            0 :       ELSE IF (coord < 10000/angstrom) THEN
    1727            0 :          print_format = "F7.2"
    1728              :       ELSE
    1729            0 :          print_format = "F8.2"
    1730              :       END IF
    1731              : 
    1732           96 :       CALL timestop(handle)
    1733              : 
    1734           96 :    END SUBROUTINE get_print_format
    1735              : 
    1736              : ! **************************************************************************************************
    1737              : !> \brief ...
    1738              : !> \param bs_env ...
    1739              : !> \param qs_env ...
    1740              : !> \param ikp ...
    1741              : !> \param eigenval_no_SOC ...
    1742              : !> \param E_min ...
    1743              : !> \param cfm_mos_ikp ...
    1744              : !> \param DOS ...
    1745              : !> \param PDOS ...
    1746              : !> \param band_edges ...
    1747              : !> \param eigenval_spinor ...
    1748              : !> \param cfm_spinor_wf_ikp ...
    1749              : ! **************************************************************************************************
    1750          656 :    SUBROUTINE SOC_ev(bs_env, qs_env, ikp, eigenval_no_SOC, E_min, cfm_mos_ikp, &
    1751              :                      DOS, PDOS, band_edges, eigenval_spinor, cfm_spinor_wf_ikp)
    1752              : 
    1753              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1754              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1755              :       INTEGER                                            :: ikp
    1756              :       REAL(KIND=dp), DIMENSION(:, :, :)                  :: eigenval_no_SOC
    1757              :       REAL(KIND=dp)                                      :: E_min
    1758              :       TYPE(cp_cfm_type), DIMENSION(2)                    :: cfm_mos_ikp
    1759              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: DOS
    1760              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: PDOS
    1761              :       TYPE(band_edges_type)                              :: band_edges
    1762              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigenval_spinor
    1763              :       TYPE(cp_cfm_type)                                  :: cfm_spinor_wf_ikp
    1764              : 
    1765              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'SOC_ev'
    1766              : 
    1767              :       INTEGER                                            :: handle, homo_spinor, n_ao, n_E, nkind
    1768              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigenval_spinor_no_SOC
    1769              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: proj_mo_on_kind_spinor
    1770              :       TYPE(cp_cfm_type)                                  :: cfm_eigenvec_ikp_spinor, &
    1771              :                                                             cfm_ks_ikp_spinor, cfm_mos_ikp_spinor, &
    1772              :                                                             cfm_SOC_ikp_spinor, cfm_work_ikp_spinor
    1773              : 
    1774              : !TYPE(band_edges_type)                              :: band_edges_no_SOC
    1775              : 
    1776          656 :       CALL timeset(routineN, handle)
    1777              : 
    1778          656 :       n_ao = bs_env%n_ao
    1779          656 :       homo_spinor = bs_env%n_occ(1) + bs_env%n_occ(bs_env%n_spin)
    1780          656 :       CALL get_qs_env(qs_env, nkind=nkind)
    1781              : 
    1782          656 :       CALL cp_cfm_create(cfm_ks_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
    1783          656 :       CALL cp_cfm_create(cfm_SOC_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
    1784          656 :       CALL cp_cfm_create(cfm_mos_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
    1785          656 :       CALL cp_cfm_create(cfm_work_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
    1786          656 :       CALL cp_cfm_create(cfm_eigenvec_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
    1787              : 
    1788         1968 :       ALLOCATE (eigenval_spinor_no_SOC(2*n_ao))
    1789         2624 :       ALLOCATE (proj_mo_on_kind_spinor(2*n_ao, nkind))
    1790              :       ! PDOS not yet implemented -> projection is just zero -> PDOS is zero
    1791          656 :       proj_mo_on_kind_spinor(:, :) = 0.0_dp
    1792              : 
    1793              :       ! 1. get V^SOC_µν,σσ'(k_i)
    1794          676 :       SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
    1795              :       CASE (large_cell_Gamma, large_cell_Gamma_ri_rs, non_periodic_ri_rs)
    1796              : 
    1797              :          ! 1. get V^SOC_µν,σσ'(k_i) from V^SOC_µν,σσ'(k=0)
    1798              :          CALL cfm_ikp_from_cfm_spinor_Gamma(cfm_SOC_ikp_spinor, &
    1799              :                                             bs_env%cfm_SOC_spinor_ao(1), &
    1800              :                                             bs_env%fm_s_Gamma%matrix_struct, &
    1801           20 :                                             ikp, qs_env, bs_env%kpoints_DOS, "ORB")
    1802              : 
    1803              :       CASE (small_cell_full_kp)
    1804              : 
    1805              :          ! 1. V^SOC_µν,σσ'(k_i) already there
    1806          656 :          CALL cp_cfm_to_cfm(bs_env%cfm_SOC_spinor_ao(ikp), cfm_SOC_ikp_spinor)
    1807              : 
    1808              :       END SELECT
    1809              : 
    1810              :       ! 2. V^SOC_nn',σσ'(k_i) = sum_µν C^*_µn,σ(k_i) V^SOC_µν,σσ'(k_i) C_νn'(k_i),
    1811              :       !    C_µn,σ(k_i): MO coefficiencts from diagonalizing KS-matrix h^KS_nn',σσ'(k_i)
    1812              : 
    1813              :       ! 2.1 build matrix C_µn,σ(k_i)
    1814          656 :       CALL cp_cfm_set_all(cfm_mos_ikp_spinor, z_zero)
    1815          656 :       CALL add_cfm_submat(cfm_mos_ikp_spinor, cfm_mos_ikp(1), 1, 1)
    1816          656 :       CALL add_cfm_submat(cfm_mos_ikp_spinor, cfm_mos_ikp(bs_env%n_spin), n_ao + 1, n_ao + 1)
    1817              : 
    1818              :       ! 2.2 work_nν,σσ' = sum_µ C^*_µn,σ(k_i) V^SOC_µν,σσ'(k_i)
    1819              :       CALL parallel_gemm('C', 'N', 2*n_ao, 2*n_ao, 2*n_ao, z_one, &
    1820              :                          cfm_mos_ikp_spinor, cfm_SOC_ikp_spinor, &
    1821          656 :                          z_zero, cfm_work_ikp_spinor)
    1822              : 
    1823              :       ! 2.3 V^SOC_nn',σσ'(k_i) = sum_ν work_nν,σσ' C_νn'(k_i)
    1824              :       CALL parallel_gemm('N', 'N', 2*n_ao, 2*n_ao, 2*n_ao, z_one, &
    1825              :                          cfm_work_ikp_spinor, cfm_mos_ikp_spinor, &
    1826          656 :                          z_zero, cfm_ks_ikp_spinor)
    1827              : 
    1828              :       ! 3. remove SOC outside of energy window (otherwise, numerical problems arise
    1829              :       !    because energetically low semicore states and energetically very high
    1830              :       !    unbound states couple to the states around the Fermi level)
    1831         8800 :       eigenval_spinor_no_SOC(1:n_ao) = eigenval_no_SOC(1:n_ao, ikp, 1)
    1832         8800 :       eigenval_spinor_no_SOC(n_ao + 1:) = eigenval_no_SOC(1:n_ao, ikp, bs_env%n_spin)
    1833          656 :       IF (bs_env%soc_window_occ > 0.0_dp .OR. bs_env%soc_window_virt > 0.0_dp) THEN
    1834              :          CALL remove_soc_outside_energy_window_mo(cfm_ks_ikp_spinor, &
    1835              :                                                   bs_env%soc_window_virt, &
    1836              :                                                   bs_env%soc_window_smearing, &
    1837              :                                                   eigenval_spinor_no_SOC, &
    1838          256 :                                                   bs_env%e_fermi(1))
    1839              : 
    1840              :       END IF
    1841              : 
    1842              :       ! 4. h^G0W0+SOC_nn',σσ'(k_i) = ε_nσ^G0W0(k_i) δ_nn' δ_σσ' + V^SOC_nn',σσ'(k_i)
    1843          656 :       CALL cfm_add_on_diag(cfm_ks_ikp_spinor, eigenval_spinor_no_SOC)
    1844              : 
    1845              :       ! 5. diagonalize h^G0W0+SOC_nn',σσ'(k_i) to get eigenvalues
    1846          656 :       CALL cp_cfm_heevd(cfm_ks_ikp_spinor, cfm_eigenvec_ikp_spinor, eigenval_spinor)
    1847              : 
    1848              :       ! 6. DOS from spinors, no PDOS
    1849          656 :       IF (bs_env%do_dos_pdos) THEN
    1850          452 :          n_E = SIZE(DOS)
    1851              :          CALL add_to_DOS_PDOS(DOS, PDOS, eigenval_spinor, &
    1852          452 :                               ikp, bs_env, n_E, E_min, proj_mo_on_kind_spinor)
    1853              :       END IF
    1854              : 
    1855              :       ! 7. valence band max. (VBM), conduction band min. (CBM) and direct bandgap (DBG)
    1856          656 :       band_edges%VBM = MAX(band_edges%VBM, eigenval_spinor(homo_spinor))
    1857          656 :       band_edges%CBM = MIN(band_edges%CBM, eigenval_spinor(homo_spinor + 1))
    1858              :       band_edges%DBG = MIN(band_edges%DBG, eigenval_spinor(homo_spinor + 1) &
    1859          656 :                            - eigenval_spinor(homo_spinor))
    1860              : 
    1861              :       ! 8. spinor wavefunctions:
    1862              :       CALL parallel_gemm('N', 'N', 2*n_ao, 2*n_ao, 2*n_ao, z_one, &
    1863              :                          cfm_mos_ikp_spinor, cfm_eigenvec_ikp_spinor, &
    1864          656 :                          z_zero, cfm_spinor_wf_ikp)
    1865              : 
    1866          656 :       CALL cp_cfm_release(cfm_ks_ikp_spinor)
    1867          656 :       CALL cp_cfm_release(cfm_SOC_ikp_spinor)
    1868          656 :       CALL cp_cfm_release(cfm_work_ikp_spinor)
    1869          656 :       CALL cp_cfm_release(cfm_eigenvec_ikp_spinor)
    1870          656 :       CALL cp_cfm_release(cfm_mos_ikp_spinor)
    1871              : 
    1872          656 :       CALL timestop(handle)
    1873              : 
    1874         1968 :    END SUBROUTINE SOC_ev
    1875              : 
    1876              : ! **************************************************************************************************
    1877              : !> \brief ...
    1878              : !> \param DOS ...
    1879              : !> \param PDOS ...
    1880              : !> \param eigenval ...
    1881              : !> \param ikp ...
    1882              : !> \param bs_env ...
    1883              : !> \param n_E ...
    1884              : !> \param E_min ...
    1885              : !> \param proj_mo_on_kind ...
    1886              : ! **************************************************************************************************
    1887          920 :    SUBROUTINE add_to_DOS_PDOS(DOS, PDOS, eigenval, ikp, bs_env, n_E, E_min, proj_mo_on_kind)
    1888              : 
    1889              :       REAL(KIND=dp), DIMENSION(:)                        :: DOS
    1890              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: PDOS
    1891              :       REAL(KIND=dp), DIMENSION(:)                        :: eigenval
    1892              :       INTEGER                                            :: ikp
    1893              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1894              :       INTEGER                                            :: n_E
    1895              :       REAL(KIND=dp)                                      :: E_min
    1896              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: proj_mo_on_kind
    1897              : 
    1898              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'add_to_DOS_PDOS'
    1899              : 
    1900              :       INTEGER                                            :: handle, i_E, i_kind, i_mo, n_mo, nkind
    1901              :       REAL(KIND=dp)                                      :: broadening, energy, energy_step_DOS, wkp
    1902              : 
    1903          920 :       CALL timeset(routineN, handle)
    1904              : 
    1905          920 :       energy_step_DOS = bs_env%energy_step_DOS
    1906          920 :       broadening = bs_env%broadening_DOS
    1907              : 
    1908          920 :       n_mo = SIZE(eigenval)
    1909          920 :       nkind = SIZE(proj_mo_on_kind, 2)
    1910              : 
    1911              :       ! normalize to closed-shell / open-shell
    1912          920 :       wkp = bs_env%kpoints_DOS%wkp(ikp)*bs_env%spin_degeneracy
    1913      2072664 :       DO i_E = 1, n_E
    1914      2071744 :          energy = E_min + i_E*energy_step_DOS
    1915     45624244 :          DO i_mo = 1, n_mo
    1916              :             ! DOS
    1917     43551580 :             DOS(i_E) = DOS(i_E) + wkp*Gaussian(energy - eigenval(i_mo), broadening)
    1918              : 
    1919              :             ! PDOS
    1920    132726484 :             DO i_kind = 1, nkind
    1921    130654740 :                IF (proj_mo_on_kind(i_mo, i_kind) > 0.0_dp) THEN
    1922              :                   PDOS(i_E, i_kind) = PDOS(i_E, i_kind) + &
    1923              :                                       proj_mo_on_kind(i_mo, i_kind)*wkp* &
    1924     27026364 :                                       Gaussian(energy - eigenval(i_mo), broadening)
    1925              :                END IF
    1926              :             END DO
    1927              :          END DO
    1928              :       END DO
    1929              : 
    1930          920 :       CALL timestop(handle)
    1931              : 
    1932          920 :    END SUBROUTINE add_to_DOS_PDOS
    1933              : 
    1934              : ! **************************************************************************************************
    1935              : !> \brief ...
    1936              : !> \param LDOS_2d ...
    1937              : !> \param qs_env ...
    1938              : !> \param ikp ...
    1939              : !> \param bs_env ...
    1940              : !> \param cfm_mos_ikp ...
    1941              : !> \param eigenval ...
    1942              : !> \param band_edges ...
    1943              : !> \param do_spinor ...
    1944              : !> \param cfm_non_spinor ...
    1945              : ! **************************************************************************************************
    1946            6 :    SUBROUTINE add_to_LDOS_2d(LDOS_2d, qs_env, ikp, bs_env, cfm_mos_ikp, eigenval, &
    1947              :                              band_edges, do_spinor, cfm_non_spinor)
    1948              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: LDOS_2d
    1949              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1950              :       INTEGER                                            :: ikp
    1951              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1952              :       TYPE(cp_cfm_type)                                  :: cfm_mos_ikp
    1953              :       REAL(KIND=dp), DIMENSION(:)                        :: eigenval
    1954              :       TYPE(band_edges_type)                              :: band_edges
    1955              :       LOGICAL, OPTIONAL                                  :: do_spinor
    1956              :       TYPE(cp_cfm_type), OPTIONAL                        :: cfm_non_spinor
    1957              : 
    1958              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'add_to_LDOS_2d'
    1959              : 
    1960              :       INTEGER :: handle, i_E, i_x_end, i_x_start, i_y_end, i_y_start, i_z, i_z_end, i_z_start, &
    1961              :          j_col, j_mo, n_E, n_mo, n_z, ncol_local, nimages, z_end_global, z_start_global
    1962            6 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices
    1963              :       LOGICAL                                            :: is_any_weight_non_zero, my_do_spinor
    1964              :       REAL(KIND=dp)                                      :: broadening, E_max, E_min, &
    1965              :                                                             E_total_window, energy, energy_step, &
    1966              :                                                             energy_window, spin_degeneracy, weight
    1967              :       TYPE(cp_cfm_type)                                  :: cfm_weighted_dm_ikp, cfm_work
    1968              :       TYPE(cp_fm_type)                                   :: fm_non_spinor, fm_weighted_dm_MIC
    1969            6 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: weighted_dm_MIC
    1970              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1971              :       TYPE(pw_c1d_gs_type)                               :: rho_g
    1972              :       TYPE(pw_env_type), POINTER                         :: pw_env
    1973              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    1974              :       TYPE(pw_r3d_rs_type)                               :: LDOS_3d
    1975              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
    1976              : 
    1977            6 :       CALL timeset(routineN, handle)
    1978              : 
    1979            6 :       my_do_spinor = .FALSE.
    1980            6 :       IF (PRESENT(do_spinor)) my_do_spinor = do_spinor
    1981              : 
    1982            6 :       CALL get_qs_env(qs_env, ks_env=ks_env, pw_env=pw_env, dft_control=dft_control)
    1983              : 
    1984              :       ! previously, dft_control%nimages set to # neighbor cells, revert for Γ-only KS matrix
    1985            6 :       nimages = dft_control%nimages
    1986            6 :       dft_control%nimages = bs_env%nimages_scf
    1987              : 
    1988            6 :       energy_window = bs_env%energy_window_DOS
    1989            6 :       energy_step = bs_env%energy_step_DOS
    1990            6 :       broadening = bs_env%broadening_DOS
    1991              : 
    1992            6 :       E_min = band_edges%VBM - 0.5_dp*energy_window
    1993            6 :       E_max = band_edges%CBM + 0.5_dp*energy_window
    1994            6 :       E_total_window = E_max - E_min
    1995              : 
    1996            6 :       n_E = INT(E_total_window/energy_step)
    1997              : 
    1998            6 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    1999              : 
    2000            6 :       CALL auxbas_pw_pool%create_pw(LDOS_3d)
    2001            6 :       CALL auxbas_pw_pool%create_pw(rho_g)
    2002              : 
    2003            6 :       i_x_start = LBOUND(LDOS_3d%array, 1)
    2004            6 :       i_x_end = UBOUND(LDOS_3d%array, 1)
    2005            6 :       i_y_start = LBOUND(LDOS_3d%array, 2)
    2006            6 :       i_y_end = UBOUND(LDOS_3d%array, 2)
    2007            6 :       i_z_start = LBOUND(LDOS_3d%array, 3)
    2008            6 :       i_z_end = UBOUND(LDOS_3d%array, 3)
    2009              : 
    2010            6 :       z_start_global = i_z_start
    2011            6 :       z_end_global = i_z_end
    2012              : 
    2013            6 :       CALL bs_env%para_env%min(z_start_global)
    2014            6 :       CALL bs_env%para_env%max(z_end_global)
    2015            6 :       n_z = z_end_global - z_start_global + 1
    2016              : 
    2017           36 :       IF (ANY(ABS(bs_env%hmat(1:2, 3)) > 1.0E-6_dp) .OR. ANY(ABS(bs_env%hmat(3, 1:2)) > 1.0E-6_dp)) THEN
    2018            0 :          CPABORT("Please choose a cell that has 90° angles to the z-direction.")
    2019              :       END IF
    2020              :       ! for integration, we need the dz and the conversion from H -> eV and a_Bohr -> Å
    2021            6 :       bs_env%unit_ldos_int_z_inv_Ang2_eV = bs_env%hmat(3, 3)/REAL(n_z, KIND=dp)/evolt/angstrom**2
    2022              : 
    2023            6 :       IF (ikp == 1) THEN
    2024           30 :          ALLOCATE (LDOS_2d(i_x_start:i_x_end, i_y_start:i_y_end, n_E))
    2025            6 :          LDOS_2d(:, :, :) = 0.0_dp
    2026              :       END IF
    2027              : 
    2028            6 :       CALL cp_cfm_create(cfm_work, cfm_mos_ikp%matrix_struct)
    2029            6 :       CALL cp_cfm_create(cfm_weighted_dm_ikp, cfm_mos_ikp%matrix_struct)
    2030            6 :       CALL cp_fm_create(fm_weighted_dm_MIC, cfm_mos_ikp%matrix_struct)
    2031            6 :       IF (my_do_spinor) THEN
    2032            2 :          CALL cp_fm_create(fm_non_spinor, cfm_non_spinor%matrix_struct)
    2033              :       END IF
    2034              : 
    2035              :       CALL cp_cfm_get_info(matrix=cfm_mos_ikp, &
    2036              :                            ncol_global=n_mo, &
    2037              :                            ncol_local=ncol_local, &
    2038            6 :                            col_indices=col_indices)
    2039              : 
    2040            6 :       NULLIFY (weighted_dm_MIC)
    2041            6 :       CALL dbcsr_allocate_matrix_set(weighted_dm_MIC, 1)
    2042            6 :       ALLOCATE (weighted_dm_MIC(1)%matrix)
    2043              :       CALL dbcsr_create(weighted_dm_MIC(1)%matrix, template=bs_env%mat_ao_ao%matrix, &
    2044            6 :                         matrix_type=dbcsr_type_symmetric)
    2045              : 
    2046         1678 :       DO i_E = 1, n_E
    2047              : 
    2048         1672 :          energy = E_min + i_E*energy_step
    2049              : 
    2050         1672 :          is_any_weight_non_zero = .FALSE.
    2051              : 
    2052        20950 :          DO j_col = 1, ncol_local
    2053              : 
    2054        19278 :             j_mo = col_indices(j_col)
    2055              : 
    2056        19278 :             IF (my_do_spinor) THEN
    2057              :                spin_degeneracy = 1.0_dp
    2058              :             ELSE
    2059        10818 :                spin_degeneracy = bs_env%spin_degeneracy
    2060              :             END IF
    2061              : 
    2062        19278 :             weight = Gaussian(energy - eigenval(j_mo), broadening)*spin_degeneracy
    2063              : 
    2064       144099 :             cfm_work%local_data(:, j_col) = cfm_mos_ikp%local_data(:, j_col)*weight
    2065              : 
    2066        20950 :             IF (weight > 1.0E-5_dp) is_any_weight_non_zero = .TRUE.
    2067              : 
    2068              :          END DO
    2069              : 
    2070         1672 :          CALL bs_env%para_env%sync()
    2071         1672 :          CALL bs_env%para_env%sum(is_any_weight_non_zero)
    2072         1672 :          CALL bs_env%para_env%sync()
    2073              : 
    2074              :          ! cycle if there are no states at the energy i_E
    2075         1678 :          IF (is_any_weight_non_zero) THEN
    2076              : 
    2077              :             CALL parallel_gemm('N', 'C', n_mo, n_mo, n_mo, z_one, &
    2078           24 :                                cfm_mos_ikp, cfm_work, z_zero, cfm_weighted_dm_ikp)
    2079              : 
    2080           24 :             IF (my_do_spinor) THEN
    2081              : 
    2082              :                ! contribution from up,up to fm_non_spinor
    2083            8 :                CALL get_cfm_submat(cfm_non_spinor, cfm_weighted_dm_ikp, 1, 1)
    2084            8 :                CALL cp_fm_set_all(fm_non_spinor, 0.0_dp)
    2085              :                CALL MIC_contribution_from_ikp(bs_env, qs_env, fm_non_spinor, &
    2086              :                                               cfm_non_spinor, ikp, bs_env%kpoints_DOS, &
    2087            8 :                                               "ORB", bs_env%kpoints_DOS%wkp(ikp))
    2088              : 
    2089              :                ! add contribution from down,down to fm_non_spinor
    2090            8 :                CALL get_cfm_submat(cfm_non_spinor, cfm_weighted_dm_ikp, n_mo/2, n_mo/2)
    2091              :                CALL MIC_contribution_from_ikp(bs_env, qs_env, fm_non_spinor, &
    2092              :                                               cfm_non_spinor, ikp, bs_env%kpoints_DOS, &
    2093            8 :                                               "ORB", bs_env%kpoints_DOS%wkp(ikp))
    2094              :                CALL copy_fm_to_dbcsr(fm_non_spinor, weighted_dm_MIC(1)%matrix, &
    2095            8 :                                      keep_sparsity=.FALSE.)
    2096              :             ELSE
    2097           16 :                CALL cp_fm_set_all(fm_weighted_dm_MIC, 0.0_dp)
    2098              :                CALL MIC_contribution_from_ikp(bs_env, qs_env, fm_weighted_dm_MIC, &
    2099              :                                               cfm_weighted_dm_ikp, ikp, bs_env%kpoints_DOS, &
    2100           16 :                                               "ORB", bs_env%kpoints_DOS%wkp(ikp))
    2101              :                CALL copy_fm_to_dbcsr(fm_weighted_dm_MIC, weighted_dm_MIC(1)%matrix, &
    2102           16 :                                      keep_sparsity=.FALSE.)
    2103              :             END IF
    2104              : 
    2105       338424 :             LDOS_3d%array(:, :, :) = 0.0_dp
    2106              : 
    2107              :             CALL calculate_rho_elec(matrix_p_kp=weighted_dm_MIC, &
    2108              :                                     rho=LDOS_3d, &
    2109              :                                     rho_gspace=rho_g, &
    2110           24 :                                     ks_env=ks_env)
    2111              : 
    2112          504 :             DO i_z = i_z_start, i_z_end
    2113       338424 :                LDOS_2d(:, :, i_E) = LDOS_2d(:, :, i_E) + LDOS_3d%array(:, :, i_z)
    2114              :             END DO
    2115              : 
    2116              :          END IF
    2117              : 
    2118              :       END DO
    2119              : 
    2120              :       ! set back nimages
    2121            6 :       dft_control%nimages = nimages
    2122              : 
    2123            6 :       CALL auxbas_pw_pool%give_back_pw(LDOS_3d)
    2124            6 :       CALL auxbas_pw_pool%give_back_pw(rho_g)
    2125              : 
    2126            6 :       CALL cp_cfm_release(cfm_work)
    2127            6 :       CALL cp_cfm_release(cfm_weighted_dm_ikp)
    2128              : 
    2129            6 :       CALL cp_fm_release(fm_weighted_dm_MIC)
    2130              : 
    2131            6 :       CALL dbcsr_deallocate_matrix_set(weighted_dm_MIC)
    2132              : 
    2133            6 :       IF (my_do_spinor) THEN
    2134            2 :          CALL cp_fm_release(fm_non_spinor)
    2135              :       END IF
    2136              : 
    2137            6 :       CALL timestop(handle)
    2138              : 
    2139            6 :    END SUBROUTINE add_to_LDOS_2d
    2140              : 
    2141              : ! **************************************************************************************************
    2142              : !> \brief ...
    2143              : !> \param eigenval_spinor ...
    2144              : !> \param ikp_for_file ...
    2145              : !> \param ikp ...
    2146              : !> \param bs_env ...
    2147              : !> \param eigenval_spinor_G0W0 ...
    2148              : ! **************************************************************************************************
    2149          296 :    SUBROUTINE write_SOC_eigenvalues(eigenval_spinor, ikp_for_file, ikp, bs_env, eigenval_spinor_G0W0)
    2150              : 
    2151              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigenval_spinor
    2152              :       INTEGER                                            :: ikp_for_file, ikp
    2153              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    2154              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), OPTIONAL :: eigenval_spinor_G0W0
    2155              : 
    2156              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'write_SOC_eigenvalues'
    2157              : 
    2158              :       CHARACTER(len=3)                                   :: occ_vir
    2159              :       CHARACTER(LEN=default_string_length)               :: fname
    2160              :       INTEGER                                            :: handle, i_mo, iunit, n_occ_spinor
    2161              : 
    2162          296 :       CALL timeset(routineN, handle)
    2163              : 
    2164          296 :       fname = "bandstructure_SCF_and_G0W0_plus_SOC"
    2165              : 
    2166          296 :       IF (bs_env%para_env%is_source()) THEN
    2167              : 
    2168          148 :          IF (ikp_for_file == 1) THEN
    2169              :             CALL open_file(TRIM(fname), unit_number=iunit, file_status="REPLACE", &
    2170           11 :                            file_action="WRITE")
    2171              :          ELSE
    2172              :             CALL open_file(TRIM(fname), unit_number=iunit, file_status="OLD", &
    2173          137 :                            file_action="WRITE", file_position="APPEND")
    2174              :          END IF
    2175              : 
    2176          148 :          WRITE (iunit, "(A)") " "
    2177          148 :          WRITE (iunit, "(A10,I7,A25,3F10.4)") "kpoint: ", ikp_for_file, "coordinate: ", &
    2178          740 :             bs_env%kpoints_DOS%xkp(:, ikp)
    2179          148 :          WRITE (iunit, "(A)") " "
    2180              : 
    2181          148 :          IF (PRESENT(eigenval_spinor_G0W0)) THEN
    2182              :             ! SCF+SOC and G0W0+SOC eigenvalues
    2183          148 :             WRITE (iunit, "(A5,A12,2A22)") "n", "k", "ϵ_nk^DFT+SOC (eV)", "ϵ_nk^G0W0+SOC (eV)"
    2184              :          ELSE
    2185              :             ! SCF+SOC eigenvalues only
    2186            0 :             WRITE (iunit, "(A5,A12,A22)") "n", "k", "ϵ_nk^DFT+SOC (eV)"
    2187              :          END IF
    2188              : 
    2189          148 :          n_occ_spinor = bs_env%n_occ(1) + bs_env%n_occ(bs_env%n_spin)
    2190              : 
    2191         3932 :          DO i_mo = 1, SIZE(eigenval_spinor)
    2192         3784 :             IF (i_mo <= n_occ_spinor) occ_vir = 'occ'
    2193         3784 :             IF (i_mo > n_occ_spinor) occ_vir = 'vir'
    2194         3932 :             IF (PRESENT(eigenval_spinor_G0W0)) THEN
    2195              :                ! SCF+SOC and G0W0+SOC eigenvalues
    2196         3784 :                WRITE (iunit, "(I5,3A,I5,4F16.3,2F17.3)") i_mo, ' (', occ_vir, ') ', &
    2197         7568 :                   ikp_for_file, eigenval_spinor(i_mo)*evolt, eigenval_spinor_G0W0(i_mo)*evolt
    2198              :             ELSE
    2199              :                ! SCF+SOC eigenvalues only
    2200            0 :                WRITE (iunit, "(I5,3A,I5,4F16.3,F17.3)") i_mo, ' (', occ_vir, ') ', &
    2201            0 :                   ikp_for_file, eigenval_spinor(i_mo)*evolt
    2202              :             END IF
    2203              :          END DO
    2204              : 
    2205          148 :          CALL close_file(iunit)
    2206              : 
    2207              :       END IF
    2208              : 
    2209          296 :       CALL timestop(handle)
    2210              : 
    2211          296 :    END SUBROUTINE write_SOC_eigenvalues
    2212              : 
    2213              : ! **************************************************************************************************
    2214              : !> \brief ...
    2215              : !> \param int_number ...
    2216              : !> \return ...
    2217              : ! **************************************************************************************************
    2218            0 :    PURE FUNCTION count_digits(int_number)
    2219              : 
    2220              :       INTEGER, INTENT(IN)                                :: int_number
    2221              :       INTEGER                                            :: count_digits
    2222              : 
    2223              :       INTEGER                                            :: digitCount, tempInt
    2224              : 
    2225            0 :       digitCount = 0
    2226              : 
    2227            0 :       tempInt = int_number
    2228              : 
    2229            0 :       DO WHILE (tempInt /= 0)
    2230            0 :          tempInt = tempInt/10
    2231            0 :          digitCount = digitCount + 1
    2232              :       END DO
    2233              : 
    2234            0 :       count_digits = digitCount
    2235              : 
    2236            0 :    END FUNCTION count_digits
    2237              : 
    2238              : ! **************************************************************************************************
    2239              : !> \brief ...
    2240              : !> \param band_edges ...
    2241              : !> \param scf_gw_soc ...
    2242              : !> \param bs_env ...
    2243              : ! **************************************************************************************************
    2244          412 :    SUBROUTINE write_band_edges(band_edges, scf_gw_soc, bs_env)
    2245              : 
    2246              :       TYPE(band_edges_type)                              :: band_edges
    2247              :       CHARACTER(LEN=*)                                   :: scf_gw_soc
    2248              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    2249              : 
    2250              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'write_band_edges'
    2251              : 
    2252              :       CHARACTER(LEN=17)                                  :: print_format
    2253              :       INTEGER                                            :: handle, u
    2254              : 
    2255          412 :       CALL timeset(routineN, handle)
    2256              : 
    2257              :       ! print format
    2258          412 :       print_format = "(T2,2A,T61,F20.3)"
    2259              : 
    2260          412 :       u = bs_env%unit_nr
    2261          412 :       IF (u > 0) THEN
    2262          206 :          WRITE (u, '(T2,A)') ''
    2263          206 :          WRITE (u, print_format) scf_gw_soc, ' valence band maximum (eV):', band_edges%VBM*evolt
    2264          206 :          WRITE (u, print_format) scf_gw_soc, ' conduction band minimum (eV):', band_edges%CBM*evolt
    2265          206 :          WRITE (u, print_format) scf_gw_soc, ' indirect band gap (eV):', band_edges%IDBG*evolt
    2266          206 :          WRITE (u, print_format) scf_gw_soc, ' direct band gap (eV):', band_edges%DBG*evolt
    2267              :       END IF
    2268              : 
    2269          412 :       CALL timestop(handle)
    2270              : 
    2271          412 :    END SUBROUTINE write_band_edges
    2272              : 
    2273              : ! **************************************************************************************************
    2274              : !> \brief ...
    2275              : !> \param DOS ...
    2276              : !> \param PDOS ...
    2277              : !> \param bs_env ...
    2278              : !> \param qs_env ...
    2279              : !> \param scf_gw_soc ...
    2280              : !> \param E_min ...
    2281              : !> \param E_VBM ...
    2282              : ! **************************************************************************************************
    2283           72 :    SUBROUTINE write_dos_pdos(DOS, PDOS, bs_env, qs_env, scf_gw_soc, E_min, E_VBM)
    2284              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: DOS
    2285              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: PDOS
    2286              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    2287              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2288              :       CHARACTER(LEN=*)                                   :: scf_gw_soc
    2289              :       REAL(KIND=dp)                                      :: E_min, E_VBM
    2290              : 
    2291              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'write_dos_pdos'
    2292              : 
    2293              :       CHARACTER(LEN=3), DIMENSION(100)                   :: elements
    2294              :       CHARACTER(LEN=default_string_length)               :: atom_name, fname, output_string
    2295              :       INTEGER                                            :: handle, i_E, i_kind, iatom, iunit, n_A, &
    2296              :                                                             n_E, nkind
    2297              :       REAL(KIND=dp)                                      :: energy
    2298           72 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    2299              : 
    2300           72 :       CALL timeset(routineN, handle)
    2301              : 
    2302           72 :       WRITE (fname, "(3A)") "DOS_PDOS_", scf_gw_soc, ".out"
    2303              : 
    2304           72 :       n_E = SIZE(PDOS, 1)
    2305           72 :       nkind = SIZE(PDOS, 2)
    2306           72 :       CALL get_qs_env(qs_env, particle_set=particle_set)
    2307              : 
    2308           72 :       IF (bs_env%para_env%is_source()) THEN
    2309              : 
    2310           36 :          CALL open_file(TRIM(fname), unit_number=iunit, file_status="REPLACE", file_action="WRITE")
    2311              : 
    2312           36 :          n_A = 2 + nkind
    2313              : 
    2314          140 :          DO iatom = 1, bs_env%n_atom
    2315              :             CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
    2316          104 :                                  kind_number=i_kind, name=atom_name)
    2317          140 :             elements(i_kind) = atom_name(1:3)
    2318              :          END DO
    2319              : 
    2320           36 :          WRITE (output_string, "(A,I1,A)") "(", n_A, "A)"
    2321              : 
    2322           36 :          WRITE (iunit, TRIM(output_string)) "Energy-E_F (eV)    DOS (1/eV)    PDOS (1/eV) ", &
    2323           72 :             " of atom type ", elements(1:nkind)
    2324              : 
    2325           36 :          WRITE (output_string, "(A,I1,A)") "(", n_A, "F13.5)"
    2326              : 
    2327        73686 :          DO i_E = 1, n_E
    2328              :             ! energy is relative to valence band maximum => - E_VBM
    2329        73650 :             energy = E_min + i_E*bs_env%energy_step_DOS - E_VBM
    2330       220986 :             WRITE (iunit, TRIM(output_string)) energy*evolt, DOS(i_E)/evolt, PDOS(i_E, :)/evolt
    2331              :          END DO
    2332              : 
    2333           36 :          CALL close_file(iunit)
    2334              : 
    2335              :       END IF
    2336              : 
    2337           72 :       CALL timestop(handle)
    2338              : 
    2339           72 :    END SUBROUTINE write_dos_pdos
    2340              : 
    2341              : ! **************************************************************************************************
    2342              : !> \brief ...
    2343              : !> \param energy ...
    2344              : !> \param broadening ...
    2345              : !> \return ...
    2346              : ! **************************************************************************************************
    2347     70597222 :    PURE FUNCTION Gaussian(energy, broadening)
    2348              : 
    2349              :       REAL(KIND=dp), INTENT(IN)                          :: energy, broadening
    2350              :       REAL(KIND=dp)                                      :: Gaussian
    2351              : 
    2352     70597222 :       IF (ABS(energy) < 5*broadening) THEN
    2353       111792 :          Gaussian = 1.0_dp/broadening/SQRT(twopi)*EXP(-0.5_dp*energy**2/broadening**2)
    2354              :       ELSE
    2355              :          Gaussian = 0.0_dp
    2356              :       END IF
    2357              : 
    2358     70597222 :    END FUNCTION Gaussian
    2359              : 
    2360              : ! **************************************************************************************************
    2361              : !> \brief ...
    2362              : !> \param proj_mo_on_kind ...
    2363              : !> \param qs_env ...
    2364              : !> \param cfm_mos ...
    2365              : !> \param cfm_s ...
    2366              : ! **************************************************************************************************
    2367          486 :    SUBROUTINE compute_proj_mo_on_kind(proj_mo_on_kind, qs_env, cfm_mos, cfm_s)
    2368              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: proj_mo_on_kind
    2369              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2370              :       TYPE(cp_cfm_type)                                  :: cfm_mos, cfm_s
    2371              : 
    2372              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_proj_mo_on_kind'
    2373              : 
    2374              :       INTEGER                                            :: handle, i_atom, i_global, i_kind, i_row, &
    2375              :                                                             j_col, n_ao, n_mo, ncol_local, nkind, &
    2376              :                                                             nrow_local
    2377          486 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_from_bf, kind_of
    2378          486 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
    2379          486 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    2380              :       TYPE(cp_cfm_type)                                  :: cfm_proj, cfm_s_i_kind, cfm_work
    2381              :       TYPE(cp_fm_type)                                   :: fm_proj_im, fm_proj_re
    2382              : 
    2383          486 :       CALL timeset(routineN, handle)
    2384              : 
    2385          486 :       CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, nkind=nkind)
    2386          486 :       CALL get_atomic_kind_set(atomic_kind_set, kind_of=kind_of)
    2387              : 
    2388              :       CALL cp_cfm_get_info(matrix=cfm_mos, &
    2389              :                            nrow_global=n_mo, &
    2390              :                            nrow_local=nrow_local, &
    2391              :                            ncol_local=ncol_local, &
    2392              :                            row_indices=row_indices, &
    2393          486 :                            col_indices=col_indices)
    2394              : 
    2395          486 :       n_ao = qs_env%bs_env%n_ao
    2396              : 
    2397         1458 :       ALLOCATE (atom_from_bf(n_ao))
    2398          486 :       CALL get_atom_index_from_basis_function_index(qs_env, atom_from_bf, n_ao, "ORB")
    2399              : 
    2400          486 :       proj_mo_on_kind(:, :) = 0.0_dp
    2401              : 
    2402          486 :       CALL cp_cfm_create(cfm_s_i_kind, cfm_s%matrix_struct)
    2403          486 :       CALL cp_cfm_create(cfm_work, cfm_s%matrix_struct)
    2404          486 :       CALL cp_cfm_create(cfm_proj, cfm_s%matrix_struct)
    2405          486 :       CALL cp_fm_create(fm_proj_re, cfm_s%matrix_struct)
    2406          486 :       CALL cp_fm_create(fm_proj_im, cfm_s%matrix_struct)
    2407              : 
    2408         1336 :       DO i_kind = 1, nkind
    2409              : 
    2410          850 :          CALL cp_cfm_to_cfm(cfm_s, cfm_s_i_kind)
    2411              : 
    2412              :          ! set entries in overlap matrix to zero which do not belong to atoms of i_kind
    2413        10958 :          DO j_col = 1, ncol_local
    2414        75414 :             DO i_row = 1, nrow_local
    2415              : 
    2416        64456 :                i_global = row_indices(i_row)
    2417              : 
    2418        64456 :                IF (i_global <= n_ao) THEN
    2419        64456 :                   i_atom = atom_from_bf(i_global)
    2420            0 :                ELSE IF (i_global <= 2*n_ao) THEN
    2421            0 :                   i_atom = atom_from_bf(i_global - n_ao)
    2422              :                ELSE
    2423            0 :                   CPABORT("Wrong indices.")
    2424              :                END IF
    2425              : 
    2426        74564 :                IF (i_kind /= kind_of(i_atom)) THEN
    2427        29094 :                   cfm_s_i_kind%local_data(i_row, j_col) = z_zero
    2428              :                END IF
    2429              : 
    2430              :             END DO
    2431              :          END DO
    2432              : 
    2433              :          CALL parallel_gemm('N', 'N', n_mo, n_mo, n_mo, z_one, &
    2434          850 :                             cfm_s_i_kind, cfm_mos, z_zero, cfm_work)
    2435              :          CALL parallel_gemm('C', 'N', n_mo, n_mo, n_mo, z_one, &
    2436          850 :                             cfm_mos, cfm_work, z_zero, cfm_proj)
    2437              : 
    2438          850 :          CALL cp_cfm_to_fm(cfm_proj, fm_proj_re, fm_proj_im)
    2439              : 
    2440          850 :          CALL cp_fm_get_diag(fm_proj_im, proj_mo_on_kind(:, i_kind))
    2441         1336 :          CALL cp_fm_get_diag(fm_proj_re, proj_mo_on_kind(:, i_kind))
    2442              : 
    2443              :       END DO ! i_kind
    2444              : 
    2445          486 :       CALL cp_cfm_release(cfm_s_i_kind)
    2446          486 :       CALL cp_cfm_release(cfm_work)
    2447          486 :       CALL cp_cfm_release(cfm_proj)
    2448          486 :       CALL cp_fm_release(fm_proj_re)
    2449          486 :       CALL cp_fm_release(fm_proj_im)
    2450              : 
    2451          486 :       CALL timestop(handle)
    2452              : 
    2453         1944 :    END SUBROUTINE compute_proj_mo_on_kind
    2454              : 
    2455              : ! **************************************************************************************************
    2456              : !> \brief ...
    2457              : !> \param cfm_spinor_ikp ...
    2458              : !> \param cfm_spinor_Gamma ...
    2459              : !> \param fm_struct_non_spinor ...
    2460              : !> \param ikp ...
    2461              : !> \param qs_env ...
    2462              : !> \param kpoints ...
    2463              : !> \param basis_type ...
    2464              : ! **************************************************************************************************
    2465          120 :    SUBROUTINE cfm_ikp_from_cfm_spinor_Gamma(cfm_spinor_ikp, cfm_spinor_Gamma, fm_struct_non_spinor, &
    2466              :                                             ikp, qs_env, kpoints, basis_type)
    2467              :       TYPE(cp_cfm_type)                                  :: cfm_spinor_ikp, cfm_spinor_Gamma
    2468              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_non_spinor
    2469              :       INTEGER                                            :: ikp
    2470              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2471              :       TYPE(kpoint_type), POINTER                         :: kpoints
    2472              :       CHARACTER(LEN=*)                                   :: basis_type
    2473              : 
    2474              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'cfm_ikp_from_cfm_spinor_Gamma'
    2475              : 
    2476              :       INTEGER                                            :: handle, i_block, i_offset, j_block, &
    2477              :                                                             j_offset, n_ao
    2478              :       TYPE(cp_cfm_type)                                  :: cfm_non_spinor_Gamma, cfm_non_spinor_ikp
    2479              :       TYPE(cp_fm_type)                                   :: fm_non_spinor_Gamma_im, &
    2480              :                                                             fm_non_spinor_Gamma_re
    2481              : 
    2482           20 :       CALL timeset(routineN, handle)
    2483              : 
    2484           20 :       CALL cp_cfm_create(cfm_non_spinor_Gamma, fm_struct_non_spinor)
    2485           20 :       CALL cp_cfm_create(cfm_non_spinor_ikp, fm_struct_non_spinor)
    2486           20 :       CALL cp_fm_create(fm_non_spinor_Gamma_re, fm_struct_non_spinor)
    2487           20 :       CALL cp_fm_create(fm_non_spinor_Gamma_im, fm_struct_non_spinor)
    2488              : 
    2489           20 :       CALL cp_cfm_get_info(cfm_non_spinor_Gamma, nrow_global=n_ao)
    2490              : 
    2491           20 :       CALL cp_cfm_set_all(cfm_spinor_ikp, z_zero)
    2492              : 
    2493           60 :       DO i_block = 0, 1
    2494          140 :          DO j_block = 0, 1
    2495           80 :             i_offset = i_block*n_ao + 1
    2496           80 :             j_offset = j_block*n_ao + 1
    2497           80 :             CALL get_cfm_submat(cfm_non_spinor_Gamma, cfm_spinor_Gamma, i_offset, j_offset)
    2498           80 :             CALL cp_cfm_to_fm(cfm_non_spinor_Gamma, fm_non_spinor_Gamma_re, fm_non_spinor_Gamma_im)
    2499              : 
    2500              :             ! transform real part of Gamma-point matrix to ikp
    2501              :             CALL cfm_ikp_from_fm_Gamma(cfm_non_spinor_ikp, fm_non_spinor_Gamma_re, &
    2502           80 :                                        ikp, qs_env, kpoints, basis_type)
    2503           80 :             CALL add_cfm_submat(cfm_spinor_ikp, cfm_non_spinor_ikp, i_offset, j_offset)
    2504              : 
    2505              :             ! transform imag part of Gamma-point matrix to ikp
    2506              :             CALL cfm_ikp_from_fm_Gamma(cfm_non_spinor_ikp, fm_non_spinor_Gamma_im, &
    2507           80 :                                        ikp, qs_env, kpoints, basis_type)
    2508          120 :             CALL add_cfm_submat(cfm_spinor_ikp, cfm_non_spinor_ikp, i_offset, j_offset, gaussi)
    2509              : 
    2510              :          END DO
    2511              :       END DO
    2512              : 
    2513           20 :       CALL cp_cfm_release(cfm_non_spinor_Gamma)
    2514           20 :       CALL cp_cfm_release(cfm_non_spinor_ikp)
    2515           20 :       CALL cp_fm_release(fm_non_spinor_Gamma_re)
    2516           20 :       CALL cp_fm_release(fm_non_spinor_Gamma_im)
    2517              : 
    2518           20 :       CALL timestop(handle)
    2519              : 
    2520           20 :    END SUBROUTINE cfm_ikp_from_cfm_spinor_Gamma
    2521              : 
    2522              : ! **************************************************************************************************
    2523              : !> \brief ...
    2524              : !> \param cfm_ikp ...
    2525              : !> \param fm_Gamma ...
    2526              : !> \param ikp ...
    2527              : !> \param qs_env ...
    2528              : !> \param kpoints ...
    2529              : !> \param basis_type ...
    2530              : ! **************************************************************************************************
    2531         6338 :    SUBROUTINE cfm_ikp_from_fm_Gamma(cfm_ikp, fm_Gamma, ikp, qs_env, kpoints, basis_type)
    2532              :       TYPE(cp_cfm_type)                                  :: cfm_ikp
    2533              :       TYPE(cp_fm_type)                                   :: fm_Gamma
    2534              :       INTEGER                                            :: ikp
    2535              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2536              :       TYPE(kpoint_type), POINTER                         :: kpoints
    2537              :       CHARACTER(LEN=*)                                   :: basis_type
    2538              : 
    2539              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'cfm_ikp_from_fm_Gamma'
    2540              : 
    2541              :       INTEGER :: col_global, handle, i_atom, i_atom_old, i_cell, i_mic_cell, i_row, j_atom, &
    2542              :          j_atom_old, j_cell, j_col, n_bf, ncol_local, nrow_local, num_cells, row_global
    2543         6338 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_from_bf
    2544         6338 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
    2545         6338 :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell
    2546              :       LOGICAL :: i_cell_is_the_minimum_image_cell
    2547              :       REAL(KIND=dp)                                      :: abs_rab_cell_i, abs_rab_cell_j, arg
    2548              :       REAL(KIND=dp), DIMENSION(3)                        :: cell_vector, cell_vector_j, rab_cell_i, &
    2549              :                                                             rab_cell_j
    2550              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: hmat
    2551              :       TYPE(cell_type), POINTER                           :: cell
    2552         6338 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    2553              : 
    2554         6338 :       CALL timeset(routineN, handle)
    2555              : 
    2556         6338 :       IF (.NOT. ASSOCIATED(cfm_ikp%local_data)) THEN
    2557         2874 :          CALL cp_cfm_create(cfm_ikp, fm_Gamma%matrix_struct)
    2558              :       END IF
    2559         6338 :       CALL cp_cfm_set_all(cfm_ikp, z_zero)
    2560              : 
    2561              :       CALL cp_fm_get_info(matrix=fm_Gamma, &
    2562              :                           nrow_local=nrow_local, &
    2563              :                           ncol_local=ncol_local, &
    2564              :                           row_indices=row_indices, &
    2565         6338 :                           col_indices=col_indices)
    2566              : 
    2567              :       ! get number of basis functions (bf) for different basis sets
    2568         6338 :       IF (basis_type == "ORB") THEN
    2569         3918 :          n_bf = qs_env%bs_env%n_ao
    2570         2420 :       ELSE IF (basis_type == "RI_AUX") THEN
    2571         2420 :          n_bf = qs_env%bs_env%n_RI
    2572              :       ELSE
    2573            0 :          CPABORT("Only ORB and RI_AUX basis implemented.")
    2574              :       END IF
    2575              : 
    2576        19014 :       ALLOCATE (atom_from_bf(n_bf))
    2577         6338 :       CALL get_atom_index_from_basis_function_index(qs_env, atom_from_bf, n_bf, basis_type)
    2578              : 
    2579         6338 :       NULLIFY (cell, particle_set)
    2580         6338 :       CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
    2581         6338 :       CALL get_cell(cell=cell, h=hmat)
    2582              : 
    2583         6338 :       index_to_cell => kpoints%index_to_cell
    2584              : 
    2585         6338 :       num_cells = SIZE(index_to_cell, 2)
    2586         6338 :       i_atom_old = 0
    2587         6338 :       j_atom_old = 0
    2588              : 
    2589        99644 :       DO j_col = 1, ncol_local
    2590      1349911 :          DO i_row = 1, nrow_local
    2591              : 
    2592      1250267 :             row_global = row_indices(i_row)
    2593      1250267 :             col_global = col_indices(j_col)
    2594              : 
    2595      1250267 :             i_atom = atom_from_bf(row_global)
    2596      1250267 :             j_atom = atom_from_bf(col_global)
    2597              : 
    2598              :             ! we only need to check for new MIC cell for new i_atom-j_atom pair
    2599      1250267 :             IF (i_atom /= i_atom_old .OR. j_atom /= j_atom_old) THEN
    2600       727768 :                DO i_cell = 1, num_cells
    2601              : 
    2602              :                   ! only check nearest neigbors
    2603      1813456 :                   IF (ANY(ABS(index_to_cell(1:3, i_cell)) > 1)) CYCLE
    2604              : 
    2605      5799552 :                   cell_vector(1:3) = MATMUL(hmat, REAL(index_to_cell(1:3, i_cell), dp))
    2606              : 
    2607              :                   rab_cell_i(1:3) = pbc(particle_set(i_atom)%r(1:3), cell) - &
    2608      1449888 :                                     (pbc(particle_set(j_atom)%r(1:3), cell) + cell_vector(1:3))
    2609       362472 :                   abs_rab_cell_i = SQRT(rab_cell_i(1)**2 + rab_cell_i(2)**2 + rab_cell_i(3)**2)
    2610              : 
    2611              :                   ! minimum image convention
    2612       362472 :                   i_cell_is_the_minimum_image_cell = .TRUE.
    2613      3766872 :                   DO j_cell = 1, num_cells
    2614     54470400 :                      cell_vector_j(1:3) = MATMUL(hmat, REAL(index_to_cell(1:3, j_cell), dp))
    2615              :                      rab_cell_j(1:3) = pbc(particle_set(i_atom)%r(1:3), cell) - &
    2616     13617600 :                                        (pbc(particle_set(j_atom)%r(1:3), cell) + cell_vector_j(1:3))
    2617      3404400 :                      abs_rab_cell_j = SQRT(rab_cell_j(1)**2 + rab_cell_j(2)**2 + rab_cell_j(3)**2)
    2618              : 
    2619      3766872 :                      IF (abs_rab_cell_i > abs_rab_cell_j + 1.0E-6_dp) THEN
    2620       676826 :                         i_cell_is_the_minimum_image_cell = .FALSE.
    2621              :                      END IF
    2622              :                   END DO
    2623              : 
    2624       544096 :                   IF (i_cell_is_the_minimum_image_cell) THEN
    2625       181624 :                      i_mic_cell = i_cell
    2626              :                   END IF
    2627              : 
    2628              :                END DO ! i_cell
    2629              :             END IF
    2630              : 
    2631              :             arg = REAL(index_to_cell(1, i_mic_cell), dp)*kpoints%xkp(1, ikp) + &
    2632              :                   REAL(index_to_cell(2, i_mic_cell), dp)*kpoints%xkp(2, ikp) + &
    2633      1250267 :                   REAL(index_to_cell(3, i_mic_cell), dp)*kpoints%xkp(3, ikp)
    2634              : 
    2635              :             cfm_ikp%local_data(i_row, j_col) = COS(twopi*arg)*fm_Gamma%local_data(i_row, j_col)*z_one + &
    2636      1250267 :                                                SIN(twopi*arg)*fm_Gamma%local_data(i_row, j_col)*gaussi
    2637              : 
    2638      1250267 :             j_atom_old = j_atom
    2639      1343573 :             i_atom_old = i_atom
    2640              : 
    2641              :          END DO ! j_col
    2642              :       END DO ! i_row
    2643              : 
    2644         6338 :       CALL timestop(handle)
    2645              : 
    2646        19014 :    END SUBROUTINE cfm_ikp_from_fm_Gamma
    2647              : 
    2648              : ! **************************************************************************************************
    2649              : !> \brief ...
    2650              : !> \param bs_env ...
    2651              : !> \param qs_env ...
    2652              : !> \param fm_W_MIC_freq_j ...
    2653              : !> \param cfm_W_ikp_freq_j ...
    2654              : !> \param ikp ...
    2655              : !> \param kpoints ...
    2656              : !> \param basis_type ...
    2657              : !> \param wkp_ext ...
    2658              : ! **************************************************************************************************
    2659         2484 :    SUBROUTINE MIC_contribution_from_ikp(bs_env, qs_env, fm_W_MIC_freq_j, &
    2660              :                                         cfm_W_ikp_freq_j, ikp, kpoints, basis_type, wkp_ext)
    2661              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    2662              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2663              :       TYPE(cp_fm_type)                                   :: fm_W_MIC_freq_j
    2664              :       TYPE(cp_cfm_type)                                  :: cfm_W_ikp_freq_j
    2665              :       INTEGER, INTENT(IN)                                :: ikp
    2666              :       TYPE(kpoint_type), POINTER                         :: kpoints
    2667              :       CHARACTER(LEN=*)                                   :: basis_type
    2668              :       REAL(KIND=dp), OPTIONAL                            :: wkp_ext
    2669              : 
    2670              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'MIC_contribution_from_ikp'
    2671              : 
    2672              :       INTEGER                                            :: handle, i_bf, iatom, iatom_old, irow, &
    2673              :                                                             j_bf, jatom, jatom_old, jcol, n_bf, &
    2674              :                                                             ncol_local, nrow_local, num_cells
    2675         2484 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_from_bf_index
    2676         2484 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
    2677         2484 :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell
    2678              :       REAL(KIND=dp)                                      :: contribution, weight_im, weight_re, &
    2679              :                                                             wkp_of_ikp
    2680              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: hmat
    2681         2484 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: wkp
    2682         2484 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
    2683              :       TYPE(cell_type), POINTER                           :: cell
    2684         2484 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    2685              : 
    2686         2484 :       CALL timeset(routineN, handle)
    2687              : 
    2688              :       ! get number of basis functions (bf) for different basis sets
    2689         2484 :       IF (basis_type == "ORB") THEN
    2690           32 :          n_bf = qs_env%bs_env%n_ao
    2691         2452 :       ELSE IF (basis_type == "RI_AUX") THEN
    2692         2452 :          n_bf = qs_env%bs_env%n_RI
    2693              :       ELSE
    2694            0 :          CPABORT("Only ORB and RI_AUX basis implemented.")
    2695              :       END IF
    2696              : 
    2697         7452 :       ALLOCATE (atom_from_bf_index(n_bf))
    2698         2484 :       CALL get_atom_index_from_basis_function_index(qs_env, atom_from_bf_index, n_bf, basis_type)
    2699              : 
    2700         2484 :       NULLIFY (cell, particle_set)
    2701         2484 :       CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
    2702         2484 :       CALL get_cell(cell=cell, h=hmat)
    2703              : 
    2704              :       CALL cp_cfm_get_info(matrix=cfm_W_ikp_freq_j, &
    2705              :                            nrow_local=nrow_local, &
    2706              :                            ncol_local=ncol_local, &
    2707              :                            row_indices=row_indices, &
    2708         2484 :                            col_indices=col_indices)
    2709              : 
    2710         2484 :       CALL get_kpoint_info(kpoints, xkp=xkp, wkp=wkp)
    2711         2484 :       index_to_cell => kpoints%index_to_cell
    2712         2484 :       num_cells = SIZE(index_to_cell, 2)
    2713              : 
    2714         2484 :       iatom_old = 0
    2715         2484 :       jatom_old = 0
    2716              : 
    2717        56384 :       DO jcol = 1, ncol_local
    2718      1066438 :          DO irow = 1, nrow_local
    2719              : 
    2720      1010054 :             i_bf = row_indices(irow)
    2721      1010054 :             j_bf = col_indices(jcol)
    2722              : 
    2723      1010054 :             iatom = atom_from_bf_index(i_bf)
    2724      1010054 :             jatom = atom_from_bf_index(j_bf)
    2725              : 
    2726      1010054 :             IF (PRESENT(wkp_ext)) THEN
    2727         3496 :                wkp_of_ikp = wkp_ext
    2728              :             ELSE
    2729      1040270 :                SELECT CASE (bs_env%l_RI(i_bf) + bs_env%l_RI(j_bf))
    2730              :                CASE (0)
    2731              :                   ! both RI functions are s-functions, k-extrapolation for 2D and 3D
    2732        33712 :                   wkp_of_ikp = wkp(ikp)
    2733              :                CASE (1)
    2734              :                   ! one function is an s-function, the other a p-function, k-extrapolation for 3D
    2735       144552 :                   wkp_of_ikp = bs_env%wkp_s_p(ikp)
    2736              :                CASE DEFAULT
    2737              :                   ! for any other matrix element of W, there is no need for extrapolation
    2738      1006558 :                   wkp_of_ikp = bs_env%wkp_no_extra(ikp)
    2739              :                END SELECT
    2740              :             END IF
    2741              : 
    2742      1010054 :             IF (iatom /= iatom_old .OR. jatom /= jatom_old) THEN
    2743              : 
    2744              :                CALL compute_weight_re_im(weight_re, weight_im, &
    2745              :                                          num_cells, iatom, jatom, xkp(1:3, ikp), wkp_of_ikp, &
    2746       104552 :                                          cell, index_to_cell, hmat, particle_set)
    2747              : 
    2748       104552 :                iatom_old = iatom
    2749       104552 :                jatom_old = jatom
    2750              : 
    2751              :             END IF
    2752              : 
    2753              :             contribution = weight_re*REAL(cfm_W_ikp_freq_j%local_data(irow, jcol)) + &
    2754      1010054 :                            weight_im*AIMAG(cfm_W_ikp_freq_j%local_data(irow, jcol))
    2755              : 
    2756              :             fm_W_MIC_freq_j%local_data(irow, jcol) = fm_W_MIC_freq_j%local_data(irow, jcol) &
    2757      1063954 :                                                      + contribution
    2758              : 
    2759              :          END DO
    2760              :       END DO
    2761              : 
    2762         2484 :       CALL timestop(handle)
    2763              : 
    2764         7452 :    END SUBROUTINE MIC_contribution_from_ikp
    2765              : 
    2766              : ! **************************************************************************************************
    2767              : !> \brief ...
    2768              : !> \param xkp ...
    2769              : !> \param ikp_start ...
    2770              : !> \param ikp_end ...
    2771              : !> \param grid ...
    2772              : ! **************************************************************************************************
    2773          142 :    SUBROUTINE compute_xkp(xkp, ikp_start, ikp_end, grid)
    2774              : 
    2775              :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
    2776              :       INTEGER                                            :: ikp_start, ikp_end
    2777              :       INTEGER, DIMENSION(3)                              :: grid
    2778              : 
    2779              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'compute_xkp'
    2780              : 
    2781              :       INTEGER                                            :: handle, i, ix, iy, iz
    2782              : 
    2783          142 :       CALL timeset(routineN, handle)
    2784              : 
    2785          142 :       i = ikp_start
    2786          312 :       DO ix = 1, grid(1)
    2787          674 :          DO iy = 1, grid(2)
    2788         1240 :             DO iz = 1, grid(3)
    2789              : 
    2790          708 :                IF (i > ikp_end) CYCLE
    2791              : 
    2792          690 :                xkp(1, i) = REAL(2*ix - grid(1) - 1, KIND=dp)/(2._dp*REAL(grid(1), KIND=dp))
    2793          690 :                xkp(2, i) = REAL(2*iy - grid(2) - 1, KIND=dp)/(2._dp*REAL(grid(2), KIND=dp))
    2794          690 :                xkp(3, i) = REAL(2*iz - grid(3) - 1, KIND=dp)/(2._dp*REAL(grid(3), KIND=dp))
    2795         1070 :                i = i + 1
    2796              : 
    2797              :             END DO
    2798              :          END DO
    2799              :       END DO
    2800              : 
    2801          142 :       CALL timestop(handle)
    2802              : 
    2803          142 :    END SUBROUTINE compute_xkp
    2804              : 
    2805              : ! **************************************************************************************************
    2806              : !> \brief ...
    2807              : !> \param kpoints ...
    2808              : !> \param qs_env ...
    2809              : ! **************************************************************************************************
    2810          212 :    SUBROUTINE kpoint_init_cell_index_simple(kpoints, qs_env)
    2811              : 
    2812              :       TYPE(kpoint_type), POINTER                         :: kpoints
    2813              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2814              : 
    2815              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_init_cell_index_simple'
    2816              : 
    2817              :       INTEGER                                            :: handle, nimages
    2818              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2819              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    2820          106 :          POINTER                                         :: sab_orb
    2821              : 
    2822          106 :       CALL timeset(routineN, handle)
    2823              : 
    2824          106 :       NULLIFY (para_env, sab_orb)
    2825          106 :       CALL get_qs_env(qs_env=qs_env, para_env=para_env, sab_orb=sab_orb)
    2826          106 :       CALL kpoint_init_cell_index(kpoints, sab_orb, para_env, nimages)
    2827              : 
    2828          106 :       CALL timestop(handle)
    2829              : 
    2830          106 :    END SUBROUTINE kpoint_init_cell_index_simple
    2831              : 
    2832              : ! **************************************************************************************************
    2833              : !> \brief ...
    2834              : !> \param qs_env ...
    2835              : !> \param bs_env ...
    2836              : ! **************************************************************************************************
    2837           22 :    SUBROUTINE soc(qs_env, bs_env)
    2838              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2839              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    2840              : 
    2841              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'soc'
    2842              : 
    2843              :       INTEGER                                            :: handle
    2844              : 
    2845           22 :       CALL timeset(routineN, handle)
    2846              : 
    2847              :       ! V^SOC_µν^(α),R = ħ/2 < ϕ_µ cell O | sum_ℓ ΔV_ℓ^SO(r,r') L^(α) | ϕ_ν cell R>, α = x,y,z
    2848              :       ! see Hartwigsen, Goedecker, Hutter, Eq.(18), (19) (doi.org/10.1103/PhysRevB.58.3641)
    2849           22 :       CALL V_SOC_xyz_from_pseudopotential(qs_env, bs_env%mat_V_SOC_xyz)
    2850              : 
    2851              :       ! Calculate H^SOC_µν,σσ'(k) = sum_α V^SOC_µν^(α)(k)*Pauli-matrix^(α)_σσ'
    2852              :       ! see Hartwigsen, Goedecker, Hutter, Eq.(18) (doi.org/10.1103/PhysRevB.58.3641)
    2853           28 :       SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
    2854              :       CASE (large_cell_Gamma, large_cell_Gamma_ri_rs, non_periodic_ri_rs)
    2855              : 
    2856              :          ! H^SOC_µν,σσ' = sum_α V^SOC_µν^(α)*Pauli-matrix^(α)_σσ'
    2857            6 :          CALL H_KS_spinor_Gamma(bs_env)
    2858              : 
    2859              :       CASE (small_cell_full_kp)
    2860              : 
    2861              :          ! V^SOC_µν^(α),R -> V^SOC_µν^(α)(k); then calculate spinor H^SOC_µν,σσ'(k) (see above)
    2862           22 :          CALL H_KS_spinor_kp(qs_env, bs_env)
    2863              : 
    2864              :       END SELECT
    2865              : 
    2866           22 :       CALL timestop(handle)
    2867              : 
    2868           22 :    END SUBROUTINE soc
    2869              : 
    2870              : ! **************************************************************************************************
    2871              : !> \brief ...
    2872              : !> \param bs_env ...
    2873              : ! **************************************************************************************************
    2874            6 :    SUBROUTINE H_KS_spinor_Gamma(bs_env)
    2875              : 
    2876              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    2877              : 
    2878              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'H_KS_spinor_Gamma'
    2879              : 
    2880              :       INTEGER                                            :: handle, nao, s
    2881              :       TYPE(cp_fm_struct_type), POINTER                   :: str
    2882              : 
    2883            6 :       CALL timeset(routineN, handle)
    2884              : 
    2885            6 :       CALL cp_fm_get_info(bs_env%fm_ks_Gamma(1), nrow_global=nao)
    2886              : 
    2887           12 :       ALLOCATE (bs_env%cfm_SOC_spinor_ao(1))
    2888            6 :       CALL create_cfm_double(bs_env%cfm_SOC_spinor_ao(1), fm_orig=bs_env%fm_ks_Gamma(1))
    2889            6 :       CALL cp_cfm_set_all(bs_env%cfm_SOC_spinor_ao(1), z_zero)
    2890              : 
    2891            6 :       str => bs_env%fm_ks_Gamma(1)%matrix_struct
    2892              : 
    2893            6 :       s = nao + 1
    2894              : 
    2895              :       ! careful: inside add_dbcsr_submat, mat_V_SOC_xyz is multiplied by i because the real matrix
    2896              :       !          mat_V_SOC_xyz is antisymmetric as V_SOC matrix is purely imaginary and Hermitian
    2897              :       ! V_x * sigma_x: sigma_x = ((0,1),(1,0))
    2898              :       ! ud block (1,s): +i*V_x
    2899              :       CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(1, 1)%matrix, &
    2900            6 :                             str, 1, s, z_one, .FALSE.)
    2901              :       ! du block (s,1): +i*V_x
    2902              :       CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(1, 1)%matrix, &
    2903            6 :                             str, s, 1, z_one, .FALSE.)
    2904              : 
    2905              :       ! V_y * sigma_y: sigma_y = ((0,-i),(i,0))
    2906              :       ! ud block (1,s): i*(i*V_y) = -V_y  (extra gaussi factor)
    2907              :       CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(2, 1)%matrix, &
    2908            6 :                             str, 1, s, gaussi, .FALSE.)
    2909              :       ! du block (s,1): -i*(i*V_y) = +V_y  (extra -gaussi factor)
    2910              :       CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(2, 1)%matrix, &
    2911            6 :                             str, s, 1, -gaussi, .FALSE.)
    2912              : 
    2913              :       ! V_z * sigma_z: sigma_z = ((1,0),(0,-1))
    2914              :       ! uu block (1,1): +i*V_z
    2915              :       CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(3, 1)%matrix, &
    2916            6 :                             str, 1, 1, z_one, .FALSE.)
    2917              :       ! dd block (s,s): -i*V_z
    2918              :       CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(3, 1)%matrix, &
    2919            6 :                             str, s, s, -z_one, .FALSE.)
    2920              : 
    2921            6 :       CALL timestop(handle)
    2922              : 
    2923            6 :    END SUBROUTINE H_KS_spinor_Gamma
    2924              : 
    2925              : ! **************************************************************************************************
    2926              : !> \brief ...
    2927              : !> \param qs_env ...
    2928              : !> \param bs_env ...
    2929              : ! **************************************************************************************************
    2930           32 :    SUBROUTINE H_KS_spinor_kp(qs_env, bs_env)
    2931              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2932              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    2933              : 
    2934              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'H_KS_spinor_kp'
    2935              : 
    2936              :       INTEGER                                            :: handle, i_dim, ikp, n_spin, &
    2937              :                                                             nkp_bs_and_DOS, s
    2938           16 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index_scf
    2939              :       REAL(KIND=dp), DIMENSION(3)                        :: xkp
    2940              :       TYPE(cp_cfm_type)                                  :: cfm_V_SOC_xyz_ikp
    2941              :       TYPE(cp_fm_struct_type), POINTER                   :: str
    2942              :       TYPE(kpoint_type), POINTER                         :: kpoints_scf
    2943              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    2944           16 :          POINTER                                         :: sab_nl
    2945              : 
    2946           16 :       CALL timeset(routineN, handle)
    2947              : 
    2948           16 :       nkp_bs_and_DOS = bs_env%nkp_bs_and_DOS
    2949           16 :       n_spin = bs_env%n_spin
    2950           16 :       s = bs_env%n_ao + 1
    2951           16 :       str => bs_env%cfm_ks_kp(1, 1)%matrix_struct
    2952              : 
    2953           16 :       CALL cp_cfm_create(cfm_V_SOC_xyz_ikp, bs_env%cfm_work_mo%matrix_struct)
    2954              : 
    2955           16 :       CALL alloc_cfm_double_array_1d(bs_env%cfm_SOC_spinor_ao, bs_env%cfm_ks_kp(1, 1), nkp_bs_and_DOS)
    2956              : 
    2957           16 :       CALL get_qs_env(qs_env, kpoints=kpoints_scf)
    2958              : 
    2959           16 :       NULLIFY (sab_nl)
    2960           16 :       CALL get_kpoint_info(kpoints_scf, sab_nl=sab_nl, cell_to_index=cell_to_index_scf)
    2961              : 
    2962           64 :       DO i_dim = 1, 3
    2963              : 
    2964         1018 :          DO ikp = 1, nkp_bs_and_DOS
    2965              : 
    2966         3816 :             xkp(1:3) = bs_env%kpoints_DOS%xkp(1:3, ikp)
    2967              : 
    2968          954 :             CALL cp_cfm_set_all(cfm_V_SOC_xyz_ikp, z_zero)
    2969              : 
    2970              :             CALL rsmat_to_kp(bs_env%mat_V_SOC_xyz, i_dim, xkp, cell_to_index_scf, &
    2971          954 :                              sab_nl, bs_env, cfm_V_SOC_xyz_ikp, imag_rs_mat=.TRUE.)
    2972              : 
    2973              :             ! multiply V_SOC with i because bs_env%mat_V_SOC_xyz stores imag. part (real part = 0)
    2974          954 :             CALL cp_cfm_scale(gaussi, cfm_V_SOC_xyz_ikp)
    2975              : 
    2976           48 :             SELECT CASE (i_dim)
    2977              :             CASE (1)
    2978              :                ! add V^SOC_x * σ_x for σ_x = ( (0,1) (1,0) )
    2979          318 :                CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_V_SOC_xyz_ikp, 1, s)
    2980          318 :                CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_V_SOC_xyz_ikp, s, 1)
    2981              :             CASE (2)
    2982              :                ! add V^SOC_y * σ_y for σ_y = ( (0,-i) (i,0) )
    2983          318 :                CALL cp_cfm_scale(gaussi, cfm_V_SOC_xyz_ikp)
    2984          318 :                CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_V_SOC_xyz_ikp, 1, s)
    2985          318 :                CALL cp_cfm_scale(-z_one, cfm_V_SOC_xyz_ikp)
    2986          318 :                CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_V_SOC_xyz_ikp, s, 1)
    2987              :             CASE (3)
    2988              :                ! add V^SOC_z * σ_z for σ_z = ( (1,0) (0,1) )
    2989          318 :                CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_V_SOC_xyz_ikp, 1, 1)
    2990          318 :                CALL cp_cfm_scale(-z_one, cfm_V_SOC_xyz_ikp)
    2991         1272 :                CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_V_SOC_xyz_ikp, s, s)
    2992              :             END SELECT
    2993              : 
    2994              :          END DO
    2995              : 
    2996              :       END DO ! ikp
    2997              : 
    2998           16 :       CALL cp_cfm_release(cfm_V_SOC_xyz_ikp)
    2999              : 
    3000           16 :       CALL timestop(handle)
    3001              : 
    3002           16 :    END SUBROUTINE H_KS_spinor_kp
    3003              : 
    3004              : ! **************************************************************************************************
    3005              : !> \brief ...
    3006              : !> \param cfm_array ...
    3007              : !> \param cfm_template ...
    3008              : !> \param n ...
    3009              : ! **************************************************************************************************
    3010           16 :    SUBROUTINE alloc_cfm_double_array_1d(cfm_array, cfm_template, n)
    3011              :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:)       :: cfm_array
    3012              :       TYPE(cp_cfm_type)                                  :: cfm_template
    3013              :       INTEGER                                            :: n
    3014              : 
    3015              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'alloc_cfm_double_array_1d'
    3016              : 
    3017              :       INTEGER                                            :: handle, i
    3018              : 
    3019           16 :       CALL timeset(routineN, handle)
    3020              : 
    3021          366 :       ALLOCATE (cfm_array(n))
    3022          334 :       DO i = 1, n
    3023          318 :          CALL create_cfm_double(cfm_array(i), cfm_orig=cfm_template)
    3024          334 :          CALL cp_cfm_set_all(cfm_array(i), z_zero)
    3025              :       END DO
    3026              : 
    3027           16 :       CALL timestop(handle)
    3028              : 
    3029           16 :    END SUBROUTINE alloc_cfm_double_array_1d
    3030              : 
    3031              : ! **************************************************************************************************
    3032              : !> \brief ...
    3033              : !> \param bs_env ...
    3034              : ! **************************************************************************************************
    3035          136 :    SUBROUTINE get_all_VBM_CBM_bandgaps(bs_env)
    3036              : 
    3037              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    3038              : 
    3039              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'get_all_VBM_CBM_bandgaps'
    3040              : 
    3041              :       INTEGER                                            :: handle
    3042              : 
    3043          136 :       CALL timeset(routineN, handle)
    3044              : 
    3045          136 :       CALL get_VBM_CBM_bandgaps(bs_env%band_edges_scf, bs_env%eigenval_scf, bs_env)
    3046          136 :       CALL get_VBM_CBM_bandgaps(bs_env%band_edges_GW, bs_env%eigenval_GW, bs_env)
    3047          136 :       CALL get_VBM_CBM_bandgaps(bs_env%band_edges_HF, bs_env%eigenval_HF, bs_env)
    3048              : 
    3049          136 :       CALL check_qp_gap_sanity(bs_env)
    3050              : 
    3051          136 :       CALL check_scf_gw_level_ordering(bs_env)
    3052              : 
    3053          136 :       CALL timestop(handle)
    3054              : 
    3055          136 :    END SUBROUTINE get_all_VBM_CBM_bandgaps
    3056              : 
    3057              : ! **************************************************************************************************
    3058              : !> \brief Warn if the GW fundamental band gap is inverted or implausibly large, i.e. if the
    3059              : !>        quasiparticle solve has produced a spectrum that cannot be physical.
    3060              : !> \param bs_env ...
    3061              : ! **************************************************************************************************
    3062          136 :    SUBROUTINE check_qp_gap_sanity(bs_env)
    3063              : 
    3064              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    3065              : 
    3066              :       CHARACTER(LEN=default_string_length)               :: gw_label
    3067              :       REAL(KIND=dp)                                      :: gap, gap_scf
    3068              : 
    3069          136 :       gap = bs_env%band_edges_GW%IDBG
    3070          136 :       gap_scf = bs_env%band_edges_scf%IDBG
    3071          136 :       gw_label = gw_flavour_label(bs_env)
    3072              : 
    3073              :       ! requiring a healthy SCF gap keeps the inversion test from firing on a genuine metal
    3074          136 :       IF (gap < -eps_qp_gap .AND. gap_scf > eps_qp_gap) THEN
    3075              :          CALL cp_warn(__LOCATION__, &
    3076              :                       TRIM(gw_label)//" band gap is negative ("// &
    3077              :                       TRIM(ADJUSTL(cp_to_string(gap*evolt, '(F12.3)')))//" eV): the quasiparticle "// &
    3078            0 :                       "spectrum is inverted. Check numerical parameters.")
    3079          136 :       ELSE IF (ABS(gap) > max_qp_gap) THEN
    3080              :          CALL cp_warn(__LOCATION__, &
    3081              :                       TRIM(gw_label)//" band gap is implausibly large ("// &
    3082              :                       TRIM(ADJUSTL(cp_to_string(gap*evolt, '(F12.3)')))//" eV): the quasiparticle "// &
    3083            0 :                       "solve has likely diverged. Check numerical parameters.")
    3084              :       END IF
    3085              : 
    3086          136 :    END SUBROUTINE check_qp_gap_sanity
    3087              : 
    3088              : ! **************************************************************************************************
    3089              : !> \brief Check whether the GW correction reorders the frontier levels with respect to the SCF
    3090              : !>        eigenvalues, i.e. whether the SCF HOMO (LUMO) is a different level than the GW HOMO
    3091              : !>        (LUMO). If so, the SCF and GW band edges printed afterwards belong to different
    3092              : !>        orbitals, which is easily overlooked => warn.
    3093              : !>        Levels closer than eps_degeneracy in the SCF spectrum count as degenerate, i.e. their
    3094              : !>        reordering by GW is not reported.
    3095              : !> \param bs_env ...
    3096              : ! **************************************************************************************************
    3097          136 :    SUBROUTINE check_scf_gw_level_ordering(bs_env)
    3098              : 
    3099              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    3100              : 
    3101              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'check_scf_gw_level_ordering'
    3102              :       REAL(KIND=dp), PARAMETER                           :: eps_degeneracy = 1.0E-05_dp
    3103              : 
    3104              :       CHARACTER(LEN=default_string_length)               :: gw_label, level_gw, level_scf, &
    3105              :                                                             spin_string
    3106              :       CHARACTER(LEN=max_line_length)                     :: msg
    3107              :       INTEGER                                            :: handle, homo, ispin, n_mo
    3108              :       INTEGER, DIMENSION(2)                              :: loc_gw, loc_scf
    3109              : 
    3110          136 :       CALL timeset(routineN, handle)
    3111              : 
    3112          136 :       n_mo = bs_env%n_ao
    3113          136 :       gw_label = gw_flavour_label(bs_env)
    3114              : 
    3115          294 :       DO ispin = 1, bs_env%n_spin
    3116              : 
    3117          158 :          homo = bs_env%n_occ(ispin)
    3118              : 
    3119          158 :          IF (bs_env%n_spin == 2) THEN
    3120           44 :             WRITE (spin_string, '(A,I0,A)') " (spin ", ispin, ")"
    3121              :          ELSE
    3122          114 :             spin_string = ""
    3123              :          END IF
    3124              : 
    3125              :          ! occupied levels: level carrying the SCF VBM versus level carrying the GW VBM
    3126         2680 :          loc_scf(:) = MAXLOC(bs_env%eigenval_scf(1:homo, :, ispin))
    3127         2680 :          loc_gw(:) = MAXLOC(bs_env%eigenval_GW(1:homo, :, ispin))
    3128              : 
    3129              :          ! only report a genuine reordering, not a permutation within a degenerate SCF shell
    3130          158 :          IF (bs_env%eigenval_scf(loc_scf(1), loc_scf(2), ispin) - &
    3131              :              bs_env%eigenval_scf(loc_gw(1), loc_gw(2), ispin) > eps_degeneracy) THEN
    3132              : 
    3133            2 :             CALL level_string(level_scf, loc_scf, bs_env)
    3134            2 :             CALL level_string(level_gw, loc_gw, bs_env)
    3135              : 
    3136              :             msg = TRIM(gw_label)//" reorders the occupied levels"//TRIM(spin_string)// &
    3137              :                   ": the SCF valence band maximum (SCF HOMO) is "//TRIM(level_scf)// &
    3138              :                   ", whereas the "//TRIM(gw_label)//" valence band maximum ("// &
    3139              :                   TRIM(gw_label)//" HOMO) is "//TRIM(level_gw)//". The SCF and "// &
    3140              :                   TRIM(gw_label)//" band edges printed below therefore belong to different "// &
    3141            2 :                   "orbitals; see the eigenvalues in the file bandstructure_SCF_and_G0W0."
    3142            2 :             CPWARN(TRIM(msg))
    3143              : 
    3144              :          END IF
    3145              : 
    3146              :          ! empty levels: level carrying the SCF CBM versus level carrying the GW CBM
    3147         4756 :          loc_scf(:) = MINLOC(bs_env%eigenval_scf(homo + 1:n_mo, :, ispin))
    3148         4756 :          loc_gw(:) = MINLOC(bs_env%eigenval_GW(homo + 1:n_mo, :, ispin))
    3149          158 :          loc_scf(1) = loc_scf(1) + homo
    3150          158 :          loc_gw(1) = loc_gw(1) + homo
    3151              : 
    3152          158 :          IF (bs_env%eigenval_scf(loc_gw(1), loc_gw(2), ispin) - &
    3153          136 :              bs_env%eigenval_scf(loc_scf(1), loc_scf(2), ispin) > eps_degeneracy) THEN
    3154              : 
    3155            0 :             CALL level_string(level_scf, loc_scf, bs_env)
    3156            0 :             CALL level_string(level_gw, loc_gw, bs_env)
    3157              : 
    3158              :             msg = TRIM(gw_label)//" reorders the empty levels"//TRIM(spin_string)// &
    3159              :                   ": the SCF conduction band minimum (SCF LUMO) is "//TRIM(level_scf)// &
    3160              :                   ", whereas the "//TRIM(gw_label)//" conduction band minimum ("// &
    3161              :                   TRIM(gw_label)//" LUMO) is "//TRIM(level_gw)//". The SCF and "// &
    3162              :                   TRIM(gw_label)//" band edges printed below therefore belong to different "// &
    3163            0 :                   "orbitals; see the eigenvalues in the file bandstructure_SCF_and_G0W0."
    3164            0 :             CPWARN(TRIM(msg))
    3165              : 
    3166              :          END IF
    3167              : 
    3168              :       END DO
    3169              : 
    3170          136 :       CALL timestop(handle)
    3171              : 
    3172          136 :    END SUBROUTINE check_scf_gw_level_ordering
    3173              : 
    3174              : ! **************************************************************************************************
    3175              : !> \brief Human readable name of the level (i_mo, ikp) given as loc = [i_mo, ikp]
    3176              : !> \param string ...
    3177              : !> \param loc ...
    3178              : !> \param bs_env ...
    3179              : ! **************************************************************************************************
    3180            4 :    SUBROUTINE level_string(string, loc, bs_env)
    3181              : 
    3182              :       CHARACTER(LEN=*), INTENT(OUT)                      :: string
    3183              :       INTEGER, DIMENSION(2), INTENT(IN)                  :: loc
    3184              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    3185              : 
    3186            4 :       IF (bs_env%nkp_bs_and_DOS > 1) THEN
    3187            4 :          WRITE (string, '(A,I0,A,I0)') "level ", loc(1), " at k-point ", loc(2)
    3188              :       ELSE
    3189            0 :          WRITE (string, '(A,I0)') "level ", loc(1)
    3190              :       END IF
    3191              : 
    3192            4 :    END SUBROUTINE level_string
    3193              : 
    3194              : ! **************************************************************************************************
    3195              : !> \brief ...
    3196              : !> \param band_edges ...
    3197              : !> \param ev ...
    3198              : !> \param bs_env ...
    3199              : ! **************************************************************************************************
    3200          426 :    SUBROUTINE get_VBM_CBM_bandgaps(band_edges, ev, bs_env)
    3201              :       TYPE(band_edges_type)                              :: band_edges
    3202              :       REAL(KIND=dp), DIMENSION(:, :, :)                  :: ev
    3203              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    3204              : 
    3205              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'get_VBM_CBM_bandgaps'
    3206              : 
    3207              :       INTEGER                                            :: handle, homo, homo_1, homo_2, ikp, &
    3208              :                                                             ispin, lumo, lumo_1, lumo_2, n_mo
    3209              :       REAL(KIND=dp)                                      :: E_DBG_at_ikp
    3210              : 
    3211          426 :       CALL timeset(routineN, handle)
    3212              : 
    3213          426 :       n_mo = bs_env%n_ao
    3214              : 
    3215          426 :       band_edges%DBG = 1000.0_dp
    3216              : 
    3217          786 :       SELECT CASE (bs_env%n_spin)
    3218              :       CASE (1)
    3219          360 :          homo = bs_env%n_occ(1)
    3220          360 :          lumo = homo + 1
    3221         7886 :          band_edges%VBM = MAXVAL(ev(1:homo, :, 1))
    3222        15336 :          band_edges%CBM = MINVAL(ev(homo + 1:n_mo, :, 1))
    3223              :       CASE (2)
    3224           66 :          homo_1 = bs_env%n_occ(1)
    3225           66 :          lumo_1 = homo_1 + 1
    3226           66 :          homo_2 = bs_env%n_occ(2)
    3227           66 :          lumo_2 = homo_2 + 1
    3228          918 :          band_edges%VBM = MAX(MAXVAL(ev(1:homo_1, :, 1)), MAXVAL(ev(1:homo_2, :, 2)))
    3229         1134 :          band_edges%CBM = MIN(MINVAL(ev(homo_1 + 1:n_mo, :, 1)), MINVAL(ev(homo_2 + 1:n_mo, :, 2)))
    3230              :       CASE DEFAULT
    3231          426 :          CPABORT("Error with number of spins.")
    3232              :       END SELECT
    3233              : 
    3234          426 :       band_edges%IDBG = band_edges%CBM - band_edges%VBM
    3235              : 
    3236          918 :       DO ispin = 1, bs_env%n_spin
    3237              : 
    3238          492 :          homo = bs_env%n_occ(ispin)
    3239              : 
    3240         2686 :          DO ikp = 1, bs_env%nkp_bs_and_DOS
    3241              : 
    3242        22654 :             E_DBG_at_ikp = -MAXVAL(ev(1:homo, ikp, ispin)) + MINVAL(ev(homo + 1:n_mo, ikp, ispin))
    3243              : 
    3244         2260 :             IF (E_DBG_at_ikp < band_edges%DBG) band_edges%DBG = E_DBG_at_ikp
    3245              : 
    3246              :          END DO
    3247              : 
    3248              :       END DO
    3249              : 
    3250          426 :       CALL timestop(handle)
    3251              : 
    3252          426 :    END SUBROUTINE get_VBM_CBM_bandgaps
    3253              : 
    3254              : END MODULE post_scf_bandstructure_utils
        

Generated by: LCOV version 2.0-1