Line data Source code
1 : !!****m* ABINIT/m_pptools
2 : !! NAME
3 : !! m_pptools
4 : !!
5 : !! FUNCTION
6 : !! Helper functions used for post-processing.
7 : !!
8 : !! COPYRIGHT
9 : !! Copyright (C) 2002-2026 ABINIT group (MG, ZL, MJV, BXu)
10 : !! This file is distributed under the terms of the
11 : !! GNU General Public License, see ~abinit/COPYING
12 : !! or http://www.gnu.org/copyleft/gpl.txt .
13 : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
14 : !!
15 : !! SOURCE
16 :
17 : #if defined HAVE_CONFIG_H
18 : #include "config.h"
19 : #endif
20 :
21 : #include "abi_common.h"
22 :
23 : MODULE m_pptools
24 :
25 : use defs_basis
26 : use m_errors
27 : use m_abicore
28 : use m_krank
29 :
30 : use m_io_tools, only : open_file
31 : use m_fstrings, only : sjoin, itoa
32 : use m_numeric_tools, only : wrap2_pmhalf
33 :
34 : implicit none
35 :
36 : private
37 :
38 : public :: prmat ! print real(dp) matrices in an attractive format.
39 : public :: write_xsf ! Open file and Write a generic array in the XSF format (XCrysden format)
40 : public :: printxsf ! Write a generic array in the XSF format (XCrysden format)
41 : public :: print_fofr_ri ! Print the [real, imaginary] part of an array
42 : public :: print_fofr_xyzri ! Print the Cartesian coordinates and the [real,imaginary] part of an array
43 : public :: print_fofr_cube ! Print ||fofr|| in CUBE format.
44 : public :: printbxsf ! Print band structure energies in XCrysDen format.
45 : public :: printvtk ! Print band structure energies and velocities in VTK format.
46 :
47 : CONTAINS !===========================================================
48 : !!***
49 :
50 : !!****f* m_pptools/prmat
51 : !! NAME
52 : !! prmat
53 : !!
54 : !! FUNCTION
55 : !! This subroutine prints real*8 matrices in an attractive format.
56 : !!
57 : !! INPUTS
58 : !! mat(mi,nj)= matrix to be printed
59 : !! mi = no rows of mat
60 : !! ni = no rows to print
61 : !! nj = no colums of mat
62 : !! unitm = unit to print to, if not provided std_out is chosen
63 : !!
64 : !! OUTPUT
65 : !! (only writing)
66 : !!
67 : !! SOURCE
68 :
69 624 : subroutine prmat(mat, ni, nj, mi, unitm)
70 :
71 : !Arguments ------------------------------------
72 : !scalars
73 : integer,intent(in) :: mi,ni,nj
74 : integer,intent(in), optional :: unitm
75 : !arrays
76 : real(dp),intent(in) :: mat(mi,nj)
77 :
78 : !Local variables-------------------------------
79 : !scalars
80 : character(len=1000) :: msg
81 : integer,parameter :: nline=10
82 : integer :: ii,jj,jstart,jstop,unitn
83 : ! *************************************************************************
84 :
85 624 : unitn = std_out; if (present(unitm)) unitn = unitm
86 :
87 1248 : do jstart = 1, nj, nline
88 624 : jstop = min(nj, jstart+nline-1)
89 2452 : write(msg, '(3x,10(i4,8x))' ) (jj,jj=jstart,jstop)
90 1248 : call wrtout(unitn,msg)
91 : end do
92 :
93 1872 : do ii = 1,ni
94 3120 : do jstart= 1, nj, nline
95 1248 : jstop = min(nj, jstart+nline-1)
96 2496 : if (jstart==1) then
97 1248 : write(msg, '(i3,1p,10e12.4)' ) ii, (mat(ii,jj),jj=jstart,jstop)
98 1248 : call wrtout(unitn,msg)
99 : else
100 0 : write(msg, '(3x,1p,10e12.4)' ) (mat(ii,jj),jj=jstart,jstop)
101 0 : call wrtout(unitn,msg)
102 : end if
103 : end do
104 : end do
105 :
106 624 : end subroutine prmat
107 : !!***
108 :
109 : !----------------------------------------------------------------------
110 :
111 : !!****f* m_pptools/write_xsf
112 : !! NAME
113 : !! write_xsf
114 : !!
115 : !! FUNCTION
116 : !! Open file and write a generic array in the XSF format (XCrysden format)
117 : !! See printxsf for the meaning of the arguments.
118 : !!
119 : !! OUTPUT
120 : !! Only write
121 : !!
122 : !! SOURCE
123 :
124 8 : subroutine write_xsf(filepath, n1, n2, n3, datagrid, basis, origin, natom, ntypat, typat, xcart, znucl, realrecip)
125 :
126 : !Arguments ------------------------------------
127 : !scalars
128 : character(len=*),intent(in) :: filepath
129 : integer,intent(in) :: n1, n2, n3, realrecip, natom, ntypat
130 : !arrays
131 : integer,intent(in) :: typat(natom)
132 : real(dp),intent(in) :: basis(3,3), datagrid(n1*n2*n3), origin(3), xcart(3,natom), znucl(ntypat)
133 :
134 : !Local variables-------------------------------
135 : integer :: ount
136 : character(len=500) :: msg
137 : ! *************************************************************************
138 :
139 8 : if (open_file(filepath, msg, newunit=ount, form='formatted', status='unknown', action="write") /= 0) then
140 0 : ABI_ERROR(msg)
141 : end if
142 :
143 8 : call printxsf(n1, n2, n3, datagrid, basis, origin, natom, ntypat, typat, xcart, znucl, ount, realrecip)
144 8 : close(ount)
145 :
146 8 : end subroutine write_xsf
147 : !!***
148 :
149 : !----------------------------------------------------------------------
150 :
151 : !!****f* m_pptools/printxsf
152 : !! NAME
153 : !! printxsf
154 : !!
155 : !! FUNCTION
156 : !! Write a generic array in the XSF format (XCrysden format)
157 : !!
158 : !! INPUTS
159 : !! n1, n2, n3=grid size along x, y, z
160 : !! datagrid(n1*n2*n3) = datagrid values stored using the fortran convention
161 : !! basis(3,3) = basis vectors of the direct real lattice or of the reciprocal lattice (fortran convention)
162 : !! (Bohr units if realrecip=0, Bohr^-1 if realrecip=1, see below)
163 : !! origin(3) = origin of the grid
164 : !! ount = unit number of the output file (already open by the caller, not closed here!)
165 : !! realrecip = 0 for a plot in real space
166 : !! 1 for a plot in reciprocal space
167 : !!
168 : !! OUTPUT
169 : !! Only write
170 : !!
171 : !! SOURCE
172 :
173 20 : subroutine printxsf(n1, n2, n3, datagrid, basis, origin, natom, ntypat, typat, xcart, znucl, ount, realrecip)
174 :
175 : !Arguments ------------------------------------
176 : !scalars
177 : integer,intent(in) :: n1, n2, n3, ount, realrecip, natom, ntypat
178 : !arrays
179 : integer,intent(in) :: typat(natom)
180 : real(dp),intent(in) :: basis(3,3), datagrid(n1*n2*n3), origin(3), xcart(3,natom), znucl(ntypat)
181 :
182 : !Local variables-------------------------------
183 : !scalars
184 : integer :: ix,iy,iz,nslice,nsym,iatom
185 : real(dp) :: fact
186 : !arrays
187 40 : real(dp) :: tau(3,natom)
188 : ! *************************************************************************
189 :
190 20 : if (all(realrecip /= [0, 1])) then
191 0 : ABI_BUG(sjoin('The argument realrecip should be 0 or 1, received:', itoa(realrecip)))
192 : end if
193 :
194 : ! conversion between ABINIT default units and XCrysden units
195 20 : fact = Bohr_Ang; if (realrecip == 1) fact=one/fact ! since we are in reciprocal space
196 :
197 : ! TODO insert crystalline structure and dummy atoms in case of reciprocal space need to convert basis too
198 20 : write(ount,'(1X,A)') 'DIM-GROUP'
199 20 : write(ount,*) '3 1'
200 20 : write(ount,'(1X,A)') 'PRIMVEC'
201 80 : do iy = 1,3
202 260 : write(ount,'(3(ES17.10,2X))') (Bohr_Ang*basis(ix,iy), ix=1,3)
203 : end do
204 :
205 : ! generate translated coordinates to fit origin shift
206 9144 : do iatom = 1,natom
207 36516 : tau(:,iatom) = xcart(:,iatom) - origin(:)
208 : end do
209 :
210 20 : write(ount,'(1X,A)') 'PRIMCOORD'
211 20 : write(ount,*) natom, ' 1'
212 9144 : do iatom = 1,natom
213 9124 : write(ount,'(i9,3(3X,ES17.10))') NINT(znucl(typat(iatom))), & ! WARNING alchemy not supported by XCrysden
214 18268 : Bohr_Ang*tau(1,iatom), Bohr_Ang*tau(2,iatom), Bohr_Ang*tau(3,iatom)
215 : end do
216 20 : write(ount,'(1X,A)') 'ATOMS'
217 9144 : do iatom = 1,natom
218 9124 : write(ount,'(i9,3(3X,ES17.10))') NINT(znucl(typat(iatom))), & ! WARNING alchemy not supported by XCrysden
219 18268 : Bohr_Ang*tau(1,iatom), Bohr_Ang*tau(2,iatom), Bohr_Ang*tau(3,iatom)
220 : end do
221 :
222 20 : write(ount,'(a)')' BEGIN_BLOCK_DATAGRID3D'
223 20 : write(ount,'(a)')' datagrid'
224 20 : write(ount,'(a)')' DATAGRID_3D_DENSITY'
225 : ! NOTE: XCrysden uses aperiodical data grid
226 20 : write(ount,*)n1+1,n2+1,n3+1
227 20 : write(ount,*)origin
228 80 : write(ount,*)basis(:,1)*fact
229 80 : write(ount,*)basis(:,2)*fact
230 80 : write(ount,*)basis(:,3)*fact
231 :
232 20 : nslice=1
233 626 : do iz=1,n3
234 27624 : do iy=1,n2
235 27018 : write(ount,'(8es16.8)') datagrid(1+n1*(nslice-1):n1+n1*(nslice-1)),datagrid(1+n1*(nslice-1))
236 27624 : nslice = nslice+1
237 : end do
238 606 : nsym=nslice-n2
239 626 : write(ount,'(8es16.8)') datagrid(1+n1*(nsym-1):n1+n1*(nsym-1)),datagrid(1+n1*(nsym-1))
240 : end do
241 :
242 : ! Now write upper plane
243 : nslice = 1
244 626 : do iy=1,n2
245 606 : write(ount,'(8es16.8)') datagrid(1+n1*(nslice-1):n1+n1*(nslice-1)),datagrid(1+n1*(nslice-1))
246 626 : nslice=nslice+1
247 : end do
248 :
249 20 : nsym = nslice-n2
250 20 : write(ount,'(8es16.8)') datagrid(1+n1*(nsym-1):n1+n1*(nsym-1)),datagrid(1+n1*(nsym-1))
251 :
252 20 : write(ount,'(a)')' END_DATAGRID_3D'
253 20 : write(ount,'(a)')' END_BLOCK_DATAGRID3D'
254 :
255 20 : end subroutine printxsf
256 : !!***
257 :
258 : !----------------------------------------------------------------------
259 :
260 : !!****f* m_pptools/print_fofr_ri
261 : !! NAME
262 : !! print_fofr_ri
263 : !!
264 : !! FUNCTION
265 : !! Print the [real,imaginary] part of fofr on unit unit
266 : !!
267 : !! INPUTS
268 : !! ri_mode =
269 : !! "RI" if both real and imag part are wanted
270 : !! "R" for real part
271 : !! "I" for imaginary part
272 : !! nx,ny,nz,ldx,ldy,ldz = Logical and physical dimensions of the array.
273 : !! fofr(2,ldx,ldy,ldz) = Input data
274 : !! [unit] = Fortran unit number. Default: std_out
275 : !!
276 : !! OUTPUT
277 : !! Only writing
278 : !!
279 : !! SOURCE
280 :
281 2 : subroutine print_fofr_ri(ri_mode,nx,ny,nz,ldx,ldy,ldz,fofr,unit)
282 :
283 : !Arguments -----------------------------------------------
284 : !scalars
285 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz
286 : integer,optional,intent(in) :: unit
287 : character(len=*),intent(in) :: ri_mode
288 : !arrays
289 : real(dp),intent(in) :: fofr(2,ldx,ldy,ldz)
290 :
291 : !Local variables-------------------------------
292 : integer :: ount,ix,iy,iz
293 : ! *************************************************************************
294 :
295 2 : ount = std_out; if (PRESENT(unit)) ount = unit
296 :
297 1 : SELECT CASE (ri_mode)
298 : CASE ("RI","ri")
299 13 : do iz=1,nz
300 157 : do iy=1,ny
301 1884 : do ix=1,nx
302 1872 : write(ount,'(2f20.16)') fofr(:,ix,iy,iz)
303 : end do
304 : end do
305 : end do
306 :
307 : CASE ("R","r")
308 25 : do iz=1,nz
309 409 : do iy=1,ny
310 4248 : do ix=1,nx
311 4224 : write(ount,'(f20.16)') fofr(1,ix,iy,iz)
312 : end do
313 : end do
314 : end do
315 :
316 : CASE ("I","i")
317 0 : do iz=1,nz
318 0 : do iy=1,ny
319 0 : do ix=1,nx
320 0 : write(ount,'(f20.16)') fofr(2,ix,iy,iz)
321 : end do
322 : end do
323 : end do
324 :
325 : CASE DEFAULT
326 2 : ABI_ERROR("Wrong ri_mode")
327 : END SELECT
328 :
329 2 : end subroutine print_fofr_ri
330 : !!***
331 :
332 : !----------------------------------------------------------------------
333 :
334 : !!****f* m_pptools/print_fofr_xyzri
335 : !! NAME
336 : !! print_fofr_xyzri
337 : !!
338 : !! FUNCTION
339 : !! Print the Cartesian coordinates and the [real,imaginary] part of fofr on unit unit
340 : !!
341 : !! INPUTS
342 : !! ri_mode =
343 : !! "RI" if both real and imag part are wanted
344 : !! "R" for real part
345 : !! "I" for imaginary part
346 : !! nx,ny,nz,ldx,ldy,ldz = Logical and physical dimensions of the array.
347 : !! fofr(2,ldx,ldy,ldz) = Input data
348 : !! rprimd(3,3)=Lattive vectors in Bohr
349 : !! [conv_fact] = Conversion factor for rprimd (rprimd is multiplied by conv_fact). Default is one
350 : !! [unit] = Fortran unit number. Default: std_out
351 : !!
352 : !! OUTPUT
353 : !! Only writing
354 : !!
355 : !! SOURCE
356 :
357 1 : subroutine print_fofr_xyzri(ri_mode,nx,ny,nz,ldx,ldy,ldz,fofr,rprimd,conv_fact,unit)
358 :
359 : !Arguments -----------------------------------------------
360 : !scalars
361 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz
362 : integer,optional,intent(in) :: unit
363 : real(dp),optional,intent(in) :: conv_fact
364 : character(len=*),intent(in) :: ri_mode
365 : !arrays
366 : real(dp),intent(in) :: rprimd(3,3)
367 : real(dp),intent(in) :: fofr(2,ldx,ldy,ldz)
368 :
369 : !Local variables-------------------------------
370 : !scalars
371 : integer :: ount,ix,iy,iz
372 : real(dp) :: xnow,ynow,znow,my_cfact
373 : ! *************************************************************************
374 :
375 1 : ount = std_out; if (PRESENT(unit)) ount = unit
376 1 : my_cfact = one; if (PRESENT(conv_fact)) my_cfact = conv_fact
377 :
378 1 : SELECT CASE (ri_mode)
379 : CASE ("RI","ri")
380 13 : do iz=1,nz
381 157 : do iy=1,ny
382 1884 : do ix=1,nx
383 1728 : xnow = rprimd(1,1)*(ix-1)/nx + rprimd(1,2)*(iy-1)/ny + rprimd(1,3)*(iz-1)/nz
384 1728 : ynow = rprimd(2,1)*(ix-1)/nx + rprimd(2,2)*(iy-1)/ny + rprimd(2,3)*(iz-1)/nz
385 1728 : znow = rprimd(3,1)*(ix-1)/nx + rprimd(3,2)*(iy-1)/ny + rprimd(3,3)*(iz-1)/nz
386 1872 : write(ount,'(3f16.10,2f20.16)') my_cfact*xnow, my_cfact*ynow, my_cfact*znow,fofr(:,ix,iy,iz)
387 : end do
388 : end do
389 : end do
390 :
391 : CASE ("R","r")
392 0 : do iz=1,nz
393 0 : do iy=1,ny
394 0 : do ix=1,nx
395 0 : xnow = rprimd(1,1)*(ix-1)/nx + rprimd(1,2)*(iy-1)/ny + rprimd(1,3)*(iz-1)/nz
396 0 : ynow = rprimd(2,1)*(ix-1)/nx + rprimd(2,2)*(iy-1)/ny + rprimd(2,3)*(iz-1)/nz
397 0 : znow = rprimd(3,1)*(ix-1)/nx + rprimd(3,2)*(iy-1)/ny + rprimd(3,3)*(iz-1)/nz
398 0 : write(ount,'(3f16.10,f20.16)') my_cfact*xnow, my_cfact*ynow, my_cfact*znow,fofr(1,ix,iy,iz)
399 : end do
400 : end do
401 : end do
402 :
403 : CASE ("I","i")
404 0 : do iz=1,nz
405 0 : do iy=1,ny
406 0 : do ix=1,nx
407 0 : xnow = rprimd(1,1)*(ix-1)/nx + rprimd(1,2)*(iy-1)/ny + rprimd(1,3)*(iz-1)/nz
408 0 : ynow = rprimd(2,1)*(ix-1)/nx + rprimd(2,2)*(iy-1)/ny + rprimd(2,3)*(iz-1)/nz
409 0 : znow = rprimd(3,1)*(ix-1)/nx + rprimd(3,2)*(iy-1)/ny + rprimd(3,3)*(iz-1)/nz
410 0 : write(ount,'(3f16.10,f20.16)') my_cfact*xnow, my_cfact*ynow, my_cfact*znow,fofr(2,ix,iy,iz)
411 : end do
412 : end do
413 : end do
414 :
415 : CASE DEFAULT
416 1 : ABI_ERROR("Wrong ri_mode")
417 : END SELECT
418 :
419 1 : end subroutine print_fofr_xyzri
420 : !!***
421 :
422 : !----------------------------------------------------------------------
423 :
424 : !!****f* m_pptools/print_fofr_cube
425 : !! NAME
426 : !! print_fofr_cube
427 : !!
428 : !! FUNCTION
429 : !! Print array fofr in the cube file format
430 : !!
431 : !! INPUTS
432 : !! nx,ny,nz,ldx,ldy,ldz = Logical and physical dimensions of the array.
433 : !! fofr(2,ldx,ldy,ldz) = Input data
434 : !! rprimd(3,3)=Lattive vectors in Bohr
435 : !! [unit] = Fortran unit number. Default: std_out
436 : !!
437 : !! OUTPUT
438 : !! Only writing
439 : !!
440 : !! SOURCE
441 :
442 :
443 1 : subroutine print_fofr_cube(nx,ny,nz,ldx,ldy,ldz,fofr,rprimd,natom,znucl_atom,xcart,unit)
444 :
445 : !Arguments -----------------------------------------------
446 : !scalars
447 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,natom
448 : integer,optional,intent(in) :: unit
449 : !arrays
450 : integer,intent(in) :: znucl_atom(natom)
451 : real(dp),intent(in) :: rprimd(3,3),xcart(3,natom)
452 : real(dp),intent(in) :: fofr(2,ldx,ldy,ldz)
453 :
454 : !Local variables-------------------------------
455 : !scalars
456 : integer,parameter :: cplx=2
457 : integer :: ount,ix,iy,iz,iatom
458 : ! *************************************************************************
459 :
460 1 : ount = std_out; if (PRESENT(unit)) ount = unit
461 :
462 : ! EXAMPLE FROM THE WEB
463 : ! CPMD CUBE FILE.
464 : ! OUTER LOOP: X, MIDDLE LOOP: Y, INNER LOOP: Z
465 : ! 3 0.000000 0.000000 0.000000
466 : ! 40 0.283459 0.000000 0.000000
467 : ! 40 0.000000 0.283459 0.000000
468 : ! 40 0.000000 0.000000 0.283459
469 : ! 8 0.000000 5.570575 5.669178 5.593517
470 : ! 1 0.000000 5.562867 5.669178 7.428055
471 : ! 1 0.000000 7.340606 5.669178 5.111259
472 : ! -0.25568E-04 0.59213E-05 0.81068E-05 0.10868E-04 0.11313E-04 0.35999E-05
473 :
474 1 : write(ount,'(a)') 'ABINIT generated cube file'
475 1 : write(ount,'(a)') 'from cut3d tool'
476 :
477 1 : write(ount,'(i9,3(1x,f12.6))') natom,0.,0.,0.
478 4 : write(ount,'(i9,3(1x,f12.6))') nx,(rprimd(iy,1)/nx, iy=1,3)
479 4 : write(ount,'(i9,3(1x,f12.6))') ny,(rprimd(iy,2)/ny, iy=1,3)
480 4 : write(ount,'(i9,3(1x,f12.6))') nz,(rprimd(iy,3)/nz, iy=1,3)
481 :
482 2 : do iatom=1,natom
483 2 : write(ount,'(i9,4(3X,ES17.10))') znucl_atom(iatom),0.d0,xcart(1:3,iatom)
484 : end do
485 :
486 : ! Note C ordering of the indexes
487 : if (cplx==2) then
488 17 : do ix=1,nx
489 273 : do iy=1,ny
490 4368 : do iz=1,nz
491 4352 : write(ount,'(6(f12.6,2x))') sqrt(fofr(1,ix,iy,iz)**2 + fofr(2,ix,iy,iz)**2 )
492 : end do
493 : end do
494 : end do
495 : else
496 : do ix=1,nx
497 : do iy=1,ny
498 : do iz=1,nz
499 : write(ount,'(6(f12.6,2x))') fofr(1,ix,iy,iz)
500 : end do
501 : end do
502 : end do
503 : end if
504 :
505 1 : end subroutine print_fofr_cube
506 : !!***
507 :
508 : !----------------------------------------------------------------------
509 :
510 : !!****f* m_pptools/printbxsf
511 : !! NAME
512 : !! printbxsf
513 : !!
514 : !! FUNCTION
515 : !! Print band structure energies in XCrysDen format.
516 : !!
517 : !! INPUTS
518 : !! eigen(mband,nkpt,nsppol) = eigenvalues in hartree
519 : !! ewind = energy window around the fermi level.
520 : !! if ewind /= 0 ==> a band is considered in the plot of FSurf
521 : !! only if it is inside [ ef-ewind, ef+ewind ] for some k point
522 : !! if ewind == 0 ==> all bands will be keept in the _BXSF file
523 : !! fermie = Fermi energy (Hartree)
524 : !! gprimd(3,3) = dimensional primitive translations for reciprocal space (bohr^-1)
525 : !! kptrlatt(3,3) = reciprocal of lattice vectors for full kpoint grid
526 : !! mband = maximum number of bands
527 : !! nsppol = 1 for unpolarized, 2 for spin-polarized
528 : !! shiftk(3,nshiftk) =shift vector for k point grid
529 : !! fname = filename for the fortran file
530 : !! symafm(nsym)=(Anti)ferromagnetic symmetries.
531 : !! use_afm=.TRUE. if (anti)ferromagnetic symmetries are used.
532 : !!
533 : !! OUTPUT
534 : !! ierr=Status error.
535 : !! BXSF file.
536 : !!
537 : !! SOURCE
538 :
539 3 : subroutine printbxsf(eigen,ewind,fermie,gprimd,kptrlatt,mband,&
540 3 : nkptirred,kptirred,nsym,use_afm,symrec,symafm,use_tr,nsppol,shiftk,nshiftk,fname,ierr)
541 :
542 : !Arguments ------------------------------------
543 : !scalars
544 : integer,intent(in) :: mband,nkptirred,nshiftk,nsppol,nsym
545 : integer,intent(out) :: ierr
546 : real(dp),intent(in) :: ewind,fermie
547 : logical,intent(in) :: use_afm,use_tr
548 : character(len=*),intent(in) :: fname
549 : !arrays
550 : integer,intent(in) :: kptrlatt(3,3),symafm(nsym),symrec(3,3,nsym)
551 : real(dp),intent(in) :: eigen(mband,nkptirred,nsppol),gprimd(3,3)
552 : real(dp),intent(in) :: kptirred(3,nkptirred),shiftk(3,nshiftk)
553 :
554 : !Local variables-------------------------------
555 : !scalars
556 : integer,parameter :: enough = 50
557 : integer :: iband,ik1,ik2,ik3,ikgrid,ikpt,indx
558 : integer :: isppol,isym,maxband,minband,nk1,nk2,nk3,nkptfull,ubxsf,timrev
559 : integer :: symkptrank, nsymfm, isymfm
560 : real(dp) :: ene
561 : character(len=500) :: msg
562 3 : type(krank_t) :: krank
563 : !arrays
564 3 : integer,allocatable :: fulltoirred(:),symrecfm(:,:,:)
565 : real(dp) :: kptgrid(3),gmet(3,3)
566 : ! *************************************************************************
567 :
568 3 : ierr = 0
569 :
570 : ! Error if klatt is no simple orthogonal lattice (in red space)
571 : ! for generalization to MP grids, need new version of XCrysDen
572 : if (kptrlatt(1,2)/=0 .or. kptrlatt(1,3)/=0 .or. kptrlatt(2,1)/=0 .or. &
573 3 : kptrlatt(2,3)/=0 .or. kptrlatt(3,1)/=0 .or. kptrlatt(3,2)/=0 ) then
574 : write(msg,'(3a)')&
575 0 : 'kptrlatt should be diagonal, for the FS calculation ',ch10,&
576 0 : 'Action: use an orthogonal k-grid for the GS calculation '
577 0 : ABI_COMMENT(msg)
578 0 : ierr = ierr + 1
579 : end if
580 :
581 : ! Error if there are not at least 2 kpts in each direction:
582 : ! kptrank will fail for the intermediate points below
583 3 : if (abs(kptrlatt(1,1)) < 2 .or. abs(kptrlatt(2,2)) < 2 .or. abs(kptrlatt(3,3)) < 2) then
584 : write(msg,'(3a)')&
585 0 : 'You need at least 2 points in each direction in k space to output BXSF files ',ch10,&
586 0 : 'Action: use an augmented k-grid for the GS calculation (at least 2x2x2) '
587 0 : ABI_COMMENT(msg)
588 0 : ierr = ierr + 1
589 : end if
590 :
591 15 : if (ANY(ABS(shiftk) > tol10)) then
592 : write(msg,'(3a)')&
593 0 : 'Origin of the k-grid should be (0,0,0) for the FS calculation ',ch10,&
594 0 : 'Action: use a non-shifted k-grid for the GS calculation. Returning '
595 0 : ABI_COMMENT(msg)
596 0 : ierr = ierr + 1
597 : end if
598 :
599 3 : if (ierr /= 0) return
600 :
601 : ! Compute reciprocal space metric.
602 3 : gmet = MATMUL(TRANSPOSE(gprimd), gprimd)
603 :
604 3 : if (use_afm) then
605 0 : nsymfm = 0
606 0 : do isym = 1, nsym
607 0 : if (symafm(isym) == 1) nsymfm = nsymfm+1
608 : end do
609 0 : ABI_MALLOC(symrecfm, (3,3,nsymfm))
610 0 : isymfm = 0
611 0 : do isym = 1, nsym
612 0 : if (symafm(isym) == 1) then
613 0 : isymfm = isymfm + 1
614 0 : symrecfm(:,:,isymfm) = symrec(:,:,isym)
615 : end if
616 : end do
617 : else
618 3 : nsymfm = nsym
619 9 : ABI_MALLOC(symrecfm, (3,3,nsymfm))
620 1566 : symrecfm = symrec
621 : end if
622 :
623 : ! Xcrysden uses aperiodic data-grid (images are included in the grid)
624 3 : nk1 = kptrlatt(1,1); nk2 = kptrlatt(2,2); nk3 = kptrlatt(3,3)
625 3 : nkptfull = (nk1+1) * (nk2+1) * (nk3+1)
626 :
627 9 : ABI_MALLOC(fulltoirred, (nkptfull))
628 3 : timrev = 0; if (use_tr) timrev=1
629 :
630 3 : call krank%init(nkptirred, kptirred, nsym=nsymfm, symrec=symrecfm, time_reversal=use_tr)
631 :
632 : ! Xcrysden employs the C-ordering for the Fermi Surface (x-y-z)
633 3 : ikgrid=0
634 38 : do ik1=0,nk1
635 489 : do ik2=0,nk2
636 6857 : do ik3=0,nk3
637 :
638 6371 : ikgrid = ikgrid+1
639 6371 : kptgrid(1) = DBLE(ik1)/kptrlatt(1,1)
640 6371 : kptgrid(2) = DBLE(ik2)/kptrlatt(2,2)
641 6371 : kptgrid(3) = DBLE(ik3)/kptrlatt(3,3)
642 :
643 : ! Find correspondence between the Xcrysden grid and the IBZ
644 6371 : symkptrank = krank%get_rank(kptgrid)
645 6371 : fulltoirred(ikgrid) = krank%invrank(symkptrank)
646 :
647 6822 : if (fulltoirred(ikgrid) < 1) then
648 0 : if (ierr <= enough) then
649 : write(msg,'(a,3es16.8,2a,i0,2a)')&
650 0 : 'kpt = ',kptgrid,ch10,' with rank ', symkptrank, ch10,&
651 0 : 'has no symmetric among the k-points used in the GS calculation '
652 0 : ABI_WARNING(msg)
653 : end if
654 0 : ierr = ierr + 1
655 : end if
656 :
657 : end do !ik1
658 : end do !ik2
659 : end do !ik3
660 :
661 3 : call krank%free()
662 :
663 3 : ABI_CHECK(ierr == 0, "See above warnings")
664 :
665 3 : if (abs(ewind) < tol12 ) then
666 : ! Keep all bands.
667 3 : minband=1
668 3 : maxband=mband
669 : else
670 : ! Select a subset of bands.
671 0 : minband = mband
672 0 : maxband = 0
673 0 : ene=abs(ewind)
674 0 : do isppol=1,nsppol
675 0 : do iband=1,mband
676 0 : if(minval(eigen(iband,:,isppol))-fermie < -ene) minband = iband
677 : end do
678 0 : do iband=mband,1,-1
679 0 : if (maxval(eigen(iband,:,isppol))-fermie > ene) maxband = iband
680 : end do
681 : end do ! isppol
682 :
683 : end if ! abs(energy_window)
684 :
685 : ! Dump results to file
686 3 : if (open_file(fname,msg, newunit=ubxsf, status='unknown', action="write", form='formatted') /= 0 ) then
687 0 : ABI_WARNING(msg)
688 0 : ierr=ierr +1; RETURN
689 : end if
690 :
691 : ! Write header
692 3 : write(ubxsf,*)' BEGIN_INFO'
693 3 : write(ubxsf,*)' #'
694 3 : write(ubxsf,*)' # this is a Band-XCRYSDEN-Structure-File for Visualization of Fermi Surface'
695 3 : write(ubxsf,*)' # generated by the ABINIT package'
696 3 : write(ubxsf,*)' #'
697 3 : write(ubxsf,*)' # bands between ',minband,' and ',maxband
698 3 : write(ubxsf,*)' #'
699 3 : if (nsppol == 2 ) then
700 0 : write(ubxsf,*)' # NOTE: the first band is relative to spin-up electrons,'
701 0 : write(ubxsf,*)' # the second band to spin-down and so on .. '
702 0 : write(ubxsf,*)' #'
703 : end if
704 3 : write(ubxsf,*)' # Launch as: xcrysden --bxsf '
705 3 : write(ubxsf,*)' #'
706 3 : write(ubxsf,'(a,es16.8)')' Fermi Energy: ',fermie
707 3 : write(ubxsf,*)' END_INFO'
708 3 : write(ubxsf,*)' '
709 3 : write(ubxsf,*)' BEGIN_BLOCK_BANDGRID_3D'
710 3 : write(ubxsf,*)' band_energies'
711 3 : write(ubxsf,*)' BEGIN_BANDGRID_3D'
712 :
713 3 : write(ubxsf,*)' ',(maxband-minband+1)*nsppol
714 3 : write(ubxsf,*)' ',nk1+1,nk2+1,nk3+1
715 3 : write(ubxsf,*)' ',shiftk(:,1)
716 : ! Angstrom units are used in the BXSF format
717 12 : write(ubxsf,*)' ',gprimd(:,1)/Bohr_Ang
718 12 : write(ubxsf,*)' ',gprimd(:,2)/Bohr_Ang
719 12 : write(ubxsf,*)' ',gprimd(:,3)/Bohr_Ang
720 :
721 : ! print out data for all relevant bands and full kpt grid (redundant, yes)
722 : ! for each kpt in full zone, find equivalent irred kpt and print eigenval
723 3 : indx = 0
724 22 : do iband=minband,maxband
725 41 : do isppol=1,nsppol
726 19 : write(ubxsf,*)' BAND: ',indx+minband
727 26422 : write(ubxsf,'(7(es16.8))')(eigen(iband,fulltoirred(ikpt),isppol),ikpt=1,nkptfull)
728 38 : indx=indx+1
729 : end do
730 : end do
731 :
732 3 : write(ubxsf,*)' END_BANDGRID_3D'
733 3 : write(ubxsf,*)' END_BLOCK_BANDGRID_3D'
734 3 : close(ubxsf)
735 :
736 3 : ABI_FREE(fulltoirred)
737 3 : ABI_FREE(symrecfm)
738 :
739 3 : end subroutine printbxsf
740 : !!***
741 :
742 : !!****f* m_pptools/printvtk
743 : !! NAME
744 : !! printvtk
745 : !!
746 : !! FUNCTION
747 : !! Print band structure energies and velocities in VTK format.
748 : !!
749 : !! INPUTS
750 : !! eigen(mband,nkpt,nsppol) = eigenvalues in hartree
751 : !! ewind = energy window around the fermi level.
752 : !! if ewind /= 0 ==> a band is considered in the plot of FSurf
753 : !! only if it is inside [ ef-ewind, ef+ewind ] for some k point
754 : !! if ewind == 0 ==> all bands will be keept in the _BXSF file
755 : !! fermie = Fermi energy (Hartree)
756 : !! gprimd(3,3) = dimensional primitive translations for reciprocal space (bohr^-1)
757 : !! kptrlatt(3,3) = reciprocal of lattice vectors for full kpoint grid
758 : !! mband = maximum number of bands
759 : !! nsppol = 1 for unpolarized, 2 for spin-polarized
760 : !! shiftk(3,nshiftk) =shift vector for k point grid
761 : !! fname = filename for the fortran file
762 : !! symafm(nsym)=(Anti)ferromagnetic symmetries.
763 : !! use_afm=.TRUE. if (anti)ferromagnetic symmetries are used.
764 : !!
765 : !! OUTPUT
766 : !! ierr=Status error.
767 : !! BXSF file.
768 : !!
769 : !! SOURCE
770 :
771 0 : subroutine printvtk(eigen,v_surf,ewind,fermie,gprimd,kptrlatt,mband,&
772 0 : & nkptirred,kptirred,nsym,use_afm,symrec,symafm,use_tr,nsppol,shiftk,nshiftk,fname,ierr)
773 :
774 :
775 : !Arguments ------------------------------------
776 : !scalars
777 : integer,intent(in) :: mband,nkptirred,nshiftk,nsppol,nsym
778 : integer,intent(out) :: ierr
779 : real(dp),intent(in) :: ewind,fermie
780 : logical,intent(in) :: use_afm,use_tr
781 : character(len=*),intent(in) :: fname
782 : !arrays
783 : integer,intent(in) :: kptrlatt(3,3),symafm(nsym),symrec(3,3,nsym)
784 : real(dp),intent(in) :: eigen(mband,nkptirred,nsppol),gprimd(3,3)
785 : real(dp),intent(in) :: v_surf(mband,kptrlatt(1,1)+1,kptrlatt(2,2)+1,kptrlatt(3,3)+1,3,nsppol)
786 : real(dp),intent(in) :: kptirred(3,nkptirred),shiftk(3,nshiftk)
787 :
788 : !Local variables-------------------------------
789 : !scalars
790 : integer :: iband,ikgrid,ikpt1,indx
791 : integer :: ikpt,jkpt,kkpt,ikpt_fine, ik1, ik2, ik3
792 : integer :: isppol,isym,itim,maxband,minband,nk1,nk2,nk3,nkptfull,uvtk,timrev
793 : real(dp) :: ene,res,ss,timsign
794 : logical :: found
795 : character(len=500) :: msg, format_str
796 : !arrays
797 0 : integer,allocatable :: fulltoirred(:)
798 : real(dp) :: kconv(3),kpt(3),kptgrid(3),kptsym(3)
799 : ! *************************************************************************
800 :
801 0 : ierr=0
802 :
803 : !Error if klatt is no simple orthogonal lattice (in red space)
804 : !for generalization to MP grids, need new version of XCrysDen
805 :
806 : if (kptrlatt(1,2)/=0 .or. kptrlatt(1,3)/=0 .or. kptrlatt(2,1)/=0 .or. &
807 0 : kptrlatt(2,3)/=0 .or. kptrlatt(3,1)/=0 .or. kptrlatt(3,2)/=0 ) then
808 : write(msg,'(3a)')&
809 0 : 'kptrlatt should be diagonal, for the FS calculation ',ch10,&
810 0 : 'action: use an orthogonal k-grid for the GS calculation '
811 0 : ABI_COMMENT(msg)
812 0 : ierr=ierr+1
813 : end if
814 :
815 0 : if (ANY(ABS(shiftk(:,:))>tol10)) then
816 : write(msg,'(3a)')&
817 0 : 'Origin of the k-grid should be (0,0,0) for the FS calculation ',ch10,&
818 0 : 'Action: use a non-shifted k-grid for the GS calculation. Returning '
819 0 : ABI_COMMENT(msg)
820 0 : ierr=ierr+1
821 : end if
822 :
823 0 : if (ierr/=0) RETURN
824 :
825 : ! Xcrysden uses aperiodical data-grid
826 0 : nk1 = kptrlatt(1,1)
827 0 : nk2 = kptrlatt(2,2)
828 0 : nk3 = kptrlatt(3,3)
829 0 : nkptfull=(nk1+1)*(nk2+1)*(nk3+1)
830 :
831 0 : ABI_MALLOC(fulltoirred,(nkptfull))
832 0 : timrev=0; if (use_tr) timrev=1
833 :
834 : !Xcrysden employs C-ordering for the Fermi Surface.
835 0 : ierr = 0
836 0 : ikgrid=0
837 0 : do ik1=0,nk1
838 0 : do ik2=0,nk2
839 0 : do ik3=0,nk3
840 :
841 0 : ikgrid=ikgrid+1
842 0 : kptgrid(1)=DBLE(ik1)/kptrlatt(1,1)
843 0 : kptgrid(2)=DBLE(ik2)/kptrlatt(2,2)
844 0 : kptgrid(3)=DBLE(ik3)/kptrlatt(3,3)
845 0 : call wrap2_pmhalf(kptgrid(1),kpt(1),res)
846 0 : call wrap2_pmhalf(kptgrid(2),kpt(2),res)
847 0 : call wrap2_pmhalf(kptgrid(3),kpt(3),res)
848 :
849 : ! === Find correspondence between the Xcrysden grid and the IBZ ===
850 : ! If AFM case, use only Ferromagetic symmetries.
851 0 : found=.FALSE.
852 0 : irred: do ikpt1=1,nkptirred
853 0 : do itim=0,timrev
854 0 : do isym=1,nsym
855 0 : if (use_afm.and.symafm(isym)==-1) CYCLE
856 0 : timsign = one-two*itim
857 : kptsym(:) = timsign*(symrec(:,1,isym)*kptirred(1,ikpt1) + &
858 : symrec(:,2,isym)*kptirred(2,ikpt1) + &
859 0 : symrec(:,3,isym)*kptirred(3,ikpt1))
860 0 : call wrap2_pmhalf(kptsym(1),kconv(1),res)
861 0 : call wrap2_pmhalf(kptsym(2),kconv(2),res)
862 0 : call wrap2_pmhalf(kptsym(3),kconv(3),res)
863 : ! is kconv equivalent to kpt?
864 0 : ss= (kpt(1)-kconv(1))**2 + (kpt(2)-kconv(2))**2 + (kpt(3)-kconv(3))**2
865 0 : if (ss < tol6) then
866 0 : found=.TRUE.
867 0 : fulltoirred(ikgrid)=ikpt1
868 : exit irred
869 : end if
870 :
871 : end do !itim
872 : end do !isym
873 : end do irred
874 :
875 0 : if (.not.found) then
876 : write(msg,'(a,3es16.8,2a)')&
877 0 : ' kpt = ',kpt,ch10,' has no symmetric among the irred k-points used in the GS calculation '
878 0 : ierr=ierr+1
879 0 : ABI_ERROR(msg)
880 : end if
881 :
882 : end do !ik1
883 : end do !ik2
884 : end do !ik3
885 :
886 0 : if (ierr/=0) then
887 0 : ABI_FREE(fulltoirred)
888 0 : RETURN
889 : end if
890 :
891 0 : if (abs(ewind) < tol12 ) then
892 : ! Keep all bands.
893 : minband=1
894 : maxband=mband
895 : else
896 : ! Select a subset of bands.
897 : minband = mband
898 : maxband = 0
899 : ene=abs(ewind)
900 0 : do isppol=1,nsppol
901 0 : do iband=1,mband
902 0 : if(minval(eigen(iband,:,isppol))-fermie < -ene) then
903 0 : minband = iband
904 : end if
905 : end do
906 0 : do iband=mband,1,-1
907 0 : if (maxval(eigen(iband,:,isppol))-fermie > ene) then
908 0 : maxband = iband
909 : end if
910 : end do
911 : end do ! isppol
912 :
913 : end if ! abs(energy_window)
914 :
915 : ! Dump the results on file ===
916 0 : if (open_file(fname,msg,newunit=uvtk,status='unknown',form='formatted') /= 0) then
917 0 : ABI_FREE(fulltoirred)
918 0 : ABI_WARNING(msg)
919 0 : ierr=ierr +1; RETURN
920 : end if
921 :
922 : ! write header
923 0 : write(uvtk,"(a)") '# vtk DataFile Version 2.0'
924 0 : write(uvtk,"(a)") 'Eigen values for the Fermi surface'
925 0 : write(uvtk,"(a)") 'ASCII'
926 0 : write(uvtk,*) ''
927 0 : write(uvtk,"(a)") 'DATASET STRUCTURED_GRID'
928 0 : write(uvtk,"(a,3i6)") 'DIMENSIONS', nk1+1,nk2+1,nk3+1
929 0 : write(uvtk,"(a,i6,a)") 'POINTS',nkptfull,' float'
930 :
931 0 : do ik3 = 0, nk3
932 0 : do ik2 = 0, nk2
933 0 : do ik1 = 0, nk1
934 : write(uvtk,'(3es16.8)') dble(ik1)/nk1*gprimd(1,1)+ &
935 : dble(ik2)/nk2*gprimd(1,2)+ &
936 0 : dble(ik3)/nk3*gprimd(1,3), &
937 : dble(ik1)/nk1*gprimd(2,1)+ &
938 : dble(ik2)/nk2*gprimd(2,2)+ &
939 0 : dble(ik3)/nk3*gprimd(2,3), &
940 : dble(ik1)/nk1*gprimd(3,1)+ &
941 : dble(ik2)/nk2*gprimd(3,2)+ &
942 0 : dble(ik3)/nk3*gprimd(3,3)
943 : end do
944 : end do
945 : end do
946 :
947 : !print out data for all relevant bands and full kpt grid (redundant, yes)
948 : !for each kpt in full zone, find equivalent irred kpt and print eigenval
949 0 : write(uvtk,*) ''
950 0 : write(uvtk,"(a,i6)") 'POINT_DATA',nkptfull
951 0 : indx=0
952 0 : do iband=minband,maxband
953 0 : do isppol=1,nsppol
954 0 : if (minband+indx < 10) then
955 0 : format_str="(a14,i1,1X,a)"
956 : else
957 0 : format_str="(a14,i2,1X,a)"
958 : end if
959 0 : write(uvtk,format_str) 'SCALARS eigval', minband+indx, 'float 1'
960 0 : write(uvtk,"(a)") 'LOOKUP_TABLE default'
961 0 : write(uvtk,*) ' '
962 0 : do kkpt = nk3/2+1, nk3+nk3/2+1
963 0 : do jkpt = nk2/2+1, nk2+nk2/2+1
964 0 : do ikpt = nk1/2+1, nk1+nk1/2+1
965 0 : ik1 = ikpt
966 0 : ik2 = jkpt
967 0 : ik3 = kkpt
968 0 : if (ikpt > nk1+1) ik1 = ikpt - nk1
969 0 : if (jkpt > nk2+1) ik2 = jkpt - nk2
970 0 : if (kkpt > nk3+1) ik3 = kkpt - nk3
971 : ! get the index with zyx order
972 0 : ikpt_fine = (ik1-1)*(nk2+1)*(nk3+1) + (ik2-1)*(nk3+1) + ik3
973 0 : write(uvtk,'(es16.8)') eigen(iband,fulltoirred(ikpt_fine),isppol)
974 : end do
975 : end do
976 : end do
977 0 : indx=indx+1
978 : end do
979 : end do
980 :
981 0 : write(uvtk,*) ''
982 0 : indx=0
983 0 : do iband=minband,maxband
984 0 : do isppol=1,nsppol
985 0 : if (minband+indx < 10) then
986 0 : format_str="(a10,i1,1X,a)"
987 : else
988 0 : format_str="(a10,i2,1X,a)"
989 : end if
990 0 : write(uvtk,format_str) 'SCALARS ve', minband+indx, 'float'
991 0 : write(uvtk,"(a)") 'LOOKUP_TABLE default'
992 0 : write(uvtk,*) ' '
993 0 : do kkpt = nk3/2+1, nk3+nk3/2+1
994 0 : do jkpt = nk2/2+1, nk2+nk2/2+1
995 0 : do ikpt = nk1/2+1, nk1+nk1/2+1
996 0 : ik1 = ikpt
997 0 : ik2 = jkpt
998 0 : ik3 = kkpt
999 0 : if (ikpt > nk1+1) ik1 = ikpt - nk1
1000 0 : if (jkpt > nk2+1) ik2 = jkpt - nk2
1001 0 : if (kkpt > nk3+1) ik3 = kkpt - nk3
1002 : ! write(uvtk,'(3i6,3es16.8)') ik1,ik2,ik3,v_surf(iband,ik1,ik2,ik3,1,isppol), &
1003 : ! & v_surf(iband,ik1,ik2,ik3,2,isppol), &
1004 : ! & v_surf(iband,ik1,ik2,ik3,3,isppol)
1005 : write(uvtk,'(es16.8)') sqrt(v_surf(iband,ik1,ik2,ik3,1,isppol)*v_surf(iband,ik1,ik2,ik3,1,isppol)+ &
1006 : & v_surf(iband,ik1,ik2,ik3,2,isppol)*v_surf(iband,ik1,ik2,ik3,2,isppol)+ &
1007 0 : & v_surf(iband,ik1,ik2,ik3,3,isppol)*v_surf(iband,ik1,ik2,ik3,3,isppol))
1008 : end do
1009 : end do
1010 : end do
1011 0 : write(uvtk,format_str) 'SCALARS vx', minband+indx, 'float'
1012 0 : write(uvtk,"(a)") 'LOOKUP_TABLE default'
1013 0 : write(uvtk,*) ' '
1014 0 : do kkpt = nk3/2+1, nk3+nk3/2+1
1015 0 : do jkpt = nk2/2+1, nk2+nk2/2+1
1016 0 : do ikpt = nk1/2+1, nk1+nk1/2+1
1017 0 : ik1 = ikpt
1018 0 : ik2 = jkpt
1019 0 : ik3 = kkpt
1020 0 : if (ikpt > nk1+1) ik1 = ikpt - nk1
1021 0 : if (jkpt > nk2+1) ik2 = jkpt - nk2
1022 0 : if (kkpt > nk3+1) ik3 = kkpt - nk3
1023 0 : write(uvtk,'(es16.8)') v_surf(iband,ik1,ik2,ik3,1,isppol)
1024 : end do
1025 : end do
1026 : end do
1027 0 : write(uvtk,format_str) 'SCALARS vy', minband+indx, 'float'
1028 0 : write(uvtk,"(a)") 'LOOKUP_TABLE default'
1029 0 : write(uvtk,*) ' '
1030 0 : do kkpt = nk3/2+1, nk3+nk3/2+1
1031 0 : do jkpt = nk2/2+1, nk2+nk2/2+1
1032 0 : do ikpt = nk1/2+1, nk1+nk1/2+1
1033 0 : ik1 = ikpt
1034 0 : ik2 = jkpt
1035 0 : ik3 = kkpt
1036 0 : if (ikpt > nk1+1) ik1 = ikpt - nk1
1037 0 : if (jkpt > nk2+1) ik2 = jkpt - nk2
1038 0 : if (kkpt > nk3+1) ik3 = kkpt - nk3
1039 0 : write(uvtk,'(es16.8)') v_surf(iband,ik1,ik2,ik3,2,isppol)
1040 : end do
1041 : end do
1042 : end do
1043 0 : write(uvtk,format_str) 'SCALARS vz', minband+indx, 'float'
1044 0 : write(uvtk,"(a)") 'LOOKUP_TABLE default'
1045 0 : write(uvtk,*) ' '
1046 0 : do kkpt = nk3/2+1, nk3+nk3/2+1
1047 0 : do jkpt = nk2/2+1, nk2+nk2/2+1
1048 0 : do ikpt = nk1/2+1, nk1+nk1/2+1
1049 0 : ik1 = ikpt
1050 0 : ik2 = jkpt
1051 0 : ik3 = kkpt
1052 0 : if (ikpt > nk1+1) ik1 = ikpt - nk1
1053 0 : if (jkpt > nk2+1) ik2 = jkpt - nk2
1054 0 : if (kkpt > nk3+1) ik3 = kkpt - nk3
1055 0 : write(uvtk,'(es16.8)') v_surf(iband,ik1,ik2,ik3,3,isppol)
1056 : end do
1057 : end do
1058 : end do
1059 0 : indx=indx+1
1060 : end do
1061 : end do
1062 :
1063 0 : close (uvtk)
1064 0 : ABI_FREE(fulltoirred)
1065 :
1066 : end subroutine printvtk
1067 : !!***
1068 :
1069 : END MODULE m_pptools
|