Commit 6d014704 authored by Nick R. Papior's avatar Nick R. Papior
Browse files

Merged transiesta

Added die routine for non-complete principal connections
and precision control of the SE convergence.

Changed the { to [ for list construction in FDF.

Added fdf_bphysical to read 'VN' (value name)
parents fd38db27 477be823
......@@ -157,7 +157,7 @@ MODULE fdf
public :: fdf_block, fdf_bline, fdf_bbackspace, fdf_brewind
public :: fdf_bnintegers, fdf_bnreals, fdf_bnvalues, fdf_bnnames, fdf_bntokens
public :: fdf_bintegers, fdf_breals, fdf_bvalues, fdf_bnames, fdf_btokens
public :: fdf_bboolean
public :: fdf_bboolean, fdf_bphysical
public :: fdf_bnlists, fdf_blists
! Match, search over blocks, and destroy block structure
......@@ -2348,6 +2348,66 @@ MODULE fdf
!--------------------------------------------------------------------------- END
END FUNCTION fdf_physical
!
! Returns a double precision value from a block-line after a certain input value
! or the default value if label is not found in the fdf file.
! Converts the units to defunit.
!
FUNCTION fdf_bphysical(pline, default, defunit, after)
implicit none
!--------------------------------------------------------------- Input Variables
type(parsed_line), pointer :: pline
real(dp) :: default
character(*) :: defunit
integer(ip), intent(in), optional :: after
!-------------------------------------------------------------- Output Variables
real(dp) :: fdf_bphysical
!--------------------------------------------------------------- Local Variables
character(10) :: unitstr
character(80) :: msg
real(dp) :: value
type(line_dlist), pointer :: mark
!------------------------------------------------------------------------- BEGIN
! Prevents using FDF routines without initialize
if (.not. fdf_started) then
call die('FDF module: fdf_bphysical', 'FDF subsystem not initialized', &
THIS_FILE, __LINE__, fdf_err)
endif
if (.not. match(pline, 'vn', after)) then
write(msg,*) 'no real value for line: '//pline%line
call die('FDF module: fdf_bphysical', msg, THIS_FILE, &
__LINE__, fdf_err)
endif
! get value in block-line
value = values(pline, 1, after)
! get unit in block-line
unitstr = names(pline, 1, after)
if ( leqi(unitstr, defunit) ) then
fdf_bphysical = value
else
fdf_bphysical = value * fdf_convfac(unitstr, defunit)
end if
if ( fdf_output ) then
if ( present(after) ) then
write(fdf_out,'(5x,g20.10,1x,a10,1x,i0)') fdf_bphysical, &
defunit, after
else
write(fdf_out,'(5x,g20.10,1x,a10)') fdf_bphysical, defunit
end if
write(fdf_out,'(a,a,5x,g20.10,1x,a10)') &
'# above item on line: ', pline%line
end if
!--------------------------------------------------------------------------- END
END FUNCTION fdf_bphysical
!
! Returns conversion factor between a subset of physical units
! Written by j.m.soler. dec'96.
......@@ -2640,6 +2700,8 @@ MODULE fdf
!--------------------------------------------------------------------------- END
END FUNCTION fdf_bline
!
! Backspace to the previous physical line in the block
! returning .TRUE. while more lines exist in the block bfdf.
......
......@@ -1129,8 +1129,11 @@ MODULE parse
! String delimiters: " ' `
is_delstr(i) = (i .eq. 34) .or. (i .eq. 39) .or. (i .eq. 96)
! List delimiters: { }
is_dellist(i) = (i .eq. 123) .or. (i .eq. 125)
! List delimiters: [ ]
is_dellist(i) = (i .eq. 91) .or. (i .eq. 93)
! Dictionary delimiters: { }
! is_deldict(i) = (i .eq. 123) .or. (i .eq. 125)
! Special characters which are tokens by themselves: <
is_special(i) = (i .eq. 60)
......@@ -1258,10 +1261,14 @@ MODULE parse
do i= 1, ntokens
token = line(first(i):last(i))
j = last(i) - first(i) + 1
if ( ichar(token(1:1)) .eq. 123 .and. &
ichar(token(j:j)) .eq. 125 ) then
! if the token starts with { and ends with }, it will be a list
if ( ichar(token(1:1)) .eq. 91 .and. &
ichar(token(j:j)) .eq. 93 ) then
! if the token starts with [ and ends with ], it will be a list
token_id(i) = 'a'
! else if ( ichar(token(1:1)) .eq. 123 .and. &
! ichar(token(j:j)) .eq. 125 ) then
! if the token starts with { and ends with }, it will be a dictionary
! token_id(i) = 'd'
elseif (is_value(token)) then
! This read also serves to double check the token for
......
......@@ -20,12 +20,12 @@ AtomicCoordinatesAndAtomicSpecies < coords.fdf # Search in file
%endblock Other-Block
%block ListBlock
List1 {1,2,3 ,5 , 6 } {-1,-3} {100 -- 10 step 7}
List2 { 1 to 5 , 4 } {10 -- 20 step 4 , 3 }
List2 { 1 to 5 , 4 , 2 to 10 , -2 to -20}
List1 [1,2,3 ,5 , 6 ] [-1,-3] [100 -- 10 step 7]
List2 [ 1 to 5 , 4 ] [10 -- 20 step 4 , 3 ]
List2 [ 1 to 5 , 4 , 2 to 10 , -2 to -20]
%endblock ListBlock
MyList { 2 -- 10 , 11 , 20 }
MyList [ 2 -- 10 , 11 , 20 ]
debug faLSE # Case insensitive!!
......
......@@ -171,6 +171,11 @@ module dictionary
end interface pop
public :: pop
interface copy
module procedure copy_
end interface
public :: copy
interface nullify
module procedure nullify_
end interface nullify
......@@ -724,6 +729,35 @@ contains
end subroutine delete_
!> Generate the copy routine
subroutine copy_(from, to)
type(dict), intent(in) :: from
type(dict), intent(inout) :: to
type(d_entry), pointer :: d
type(var) :: v
! Delete the dictionary
call delete(to)
d => from%first
do while ( associated(d) )
! Associate data...
call associate(v, d%value)
! Copy data, hence .kv.
to = to // (trim(d%key).kv.v)
d => d%next
end do
! Clean up pointers...
call nullify(v)
nullify(d)
end subroutine copy_
subroutine pop_(val,this,key,dealloc)
type(var), intent(inout) :: val
type(dict), intent(inout) :: this
......
......@@ -21,8 +21,6 @@ module m_ts_electrode
private
! Accuracy of the surface-Green function
real(dp), parameter :: accur = 1.e-15_dp
! BLAS parameters
complex(dp), parameter :: z_1 = dcmplx(1._dp,0._dp)
complex(dp), parameter :: z_m1 = dcmplx(-1._dp,0._dp)
......@@ -39,7 +37,7 @@ contains
! Calculates the surface Green function for the electrodes
! Handles both the left and right one
! this is the Sancho, Sancho and Rubio algorithm
subroutine SSR_sGreen_DOS(no,ZE,H00,S00,H01,S01,GS, &
subroutine SSR_sGreen_DOS(no,ZE,H00,S00,H01,S01,accu, GS, &
DOS, T, &
nwork, zwork, &
iterations, final_invert)
......@@ -51,9 +49,11 @@ contains
! complex(dp) S00 : Overlap matrix within the first unit cell (discarding T-direction)
! complex(dp) H01 : Transfer matrix from H00 to the neighbouring cell (in T-direction)
! complex(dp) S01 : Transfer matrix from S00 to the neighbouring cell (in T-direction)
! real(dp) accu : Define the accuracy needed for convergence.
! ***************** OUTPUT *********************************************
! complex(dp) GS : Surface Green function of the electrode
! real(dp) DOS : DOS of bulk electrode (additive)
! real(dp) T : transmission of bulk electrode (additive)
! **********************************************************************
use m_pivot_array, only : ipiv
use m_mat_invert
......@@ -68,8 +68,9 @@ contains
complex(dp), intent(in) :: ZE
complex(dp), intent(in) :: H00(no*no),S00(no*no)
complex(dp), intent(in) :: H01(no*no),S01(no*no)
real(dp), intent(in) :: accu
integer, intent(in) :: nwork
integer, intent(in) :: nwork
logical, intent(in), optional :: final_invert
......@@ -174,9 +175,9 @@ contains
!$OMP end parallel
! Initialize loop
ro = accur + 1._dp
ro = accu + 1._dp
as_first = .false.
do while ( ro > accur )
do while ( ro > accu )
! Increment iterations
if ( present(iterations) ) &
......@@ -507,7 +508,7 @@ contains
! Calculates the surface Green function for the electrodes
! Handles both the left and right one
! this is the Sancho, Sancho and Rubio algorithm
subroutine SSR_sGreen_NoDOS(no,ZE,H00,S00,H01,S01,GS, &
subroutine SSR_sGreen_NoDOS(no,ZE,H00,S00,H01,S01,accu, GS, &
nwork, zwork, &
iterations, final_invert)
......@@ -532,6 +533,7 @@ contains
complex(dp), intent(in) :: ZE
complex(dp), intent(in) :: H00(no*no),S00(no*no)
complex(dp), intent(in) :: H01(no*no),S01(no*no)
real(dp), intent(in) :: accu
integer, intent(in) :: nwork
......@@ -619,9 +621,9 @@ contains
!$OMP end parallel
! Initialize loop
ro = accur + 1._dp
ro = accu + 1._dp
as_first = .false.
do while ( ro > accur )
do while ( ro > accu )
! Increment iterations
if ( present(iterations) ) &
......@@ -1193,7 +1195,8 @@ contains
! Zenergy is wrt. to the system Fermi-level
if ( CalcDOS ) then
lDOS = 0._dp
call SSR_sGreen_DOS(nuo_E,ZEnergy,H00,S00,H01,S01,GS, &
call SSR_sGreen_DOS(nuo_E,ZEnergy,H00,S00,H01,S01, &
El%accu, GS, &
lDOS,i_mean,9*nS,zwork, &
iterations=iters(iqpt,iEn,ikpt,1), final_invert = reduce_size)
......@@ -1202,7 +1205,8 @@ contains
if ( CalcT ) T(iEn,ispin) = T(iEn,ispin) + i_mean
else
call SSR_sGreen_NoDos(nuo_E,ZEnergy,H00,S00,H01,S01,GS, &
call SSR_sGreen_NoDos(nuo_E,ZEnergy,H00,S00,H01,S01, &
El%accu, GS, &
8*nS,zwork, &
iterations=iters(iqpt,iEn,ikpt,1), final_invert = reduce_size)
......@@ -1520,12 +1524,20 @@ contains
subroutine init_Electrode_HS(El)
use m_ts_electype
use fdf, only: fdf_get
#ifdef MPI
use mpi_siesta
#endif
use class_Sparsity
use class_dSpData1D
use class_dSpData2D
use m_ts_electype
type(Elec), intent(inout) :: El
#ifdef MPI
integer :: error
#endif
logical :: neglect_conn
! Read-in and create the corresponding transfer-matrices
call delete(El) ! ensure clean electrode
......@@ -1538,7 +1550,22 @@ contains
! print out the precision of the electrode (whether it extends
! beyond first principal layer)
call check_Connectivity(El)
if ( check_connectivity(El) ) then
neglect_conn = .true.
else
neglect_conn = fdf_get('TS.Elecs.Neglect.Principal', .false.)
#ifdef TBTRANS
neglect_conn = fdf_get('TBT.Elecs.Neglect.Principal', neglect_conn)
#endif
end if
#ifdef MPI
call MPI_Barrier(MPI_Comm_World,error)
#endif
if ( .not. neglect_conn ) then
call die('Electrode connectivity is not perfect, &
&refer to the manual for achieving a perfect electrode.')
end if
call create_sp2sp01(El)
! Clean-up, we will not need these!
......@@ -1934,12 +1961,14 @@ contains
! calculate the contribution for this q-point
if ( calc_DOS ) then
call SSR_sGreen_DOS(nuo_E,Z,H00,S00,H01,S01,GS, &
call SSR_sGreen_DOS(nuo_E,Z,H00,S00,H01,S01, &
El%accu, GS, &
DOS(1:nuo_E), T, &
nw, zwork, &
final_invert = reduce_size)
else
call SSR_sGreen_NoDOS(nuo_E,Z,H00,S00,H01,S01,GS, &
call SSR_sGreen_NoDOS(nuo_E,Z,H00,S00,H01,S01, &
El%accu, GS, &
nw, zwork, &
final_invert = reduce_size)
end if
......
......@@ -146,8 +146,13 @@ module m_ts_electype
! and NOT: i (Sigma - Sigma^\dagger)
complex(dp), pointer :: Gamma(:), Sigma(:)
! The accuracy required for the self-energy
! == 1e-13 * eV
real(dp) :: accu = 7.349806700083788e-15_dp
! The imaginary part in the electrode
real(dp) :: Eta = 7.3498067e-6_dp ! corresponds to 0.0001 eV
! == 0.0001 * eV
real(dp) :: Eta = 7.3498067e-6_dp
! The region of the down-folded region
type(tRgn) :: o_inD, inDpvt
......@@ -558,6 +563,14 @@ contains
if ( fdf_bnnames(pline) < 2 ) call die('TSDE name not supplied')
this%DEfile = trim(fdf_bnames(pline,2))
#ifdef TBTRANS
else if ( leqi(ln,'tbt.Accuracy') .or. leqi(ln,'Accuracy') ) then
#else
else if ( leqi(ln,'Accuracy') ) then
#endif
call pline_E_parse(pline,1,ln, &
val = this%accu, before=3)
#ifdef TBTRANS
else if ( leqi(ln,'tbt.Eta') .or. leqi(ln,'Eta') ) then
#else
......@@ -1637,7 +1650,7 @@ contains
end subroutine delete_
subroutine check_connectivity(this)
function check_connectivity(this) result(good)
use parallel, only : IONode
use units, only : eV
......@@ -1652,6 +1665,7 @@ contains
#endif
type(Elec), intent(inout) :: this
logical :: good
real(dp), pointer :: H(:,:)
real(dp), pointer :: S(:)
......@@ -1740,6 +1754,10 @@ contains
! clean-up
call delete(sp02)
! If both number
good = ind == 0
if ( .not. good ) good = maxi == 0
if ( .not. IONode ) return
if ( ind == 0 ) then
......@@ -1758,7 +1776,7 @@ contains
maxi,',',maxj,')|@R=',tm(this%t_dir),' = ',maxS
end if
end subroutine check_connectivity
end function check_connectivity
! Routine for checking the validity of the electrode against the
! system setup in transiesta
......@@ -2023,6 +2041,7 @@ contains
#else
write(*,f9) ' Electrode self-energy imaginary Eta', this%Eta/eV,' eV'
#endif
write(*,f9) ' Electrode self-energy accuracy', this%accu/eV,' eV'
write(*,f6) ' Electrode inter-layer distance (semi-inf)', this%dINF_layer/Ang,' Ang'
......
......@@ -428,6 +428,8 @@ contains
! the remaining electrodes have their chemical potential at 0
! We should probably warn if +2 electrodes are used and t_dir is the
! same for all electrodes... Then the user needs to know what (s)he is doing...
! Accuracy required for self-energy convergence
Elecs(:)%accu = fdf_get('TS.Elecs.Accuracy',1e-14_dp*eV,'Ry')
Elecs(:)%Eta = fdf_get('TS.Contours.nEq.Eta',0.0001_dp*eV,'Ry')
Elecs(:)%Eta = fdf_get('TS.Elecs.Eta',Elecs(1)%Eta,'Ry')
Elecs(:)%Bulk = fdf_get('TS.Elecs.Bulk',.true.) ! default everything to bulk electrodes
......
......@@ -31,6 +31,7 @@ contains
use parallel, only : IONode
use m_os, only : file_exist
use fdf, only: fdf_get
use m_ts_gf, only : do_Green, do_Green_Fermi
use m_ts_electrode, only : init_Electrode_HS
......@@ -66,6 +67,7 @@ contains
! *********************
! * LOCAL variables *
! *********************
logical :: neglect_conn
integer :: i, ia
integer :: nC, nTS
real(dp) :: mean_kT
......@@ -210,17 +212,35 @@ contains
end do
else
neglect_conn = .false.
do i = 1 , N_Elec
call delete(Elecs(i)) ! ensure clean electrode
call read_Elec(Elecs(i),Bcast=.true.)
! print out the precision of the electrode (whether it extends
! beyond first principal layer)
call check_Connectivity(Elecs(i))
if ( .not. check_Connectivity(Elecs(i)) ) then
neglect_conn = .true.
end if
call delete(Elecs(i))
end do
if ( neglect_conn ) then
neglect_conn = fdf_get('TS.Elecs.Neglect.Principal', .false.)
if ( .not. neglect_conn ) then
call die('Electrode connectivity is not perfect, refer &
&to the manual for achieving a perfect electrode.')
end if
end if
end if
end subroutine ts_init
......
......@@ -266,6 +266,10 @@ contains
rtmp = rtmp ** 2
#endif
Elecs(:)%Eta = rtmp
rtmp = 1.e-14_dp * eV
rtmp = fdf_get('TS.Elecs.Accuracy',rtmp,'Ry')
rtmp = fdf_get('TBT.Elecs.Accuracy',rtmp,'Ry')
Elecs(:)%accu = rtmp
! whether all calculations should be performed
! "out-of-core" i.e. whether the GF files should be created or not
......
......@@ -383,6 +383,9 @@ contains
dic = ('info'.kv.'Imaginary part of self-energy')//('unit'.kv.'Ry')
call ncdf_def_var(grp,'Eta',NF90_DOUBLE,(/'one'/), atts = dic)
dic = ('info'.kv.'Accuracy of the self-energy')//('unit'.kv.'Ry')
call ncdf_def_var(grp,'Accuracy',NF90_DOUBLE,(/'one'/), atts = dic)
call delete(dic)
call ncdf_def_dim(grp,'no_e',Elecs(iEl)%o_inD%n)
......@@ -399,6 +402,7 @@ contains
call delete(dic)
call ncdf_put_var(grp,'Eta',Elecs(iEl)%Eta)
call ncdf_put_var(grp,'Accuracy',Elecs(iEl)%accu)
call ncdf_put_var(grp,'pivot',Elecs(iEl)%o_inD%r)
end do
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment