!-----------------------------------------------------------------------------------------! ! Copyright (c) 2018 Peter Grünberg Institut, Forschungszentrum Jülich, Germany ! ! This file is part of Jülich KKR code and available as free software under the conditions! ! of the MIT license as expressed in the LICENSE.md file in more detail. ! !-----------------------------------------------------------------------------------------! !------------------------------------------------------------------------------- !> Summary: This module contains everything needed in the host code to prepare a !> quasiparticle interference (QPI) simulation. !> Author: Philipp Ruessmann !> Deprecated: False !> For details on the quasiparticle interference technique and it's implementation !> see chapter 4 of the PhD thesis of Philipp Ruessmann which is available here: !> http://epflicht.ulb.uni-bonn.de/urn/urn:nbn:de:hbz:5:2-162838 !------------------------------------------------------------------------------- module mod_rhoqtools use :: mod_datatypes, only: dp private public :: rhoq_save_refpot, rhoq_save_rmesh, rhoq_write_kmesh, rhoq_find_kmask, rhoq_saveg, rhoq_write_tau0, rhoq_read_mu0_scoef contains !------------------------------------------------------------------------------- !> Summary: Write the k-mesh to file for the use in the QPI-tool !> Author: Philipp Ruessmann !> Category: input-output, k-points, KKRhost !> Deprecated: False !> Write the k-mesh to file with its respective weights !------------------------------------------------------------------------------- subroutine rhoq_write_kmesh(nofks, nxyz, volbz, bzkp, volcub, recbv, bravais) implicit none integer, intent (in) :: nofks !! number of points in irreducible BZ real (kind=dp), intent (in) :: volbz !! volume of the BZ integer, dimension(3), intent (in) :: nxyz !! original k-mesh net in the 3 directions of the reciprocal lattice vectors (not xyz directions) real (kind=dp), dimension(nofks), intent (in) :: volcub !! Weight of the k-points real (kind=dp), dimension(3, nofks), intent (in) :: bzkp !! k-point mesh real (kind=dp), dimension(3, 3), intent (in) :: recbv !! Reciprocal basis vectors real (kind=dp), dimension(3, 3), intent (in) :: bravais !! Bravais lattice vectors ! .. Local variables integer :: ks, i ! write out kpoints open (8888, file='kpts.txt', form='formatted') write (8888, '(3I9)') nofks, nxyz(1), nxyz(2) write (8888, '(E16.7)') volbz do ks = 1, nofks write (8888, '(4E16.7)')(bzkp(i,ks), i=1, 3), volcub(ks) end do write (8888, '(100E16.7)') recbv(1:3, 1:3), bravais(1:3, 1:3) close (8888) end subroutine rhoq_write_kmesh !------------------------------------------------------------------------------- !> Summary: Read information about scanning position of the QPI-tool !> Author: Philipp Ruessmann !> Category: input-output, KKRhost !> Deprecated: False !> Reads in information about scanning layers from file 'mu0' and distributes !> the information over the MPI ranks !> @note Should be redone in the future so that the information is created automatically and not read in from a file. @endnote !------------------------------------------------------------------------------- subroutine rhoq_read_mu0_scoef(iatomimp, mu, nscoef, imin) #ifdef CPP_MPI use :: mpi #endif use :: mod_mympi, only: myrank, master implicit none integer, intent (out) :: mu !! scannning position (mu0 in PhD Ruessmann) integer, intent (out) :: nscoef !! number of layers in the impurity cluster integer, intent (out) :: imin !! smalles layer index of impurity cluster integer, allocatable, intent (inout) :: iatomimp(:) !! layer indices ! local integer :: i1 !! counter for atoms in impurity cluster #ifdef CPP_MPI integer :: ierr !! exit status of MPI calls #endif ! read in mu0 if (myrank==master) then open (8888, file='mu0', form='formatted') read (8888, *) mu, nscoef allocate (iatomimp(nscoef)) do i1 = 1, nscoef read (8888, *) iatomimp(i1) end do close (8888) end if #ifdef CPP_MPI ! communicate mu and nscoef call mpi_bcast(mu, 1, mpi_integer, master, mpi_comm_world, ierr) if (ierr/=mpi_success) stop 'Error Bcast mu0' call mpi_bcast(nscoef, 1, mpi_integer, master, mpi_comm_world, ierr) if (ierr/=mpi_success) stop 'Error Bcast nscoef' if (.not. allocated(iatomimp)) allocate (iatomimp(nscoef)) call mpi_bcast(iatomimp, nscoef, mpi_integer, master, mpi_comm_world, ierr) if (ierr/=mpi_success) stop 'Error Bcast iatomimp' #endif ! find imin imin = 100000 do i1 = 1, nscoef if (iatomimp(i1)<imin) imin = iatomimp(i1) end do nscoef = nscoef - 1 end subroutine rhoq_read_mu0_scoef !------------------------------------------------------------------------------- !> Summary: Find mask of necessary k-points for the QPI-tool !> Author: Philipp Ruessmann !> Category: k-points, input-output, KKRhost !> Deprecated: False !> Read `kpts.txt` file and `kmask_info.txt` file on master and from there determine if !> some k-points can be thrown out. The input of the `kmask_info.txt` file determines the behavior of this routine: !> * file not present: take all k-points !> * 1 in first line (determines mode): ring-like region around R0=(kx,ky) [in line 2] with inner and outer radii being R1 and R2 [lines 3 and 4] !> * 2 in first line: take box defined by kx_min, kx_max, ky_min, ky_max (each given in a new line) !> * 3 in first line: read predefined mask (1/0) values need to be given for all k-points, each in a new line !------------------------------------------------------------------------------- subroutine rhoq_find_kmask(nofks, k_end, bzkp, kmask, rhoq_kmask) #ifdef CPP_MPI use :: mpi #endif use :: mod_mympi, only: myrank, master use :: mod_datatypes implicit none integer, intent (in) :: nofks !! number of k-points integer, intent (out) :: k_end !! number of k-points after filtering integer, allocatable, intent (out) :: kmask(:) !! kmask array labelling points (either inside or outside of masked region) real (kind=dp), intent (in) :: bzkp(3, nofks) !! k-points array real (kind=dp), allocatable, intent (out) :: rhoq_kmask(:, :) !! output array holding kpoints and indices in reduced region only ! local integer :: i, j, kpt, kmask_mode, k_start logical :: kmask_info real (kind=dp) :: k_mask_bounds(4), recbv(3, 3), kp(3) #ifdef CPP_MPI integer :: ierr #endif ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! if (myrank==master) then ! read recbv open (8888, file='kpts.txt', form='formatted') read (8888, *) read (8888, *) do kpt = 1, nofks read (8888, *) end do read (8888, '(100E16.7)') recbv(1:3, 1:3) close (8888) allocate (kmask(nofks)) ! determine kmask parameters inquire (file='kmask_info.txt', exist=kmask_info) if (kmask_info) then write (*, *) 'found ''kmask_info.txt'' file, start reading...' open (8888, file='kmask_info.txt', form='formatted') read (8888, *) kmask_mode if (kmask_mode==1) then ! read R0=(x,y), then R1 and R2 (outer and inner radius around R0) write (*, *) 'kmask_mode is 1: spherical region' read (8888, *) k_mask_bounds(1), k_mask_bounds(2) write (*, *) 'R0=', k_mask_bounds(1), k_mask_bounds(2) read (8888, *) k_mask_bounds(3) write (*, *) 'R1=', k_mask_bounds(3) read (8888, *) k_mask_bounds(4) write (*, *) 'R2=', k_mask_bounds(4) else if (kmask_mode==2) then ! read xmin, xmax, ymin, ymax of kmask_box write (*, *) 'kmask_mode is 2: box' read (8888, *) k_mask_bounds(1) read (8888, *) k_mask_bounds(2) read (8888, *) k_mask_bounds(3) read (8888, *) k_mask_bounds(4) write (*, *) 'xmin=', k_mask_bounds(1) write (*, *) 'xmax=', k_mask_bounds(2) write (*, *) 'ymin=', k_mask_bounds(3) write (*, *) 'ymax=', k_mask_bounds(4) end if ! kmask_mode 1 or 2 ! close kmask_info.txt close (8888) else kmask_mode = 0 end if ! kmask_info.txt file found if (kmask_mode==3) then ! read kmask from file write (*, *) 'kmask_mode is 3: read ''kpts_mask.txt'' file' open (8888, file='kpts_mask.txt', form='formatted') end if ! use these as counters k_start = 1 k_end = 0 ! find kmask and number points in box do kpt = 1, nofks ! findig kmask ! default is take all kmask(kpt) = 1 if (kmask_mode==1) then ! sph mode kmask(kpt) = 0 do i = -1, 1, 1 do j = -1, 1, 1 kp(1:3) = bzkp(1:3, kpt) + i*recbv(1:3, 1) + j*recbv(1:3, 2) ! first shift kpt to be centered around R0 kp(1) = kp(1) - k_mask_bounds(1) kp(2) = kp(2) - k_mask_bounds(2) ! then apply rules concerning inner and outer radius if (sqrt(kp(1)**2+kp(2)**2)<k_mask_bounds(3)) kmask(kpt) = 1 if (sqrt(kp(1)**2+kp(2)**2)<k_mask_bounds(4)) kmask(kpt) = 0 end do ! j end do ! i else if (kmask_mode==2) then ! box mode do i = -1, 1, 1 do j = -1, 1, 1 kp(1:3) = bzkp(1:3, kpt) + i*recbv(1:3, 1) + j*recbv(1:3, 2) if (kp(1)<k_mask_bounds(1)) kmask(kpt) = 0 if (kp(1)>k_mask_bounds(2)) kmask(kpt) = 0 if (kp(2)<k_mask_bounds(3)) kmask(kpt) = 0 if (kp(2)>k_mask_bounds(4)) kmask(kpt) = 0 end do ! j end do ! i else if (kmask_mode==3) then ! read kmask from file read (8888, *) kmask(kpt) end if ! kmask_mode ! count number of kpts in reduced part if (kmask(kpt)>0) k_end = k_end + 1 end do ! kpt loop ! close kmask file if (kmask_mode==3) then ! read kmask from file close (8888) end if ! fill rhoq_kmask (on reduced set of kpts) allocate (rhoq_kmask(1:5,k_end)) do kpt = 1, nofks if (kmask(kpt)>0) then rhoq_kmask(1:3, k_start) = bzkp(1:3, kpt) rhoq_kmask(4, k_start) = real(kpt, kind=dp) rhoq_kmask(5, k_start) = real(kmask(kpt), kind=dp) k_start = k_start + 1 end if end do write (*, *) 'found ', k_end, 'kpoints' open (8888, file='rhoq_kmask.test', form='formatted') do kpt = 1, k_end write (8888, '(5F14.7)') rhoq_kmask(1:3, kpt), rhoq_kmask(4, kpt), rhoq_kmask(5, kpt) end do close (8888) end if ! (myrank==master) #ifdef CPP_MPI ! communicate kmask stuff from master to all others call mpi_bcast(k_end, 1, mpi_integer, master, mpi_comm_world, ierr) if (myrank/=master) then allocate (kmask(nofks)) allocate (rhoq_kmask(1:5,k_end)) end if call mpi_bcast(kmask, nofks, mpi_integer, master, mpi_comm_world, ierr) call mpi_bcast(rhoq_kmask, 5*k_end, mpi_double_precision, master, mpi_comm_world, ierr) #endif end subroutine rhoq_find_kmask !------------------------------------------------------------------------------- !> Summary: Save k-dependent GF to file for the QPI-tool !> Author: Philipp Ruessmann !> Category: input-output, k-points, structural-greensfunction, KKRhost !> Deprecated: False !> Write out G_ij as well as G_ji !------------------------------------------------------------------------------- subroutine rhoq_saveg(nscoef, rhoq_kmask, kpt, k_end, kp, i, j, mu, imin, iatomimp, lmmaxd, g) #ifdef CPP_HYBRID use :: omp_lib #endif implicit none integer, intent (in) :: i !! atom index i integer, intent (in) :: j !! atom index j integer, intent (in) :: mu !! scanning position (mu0) integer, intent (in) :: imin !! minimal layer index integer, intent (in) :: lmmaxd !! lm-size of GF matrices integer, intent (in) :: nscoef !! number of layers in imp. cluster integer, intent (in) :: k_end !! number of kpoints to be stored integer, intent (in) :: kpt !! kpoint index integer, intent (in) :: iatomimp(nscoef) !! layer indices of imp. cluster real (kind=dp), intent (in) :: rhoq_kmask(5, k_end) !! mask and mapping array of reduced k-point set real (kind=dp), intent (in) :: kp(3) !! kpoint complex (kind=dp), intent (in) :: g(lmmaxd, lmmaxd) !! structural GF (of pair i,j, and k-point) ! local integer :: ix, jx, lm1, irec #ifdef CPP_HYBRID ! $omp critical #endif irec = (nscoef*2)*(int(rhoq_kmask(4,kpt))-1) if (((i==mu) .and. any(j==iatomimp(1:nscoef)))) then ix = 0 jx = 0 lm1 = 1 do while (ix==0 .and. lm1<=nscoef) if (iatomimp(lm1)==j) ix = j - imin + 1 lm1 = lm1 + 1 end do irec = irec + nscoef + ix write (9889, rec=irec) kp(1:2), g(1:lmmaxd, 1:lmmaxd) ! * ! rhoq_kmask(5,kpt) end if irec = (nscoef*2)*(int(rhoq_kmask(4,kpt))-1) if (((j==mu) .and. any(i==iatomimp(1:nscoef)))) then ix = 0 jx = 0 lm1 = 1 do while (jx==0 .and. lm1<=nscoef+1) if (iatomimp(lm1)==i) jx = i - imin + 1 lm1 = lm1 + 1 end do irec = irec + jx write (9889, rec=irec) kp(1:2), g(1:lmmaxd, 1:lmmaxd) ! * !*ETAIKR(ISYM,NS) not this factor because it is dealt with explicitly in rhoq module ! rhoq_kmask(5,kpt) end if ! i==mu ... #ifdef CPP_HYBRID ! $omp end critical #endif end subroutine rhoq_saveg !------------------------------------------------------------------------------- !> Summary: Write out scattering path operator to fort.990099 and fort 998888 files for the QPI-tool !> Author: Philipp Ruessmann !> Category: input-output, k-points, structural-greensfunction, KKRhost !> Deprecated: False !> Reads in stored structural GF from file and converts to human redable files !> @note Can be removed in a later version. @endnote !------------------------------------------------------------------------------- subroutine rhoq_write_tau0(nofks, nshell, nsh1, nsh2, nsymat, nscoef, mu, iatomimp, kmask, lmmaxd, bzkp, imin) use :: mod_mympi, only: myrank, master use :: mod_datatypes use :: mod_constants, only: czero implicit none integer, intent (in) :: nofks, nshell, nsymat, nscoef, mu, lmmaxd, imin integer, intent (in) :: nsh1(nshell), nsh2(nshell), iatomimp(nscoef) real (kind=dp), intent (in) :: bzkp(3, nofks) integer, allocatable, intent (inout) :: kmask(:) ! local integer :: kpt, ns, i, j, isym, irec, ix, jx, lm1 real (kind=dp) :: kp(3) complex (kind=dp) :: g(lmmaxd, lmmaxd) if (myrank==master) then write (*, *) ! status bar write (*, *) 'rhoq: write-out loop' write (*, '("Loop over points:|",5(1X,I2,"%",5X,"|"),1X,I3,"%")') 0, 20, 40, 60, 80, 100 write (*, fmt=100, advance='no') ! beginning of statusbar ! write out fort.998899, fort.998888 ! ====================================================================== do kpt = 1, nofks do ns = 1, nshell i = nsh1(ns) j = nsh2(ns) do isym = 1, nsymat irec = (nscoef*2)*(kpt-1) if (((i==mu) .and. any(j==iatomimp(1:nscoef)))) then ix = 0 jx = 0 lm1 = 1 do while (ix==0 .and. lm1<=nscoef) if (iatomimp(lm1)==j) ix = j - imin + 1 lm1 = lm1 + 1 end do irec = irec + nscoef + ix if (kmask(kpt)>0) then read (9889, rec=irec) kp(1:2), g(1:lmmaxd, 1:lmmaxd) else kp(1:3) = bzkp(1:3, kpt) g(1:lmmaxd, 1:lmmaxd) = czero end if write (998899, '(10000ES15.7)') kp(1:2), g(1:lmmaxd, 1:lmmaxd)*real(kmask(kpt), kind=dp) end if irec = (nscoef*2)*(kpt-1) if (((j==mu) .and. any(i==iatomimp(1:nscoef)))) then ix = 0 jx = 0 lm1 = 1 do while (jx==0 .and. lm1<=nscoef+1) if (iatomimp(lm1)==i) jx = i - imin + 1 lm1 = lm1 + 1 end do irec = irec + jx if (kmask(kpt)>0) then read (9889, rec=irec) kp(1:2), g(1:lmmaxd, 1:lmmaxd) else kp(1:3) = bzkp(1:3, kpt) g(1:lmmaxd, 1:lmmaxd) = czero end if write (998888, '(10000ES15.7)') kp(1:2), g(1:lmmaxd, 1:lmmaxd)*real(kmask(kpt), kind=dp) end if ! iii==mu ... end do ! ISYM = 1,NSYMAT end do ! NS = 1,NSHELL if (nofks>=50) then if (mod(kpt-0,nofks/50)==0) write (6, fmt=110, advance='no') else write (6, fmt=110, advance='no') end if end do ! kpt=1,nofks ! ====================================================================== write (6, *) ! status bar end if ! myrank==master deallocate (kmask) 100 format (' |') ! status bar 110 format ('|') ! status bar end subroutine rhoq_write_tau0 !------------------------------------------------------------------------------- !> Summary: Write the radial mesh information to file for QPI-tool !> Author: Philipp Ruessmann !> Category: radial-grid, input-output, KKRhost !> Deprecated: False !> Read in scanning position and write out information for the radial mesh to file !------------------------------------------------------------------------------- subroutine rhoq_save_rmesh(natyp,irmd,ipand,irmin,irws,ipan,rmesh,ntcell,ircut, & r_log,npan_log,npan_eq) implicit none integer, intent (in) :: natyp, irmd, ipand, npan_log, npan_eq integer, intent (in) :: irmin(natyp), irws(natyp), ipan(natyp), ntcell(natyp), ircut(0:ipand, natyp) real (kind=dp), intent (in) :: r_log real (kind=dp), intent (in) :: rmesh(irmd, natyp) ! local integer :: i1 ! read mu_0 open (9999, file='mu0', form='formatted') read (9999, *) i1 close (9999) ! write out corresponding mesh information open (9999, file='rmesh_mu0.txt', form='formatted') write (9999, '(A)') '# mu_0, IRMIN, IRWS, IPAN' write (9999, '(4I9)') i1, irmin(i1), irws(i1), ipan(i1) write (9999, '(A)') '# Rmesh(1:IRWS)' write (9999, '(1000E22.15)') rmesh(1:irws(i1), i1) write (9999, '(A)') '# NTCELL(1:NATYP)' write (9999, '(1000I9)') ntcell(1:natyp) write (9999, '(A)') '# IRCUT(1:IPAN)' write (9999, '(1000I9)') ircut(1:ipan(i1), i1) write (9999, '(A)') '# R_LOG, NPAN_LOG, NPAN_EQ' write (9999, '(E22.15,2I9)') r_log, npan_log, npan_eq close (9999) end subroutine rhoq_save_rmesh !------------------------------------------------------------------------------- !> Summary: Save the reference potentials to an unformatted filefor the QPI-tool !> Author: Philipp Ruessmann !> Category: input-output, reference-system, KKRhost !> Deprecated: False !> Save the reference potentials to an unformatted file called refinfo !------------------------------------------------------------------------------- subroutine rhoq_save_refpot(ielast,i1,nref,natyp,refpot,wlength,lmmaxd,ie,trefll) implicit none integer, intent (in) :: ielast, i1, nref, natyp, wlength, lmmaxd, ie integer, intent (in) :: refpot(natyp) complex (kind=dp), intent (in) :: trefll(lmmaxd, lmmaxd, natyp) ! local integer :: irec if (i1==1) then open (99991, file='refinfo') write (99991, '(2I9)') nref, natyp write (99991, '(1000I9)') refpot(1:natyp) close (99991) open (99992, file='tref', access='direct', recl=wlength*4*lmmaxd**2, form='unformatted') end if irec = ie + ielast*(i1-1) write (99992, rec=irec) trefll(:, :, i1) end subroutine rhoq_save_refpot end module mod_rhoqtools