LCOV - code coverage report
Current view: top level - shared/common/src/32_util - m_pptools.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 43.3 % 397 172
Test Date: 2026-11-08 02:25:56 Functions: 87.5 % 8 7
Branches: 32.3 % 462 149

             Branch data     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
        

Generated by: LCOV version 2.3-1