LCOV - code coverage report
Current view: top level - src - smeagol_interface.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 107 241 44.4 %
Date: 2024-12-21 06:28:57 Functions: 2 6 33.3 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief CP2K+SMEAGOL interface.
      10             : !> \author Sergey Chulkov
      11             : !> \author Christian Ahart
      12             : !> \author Clotilde Cucinotta
      13             : ! **************************************************************************************************
      14             : MODULE smeagol_interface
      15             :    USE bibliography, ONLY: Ahart2024, &
      16             :                            Bailey2006, &
      17             :                            cite_reference
      18             :    USE cell_types, ONLY: cell_type, &
      19             :                          real_to_scaled, &
      20             :                          scaled_to_real
      21             :    USE cp_control_types, ONLY: dft_control_type
      22             :    USE cp_dbcsr_operations, ONLY: dbcsr_allocate_matrix_set
      23             :    USE cp_files, ONLY: close_file, &
      24             :                        open_file
      25             :    USE cp_log_handling, ONLY: cp_get_default_logger, &
      26             :                               cp_logger_get_default_io_unit, &
      27             :                               cp_logger_type
      28             :    USE cp_output_handling, ONLY: cp_get_iter_level_by_name, &
      29             :                                  cp_get_iter_nr
      30             :    USE cp_dbcsr_api, ONLY: dbcsr_copy, &
      31             :                            dbcsr_p_type, &
      32             :                            dbcsr_set
      33             :    USE input_constants, ONLY: smeagol_bulklead_left, &
      34             :                               smeagol_bulklead_leftright, &
      35             :                               smeagol_bulklead_right, &
      36             :                               smeagol_runtype_bulktransport, &
      37             :                               smeagol_runtype_emtransport
      38             :    USE kahan_sum, ONLY: accurate_dot_product, &
      39             :                         accurate_sum
      40             :    USE kinds, ONLY: dp, &
      41             :                     int_8
      42             :    USE kpoint_types, ONLY: get_kpoint_info, &
      43             :                            kpoint_type
      44             :    USE message_passing, ONLY: mp_para_env_type
      45             : #if defined(__SMEAGOL)
      46             :    USE mmpi_negf, ONLY: create_communicators_negf, &
      47             :                         destroy_communicators_negf
      48             :    USE mnegf_interface, ONLY: negf_interface
      49             :    USE negfmod, ONLY: smeagolglobal_em_nas => em_nas, &
      50             :                       smeagolglobal_em_nau => em_nau, &
      51             :                       smeagolglobal_em_nso => em_nso, &
      52             :                       smeagolglobal_em_nuo => em_nuo, &
      53             :                       smeagolglobal_negfon => negfon
      54             : #endif
      55             :    USE physcon, ONLY: bohr, &
      56             :                       evolt
      57             :    USE pw_grid_types, ONLY: pw_grid_type
      58             :    USE pw_types, ONLY: pw_r3d_rs_type
      59             :    USE qs_matrix_w, ONLY: compute_matrix_w
      60             :    USE qs_energy_types, ONLY: qs_energy_type
      61             :    USE qs_environment_types, ONLY: get_qs_env, &
      62             :                                    qs_environment_type
      63             :    USE qs_ks_types, ONLY: qs_ks_env_type, &
      64             :                           set_ks_env
      65             :    USE qs_neighbor_list_types, ONLY: neighbor_list_set_p_type
      66             :    USE qs_rho_types, ONLY: qs_rho_get, &
      67             :                            qs_rho_type
      68             :    USE qs_subsys_types, ONLY: qs_subsys_get, &
      69             :                               qs_subsys_type
      70             :    USE scf_control_types, ONLY: scf_control_type
      71             :    USE smeagol_control_types, ONLY: smeagol_control_type
      72             :    USE smeagol_emtoptions, ONLY: ReadOptionsNEGF_DFT, &
      73             :                                  emtrans_deallocate_global_arrays, &
      74             :                                  emtrans_options, &
      75             :                                  reademtr
      76             :    USE smeagol_matrix_utils, ONLY: convert_dbcsr_to_distributed_siesta, &
      77             :                                    convert_distributed_siesta_to_dbcsr, &
      78             :                                    siesta_distrib_csc_struct_type, &
      79             :                                    siesta_struct_create, &
      80             :                                    siesta_struct_release
      81             : #include "./base/base_uses.f90"
      82             : 
      83             :    IMPLICIT NONE
      84             :    PRIVATE
      85             : 
      86             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'smeagol_interface'
      87             : 
      88             :    PUBLIC :: run_smeagol_bulktrans, run_smeagol_emtrans
      89             :    PUBLIC :: smeagol_shift_v_hartree
      90             : 
      91             : CONTAINS
      92             : 
      93             : ! **************************************************************************************************
      94             : !> \brief Save overlap, Kohn-Sham, electron density, and energy-density matrices of semi-infinite
      95             : !>        electrodes in SIESTA format.
      96             : !> \param qs_env  QuickStep environment
      97             : ! **************************************************************************************************
      98       16977 :    SUBROUTINE run_smeagol_bulktrans(qs_env)
      99             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     100             : 
     101             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'run_smeagol_bulktrans'
     102             : 
     103             :       CHARACTER(len=32)                                  :: hst_fmt
     104             :       INTEGER                                            :: funit, handle, img, ispin, lead_label, &
     105             :                                                             log_unit, nimages, nspin
     106             :       INTEGER(kind=int_8)                                :: ielem
     107             :       INTEGER, DIMENSION(2)                              :: max_ij_cell_image
     108       16977 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
     109             :       LOGICAL                                            :: do_kpoints, has_unit_metric, not_regtest
     110             :       REAL(kind=dp)                                      :: H_to_Ry
     111       16977 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:)           :: matrix_siesta_1d, nelectrons
     112       16977 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :)        :: matrix_siesta_2d
     113       16977 :       TYPE(dbcsr_p_type), ALLOCATABLE, DIMENSION(:)      :: matrix_kp_generic
     114       16977 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks_kp, matrix_s_kp, matrix_w_kp, &
     115       16977 :                                                             rho_ao_kp
     116             :       TYPE(dft_control_type), POINTER                    :: dft_control
     117             :       TYPE(kpoint_type), POINTER                         :: kpoints
     118             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     119             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     120       16977 :          POINTER                                         :: sab_nl
     121             :       TYPE(pw_r3d_rs_type), POINTER                      :: v_hartree_rspace
     122             :       TYPE(qs_energy_type), POINTER                      :: energy
     123             :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     124             :       TYPE(qs_rho_type), POINTER                         :: rho
     125             :       TYPE(qs_subsys_type), POINTER                      :: subsys
     126             :       TYPE(scf_control_type), POINTER                    :: scf_control
     127       16977 :       TYPE(siesta_distrib_csc_struct_type)               :: siesta_struct
     128             :       TYPE(smeagol_control_type), POINTER                :: smeagol_control
     129             : 
     130       16977 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     131       16977 :       smeagol_control => dft_control%smeagol_control
     132       16977 :       IF (.NOT. (smeagol_control%smeagol_enabled .AND. smeagol_control%run_type == smeagol_runtype_bulktransport)) RETURN
     133             : 
     134           2 :       CALL timeset(routineN, handle)
     135             : 
     136           2 :       log_unit = cp_logger_get_default_io_unit()
     137           2 :       H_to_Ry = smeagol_control%to_smeagol_energy_units
     138           2 :       not_regtest = .NOT. smeagol_control%do_regtest
     139             : 
     140           2 :       lead_label = smeagol_control%lead_label
     141           2 :       nspin = dft_control%nspins
     142             : 
     143           2 :       NULLIFY (v_hartree_rspace)
     144             :       CALL get_qs_env(qs_env, energy=energy, para_env=para_env, subsys=subsys, &
     145             :                       scf_control=scf_control, &
     146             :                       do_kpoints=do_kpoints, kpoints=kpoints, &
     147             :                       matrix_ks_kp=matrix_ks_kp, matrix_s_kp=matrix_s_kp, &
     148           2 :                       rho=rho, sab_orb=sab_nl, v_hartree_rspace=v_hartree_rspace)
     149           2 :       CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
     150             : 
     151           2 :       IF (not_regtest) THEN
     152             :          ! save average electrostatic potential of the electrode along transport direction
     153           0 :          CALL write_average_hartree_potential(v_hartree_rspace, smeagol_control%project_name)
     154             :       END IF
     155             : 
     156           2 :       IF (log_unit > 0) THEN
     157           1 :          WRITE (log_unit, '(/,T2,A,T61,ES20.10E2)') "SMEAGOL| E_FERMI [a.u.] = ", energy%efermi
     158             :       END IF
     159             : 
     160           2 :       IF (do_kpoints) THEN
     161           2 :          nimages = dft_control%nimages
     162           2 :          CALL get_kpoint_info(kpoints, cell_to_index=cell_to_index)
     163             :       ELSE
     164           0 :          nimages = 1
     165           0 :          ALLOCATE (cell_to_index(0:0, 0:0, 0:0))
     166           0 :          cell_to_index(0, 0, 0) = 1
     167             :          ! We do need at least two cell images along transport direction.
     168           0 :          CPABORT("Please enable k-points")
     169             :       END IF
     170             : 
     171             :       ! largest index of cell images along i and j cell vectors
     172             :       ! e.g., (2,0) in case of 5 cell images (0,0), (1,0), (-1,0), (2,0), and (-2,0)
     173             :       ! -1 means to use all available cell images along a particular cell vector.
     174           6 :       max_ij_cell_image(:) = -1
     175           6 :       DO img = 1, 2
     176           6 :          IF (smeagol_control%n_cell_images(img) > 0) THEN
     177           0 :             max_ij_cell_image(img) = smeagol_control%n_cell_images(img)/2
     178             :          END IF
     179             :       END DO
     180             : 
     181         144 :       ALLOCATE (matrix_kp_generic(nimages))
     182             : 
     183             :       ! compute energy-density (W) matrix. We may need it later to calculate NEGF forces
     184           2 :       CALL get_qs_env(qs_env, has_unit_metric=has_unit_metric)
     185           2 :       IF (.NOT. has_unit_metric) THEN
     186           2 :          CALL get_qs_env(qs_env, matrix_w_kp=matrix_w_kp)
     187           2 :          IF (.NOT. ASSOCIATED(matrix_w_kp)) THEN
     188           2 :             NULLIFY (matrix_w_kp)
     189           2 :             CALL get_qs_env(qs_env, ks_env=ks_env)
     190           2 :             CALL dbcsr_allocate_matrix_set(matrix_w_kp, nspin, nimages)
     191           4 :             DO ispin = 1, nspin
     192         142 :                DO img = 1, nimages
     193         138 :                   ALLOCATE (matrix_w_kp(ispin, img)%matrix)
     194         138 :                   CALL dbcsr_copy(matrix_w_kp(ispin, img)%matrix, matrix_s_kp(1, 1)%matrix, name="W MATRIX")
     195         140 :                   CALL dbcsr_set(matrix_w_kp(ispin, img)%matrix, 0.0_dp)
     196             :                END DO
     197             :             END DO
     198           2 :             CALL set_ks_env(ks_env, matrix_w_kp=matrix_w_kp)
     199             :          END IF
     200             :       END IF
     201           2 :       CALL compute_matrix_w(qs_env, calc_forces=.TRUE.)
     202             : 
     203             :       ! obtain the sparsity pattern of the overlap matrix
     204         140 :       DO img = 1, nimages
     205         140 :          matrix_kp_generic(img)%matrix => matrix_s_kp(1, img)%matrix
     206             :       END DO
     207             : 
     208             :       CALL siesta_struct_create(siesta_struct, matrix_kp_generic, subsys, cell_to_index, &
     209           2 :                                 sab_nl, para_env, max_ij_cell_image, do_merge=.FALSE., gather_root=para_env%source)
     210             : 
     211             :       ! write 'bulklft.DAT' and 'bulkrgt.DAT' files
     212           2 :       funit = -1
     213           2 :       IF (not_regtest .AND. para_env%mepos == para_env%source) THEN
     214             :          ! I/O process
     215           0 :          IF (lead_label == smeagol_bulklead_left .OR. lead_label == smeagol_bulklead_leftright) THEN
     216           0 :             CALL open_file("bulklft.DAT", file_status="REPLACE", file_form="FORMATTED", file_action="WRITE", unit_number=funit)
     217             : 
     218             :             CALL write_bulk_dat_file(funit, siesta_struct, smeagol_control%project_name, nspin, &
     219             :                                      energy%efermi, scf_control%smear%ELECTRONIC_TEMPERATURE, &
     220           0 :                                      H_to_Ry, do_kpoints, max_ij_cell_image)
     221             : 
     222           0 :             CALL close_file(funit)
     223             :          END IF
     224             : 
     225           0 :          IF (lead_label == smeagol_bulklead_right .OR. lead_label == smeagol_bulklead_leftright) THEN
     226           0 :             CALL open_file("bulkrgt.DAT", file_status="REPLACE", file_form="FORMATTED", file_action="WRITE", unit_number=funit)
     227             : 
     228             :             CALL write_bulk_dat_file(funit, siesta_struct, smeagol_control%project_name, nspin, &
     229             :                                      energy%efermi, scf_control%smear%ELECTRONIC_TEMPERATURE, &
     230           0 :                                      H_to_Ry, do_kpoints, max_ij_cell_image)
     231             : 
     232           0 :             CALL close_file(funit)
     233             :          END IF
     234             :       END IF
     235             : 
     236             :       ! write project_name.HST file
     237           2 :       funit = -1
     238           2 :       IF (para_env%mepos == para_env%source) THEN
     239           3 :          ALLOCATE (matrix_siesta_1d(siesta_struct%n_nonzero_elements))
     240           4 :          ALLOCATE (matrix_siesta_2d(siesta_struct%n_nonzero_elements, nspin))
     241             : 
     242           1 :          IF (not_regtest) THEN
     243             :             CALL open_file(TRIM(smeagol_control%project_name)//".HST", &
     244           0 :                            file_status="REPLACE", file_form="FORMATTED", file_action="WRITE", unit_number=funit)
     245             :          END IF
     246             :       ELSE
     247           1 :          ALLOCATE (matrix_siesta_1d(1))
     248           3 :          ALLOCATE (matrix_siesta_2d(1, nspin))
     249             :       END IF
     250             : 
     251             :       !DO img = 1, nimages
     252             :       !   matrix_kp_generic(img)%matrix => matrix_s_kp(1, img)%matrix
     253             :       !END DO
     254           2 :       CALL convert_dbcsr_to_distributed_siesta(matrix_siesta_1d, matrix_kp_generic, siesta_struct, para_env)
     255             : 
     256           4 :       DO ispin = 1, nspin
     257         140 :          DO img = 1, nimages
     258         140 :             matrix_kp_generic(img)%matrix => matrix_ks_kp(ispin, img)%matrix
     259             :          END DO
     260           4 :          CALL convert_dbcsr_to_distributed_siesta(matrix_siesta_2d(:, ispin), matrix_kp_generic, siesta_struct, para_env)
     261             :       END DO
     262             :       ! As SIESTA's default energy unit is Rydberg, scale the KS-matrix
     263     1091237 :       matrix_siesta_2d(:, :) = H_to_Ry*matrix_siesta_2d(:, :)
     264             : 
     265           2 :       IF (funit > 0) THEN ! not_regtest .AND. para_env%mepos == para_env%source
     266           0 :          WRITE (hst_fmt, '(A,I0,A)') "(", nspin, "ES26.17E3)"
     267           0 :          DO ielem = 1, siesta_struct%n_nonzero_elements
     268           0 :             WRITE (funit, '(ES26.17E3)') matrix_siesta_1d(ielem)
     269           0 :             WRITE (funit, hst_fmt) matrix_siesta_2d(ielem, :)
     270             :          END DO
     271             : 
     272           0 :          CALL close_file(funit)
     273             :       END IF
     274             : 
     275             :       ! write density matrix
     276           4 :       DO ispin = 1, nspin
     277         140 :          DO img = 1, nimages
     278         140 :             matrix_kp_generic(img)%matrix => rho_ao_kp(ispin, img)%matrix
     279             :          END DO
     280           4 :          CALL convert_dbcsr_to_distributed_siesta(matrix_siesta_2d(:, ispin), matrix_kp_generic, siesta_struct, para_env)
     281             :       END DO
     282             : 
     283           2 :       IF (para_env%mepos == para_env%source) THEN
     284           3 :          ALLOCATE (nelectrons(nspin))
     285           2 :          DO ispin = 1, nspin
     286           2 :             nelectrons(ispin) = accurate_dot_product(matrix_siesta_2d(:, ispin), matrix_siesta_1d)
     287             :          END DO
     288             : 
     289           1 :          CPASSERT(log_unit > 0)
     290           1 :          IF (nspin > 1) THEN
     291           0 :             WRITE (log_unit, '(T2,A,T61,F20.10)') "SMEAGOL| Number of alpha-spin electrons: ", nelectrons(1)
     292           0 :             WRITE (log_unit, '(T2,A,T61,F20.10)') "SMEAGOL| Number of  beta-spin electrons: ", nelectrons(2)
     293             :          ELSE
     294           1 :             WRITE (log_unit, '(T2,A,T61,F20.10)') "SMEAGOL| Number of electrons: ", nelectrons(1)
     295             :          END IF
     296           1 :          DEALLOCATE (nelectrons)
     297             : 
     298           1 :          IF (not_regtest) THEN
     299             :             CALL open_file(TRIM(smeagol_control%project_name)//".DM", &
     300           0 :                            file_status="REPLACE", file_form="UNFORMATTED", file_action="WRITE", unit_number=funit)
     301             : 
     302           0 :             CALL write_bulk_dm_file(funit, siesta_struct, nspin, matrix_siesta_2d)
     303             : 
     304           0 :             CALL close_file(funit)
     305             :          END IF
     306             :       END IF
     307             : 
     308           2 :       CALL get_qs_env(qs_env, matrix_w_kp=matrix_w_kp)
     309           2 :       IF (ASSOCIATED(matrix_w_kp)) THEN
     310             :          ! write energy density matrix
     311           4 :          DO ispin = 1, nspin
     312         140 :             DO img = 1, nimages
     313         140 :                matrix_kp_generic(img)%matrix => matrix_w_kp(ispin, img)%matrix
     314             :             END DO
     315             :             CALL convert_dbcsr_to_distributed_siesta(matrix_siesta_2d(:, ispin), matrix_kp_generic, &
     316           4 :                                                      siesta_struct, para_env)
     317             :          END DO
     318             : 
     319           2 :          IF (not_regtest .AND. para_env%mepos == para_env%source) THEN
     320             :             CALL open_file(TRIM(smeagol_control%project_name)//".EDM", &
     321           0 :                            file_status="REPLACE", file_form="UNFORMATTED", file_action="WRITE", unit_number=funit)
     322             : 
     323           0 :             CALL write_bulk_dm_file(funit, siesta_struct, nspin, matrix_siesta_2d)
     324             : 
     325           0 :             CALL close_file(funit)
     326             :          END IF
     327             :       END IF
     328             : 
     329           2 :       DEALLOCATE (matrix_siesta_2d)
     330           2 :       DEALLOCATE (matrix_siesta_1d)
     331             : 
     332           2 :       DEALLOCATE (matrix_kp_generic)
     333           2 :       IF (.NOT. do_kpoints) DEALLOCATE (cell_to_index)
     334             : 
     335           2 :       CALL siesta_struct_release(siesta_struct)
     336           2 :       CALL timestop(handle)
     337       33956 :    END SUBROUTINE run_smeagol_bulktrans
     338             : 
     339             : ! **************************************************************************************************
     340             : !> \brief Write a sparse matrix structure file in SIESTA format. Should be called on I/O MPI process only.
     341             : !> \param funit             file to write
     342             : !> \param siesta_struct     sparse matrix structure in SIESTA format
     343             : !> \param system_label      SMEAGOL project name (first components of file names, i.e. system_label.HST)
     344             : !> \param nspin             number of spin components
     345             : !> \param EFermi            Fermi level
     346             : !> \param temperature       electronic temperature
     347             : !> \param H_to_Ry           Hartree to Rydberg scale factor
     348             : !> \param do_kpoints        whether to perform k-point calculation. Should always be enabled as
     349             : !>                          SMEAGOL expects at least 3 cell replicas along the transport direction
     350             : !> \param max_ij_cell_image maximum cell-replica indices along i- and j- lattice vectors
     351             : !>                          (perpendicular the transport direction)
     352             : ! **************************************************************************************************
     353           0 :    SUBROUTINE write_bulk_dat_file(funit, siesta_struct, system_label, nspin, EFermi, temperature, &
     354             :                                   H_to_Ry, do_kpoints, max_ij_cell_image)
     355             :       INTEGER, INTENT(in)                                :: funit
     356             :       TYPE(siesta_distrib_csc_struct_type), INTENT(in)   :: siesta_struct
     357             :       CHARACTER(len=*), INTENT(in)                       :: system_label
     358             :       INTEGER, INTENT(in)                                :: nspin
     359             :       REAL(kind=dp), INTENT(in)                          :: EFermi, temperature, H_to_Ry
     360             :       LOGICAL, INTENT(in)                                :: do_kpoints
     361             :       INTEGER, DIMENSION(2), INTENT(in)                  :: max_ij_cell_image
     362             : 
     363             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'write_bulk_dat_file'
     364             : 
     365             :       INTEGER                                            :: handle, icol, irow, nao_supercell, &
     366             :                                                             nao_unitcell
     367             :       INTEGER, DIMENSION(2)                              :: ncells_siesta
     368             : 
     369           0 :       CALL timeset(routineN, handle)
     370             : 
     371             :       ! ++ header
     372           0 :       nao_unitcell = siesta_struct%nrows
     373           0 :       nao_supercell = siesta_struct%ncols
     374           0 :       ncells_siesta(1:2) = 2*max_ij_cell_image(1:2) + 1
     375             : 
     376             :       ! SMEAGOL expects Temperature and Fermi energy in Rydberg energy units, not in Hartree energy units.
     377             :       ! It is why these values are doubled.
     378             : 
     379             :       WRITE (funit, '(1X,A20,3I12,2ES26.17E3,3I12)') &
     380           0 :          system_label, nao_unitcell, nspin, siesta_struct%n_nonzero_elements, &
     381           0 :          H_to_Ry*EFermi, H_to_Ry*temperature, ncells_siesta(1:2), nao_supercell
     382             : 
     383             :       ! ++ number of non-zero matrix elements on each row and
     384             :       !    the index of the first non-zero matrix element on this row -1 in 1D data array.
     385           0 :       DO irow = 1, nao_unitcell
     386           0 :          WRITE (funit, '(2I12)') siesta_struct%n_nonzero_cols(irow), siesta_struct%row_offset(irow)
     387             :       END DO
     388             : 
     389           0 :       DO icol = 1, nao_supercell
     390           0 :          WRITE (funit, '(I12)') siesta_struct%indxuo(icol)
     391             :       END DO
     392             : 
     393             :       ! ++ column indices of non-zero matrix elements
     394           0 :       DO irow = 1, nao_unitcell
     395           0 :          DO icol = 1, siesta_struct%n_nonzero_cols(irow)
     396           0 :             WRITE (funit, '(I12)') siesta_struct%col_index(siesta_struct%row_offset(irow) + icol)
     397             : 
     398           0 :             IF (do_kpoints) THEN
     399           0 :                WRITE (funit, '(F21.16,5X,F21.16,5X,F21.16)') siesta_struct%xij(:, siesta_struct%row_offset(irow) + icol)
     400             :             END IF
     401             :          END DO
     402             :       END DO
     403             : 
     404           0 :       CALL timestop(handle)
     405           0 :    END SUBROUTINE write_bulk_dat_file
     406             : 
     407             : ! **************************************************************************************************
     408             : !> \brief Write an (energy-) density matrix. Should be called on I/O MPI process only.
     409             : !> \param funit          file to write
     410             : !> \param siesta_struct  sparse matrix structure in SIESTA format
     411             : !> \param nspin          number of spin components
     412             : !> \param matrix_siesta  non-zero matrix elements (1:siesta_struct%n_nonzero_elements, 1:nspin)
     413             : ! **************************************************************************************************
     414           0 :    SUBROUTINE write_bulk_dm_file(funit, siesta_struct, nspin, matrix_siesta)
     415             :       INTEGER, INTENT(in)                                :: funit
     416             :       TYPE(siesta_distrib_csc_struct_type), INTENT(in)   :: siesta_struct
     417             :       INTEGER, INTENT(in)                                :: nspin
     418             :       REAL(kind=dp), DIMENSION(:, :), INTENT(in)         :: matrix_siesta
     419             : 
     420             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'write_bulk_dm_file'
     421             : 
     422             :       INTEGER                                            :: handle, irow, ispin
     423             : 
     424           0 :       CALL timeset(routineN, handle)
     425             : 
     426             :       ! ++ number of compressed rows, number of spin components
     427           0 :       WRITE (funit) siesta_struct%nrows, nspin
     428             : 
     429             :       ! ++ number of non-zero matrix elements on each compressed row.
     430             :       !    The sparsity pattern for alpha- and beta-spin density matrices are identical
     431           0 :       WRITE (funit) siesta_struct%n_nonzero_cols
     432             : 
     433             :       ! ++ column indices of non-zero matrix elements
     434           0 :       DO irow = 1, siesta_struct%nrows
     435             :          WRITE (funit) siesta_struct%col_index(siesta_struct%row_offset(irow) + 1: &
     436           0 :                                                siesta_struct%row_offset(irow) + siesta_struct%n_nonzero_cols(irow))
     437             :       END DO
     438             : 
     439             :       ! ++ non-zero matrix blocks
     440           0 :       DO ispin = 1, nspin
     441           0 :          DO irow = 1, siesta_struct%nrows
     442             :             WRITE (funit) matrix_siesta(siesta_struct%row_offset(irow) + 1: &
     443           0 :                                         siesta_struct%row_offset(irow) + siesta_struct%n_nonzero_cols(irow), ispin)
     444             :          END DO
     445             :       END DO
     446             : 
     447           0 :       CALL timestop(handle)
     448           0 :    END SUBROUTINE write_bulk_dm_file
     449             : 
     450             : ! **************************************************************************************************
     451             : !> \brief Write the average value of Hartree potential along transport direction.
     452             : !>        SMEAGOL assumes that the transport direction coincides with z-axis.
     453             : !> \param v_hartree_rspace   Hartree potential on a real-space 3-D grid
     454             : !> \param project_name       SMEAGOL project name
     455             : !> \note This routine assumes that the lattice vector 'k' coincides with z-axis
     456             : ! **************************************************************************************************
     457           0 :    SUBROUTINE write_average_hartree_potential(v_hartree_rspace, project_name)
     458             :       TYPE(pw_r3d_rs_type), POINTER                      :: v_hartree_rspace
     459             :       CHARACTER(len=*), INTENT(in)                       :: project_name
     460             : 
     461             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'write_average_hartree_potential'
     462             : 
     463             :       INTEGER                                            :: funit, handle, iz, lz, uz
     464             :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:)           :: v_hartree_z_average
     465             :       REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :, :), &
     466           0 :          POINTER                                         :: cr3d
     467             :       TYPE(pw_grid_type), POINTER                        :: pw_grid
     468             : 
     469           0 :       CALL timeset(routineN, handle)
     470             : 
     471           0 :       pw_grid => v_hartree_rspace%pw_grid
     472           0 :       cr3d => v_hartree_rspace%array
     473             : 
     474           0 :       ALLOCATE (v_hartree_z_average(pw_grid%bounds(1, 3):pw_grid%bounds(2, 3)))
     475           0 :       v_hartree_z_average(:) = 0.0_dp
     476             : 
     477           0 :       lz = pw_grid%bounds_local(1, 3)
     478           0 :       uz = pw_grid%bounds_local(2, 3)
     479             : 
     480             :       ! save average electrostatic potential
     481           0 :       DO iz = lz, uz
     482           0 :          v_hartree_z_average(iz) = accurate_sum(cr3d(:, :, iz))
     483             :       END DO
     484           0 :       CALL pw_grid%para%group%sum(v_hartree_z_average)
     485             :       v_hartree_z_average(:) = v_hartree_z_average(:)/ &
     486           0 :                                (REAL(pw_grid%npts(1), kind=dp)*REAL(pw_grid%npts(2), kind=dp))
     487             : 
     488           0 :       funit = -1
     489           0 :       IF (pw_grid%para%group%mepos == pw_grid%para%group%source) THEN
     490             :          CALL open_file(TRIM(ADJUSTL(project_name))//"-VH_AV.dat", &
     491           0 :                         file_status="REPLACE", file_form="FORMATTED", file_action="WRITE", unit_number=funit)
     492           0 :          WRITE (funit, '(A,T10,A,T25,A)') "#", "z (A)", "V_H average (eV)"
     493           0 :          DO iz = lz, uz
     494           0 :             WRITE (funit, '(F20.10,ES20.10E3)') pw_grid%dh(3, 3)*REAL(iz - lz, kind=dp)/bohr, &
     495           0 :                v_hartree_z_average(iz)/pw_grid%dvol*evolt
     496             :          END DO
     497           0 :          CALL close_file(funit)
     498             :       END IF
     499             : 
     500           0 :       DEALLOCATE (v_hartree_z_average)
     501           0 :       CALL timestop(handle)
     502           0 :    END SUBROUTINE write_average_hartree_potential
     503             : 
     504             : ! **************************************************************************************************
     505             : !> \brief Align Hatree potential of semi-infinite leads to match bulk-transport calculation
     506             : !>        and apply external electrostatic potential (bias).
     507             : !> \param v_hartree_rspace     Hartree potential on a real-space 3-D grid [inout]
     508             : !> \param cell                 unit cell
     509             : !> \param HartreeLeadsLeft     z-coordinate of the left lead
     510             : !> \param HartreeLeadsRight    z-coordinate of the right lead
     511             : !> \param HartreeLeadsBottom   average Hartree potential (from bulk-transport calculation)
     512             : !>                             at HartreeLeadsLeft and HartreeLeadsRight
     513             : !> \param Vbias                the value of external potential to apply
     514             : !> \param zleft                starting point of external potential drop (initial value 0.5*Vbias)
     515             : !> \param zright               final point of external potential drop (final value -0.5*Vbias)
     516             : !> \param isexplicit_zright    whether zright has beed provided explicitly via the input file.
     517             : !>                             If not, use the cell boundary.
     518             : !> \param isexplicit_bottom    whether the reference Hatree potential for bulk regions has been
     519             : !>                             provided explicitly via the input file. If not, do not align the
     520             : !>                             potential at all (instead of aligning it to 0 which is incorrect).
     521             : !> \note This routine assumes that the lattice vector 'k' coincides with z-axis
     522             : ! **************************************************************************************************
     523           0 :    SUBROUTINE smeagol_shift_v_hartree(v_hartree_rspace, cell, &
     524             :                                       HartreeLeadsLeft, HartreeLeadsRight, HartreeLeadsBottom, &
     525             :                                       Vbias, zleft, zright, isexplicit_zright, isexplicit_bottom)
     526             :       TYPE(pw_r3d_rs_type), POINTER                      :: v_hartree_rspace
     527             :       TYPE(cell_type), POINTER                           :: cell
     528             :       REAL(kind=dp), INTENT(in)                          :: HartreeLeadsLeft, HartreeLeadsRight, &
     529             :                                                             HartreeLeadsBottom, Vbias, zleft, &
     530             :                                                             zright
     531             :       LOGICAL, INTENT(in)                                :: isexplicit_zright, isexplicit_bottom
     532             : 
     533             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'smeagol_shift_v_hartree'
     534             : 
     535             :       INTEGER                                            :: handle, iz, l_right, lz, u_left, uz
     536             :       REAL(kind=dp)                                      :: v_average_left, v_average_right, &
     537             :                                                             v_bias_iz, zright_explicit
     538           0 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:)           :: v_hartree_z_average
     539             :       REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :, :), &
     540           0 :          POINTER                                         :: cr3d
     541             :       REAL(kind=dp), DIMENSION(3)                        :: r, r_pbc
     542             :       TYPE(pw_grid_type), POINTER                        :: pw_grid
     543             : 
     544           0 :       CALL timeset(routineN, handle)
     545           0 :       pw_grid => v_hartree_rspace%pw_grid
     546           0 :       cr3d => v_hartree_rspace%array
     547             : 
     548           0 :       zright_explicit = zright
     549           0 :       IF (.NOT. isexplicit_zright) THEN
     550           0 :          r_pbc(:) = (/0.0_dp, 0.0_dp, 1.0_dp/)
     551           0 :          CALL scaled_to_real(r, r_pbc, cell)
     552           0 :          zright_explicit = r(3)
     553             :       END IF
     554             : 
     555           0 :       ALLOCATE (v_hartree_z_average(pw_grid%bounds(1, 3):pw_grid%bounds(2, 3)))
     556             : 
     557           0 :       lz = pw_grid%bounds_local(1, 3)
     558           0 :       uz = pw_grid%bounds_local(2, 3)
     559             : 
     560           0 :       v_hartree_z_average(:) = 0.0_dp
     561           0 :       DO iz = lz, uz
     562           0 :          v_hartree_z_average(iz) = accurate_sum(cr3d(:, :, iz))
     563             :       END DO
     564             : 
     565           0 :       CALL pw_grid%para%group%sum(v_hartree_z_average)
     566             :       v_hartree_z_average(:) = v_hartree_z_average(:)/ &
     567           0 :                                (REAL(pw_grid%npts(1), kind=dp)*REAL(pw_grid%npts(2), kind=dp))
     568             : 
     569             :       ! z-indices of the V_hartree related to the left lead: pw_grid%bounds(1,3) .. u_left
     570           0 :       r(1:3) = (/0.0_dp, 0.0_dp, HartreeLeadsLeft/)
     571           0 :       CALL real_to_scaled(r_pbc, r, cell)
     572           0 :       u_left = NINT(r_pbc(3)*REAL(pw_grid%npts(3), kind=dp)) + pw_grid%bounds(1, 3)
     573           0 :       IF (u_left > pw_grid%bounds(2, 3)) u_left = pw_grid%bounds(2, 3)
     574             : 
     575             :       ! z-indices of the V_hartree related to the right lead: l_right .. pw_grid%bounds(2, 3)
     576           0 :       r(1:3) = (/0.0_dp, 0.0_dp, HartreeLeadsRight/)
     577           0 :       CALL real_to_scaled(r_pbc, r, cell)
     578           0 :       l_right = NINT(r_pbc(3)*REAL(pw_grid%npts(3), kind=dp)) + pw_grid%bounds(1, 3)
     579           0 :       IF (l_right > pw_grid%bounds(2, 3)) l_right = pw_grid%bounds(2, 3)
     580             : 
     581           0 :       CPASSERT(u_left <= l_right)
     582             : 
     583           0 :       v_average_left = v_hartree_z_average(u_left)
     584           0 :       v_average_right = v_hartree_z_average(l_right)
     585             : 
     586             :       ! align electrostatic potential of leads' regions with ones from bulk transport calculation
     587           0 :       IF (isexplicit_bottom) THEN
     588           0 :          v_hartree_z_average(:) = HartreeLeadsBottom*pw_grid%dvol - 0.5_dp*(v_average_left + v_average_right)
     589             :       ELSE
     590             :          ! do not align electrostatic potential
     591           0 :          v_hartree_z_average(:) = 0.0_dp
     592             :       END IF
     593             : 
     594             :       ! external Vbias
     595             :       ! TO DO: convert zright and zleft to scaled coordinates instead
     596           0 :       DO iz = lz, uz
     597           0 :          r_pbc(1) = 0.0_dp
     598           0 :          r_pbc(2) = 0.0_dp
     599           0 :          r_pbc(3) = REAL(iz - pw_grid%bounds(1, 3), kind=dp)/REAL(pw_grid%npts(3), kind=dp)
     600           0 :          CALL scaled_to_real(r, r_pbc, cell)
     601           0 :          IF (r(3) < zleft) THEN
     602           0 :             v_bias_iz = 0.5_dp*Vbias
     603           0 :          ELSE IF (r(3) > zright_explicit) THEN
     604           0 :             v_bias_iz = -0.5_dp*Vbias
     605             :          ELSE
     606           0 :             v_bias_iz = Vbias*(0.5_dp - (r(3) - zleft)/(zright_explicit - zleft))
     607             :          END IF
     608           0 :          v_hartree_z_average(iz) = v_hartree_z_average(iz) + v_bias_iz*pw_grid%dvol
     609             :       END DO
     610             : 
     611           0 :       DO iz = lz, uz
     612           0 :          cr3d(:, :, iz) = cr3d(:, :, iz) + v_hartree_z_average(iz)
     613             :       END DO
     614             : 
     615           0 :       DEALLOCATE (v_hartree_z_average)
     616           0 :       CALL timestop(handle)
     617           0 :    END SUBROUTINE smeagol_shift_v_hartree
     618             : 
     619             : ! **************************************************************************************************
     620             : !> \brief Run NEGF/SMEAGOL transport calculation.
     621             : !> \param qs_env     QuickStep environment
     622             : !> \param last       converged SCF iterations; compute NEGF properties [in]
     623             : !> \param iter       index of the current iteration [in]
     624             : !> \param rho_ao_kp  refined electron density; to be mixed with electron density from the previous
     625             : !>                   SCF iteration [out]
     626             : ! **************************************************************************************************
     627       16977 :    SUBROUTINE run_smeagol_emtrans(qs_env, last, iter, rho_ao_kp)
     628             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     629             :       LOGICAL, INTENT(in)                                :: last
     630             :       INTEGER, INTENT(in)                                :: iter
     631             :       TYPE(dbcsr_p_type), DIMENSION(:, :), OPTIONAL, &
     632             :          POINTER                                         :: rho_ao_kp
     633             : 
     634             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'run_smeagol_emtrans'
     635             : 
     636             :       INTEGER                                            :: handle, img, ispin, md_step, natoms, &
     637             :                                                             nimages, nspin
     638             :       INTEGER, DIMENSION(2)                              :: max_ij_cell_image, n_cell_images
     639       16977 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
     640             :       LOGICAL                                            :: do_kpoints, local_ldos, local_TrCoeff, &
     641             :                                                             negfon_saved, structure_changed
     642             :       REAL(kind=dp)                                      :: H_to_Ry
     643       16977 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:)           :: matrix_s_csc_merged
     644       16977 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :)        :: Dnew_csc_merged, Enew_csc_merged, &
     645       16977 :                                                             matrix_ks_csc_merged
     646             :       TYPE(cell_type), POINTER                           :: ucell
     647             :       TYPE(cp_logger_type), POINTER                      :: logger
     648       16977 :       TYPE(dbcsr_p_type), ALLOCATABLE, DIMENSION(:)      :: matrix_kp_generic
     649       16977 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks_kp, matrix_s_kp, matrix_w_kp
     650             :       TYPE(dft_control_type), POINTER                    :: dft_control
     651             :       TYPE(kpoint_type), POINTER                         :: kpoints
     652             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     653             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     654       16977 :          POINTER                                         :: sab_nl
     655             :       TYPE(qs_subsys_type), POINTER                      :: subsys
     656             :       TYPE(scf_control_type), POINTER                    :: scf_control
     657       16977 :       TYPE(siesta_distrib_csc_struct_type)               :: siesta_struct_merged
     658             :       TYPE(smeagol_control_type), POINTER                :: smeagol_control
     659             : 
     660       16977 :       logger => cp_get_default_logger()
     661             : 
     662       16977 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     663             : 
     664       16977 :       nspin = dft_control%nspins
     665       16977 :       smeagol_control => dft_control%smeagol_control
     666       16977 :       H_to_Ry = smeagol_control%to_smeagol_energy_units
     667             : 
     668       16977 :       IF (.NOT. (smeagol_control%smeagol_enabled .AND. smeagol_control%run_type == smeagol_runtype_emtransport)) RETURN
     669           0 :       CALL timeset(routineN, handle)
     670             : 
     671           0 :       NULLIFY (kpoints, matrix_s_kp, matrix_ks_kp, matrix_w_kp, para_env, sab_nl, scf_control, subsys)
     672             : #if defined(__SMEAGOL)
     673             :       CALL cite_reference(Ahart2024)
     674             :       CALL cite_reference(Bailey2006)
     675             : 
     676             :       CPASSERT(ASSOCIATED(smeagol_control%aux))
     677             :       CALL get_qs_env(qs_env, para_env=para_env, scf_control=scf_control, &
     678             :                       do_kpoints=do_kpoints, kpoints=kpoints, &
     679             :                       matrix_ks_kp=matrix_ks_kp, matrix_s_kp=matrix_s_kp, matrix_w_kp=matrix_w_kp, &
     680             :                       sab_orb=sab_nl, subsys=subsys)
     681             :       CALL qs_subsys_get(subsys, cell=ucell, natom=natoms)
     682             : 
     683             :       IF (do_kpoints) THEN
     684             :          nimages = dft_control%nimages
     685             :          CALL get_kpoint_info(kpoints, cell_to_index=cell_to_index)
     686             :       ELSE
     687             :          nimages = 1
     688             :          ALLOCATE (cell_to_index(0:0, 0:0, 0:0))
     689             :          cell_to_index(0, 0, 0) = 1
     690             :       END IF
     691             : 
     692             :       max_ij_cell_image(:) = -1
     693             :       DO img = 1, 2
     694             :          IF (smeagol_control%n_cell_images(img) > 0) THEN
     695             :             max_ij_cell_image(img) = smeagol_control%n_cell_images(img)/2
     696             :          END IF
     697             :       END DO
     698             : 
     699             :       ! obtain the sparsity pattern of the Kohn-Sham matrix
     700             :       ALLOCATE (matrix_kp_generic(nimages))
     701             :       DO img = 1, nimages
     702             :          matrix_kp_generic(img)%matrix => matrix_s_kp(1, img)%matrix
     703             :       END DO
     704             : 
     705             :       CALL siesta_struct_create(siesta_struct_merged, matrix_kp_generic, subsys, &
     706             :                                 cell_to_index, sab_nl, para_env, max_ij_cell_image, do_merge=.TRUE., gather_root=-1)
     707             : 
     708             :       ! Number of unit cells along (x and y ?) directions
     709             :       n_cell_images(1:2) = 2*max_ij_cell_image(1:2) + 1
     710             : 
     711             :       ALLOCATE (matrix_s_csc_merged(siesta_struct_merged%n_nonzero_elements))
     712             :       ALLOCATE (matrix_ks_csc_merged(siesta_struct_merged%n_nonzero_elements, nspin))
     713             : 
     714             :       CALL convert_dbcsr_to_distributed_siesta(matrix_s_csc_merged, matrix_kp_generic, siesta_struct_merged, para_env)
     715             : 
     716             :       DO ispin = 1, nspin
     717             :          DO img = 1, nimages
     718             :             matrix_kp_generic(img)%matrix => matrix_ks_kp(ispin, img)%matrix
     719             :          END DO
     720             : 
     721             :          CALL convert_dbcsr_to_distributed_siesta(matrix_ks_csc_merged(:, ispin), matrix_kp_generic, &
     722             :                                                   siesta_struct_merged, para_env)
     723             :       END DO
     724             : 
     725             :       IF (smeagol_control%aux%md_iter_level > 0) THEN
     726             :          CALL cp_get_iter_nr(logger%iter_info, smeagol_control%aux%md_iter_level, iter_nr=md_step)
     727             :       ELSE IF (smeagol_control%aux%md_iter_level == 0) THEN
     728             :          ! single-point energy calculation : there is only one MD step in this case
     729             :          md_step = smeagol_control%aux%md_first_step
     730             :       ELSE
     731             :          ! first invocation of the subroutine : initialise md_iter_level and md_first_step variables
     732             :          smeagol_control%aux%md_iter_level = cp_get_iter_level_by_name(logger%iter_info, "MD")
     733             : 
     734             :          IF (smeagol_control%aux%md_iter_level <= 0) &
     735             :             smeagol_control%aux%md_iter_level = cp_get_iter_level_by_name(logger%iter_info, "GEO_OPT")
     736             : 
     737             :          IF (smeagol_control%aux%md_iter_level <= 0) &
     738             :             smeagol_control%aux%md_iter_level = 0
     739             : 
     740             :          !  index of the first GEO_OPT / MD step
     741             :          IF (smeagol_control%aux%md_iter_level > 0) THEN
     742             :             CALL cp_get_iter_nr(logger%iter_info, smeagol_control%aux%md_iter_level, iter_nr=smeagol_control%aux%md_first_step)
     743             :          ELSE
     744             :             ! it has already been initialised in read_smeagol_control()
     745             :             smeagol_control%aux%md_first_step = 0
     746             :          END IF
     747             : 
     748             :          md_step = smeagol_control%aux%md_first_step
     749             :       END IF
     750             : 
     751             :       CALL reademtr(smeagol_control, natoms, gamma_negf=.FALSE.)
     752             :       CALL ReadOptionsNEGF_DFT(smeagol_control, ucell, torqueflag=.FALSE., torquelin=.FALSE.)
     753             : 
     754             :       CALL emtrans_options(smeagol_control, &
     755             :                            matrix_s=matrix_s_kp(1, 1)%matrix, para_env=para_env, iter=iter, &
     756             :                            istep=md_step, inicoor=smeagol_control%aux%md_first_step, iv=0, &
     757             :                            delta=smeagol_control%aux%delta, nk=kpoints%nkp)
     758             : 
     759             :       CALL create_communicators_negf(parent_comm=para_env%get_handle(), &
     760             :                                      nprocs_inverse=smeagol_control%aux%nprocs_inverse, &
     761             :                                      NParallelK=smeagol_control%aux%NParallelK)
     762             : 
     763             :       ALLOCATE (Dnew_csc_merged(siesta_struct_merged%n_nonzero_elements, nspin))
     764             :       ALLOCATE (Enew_csc_merged(siesta_struct_merged%n_nonzero_elements, nspin))
     765             : 
     766             :       ! As SMEAGOL's default energy unit is Rydberg, scale the KS-matrix
     767             :       matrix_ks_csc_merged(:, :) = H_to_Ry*matrix_ks_csc_merged(:, :)
     768             : 
     769             :       ! SMEAGOL computes current if EM.OrderN = .false., otherwise the printed current is equal to 0.
     770             :       ! The following computes current regardless the value of EM.OrderN parameter
     771             :       IF (last) THEN
     772             :          negfon_saved = smeagolglobal_negfon
     773             :          smeagolglobal_negfon = .FALSE.
     774             :       END IF
     775             : 
     776             :       IF (last) THEN
     777             :          local_TrCoeff = smeagol_control%aux%TrCoeff
     778             :          local_ldos = .TRUE. ! TO DO: find out initial value of ldos
     779             :       ELSE
     780             :          local_TrCoeff = .FALSE.
     781             :          local_ldos = .FALSE.
     782             :       END IF
     783             : 
     784             :       ! number of atoms in the unit cell
     785             :       smeagolglobal_em_nau = natoms ! number of atoms in the unit cell
     786             : 
     787             :       ! number of atomic orbitals in the unit cell.
     788             :       ! This global variable defines the size of temporary arrays for (P)DOS calculation.
     789             :       ! This should be the total number of the atomic orbitals in the unit cell,
     790             :       ! instead of the number of atomic orbitals local to the current MPI process.
     791             :       smeagolglobal_em_nuo = siesta_struct_merged%ncols/(n_cell_images(1)*n_cell_images(2))
     792             : 
     793             :       ! number of atoms in the super cell
     794             :       smeagolglobal_em_nas = SIZE(siesta_struct_merged%xa)
     795             : 
     796             :       ! number of atomic orbitals in the super cell
     797             :       smeagolglobal_em_nso = siesta_struct_merged%ncols
     798             : 
     799             :       ! The following global variables are only used in writephibin() which is not called by this interface
     800             :       !   smeagolglobal_em_isa => isa
     801             :       !   smeagolglobal_em_iaorb => iaorb
     802             :       !   smeagolglobal_em_iphorb => iphorb
     803             : 
     804             :       structure_changed = (iter == 1)
     805             : 
     806             :       CALL Negf_Interface( &
     807             :          ! distributed Kohn-Sham, overlap, density, and energy-density matrices in SIESTA format
     808             :          H=matrix_ks_csc_merged, &
     809             :          S=matrix_s_csc_merged, &
     810             :          DM=Dnew_csc_merged, &
     811             :          Omega=Enew_csc_merged, &
     812             :          ! interatomic distances for each non-zero matrix element
     813             :          xij=siesta_struct_merged%xij, &
     814             :          ! number of atomic orbitals in a supercell
     815             :          no_s=siesta_struct_merged%ncols, &
     816             :          ! number of atomic orbitals in the unit cell
     817             :          no_u=siesta_struct_merged%ncols/(n_cell_images(1)*n_cell_images(2)), &
     818             :          ! number of AOs local to the given MPI process
     819             :          no_u_node=siesta_struct_merged%nrows, &
     820             :          ! atomic coordinates for each atom in the supercell
     821             :          xa=siesta_struct_merged%xa, &
     822             :          ! unused dummy variable na_u
     823             :          na_u=natoms, &
     824             :          ! number of atoms in the supercell
     825             :          na_s=SIZE(siesta_struct_merged%xa), &
     826             :          ! number of spin-components
     827             :          NspinRealInputMatrix=nspin, &
     828             :          ! number of non-zero matrix element
     829             :          maxnh=INT(siesta_struct_merged%n_nonzero_elements), &
     830             :          ! number of non-zero matrix elements on each locally stored row
     831             :          numh=siesta_struct_merged%n_nonzero_cols, &
     832             :          ! offset (index-1) of first non-zero matrix elements on each locally stored row
     833             :          listhptr=siesta_struct_merged%row_offset, &
     834             :          ! column number (AO index) for each non-zero matrix element
     835             :          listh=siesta_struct_merged%col_index, &
     836             :          ! number of k-points
     837             :          nkpts=kpoints%nkp, &
     838             :          ! k-point coordinates
     839             :          kpoint=kpoints%xkp, &
     840             :          ! k-point weight
     841             :          weight_k=kpoints%wkp, &
     842             :          ! index of equivalent atomic orbital within the primary unit cell for each AO in the supercell
     843             :          indxuo=siesta_struct_merged%indxuo, &
     844             :          ! list of atomic indices on which each AO (in the supercell) is centred
     845             :          iaorb=siesta_struct_merged%iaorb, &
     846             :          ! GEO_OPT / MD step index
     847             :          MD_Step=md_step, &
     848             :          ! GEO_OPT / MD at which SMEAGOL should allocate its internal data structures
     849             :          inicoor=smeagol_control%aux%md_first_step, &
     850             :          ! ivv (step over bias, first IV step should always be 0 (hardcoded in SMEAGOL)
     851             :          !    we iterate over GEO_OPT / MD steps instead of bias steps in order not to overwrite
     852             :          !    TRC (Transmission coefficients) files
     853             :          IV_step=md_step - smeagol_control%aux%md_first_step, &
     854             :          ! applied electrostatic bias
     855             :          Vb=smeagol_control%aux%VBias*H_to_Ry, &
     856             :          ! index of the currect SCF iteration
     857             :          SCF_step=iter, &
     858             :          ! compute density matrix (.FALSE.) or properties (.TRUE.)
     859             :          Last_SCF_step=last, &
     860             :          ! recompute self-energy matrices
     861             :          StructureChanged=structure_changed, &
     862             :          ! electronic temperature in Ry
     863             :          temp=smeagol_control%aux%temperature*H_to_Ry, &
     864             :          ! number of unit cell replicas along i-, and j- cell verctors
     865             :          nsc=n_cell_images, &
     866             :          ! name of SMEAGOL project (partial file name for files created by SMEAGOL)
     867             :          slabel=smeagol_control%project_name, &
     868             :          ! number of integration points along real axis, circular path and a line in imaginary space parallel to the real axis
     869             :          NEnergR=smeagol_control%aux%NEnergR, &
     870             :          NEnergIC=smeagol_control%aux%NEnergIC, &
     871             :          NEnergIL=smeagol_control%aux%NEnergIL, &
     872             :          ! number of poles
     873             :          NPoles=smeagol_control%aux%NPoles, &
     874             :          ! small imaginary shift that makes matrix inversion computationally stable
     875             :          Delta=smeagol_control%aux%deltamin*H_to_Ry, &
     876             :          ! integration lower bound
     877             :          EnergLB=smeagol_control%aux%EnergLB*H_to_Ry, &
     878             :          ! [unused dummy arguments] initial (VInitial) and final (VFinal) voltage
     879             :          VInitial=smeagol_control%aux%VBias, &
     880             :          VFinal=smeagol_control%aux%VBias, &
     881             :          !
     882             :          SpinCL=smeagol_control%aux%SpinCL, &
     883             :          ! number of slices for OrderN matrix inversion
     884             :          NSlices=smeagol_control%aux%NSlices, &
     885             :          ! whether to compute transmission coefficients (TrCoeff), IETS spectrum (CalcIETS), and local Dnsity-of-States (ldos)
     886             :          TrCoeff=local_TrCoeff, &
     887             :          CalcIETS=smeagol_control%aux%CalcIETS, &
     888             :          ldos=local_ldos, &
     889             :          ! Transmission coefficients are only computed for certain runtypes (encoded with magic numbers).
     890             :          ! In case of idyn=0, transmission coefficients are always computed.
     891             :          idyn=0, &
     892             :          ! do not compute transmission coefficient for initial GEO_OPT / MD iterations
     893             :          tmdskip=smeagol_control%aux%tmdskip, &
     894             :          ! computes transmission coefficients once for each 'tmdsampling' MD iterations
     895             :          tmdsampling=smeagol_control%aux%tmdsampling)
     896             : 
     897             :       ! *** Bound-state correction method ***
     898             : 
     899             :       ! smeagol_control%bs_add    : BS.Add (.FALSE.) ; add bound states
     900             :       ! smeagol_control%bs_method : BS.Method (0) ; 0 - use effective Hamiltonian; 1 - add small imaginary part to the selfenergies
     901             :       ! smeagol_control%bssc      : BS.SetOccupation (1)
     902             :       IF (smeagol_control%aux%bs_add .AND. smeagol_control%aux%bs_method == 1 .AND. smeagol_control%aux%bssc == 0 .AND. &
     903             :           kpoints%nkp > 1 .AND. (.NOT. last)) THEN
     904             : 
     905             :          CALL Negf_Interface(H=matrix_ks_csc_merged, &
     906             :                              S=matrix_s_csc_merged, &
     907             :                              DM=Dnew_csc_merged, &
     908             :                              Omega=Enew_csc_merged, &
     909             :                              xij=siesta_struct_merged%xij, &
     910             :                              no_s=siesta_struct_merged%ncols, &
     911             :                              no_u=siesta_struct_merged%ncols/(n_cell_images(1)*n_cell_images(2)), &
     912             :                              no_u_node=siesta_struct_merged%nrows, &
     913             :                              xa=siesta_struct_merged%xa, &
     914             :                              ! unused dummy variable
     915             :                              na_u=natoms, &
     916             :                              na_s=SIZE(siesta_struct_merged%xa), &
     917             :                              NspinRealInputMatrix=nspin, &
     918             :                              maxnh=INT(siesta_struct_merged%n_nonzero_elements), &
     919             :                              numh=siesta_struct_merged%n_nonzero_cols, &
     920             :                              listhptr=siesta_struct_merged%row_offset, &
     921             :                              listh=siesta_struct_merged%col_index, &
     922             :                              nkpts=kpoints%nkp, &
     923             :                              kpoint=kpoints%xkp, &
     924             :                              weight_k=kpoints%wkp, &
     925             :                              indxuo=siesta_struct_merged%indxuo, &
     926             :                              iaorb=siesta_struct_merged%iaorb, &
     927             :                              MD_Step=md_step, &
     928             :                              inicoor=smeagol_control%aux%md_first_step, &
     929             :                              IV_step=md_step - smeagol_control%aux%md_first_step, &
     930             :                              Vb=smeagol_control%aux%VBias*H_to_Ry, &
     931             :                              ! This line is the only difference from the first Negf_Interface() call
     932             :                              SCF_step=MERGE(2, 1, structure_changed), &
     933             :                              Last_SCF_step=last, &
     934             :                              StructureChanged=structure_changed, &
     935             :                              temp=smeagol_control%aux%temperature*H_to_Ry, &
     936             :                              nsc=n_cell_images, &
     937             :                              slabel=smeagol_control%project_name, &
     938             :                              NEnergR=smeagol_control%aux%NEnergR, &
     939             :                              NEnergIC=smeagol_control%aux%NEnergIC, &
     940             :                              NEnergIL=smeagol_control%aux%NEnergIL, &
     941             :                              NPoles=smeagol_control%aux%NPoles, &
     942             :                              Delta=smeagol_control%aux%deltamin*H_to_Ry, &
     943             :                              EnergLB=smeagol_control%aux%EnergLB*H_to_Ry, &
     944             :                              ! unused dummy variable
     945             :                              VInitial=smeagol_control%aux%VBias, &
     946             :                              ! unused dummy variable
     947             :                              VFinal=smeagol_control%aux%VBias, &
     948             :                              SpinCL=smeagol_control%aux%SpinCL, &
     949             :                              NSlices=smeagol_control%aux%NSlices, &
     950             :                              TrCoeff=local_TrCoeff, &
     951             :                              CalcIETS=smeagol_control%aux%CalcIETS, &
     952             :                              ldos=local_ldos, &
     953             :                              idyn=0, & !
     954             :                              tmdskip=smeagol_control%aux%tmdskip, &
     955             :                              tmdsampling=smeagol_control%aux%tmdsampling)
     956             :       END IF
     957             : 
     958             :       ! Restore ovewriten EM.OrderN parameter
     959             :       IF (last) THEN
     960             :          smeagolglobal_negfon = negfon_saved
     961             :       END IF
     962             : 
     963             :       IF (PRESENT(rho_ao_kp)) THEN
     964             :          DO ispin = 1, nspin
     965             :             DO img = 1, nimages
     966             :                ! To be on a safe size, zeroize the new density matrix first. It is not actually needed.
     967             :                CALL dbcsr_set(rho_ao_kp(ispin, img)%matrix, 0.0_dp)
     968             :                matrix_kp_generic(img)%matrix => rho_ao_kp(ispin, img)%matrix
     969             :             END DO
     970             : 
     971             :             CALL convert_distributed_siesta_to_dbcsr(matrix_kp_generic, Dnew_csc_merged(:, ispin), &
     972             :                                                      siesta_struct_merged, para_env)
     973             :          END DO
     974             : 
     975             :          ! current-induced forces
     976             :          IF (smeagol_control%emforces) THEN
     977             :             Enew_csc_merged(:, :) = (1.0_dp/H_to_Ry)*Enew_csc_merged(:, :)
     978             : 
     979             :             DO ispin = 1, nspin
     980             :                DO img = 1, nimages
     981             :                   ! To be on a safe size, zeroize the new energy-density matrix first. It is not actually needed.
     982             :                   CALL dbcsr_set(matrix_w_kp(ispin, img)%matrix, 0.0_dp)
     983             :                   matrix_kp_generic(img)%matrix => matrix_w_kp(ispin, img)%matrix
     984             :                END DO
     985             : 
     986             :                CALL convert_distributed_siesta_to_dbcsr(matrix_kp_generic, Enew_csc_merged(:, ispin), &
     987             :                                                         siesta_struct_merged, para_env)
     988             :             END DO
     989             :          END IF
     990             :       END IF
     991             : 
     992             :       CALL destroy_communicators_negf()
     993             :       CALL emtrans_deallocate_global_arrays()
     994             : 
     995             :       DEALLOCATE (Dnew_csc_merged, Enew_csc_merged)
     996             :       DEALLOCATE (matrix_s_csc_merged, matrix_ks_csc_merged)
     997             : 
     998             :       CALL siesta_struct_release(siesta_struct_merged)
     999             : 
    1000             :       IF (.NOT. do_kpoints) DEALLOCATE (cell_to_index)
    1001             : #else
    1002             :       CALL cp_abort(__LOCATION__, &
    1003           0 :                     "CP2K was compiled with no SMEAGOL support.")
    1004             :       MARK_USED(last)
    1005             :       MARK_USED(iter)
    1006             :       MARK_USED(rho_ao_kp)
    1007             :       ! local variables
    1008             :       MARK_USED(cell_to_index)
    1009             :       MARK_USED(do_kpoints)
    1010             :       MARK_USED(Dnew_csc_merged)
    1011             :       MARK_USED(Enew_csc_merged)
    1012             :       MARK_USED(img)
    1013             :       MARK_USED(ispin)
    1014             :       MARK_USED(local_ldos)
    1015             :       MARK_USED(local_TrCoeff)
    1016             :       MARK_USED(max_ij_cell_image)
    1017             :       MARK_USED(matrix_kp_generic)
    1018             :       MARK_USED(matrix_ks_csc_merged)
    1019             :       MARK_USED(matrix_s_csc_merged)
    1020             :       MARK_USED(md_step)
    1021             :       MARK_USED(natoms)
    1022             :       MARK_USED(negfon_saved)
    1023             :       MARK_USED(nimages)
    1024             :       MARK_USED(n_cell_images)
    1025             :       MARK_USED(siesta_struct_merged)
    1026             :       MARK_USED(structure_changed)
    1027             :       MARK_USED(ucell)
    1028             : #endif
    1029             : 
    1030           0 :       CALL timestop(handle)
    1031       16977 :    END SUBROUTINE run_smeagol_emtrans
    1032             : 
    1033             : END MODULE smeagol_interface

Generated by: LCOV version 1.15