Line data Source code
1 : !!****m* ABINIT/m_nesting
2 : !! NAME
3 : !! m_nesting
4 : !!
5 : !! FUNCTION
6 : !! This module provides functions to compute the nesting factor:
7 : !! N(\qq) = \sum_{mn\kk} \delta(\ee_{\kpq m}) \delta(\ee_{\kk n})
8 : !!
9 : !! COPYRIGHT
10 : !! Copyright (C) 2008-2026 ABINIT group (MG, MJV)
11 : !! This file is distributed under the terms of the
12 : !! GNU General Public License, see ~abinit/COPYING
13 : !! or http://www.gnu.org/copyleft/gpl.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_nesting
24 :
25 : use defs_basis
26 : use m_errors
27 : use m_abicore
28 : use m_krank
29 : use m_sort
30 :
31 : use m_numeric_tools, only : wrap2_zero_one, interpol3d_0d
32 : use m_io_tools, only : open_file
33 : use m_bz_mesh, only : make_path
34 : use m_pptools, only : printxsf
35 :
36 : implicit none
37 :
38 : private
39 :
40 : public :: bfactor
41 : public :: mknesting
42 : public :: outnesting
43 : !!***
44 :
45 : !----------------------------------------------------------------------
46 :
47 : CONTAINS !=============================================================================
48 : !!***
49 :
50 : !!****f* m_nesting/bfactor
51 : !! NAME
52 : !! bfactor
53 : !!
54 : !! FUNCTION
55 : !! Calculate the nesting factor
56 : !!
57 : !! INPUTS
58 : !! nkptfull = number of k-points in full grid
59 : !! kptfull(3,nkptfull) = k-point grid
60 : !! nqpt = number of qpoints
61 : !! qpt(3,nqpt) = q-point grid (must be a subgrid of the k grid),
62 : !! the nesting factor will be calculated for each q point in this array
63 : !! nkpt = eventually reduced number of k-points
64 : !! weight(nband,nkpt) = integration weights for each k-point and band (NOT NORMALISED!!!)
65 : !! nband = number of bands
66 : !!
67 : !! OUTPUT
68 : !! nestfactor(nqpt) = array containing the nesting factor values
69 : !!
70 : !! NOTES
71 : !! Inspired to nmsq_gam_sumfs and mkqptequiv
72 : !! TODO : better use of symmetries to reduce the computational effort
73 : !! Must be called with kpt = full grid! Reduction by symmetry is not possible for q-dependent quantities (or not easy :)
74 : !!
75 : !! SOURCE
76 :
77 23 : subroutine bfactor(nkptfull,kptfull,nqpt,qpt,krank,nkpt,weight,nband,nestfactor)
78 :
79 : !Arguments ------------------------------------
80 : !scalars
81 : integer,intent(in) :: nband,nkptfull,nqpt,nkpt
82 : !arrays
83 : real(dp),intent(in) :: kptfull(3,nkptfull),qpt(3,nqpt),weight(nband,nkpt)
84 : real(dp),intent(out) :: nestfactor(nqpt)
85 : type(krank_t), intent(in) :: krank
86 :
87 : !Local variables-------------------------------
88 : !scalars
89 : integer :: ib1,ib2,ikplusq_irr,ikpt
90 : integer :: irank_kpt,ikpt_irr,iqpt,symrank_kpt
91 : real(dp) :: w1,w2
92 : !character(len=500) :: msg
93 : !arrays
94 : real(dp) :: kptpq(3)
95 : ! *************************************************************************
96 :
97 1056 : nestfactor(:)=zero
98 :
99 1056 : do iqpt=1,nqpt
100 364944 : do ikpt=1,nkptfull
101 363888 : irank_kpt = krank%get_rank(kptfull(:,ikpt))
102 363888 : ikpt_irr = krank%invrank(irank_kpt)
103 :
104 1455552 : kptpq(:) = kptfull(:,ikpt) + qpt(:,iqpt)
105 363888 : symrank_kpt = krank%get_rank(kptpq)
106 :
107 363888 : ikplusq_irr = krank%invrank(symrank_kpt)
108 363888 : if (ikplusq_irr == -1) then
109 0 : ABI_ERROR('It looks like no kpoint equiv to k+q!')
110 : end if
111 :
112 2286441 : do ib1=1,nband
113 1921520 : w1 = weight(ib1, ikpt_irr) ! weight for distance from the Fermi surface
114 1921520 : if (w1 < tol6 ) cycle
115 3912420 : do ib2=1,nband
116 2973720 : w2 = weight(ib2, ikplusq_irr) ! weight for distance from the Fermi surface
117 : if (w1 < tol6 ) cycle
118 4895240 : nestfactor(iqpt) = nestfactor(iqpt) + w1 * w2
119 : end do !ib2
120 : end do !ib1
121 :
122 : end do !ikpt
123 : end do !iqpt
124 :
125 : ! need prefactor of (1/nkptfull) for normalisation of integration
126 1056 : nestfactor(:) = (one/nkptfull) * nestfactor(:)
127 :
128 23 : end subroutine bfactor
129 : !!***
130 :
131 : !----------------------------------------------------------------------
132 :
133 : !!****f* m_nesting/mknesting
134 : !! NAME
135 : !! mknesting
136 : !!
137 : !! FUNCTION
138 : !! Calculate the nesting factor over the dense k-grid, interpolate the values along a given q path
139 : !! and write the data on file in the X-Y format or in the XCrysden format (XSF)
140 : !!
141 : !! INPUTS
142 : !! nkpt = number of k points
143 : !! kpt(3,nkpt) = k points
144 : !! nkx, nky, nkz = number of k-point along each direction
145 : !! nband = number of bands to be considered in the calculation
146 : !! weight(nband,nkpt) = integration weights for each k-point and band
147 : !! nqpath = number of points requested along the trajectory
148 : !! qpath_vertices = vertices of the reciprocal space trajectory
149 : !! base_name = prefix of the output file
150 : !! gprimd(3,3) dimensional reciprocal lattice vectors
151 : !! gmet = metric in reciprocal space
152 : !! prtnest = flags governing the format of the output file
153 : !!
154 : !! OUTPUT
155 : !! Write data to file.
156 : !!
157 : !! SOURCE
158 :
159 4 : subroutine mknesting(nkpt,kpt,kptrlatt,nband,weight,nqpath,&
160 4 : qpath_vertices,nqptfull,qptfull,base_name,gprimd,gmet,prtnest,qptrlatt,&
161 : nsym,symrec) ! optional
162 :
163 : !Arguments ------------------------------------
164 : !scalars
165 : integer,intent(in) :: nband,nkpt,nqpath,prtnest
166 : integer, intent(in) :: nqptfull
167 : integer, intent(in), optional :: nsym
168 : character(len=*),intent(in) :: base_name
169 : !arrays
170 : integer,intent(in) :: kptrlatt(3,3)
171 : integer,intent(in),optional :: symrec(3,3,*)
172 : real(dp),intent(in) :: gprimd(3,3),kpt(3,nkpt)
173 : real(dp),intent(in) :: qptfull(3,nqptfull)
174 : real(dp),intent(in) :: gmet(3,3)
175 : real(dp),intent(in) :: qpath_vertices(3,nqpath)
176 : real(dp),intent(in) :: weight(nband,nkpt)
177 : integer,intent(in) :: qptrlatt(3,3)
178 :
179 : !Local variables-------------------------------
180 : !scalars
181 : integer :: ikpt,jkpt
182 : integer :: ik1, ik2, ik3, nkptfull
183 : character(len=500) :: msg
184 4 : type(krank_t) :: krank
185 : !arrays
186 4 : integer,allocatable :: tmprank(:),ktable(:)
187 : character(len=fnlen) :: tmpname
188 4 : real(dp),allocatable :: nestfactor(:), nestordered(:), kptfull(:,:)
189 : ! *************************************************************************
190 :
191 : if (kptrlatt(1,2) /= 0 .or. kptrlatt(1,3) /= 0 .or. kptrlatt(2,1) /= 0 .or. &
192 4 : kptrlatt(2,3) /= 0 .or. kptrlatt(3,1) /= 0 .or. kptrlatt(3,2) /= 0 ) then
193 : write (msg,'(4a)')&
194 0 : 'kptrlatt should be diagonal in order to calculate the nesting factor,',ch10,&
195 0 : 'skipping the nesting factor calculation ',ch10
196 0 : ABI_WARNING(msg)
197 0 : return
198 : end if
199 :
200 4 : if (prtnest /= 1 .and. prtnest /= 2) then
201 0 : ABI_BUG('prtnest should be 1 or 2')
202 : end if
203 :
204 : !write(msg,'(a,9(i0,1x))')' mknesting : kptrlatt = ',kptrlatt
205 : !call wrtout(std_out,msg,'COLL')
206 :
207 4 : nkptfull = kptrlatt(1,1)*kptrlatt(2,2)*kptrlatt(3,3)
208 972 : ABI_CALLOC(nestordered, (nkptfull))
209 12 : ABI_MALLOC(kptfull,(3,nkptfull))
210 :
211 28 : ikpt = 0
212 28 : do ik3 = 0, kptrlatt(3,3)-1
213 172 : do ik2 = 0, kptrlatt(2,2)-1
214 1128 : do ik1 = 0, kptrlatt(1,1)-1
215 960 : ikpt = ikpt+1
216 3984 : kptfull(:,ikpt) = [dble(ik1)/dble(kptrlatt(1,1)), dble(ik2)/dble(kptrlatt(2,2)),dble(ik3)/dble(kptrlatt(3,3))]
217 : end do
218 : end do
219 : end do
220 :
221 : ! NOTE: input weights are not normalised, the normalisation factor in introduced in bfactor
222 : ! new version now puts kptfull in correct order before bfactor, so no need to re-order...
223 4 : if (present(symrec)) then
224 1 : ABI_CHECK(present(nsym), "error - provide nsym and symrec arguments together")
225 1 : call krank%init(nkpt, kpt, nsym=nsym, symrec=symrec)
226 : else
227 3 : call krank%init(nkpt, kpt)
228 : end if
229 :
230 4 : call bfactor(nkptfull, kptfull, nkptfull, kptfull, krank, nkpt, weight, nband, nestordered)
231 :
232 : !================================================================================================
233 : !use linear interpolation to plot the bfactor along the given q-path
234 : ! 1) order the kpoints of the grid putting them in increasing x, then y, then z (FORTRAN convention)
235 : ! 2) make table from input kpts to ordered kpts
236 : ! 3) perform interpolation
237 : !================================================================================================
238 :
239 4 : call outnesting(base_name,gmet,gprimd,kptrlatt,nestordered,nkptfull,nqpath,prtnest,qpath_vertices)
240 4 : ABI_FREE(nestordered)
241 :
242 : ! Now do the same, but for the nesting factor over the phonon qpoints only
243 12 : ABI_MALLOC(nestfactor, (nqptfull))
244 4 : call bfactor(nkptfull,kptfull,nqptfull,qptfull,krank,nkpt,weight,nband,nestfactor)
245 :
246 4 : call krank%free()
247 4 : ABI_FREE(kptfull)
248 :
249 4 : call krank%init(nqptfull, qptfull)
250 :
251 12 : ABI_MALLOC(ktable,(nqptfull))
252 29 : do ikpt=1,nqptfull
253 29 : ktable(ikpt) = ikpt
254 : end do
255 :
256 8 : ABI_MALLOC(tmprank, (nqptfull))
257 29 : do ikpt=1,nqptfull
258 29 : tmprank(ikpt) = krank%get_rank(qptfull(:,ikpt))
259 : end do
260 4 : call sort_int(nqptfull, tmprank, ktable)
261 4 : ABI_FREE(tmprank)
262 4 : call krank%free()
263 :
264 : !fill the datagrid for the nesting factor using the Fortran convention and the conventional unit cell
265 : !NOTE: the Fortran convention is a must if we want to plot the data
266 : !in the BXSF format, useful for the linear interpolation since we use interpol3d_0d.F90
267 8 : ABI_MALLOC(nestordered,(nqptfull))
268 29 : nestordered(:)=zero
269 29 : do jkpt=1,nqptfull
270 25 : ikpt = ktable(jkpt)
271 29 : nestordered(ikpt)=nestfactor(jkpt)
272 : end do
273 4 : ABI_FREE(nestfactor)
274 4 : ABI_FREE(ktable)
275 :
276 4 : tmpname = trim(base_name)//"kplusq"
277 4 : call outnesting(tmpname,gmet,gprimd,qptrlatt,nestordered,nqptfull,nqpath,prtnest,qpath_vertices)
278 :
279 4 : ABI_FREE(nestordered)
280 :
281 4 : end subroutine mknesting
282 : !!***
283 :
284 : !----------------------------------------------------------------------
285 :
286 : !!****f* m_nesting/outnesting
287 : !! NAME
288 : !! outnesting
289 : !!
290 : !! FUNCTION
291 : !! Write ou the nesting factors calculated in mknesting
292 : !! Data on file in the X-Y format (prtnest 1) or
293 : !! in the XCrysden format (XSF) (prtnest 2)
294 : !!
295 : !! INPUTS
296 : !! base_name = prefix of the output file
297 : !! gmet = metric in reciprocal space
298 : !! gprimd(3,3) dimensional reciprocal lattice vectors
299 : !! kptrlatt(3,3) basis vectors for k-grid
300 : !! nestordered = nesting function on full grid, points ordered in x, then y, then z
301 : !! nkpt = number of k points
302 : !! nqpath = number of points requested along the trajectory
303 : !! prtnest = flags governing the format of the output file
304 : !! qpath_vertices = vertices of the reciprocal space trajectory
305 : !!
306 : !! OUTPUT
307 : !! only write to file
308 : !!
309 : !! SOURCE
310 :
311 8 : subroutine outnesting(base_name,gmet,gprimd,kptrlatt,nestordered,nkpt,nqpath,prtnest,qpath_vertices)
312 :
313 : !Arguments ------------------------------------
314 : integer,intent(in) :: nqpath,prtnest,nkpt
315 : character(len=*),intent(in) :: base_name
316 : !arrays
317 : integer,intent(in) :: kptrlatt(3,3)
318 : real(dp),intent(in) :: gprimd(3,3), gmet(3,3)
319 : real(dp),intent(in) :: qpath_vertices(3,nqpath), nestordered(nkpt)
320 :
321 : !Local variables-------------------------------
322 : !scalars
323 : integer :: unit_nest,nkx,nky,nkz,indx,ii,ipoint,npt_tot,realrecip
324 : character(len=fnlen) :: fname
325 : character(len=500) :: msg
326 : real(dp) :: res(3), kval
327 : !arrays
328 16 : integer :: ndiv(nqpath-1)
329 8 : real(dp),allocatable :: finepath(:,:)
330 : real(dp) :: tmpkpt(3),origin(3),qpt(3)
331 : ! dummy variables for call to printxsf
332 : integer :: natom, ntypat, typat(1)
333 : real(dp) :: xcart (3,1), znucl(1)
334 : ! *************************************************************************
335 :
336 : ! Definition of the q path along which ph linwid will be interpolated
337 8 : call make_path(nqpath,qpath_vertices,gmet,'G',20,ndiv,npt_tot,finepath)
338 :
339 8 : nkx = kptrlatt(1,1)
340 8 : nky = kptrlatt(2,2)
341 8 : nkz = kptrlatt(3,3)
342 :
343 8 : if (nkpt /= nkx*nky*nkz) then
344 0 : write(msg,'(a,9(i0,1x),2x,i0)')' Wrong input value for kptrlatt ',kptrlatt, nkpt
345 0 : ABI_BUG(msg)
346 : end if
347 :
348 : ! Open output file and write header
349 8 : if (open_file(base_name,msg,newunit=unit_nest,status="unknown",form="formatted",action="write") /= 0) then
350 0 : ABI_ERROR(msg)
351 : end if
352 :
353 8 : write(unit_nest,'(a)')'#'
354 8 : write(unit_nest,'(a)')'# ABINIT package : Nesting factor file'
355 8 : write(unit_nest,'(a)')'#'
356 8 : write(unit_nest,'(a,i10,a)')'# Nesting factor calculated on ',npt_tot,' Q-points'
357 8 : write(unit_nest,'(a)')'# Description of the Q-path :'
358 8 : write(unit_nest,'(a,i10)')'# Number of line segments = ',nqpath-1
359 8 : write(unit_nest,'(a)')'# Vertices of the Q-path and corresponding index = '
360 8 : indx=1
361 66 : do ii=1,nqpath
362 58 : write(unit_nest,'(a,3(E16.6,1x),i8)')'# ',qpath_vertices(:,ii),indx
363 66 : if(ii<nqpath) indx=indx+ndiv(ii)
364 : end do
365 8 : write(unit_nest,'(a)')'#'
366 :
367 : !Get qpoint along the q-path from finepath and interpolate the nesting factor
368 8 : indx=1
369 :
370 8 : write (unit_nest,'(a)')'# index nesting, qfrac_coords'
371 1592 : do ipoint=1, npt_tot
372 6336 : qpt(:) = finepath(:,ipoint)
373 6336 : call wrap2_zero_one(qpt, tmpkpt, res)
374 1584 : kval = interpol3d_0d(tmpkpt, nkx, nky, nkz, nestordered)
375 1584 : write(unit_nest,'(i5,e16.5,1x,3(es11.4,1x))')indx,kval,tmpkpt
376 1592 : indx = indx + 1
377 : end do
378 :
379 8 : close (unit_nest)
380 8 : ABI_FREE(finepath)
381 :
382 8 : if (prtnest==2) then
383 : ! write also the nesting factor in the XSF format
384 0 : fname = trim(base_name) // '_NEST_XSF'
385 :
386 0 : if (open_file(fname,msg,newunit=unit_nest,status="unknown",form="formatted",action="write") /= 0) then
387 0 : ABI_ERROR(msg)
388 : end if
389 :
390 0 : origin(:) = zero
391 0 : realrecip = 1 !reciprocal space
392 0 : natom = 1
393 0 : ntypat = 1
394 0 : typat = [1]
395 0 : xcart = reshape ([zero, zero, zero], [3, 1])
396 0 : znucl = [one]
397 0 : call printxsf(nkx,nky,nkz,nestordered,gprimd,origin,natom, ntypat, typat, xcart, znucl, unit_nest,realrecip)
398 :
399 0 : close (unit_nest)
400 : end if
401 :
402 8 : end subroutine outnesting
403 : !!***
404 :
405 : end module m_nesting
406 : !!***
|