1!============================================================= 2! Utilities: 3! 4! wfnmerge Originally by JLL. Modifications by JRD. Version compatible 5! with new wavefunction format by BDM. 6! 7! Merges many WFN files into one. It assumes that all input files have the 8! same number and same ordering of G-vectors for the charge density. 9! The number and name of input files is read from "wfnmerge.inp", as well 10! as the k-grid and the k-shift. 11! 12! FAQ: 13! Q: Why would someone want to use this? 14! A: For example, maybe to do a converged calculation one needs to include a 15! large number of unoccupied states. There may not be the resources (either 16! CPUs or wallclock) to do this all in one shot, so it may be beneficial to 17! split up a calculation of kpoints (e.g., 4x4x4 MP grid) into smaller 18! pieces and then add up the final wavefunctions. 19! Q: What is the deal with kpoint weights? 20! A: Quantum Espresso renormalizes the kpoint weights that you use in a 21! calculation. If you are splitting up a MP grid into different groups of 22! kpoints, and each group is normalized, the relative weights between 23! kpoints in different groups is no longer correct. BerkeleyGW does not 24! make use of the kpoint weights (except for in determining whether the 25! Fermi level is reasonable for metallic calculations). So for most uses 26! the fact that these weights are incorrect does not matter and you can 27! set the relative weights for each group of k-points to 1 in the input 28! file. If it matters to you, set the relative weights according to the 29! weights of k-points in the original MP grid and check the weights in 30! the final WFN file using wfn_rho_vxc_info.x. 31!============================================================= 32 33#include "f_defs.h" 34 35program wfnmerge 36 37 use global_m 38 use wfn_rho_vxc_io_m 39 implicit none 40 41 integer, pointer :: atyp(:) 42 real(DP),pointer :: kw(:) 43 real(DP),pointer :: tkw(:) !< total kweights 44 real(DP),pointer :: kpt(:,:) 45 real(DP),pointer :: tkpt(:,:) !< total list of kpoints 46 integer,pointer :: ifmin(:,:) 47 integer, pointer :: tifmin(:,:) !< total ifmin 48 integer,pointer :: ifmax(:,:) 49 integer, pointer :: tifmax(:,:) !< total ifmax 50 real(DP),pointer :: occ(:,:,:) 51 real(DP),pointer :: tocc(:,:,:) !< total occupancy 52 real(DP),pointer :: en(:,:,:) 53 real(DP),pointer :: ten(:,:,:) !< total energies 54 integer, pointer :: ngk(:) 55 integer, pointer :: tngk(:) !< total number of gvectors 56 real(DP),pointer :: apos(:,:) 57 integer, allocatable :: gvec(:,:) 58 integer, allocatable :: kptfile(:) !< kpts per file 59 integer, allocatable :: tngkmax(:) !< ngkmax for each file 60 real(DP), allocatable :: rdata(:,:) 61 complex(DPC), allocatable :: cdata(:,:) 62 integer :: cell_symmetry,iflavor,ns,nspinor,ng,nsym,nat,nk,nb,& 63 ngkmax,kmax(3),kgrid(3),rot(3,3,48),expkpt 64 real(DP) :: ecutrho,ecutwfn,celvol,recvol,al,bl,a(3,3),b(3,3),adot(3,3),& 65 bdot(3,3),kshift(3),tau(3,48),thesum 66 67 integer :: total_kgrid(3),ifil,ik,ikindex,ib 68 integer :: mngkmax !< maximum number of gvectors for all kpoints 69 real(DP) :: grid_shift(3) 70 character*80 :: outfile 71 character*80, allocatable :: infile(:) 72 real(DP), allocatable :: relweight(:) 73 character*3 :: sheader 74 integer :: nfil,iunit,index 75 integer, allocatable :: nkfil(:) 76 integer :: tnk ! total number of kpoints 77 78! Read wfnmerge.inp 79 call open_file(55,file='wfnmerge.inp',form='formatted',status='old') 80 read(55,'(a80)') outfile 81 read(55,*) total_kgrid(1),total_kgrid(2),total_kgrid(3) 82 read(55,*) grid_shift(1),grid_shift(2),grid_shift(3) 83 read(55,*) nfil 84 read(55,*) expkpt ! the expected number of kpoints 85 SAFE_ALLOCATE(infile,(nfil)) 86 SAFE_ALLOCATE(relweight,(nfil)) 87 SAFE_ALLOCATE(nkfil,(nfil)) 88 do ifil=1,nfil 89 read(55,'(a80)') infile(ifil) 90 enddo 91 do ifil=1,nfil 92 read(55,*) relweight(ifil) 93 enddo 94 call close_file(55) 95 96 write(6,*) 'Output -> ', TRUNC(outfile) 97 98 SAFE_ALLOCATE(tkw,(expkpt)) 99 SAFE_ALLOCATE(tkpt,(3,expkpt)) 100 SAFE_ALLOCATE(tngk,(expkpt)) 101 SAFE_ALLOCATE(kptfile,(nfil)) 102 SAFE_ALLOCATE(tngkmax,(nfil)) 103 104! Open all the WFN files to be read 105 106 call open_file(8,file=outfile,form='unformatted',status='replace') 107 do ifil=1,nfil 108 iunit=128+ifil 109 call open_file(iunit,file=infile(ifil),form='unformatted',status='old') 110 end do 111 112! Read headers 113 tnk=0 114 index=1 115 sheader='WFN' 116 iflavor=-1 117 mngkmax=-1000 118 do ifil=1,nfil 119 iunit=128+ifil 120 call read_binary_header(iunit,sheader,iflavor,ns,ng,nsym,& 121 cell_symmetry,nat,nk,nb,ngkmax,ecutrho,ecutwfn,kmax, & 122 kgrid,kshift,celvol,al,a,adot,recvol,bl,b,bdot, & 123 rot,tau,atyp,apos,ngk,kw,kpt,ifmin,ifmax,en,occ,nspinor,dont_warn_kgrid=.true.) 124 if (ifil.eq.1) then 125 SAFE_ALLOCATE(tifmin,(expkpt,ns)) 126 SAFE_ALLOCATE(tifmax,(expkpt,ns)) 127 SAFE_ALLOCATE(ten,(nb,expkpt,ns)) 128 SAFE_ALLOCATE(tocc,(nb,expkpt,ns)) 129 end if 130 tnk=tnk+nk 131 kptfile(ifil)=nk 132 if (ngkmax>mngkmax) mngkmax=ngkmax 133 tngkmax(ifil)=ngkmax 134 tkw(index:index+nk-1)=kw(1:nk)*relweight(ifil) 135 tkpt(:,index:index+nk-1)=kpt(:,1:nk) 136 tifmin(index:index+nk-1,:)=ifmin(1:nk,:) 137 tifmax(index:index+nk-1,:)=ifmax(1:nk,:) 138 ten(:,index:index+nk-1,:)=en(:,1:nk,:) 139 tocc(:,index:index+nk-1,:)=occ(:,1:nk,:) 140 tngk(index:index+nk-1)=ngk(1:nk) 141 index=index+nk 142 end do 143 144! Renormalize the weights. 145! See note in the header for more about this 146 147 thesum=sum(tkw(1:tnk)) 148 do ik=1,tnk 149 tkw(ik)=tkw(ik)/thesum 150 end do 151 152 write(6,*) 'Total number of kpoints found=',tnk 153 if (tnk.ne.expkpt) then 154 call die('Unexpected number of kpoints found!') 155 end if 156 157! Headers read. Write output header 158 159 call write_binary_header(8,sheader,iflavor,ns,ng,nsym,& 160 cell_symmetry,nat,tnk,nb,mngkmax,ecutrho,ecutwfn,kmax,& 161 total_kgrid,grid_shift,celvol,al,a,adot,recvol,bl,b,bdot,& 162 rot,tau,atyp,apos,tngk,tkw,tkpt,tifmin,tifmax,ten,tocc,nspinor,dont_warn_kgrid=.true.) 163 164! Read charge density gvectors 165 166 SAFE_ALLOCATE(gvec,(3,ng)) 167 do ifil=1,nfil 168 iunit=128+ifil 169 call read_binary_gvectors(iunit,ng,ng,gvec) 170 if (ifil.eq.1) then 171 call write_binary_gvectors(8,ng,ng,gvec) 172 end if 173 end do 174 SAFE_DEALLOCATE(gvec) 175 176! Now we loop over kpoints, get their respective gvectors, and 177! read/write data band-by-band 178 179 SAFE_ALLOCATE(gvec,(3,mngkmax)) 180 if (iflavor .eq. 1) then 181 SAFE_ALLOCATE(rdata,(mngkmax,ns*nspinor)) 182 else 183 SAFE_ALLOCATE(cdata,(mngkmax,ns*nspinor)) 184 end if 185 ikindex=0 186 do ifil=1,nfil 187 iunit=128+ifil 188 do ik=1,kptfile(ifil) 189 ikindex=ikindex+1 190 write(6,*) 'Working on kpoint #', ikindex 191 ! read g-vectors for current k-point 192 call read_binary_gvectors(iunit,tngk(ikindex),tngkmax(ifil),gvec) 193 ! write these g-vectors back to the outfile 194 call write_binary_gvectors(8,tngk(ikindex),mngkmax,gvec) 195 ! now read/write band data 196 do ib=1,nb 197 if (iflavor .eq. 1) then 198 rdata(:,:) = 0d0 199 call read_binary_data(iunit,tngk(ikindex),tngkmax(ifil),ns*nspinor,rdata(1:tngkmax(ifil),:)) 200 call write_binary_data(8,tngk(ikindex),mngkmax,ns*nspinor,rdata) 201 else 202 cdata(:,:) = CMPLX(0d0, 0d0) 203 call read_binary_data(iunit,tngk(ikindex),tngkmax(ifil),ns*nspinor,cdata(1:tngkmax(ifil),:)) 204 call write_binary_data(8,tngk(ikindex),mngkmax,ns*nspinor,cdata) 205 endif 206 end do 207 end do ! ik 208 end do ! ifil 209 210 write(6,*) 'JOB DONE. #', ikindex 211 212! Close files 213 214 do ifil=1,nfil 215 iunit=128+ifil 216 call close_file(iunit) 217 end do 218 call close_file(8) 219 220! Deallocate arrays 221 222 if (iflavor .eq. 1) then 223 SAFE_DEALLOCATE(rdata) 224 else 225 SAFE_DEALLOCATE(cdata) 226 endif 227 SAFE_DEALLOCATE(gvec) 228 SAFE_DEALLOCATE(tngkmax) 229 SAFE_DEALLOCATE(kptfile) 230 SAFE_DEALLOCATE_P(tkw) 231 SAFE_DEALLOCATE_P(tngk) 232 SAFE_DEALLOCATE_P(tkpt) 233 SAFE_DEALLOCATE_P(tifmin) 234 SAFE_DEALLOCATE_P(tifmax) 235 SAFE_DEALLOCATE_P(ten) 236 SAFE_DEALLOCATE_P(tocc) 237 SAFE_DEALLOCATE(infile) 238 SAFE_DEALLOCATE(relweight) 239 SAFE_DEALLOCATE(nkfil) 240 241end program wfnmerge 242