forked from qphensurf/STMpw
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSTMpw.f90
1295 lines (1063 loc) · 42.1 KB
/
STMpw.f90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
program STMpw
!
! Simple implementation for Bardeen's transfer hamiltonian
! and tunneling extension for the STM
!
use declaration
use determinequantities
use volumen
use Fourier
use currentBardeen
use mappingscar_gen
implicit none
! test if input.STMpw exists, if not stop
inquire (file = 'input.STMpw', exist = fichero)
if (fichero) then
! reading input.STMpw
open (8, file = 'input.STMpw', status='old')
read (8,*, IOSTAT=ios, ERR=100,END=200) phi
phi = phi / hartree ! all calculations in atomic units
read (8,*, IOSTAT=ios, ERR=100,END=200) nV
allocate (V(nV))
read (8,*, IOSTAT=ios, ERR=100,END=200) (V(jv),jv=1,nV)
write(*,'(A,30F7.3)') "Voltages to calculate (in V): ",(V(jv),jv=1,nV)
do jv=1,nV
V(jv) = V(jv) / hartree ! all calculations in atomic units
enddo
read (8,*, IOSTAT=ios, ERR=100,END=200) N_sampling_z
read (8,*, IOSTAT=ios, ERR=100,END=200) Zmax
Zmax = Zmax / bohr
read (8,*, IOSTAT=ios, ERR=100,END=200) Zsurf
read (8,*, IOSTAT=ios, ERR=100,END=200) z_s
read (8,*, IOSTAT=ios, ERR=100,END=200) Bardeen
if (Bardeen) then
write(*,'(A)') "Bardeen calculation. NOT TESTED FOR SEVERAL VOLTAGES OR dIdV CURVES!!!"
read (8,*, IOSTAT=ios, ERR=100,END=200) Ztip
else
write(*,'(A)') "Tersoff-Hamman calculation"
Ztip = 100d0
endif
!! matching distance for the tip is hardwired
!! z_t = Ztip - 2.0 Angstroems
! dIdV curve
read (8,*, IOSTAT=ios, ERR=100,END=200) LDIDV !.true. or .false.
if (LDIDV) then
read (8,*, IOSTAT=ios, ERR=100,END=200) Vmin, Vmax
read (8,*, IOSTAT=ios, ERR=100,END=200) ndiv
read (8,*, IOSTAT=ios, ERR=100,END=200) npts
allocate(cdIdV(npts,3))
do i=1,npts
read (8,*, IOSTAT=ios, ERR=100,END=200) (cdIdV(i,j),j=1,3)
enddo
if(npts.gt.1000) then
write(*,'(A)') "We can not calculate more than 1000 dIdV curves."
npts = 1000
endif
cdIdV = cdIdV / bohr
allocate(V1(ndiv+1))
allocate(IV(npts,ndiv+1))
allocate(ngp(npts,3))
write(*,'(A,F7.3,A,F7.3,A)') "Calculation of IV curves between ",Vmin," eV and ",Vmax," eV"
endif
read (8,*, IOSTAT=ios, ERR=100,END=200) NamePOSCAR
read (8,*, IOSTAT=ios, ERR=100,END=200) NameWF
read (8,*, IOSTAT=ios, ERR=100,END=200) MAPfile !.true. or .false.
if (MAPfile) then
read (8,*, IOSTAT=ios, ERR=100,END=200) NameMAP
write(*,'(3A)') "We will use '",trim(adjustl(NameMAP)),"' as MappingsCAR file"
else
read (8,*, IOSTAT=ios, ERR=100,END=200) NameOUTCAR
write(*,'(A)') "We will generate MappingsCAR data from OUTCAR"
endif
read (8,*, IOSTAT=ios, ERR=100,END=200) LGAMMA !.true. or .false.
read (8,*, IOSTAT=ios, ERR=100,END=200) wsxm !.true. or .false.
if(wsxm) read (8,*, IOSTAT=ios, ERR=100,END=200) factor
read (8,*, IOSTAT=ios, ERR=100,END=200) dat !.true. or .false.
read (8,*, IOSTAT=ios, ERR=100,END=200) cube !.true. or .false.
close (8)
else
write(*,*) "You must supply an input.STMpw file."
stop
endif
! end of reading input.STMpw
if(.not.wsxm.AND..not.dat.AND..not.cube.AND..not.LDIDV) then
write(*,'(A)') "No output has been requested. I refuse to work for nothing."
stop
endif
call test_POSCAR !test that matching
! distance is far (<2. Ang) the topmost atom
!determine quantities of the system
call determine_quantities( NameWF, Number_of_SPIN, Total_Bands , &
& Number_of_KPOINTS)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! read WF for constant current computations and elastic contribution
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! first reopen with assumed (wrong) record length ICMPLX
OPEN(UNIT=13,FILE= NameWF,ACCESS='DIRECT', &
FORM='UNFORMATTED',STATUS='UNKNOWN',RECL=ICMPLX)
! the first record contains the record length, get it ...
RDUM=0._q
READ(13,REC=1,ERR=17421) RDUM,RISPIN ; IDUM=NINT(RDUM)
IF ((IDUM<=0).OR.(IDUM>10000000)) IDUM=ICMPLX ! -> error reading
GOTO 17422
17421 CONTINUE
IDUM=ICMPLX
17422 CONTINUE
close (13)
ISPIN = NINT(RISPIN)
! Allocates
ALLOCATE(VKPT(3,Number_of_KPOINTS))
ALLOCATE (FERTOT (Total_Bands, Number_of_KPOINTS, ISPIN))
if (MAPfile) allocate (onpl(ISPIN, Number_of_KPOINTS))
! reopen with correct record length (clumsy all that, I know ...)
! Reciprocal vector and wave index file
unitMAP = 8
! output current units
unitI = 9
unitIdat = 19
! output conductance unit
unitdI = 10
! output conductance unit
unitdIdat = 25
! output current units Tersoff-Hamman
unitTH = 11
unitTHdat = 21
! output conductance unit TH
unitdITHdat = 20
! output current units Tersoff-Hamman for the TIP
unitTIP =12
unitTIPdat =22
! WF input file unit
unitWF = 13
! output current unit Tersoff-Hamman in cube format
unitTHcub = 14
! output current unit Tersoff-Hamman in cube format
unitdITHcub = 15
OPEN(UNIT=unitWF,FILE=NameWF,ACCESS='DIRECT', &
FORM='UNFORMATTED',STATUS='UNKNOWN',RECL=IDUM)
! Record 2 read in lattice
READ(unitWF,REC=2,ERR=200) RKPTSF,RBANDS,ENMAXW, &
& ((A(I,J),I=1,3),J=1,3)
! write(*,*) "RKPTSF,RBANDS,ENMAXW",RKPTSF,RBANDS,ENMAXW
! transformation into atomic units
! of the unit cell vectors
A = A /bohr
! generate reciprocal unit cell
! third dimension in 90 degrees with respect to surface
if (A (1,3) > 0.1 .or. A(2,3) > 0.1 ) then
print *, 'The calculation has to be repeated'
print *, 'with the 3rd axis perpendicular to the surface plane!'
stop
endif
! test on cells to check that ionic positions are the same
! for WAVECAR and POSCAR
! we test that the 3rd axis is the same withing 0.1 Angstroems
!
if (abs (cell(3,3)*lat_par - A(3,3) * bohr) > 0.1 ) then
print *, 'The cells in POSCAR and WAVECAR'
print *, 'are more than 0.1 angstroems different!!'
print *, 'STOP and check the input files!'
stop
endif
call volume (A(:,1),A(:,2),A(:,3),vol)
call surface (A(:,1),A(:,2),surf)
! call reciprocal (A(:,1),A(:,2),A(:,3),vol,vec(:,1),vec(:,2),vec(:,3))
! When reading it from MappingsCAR, you don't need to calculate the
! reciprocal vector:
! Reading MappingsCAR
! Reciprocal vector and wave index file
if(.not.MAPfile) then
call mappings_from_outcar(NameOUTCAR,ENMAXW, ONPL, oerror)
if(oerror.gt.0) then
write(*,'(A)') "Generation of OUTCAR failed"
stop
endif
NameMAP = "MappingsCAR_gen"
endif
open (unitMAP, file = NameMAP, form = 'unformatted' )
read (unitMAP) Efermi
write(*,'(A,F9.4,A)') "Fermi energy at ",Efermi," eV"
Efermi = Efermi / hartree ! all calculations in atomic units
read (unitMAP) NSPIN, NKPTS, NGX, NGY, NGZ
! general allocation
call allocation
! spin factor
if (Number_of_SPIN == 1) then
spin_factor = 2
else
spin_factor = 1
endif
if (NSPIN /= Number_of_SPIN) then
print *, 'WAVECAR and MappingsCAR do not match: '
print *, ' different spin.'
stop
endif
if (NKPTS /= Number_of_KPOINTS) then
print *, 'WAVECAR and MappingsCAR do not match: '
print *, ' different number of K points.'
stop
endif
Zmin = (z_s - Zsurf) * A(3,3)
stepX = sqrt(sum(A(:,1)**2))/(Ngx)
stepY = sqrt(sum(A(:,2)**2))/(Ngy)
! matching point to tip distance
distance = (Ztip-z_t) * A(3,3)
! z is the difference
! between matching points in this program
! in other words: when z=0 the distance
! between tip and sample is the offset
offset = Zmin + distance
stepZ = Zmax / (N_sampling_z-1)
! Hence the initial distance is "offset"
! the maximum distance is "Zmax+offset"
if (LDIDV) then
! do i=1,npts
! if(cdIdV(i,3).lt.z_s*A(3,3)) then
! write(*,'(A)') "We do not calculate de dIdV curves because one point is out of range:"
! write(*,*) cdIdV(i,3)*bohr," < ", z_s*A(3,3)*bohr
! LDIDV = 0
! elseif(cdIdV(i,3).gt.(z_s*A(3,3)+Zmax)) then
! write(*,'(A)') "We do not calculate de dIdV curves because one point is out of range:"
! write(*,*) cdIdV(i,3)*bohr," > ", (z_s*A(3,3)+Zmax)*bohr
! LDIDV = 0
! endif
! enddo
do jv=1,ndiv+1
V1(jv) = Vmin + (Vmax-Vmin)/(ndiv-1)*(jv-1)
V1(jv) = V1(jv) / hartree
! write(*,*) "V(",jv,")=",V1(jv)
enddo
ndiv = ndiv + 1
do iy = 0, ngy
do ix = 0, ngx
cngx(ix,iy)=cell(1,1)*ix/(ngx+1)+cell(2,1)*iy/(ngy+1)
cngy(ix,iy)=cell(1,2)*ix/(ngx+1)+cell(2,2)*iy/(ngy+1)
cngx(ix,iy)=cngx(ix,iy)*lat_par
cngy(ix,iy)=cngy(ix,iy)*lat_par
enddo
enddo
!
write(*,'(A)') "Points to calculate dIdV curves (in angs):"
do i=1,npts
ngp(i,1)=ngx+100
do iy = 0, ngy
do ix = 0, ngx
if(abs(cdIdV(i,1)-cngx(ix,iy)/bohr).lt.stepX/2.AND.abs(cdIdV(i,2)-cngy(ix,iy)/bohr).lt.stepY/2) then
ngp(i,1)=ix
ngp(i,2)=iy
endif
enddo
enddo
if(ngp(i,1).eq.ngx+100) then
write(*,'(A,i4,A)') "We do not calculate de dIdV curves because point",i," is out of range:"
write(*,'(A,2F8.3,A)') "(",(cdIdV(i,j)*bohr,j=1,2),") not in the unit cell."
LDIDV = .false.
endif
ngp(i,3)=N_sampling_z+100
do iz=1,N_sampling_z
if(abs(cdIdV(i,3)-(z_s*A(3,3)+stepZ*(iz-1))).lt.stepZ/2) then
ngp(i,3)=iz
endif
enddo
if(ngp(i,3).eq.N_sampling_z+100) then
write(*,'(A,i4,A)') "We do not calculate de dIdV curves because point",i," is out of range:"
write(*,'(F8.3,A,F8.3,A,F8.3,A)') &
cdIdV(i,3)*bohr," not in [", z_s*A(3,3)*bohr,",",(z_s*A(3,3)+Zmax)*bohr,"]"
LDIDV = .false.
endif
write(*,'(A,i3,A,3F8.3,A)') " Requested point",i," = (",(cdIdV(i,j)*bohr,j=1,3),")"
write(*,'(A,i3,A,3F8.3,A)') " Actual point",i," = (",&
cngx(ngp(i,1),ngp(i,2)),cngy(ngp(i,1),ngp(i,2)),bohr*(z_s*A(3,3)+stepZ*(ngp(i,3)-1)),")"
enddo
endif
!Initialise records
IREC = 2
! compute current as we read WF file
if(Bardeen) then
intensity = 0
dintensity_dV = 0
if(LDIDV) intensity2 = 0
Tersoff_t = 0
endif
Tersoff_c = 0
Tersoff_s = 0
if(LDIDV) Tersoff_s2 = 0
! density_z = 0
!Loop on spin and k-points
SPIN: do spin1=1, Number_of_SPIN
write(*,'(A,i2,A)') " Calculating spin ", spin1, " ..."
KPOINTS: do kp=1, Number_of_KPOINTS
write(*,'(A,i4,A)') " Calculating kpoint ", kp, " ..."
!read in orbitals
IREC = IREC + 1
! eigen energies:
read (unitWF, REC = IREC) RNPL,VKPT (1,kp), &
VKPT (2,kp), VKPT (3,kp), &
(EIG(J),FERTOT(J,kp,spin1),J=1,Total_Bands)
EIG = EIG/hartree - Efermi
NPL=NINT(RNPL)
if(.not.MAPfile) then
if(NPL.ne.onpl(spin1,kp)) then
write(*,'(A)') "The number of planewaves is not the same in WAVECAR and MappingsCAR"
write(*,'(A)') " We can not continue. It might be a problem reading ENCUT from OUTCAR."
write(*,'(A,I9,A,I9)') " NPL from WAVECAR = ", NPL, ", ONPL from MappingsCAR = ", onpl(spin1,kp)
stop
endif
endif
allocate (IGX(NPL),IGY(NPL),IGZ(NPL))
! reciprocal vectors
i = 0
do iy = 1, NGY
do ix = 1, NGX
i = i+1
read (unitMAP) gx (i), gy (i)
enddo
enddo
! reading wave function indices
do i = 1, NPL
read (unitMAP) IGX (i), IGY (i), IGZ (i)
! IGX (i) = mod (IGX (i) + ngx/2, ngx)
! IGY (i) = mod (IGY (i) + ngy/2, ngy)
enddo
! change to atomic units
gx = gx * bohr
gy = gy * bohr
write(*,*) " Reading and matching wavefunctions ..."
t_wf = 0.0_q
t_ma = 0.0_q
call cpu_time(start)
BANDS: do iband=1,Total_Bands
IREC = IREC + 1
CW =(0.0,0.0)
call cpu_time(st_tmp)
read (unitWF, REC = IREC) ( CW (I), I = 1, NPL )
call cpu_time(fi_tmp)
t_wf = t_wf + fi_tmp - st_tmp
!uncomment test on the electron density to check
! that everything is OK
! density on the spot x =0 y =0 and dependence on z
!BEGIN test
! call density(density1,CW,ngx, ngy, ngz, IGX,IGY,IGZ,NPL)
! density_z(:) = density_z(:) + Fermi(dreal(EIG(iband)))*density1(:)/Number_of_KPOINTS
!MID test
! obtain 2-D coefficients for the surface and the tip
! by performing the exponential matching
call cpu_time(st_tmp)
call matching (CW, A_S, C_T, ngx, ngy, ngz, z_s,z_t,IGX,IGY,IGZ,NPL,temp)
call cpu_time(fi_tmp)
t_ma = t_ma + fi_tmp - st_tmp
A_G(:,:,iband)=A_S(:,:)
C_G(:,:,iband)=C_T(:,:)
! close Loop on bands
enddo BANDS
call cpu_time(finish)
write (*,'(A, F8.1, A)') " Time to read and match wavefunctions = ", finish-start, " s"
write (*,'(A, F8.1, A)') " Time to read wavefunctions = ", t_wf, " s"
write (*,'(A, F8.1, A)') " Time to match wavefunctions = ", t_ma, " s"
!END test
! do iz = 1, ngz
! print *, iz, density_z(iz)/vol/(bohr*bohr*bohr)
! enddo
! stop
! Compute the current calculation for all different tip
! positions in the cell and from Z_min to Z_max.
! Loop on tip-surface distances:
call cpu_time(start)
write(*,*) " Computing current ..."
! Loop on voltages
VOLTAGES: do jv = 1, nV
write(*,'(A,F7.3)') " Computing V = ", V(jv)*hartree
Heights: do iz=1,N_sampling_z
z=stepZ*(iz-1)
if (Bardeen) then
! Loop on tip bands
do tband=1,Total_Bands
! Loop on substrate bands
do sband=1,Total_Bands
! Check voltage sign (tip to mass, then positive
! means empty substrate states)
if ( V(jv) < 0 ) then
Fermi_t = 1-Fermi(dreal(EIG(tband)))
Fermi_s = Fermi (dreal(EIG(sband)))
constant_I= - 2 * pi_d /( sqrpi * sigma)
constant_dIdV= 4 * pi_d /( sqrpi * sigma**3)
else
Fermi_t = Fermi(dreal(EIG(tband)))
Fermi_s = 1-Fermi (dreal(EIG(sband)))
constant_I= 2 * pi_d /( sqrpi * sigma)
constant_dIdV= - 4 * pi_d /( sqrpi * sigma**3)
endif
constant_I=spin_factor*constant_I*surf**2/vol**2
constant_dIdV=spin_factor*constant_dIdV*surf**2/vol**2
! before calculating we check for empty states ...
! and energy conservation
if (Fermi_t*Fermi_s > 0.1) then
delta_E = ((dreal(EIG(tband)-EIG(sband)) + V(jv))/sigma) **2
if (delta_E <3.) then
! compute Bardeen's matrix element: currentSQ which is already
! the squared modulus
A_S(:,:)=A_G(:,:,sband)
C_T(:,:)=C_G(:,:,tband)
call matrix_element (A_S,C_T,ngx,ngy,phi,gx,gy,z,currentSQ)
! compute current
if (.not.LGAMMA) then
intensity(:,:,iz,jv) = intensity (:,:,iz,jv) + constant_I * Fermi_t * &
& Fermi_s * currentSQ(:,:) * exp (-delta_E)/ &
& (Number_of_KPOINTS)
elseif (kp == 1) then
intensity(:,:,iz,jv) = intensity (:,:,iz,jv) + constant_I * Fermi_t * &
& Fermi_s * currentSQ(:,:) * exp (-delta_E)/ &
& (2*Number_of_KPOINTS-1)
else
intensity(:,:,iz,jv) = intensity (:,:,iz,jv) + 2.0*constant_I * Fermi_t * &
& Fermi_s * currentSQ(:,:) * exp (-delta_E)/ &
& (2*Number_of_KPOINTS-1)
end if
! compute conductance
if (.not.LGAMMA) then
dintensity_dV(:,:,iz,jv) = dintensity_dV(:,:,iz,jv) + constant_dIdV * Fermi_t * &
& Fermi_s * currentSQ(:,:) * exp (-delta_E) * &
& (dreal(EIG(tband)-EIG(sband)) + V(jv))/ &
& (Number_of_KPOINTS)
elseif (kp == 1) then
dintensity_dV(:,:,iz,jv) = dintensity_dV(:,:,iz,jv) + constant_dIdV * Fermi_t * &
& Fermi_s * currentSQ(:,:) * exp (-delta_E) * &
& (dreal(EIG(tband)-EIG(sband)) + V(jv))/ &
& (2*Number_of_KPOINTS-1)
else
dintensity_dV(:,:,iz,jv) = dintensity_dV(:,:,iz,jv) + 2.0*constant_dIdV * Fermi_t * &
& Fermi_s * currentSQ(:,:) * exp (-delta_E) * &
& (dreal(EIG(tband)-EIG(sband)) + V(jv))/ &
& (2*Number_of_KPOINTS-1)
end if
endif
endif
enddo
enddo
endif ! Bardeen part
! Redo calculation to
! calculate Tersoff-Hamman picture
if ( V(jv) < 0 ) then
constant_I= - 2 * pi_d /( sqrpi * sigma)
else
constant_I= 2 * pi_d /( sqrpi * sigma)
endif
constant_I=spin_factor*constant_I*surf**2/vol**2
! Loop on bands
do tband=1,Total_Bands
if ( V(jv) > 0) then
if (dreal(EIG(tband)) > 0 .and. dreal(EIG(tband)) < V(jv) ) then
A_S(:,:)=A_G(:,:,tband)
C_T(:,:)=C_G(:,:,tband)
call matrix_TH (A_S,C_T,ngx,ngy,phi,gx,gy,z,TH_t,TH_s)
if (.not.LGAMMA) then
Tersoff_c(:,:,iz,jv) = Tersoff_c(:,:,iz,jv) + TH_s (:,:)/vol/ &
& (Number_of_KPOINTS) * exp (-((dreal(EIG(tband)-V(jv))/sigma)**2))&
& * constant_I
if(Bardeen) Tersoff_t(:,:,iz,jv) = Tersoff_t(:,:,iz,jv) + TH_t (:,:)/vol/ &
& (Number_of_KPOINTS)
Tersoff_s(:,:,iz,jv) = Tersoff_s(:,:,iz,jv) + TH_s (:,:)/vol/ &
& (Number_of_KPOINTS)
elseif (kp == 1) then
Tersoff_c(:,:,iz,jv) = Tersoff_c(:,:,iz,jv) + TH_s (:,:)/vol/ &
& (2*Number_of_KPOINTS-1) * exp (-((dreal(EIG(tband)-V(jv))/sigma)**2))&
& * constant_I
if(Bardeen) Tersoff_t(:,:,iz,jv) = Tersoff_t(:,:,iz,jv) + TH_t (:,:)/vol/ &
& (2*Number_of_KPOINTS-1)
Tersoff_s(:,:,iz,jv) = Tersoff_s(:,:,iz,jv) + TH_s (:,:)/vol/ &
& (2*Number_of_KPOINTS-1)
else
Tersoff_c(:,:,iz,jv) = Tersoff_c(:,:,iz,jv) + 2.0*TH_s (:,:)/vol/ &
& (2*Number_of_KPOINTS-1) * exp (-((dreal(EIG(tband)-V(jv))/sigma)**2))&
& * constant_I
if(Bardeen) Tersoff_t(:,:,iz,jv) = Tersoff_t(:,:,iz,jv) + 2.0*TH_t (:,:)/vol/ &
& (2*Number_of_KPOINTS-1)
Tersoff_s(:,:,iz,jv) = Tersoff_s(:,:,iz,jv) + 2.0*TH_s (:,:)/vol/ &
& (2*Number_of_KPOINTS-1)
end if
endif
else
if (dreal(EIG(tband)) < 0 .and. dreal(EIG(tband)) > V(jv) ) then
A_S(:,:)=A_G(:,:,tband)
C_T(:,:)=C_G(:,:,tband)
call matrix_TH (A_S,C_T,ngx,ngy,phi,gx,gy,z,TH_t,TH_s)
if (.not.LGAMMA) then
Tersoff_c(:,:,iz,jv) = Tersoff_c(:,:,iz,jv) + TH_s (:,:)/vol/ &
& (Number_of_KPOINTS) * exp (-((dreal(EIG(tband)-V(jv))/sigma)**2))&
& * constant_I
if(Bardeen) Tersoff_t(:,:,iz,jv) = Tersoff_t(:,:,iz,jv) + TH_t (:,:)/vol/ &
& (Number_of_KPOINTS)
Tersoff_s(:,:,iz,jv) = Tersoff_s(:,:,iz,jv) + TH_s (:,:)/vol/ &
& (Number_of_KPOINTS)
elseif (kp == 1) then
Tersoff_c(:,:,iz,jv) = Tersoff_c(:,:,iz,jv) + TH_s (:,:)/vol/ &
& (2*Number_of_KPOINTS-1) * exp (-((dreal(EIG(tband)-V(jv))/sigma)**2))&
& * constant_I
if(Bardeen) Tersoff_t(:,:,iz,jv) = Tersoff_t(:,:,iz,jv) + TH_t (:,:)/vol/ &
& (2*Number_of_KPOINTS-1)
Tersoff_s(:,:,iz,jv) = Tersoff_s(:,:,iz,jv) + TH_s (:,:)/vol/ &
& (2*Number_of_KPOINTS-1)
else
Tersoff_c(:,:,iz,jv) = Tersoff_c(:,:,iz,jv) + 2.0*TH_s (:,:)/vol/ &
& (2*Number_of_KPOINTS-1) * exp (-((dreal(EIG(tband)-V(jv))/sigma)**2))&
& * constant_I
if(Bardeen) Tersoff_t(:,:,iz,jv) = Tersoff_t(:,:,iz,jv) + 2.0*TH_t (:,:)/vol/ &
& (2*Number_of_KPOINTS-1)
Tersoff_s(:,:,iz,jv) = Tersoff_s(:,:,iz,jv) + 2.0*TH_s (:,:)/vol/ &
& (2*Number_of_KPOINTS-1)
end if
endif
endif
! Loop on bands
enddo
enddo Heights
enddo VOLTAGES
call cpu_time(finish)
write (*,'(A, F8.1, A)') " Time for current = ", finish-start, " s"
! Calculation on dIdV curves
if(LDIDV) then
call cpu_time(start)
write(*,*) " Computing dIdV curves ..."
npts_dIdV: do ip = 1,npts
dIdV: do jv = 1, ndiv
iz=ngp(ip,3)
z=stepZ*(iz-1)
if (Bardeen) then
! Loop on tip bands
do tband=1,Total_Bands
! Loop on substrate bands
do sband=1,Total_Bands
! Check voltage sign (tip to mass, then positive
! means empty substrate states)
if ( V1(jv) < 0 ) then
Fermi_t = 1-Fermi(dreal(EIG(tband)))
Fermi_s = Fermi (dreal(EIG(sband)))
constant_I= - 2 * pi_d /( sqrpi * sigma)
constant_dIdV= 4 * pi_d /( sqrpi * sigma**3)
else
Fermi_t = Fermi(dreal(EIG(tband)))
Fermi_s = 1-Fermi (dreal(EIG(sband)))
constant_I= 2 * pi_d /( sqrpi * sigma)
constant_dIdV= - 4 * pi_d /( sqrpi * sigma**3)
endif
constant_I=spin_factor*constant_I*surf**2/vol**2
constant_dIdV=spin_factor*constant_dIdV*surf**2/vol**2
! before calculating we check for empty states ...
! and energy conservation
if (Fermi_t*Fermi_s > 0.1) then
delta_E = ((dreal(EIG(tband)-EIG(sband)) + V1(jv))/sigma) **2
if (delta_E <3.) then
! compute Bardeen's matrix element: currentSQ which is already
! the squared modulus
A_S(:,:)=A_G(:,:,sband)
C_T(:,:)=C_G(:,:,tband)
call matrix_element (A_S,C_T,ngx,ngy,phi,gx,gy,z,currentSQ)
! compute current
if (.not.LGAMMA) then
intensity2(ip,jv) = intensity2 (ip,jv) + constant_I * Fermi_t * &
& Fermi_s * currentSQ(ngp(ip,1),ngp(ip,2)) * exp (-delta_E)/ &
& (Number_of_KPOINTS)
elseif (kp == 1) then
intensity2(ip,jv) = intensity2 (ip,jv) + constant_I * Fermi_t * &
& Fermi_s * currentSQ(ngp(ip,1),ngp(ip,2)) * exp (-delta_E)/ &
& (2*Number_of_KPOINTS-1)
else
intensity2(ip,jv) = intensity2 (ip,jv) + 2.0*constant_I * Fermi_t * &
& Fermi_s * currentSQ(ngp(ip,1),ngp(ip,2)) * exp (-delta_E)/ &
& (2*Number_of_KPOINTS-1)
end if
endif
endif
enddo
enddo
endif ! Bardeen part
! Redo calculation to
! calculate Tersoff-Hamman picture
if ( V1(jv) < 0 ) then
constant_I= - 2 * pi_d /( sqrpi * sigma)
else
constant_I= 2 * pi_d /( sqrpi * sigma)
endif
constant_I=spin_factor*constant_I*surf**2/vol**2
! Loop on bands
do tband=1,Total_Bands
if ( V1(jv) > 0) then
if (dreal(EIG(tband)) > 0 .and. dreal(EIG(tband)) < V1(jv) ) then
A_S(:,:)=A_G(:,:,tband)
C_T(:,:)=C_G(:,:,tband)
call matrix_TH (A_S,C_T,ngx,ngy,phi,gx,gy,z,TH_t,TH_s)
if (.not.LGAMMA) then
Tersoff_s2(ip,jv) = Tersoff_s2(ip,jv) + TH_s (ngp(ip,1),ngp(ip,2))/vol/ &
& (Number_of_KPOINTS)
elseif (kp == 1) then
Tersoff_s2(ip,jv) = Tersoff_s2(ip,jv) + TH_s (ngp(ip,1),ngp(ip,2))/vol/ &
& (2*Number_of_KPOINTS-1)
else
Tersoff_s2(ip,jv) = Tersoff_s2(ip,jv) + 2.0*TH_s (ngp(ip,1),ngp(ip,2))/vol/ &
& (2*Number_of_KPOINTS-1)
end if
endif
else
if (dreal(EIG(tband)) < 0 .and. dreal(EIG(tband)) > V1(jv) ) then
A_S(:,:)=A_G(:,:,tband)
C_T(:,:)=C_G(:,:,tband)
call matrix_TH (A_S,C_T,ngx,ngy,phi,gx,gy,z,TH_t,TH_s)
if (.not.LGAMMA) then
Tersoff_s2(ip,jv) = Tersoff_s2(ip,jv) + TH_s (ngp(ip,1),ngp(ip,2))/vol/ &
& (Number_of_KPOINTS)
elseif (kp == 1) then
Tersoff_s2(ip,jv) = Tersoff_s2(ip,jv) + TH_s (ngp(ip,1),ngp(ip,2))/vol/ &
& (2*Number_of_KPOINTS-1)
else
Tersoff_s2(ip,jv) = Tersoff_s2(ip,jv) + 2.0*TH_s (ngp(ip,1),ngp(ip,2))/vol/ &
& (2*Number_of_KPOINTS-1)
end if
endif
endif
! Loop on bands
enddo
enddo dIdV
enddo npts_dIdV
call cpu_time(finish)
write (*,'(A, F8.1, A)') " Time for computing dIdV curves = ", finish-start, " s"
endif
deallocate (IGX,IGY,IGZ)
enddo KPOINTS
enddo SPIN
if(.not.MAPfile) then
cmd = 'rm -f MappingsCAR_gen'
call system(cmd)
endif
! output in WSxM format
! *.siesta
! output in ASCII to be converted into STM.dato
! and read by imagen.f into Mathematica
write(*,*) "Writing files ..."
call cpu_time(start)
if(wsxm) write(*,'(A,F8.0)') "Output in WSxM format. Output will be multiplied by ",factor
if(dat) write(*,'(A)') "Output for gnuplot"
if(cube) write(*,'(A)') "Output for TH in cube format"
do jv=1,nV
write(volt,'(F6.3)') V(jv)*hartree
cmd = 'mkdir V_'//trim(adjustl(volt))
call system(cmd)
UCELL = A
UCELL (3,3) = Zmax
if(wsxm) then
name_file = 'V_'//trim(adjustl(volt))//'/Bardeen_V_'//trim(adjustl(volt))//'.siesta'
if (Bardeen) open (unitI,file=name_file, form = 'unformatted')
name_file = 'V_'//trim(adjustl(volt))//'/TH_V_'//trim(adjustl(volt))//'.siesta'
open (unitTH,file=name_file, form = 'unformatted')
name_file = 'V_'//trim(adjustl(volt))//'/TH_tip_V_'//trim(adjustl(volt))//'.siesta'
if (Bardeen) open (unitTIP,file=name_file, form = 'unformatted')
if (Bardeen) write (unitI) UCELL
write (unitTH) UCELL
if (Bardeen) write (unitTIP) UCELL
if (Bardeen) write (unitI) ngx, ngy, N_sampling_z,1
write (unitTH) ngx, ngy, N_sampling_z,1
if (Bardeen) write (unitTIP) ngx, ngy, N_sampling_z,1
do iz= 1, N_sampling_z
do iy = 0, ngy-1
if (Bardeen) write (unitI) (real(abs(intensity (ix,iy,iz,jv))*factor), ix=0,ngx-1)
write (unitTH) (real(Tersoff_s(ix,iy,iz,jv)*factor), ix=0,ngx-1)
if (Bardeen) write (unitTIP) (real(Tersoff_t(ix,iy,iz,jv)*factor), ix=0,ngx-1)
enddo
enddo
if (Bardeen) close (unitI)
close (unitTH)
if (Bardeen) close (unitTIP)
! Output for conductance.
! Output in WSxM format,
! not extremely useful because you can't do a scan on voltage
! but you can get a conductance map
! if (Bardeen) then
! name_file = 'V_'//trim(adjustl(volt))//'/dIdV_Bardeen_V_'//trim(adjustl(volt))//'.siesta'
! open (unitdI,file=name_file, form = 'unformatted')
! write (unitdI) UCELL
! write (unitdI) ngx, ngy, N_sampling_z,1
! do iz= 1, N_sampling_z
! do iy= 0, ngy-1
! write (unitdI) (real(dintensity_dV (ix,iy,iz,jv)*factor), ix=0,ngx-1)
! enddo
! enddo
! close (unitdI)
! endif
endif
if(dat) then
name_file = 'V_'//trim(adjustl(volt))//'/Bardeen.dat'
if (Bardeen) open (unitIdat,file=name_file)
name_file = 'V_'//trim(adjustl(volt))//'/TH.dat'
open (unitTHdat,file=name_file)
name_file = 'V_'//trim(adjustl(volt))//'/TH_tip.dat'
if (Bardeen) open (unitTIPdat,file=name_file)
name_file = 'V_'//trim(adjustl(volt))//'/dIdV_TH.dat'
open (unitdITHdat,file=name_file)
name_file = 'V_'//trim(adjustl(volt))//'/dIdV_Bardeen.dat'
if (Bardeen) open (unitdIdat,file=name_file)
write(unitdITHdat,*) N_sampling_z, ngy, ngx
write(unitTHdat,*) N_sampling_z, ngy, ngx
if (Bardeen) write(unitTIPdat,*) N_sampling_z, ngy, ngx
if (Bardeen) write(unitIdat,*) N_sampling_z, ngy, ngx
if (Bardeen) write(unitdIdat,*) N_sampling_z, ngy, ngx
do iz= 1, N_sampling_z
do iy = 0, ngy-1
do ix = 0, ngx-1
write (unitdITHdat,'(4g14.4)') &
bohr*(Zmin+stepZ*(iz-1)),bohr*(iy)*stepY, bohr*(ix)*stepX, Tersoff_c(ix,iy,iz,jv)
write (unitTHdat,'(4g14.4)') &
bohr*(Zmin+stepZ*(iz-1)),bohr*(iy)*stepY, bohr*(ix)*stepX, Tersoff_s(ix,iy,iz,jv)
if (Bardeen) write (unitTIPdat,'(4g14.4)') &
bohr*(Zmin+stepZ*(iz-1)), bohr*(iy)*stepY, bohr*(ix)*stepX, Tersoff_t(ix,iy,iz,jv)
if (Bardeen) write (unitIdat,'(4g14.4)') &
bohr*(Zmin+stepZ*(iz-1)),bohr*(iy)*stepY, bohr*(ix)*stepX, intensity (ix,iy,iz,jv)
if (Bardeen) write (unitdIdat,'(4g14.4)') &
bohr*(Zmin+stepZ*(iz-1)),bohr*(iy)*stepY, bohr*(ix)*stepX, dintensity_dV (ix,iy,iz,jv)
enddo
enddo
enddo
close(unitTHdat)
if (Bardeen) close(unitTIPdat)
if (Bardeen) close(unitIdat)
if (Bardeen) close(unitdIdat)
close(unitdITHdat)
endif
if (cube) then
name_file = 'V_'//trim(adjustl(volt))//'/TH_V_'//trim(adjustl(volt))//'.cube'
open (unitTHcub,file=name_file)
write(unitTHcub,'(A)') "STM image in TH approximation."
write(unitTHcub,'(3A,F6.3,A)') "V = ",volt," V. z = 0 is at",Zmin*bohr," angs over the surface."
write(unitTHcub,'(i5,3F12.6)') nat, 0.0, 0.0, z_s*cell(3,3)*lat_par/bohr
write(unitTHcub,'(i5,3F12.6)') ngx, (UCELL(j,1)/ngx,j=1,3)
write(unitTHcub,'(i5,3F12.6)') ngy, (UCELL(j,2)/ngy,j=1,3)
write(unitTHcub,'(i5,3F12.6)') N_sampling_z, (UCELL(j,3)/N_sampling_z,j=1,3)
do i=1,nat
write(unitTHcub,'(i5,4F12.6)') zat(i),0.000,(coord(i,j)/bohr,j=1,3)
enddo
do ix = 0, ngx-1
do iy = 0, ngy-1
write(unitTHcub, '(6E13.5)') (Tersoff_s(ix,iy,iz,jv), iz=1,N_sampling_z)
enddo
enddo
close(unitTHcub)
! dIdV
name_file = 'V_'//trim(adjustl(volt))//'/dIdV_TH_V_'//trim(adjustl(volt))//'.cube'
open (unitdITHcub,file=name_file)
write(unitdITHcub,'(A)') "dIdV in TH approximation."
write(unitdITHcub,'(3A,F6.3,A)') "V = ",volt," V. z = 0 is at",Zmin*bohr," angs over the surface."
write(unitdITHcub,'(i5,3F12.6)') nat, 0.0, 0.0, z_s*cell(3,3)*lat_par/bohr
write(unitdITHcub,'(i5,3F12.6)') ngx, (UCELL(j,1)/ngx,j=1,3)
write(unitdITHcub,'(i5,3F12.6)') ngy, (UCELL(j,2)/ngy,j=1,3)
write(unitdITHcub,'(i5,3F12.6)') N_sampling_z, (UCELL(j,3)/N_sampling_z,j=1,3)
do i=1,nat
write(unitdITHcub,'(i5,4F12.6)') zat(i),0.000,(coord(i,j)/bohr,j=1,3)
enddo
do ix = 0, ngx-1
do iy = 0, ngy-1
write(unitdITHcub, '(6E13.5)') (abs(Tersoff_c(ix,iy,iz,jv)), iz=1,N_sampling_z)
enddo
enddo
close(unitdITHcub)
endif
enddo ! Voltages
if (LDIDV) then
cmd = 'mkdir dIdV_curves'
call system(cmd)
do ip=1,npts
unitIV=1000+ip
write(cnpt,'(I6)') ip
name_file = 'dIdV_curves/IV_TH_npt_'//trim(adjustl(cnpt))//'.dat'
open (unitIV,file=name_file)
! write(unitIV,'(A,3F7.3,A)') "# IV for point (",(cdIdV(ip,j)*bohr,j=1,3),")"
write(unitIV,'(A,3F7.3,A)') "# Actual point (", &
cngx(ngp(ip,1),ngp(ip,2)),cngy(ngp(ip,1),ngp(ip,2)),bohr*(z_s*A(3,3)+stepZ*(ngp(ip,3)-1)),")"
do jv=1,ndiv-1
if(V1(jv).lt.0) Tersoff_s2(ip,jv) = -1.0 * Tersoff_s2(ip,jv)
write(unitIV,*) V1(jv)*hartree,Tersoff_s2(ip,jv)
enddo
close (unitIV)
enddo ! points for dIdV
do ip=1,npts
unitIV=2000+ip
write(cnpt,'(I6)') ip
name_file = 'dIdV_curves/dIdV_TH_npt_'//trim(adjustl(cnpt))//'.dat'
open (unitIV,file=name_file)
! write(unitIV,'(A,3F7.3,A)') "# dIdV for point (",(cdIdV(ip,j)*bohr,j=1,3),")"
write(unitIV,'(A,3F7.3,A)') "# Actual point (", &
cngx(ngp(ip,1),ngp(ip,2)),cngy(ngp(ip,1),ngp(ip,2)),bohr*(z_s*A(3,3)+stepZ*(ngp(ip,3)-1)),")"
do jv=1,ndiv-1
write(unitIV,*) V1(jv)*hartree,(Tersoff_s2(ip,jv+1)-Tersoff_s2(ip,jv))/(V1(jv+1)-V1(jv))/hartree
enddo
close (unitIV)
enddo ! points for dIdV
!
if (Bardeen) then
do ip=1,npts
unitIV=3000+ip
write(cnpt,'(I6)') ip
name_file = 'dIdV_curves/IV_Bardeen_npt_'//trim(adjustl(cnpt))//'.dat'
open (unitIV,file=name_file)
! write(unitIV,'(A,3F7.3,A)') "# IV for point (",(cdIdV(ip,j)*bohr,j=1,3),")"
write(unitIV,'(A,3F7.3,A)') "# Actual point (", &
cngx(ngp(ip,1),ngp(ip,2)),cngy(ngp(ip,1),ngp(ip,2)),bohr*(z_s*A(3,3)+stepZ*(ngp(ip,3)-1)),")"
do jv=1,ndiv-1
if(V1(jv).lt.0) intensity2(ip,jv) = -1.0 * intensity2(ip,jv)
write(unitIV,*) V1(jv)*hartree,intensity2(ip,jv)
enddo
close (unitIV)
enddo ! points for dIdV
do ip=1,npts
unitIV=4000+ip
write(cnpt,'(I6)') ip
name_file = 'dIdV_curves/dIdV_Bardeen_npt_'//trim(adjustl(cnpt))//'.dat'
open (unitIV,file=name_file)
! write(unitIV,'(A,3F7.3,A)') "# dIdV for point (",(cdIdV(ip,j)*bohr,j=1,3),")"
write(unitIV,'(A,3F7.3,A)') "# Actual point (", &
cngx(ngp(ip,1),ngp(ip,2)),cngy(ngp(ip,1),ngp(ip,2)),bohr*(z_s*A(3,3)+stepZ*(ngp(ip,3)-1)),")"
do jv=1,ndiv-1
write(unitIV,*) V1(jv)*hartree,(intensity2(ip,jv+1)-intensity2(ip,jv))/(V1(jv+1)-V1(jv))/hartree
enddo
close (unitIV)
enddo ! points for dIdV