LCOV - code coverage report
Current view: top level - src - negf_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:24d69ee) Lines: 78.9 % 1501 1184
Test Date: 2026-09-03 07:32:15 Functions: 84.2 % 19 16

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

Generated by: LCOV version 2.0-1