LCOV - code coverage report
Current view: top level - src - negf_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 73.0 % 1191 869
Test Date: 2025-12-04 06:27:48 Functions: 88.2 % 17 15

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief NEGF based quantum transport calculations
      10              : ! **************************************************************************************************
      11              : MODULE negf_methods
      12              :    USE bibliography,                    ONLY: Bailey2006,&
      13              :                                               Papior2017,&
      14              :                                               cite_reference
      15              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      16              :    USE cp_cfm_basic_linalg,             ONLY: cp_cfm_scale,&
      17              :                                               cp_cfm_scale_and_add,&
      18              :                                               cp_cfm_trace
      19              :    USE cp_cfm_types,                    ONLY: &
      20              :         copy_cfm_info_type, cp_cfm_cleanup_copy_general, cp_cfm_create, &
      21              :         cp_cfm_finish_copy_general, cp_cfm_get_info, cp_cfm_get_submatrix, cp_cfm_release, &
      22              :         cp_cfm_set_submatrix, cp_cfm_start_copy_general, cp_cfm_to_fm, cp_cfm_type
      23              :    USE cp_control_types,                ONLY: dft_control_type
      24              :    USE cp_dbcsr_api,                    ONLY: dbcsr_copy,&
      25              :                                               dbcsr_deallocate_matrix,&
      26              :                                               dbcsr_init_p,&
      27              :                                               dbcsr_p_type
      28              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_dot
      29              :    USE cp_dbcsr_operations,             ONLY: dbcsr_allocate_matrix_set
      30              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_scale,&
      31              :                                               cp_fm_scale_and_add,&
      32              :                                               cp_fm_trace
      33              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      34              :                                               cp_fm_struct_release,&
      35              :                                               cp_fm_struct_type
      36              :    USE cp_fm_types,                     ONLY: cp_fm_copy_general,&
      37              :                                               cp_fm_create,&
      38              :                                               cp_fm_get_info,&
      39              :                                               cp_fm_get_submatrix,&
      40              :                                               cp_fm_release,&
      41              :                                               cp_fm_set_all,&
      42              :                                               cp_fm_to_fm,&
      43              :                                               cp_fm_type
      44              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      45              :                                               cp_logger_get_default_io_unit,&
      46              :                                               cp_logger_type
      47              :    USE cp_output_handling,              ONLY: cp_p_file,&
      48              :                                               cp_print_key_finished_output,&
      49              :                                               cp_print_key_should_output,&
      50              :                                               cp_print_key_unit_nr,&
      51              :                                               debug_print_level,&
      52              :                                               high_print_level
      53              :    USE cp_subsys_types,                 ONLY: cp_subsys_type
      54              :    USE force_env_types,                 ONLY: force_env_get,&
      55              :                                               force_env_p_type,&
      56              :                                               force_env_type
      57              :    USE global_types,                    ONLY: global_environment_type
      58              :    USE input_constants,                 ONLY: negfint_method_cc,&
      59              :                                               negfint_method_simpson
      60              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      61              :                                               section_vals_type,&
      62              :                                               section_vals_val_get
      63              :    USE kinds,                           ONLY: default_string_length,&
      64              :                                               dp
      65              :    USE kpoint_types,                    ONLY: get_kpoint_info,&
      66              :                                               kpoint_type
      67              :    USE machine,                         ONLY: m_walltime
      68              :    USE mathconstants,                   ONLY: pi,&
      69              :                                               twopi,&
      70              :                                               z_one,&
      71              :                                               z_zero
      72              :    USE message_passing,                 ONLY: mp_para_env_type
      73              :    USE negf_control_types,              ONLY: negf_control_create,&
      74              :                                               negf_control_release,&
      75              :                                               negf_control_type,&
      76              :                                               read_negf_control
      77              :    USE negf_env_types,                  ONLY: negf_env_create,&
      78              :                                               negf_env_release,&
      79              :                                               negf_env_type
      80              :    USE negf_green_cache,                ONLY: green_functions_cache_expand,&
      81              :                                               green_functions_cache_release,&
      82              :                                               green_functions_cache_reorder,&
      83              :                                               green_functions_cache_type
      84              :    USE negf_green_methods,              ONLY: do_sancho,&
      85              :                                               negf_contact_broadening_matrix,&
      86              :                                               negf_contact_self_energy,&
      87              :                                               negf_retarded_green_function,&
      88              :                                               sancho_work_matrices_create,&
      89              :                                               sancho_work_matrices_release,&
      90              :                                               sancho_work_matrices_type
      91              :    USE negf_integr_cc,                  ONLY: &
      92              :         cc_interval_full, cc_interval_half, cc_shape_arc, cc_shape_linear, &
      93              :         ccquad_double_number_of_points, ccquad_init, ccquad_reduce_and_append_zdata, &
      94              :         ccquad_refine_integral, ccquad_release, ccquad_type
      95              :    USE negf_integr_simpson,             ONLY: simpsonrule_get_next_nodes,&
      96              :                                               simpsonrule_init,&
      97              :                                               simpsonrule_refine_integral,&
      98              :                                               simpsonrule_release,&
      99              :                                               simpsonrule_type,&
     100              :                                               sr_shape_arc,&
     101              :                                               sr_shape_linear
     102              :    USE negf_matrix_utils,               ONLY: invert_cell_to_index,&
     103              :                                               negf_copy_fm_submat_to_dbcsr,&
     104              :                                               negf_copy_sym_dbcsr_to_fm_submat
     105              :    USE negf_subgroup_types,             ONLY: negf_sub_env_create,&
     106              :                                               negf_sub_env_release,&
     107              :                                               negf_subgroup_env_type
     108              :    USE parallel_gemm_api,               ONLY: parallel_gemm
     109              :    USE physcon,                         ONLY: e_charge,&
     110              :                                               evolt,&
     111              :                                               kelvin,&
     112              :                                               seconds
     113              :    USE qs_density_mixing_types,         ONLY: direct_mixing_nr,&
     114              :                                               gspace_mixing_nr
     115              :    USE qs_energy_types,                 ONLY: qs_energy_type
     116              :    USE qs_environment_types,            ONLY: get_qs_env,&
     117              :                                               qs_environment_type
     118              :    USE qs_gspace_mixing,                ONLY: gspace_mixing
     119              :    USE qs_ks_methods,                   ONLY: qs_ks_build_kohn_sham_matrix
     120              :    USE qs_mixing_utils,                 ONLY: mixing_allocate,&
     121              :                                               mixing_init
     122              :    USE qs_rho_methods,                  ONLY: qs_rho_update_rho
     123              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
     124              :                                               qs_rho_type
     125              :    USE qs_scf_methods,                  ONLY: scf_env_density_mixing
     126              :    USE qs_subsys_types,                 ONLY: qs_subsys_type
     127              :    USE string_utilities,                ONLY: integer_to_string
     128              : #include "./base/base_uses.f90"
     129              : 
     130              :    IMPLICIT NONE
     131              :    PRIVATE
     132              : 
     133              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'negf_methods'
     134              :    LOGICAL, PARAMETER, PRIVATE          :: debug_this_module = .TRUE.
     135              : 
     136              :    PUBLIC :: do_negf
     137              : 
     138              : ! **************************************************************************************************
     139              : !> \brief Type to accumulate the total number of points used in integration as well as
     140              : !>        the final error estimate
     141              : !> \author Sergey Chulkov
     142              : ! **************************************************************************************************
     143              :    TYPE integration_status_type
     144              :       INTEGER                                            :: npoints = -1
     145              :       REAL(kind=dp)                                      :: error = -1.0_dp
     146              :    END TYPE integration_status_type
     147              : 
     148              : CONTAINS
     149              : 
     150              : ! **************************************************************************************************
     151              : !> \brief Perform NEGF calculation.
     152              : !> \param force_env  Force environment
     153              : !> \par History
     154              : !>    * 01.2017 created  [Sergey Chulkov]
     155              : !>    * 11.2025 modified [Dmitry Ryndyk]
     156              : ! **************************************************************************************************
     157            4 :    SUBROUTINE do_negf(force_env)
     158              :       TYPE(force_env_type), POINTER                      :: force_env
     159              : 
     160              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'do_negf'
     161              : 
     162              :       CHARACTER(len=default_string_length)               :: contact_id_str
     163              :       INTEGER                                            :: handle, icontact, ispin, log_unit, &
     164              :                                                             ncontacts, npoints, nspins, &
     165              :                                                             print_level, print_unit
     166              :       LOGICAL                                            :: debug_output, should_output, &
     167              :                                                             verbose_output
     168              :       REAL(kind=dp)                                      :: energy_max, energy_min
     169              :       REAL(kind=dp), DIMENSION(2)                        :: current
     170              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     171              :       TYPE(cp_logger_type), POINTER                      :: logger
     172              :       TYPE(cp_subsys_type), POINTER                      :: cp_subsys
     173              :       TYPE(dft_control_type), POINTER                    :: dft_control
     174            4 :       TYPE(force_env_p_type), DIMENSION(:), POINTER      :: sub_force_env
     175              :       TYPE(global_environment_type), POINTER             :: global_env
     176              :       TYPE(mp_para_env_type), POINTER                    :: para_env_global
     177              :       TYPE(negf_control_type), POINTER                   :: negf_control
     178            4 :       TYPE(negf_env_type)                                :: negf_env
     179            4 :       TYPE(negf_subgroup_env_type)                       :: sub_env
     180              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     181              :       TYPE(section_vals_type), POINTER                   :: negf_contact_section, &
     182              :                                                             negf_mixing_section, negf_section, &
     183              :                                                             print_section, root_section
     184              : 
     185            4 :       CALL timeset(routineN, handle)
     186            4 :       logger => cp_get_default_logger()
     187            4 :       log_unit = cp_logger_get_default_io_unit()
     188              : 
     189            4 :       CALL cite_reference(Bailey2006)
     190            4 :       CALL cite_reference(Papior2017)
     191              : 
     192            4 :       NULLIFY (blacs_env, cp_subsys, global_env, qs_env, root_section, sub_force_env)
     193              :       CALL force_env_get(force_env, globenv=global_env, qs_env=qs_env, root_section=root_section, &
     194            4 :                          sub_force_env=sub_force_env, subsys=cp_subsys)
     195              : 
     196            4 :       CALL get_qs_env(qs_env, blacs_env=blacs_env, para_env=para_env_global)
     197              : 
     198            4 :       negf_section => section_vals_get_subs_vals(root_section, "NEGF")
     199            4 :       negf_contact_section => section_vals_get_subs_vals(negf_section, "CONTACT")
     200            4 :       negf_mixing_section => section_vals_get_subs_vals(negf_section, "MIXING")
     201              : 
     202            4 :       NULLIFY (negf_control)
     203            4 :       CALL negf_control_create(negf_control)
     204            4 :       CALL read_negf_control(negf_control, root_section, cp_subsys)
     205            4 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     206              : 
     207              :       ! print unit, if log_unit > 0, otherwise no output
     208            4 :       log_unit = cp_print_key_unit_nr(logger, negf_section, "PRINT%PROGRAM_RUN_INFO", extension=".Log")
     209              : 
     210            4 :       IF (log_unit > 0) THEN
     211            2 :          WRITE (log_unit, '(/,T2,79("-"))')
     212            2 :          WRITE (log_unit, '(T27,A,T62)') "NEGF calculation is started"
     213            2 :          WRITE (log_unit, '(T2,79("-"))')
     214              :       END IF
     215              : 
     216              :       ! print levels, are used if log_unit > 0
     217              :       ! defined for all parallel MPI processes
     218            4 :       CALL section_vals_val_get(negf_section, "PRINT%PROGRAM_RUN_INFO%PRINT_LEVEL", i_val=print_level)
     219            0 :       SELECT CASE (print_level)
     220              :       CASE (high_print_level)
     221            0 :          verbose_output = .TRUE.
     222              :       CASE (debug_print_level)
     223            4 :          verbose_output = .TRUE.
     224            4 :          debug_output = .TRUE.
     225              :       CASE DEFAULT
     226            0 :          verbose_output = .FALSE.
     227            4 :          debug_output = .FALSE.
     228              :       END SELECT
     229              : 
     230            4 :       IF (log_unit > 0) THEN
     231            2 :          WRITE (log_unit, "(/,' THE RELEVANT HAMILTONIAN AND OVERLAP MATRICES FROM DFT')")
     232            2 :          WRITE (log_unit, "(  ' ------------------------------------------------------')")
     233              :       END IF
     234              : 
     235            4 :       CALL negf_sub_env_create(sub_env, negf_control, blacs_env, global_env%blacs_grid_layout, global_env%blacs_repeatable)
     236            4 :       CALL negf_env_create(negf_env, sub_env, negf_control, force_env, negf_mixing_section, log_unit)
     237              : 
     238            4 :       IF (log_unit > 0) THEN
     239            2 :          WRITE (log_unit, "(/,' NEGF| The initial Hamiltonian and Overlap matrices are calculated.')")
     240              :       END IF
     241              : 
     242            4 :       CALL negf_output_initial(log_unit, negf_env, sub_env, negf_control, dft_control, verbose_output, debug_output)
     243              : 
     244              :       ! NEGF procedure
     245              :       ! --------------
     246              : 
     247              :       ! Compute contact Fermi levels as well as requested properties
     248              :       ! ------------------------------------------------------------
     249            4 :       ncontacts = SIZE(negf_control%contacts)
     250           12 :       DO icontact = 1, ncontacts
     251            8 :          NULLIFY (qs_env)
     252            8 :          IF (negf_control%contacts(icontact)%force_env_index > 0) THEN
     253            4 :             CALL force_env_get(sub_force_env(negf_control%contacts(icontact)%force_env_index)%force_env, qs_env=qs_env)
     254              :          ELSE
     255            4 :             CALL force_env_get(force_env, qs_env=qs_env)
     256              :          END IF
     257              : 
     258            8 :          CALL guess_fermi_level(icontact, negf_env, negf_control, sub_env, qs_env, log_unit)
     259              : 
     260            8 :          print_section => section_vals_get_subs_vals(negf_contact_section, "PRINT", i_rep_section=icontact)
     261            8 :          should_output = BTEST(cp_print_key_should_output(logger%iter_info, print_section, "DOS"), cp_p_file)
     262              : 
     263           12 :          IF (should_output) THEN
     264            0 :             CALL section_vals_val_get(print_section, "DOS%FROM_ENERGY", r_val=energy_min)
     265            0 :             CALL section_vals_val_get(print_section, "DOS%TILL_ENERGY", r_val=energy_max)
     266            0 :             CALL section_vals_val_get(print_section, "DOS%N_GRIDPOINTS", i_val=npoints)
     267              : 
     268            0 :             CALL integer_to_string(icontact, contact_id_str)
     269              :             print_unit = cp_print_key_unit_nr(logger, print_section, "DOS", &
     270              :                                               extension=".dos", &
     271              :                                               middle_name=TRIM(ADJUSTL(contact_id_str)), &
     272            0 :                                               file_status="REPLACE")
     273              :             CALL negf_print_dos(print_unit, energy_min, energy_max, npoints, &
     274              :                                 v_shift=0.0_dp, negf_env=negf_env, negf_control=negf_control, &
     275            0 :                                 sub_env=sub_env, base_contact=icontact, just_contact=icontact)
     276            0 :             CALL cp_print_key_finished_output(print_unit, logger, print_section, "DOS")
     277              :          END IF
     278              : 
     279              :       END DO
     280              : 
     281              :       ! Compute multi-terminal systems
     282              :       ! ------------------------------
     283            4 :       IF (ncontacts > 1) THEN
     284            4 :          CALL force_env_get(force_env, qs_env=qs_env)
     285              : 
     286              :          ! shift potential
     287              :          ! ---------------
     288            4 :          CALL shift_potential(negf_env, negf_control, sub_env, qs_env, base_contact=1, log_unit=log_unit)
     289              : 
     290              :          ! self-consistent density
     291              :          ! -----------------------
     292            4 :          CALL converge_density(negf_env, negf_control, sub_env, qs_env, negf_control%v_shift, base_contact=1, log_unit=log_unit)
     293              : 
     294              :          ! current
     295              :          ! -------
     296            4 :          CALL get_qs_env(qs_env, dft_control=dft_control)
     297              : 
     298            4 :          nspins = dft_control%nspins
     299              : 
     300            4 :          CPASSERT(nspins <= 2)
     301            8 :          DO ispin = 1, nspins
     302              :             ! compute the electric current flown through a pair of electrodes
     303              :             ! contact_id1 -> extended molecule -> contact_id2.
     304              :             ! Only extended systems with two electrodes are supported at the moment,
     305              :             ! so for the time being the contacts' indices are hardcoded.
     306              :             current(ispin) = negf_compute_current(contact_id1=1, contact_id2=2, &
     307              :                                                   v_shift=negf_control%v_shift, &
     308              :                                                   negf_env=negf_env, &
     309              :                                                   negf_control=negf_control, &
     310              :                                                   sub_env=sub_env, &
     311              :                                                   ispin=ispin, &
     312            8 :                                                   blacs_env_global=blacs_env)
     313              :          END DO
     314              : 
     315            4 :          IF (log_unit > 0) THEN
     316            2 :             IF (nspins > 1) THEN
     317            0 :                WRITE (log_unit, '(/,T2,A,T60,ES20.7E2)') "NEGF| Alpha-spin electric current (A)", current(1)
     318            0 :                WRITE (log_unit, '(T2,A,T60,ES20.7E2)') "NEGF|  Beta-spin electric current (A)", current(2)
     319              :             ELSE
     320            2 :                WRITE (log_unit, '(/,T2,A,T60,ES20.7E2)') "NEGF|  Electric current (A)", 2.0_dp*current(1)
     321              :             END IF
     322              :          END IF
     323              : 
     324              :          ! density of states
     325              :          ! -----------------
     326            4 :          print_section => section_vals_get_subs_vals(negf_section, "PRINT")
     327            4 :          should_output = BTEST(cp_print_key_should_output(logger%iter_info, print_section, "DOS"), cp_p_file)
     328              : 
     329            4 :          IF (should_output) THEN
     330            4 :             CALL section_vals_val_get(print_section, "DOS%FROM_ENERGY", r_val=energy_min)
     331            4 :             CALL section_vals_val_get(print_section, "DOS%TILL_ENERGY", r_val=energy_max)
     332            4 :             CALL section_vals_val_get(print_section, "DOS%N_GRIDPOINTS", i_val=npoints)
     333              : 
     334            4 :             CALL integer_to_string(0, contact_id_str)
     335              :             print_unit = cp_print_key_unit_nr(logger, print_section, "DOS", &
     336              :                                               extension=".dos", &
     337              :                                               middle_name=TRIM(ADJUSTL(contact_id_str)), &
     338            4 :                                               file_status="REPLACE")
     339              : 
     340              :             CALL negf_print_dos(print_unit, energy_min, energy_max, npoints, negf_control%v_shift, &
     341              :                                 negf_env=negf_env, negf_control=negf_control, &
     342            4 :                                 sub_env=sub_env, base_contact=1)
     343              : 
     344            4 :             CALL cp_print_key_finished_output(print_unit, logger, print_section, "DOS")
     345              :          END IF
     346              : 
     347              :          ! transmission coefficient
     348              :          ! ------------------------
     349            4 :          should_output = BTEST(cp_print_key_should_output(logger%iter_info, print_section, "TRANSMISSION"), cp_p_file)
     350              : 
     351            4 :          IF (should_output) THEN
     352            4 :             CALL section_vals_val_get(print_section, "TRANSMISSION%FROM_ENERGY", r_val=energy_min)
     353            4 :             CALL section_vals_val_get(print_section, "TRANSMISSION%TILL_ENERGY", r_val=energy_max)
     354            4 :             CALL section_vals_val_get(print_section, "TRANSMISSION%N_GRIDPOINTS", i_val=npoints)
     355              : 
     356            4 :             CALL integer_to_string(0, contact_id_str)
     357              :             print_unit = cp_print_key_unit_nr(logger, print_section, "TRANSMISSION", &
     358              :                                               extension=".transm", &
     359              :                                               middle_name=TRIM(ADJUSTL(contact_id_str)), &
     360            4 :                                               file_status="REPLACE")
     361              : 
     362              :             CALL negf_print_transmission(print_unit, energy_min, energy_max, npoints, negf_control%v_shift, &
     363              :                                          negf_env=negf_env, negf_control=negf_control, &
     364            4 :                                          sub_env=sub_env, contact_id1=1, contact_id2=2)
     365              : 
     366            4 :             CALL cp_print_key_finished_output(print_unit, logger, print_section, "TRANSMISSION")
     367              :          END IF
     368              : 
     369              :       END IF
     370              : 
     371            4 :       IF (log_unit > 0) THEN
     372            2 :          WRITE (log_unit, '(/,T2,79("-"))')
     373            2 :          WRITE (log_unit, '(T27,A,T62)') "NEGF calculation is finished"
     374            2 :          WRITE (log_unit, '(T2,79("-"))')
     375              :       END IF
     376              : 
     377            4 :       CALL negf_env_release(negf_env)
     378            4 :       CALL negf_sub_env_release(sub_env)
     379            4 :       CALL negf_control_release(negf_control)
     380            4 :       CALL timestop(handle)
     381            8 :    END SUBROUTINE do_negf
     382              : 
     383              : ! **************************************************************************************************
     384              : !> \brief Compute the contact's Fermi level.
     385              : !> \param contact_id    index of the contact
     386              : !> \param negf_env      NEGF environment
     387              : !> \param negf_control  NEGF control
     388              : !> \param sub_env       NEGF parallel (sub)group environment
     389              : !> \param qs_env        QuickStep environment
     390              : !> \param log_unit      output unit
     391              : !> \par History
     392              : !>    * 10.2017 created  [Sergey Chulkov]
     393              : !>    * 11.2025 modified [Dmitry Ryndyk]
     394              : ! **************************************************************************************************
     395            8 :    SUBROUTINE guess_fermi_level(contact_id, negf_env, negf_control, sub_env, qs_env, log_unit)
     396              :       INTEGER, INTENT(in)                                :: contact_id
     397              :       TYPE(negf_env_type), INTENT(in)                    :: negf_env
     398              :       TYPE(negf_control_type), POINTER                   :: negf_control
     399              :       TYPE(negf_subgroup_env_type), INTENT(in)           :: sub_env
     400              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     401              :       INTEGER, INTENT(in)                                :: log_unit
     402              : 
     403              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'guess_fermi_level'
     404              :       TYPE(cp_fm_type), PARAMETER                        :: fm_dummy = cp_fm_type()
     405              : 
     406              :       CHARACTER(len=default_string_length)               :: temperature_str
     407              :       COMPLEX(kind=dp)                                   :: lbound_cpath, lbound_lpath, ubound_lpath
     408              :       INTEGER                                            :: direction_axis_abs, handle, image, &
     409              :                                                             ispin, nao, nimages, nspins, step
     410            8 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: index_to_cell
     411            8 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
     412              :       LOGICAL                                            :: do_kpoints
     413              :       REAL(kind=dp) :: delta_au, energy_ubound_minus_fermi, fermi_level_guess, fermi_level_max, &
     414              :          fermi_level_min, nelectrons_guess, nelectrons_max, nelectrons_min, nelectrons_qs_cell0, &
     415              :          nelectrons_qs_cell1, offset_au, rscale, t1, t2, trace
     416              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env_global
     417              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
     418              :       TYPE(cp_fm_type)                                   :: rho_ao_fm
     419              :       TYPE(cp_fm_type), POINTER                          :: matrix_s_fm
     420            8 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_s_kp, rho_ao_qs_kp
     421              :       TYPE(dft_control_type), POINTER                    :: dft_control
     422            8 :       TYPE(green_functions_cache_type)                   :: g_surf_cache
     423              :       TYPE(integration_status_type)                      :: stats
     424              :       TYPE(kpoint_type), POINTER                         :: kpoints
     425              :       TYPE(mp_para_env_type), POINTER                    :: para_env_global
     426              :       TYPE(qs_energy_type), POINTER                      :: energy
     427              :       TYPE(qs_rho_type), POINTER                         :: rho_struct
     428              :       TYPE(qs_subsys_type), POINTER                      :: subsys
     429              : 
     430            8 :       CALL timeset(routineN, handle)
     431              : 
     432            8 :       IF (negf_control%contacts(contact_id)%compute_fermi_level) THEN
     433              : 
     434              :          CALL get_qs_env(qs_env, &
     435              :                          blacs_env=blacs_env_global, &
     436              :                          dft_control=dft_control, &
     437              :                          do_kpoints=do_kpoints, &
     438              :                          kpoints=kpoints, &
     439              :                          matrix_s_kp=matrix_s_kp, &
     440              :                          para_env=para_env_global, &
     441            4 :                          rho=rho_struct, subsys=subsys)
     442            4 :          CALL qs_rho_get(rho_struct, rho_ao_kp=rho_ao_qs_kp)
     443              : 
     444            4 :          nimages = dft_control%nimages
     445            4 :          nspins = dft_control%nspins
     446            4 :          direction_axis_abs = ABS(negf_env%contacts(contact_id)%direction_axis)
     447              : 
     448            4 :          CPASSERT(SIZE(negf_env%contacts(contact_id)%h_00) == nspins)
     449              : 
     450            4 :          IF (sub_env%ngroups > 1) THEN
     451            4 :             NULLIFY (matrix_s_fm, fm_struct)
     452              : 
     453            4 :             CALL cp_fm_get_info(negf_env%contacts(contact_id)%s_00, nrow_global=nao)
     454            4 :             CALL cp_fm_struct_create(fm_struct, nrow_global=nao, ncol_global=nao, context=blacs_env_global)
     455            4 :             CALL cp_fm_create(rho_ao_fm, fm_struct)
     456              : 
     457            4 :             ALLOCATE (matrix_s_fm)
     458            4 :             CALL cp_fm_create(matrix_s_fm, fm_struct)
     459            4 :             CALL cp_fm_struct_release(fm_struct)
     460              : 
     461            4 :             IF (sub_env%group_distribution(sub_env%mepos_global) == 0) THEN
     462            2 :                CALL cp_fm_copy_general(negf_env%contacts(contact_id)%s_00, matrix_s_fm, para_env_global)
     463              :             ELSE
     464            2 :                CALL cp_fm_copy_general(fm_dummy, matrix_s_fm, para_env_global)
     465              :             END IF
     466              :          ELSE
     467            0 :             matrix_s_fm => negf_env%contacts(contact_id)%s_00
     468            0 :             CALL cp_fm_get_info(matrix_s_fm, matrix_struct=fm_struct)
     469            0 :             CALL cp_fm_create(rho_ao_fm, fm_struct)
     470              :          END IF
     471              : 
     472            4 :          IF (do_kpoints) THEN
     473            0 :             CALL get_kpoint_info(kpoints, cell_to_index=cell_to_index)
     474              :          ELSE
     475            4 :             ALLOCATE (cell_to_index(0:0, 0:0, 0:0))
     476            4 :             cell_to_index(0, 0, 0) = 1
     477              :          END IF
     478              : 
     479           12 :          ALLOCATE (index_to_cell(3, nimages))
     480            4 :          CALL invert_cell_to_index(cell_to_index, nimages, index_to_cell)
     481            4 :          IF (.NOT. do_kpoints) DEALLOCATE (cell_to_index)
     482              : 
     483            4 :          IF (nspins == 1) THEN
     484              :             ! spin-restricted calculation: number of electrons must be doubled
     485              :             rscale = 2.0_dp
     486              :          ELSE
     487            0 :             rscale = 1.0_dp
     488              :          END IF
     489              : 
     490              :          ! compute the refence number of electrons using the electron density
     491            4 :          nelectrons_qs_cell0 = 0.0_dp
     492            4 :          nelectrons_qs_cell1 = 0.0_dp
     493            4 :          IF (negf_control%contacts(contact_id)%force_env_index > 0) THEN
     494            0 :             DO image = 1, nimages
     495            0 :                IF (index_to_cell(direction_axis_abs, image) == 0) THEN
     496            0 :                   DO ispin = 1, nspins
     497            0 :                      CALL dbcsr_dot(rho_ao_qs_kp(ispin, image)%matrix, matrix_s_kp(1, image)%matrix, trace)
     498            0 :                      nelectrons_qs_cell0 = nelectrons_qs_cell0 + trace
     499              :                   END DO
     500            0 :                ELSE IF (ABS(index_to_cell(direction_axis_abs, image)) == 1) THEN
     501            0 :                   DO ispin = 1, nspins
     502            0 :                      CALL dbcsr_dot(rho_ao_qs_kp(ispin, image)%matrix, matrix_s_kp(1, image)%matrix, trace)
     503            0 :                      nelectrons_qs_cell1 = nelectrons_qs_cell1 + trace
     504              :                   END DO
     505              :                END IF
     506              :             END DO
     507              :          ELSE
     508            8 :             DO ispin = 1, nspins
     509              :                CALL cp_fm_trace(negf_env%contacts(contact_id)%rho_00(ispin), &
     510            4 :                                 negf_env%contacts(contact_id)%s_00, trace)
     511            4 :                nelectrons_qs_cell0 = nelectrons_qs_cell0 + trace
     512              :                CALL cp_fm_trace(negf_env%contacts(contact_id)%rho_01(ispin), &
     513            4 :                                 negf_env%contacts(contact_id)%s_01, trace)
     514            8 :                nelectrons_qs_cell1 = nelectrons_qs_cell1 + 2.0*trace
     515              :             END DO
     516              :          END IF
     517              : 
     518            4 :          DEALLOCATE (index_to_cell)
     519              : 
     520            4 :          IF (log_unit > 0) THEN
     521            2 :             WRITE (temperature_str, '(F11.3)') negf_control%contacts(contact_id)%temperature*kelvin
     522            2 :             WRITE (log_unit, '(/,T2,A,I3)') "COMPUTE FERMI LEVEL OF CONTACT ", contact_id
     523            2 :             WRITE (log_unit, "(            ' ----------------------------------')")
     524            2 :             WRITE (log_unit, '(A)') " Temperature "//TRIM(ADJUSTL(temperature_str))//" Kelvin"
     525            2 :             WRITE (log_unit, '(/,T2,A,T60,F20.10,/)') "Electronic density of the electrode unit cell:", &
     526            4 :                -1.0_dp*(nelectrons_qs_cell0 + nelectrons_qs_cell1)
     527            2 :             WRITE (log_unit, '(T3,A)') "Step     Integration method      Time      Fermi level   Convergence (density)"
     528            2 :             WRITE (log_unit, '(T3,78("-"))')
     529              :          END IF
     530              : 
     531              :          ! Use the Fermi level given in the input file or the Fermi level of bulk electrodes as a reference point
     532              :          ! and then refine the Fermi level by using a simple linear interpolation technique
     533            4 :          CALL get_qs_env(qs_env, energy=energy)
     534            4 :          IF (negf_control%homo_lumo_gap > 0.0_dp) THEN
     535            4 :             IF (negf_control%contacts(contact_id)%refine_fermi_level) THEN
     536            4 :                fermi_level_min = negf_control%contacts(contact_id)%fermi_level
     537              :             ELSE
     538            0 :                fermi_level_min = energy%efermi
     539              :             END IF
     540            4 :             fermi_level_max = fermi_level_min + negf_control%homo_lumo_gap
     541              :          ELSE
     542            0 :             IF (negf_control%contacts(contact_id)%refine_fermi_level) THEN
     543            0 :                fermi_level_max = negf_control%contacts(contact_id)%fermi_level
     544              :             ELSE
     545            0 :                fermi_level_max = energy%efermi
     546              :             END IF
     547            0 :             fermi_level_min = fermi_level_max + negf_control%homo_lumo_gap
     548              :          END IF
     549              : 
     550            4 :          step = 0
     551            4 :          lbound_cpath = CMPLX(negf_control%energy_lbound, negf_control%eta, kind=dp)
     552            4 :          delta_au = REAL(negf_control%delta_npoles, kind=dp)*twopi*negf_control%contacts(contact_id)%temperature
     553            4 :          offset_au = REAL(negf_control%gamma_kT, kind=dp)*negf_control%contacts(contact_id)%temperature
     554            4 :          energy_ubound_minus_fermi = -2.0_dp*LOG(negf_control%conv_density)*negf_control%contacts(contact_id)%temperature
     555            4 :          t1 = m_walltime()
     556              : 
     557              :          DO
     558            4 :             step = step + 1
     559              : 
     560            4 :             SELECT CASE (step)
     561              :             CASE (1)
     562            4 :                fermi_level_guess = fermi_level_min
     563              :             CASE (2)
     564            0 :                fermi_level_guess = fermi_level_max
     565              :             CASE DEFAULT
     566              :                fermi_level_guess = fermi_level_min - (nelectrons_min - nelectrons_qs_cell0)* &
     567            4 :                                    (fermi_level_max - fermi_level_min)/(nelectrons_max - nelectrons_min)
     568              :             END SELECT
     569              : 
     570            4 :             negf_control%contacts(contact_id)%fermi_level = fermi_level_guess
     571            4 :             nelectrons_guess = 0.0_dp
     572              : 
     573            4 :             lbound_lpath = CMPLX(fermi_level_guess - offset_au, delta_au, kind=dp)
     574            4 :             ubound_lpath = CMPLX(fermi_level_guess + energy_ubound_minus_fermi, delta_au, kind=dp)
     575              : 
     576            4 :             CALL integration_status_reset(stats)
     577              : 
     578            8 :             DO ispin = 1, nspins
     579              :                CALL negf_init_rho_equiv_residuals(rho_ao_fm=rho_ao_fm, &
     580              :                                                   v_shift=0.0_dp, &
     581              :                                                   ignore_bias=.TRUE., &
     582              :                                                   negf_env=negf_env, &
     583              :                                                   negf_control=negf_control, &
     584              :                                                   sub_env=sub_env, &
     585              :                                                   ispin=ispin, &
     586              :                                                   base_contact=contact_id, &
     587            4 :                                                   just_contact=contact_id)
     588              : 
     589              :                CALL negf_add_rho_equiv_low(rho_ao_fm=rho_ao_fm, &
     590              :                                            stats=stats, &
     591              :                                            v_shift=0.0_dp, &
     592              :                                            ignore_bias=.TRUE., &
     593              :                                            negf_env=negf_env, &
     594              :                                            negf_control=negf_control, &
     595              :                                            sub_env=sub_env, &
     596              :                                            ispin=ispin, &
     597              :                                            base_contact=contact_id, &
     598              :                                            integr_lbound=lbound_cpath, &
     599              :                                            integr_ubound=lbound_lpath, &
     600              :                                            matrix_s_global=matrix_s_fm, &
     601              :                                            is_circular=.TRUE., &
     602              :                                            g_surf_cache=g_surf_cache, &
     603            4 :                                            just_contact=contact_id)
     604            4 :                CALL green_functions_cache_release(g_surf_cache)
     605              : 
     606              :                CALL negf_add_rho_equiv_low(rho_ao_fm=rho_ao_fm, &
     607              :                                            stats=stats, &
     608              :                                            v_shift=0.0_dp, &
     609              :                                            ignore_bias=.TRUE., &
     610              :                                            negf_env=negf_env, &
     611              :                                            negf_control=negf_control, &
     612              :                                            sub_env=sub_env, &
     613              :                                            ispin=ispin, &
     614              :                                            base_contact=contact_id, &
     615              :                                            integr_lbound=lbound_lpath, &
     616              :                                            integr_ubound=ubound_lpath, &
     617              :                                            matrix_s_global=matrix_s_fm, &
     618              :                                            is_circular=.FALSE., &
     619              :                                            g_surf_cache=g_surf_cache, &
     620            4 :                                            just_contact=contact_id)
     621            4 :                CALL green_functions_cache_release(g_surf_cache)
     622              : 
     623            4 :                CALL cp_fm_trace(rho_ao_fm, matrix_s_fm, trace)
     624            8 :                nelectrons_guess = nelectrons_guess + trace
     625              :             END DO
     626            4 :             nelectrons_guess = nelectrons_guess*rscale
     627              : 
     628            4 :             t2 = m_walltime()
     629              : 
     630            4 :             IF (log_unit > 0) THEN
     631              :                WRITE (log_unit, '(T2,I5,T12,A,T32,F8.1,T42,F15.8,T60,ES20.5E2)') &
     632            2 :                   step, get_method_description_string(stats, negf_control%integr_method), &
     633            4 :                   t2 - t1, fermi_level_guess, nelectrons_guess - nelectrons_qs_cell0
     634              :             END IF
     635              : 
     636            4 :             IF (ABS(nelectrons_qs_cell0 - nelectrons_guess) < negf_control%conv_density) EXIT
     637              : 
     638              :             SELECT CASE (step)
     639              :             CASE (1)
     640            0 :                nelectrons_min = nelectrons_guess
     641              :             CASE (2)
     642            0 :                nelectrons_max = nelectrons_guess
     643              :             CASE DEFAULT
     644            0 :                IF (fermi_level_guess < fermi_level_min) THEN
     645              :                   fermi_level_max = fermi_level_min
     646              :                   nelectrons_max = nelectrons_min
     647              :                   fermi_level_min = fermi_level_guess
     648              :                   nelectrons_min = nelectrons_guess
     649            0 :                ELSE IF (fermi_level_guess > fermi_level_max) THEN
     650              :                   fermi_level_min = fermi_level_max
     651              :                   nelectrons_min = nelectrons_max
     652              :                   fermi_level_max = fermi_level_guess
     653              :                   nelectrons_max = nelectrons_guess
     654            0 :                ELSE IF (fermi_level_max - fermi_level_guess < fermi_level_guess - fermi_level_min) THEN
     655              :                   fermi_level_max = fermi_level_guess
     656              :                   nelectrons_max = nelectrons_guess
     657              :                ELSE
     658            0 :                   fermi_level_min = fermi_level_guess
     659            0 :                   nelectrons_min = nelectrons_guess
     660              :                END IF
     661              :             END SELECT
     662              : 
     663            4 :             t1 = t2
     664              :          END DO
     665              : 
     666            4 :          negf_control%contacts(contact_id)%fermi_level = fermi_level_guess
     667              : 
     668            4 :          IF (sub_env%ngroups > 1) THEN
     669            4 :             CALL cp_fm_release(matrix_s_fm)
     670            4 :             DEALLOCATE (matrix_s_fm)
     671              :          END IF
     672            4 :          CALL cp_fm_release(rho_ao_fm)
     673              :       END IF
     674              : 
     675            8 :       IF (log_unit > 0) THEN
     676            4 :          WRITE (temperature_str, '(F11.3)') negf_control%contacts(contact_id)%temperature*kelvin
     677            4 :          WRITE (log_unit, '(/,T2,A,I0)') "NEGF| Contact No. ", contact_id
     678              :          WRITE (log_unit, '(T2,A,T62,F18.8)') "NEGF|    Fermi level at "//TRIM(ADJUSTL(temperature_str))// &
     679            4 :             " Kelvin (a.u.):", negf_control%contacts(contact_id)%fermi_level
     680              :          WRITE (log_unit, '(T2,A,T62,F18.8)') "NEGF|    Fermi level at "//TRIM(ADJUSTL(temperature_str))// &
     681            4 :             " Kelvin (eV):", negf_control%contacts(contact_id)%fermi_level*evolt
     682            4 :          WRITE (log_unit, '(T2,A,T62,F18.8)') "NEGF|    Electric potential (a.u.):", &
     683            8 :             negf_control%contacts(contact_id)%v_external
     684            4 :          WRITE (log_unit, '(T2,A,T62,F18.8)') "NEGF|    Electric potential (Volt):", &
     685            8 :             negf_control%contacts(contact_id)%v_external*evolt
     686            4 :          WRITE (log_unit, '(T2,A,T62,F18.8)') "NEGF|    Electro-chemical potential Ef-|e|V (a.u.):", &
     687            8 :             (negf_control%contacts(contact_id)%fermi_level - negf_control%contacts(contact_id)%v_external)
     688            4 :          WRITE (log_unit, '(T2,A,T62,F18.8)') "NEGF|    Electro-chemical potential Ef-|e|V (eV):", &
     689            8 :             (negf_control%contacts(contact_id)%fermi_level - negf_control%contacts(contact_id)%v_external)*evolt
     690              :       END IF
     691              : 
     692            8 :       CALL timestop(handle)
     693           16 :    END SUBROUTINE guess_fermi_level
     694              : 
     695              : ! **************************************************************************************************
     696              : !> \brief Compute shift in Hartree potential
     697              : !> \param negf_env      NEGF environment
     698              : !> \param negf_control  NEGF control
     699              : !> \param sub_env       NEGF parallel (sub)group environment
     700              : !> \param qs_env        QuickStep environment
     701              : !> \param base_contact  index of the reference contact
     702              : !> \param log_unit      output unit
     703              : !>    * 09.2017 created  [Sergey Chulkov]
     704              : !>    * 11.2025 modified [Dmitry Ryndyk]
     705              : ! **************************************************************************************************
     706            4 :    SUBROUTINE shift_potential(negf_env, negf_control, sub_env, qs_env, base_contact, log_unit)
     707              :       TYPE(negf_env_type), INTENT(in)                    :: negf_env
     708              :       TYPE(negf_control_type), POINTER                   :: negf_control
     709              :       TYPE(negf_subgroup_env_type), INTENT(in)           :: sub_env
     710              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     711              :       INTEGER, INTENT(in)                                :: base_contact, log_unit
     712              : 
     713              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'shift_potential'
     714              :       TYPE(cp_fm_type), PARAMETER                        :: fm_dummy = cp_fm_type()
     715              : 
     716              :       COMPLEX(kind=dp)                                   :: lbound_cpath, ubound_cpath, ubound_lpath
     717              :       INTEGER                                            :: handle, ispin, iter_count, nao, &
     718              :                                                             ncontacts, nspins
     719              :       LOGICAL                                            :: do_kpoints
     720              :       REAL(kind=dp) :: mu_base, nelectrons_guess, nelectrons_max, nelectrons_min, nelectrons_ref, &
     721              :          t1, t2, temperature, trace, v_shift_guess, v_shift_max, v_shift_min
     722              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     723              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
     724            4 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: rho_ao_fm
     725              :       TYPE(cp_fm_type), POINTER                          :: matrix_s_fm
     726            4 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rho_ao_qs_kp
     727              :       TYPE(dft_control_type), POINTER                    :: dft_control
     728              :       TYPE(green_functions_cache_type), ALLOCATABLE, &
     729            4 :          DIMENSION(:)                                    :: g_surf_circular, g_surf_linear
     730              :       TYPE(integration_status_type)                      :: stats
     731              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     732              :       TYPE(qs_rho_type), POINTER                         :: rho_struct
     733              :       TYPE(qs_subsys_type), POINTER                      :: subsys
     734              : 
     735            4 :       ncontacts = SIZE(negf_control%contacts)
     736              :       ! nothing to do
     737            4 :       IF (.NOT. (ALLOCATED(negf_env%h_s) .AND. ALLOCATED(negf_env%h_sc) .AND. &
     738              :                  ASSOCIATED(negf_env%s_s) .AND. ALLOCATED(negf_env%s_sc))) RETURN
     739            4 :       IF (ncontacts < 2) RETURN
     740              : 
     741            4 :       CALL timeset(routineN, handle)
     742              : 
     743              :       CALL get_qs_env(qs_env, blacs_env=blacs_env, do_kpoints=do_kpoints, dft_control=dft_control, &
     744            4 :                       para_env=para_env, rho=rho_struct, subsys=subsys)
     745            4 :       CPASSERT(.NOT. do_kpoints)
     746              : 
     747              :       ! apply external NEGF potential
     748            4 :       t1 = m_walltime()
     749              : 
     750              :       ! need a globally distributed overlap matrix in order to compute integration errors
     751            4 :       IF (sub_env%ngroups > 1) THEN
     752            4 :          NULLIFY (matrix_s_fm, fm_struct)
     753              : 
     754            4 :          CALL cp_fm_get_info(negf_env%s_s, nrow_global=nao)
     755            4 :          CALL cp_fm_struct_create(fm_struct, nrow_global=nao, ncol_global=nao, context=blacs_env)
     756              : 
     757            4 :          ALLOCATE (matrix_s_fm)
     758            4 :          CALL cp_fm_create(matrix_s_fm, fm_struct)
     759            4 :          CALL cp_fm_struct_release(fm_struct)
     760              : 
     761            4 :          IF (sub_env%group_distribution(sub_env%mepos_global) == 0) THEN
     762            2 :             CALL cp_fm_copy_general(negf_env%s_s, matrix_s_fm, para_env)
     763              :          ELSE
     764            2 :             CALL cp_fm_copy_general(fm_dummy, matrix_s_fm, para_env)
     765              :          END IF
     766              :       ELSE
     767            0 :          matrix_s_fm => negf_env%s_s
     768              :       END IF
     769              : 
     770            4 :       CALL cp_fm_get_info(matrix_s_fm, matrix_struct=fm_struct)
     771              : 
     772            4 :       nspins = SIZE(negf_env%h_s)
     773              : 
     774            4 :       mu_base = negf_control%contacts(base_contact)%fermi_level
     775              : 
     776              :       ! keep the initial charge density matrix and Kohn-Sham matrix
     777            4 :       CALL qs_rho_get(rho_struct, rho_ao_kp=rho_ao_qs_kp)
     778              : 
     779              :       ! extract the reference density matrix blocks
     780            4 :       nelectrons_ref = 0.0_dp
     781           16 :       ALLOCATE (rho_ao_fm(nspins))
     782            8 :       DO ispin = 1, nspins
     783            4 :          CALL cp_fm_create(rho_ao_fm(ispin), fm_struct)
     784              : 
     785              :          CALL negf_copy_sym_dbcsr_to_fm_submat(matrix=rho_ao_qs_kp(ispin, 1)%matrix, &
     786              :                                                fm=rho_ao_fm(ispin), &
     787              :                                                atomlist_row=negf_control%atomlist_S_screening, &
     788              :                                                atomlist_col=negf_control%atomlist_S_screening, &
     789              :                                                subsys=subsys, mpi_comm_global=para_env, &
     790            4 :                                                do_upper_diag=.TRUE., do_lower=.TRUE.)
     791              : 
     792            4 :          CALL cp_fm_trace(rho_ao_fm(ispin), matrix_s_fm, trace)
     793            8 :          nelectrons_ref = nelectrons_ref + trace
     794              :       END DO
     795              : 
     796            4 :       IF (log_unit > 0) THEN
     797            2 :          WRITE (log_unit, '(/,T2,A)') "COMPUTE SHIFT IN HARTREE POTENTIAL"
     798            2 :          WRITE (log_unit, "(         ' ----------------------------------')")
     799            2 :          WRITE (log_unit, '(/,T2,A,T55,F25.14,/)') "Initial electronic density of the scattering region:", -1.0_dp*nelectrons_ref
     800            2 :          WRITE (log_unit, '(T3,A)') "Step     Integration method      Time        V shift     Convergence (density)"
     801            2 :          WRITE (log_unit, '(T3,78("-"))')
     802              :       END IF
     803              : 
     804            4 :       temperature = negf_control%contacts(base_contact)%temperature
     805              : 
     806              :       ! integration limits: C-path (arch)
     807            4 :       lbound_cpath = CMPLX(negf_control%energy_lbound, negf_control%eta, kind=dp)
     808              :       ubound_cpath = CMPLX(mu_base - REAL(negf_control%gamma_kT, kind=dp)*temperature, &
     809            4 :                            REAL(negf_control%delta_npoles, kind=dp)*twopi*temperature, kind=dp)
     810              : 
     811              :       ! integration limits: L-path (linear)
     812              :       ubound_lpath = CMPLX(mu_base - LOG(negf_control%conv_density)*temperature, &
     813            4 :                            REAL(negf_control%delta_npoles, kind=dp)*twopi*temperature, kind=dp)
     814              : 
     815            4 :       v_shift_min = negf_control%v_shift
     816            4 :       v_shift_max = negf_control%v_shift + negf_control%v_shift_offset
     817              : 
     818           24 :       ALLOCATE (g_surf_circular(nspins), g_surf_linear(nspins))
     819              : 
     820           10 :       DO iter_count = 1, negf_control%v_shift_maxiters
     821            4 :          SELECT CASE (iter_count)
     822              :          CASE (1)
     823            4 :             v_shift_guess = v_shift_min
     824              :          CASE (2)
     825            2 :             v_shift_guess = v_shift_max
     826              :          CASE DEFAULT
     827              :             v_shift_guess = v_shift_min - (nelectrons_min - nelectrons_ref)* &
     828           10 :                             (v_shift_max - v_shift_min)/(nelectrons_max - nelectrons_min)
     829              :          END SELECT
     830              : 
     831              :          ! compute an updated density matrix
     832           10 :          CALL integration_status_reset(stats)
     833              : 
     834           20 :          DO ispin = 1, nspins
     835              :             ! closed contour: residuals
     836              :             CALL negf_init_rho_equiv_residuals(rho_ao_fm=rho_ao_fm(ispin), &
     837              :                                                v_shift=v_shift_guess, &
     838              :                                                ignore_bias=.TRUE., &
     839              :                                                negf_env=negf_env, &
     840              :                                                negf_control=negf_control, &
     841              :                                                sub_env=sub_env, &
     842              :                                                ispin=ispin, &
     843           10 :                                                base_contact=base_contact)
     844              : 
     845              :             ! closed contour: C-path
     846              :             CALL negf_add_rho_equiv_low(rho_ao_fm=rho_ao_fm(ispin), &
     847              :                                         stats=stats, &
     848              :                                         v_shift=v_shift_guess, &
     849              :                                         ignore_bias=.TRUE., &
     850              :                                         negf_env=negf_env, &
     851              :                                         negf_control=negf_control, &
     852              :                                         sub_env=sub_env, &
     853              :                                         ispin=ispin, &
     854              :                                         base_contact=base_contact, &
     855              :                                         integr_lbound=lbound_cpath, &
     856              :                                         integr_ubound=ubound_cpath, &
     857              :                                         matrix_s_global=matrix_s_fm, &
     858              :                                         is_circular=.TRUE., &
     859           10 :                                         g_surf_cache=g_surf_circular(ispin))
     860           10 :             IF (negf_control%disable_cache) &
     861            0 :                CALL green_functions_cache_release(g_surf_circular(ispin))
     862              : 
     863              :             ! closed contour: L-path
     864              :             CALL negf_add_rho_equiv_low(rho_ao_fm=rho_ao_fm(ispin), &
     865              :                                         stats=stats, &
     866              :                                         v_shift=v_shift_guess, &
     867              :                                         ignore_bias=.TRUE., &
     868              :                                         negf_env=negf_env, &
     869              :                                         negf_control=negf_control, &
     870              :                                         sub_env=sub_env, &
     871              :                                         ispin=ispin, &
     872              :                                         base_contact=base_contact, &
     873              :                                         integr_lbound=ubound_cpath, &
     874              :                                         integr_ubound=ubound_lpath, &
     875              :                                         matrix_s_global=matrix_s_fm, &
     876              :                                         is_circular=.FALSE., &
     877           10 :                                         g_surf_cache=g_surf_linear(ispin))
     878           10 :             IF (negf_control%disable_cache) &
     879           10 :                CALL green_functions_cache_release(g_surf_linear(ispin))
     880              :          END DO
     881              : 
     882           10 :          IF (nspins > 1) THEN
     883            0 :             DO ispin = 2, nspins
     884            0 :                CALL cp_fm_scale_and_add(1.0_dp, rho_ao_fm(1), 1.0_dp, rho_ao_fm(ispin))
     885              :             END DO
     886              :          ELSE
     887           10 :             CALL cp_fm_scale(2.0_dp, rho_ao_fm(1))
     888              :          END IF
     889              : 
     890           10 :          CALL cp_fm_trace(rho_ao_fm(1), matrix_s_fm, nelectrons_guess)
     891              : 
     892           10 :          t2 = m_walltime()
     893              : 
     894           10 :          IF (log_unit > 0) THEN
     895              :             WRITE (log_unit, '(T2,I5,T12,A,T32,F8.1,T42,F15.8,T60,ES20.5E2)') &
     896            5 :                iter_count, get_method_description_string(stats, negf_control%integr_method), &
     897           10 :                t2 - t1, v_shift_guess, nelectrons_guess - nelectrons_ref
     898              :          END IF
     899              : 
     900           10 :          IF (ABS(nelectrons_guess - nelectrons_ref) < negf_control%conv_scf) EXIT
     901              : 
     902              :          ! compute correction
     903              :          SELECT CASE (iter_count)
     904              :          CASE (1)
     905            2 :             nelectrons_min = nelectrons_guess
     906              :          CASE (2)
     907            2 :             nelectrons_max = nelectrons_guess
     908              :          CASE DEFAULT
     909            6 :             IF (v_shift_guess < v_shift_min) THEN
     910              :                v_shift_max = v_shift_min
     911              :                nelectrons_max = nelectrons_min
     912              :                v_shift_min = v_shift_guess
     913              :                nelectrons_min = nelectrons_guess
     914            0 :             ELSE IF (v_shift_guess > v_shift_max) THEN
     915              :                v_shift_min = v_shift_max
     916              :                nelectrons_min = nelectrons_max
     917              :                v_shift_max = v_shift_guess
     918              :                nelectrons_max = nelectrons_guess
     919            0 :             ELSE IF (v_shift_max - v_shift_guess < v_shift_guess - v_shift_min) THEN
     920              :                v_shift_max = v_shift_guess
     921              :                nelectrons_max = nelectrons_guess
     922              :             ELSE
     923            0 :                v_shift_min = v_shift_guess
     924            0 :                nelectrons_min = nelectrons_guess
     925              :             END IF
     926              :          END SELECT
     927              : 
     928           20 :          t1 = t2
     929              :       END DO
     930              : 
     931            4 :       negf_control%v_shift = v_shift_guess
     932              : 
     933            4 :       IF (log_unit > 0) THEN
     934            2 :          WRITE (log_unit, '(T2,A,T62,F18.8)') "NEGF|    Shift in Hartree potential (a.u.):", negf_control%v_shift
     935            2 :          WRITE (log_unit, '(T2,A,T62,F18.8)') "NEGF|    Shift in Hartree potential (eV):", negf_control%v_shift*evolt
     936              :       END IF
     937              : 
     938            8 :       DO ispin = nspins, 1, -1
     939            4 :          CALL green_functions_cache_release(g_surf_circular(ispin))
     940            8 :          CALL green_functions_cache_release(g_surf_linear(ispin))
     941              :       END DO
     942           12 :       DEALLOCATE (g_surf_circular, g_surf_linear)
     943              : 
     944            4 :       CALL cp_fm_release(rho_ao_fm)
     945              : 
     946            4 :       IF (sub_env%ngroups > 1 .AND. ASSOCIATED(matrix_s_fm)) THEN
     947            4 :          CALL cp_fm_release(matrix_s_fm)
     948            4 :          DEALLOCATE (matrix_s_fm)
     949              :       END IF
     950              : 
     951            4 :       CALL timestop(handle)
     952           12 :    END SUBROUTINE shift_potential
     953              : 
     954              : ! **************************************************************************************************
     955              : !> \brief Converge electronic density of the scattering region.
     956              : !> \param negf_env      NEGF environment
     957              : !> \param negf_control  NEGF control
     958              : !> \param sub_env       NEGF parallel (sub)group environment
     959              : !> \param qs_env        QuickStep environment
     960              : !> \param v_shift       shift in Hartree potential
     961              : !> \param base_contact  index of the reference contact
     962              : !> \param log_unit      output unit
     963              : !> \par History
     964              : !>    * 06.2017 created  [Sergey Chulkov]
     965              : !>    * 11.2025 modified [Dmitry Ryndyk]
     966              : ! **************************************************************************************************
     967            4 :    SUBROUTINE converge_density(negf_env, negf_control, sub_env, qs_env, v_shift, base_contact, log_unit)
     968              :       TYPE(negf_env_type), INTENT(in)                    :: negf_env
     969              :       TYPE(negf_control_type), POINTER                   :: negf_control
     970              :       TYPE(negf_subgroup_env_type), INTENT(in)           :: sub_env
     971              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     972              :       REAL(kind=dp), INTENT(in)                          :: v_shift
     973              :       INTEGER, INTENT(in)                                :: base_contact, log_unit
     974              : 
     975              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'converge_density'
     976              :       REAL(kind=dp), PARAMETER :: threshold = 16.0_dp*EPSILON(0.0_dp)
     977              :       TYPE(cp_fm_type), PARAMETER                        :: fm_dummy = cp_fm_type()
     978              : 
     979              :       COMPLEX(kind=dp)                                   :: lbound_cpath, ubound_cpath, ubound_lpath
     980              :       INTEGER                                            :: handle, icontact, image, ispin, &
     981              :                                                             iter_count, nao, ncontacts, nimages, &
     982              :                                                             nspins
     983              :       LOGICAL                                            :: do_kpoints
     984              :       REAL(kind=dp)                                      :: delta, iter_delta, mu_base, nelectrons, &
     985              :                                                             nelectrons_diff, t1, t2, temperature, &
     986              :                                                             trace, v_base
     987              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     988              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
     989            4 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: rho_ao_delta_fm, rho_ao_new_fm
     990              :       TYPE(cp_fm_type), POINTER                          :: matrix_s_fm
     991            4 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks_initial_kp, matrix_ks_qs_kp, &
     992            4 :                                                             rho_ao_initial_kp, rho_ao_new_kp, &
     993            4 :                                                             rho_ao_qs_kp
     994              :       TYPE(dft_control_type), POINTER                    :: dft_control
     995              :       TYPE(green_functions_cache_type), ALLOCATABLE, &
     996            4 :          DIMENSION(:)                                    :: g_surf_circular, g_surf_linear, &
     997            4 :                                                             g_surf_nonequiv
     998              :       TYPE(integration_status_type)                      :: stats
     999              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1000              :       TYPE(qs_rho_type), POINTER                         :: rho_struct
    1001              :       TYPE(qs_subsys_type), POINTER                      :: subsys
    1002              : 
    1003            4 :       ncontacts = SIZE(negf_control%contacts)
    1004              :       ! nothing to do
    1005            4 :       IF (.NOT. (ALLOCATED(negf_env%h_s) .AND. ALLOCATED(negf_env%h_sc) .AND. &
    1006              :                  ASSOCIATED(negf_env%s_s) .AND. ALLOCATED(negf_env%s_sc))) RETURN
    1007            4 :       IF (ncontacts < 2) RETURN
    1008              : 
    1009            4 :       CALL timeset(routineN, handle)
    1010              : 
    1011              :       CALL get_qs_env(qs_env, blacs_env=blacs_env, do_kpoints=do_kpoints, dft_control=dft_control, &
    1012            4 :                       matrix_ks_kp=matrix_ks_qs_kp, para_env=para_env, rho=rho_struct, subsys=subsys)
    1013            4 :       CPASSERT(.NOT. do_kpoints)
    1014              : 
    1015              :       ! apply external NEGF potential
    1016            4 :       t1 = m_walltime()
    1017              : 
    1018              :       ! need a globally distributed overlap matrix in order to compute integration errors
    1019            4 :       IF (sub_env%ngroups > 1) THEN
    1020            4 :          NULLIFY (matrix_s_fm, fm_struct)
    1021              : 
    1022            4 :          CALL cp_fm_get_info(negf_env%s_s, nrow_global=nao)
    1023            4 :          CALL cp_fm_struct_create(fm_struct, nrow_global=nao, ncol_global=nao, context=blacs_env)
    1024              : 
    1025            4 :          ALLOCATE (matrix_s_fm)
    1026            4 :          CALL cp_fm_create(matrix_s_fm, fm_struct)
    1027            4 :          CALL cp_fm_struct_release(fm_struct)
    1028              : 
    1029            4 :          IF (sub_env%group_distribution(sub_env%mepos_global) == 0) THEN
    1030            2 :             CALL cp_fm_copy_general(negf_env%s_s, matrix_s_fm, para_env)
    1031              :          ELSE
    1032            2 :             CALL cp_fm_copy_general(fm_dummy, matrix_s_fm, para_env)
    1033              :          END IF
    1034              :       ELSE
    1035            0 :          matrix_s_fm => negf_env%s_s
    1036              :       END IF
    1037              : 
    1038            4 :       CALL cp_fm_get_info(matrix_s_fm, matrix_struct=fm_struct)
    1039              : 
    1040            4 :       nspins = SIZE(negf_env%h_s)
    1041            4 :       nimages = dft_control%nimages
    1042              : 
    1043            4 :       v_base = negf_control%contacts(base_contact)%v_external
    1044            4 :       mu_base = negf_control%contacts(base_contact)%fermi_level - v_base
    1045              : 
    1046              :       ! the current subroutine works for the general case as well, but the Poisson solver does not
    1047            4 :       IF (ncontacts > 2) THEN
    1048            0 :          CPABORT("Poisson solver does not support the general NEGF setup (>2 contacts).")
    1049              :       END IF
    1050              : 
    1051              :       ! keep the initial charge density matrix and Kohn-Sham matrix
    1052            4 :       CALL qs_rho_get(rho_struct, rho_ao_kp=rho_ao_qs_kp)
    1053              : 
    1054            4 :       NULLIFY (matrix_ks_initial_kp, rho_ao_initial_kp, rho_ao_new_kp)
    1055            4 :       CALL dbcsr_allocate_matrix_set(matrix_ks_initial_kp, nspins, nimages)
    1056            4 :       CALL dbcsr_allocate_matrix_set(rho_ao_initial_kp, nspins, nimages)
    1057            4 :       CALL dbcsr_allocate_matrix_set(rho_ao_new_kp, nspins, nimages)
    1058              : 
    1059            8 :       DO image = 1, nimages
    1060           12 :          DO ispin = 1, nspins
    1061            4 :             CALL dbcsr_init_p(matrix_ks_initial_kp(ispin, image)%matrix)
    1062            4 :             CALL dbcsr_copy(matrix_b=matrix_ks_initial_kp(ispin, image)%matrix, matrix_a=matrix_ks_qs_kp(ispin, image)%matrix)
    1063              : 
    1064            4 :             CALL dbcsr_init_p(rho_ao_initial_kp(ispin, image)%matrix)
    1065            4 :             CALL dbcsr_copy(matrix_b=rho_ao_initial_kp(ispin, image)%matrix, matrix_a=rho_ao_qs_kp(ispin, image)%matrix)
    1066              : 
    1067            4 :             CALL dbcsr_init_p(rho_ao_new_kp(ispin, image)%matrix)
    1068            8 :             CALL dbcsr_copy(matrix_b=rho_ao_new_kp(ispin, image)%matrix, matrix_a=rho_ao_qs_kp(ispin, image)%matrix)
    1069              :          END DO
    1070              :       END DO
    1071              : 
    1072              :       ! extract the reference density matrix blocks
    1073            4 :       nelectrons = 0.0_dp
    1074           24 :       ALLOCATE (rho_ao_delta_fm(nspins), rho_ao_new_fm(nspins))
    1075            8 :       DO ispin = 1, nspins
    1076            4 :          CALL cp_fm_create(rho_ao_delta_fm(ispin), fm_struct)
    1077            4 :          CALL cp_fm_create(rho_ao_new_fm(ispin), fm_struct)
    1078              : 
    1079              :          CALL negf_copy_sym_dbcsr_to_fm_submat(matrix=rho_ao_qs_kp(ispin, 1)%matrix, &
    1080              :                                                fm=rho_ao_delta_fm(ispin), &
    1081              :                                                atomlist_row=negf_control%atomlist_S_screening, &
    1082              :                                                atomlist_col=negf_control%atomlist_S_screening, &
    1083              :                                                subsys=subsys, mpi_comm_global=para_env, &
    1084            4 :                                                do_upper_diag=.TRUE., do_lower=.TRUE.)
    1085              : 
    1086            4 :          CALL cp_fm_trace(rho_ao_delta_fm(ispin), matrix_s_fm, trace)
    1087            8 :          nelectrons = nelectrons + trace
    1088              :       END DO
    1089              : 
    1090              :       ! mixing storage allocation
    1091            4 :       IF (negf_env%mixing_method >= gspace_mixing_nr) THEN
    1092            4 :          CALL mixing_allocate(qs_env, negf_env%mixing_method, nspins=nspins, mixing_store=negf_env%mixing_storage)
    1093            4 :          IF (dft_control%qs_control%dftb .OR. dft_control%qs_control%xtb) THEN
    1094            0 :             CPABORT('TB Code not available')
    1095            4 :          ELSE IF (dft_control%qs_control%semi_empirical) THEN
    1096            0 :             CPABORT('SE Code not possible')
    1097              :          ELSE
    1098            4 :             CALL mixing_init(negf_env%mixing_method, rho_struct, negf_env%mixing_storage, para_env)
    1099              :          END IF
    1100              :       END IF
    1101              : 
    1102            4 :       IF (log_unit > 0) THEN
    1103            2 :          WRITE (log_unit, '(/,T2,A)') "NEGF SELF-CONSISTENT PROCEDURE"
    1104            2 :          WRITE (log_unit, "(         ' ------------------------------')")
    1105            2 :          WRITE (log_unit, '(/,T2,A,T55,F25.14,/)') "Initial electronic density of the scattering region:", -1.0_dp*nelectrons
    1106            2 :          WRITE (log_unit, '(T3,A)') "Step     Integration method      Time     Electronic density      Convergence"
    1107            2 :          WRITE (log_unit, '(T3,78("-"))')
    1108              :       END IF
    1109              : 
    1110            4 :       temperature = negf_control%contacts(base_contact)%temperature
    1111              : 
    1112              :       ! integration limits: C-path (arch)
    1113            4 :       lbound_cpath = CMPLX(negf_control%energy_lbound, negf_control%eta, kind=dp)
    1114              :       ubound_cpath = CMPLX(mu_base - REAL(negf_control%gamma_kT, kind=dp)*temperature, &
    1115            4 :                            REAL(negf_control%delta_npoles, kind=dp)*twopi*temperature, kind=dp)
    1116              : 
    1117              :       ! integration limits: L-path (linear)
    1118              :       ubound_lpath = CMPLX(mu_base - LOG(negf_control%conv_density)*temperature, &
    1119            4 :                            REAL(negf_control%delta_npoles, kind=dp)*twopi*temperature, kind=dp)
    1120              : 
    1121           32 :       ALLOCATE (g_surf_circular(nspins), g_surf_linear(nspins), g_surf_nonequiv(nspins))
    1122              : 
    1123              :       !--- main SCF cycle -------------------------------------------------------------------!
    1124            4 :       DO iter_count = 1, negf_control%max_scf
    1125              :          ! compute an updated density matrix
    1126            4 :          CALL integration_status_reset(stats)
    1127              : 
    1128            8 :          DO ispin = 1, nspins
    1129              :             ! closed contour: residuals
    1130              :             CALL negf_init_rho_equiv_residuals(rho_ao_fm=rho_ao_new_fm(ispin), &
    1131              :                                                v_shift=v_shift, &
    1132              :                                                ignore_bias=.FALSE., &
    1133              :                                                negf_env=negf_env, &
    1134              :                                                negf_control=negf_control, &
    1135              :                                                sub_env=sub_env, &
    1136              :                                                ispin=ispin, &
    1137            4 :                                                base_contact=base_contact)
    1138              : 
    1139              :             ! closed contour: C-path
    1140              :             CALL negf_add_rho_equiv_low(rho_ao_fm=rho_ao_new_fm(ispin), &
    1141              :                                         stats=stats, &
    1142              :                                         v_shift=v_shift, &
    1143              :                                         ignore_bias=.FALSE., &
    1144              :                                         negf_env=negf_env, &
    1145              :                                         negf_control=negf_control, &
    1146              :                                         sub_env=sub_env, &
    1147              :                                         ispin=ispin, &
    1148              :                                         base_contact=base_contact, &
    1149              :                                         integr_lbound=lbound_cpath, &
    1150              :                                         integr_ubound=ubound_cpath, &
    1151              :                                         matrix_s_global=matrix_s_fm, &
    1152              :                                         is_circular=.TRUE., &
    1153            4 :                                         g_surf_cache=g_surf_circular(ispin))
    1154            4 :             IF (negf_control%disable_cache) &
    1155            0 :                CALL green_functions_cache_release(g_surf_circular(ispin))
    1156              : 
    1157              :             ! closed contour: L-path
    1158              :             CALL negf_add_rho_equiv_low(rho_ao_fm=rho_ao_new_fm(ispin), &
    1159              :                                         stats=stats, &
    1160              :                                         v_shift=v_shift, &
    1161              :                                         ignore_bias=.FALSE., &
    1162              :                                         negf_env=negf_env, &
    1163              :                                         negf_control=negf_control, &
    1164              :                                         sub_env=sub_env, &
    1165              :                                         ispin=ispin, &
    1166              :                                         base_contact=base_contact, &
    1167              :                                         integr_lbound=ubound_cpath, &
    1168              :                                         integr_ubound=ubound_lpath, &
    1169              :                                         matrix_s_global=matrix_s_fm, &
    1170              :                                         is_circular=.FALSE., &
    1171            4 :                                         g_surf_cache=g_surf_linear(ispin))
    1172            4 :             IF (negf_control%disable_cache) &
    1173            0 :                CALL green_functions_cache_release(g_surf_linear(ispin))
    1174              : 
    1175              :             ! non-equilibrium part
    1176            4 :             delta = 0.0_dp
    1177           12 :             DO icontact = 1, ncontacts
    1178           12 :                IF (icontact /= base_contact) THEN
    1179              :                   delta = delta + ABS(negf_control%contacts(icontact)%v_external - &
    1180              :                                       negf_control%contacts(base_contact)%v_external) + &
    1181              :                           ABS(negf_control%contacts(icontact)%temperature - &
    1182            4 :                               negf_control%contacts(base_contact)%temperature)
    1183              :                END IF
    1184              :             END DO
    1185            8 :             IF (delta >= threshold) THEN
    1186              : 
    1187              :                CALL negf_add_rho_nonequiv(rho_ao_fm=rho_ao_new_fm(ispin), &
    1188              :                                           stats=stats, &
    1189              :                                           v_shift=v_shift, &
    1190              :                                           negf_env=negf_env, &
    1191              :                                           negf_control=negf_control, &
    1192              :                                           sub_env=sub_env, &
    1193              :                                           ispin=ispin, &
    1194              :                                           base_contact=base_contact, &
    1195              :                                           matrix_s_global=matrix_s_fm, &
    1196            0 :                                           g_surf_cache=g_surf_nonequiv(ispin))
    1197            0 :                IF (negf_control%disable_cache) &
    1198            0 :                   CALL green_functions_cache_release(g_surf_nonequiv(ispin))
    1199              :             END IF
    1200              :          END DO
    1201              : 
    1202            4 :          IF (nspins == 1) CALL cp_fm_scale(2.0_dp, rho_ao_new_fm(1))
    1203              : 
    1204            4 :          nelectrons = 0.0_dp
    1205            4 :          nelectrons_diff = 0.0_dp
    1206            8 :          DO ispin = 1, nspins
    1207            4 :             CALL cp_fm_trace(rho_ao_new_fm(ispin), matrix_s_fm, trace)
    1208            4 :             nelectrons = nelectrons + trace
    1209              : 
    1210              :             ! rho_ao_delta_fm contains the original (non-mixed) density matrix from the previous iteration
    1211            4 :             CALL cp_fm_scale_and_add(1.0_dp, rho_ao_delta_fm(ispin), -1.0_dp, rho_ao_new_fm(ispin))
    1212            4 :             CALL cp_fm_trace(rho_ao_delta_fm(ispin), matrix_s_fm, trace)
    1213            4 :             nelectrons_diff = nelectrons_diff + trace
    1214              : 
    1215              :             ! rho_ao_new_fm -> rho_ao_delta_fm
    1216           12 :             CALL cp_fm_to_fm(rho_ao_new_fm(ispin), rho_ao_delta_fm(ispin))
    1217              :          END DO
    1218              : 
    1219            4 :          t2 = m_walltime()
    1220              : 
    1221            4 :          IF (log_unit > 0) THEN
    1222              :             WRITE (log_unit, '(T2,I5,T12,A,T32,F8.1,T43,F20.8,T65,ES15.5E2)') &
    1223            2 :                iter_count, get_method_description_string(stats, negf_control%integr_method), &
    1224            4 :                t2 - t1, -1.0_dp*nelectrons, nelectrons_diff
    1225              :          END IF
    1226              : 
    1227            4 :          IF (ABS(nelectrons_diff) < negf_control%conv_scf) EXIT
    1228              : 
    1229            0 :          t1 = t2
    1230              : 
    1231              :          ! mix density matrices
    1232            0 :          IF (negf_env%mixing_method == direct_mixing_nr) THEN
    1233            0 :             DO image = 1, nimages
    1234            0 :                DO ispin = 1, nspins
    1235              :                   CALL dbcsr_copy(matrix_b=rho_ao_new_kp(ispin, image)%matrix, &
    1236            0 :                                   matrix_a=rho_ao_initial_kp(ispin, image)%matrix)
    1237              :                END DO
    1238              :             END DO
    1239              : 
    1240            0 :             DO ispin = 1, nspins
    1241              :                CALL negf_copy_fm_submat_to_dbcsr(fm=rho_ao_new_fm(ispin), &
    1242              :                                                  matrix=rho_ao_new_kp(ispin, 1)%matrix, &
    1243              :                                                  atomlist_row=negf_control%atomlist_S_screening, &
    1244              :                                                  atomlist_col=negf_control%atomlist_S_screening, &
    1245            0 :                                                  subsys=subsys)
    1246              :             END DO
    1247              : 
    1248              :             CALL scf_env_density_mixing(rho_ao_new_kp, negf_env%mixing_storage, rho_ao_qs_kp, &
    1249            0 :                                         para_env, iter_delta, iter_count)
    1250              : 
    1251            0 :             DO image = 1, nimages
    1252            0 :                DO ispin = 1, nspins
    1253            0 :                   CALL dbcsr_copy(rho_ao_qs_kp(ispin, image)%matrix, rho_ao_new_kp(ispin, image)%matrix)
    1254              :                END DO
    1255              :             END DO
    1256              :          ELSE
    1257              :             ! store the updated density matrix directly into the variable 'rho_ao_qs_kp'
    1258              :             ! (which is qs_env%rho%rho_ao_kp); density mixing will be done on an inverse-space grid
    1259            0 :             DO image = 1, nimages
    1260            0 :                DO ispin = 1, nspins
    1261              :                   CALL dbcsr_copy(matrix_b=rho_ao_qs_kp(ispin, image)%matrix, &
    1262            0 :                                   matrix_a=rho_ao_initial_kp(ispin, image)%matrix)
    1263              :                END DO
    1264              :             END DO
    1265              : 
    1266            0 :             DO ispin = 1, nspins
    1267              :                CALL negf_copy_fm_submat_to_dbcsr(fm=rho_ao_new_fm(ispin), &
    1268              :                                                  matrix=rho_ao_qs_kp(ispin, 1)%matrix, &
    1269              :                                                  atomlist_row=negf_control%atomlist_S_screening, &
    1270              :                                                  atomlist_col=negf_control%atomlist_S_screening, &
    1271            0 :                                                  subsys=subsys)
    1272              :             END DO
    1273              :          END IF
    1274              : 
    1275            0 :          CALL qs_rho_update_rho(rho_struct, qs_env=qs_env)
    1276              : 
    1277            0 :          IF (negf_env%mixing_method >= gspace_mixing_nr) THEN
    1278              :             CALL gspace_mixing(qs_env, negf_env%mixing_method, negf_env%mixing_storage, &
    1279            0 :                                rho_struct, para_env, iter_count)
    1280              :          END IF
    1281              : 
    1282              :          ! update KS-matrix
    1283            0 :          CALL qs_ks_build_kohn_sham_matrix(qs_env, calculate_forces=.FALSE., just_energy=.FALSE.)
    1284              : 
    1285              :          ! extract blocks from the updated Kohn-Sham matrix
    1286            4 :          DO ispin = 1, nspins
    1287              :             CALL negf_copy_sym_dbcsr_to_fm_submat(matrix=matrix_ks_qs_kp(ispin, 1)%matrix, &
    1288              :                                                   fm=negf_env%h_s(ispin), &
    1289              :                                                   atomlist_row=negf_control%atomlist_S_screening, &
    1290              :                                                   atomlist_col=negf_control%atomlist_S_screening, &
    1291              :                                                   subsys=subsys, mpi_comm_global=para_env, &
    1292            0 :                                                   do_upper_diag=.TRUE., do_lower=.TRUE.)
    1293              : 
    1294              :          END DO
    1295              :       END DO
    1296              : 
    1297              :       !--------------------------------------------------------------------------------------!
    1298              : 
    1299            4 :       IF (log_unit > 0) THEN
    1300            2 :          IF (iter_count <= negf_control%max_scf) THEN
    1301            2 :             WRITE (log_unit, '(/,T11,1X,A,I0,A)') "*** NEGF run converged in ", iter_count, " iteration(s) ***"
    1302              :          ELSE
    1303            0 :             WRITE (log_unit, '(/,T11,1X,A,I0,A)') "*** NEGF run did NOT converge after ", iter_count - 1, " iteration(s) ***"
    1304              :          END IF
    1305              :       END IF
    1306              : 
    1307            8 :       DO ispin = nspins, 1, -1
    1308            4 :          CALL green_functions_cache_release(g_surf_circular(ispin))
    1309            4 :          CALL green_functions_cache_release(g_surf_linear(ispin))
    1310            8 :          CALL green_functions_cache_release(g_surf_nonequiv(ispin))
    1311              :       END DO
    1312           16 :       DEALLOCATE (g_surf_circular, g_surf_linear, g_surf_nonequiv)
    1313              : 
    1314            4 :       CALL cp_fm_release(rho_ao_new_fm)
    1315            4 :       CALL cp_fm_release(rho_ao_delta_fm)
    1316              : 
    1317            8 :       DO image = 1, nimages
    1318           12 :          DO ispin = 1, nspins
    1319            4 :             CALL dbcsr_copy(matrix_b=matrix_ks_qs_kp(ispin, image)%matrix, matrix_a=matrix_ks_initial_kp(ispin, image)%matrix)
    1320            4 :             CALL dbcsr_copy(matrix_b=rho_ao_qs_kp(ispin, image)%matrix, matrix_a=rho_ao_initial_kp(ispin, image)%matrix)
    1321              : 
    1322            4 :             CALL dbcsr_deallocate_matrix(matrix_ks_initial_kp(ispin, image)%matrix)
    1323            4 :             CALL dbcsr_deallocate_matrix(rho_ao_initial_kp(ispin, image)%matrix)
    1324            8 :             CALL dbcsr_deallocate_matrix(rho_ao_new_kp(ispin, image)%matrix)
    1325              :          END DO
    1326              :       END DO
    1327            4 :       DEALLOCATE (matrix_ks_initial_kp, rho_ao_new_kp, rho_ao_initial_kp)
    1328              : 
    1329            4 :       IF (sub_env%ngroups > 1 .AND. ASSOCIATED(matrix_s_fm)) THEN
    1330            4 :          CALL cp_fm_release(matrix_s_fm)
    1331            4 :          DEALLOCATE (matrix_s_fm)
    1332              :       END IF
    1333              : 
    1334            4 :       CALL timestop(handle)
    1335           12 :    END SUBROUTINE converge_density
    1336              : 
    1337              : ! **************************************************************************************************
    1338              : !> \brief Compute the surface retarded Green's function at a set of points in parallel.
    1339              : !> \param g_surf      set of surface Green's functions computed within the given parallel group
    1340              : !> \param omega       list of energy points where the surface Green's function need to be computed
    1341              : !> \param h0          diagonal block of the Kohn-Sham matrix (must be Hermitian)
    1342              : !> \param s0          diagonal block of the overlap matrix (must be Hermitian)
    1343              : !> \param h1          off-fiagonal block of the Kohn-Sham matrix
    1344              : !> \param s1          off-fiagonal block of the overlap matrix
    1345              : !> \param sub_env     NEGF parallel (sub)group environment
    1346              : !> \param v_external  applied electric potential
    1347              : !> \param conv        convergence threshold
    1348              : !> \param transp      flag which indicates that the matrices h1 and s1 should be transposed
    1349              : !> \par History
    1350              : !>    * 07.2017 created [Sergey Chulkov]
    1351              : ! **************************************************************************************************
    1352         1088 :    SUBROUTINE negf_surface_green_function_batch(g_surf, omega, h0, s0, h1, s1, sub_env, v_external, conv, transp)
    1353              :       TYPE(cp_cfm_type), DIMENSION(:), INTENT(inout)     :: g_surf
    1354              :       COMPLEX(kind=dp), DIMENSION(:), INTENT(in)         :: omega
    1355              :       TYPE(cp_fm_type), INTENT(IN)                       :: h0, s0, h1, s1
    1356              :       TYPE(negf_subgroup_env_type), INTENT(in)           :: sub_env
    1357              :       REAL(kind=dp), INTENT(in)                          :: v_external, conv
    1358              :       LOGICAL, INTENT(in)                                :: transp
    1359              : 
    1360              :       CHARACTER(len=*), PARAMETER :: routineN = 'negf_surface_green_function_batch'
    1361              :       TYPE(cp_cfm_type), PARAMETER                       :: cfm_null = cp_cfm_type()
    1362              : 
    1363              :       INTEGER                                            :: handle, igroup, ipoint, npoints
    1364              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    1365              :       TYPE(sancho_work_matrices_type)                    :: work
    1366              : 
    1367         1088 :       CALL timeset(routineN, handle)
    1368         1088 :       npoints = SIZE(omega)
    1369              : 
    1370         1088 :       CALL cp_fm_get_info(s0, matrix_struct=fm_struct)
    1371         1088 :       CALL sancho_work_matrices_create(work, fm_struct)
    1372              : 
    1373         1088 :       igroup = sub_env%group_distribution(sub_env%mepos_global)
    1374              : 
    1375        10848 :       g_surf(1:npoints) = cfm_null
    1376              : 
    1377         5968 :       DO ipoint = igroup + 1, npoints, sub_env%ngroups
    1378              :          IF (debug_this_module) THEN
    1379         4880 :             CPASSERT(.NOT. ASSOCIATED(g_surf(ipoint)%matrix_struct))
    1380              :          END IF
    1381         4880 :          CALL cp_cfm_create(g_surf(ipoint), fm_struct)
    1382              : 
    1383              :          CALL do_sancho(g_surf(ipoint), omega(ipoint) + v_external, &
    1384         5968 :                         h0, s0, h1, s1, conv, transp, work)
    1385              :       END DO
    1386              : 
    1387         1088 :       CALL sancho_work_matrices_release(work)
    1388         1088 :       CALL timestop(handle)
    1389         1088 :    END SUBROUTINE negf_surface_green_function_batch
    1390              : 
    1391              : ! **************************************************************************************************
    1392              : !> \brief Compute the retarded Green's function and related properties at a set of points in parallel.
    1393              : !> \param omega              list of energy points
    1394              : !> \param v_shift            shift in Hartree potential
    1395              : !> \param ignore_bias        ignore v_external from negf_control
    1396              : !> \param negf_env           NEGF environment
    1397              : !> \param negf_control       NEGF control
    1398              : !> \param sub_env            (sub)group environment
    1399              : !> \param ispin              spin component to compute
    1400              : !> \param g_surf_contacts    set of surface Green's functions for every contact that computed
    1401              : !>                           within the given parallel group
    1402              : !> \param g_ret_s            globally distributed matrices to store retarded Green's functions
    1403              : !> \param g_ret_scale        scale factor for retarded Green's functions
    1404              : !> \param gamma_contacts     2-D array of globally distributed matrices to store broadening matrices
    1405              : !>                           for every contact ([n_contacts, npoints])
    1406              : !> \param gret_gamma_gadv    2-D array of globally distributed matrices to store the spectral function:
    1407              : !>                           g_ret_s * gamma * g_ret_s^C for every contact ([n_contacts, n_points])
    1408              : !> \param dos                density of states at 'omega' ([n_points])
    1409              : !> \param transm_coeff       transmission coefficients between two contacts 'transm_contact1'
    1410              : !>                           and 'transm_contact2' computed at points 'omega' ([n_points])
    1411              : !> \param transm_contact1    index of the first contact
    1412              : !> \param transm_contact2    index of the second contact
    1413              : !> \param just_contact       if present, compute the retarded Green's function of the system
    1414              : !>                           lead1 -- device -- lead2. All 3 regions have the same Kohn-Sham
    1415              : !>                           matrices which are taken from 'negf_env%contacts(just_contact)%h'.
    1416              : !>                           Useful to apply NEGF procedure a single contact in order to compute
    1417              : !>                           its Fermi level
    1418              : !> \par History
    1419              : !>    * 07.2017 created [Sergey Chulkov]
    1420              : ! **************************************************************************************************
    1421          556 :    SUBROUTINE negf_retarded_green_function_batch(omega, v_shift, ignore_bias, negf_env, negf_control, sub_env, ispin, &
    1422          556 :                                                  g_surf_contacts, &
    1423         1112 :                                                  g_ret_s, g_ret_scale, gamma_contacts, gret_gamma_gadv, dos, &
    1424          556 :                                                  transm_coeff, transm_contact1, transm_contact2, just_contact)
    1425              :       COMPLEX(kind=dp), DIMENSION(:), INTENT(in)         :: omega
    1426              :       REAL(kind=dp), INTENT(in)                          :: v_shift
    1427              :       LOGICAL, INTENT(in)                                :: ignore_bias
    1428              :       TYPE(negf_env_type), INTENT(in)                    :: negf_env
    1429              :       TYPE(negf_control_type), POINTER                   :: negf_control
    1430              :       TYPE(negf_subgroup_env_type), INTENT(in)           :: sub_env
    1431              :       INTEGER, INTENT(in)                                :: ispin
    1432              :       TYPE(cp_cfm_type), DIMENSION(:, :), INTENT(in)     :: g_surf_contacts
    1433              :       TYPE(cp_cfm_type), DIMENSION(:), INTENT(in), &
    1434              :          OPTIONAL                                        :: g_ret_s
    1435              :       COMPLEX(kind=dp), DIMENSION(:), INTENT(in), &
    1436              :          OPTIONAL                                        :: g_ret_scale
    1437              :       TYPE(cp_cfm_type), DIMENSION(:, :), INTENT(in), &
    1438              :          OPTIONAL                                        :: gamma_contacts, gret_gamma_gadv
    1439              :       REAL(kind=dp), DIMENSION(:), INTENT(out), OPTIONAL :: dos
    1440              :       COMPLEX(kind=dp), DIMENSION(:), INTENT(out), &
    1441              :          OPTIONAL                                        :: transm_coeff
    1442              :       INTEGER, INTENT(in), OPTIONAL                      :: transm_contact1, transm_contact2, &
    1443              :                                                             just_contact
    1444              : 
    1445              :       CHARACTER(len=*), PARAMETER :: routineN = 'negf_retarded_green_function_batch'
    1446              : 
    1447              :       INTEGER                                            :: handle, icontact, igroup, ipoint, &
    1448              :                                                             ncontacts, npoints, nrows
    1449              :       REAL(kind=dp)                                      :: v_external
    1450              :       TYPE(copy_cfm_info_type), ALLOCATABLE, &
    1451          556 :          DIMENSION(:)                                    :: info1
    1452              :       TYPE(copy_cfm_info_type), ALLOCATABLE, &
    1453          556 :          DIMENSION(:, :)                                 :: info2
    1454          556 :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:)       :: g_ret_s_group, self_energy_contacts, &
    1455          556 :                                                             zwork1_contacts, zwork2_contacts
    1456          556 :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:, :)    :: gamma_contacts_group, &
    1457          556 :                                                             gret_gamma_gadv_group
    1458              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    1459              :       TYPE(cp_fm_type)                                   :: g_ret_imag
    1460              :       TYPE(cp_fm_type), POINTER                          :: matrix_s
    1461              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1462              : 
    1463          556 :       CALL timeset(routineN, handle)
    1464          556 :       npoints = SIZE(omega)
    1465          556 :       ncontacts = SIZE(negf_env%contacts)
    1466          556 :       CPASSERT(SIZE(negf_control%contacts) == ncontacts)
    1467              : 
    1468          556 :       IF (PRESENT(just_contact)) THEN
    1469           36 :          CPASSERT(just_contact <= ncontacts)
    1470              :          ncontacts = 2
    1471              :       END IF
    1472              : 
    1473          520 :       CPASSERT(ncontacts >= 2)
    1474              : 
    1475              :       IF (ignore_bias) v_external = 0.0_dp
    1476              : 
    1477          556 :       IF (PRESENT(transm_coeff) .OR. PRESENT(transm_contact1) .OR. PRESENT(transm_contact2)) THEN
    1478          204 :          CPASSERT(PRESENT(transm_coeff))
    1479          204 :          CPASSERT(PRESENT(transm_contact1))
    1480          204 :          CPASSERT(PRESENT(transm_contact2))
    1481          204 :          CPASSERT(.NOT. PRESENT(just_contact))
    1482              :       END IF
    1483              : 
    1484         6116 :       ALLOCATE (self_energy_contacts(ncontacts), zwork1_contacts(ncontacts), zwork2_contacts(ncontacts))
    1485              : 
    1486          556 :       IF (PRESENT(just_contact)) THEN
    1487           36 :          CALL cp_fm_get_info(negf_env%contacts(just_contact)%s_01, matrix_struct=fm_struct)
    1488          108 :          DO icontact = 1, ncontacts
    1489           72 :             CALL cp_cfm_create(zwork1_contacts(icontact), fm_struct)
    1490          108 :             CALL cp_cfm_create(zwork2_contacts(icontact), fm_struct)
    1491              :          END DO
    1492              : 
    1493           36 :          CALL cp_fm_get_info(negf_env%contacts(just_contact)%s_00, nrow_global=nrows, matrix_struct=fm_struct)
    1494          108 :          DO icontact = 1, ncontacts
    1495          108 :             CALL cp_cfm_create(self_energy_contacts(icontact), fm_struct)
    1496              :          END DO
    1497              :       ELSE
    1498         1560 :          DO icontact = 1, ncontacts
    1499         1040 :             CALL cp_fm_get_info(negf_env%s_sc(icontact), matrix_struct=fm_struct)
    1500         1040 :             CALL cp_cfm_create(zwork1_contacts(icontact), fm_struct)
    1501         1560 :             CALL cp_cfm_create(zwork2_contacts(icontact), fm_struct)
    1502              :          END DO
    1503              : 
    1504          520 :          CALL cp_fm_get_info(negf_env%s_s, nrow_global=nrows, matrix_struct=fm_struct)
    1505         1560 :          DO icontact = 1, ncontacts
    1506         1560 :             CALL cp_cfm_create(self_energy_contacts(icontact), fm_struct)
    1507              :          END DO
    1508              :       END IF
    1509              : 
    1510              :       IF (PRESENT(g_ret_s) .OR. PRESENT(gret_gamma_gadv) .OR. &
    1511          556 :           PRESENT(dos) .OR. PRESENT(transm_coeff)) THEN
    1512         7624 :          ALLOCATE (g_ret_s_group(npoints))
    1513              : 
    1514          556 :          IF (sub_env%ngroups <= 1 .AND. PRESENT(g_ret_s)) THEN
    1515            0 :             g_ret_s_group(1:npoints) = g_ret_s(1:npoints)
    1516              :          END IF
    1517              :       END IF
    1518              : 
    1519          556 :       IF (PRESENT(gamma_contacts) .OR. PRESENT(gret_gamma_gadv) .OR. PRESENT(transm_coeff)) THEN
    1520          204 :          IF (debug_this_module .AND. PRESENT(gamma_contacts)) THEN
    1521            0 :             CPASSERT(SIZE(gamma_contacts, 1) == ncontacts)
    1522              :          END IF
    1523              : 
    1524         5628 :          ALLOCATE (gamma_contacts_group(ncontacts, npoints))
    1525          204 :          IF (sub_env%ngroups <= 1 .AND. PRESENT(gamma_contacts)) THEN
    1526            0 :             gamma_contacts_group(1:ncontacts, 1:npoints) = gamma_contacts(1:ncontacts, 1:npoints)
    1527              :          END IF
    1528              :       END IF
    1529              : 
    1530          556 :       IF (PRESENT(gret_gamma_gadv)) THEN
    1531              :          IF (debug_this_module .AND. PRESENT(gret_gamma_gadv)) THEN
    1532            0 :             CPASSERT(SIZE(gret_gamma_gadv, 1) == ncontacts)
    1533              :          END IF
    1534              : 
    1535            0 :          ALLOCATE (gret_gamma_gadv_group(ncontacts, npoints))
    1536            0 :          IF (sub_env%ngroups <= 1) THEN
    1537            0 :             gret_gamma_gadv_group(1:ncontacts, 1:npoints) = gret_gamma_gadv(1:ncontacts, 1:npoints)
    1538              :          END IF
    1539              :       END IF
    1540              : 
    1541          556 :       igroup = sub_env%group_distribution(sub_env%mepos_global)
    1542              : 
    1543         6512 :       DO ipoint = 1, npoints
    1544         6512 :          IF (ASSOCIATED(g_surf_contacts(1, ipoint)%matrix_struct)) THEN
    1545         2978 :             IF (sub_env%ngroups > 1 .OR. .NOT. PRESENT(g_ret_s)) THEN
    1546              :                ! create a group-specific matrix to store retarded Green's function if there are
    1547              :                ! at least two parallel groups; otherwise pointers to group-specific matrices have
    1548              :                ! already been initialised and they point to globally distributed matrices
    1549         2978 :                IF (ALLOCATED(g_ret_s_group)) THEN
    1550         2978 :                   CALL cp_cfm_create(g_ret_s_group(ipoint), fm_struct)
    1551              :                END IF
    1552              :             END IF
    1553              : 
    1554         2978 :             IF (sub_env%ngroups > 1 .OR. .NOT. PRESENT(gamma_contacts)) THEN
    1555         2978 :                IF (ALLOCATED(gamma_contacts_group)) THEN
    1556         2406 :                   DO icontact = 1, ncontacts
    1557         2406 :                      CALL cp_cfm_create(gamma_contacts_group(icontact, ipoint), fm_struct)
    1558              :                   END DO
    1559              :                END IF
    1560              :             END IF
    1561              : 
    1562         2978 :             IF (sub_env%ngroups > 1) THEN
    1563         2978 :                IF (ALLOCATED(gret_gamma_gadv_group)) THEN
    1564            0 :                   DO icontact = 1, ncontacts
    1565            0 :                      IF (ASSOCIATED(gret_gamma_gadv(icontact, ipoint)%matrix_struct)) THEN
    1566            0 :                         CALL cp_cfm_create(gret_gamma_gadv_group(icontact, ipoint), fm_struct)
    1567              :                      END IF
    1568              :                   END DO
    1569              :                END IF
    1570              :             END IF
    1571              : 
    1572         2978 :             IF (PRESENT(just_contact)) THEN
    1573              :                ! self energy of the "left" (1) and "right" contacts
    1574          612 :                DO icontact = 1, ncontacts
    1575              :                   CALL negf_contact_self_energy(self_energy_c=self_energy_contacts(icontact), &
    1576              :                                                 omega=omega(ipoint), &
    1577              :                                                 g_surf_c=g_surf_contacts(icontact, ipoint), &
    1578              :                                                 h_sc0=negf_env%contacts(just_contact)%h_01(ispin), &
    1579              :                                                 s_sc0=negf_env%contacts(just_contact)%s_01, &
    1580              :                                                 zwork1=zwork1_contacts(icontact), &
    1581              :                                                 zwork2=zwork2_contacts(icontact), &
    1582          612 :                                                 transp=(icontact == 1))
    1583              :                END DO
    1584              :             ELSE
    1585              :                ! contact self energies
    1586         8322 :                DO icontact = 1, ncontacts
    1587         5548 :                   IF (.NOT. ignore_bias) v_external = negf_control%contacts(icontact)%v_external
    1588              : 
    1589              :                   CALL negf_contact_self_energy(self_energy_c=self_energy_contacts(icontact), &
    1590              :                                                 omega=omega(ipoint) + v_external, &
    1591              :                                                 g_surf_c=g_surf_contacts(icontact, ipoint), &
    1592              :                                                 h_sc0=negf_env%h_sc(ispin, icontact), &
    1593              :                                                 s_sc0=negf_env%s_sc(icontact), &
    1594              :                                                 zwork1=zwork1_contacts(icontact), &
    1595              :                                                 zwork2=zwork2_contacts(icontact), &
    1596         8322 :                                                 transp=.FALSE.)
    1597              :                END DO
    1598              :             END IF
    1599              : 
    1600              :             ! broadening matrices
    1601         2978 :             IF (ALLOCATED(gamma_contacts_group)) THEN
    1602         2406 :                DO icontact = 1, ncontacts
    1603              :                   CALL negf_contact_broadening_matrix(gamma_c=gamma_contacts_group(icontact, ipoint), &
    1604         2406 :                                                       self_energy_c=self_energy_contacts(icontact))
    1605              :                END DO
    1606              :             END IF
    1607              : 
    1608         2978 :             IF (ALLOCATED(g_ret_s_group)) THEN
    1609              :                ! sum up self energies for all contacts
    1610         5956 :                DO icontact = 2, ncontacts
    1611         5956 :                   CALL cp_cfm_scale_and_add(z_one, self_energy_contacts(1), z_one, self_energy_contacts(icontact))
    1612              :                END DO
    1613              : 
    1614              :                ! retarded Green's function for the scattering region
    1615         2978 :                IF (PRESENT(just_contact)) THEN
    1616              :                   CALL negf_retarded_green_function(g_ret_s=g_ret_s_group(ipoint), &
    1617              :                                                     omega=omega(ipoint) - v_shift, &
    1618              :                                                     self_energy_ret_sum=self_energy_contacts(1), &
    1619              :                                                     h_s=negf_env%contacts(just_contact)%h_00(ispin), &
    1620          204 :                                                     s_s=negf_env%contacts(just_contact)%s_00)
    1621         2774 :                ELSE IF (ignore_bias) THEN
    1622              :                   CALL negf_retarded_green_function(g_ret_s=g_ret_s_group(ipoint), &
    1623              :                                                     omega=omega(ipoint) - v_shift, &
    1624              :                                                     self_energy_ret_sum=self_energy_contacts(1), &
    1625              :                                                     h_s=negf_env%h_s(ispin), &
    1626          894 :                                                     s_s=negf_env%s_s)
    1627              :                ELSE
    1628              :                   CALL negf_retarded_green_function(g_ret_s=g_ret_s_group(ipoint), &
    1629              :                                                     omega=omega(ipoint) - v_shift, &
    1630              :                                                     self_energy_ret_sum=self_energy_contacts(1), &
    1631              :                                                     h_s=negf_env%h_s(ispin), &
    1632              :                                                     s_s=negf_env%s_s, &
    1633         1880 :                                                     v_hartree_s=negf_env%v_hartree_s)
    1634              :                END IF
    1635              : 
    1636         2978 :                IF (PRESENT(g_ret_scale)) THEN
    1637         1338 :                   IF (g_ret_scale(ipoint) /= z_one) CALL cp_cfm_scale(g_ret_scale(ipoint), g_ret_s_group(ipoint))
    1638              :                END IF
    1639              :             END IF
    1640              : 
    1641         2978 :             IF (ALLOCATED(gret_gamma_gadv_group)) THEN
    1642              :                ! we do not need contact self energies any longer, so we can use
    1643              :                ! the array 'self_energy_contacts' as a set of work matrices
    1644            0 :                DO icontact = 1, ncontacts
    1645            0 :                   IF (ASSOCIATED(gret_gamma_gadv_group(icontact, ipoint)%matrix_struct)) THEN
    1646              :                      CALL parallel_gemm('N', 'C', nrows, nrows, nrows, &
    1647              :                                         z_one, gamma_contacts_group(icontact, ipoint), &
    1648              :                                         g_ret_s_group(ipoint), &
    1649            0 :                                         z_zero, self_energy_contacts(icontact))
    1650              :                      CALL parallel_gemm('N', 'N', nrows, nrows, nrows, &
    1651              :                                         z_one, g_ret_s_group(ipoint), &
    1652              :                                         self_energy_contacts(icontact), &
    1653            0 :                                         z_zero, gret_gamma_gadv_group(icontact, ipoint))
    1654              :                   END IF
    1655              :                END DO
    1656              :             END IF
    1657              :          END IF
    1658              :       END DO
    1659              : 
    1660              :       ! redistribute locally stored matrices
    1661          556 :       IF (PRESENT(g_ret_s)) THEN
    1662          148 :          IF (sub_env%ngroups > 1) THEN
    1663          148 :             NULLIFY (para_env)
    1664          148 :             DO ipoint = 1, npoints
    1665          148 :                IF (ASSOCIATED(g_ret_s(ipoint)%matrix_struct)) THEN
    1666          148 :                   CALL cp_cfm_get_info(g_ret_s(ipoint), para_env=para_env)
    1667          148 :                   EXIT
    1668              :                END IF
    1669              :             END DO
    1670              : 
    1671          148 :             IF (ASSOCIATED(para_env)) THEN
    1672         4376 :                ALLOCATE (info1(npoints))
    1673              : 
    1674         2896 :                DO ipoint = 1, npoints
    1675              :                   CALL cp_cfm_start_copy_general(g_ret_s_group(ipoint), &
    1676              :                                                  g_ret_s(ipoint), &
    1677         2896 :                                                  para_env, info1(ipoint))
    1678              :                END DO
    1679              : 
    1680         2896 :                DO ipoint = 1, npoints
    1681         2896 :                   IF (ASSOCIATED(g_ret_s(ipoint)%matrix_struct)) THEN
    1682         2748 :                      CALL cp_cfm_finish_copy_general(g_ret_s(ipoint), info1(ipoint))
    1683         2748 :                      IF (ASSOCIATED(g_ret_s_group(ipoint)%matrix_struct)) &
    1684         1374 :                         CALL cp_cfm_cleanup_copy_general(info1(ipoint))
    1685              :                   END IF
    1686              :                END DO
    1687              : 
    1688         2896 :                DEALLOCATE (info1)
    1689              :             END IF
    1690              :          END IF
    1691              :       END IF
    1692              : 
    1693          556 :       IF (PRESENT(gamma_contacts)) THEN
    1694            0 :          IF (sub_env%ngroups > 1) THEN
    1695            0 :             NULLIFY (para_env)
    1696            0 :             pnt1: DO ipoint = 1, npoints
    1697            0 :                DO icontact = 1, ncontacts
    1698            0 :                   IF (ASSOCIATED(gamma_contacts(icontact, ipoint)%matrix_struct)) THEN
    1699            0 :                      CALL cp_cfm_get_info(gamma_contacts(icontact, ipoint), para_env=para_env)
    1700            0 :                      EXIT pnt1
    1701              :                   END IF
    1702              :                END DO
    1703              :             END DO pnt1
    1704              : 
    1705            0 :             IF (ASSOCIATED(para_env)) THEN
    1706            0 :                ALLOCATE (info2(ncontacts, npoints))
    1707              : 
    1708            0 :                DO ipoint = 1, npoints
    1709            0 :                   DO icontact = 1, ncontacts
    1710              :                      CALL cp_cfm_start_copy_general(gamma_contacts_group(icontact, ipoint), &
    1711              :                                                     gamma_contacts(icontact, ipoint), &
    1712            0 :                                                     para_env, info2(icontact, ipoint))
    1713              :                   END DO
    1714              :                END DO
    1715              : 
    1716            0 :                DO ipoint = 1, npoints
    1717            0 :                   DO icontact = 1, ncontacts
    1718            0 :                      IF (ASSOCIATED(gamma_contacts(icontact, ipoint)%matrix_struct)) THEN
    1719            0 :                         CALL cp_cfm_finish_copy_general(gamma_contacts(icontact, ipoint), info2(icontact, ipoint))
    1720            0 :                         IF (ASSOCIATED(gamma_contacts_group(icontact, ipoint)%matrix_struct)) THEN
    1721            0 :                            CALL cp_cfm_cleanup_copy_general(info2(icontact, ipoint))
    1722              :                         END IF
    1723              :                      END IF
    1724              :                   END DO
    1725              :                END DO
    1726              : 
    1727            0 :                DEALLOCATE (info2)
    1728              :             END IF
    1729              :          END IF
    1730              :       END IF
    1731              : 
    1732          556 :       IF (PRESENT(gret_gamma_gadv)) THEN
    1733            0 :          IF (sub_env%ngroups > 1) THEN
    1734            0 :             NULLIFY (para_env)
    1735            0 :             pnt2: DO ipoint = 1, npoints
    1736            0 :                DO icontact = 1, ncontacts
    1737            0 :                   IF (ASSOCIATED(gret_gamma_gadv(icontact, ipoint)%matrix_struct)) THEN
    1738            0 :                      CALL cp_cfm_get_info(gret_gamma_gadv(icontact, ipoint), para_env=para_env)
    1739            0 :                      EXIT pnt2
    1740              :                   END IF
    1741              :                END DO
    1742              :             END DO pnt2
    1743              : 
    1744            0 :             IF (ASSOCIATED(para_env)) THEN
    1745            0 :                ALLOCATE (info2(ncontacts, npoints))
    1746              : 
    1747            0 :                DO ipoint = 1, npoints
    1748            0 :                   DO icontact = 1, ncontacts
    1749              :                      CALL cp_cfm_start_copy_general(gret_gamma_gadv_group(icontact, ipoint), &
    1750              :                                                     gret_gamma_gadv(icontact, ipoint), &
    1751            0 :                                                     para_env, info2(icontact, ipoint))
    1752              :                   END DO
    1753              :                END DO
    1754              : 
    1755            0 :                DO ipoint = 1, npoints
    1756            0 :                   DO icontact = 1, ncontacts
    1757            0 :                      IF (ASSOCIATED(gret_gamma_gadv(icontact, ipoint)%matrix_struct)) THEN
    1758            0 :                         CALL cp_cfm_finish_copy_general(gret_gamma_gadv(icontact, ipoint), info2(icontact, ipoint))
    1759            0 :                         IF (ASSOCIATED(gret_gamma_gadv_group(icontact, ipoint)%matrix_struct)) THEN
    1760            0 :                            CALL cp_cfm_cleanup_copy_general(info2(icontact, ipoint))
    1761              :                         END IF
    1762              :                      END IF
    1763              :                   END DO
    1764              :                END DO
    1765              : 
    1766            0 :                DEALLOCATE (info2)
    1767              :             END IF
    1768              :          END IF
    1769              :       END IF
    1770              : 
    1771          556 :       IF (PRESENT(dos)) THEN
    1772         1808 :          dos(:) = 0.0_dp
    1773              : 
    1774          204 :          IF (PRESENT(just_contact)) THEN
    1775            0 :             matrix_s => negf_env%contacts(just_contact)%s_00
    1776              :          ELSE
    1777          204 :             matrix_s => negf_env%s_s
    1778              :          END IF
    1779              : 
    1780          204 :          CALL cp_fm_get_info(matrix_s, matrix_struct=fm_struct)
    1781          204 :          CALL cp_fm_create(g_ret_imag, fm_struct)
    1782              : 
    1783         1808 :          DO ipoint = 1, npoints
    1784         1808 :             IF (ASSOCIATED(g_ret_s_group(ipoint)%matrix_struct)) THEN
    1785          802 :                CALL cp_cfm_to_fm(g_ret_s_group(ipoint), mtargeti=g_ret_imag)
    1786          802 :                CALL cp_fm_trace(g_ret_imag, matrix_s, dos(ipoint))
    1787          802 :                IF (sub_env%para_env%mepos /= 0) dos(ipoint) = 0.0_dp
    1788              :             END IF
    1789              :          END DO
    1790              : 
    1791          204 :          CALL cp_fm_release(g_ret_imag)
    1792              : 
    1793         3412 :          CALL sub_env%mpi_comm_global%sum(dos)
    1794         1808 :          dos(:) = -1.0_dp/pi*dos(:)
    1795              :       END IF
    1796              : 
    1797          556 :       IF (PRESENT(transm_coeff)) THEN
    1798         1808 :          transm_coeff(:) = z_zero
    1799              : 
    1800         1808 :          DO ipoint = 1, npoints
    1801         1808 :             IF (ASSOCIATED(g_ret_s_group(ipoint)%matrix_struct)) THEN
    1802              :                ! gamma_1 * g_adv_s * gamma_2
    1803              :                CALL parallel_gemm('N', 'C', nrows, nrows, nrows, &
    1804              :                                   z_one, gamma_contacts_group(transm_contact1, ipoint), &
    1805              :                                   g_ret_s_group(ipoint), &
    1806          802 :                                   z_zero, self_energy_contacts(transm_contact1))
    1807              :                CALL parallel_gemm('N', 'N', nrows, nrows, nrows, &
    1808              :                                   z_one, self_energy_contacts(transm_contact1), &
    1809              :                                   gamma_contacts_group(transm_contact2, ipoint), &
    1810          802 :                                   z_zero, self_energy_contacts(transm_contact2))
    1811              : 
    1812              :                !  Trace[ g_ret_s * gamma_1 * g_adv_s * gamma_2 ]
    1813              :                CALL cp_cfm_trace(g_ret_s_group(ipoint), &
    1814              :                                  self_energy_contacts(transm_contact2), &
    1815          802 :                                  transm_coeff(ipoint))
    1816          802 :                IF (sub_env%para_env%mepos /= 0) transm_coeff(ipoint) = 0.0_dp
    1817              :             END IF
    1818              :          END DO
    1819              : 
    1820              :          ! transmission coefficients are scaled by 2/pi
    1821         3412 :          CALL sub_env%mpi_comm_global%sum(transm_coeff)
    1822              :          !transm_coeff(:) = 0.5_dp/pi*transm_coeff(:)
    1823              :       END IF
    1824              : 
    1825              :       ! -- deallocate temporary matrices
    1826          556 :       IF (ALLOCATED(g_ret_s_group)) THEN
    1827         6512 :          DO ipoint = npoints, 1, -1
    1828         6512 :             IF (sub_env%ngroups > 1 .OR. .NOT. PRESENT(g_ret_s)) THEN
    1829         5956 :                CALL cp_cfm_release(g_ret_s_group(ipoint))
    1830              :             END IF
    1831              :          END DO
    1832          556 :          DEALLOCATE (g_ret_s_group)
    1833              :       END IF
    1834              : 
    1835          556 :       IF (ALLOCATED(gamma_contacts_group)) THEN
    1836         1808 :          DO ipoint = npoints, 1, -1
    1837         5016 :             DO icontact = ncontacts, 1, -1
    1838         4812 :                IF (sub_env%ngroups > 1 .OR. .NOT. PRESENT(gamma_contacts)) THEN
    1839         3208 :                   CALL cp_cfm_release(gamma_contacts_group(icontact, ipoint))
    1840              :                END IF
    1841              :             END DO
    1842              :          END DO
    1843          204 :          DEALLOCATE (gamma_contacts_group)
    1844              :       END IF
    1845              : 
    1846          556 :       IF (ALLOCATED(gret_gamma_gadv_group)) THEN
    1847            0 :          DO ipoint = npoints, 1, -1
    1848            0 :             DO icontact = ncontacts, 1, -1
    1849            0 :                IF (sub_env%ngroups > 1) THEN
    1850            0 :                   CALL cp_cfm_release(gret_gamma_gadv_group(icontact, ipoint))
    1851              :                END IF
    1852              :             END DO
    1853              :          END DO
    1854            0 :          DEALLOCATE (gret_gamma_gadv_group)
    1855              :       END IF
    1856              : 
    1857          556 :       IF (ALLOCATED(self_energy_contacts)) THEN
    1858         1668 :          DO icontact = ncontacts, 1, -1
    1859         1668 :             CALL cp_cfm_release(self_energy_contacts(icontact))
    1860              :          END DO
    1861          556 :          DEALLOCATE (self_energy_contacts)
    1862              :       END IF
    1863              : 
    1864          556 :       IF (ALLOCATED(zwork1_contacts)) THEN
    1865         1668 :          DO icontact = ncontacts, 1, -1
    1866         1668 :             CALL cp_cfm_release(zwork1_contacts(icontact))
    1867              :          END DO
    1868          556 :          DEALLOCATE (zwork1_contacts)
    1869              :       END IF
    1870              : 
    1871          556 :       IF (ALLOCATED(zwork2_contacts)) THEN
    1872         1668 :          DO icontact = ncontacts, 1, -1
    1873         1668 :             CALL cp_cfm_release(zwork2_contacts(icontact))
    1874              :          END DO
    1875          556 :          DEALLOCATE (zwork2_contacts)
    1876              :       END IF
    1877              : 
    1878          556 :       CALL timestop(handle)
    1879         1112 :    END SUBROUTINE negf_retarded_green_function_batch
    1880              : 
    1881              : ! **************************************************************************************************
    1882              : !> \brief Fermi function (exp(E/(kT)) + 1) ^ {-1} .
    1883              : !> \param omega       'energy' point on the complex plane
    1884              : !> \param temperature temperature in atomic units
    1885              : !> \return value
    1886              : !> \par History
    1887              : !>    * 05.2017 created [Sergey Chulkov]
    1888              : ! **************************************************************************************************
    1889         2676 :    PURE FUNCTION fermi_function(omega, temperature) RESULT(val)
    1890              :       COMPLEX(kind=dp), INTENT(in)                       :: omega
    1891              :       REAL(kind=dp), INTENT(in)                          :: temperature
    1892              :       COMPLEX(kind=dp)                                   :: val
    1893              : 
    1894              :       REAL(kind=dp), PARAMETER :: max_ln_omega_over_T = LOG(HUGE(0.0_dp))/16.0_dp
    1895              : 
    1896         2676 :       IF (REAL(omega, kind=dp) <= temperature*max_ln_omega_over_T) THEN
    1897              :          ! exp(omega / T) < huge(0), so EXP() should not return infinity
    1898         2676 :          val = z_one/(EXP(omega/temperature) + z_one)
    1899              :       ELSE
    1900              :          val = z_zero
    1901              :       END IF
    1902         2676 :    END FUNCTION fermi_function
    1903              : 
    1904              : ! **************************************************************************************************
    1905              : !> \brief Compute contribution to the density matrix from the poles of the Fermi function.
    1906              : !> \param rho_ao_fm     density matrix (initialised on exit)
    1907              : !> \param v_shift       shift in Hartree potential
    1908              : !> \param ignore_bias   ignore v_external from negf_control
    1909              : !> \param negf_env      NEGF environment
    1910              : !> \param negf_control  NEGF control
    1911              : !> \param sub_env       NEGF parallel (sub)group environment
    1912              : !> \param ispin         spin conponent to proceed
    1913              : !> \param base_contact  index of the reference contact
    1914              : !> \param just_contact  ...
    1915              : !> \author Sergey Chulkov
    1916              : ! **************************************************************************************************
    1917           18 :    SUBROUTINE negf_init_rho_equiv_residuals(rho_ao_fm, v_shift, ignore_bias, negf_env, &
    1918              :                                             negf_control, sub_env, ispin, base_contact, just_contact)
    1919              :       TYPE(cp_fm_type), INTENT(IN)                       :: rho_ao_fm
    1920              :       REAL(kind=dp), INTENT(in)                          :: v_shift
    1921              :       LOGICAL, INTENT(in)                                :: ignore_bias
    1922              :       TYPE(negf_env_type), INTENT(in)                    :: negf_env
    1923              :       TYPE(negf_control_type), POINTER                   :: negf_control
    1924              :       TYPE(negf_subgroup_env_type), INTENT(in)           :: sub_env
    1925              :       INTEGER, INTENT(in)                                :: ispin, base_contact
    1926              :       INTEGER, INTENT(in), OPTIONAL                      :: just_contact
    1927              : 
    1928              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'negf_init_rho_equiv_residuals'
    1929              : 
    1930           18 :       COMPLEX(kind=dp), ALLOCATABLE, DIMENSION(:)        :: omega
    1931              :       INTEGER                                            :: handle, icontact, ipole, ncontacts, &
    1932              :                                                             npoles
    1933              :       REAL(kind=dp)                                      :: mu_base, pi_temperature, temperature, &
    1934              :                                                             v_external
    1935           18 :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:)       :: g_ret_s
    1936              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    1937           18 :       TYPE(green_functions_cache_type)                   :: g_surf_cache
    1938              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1939              : 
    1940           18 :       CALL timeset(routineN, handle)
    1941              : 
    1942           18 :       temperature = negf_control%contacts(base_contact)%temperature
    1943           18 :       IF (ignore_bias) THEN
    1944           14 :          mu_base = negf_control%contacts(base_contact)%fermi_level
    1945           14 :          v_external = 0.0_dp
    1946              :       ELSE
    1947            4 :          mu_base = negf_control%contacts(base_contact)%fermi_level - negf_control%contacts(base_contact)%v_external
    1948              :       END IF
    1949              : 
    1950           18 :       pi_temperature = pi*temperature
    1951           18 :       npoles = negf_control%delta_npoles
    1952              : 
    1953           18 :       ncontacts = SIZE(negf_env%contacts)
    1954           18 :       CPASSERT(base_contact <= ncontacts)
    1955           18 :       IF (PRESENT(just_contact)) THEN
    1956            4 :          ncontacts = 2
    1957            4 :          CPASSERT(just_contact == base_contact)
    1958              :       END IF
    1959              : 
    1960           18 :       IF (npoles > 0) THEN
    1961           18 :          CALL cp_fm_get_info(rho_ao_fm, para_env=para_env, matrix_struct=fm_struct)
    1962              : 
    1963          162 :          ALLOCATE (omega(npoles), g_ret_s(npoles))
    1964              : 
    1965           90 :          DO ipole = 1, npoles
    1966           72 :             CALL cp_cfm_create(g_ret_s(ipole), fm_struct)
    1967              : 
    1968           90 :             omega(ipole) = CMPLX(mu_base, REAL(2*ipole - 1, kind=dp)*pi_temperature, kind=dp)
    1969              :          END DO
    1970              : 
    1971           18 :          CALL green_functions_cache_expand(g_surf_cache, ncontacts, npoles)
    1972              : 
    1973           18 :          IF (PRESENT(just_contact)) THEN
    1974              :             ! do not apply the external potential when computing the Fermi level of a bulk contact.
    1975              :             ! We are using a fictitious electronic device, which identical to the bulk contact in question;
    1976              :             ! icontact == 1 corresponds to the "left" contact, so the matrices h_01 and s_01 needs to be transposed,
    1977              :             ! while icontact == 2 correspond to the "right" contact and we should use the matrices h_01 and s_01 as is.
    1978           12 :             DO icontact = 1, ncontacts
    1979              :                CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, :), &
    1980              :                                                       omega=omega(:), &
    1981              :                                                       h0=negf_env%contacts(just_contact)%h_00(ispin), &
    1982              :                                                       s0=negf_env%contacts(just_contact)%s_00, &
    1983              :                                                       h1=negf_env%contacts(just_contact)%h_01(ispin), &
    1984              :                                                       s1=negf_env%contacts(just_contact)%s_01, &
    1985              :                                                       sub_env=sub_env, v_external=0.0_dp, &
    1986           12 :                                                       conv=negf_control%conv_green, transp=(icontact == 1))
    1987              :             END DO
    1988              :          ELSE
    1989           42 :             DO icontact = 1, ncontacts
    1990           28 :                IF (.NOT. ignore_bias) v_external = negf_control%contacts(icontact)%v_external
    1991              : 
    1992              :                CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, :), &
    1993              :                                                       omega=omega(:), &
    1994              :                                                       h0=negf_env%contacts(icontact)%h_00(ispin), &
    1995              :                                                       s0=negf_env%contacts(icontact)%s_00, &
    1996              :                                                       h1=negf_env%contacts(icontact)%h_01(ispin), &
    1997              :                                                       s1=negf_env%contacts(icontact)%s_01, &
    1998              :                                                       sub_env=sub_env, &
    1999              :                                                       v_external=v_external, &
    2000           42 :                                                       conv=negf_control%conv_green, transp=.FALSE.)
    2001              :             END DO
    2002              :          END IF
    2003              : 
    2004              :          CALL negf_retarded_green_function_batch(omega=omega(:), &
    2005              :                                                  v_shift=v_shift, &
    2006              :                                                  ignore_bias=ignore_bias, &
    2007              :                                                  negf_env=negf_env, &
    2008              :                                                  negf_control=negf_control, &
    2009              :                                                  sub_env=sub_env, &
    2010              :                                                  ispin=ispin, &
    2011              :                                                  g_surf_contacts=g_surf_cache%g_surf_contacts, &
    2012              :                                                  g_ret_s=g_ret_s, &
    2013           18 :                                                  just_contact=just_contact)
    2014              : 
    2015           18 :          CALL green_functions_cache_release(g_surf_cache)
    2016              : 
    2017           72 :          DO ipole = 2, npoles
    2018           72 :             CALL cp_cfm_scale_and_add(z_one, g_ret_s(1), z_one, g_ret_s(ipole))
    2019              :          END DO
    2020              : 
    2021              :          !Re(-i * (-2*pi*i*kB*T/(-pi) * [Re(G)+i*Im(G)]) == 2*kB*T * Re(G)
    2022           18 :          CALL cp_cfm_to_fm(g_ret_s(1), mtargetr=rho_ao_fm)
    2023           18 :          CALL cp_fm_scale(2.0_dp*temperature, rho_ao_fm)
    2024              : 
    2025           90 :          DO ipole = npoles, 1, -1
    2026           90 :             CALL cp_cfm_release(g_ret_s(ipole))
    2027              :          END DO
    2028           18 :          DEALLOCATE (g_ret_s, omega)
    2029              :       END IF
    2030              : 
    2031           18 :       CALL timestop(handle)
    2032           18 :    END SUBROUTINE negf_init_rho_equiv_residuals
    2033              : 
    2034              : ! **************************************************************************************************
    2035              : !> \brief Compute equilibrium contribution to the density matrix.
    2036              : !> \param rho_ao_fm       density matrix (initialised on exit)
    2037              : !> \param stats           integration statistics (updated on exit)
    2038              : !> \param v_shift         shift in Hartree potential
    2039              : !> \param ignore_bias     ignore v_external from negf_control
    2040              : !> \param negf_env        NEGF environment
    2041              : !> \param negf_control    NEGF control
    2042              : !> \param sub_env         NEGF parallel (sub)group environment
    2043              : !> \param ispin           spin conponent to proceed
    2044              : !> \param base_contact    index of the reference contact
    2045              : !> \param integr_lbound   integration lower bound
    2046              : !> \param integr_ubound   integration upper bound
    2047              : !> \param matrix_s_global globally distributed overlap matrix
    2048              : !> \param is_circular     compute the integral along the circular path
    2049              : !> \param g_surf_cache    set of precomputed surface Green's functions (updated on exit)
    2050              : !> \param just_contact    ...
    2051              : !> \author Sergey Chulkov
    2052              : ! **************************************************************************************************
    2053           36 :    SUBROUTINE negf_add_rho_equiv_low(rho_ao_fm, stats, v_shift, ignore_bias, negf_env, negf_control, sub_env, &
    2054              :                                      ispin, base_contact, integr_lbound, integr_ubound, matrix_s_global, &
    2055              :                                      is_circular, g_surf_cache, just_contact)
    2056              :       TYPE(cp_fm_type), INTENT(IN)                       :: rho_ao_fm
    2057              :       TYPE(integration_status_type), INTENT(inout)       :: stats
    2058              :       REAL(kind=dp), INTENT(in)                          :: v_shift
    2059              :       LOGICAL, INTENT(in)                                :: ignore_bias
    2060              :       TYPE(negf_env_type), INTENT(in)                    :: negf_env
    2061              :       TYPE(negf_control_type), POINTER                   :: negf_control
    2062              :       TYPE(negf_subgroup_env_type), INTENT(in)           :: sub_env
    2063              :       INTEGER, INTENT(in)                                :: ispin, base_contact
    2064              :       COMPLEX(kind=dp), INTENT(in)                       :: integr_lbound, integr_ubound
    2065              :       TYPE(cp_fm_type), INTENT(IN)                       :: matrix_s_global
    2066              :       LOGICAL, INTENT(in)                                :: is_circular
    2067              :       TYPE(green_functions_cache_type), INTENT(inout)    :: g_surf_cache
    2068              :       INTEGER, INTENT(in), OPTIONAL                      :: just_contact
    2069              : 
    2070              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'negf_add_rho_equiv_low'
    2071              : 
    2072           36 :       COMPLEX(kind=dp), ALLOCATABLE, DIMENSION(:)        :: xnodes, zscale
    2073              :       INTEGER :: handle, icontact, interval_id, ipoint, max_points, min_points, ncontacts, &
    2074              :          npoints, npoints_exist, npoints_tmp, npoints_total, shape_id
    2075              :       LOGICAL                                            :: do_surface_green
    2076              :       REAL(kind=dp)                                      :: conv_integr, mu_base, temperature, &
    2077              :                                                             v_external
    2078           36 :       TYPE(ccquad_type)                                  :: cc_env
    2079           36 :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:)       :: zdata, zdata_tmp
    2080              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    2081              :       TYPE(cp_fm_type)                                   :: integral_imag
    2082              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2083           36 :       TYPE(simpsonrule_type)                             :: sr_env
    2084              : 
    2085           36 :       CALL timeset(routineN, handle)
    2086              : 
    2087              :       ! convergence criteria for the integral of the retarded Green's function. This integral needs to be
    2088              :       ! computed for both spin-components and needs to be scaled by -1/pi to obtain the electron density.
    2089           36 :       conv_integr = 0.5_dp*negf_control%conv_density*pi
    2090              : 
    2091           36 :       IF (ignore_bias) THEN
    2092           28 :          mu_base = negf_control%contacts(base_contact)%fermi_level
    2093           28 :          v_external = 0.0_dp
    2094              :       ELSE
    2095            8 :          mu_base = negf_control%contacts(base_contact)%fermi_level - negf_control%contacts(base_contact)%v_external
    2096              :       END IF
    2097              : 
    2098           36 :       min_points = negf_control%integr_min_points
    2099           36 :       max_points = negf_control%integr_max_points
    2100           36 :       temperature = negf_control%contacts(base_contact)%temperature
    2101              : 
    2102           36 :       ncontacts = SIZE(negf_env%contacts)
    2103           36 :       CPASSERT(base_contact <= ncontacts)
    2104           36 :       IF (PRESENT(just_contact)) THEN
    2105            8 :          ncontacts = 2
    2106            8 :          CPASSERT(just_contact == base_contact)
    2107              :       END IF
    2108              : 
    2109           36 :       do_surface_green = .NOT. ALLOCATED(g_surf_cache%tnodes)
    2110              : 
    2111           36 :       IF (do_surface_green) THEN
    2112           24 :          npoints = min_points
    2113              :       ELSE
    2114           12 :          npoints = SIZE(g_surf_cache%tnodes)
    2115              :       END IF
    2116           36 :       npoints_total = 0
    2117              : 
    2118           36 :       CALL cp_fm_get_info(rho_ao_fm, para_env=para_env, matrix_struct=fm_struct)
    2119           36 :       CALL cp_fm_create(integral_imag, fm_struct)
    2120              : 
    2121           36 :       SELECT CASE (negf_control%integr_method)
    2122              :       CASE (negfint_method_cc)
    2123              :          ! Adaptive Clenshaw-Curtis method
    2124            0 :          ALLOCATE (xnodes(npoints))
    2125              : 
    2126            0 :          IF (is_circular) THEN
    2127            0 :             shape_id = cc_shape_arc
    2128            0 :             interval_id = cc_interval_full
    2129              :          ELSE
    2130            0 :             shape_id = cc_shape_linear
    2131            0 :             interval_id = cc_interval_half
    2132              :          END IF
    2133              : 
    2134            0 :          IF (do_surface_green) THEN
    2135              :             CALL ccquad_init(cc_env, xnodes, npoints, integr_lbound, integr_ubound, &
    2136            0 :                              interval_id, shape_id, matrix_s_global)
    2137              :          ELSE
    2138              :             CALL ccquad_init(cc_env, xnodes, npoints, integr_lbound, integr_ubound, &
    2139            0 :                              interval_id, shape_id, matrix_s_global, tnodes_restart=g_surf_cache%tnodes)
    2140              :          END IF
    2141              : 
    2142            0 :          ALLOCATE (zdata(npoints))
    2143            0 :          DO ipoint = 1, npoints
    2144            0 :             CALL cp_cfm_create(zdata(ipoint), fm_struct)
    2145              :          END DO
    2146              : 
    2147              :          DO
    2148            0 :             IF (do_surface_green) THEN
    2149            0 :                CALL green_functions_cache_expand(g_surf_cache, ncontacts, npoints)
    2150              : 
    2151            0 :                IF (PRESENT(just_contact)) THEN
    2152              :                   ! do not apply the external potential when computing the Fermi level of a bulk contact.
    2153            0 :                   DO icontact = 1, ncontacts
    2154              :                      CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, npoints_total + 1:), &
    2155              :                                                             omega=xnodes(1:npoints), &
    2156              :                                                             h0=negf_env%contacts(just_contact)%h_00(ispin), &
    2157              :                                                             s0=negf_env%contacts(just_contact)%s_00, &
    2158              :                                                             h1=negf_env%contacts(just_contact)%h_01(ispin), &
    2159              :                                                             s1=negf_env%contacts(just_contact)%s_01, &
    2160              :                                                             sub_env=sub_env, v_external=0.0_dp, &
    2161            0 :                                                             conv=negf_control%conv_green, transp=(icontact == 1))
    2162              :                   END DO
    2163              :                ELSE
    2164            0 :                   DO icontact = 1, ncontacts
    2165            0 :                      IF (.NOT. ignore_bias) v_external = negf_control%contacts(icontact)%v_external
    2166              : 
    2167              :                      CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, npoints_total + 1:), &
    2168              :                                                             omega=xnodes(1:npoints), &
    2169              :                                                             h0=negf_env%contacts(icontact)%h_00(ispin), &
    2170              :                                                             s0=negf_env%contacts(icontact)%s_00, &
    2171              :                                                             h1=negf_env%contacts(icontact)%h_01(ispin), &
    2172              :                                                             s1=negf_env%contacts(icontact)%s_01, &
    2173              :                                                             sub_env=sub_env, &
    2174              :                                                             v_external=v_external, &
    2175            0 :                                                             conv=negf_control%conv_green, transp=.FALSE.)
    2176              :                   END DO
    2177              :                END IF
    2178              :             END IF
    2179              : 
    2180            0 :             ALLOCATE (zscale(npoints))
    2181              : 
    2182            0 :             IF (temperature >= 0.0_dp) THEN
    2183            0 :                DO ipoint = 1, npoints
    2184            0 :                   zscale(ipoint) = fermi_function(xnodes(ipoint) - mu_base, temperature)
    2185              :                END DO
    2186              :             ELSE
    2187            0 :                zscale(:) = z_one
    2188              :             END IF
    2189              : 
    2190              :             CALL negf_retarded_green_function_batch(omega=xnodes(1:npoints), &
    2191              :                                                     v_shift=v_shift, &
    2192              :                                                     ignore_bias=ignore_bias, &
    2193              :                                                     negf_env=negf_env, &
    2194              :                                                     negf_control=negf_control, &
    2195              :                                                     sub_env=sub_env, &
    2196              :                                                     ispin=ispin, &
    2197              :                                                     g_surf_contacts=g_surf_cache%g_surf_contacts(:, npoints_total + 1:), &
    2198              :                                                     g_ret_s=zdata(1:npoints), &
    2199              :                                                     g_ret_scale=zscale(1:npoints), &
    2200            0 :                                                     just_contact=just_contact)
    2201              : 
    2202            0 :             DEALLOCATE (xnodes, zscale)
    2203            0 :             npoints_total = npoints_total + npoints
    2204              : 
    2205            0 :             CALL ccquad_reduce_and_append_zdata(cc_env, zdata)
    2206            0 :             CALL MOVE_ALLOC(zdata, zdata_tmp)
    2207              : 
    2208            0 :             CALL ccquad_refine_integral(cc_env)
    2209              : 
    2210            0 :             IF (cc_env%error <= conv_integr) EXIT
    2211            0 :             IF (2*(npoints_total - 1) + 1 > max_points) EXIT
    2212              : 
    2213              :             ! all cached points have been reused at the first iteration;
    2214              :             ! we need to compute surface Green's function at extra points if the integral has not been converged
    2215            0 :             do_surface_green = .TRUE.
    2216              : 
    2217            0 :             npoints_tmp = npoints
    2218            0 :             CALL ccquad_double_number_of_points(cc_env, xnodes)
    2219            0 :             npoints = SIZE(xnodes)
    2220              : 
    2221            0 :             ALLOCATE (zdata(npoints))
    2222              : 
    2223            0 :             npoints_exist = 0
    2224            0 :             DO ipoint = 1, npoints_tmp
    2225            0 :                IF (ASSOCIATED(zdata_tmp(ipoint)%matrix_struct)) THEN
    2226            0 :                   npoints_exist = npoints_exist + 1
    2227            0 :                   zdata(npoints_exist) = zdata_tmp(ipoint)
    2228              :                END IF
    2229              :             END DO
    2230            0 :             DEALLOCATE (zdata_tmp)
    2231              : 
    2232            0 :             DO ipoint = npoints_exist + 1, npoints
    2233            0 :                CALL cp_cfm_create(zdata(ipoint), fm_struct)
    2234              :             END DO
    2235              :          END DO
    2236              : 
    2237              :          ! the obtained integral will be scaled by -1/pi, so scale the error extimate as well
    2238            0 :          stats%error = stats%error + cc_env%error/pi
    2239              : 
    2240            0 :          DO ipoint = SIZE(zdata_tmp), 1, -1
    2241            0 :             CALL cp_cfm_release(zdata_tmp(ipoint))
    2242              :          END DO
    2243            0 :          DEALLOCATE (zdata_tmp)
    2244              : 
    2245            0 :          CALL cp_cfm_to_fm(cc_env%integral, mtargeti=integral_imag)
    2246              : 
    2247              :          ! keep the cache
    2248            0 :          IF (do_surface_green) THEN
    2249            0 :             CALL green_functions_cache_reorder(g_surf_cache, cc_env%tnodes)
    2250              :          END IF
    2251            0 :          CALL ccquad_release(cc_env)
    2252              : 
    2253              :       CASE (negfint_method_simpson)
    2254              :          ! Adaptive Simpson's rule method
    2255         1676 :          ALLOCATE (xnodes(npoints), zdata(npoints), zscale(npoints))
    2256              : 
    2257           36 :          IF (is_circular) THEN
    2258           18 :             shape_id = sr_shape_arc
    2259              :          ELSE
    2260           18 :             shape_id = sr_shape_linear
    2261              :          END IF
    2262              : 
    2263           36 :          IF (do_surface_green) THEN
    2264              :             CALL simpsonrule_init(sr_env, xnodes, npoints, integr_lbound, integr_ubound, &
    2265           24 :                                   shape_id, conv_integr, matrix_s_global)
    2266              :          ELSE
    2267              :             CALL simpsonrule_init(sr_env, xnodes, npoints, integr_lbound, integr_ubound, &
    2268           12 :                                   shape_id, conv_integr, matrix_s_global, tnodes_restart=g_surf_cache%tnodes)
    2269              :          END IF
    2270              : 
    2271          130 :          DO WHILE (npoints > 0 .AND. npoints_total < max_points)
    2272         2806 :             DO ipoint = 1, npoints
    2273         2806 :                CALL cp_cfm_create(zdata(ipoint), fm_struct)
    2274              :             END DO
    2275              : 
    2276          130 :             IF (do_surface_green) THEN
    2277          118 :                CALL green_functions_cache_expand(g_surf_cache, ncontacts, npoints)
    2278              : 
    2279          118 :                IF (PRESENT(just_contact)) THEN
    2280              :                   ! do not apply the external potential when computing the Fermi level of a bulk contact.
    2281           96 :                   DO icontact = 1, ncontacts
    2282              :                      CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, npoints_total + 1:), &
    2283              :                                                             omega=xnodes(1:npoints), &
    2284              :                                                             h0=negf_env%contacts(just_contact)%h_00(ispin), &
    2285              :                                                             s0=negf_env%contacts(just_contact)%s_00, &
    2286              :                                                             h1=negf_env%contacts(just_contact)%h_01(ispin), &
    2287              :                                                             s1=negf_env%contacts(just_contact)%s_01, &
    2288              :                                                             sub_env=sub_env, v_external=0.0_dp, &
    2289           96 :                                                             conv=negf_control%conv_green, transp=(icontact == 1))
    2290              :                   END DO
    2291              :                ELSE
    2292          258 :                   DO icontact = 1, ncontacts
    2293          172 :                      IF (.NOT. ignore_bias) v_external = negf_control%contacts(icontact)%v_external
    2294              : 
    2295              :                      CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, npoints_total + 1:), &
    2296              :                                                             omega=xnodes(1:npoints), &
    2297              :                                                             h0=negf_env%contacts(icontact)%h_00(ispin), &
    2298              :                                                             s0=negf_env%contacts(icontact)%s_00, &
    2299              :                                                             h1=negf_env%contacts(icontact)%h_01(ispin), &
    2300              :                                                             s1=negf_env%contacts(icontact)%s_01, &
    2301              :                                                             sub_env=sub_env, &
    2302              :                                                             v_external=v_external, &
    2303          258 :                                                             conv=negf_control%conv_green, transp=.FALSE.)
    2304              :                   END DO
    2305              :                END IF
    2306              :             END IF
    2307              : 
    2308          130 :             IF (temperature >= 0.0_dp) THEN
    2309         2806 :                DO ipoint = 1, npoints
    2310         2806 :                   zscale(ipoint) = fermi_function(xnodes(ipoint) - mu_base, temperature)
    2311              :                END DO
    2312              :             ELSE
    2313            0 :                zscale(:) = z_one
    2314              :             END IF
    2315              : 
    2316              :             CALL negf_retarded_green_function_batch(omega=xnodes(1:npoints), &
    2317              :                                                     v_shift=v_shift, &
    2318              :                                                     ignore_bias=ignore_bias, &
    2319              :                                                     negf_env=negf_env, &
    2320              :                                                     negf_control=negf_control, &
    2321              :                                                     sub_env=sub_env, &
    2322              :                                                     ispin=ispin, &
    2323              :                                                     g_surf_contacts=g_surf_cache%g_surf_contacts(:, npoints_total + 1:), &
    2324              :                                                     g_ret_s=zdata(1:npoints), &
    2325              :                                                     g_ret_scale=zscale(1:npoints), &
    2326          130 :                                                     just_contact=just_contact)
    2327              : 
    2328          130 :             npoints_total = npoints_total + npoints
    2329              : 
    2330          130 :             CALL simpsonrule_refine_integral(sr_env, zdata(1:npoints))
    2331              : 
    2332          130 :             IF (sr_env%error <= conv_integr) EXIT
    2333              : 
    2334              :             ! all cached points have been reused at the first iteration;
    2335              :             ! if the integral has not been converged, turn on the 'do_surface_green' flag
    2336              :             ! in order to add more points
    2337           94 :             do_surface_green = .TRUE.
    2338              : 
    2339           94 :             npoints = max_points - npoints_total
    2340           94 :             IF (npoints <= 0) EXIT
    2341           94 :             IF (npoints > SIZE(xnodes)) npoints = SIZE(xnodes)
    2342              : 
    2343          130 :             CALL simpsonrule_get_next_nodes(sr_env, xnodes, npoints)
    2344              :          END DO
    2345              : 
    2346              :          ! the obtained integral will be scaled by -1/pi, so scale the error extimate as well
    2347           36 :          stats%error = stats%error + sr_env%error/pi
    2348              : 
    2349           36 :          CALL cp_cfm_to_fm(sr_env%integral, mtargeti=integral_imag)
    2350              : 
    2351              :          ! keep the cache
    2352           36 :          IF (do_surface_green) THEN
    2353           26 :             CALL green_functions_cache_reorder(g_surf_cache, sr_env%tnodes)
    2354              :          END IF
    2355              : 
    2356           36 :          CALL simpsonrule_release(sr_env)
    2357           36 :          DEALLOCATE (xnodes, zdata, zscale)
    2358              : 
    2359              :       CASE DEFAULT
    2360           36 :          CPABORT("Unimplemented integration method")
    2361              :       END SELECT
    2362              : 
    2363           36 :       stats%npoints = stats%npoints + npoints_total
    2364              : 
    2365           36 :       CALL cp_fm_scale_and_add(1.0_dp, rho_ao_fm, -1.0_dp/pi, integral_imag)
    2366           36 :       CALL cp_fm_release(integral_imag)
    2367              : 
    2368           36 :       CALL timestop(handle)
    2369           72 :    END SUBROUTINE negf_add_rho_equiv_low
    2370              : 
    2371              : ! **************************************************************************************************
    2372              : !> \brief Compute non-equilibrium contribution to the density matrix.
    2373              : !> \param rho_ao_fm       density matrix (initialised on exit)
    2374              : !> \param stats           integration statistics (updated on exit)
    2375              : !> \param v_shift         shift in Hartree potential
    2376              : !> \param negf_env        NEGF environment
    2377              : !> \param negf_control    NEGF control
    2378              : !> \param sub_env         NEGF parallel (sub)group environment
    2379              : !> \param ispin           spin conponent to proceed
    2380              : !> \param base_contact    index of the reference contact
    2381              : !> \param matrix_s_global globally distributed overlap matrix
    2382              : !> \param g_surf_cache    set of precomputed surface Green's functions (updated on exit)
    2383              : !> \author Sergey Chulkov
    2384              : ! **************************************************************************************************
    2385            0 :    SUBROUTINE negf_add_rho_nonequiv(rho_ao_fm, stats, v_shift, negf_env, negf_control, sub_env, &
    2386              :                                     ispin, base_contact, matrix_s_global, g_surf_cache)
    2387              :       TYPE(cp_fm_type), INTENT(IN)                       :: rho_ao_fm
    2388              :       TYPE(integration_status_type), INTENT(inout)       :: stats
    2389              :       REAL(kind=dp), INTENT(in)                          :: v_shift
    2390              :       TYPE(negf_env_type), INTENT(in)                    :: negf_env
    2391              :       TYPE(negf_control_type), POINTER                   :: negf_control
    2392              :       TYPE(negf_subgroup_env_type), INTENT(in)           :: sub_env
    2393              :       INTEGER, INTENT(in)                                :: ispin, base_contact
    2394              :       TYPE(cp_fm_type), INTENT(IN)                       :: matrix_s_global
    2395              :       TYPE(green_functions_cache_type), INTENT(inout)    :: g_surf_cache
    2396              : 
    2397              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'negf_add_rho_nonequiv'
    2398              : 
    2399              :       COMPLEX(kind=dp)                                   :: fermi_base, fermi_contact, &
    2400              :                                                             integr_lbound, integr_ubound
    2401            0 :       COMPLEX(kind=dp), ALLOCATABLE, DIMENSION(:)        :: xnodes
    2402              :       INTEGER                                            :: handle, icontact, ipoint, jcontact, &
    2403              :                                                             max_points, min_points, ncontacts, &
    2404              :                                                             npoints, npoints_total
    2405              :       LOGICAL                                            :: do_surface_green
    2406              :       REAL(kind=dp)                                      :: conv_density, conv_integr, eta, &
    2407              :                                                             ln_conv_density, mu_base, mu_contact, &
    2408              :                                                             temperature_base, temperature_contact
    2409            0 :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:, :)    :: zdata
    2410              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    2411              :       TYPE(cp_fm_type)                                   :: integral_real
    2412              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2413            0 :       TYPE(simpsonrule_type)                             :: sr_env
    2414              : 
    2415            0 :       CALL timeset(routineN, handle)
    2416              : 
    2417            0 :       ncontacts = SIZE(negf_env%contacts)
    2418            0 :       CPASSERT(base_contact <= ncontacts)
    2419              : 
    2420              :       ! the current subroutine works for the general case as well, but the Poisson solver does not
    2421            0 :       IF (ncontacts > 2) THEN
    2422            0 :          CPABORT("Poisson solver does not support the general NEGF setup (>2 contacts).")
    2423              :       END IF
    2424              : 
    2425            0 :       mu_base = negf_control%contacts(base_contact)%fermi_level - negf_control%contacts(base_contact)%v_external
    2426            0 :       min_points = negf_control%integr_min_points
    2427            0 :       max_points = negf_control%integr_max_points
    2428            0 :       temperature_base = negf_control%contacts(base_contact)%temperature
    2429            0 :       eta = negf_control%eta
    2430            0 :       conv_density = negf_control%conv_density
    2431            0 :       ln_conv_density = LOG(conv_density)
    2432              : 
    2433              :       ! convergence criteria for the integral. This integral needs to be computed for both
    2434              :       ! spin-components and needs to be scaled by -1/pi to obtain the electron density.
    2435            0 :       conv_integr = 0.5_dp*conv_density*pi
    2436              : 
    2437            0 :       DO icontact = 1, ncontacts
    2438            0 :          IF (icontact /= base_contact) THEN
    2439            0 :             mu_contact = negf_control%contacts(icontact)%fermi_level - negf_control%contacts(icontact)%v_external
    2440            0 :             temperature_contact = negf_control%contacts(icontact)%temperature
    2441              : 
    2442              :             integr_lbound = CMPLX(MIN(mu_base + ln_conv_density*temperature_base, &
    2443            0 :                                       mu_contact + ln_conv_density*temperature_contact), eta, kind=dp)
    2444              :             integr_ubound = CMPLX(MAX(mu_base - ln_conv_density*temperature_base, &
    2445            0 :                                       mu_contact - ln_conv_density*temperature_contact), eta, kind=dp)
    2446              : 
    2447            0 :             do_surface_green = .NOT. ALLOCATED(g_surf_cache%tnodes)
    2448              : 
    2449            0 :             IF (do_surface_green) THEN
    2450            0 :                npoints = min_points
    2451              :             ELSE
    2452            0 :                npoints = SIZE(g_surf_cache%tnodes)
    2453              :             END IF
    2454            0 :             npoints_total = 0
    2455              : 
    2456            0 :             CALL cp_fm_get_info(rho_ao_fm, para_env=para_env, matrix_struct=fm_struct)
    2457              : 
    2458            0 :             ALLOCATE (xnodes(npoints))
    2459            0 :             ALLOCATE (zdata(ncontacts, npoints))
    2460            0 :             DO ipoint = 1, npoints
    2461            0 :                CALL cp_cfm_create(zdata(base_contact, ipoint), fm_struct)
    2462              :             END DO
    2463              : 
    2464            0 :             IF (do_surface_green) THEN
    2465              :                CALL simpsonrule_init(sr_env, xnodes, npoints, integr_lbound, integr_ubound, &
    2466            0 :                                      sr_shape_linear, conv_integr, matrix_s_global)
    2467              :             ELSE
    2468              :                CALL simpsonrule_init(sr_env, xnodes, npoints, integr_lbound, integr_ubound, &
    2469            0 :                                      sr_shape_linear, conv_integr, matrix_s_global, tnodes_restart=g_surf_cache%tnodes)
    2470              :             END IF
    2471              : 
    2472            0 :             DO WHILE (npoints > 0 .AND. npoints_total < max_points)
    2473            0 :                IF (do_surface_green) THEN
    2474            0 :                   CALL green_functions_cache_expand(g_surf_cache, ncontacts, npoints)
    2475              : 
    2476            0 :                   DO jcontact = 1, ncontacts
    2477              :                      CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(jcontact, npoints_total + 1:), &
    2478              :                                                             omega=xnodes(1:npoints), &
    2479              :                                                             h0=negf_env%contacts(jcontact)%h_00(ispin), &
    2480              :                                                             s0=negf_env%contacts(jcontact)%s_00, &
    2481              :                                                             h1=negf_env%contacts(jcontact)%h_01(ispin), &
    2482              :                                                             s1=negf_env%contacts(jcontact)%s_01, &
    2483              :                                                             sub_env=sub_env, &
    2484              :                                                             v_external=negf_control%contacts(jcontact)%v_external, &
    2485            0 :                                                             conv=negf_control%conv_green, transp=.FALSE.)
    2486              :                   END DO
    2487              :                END IF
    2488            0 :                DO ipoint = 1, npoints
    2489            0 :                   CALL cp_cfm_create(zdata(icontact, ipoint), fm_struct)
    2490              :                END DO
    2491              : 
    2492              :                CALL negf_retarded_green_function_batch(omega=xnodes(1:npoints), &
    2493              :                                                        v_shift=v_shift, &
    2494              :                                                        ignore_bias=.FALSE., &
    2495              :                                                        negf_env=negf_env, &
    2496              :                                                        negf_control=negf_control, &
    2497              :                                                        sub_env=sub_env, &
    2498              :                                                        ispin=ispin, &
    2499              :                                                        g_surf_contacts=g_surf_cache%g_surf_contacts(:, npoints_total + 1:), &
    2500            0 :                                                        gret_gamma_gadv=zdata(:, 1:npoints))
    2501              : 
    2502            0 :                DO ipoint = 1, npoints
    2503              :                   fermi_base = fermi_function(CMPLX(REAL(xnodes(ipoint), kind=dp) - mu_base, 0.0_dp, kind=dp), &
    2504            0 :                                               temperature_base)
    2505              :                   fermi_contact = fermi_function(CMPLX(REAL(xnodes(ipoint), kind=dp) - mu_contact, 0.0_dp, kind=dp), &
    2506            0 :                                                  temperature_contact)
    2507            0 :                   CALL cp_cfm_scale(fermi_contact - fermi_base, zdata(icontact, ipoint))
    2508              :                END DO
    2509              : 
    2510            0 :                npoints_total = npoints_total + npoints
    2511              : 
    2512            0 :                CALL simpsonrule_refine_integral(sr_env, zdata(icontact, 1:npoints))
    2513              : 
    2514            0 :                IF (sr_env%error <= conv_integr) EXIT
    2515              : 
    2516              :                ! not enought cached points to achieve target accuracy
    2517            0 :                do_surface_green = .TRUE.
    2518              : 
    2519            0 :                npoints = max_points - npoints_total
    2520            0 :                IF (npoints <= 0) EXIT
    2521            0 :                IF (npoints > SIZE(xnodes)) npoints = SIZE(xnodes)
    2522              : 
    2523            0 :                CALL simpsonrule_get_next_nodes(sr_env, xnodes, npoints)
    2524              : 
    2525              :             END DO
    2526              : 
    2527            0 :             CALL cp_fm_create(integral_real, fm_struct)
    2528              : 
    2529            0 :             CALL cp_cfm_to_fm(sr_env%integral, mtargetr=integral_real)
    2530            0 :             CALL cp_fm_scale_and_add(1.0_dp, rho_ao_fm, 0.5_dp/pi, integral_real)
    2531              : 
    2532            0 :             CALL cp_fm_release(integral_real)
    2533              : 
    2534            0 :             DO ipoint = 1, npoints
    2535            0 :                CALL cp_cfm_release(zdata(base_contact, ipoint))
    2536              :             END DO
    2537            0 :             DEALLOCATE (xnodes)
    2538            0 :             DEALLOCATE (zdata)
    2539              : 
    2540            0 :             stats%error = stats%error + sr_env%error*0.5_dp/pi
    2541            0 :             stats%npoints = stats%npoints + npoints_total
    2542              : 
    2543              :             ! keep the cache
    2544            0 :             IF (do_surface_green) THEN
    2545            0 :                CALL green_functions_cache_reorder(g_surf_cache, sr_env%tnodes)
    2546              :             END IF
    2547              : 
    2548            0 :             CALL simpsonrule_release(sr_env)
    2549              :          END IF
    2550              :       END DO
    2551              : 
    2552            0 :       CALL timestop(handle)
    2553            0 :    END SUBROUTINE negf_add_rho_nonequiv
    2554              : 
    2555              : ! **************************************************************************************************
    2556              : !> \brief Reset integration statistics.
    2557              : !> \param stats integration statistics
    2558              : !> \author Sergey Chulkov
    2559              : ! **************************************************************************************************
    2560           18 :    ELEMENTAL SUBROUTINE integration_status_reset(stats)
    2561              :       TYPE(integration_status_type), INTENT(out)         :: stats
    2562              : 
    2563           18 :       stats%npoints = 0
    2564           18 :       stats%error = 0.0_dp
    2565           18 :    END SUBROUTINE integration_status_reset
    2566              : 
    2567              : ! **************************************************************************************************
    2568              : !> \brief Generate an integration method description string.
    2569              : !> \param stats              integration statistics
    2570              : !> \param integration_method integration method used
    2571              : !> \return description string
    2572              : !> \author Sergey Chulkov
    2573              : ! **************************************************************************************************
    2574            9 :    ELEMENTAL FUNCTION get_method_description_string(stats, integration_method) RESULT(method_descr)
    2575              :       TYPE(integration_status_type), INTENT(in)          :: stats
    2576              :       INTEGER, INTENT(in)                                :: integration_method
    2577              :       CHARACTER(len=18)                                  :: method_descr
    2578              : 
    2579              :       CHARACTER(len=2)                                   :: method_abbr
    2580              :       CHARACTER(len=6)                                   :: npoints_str
    2581              : 
    2582            9 :       SELECT CASE (integration_method)
    2583              :       CASE (negfint_method_cc)
    2584              :          ! Adaptive Clenshaw-Curtis method
    2585            0 :          method_abbr = "CC"
    2586              :       CASE (negfint_method_simpson)
    2587              :          ! Adaptive Simpson's rule method
    2588            9 :          method_abbr = "SR"
    2589              :       CASE DEFAULT
    2590            9 :          method_abbr = "??"
    2591              :       END SELECT
    2592              : 
    2593            9 :       WRITE (npoints_str, '(I6)') stats%npoints
    2594            9 :       WRITE (method_descr, '(A2,T4,A,T11,ES8.2E2)') method_abbr, TRIM(ADJUSTL(npoints_str)), stats%error
    2595            9 :    END FUNCTION get_method_description_string
    2596              : 
    2597              : ! **************************************************************************************************
    2598              : !> \brief Compute electric current for one spin-channel through the scattering region.
    2599              : !> \param contact_id1       reference contact
    2600              : !> \param contact_id2       another contact
    2601              : !> \param v_shift           shift in Hartree potential
    2602              : !> \param negf_env          NEFG environment
    2603              : !> \param negf_control      NEGF control
    2604              : !> \param sub_env           NEGF parallel (sub)group environment
    2605              : !> \param ispin             spin conponent to proceed
    2606              : !> \param blacs_env_global  global BLACS environment
    2607              : !> \return electric current in Amper
    2608              : !> \author Sergey Chulkov
    2609              : ! **************************************************************************************************
    2610            4 :    FUNCTION negf_compute_current(contact_id1, contact_id2, v_shift, negf_env, negf_control, sub_env, ispin, &
    2611              :                                  blacs_env_global) RESULT(current)
    2612              :       INTEGER, INTENT(in)                                :: contact_id1, contact_id2
    2613              :       REAL(kind=dp), INTENT(in)                          :: v_shift
    2614              :       TYPE(negf_env_type), INTENT(in)                    :: negf_env
    2615              :       TYPE(negf_control_type), POINTER                   :: negf_control
    2616              :       TYPE(negf_subgroup_env_type), INTENT(in)           :: sub_env
    2617              :       INTEGER, INTENT(in)                                :: ispin
    2618              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env_global
    2619              :       REAL(kind=dp)                                      :: current
    2620              : 
    2621              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'negf_compute_current'
    2622              :       REAL(kind=dp), PARAMETER :: threshold = 16.0_dp*EPSILON(0.0_dp)
    2623              : 
    2624              :       COMPLEX(kind=dp)                                   :: fermi_contact1, fermi_contact2, &
    2625              :                                                             integr_lbound, integr_ubound
    2626            4 :       COMPLEX(kind=dp), ALLOCATABLE, DIMENSION(:)        :: transm_coeff, xnodes
    2627              :       COMPLEX(kind=dp), DIMENSION(1, 1)                  :: transmission
    2628              :       INTEGER                                            :: handle, icontact, ipoint, max_points, &
    2629              :                                                             min_points, ncontacts, npoints, &
    2630              :                                                             npoints_total
    2631              :       REAL(kind=dp) :: conv_density, energy, eta, ln_conv_density, mu_contact1, mu_contact2, &
    2632              :          temperature_contact1, temperature_contact2, v_contact1, v_contact2
    2633            4 :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:)       :: zdata
    2634              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_single
    2635              :       TYPE(cp_fm_type)                                   :: weights
    2636            4 :       TYPE(green_functions_cache_type)                   :: g_surf_cache
    2637            4 :       TYPE(simpsonrule_type)                             :: sr_env
    2638              : 
    2639            4 :       current = 0.0_dp
    2640              :       ! nothing to do
    2641            4 :       IF (.NOT. ASSOCIATED(negf_env%s_s)) RETURN
    2642              : 
    2643            4 :       CALL timeset(routineN, handle)
    2644              : 
    2645            4 :       ncontacts = SIZE(negf_env%contacts)
    2646            4 :       CPASSERT(contact_id1 <= ncontacts)
    2647            4 :       CPASSERT(contact_id2 <= ncontacts)
    2648            4 :       CPASSERT(contact_id1 /= contact_id2)
    2649              : 
    2650            4 :       v_contact1 = negf_control%contacts(contact_id1)%v_external
    2651            4 :       mu_contact1 = negf_control%contacts(contact_id1)%fermi_level - v_contact1
    2652            4 :       v_contact2 = negf_control%contacts(contact_id2)%v_external
    2653            4 :       mu_contact2 = negf_control%contacts(contact_id2)%fermi_level - v_contact2
    2654              : 
    2655            4 :       IF (ABS(mu_contact1 - mu_contact2) < threshold) THEN
    2656            4 :          CALL timestop(handle)
    2657            4 :          RETURN
    2658              :       END IF
    2659              : 
    2660            0 :       min_points = negf_control%integr_min_points
    2661            0 :       max_points = negf_control%integr_max_points
    2662            0 :       temperature_contact1 = negf_control%contacts(contact_id1)%temperature
    2663            0 :       temperature_contact2 = negf_control%contacts(contact_id2)%temperature
    2664            0 :       eta = negf_control%eta
    2665            0 :       conv_density = negf_control%conv_density
    2666            0 :       ln_conv_density = LOG(conv_density)
    2667              : 
    2668              :       integr_lbound = CMPLX(MIN(mu_contact1 + ln_conv_density*temperature_contact1, &
    2669            0 :                                 mu_contact2 + ln_conv_density*temperature_contact2), eta, kind=dp)
    2670              :       integr_ubound = CMPLX(MAX(mu_contact1 - ln_conv_density*temperature_contact1, &
    2671            0 :                                 mu_contact2 - ln_conv_density*temperature_contact2), eta, kind=dp)
    2672              : 
    2673            0 :       npoints_total = 0
    2674            0 :       npoints = min_points
    2675              : 
    2676            0 :       NULLIFY (fm_struct_single)
    2677            0 :       CALL cp_fm_struct_create(fm_struct_single, nrow_global=1, ncol_global=1, context=blacs_env_global)
    2678            0 :       CALL cp_fm_create(weights, fm_struct_single)
    2679            0 :       CALL cp_fm_set_all(weights, 1.0_dp)
    2680              : 
    2681            0 :       ALLOCATE (transm_coeff(npoints), xnodes(npoints), zdata(npoints))
    2682              : 
    2683              :       CALL simpsonrule_init(sr_env, xnodes, npoints, integr_lbound, integr_ubound, &
    2684            0 :                             sr_shape_linear, negf_control%conv_density, weights)
    2685              : 
    2686            0 :       DO WHILE (npoints > 0 .AND. npoints_total < max_points)
    2687            0 :          CALL green_functions_cache_expand(g_surf_cache, ncontacts, npoints)
    2688              : 
    2689            0 :          DO icontact = 1, ncontacts
    2690              :             CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, 1:npoints), &
    2691              :                                                    omega=xnodes(1:npoints), &
    2692              :                                                    h0=negf_env%contacts(icontact)%h_00(ispin), &
    2693              :                                                    s0=negf_env%contacts(icontact)%s_00, &
    2694              :                                                    h1=negf_env%contacts(icontact)%h_01(ispin), &
    2695              :                                                    s1=negf_env%contacts(icontact)%s_01, &
    2696              :                                                    sub_env=sub_env, &
    2697              :                                                    v_external=negf_control%contacts(icontact)%v_external, &
    2698            0 :                                                    conv=negf_control%conv_green, transp=.FALSE.)
    2699              :          END DO
    2700              : 
    2701              :          CALL negf_retarded_green_function_batch(omega=xnodes(1:npoints), &
    2702              :                                                  v_shift=v_shift, &
    2703              :                                                  ignore_bias=.FALSE., &
    2704              :                                                  negf_env=negf_env, &
    2705              :                                                  negf_control=negf_control, &
    2706              :                                                  sub_env=sub_env, &
    2707              :                                                  ispin=ispin, &
    2708              :                                                  g_surf_contacts=g_surf_cache%g_surf_contacts(:, 1:npoints), &
    2709              :                                                  transm_coeff=transm_coeff(1:npoints), &
    2710              :                                                  transm_contact1=contact_id1, &
    2711            0 :                                                  transm_contact2=contact_id2)
    2712              : 
    2713            0 :          DO ipoint = 1, npoints
    2714            0 :             CALL cp_cfm_create(zdata(ipoint), fm_struct_single)
    2715              : 
    2716            0 :             energy = REAL(xnodes(ipoint), kind=dp)
    2717            0 :             fermi_contact1 = fermi_function(CMPLX(energy - mu_contact1, 0.0_dp, kind=dp), temperature_contact1)
    2718            0 :             fermi_contact2 = fermi_function(CMPLX(energy - mu_contact2, 0.0_dp, kind=dp), temperature_contact2)
    2719              : 
    2720            0 :             transmission(1, 1) = transm_coeff(ipoint)*(fermi_contact1 - fermi_contact2)
    2721            0 :             CALL cp_cfm_set_submatrix(zdata(ipoint), transmission)
    2722              :          END DO
    2723              : 
    2724            0 :          CALL green_functions_cache_release(g_surf_cache)
    2725              : 
    2726            0 :          npoints_total = npoints_total + npoints
    2727              : 
    2728            0 :          CALL simpsonrule_refine_integral(sr_env, zdata(1:npoints))
    2729              : 
    2730            0 :          IF (sr_env%error <= negf_control%conv_density) EXIT
    2731              : 
    2732            0 :          npoints = max_points - npoints_total
    2733            0 :          IF (npoints <= 0) EXIT
    2734            0 :          IF (npoints > SIZE(xnodes)) npoints = SIZE(xnodes)
    2735              : 
    2736            0 :          CALL simpsonrule_get_next_nodes(sr_env, xnodes, npoints)
    2737              :       END DO
    2738              : 
    2739            0 :       CALL cp_cfm_get_submatrix(sr_env%integral, transmission)
    2740              : 
    2741            0 :       current = -0.5_dp/pi*REAL(transmission(1, 1), kind=dp)*e_charge/seconds
    2742              : 
    2743            0 :       CALL cp_fm_release(weights)
    2744            0 :       CALL cp_fm_struct_release(fm_struct_single)
    2745              : 
    2746            0 :       CALL simpsonrule_release(sr_env)
    2747            0 :       DEALLOCATE (transm_coeff, xnodes, zdata)
    2748              : 
    2749            0 :       CALL timestop(handle)
    2750            8 :    END FUNCTION negf_compute_current
    2751              : 
    2752              : ! **************************************************************************************************
    2753              : !> \brief Print the Density of States.
    2754              : !> \param log_unit     output unit
    2755              : !> \param energy_min   energy point to start with
    2756              : !> \param energy_max   energy point to end with
    2757              : !> \param npoints      number of points to compute
    2758              : !> \param v_shift      shift in Hartree potential
    2759              : !> \param negf_env     NEFG environment
    2760              : !> \param negf_control NEGF control
    2761              : !> \param sub_env      NEGF parallel (sub)group environment
    2762              : !> \param base_contact index of the reference contact
    2763              : !> \param just_contact compute DOS for the given contact rather than for a scattering region
    2764              : !> \param volume       unit cell volume
    2765              : !> \author Sergey Chulkov
    2766              : ! **************************************************************************************************
    2767            4 :    SUBROUTINE negf_print_dos(log_unit, energy_min, energy_max, npoints, v_shift, negf_env, &
    2768              :                              negf_control, sub_env, base_contact, just_contact, volume)
    2769              :       INTEGER, INTENT(in)                                :: log_unit
    2770              :       REAL(kind=dp), INTENT(in)                          :: energy_min, energy_max
    2771              :       INTEGER, INTENT(in)                                :: npoints
    2772              :       REAL(kind=dp), INTENT(in)                          :: v_shift
    2773              :       TYPE(negf_env_type), INTENT(in)                    :: negf_env
    2774              :       TYPE(negf_control_type), POINTER                   :: negf_control
    2775              :       TYPE(negf_subgroup_env_type), INTENT(in)           :: sub_env
    2776              :       INTEGER, INTENT(in)                                :: base_contact
    2777              :       INTEGER, INTENT(in), OPTIONAL                      :: just_contact
    2778              :       REAL(kind=dp), INTENT(in), OPTIONAL                :: volume
    2779              : 
    2780              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'negf_print_dos'
    2781              : 
    2782              :       CHARACTER                                          :: uks_str
    2783              :       CHARACTER(len=15)                                  :: units_str
    2784            4 :       COMPLEX(kind=dp), ALLOCATABLE, DIMENSION(:)        :: xnodes
    2785              :       INTEGER                                            :: handle, icontact, ipoint, ispin, &
    2786              :                                                             ncontacts, npoints_bundle, &
    2787              :                                                             npoints_remain, nspins
    2788            4 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :)        :: dos
    2789            4 :       TYPE(green_functions_cache_type)                   :: g_surf_cache
    2790              : 
    2791            4 :       CALL timeset(routineN, handle)
    2792              : 
    2793            4 :       IF (PRESENT(just_contact)) THEN
    2794            0 :          nspins = SIZE(negf_env%contacts(just_contact)%h_00)
    2795              :       ELSE
    2796            4 :          nspins = SIZE(negf_env%h_s)
    2797              :       END IF
    2798              : 
    2799            4 :       IF (log_unit > 0) THEN
    2800            2 :          IF (PRESENT(volume)) THEN
    2801            0 :             units_str = ' (angstroms^-3)'
    2802              :          ELSE
    2803            2 :             units_str = ''
    2804              :          END IF
    2805              : 
    2806            2 :          IF (nspins > 1) THEN
    2807              :             ! [alpha , beta]
    2808            0 :             uks_str = ','
    2809              :          ELSE
    2810              :             ! [alpha + beta]
    2811            2 :             uks_str = '+'
    2812              :          END IF
    2813              : 
    2814            2 :          IF (PRESENT(just_contact)) THEN
    2815            0 :             WRITE (log_unit, '(3A,T70,I11)') "# Density of states", TRIM(units_str), " for the contact No. ", just_contact
    2816              :          ELSE
    2817            2 :             WRITE (log_unit, '(3A)') "# Density of states", TRIM(units_str), " for the scattering region"
    2818              :          END IF
    2819              : 
    2820            2 :          WRITE (log_unit, '(A,T10,A,T43,3A)') "#", "Energy (a.u.)", "Number of states [alpha ", uks_str, " beta]"
    2821              : 
    2822            2 :          WRITE (log_unit, '("#", T3,78("-"))')
    2823              :       END IF
    2824              : 
    2825            4 :       ncontacts = SIZE(negf_env%contacts)
    2826            4 :       CPASSERT(base_contact <= ncontacts)
    2827            4 :       IF (PRESENT(just_contact)) THEN
    2828            0 :          ncontacts = 2
    2829            0 :          CPASSERT(just_contact == base_contact)
    2830              :       END IF
    2831              :       MARK_USED(base_contact)
    2832              : 
    2833            4 :       npoints_bundle = 4*sub_env%ngroups
    2834            4 :       IF (npoints_bundle > npoints) npoints_bundle = npoints
    2835              : 
    2836           24 :       ALLOCATE (dos(npoints_bundle, nspins), xnodes(npoints_bundle))
    2837              : 
    2838          208 :       npoints_remain = npoints
    2839          208 :       DO WHILE (npoints_remain > 0)
    2840          204 :          IF (npoints_bundle > npoints_remain) npoints_bundle = npoints_remain
    2841              : 
    2842          204 :          IF (npoints > 1) THEN
    2843         1808 :             DO ipoint = 1, npoints_bundle
    2844              :                xnodes(ipoint) = CMPLX(energy_min + REAL(npoints - npoints_remain + ipoint - 1, kind=dp)/ &
    2845         1808 :                                       REAL(npoints - 1, kind=dp)*(energy_max - energy_min), negf_control%eta, kind=dp)
    2846              :             END DO
    2847              :          ELSE
    2848            0 :             xnodes(ipoint) = CMPLX(energy_min, negf_control%eta, kind=dp)
    2849              :          END IF
    2850              : 
    2851          408 :          DO ispin = 1, nspins
    2852          204 :             CALL green_functions_cache_expand(g_surf_cache, ncontacts, npoints_bundle)
    2853              : 
    2854          204 :             IF (PRESENT(just_contact)) THEN
    2855            0 :                DO icontact = 1, ncontacts
    2856              :                   CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, :), &
    2857              :                                                          omega=xnodes(1:npoints_bundle), &
    2858              :                                                          h0=negf_env%contacts(just_contact)%h_00(ispin), &
    2859              :                                                          s0=negf_env%contacts(just_contact)%s_00, &
    2860              :                                                          h1=negf_env%contacts(just_contact)%h_01(ispin), &
    2861              :                                                          s1=negf_env%contacts(just_contact)%s_01, &
    2862              :                                                          sub_env=sub_env, v_external=0.0_dp, &
    2863            0 :                                                          conv=negf_control%conv_green, transp=(icontact == 1))
    2864              :                END DO
    2865              :             ELSE
    2866          612 :                DO icontact = 1, ncontacts
    2867              :                   CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, :), &
    2868              :                                                          omega=xnodes(1:npoints_bundle), &
    2869              :                                                          h0=negf_env%contacts(icontact)%h_00(ispin), &
    2870              :                                                          s0=negf_env%contacts(icontact)%s_00, &
    2871              :                                                          h1=negf_env%contacts(icontact)%h_01(ispin), &
    2872              :                                                          s1=negf_env%contacts(icontact)%s_01, &
    2873              :                                                          sub_env=sub_env, &
    2874              :                                                          v_external=negf_control%contacts(icontact)%v_external, &
    2875          612 :                                                          conv=negf_control%conv_green, transp=.FALSE.)
    2876              :                END DO
    2877              :             END IF
    2878              : 
    2879              :             CALL negf_retarded_green_function_batch(omega=xnodes(1:npoints_bundle), &
    2880              :                                                     v_shift=v_shift, &
    2881              :                                                     ignore_bias=.FALSE., &
    2882              :                                                     negf_env=negf_env, &
    2883              :                                                     negf_control=negf_control, &
    2884              :                                                     sub_env=sub_env, &
    2885              :                                                     ispin=ispin, &
    2886              :                                                     g_surf_contacts=g_surf_cache%g_surf_contacts, &
    2887              :                                                     dos=dos(1:npoints_bundle, ispin), &
    2888          204 :                                                     just_contact=just_contact)
    2889              : 
    2890          408 :             CALL green_functions_cache_release(g_surf_cache)
    2891              :          END DO
    2892              : 
    2893          204 :          IF (log_unit > 0) THEN
    2894          904 :             DO ipoint = 1, npoints_bundle
    2895          904 :                IF (nspins > 1) THEN
    2896              :                   ! spin-polarised calculations: print alpha- and beta-spin components separately
    2897            0 :                   WRITE (log_unit, '(T2,F20.8,T30,2ES25.11E3)') REAL(xnodes(ipoint), kind=dp), dos(ipoint, 1), dos(ipoint, 2)
    2898              :                ELSE
    2899              :                   ! spin-restricted calculations: print alpha- and beta-spin components together
    2900          802 :                   WRITE (log_unit, '(T2,F20.8,T43,ES25.11E3)') REAL(xnodes(ipoint), kind=dp), 2.0_dp*dos(ipoint, 1)
    2901              :                END IF
    2902              :             END DO
    2903              :          END IF
    2904              : 
    2905          204 :          npoints_remain = npoints_remain - npoints_bundle
    2906              :       END DO
    2907              : 
    2908            4 :       DEALLOCATE (dos, xnodes)
    2909            4 :       CALL timestop(handle)
    2910            8 :    END SUBROUTINE negf_print_dos
    2911              : 
    2912              : ! **************************************************************************************************
    2913              : !> \brief Print the transmission coefficient.
    2914              : !> \param log_unit     output unit
    2915              : !> \param energy_min   energy point to start with
    2916              : !> \param energy_max   energy point to end with
    2917              : !> \param npoints      number of points to compute
    2918              : !> \param v_shift      shift in Hartree potential
    2919              : !> \param negf_env     NEFG environment
    2920              : !> \param negf_control NEGF control
    2921              : !> \param sub_env      NEGF parallel (sub)group environment
    2922              : !> \param contact_id1  index of a reference contact
    2923              : !> \param contact_id2  index of another contact
    2924              : !> \author Sergey Chulkov
    2925              : ! **************************************************************************************************
    2926            4 :    SUBROUTINE negf_print_transmission(log_unit, energy_min, energy_max, npoints, v_shift, negf_env, &
    2927              :                                       negf_control, sub_env, contact_id1, contact_id2)
    2928              :       INTEGER, INTENT(in)                                :: log_unit
    2929              :       REAL(kind=dp), INTENT(in)                          :: energy_min, energy_max
    2930              :       INTEGER, INTENT(in)                                :: npoints
    2931              :       REAL(kind=dp), INTENT(in)                          :: v_shift
    2932              :       TYPE(negf_env_type), INTENT(in)                    :: negf_env
    2933              :       TYPE(negf_control_type), POINTER                   :: negf_control
    2934              :       TYPE(negf_subgroup_env_type), INTENT(in)           :: sub_env
    2935              :       INTEGER, INTENT(in)                                :: contact_id1, contact_id2
    2936              : 
    2937              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'negf_print_transmission'
    2938              : 
    2939              :       CHARACTER                                          :: uks_str
    2940            4 :       COMPLEX(kind=dp), ALLOCATABLE, DIMENSION(:)        :: xnodes
    2941            4 :       COMPLEX(kind=dp), ALLOCATABLE, DIMENSION(:, :)     :: transm_coeff
    2942              :       INTEGER                                            :: handle, icontact, ipoint, ispin, &
    2943              :                                                             ncontacts, npoints_bundle, &
    2944              :                                                             npoints_remain, nspins
    2945              :       REAL(kind=dp)                                      :: rscale
    2946            4 :       TYPE(green_functions_cache_type)                   :: g_surf_cache
    2947              : 
    2948            4 :       CALL timeset(routineN, handle)
    2949              : 
    2950            4 :       nspins = SIZE(negf_env%h_s)
    2951              : 
    2952            4 :       IF (nspins > 1) THEN
    2953              :          ! [alpha , beta]
    2954            0 :          uks_str = ','
    2955              :       ELSE
    2956              :          ! [alpha + beta]
    2957            4 :          uks_str = '+'
    2958              :       END IF
    2959              : 
    2960            4 :       IF (log_unit > 0) THEN
    2961            2 :          WRITE (log_unit, '(A)') "# Transmission coefficient (G0 = 2 e^2/h) for the scattering region"
    2962              : 
    2963            2 :          WRITE (log_unit, '(A,T10,A,T39,3A)') "#", "Energy (a.u.)", "Transmission coefficient [alpha ", uks_str, " beta]"
    2964            2 :          WRITE (log_unit, '("#", T3,78("-"))')
    2965              :       END IF
    2966              : 
    2967            4 :       ncontacts = SIZE(negf_env%contacts)
    2968            4 :       CPASSERT(contact_id1 <= ncontacts)
    2969            4 :       CPASSERT(contact_id2 <= ncontacts)
    2970              : 
    2971            4 :       IF (nspins == 1) THEN
    2972              :          rscale = 2.0_dp
    2973              :       ELSE
    2974            0 :          rscale = 1.0_dp
    2975              :       END IF
    2976              : 
    2977              :       ! print transmission coefficients in terms of G0 = 2 * e^2 / h = 1 / pi ;
    2978              :       ! transmission coefficients returned by negf_retarded_green_function_batch() are already multiplied by 2 / pi
    2979            4 :       rscale = 0.5_dp*rscale
    2980              : 
    2981            4 :       npoints_bundle = 4*sub_env%ngroups
    2982            4 :       IF (npoints_bundle > npoints) npoints_bundle = npoints
    2983              : 
    2984           24 :       ALLOCATE (transm_coeff(npoints_bundle, nspins), xnodes(npoints_bundle))
    2985              : 
    2986          208 :       npoints_remain = npoints
    2987          208 :       DO WHILE (npoints_remain > 0)
    2988          204 :          IF (npoints_bundle > npoints_remain) npoints_bundle = npoints_remain
    2989              : 
    2990          204 :          IF (npoints > 1) THEN
    2991         1808 :             DO ipoint = 1, npoints_bundle
    2992              :                xnodes(ipoint) = CMPLX(energy_min + REAL(npoints - npoints_remain + ipoint - 1, kind=dp)/ &
    2993         1808 :                                       REAL(npoints - 1, kind=dp)*(energy_max - energy_min), negf_control%eta, kind=dp)
    2994              :             END DO
    2995              :          ELSE
    2996            0 :             xnodes(ipoint) = CMPLX(energy_min, negf_control%eta, kind=dp)
    2997              :          END IF
    2998              : 
    2999          408 :          DO ispin = 1, nspins
    3000          204 :             CALL green_functions_cache_expand(g_surf_cache, ncontacts, npoints_bundle)
    3001              : 
    3002          612 :             DO icontact = 1, ncontacts
    3003              :                CALL negf_surface_green_function_batch(g_surf=g_surf_cache%g_surf_contacts(icontact, :), &
    3004              :                                                       omega=xnodes(1:npoints_bundle), &
    3005              :                                                       h0=negf_env%contacts(icontact)%h_00(ispin), &
    3006              :                                                       s0=negf_env%contacts(icontact)%s_00, &
    3007              :                                                       h1=negf_env%contacts(icontact)%h_01(ispin), &
    3008              :                                                       s1=negf_env%contacts(icontact)%s_01, &
    3009              :                                                       sub_env=sub_env, &
    3010              :                                                       v_external=negf_control%contacts(icontact)%v_external, &
    3011          612 :                                                       conv=negf_control%conv_green, transp=.FALSE.)
    3012              :             END DO
    3013              : 
    3014              :             CALL negf_retarded_green_function_batch(omega=xnodes(1:npoints_bundle), &
    3015              :                                                     v_shift=v_shift, &
    3016              :                                                     ignore_bias=.FALSE., &
    3017              :                                                     negf_env=negf_env, &
    3018              :                                                     negf_control=negf_control, &
    3019              :                                                     sub_env=sub_env, &
    3020              :                                                     ispin=ispin, &
    3021              :                                                     g_surf_contacts=g_surf_cache%g_surf_contacts, &
    3022              :                                                     transm_coeff=transm_coeff(1:npoints_bundle, ispin), &
    3023              :                                                     transm_contact1=contact_id1, &
    3024          204 :                                                     transm_contact2=contact_id2)
    3025              : 
    3026          408 :             CALL green_functions_cache_release(g_surf_cache)
    3027              :          END DO
    3028              : 
    3029          204 :          IF (log_unit > 0) THEN
    3030          904 :             DO ipoint = 1, npoints_bundle
    3031          904 :                IF (nspins > 1) THEN
    3032              :                   ! spin-polarised calculations: print alpha- and beta-spin components separately
    3033              :                   WRITE (log_unit, '(T2,F20.8,T30,2ES25.11E3)') &
    3034            0 :                      REAL(xnodes(ipoint), kind=dp), rscale*REAL(transm_coeff(ipoint, 1:2), kind=dp)
    3035              :                ELSE
    3036              :                   ! spin-restricted calculations: print alpha- and beta-spin components together
    3037              :                   WRITE (log_unit, '(T2,F20.8,T43,ES25.11E3)') &
    3038          802 :                      REAL(xnodes(ipoint), kind=dp), rscale*REAL(transm_coeff(ipoint, 1), kind=dp)
    3039              :                END IF
    3040              :             END DO
    3041              :          END IF
    3042              : 
    3043          204 :          npoints_remain = npoints_remain - npoints_bundle
    3044              :       END DO
    3045              : 
    3046            4 :       DEALLOCATE (transm_coeff, xnodes)
    3047            4 :       CALL timestop(handle)
    3048            8 :    END SUBROUTINE negf_print_transmission
    3049              : 
    3050              : ! **************************************************************************************************
    3051              : !> \brief Print the initial info and Hamiltonian / overlap matrices.
    3052              : !> \param log_unit ...
    3053              : !> \param negf_env ...
    3054              : !> \param sub_env ...
    3055              : !> \param negf_control ...
    3056              : !> \param dft_control ...
    3057              : !> \param verbose_output ...
    3058              : !> \param debug_output ...
    3059              : !> \par History
    3060              : !>    * 11.2025 created [Dmitry Ryndyk]
    3061              : ! **************************************************************************************************
    3062            4 :    SUBROUTINE negf_output_initial(log_unit, negf_env, sub_env, negf_control, dft_control, verbose_output, &
    3063              :                                   debug_output)
    3064              :       INTEGER, INTENT(in)                                :: log_unit
    3065              :       TYPE(negf_env_type), INTENT(in)                    :: negf_env
    3066              :       TYPE(negf_subgroup_env_type), INTENT(in)           :: sub_env
    3067              :       TYPE(negf_control_type), POINTER                   :: negf_control
    3068              :       TYPE(dft_control_type), POINTER                    :: dft_control
    3069              :       LOGICAL, INTENT(in)                                :: verbose_output, debug_output
    3070              : 
    3071              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'negf_output_initial'
    3072              : 
    3073              :       CHARACTER(len=100)                                 :: sfmt
    3074              :       INTEGER                                            :: handle, i, icontact, j, k, n, nrow
    3075            4 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: target_m
    3076              : 
    3077            4 :       CALL timeset(routineN, handle)
    3078              : 
    3079              :       ! Electrodes
    3080           12 :       DO icontact = 1, SIZE(negf_control%contacts)
    3081            8 :          IF (log_unit > 0) THEN
    3082            4 :             WRITE (log_unit, "(/,' The electrode',I5)") icontact
    3083            4 :             WRITE (log_unit, "(  ' ------------------')")
    3084            4 :             WRITE (log_unit, "(' From the force environment:',I16)") negf_control%contacts(icontact)%force_env_index
    3085            4 :             WRITE (log_unit, "(' Number of atoms:',I27)") SIZE(negf_control%contacts(icontact)%atomlist_bulk)
    3086            4 :             IF (verbose_output) WRITE (log_unit, "(' Atoms belonging to a contact (from the entire system):')")
    3087           36 :             IF (verbose_output) WRITE (log_unit, "(16I5)") negf_control%contacts(icontact)%atomlist_bulk
    3088              :             WRITE (log_unit, "(' Number of atoms in a primary unit cell:',I4)") &
    3089            4 :                SIZE(negf_env%contacts(icontact)%atomlist_cell0)
    3090              :          END IF
    3091            8 :          IF (log_unit > 0 .AND. verbose_output) THEN
    3092            4 :             WRITE (log_unit, "(' Atoms belonging to a primary unit cell (from the entire system):')")
    3093           20 :             WRITE (log_unit, "(16I5)") negf_env%contacts(icontact)%atomlist_cell0
    3094            4 :             WRITE (log_unit, "(' Direction of an electrode: ',I16)") negf_env%contacts(icontact)%direction_axis
    3095              :          END IF
    3096              :          ! print the electrode Hamiltonians for check and debuging
    3097           12 :          IF (debug_output) THEN
    3098            8 :             CALL cp_fm_get_info(negf_env%contacts(icontact)%s_00, nrow_global=nrow)
    3099           32 :             ALLOCATE (target_m(nrow, nrow))
    3100            8 :             IF (log_unit > 0) WRITE (log_unit, "(' The number of atomic orbitals:',I13)") nrow
    3101           16 :             DO k = 1, dft_control%nspins
    3102            8 :                CALL cp_fm_get_submatrix(negf_env%contacts(icontact)%h_00(k), target_m)
    3103            8 :                IF (log_unit > 0) THEN
    3104            4 :                   WRITE (sfmt, "('(',i0,'(E15.5))')") nrow
    3105            4 :                   WRITE (log_unit, "(' The H_00 electrode Hamiltonian for spin',I2)") k
    3106           20 :                   DO i = 1, nrow
    3107           20 :                      WRITE (log_unit, sfmt) (target_m(i, j), j=1, nrow)
    3108              :                   END DO
    3109              :                END IF
    3110            8 :                CALL cp_fm_get_submatrix(negf_env%contacts(icontact)%h_01(k), target_m)
    3111           16 :                IF (log_unit > 0) THEN
    3112            4 :                   WRITE (log_unit, "(' The H_01 electrode Hamiltonian for spin',I2)") k
    3113           20 :                   DO i = 1, nrow
    3114           20 :                      WRITE (log_unit, sfmt) (target_m(i, j), j=1, nrow)
    3115              :                   END DO
    3116              :                END IF
    3117              :             END DO
    3118            8 :             CALL cp_fm_get_submatrix(negf_env%contacts(icontact)%s_00, target_m)
    3119            8 :             IF (log_unit > 0) THEN
    3120            4 :                WRITE (log_unit, "(' The S_00 overlap matrix')")
    3121           20 :                DO i = 1, nrow
    3122           20 :                   WRITE (log_unit, sfmt) (target_m(i, j), j=1, nrow)
    3123              :                END DO
    3124              :             END IF
    3125            8 :             CALL cp_fm_get_submatrix(negf_env%contacts(icontact)%s_01, target_m)
    3126            8 :             IF (log_unit > 0) THEN
    3127            4 :                WRITE (log_unit, "(' The S_01 overlap matrix')")
    3128           20 :                DO i = 1, nrow
    3129           20 :                   WRITE (log_unit, sfmt) (target_m(i, j), j=1, nrow)
    3130              :                END DO
    3131              :             END IF
    3132           16 :             DEALLOCATE (target_m)
    3133              :          END IF
    3134              :       END DO
    3135              : 
    3136              :       ! Scattering region and contacts
    3137            4 :       IF (log_unit > 0) THEN
    3138            2 :          WRITE (log_unit, "(/,' The full scattering region')")
    3139            2 :          WRITE (log_unit, "(  ' --------------------------')")
    3140            2 :          WRITE (log_unit, "(' Number of atoms:',I27)") SIZE(negf_control%atomlist_S_screening)
    3141            2 :          IF (verbose_output) WRITE (log_unit, "(' Atoms belonging to a full scattering region:')")
    3142            2 :          IF (verbose_output) WRITE (log_unit, "(16I5)") negf_control%atomlist_S_screening
    3143              :       END IF
    3144              :       ! print the full scattering region Hamiltonians for check and debuging
    3145            4 :       IF (debug_output) THEN
    3146            4 :          CALL cp_fm_get_info(negf_env%s_s, nrow_global=n)
    3147           16 :          ALLOCATE (target_m(n, n))
    3148            4 :          WRITE (sfmt, "('(',i0,'(E15.5))')") n
    3149            4 :          IF (log_unit > 0) WRITE (log_unit, "(' The number of atomic orbitals:',I14)") n
    3150            8 :          DO k = 1, dft_control%nspins
    3151            4 :             IF (log_unit > 0) WRITE (log_unit, "(' The H_s Hamiltonian for spin',I2)") k
    3152            4 :             CALL cp_fm_get_submatrix(negf_env%h_s(k), target_m)
    3153           56 :             DO i = 1, n
    3154           52 :                IF (log_unit > 0) WRITE (log_unit, sfmt) (target_m(i, j), j=1, n)
    3155              :             END DO
    3156              :          END DO
    3157            4 :          IF (log_unit > 0) WRITE (log_unit, "(' The S_s overlap matrix')")
    3158            4 :          CALL cp_fm_get_submatrix(negf_env%s_s, target_m)
    3159           52 :          DO i = 1, n
    3160           52 :             IF (log_unit > 0) WRITE (log_unit, sfmt) (target_m(i, j), j=1, n)
    3161              :          END DO
    3162            4 :          DEALLOCATE (target_m)
    3163            4 :          IF (log_unit > 0) WRITE (log_unit, "(/,' Scattering region - electrode contacts')")
    3164            4 :          IF (log_unit > 0) WRITE (log_unit, "(  ' ---------------------------------------')")
    3165           16 :          ALLOCATE (target_m(n, nrow))
    3166           12 :          DO icontact = 1, SIZE(negf_control%contacts)
    3167            8 :             IF (log_unit > 0) WRITE (log_unit, "(/,' The contact',I5)") icontact
    3168            8 :             IF (log_unit > 0) WRITE (log_unit, "(  ' ----------------')")
    3169           16 :             DO k = 1, dft_control%nspins
    3170            8 :                CALL cp_fm_get_submatrix(negf_env%h_sc(k, icontact), target_m)
    3171           16 :                IF (log_unit > 0) THEN
    3172            4 :                   WRITE (log_unit, "(' The H_sc Hamiltonian for spin',I2)") k
    3173           52 :                   DO i = 1, n
    3174           52 :                      WRITE (log_unit, sfmt) (target_m(i, j), j=1, nrow)
    3175              :                   END DO
    3176              :                END IF
    3177              :             END DO
    3178            8 :             CALL cp_fm_get_submatrix(negf_env%s_sc(icontact), target_m)
    3179           12 :             IF (log_unit > 0) THEN
    3180            4 :                WRITE (log_unit, "(' The S_sc overlap matrix')")
    3181           52 :                DO i = 1, n
    3182           52 :                   WRITE (log_unit, sfmt) (target_m(i, j), j=1, nrow)
    3183              :                END DO
    3184              :             END IF
    3185              :          END DO
    3186            8 :          DEALLOCATE (target_m)
    3187              :       END IF
    3188              : 
    3189            4 :       IF (log_unit > 0) THEN
    3190            2 :          WRITE (log_unit, "(/,' NEGF| Number of MPI processes:                     ',I5)") sub_env%mpi_comm_global%num_pe
    3191            2 :          WRITE (log_unit, "(' NEGF| Maximal number of processes per energy point:',I5)") negf_control%nprocs
    3192            2 :          WRITE (log_unit, "(' NEGF| Number of parallel MPI (energy) groups:      ',I5)") sub_env%ngroups
    3193              :       END IF
    3194              : 
    3195            4 :       CALL timestop(handle)
    3196            4 :    END SUBROUTINE negf_output_initial
    3197              : 
    3198            0 : END MODULE negf_methods
        

Generated by: LCOV version 2.0-1