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

Generated by: LCOV version 2.0-1