2
! Copyright (C) 1996-2016 The SIESTA group
2
! Copyright (C) 1996-2016 The SIESTA group
3
3
! This file is distributed under the terms of the
4
4
! GNU General Public License: see COPYING in the top directory
5
5
! or http://www.gnu.org/copyleft/gpl.txt.
6
6
! See Docs/Contributors.txt for a list of contributors.
11
c****************************************************************************
14
c This program PLSTM reads a charge density or local density of states
15
c generated by SIESTA, and simulates STM images at constant current
16
c or constant height mode using the Tersoff-Hamann approximation.
18
c Written by P. Ordejon, June 2001
19
c Last modification: June 2003
20
c (basic structure from Plrho package of J.M.Soler)
21
c****************************************************************************
24
c This version works assuming that the scanning plane is the XY plane.
25
c This plane must be perpendicular to the third lattice vector of
26
c the supercell (the Z direction).
27
c****************************************************************************
30
c This program reads files generated from SIESTA, with information of
31
c the charge density (filename.RHO) or local density of states (filename.LDOS)
32
c and computes a simulations of STM images, in the Tersoff-Hamann
33
c approximation. Two modes are available: constant current (simulated
34
c by computing a constant density surface z=z(x,y)) and constant hight
35
c (obtaining the charge density at the tip position at a given height).
37
c The program needs two input files:
39
c 1) Main input file, read by standard input. A sample of input file is:
41
c --- begin input file ---
47
c --- end input file ---
50
c - The first line is the label of the system, as in SIESTA SystemLabel.
51
c Files will be searched as SystemLabel.* (in the example, graf.RHO).
52
c - The second line is the task, which should be either rho or ldos
54
c - The third line specifies the STM mode: 'constant-current' or
55
c 'constant-height' (in lowercase).
56
c - The fourth line is a value that determines the details of the
57
c STM image. In the case of 'constant-current' mode, this is the
58
c value of the density (in units of e/bohr**3). at which the isosurface
59
c is computed. For the 'constant-height' mode, the value specifies
60
c the Z (in bohr) level at which the charge is computed.
61
c - The fifth line indicates if the grid data file SystemLabel.TASK
62
c is formatted or unformatted (the latter being the standard option
65
c 2) SystemLabel.TASK file: this is a file generated by SIESTA, with
66
c the values of the appropriate quantity on the grid.
67
c In example above: grid.RHO. You should copy it from the directory
68
c with your SIESTA output files.
70
c The program generates some informative output on standard output,
71
c and writes one file. In the case of 'constant-current' mode,
72
c this file's name is SystemLabel.CC.STM, and contains the X,Y,Z
73
c values of the isosurface (a grid of X,Y and the value of Z(X,Y) of
74
c the isosurface). In the case of 'constant-height' mode, the name
75
c is SystemLabel.CH.STM, and contains the values X,Y,RHO for each
76
c X,Y of the grid, where RHO is the charge computed at the point X,Y,Z
77
c (Z being the hight specified in the input).
79
c If your SIESTA calculation was spin polarized, the program adds
80
c the two spin components, so the output represents the total charge
82
c****************************************************************************
88
integer, parameter :: dp = selected_real_kind(10,100)
90
c maxp : Maximun number of points
91
integer, parameter :: maxp = 10000000
95
. name*75, fform*12, fname*80, oname*80, task*15,
98
. i, ip, is, j, mesh(3), np, nspin, nt, Ind, iz, iy
100
real :: f(maxp,2), fvalue, rho
101
real(dp) :: cell(3,3)
112
if (task .eq. 'ldos') then
113
fname = trim(name)//'.LDOS'
114
else if (task .eq. 'rho') then
115
fname = trim(name)//'.RHO'
117
stop ' ERROR: Task should be RHO or LDOS'
12
! Program PLSTM reads a charge density or local density of states
13
! generated by SIESTA, and simulates STM images at constant-current
14
! or constant-height mode using the Tersoff-Hamann approximation.
16
! Written by P. Ordejon, June 2001
17
! (basic structure from Plrho package of J.M.Soler)
18
! Spin capability and restructuring by Alberto García (March 2019)
22
! This version works assuming that the scanning plane is the XY plane.
23
! This plane must be perpendicular to the third lattice vector of
24
! the supercell (the Z direction).
28
! This program reads grid files generated from SIESTA or other programs
29
! (such as ol-stm/wfs2ldos), with information on the local density of
30
! states (filename.LDOS) and computes a simulated STM image, in the
31
! Tersoff-Hamann approximation. Two modes are available:
32
! constant-current (simulated by computing a constant ldos surface
33
! z=z(x,y)) and constant-height (obtaining the ldos at the tip position
36
! The program uses command-line options. Type 'plstm -h' for usage.
38
! It is possible to analyze just the 'charge', or arbitrary components
39
! of the spin, by using the '-s' or '-v' options.
40
! '-v', followed by a line with three real numbers,
41
! serves to simulate a spin-polarized tip. The scalar product of the
42
! "tip spin vector" and the "local spin vector" is recorded at each point.
44
! The program generates some informative output on standard output,
45
! including valid ranges, and writes one file. In the case of
46
! 'constant-current' mode, this file's name is SystemLabel.*.CC.STM,
47
! and contains the X,Y,Z values of the isosurface (a grid of X,Y and
48
! the value of Z(X,Y) of the isosurface). In the case of
49
! 'constant-height' mode, the name is SystemLabel.*.CH.STM, and
50
! contains the values X,Y,RHO for each X,Y of the grid, where RHO is
51
! the charge (or spin component) computed at the point X,Y,Z (Z being
52
! the height specified in the input).
54
! In the filenames, '*' stands for the 'spin code'
55
! (as entered with the '-s' flag).
57
use m_gridfunc, only: monoclinic_z
58
use m_gridfunc, only: gridfunc_t, read_gridfunc
63
type(gridfunc_t) :: gf
65
integer, parameter :: dp = selected_real_kind(10,100)
67
character(len=200) :: opt_arg
68
character(len=10) :: opt_name
69
integer :: nargs, iostat, n_opts, nlabels
71
logical :: debug = .false.
73
real, allocatable :: rho(:), f2d(:,:)
75
character name*75, fform*12, fname*80, oname*80, task*15, &
77
integer :: i, ip, is, j, mesh(3), np, nspin, nt, Ind, iz, iy
78
integer :: k1, k2, ic, ix
79
real :: fvalue, sx, sy, sz, x, y
81
real(dp) :: zmin, zmax, stepz
83
real(dp) :: cell(3,3), origin(3)
84
real(dp) :: dxdm(2,2) ! 2D plane grid vectors
85
real(dp) :: tip_spin(3)
86
logical :: get_current_range, get_height_range
92
get_current_range = .false.
93
get_height_range = .false.
94
spin_code = 'q' ! default value
99
call getopts('hdz:i:s:v:X:Y:IH',opt_name,opt_arg,n_opts,iostat)
100
if (iostat /= 0) exit
101
select case(opt_name)
105
mode = 'constant-height'
106
read(opt_arg,*) fvalue
108
mode = 'constant-current'
109
read(opt_arg,*) fvalue
111
read(opt_arg,*) spin_code
114
read(opt_arg,*) tip_spin(1:3)
120
get_current_range = .true.
122
get_height_range = .true.
127
write(0,*) "Invalid option: ", opt_arg(1:1)
128
write(0,*) "Use -h option for manual"
135
nargs = command_argument_count()
136
nlabels = nargs - n_opts + 1
137
if (nlabels /= 1) then
138
write(0,*) "Use -h option for manual"
144
call get_command_argument(n_opts,value=fname,status=iostat)
145
if ( iostat /= 0 ) then
146
stop "Cannot get LDOS file"
149
if (spin_code == 'q') then
150
write(0,*) "Using 'total charge' ('q') mode"
153
write(6,*) 'Reading grid data from file ',trim(fname)
155
!! SHOULD MAKE SURE OF THE UNITS... although for plots
156
! it should not make much difference
158
! We might want to try to detect file extension and use
160
call read_gridfunc(fname,gf)
162
np = product(gf%n(1:3))
169
write(6,*) 'Cell vectors (bohr)'
175
write(6,*) 'Grid mesh: ',mesh(1),'x',mesh(2),'x',mesh(3)
177
write(6,*) 'nspin = ',nspin
179
write(6,"(a,3f10.5)") 'Box origin (bohr): ', origin(1:3)
181
if (.not. monoclinic_z(cell)) then
182
write(0,*) 'The cell is not monoclinic with ' // &
183
'c lattice vector along z...'
184
stop " *** Unsuitable cell for STM program"
121
write(6,*) '**********************************************'
122
if (mode .eq. 'constant-current') then
123
write(6,*) 'Calculating STM image in Constant Current mode'
124
write(6,*) 'The STM image is obtained as the isosurface of'
125
write(6,*) 'constant charge density RHO =', fvalue,' e/Bohr**3'
126
oname = trim(name)//'.CC.STM'
127
else if (mode .eq. 'constant-height') then
128
write(6,*) 'Calculating STM image in Constant Height mode'
129
write(6,*) 'The STM image is obtained as the value of the'
130
write(6,*) 'charge at a given tip height Z = ', fvalue, 'Bohr'
131
oname = trim(name)//'.CH.STM'
187
! Note that the last slice with information in the file is
190
zmax = (n3-1) * cell(3,3) / n3 + origin(3)
193
write(6,"(/,a)") "The file contains a single plane of data"
194
write(6,"(/,a)") "Only constant-height mode is allowed"
197
stepz = cell(3,3) / n3
199
write(6,"(a,3f12.5)") "Zmin, Zmax (bohr): ", zmin, zmax
202
if (mode .eq. 'constant-current') then
205
STOP "Constant-current mode not available for n3=1"
208
! It does not make physical sense to get topography
209
! for spin components
210
if (spin_code /= "q") then
211
STOP "Constant-current mode only available " // &
215
else if (mode .eq. 'constant-height') then
218
write(6,"(/,a)") "The file contains a single plane of data"
219
write(6,"(/,a)") "Height set to plane's height"
223
! Check that value is within range
224
if ((fvalue > zmax) .or. (fvalue < zmin)) then
225
STOP 'Z requested is beyond box limits'
133
write(6,*) 'ERROR: mode must be either constant current'
134
write(6,*) ' or constant height (in lower case)'
230
write(6,*) 'ERROR: mode must be either constant-current'
231
write(6,*) ' or constant-height (in lower case)'
137
write(6,*) '**********************************************'
142
write(6,*) 'Reading grid data from file ',trim(fname)
144
open( unit=1, file=fname, status='old', form=fform )
145
if (fform .eq. 'formatted') then
147
read(1,*) mesh, nspin
148
np = mesh(1) * mesh(2) * mesh(3)
149
if (np .gt. maxp) stop 'plrho: parameter maxp too small'
154
read(1,'(e15.6)') (f(Ind+ip,is),ip=1,mesh(1))
162
np = mesh(1) * mesh(2) * mesh(3)
163
C write(6,*) cell,mesh,nspin
164
if (np .gt. maxp) stop 'plrho: parameter maxp too small'
169
read(1) (f(Ind+ip,is),ip=1,mesh(1))
178
write(6,*) 'Cell vectors'
180
write(6,*) cell(1,1),cell(2,1),cell(3,1)
181
write(6,*) cell(1,2),cell(2,2),cell(3,2)
182
write(6,*) cell(1,3),cell(2,3),cell(3,3)
184
write(6,*) 'Grid mesh: ',mesh(1),'x',mesh(2),'x',mesh(3)
186
write(6,*) 'nspin = ',nspin
190
c Get total density if spin polarized
191
if (nspin .eq. 2) then
193
rho = f(ip,1) + f(ip,2)
194
f(ip,2) = f(ip,1) - f(ip,2)
199
c Generate x,y,z surface (dump to output file)
201
if (mode .eq. 'constant-current') then
202
call isocharge( cell, mesh, mesh, f(1,1), fvalue, oname)
204
call isoz( cell, mesh, mesh, f(1,1), fvalue, oname)
210
SUBROUTINE ISOCHARGE( CELL, NMESH, NSPAN, F, FVALUE, ONAME)
212
C *******************************************************************
213
C Calculates the surface z=z(x,y) with constant function value.
214
C The surface is determined by the condition function=value, and
215
C it is printed in a file as x,y,z. The function must
216
C be given in a regular 3-D grid of points.
217
C Notice single precision in this version
219
C Written by P. Ordejon. June 2001.
220
C from plsurf.f (written by J. M. Soler)
221
C ************************* INPUT ***********************************
222
C REAL*8 CELL(3,3) : Unit cell vectors CELL(ixyz,ivector)
223
C INTEGER NMESH(3) : Number of mesh divisions of each vector
224
C INTEGER NSPAN(3) : Physical dimensions of array F
225
C See usage section for more information
226
C REAL F(*) : Function such that F=FVALUE determines
227
C the shape of the solid surface.
228
C REAL FVALUE : Value such that F=FVALUE
229
C determines the shape of the solid surface.
230
C CHARACTER*80 ONAME : Output file name
231
C ************************* OUTPUT **********************************
232
C None. Results are printed on ONAME file
233
C *******************************************************************
236
C Next line is nonstandard but may be suppressed
236
allocate(rho(product(mesh(1:3))))
238
call get_function(nspin, spin_code, mesh, gf%val, &
239
rho, tip_spin, fmin, fmax)
241
select case (spin_code)
243
write(6,*) "Using 'total charge' ('q') mode"
245
write(6,*) "Using 'x-component of spin' ('x') mode"
247
write(6,*) "Using 'y-component of spin' ('y') mode"
249
write(6,*) "Using 'z-component of spin' ('z') mode"
251
write(6,*) "Using 'total spin' ('s') mode"
253
write(6,"(a,3f10.5)") "Using a 'polarized tip' ('-v') " // &
254
"with spin: ", tip_spin(1:3)
257
write(6,"(a,3g20.8,/)") "Range of values of processed function: ", fmin, fmax
259
allocate(f2d(0:mesh(1)-1,0:mesh(2)-1))
261
if (mode .eq. 'constant-current') then
262
write(6,"(/a)") 'Calculating STM image in Constant Current mode'
263
write(6,"(a)") 'The STM image is obtained as the isosurface of'
264
write(6,"(a)") 'constant function value =', fvalue,' e/Bohr**3'
265
! Check that value is within range
266
if ((fvalue > fmax) .or. (fvalue < fmin)) then
267
STOP 'Function value outside range of values in box'
269
oname = trim(fname)// "." // spin_code // '.CC.STM'
271
! Generate x,y,z surface (dump to output file)
272
call isocharge( stepz, origin, mesh, rho, fvalue, f2d)
276
! Dump slice to output file
277
write(6,"(/a)") 'Calculating STM image in Constant Height mode'
278
write(6,"(a)") 'The STM image is obtained as the value of the'
279
write(6,"(a,f9.4,a)") 'charge at a given tip height Z = ', fvalue, 'Bohr'
280
oname = trim(fname)// "." // spin_code // '.CH.STM'
282
call isoz( stepz, origin, mesh, rho, fvalue, f2d )
287
OPEN( unit=2, file=oname )
288
write(6,*) 'Writing STM image in file ', trim(oname)
292
DXDM(IX,IC) = CELL(IX,IC) / MESH(IC)
296
! Possibly use nx, ny multipliers here
297
do k1 = 0, nx*mesh(1) - 1
298
do k2 = 0, ny*mesh(2) - 1
299
x = dxdm(1,1) * k1 + dxdm(1,2) * k2
300
y = dxdm(2,1) * k1 + dxdm(2,2) * k2
303
write(2,*) x, y, f2d(q1,q2)
312
write(0,"(a)") " -------------------"
313
write(0,"(a)") " Usage: plstm [options] LDOSfile"
316
write(0,"(a)") " OPTIONS: "
318
write(0,"(a)") " -h Print this help"
319
write(0,"(a)") " -d Print debugging info"
321
write(0,"(a)") " -i current Constant-current calculation"
322
write(0,"(a)") " with 'current' in e/bohr**3 "
323
write(0,"(a)") " -z height Constant-height calculation"
324
write(0,"(a)") " with 'height' in bohr "
326
write(0,"(a)") " -s {q,x,y,z,s} Spin code (default 'q' for total 'charge')"
327
write(0,"(a)") " (x|y|z) select cartesian components of spin "
328
write(0,"(a)") " s selects total spin magnitude "
329
write(0,"(a)") " -v 'ux uy uz' Tip spin direction for selection of spin component"
330
write(0,"(a)") " The vector (ux,uy,uz) should be normalized"
332
write(0,"(a)") " -X NX Request multiple copies of plot domain along X"
333
write(0,"(a)") " -Y NY Request multiple copies of plot domain along Y"
335
write(0,"(a)") " -H Return range of height (not implemented yet)"
336
write(0,"(a)") " -I Return range of current (not implemented yet)"
337
write(0,"(a)") " -------------------"
339
end subroutine manual
342
subroutine get_function(nspin, spin_code, mesh, f, rho, &
343
tip_spin, fmin, fmax)
345
integer, parameter :: dp = selected_real_kind(10,100)
346
integer, parameter :: sp = kind(1.0)
348
integer, intent(in) :: nspin, mesh(3)
349
real(sp), intent(in) :: f(mesh(1)*mesh(2)*mesh(3),nspin)
350
character(len=1), intent(in) :: spin_code
351
real(dp), intent(in) :: tip_spin(3)
353
real(sp), intent(out) :: rho(mesh(1)*mesh(2)*mesh(3))
354
real(sp), intent(out) :: fmin, fmax
359
np = product(mesh(1:3))
362
select case (spin_code)
363
case ( 'x', 'y', 'z', 's')
364
stop "Cannot choose spin for spin-less file"
366
stop "Cannot use tip spin for spin-less file"
370
else if (nspin == 2) then
371
select case (spin_code)
373
stop "Cannot choose x, y comps for collinear file"
375
stop "Cannot use tip spin for collinear file"
377
rho(:) = f(:,1) + f(:,2)
379
rho(:) = f(:,1) - f(:,2)
381
rho(:) = abs(f(:,1) - f(:,2))
383
else if (nspin == 4) then
384
select case (spin_code)
386
rho(:) = 2.0 * f(:,3)
388
rho(:) = 2.0 * f(:,4)
390
rho(:) = f(:,1) - f(:,2)
392
rho(:) = f(:,1) + f(:,2)
398
rho(i) = sqrt(sx**2 + sy**2 + sz**2)
405
rho(i) = tip_spin(1) * sx + &
413
end subroutine get_function
415
! Some extra optimizations and clarifications are possible in these routines
416
! for a monoclinic cell
418
SUBROUTINE ISOCHARGE( stepz, origin, NMESH, F, FVALUE, f2d)
420
! *******************************************************************
421
! Calculates the surface z=z(x,y) with constant function value.
422
! The surface is determined by the condition function=value, and
423
! it is printed in a file as x,y,z. The function must
424
! be given in a regular 3-D grid of points.
425
! Notice single precision in this version
427
! Written by P. Ordejon. June 2001.
428
! from plsurf.f (written by J. M. Soler)
429
! Modified by A. Garcia, March 2019
430
! ************************* INPUT ***********************************
432
! INTEGER NMESH(3) : Number of mesh divisions of each vector
433
! REAL F(:,:,:) : Function such that F=FVALUE determines
434
! the shape of the solid surface.
435
! REAL FVALUE : Value such that F=FVALUE
436
! determines the shape of the solid surface.
437
! ************************* OUTPUT **********************************
439
! *******************************************************************
239
442
integer, parameter :: dp = selected_real_kind(10,100)
241
C Argument types and dimensions
243
. NMESH(3), NSPAN(3), NT
244
REAL(dp) :: CELL(3,3)
251
C Local variables and arrays
255
. IC, IP, IPM, IX, K1, K2, K3
260
OPEN( unit=2, file=oname)
262
write(6,*) 'Writing STM image in file', trim(oname)
266
C Find Jacobian matrix dx/dmesh and its inverse
269
DXDM(IX,IC) = CELL(IX,IC) / NMESH(IC)
444
INTEGER, intent(in) :: NMESH(3)
445
REAL(DP), intent(in) :: STEPZ
446
REAL(DP), intent(in) :: origin(3)
447
REAL, intent(in) :: F(0:nmesh(1)-1,0:nmesh(2)-1,0:nmesh(3)-1)
448
REAL, intent(in) :: FVALUE
449
REAL, intent(out) :: F2D(0:nmesh(1)-1,0:nmesh(2)-1)
451
! Local variables and arrays
453
INTEGER IC, IX, K1, K2, K3
275
C Loop on mesh points
276
459
DO K1 = 0,NMESH(1)-1
278
C z-direction is scanned from top to bottom
279
DO K3 = NMESH(3)-1,0,-1
281
C Check if all cube vertices are above or below equi-surface.
284
C Find mesh index of this point
285
IP = 1 + K1 + NSPAN(1) * K2 + NSPAN(1) * NSPAN(2) * K3
287
C Find if this point is above FVALUE
288
HIGH = (F(IP) .GT. FVALUE)
291
if (K3 .eq. NMESH(3)-1) stop 'Surface above box boundary!!!'
293
C Linear interpolation to find z-coordinate of surface
295
IPM = 1 + K1 + NSPAN(1)*K2 + NSPAN(1)*NSPAN(2)*(K3+1)
296
ZK3 = (K3+1) - (FVALUE - F(IPM)) / (F(IP) - F(IPM))
299
. ( DXDM(IX,1) * K1 +
301
. DXDM(IX,3) * ZK3 , IX=1,3)
308
. ( DXDM(IX,1) * K1 +
310
. DXDM(IX,3) * ZK3 , IX=1,3)
461
! z-direction is scanned from top to bottom
462
! We assume that the function decreases as z increases
463
! This is reasonable for the charge density, but not
464
! necessarily true for spin components.
465
! We might need to work with absolute values
466
DO K3 = NMESH(3)-1,0,-1
468
!Find if this point is above FVALUE
470
HIGH = ( f_cur .GT. FVALUE)
472
if (HIGH) then ! our point is between k3 and k3+1
473
if (K3 .eq. NMESH(3)-1) then
474
stop 'Surface above box boundary!!!'
476
! Linear interpolation to find z-coordinate of surface
478
! This is a real number in [k3,k3+1]
479
ZK3 = (K3+1) - (FVALUE - f_up) / (f_cur - f_up)
480
f2d(k1,k2) = stepz * zk3 + origin(3)
485
! Note that K3 is zero here, at the end of the loop
486
f2d(k1,k2) = origin(3)
320
write(6,*) 'WARNING: I could not find the isosurface'
321
write(6,*) ' for some X,Y points. For these, I set Z = 0'
493
write(6,*) 'WARNING: I could not find the isosurface'
494
write(6,*) ' for some X,Y points. For these, Z = ZMIN (0)'
327
SUBROUTINE ISOZ( CELL, NMESH, NSPAN, F, ZVALUE, ONAME)
497
END SUBROUTINE ISOCHARGE
499
SUBROUTINE ISOZ( stepz, origin, NMESH, F, ZVALUE, f2d)
329
C *******************************************************************
330
C Calculates the value of the function F at the plane Z=ZVALUE
331
C The function must be given in a regular 3-D grid of points.
332
C Notice single precision in this version
334
C Written by P. Ordejon. June 2001.
335
C from plsurf.f (written by J. M. Soler)
336
C ************************* INPUT ***********************************
337
C REAL*8 CELL(3,3) : Unit cell vectors CELL(ixyz,ivector)
338
C INTEGER NMESH(3) : Number of mesh divisions of each vector
339
C INTEGER NSPAN(3) : Physical dimensions of array F
340
C See usage section for more information
341
C REAL F(*) : Function such that F=FVALUE determines
342
C the shape of the solid surface.
343
C REAL ZVALUE : Z level where the function is written
344
C CHARACTER*80 ONAME : Output file name
345
C ************************* OUTPUT **********************************
346
C None. Results are printed on ONAME file
347
C *******************************************************************
350
C Next line is nonstandard but may be suppressed
501
! Calculates the value of the function F at the plane Z=ZVALUE
502
! The function must be given in a regular 3-D grid of points.
503
! Notice single precision in this version
505
! Written by P. Ordejon. June 2001.
506
! from plsurf.f (written by J. M. Soler)
507
! ************************* INPUT ***********************************
508
! REAL(DP) CELL(3,3) : Unit cell vectors CELL(ixyz,ivector)
509
! INTEGER NMESH(3) : Number of mesh divisions of each vector
510
! REAL F(*) : Function such that F=FVALUE determines
511
! the shape of the solid surface.
512
! REAL ZVALUE : Z level where the function is written
513
! CHARACTER*80 ONAME : Output file name
514
! ************************* OUTPUT **********************************
516
! *******************************************************************
353
520
integer, parameter :: dp = selected_real_kind(10,100)
354
C Argument types and dimensions
356
. NMESH(3), NSPAN(3), NT
357
REAL(dp) :: CELL(3,3)
359
. F(*), ZVALUE, Z, FV, ZM
364
C Local variables and arrays
366
. IC, IP, IPM, IX, K1, K2, K3
371
OPEN( unit=2, file=oname )
373
write(6,*) 'Writing STM image in file', trim(oname)
376
C Find Jacobian matrix dx/dmesh and its inverse
379
DXDM(IX,IC) = CELL(IX,IC) / NMESH(IC)
384
C Loop on mesh points
387
C z-direction is scanned from top to bottom
388
DO K3 = NMESH(3)-1,0,-1
390
C Find mesh index of this point
391
IP = 1 + K1 + NSPAN(1) * K2 + NSPAN(1) * NSPAN(2) * K3
393
C Calculate Z coordinate of this point:
394
Z = DXDM(3,1) * K1 + DXDM(3,2) * K2 + DXDM(3,3) * K3
396
IF (Z .LT. ZVALUE) THEN
398
C Linear interpolation to find the value of F at ZVALUE
400
IPM = 1 + K1 + NSPAN(1)*K2 + NSPAN(1)*NSPAN(2)*(K3+1)
401
ZM = DXDM(3,1) * K1 + DXDM(3,2) * K2 + DXDM(3,3) * (K3+1)
403
FV = F(IPM) + (F(IP)-F(IPM)) * (ZVALUE - ZM) / (Z - ZM)
406
. ( DXDM(IX,1) * K1 +
408
. DXDM(IX,3) * K3 , IX=1,2), FV
522
INTEGER, intent(in) :: NMESH(3)
523
REAL(dp), intent(in) :: STEPZ
524
REAL(dp), intent(in) :: origin(3)
525
REAL, intent(in) :: F(0:nmesh(1)-1,0:nmesh(2)-1,0:nmesh(3)-1)
526
REAL, intent(in) :: ZVALUE
527
REAL, intent(out) :: f2d(0:nmesh(1)-1,0:nmesh(2)-1)
530
INTEGER IC, IP, IPM, IX, K1, K2, K3
534
if (nmesh(3) == 1) then
537
! Loop on mesh points
540
! z-direction is scanned from top to bottom
541
DO K3 = NMESH(3)-1,0,-1
543
! Calculate Z coordinate of this point:
544
Z = stepz * K3 + origin(3)
546
IF (Z .LT. ZVALUE) THEN
548
! Linear interpolation to find the value of F at ZVALUE
552
ZM = stepz * (K3+1) + origin(3)
554
FV = f_up + (f_cur-f_up) * (ZVALUE - ZM) / (Z - ZM)
416
WRITE(6,*) 'Z = ',ZVALUE,
417
. ' not found. It is probably outside your cell'
563
WRITE(6,*) 'Z = ',ZVALUE, &
564
' not found. It is probably outside your cell'