Line data Source code
1 : !!****m* ABINIT/m_outwant
2 : !! NAME
3 : !! m_outwant
4 : !!
5 : !! FUNCTION
6 : !! Interface with want code.
7 : !!
8 : !! COPYRIGHT
9 : !! Copyright (C) 2005-2026 ABINIT group (CMorari)
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_outwant
24 :
25 : use defs_basis
26 : use m_errors
27 : use m_abicore
28 : use m_hdr
29 : use m_dtset
30 :
31 : use m_io_tools, only : open_file
32 : use m_matrix, only : matr3inv
33 :
34 : implicit none
35 :
36 : private
37 : public :: outwant
38 :
39 : contains
40 : !!***
41 :
42 : !!****f* m_outwant/outwant
43 : !! NAME
44 : !! outwant
45 : !!
46 : !! FUNCTION
47 : !! This routine creates an output file containing all the
48 : !! information needed to run WanT as a post-processing program
49 : !! The resulting file is 'launch.dat'.
50 : !!
51 : !! The routine writes to the disk (unformatted file unitwnt) the following information:
52 : !!
53 : !! alat - lattice parameter
54 : !! rprim - primitive translation vectors
55 : !! ntypat - nr of atom types in elementary cell
56 : !! tpat - nr of types of atoms in the elementary cell
57 : !! xcart - cartesian coordinates of the atoms in the elem. cell
58 : !! ecut - energy cut-off
59 : !! mband - # of bands taken in calculation (same for each K-pt)
60 : !! nk(3) - # of k-pts for each direction (uniform grid in the WHOLE BZ)
61 : !! s0(3) - the origin of the K-space
62 : !! kg_tmp(3,mpw*mkmem ) - reduced planewave coordinates
63 : !! imax - Maximum index of a G vector among all k points (see explanation bellow)
64 : !! nkpt - total no of K-pts
65 : !! nsppol - nr of spin polarisations (1 or 2)
66 : !! eig(mband, nkp_tot) - eigenvalues/band/K_point
67 : !! ngfft(3) - nr of points used for FFT in each direction
68 : !! wfc(i)- cmplx(cg(1,i),cg(2,i)) - wavefunction
69 : !!
70 : !! INPUTS
71 : !! dtset <type(dataset_type)>=all input variables for this dataset
72 : !! eig(mband*nkpt*nsppol) = array for holding eigenvalues (Hartree)
73 : !! cg(2,mcg) = planewave coefficients of wavefunction
74 : !! kg(3, mpw*mkmem) = reduced planewave coordinates
75 : !! npwarr(nkpt) = number of planewaves in basis at this k-point
76 : !! mband = maximum number of bands
77 : !! mcg=size of wave-functions array (cg) =mpw*nspinor*mband*mkmem*nsppol
78 : !! nkpt = number of k - points
79 : !! nsppol = 1 for unpolarized, 2 for spin polarized
80 : !! nspinor = number of spinorial components of the wavefunction (on current proc)
81 : !! mkmem = number of k points treated by this node.
82 : !! mpw = maximum dimensioned size of npw
83 : !! prtwant = if set to 1, print 0 in S0 output
84 : !!
85 : !! OUTPUT
86 : !! (only writing)
87 : !!
88 : !! SOURCE
89 :
90 1 : subroutine outwant(dtset,eig,cg,kg,npwarr,mband,mcg,nkpt,nsppol,mkmem,mpw,prtwant)
91 :
92 : !Arguments ------------------------------------
93 : !scalars
94 : integer :: mband,mcg,mkmem,mpw,nkpt,nsppol,prtwant
95 : type(dataset_type),intent(in) :: dtset
96 : !arrays
97 : integer :: kg(3,mpw*mkmem),npwarr(nkpt)
98 : real(dp) :: cg(2,mcg),eig(mband*nkpt*nsppol)
99 :
100 : !Local variables-------------------------------
101 : ! the following variables are not used; they are written to 'launch.dat'
102 : ! in order to be compatible with the WANT format
103 : !scalars
104 : integer :: bandtot,i,icount,ifind,ig,ii,iij,ik,ik_,imax
105 : integer :: index,index1,ispin_,iunit,iwf,iwf_k,j,k
106 : integer :: maxat,ngm,ngw_,nk_,nkp,nspin_
107 : integer :: unitwnt
108 : real(dp) :: alat,scal,scal_,tt
109 : logical :: twrite=.true.
110 : character(len=20) :: section_name
111 : character(len=3) :: nameat
112 : character(len=500) :: message
113 : character(len=fnlen) :: filewnt
114 : !arrays
115 : integer :: ikg(3),nk(3)
116 1 : integer,allocatable :: iwfi(:,:),kg_tmp(:,:),tpat(:)
117 : real(dp) :: drprim(3,3),gmat(3,3),gmod(3),s0(3),t1(3),t2(3)
118 1 : real(dp),allocatable :: xcoord(:,:,:)
119 1 : complex,allocatable :: wfc(:)
120 :
121 : ! ***************************************************************************
122 :
123 : !WARNING: not tested for nsppol,nspinor >1
124 : !
125 : !Initialisations
126 1 : nameat = ' '
127 1 : bandtot=mband*nkpt*nsppol*dtset%nspinor
128 1 : filewnt='launch.dat'
129 :
130 1 : write(message,'(3a)')ch10,' Opening file for WanT input: ',trim(filewnt)
131 1 : call wrtout(std_out,message,'COLL')
132 :
133 : !Open the file
134 1 : if (open_file(filewnt,message,newunit=unitwnt,form='unformatted', status='unknown') /=0) then
135 0 : ABI_ERROR(message)
136 : end if
137 :
138 : !Comments
139 1 : if(prtwant>1) then
140 0 : write(std_out,*) 'Wrong value for prtwant. Reseting to 1'
141 0 : prtwant=1
142 1 : elseif(prtwant==1) then
143 4 : do i=1,3
144 4 : s0(i)=0._dp
145 : end do
146 : end if
147 :
148 : !Discussion of 'alat' ABINIT/ WanT
149 1 : if(dtset%acell_orig(1,1)==dtset%acell_orig(2,1).and.&
150 : dtset%acell_orig(1,1)==dtset%acell_orig(3,1)) then
151 1 : alat=dtset%acell_orig(1,1)
152 4 : do i=1,3
153 13 : do j=1,3
154 12 : drprim( i, j) = dtset%rprim_orig( i, j, 1 )
155 : end do
156 : end do
157 : else
158 : ! Redefining the drprim( i, j)
159 0 : alat=dtset%acell_orig(1,1)
160 0 : do i=1,3
161 0 : do j=1,3
162 0 : drprim( i, j) = dtset%rprim_orig( i, j, 1 )*dtset%acell_orig(j, 1)/alat
163 : end do
164 : end do
165 : end if
166 :
167 : !Now finding the no of k-pt for each direction PARALEL with the
168 : !generators of the first B.Z.
169 : !First decide if we have the Gamma point in the list; its index in the list is ... index
170 4 : nk(:)=1
171 1 : ifind=0
172 1 : icount=2
173 5 : do i=1,nkpt
174 : index1=0
175 16 : do j=1,3
176 16 : if(dtset%kptns(j,i)<tol8) index1=index1+1
177 : end do
178 5 : if(index1==3) then
179 1 : index=i
180 1 : ifind=1
181 1 : cycle
182 : end if
183 : end do
184 1 : if(ifind==0) then
185 0 : write(std_out,*) 'GAMMA POINT NOT IN THE LIST OF KPTS?'
186 0 : do ii=1,nkpt
187 0 : write(std_out,*) (dtset%kptns(j,ii),j=1,3)
188 : end do
189 0 : ABI_ERROR("fatal error")
190 : end if
191 :
192 1 : call matr3inv(drprim,gmat)
193 :
194 : !Modules for each vector in recip. space; nb: g(index coord, index point)
195 4 : do j=1,3
196 3 : gmod(j)=0.D0
197 12 : do i=1,3
198 12 : gmod(j)=gmod(j)+gmat(i,j)**2
199 : end do
200 4 : gmod(j)=sqrt(gmod(j))
201 : end do
202 1 : if(nkpt==2) then
203 0 : do j=1,3
204 0 : do ii=1,3
205 0 : t1(ii)=dtset%kptns(ii,1)-dtset%kptns(ii,2)
206 : end do
207 : tt=0._dp
208 0 : do iij=1,3
209 0 : t2(iij)=0._dp
210 0 : do ii=1,3
211 0 : t2(iij)=t2(iij)+t1(ii)*gmat(ii,iij)
212 : end do
213 0 : tt=tt + t2(iij)**2
214 : end do
215 0 : tt=sqrt(tt)
216 0 : scal=0._dp
217 0 : do ii=1,3
218 0 : scal=scal+t2(ii)*gmat(j,ii)
219 : end do
220 0 : scal=abs(scal)
221 : ! Compare scal(tt,gmat) with simple product of modules -> paralel or not
222 0 : if(abs(scal-tt*gmod(j))<tol8) nk(j)=2
223 : end do
224 :
225 1 : elseif(nkpt>2) then
226 :
227 5 : do i=1,nkpt
228 5 : if(i.ne.index) then
229 12 : do ii=1,3
230 12 : t1(ii)=dtset%kptns(ii,index)-dtset%kptns(ii,i)
231 : end do
232 : tt=0._dp
233 12 : do iij=1,3
234 9 : t2(iij)=0._dp
235 36 : do ii=1,3
236 36 : t2(iij)=t2(iij)+t1(ii)*gmat(ii,iij)
237 : end do
238 12 : tt=tt + t2(iij)**2
239 : end do
240 3 : tt=sqrt(tt)
241 : ! check for each direction in the BZ
242 12 : do j=1,3
243 : scal=0._dp
244 36 : do ii=1,3
245 36 : scal=scal+t2(ii)*gmat(j,ii)
246 : end do
247 9 : scal=abs(scal)
248 : ! Compare scal(t1,gmat) with simple product of modules -> paralel or not
249 12 : if(abs(scal-tt*gmod(j))<tol8) nk(j)=nk(j)+1
250 : end do
251 : end if
252 : end do
253 : end if
254 1 : index=1
255 4 : do i=1,3
256 4 : index=index*nk(i)
257 : end do
258 :
259 1 : if(index.ne.nkpt) then
260 0 : write(message,'(a,2i0)')' OutwanT: Wrong assignemt of kpts', index,nkpt
261 0 : ABI_ERROR(message)
262 : end if
263 :
264 : !End counting/assigning no of kpts/direction
265 : !Reordering the coordinates of all atoms - xcoord array
266 3 : ABI_MALLOC(tpat,(dtset%ntypat))
267 2 : tpat(:)=zero
268 2 : do i=1,dtset%natom
269 3 : do j=1,dtset%ntypat
270 2 : if(dtset%typat(i)==j) tpat(j)=tpat(j)+1
271 : end do
272 : end do
273 2 : maxat=maxval(tpat(:))
274 4 : ABI_MALLOC(xcoord,(3,maxat,dtset%ntypat))
275 1 : index=1
276 2 : do i=1, dtset%ntypat
277 3 : do k=1,tpat(i)
278 4 : do j=1,3
279 4 : xcoord(j,k,i)=dtset%xred_orig(j,index,1)
280 : end do
281 2 : index=index+1
282 : end do
283 : end do
284 : !
285 : !Defining the kg_tmp list
286 : !Preparing the output of reduced coords., in a single list (kg_tmp(3,imax))
287 : !We start with kg_tmp(:,i)=kg(:,i=1,npwarr(1)) then the new coordinates are added
288 : !ONLY if they are not allready in the list. An index is associated
289 : !for each kg_tmp which allow us to recover kg(3,mpw*nkpt) from
290 : !the smaller list kg_tmp(3, imax)
291 3 : ABI_MALLOC(kg_tmp,(3,mpw*nkpt))
292 4 : ABI_MALLOC(iwfi,(nkpt,mpw))
293 7873 : kg_tmp(:,:)=zero
294 2461 : iwfi(:,:)=zero
295 1 : imax=npwarr(1)
296 1 : index=0
297 :
298 5 : do i=1, nkpt
299 4 : if(i>1) then
300 3 : index=index+npwarr(i-1)
301 : end if
302 1892 : do j=1, npwarr(i)
303 1891 : if(i.eq.1) then
304 459 : iwfi(i,j)=j
305 1836 : if(mkmem>0) kg_tmp(:,j)=kg(:,j)
306 : else
307 1428 : ifind=0
308 5712 : if(mkmem>0) ikg(:)=kg(:,index+j)
309 :
310 754939 : do k=1,imax
311 754939 : if(ikg(1)==kg_tmp(1,k)) then
312 57817 : if(ikg(2)==kg_tmp(2,k)) then
313 4361 : if(ikg(3)==kg_tmp(3,k)) then
314 1279 : ifind=1
315 1279 : iwfi(i,j)=k
316 : end if
317 : end if
318 : end if
319 : end do
320 :
321 1428 : if(ifind==0) then
322 149 : imax=imax+1
323 596 : kg_tmp(:,imax)=ikg(:)
324 149 : iwfi(i,j)=imax
325 : end if
326 : end if
327 : end do
328 : end do
329 1 : ngm=imax
330 :
331 : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
332 : !PART ONE: writing the header
333 : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
334 1 : write(unitwnt) alat
335 1 : write(unitwnt) ( drprim( i, 1 ), i = 1, 3 ) ! save A1
336 1 : write(unitwnt) ( drprim( i, 2 ), i = 1, 3 ) ! save A2
337 1 : write(unitwnt) ( drprim( i, 3 ), i = 1, 3 ) ! save A3
338 : !write(std_out,* ) ( drprim( i, 1 ), i = 1, 3 ) ! save A1
339 : !write(std_out,* ) ( drprim( i, 2 ), i = 1, 3 ) ! save A2
340 : !write(std_out,* ) ( drprim( i, 3 ), i = 1, 3 ) ! save A3
341 :
342 1 : write(unitwnt) dtset%ntypat
343 : !write(std_out,*) dtset%ntypat, 'NTYPAT', tpat
344 :
345 2 : do i = 1, dtset%ntypat
346 1 : write(unitwnt) tpat(i), nameat
347 2 : write(unitwnt) ((xcoord(j,k,i),j=1,3), k=1, tpat(i))
348 : ! write(std_out,*) tpat(i), nameat
349 : ! write(std_out,*) ((xcoord(j,k,i),j=1,3),k=1,tpat(i)), 'XCART'
350 : end do
351 1 : ABI_FREE(tpat)
352 1 : ABI_FREE(xcoord)
353 :
354 : !energy cut-off in Rydberg (WANT option)
355 1 : write (unitwnt) 2._dp*dtset%ecut, mband
356 : !write(std_out,*) 2._dp*dtset%ecut, mband
357 1 : write (unitwnt) ( nk(i), i = 1, 3 ), ( s0(j), j = 1, 3 ),ngm
358 : !write(std_out,*) ( nk(i), i = 1, 3 ), ( s0(j), j = 1, 3 ),imax
359 609 : write (unitwnt) ( kg_tmp( 1, i ), kg_tmp( 2, i ), kg_tmp( 3, i ), i = 1, ngm )
360 1 : write (unitwnt) mpw, mband, dtset%nkpt/dtset%nsppol
361 : !write(std_out,*) mpw, mband, dtset%nkpt/dtset%nsppol
362 :
363 5 : do i=1, nkpt
364 5 : write(unitwnt) (iwfi(i,j), j=1,mpw)
365 : end do
366 1 : ABI_FREE(kg_tmp)
367 :
368 : !Eigenvalues in HARTREE
369 1 : write (unitwnt) ( eig( i ), i = 1, bandtot)
370 1 : write (unitwnt) ( npwarr( ik ), ik = 1, nkpt )
371 5 : write (unitwnt) ( mband, ik = 1, nkpt )
372 4 : write (unitwnt) (dtset%ngfft(i),i=1,3), imax, imax
373 : !write(std_out,*) ( eig( i ), i = 1, bandtot )
374 : !write(std_out,*) ( npwarr( ik ), ik = 1, nkpt )
375 : !write(std_out,*) ( mband, ik = 1, nkpt )
376 : !write(std_out,*) (dtset%ngfft(i),i=1,3), imax ,imax
377 : !a list with the band structure; usefull for 'windows' and 'disentangle' programs
378 : !from WanT distribution
379 :
380 1 : if (open_file('band.gpl',message,newunit=iunit,status='unknown') /=0) then
381 0 : ABI_ERROR(message)
382 : end if
383 :
384 1 : index=1
385 11 : do i=1,mband
386 10 : index=1
387 50 : do j=1,nkpt
388 40 : write(iunit,*) index, Ha_eV*eig(i+(j-1)*mband), eig(i+(j-1)*mband)
389 50 : index=index+1
390 : end do
391 11 : write(iunit,*)
392 : end do
393 :
394 1 : close(iunit)
395 :
396 : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
397 : !PART TWO: Writing the wavefunction
398 : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
399 : !not used
400 1 : ngw_=0
401 1 : ik_=0
402 1 : nk_=0
403 1 : ispin_=0
404 1 : nspin_=0
405 1 : scal_=1._dp
406 : !!!!!!!!!!!!!!!!!!!!!!!!!!
407 1 : iwf = 1
408 1 : iwf_k=1
409 3 : ABI_MALLOC(wfc,(imax))
410 :
411 : !Loop over k-pt
412 5 : do nkp=1,nkpt
413 : ! Not relevant
414 4 : write(unitwnt) twrite, ik_, section_name
415 : ! Only 'mband' is relevant here
416 4 : write(unitwnt) ngw_, mband, ik_, nk_, nk_,ispin_, nspin_, scal_
417 4 : write(unitwnt) imax
418 : ! Not relevant
419 4 : write(unitwnt) twrite
420 : ! Loop over bands
421 :
422 : ! Preparing WF
423 44 : do k=1,mband
424 40 : if(mkmem >0) then
425 24360 : wfc(:)=zero
426 : ! From cg to wf:
427 18910 : do i=iwf, iwf+npwarr(nkp)-1
428 18870 : index=i-iwf+1
429 18910 : wfc(iwfi(nkp,index))=cmplx(cg(1,i), cg(2,i), kind(0._dp))
430 : end do
431 : iwf=iwf+npwarr(nkp)
432 : else
433 0 : message = 'Wrong mkmem in outwant'
434 0 : ABI_ERROR(message)
435 : end if
436 44 : write(unitwnt) (wfc(ig), ig=1,imax)
437 : ! End loop over bands
438 : end do
439 :
440 : ! Not relevant
441 4 : write(unitwnt) twrite
442 : ! Not relevant
443 45 : do i=1,mband
444 44 : write(unitwnt) i
445 : end do
446 :
447 : ! End loop over k-pts
448 : end do
449 :
450 1 : ABI_FREE(iwfi)
451 1 : ABI_FREE(wfc)
452 :
453 1 : call wrtout(std_out,'Closing file','COLL')
454 1 : close(unit=unitwnt)
455 :
456 1 : end subroutine outwant
457 : !!***
458 :
459 : end module m_outwant
460 : !!***
|