Line data Source code
1 : !!****p* ABINIT/mrggkk
2 : !! NAME
3 : !! mrggkk
4 : !!
5 : !! FUNCTION
6 : !! This program merges a GS file and several 1WF or GKK files for
7 : !! different q-vectors and perturbations.
8 : !!
9 : !! COPYRIGHT
10 : !! Copyright (C) 2004-2026 ABINIT group (MVer, MG)
11 : !! This file is distributed under the terms of the
12 : !! GNU General Public Licence, see ~abinit/COPYING
13 : !! or http://www.gnu.org/copyleft/gpl.txt .
14 : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
15 : !!
16 : !! INPUTS
17 : !! (main routine)
18 : !!
19 : !! OUTPUT
20 : !! (main routine)
21 : !!
22 : !! NOTES
23 : !! GKK file structure is composed of header records and eigenvalue arrays,
24 : !! in binary or ascii:
25 : !! GS header = hdr
26 : !! GS eigenvalues = eigen
27 : !! number of perturbations = ntot
28 : !! for each perturbation
29 : !! 1WF header = hdr1
30 : !! 1st order eigenvalues = eigen1
31 : !!
32 : !! SOURCE
33 :
34 : #if defined HAVE_CONFIG_H
35 : #include "config.h"
36 : #endif
37 :
38 : #include "abi_common.h"
39 :
40 14 : program mrggkk
41 :
42 14 : use defs_basis
43 : use m_abicore
44 : use m_xmpi
45 : use m_errors
46 : use m_wfk
47 : use m_nctk
48 : use netcdf
49 : use m_hdr
50 :
51 : use m_build_info, only : abinit_version
52 : use m_specialmsg, only : specialmsg_getcount, herald
53 : use m_fstrings, only : endswith, sjoin
54 : use m_io_tools, only : flush_unit, open_file, file_exists
55 : use m_mpinfo, only : destroy_mpi_enreg, initmpi_seq
56 :
57 : implicit none
58 :
59 : !Arguments ------------------------------------
60 :
61 : !Local variables-------------------------------
62 : !scalars
63 : integer,parameter :: unit1wf=22,unitgkk=24,unitgs=21,unitout=23,formeig0=0,formeig1=1
64 : integer :: binascii,fform,headform,i1wf,igkk,ik_ibz,ios,spin,mband
65 : integer :: n1wf,ngkk,ntot,ntotgkk,comm,iomode
66 : integer :: iband,jband,nband_k,rdwrout,ierr,ipos !base,
67 : real(dp) :: tolgkk=tol6
68 : character(len=1),parameter :: comment="#"
69 : character(len=24) :: codename
70 : character(len=500) :: msg
71 : character(len=fnlen) :: file1wf,filegkk,filegs,outfile
72 14 : type(hdr_type) :: hdr,hdr1
73 98 : type(wfk_t) :: GS_wfk,PH_wfk
74 : !arrays
75 14 : real(dp),allocatable :: eig_k(:)
76 :
77 : ! *************************************************************************
78 :
79 : !Change communicator for I/O (mandatory!)
80 14 : call abi_io_redirect(new_io_comm=xmpi_world)
81 :
82 : !Initialize MPI
83 14 : call xmpi_init()
84 14 : comm = xmpi_world
85 :
86 : !Initialize memory profiling if it is activated
87 : !if a full abimem.mocc report is desired, set the argument of abimem_init to "2" instead of "0"
88 : !note that abimem.mocc files can easily be multiple GB in size so don't use this option normally
89 : #ifdef HAVE_MEM_PROFILING
90 : call abimem_init(0)
91 : #endif
92 :
93 14 : codename='MRGGKK'//repeat(' ',18)
94 :
95 : !write greating,read the file names, etc.
96 14 : call herald(codename,abinit_version,std_out)
97 :
98 : write(msg,'(17a)')&
99 14 : & ' Files file format: ',ch10,ch10,&
100 14 : & ' Name of the output file',ch10,&
101 14 : & ' Integer flag: 0 --> binary output, 1 --> ascii formatted output',ch10,&
102 14 : & ' Name of the groud state wavefunction file WF',ch10,&
103 14 : & ' Number of 1WF, of GKK files, and number of 1WF files in all the GKK files',ch10,&
104 14 : & ' Names of the 1WF files...',ch10,&
105 14 : & ' Names of the GKK files...',ch10,ch10,&
106 28 : & ' Enter name of output file: '
107 14 : call wrtout(std_out,msg)
108 :
109 : !get file with filenames and number of 1wf files
110 14 : read(*,'(a)') outfile
111 14 : ipos=INDEX(outfile,comment)
112 14 : if (ipos/=0) outfile=outfile(:ipos-1)
113 :
114 14 : read(*,*) binascii
115 :
116 14 : read(*,'(a)') filegs
117 14 : ipos=INDEX(filegs,comment)
118 14 : if (ipos/=0) filegs=filegs(:ipos-1)
119 :
120 14 : read(*,*) n1wf,ngkk,ntotgkk
121 :
122 : write(msg,'(7a,i4,2a,i4,2a,i4,a)')&
123 14 : ' Output = ',trim(outfile),ch10,&
124 14 : ' Ground State file = ',trim(filegs),ch10,&
125 14 : ' Number of 1WF files = ',n1wf,ch10,&
126 14 : ' Number of GKK files = ',ngkk,ch10,&
127 28 : ' Total Number of 1WF in GKK = ',ntotgkk,ch10
128 14 : call wrtout(std_out,msg)
129 :
130 14 : iomode = IO_MODE_FORTRAN
131 : #ifdef HAVE_MPI_IO
132 14 : iomode = IO_MODE_MPI
133 : #endif
134 : !iomode = IO_MODE_FORTRAN
135 :
136 : ! Trick needed so that we can run the automatic tests with both Fortran and netcdf
137 14 : if (.not. file_exists(filegs) .and. file_exists(nctk_ncify(filegs))) then
138 14 : write(msg, "(3a)")"- File: ",trim(filegs)," does not exist but found netcdf file with similar name."
139 14 : call wrtout(std_out,msg)
140 14 : filegs = nctk_ncify(filegs)
141 28 : iomode = IO_MODE_ETSF
142 : end if
143 :
144 : !output without rewinding the file
145 14 : if (binascii == 0) then
146 : ! open output file
147 14 : ios = open_file(outfile,msg,unit=unitout,form='unformatted')
148 14 : rdwrout = 6
149 0 : else if (binascii == 1) then
150 : ! rdwrout=4 ! use for screen output and change writes of eigen to (*,*)
151 : ! MJV 27/5/2008 removed 'new' constraint on gkk files: presume competent user!
152 0 : ios = open_file(outfile,msg,unit=unitout,form='formatted')
153 0 : rdwrout = 4
154 0 : else if (binascii == 2) then
155 : ! this is for simple "short" output of the matrices, without headers or imaginary part
156 0 : ios = open_file(outfile,msg,unit=unitout,form='formatted')
157 0 : rdwrout = 4
158 : else
159 0 : ABI_ERROR(' binascii must be between 0 and 2')
160 : end if
161 :
162 14 : ABI_CHECK(ios==0,msg)
163 14 : rewind (unitout)
164 :
165 : !-------------------------------------------------------
166 : !now read and write information for GS file
167 : !-------------------------------------------------------
168 :
169 : !open GS wf file
170 14 : call wrtout(std_out,' normal input for GS file')
171 14 : call gs_wfk%open_read(filegs, formeig0, iomode, unitgs, comm)
172 :
173 : !Copy header of GS file to output.
174 14 : if (binascii /= 2) then
175 14 : if (rdwrout == 4) then
176 0 : call GS_wfk%Hdr%echo(GS_wfk%fform, rdwrout)
177 : else
178 14 : call GS_wfk%Hdr%fort_write(unitout, GS_wfk%fform, ierr)
179 14 : ABI_CHECK(ierr == 0 , "hdr_fort_write returned ierr != 0")
180 : end if
181 : end if
182 14 : call wrtout(std_out,' header echoed to output file')
183 :
184 14 : ABI_MALLOC(eig_k,(GS_wfk%mband))
185 :
186 : !Retrieve GS eigenvalues from GS wf file and echo to output
187 30 : do spin=1,GS_wfk%nsppol
188 942 : do ik_ibz=1,GS_wfk%nkpt
189 912 : nband_k = GS_wfk%nband(ik_ibz,spin)
190 :
191 912 : call GS_wfk%read_eigk(ik_ibz,spin,xmpio_single,eig_k)
192 928 : if (binascii==0) then
193 912 : write(unitout) eig_k(1:nband_k)
194 : else
195 0 : write(unitout,*) eig_k(1:nband_k)
196 : end if
197 : end do
198 : end do
199 :
200 14 : ABI_FREE(eig_k)
201 :
202 : !Close GS wf file
203 14 : call GS_wfk%close()
204 :
205 14 : ntot = n1wf + ntotgkk
206 14 : if (binascii==0) then
207 14 : write (unitout) ntot
208 : else
209 0 : write (unitout,*) ntot
210 : end if
211 :
212 : !-------------------------------------------------------
213 : !now read and write information for 1WF files
214 : !-------------------------------------------------------
215 50 : do i1wf=1,n1wf
216 : ! for each 1wf file, get name...
217 36 : read(*,'(a)') file1wf
218 36 : ipos=INDEX(file1wf,comment)
219 36 : if (ipos/=0) file1wf=file1wf(:ipos-1)
220 :
221 : ! Trick needed so that we can run the automatic tests with both Fortran and netcdf
222 36 : if (.not. file_exists(file1wf) .and. file_exists(nctk_ncify(file1wf))) then
223 36 : write(msg, "(3a)")"- File: ",trim(file1wf)," does not exist but found netcdf file with similar name."
224 36 : call wrtout(std_out,msg)
225 36 : file1wf = nctk_ncify(file1wf)
226 72 : iomode = IO_MODE_ETSF
227 : end if
228 :
229 : ! open 1wf file
230 36 : call wrtout(std_out,' normal input for 1WF file ')
231 36 : call ph_wfk%open_read(file1wf, formeig1, iomode, unit1wf, comm, Hdr_out=hdr1)
232 :
233 : ! copy header of 1WF file to output
234 36 : if (binascii /= 2) then
235 36 : if (rdwrout == 4) then
236 0 : call hdr1%echo(PH_wfk%fform, rdwrout)
237 : else
238 36 : call hdr1%fort_write(unitout, PH_wfk%fform, ierr)
239 36 : ABI_CHECK(ierr == 0 , "hdr_fort_write returned ierr != 0")
240 : end if
241 : else
242 0 : write (unitout,'(a,3E20.10)') "qpt ", hdr1%qptn
243 0 : write (unitout,'(a,I6)') "pertnum ", hdr1%pertcase
244 : end if
245 :
246 : ! retrieve 1WF <psi_k+q | H | psi_k> from 1wf file and echo to output
247 1408 : mband = maxval(hdr1%nband)
248 36 : headform=hdr1%headform
249 36 : ABI_MALLOC(eig_k,(2*mband*mband))
250 :
251 1462 : ABI_CHECK(ALL(PH_wfk%nband == PH_wfk%nband(1,1)),"nband must be constant")
252 :
253 90 : do spin=1,hdr1%nsppol
254 1426 : do ik_ibz=1,hdr1%nkpt
255 : ! write(std_out,*) 'spin,ik_ibz = ', spin,ik_ibz
256 1372 : nband_k = PH_wfk%nband(ik_ibz,spin)
257 :
258 1372 : call PH_wfk%read_eigk(ik_ibz,spin,xmpio_single,eig_k)
259 :
260 : !base = 0
261 : !do jband=1,nband_k
262 : ! base = 2*(jband-1)*nband_k
263 : ! do iband=1,2*nband_k
264 : ! write(777,*) iband,jband,eig_k(base+iband)
265 : ! end do
266 : !end do
267 :
268 1426 : if (binascii==0) then
269 1372 : write(unitout) eig_k(1:2*nband_k**2)
270 0 : else if (binascii==1) then
271 0 : write(unitout,*) eig_k(1:2*nband_k**2)
272 0 : else if (binascii==2) then
273 0 : do iband=1,nband_k
274 0 : do jband=1,nband_k
275 0 : if (abs(eig_k(2*nband_k*(iband-1)+2*(jband-1)+1))>tolgkk) then
276 0 : write(unitout,'(E18.7, 2x)', ADVANCE='NO') eig_k(2*nband_k*(iband-1)+2*(jband-1)+1)
277 : else
278 0 : write(unitout,'(I18, 2x)', ADVANCE='NO') 0
279 : end if
280 0 : if (abs(eig_k(2*nband_k*(iband-1)+2*(jband-1)+2))>tolgkk) then
281 0 : write(unitout,'(E18.7, 2x)', ADVANCE='NO') eig_k(2*nband_k*(iband-1)+2*(jband-1)+2)
282 : else
283 0 : write(unitout,'(I18, 2x)', ADVANCE='NO') 0
284 : end if
285 : end do
286 0 : write(unitout,*)
287 : end do
288 0 : write(unitout,*)
289 : end if
290 : !
291 : end do
292 90 : if (binascii==2) write(unitout,'(2a)') ch10, ch10
293 : end do
294 :
295 36 : ABI_FREE(eig_k)
296 :
297 : ! clean header to deallocate everything
298 36 : call hdr1%free()
299 50 : call PH_wfk%close()
300 : end do
301 :
302 : !-------------------------------------------------------
303 : !now read and write information for small GKK files
304 : !-------------------------------------------------------
305 146 : do igkk=1,ngkk
306 : !
307 : ! for each gkk file, get name...
308 132 : read(*,'(a)') filegkk
309 132 : ipos=INDEX(filegkk,comment)
310 132 : if (ipos/=0) filegkk=filegkk(:ipos-1)
311 :
312 : ! open gkk file
313 132 : call wrtout(std_out,' normal input for GKK file')
314 :
315 132 : if (open_file(filegkk,msg,unit=unitgkk,form='unformatted',status='old') /= 0) then
316 0 : ABI_ERROR(msg)
317 : end if
318 132 : rewind (unitgkk)
319 :
320 : ! read in header of GS file and eigenvalues
321 : ! could force a comparison of header with global header above for consistency
322 132 : call hdr%fort_read(unitgkk, fform)
323 132 : ABI_CHECK(fform /= 0, sjoin("fform == 0 while reading:", filegkk))
324 :
325 9012 : mband = maxval(hdr%nband)
326 132 : ABI_MALLOC(eig_k,(mband))
327 132 : call wrtout(std_out,'mrggkk : try to reread GS eigenvalues')
328 :
329 264 : do spin=1,hdr%nsppol
330 9144 : do ik_ibz=1,hdr%nkpt
331 8880 : nband_k = hdr%nband(ik_ibz + (spin-1)* hdr%nkpt)
332 8880 : read (unitgkk,IOSTAT=ierr) eig_k(1:nband_k)
333 9012 : ABI_CHECK(ierr==0,'error reading eigen from gkk file')
334 : end do
335 : end do
336 132 : ABI_FREE(eig_k)
337 :
338 132 : read(unitgkk,IOSTAT=ierr) n1wf
339 132 : ABI_CHECK(ierr==0,'error reading n1wf record')
340 :
341 132 : ABI_MALLOC(eig_k,(2*mband*mband))
342 264 : do i1wf=1,n1wf
343 : ! read in header of 1WF file
344 132 : call hdr1%fort_read(unitgkk, fform)
345 132 : if (fform == 0) then
346 0 : write(msg,'(a,i0,a)')' 1WF header number ',i1wf,' was mis-read. fform == 0'
347 0 : ABI_ERROR(msg)
348 : end if
349 :
350 : ! copy header of 1WF file to output
351 132 : if (binascii /= 2) then
352 132 : if (rdwrout == 4) then
353 0 : call hdr1%echo(fform, rdwrout)
354 : else
355 132 : call hdr1%fort_write(unitout, fform, ierr)
356 132 : ABI_CHECK(ierr == 0 , "hdr_fort_write returned ierr != 0")
357 : end if
358 : else
359 0 : write (unitout,'(a,3E20.10)') "qpt ", hdr1%qptn
360 0 : write (unitout,'(a,I6)') "pertnum ", hdr1%pertcase
361 : end if
362 :
363 : ! retrieve 1WF <psi_k+q | H | psi_k> from gkk file and echo to output
364 264 : do spin=1,hdr1%nsppol
365 9012 : do ik_ibz=1,hdr1%nkpt
366 8880 : nband_k = hdr%nband(ik_ibz + (spin-1)* hdr1%nkpt)
367 8880 : read (unitgkk,IOSTAT=ierr) eig_k(1:2*nband_k**2)
368 8880 : if (ierr /= 0) write (std_out,*) 'error reading eigen2 from gkk file',spin,ik_ibz
369 :
370 9012 : if (binascii==0) then
371 8880 : write (unitout) eig_k(1:2*nband_k**2)
372 0 : else if (binascii==1) then
373 0 : write (unitout,*) eig_k(1:2*nband_k**2)
374 0 : else if (binascii==2) then
375 0 : do iband=1,nband_k
376 0 : do jband=1,nband_k
377 0 : if (abs(eig_k(2*nband_k*(iband-1)+2*(jband-1)+1))>tolgkk) then
378 0 : write(unitout,'(E18.7, 2x)', ADVANCE='NO') eig_k(2*nband_k*(iband-1)+2*(jband-1)+1)
379 : else
380 0 : write(unitout,'(I18, 2x)', ADVANCE='NO') 0
381 : end if
382 0 : if (abs(eig_k(2*nband_k*(iband-1)+2*(jband-1)+2))>tolgkk) then
383 0 : write(unitout,'(E18.7, 2x)', ADVANCE='NO') eig_k(2*nband_k*(iband-1)+2*(jband-1)+2)
384 : else
385 0 : write(unitout,'(I18, 2x)', ADVANCE='NO') 0
386 : end if
387 : end do
388 0 : write(unitout,*)
389 : end do
390 0 : write(unitout,*)
391 : end if
392 : !
393 : end do
394 264 : if (binascii==2) write(unitout,'(2a)') ch10, ch10
395 : end do
396 264 : call hdr1%free()
397 : end do ! end loop over 1wf segments in small gkk file
398 :
399 132 : ABI_FREE(eig_k)
400 :
401 132 : close (unitgkk)
402 146 : call hdr%free()
403 : end do !end loop over small gkk files
404 :
405 14 : close(unitout)
406 :
407 14 : write(msg,'(2a)')ch10,' Done'
408 14 : call wrtout(std_out,msg)
409 :
410 14 : call flush_unit(std_out)
411 14 : call abinit_doctor("__mrggkk")
412 :
413 14 : call xmpi_end()
414 :
415 0 : end program mrggkk
416 : !!***
|