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