LCOV - code coverage report
Current view: top level - src - gw_utils.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:b1f098b) Lines: 595 624 95.4 %
Date: 2024-05-05 06:30:09 Functions: 24 25 96.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 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 gw_utils
      14             :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      15             :                                               get_atomic_kind_set
      16             :    USE basis_set_types,                 ONLY: gto_basis_set_type
      17             :    USE bibliography,                    ONLY: Graml2024,&
      18             :                                               cite_reference
      19             :    USE cell_types,                      ONLY: cell_type,&
      20             :                                               pbc
      21             :    USE cp_blacs_env,                    ONLY: cp_blacs_env_create,&
      22             :                                               cp_blacs_env_release,&
      23             :                                               cp_blacs_env_type
      24             :    USE cp_control_types,                ONLY: dft_control_type
      25             :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      26             :                                               dbcsr_allocate_matrix_set,&
      27             :                                               dbcsr_deallocate_matrix_set
      28             :    USE cp_fm_basic_linalg,              ONLY: cp_fm_scale_and_add
      29             :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      30             :                                               cp_fm_struct_release,&
      31             :                                               cp_fm_struct_type
      32             :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      33             :                                               cp_fm_set_all
      34             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      35             :                                               cp_logger_type
      36             :    USE cp_output_handling,              ONLY: cp_print_key_generate_filename
      37             :    USE dbcsr_api,                       ONLY: dbcsr_create,&
      38             :                                               dbcsr_p_type
      39             :    USE dbt_api,                         ONLY: &
      40             :         dbt_clear, dbt_create, dbt_destroy, dbt_filter, dbt_iterator_blocks_left, &
      41             :         dbt_iterator_next_block, dbt_iterator_start, dbt_iterator_stop, dbt_iterator_type, &
      42             :         dbt_mp_environ_pgrid, dbt_pgrid_create, dbt_pgrid_destroy, dbt_pgrid_type, dbt_type
      43             :    USE input_constants,                 ONLY: do_potential_truncated,&
      44             :                                               xc_none
      45             :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      46             :                                               section_vals_type,&
      47             :                                               section_vals_val_get,&
      48             :                                               section_vals_val_set
      49             :    USE kinds,                           ONLY: default_string_length,&
      50             :                                               dp,&
      51             :                                               int_8
      52             :    USE kpoint_methods,                  ONLY: kpoint_init_cell_index
      53             :    USE kpoint_types,                    ONLY: kpoint_create,&
      54             :                                               kpoint_type
      55             :    USE libint_wrapper,                  ONLY: cp_libint_static_cleanup,&
      56             :                                               cp_libint_static_init
      57             :    USE machine,                         ONLY: m_memory,&
      58             :                                               m_walltime
      59             :    USE mathlib,                         ONLY: gcd
      60             :    USE message_passing,                 ONLY: mp_cart_type,&
      61             :                                               mp_para_env_type
      62             :    USE minimax_exp,                     ONLY: get_exp_minimax_coeff
      63             :    USE minimax_exp_gw,                  ONLY: get_exp_minimax_coeff_gw
      64             :    USE minimax_rpa,                     ONLY: get_rpa_minimax_coeff,&
      65             :                                               get_rpa_minimax_coeff_larger_grid
      66             :    USE mp2_gpw,                         ONLY: create_mat_munu
      67             :    USE mp2_grids,                       ONLY: get_l_sq_wghts_cos_tf_t_to_w,&
      68             :                                               get_l_sq_wghts_cos_tf_w_to_t,&
      69             :                                               get_l_sq_wghts_sin_tf_t_to_w
      70             :    USE mp2_ri_2c,                       ONLY: setup_trunc_coulomb_pot_for_exchange_self_energy
      71             :    USE particle_methods,                ONLY: get_particle_set
      72             :    USE particle_types,                  ONLY: particle_type
      73             :    USE physcon,                         ONLY: angstrom,&
      74             :                                               evolt
      75             :    USE post_scf_bandstructure_types,    ONLY: post_scf_bandstructure_type
      76             :    USE qs_energy_types,                 ONLY: qs_energy_type
      77             :    USE qs_environment_types,            ONLY: get_qs_env,&
      78             :                                               qs_env_part_release,&
      79             :                                               qs_environment_type
      80             :    USE qs_integral_utils,               ONLY: basis_set_list_setup
      81             :    USE qs_interactions,                 ONLY: init_interaction_radii_orb_basis
      82             :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      83             :                                               qs_kind_type
      84             :    USE qs_ks_methods,                   ONLY: qs_ks_build_kohn_sham_matrix
      85             :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      86             :    USE qs_tensors,                      ONLY: build_3c_integrals,&
      87             :                                               build_3c_neighbor_lists,&
      88             :                                               get_tensor_occupancy,&
      89             :                                               neighbor_list_3c_destroy
      90             :    USE qs_tensors_types,                ONLY: create_2c_tensor,&
      91             :                                               create_3c_tensor,&
      92             :                                               distribution_3d_create,&
      93             :                                               distribution_3d_type,&
      94             :                                               neighbor_list_3c_type
      95             : #include "base/base_uses.f90"
      96             : 
      97             :    IMPLICIT NONE
      98             : 
      99             :    PRIVATE
     100             : 
     101             :    PUBLIC :: create_and_init_bs_env_for_gw, de_init_bs_env, get_i_j_atoms, &
     102             :              kpoint_init_cell_index_simple, compute_xkp
     103             : 
     104             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'gw_utils'
     105             : 
     106             : CONTAINS
     107             : 
     108             : ! **************************************************************************************************
     109             : !> \brief ...
     110             : !> \param qs_env ...
     111             : !> \param bs_env ...
     112             : !> \param bs_sec ...
     113             : ! **************************************************************************************************
     114          18 :    SUBROUTINE create_and_init_bs_env_for_gw(qs_env, bs_env, bs_sec)
     115             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     116             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     117             :       TYPE(section_vals_type), POINTER                   :: bs_sec
     118             : 
     119             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'create_and_init_bs_env_for_gw'
     120             : 
     121             :       INTEGER                                            :: handle
     122             : 
     123          18 :       CALL timeset(routineN, handle)
     124             : 
     125          18 :       CALL cite_reference(Graml2024)
     126             : 
     127          18 :       CALL read_gw_input_parameters(bs_env, bs_sec)
     128             : 
     129          18 :       CALL print_header_and_input_parameters(bs_env)
     130             : 
     131          18 :       CALL setup_AO_and_RI_basis_set(qs_env, bs_env)
     132             : 
     133          18 :       CALL get_RI_basis_and_basis_function_indices(qs_env, bs_env)
     134             : 
     135          18 :       CALL setup_kpoints_chi_eps_W(qs_env, bs_env, bs_env%kpoints_chi_eps_W)
     136             : 
     137          18 :       CALL set_heuristic_parameters(bs_env, qs_env)
     138             : 
     139          18 :       CALL set_parallelization_parameters(qs_env, bs_env)
     140             : 
     141          18 :       CALL allocate_and_fill_matrices_and_arrays(qs_env, bs_env)
     142             : 
     143          18 :       CALL cp_libint_static_init()
     144             : 
     145          18 :       CALL create_tensors(qs_env, bs_env)
     146             : 
     147          18 :       CALL set_sparsity_parallelization_parameters(bs_env)
     148             : 
     149          18 :       CALL check_for_restart_files(qs_env, bs_env)
     150             : 
     151          18 :       CALL compute_fm_V_xc_Gamma(qs_env, bs_env)
     152             : 
     153          18 :       CALL setup_time_and_frequency_minimax_grid(bs_env)
     154             : 
     155             :       ! free memory in qs_env; only if one is not calculating the LDOS because
     156             :       ! we need real-space grid operations in pw_env, task_list for the LDOS
     157             :       ! Recommendation in case of memory issues: first perform GW calculation without calculating
     158             :       !                                          LDOS (to safe memor). Then, use GW restart files
     159             :       !                                          in a subsequent calculation to calculate the LDOS
     160          18 :       IF (.NOT. bs_env%do_ldos) THEN
     161          14 :          CALL qs_env_part_release(qs_env)
     162             :       END IF
     163             : 
     164          18 :       CALL timestop(handle)
     165             : 
     166          18 :    END SUBROUTINE create_and_init_bs_env_for_gw
     167             : 
     168             : ! **************************************************************************************************
     169             : !> \brief ...
     170             : !> \param bs_env ...
     171             : ! **************************************************************************************************
     172          18 :    SUBROUTINE de_init_bs_env(bs_env)
     173             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     174             : 
     175             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'de_init_bs_env'
     176             : 
     177             :       INTEGER                                            :: handle
     178             : 
     179          18 :       CALL timeset(routineN, handle)
     180             :       ! deallocate quantities here which:
     181             :       ! 1. cannot be deallocated in bs_env_release due to circular dependencies
     182             :       ! 2. consume a lot of memory and should not be kept until the quantity is
     183             :       !    deallocated in bs_env_release
     184             : 
     185          18 :       IF (ASSOCIATED(bs_env%nl_3c%ij_list)) CALL neighbor_list_3c_destroy(bs_env%nl_3c)
     186             : 
     187          18 :       CALL cp_libint_static_cleanup()
     188             : 
     189          18 :       CALL timestop(handle)
     190             : 
     191          18 :    END SUBROUTINE de_init_bs_env
     192             : 
     193             : ! **************************************************************************************************
     194             : !> \brief ...
     195             : !> \param bs_env ...
     196             : !> \param bs_sec ...
     197             : ! **************************************************************************************************
     198          18 :    SUBROUTINE read_gw_input_parameters(bs_env, bs_sec)
     199             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     200             :       TYPE(section_vals_type), POINTER                   :: bs_sec
     201             : 
     202             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'read_gw_input_parameters'
     203             : 
     204             :       INTEGER                                            :: handle
     205             :       TYPE(section_vals_type), POINTER                   :: gw_sec
     206             : 
     207          18 :       CALL timeset(routineN, handle)
     208             : 
     209          18 :       NULLIFY (gw_sec)
     210          18 :       gw_sec => section_vals_get_subs_vals(bs_sec, "GW")
     211             : 
     212          18 :       CALL section_vals_val_get(gw_sec, "NUM_TIME_FREQ_POINTS", i_val=bs_env%num_time_freq_points)
     213          18 :       CALL section_vals_val_get(gw_sec, "EPS_FILTER", r_val=bs_env%eps_filter)
     214          18 :       CALL section_vals_val_get(gw_sec, "MEMORY_PER_PROC", r_val=bs_env%input_memory_per_proc_GB)
     215          18 :       CALL section_vals_val_get(gw_sec, "APPROX_KP_EXTRAPOL", l_val=bs_env%approx_kp_extrapol)
     216             : 
     217          18 :       CALL timestop(handle)
     218             : 
     219          18 :    END SUBROUTINE read_gw_input_parameters
     220             : 
     221             : ! **************************************************************************************************
     222             : !> \brief ...
     223             : !> \param qs_env ...
     224             : !> \param bs_env ...
     225             : ! **************************************************************************************************
     226          18 :    SUBROUTINE setup_AO_and_RI_basis_set(qs_env, bs_env)
     227             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     228             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     229             : 
     230             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'setup_AO_and_RI_basis_set'
     231             : 
     232             :       INTEGER                                            :: handle, natom, nkind
     233          18 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     234          18 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     235             : 
     236          18 :       CALL timeset(routineN, handle)
     237             : 
     238             :       CALL get_qs_env(qs_env, &
     239             :                       qs_kind_set=qs_kind_set, &
     240             :                       particle_set=particle_set, &
     241          18 :                       natom=natom, nkind=nkind)
     242             : 
     243             :       ! set up basis
     244          90 :       ALLOCATE (bs_env%sizes_RI(natom), bs_env%sizes_AO(natom))
     245         162 :       ALLOCATE (bs_env%basis_set_RI(nkind), bs_env%basis_set_AO(nkind))
     246             : 
     247          18 :       CALL basis_set_list_setup(bs_env%basis_set_RI, "RI_AUX", qs_kind_set)
     248          18 :       CALL basis_set_list_setup(bs_env%basis_set_AO, "ORB", qs_kind_set)
     249             : 
     250             :       CALL get_particle_set(particle_set, qs_kind_set, nsgf=bs_env%sizes_RI, &
     251          18 :                             basis=bs_env%basis_set_RI)
     252             :       CALL get_particle_set(particle_set, qs_kind_set, nsgf=bs_env%sizes_AO, &
     253          18 :                             basis=bs_env%basis_set_AO)
     254             : 
     255          18 :       CALL timestop(handle)
     256             : 
     257          18 :    END SUBROUTINE setup_AO_and_RI_basis_set
     258             : 
     259             : ! **************************************************************************************************
     260             : !> \brief ...
     261             : !> \param qs_env ...
     262             : !> \param bs_env ...
     263             : ! **************************************************************************************************
     264          18 :    SUBROUTINE get_RI_basis_and_basis_function_indices(qs_env, bs_env)
     265             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     266             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     267             : 
     268             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'get_RI_basis_and_basis_function_indices'
     269             : 
     270             :       INTEGER                                            :: handle, i_RI, iatom, ikind, iset, &
     271             :                                                             max_AO_bf_per_atom, n_ao_test, n_atom, &
     272             :                                                             n_kind, n_RI, nset, nsgf, u
     273          18 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: kind_of
     274          18 :       INTEGER, DIMENSION(:), POINTER                     :: l_max, l_min, nsgf_set
     275          18 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     276             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a
     277          18 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     278             : 
     279          18 :       CALL timeset(routineN, handle)
     280             : 
     281             :       ! determine RI basis set size
     282          18 :       CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, qs_kind_set=qs_kind_set)
     283             : 
     284          18 :       n_kind = SIZE(qs_kind_set)
     285          18 :       n_atom = bs_env%n_atom
     286             : 
     287          18 :       CALL get_atomic_kind_set(atomic_kind_set, kind_of=kind_of)
     288             : 
     289          54 :       DO ikind = 1, n_kind
     290             :          CALL get_qs_kind(qs_kind=qs_kind_set(ikind), basis_set=basis_set_a, &
     291          36 :                           basis_type="RI_AUX")
     292          54 :          CPASSERT(ASSOCIATED(basis_set_a))
     293             :       END DO
     294             : 
     295          54 :       ALLOCATE (bs_env%i_RI_start_from_atom(n_atom))
     296          36 :       ALLOCATE (bs_env%i_RI_end_from_atom(n_atom))
     297          36 :       ALLOCATE (bs_env%i_ao_start_from_atom(n_atom))
     298          36 :       ALLOCATE (bs_env%i_ao_end_from_atom(n_atom))
     299             : 
     300          18 :       n_RI = 0
     301          92 :       DO iatom = 1, n_atom
     302          74 :          bs_env%i_RI_start_from_atom(iatom) = n_RI + 1
     303          74 :          ikind = kind_of(iatom)
     304          74 :          CALL get_qs_kind(qs_kind=qs_kind_set(ikind), nsgf=nsgf, basis_type="RI_AUX")
     305          74 :          n_RI = n_RI + nsgf
     306          92 :          bs_env%i_RI_end_from_atom(iatom) = n_RI
     307             :       END DO
     308          18 :       bs_env%n_RI = n_RI
     309             : 
     310          18 :       max_AO_bf_per_atom = 0
     311          18 :       n_ao_test = 0
     312          92 :       DO iatom = 1, n_atom
     313          74 :          bs_env%i_ao_start_from_atom(iatom) = n_ao_test + 1
     314          74 :          ikind = kind_of(iatom)
     315          74 :          CALL get_qs_kind(qs_kind=qs_kind_set(ikind), nsgf=nsgf, basis_type="ORB")
     316          74 :          n_ao_test = n_ao_test + nsgf
     317          74 :          bs_env%i_ao_end_from_atom(iatom) = n_ao_test
     318          92 :          max_AO_bf_per_atom = MAX(max_AO_bf_per_atom, nsgf)
     319             :       END DO
     320          18 :       CPASSERT(n_ao_test == bs_env%n_ao)
     321          18 :       bs_env%max_AO_bf_per_atom = max_AO_bf_per_atom
     322             : 
     323          54 :       ALLOCATE (bs_env%l_RI(n_RI))
     324          18 :       i_RI = 0
     325          92 :       DO iatom = 1, n_atom
     326          74 :          ikind = kind_of(iatom)
     327             : 
     328          74 :          nset = bs_env%basis_set_RI(ikind)%gto_basis_set%nset
     329          74 :          l_max => bs_env%basis_set_RI(ikind)%gto_basis_set%lmax
     330          74 :          l_min => bs_env%basis_set_RI(ikind)%gto_basis_set%lmin
     331          74 :          nsgf_set => bs_env%basis_set_RI(ikind)%gto_basis_set%nsgf_set
     332             : 
     333         202 :          DO iset = 1, nset
     334         110 :             CPASSERT(l_max(iset) == l_min(iset))
     335         296 :             bs_env%l_RI(i_RI + 1:i_RI + nsgf_set(iset)) = l_max(iset)
     336         184 :             i_RI = i_RI + nsgf_set(iset)
     337             :          END DO
     338             : 
     339             :       END DO
     340          18 :       CPASSERT(i_RI == n_RI)
     341             : 
     342          18 :       u = bs_env%unit_nr
     343             : 
     344          18 :       IF (u > 0) THEN
     345           9 :          WRITE (UNIT=u, FMT="(T2,A)") " "
     346           9 :          WRITE (UNIT=u, FMT="(T2,2A,T75,I8)") "Number of auxiliary Gaussian basis functions ", &
     347          18 :             "for χ, ε, W", n_RI
     348             :       END IF
     349             : 
     350          18 :       CALL timestop(handle)
     351             : 
     352          36 :    END SUBROUTINE get_RI_basis_and_basis_function_indices
     353             : 
     354             : ! **************************************************************************************************
     355             : !> \brief ...
     356             : !> \param qs_env ...
     357             : !> \param bs_env ...
     358             : !> \param kpoints ...
     359             : ! **************************************************************************************************
     360          18 :    SUBROUTINE setup_kpoints_chi_eps_W(qs_env, bs_env, kpoints)
     361             : 
     362             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     363             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     364             :       TYPE(kpoint_type), POINTER                         :: kpoints
     365             : 
     366             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'setup_kpoints_chi_eps_W'
     367             : 
     368             :       INTEGER                                            :: handle, i_dim, n_dim, nkp, nkp_extra, &
     369             :                                                             nkp_orig, u
     370             :       INTEGER, DIMENSION(3)                              :: nkp_grid, nkp_grid_extra, periodic
     371             :       REAL(KIND=dp)                                      :: exp_s_p, n_dim_inv
     372             : 
     373          18 :       CALL timeset(routineN, handle)
     374             : 
     375             :       ! routine adapted from mp2_integrals.F
     376          18 :       NULLIFY (kpoints)
     377          18 :       CALL kpoint_create(kpoints)
     378             : 
     379          18 :       kpoints%kp_scheme = "GENERAL"
     380             : 
     381          72 :       periodic(1:3) = bs_env%periodic(1:3)
     382             : 
     383          72 :       DO i_dim = 1, 3
     384             : 
     385          54 :          CPASSERT(periodic(i_dim) == 0 .OR. periodic(i_dim) == 1)
     386             : 
     387          54 :          IF (periodic(i_dim) == 1) nkp_grid(i_dim) = 4
     388          54 :          IF (periodic(i_dim) == 0) nkp_grid(i_dim) = 1
     389             : 
     390          54 :          IF (periodic(i_dim) == 1) THEN
     391             :             ! only even k-meshes in periodic direction implemented
     392          36 :             CPASSERT(MODULO(nkp_grid(i_dim), 2) == 0)
     393             :          END IF
     394          54 :          IF (periodic(i_dim) == 0) THEN
     395             :             ! single k-kpoint in non-periodic direction needed
     396          18 :             CPASSERT(nkp_grid(i_dim) == 1)
     397             :          END IF
     398             : 
     399          54 :          IF (periodic(i_dim) == 1) nkp_grid_extra(i_dim) = nkp_grid(i_dim) + 2
     400          72 :          IF (periodic(i_dim) == 0) nkp_grid_extra(i_dim) = 1
     401             : 
     402             :       END DO
     403             : 
     404          18 :       nkp_orig = MAX(nkp_grid(1)*nkp_grid(2)*nkp_grid(3)/2, 1)
     405             : 
     406          18 :       nkp_extra = nkp_grid_extra(1)*nkp_grid_extra(2)*nkp_grid_extra(3)/2
     407             : 
     408          18 :       nkp = nkp_orig + nkp_extra
     409             : 
     410          72 :       kpoints%nkp_grid(1:3) = nkp_grid(1:3)
     411          18 :       kpoints%nkp = nkp
     412             : 
     413          72 :       bs_env%nkp_grid_chi_eps_W_orig(1:3) = nkp_grid(1:3)
     414          72 :       bs_env%nkp_grid_chi_eps_W_extra(1:3) = nkp_grid_extra(1:3)
     415          18 :       bs_env%nkp_chi_eps_W_orig = nkp_orig
     416          18 :       bs_env%nkp_chi_eps_W_extra = nkp_extra
     417          18 :       bs_env%nkp_chi_eps_W_orig_plus_extra = nkp
     418             : 
     419          90 :       ALLOCATE (kpoints%xkp(3, nkp), kpoints%wkp(nkp))
     420          90 :       ALLOCATE (bs_env%wkp_no_extra(nkp), bs_env%wkp_s_p(nkp))
     421             : 
     422          18 :       CALL compute_xkp(kpoints%xkp, 1, nkp_orig, nkp_grid)
     423          18 :       CALL compute_xkp(kpoints%xkp, nkp_orig + 1, nkp, nkp_grid_extra)
     424             : 
     425          72 :       n_dim = SUM(periodic)
     426          18 :       IF (n_dim == 0) THEN
     427             :          ! molecules
     428           0 :          kpoints%wkp(1) = 1.0_dp
     429           0 :          bs_env%wkp_s_p(1) = 1.0_dp
     430           0 :          bs_env%wkp_no_extra(1) = 1.0_dp
     431             :       ELSE
     432             : 
     433          18 :          n_dim_inv = 1.0_dp/REAL(n_dim, KIND=dp)
     434             : 
     435             :          ! k-point weights are chosen to automatically extrapolate the k-point mesh
     436          18 :          CALL compute_wkp(kpoints%wkp(1:nkp_orig), nkp_orig, nkp_extra, n_dim_inv)
     437          18 :          CALL compute_wkp(kpoints%wkp(nkp_orig + 1:nkp), nkp_extra, nkp_orig, n_dim_inv)
     438             : 
     439         162 :          bs_env%wkp_no_extra(1:nkp_orig) = 0.0_dp
     440         342 :          bs_env%wkp_no_extra(nkp_orig + 1:nkp) = 1.0_dp/REAL(nkp_extra, KIND=dp)
     441             : 
     442          18 :          IF (n_dim == 3) THEN
     443             :             ! W_PQ(k) for an s-function P and a p-function Q diverges as 1/k at k=0
     444             :             ! (instead of 1/k^2 for P and Q both being s-functions).
     445           0 :             exp_s_p = 2.0_dp*n_dim_inv
     446           0 :             CALL compute_wkp(bs_env%wkp_s_p(1:nkp_orig), nkp_orig, nkp_extra, exp_s_p)
     447           0 :             CALL compute_wkp(bs_env%wkp_s_p(nkp_orig + 1:nkp), nkp_extra, nkp_orig, exp_s_p)
     448             :          ELSE
     449         486 :             bs_env%wkp_s_p(1:nkp) = bs_env%wkp_no_extra(1:nkp)
     450             :          END IF
     451             : 
     452             :       END IF
     453             : 
     454          18 :       IF (bs_env%approx_kp_extrapol) THEN
     455           2 :          bs_env%wkp_orig = 1.0_dp/REAL(nkp_orig, KIND=dp)
     456             :       END IF
     457             : 
     458          18 :       CALL kpoint_init_cell_index_simple(kpoints, qs_env)
     459             : 
     460             :       ! heuristic parameter: how many k-points for χ, ε, and W are used simultaneously
     461             :       ! (less simultaneous k-points: less memory, but more computational effort because of
     462             :       !  recomputation of V(k))
     463          18 :       bs_env%nkp_chi_eps_W_batch = 4
     464             : 
     465             :       bs_env%num_chi_eps_W_batches = (bs_env%nkp_chi_eps_W_orig_plus_extra - 1)/ &
     466          18 :                                      bs_env%nkp_chi_eps_W_batch + 1
     467             : 
     468          18 :       u = bs_env%unit_nr
     469             : 
     470          18 :       IF (u > 0) THEN
     471           9 :          WRITE (UNIT=u, FMT="(T2,A)") " "
     472           9 :          WRITE (UNIT=u, FMT="(T2,1A,T71,3I4)") "K-point mesh 1 for χ, ε, W", nkp_grid(1:3)
     473           9 :          WRITE (UNIT=u, FMT="(T2,2A,T71,3I4)") "K-point mesh 2 for χ, ε, W ", &
     474          18 :             "(for k-point extrapolation of W)", nkp_grid_extra(1:3)
     475           9 :          WRITE (UNIT=u, FMT="(T2,A,T80,L)") "Approximate the k-point extrapolation", &
     476          18 :             bs_env%approx_kp_extrapol
     477             :       END IF
     478             : 
     479          18 :       CALL timestop(handle)
     480             : 
     481          18 :    END SUBROUTINE setup_kpoints_chi_eps_W
     482             : 
     483             : ! **************************************************************************************************
     484             : !> \brief ...
     485             : !> \param kpoints ...
     486             : !> \param qs_env ...
     487             : ! **************************************************************************************************
     488          36 :    SUBROUTINE kpoint_init_cell_index_simple(kpoints, qs_env)
     489             : 
     490             :       TYPE(kpoint_type), POINTER                         :: kpoints
     491             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     492             : 
     493             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_init_cell_index_simple'
     494             : 
     495             :       INTEGER                                            :: handle
     496             :       TYPE(dft_control_type), POINTER                    :: dft_control
     497             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     498             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     499          36 :          POINTER                                         :: sab_orb
     500             : 
     501          36 :       CALL timeset(routineN, handle)
     502             : 
     503          36 :       NULLIFY (dft_control, para_env, sab_orb)
     504          36 :       CALL get_qs_env(qs_env=qs_env, para_env=para_env, dft_control=dft_control, sab_orb=sab_orb)
     505          36 :       CALL kpoint_init_cell_index(kpoints, sab_orb, para_env, dft_control)
     506             : 
     507          36 :       CALL timestop(handle)
     508             : 
     509          36 :    END SUBROUTINE kpoint_init_cell_index_simple
     510             : 
     511             : ! **************************************************************************************************
     512             : !> \brief ...
     513             : !> \param xkp ...
     514             : !> \param ikp_start ...
     515             : !> \param ikp_end ...
     516             : !> \param grid ...
     517             : ! **************************************************************************************************
     518          54 :    SUBROUTINE compute_xkp(xkp, ikp_start, ikp_end, grid)
     519             : 
     520             :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
     521             :       INTEGER                                            :: ikp_start, ikp_end
     522             :       INTEGER, DIMENSION(3)                              :: grid
     523             : 
     524             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'compute_xkp'
     525             : 
     526             :       INTEGER                                            :: handle, i, ix, iy, iz
     527             : 
     528          54 :       CALL timeset(routineN, handle)
     529             : 
     530          54 :       i = ikp_start
     531         216 :       DO ix = 1, grid(1)
     532         956 :          DO iy = 1, grid(2)
     533        1902 :             DO iz = 1, grid(3)
     534             : 
     535        1000 :                IF (i > ikp_end) CYCLE
     536             : 
     537         500 :                xkp(1, i) = REAL(2*ix - grid(1) - 1, KIND=dp)/(2._dp*REAL(grid(1), KIND=dp))
     538         500 :                xkp(2, i) = REAL(2*iy - grid(2) - 1, KIND=dp)/(2._dp*REAL(grid(2), KIND=dp))
     539         500 :                xkp(3, i) = REAL(2*iz - grid(3) - 1, KIND=dp)/(2._dp*REAL(grid(3), KIND=dp))
     540        1740 :                i = i + 1
     541             : 
     542             :             END DO
     543             :          END DO
     544             :       END DO
     545             : 
     546          54 :       CALL timestop(handle)
     547             : 
     548          54 :    END SUBROUTINE compute_xkp
     549             : 
     550             : ! **************************************************************************************************
     551             : !> \brief ...
     552             : !> \param wkp ...
     553             : !> \param nkp_1 ...
     554             : !> \param nkp_2 ...
     555             : !> \param exponent ...
     556             : ! **************************************************************************************************
     557          36 :    SUBROUTINE compute_wkp(wkp, nkp_1, nkp_2, exponent)
     558             :       REAL(KIND=dp), DIMENSION(:)                        :: wkp
     559             :       INTEGER                                            :: nkp_1, nkp_2
     560             :       REAL(KIND=dp)                                      :: exponent
     561             : 
     562             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'compute_wkp'
     563             : 
     564             :       INTEGER                                            :: handle
     565             :       REAL(KIND=dp)                                      :: nkp_ratio
     566             : 
     567          36 :       CALL timeset(routineN, handle)
     568             : 
     569          36 :       nkp_ratio = REAL(nkp_2, KIND=dp)/REAL(nkp_1, KIND=dp)
     570             : 
     571         504 :       wkp(:) = 1.0_dp/REAL(nkp_1, KIND=dp)/(1.0_dp - nkp_ratio**exponent)
     572             : 
     573          36 :       CALL timestop(handle)
     574             : 
     575          36 :    END SUBROUTINE
     576             : 
     577             : ! **************************************************************************************************
     578             : !> \brief ...
     579             : !> \param qs_env ...
     580             : !> \param bs_env ...
     581             : ! **************************************************************************************************
     582          18 :    SUBROUTINE allocate_and_fill_matrices_and_arrays(qs_env, bs_env)
     583             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     584             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     585             : 
     586             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'allocate_and_fill_matrices_and_arrays'
     587             : 
     588             :       INTEGER                                            :: handle, i_t, num_time_freq_points
     589             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env, blacs_env_tensor
     590             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct, fm_struct_RI_global
     591          18 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
     592             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     593             : 
     594          18 :       CALL timeset(routineN, handle)
     595             : 
     596          18 :       CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env, matrix_s=matrix_s)
     597             : 
     598          18 :       fm_struct => bs_env%fm_ks_Gamma(1)%matrix_struct
     599             : 
     600          18 :       CALL cp_fm_create(bs_env%fm_Gocc, fm_struct)
     601          18 :       CALL cp_fm_create(bs_env%fm_Gvir, fm_struct)
     602          18 :       CALL cp_fm_create(bs_env%fm_h_G0W0_Gamma, fm_struct)
     603             : 
     604          18 :       NULLIFY (fm_struct_RI_global)
     605             :       CALL cp_fm_struct_create(fm_struct_RI_global, context=blacs_env, nrow_global=bs_env%n_RI, &
     606          18 :                                ncol_global=bs_env%n_RI, para_env=para_env)
     607          18 :       CALL cp_fm_create(bs_env%fm_RI_RI, fm_struct_RI_global)
     608          18 :       CALL cp_fm_create(bs_env%fm_chi_Gamma_freq, fm_struct_RI_global)
     609          18 :       CALL cp_fm_create(bs_env%fm_W_MIC_freq, fm_struct_RI_global)
     610          18 :       IF (bs_env%approx_kp_extrapol) THEN
     611           2 :          CALL cp_fm_create(bs_env%fm_W_MIC_freq_1_extra, fm_struct_RI_global)
     612           2 :          CALL cp_fm_create(bs_env%fm_W_MIC_freq_1_no_extra, fm_struct_RI_global)
     613           2 :          CALL cp_fm_set_all(bs_env%fm_W_MIC_freq_1_extra, 0.0_dp)
     614           2 :          CALL cp_fm_set_all(bs_env%fm_W_MIC_freq_1_no_extra, 0.0_dp)
     615             :       END IF
     616          18 :       CALL cp_fm_struct_release(fm_struct_RI_global)
     617             : 
     618          90 :       ALLOCATE (bs_env%eigenval_G0W0(bs_env%n_ao, bs_env%nkp_DOS, bs_env%n_spin))
     619             : 
     620          18 :       num_time_freq_points = bs_env%num_time_freq_points
     621             : 
     622          54 :       ALLOCATE (bs_env%imag_freq_points(num_time_freq_points))
     623          54 :       ALLOCATE (bs_env%imag_time_points(num_time_freq_points))
     624          72 :       ALLOCATE (bs_env%weights_cos_t_to_w(num_time_freq_points, num_time_freq_points))
     625          72 :       ALLOCATE (bs_env%weights_cos_w_to_t(num_time_freq_points, num_time_freq_points))
     626          72 :       ALLOCATE (bs_env%weights_sin_t_to_w(num_time_freq_points, num_time_freq_points))
     627             : 
     628             :       ! create blacs_env for subgroups of tensor operations
     629          18 :       NULLIFY (blacs_env_tensor)
     630          18 :       CALL cp_blacs_env_create(blacs_env=blacs_env_tensor, para_env=bs_env%para_env_tensor)
     631             : 
     632             :       ! allocate dbcsr matrices in the tensor subgroup; actually, one only needs a small
     633             :       ! subset of blocks in the tensor subgroup, however, all atomic blocks are allocated.
     634             :       ! One might think of creating a dbcsr matrix with only the blocks that are needed
     635             :       ! in the tensor subgroup
     636             :       CALL create_mat_munu(bs_env%mat_ao_ao_tensor, qs_env, bs_env%eps_atom_grid_2d_mat, &
     637          18 :                            blacs_env_tensor, do_ri_aux_basis=.FALSE.)
     638             : 
     639             :       CALL create_mat_munu(bs_env%mat_RI_RI_tensor, qs_env, bs_env%eps_atom_grid_2d_mat, &
     640          18 :                            blacs_env_tensor, do_ri_aux_basis=.TRUE.)
     641             : 
     642             :       CALL create_mat_munu(bs_env%mat_RI_RI, qs_env, bs_env%eps_atom_grid_2d_mat, &
     643          18 :                            blacs_env, do_ri_aux_basis=.TRUE.)
     644             : 
     645          18 :       CALL cp_blacs_env_release(blacs_env_tensor)
     646             : 
     647          18 :       NULLIFY (bs_env%mat_chi_Gamma_tau)
     648          18 :       CALL dbcsr_allocate_matrix_set(bs_env%mat_chi_Gamma_tau, bs_env%num_time_freq_points)
     649             : 
     650         190 :       DO i_t = 1, bs_env%num_time_freq_points
     651         172 :          ALLOCATE (bs_env%mat_chi_Gamma_tau(i_t)%matrix)
     652         190 :          CALL dbcsr_create(bs_env%mat_chi_Gamma_tau(i_t)%matrix, template=bs_env%mat_RI_RI%matrix)
     653             :       END DO
     654             : 
     655          18 :       CALL timestop(handle)
     656             : 
     657          18 :    END SUBROUTINE allocate_and_fill_matrices_and_arrays
     658             : 
     659             : ! **************************************************************************************************
     660             : !> \brief ...
     661             : !> \param qs_env ...
     662             : !> \param bs_env ...
     663             : ! **************************************************************************************************
     664          18 :    SUBROUTINE create_tensors(qs_env, bs_env)
     665             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     666             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     667             : 
     668             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'create_tensors'
     669             : 
     670             :       INTEGER                                            :: handle, n_atom_step, RI_atom
     671             :       INTEGER(int_8)                                     :: mem, non_zero_elements_sum, nze
     672             :       REAL(dp)                                           :: max_dist_AO_atoms, occ, occupation_sum
     673         126 :       TYPE(dbt_type)                                     :: t_3c_global
     674          18 :       TYPE(dbt_type), ALLOCATABLE, DIMENSION(:, :)       :: t_3c_global_array
     675             :       TYPE(neighbor_list_3c_type)                        :: nl_3c_global
     676             : 
     677          18 :       CALL timeset(routineN, handle)
     678             : 
     679             :       ! be careful: routine needs bs_env%eps_3c_int which is set in set_heuristic_parameters
     680          18 :       CALL init_interaction_radii(bs_env)
     681             : 
     682             :       ! split blocks does not improve load balancing/efficienfy for tensor contraction, so we go
     683             :       ! with the standard atomic blocks
     684             :       CALL create_3c_t(bs_env%t_RI_AO__AO, bs_env%para_env_tensor, "(RI AO | AO)", [1, 2], [3], &
     685             :                        bs_env%sizes_RI, bs_env%sizes_AO, &
     686          18 :                        create_nl_3c=.TRUE., nl_3c=bs_env%nl_3c, qs_env=qs_env)
     687             :       CALL create_3c_t(bs_env%t_RI__AO_AO, bs_env%para_env_tensor, "(RI | AO AO)", [1], [2, 3], &
     688          18 :                        bs_env%sizes_RI, bs_env%sizes_AO)
     689             : 
     690          18 :       CALL create_2c_t(bs_env, bs_env%sizes_RI, bs_env%sizes_AO)
     691             : 
     692             :       ! check the sparsity of 3c integral tensor (µν|P); calculate maximum distance between
     693             :       ! AO atoms µ, ν where at least a single integral (µν|P) is larger than the filter threshold
     694             :       CALL create_3c_t(t_3c_global, bs_env%para_env, "(RI AO | AO)", [1, 2], [3], &
     695             :                        bs_env%sizes_RI, bs_env%sizes_AO, &
     696          18 :                        create_nl_3c=.TRUE., nl_3c=nl_3c_global, qs_env=qs_env)
     697             : 
     698          18 :       CALL m_memory(mem)
     699          18 :       CALL bs_env%para_env%max(mem)
     700             : 
     701         162 :       ALLOCATE (t_3c_global_array(1, 1))
     702          18 :       CALL dbt_create(t_3c_global, t_3c_global_array(1, 1))
     703             : 
     704          18 :       CALL bs_env%para_env%sync()
     705          18 :       bs_env%t1 = m_walltime()
     706             : 
     707          18 :       occupation_sum = 0.0_dp
     708          18 :       non_zero_elements_sum = 0
     709          18 :       max_dist_AO_atoms = 0.0_dp
     710          18 :       n_atom_step = INT(SQRT(REAL(bs_env%n_atom, KIND=dp)))
     711             :       ! do not compute full 3c integrals at once because it may cause out of memory
     712          62 :       DO RI_atom = 1, bs_env%n_atom, n_atom_step
     713             : 
     714             :          CALL build_3c_integrals(t_3c_global_array, &
     715             :                                  bs_env%eps_filter, &
     716             :                                  qs_env, &
     717             :                                  nl_3c_global, &
     718             :                                  int_eps=bs_env%eps_3c_int, &
     719             :                                  basis_i=bs_env%basis_set_RI, &
     720             :                                  basis_j=bs_env%basis_set_AO, &
     721             :                                  basis_k=bs_env%basis_set_AO, &
     722             :                                  bounds_i=[RI_atom, MIN(RI_atom + n_atom_step - 1, bs_env%n_atom)], &
     723             :                                  potential_parameter=bs_env%ri_metric, &
     724         132 :                                  desymmetrize=.FALSE.)
     725             : 
     726          44 :          CALL dbt_filter(t_3c_global_array(1, 1), bs_env%eps_filter)
     727             : 
     728          44 :          CALL bs_env%para_env%sync()
     729             : 
     730          44 :          CALL get_tensor_occupancy(t_3c_global_array(1, 1), nze, occ)
     731          44 :          non_zero_elements_sum = non_zero_elements_sum + nze
     732          44 :          occupation_sum = occupation_sum + occ
     733             : 
     734          44 :          CALL get_max_dist_AO_atoms(t_3c_global_array(1, 1), max_dist_AO_atoms, qs_env)
     735             : 
     736         106 :          CALL dbt_clear(t_3c_global_array(1, 1))
     737             : 
     738             :       END DO
     739             : 
     740          18 :       bs_env%t2 = m_walltime()
     741             : 
     742          18 :       bs_env%occupation_3c_int = occupation_sum
     743          18 :       bs_env%max_dist_AO_atoms = max_dist_AO_atoms
     744             : 
     745          18 :       CALL dbt_destroy(t_3c_global)
     746          18 :       CALL dbt_destroy(t_3c_global_array(1, 1))
     747          36 :       DEALLOCATE (t_3c_global_array)
     748             : 
     749          18 :       CALL neighbor_list_3c_destroy(nl_3c_global)
     750             : 
     751          18 :       IF (bs_env%unit_nr > 0) THEN
     752           9 :          WRITE (bs_env%unit_nr, '(T2,A)') ''
     753             :          WRITE (bs_env%unit_nr, '(T2,A,F27.1,A)') &
     754           9 :             'Computed 3-center integrals (µν|P), execution time', bs_env%t2 - bs_env%t1, ' s'
     755           9 :          WRITE (bs_env%unit_nr, '(T2,A,F48.3,A)') 'Percentage of non-zero (µν|P)', &
     756          18 :             occupation_sum*100, ' %'
     757           9 :          WRITE (bs_env%unit_nr, '(T2,A,F33.1,A)') 'Max. distance between µ,ν in non-zero (µν|P)', &
     758          18 :             max_dist_AO_atoms*angstrom, ' A'
     759           9 :          WRITE (bs_env%unit_nr, '(T2,2A,I20,A)') 'Required memory if storing all 3-center ', &
     760          18 :             'integrals (µν|P)', INT(REAL(non_zero_elements_sum, KIND=dp)*8.0E-9_dp), ' GB'
     761             :       END IF
     762             : 
     763          18 :       CALL timestop(handle)
     764             : 
     765          72 :    END SUBROUTINE create_tensors
     766             : 
     767             : ! **************************************************************************************************
     768             : !> \brief ...
     769             : !> \param bs_env ...
     770             : !> \param sizes_RI ...
     771             : !> \param sizes_AO ...
     772             : ! **************************************************************************************************
     773          18 :    SUBROUTINE create_2c_t(bs_env, sizes_RI, sizes_AO)
     774             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     775             :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: sizes_RI, sizes_AO
     776             : 
     777             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'create_2c_t'
     778             : 
     779             :       INTEGER                                            :: handle
     780          18 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: dist_1, dist_2
     781             :       INTEGER, DIMENSION(2)                              :: pdims_2d
     782          54 :       TYPE(dbt_pgrid_type)                               :: pgrid_2d
     783             : 
     784          18 :       CALL timeset(routineN, handle)
     785             : 
     786             :       ! inspired from rpa_im_time.F / hfx_types.F
     787             : 
     788          18 :       pdims_2d = 0
     789          18 :       CALL dbt_pgrid_create(bs_env%para_env_tensor, pdims_2d, pgrid_2d)
     790             : 
     791             :       CALL create_2c_tensor(bs_env%t_G, dist_1, dist_2, pgrid_2d, sizes_AO, sizes_AO, &
     792          18 :                             name="(AO | AO)")
     793          18 :       DEALLOCATE (dist_1, dist_2)
     794             :       CALL create_2c_tensor(bs_env%t_chi, dist_1, dist_2, pgrid_2d, sizes_RI, sizes_RI, &
     795          18 :                             name="(RI | RI)")
     796          18 :       DEALLOCATE (dist_1, dist_2)
     797             :       CALL create_2c_tensor(bs_env%t_W, dist_1, dist_2, pgrid_2d, sizes_RI, sizes_RI, &
     798          18 :                             name="(RI | RI)")
     799          18 :       DEALLOCATE (dist_1, dist_2)
     800          18 :       CALL dbt_pgrid_destroy(pgrid_2d)
     801             : 
     802          18 :       CALL timestop(handle)
     803             : 
     804          18 :    END SUBROUTINE create_2c_t
     805             : 
     806             : ! **************************************************************************************************
     807             : !> \brief ...
     808             : !> \param tensor ...
     809             : !> \param para_env ...
     810             : !> \param tensor_name ...
     811             : !> \param map1 ...
     812             : !> \param map2 ...
     813             : !> \param sizes_RI ...
     814             : !> \param sizes_AO ...
     815             : !> \param create_nl_3c ...
     816             : !> \param nl_3c ...
     817             : !> \param qs_env ...
     818             : ! **************************************************************************************************
     819          54 :    SUBROUTINE create_3c_t(tensor, para_env, tensor_name, map1, map2, sizes_RI, sizes_AO, &
     820             :                           create_nl_3c, nl_3c, qs_env)
     821             :       TYPE(dbt_type)                                     :: tensor
     822             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     823             :       CHARACTER(LEN=12)                                  :: tensor_name
     824             :       INTEGER, DIMENSION(:)                              :: map1, map2
     825             :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: sizes_RI, sizes_AO
     826             :       LOGICAL, OPTIONAL                                  :: create_nl_3c
     827             :       TYPE(neighbor_list_3c_type), OPTIONAL              :: nl_3c
     828             :       TYPE(qs_environment_type), OPTIONAL, POINTER       :: qs_env
     829             : 
     830             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'create_3c_t'
     831             : 
     832             :       INTEGER                                            :: handle, nkind
     833          54 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: dist_AO_1, dist_AO_2, dist_RI
     834             :       INTEGER, DIMENSION(3)                              :: pcoord, pdims, pdims_3d
     835             :       LOGICAL                                            :: my_create_nl_3c
     836         162 :       TYPE(dbt_pgrid_type)                               :: pgrid_3d
     837             :       TYPE(distribution_3d_type)                         :: dist_3d
     838          54 :       TYPE(mp_cart_type)                                 :: mp_comm_t3c_2
     839          54 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     840             : 
     841          54 :       CALL timeset(routineN, handle)
     842             : 
     843          54 :       pdims_3d = 0
     844          54 :       CALL dbt_pgrid_create(para_env, pdims_3d, pgrid_3d)
     845             :       CALL create_3c_tensor(tensor, dist_RI, dist_AO_1, dist_AO_2, &
     846             :                             pgrid_3d, sizes_RI, sizes_AO, sizes_AO, &
     847          54 :                             map1=map1, map2=map2, name=tensor_name)
     848             : 
     849          54 :       IF (PRESENT(create_nl_3c)) THEN
     850          36 :          my_create_nl_3c = create_nl_3c
     851             :       ELSE
     852             :          my_create_nl_3c = .FALSE.
     853             :       END IF
     854             : 
     855          36 :       IF (my_create_nl_3c) THEN
     856          36 :          CALL get_qs_env(qs_env, nkind=nkind, particle_set=particle_set)
     857          36 :          CALL dbt_mp_environ_pgrid(pgrid_3d, pdims, pcoord)
     858          36 :          CALL mp_comm_t3c_2%create(pgrid_3d%mp_comm_2d, 3, pdims)
     859             :          CALL distribution_3d_create(dist_3d, dist_RI, dist_AO_1, dist_AO_2, &
     860          36 :                                      nkind, particle_set, mp_comm_t3c_2, own_comm=.TRUE.)
     861             : 
     862             :          CALL build_3c_neighbor_lists(nl_3c, &
     863             :                                       qs_env%bs_env%basis_set_RI, &
     864             :                                       qs_env%bs_env%basis_set_AO, &
     865             :                                       qs_env%bs_env%basis_set_AO, &
     866             :                                       dist_3d, qs_env%bs_env%ri_metric, &
     867          36 :                                       "GW_3c_nl", qs_env, own_dist=.TRUE.)
     868             :       END IF
     869             : 
     870          54 :       DEALLOCATE (dist_RI, dist_AO_1, dist_AO_2)
     871          54 :       CALL dbt_pgrid_destroy(pgrid_3d)
     872             : 
     873          54 :       CALL timestop(handle)
     874             : 
     875         108 :    END SUBROUTINE create_3c_t
     876             : 
     877             : ! **************************************************************************************************
     878             : !> \brief ...
     879             : !> \param bs_env ...
     880             : ! **************************************************************************************************
     881          18 :    SUBROUTINE init_interaction_radii(bs_env)
     882             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     883             : 
     884             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'init_interaction_radii'
     885             : 
     886             :       INTEGER                                            :: handle, ibasis
     887             :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis, ri_basis
     888             : 
     889          18 :       CALL timeset(routineN, handle)
     890             : 
     891          54 :       DO ibasis = 1, SIZE(bs_env%basis_set_AO)
     892             : 
     893          36 :          orb_basis => bs_env%basis_set_AO(ibasis)%gto_basis_set
     894          36 :          CALL init_interaction_radii_orb_basis(orb_basis, bs_env%eps_3c_int)
     895             : 
     896          36 :          ri_basis => bs_env%basis_set_RI(ibasis)%gto_basis_set
     897          54 :          CALL init_interaction_radii_orb_basis(ri_basis, bs_env%eps_3c_int)
     898             : 
     899             :       END DO
     900             : 
     901          18 :       CALL timestop(handle)
     902             : 
     903          18 :    END SUBROUTINE init_interaction_radii
     904             : 
     905             : ! **************************************************************************************************
     906             : !> \brief ...
     907             : !> \param t_3c_int ...
     908             : !> \param max_dist_AO_atoms ...
     909             : !> \param qs_env ...
     910             : ! **************************************************************************************************
     911          44 :    SUBROUTINE get_max_dist_AO_atoms(t_3c_int, max_dist_AO_atoms, qs_env)
     912             :       TYPE(dbt_type)                                     :: t_3c_int
     913             :       REAL(KIND=dp)                                      :: max_dist_AO_atoms
     914             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     915             : 
     916             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'get_max_dist_AO_atoms'
     917             : 
     918             :       INTEGER                                            :: atom_1, atom_2, handle, num_cells
     919             :       INTEGER, DIMENSION(3)                              :: atom_ind
     920          44 :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell
     921             :       REAL(KIND=dp)                                      :: abs_rab
     922             :       REAL(KIND=dp), DIMENSION(3)                        :: rab
     923             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: hmat
     924             :       TYPE(cell_type), POINTER                           :: cell
     925             :       TYPE(dbt_iterator_type)                            :: iter
     926             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     927          44 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     928             : 
     929          44 :       CALL timeset(routineN, handle)
     930             : 
     931          44 :       NULLIFY (cell, particle_set, para_env)
     932          44 :       CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set, para_env=para_env)
     933             : 
     934             : !$OMP PARALLEL DEFAULT(NONE) &
     935             : !$OMP SHARED(t_3c_int, max_dist_AO_atoms, num_cells, index_to_cell, hmat, particle_set, cell) &
     936          44 : !$OMP PRIVATE(iter,atom_ind,rab, abs_rab, atom_1, atom_2)
     937             :       CALL dbt_iterator_start(iter, t_3c_int)
     938             :       DO WHILE (dbt_iterator_blocks_left(iter))
     939             :          CALL dbt_iterator_next_block(iter, atom_ind)
     940             : 
     941             :          atom_1 = atom_ind(2)
     942             :          atom_2 = atom_ind(3)
     943             : 
     944             :          rab = pbc(particle_set(atom_1)%r(1:3), particle_set(atom_2)%r(1:3), cell)
     945             : 
     946             :          abs_rab = SQRT(rab(1)**2 + rab(2)**2 + rab(3)**2)
     947             : 
     948             :          max_dist_AO_atoms = MAX(max_dist_AO_atoms, abs_rab)
     949             : 
     950             :       END DO
     951             :       CALL dbt_iterator_stop(iter)
     952             : !$OMP END PARALLEL
     953             : 
     954          44 :       CALL para_env%max(max_dist_AO_atoms)
     955             : 
     956          44 :       CALL timestop(handle)
     957             : 
     958          44 :    END SUBROUTINE get_max_dist_AO_atoms
     959             : 
     960             : ! **************************************************************************************************
     961             : !> \brief ...
     962             : !> \param bs_env ...
     963             : ! **************************************************************************************************
     964          18 :    SUBROUTINE set_sparsity_parallelization_parameters(bs_env)
     965             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     966             : 
     967             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'set_sparsity_parallelization_parameters'
     968             : 
     969             :       INTEGER :: handle, i_ivl, IL_ivl, j_ivl, n_atom_per_IL_ivl, n_atom_per_ivl, n_intervals_i, &
     970             :          n_intervals_inner_loop_atoms, n_intervals_j, u
     971             : 
     972          18 :       CALL timeset(routineN, handle)
     973             : 
     974             :       ! heuristic parameter to prevent out of memory
     975          18 :       bs_env%safety_factor_memory = 0.10_dp
     976             : 
     977             :       ! choose atomic range for λ ("i_atom"), ν ("j_atom") in
     978             :       ! M_λνP(iτ) = sum_µ (µν|P) G^occ_µλ(i|τ|,k=0)
     979             :       ! N_νλQ(iτ) = sum_σ (σλ|Q) G^vir_σν(i|τ|,k=0)
     980             :       ! such that M and N fit into the memory
     981             :       n_atom_per_ivl = INT(SQRT(bs_env%safety_factor_memory*bs_env%input_memory_per_proc &
     982             :                                 *bs_env%group_size_tensor/24/bs_env%n_RI &
     983          18 :                                 /SQRT(bs_env%occupation_3c_int)))/bs_env%max_AO_bf_per_atom
     984             : 
     985          18 :       n_intervals_i = (bs_env%n_atom_i - 1)/n_atom_per_ivl + 1
     986          18 :       n_intervals_j = (bs_env%n_atom_j - 1)/n_atom_per_ivl + 1
     987             : 
     988          18 :       bs_env%n_atom_per_interval_ij = n_atom_per_ivl
     989          18 :       bs_env%n_intervals_i = n_intervals_i
     990          18 :       bs_env%n_intervals_j = n_intervals_j
     991             : 
     992          54 :       ALLOCATE (bs_env%i_atom_intervals(2, n_intervals_i))
     993          54 :       ALLOCATE (bs_env%j_atom_intervals(2, n_intervals_j))
     994             : 
     995          36 :       DO i_ivl = 1, n_intervals_i
     996          18 :          bs_env%i_atom_intervals(1, i_ivl) = (i_ivl - 1)*n_atom_per_ivl + bs_env%atoms_i(1)
     997             :          bs_env%i_atom_intervals(2, i_ivl) = MIN(i_ivl*n_atom_per_ivl + bs_env%atoms_i(1) - 1, &
     998          36 :                                                  bs_env%atoms_i(2))
     999             :       END DO
    1000             : 
    1001          36 :       DO j_ivl = 1, n_intervals_j
    1002          18 :          bs_env%j_atom_intervals(1, j_ivl) = (j_ivl - 1)*n_atom_per_ivl + bs_env%atoms_j(1)
    1003             :          bs_env%j_atom_intervals(2, j_ivl) = MIN(j_ivl*n_atom_per_ivl + bs_env%atoms_j(1) - 1, &
    1004          36 :                                                  bs_env%atoms_j(2))
    1005             :       END DO
    1006             : 
    1007          72 :       ALLOCATE (bs_env%skip_Sigma_occ(n_intervals_i, n_intervals_j))
    1008          54 :       ALLOCATE (bs_env%skip_Sigma_vir(n_intervals_i, n_intervals_j))
    1009          54 :       bs_env%skip_Sigma_occ(:, :) = .FALSE.
    1010          54 :       bs_env%skip_Sigma_vir(:, :) = .FALSE.
    1011             : 
    1012             :       ! choose atomic range for µ and σ ("inner loop (IL) atom") in
    1013             :       ! M_λνP(iτ) = sum_µ (µν|P) G^occ_µλ(i|τ|,k=0)
    1014             :       ! N_νλQ(iτ) = sum_σ (σλ|Q) G^vir_σν(i|τ|,k=0)
    1015             :       n_atom_per_IL_ivl = MIN(INT(bs_env%safety_factor_memory*bs_env%input_memory_per_proc &
    1016             :                                   *bs_env%group_size_tensor/n_atom_per_ivl &
    1017             :                                   /bs_env%max_AO_bf_per_atom &
    1018             :                                   /bs_env%n_RI/8/SQRT(bs_env%occupation_3c_int) &
    1019          18 :                                   /bs_env%max_AO_bf_per_atom), bs_env%n_atom)
    1020             : 
    1021          18 :       n_intervals_inner_loop_atoms = (bs_env%n_atom - 1)/n_atom_per_IL_ivl + 1
    1022             : 
    1023          18 :       bs_env%n_atom_per_IL_interval = n_atom_per_IL_ivl
    1024          18 :       bs_env%n_intervals_inner_loop_atoms = n_intervals_inner_loop_atoms
    1025             : 
    1026          54 :       ALLOCATE (bs_env%inner_loop_atom_intervals(2, n_intervals_inner_loop_atoms))
    1027          36 :       DO IL_ivl = 1, n_intervals_inner_loop_atoms
    1028          18 :          bs_env%inner_loop_atom_intervals(1, IL_ivl) = (IL_ivl - 1)*n_atom_per_IL_ivl + 1
    1029          36 :          bs_env%inner_loop_atom_intervals(2, IL_ivl) = MIN(IL_ivl*n_atom_per_IL_ivl, bs_env%n_atom)
    1030             :       END DO
    1031             : 
    1032          18 :       u = bs_env%unit_nr
    1033          18 :       IF (u > 0) THEN
    1034           9 :          WRITE (u, '(T2,A)') ''
    1035           9 :          WRITE (u, '(T2,A,I33)') 'Number of i and j atoms in M_λνP(τ), N_νλQ(τ):', n_atom_per_ivl
    1036           9 :          WRITE (u, '(T2,A,I18)') 'Number of inner loop atoms for µ in M_λνP = sum_µ (µν|P) G_µλ', &
    1037          18 :             n_atom_per_IL_ivl
    1038             :       END IF
    1039             : 
    1040          18 :       CALL timestop(handle)
    1041             : 
    1042          18 :    END SUBROUTINE set_sparsity_parallelization_parameters
    1043             : 
    1044             : ! **************************************************************************************************
    1045             : !> \brief ...
    1046             : !> \param qs_env ...
    1047             : !> \param bs_env ...
    1048             : ! **************************************************************************************************
    1049          18 :    SUBROUTINE check_for_restart_files(qs_env, bs_env)
    1050             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1051             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1052             : 
    1053             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'check_for_restart_files'
    1054             : 
    1055             :       CHARACTER(LEN=9)                                   :: frmt
    1056             :       CHARACTER(LEN=default_string_length)               :: f_chi, f_S_n, f_S_p, f_S_x, f_W_t, &
    1057             :                                                             prefix, project_name
    1058             :       INTEGER                                            :: handle, i_spin, i_t_or_w, ind, n_spin, &
    1059             :                                                             num_time_freq_points
    1060             :       LOGICAL                                            :: chi_exists, Sigma_neg_time_exists, &
    1061             :                                                             Sigma_pos_time_exists, &
    1062             :                                                             Sigma_x_spin_exists, W_time_exists
    1063             :       TYPE(cp_logger_type), POINTER                      :: logger
    1064             :       TYPE(section_vals_type), POINTER                   :: input, print_key
    1065             : 
    1066          18 :       CALL timeset(routineN, handle)
    1067             : 
    1068          18 :       num_time_freq_points = bs_env%num_time_freq_points
    1069          18 :       n_spin = bs_env%n_spin
    1070             : 
    1071          54 :       ALLOCATE (bs_env%read_chi(num_time_freq_points))
    1072          36 :       ALLOCATE (bs_env%calc_chi(num_time_freq_points))
    1073          72 :       ALLOCATE (bs_env%Sigma_c_exists(num_time_freq_points, n_spin))
    1074             : 
    1075          18 :       CALL get_qs_env(qs_env, input=input)
    1076             : 
    1077          18 :       logger => cp_get_default_logger()
    1078          18 :       print_key => section_vals_get_subs_vals(input, 'PROPERTIES%BANDSTRUCTURE%GW%PRINT%RESTART')
    1079             :       project_name = cp_print_key_generate_filename(logger, print_key, extension="", &
    1080          18 :                                                     my_local=.FALSE.)
    1081          18 :       WRITE (prefix, '(2A)') TRIM(project_name), "-RESTART_"
    1082          18 :       bs_env%prefix = prefix
    1083             : 
    1084          18 :       bs_env%all_W_exist = .TRUE.
    1085             : 
    1086         190 :       DO i_t_or_w = 1, num_time_freq_points
    1087             : 
    1088         172 :          IF (i_t_or_w < 10) THEN
    1089         156 :             WRITE (frmt, '(A)') '(3A,I1,A)'
    1090         156 :             WRITE (f_chi, frmt) TRIM(prefix), bs_env%chi_name, "_0", i_t_or_w, ".matrix"
    1091         156 :             WRITE (f_W_t, frmt) TRIM(prefix), bs_env%W_time_name, "_0", i_t_or_w, ".matrix"
    1092          16 :          ELSE IF (i_t_or_w < 100) THEN
    1093          16 :             WRITE (frmt, '(A)') '(3A,I2,A)'
    1094          16 :             WRITE (f_chi, frmt) TRIM(prefix), bs_env%chi_name, "_", i_t_or_w, ".matrix"
    1095          16 :             WRITE (f_W_t, frmt) TRIM(prefix), bs_env%W_time_name, "_", i_t_or_w, ".matrix"
    1096             :          ELSE
    1097           0 :             CPABORT('Please implement more than 99 time/frequency points.')
    1098             :          END IF
    1099             : 
    1100         172 :          INQUIRE (file=TRIM(f_chi), exist=chi_exists)
    1101         172 :          INQUIRE (file=TRIM(f_W_t), exist=W_time_exists)
    1102             : 
    1103         172 :          bs_env%read_chi(i_t_or_w) = chi_exists
    1104         172 :          bs_env%calc_chi(i_t_or_w) = .NOT. chi_exists
    1105             : 
    1106         172 :          bs_env%all_W_exist = bs_env%all_W_exist .AND. W_time_exists
    1107             : 
    1108             :          ! the self-energy is spin-dependent
    1109         422 :          DO i_spin = 1, n_spin
    1110             : 
    1111         232 :             ind = i_t_or_w + (i_spin - 1)*num_time_freq_points
    1112             : 
    1113         232 :             IF (ind < 10) THEN
    1114         156 :                WRITE (frmt, '(A)') '(3A,I1,A)'
    1115         156 :                WRITE (f_S_p, frmt) TRIM(prefix), bs_env%Sigma_p_name, "_0", ind, ".matrix"
    1116         156 :                WRITE (f_S_n, frmt) TRIM(prefix), bs_env%Sigma_n_name, "_0", ind, ".matrix"
    1117          76 :             ELSE IF (i_t_or_w < 100) THEN
    1118          76 :                WRITE (frmt, '(A)') '(3A,I2,A)'
    1119          76 :                WRITE (f_S_p, frmt) TRIM(prefix), bs_env%Sigma_p_name, "_", ind, ".matrix"
    1120          76 :                WRITE (f_S_n, frmt) TRIM(prefix), bs_env%Sigma_n_name, "_", ind, ".matrix"
    1121             :             END IF
    1122             : 
    1123         232 :             INQUIRE (file=TRIM(f_S_p), exist=Sigma_pos_time_exists)
    1124         232 :             INQUIRE (file=TRIM(f_S_n), exist=Sigma_neg_time_exists)
    1125             : 
    1126             :             bs_env%Sigma_c_exists(i_t_or_w, i_spin) = Sigma_pos_time_exists .AND. &
    1127         556 :                                                       Sigma_neg_time_exists
    1128             : 
    1129             :          END DO
    1130             : 
    1131             :       END DO
    1132             : 
    1133          18 :       IF (bs_env%all_W_exist) THEN
    1134          44 :          bs_env%read_chi(:) = .FALSE.
    1135          44 :          bs_env%calc_chi(:) = .FALSE.
    1136             :       END IF
    1137             : 
    1138          18 :       bs_env%Sigma_x_exists = .TRUE.
    1139          42 :       DO i_spin = 1, n_spin
    1140          24 :          WRITE (f_S_x, '(3A,I1,A)') TRIM(prefix), bs_env%Sigma_x_name, "_0", i_spin, ".matrix"
    1141          24 :          INQUIRE (file=TRIM(f_S_x), exist=Sigma_x_spin_exists)
    1142          58 :          bs_env%Sigma_x_exists = bs_env%Sigma_x_exists .AND. Sigma_x_spin_exists
    1143             :       END DO
    1144             : 
    1145          18 :       CALL timestop(handle)
    1146             : 
    1147          18 :    END SUBROUTINE check_for_restart_files
    1148             : 
    1149             : ! **************************************************************************************************
    1150             : !> \brief ...
    1151             : !> \param qs_env ...
    1152             : !> \param bs_env ...
    1153             : ! **************************************************************************************************
    1154          18 :    SUBROUTINE set_parallelization_parameters(qs_env, bs_env)
    1155             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1156             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1157             : 
    1158             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'set_parallelization_parameters'
    1159             : 
    1160             :       INTEGER                                            :: color_sub, dummy_1, dummy_2, handle, &
    1161             :                                                             num_pe, num_t_groups, u
    1162             :       INTEGER(KIND=int_8)                                :: mem
    1163             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1164             : 
    1165          18 :       CALL timeset(routineN, handle)
    1166             : 
    1167          18 :       CALL get_qs_env(qs_env, para_env=para_env)
    1168             : 
    1169          18 :       num_pe = para_env%num_pe
    1170             :       ! use all processors for the group (in principle, number could be changed, but performance
    1171             :       ! seems to be best for a single group with all MPI processes per group)
    1172          18 :       bs_env%group_size_tensor = num_pe
    1173             : 
    1174             :       ! group_size_tensor must divide num_pe without rest; otherwise everything will be complicated
    1175          18 :       IF (MODULO(num_pe, bs_env%group_size_tensor) .NE. 0) THEN
    1176           0 :          CALL find_good_group_size(num_pe, bs_env%group_size_tensor)
    1177             :       END IF
    1178             : 
    1179             :       ! para_env_tensor for tensor subgroups
    1180          18 :       color_sub = para_env%mepos/bs_env%group_size_tensor
    1181          18 :       bs_env%tensor_group_color = color_sub
    1182             : 
    1183          18 :       ALLOCATE (bs_env%para_env_tensor)
    1184          18 :       CALL bs_env%para_env_tensor%from_split(para_env, color_sub)
    1185             : 
    1186          18 :       num_t_groups = para_env%num_pe/bs_env%group_size_tensor
    1187          18 :       bs_env%num_tensor_groups = num_t_groups
    1188             : 
    1189             :       CALL get_i_j_atoms(bs_env%atoms_i, bs_env%atoms_j, bs_env%n_atom_i, bs_env%n_atom_j, &
    1190          18 :                          color_sub, bs_env)
    1191             : 
    1192          54 :       ALLOCATE (bs_env%atoms_i_t_group(2, num_t_groups))
    1193          54 :       ALLOCATE (bs_env%atoms_j_t_group(2, num_t_groups))
    1194          36 :       DO color_sub = 0, num_t_groups - 1
    1195             :          CALL get_i_j_atoms(bs_env%atoms_i_t_group(1:2, color_sub + 1), &
    1196             :                             bs_env%atoms_j_t_group(1:2, color_sub + 1), &
    1197          36 :                             dummy_1, dummy_2, color_sub, bs_env)
    1198             :       END DO
    1199             : 
    1200          18 :       CALL m_memory(mem)
    1201          18 :       CALL bs_env%para_env%max(mem)
    1202             : 
    1203          18 :       bs_env%input_memory_per_proc = INT(bs_env%input_memory_per_proc_GB*1.0E9_dp, KIND=int_8)
    1204             : 
    1205          18 :       u = bs_env%unit_nr
    1206          18 :       IF (u > 0) THEN
    1207           9 :          WRITE (u, '(T2,A)') ''
    1208           9 :          WRITE (u, '(T2,A,I47)') 'Group size for tensor operations', bs_env%group_size_tensor
    1209           9 :          WRITE (u, '(T2,A)') ''
    1210           9 :          WRITE (u, '(T2,A,F37.1,A)') 'Input: Available memory per MPI process', &
    1211          18 :             bs_env%input_memory_per_proc_GB, ' GB'
    1212           9 :          WRITE (u, '(T2,A,F35.1,A)') 'Used memory per MPI process before GW run', &
    1213          18 :             REAL(mem, KIND=dp)/1.E9_dp, ' GB'
    1214             :       END IF
    1215             : 
    1216          18 :       CALL timestop(handle)
    1217             : 
    1218          36 :    END SUBROUTINE set_parallelization_parameters
    1219             : 
    1220             : ! **************************************************************************************************
    1221             : !> \brief ...
    1222             : !> \param num_pe ...
    1223             : !> \param group_size ...
    1224             : ! **************************************************************************************************
    1225           0 :    SUBROUTINE find_good_group_size(num_pe, group_size)
    1226             : 
    1227             :       INTEGER                                            :: num_pe, group_size
    1228             : 
    1229             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'find_good_group_size'
    1230             : 
    1231             :       INTEGER                                            :: group_size_minus, group_size_orig, &
    1232             :                                                             group_size_plus, handle, i_diff
    1233             : 
    1234           0 :       CALL timeset(routineN, handle)
    1235             : 
    1236           0 :       group_size_orig = group_size
    1237             : 
    1238           0 :       DO i_diff = 1, num_pe
    1239             : 
    1240           0 :          group_size_minus = group_size - i_diff
    1241             : 
    1242           0 :          IF (MODULO(num_pe, group_size_minus) == 0 .AND. group_size_minus > 0) THEN
    1243           0 :             group_size = group_size_minus
    1244           0 :             EXIT
    1245             :          END IF
    1246             : 
    1247           0 :          group_size_plus = group_size + i_diff
    1248             : 
    1249           0 :          IF (MODULO(num_pe, group_size_plus) == 0 .AND. group_size_plus <= num_pe) THEN
    1250           0 :             group_size = group_size_plus
    1251           0 :             EXIT
    1252             :          END IF
    1253             : 
    1254             :       END DO
    1255             : 
    1256           0 :       IF (group_size_orig == group_size) CPABORT("Group size error")
    1257             : 
    1258           0 :       CALL timestop(handle)
    1259             : 
    1260           0 :    END SUBROUTINE find_good_group_size
    1261             : 
    1262             : ! **************************************************************************************************
    1263             : !> \brief ...
    1264             : !> \param atoms_i ...
    1265             : !> \param atoms_j ...
    1266             : !> \param n_atom_i ...
    1267             : !> \param n_atom_j ...
    1268             : !> \param color_sub ...
    1269             : !> \param bs_env ...
    1270             : ! **************************************************************************************************
    1271          36 :    SUBROUTINE get_i_j_atoms(atoms_i, atoms_j, n_atom_i, n_atom_j, color_sub, bs_env)
    1272             : 
    1273             :       INTEGER, DIMENSION(2)                              :: atoms_i, atoms_j
    1274             :       INTEGER                                            :: n_atom_i, n_atom_j, color_sub
    1275             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1276             : 
    1277             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'get_i_j_atoms'
    1278             : 
    1279             :       INTEGER                                            :: handle, i_atoms_per_group, i_group, &
    1280             :                                                             ipcol, ipcol_loop, iprow, iprow_loop, &
    1281             :                                                             j_atoms_per_group, npcol, nprow
    1282             : 
    1283          36 :       CALL timeset(routineN, handle)
    1284             : 
    1285             :       ! create a square mesh of tensor groups for iatom and jatom; code from blacs_env_create
    1286          36 :       CALL square_mesh(nprow, npcol, bs_env%num_tensor_groups)
    1287             : 
    1288          36 :       i_group = 0
    1289          72 :       DO ipcol_loop = 0, npcol - 1
    1290         108 :          DO iprow_loop = 0, nprow - 1
    1291          36 :             IF (i_group == color_sub) THEN
    1292          36 :                iprow = iprow_loop
    1293          36 :                ipcol = ipcol_loop
    1294             :             END IF
    1295          72 :             i_group = i_group + 1
    1296             :          END DO
    1297             :       END DO
    1298             : 
    1299          36 :       IF (MODULO(bs_env%n_atom, nprow) == 0) THEN
    1300          36 :          i_atoms_per_group = bs_env%n_atom/nprow
    1301             :       ELSE
    1302           0 :          i_atoms_per_group = bs_env%n_atom/nprow + 1
    1303             :       END IF
    1304             : 
    1305          36 :       IF (MODULO(bs_env%n_atom, npcol) == 0) THEN
    1306          36 :          j_atoms_per_group = bs_env%n_atom/npcol
    1307             :       ELSE
    1308           0 :          j_atoms_per_group = bs_env%n_atom/npcol + 1
    1309             :       END IF
    1310             : 
    1311          36 :       atoms_i(1) = iprow*i_atoms_per_group + 1
    1312          36 :       atoms_i(2) = MIN((iprow + 1)*i_atoms_per_group, bs_env%n_atom)
    1313          36 :       n_atom_i = atoms_i(2) - atoms_i(1) + 1
    1314             : 
    1315          36 :       atoms_j(1) = ipcol*j_atoms_per_group + 1
    1316          36 :       atoms_j(2) = MIN((ipcol + 1)*j_atoms_per_group, bs_env%n_atom)
    1317          36 :       n_atom_j = atoms_j(2) - atoms_j(1) + 1
    1318             : 
    1319          36 :       CALL timestop(handle)
    1320             : 
    1321          36 :    END SUBROUTINE get_i_j_atoms
    1322             : 
    1323             : ! **************************************************************************************************
    1324             : !> \brief ...
    1325             : !> \param nprow ...
    1326             : !> \param npcol ...
    1327             : !> \param nproc ...
    1328             : ! **************************************************************************************************
    1329          36 :    SUBROUTINE square_mesh(nprow, npcol, nproc)
    1330             :       INTEGER                                            :: nprow, npcol, nproc
    1331             : 
    1332             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'square_mesh'
    1333             : 
    1334             :       INTEGER                                            :: gcd_max, handle, ipe, jpe
    1335             : 
    1336          36 :       CALL timeset(routineN, handle)
    1337             : 
    1338          36 :       gcd_max = -1
    1339          72 :       DO ipe = 1, CEILING(SQRT(REAL(nproc, dp)))
    1340          36 :          jpe = nproc/ipe
    1341          36 :          IF (ipe*jpe .NE. nproc) CYCLE
    1342          72 :          IF (gcd(ipe, jpe) >= gcd_max) THEN
    1343          36 :             nprow = ipe
    1344          36 :             npcol = jpe
    1345          36 :             gcd_max = gcd(ipe, jpe)
    1346             :          END IF
    1347             :       END DO
    1348             : 
    1349          36 :       CALL timestop(handle)
    1350             : 
    1351          36 :    END SUBROUTINE square_mesh
    1352             : 
    1353             : ! **************************************************************************************************
    1354             : !> \brief ...
    1355             : !> \param bs_env ...
    1356             : !> \param qs_env ...
    1357             : ! **************************************************************************************************
    1358          18 :    SUBROUTINE set_heuristic_parameters(bs_env, qs_env)
    1359             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1360             :       TYPE(qs_environment_type), OPTIONAL, POINTER       :: qs_env
    1361             : 
    1362             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'set_heuristic_parameters'
    1363             : 
    1364             :       INTEGER                                            :: handle
    1365             : 
    1366          18 :       CALL timeset(routineN, handle)
    1367             : 
    1368             :       ! use the same threshold for computing 3-center integrals (µν|P) as for filtering
    1369             :       ! tensor operations
    1370          18 :       bs_env%eps_3c_int = bs_env%eps_filter
    1371             : 
    1372             :       ! Determines number of cells used for summing the cells R in the Coulomb matrix,
    1373             :       ! V_PQ(k) = \sum_R <P,cell=0 | 1/r | Q,cell=R>. SIZE_LATTICE_SUM_V 3 gives
    1374             :       ! good convergence
    1375          18 :       bs_env%size_lattice_sum_V = 3
    1376             : 
    1377             :       ! for generating numerically stable minimax Fourier integration weights
    1378          18 :       bs_env%num_points_per_magnitude = 200
    1379             : 
    1380             :       ! for periodic systems and for 20 minimax points, we use a regularized minimax mesh
    1381             :       ! (from experience: regularized minimax meshes converges faster for periodic systems
    1382             :       !  and for 20 pts)
    1383          72 :       IF (SUM(bs_env%periodic) .NE. 0 .OR. bs_env%num_time_freq_points == 20) THEN
    1384          18 :          bs_env%regularization_minimax = 1.0E-6_dp
    1385             :       ELSE
    1386           0 :          bs_env%regularization_minimax = 0.0_dp
    1387             :       END IF
    1388             : 
    1389          18 :       bs_env%stabilize_exp = 70.0_dp
    1390          18 :       bs_env%eps_atom_grid_2d_mat = 1.0E-50_dp
    1391             : 
    1392             :       ! only use interval ω in [0, 27.211 eV] (1 Hartree = 27.211 eV) for virt, and ω in
    1393             :       ! [-27.211 eV, 0] for occ for use in analytic continuation of
    1394             :       ! self-energy Σ^c_n(iω,k) -> Σ^c_n(ϵ,k)
    1395          18 :       bs_env%freq_max_fit = 1.0_dp
    1396             : 
    1397             :       ! use a 16-parameter Padé fit
    1398          18 :       bs_env%nparam_pade = 16
    1399             : 
    1400             :       ! minimum block size for tensor operations, taken from MP2/RPA input
    1401          18 :       bs_env%min_block_size = 5
    1402             : 
    1403             :       ! resolution of the identity with the truncated Coulomb metric, cutoff radius 3 Angström
    1404          18 :       bs_env%ri_metric%potential_type = do_potential_truncated
    1405          18 :       bs_env%ri_metric%omega = 0.0_dp
    1406             :       ! cutoff radius = 3 Angström
    1407          18 :       bs_env%ri_metric%cutoff_radius = 3.0_dp/angstrom
    1408          18 :       bs_env%ri_metric%filename = "t_c_g.dat"
    1409             : 
    1410          18 :       bs_env%eps_eigval_mat_RI = 0.0_dp
    1411             : 
    1412             :       ! for periodic systems, we use the regularized resolution of the identity
    1413          72 :       IF (SUM(bs_env%periodic) == 0) THEN
    1414           0 :          bs_env%regularization_RI = 0.0_dp
    1415             :       ELSE
    1416          18 :          bs_env%regularization_RI = 1.0E-2_dp
    1417             :       END IF
    1418             : 
    1419             :       ! truncated Coulomb operator for exchange self-energy
    1420             :       ! (see details in Guidon, VandeVondele, Hutter, JCTC 5, 3010 (2009) and references therein)
    1421             :       CALL setup_trunc_coulomb_pot_for_exchange_self_energy(qs_env, bs_env%trunc_coulomb, &
    1422          18 :                                                             rel_cutoff_trunc_coulomb_ri_x=0.5_dp)
    1423             : 
    1424          18 :       CALL timestop(handle)
    1425             : 
    1426          18 :    END SUBROUTINE set_heuristic_parameters
    1427             : 
    1428             : ! **************************************************************************************************
    1429             : !> \brief ...
    1430             : !> \param bs_env ...
    1431             : ! **************************************************************************************************
    1432          18 :    SUBROUTINE print_header_and_input_parameters(bs_env)
    1433             : 
    1434             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1435             : 
    1436             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'print_header_and_input_parameters'
    1437             : 
    1438             :       INTEGER                                            :: handle, u
    1439             : 
    1440          18 :       CALL timeset(routineN, handle)
    1441             : 
    1442          18 :       u = bs_env%unit_nr
    1443             : 
    1444          18 :       IF (u > 0) THEN
    1445           9 :          WRITE (u, *) ' '
    1446           9 :          WRITE (u, '(T2,2A)') '------------------------------------------------', &
    1447          18 :             '-------------------------------'
    1448           9 :          WRITE (u, '(T2,2A)') '-                                               ', &
    1449          18 :             '                              -'
    1450           9 :          WRITE (u, '(T2,2A)') '-                              GW CALCULATION   ', &
    1451          18 :             '                              -'
    1452           9 :          WRITE (u, '(T2,2A)') '-                                               ', &
    1453          18 :             '                              -'
    1454           9 :          WRITE (u, '(T2,2A)') '------------------------------------------------', &
    1455          18 :             '-------------------------------'
    1456           9 :          WRITE (u, '(T2,A)') ' '
    1457           9 :          WRITE (u, '(T2,A,I45)') 'Input: Number of time/freq. points', bs_env%num_time_freq_points
    1458           9 :          WRITE (u, '(T2,A,ES27.1)') 'Input: Filter threshold for sparse tensor operations', &
    1459          18 :             bs_env%eps_filter
    1460             :       END IF
    1461             : 
    1462          18 :       CALL timestop(handle)
    1463             : 
    1464          18 :    END SUBROUTINE print_header_and_input_parameters
    1465             : 
    1466             : ! **************************************************************************************************
    1467             : !> \brief ...
    1468             : !> \param qs_env ...
    1469             : !> \param bs_env ...
    1470             : ! **************************************************************************************************
    1471          36 :    SUBROUTINE compute_fm_V_xc_Gamma(qs_env, bs_env)
    1472             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1473             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1474             : 
    1475             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_fm_V_xc_Gamma'
    1476             : 
    1477             :       INTEGER                                            :: handle, ispin, myfun, nimages
    1478             :       REAL(KIND=dp)                                      :: energy_ex, energy_exc, energy_total
    1479          18 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mat_ks_without_v_xc
    1480             :       TYPE(dft_control_type), POINTER                    :: dft_control
    1481             :       TYPE(qs_energy_type), POINTER                      :: energy
    1482             :       TYPE(section_vals_type), POINTER                   :: input, xc_section
    1483             : 
    1484          18 :       CALL timeset(routineN, handle)
    1485             : 
    1486          18 :       CALL get_qs_env(qs_env, input=input, energy=energy, dft_control=dft_control)
    1487             : 
    1488             :       ! previously, dft_control%nimages set to # neighbor cells, revert for Γ-only KS matrix
    1489          18 :       nimages = dft_control%nimages
    1490          18 :       dft_control%nimages = 1
    1491             : 
    1492             :       ! we need to reset XC functional, therefore, get XC input
    1493          18 :       xc_section => section_vals_get_subs_vals(input, "DFT%XC")
    1494          18 :       CALL section_vals_val_get(xc_section, "XC_FUNCTIONAL%_SECTION_PARAMETERS_", i_val=myfun)
    1495          18 :       CALL section_vals_val_set(xc_section, "XC_FUNCTIONAL%_SECTION_PARAMETERS_", i_val=xc_none)
    1496             : 
    1497             :       ! save the energy before the energy gets updated
    1498          18 :       energy_total = energy%total
    1499          18 :       energy_exc = energy%exc
    1500          18 :       energy_ex = energy%ex
    1501             : 
    1502          18 :       NULLIFY (mat_ks_without_v_xc)
    1503          18 :       CALL dbcsr_allocate_matrix_set(mat_ks_without_v_xc, bs_env%n_spin)
    1504             : 
    1505          42 :       DO ispin = 1, bs_env%n_spin
    1506          24 :          ALLOCATE (mat_ks_without_v_xc(ispin)%matrix)
    1507          42 :          CALL dbcsr_create(mat_ks_without_v_xc(ispin)%matrix, template=bs_env%mat_ao_ao%matrix)
    1508             :       END DO
    1509             : 
    1510             :       ! calculate KS-matrix without XC
    1511             :       CALL qs_ks_build_kohn_sham_matrix(qs_env, calculate_forces=.FALSE., just_energy=.FALSE., &
    1512          18 :                                         ext_ks_matrix=mat_ks_without_v_xc)
    1513             : 
    1514          42 :       DO ispin = 1, bs_env%n_spin
    1515             :          ! transfer dbcsr matrix to fm
    1516          24 :          CALL cp_fm_create(bs_env%fm_V_xc_Gamma(ispin), bs_env%fm_s_Gamma%matrix_struct)
    1517          24 :          CALL copy_dbcsr_to_fm(mat_ks_without_v_xc(ispin)%matrix, bs_env%fm_V_xc_Gamma(ispin))
    1518             : 
    1519             :          ! finally compute the xc potential in the AO basis
    1520             :          CALL cp_fm_scale_and_add(alpha=-1.0_dp, matrix_a=bs_env%fm_V_xc_Gamma(ispin), &
    1521          42 :                                   beta=1.0_dp, matrix_b=bs_env%fm_ks_Gamma(ispin))
    1522             :       END DO
    1523             : 
    1524             :       ! set back the energy
    1525          18 :       energy%total = energy_total
    1526          18 :       energy%exc = energy_exc
    1527          18 :       energy%ex = energy_ex
    1528             : 
    1529             :       ! set back nimages
    1530          18 :       dft_control%nimages = nimages
    1531             : 
    1532             :       ! set the DFT functional and HF fraction back
    1533             :       CALL section_vals_val_set(xc_section, "XC_FUNCTIONAL%_SECTION_PARAMETERS_", &
    1534          18 :                                 i_val=myfun)
    1535             : 
    1536          18 :       CALL dbcsr_deallocate_matrix_set(mat_ks_without_v_xc)
    1537             : 
    1538          18 :       CALL timestop(handle)
    1539             : 
    1540          18 :    END SUBROUTINE compute_fm_V_xc_Gamma
    1541             : 
    1542             : ! **************************************************************************************************
    1543             : !> \brief ...
    1544             : !> \param bs_env ...
    1545             : ! **************************************************************************************************
    1546          18 :    SUBROUTINE setup_time_and_frequency_minimax_grid(bs_env)
    1547             :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
    1548             : 
    1549             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'setup_time_and_frequency_minimax_grid'
    1550             : 
    1551             :       INTEGER                                            :: handle, homo, i_w, ierr, j_w, n_mo, &
    1552             :                                                             num_time_freq_points, u
    1553             :       REAL(KIND=dp)                                      :: E_max, E_min, E_range, max_error_min
    1554             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: points_and_weights
    1555             : 
    1556          18 :       CALL timeset(routineN, handle)
    1557             : 
    1558          18 :       homo = bs_env%n_occ(1)
    1559          18 :       n_mo = bs_env%n_ao
    1560          18 :       num_time_freq_points = bs_env%num_time_freq_points
    1561             : 
    1562             :       ! minimum and maximum difference between eigenvalues of unoccupied and an occupied MOs
    1563             :       E_min = MINVAL(bs_env%eigenval_scf_Gamma(homo + 1, :)) - &
    1564         102 :               MAXVAL(bs_env%eigenval_scf_Gamma(homo, :))
    1565             :       E_max = MAXVAL(bs_env%eigenval_scf_Gamma(n_mo, :)) - &
    1566         102 :               MINVAL(bs_env%eigenval_scf_Gamma(1, :))
    1567             : 
    1568          18 :       E_range = E_max/E_min
    1569             : 
    1570          54 :       ALLOCATE (points_and_weights(2*num_time_freq_points))
    1571             : 
    1572             :       ! frequency points
    1573          18 :       IF (num_time_freq_points .LE. 20) THEN
    1574          18 :          CALL get_rpa_minimax_coeff(num_time_freq_points, E_range, points_and_weights, ierr, .FALSE.)
    1575             :       ELSE
    1576           0 :          CALL get_rpa_minimax_coeff_larger_grid(num_time_freq_points, E_range, points_and_weights)
    1577             :       END IF
    1578             : 
    1579             :       ! one needs to scale the minimax grids, see Azizi, Wilhelm, Golze, Panades-Barrueta,
    1580             :       ! Giantomassi, Rinke, Draxl, Gonze et al., 2 publications
    1581         190 :       bs_env%imag_freq_points(:) = points_and_weights(1:num_time_freq_points)*E_min
    1582             : 
    1583             :       ! determine number of fit points in the interval [0,ω_max] for virt, or [-ω_max,0] for occ
    1584          18 :       bs_env%num_freq_points_fit = 0
    1585         190 :       DO i_w = 1, bs_env%num_time_freq_points
    1586         190 :          IF (bs_env%imag_freq_points(i_w) < bs_env%freq_max_fit) THEN
    1587          82 :             bs_env%num_freq_points_fit = bs_env%num_freq_points_fit + 1
    1588             :          END IF
    1589             :       END DO
    1590             : 
    1591             :       ! iω values for the analytic continuation Σ^c_n(iω,k) -> Σ^c_n(ϵ,k)
    1592          54 :       ALLOCATE (bs_env%imag_freq_points_fit(bs_env%num_freq_points_fit))
    1593          18 :       j_w = 0
    1594         190 :       DO i_w = 1, bs_env%num_time_freq_points
    1595         190 :          IF (bs_env%imag_freq_points(i_w) < bs_env%freq_max_fit) THEN
    1596          82 :             j_w = j_w + 1
    1597          82 :             bs_env%imag_freq_points_fit(j_w) = bs_env%imag_freq_points(i_w)
    1598             :          END IF
    1599             :       END DO
    1600             : 
    1601             :       ! reset the number of Padé parameters if smaller than the number of
    1602             :       ! imaginary-frequency points for the fit
    1603          18 :       IF (bs_env%num_freq_points_fit < bs_env%nparam_pade) THEN
    1604          18 :          bs_env%nparam_pade = bs_env%num_freq_points_fit
    1605             :       END IF
    1606             : 
    1607             :       ! time points
    1608          18 :       IF (num_time_freq_points .LE. 20) THEN
    1609          18 :          CALL get_exp_minimax_coeff(num_time_freq_points, E_range, points_and_weights)
    1610             :       ELSE
    1611           0 :          CALL get_exp_minimax_coeff_gw(num_time_freq_points, E_range, points_and_weights)
    1612             :       END IF
    1613             : 
    1614         190 :       bs_env%imag_time_points(:) = points_and_weights(1:num_time_freq_points)/(2.0_dp*E_min)
    1615             : 
    1616          18 :       DEALLOCATE (points_and_weights)
    1617             : 
    1618             :       ! in minimax grids, Fourier transforms t -> w and w -> t are split using
    1619             :       ! e^(iwt) = cos(wt) + i sin(wt); we thus calculate weights for trafos with a cos and
    1620             :       ! sine prefactor; details in Azizi, Wilhelm, Golze, Giantomassi, Panades-Barrueta,
    1621             :       ! Rinke, Draxl, Gonze et al., 2 publications
    1622             : 
    1623             :       ! cosine transform weights imaginary time to imaginary frequency
    1624             :       CALL get_l_sq_wghts_cos_tf_t_to_w(num_time_freq_points, &
    1625             :                                         bs_env%imag_time_points, &
    1626             :                                         bs_env%weights_cos_t_to_w, &
    1627             :                                         bs_env%imag_freq_points, &
    1628             :                                         E_min, E_max, max_error_min, &
    1629             :                                         bs_env%num_points_per_magnitude, &
    1630          18 :                                         bs_env%regularization_minimax)
    1631             : 
    1632             :       ! cosine transform weights imaginary frequency to imaginary time
    1633             :       CALL get_l_sq_wghts_cos_tf_w_to_t(num_time_freq_points, &
    1634             :                                         bs_env%imag_time_points, &
    1635             :                                         bs_env%weights_cos_w_to_t, &
    1636             :                                         bs_env%imag_freq_points, &
    1637             :                                         E_min, E_max, max_error_min, &
    1638             :                                         bs_env%num_points_per_magnitude, &
    1639          18 :                                         bs_env%regularization_minimax)
    1640             : 
    1641             :       ! sine transform weights imaginary time to imaginary frequency
    1642             :       CALL get_l_sq_wghts_sin_tf_t_to_w(num_time_freq_points, &
    1643             :                                         bs_env%imag_time_points, &
    1644             :                                         bs_env%weights_sin_t_to_w, &
    1645             :                                         bs_env%imag_freq_points, &
    1646             :                                         E_min, E_max, max_error_min, &
    1647             :                                         bs_env%num_points_per_magnitude, &
    1648          18 :                                         bs_env%regularization_minimax)
    1649             : 
    1650          18 :       u = bs_env%unit_nr
    1651          18 :       IF (u > 0) THEN
    1652           9 :          WRITE (u, '(T2,A)') ''
    1653           9 :          WRITE (u, '(T2,A,F44.2)') 'SCF direct band gap at Γ-point (eV)', E_min*evolt
    1654           9 :          WRITE (u, '(T2,A,F42.2)') 'Max. SCF eigval diff. at Γ-point (eV)', E_max*evolt
    1655           9 :          WRITE (u, '(T2,A,F55.2)') 'E-Range for minimax grid', E_range
    1656           9 :          WRITE (u, '(T2,A,I27)') 'Number of Padé parameters for analytic continuation:', &
    1657          18 :             bs_env%nparam_pade
    1658           9 :          WRITE (u, '(T2,A)') ''
    1659             :       END IF
    1660          18 :       CALL timestop(handle)
    1661             : 
    1662          36 :    END SUBROUTINE setup_time_and_frequency_minimax_grid
    1663             : 
    1664             : END MODULE gw_utils

Generated by: LCOV version 1.15