Branch data Line data Source code
1 : : !!****m* ABINIT/m_tetrahedron
2 : : !! NAME
3 : : !! m_tetrahedron
4 : : !!
5 : : !! FUNCTION
6 : : !! module for tetrahedron interpolation of DOS and similar quantities
7 : : !! depends on sort_tetra and on m_kpt_rank
8 : : !!
9 : : !! COPYRIGHT
10 : : !! Copyright (C) 2010-2026 ABINIT group (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 : : !! TODO
16 : : !! 1) Test carefully the case of degenerate tetrahedron
17 : : !! 2) Change API so that we can pass the energy mesh instead of omega_min and omega_max
18 : : !! 3) Add table ik_ibz --> tetra_list to avoid cycling inside big loop over ntetra
19 : : !! 4) Add options to get only delta and/or theta ?
20 : : !!
21 : : !! SOURCE
22 : :
23 : : #if defined HAVE_CONFIG_H
24 : : #include "config.h"
25 : : #endif
26 : :
27 : : #include "libtetra.h"
28 : :
29 : : module m_tetrahedron
30 : :
31 : : ! make sure stdout is defined, as libtetra.h needs it
32 : : use, intrinsic :: iso_fortran_env, only : stdin=>input_unit, &
33 : : stdout=>output_unit, &
34 : : stderr=>error_unit
35 : : USE_MEMORY_PROFILING
36 : : USE_MSG_HANDLING
37 : : use m_krank
38 : : USE_MPI
39 : : #ifdef HAVE_LIBTETRA_ABINIT
40 : : use m_io_tools, only : open_file
41 : : use m_xmpi
42 : : use defs_basis, only : dp, zero, one, tol14, pi
43 : : #elif
44 : : integer, parameter :: dp = kind(1.0d0)
45 : : real(dp), parameter :: tol14 = 1.d-14, zero = 0.d0, one = 1.d0
46 : : real(dp), parameter :: pi=3.141592653589793238462643383279502884197_dp
47 : : #endif
48 : :
49 : : implicit none
50 : :
51 : : #if defined HAVE_MPI1
52 : : include 'mpif.h'
53 : : #endif
54 : :
55 : : private
56 : : !!***
57 : :
58 : : !!****t* m_tetrahedron/t_tetrahedron
59 : : !! NAME
60 : : !! t_tetrahedron
61 : : !!
62 : : !! FUNCTION
63 : : !! tetrahedron geometry object
64 : : !!
65 : : !! SOURCE
66 : :
67 : : type, public :: t_tetrahedron
68 : :
69 : : integer :: ntetra = 0
70 : : ! Number of tetrahedra
71 : :
72 : : real(dp) :: vv
73 : : ! volume of the tetrahedra
74 : :
75 : : real(dp) :: klatt(3, 3)
76 : : ! reciprocal of lattice vectors for full kpoint grid
77 : :
78 : : integer,allocatable :: tetra_full(:,:,:)
79 : : !(4,2,ntetra)
80 : : ! For each tetra
81 : : ! (:,1,itetra) indices of the vertex in IBZ (symmetrical image)
82 : : ! (:,2,itetra) indices of the vertexes in the BZ
83 : :
84 : : integer,allocatable :: tetra_mult(:)
85 : : !(ntetra)
86 : : ! multiplicity of each irred tetrahedron
87 : :
88 : : integer,allocatable :: tetra_wrap(:,:,:)
89 : : !(3,4,ntetra)
90 : : ! flag to wrap tetrahedron summit into IBZ
91 : :
92 : : integer,allocatable :: ibz_tetra_count(:)
93 : : ! ibz_tetra_mapping(nkpt_ibz)
94 : : ! Number of tetrahedra associated to a point in the IBZ.
95 : :
96 : : integer,allocatable :: ibz_tetra_mapping(:,:)
97 : : ! ibz_tetra_mapping(nkpt_ibz, maxval(tetra%ibz_tetra_count)))
98 : : ! map ikbz to tetra index.
99 : :
100 : : end type t_tetrahedron
101 : :
102 : : public :: init_tetra ! Initialize the object
103 : : ! See also the high-level interface tetra_from_kptrlatt provided by m_kpts.
104 : : public :: get_tetra_weight ! Calculate integration weights and their derivatives. shape (nkpt, nene).
105 : : public :: tetra_blochl_weights ! Same as in get_tetra_weight but weights have shape (nene, nkpt).
106 : : public :: get_dbl_tetra_weight ! Calculate integration weights for double tetrahedron integration of delta functions.
107 : : ! (NB these correspond to the derivative terms in normal tetrahedron).
108 : : public :: destroy_tetra ! Free memory.
109 : : public :: tetra_write ! Write text file (XML format) with tetra info.
110 : : public :: tetralib_has_mpi ! Return True if the library has been compiled with MPI support.
111 : : public :: tetra_get_onewk ! Calculate integration weights and their derivatives for a single k-point in the IBZ.
112 : : public :: tetra_get_onewk_wvals ! Similar to tetra_get_onewk_wvalsa but receives arbitrary list of frequency points.
113 : : public :: tetra_get_onetetra_wvals ! Get weights for one tetrahedra with arbitrary list of frequency points
114 : : !!***
115 : :
116 : : contains
117 : : !!***
118 : :
119 : : !----------------------------------------------------------------------
120 : :
121 : : !!****f* m_tetrahedron/destroy_tetra
122 : : !! NAME
123 : : !! destroy_tetra
124 : : !!
125 : : !! FUNCTION
126 : : !! deallocate tetrahedra pointers if needed
127 : : !!
128 : : !! SOURCE
129 : :
130 : 11 : subroutine destroy_tetra (tetra)
131 : :
132 : : type(t_tetrahedron), intent(inout) :: tetra
133 : :
134 [ + + ]: 11 : if (allocated(tetra%tetra_full)) then
135 : 4 : TETRA_DEALLOCATE(tetra%tetra_full)
136 : : end if
137 [ + + ]: 11 : if (allocated(tetra%tetra_mult)) then
138 : 4 : TETRA_DEALLOCATE(tetra%tetra_mult)
139 : : end if
140 [ + + ]: 11 : if (allocated(tetra%tetra_wrap)) then
141 : 4 : TETRA_DEALLOCATE(tetra%tetra_wrap)
142 : : end if
143 [ + + ]: 11 : if (allocated(tetra%ibz_tetra_count)) then
144 : 4 : TETRA_DEALLOCATE(tetra%ibz_tetra_count)
145 : : end if
146 [ + + ]: 11 : if (allocated(tetra%ibz_tetra_mapping)) then
147 : 4 : TETRA_DEALLOCATE(tetra%ibz_tetra_mapping)
148 : : end if
149 : :
150 : 11 : end subroutine destroy_tetra
151 : : !!***
152 : :
153 : : !----------------------------------------------------------------------
154 : :
155 : : !!****f* m_tetrahedron/init_tetra
156 : : !! NAME
157 : : !! init_tetra
158 : : !!
159 : : !! FUNCTION
160 : : !! get tetrahedra characterized by apexes
161 : : !!
162 : : !! INPUTS
163 : : !! indkpt(nkpt_fullbz)=indexes of irred kpoints equivalent to kpt_fullbz
164 : : !! gprimd(3,3) = reciprocal space vectors
165 : : !! klatt(3,3)=reciprocal of lattice vectors for full kpoint grid
166 : : !! kpt_fullbz(3,nkpt_fullbz)=kpoints in full brillouin zone
167 : : !! nkpt_fullbz=number of kpoints in full brillouin zone
168 : : !! comm= MPI communicator
169 : : !!
170 : : !! OUTPUT
171 : : !! tetra%tetra_full(4,2,ntetra)=for each tetrahedron,
172 : : !! the different instances of the tetrahedron (fullbz kpoints)
173 : : !! tetra%tetra_mult(ntetra) = store multiplicity of each irred tetrahedron
174 : : !! tetra%tetra_wrap(3,4,ntetra) = store flag to wrap tetrahedron summit into IBZ
175 : : !! tetra%ntetra = final number of irred tetra (dimensions of tetra_* remain larger)
176 : : !! tetra%vv = tetrahedron volume divided by full BZ volume
177 : : !!
178 : : !! SOURCE
179 : :
180 [ - + - + : 4 : subroutine init_tetra(indkpt, gprimd, klatt, kpt_fullbz, nkpt_fullbz, tetra, ierr, errorstring, comm)
- + - + ]
181 : :
182 : : !Arguments ------------------------------------
183 : : !scalars
184 : : integer,intent(in) :: nkpt_fullbz, comm
185 : : integer, intent(out) :: ierr
186 : : character(len=80), intent(out) :: errorstring
187 : : type(t_tetrahedron),intent(out) :: tetra
188 : : !arrays
189 : : integer,intent(in) :: indkpt(nkpt_fullbz)
190 : : real(dp) ,intent(in) :: gprimd(3,3),klatt(3,3),kpt_fullbz(3,nkpt_fullbz)
191 : :
192 : : !Local variables-------------------------------
193 : : !scalars
194 : : integer :: ialltetra,ikpt2,ikpt_full,isummit,itetra,jalltetra,jsummit
195 : : integer :: ii,jj,ikibz,nkpt_ibz, my_rank, nprocs
196 : : integer :: symrankkpt,mtetra,itmp,ntetra_irred
197 : : real(dp) :: shift1,shift2,shift3, rcvol,hashfactor
198 : : !real :: cpu_start, cpu_stop
199 : 4 : type(krank_t) :: krank
200 : : !arrays
201 : : integer :: ind_ibz(4), tetra_shifts(3,4,6) ! 3 dimensions, 4 summits, and 6 tetrahedra / kpoint box
202 : : real(dp) :: k1(3),k2(3),k3(3)
203 : 4 : integer,allocatable :: tetra_full_(:,:,:)
204 : 4 : integer,allocatable :: tetra_mult_(:)
205 : 4 : integer,allocatable :: tetra_wrap_(:,:,:)
206 : 4 : integer, allocatable :: reforder(:)
207 : 4 : integer, allocatable :: irred_itetra(:)
208 [ - + ]: 4 : real(dp), allocatable :: tetra_hash(:)
209 : :
210 : : ! *********************************************************************
211 : :
212 : : !call cpu_time(cpu_start)
213 : :
214 : 4 : my_rank = 0; nprocs = 1
215 : : #ifdef HAVE_LIBTETRA_ABINIT
216 : 4 : my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
217 : : #endif
218 : :
219 : 4 : ierr = 0
220 : 4 : errorstring = ""
221 : : !jmb
222 : 4 : shift1 = zero
223 : 4 : shift2 = zero
224 : 4 : shift3 = zero
225 : :
226 [ + + + + ]: 52 : tetra%klatt = klatt
227 : :
228 : 4 : mtetra = 6 * nkpt_fullbz
229 [ - + + - : 12 : TETRA_ALLOCATE(tetra_full_, (4,2,mtetra))
+ - + - -
+ - + ]
230 [ - + + - : 12 : TETRA_ALLOCATE(tetra_mult_, (mtetra))
+ - + - -
+ - + ]
231 [ - + + - : 12 : TETRA_ALLOCATE(tetra_wrap_, (3,4,mtetra))
+ - + - -
+ - + ]
232 : :
233 [ + + ]: 5188 : tetra_mult_ = 1
234 [ + + + + : 57028 : tetra_full_ = 0
+ + ]
235 [ + + + + : 88132 : tetra_wrap_ = 0
+ + ]
236 : :
237 : : ! tetra_shifts(:,1,1) = (/0,0,0/)
238 : : ! tetra_shifts(:,2,1) = (/0,1,0/)
239 : : ! tetra_shifts(:,3,1) = (/0,1,1/)
240 : : ! tetra_shifts(:,4,1) = (/1,1,0/)
241 : : ! tetra_shifts(:,1,2) = (/0,0,0/)
242 : : ! tetra_shifts(:,2,2) = (/0,1,1/)
243 : : ! tetra_shifts(:,3,2) = (/1,1,0/)
244 : : ! tetra_shifts(:,4,2) = (/1,1,1/)
245 : : ! tetra_shifts(:,1,3) = (/0,0,0/)
246 : : ! tetra_shifts(:,2,3) = (/1,0,0/)
247 : : ! tetra_shifts(:,3,3) = (/1,1,0/)
248 : : ! tetra_shifts(:,4,3) = (/1,1,1/)
249 : : ! tetra_shifts(:,1,4) = (/0,0,0/)
250 : : ! tetra_shifts(:,2,4) = (/0,0,1/)
251 : : ! tetra_shifts(:,3,4) = (/1,0,0/)
252 : : ! tetra_shifts(:,4,4) = (/1,1,1/)
253 : : ! tetra_shifts(:,1,5) = (/0,0,1/)
254 : : ! tetra_shifts(:,2,5) = (/1,0,0/)
255 : : ! tetra_shifts(:,3,5) = (/1,0,1/)
256 : : ! tetra_shifts(:,4,5) = (/1,1,1/)
257 : : ! tetra_shifts(:,1,6) = (/0,0,0/)
258 : : ! tetra_shifts(:,2,6) = (/0,0,1/)
259 : : ! tetra_shifts(:,3,6) = (/0,1,1/)
260 : : ! tetra_shifts(:,4,6) = (/1,1,1/)
261 : :
262 : : ! bxu, the following division scheme is according to Bloechl's paper
263 [ + + ]: 16 : tetra_shifts(:,1,1) = (/0,0,0/)
264 [ + + ]: 16 : tetra_shifts(:,2,1) = (/1,0,0/)
265 [ + + ]: 16 : tetra_shifts(:,3,1) = (/0,1,0/)
266 [ + + ]: 16 : tetra_shifts(:,4,1) = (/1,0,1/)
267 [ + + ]: 16 : tetra_shifts(:,1,2) = (/1,0,0/)
268 [ + + ]: 16 : tetra_shifts(:,2,2) = (/1,1,0/)
269 [ + + ]: 16 : tetra_shifts(:,3,2) = (/0,1,0/)
270 [ + + ]: 16 : tetra_shifts(:,4,2) = (/1,0,1/)
271 [ + + ]: 16 : tetra_shifts(:,1,3) = (/0,1,0/)
272 [ + + ]: 16 : tetra_shifts(:,2,3) = (/1,1,0/)
273 [ + + ]: 16 : tetra_shifts(:,3,3) = (/1,0,1/)
274 [ + + ]: 16 : tetra_shifts(:,4,3) = (/1,1,1/)
275 [ + + ]: 16 : tetra_shifts(:,1,4) = (/0,0,0/)
276 [ + + ]: 16 : tetra_shifts(:,2,4) = (/0,1,0/)
277 [ + + ]: 16 : tetra_shifts(:,3,4) = (/0,0,1/)
278 [ + + ]: 16 : tetra_shifts(:,4,4) = (/1,0,1/)
279 [ + + ]: 16 : tetra_shifts(:,1,5) = (/0,0,1/)
280 [ + + ]: 16 : tetra_shifts(:,2,5) = (/1,0,1/)
281 [ + + ]: 16 : tetra_shifts(:,3,5) = (/0,1,0/)
282 [ + + ]: 16 : tetra_shifts(:,4,5) = (/0,1,1/)
283 [ + + ]: 16 : tetra_shifts(:,1,6) = (/0,1,0/)
284 [ + + ]: 16 : tetra_shifts(:,2,6) = (/1,0,1/)
285 [ + + ]: 16 : tetra_shifts(:,3,6) = (/0,1,1/)
286 [ + + ]: 16 : tetra_shifts(:,4,6) = (/1,1,1/)
287 : :
288 : : ! Make full k-point rank arrays
289 : : ! TODO: Lot of memory allocated here if dense mesh e.g ~ 300 ** 3
290 : 4 : call krank%init(nkpt_fullbz, kpt_fullbz)
291 : :
292 : 4 : ialltetra = 1
293 [ + + ]: 868 : do ikpt_full=1,nkpt_fullbz
294 [ + + ]: 6052 : do itetra=1,6
295 : : !ialltetra = itetra + (ikpt_full -1) * 6
296 : : !if (mod(ialltetra, nprocs) /= my_rank) cycle ! MPI parallelism.
297 [ + + ]: 25920 : do isummit=1,4
298 : : k1(:) = kpt_fullbz(:,ikpt_full) &
299 : : + tetra_shifts(1,isummit,itetra)*klatt(:,1) &
300 : : + tetra_shifts(2,isummit,itetra)*klatt(:,2) &
301 [ + + ]: 82944 : + tetra_shifts(3,isummit,itetra)*klatt(:,3)
302 : :
303 : : ! Find full kpoint which is summit isummit of tetrahedron itetra around full kpt ikpt_full !
304 : 20736 : symrankkpt = krank%get_rank(k1)
305 : 20736 : ikpt2 = krank%invrank(symrankkpt)
306 [ - + ]: 20736 : if (ikpt2 < 1) then
307 : 0 : errorstring = 'Error in ranking k-points - exiting with un-initialized tetrahedra.'
308 : 0 : ierr = 2
309 : 0 : call krank%free()
310 [ # # # # ]: 0 : TETRA_ALLOCATE(tetra%tetra_full, (4,2,1))
311 [ # # # # ]: 0 : TETRA_ALLOCATE(tetra%tetra_mult, (1))
312 [ # # # # ]: 0 : TETRA_ALLOCATE(tetra%tetra_wrap, (3,4,1))
313 [ # # ]: 0 : TETRA_DEALLOCATE(tetra_full_)
314 [ # # ]: 0 : TETRA_DEALLOCATE(tetra_mult_)
315 [ # # ]: 0 : TETRA_DEALLOCATE(tetra_wrap_)
316 : 0 : return
317 : : end if
318 : :
319 : : ! Store irreducible kpoint equivalent to kpt_fullbz(:,ikpt2)
320 : 20736 : tetra_full_(isummit,1,ialltetra) = indkpt(ikpt2)
321 : 20736 : tetra_full_(isummit,2,ialltetra) = ikpt2
322 : 20736 : shift1 = k1(1)-kpt_fullbz(1,ikpt2)
323 : 20736 : shift2 = k1(2)-kpt_fullbz(2,ikpt2)
324 : 20736 : shift3 = k1(3)-kpt_fullbz(3,ikpt2)
325 [ + + ]: 20736 : if (shift1>0.5d0) then
326 : 1728 : tetra_wrap_(1,isummit,ialltetra) = 1
327 [ - + ]: 19008 : else if (shift1<-0.5d0) then
328 : 0 : tetra_wrap_(1,isummit,ialltetra) = -1
329 : : end if
330 [ + + ]: 20736 : if (shift2>0.5d0) then
331 : 1728 : tetra_wrap_(2,isummit,ialltetra) = 1
332 [ - + ]: 19008 : else if (shift2<-0.5d0) then
333 : 0 : tetra_wrap_(2,isummit,ialltetra) = -1
334 : : end if
335 [ + + ]: 20736 : if (shift3>0.5d0) then
336 : 1728 : tetra_wrap_(3,isummit,ialltetra) = 1
337 [ + - ]: 19008 : else if (shift3<-0.5d0) then
338 : 0 : tetra_wrap_(3,isummit,ialltetra) = -1
339 : : end if
340 : :
341 : : ! sort itetra summits
342 : : ! TODO: replace with sort_int
343 [ + + ]: 57024 : do jsummit=isummit,2,-1
344 [ + + ]: 51840 : if ( tetra_full_(jsummit,1,ialltetra) < tetra_full_(jsummit-1,1,ialltetra) ) then
345 : 6912 : itmp = tetra_full_(jsummit,1,ialltetra)
346 : 6912 : tetra_full_(jsummit,1,ialltetra) = tetra_full_(jsummit-1,1,ialltetra)
347 : 6912 : tetra_full_(jsummit-1,1,ialltetra) = itmp
348 : 6912 : itmp = tetra_full_(jsummit,2,ialltetra)
349 : 6912 : tetra_full_(jsummit,2,ialltetra) = tetra_full_(jsummit-1,2,ialltetra)
350 : 6912 : tetra_full_(jsummit-1,2,ialltetra) = itmp
351 : : ! keep fullbz_kpt tetrahedra points in same order
352 : 6912 : itmp = tetra_wrap_(1,jsummit,ialltetra)
353 : 6912 : tetra_wrap_(1,jsummit,ialltetra) = tetra_wrap_(1,jsummit-1,ialltetra)
354 : 6912 : tetra_wrap_(1,jsummit-1,ialltetra) = itmp
355 : 6912 : itmp = tetra_wrap_(2,jsummit,ialltetra)
356 : 6912 : tetra_wrap_(2,jsummit,ialltetra) = tetra_wrap_(2,jsummit-1,ialltetra)
357 : 6912 : tetra_wrap_(2,jsummit-1,ialltetra) = itmp
358 : 6912 : itmp = tetra_wrap_(1,jsummit,ialltetra)
359 : 6912 : tetra_wrap_(3,jsummit,ialltetra) = tetra_wrap_(3,jsummit-1,ialltetra)
360 : 6912 : tetra_wrap_(3,jsummit-1,ialltetra) = itmp
361 : : end if
362 : : end do ! jsummit
363 : :
364 : : end do ! isummit
365 : :
366 [ - + ]: 5184 : if (ialltetra > mtetra) then
367 : : write (errorstring, '(3a,i0,a,i0)' ) &
368 : 0 : 'init_tetra: BUG - ',&
369 : 0 : ' ialltetra > mtetra ',&
370 : 0 : ' ialltetra= ',ialltetra,', mtetra= ',mtetra
371 : 0 : ierr = 1
372 : 0 : return
373 : : end if
374 : 6048 : ialltetra = ialltetra+1
375 : : end do ! itetra
376 : : end do ! ikpt_full
377 : :
378 : : !call cpu_time(cpu_stop)
379 : : !write(*,*)"tetra_init ikpt_loop:", cpu_stop - cpu_start
380 : : !cpu_start = cpu_stop
381 : :
382 : 4 : call krank%free()
383 : :
384 : : rcvol = abs (gprimd(1,1)*(gprimd(2,2)*gprimd(3,3)-gprimd(3,2)*gprimd(2,3)) &
385 : : & -gprimd(2,1)*(gprimd(1,2)*gprimd(3,3)-gprimd(3,2)*gprimd(1,3)) &
386 : 4 : & +gprimd(3,1)*(gprimd(1,2)*gprimd(2,3)-gprimd(2,2)*gprimd(1,3)))
387 : :
388 : : ! Volume of all tetrahedra should be the same as that of tetra 1
389 : : ! this is the volume of 1 tetrahedron, should be coherent with notation in Lehmann & Taut
390 [ + + ]: 16 : k1(:) = gprimd(:,1)*klatt(1,1) + gprimd(:,2)*klatt(2,1) + gprimd(:,3)*klatt(3,1)
391 [ + + ]: 16 : k2(:) = gprimd(:,1)*klatt(1,2) + gprimd(:,2)*klatt(2,2) + gprimd(:,3)*klatt(3,2)
392 [ + + ]: 16 : k3(:) = gprimd(:,1)*klatt(1,3) + gprimd(:,2)*klatt(2,3) + gprimd(:,3)*klatt(3,3)
393 : : tetra%vv = abs (k1(1)*(k2(2)*k3(3)-k2(3)*k3(2)) &
394 : : & -k1(2)*(k2(1)*k3(3)-k2(3)*k3(1)) &
395 : 4 : & +k1(3)*(k2(1)*k3(2)-k2(2)*k3(1))) / 6.d0 / rcvol
396 : :
397 : : ! eliminate equivalent tetrahedra by symmetry and account for them in multiplicity tetra_mult
398 : 4 : tetra%ntetra = mtetra
399 : :
400 : : ! FIXME: could we replace this with a ranking algorithm to avoid the O(tetra%ntetra^2) step? For example:
401 : : ! get tetrahedron rank - problem too many combinations in principle = nkpt_irred^4 - only a few used in practice
402 : : ! sort ranks and keep indices
403 : :
404 : : ! make hash table = tetra_full_(1)*nkptirred**3+tetra_full_(2)*nkptirred**2+tetra_full_(3)*nkptirred**1+tetra_full_(4)
405 : :
406 : 4 : hashfactor = 100.d0 ! *acos(-1.d0) ! 100 pi should be far from an integer...
407 [ - + + - : 12 : TETRA_ALLOCATE(tetra_hash, (tetra%ntetra))
+ - + - -
+ - + ]
408 [ - + + - : 12 : TETRA_ALLOCATE(reforder, (tetra%ntetra))
+ - + - -
+ - + ]
409 : :
410 : : !MG: In principle the order of the indices should not matter.
411 [ + + ]: 5188 : do ialltetra=1, tetra%ntetra
412 : : tetra_hash(ialltetra) = tetra_full_(1,1,ialltetra)*hashfactor**3+&
413 : : & tetra_full_(2,1,ialltetra)*hashfactor**2+&
414 : : & tetra_full_(3,1,ialltetra)*hashfactor**1+&
415 : 5184 : & tetra_full_(4,1,ialltetra)
416 : 5188 : reforder(ialltetra) = ialltetra
417 : : end do
418 : :
419 : 4 : call sort_tetra(tetra%ntetra, tetra_hash, reforder, tol14)
420 : : ! Most of the wall-time is spent in the preamble of this routine (up to this point).
421 : : ! sort_tetra is not easy to parallelize...
422 : :
423 : : ! determine number of tetra after reduction
424 [ - + + - : 12 : TETRA_ALLOCATE(irred_itetra, (tetra%ntetra))
+ - + - -
+ - + ]
425 : 4 : jalltetra = 1
426 : 4 : irred_itetra(1) = 1
427 [ + + ]: 5184 : do ialltetra=2, tetra%ntetra
428 [ + - ]: 5180 : if (abs(tetra_hash(ialltetra)-tetra_hash(ialltetra-1)) > tol14) then
429 : : ! found a new series
430 : 5180 : jalltetra = jalltetra + 1
431 : : end if
432 : 5184 : irred_itetra(ialltetra) = jalltetra
433 : : end do
434 : :
435 : : ! reset number of tetra
436 : 4 : ntetra_irred = jalltetra
437 : :
438 : : ! allocate definitive tetra arrays and transfer to new arrays
439 [ - + + - : 12 : TETRA_ALLOCATE(tetra%tetra_full, (4,2,ntetra_irred))
+ - - + -
+ - + ]
440 [ - + + - : 12 : TETRA_ALLOCATE(tetra%tetra_mult, (ntetra_irred))
+ - - + -
+ - + ]
441 [ - + + - : 12 : TETRA_ALLOCATE(tetra%tetra_wrap, (3,4,ntetra_irred))
+ - - + -
+ - + ]
442 : :
443 : : ! eliminate equal rank tetrahedra and accumulate multiplicity into first one
444 [ + + + + : 57028 : tetra%tetra_full = 0
+ + ]
445 [ + + ]: 5188 : tetra%tetra_mult = 0
446 [ + + + + : 88132 : tetra%tetra_wrap = 0
+ + ]
447 : 4 : jalltetra = 1
448 [ + + + + ]: 44 : tetra%tetra_full(:,:,1) = tetra_full_(:,:,reforder(1))
449 : 4 : tetra%tetra_mult(1) = 1
450 [ + + + + ]: 68 : tetra%tetra_wrap(:,:,1) = tetra_wrap_(:,:,reforder(1))
451 [ + + ]: 5184 : do ialltetra=2, tetra%ntetra
452 : : ! TODO: check if tolerance is adapted
453 [ + - ]: 5184 : if (abs(tetra_hash(ialltetra)-tetra_hash(ialltetra-1)) > tol14) then
454 : : ! found a new series
455 : 5180 : jalltetra = jalltetra + 1
456 [ + + + + ]: 56980 : tetra%tetra_full(:,:,jalltetra) = tetra_full_(:,:,reforder(ialltetra))
457 [ + + + + ]: 88060 : tetra%tetra_wrap(:,:,jalltetra) = tetra_wrap_(:,:,reforder(ialltetra))
458 : 5180 : tetra%tetra_mult(jalltetra) = 1
459 : : else
460 : : ! TODO: add real check that the tetra are equivalent...
461 : : ! otherwise increment jalltetra here as well, generate new series?
462 : 0 : tetra%tetra_mult(jalltetra) = tetra%tetra_mult(jalltetra) + tetra_mult_(reforder(ialltetra))
463 : : !tetra_mult_(reforder(ialltetra)) = 0
464 : : end if
465 : : end do
466 : :
467 : : ! reset of ntetra for final version after checks and debu
468 : 4 : tetra%ntetra = ntetra_irred
469 : :
470 [ - + ]: 4 : TETRA_DEALLOCATE(tetra_hash)
471 : 4 : TETRA_DEALLOCATE(reforder)
472 : 4 : TETRA_DEALLOCATE(irred_itetra)
473 [ - + ]: 4 : TETRA_DEALLOCATE(tetra_full_)
474 [ - + ]: 4 : TETRA_DEALLOCATE(tetra_mult_)
475 [ - + ]: 4 : TETRA_DEALLOCATE(tetra_wrap_)
476 : :
477 : : ! Create mapping between the irreducible k-points
478 : : ! and all the tetrahedron contributing with some weight
479 [ + + ]: 868 : nkpt_ibz = maxval(indkpt)
480 : :
481 : : ! 1. First we count what is the maximum number of distinct tetrahedra that each k-point contains
482 [ - + + - : 12 : TETRA_ALLOCATE(tetra%ibz_tetra_count,(nkpt_ibz))
+ - + - -
+ - + -
+ ]
483 [ + + ]: 868 : tetra%ibz_tetra_count(:) = 0
484 : :
485 : : ! Count max tetra contributing
486 [ + + ]: 5188 : do ii=1,tetra%ntetra
487 : : ! Here we need the original ordering to reference the correct irred kpoints
488 [ + + ]: 25920 : ind_ibz(:) = tetra%tetra_full(:,1,ii)
489 : : ! count max tetra contributing
490 [ + + ]: 25924 : do jj=1,4
491 : 20736 : ikibz = ind_ibz(jj)
492 [ - + ]: 20736 : if (ikibz > nkpt_ibz) cycle
493 : 25920 : tetra%ibz_tetra_count(ikibz) = tetra%ibz_tetra_count(ikibz) + 1
494 : : end do
495 : : end do
496 : :
497 : : ! 2. Then we build mapping of ikbz to tetra
498 [ - + + - : 880 : TETRA_ALLOCATE(tetra%ibz_tetra_mapping,(nkpt_ibz,maxval(tetra%ibz_tetra_count)))
+ + - + +
- + - + -
- + - + -
+ ]
499 [ + + ]: 868 : tetra%ibz_tetra_count(:) = 0
500 [ + + ]: 5188 : do ii=1,tetra%ntetra
501 : : ! Here we need the original ordering to reference the correct irred kpoints
502 [ + + ]: 25920 : ind_ibz(:) = tetra%tetra_full(:,1,ii)
503 : : ! Use the counter to move pointer and then fill index
504 [ + + ]: 25924 : do jj=1,4
505 : 20736 : ikibz = ind_ibz(jj)
506 [ - + ]: 20736 : if (ikibz > nkpt_ibz) cycle
507 : : ! avoid putting the same index twice
508 [ + + ]: 20736 : if (tetra%ibz_tetra_count(ikibz) > 0) then
509 [ - + ]: 19872 : if (tetra%ibz_tetra_mapping(ikibz,tetra%ibz_tetra_count(ikibz)) == ii) cycle
510 : : end if
511 : 20736 : tetra%ibz_tetra_count(ikibz) = tetra%ibz_tetra_count(ikibz) + 1
512 : 25920 : tetra%ibz_tetra_mapping(ikibz,tetra%ibz_tetra_count(ikibz)) = ii
513 : : end do
514 : : end do
515 : :
516 : : !call cpu_time(cpu_stop)
517 : : !write(*,*)"tetra_init 2nd part:", cpu_stop - cpu_start
518 : : !cpu_start = cpu_stop
519 : :
520 [ - + - + : 4 : end subroutine init_tetra
- + - + -
+ - + ]
521 : : !!***
522 : :
523 : : !----------------------------------------------------------------------
524 : :
525 : : !!****f* m_tetrahedron/tetra_write
526 : : !! NAME
527 : : !! tetra_write
528 : : !!
529 : : !! FUNCTION
530 : : !! Write text file with tetra info.
531 : : !!
532 : : !! INPUTS
533 : : !! tetra<t_tetrahedron>=tetrahedron geometry object
534 : : !! nkibz=Number of k-points in the IBZ used to generate tetra
535 : : !! kibz(3,nkibz)=Reduced coordinates of the IBZ
536 : : !! path=Name of output file
537 : : !!
538 : : !! OUTPUT
539 : : !! Output is written to file.
540 : : !!
541 : : !! SOURCE
542 : :
543 : 0 : subroutine tetra_write(tetra, nkibz, kibz, path)
544 : :
545 : : !Arguments ------------------------------------
546 : : !scalars
547 : : integer,intent(in) :: nkibz
548 : : character(len=*),intent(in) :: path
549 : : type(t_tetrahedron),intent(in) :: tetra
550 : : !arrays
551 : : real(dp),intent(in) :: kibz(3,nkibz)
552 : :
553 : : !Local variables-------------------------------
554 : : integer,parameter :: version=1
555 : : integer :: ik,it,unt
556 : : #ifdef HAVE_LIBTETRA_ABINIT
557 : : character(len=500) :: msg
558 : : #endif
559 : :
560 : : ! *********************************************************************
561 : :
562 : : #ifdef HAVE_LIBTETRA_ABINIT
563 [ # # ]: 0 : if (open_file(file=trim(path),iomsg=msg,newunit=unt,form="formatted",status="unknown",action="write")/=0) then
564 : 0 : TETRA_ERROR(msg)
565 : : end if
566 : : #else
567 : : open(file=trim(path),newunit=unt,form="formatted",status="unknown",action="write")
568 : : #endif
569 : :
570 : 0 : write(unt,*)version, " # version number"
571 : :
572 : : ! Write IBZ
573 : 0 : write(unt,*)nkibz, " # number of k-points in the IBZ"
574 : 0 : write(unt,"(a)")"<irreducible_zone>"
575 [ # # ]: 0 : do ik=1,nkibz
576 : 0 : write(unt,"(3es22.12)") kibz(:,ik)
577 : : end do
578 : 0 : write(unt,"(a)")"</irreducible_zone>"
579 : :
580 : : ! Write tetra info
581 : 0 : write(unt,"(i0,a)")tetra%ntetra, " # number of tetrahedra"
582 : 0 : write(unt,"(es22.12,a)")tetra%vv, " # tetrahedron volume"
583 : :
584 : 0 : write(unt,"(a)")"<tetra_full>"
585 [ # # ]: 0 : do it=1,tetra%ntetra
586 : 0 : write(unt,"(8(i0,1x))")tetra%tetra_full(:,:,it)
587 : : end do
588 : 0 : write(unt,"(a)")"</tetra_full>"
589 : :
590 : 0 : write(unt,"(a)")"<tetra_mult>"
591 [ # # ]: 0 : do it=1,tetra%ntetra
592 : 0 : write(unt,"(i0)")tetra%tetra_mult(it)
593 : : end do
594 : 0 : write(unt,"(a)")"</tetra_mult>"
595 : :
596 : 0 : write(unt,"(a)")"<tetra_wrap>"
597 [ # # ]: 0 : do it=1,tetra%ntetra
598 : 0 : write(unt,"(12(i0,1x))")tetra%tetra_wrap(:,:,it)
599 : : end do
600 : 0 : write(unt,"(a)")"</tetra_wrap>"
601 : :
602 : 0 : close(unt)
603 : :
604 : 0 : end subroutine tetra_write
605 : : !!***
606 : :
607 : : !----------------------------------------------------------------------
608 : :
609 : : !!****f* m_tetrahedron/get_tetra_weight
610 : : !! NAME
611 : : !! get_tetra_weight
612 : : !!
613 : : !! FUNCTION
614 : : !! calculate integration weights and their derivatives from Blochl et al PRB 49 16223 [[cite:Bloechl1994a]]
615 : : !!
616 : : !! INPUTS
617 : : !! eigen_in(nkpt)=eigenenergies for each k point
618 : : !! enemin=minimal energy for DOS
619 : : !! enemax=maximal energy for DOS
620 : : !! max_occ=maximal occupation number (2 for nsppol=1, 1 for nsppol=2)
621 : : !! nene=number of energies for DOS
622 : : !! nkpt=number of irreducible kpoints
623 : : !! tetra<t_tetrahedron>
624 : : !! %ntetra=number of tetrahedra
625 : : !! %tetra_full(4,2,ntetra)=for each irred tetrahedron, the list of k point vertices
626 : : !! 1 -> irred kpoint 2 -> fullkpt
627 : : !! %tetra_mult(ntetra)=for each irred tetrahedron, its multiplicity
628 : : !! %vv = ratio of volume of one tetrahedron in reciprocal space to full BZ volume
629 : : !! bcorr=1 to include Blochl correction else 0.
630 : : !! comm=MPI communicator
631 : : !!
632 : : !! OUTPUT
633 : : !! tweight(nkpt,nene) = integration weights for each irred kpoint from all adjacent tetrahedra
634 : : !! dtweightde(nkpt,nene) = derivative of tweight wrt energy
635 : : !!
636 : : !! SOURCE
637 : :
638 : : ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
639 : : ! THIS FUNCTION IS DEPRECATED, USE tetra_blochl_weights
640 : : ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
641 : 18 : subroutine get_tetra_weight(eigen_in,enemin,enemax,max_occ,nene,nkpt,tetra,&
642 : 18 : bcorr,tweight,dtweightde,comm)
643 : :
644 : : !Arguments ------------------------------------
645 : : !scalars
646 : : integer,intent(in) :: nene,nkpt,bcorr,comm
647 : : type(t_tetrahedron), intent(in) :: tetra
648 : : real(dp) ,intent(in) :: enemax,enemin,max_occ
649 : : !arrays
650 : : real(dp) ,intent(in) :: eigen_in(nkpt)
651 : : real(dp) ,intent(out) :: dtweightde(nkpt,nene),tweight(nkpt,nene)
652 : :
653 : : !Local variables-------------------------------
654 : 18 : real(dp), allocatable :: dtweightde_ek(:, :), tweight_ek(:, :)
655 : :
656 : : ! *********************************************************************
657 : :
658 [ - + + - : 72 : TETRA_ALLOCATE(dtweightde_ek, (nene, nkpt))
- + + - +
- + - - +
- + ]
659 [ - + + - : 54 : TETRA_ALLOCATE(tweight_ek, (nene, nkpt))
- + + - -
+ - + ]
660 : :
661 : 18 : call tetra_blochl_weights(tetra,eigen_in,enemin,enemax,max_occ,nene,nkpt,bcorr,tweight_ek,dtweightde_ek,comm)
662 : :
663 : : ! transpose: otherwise the data access is crap and the code slows by an order of magnitude
664 [ + + + + ]: 782520 : tweight = transpose(tweight_ek)
665 [ + + + + ]: 782520 : dtweightde = transpose(dtweightde_ek)
666 : :
667 [ - + ]: 18 : TETRA_DEALLOCATE(dtweightde_ek)
668 [ - + ]: 18 : TETRA_DEALLOCATE(tweight_ek)
669 : :
670 : 18 : end subroutine get_tetra_weight
671 : : !!***
672 : :
673 : : !----------------------------------------------------------------------
674 : :
675 : : !!****f* m_tetrahedron/tetra_blochl_weights
676 : : !! NAME
677 : : !! tetra_blochl_weights
678 : : !!
679 : : !! FUNCTION
680 : : !! calculate integration weights and their derivatives from Blochl et al PRB 49 16223 [[cite:Bloechl1994a]]
681 : : !! Same API as get_tetra_weight but output weights here have shape (nene, nkpt)
682 : : !!
683 : : !! SOURCE
684 : :
685 : 18 : subroutine tetra_blochl_weights(tetra,eigen_in,enemin,enemax,max_occ,nene,nkpt,&
686 : 18 : bcorr,tweight_t,dtweightde_t,comm)
687 : :
688 : : !Arguments ------------------------------------
689 : : !scalars
690 : : integer,intent(in) :: nene,nkpt,bcorr,comm
691 : : type(t_tetrahedron), intent(in) :: tetra
692 : : real(dp) ,intent(in) :: enemax,enemin,max_occ
693 : : !arrays
694 : : real(dp) ,intent(in) :: eigen_in(nkpt)
695 : : real(dp) ,intent(out) :: dtweightde_t(nene,nkpt),tweight_t(nene,nkpt)
696 : :
697 : : !Local variables-------------------------------
698 : : !scalars
699 : : integer :: itetra,nprocs,my_start,my_stop,ierr,ii
700 : : !arrays
701 : : integer :: ind_ibz(4)
702 : : real(dp) :: eigen_1tetra(4)
703 : 18 : real(dp), allocatable :: tweight_tmp(:,:),dtweightde_tmp(:,:),buffer(:,:)
704 : :
705 : : ! *********************************************************************
706 : :
707 [ - + + - : 54 : TETRA_ALLOCATE(tweight_tmp, (nene, 4))
+ - + - -
+ - + ]
708 [ - + + - : 36 : TETRA_ALLOCATE(dtweightde_tmp, (nene, 4))
- + + - ]
709 [ + + + + : 1565604 : tweight_t = zero; dtweightde_t = zero
+ + + + ]
710 : :
711 : 18 : call split_work(tetra%ntetra, comm, nprocs, my_start, my_stop, ierr)
712 [ - + ]: 18 : if (ierr /= 0) TETRA_ERROR("Error in MPI layer")
713 : :
714 : : ! for each tetrahedron
715 [ + + ]: 23346 : do itetra=my_start,my_stop
716 [ + + + + ]: 18810144 : tweight_tmp = zero
717 [ + + + + ]: 18810144 : dtweightde_tmp = zero
718 : :
719 : : ! Here we need the original ordering to reference the correct irred kpoints
720 [ + + ]: 116640 : ind_ibz(:) = tetra%tetra_full(:,1,itetra)
721 : :
722 : : ! Sort energies before calling get_onetetra_
723 [ + + ]: 116640 : eigen_1tetra(:) = eigen_in(ind_ibz(:))
724 : 23328 : call sort_tetra(4, eigen_1tetra, ind_ibz, tol14)
725 : :
726 : 23328 : call get_onetetra_(tetra,itetra,eigen_1tetra,enemin,enemax,max_occ,nene,bcorr,tweight_tmp,dtweightde_tmp)
727 : :
728 : : ! NOTE: the following blas calls are not working systematically, or do not give speed ups, strange...
729 : : !if (nene > 100) then
730 : : ! do ii=1,4
731 : : ! call daxpy (nene, 1.d0, tweight_tmp(:,ii), 1, tweight_t(:,ind_ibz(ii)), 1)
732 : : ! end do
733 : : ! do ii=1,4
734 : : ! call daxpy (nene, 1.d0, dtweightde_tmp(:,ii), 1, dtweightde_t(:,ind_ibz(ii)), 1)
735 : : ! end do
736 : : !else
737 [ + + ]: 116640 : do ii=1,4
738 [ + + ]: 18810144 : tweight_t(:,ind_ibz(ii)) = tweight_t(:,ind_ibz(ii)) + tweight_tmp(:,ii)
739 : : end do
740 [ + + ]: 116658 : do ii=1,4
741 [ + + ]: 18810144 : dtweightde_t(:,ind_ibz(ii)) = dtweightde_t(:,ind_ibz(ii)) + dtweightde_tmp(:,ii)
742 : : end do
743 : : !end if
744 : : end do ! itetra
745 : :
746 [ - + ]: 18 : TETRA_DEALLOCATE(tweight_tmp)
747 [ - + ]: 18 : TETRA_DEALLOCATE(dtweightde_tmp)
748 : :
749 [ - + ]: 18 : if (nprocs > 1) then
750 : : #ifdef HAVE_MPI
751 [ # # # # : 0 : TETRA_ALLOCATE(buffer, (nene, nkpt))
# # # # #
# # # # #
# # ]
752 : 0 : call MPI_ALLREDUCE(tweight_t,buffer,nene*nkpt,MPI_DOUBLE_PRECISION,MPI_SUM,comm,ierr)
753 [ # # # # ]: 0 : tweight_t = buffer
754 : :
755 : 0 : call MPI_ALLREDUCE(dtweightde_t,buffer,nene*nkpt,MPI_DOUBLE_PRECISION,MPI_SUM,comm,ierr)
756 [ # # # # ]: 0 : dtweightde_t = buffer
757 [ # # ]: 0 : TETRA_DEALLOCATE(buffer)
758 : : #endif
759 : : end if
760 : :
761 : 18 : end subroutine tetra_blochl_weights
762 : : !!***
763 : :
764 : : !----------------------------------------------------------------------
765 : :
766 : : !!****f* m_tetrahedron/get_dbl_tetra_weight
767 : : !! NAME
768 : : !! get_dbl_tetra_weight
769 : : !!
770 : : !! FUNCTION
771 : : !! calculate integration weights and their derivatives
772 : : !! for double tetrahedron method from Allen Phys Stat Sol B 120 529 (1983) [[cite:Allen1983b]]
773 : : !! the k-points and tetrahedra must be the same for both grids, of course,
774 : : !! but the range of energies is arbitrary
775 : : !!
776 : : !! Omega is called eigen1 here
777 : : !! E is called eigen2 here
778 : : !! indexing goes from 1 to 4 for the tetrahedron corners, in order of increasing eigen1
779 : : !! in Allen, from 0 to 3...
780 : : !!
781 : : !! INPUTS
782 : : !! eigen1_in(nkpt)=eigenenergies for each k point
783 : : !! eigen2_in(nkpt)=eigenenergies for each k point
784 : : !! enemin1=minimal energy for DOS in energy 1
785 : : !! enemax1=maximal energy for DOS
786 : : !! enemin2=minimal energy for DOS in energy 2
787 : : !! enemax2=maximal energy for DOS
788 : : !! max_occ=maximal occupation number (2 for nsppol=1, 1 for nsppol=2)
789 : : !! nene1=number of energies for DOS in energy 1
790 : : !! nene2=number of energies for DOS in energy 2
791 : : !! nkpt=number of irreducible kpoints
792 : : !! tetra%ntetra=number of tetra
793 : : !! tetra%tetra_full(4,2,ntetra)=for each irred tetrahedron, the list of k point vertices
794 : : !! 1 -> irred kpoint 2 -> fullkpt
795 : : !! tetra%tetra_mult(ntetra)=for each irred tetrahedron, its multiplicity
796 : : !! tetra%vv = ratio of volume of one tetrahedron in reciprocal space to full BZ volume
797 : : !! ierr = error code on exit
798 : : !!
799 : : !! OUTPUT
800 : : !! tweight(nkpt,nene1,nene2) = integration weights for each irred kpoint from all adjacent tetrahedra
801 : : !! dtweightde(nkpt,nene1,nene2) = derivative of tweight wrt energy
802 : : !!
803 : : !! SOURCE
804 : :
805 : 0 : subroutine get_dbl_tetra_weight(eigen1_in,eigen2_in,enemin1,enemax1,enemin2,enemax2,&
806 : 0 : & max_occ,nene1,nene2,nkpt,tetra,tweight,dtweightde, ierr)
807 : :
808 : : !Arguments ------------------------------------
809 : : !scalars
810 : : integer,intent(in) :: nene1,nene2,nkpt
811 : : integer,intent(out) :: ierr
812 : : type(t_tetrahedron), intent(in) :: tetra
813 : : real(dp),intent(in) :: enemax1,enemin1
814 : : real(dp),intent(in) :: enemax2,enemin2
815 : : real(dp),intent(in) :: max_occ
816 : : !arrays
817 : : real(dp),intent(in) :: eigen1_in(nkpt)
818 : : real(dp),intent(in) :: eigen2_in(nkpt)
819 : : real(dp),intent(out) :: dtweightde(nkpt,nene1,nene2),tweight(nkpt,nene1,nene2)
820 : :
821 : : !Local variables-------------------------------
822 : : ! needed for gaussian replacement of Dirac functions
823 : : ! the three coefficients of the DOS as quadratic form,
824 : : ! in the interval [eig(ikpt-1), eig(ikpt)]
825 : : ! for ikpt = 1 we add a point below eigen(1) which doesnt
826 : : ! contribute to the DOS in any tetrahedron
827 : : !scalars
828 : : integer :: ieps1,ieps2,itetra
829 : : integer :: nn1_1,nn1_2,nn1_3,nn1_4
830 : : integer :: nn2_1,nn2_2,nn2_3
831 : : integer :: ind_a(3), ind_b(3), ind_c(3)
832 : : real(dp) :: deltaene1,eps1
833 : : real(dp) :: deltaene2,eps2
834 : : ! real(dp) :: gau_prefactor,gau_width,gau_width2
835 : : real(dp) :: epsilon1(4,4)
836 : : real(dp) :: epsilon2(4,4)
837 : : real(dp) :: inv_epsilon1(4,4)
838 : : real(dp) :: aa(3),bb(3),cc(3)
839 : : real(dp) :: delaa(3),delbb(3),delcc(3)
840 : : real(dp) :: delaa0,delbb0,delcc0
841 : : real(dp) :: inv_delaa(3),inv_delbb(3),inv_delcc(3)
842 : : real(dp) :: deleps1, deleps2
843 : : real(dp) :: inv_deleps1
844 : : real(dp) :: dccde1, dccde1_pre
845 : : real(dp) :: volconst,volconst_mult
846 : : real(dp) :: ii0, ii1, ii3
847 : : !arrays
848 : : integer :: ind_k(4)
849 : 0 : real(dp), allocatable :: tweight_tmp(:,:,:)
850 : 0 : real(dp), allocatable :: dtweightde_tmp(:,:,:)
851 : : real(dp) :: eigen1_1tetra(4)
852 : : real(dp) :: eigen2_1tetra(4)
853 : :
854 : : ! *********************************************************************
855 : :
856 : 0 : ierr = 0
857 [ # # # # ]: 0 : if (nene1 <= 1 .or. nene2 <= 1) then
858 : : !'get_dbl_tetra_weight: nene must be at least 2'
859 : 0 : ierr = 1
860 : : return
861 : : else
862 : 0 : deltaene1 = (enemax1-enemin1) / (nene1-1)
863 : 0 : deltaene2 = (enemax2-enemin2) / (nene2-1)
864 : : end if
865 : :
866 [ # # # # : 0 : TETRA_ALLOCATE(tweight_tmp, (4, nene2, nene1))
# # # # #
# # # #
# ]
867 [ # # # # : 0 : TETRA_ALLOCATE(dtweightde_tmp, (4, nene2, nene1))
# # # # #
# # # ]
868 : :
869 : : !print *, "warning: for the moment, heaviside weights are 0. The delta function / DOS weights are the only ones calculated "
870 : :
871 : 0 : volconst = tetra%vv/4.d0
872 : :
873 : : ! for each tetrahedron
874 [ # # ]: 0 : do itetra=1,tetra%ntetra
875 : : ! these are for 1 tetrahedron only.
876 [ # # # # : 0 : tweight_tmp = zero
# # ]
877 [ # # # # : 0 : dtweightde_tmp = zero
# # ]
878 : :
879 : 0 : volconst_mult = max_occ*volconst*dble(tetra%tetra_mult(itetra))
880 : :
881 : : ! Here we need the original ordering to reference the correct irred kpoints
882 : : ! ind_k refers to the index in the full k list of the summits of the present tetrahedra
883 : : ! we can forget the order of the summits within the tetrahedron, because eigen1 fixes that
884 : : ! order with its increasing value
885 : 0 : ind_k(1) = tetra%tetra_full(1,1,itetra)
886 : 0 : ind_k(2) = tetra%tetra_full(2,1,itetra)
887 : 0 : ind_k(3) = tetra%tetra_full(3,1,itetra)
888 : 0 : ind_k(4) = tetra%tetra_full(4,1,itetra)
889 : 0 : eigen1_1tetra(1) = eigen1_in(ind_k(1))
890 : 0 : eigen1_1tetra(2) = eigen1_in(ind_k(2))
891 : 0 : eigen1_1tetra(3) = eigen1_in(ind_k(3))
892 : 0 : eigen1_1tetra(4) = eigen1_in(ind_k(4))
893 : 0 : call sort_tetra(4,eigen1_1tetra,ind_k,tol14)
894 : :
895 : : ! re-sort eigen2 values according to order chosen for eigen1. Eigen2 are _not_ in increasing order!
896 : 0 : eigen2_1tetra(1) = eigen2_in(ind_k(1))
897 : 0 : eigen2_1tetra(2) = eigen2_in(ind_k(2))
898 : 0 : eigen2_1tetra(3) = eigen2_in(ind_k(3))
899 : 0 : eigen2_1tetra(4) = eigen2_in(ind_k(4))
900 : :
901 : : ! the epsilons are energy differences for the two eigenvalue sets
902 : 0 : epsilon1 = zero
903 : 0 : epsilon2 = zero
904 [ # # ]: 0 : do ieps1 = 1, 4
905 [ # # ]: 0 : do ieps2 = ieps1+1, 4
906 : 0 : epsilon1(ieps1,ieps2) = eigen1_1tetra(ieps1)-eigen1_1tetra(ieps2)
907 : 0 : epsilon1(ieps2,ieps1) = -epsilon1(ieps1,ieps2)
908 : 0 : epsilon2(ieps1,ieps2) = eigen2_1tetra(ieps1)-eigen2_1tetra(ieps2)
909 : 0 : epsilon2(ieps2,ieps1) = -epsilon2(ieps1,ieps2)
910 : : end do
911 : : end do
912 : :
913 : : ! we precalculate the inverses to avoid doing tons of divisions in the energy loops below
914 : : ! Allen formulae only require the inverses of the differences of eigen1 + the a b c below
915 : 0 : inv_epsilon1 = zero
916 [ # # ]: 0 : do ieps1 = 1, 4
917 [ # # ]: 0 : do ieps2 = ieps1+1, 4
918 [ # # ]: 0 : if (abs(epsilon1(ieps1,ieps2)) > tol14) then
919 : 0 : inv_epsilon1(ieps1,ieps2) = 1.d0 / epsilon1(ieps1,ieps2)
920 : 0 : inv_epsilon1(ieps2,ieps1) = -inv_epsilon1(ieps1,ieps2)
921 : : end if
922 : : end do
923 : : end do
924 : :
925 : : ! these bounds determine the intervals for Omega in Allen paper, and cases A, B, C
926 : 0 : nn1_1 = int((eigen1_1tetra(1)-enemin1)/deltaene1)+1
927 : 0 : nn1_2 = int((eigen1_1tetra(2)-enemin1)/deltaene1)+1
928 : 0 : nn1_3 = int((eigen1_1tetra(3)-enemin1)/deltaene1)+1
929 : 0 : nn1_4 = int((eigen1_1tetra(4)-enemin1)/deltaene1)+1
930 : :
931 : 0 : nn1_1 = max(1,nn1_1)
932 : 0 : nn1_1 = min(nn1_1,nene1)
933 : 0 : nn1_2 = max(1,nn1_2)
934 : 0 : nn1_2 = min(nn1_2,nene1)
935 : 0 : nn1_3 = max(1,nn1_3)
936 : 0 : nn1_3 = min(nn1_3,nene1)
937 : 0 : nn1_4 = max(1,nn1_4)
938 : 0 : nn1_4 = min(nn1_4,nene1)
939 : :
940 : : ! calculate Allen a_i b_i and c_i parameters
941 : : ! sort the a_i b_i c_i
942 : : !
943 : : ! NOTE: indices here go from 1 to 4 instead of 0 to 3 as in Allen...
944 : 0 : aa(1) = epsilon2(2,1) * inv_epsilon1(2,1)
945 : 0 : aa(2) = epsilon2(3,1) * inv_epsilon1(3,1)
946 : 0 : aa(3) = epsilon2(4,1) * inv_epsilon1(4,1)
947 : 0 : ind_a = (/2,3,4/)
948 : 0 : call sort_tetra(3,aa,ind_a,tol14)
949 : : ! aa are now in order a_s a_m a_l !!! Preserve the hash function ind_a to order the positions of k below
950 : 0 : delaa(1) = aa(2)-aa(1)
951 : 0 : delaa(2) = aa(3)-aa(1)
952 : 0 : delaa(3) = aa(3)-aa(2)
953 : 0 : inv_delaa = zero
954 [ # # ]: 0 : if(delaa(1)> tol14) inv_delaa(1)= 1.0d0 / delaa(1)
955 [ # # ]: 0 : if(delaa(2)> tol14) inv_delaa(2)= 1.0d0 / delaa(2)
956 [ # # ]: 0 : if(delaa(3)> tol14) inv_delaa(3)= 1.0d0 / delaa(3)
957 : :
958 : 0 : bb(1) = epsilon2(1,2) * inv_epsilon1(1,2)
959 : 0 : bb(2) = epsilon2(3,2) * inv_epsilon1(3,2)
960 : 0 : bb(3) = epsilon2(4,2) * inv_epsilon1(4,2)
961 : 0 : ind_b = (/1,3,4/)
962 : 0 : call sort_tetra(3,bb,ind_b,tol14)
963 : 0 : delbb(1) = bb(2)-bb(1)
964 : 0 : delbb(2) = bb(3)-bb(1)
965 : 0 : delbb(3) = bb(3)-bb(2)
966 : 0 : inv_delbb = zero
967 [ # # ]: 0 : if(delbb(1)> tol14) inv_delbb(1)= 1.0d0 / delbb(1)
968 [ # # ]: 0 : if(delbb(2)> tol14) inv_delbb(2)= 1.0d0 / delbb(2)
969 [ # # ]: 0 : if(delbb(3)> tol14) inv_delbb(3)= 1.0d0 / delbb(3)
970 : :
971 : 0 : cc(1) = epsilon2(1,4) * inv_epsilon1(1,4)
972 : 0 : cc(2) = epsilon2(2,4) * inv_epsilon1(2,4)
973 : 0 : cc(3) = epsilon2(3,4) * inv_epsilon1(3,4)
974 : 0 : ind_c = (/1,2,3/)
975 : 0 : call sort_tetra(3,cc,ind_c,tol14)
976 : 0 : delcc(1) = cc(2)-cc(1)
977 : 0 : delcc(2) = cc(3)-cc(1)
978 : 0 : delcc(3) = cc(3)-cc(2)
979 : 0 : inv_delcc = zero
980 [ # # ]: 0 : if(delcc(1)> tol14) inv_delcc(1)= 1.0d0 / delcc(1)
981 [ # # ]: 0 : if(delcc(2)> tol14) inv_delcc(2)= 1.0d0 / delcc(2)
982 [ # # ]: 0 : if(delcc(3)> tol14) inv_delcc(3)= 1.0d0 / delcc(3)
983 : :
984 : : !----------------------------------------------------------------------
985 : : ! start main loop A B C over eps1
986 : : !----------------------------------------------------------------------
987 : :
988 : : !
989 : : ! interval enemin1 < eps1 < e1 nothing to do
990 : : !
991 : : !
992 : : ! interval e1 < eps1 < e3 CASE A in Allen + first term in B
993 : : !
994 : : ! NB: eps1 is not updated inside the loop, only between the loops
995 : 0 : eps1 = enemin1+nn1_1*deltaene1
996 : 0 : deleps1 = eps1-eigen1_1tetra(1) ! this is Omega - omega_0
997 : 0 : dccde1_pre = 6.d0*volconst_mult*inv_epsilon1(2,1)*inv_epsilon1(3,1)*inv_epsilon1(4,1)
998 : :
999 : : ! note we go to nn1_3
1000 [ # # ]: 0 : do ieps1=nn1_1+1,nn1_3
1001 : :
1002 : 0 : dccde1 = dccde1_pre * deleps1 ! this is f_0(Omega)*6*v
1003 : :
1004 : : ! at fixed ieps1 we can find the pivot indices for the ieps2 loop
1005 : 0 : nn2_1 = int((eigen2_1tetra(1)+deleps1*aa(1) -enemin2)/deltaene2)+1
1006 : 0 : nn2_2 = int((eigen2_1tetra(1)+deleps1*aa(2) -enemin2)/deltaene2)+1
1007 : 0 : nn2_3 = int((eigen2_1tetra(1)+deleps1*aa(3) -enemin2)/deltaene2)+1
1008 : :
1009 : 0 : nn2_1 = max(1,nn2_1)
1010 : 0 : nn2_1 = min(nn2_1,nene2)
1011 : 0 : nn2_2 = max(1,nn2_2)
1012 : 0 : nn2_2 = min(nn2_2,nene2)
1013 : 0 : nn2_3 = max(1,nn2_3)
1014 : 0 : nn2_3 = min(nn2_3,nene2)
1015 : :
1016 : 0 : inv_deleps1 = 1.0d0 / deleps1
1017 : :
1018 : 0 : eps2 = enemin2+nn2_1*deltaene2 ! this is E
1019 : 0 : deleps2 = eps2 - eigen2_1tetra(1) ! this is E-epsilon_0
1020 : :
1021 : : !-----------------------------------------------------------------------
1022 : : ! This is case AI
1023 : : !-----------------------------------------------------------------------
1024 [ # # ]: 0 : do ieps2 = nn2_1+1, nn2_2
1025 : : ! calculate running value of del "a" = a-a_s: first term should really mix eps1 and eps2
1026 : 0 : delaa0 = deleps2*inv_deleps1 - aa(1) ! a - a_s
1027 : :
1028 : 0 : ii0 = dccde1*delaa0*inv_delaa(1)*inv_delaa(2) ! this is I_0(Omega E)
1029 : :
1030 : : dtweightde_tmp(1,ieps2,ieps1) = dtweightde_tmp(1,ieps2,ieps1) + &
1031 : : & ii0*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_a(1),1)* &
1032 : : & (-2.0d0 + delaa0*inv_delaa(1)*epsilon1(ind_a(2),ind_a(1))*inv_epsilon1(ind_a(2),1) &
1033 : 0 : & + delaa0*inv_delaa(2)*epsilon1(ind_a(3),ind_a(1))*inv_epsilon1(ind_a(3),1)))
1034 : : dtweightde_tmp(ind_a(1),ieps2,ieps1) = dtweightde_tmp(ind_a(1),ieps2,ieps1) + &
1035 : 0 : & ii0*0.5d0*deleps1*inv_epsilon1(ind_a(1),1)*(2.0d0 - delaa0*inv_delaa(1) - delaa0*inv_delaa(2))
1036 : : dtweightde_tmp(ind_a(2),ieps2,ieps1) = dtweightde_tmp(ind_a(2),ieps2,ieps1) + &
1037 : 0 : & ii0*0.5d0*delaa0*inv_delaa(1)*deleps1*inv_epsilon1(ind_a(2),1)
1038 : : dtweightde_tmp(ind_a(3),ieps2,ieps1) = dtweightde_tmp(ind_a(3),ieps2,ieps1) + &
1039 : 0 : & ii0*0.5d0*delaa0*inv_delaa(2)*deleps1*inv_epsilon1(ind_a(3),1)
1040 : 0 : deleps2 = deleps2 + deltaene2
1041 : : end do
1042 : :
1043 : :
1044 : 0 : eps2 = enemin2+nn2_2*deltaene2 ! this is E
1045 : 0 : deleps2 = eps2 - eigen2_1tetra(1) ! E-E_0
1046 : :
1047 : : !-----------------------------------------------------------------------
1048 : : ! This is case AII
1049 : : !-----------------------------------------------------------------------
1050 [ # # ]: 0 : do ieps2 = nn2_2+1, nn2_3
1051 : : ! calculate running value of del "a" = a_l-a: first term should really mix eps1 and eps2
1052 : 0 : delaa0 = aa(3) - deleps2*inv_deleps1 ! a_l - a
1053 : :
1054 : 0 : ii0 = dccde1*delaa0*inv_delaa(3)*inv_delaa(2) ! this is I_0(Omega E)
1055 : :
1056 : : dtweightde_tmp(1,ieps2,ieps1) = dtweightde_tmp(1,ieps2,ieps1) + &
1057 : : & ii0*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_a(3),1)* &
1058 : : & (-2.0d0 + delaa0*inv_delaa(3)*epsilon1(ind_a(2),ind_a(3))*inv_epsilon1(ind_a(2),1) &
1059 : 0 : & + delaa0*inv_delaa(2)*epsilon1(ind_a(1),ind_a(3))*inv_epsilon1(ind_a(1),1)))
1060 : : dtweightde_tmp(ind_a(3),ieps2,ieps1) = dtweightde_tmp(ind_a(3),ieps2,ieps1) + &
1061 : 0 : & ii0*0.5d0*deleps1*inv_epsilon1(ind_a(3),1)*(2.0d0 - delaa0*inv_delaa(3) - delaa0*inv_delaa(2))
1062 : : dtweightde_tmp(ind_a(2),ieps2,ieps1) = dtweightde_tmp(ind_a(2),ieps2,ieps1) + &
1063 : 0 : & ii0*0.5d0*delaa0*inv_delaa(3)*deleps1*inv_epsilon1(ind_a(2),1)
1064 : : dtweightde_tmp(ind_a(1),ieps2,ieps1) = dtweightde_tmp(ind_a(1),ieps2,ieps1) + &
1065 : 0 : & ii0*0.5d0*delaa0*inv_delaa(2)*deleps1*inv_epsilon1(ind_a(1),1)
1066 : :
1067 : 0 : deleps2 = deleps2 + deltaene2
1068 : : end do
1069 : 0 : deleps1 = deleps1 + deltaene1
1070 : : end do
1071 : : !
1072 : : ! interval e2 < eps < e3
1073 : : !
1074 : 0 : eps1 = eps1 + (nn1_2-nn1_1)*deltaene1
1075 : :
1076 : 0 : deleps1 = eps1-eigen1_1tetra(2) ! Omega - omega_1
1077 : :
1078 : 0 : dccde1_pre = 6.d0*volconst_mult*inv_epsilon1(2,1)*inv_epsilon1(3,2)*inv_epsilon1(4,2) ! f1 function
1079 [ # # ]: 0 : do ieps1=nn1_2+1,nn1_3
1080 : :
1081 : 0 : dccde1 = dccde1_pre * deleps1 ! f2(Omega) * 6 * v
1082 : :
1083 : : ! at fixed ieps1 we can find the pivot indices for the ieps2 loop
1084 : 0 : nn2_1 = int((eigen2_1tetra(2)+deleps1*bb(1) -enemin2)/deltaene2)+1
1085 : 0 : nn2_2 = int((eigen2_1tetra(2)+deleps1*bb(2) -enemin2)/deltaene2)+1
1086 : 0 : nn2_3 = int((eigen2_1tetra(2)+deleps1*bb(3) -enemin2)/deltaene2)+1
1087 : :
1088 : 0 : nn2_1 = max(1,nn2_1)
1089 : 0 : nn2_1 = min(nn2_1,nene2)
1090 : 0 : nn2_2 = max(1,nn2_2)
1091 : 0 : nn2_2 = min(nn2_2,nene2)
1092 : 0 : nn2_3 = max(1,nn2_3)
1093 : 0 : nn2_3 = min(nn2_3,nene2)
1094 : :
1095 : 0 : inv_deleps1 = 1.0d0 / deleps1
1096 : :
1097 : 0 : eps2 = enemin2+nn2_1*deltaene2 ! starting value for E
1098 : 0 : deleps2 = eps2 - eigen2_1tetra(2) ! E - epsilon_1
1099 : :
1100 : : !-----------------------------------------------------------------------
1101 : : ! This is case BI
1102 : : !-----------------------------------------------------------------------
1103 [ # # ]: 0 : do ieps2 = nn2_1+1, nn2_2
1104 : : ! calculate running value of del "b" = b-b_s: first term should really mix eps1 and eps2
1105 : 0 : delbb0 = deleps2*inv_deleps1 - bb(1)
1106 : :
1107 : 0 : ii1 = dccde1*delbb0*inv_delbb(1)*inv_delbb(2) ! this is I_1(Omega E)
1108 : :
1109 : : ! note negative sign here - we are correcting the I0 a0 term already calculated above
1110 : : dtweightde_tmp(2,ieps2,ieps1) = dtweightde_tmp(2,ieps2,ieps1) - &
1111 : : & ii1*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_b(1),2)* &
1112 : : & (-2.0d0 + delbb0*inv_delbb(1)*epsilon1(ind_b(2),ind_b(1))*inv_epsilon1(ind_b(2),2) &
1113 : 0 : & + delbb0*inv_delbb(2)*epsilon1(ind_b(3),ind_b(1))*inv_epsilon1(ind_b(3),2)))
1114 : : dtweightde_tmp(ind_b(1),ieps2,ieps1) = dtweightde_tmp(ind_b(1),ieps2,ieps1) - &
1115 : 0 : & ii1*0.5d0*deleps1*inv_epsilon1(ind_b(1),2)*(2.0d0 - delbb0*inv_delbb(1) - delbb0*inv_delbb(2))
1116 : : dtweightde_tmp(ind_b(2),ieps2,ieps1) = dtweightde_tmp(ind_b(2),ieps2,ieps1) - &
1117 : 0 : & ii1*0.5d0*delbb0*inv_delbb(1)*deleps1*inv_epsilon1(ind_b(2),2)
1118 : : dtweightde_tmp(ind_b(3),ieps2,ieps1) = dtweightde_tmp(ind_b(3),ieps2,ieps1) - &
1119 : 0 : & ii1*0.5d0*delbb0*inv_delbb(2)*deleps1*inv_epsilon1(ind_b(3),2)
1120 : 0 : deleps2 = deleps2 + deltaene2
1121 : : end do
1122 : :
1123 : 0 : eps2 = enemin2+nn2_2*deltaene2
1124 : 0 : deleps2 = eps2 - eigen2_1tetra(2)
1125 : :
1126 : : !-----------------------------------------------------------------------
1127 : : ! This is case BII
1128 : : !-----------------------------------------------------------------------
1129 [ # # ]: 0 : do ieps2 = nn2_2+1, nn2_3
1130 : : ! calculate running value of del "b" = b_l-b: first term should really mix eps1 and eps2
1131 : 0 : delbb0 = bb(3) - deleps2*inv_deleps1
1132 : :
1133 : 0 : ii1 = dccde1*delbb0*inv_delbb(3)*inv_delbb(2) ! this is I_1(Omega E)
1134 : :
1135 : : ! note negative sign here - we are correcting the I0 a0 term already calculated above
1136 : : dtweightde_tmp(2,ieps2,ieps1) = dtweightde_tmp(2,ieps2,ieps1) - &
1137 : : & ii1*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_b(3),2)* &
1138 : : & (-2.0d0 + delbb0*inv_delbb(3)*epsilon1(ind_b(2),ind_b(3))*inv_epsilon1(ind_b(2),2) &
1139 : 0 : & + delbb0*inv_delbb(2)*epsilon1(ind_b(1),ind_b(3))*inv_epsilon1(ind_b(1),2)))
1140 : : dtweightde_tmp(ind_b(3),ieps2,ieps1) = dtweightde_tmp(ind_b(3),ieps2,ieps1) - &
1141 : 0 : & ii1*0.5d0*deleps1*inv_epsilon1(ind_b(3),2)*(2.0d0 - delbb0*inv_delbb(3) - delbb0*inv_delbb(2))
1142 : : dtweightde_tmp(ind_b(2),ieps2,ieps1) = dtweightde_tmp(ind_b(2),ieps2,ieps1) - &
1143 : 0 : & ii1*0.5d0*delbb0*inv_delbb(3)*deleps1*inv_epsilon1(ind_b(2),2)
1144 : : dtweightde_tmp(ind_b(1),ieps2,ieps1) = dtweightde_tmp(ind_b(1),ieps2,ieps1) - &
1145 : 0 : & ii1*0.5d0*delbb0*inv_delbb(2)*deleps1*inv_epsilon1(ind_b(1),2)
1146 : :
1147 : 0 : deleps2 = deleps2 + deltaene2
1148 : : end do
1149 : :
1150 : 0 : deleps1 = deleps1 + deltaene1
1151 : : end do
1152 : :
1153 : : !
1154 : : ! interval e3 < eps < e4
1155 : : !
1156 : 0 : eps1 = eps1 + (nn1_3-nn1_2)*deltaene1
1157 : 0 : deleps1 = eps1-eigen1_1tetra(4)
1158 : 0 : dccde1_pre = 6.d0*volconst_mult*inv_epsilon1(4,1)*inv_epsilon1(4,2)*inv_epsilon1(4,3)
1159 [ # # ]: 0 : do ieps1=nn1_3+1,nn1_4
1160 : : ! note - sign from definition of f3
1161 : 0 : dccde1 = -dccde1_pre * deleps1 ! f3(Omega) * 6 * v
1162 : :
1163 : : ! at fixed ieps1 we can find the pivot indices for the ieps2 loop
1164 : : ! NB: order is inverted for cc because deleps1 is defined negative (Omega is always less than omega_3)
1165 : 0 : nn2_1 = int((eigen2_1tetra(4)+deleps1*cc(3) -enemin2)/deltaene2)+1
1166 : 0 : nn2_2 = int((eigen2_1tetra(4)+deleps1*cc(2) -enemin2)/deltaene2)+1
1167 : 0 : nn2_3 = int((eigen2_1tetra(4)+deleps1*cc(1) -enemin2)/deltaene2)+1
1168 : :
1169 : 0 : nn2_1 = max(1,nn2_1)
1170 : 0 : nn2_1 = min(nn2_1,nene2)
1171 : 0 : nn2_2 = max(1,nn2_2)
1172 : 0 : nn2_2 = min(nn2_2,nene2)
1173 : 0 : nn2_3 = max(1,nn2_3)
1174 : 0 : nn2_3 = min(nn2_3,nene2)
1175 : 0 : inv_deleps1 = 1.0d0 / deleps1
1176 : :
1177 : 0 : eps2 = enemin2+nn2_1*deltaene2 ! starting value for E
1178 : 0 : deleps2 = eps2 - eigen2_1tetra(4) ! E - epsilon_3
1179 : :
1180 : : !-----------------------------------------------------------------------
1181 : : ! This is case CII
1182 : : !-----------------------------------------------------------------------
1183 [ # # ]: 0 : do ieps2 = nn2_1+1, nn2_2
1184 : : ! calculate running value of del "c" = c_l-c: first term should really mix eps1 and eps2
1185 : 0 : delcc0 = cc(3) - deleps2*inv_deleps1
1186 : :
1187 : 0 : ii3 = dccde1*delcc0*inv_delcc(3)*inv_delcc(2) ! this is I_3(Omega E)
1188 : :
1189 : : dtweightde_tmp(4,ieps2,ieps1) = dtweightde_tmp(4,ieps2,ieps1) + &
1190 : : & ii3*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_c(3),4)* &
1191 : : & (-2.0d0 + delcc0*inv_delcc(3)*epsilon1(ind_c(2),ind_c(3))*inv_epsilon1(ind_c(2),4) &
1192 : 0 : & + delcc0*inv_delcc(2)*epsilon1(ind_c(1),ind_c(3))*inv_epsilon1(ind_c(1),4)))
1193 : : dtweightde_tmp(ind_c(3),ieps2,ieps1) = dtweightde_tmp(ind_c(3),ieps2,ieps1) + &
1194 : 0 : & ii3*0.5d0*deleps1*inv_epsilon1(ind_c(3),4)*(2.0d0 - delcc0*inv_delcc(3) - delcc0*inv_delcc(2))
1195 : : dtweightde_tmp(ind_c(2),ieps2,ieps1) = dtweightde_tmp(ind_c(2),ieps2,ieps1) + &
1196 : 0 : & ii3*0.5d0*delcc0*inv_delcc(3)*deleps1*inv_epsilon1(ind_c(2),4)
1197 : : dtweightde_tmp(ind_c(1),ieps2,ieps1) = dtweightde_tmp(ind_c(1),ieps2,ieps1) + &
1198 : 0 : & ii3*0.5d0*delcc0*inv_delcc(2)*deleps1*inv_epsilon1(ind_c(1),4)
1199 : :
1200 : 0 : deleps2 = deleps2 + deltaene2
1201 : : end do
1202 : :
1203 : :
1204 : 0 : eps2 = enemin2+nn2_2*deltaene2
1205 : 0 : deleps2 = eps2 - eigen2_1tetra(4)
1206 : :
1207 : : !-----------------------------------------------------------------------
1208 : : ! This is case CI
1209 : : !-----------------------------------------------------------------------
1210 [ # # ]: 0 : do ieps2 = nn2_2+1, nn2_3
1211 : : ! calculate running value of del "c" = c-c_s: first term should really mix eps1 and eps2
1212 : 0 : delcc0 = deleps2*inv_deleps1 - cc(1) ! c - c_s
1213 : :
1214 : 0 : ii3 = dccde1*delcc0*inv_delcc(1)*inv_delcc(2) ! this is I_3(Omega E)
1215 : :
1216 : : dtweightde_tmp(4,ieps2,ieps1) = dtweightde_tmp(4,ieps2,ieps1) + &
1217 : : & ii3*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_c(1),4)* &
1218 : : & (-2.0d0 + delcc0*inv_delcc(1)*epsilon1(ind_c(2),ind_c(1))*inv_epsilon1(ind_c(2),4) &
1219 : 0 : & + delcc0*inv_delcc(2)*epsilon1(ind_c(3),ind_c(1))*inv_epsilon1(ind_c(3),4)))
1220 : : dtweightde_tmp(ind_c(1),ieps2,ieps1) = dtweightde_tmp(ind_c(1),ieps2,ieps1) + &
1221 : 0 : & ii3*0.5d0*deleps1*inv_epsilon1(ind_c(1),4)*(2.0d0 - delcc0*inv_delcc(1) - delcc0*inv_delcc(2))
1222 : : dtweightde_tmp(ind_c(2),ieps2,ieps1) = dtweightde_tmp(ind_c(2),ieps2,ieps1) + &
1223 : 0 : & ii3*0.5d0*delcc0*inv_delcc(1)*deleps1*inv_epsilon1(ind_c(2),4)
1224 : : dtweightde_tmp(ind_c(3),ieps2,ieps1) = dtweightde_tmp(ind_c(3),ieps2,ieps1) + &
1225 : 0 : & ii3*0.5d0*delcc0*inv_delcc(2)*deleps1*inv_epsilon1(ind_c(3),4)
1226 : 0 : deleps2 = deleps2 + deltaene2
1227 : : end do
1228 : :
1229 : 0 : deleps1 = deleps1 + deltaene1
1230 : : end do
1231 : :
1232 : 0 : eps1 = eps1 + (nn1_4-nn1_3)*deltaene1
1233 : : !
1234 : : !
1235 : : ! interval e4 < eps < enemax
1236 : : !
1237 : 0 : do ieps1=nn1_4+1,nene1
1238 : : ! dtweightde unchanged by this tetrahedron
1239 : : end do
1240 : :
1241 : : ! if we have a fully degenerate tetrahedron,
1242 : : ! 1) the tweight is a Heaviside (step) function, which is correct above, but
1243 : : ! 2) the dtweightde should contain a Dirac function: add a Gaussian here
1244 : :
1245 : : ! TODO: add treatment in double tetra case
1246 : : ! end degenerate tetrahedron if
1247 : :
1248 : : ! the following blas calls are not working systematically, or do not give speed ups, strange...
1249 : : !call daxpy (nene, 1.d0, dtweightde_tmp(:,1), 1, dtweightde_t(:,ind_ibz(1)), 1)
1250 : : !call daxpy (nene, 1.d0, dtweightde_tmp(:,2), 1, dtweightde_t(:,ind_ibz(2)), 1)
1251 : : !call daxpy (nene, 1.d0, dtweightde_tmp(:,3), 1, dtweightde_t(:,ind_ibz(3)), 1)
1252 : : !call daxpy (nene, 1.d0, dtweightde_tmp(:,4), 1, dtweightde_t(:,ind_ibz(4)), 1)
1253 : :
1254 [ # # ]: 0 : do ieps2 = 1, nene2
1255 [ # # ]: 0 : dtweightde(ind_k(1),:,ieps2) = dtweightde(ind_k(1),:,ieps2) + dtweightde_tmp(1,ieps2,:)
1256 [ # # ]: 0 : dtweightde(ind_k(2),:,ieps2) = dtweightde(ind_k(2),:,ieps2) + dtweightde_tmp(2,ieps2,:)
1257 [ # # ]: 0 : dtweightde(ind_k(3),:,ieps2) = dtweightde(ind_k(3),:,ieps2) + dtweightde_tmp(3,ieps2,:)
1258 [ # # ]: 0 : dtweightde(ind_k(4),:,ieps2) = dtweightde(ind_k(4),:,ieps2) + dtweightde_tmp(4,ieps2,:)
1259 : : !tweight(nkpt,nene1,nene2)
1260 : : end do
1261 : :
1262 : : end do ! itetra
1263 : :
1264 : : ! transpose: otherwise the data access is crap and the code slows by an order of magnitude
1265 [ # # ]: 0 : TETRA_DEALLOCATE(tweight_tmp)
1266 [ # # ]: 0 : TETRA_DEALLOCATE(dtweightde_tmp)
1267 : :
1268 : : end subroutine get_dbl_tetra_weight
1269 : : !!***
1270 : :
1271 : : !!****f* m_tetrahedron/sort_tetra
1272 : : !! NAME
1273 : : !! sort_tetra
1274 : : !!
1275 : : !! FUNCTION
1276 : : !! Sort double precision array list(n) into ascending numerical order using Heapsort
1277 : : !! algorithm, while making corresponding rearrangement of the integer
1278 : : !! array iperm. Consider that two double precision numbers
1279 : : !! within tolerance tol are equal.
1280 : : !!
1281 : : !! INPUTS
1282 : : !! n intent(in) dimension of the list
1283 : : !! tol intent(in) numbers within tolerance are equal
1284 : : !! list(n) intent(inout) list of double precision numbers to be sorted
1285 : : !! iperm(n) intent(inout) iperm(i)=i (very important)
1286 : : !!
1287 : : !! OUTPUT
1288 : : !! list(n) sorted list
1289 : : !! iperm(n) index of permutation given the right ascending order
1290 : : !!
1291 : : !! SOURCE
1292 : :
1293 : :
1294 : 23332 : subroutine sort_tetra(n,list,iperm,tol)
1295 : :
1296 : : integer, intent(in) :: n
1297 : : integer, intent(inout) :: iperm(n)
1298 : : real(dp), intent(inout) :: list(n)
1299 : : real(dp), intent(in) :: tol
1300 : :
1301 : : integer :: l,ir,iap,i,j
1302 : : real(dp) :: ap
1303 : : character(len=500) :: msg
1304 : :
1305 [ - + ]: 23332 : if (n==1) then
1306 : : ! Accomodate case of array of length 1: already sorted!
1307 : 0 : return
1308 [ - + ]: 23332 : else if (n<1) then
1309 : : ! Should not call with n<1
1310 : 0 : write(msg,1000) n
1311 : : 1000 format(/,' sort_tetra has been called with array length n=',i12,/, &
1312 : : & ' having a value less than 1. This is not allowed.')
1313 : 0 : TETRA_ERROR(msg)
1314 : :
1315 : : else ! n>1
1316 : :
1317 : : ! Conduct the usual sort
1318 : 23332 : l=n/2+1
1319 : 23332 : ir=n
1320 : :
1321 : 101080 : do ! Infinite do-loop
1322 [ + + ]: 124412 : if (l>1) then
1323 : 49248 : l=l-1
1324 : 49248 : ap=list(l)
1325 : 49248 : iap=iperm(l)
1326 : :
1327 : : else ! l<=1
1328 : 75164 : ap=list(ir)
1329 : 75164 : iap=iperm(ir)
1330 : 75164 : list(ir)=list(1)
1331 : 75164 : iperm(ir)=iperm(1)
1332 : 75164 : ir=ir-1
1333 : :
1334 [ + + ]: 75164 : if (ir==1) then
1335 : 23332 : list(1)=ap
1336 : 23332 : iperm(1)=iap
1337 : 23332 : exit ! This is the end of this algorithm
1338 : : end if
1339 : : end if ! l>1
1340 : :
1341 : 101080 : i=l
1342 : 101080 : j=l+l
1343 : :
1344 [ + + ]: 252290 : do while (j<=ir)
1345 [ + + ]: 151210 : if (j<ir) then
1346 [ + + + + : 92732 : if ( list(j)<list(j+1)-tol .or. &
+ + ]
1347 : 151210 : & (list(j)<list(j+1)+tol.and.iperm(j)<iperm(j+1))) j=j+1
1348 : : endif
1349 [ + + + + : 252290 : if (ap<list(j)-tol .or. (ap<list(j)+tol.and.iap<iperm(j))) then
+ + ]
1350 : 119156 : list(i)=list(j)
1351 : 119156 : iperm(i)=iperm(j)
1352 : 119156 : i=j
1353 : 119156 : j=j+j
1354 : : else
1355 : 32054 : j=ir+1
1356 : : end if
1357 : : enddo
1358 : :
1359 : 101080 : list(i)=ap
1360 : 101080 : iperm(i)=iap
1361 : :
1362 : : enddo ! End infinite do-loop
1363 : :
1364 : : end if ! n>1
1365 : :
1366 : : end subroutine sort_tetra
1367 : : !!***
1368 : :
1369 : : !----------------------------------------------------------------------
1370 : :
1371 : : !!****f* m_tetrahedron/tetralib_has_mpi
1372 : : !! NAME
1373 : : !! tetralib_has_mpi
1374 : : !!
1375 : : !! FUNCTION
1376 : : !! Return True if library has been compiled with MPI support
1377 : : !!
1378 : : !! SOURCE
1379 : :
1380 : 0 : logical function tetralib_has_mpi() result(ans)
1381 : :
1382 : : ans = .False.
1383 : : #ifdef HAVE_MPI
1384 : 0 : ans = .True.
1385 : : #endif
1386 : :
1387 : 0 : end function tetralib_has_mpi
1388 : : !!***
1389 : :
1390 : : !----------------------------------------------------------------------
1391 : :
1392 : : !!****f* m_tetrahedron/split_work
1393 : : !! NAME
1394 : : !! split_work
1395 : : !!
1396 : : !! FUNCTION
1397 : : !! Splits the number of tasks, ntasks, among nprocs processors. Used for the MPI parallelization of simple loops.
1398 : : !!
1399 : : !! INPUTS
1400 : : !! ntasks=number of tasks
1401 : : !! comm=MPI communicator.
1402 : : !!
1403 : : !! OUTPUT
1404 : : !! nprocs=Number of MPI processes in the communicator.
1405 : : !! my_start,my_stop= indices defining the initial and final task for this processor
1406 : : !! ierr=Exit status.
1407 : : !!
1408 : : !! NOTES
1409 : : !! If nprocs>ntasks then :
1410 : : !! my_start=ntasks+1
1411 : : !! my_stop=ntask
1412 : : !!
1413 : : !! In this particular case, loops of the form
1414 : : !!
1415 : : !! do ii=my_start,my_stop
1416 : : !! ...
1417 : : !! end do
1418 : : !!
1419 : : !! are not executed. Moreover allocation such as foo(my_start:my_stop) will generate a zero-sized array.
1420 : : !!
1421 : : !! SOURCE
1422 : :
1423 : 18 : subroutine split_work(ntasks,comm,nprocs,my_start,my_stop,ierr)
1424 : :
1425 : : !Arguments ------------------------------------
1426 : : integer,intent(in) :: ntasks,comm
1427 : : integer,intent(out) :: nprocs,my_start,my_stop,ierr
1428 : :
1429 : : !Local variables-------------------------------
1430 : : integer :: res,my_rank,block_p1,block,mpierr
1431 : :
1432 : : ! *************************************************************************
1433 : :
1434 : 18 : nprocs = 1; my_start = 1; my_stop = ntasks; ierr = 1
1435 : : #ifdef HAVE_MPI
1436 [ + - ]: 18 : call MPI_COMM_SIZE(comm,nprocs,mpierr); if (mpierr /= MPI_SUCCESS) return
1437 [ + - ]: 18 : call MPI_COMM_RANK(comm,my_rank,mpierr); if (mpierr /= MPI_SUCCESS) return
1438 : :
1439 : 18 : block = ntasks/nprocs
1440 : 18 : res = MOD(ntasks,nprocs)
1441 : 18 : block_p1= block+1
1442 : :
1443 [ - + ]: 18 : if (my_rank<res) then
1444 : 0 : my_start = my_rank *block_p1+1
1445 : 0 : my_stop = (my_rank+1)*block_p1
1446 : : else
1447 : 18 : my_start = res*block_p1 + (my_rank-res )*block + 1
1448 : 18 : my_stop = res*block_p1 + (my_rank-res+1)*block
1449 : : end if
1450 : : #endif
1451 : 18 : ierr = 0
1452 : :
1453 : : end subroutine split_work
1454 : : !!***
1455 : :
1456 : : !----------------------------------------------------------------------
1457 : :
1458 : : !!****f* m_tetrahedron/get_onetetra_
1459 : : !! NAME
1460 : : !! get_onetetra_
1461 : : !!
1462 : : !! FUNCTION
1463 : : !! Private function to calculate the contributions to the weights due to a single tetrahedron.
1464 : : !! Extracted from get_tetra_weight
1465 : : !!
1466 : : !! SOURCE
1467 : :
1468 : 23328 : pure subroutine get_onetetra_(tetra,itetra,eigen_1tetra,enemin,enemax,max_occ,nene,bcorr, &
1469 : 23328 : & tweight_tmp,dtweightde_tmp)
1470 : :
1471 : : !Arguments ------------------------------------
1472 : : !scalars
1473 : : integer,intent(in) :: nene,bcorr,itetra
1474 : : type(t_tetrahedron), intent(in) :: tetra
1475 : : real(dp) ,intent(in) :: enemax,enemin,max_occ
1476 : : !arrays
1477 : : ! MGTODO: This layout is not optimal (lots of cache thrashing, I will optimize it later on)
1478 : : real(dp), intent(out) :: tweight_tmp(nene, 4)
1479 : : real(dp), intent(out) :: dtweightde_tmp(nene, 4)
1480 : : real(dp),intent(in) :: eigen_1tetra(4)
1481 : :
1482 : : !Local variables-------------------------------
1483 : : ! needed for gaussian replacement of Dirac functions
1484 : : ! the three coefficients of the DOS as quadratic form,
1485 : : ! in the interval [eig(ikpt-1), eig(ikpt)]
1486 : : ! for ikpt = 1 we add a point below eigen(1) which doesnt
1487 : : ! contribute to the DOS in any tetrahedron
1488 : : !scalars
1489 : : integer :: ieps,nn1,nn2,nn3,nn4
1490 : : real(dp) :: cc,cc1,cc2,cc3,dcc1de,dcc2de,dcc3de,dccde,deltaene,eps
1491 : : real(dp) :: epsilon21,epsilon31,epsilon32,epsilon41,epsilon42,epsilon43
1492 : : real(dp) :: gau_prefactor,gau_width,gau_width2,inv_epsilon21,inv_epsilon31,gval
1493 : : real(dp) :: inv_epsilon32,inv_epsilon41,inv_epsilon42,inv_epsilon43
1494 : : real(dp) :: deleps1, deleps2, deleps3, deleps4
1495 : : real(dp) :: invepsum, cc_pre, dccde_pre
1496 : : real(dp) :: cc1_pre, cc2_pre, cc3_pre
1497 : : real(dp) :: cc_tmp, dccde_tmp
1498 : : real(dp) :: dcc1de_pre, dcc2de_pre, dcc3de_pre
1499 : : real(dp) :: tmp,volconst,volconst_mult
1500 : :
1501 : : ! *********************************************************************
1502 : :
1503 : 23328 : volconst = tetra%vv/4.d0
1504 : :
1505 : 23328 : deltaene = (enemax-enemin) / (nene-1)
1506 : :
1507 : : ! This is output
1508 [ + + + + : 37596960 : tweight_tmp = zero; dtweightde_tmp = zero
+ + + + ]
1509 : :
1510 : 23328 : volconst_mult = max_occ*volconst*dble(tetra%tetra_mult(itetra))
1511 : :
1512 : : ! all notations are from Blochl PRB 49 16223 [[cite:Bloechl1994a]] Appendix B
1513 : 23328 : epsilon21 = eigen_1tetra(2)-eigen_1tetra(1)
1514 : 23328 : epsilon31 = eigen_1tetra(3)-eigen_1tetra(1)
1515 : 23328 : epsilon41 = eigen_1tetra(4)-eigen_1tetra(1)
1516 : 23328 : epsilon32 = eigen_1tetra(3)-eigen_1tetra(2)
1517 : 23328 : epsilon42 = eigen_1tetra(4)-eigen_1tetra(2)
1518 : 23328 : epsilon43 = eigen_1tetra(4)-eigen_1tetra(3)
1519 [ + + ]: 23328 : inv_epsilon21 = zero; if (epsilon21 > tol14) inv_epsilon21 = 1.d0 / epsilon21
1520 [ + - ]: 23328 : inv_epsilon31 = zero; if (epsilon31 > tol14) inv_epsilon31 = 1.d0 / epsilon31
1521 [ + - ]: 23328 : inv_epsilon41 = zero; if (epsilon41 > tol14) inv_epsilon41 = 1.d0 / epsilon41
1522 [ + + ]: 23328 : inv_epsilon32 = zero; if (epsilon32 > tol14) inv_epsilon32 = 1.d0 / epsilon32
1523 [ + - ]: 23328 : inv_epsilon42 = zero; if (epsilon42 > tol14) inv_epsilon42 = 1.d0 / epsilon42
1524 [ + + ]: 23328 : inv_epsilon43 = zero; if (epsilon43 > tol14) inv_epsilon43 = 1.d0 / epsilon43
1525 : :
1526 : 23328 : nn1 = int((eigen_1tetra(1)-enemin)/deltaene)+1
1527 : 23328 : nn2 = int((eigen_1tetra(2)-enemin)/deltaene)+1
1528 : 23328 : nn3 = int((eigen_1tetra(3)-enemin)/deltaene)+1
1529 : 23328 : nn4 = int((eigen_1tetra(4)-enemin)/deltaene)+1
1530 : :
1531 : 23328 : nn1 = max(1,nn1)
1532 : 23328 : nn1 = min(nn1,nene)
1533 : 23328 : nn2 = max(1,nn2)
1534 : 23328 : nn2 = min(nn2,nene)
1535 : 23328 : nn3 = max(1,nn3)
1536 : 23328 : nn3 = min(nn3,nene)
1537 : 23328 : nn4 = max(1,nn4)
1538 : 23328 : nn4 = min(nn4,nene)
1539 : :
1540 : 23328 : eps = enemin+nn1*deltaene
1541 : : !
1542 : : !interval enemin < eps < e1 nothing to do
1543 : : !
1544 : : !
1545 : : !interval e1 < eps < e2
1546 : : !
1547 : 23328 : deleps1 = eps-eigen_1tetra(1)
1548 : 23328 : cc_pre = volconst_mult*inv_epsilon21*inv_epsilon31*inv_epsilon41
1549 : 23328 : invepsum = inv_epsilon21+inv_epsilon31+inv_epsilon41
1550 : 23328 : dccde_pre = 3.d0*volconst_mult*inv_epsilon21*inv_epsilon31*inv_epsilon41
1551 [ + + ]: 302416 : do ieps=nn1+1,nn2
1552 : 279088 : cc = cc_pre * deleps1*deleps1*deleps1
1553 : 279088 : tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + cc*(4.d0-deleps1*invepsum)
1554 : 279088 : tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + cc*deleps1*inv_epsilon21
1555 : 279088 : tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + cc*deleps1*inv_epsilon31
1556 : 279088 : tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + cc*deleps1*inv_epsilon41
1557 : :
1558 : 279088 : dccde = dccde_pre * deleps1*deleps1
1559 : 279088 : dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) + dccde*(4.d0 - deleps1*invepsum) -cc*invepsum
1560 : 279088 : dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) + (dccde*deleps1 + cc) * inv_epsilon21
1561 : 279088 : dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) + (dccde*deleps1 + cc) * inv_epsilon31
1562 : 279088 : dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) + (dccde*deleps1 + cc) * inv_epsilon41
1563 : :
1564 [ - + ]: 279088 : if (bcorr == 1) then
1565 : : ! bxu, correction terms based on Bloechl's paper
1566 : : tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + &
1567 : 0 : & 4.d0*dccde_pre*deleps1*deleps1*(epsilon21+epsilon31+epsilon41)/40.d0
1568 : : tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + &
1569 : 0 : & 4.d0*dccde_pre*deleps1*deleps1*(-epsilon21+epsilon32+epsilon42)/40.d0
1570 : : tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + &
1571 : 0 : & 4.d0*dccde_pre*deleps1*deleps1*(-epsilon31-epsilon32+epsilon43)/40.d0
1572 : : tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + &
1573 : 0 : & 4.d0*dccde_pre*deleps1*deleps1*(-epsilon41-epsilon42-epsilon43)/40.d0
1574 : :
1575 : : dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) + &
1576 : 0 : & 8.d0*dccde_pre*deleps1*(epsilon21+epsilon31+epsilon41)/40.d0
1577 : : dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) + &
1578 : 0 : & 8.d0*dccde_pre*deleps1*(-epsilon21+epsilon32+epsilon42)/40.d0
1579 : : dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) + &
1580 : 0 : & 8.d0*dccde_pre*deleps1*(-epsilon31-epsilon32+epsilon43)/40.d0
1581 : : dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) + &
1582 : 0 : & 8.d0*dccde_pre*deleps1*(-epsilon41-epsilon42-epsilon43)/40.d0
1583 : : end if
1584 : :
1585 : 302416 : deleps1 = deleps1 + deltaene
1586 : : end do
1587 : :
1588 : 23328 : eps = eps + (nn2-nn1)*deltaene
1589 : : !
1590 : : ! interval e2 < eps < e3
1591 : : !
1592 : 23328 : deleps1 = eps-eigen_1tetra(1)
1593 : 23328 : deleps2 = eps-eigen_1tetra(2)
1594 : 23328 : deleps3 = eigen_1tetra(3)-eps
1595 : 23328 : deleps4 = eigen_1tetra(4)-eps
1596 : :
1597 : 23328 : cc1_pre = volconst_mult*inv_epsilon31*inv_epsilon41
1598 : 23328 : cc2_pre = volconst_mult*inv_epsilon41*inv_epsilon32*inv_epsilon31
1599 : 23328 : cc3_pre = volconst_mult*inv_epsilon42*inv_epsilon32*inv_epsilon41
1600 : :
1601 : 23328 : dcc1de_pre = 2.d0*cc1_pre
1602 : 23328 : dcc2de_pre = cc2_pre
1603 : 23328 : dcc3de_pre = cc3_pre
1604 [ + + ]: 228264 : do ieps=nn2+1,nn3
1605 : 204936 : cc1 = cc1_pre * deleps1*deleps1
1606 : 204936 : cc2 = cc2_pre * deleps1*deleps2*deleps3
1607 : 204936 : cc3 = cc3_pre * deleps2*deleps2*deleps4
1608 : :
1609 : : tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + &
1610 : 204936 : & cc1 + (cc1+cc2)*deleps3*inv_epsilon31 + (cc1+cc2+cc3)*deleps4*inv_epsilon41
1611 : : tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + &
1612 : 204936 : & cc1+cc2+cc3+(cc2+cc3)*deleps3*inv_epsilon32 + cc3*deleps4*inv_epsilon42
1613 : : tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + &
1614 : 204936 : & (cc1+cc2)*deleps1*inv_epsilon31 + (cc2+cc3)*deleps2*inv_epsilon32
1615 : : tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + &
1616 : 204936 : & (cc1+cc2+cc3)*deleps1*inv_epsilon41 + cc3*deleps2*inv_epsilon42
1617 : :
1618 : :
1619 : 204936 : dcc1de = dcc1de_pre * deleps1
1620 : 204936 : dcc2de = dcc2de_pre * (-deleps1*deleps2 +deleps1*deleps3 +deleps2*deleps3)
1621 : 204936 : dcc3de = dcc3de_pre * (2.d0*deleps2*deleps4 -deleps2*deleps2)
1622 : :
1623 : : dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) &
1624 : : & + dcc1de &
1625 : : & + ((dcc1de+dcc2de)*deleps3 -(cc1+cc2)) * inv_epsilon31 &
1626 : 204936 : & + ((dcc1de+dcc2de+dcc3de)*deleps4 -(cc1+cc2+cc3)) * inv_epsilon41
1627 : : dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) &
1628 : : & + dcc1de+dcc2de+dcc3de &
1629 : : & + ((dcc2de+dcc3de)*deleps3 -(cc2+cc3) ) * inv_epsilon32 &
1630 : 204936 : & + (dcc3de*deleps4 -cc3 ) * inv_epsilon42
1631 : : dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) &
1632 : : & + ((dcc1de+dcc2de)*deleps1 + (cc1+cc2) ) * inv_epsilon31 &
1633 : 204936 : & + ((dcc2de+dcc3de)*deleps2 + (cc2+cc3) ) * inv_epsilon32
1634 : : dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) &
1635 : : & + ((dcc1de+dcc2de+dcc3de)*deleps1 + (cc1+cc2+cc3) ) * inv_epsilon41 &
1636 : 204936 : & + (dcc3de*deleps2 + cc3) * inv_epsilon42
1637 : :
1638 [ - + ]: 204936 : if (bcorr == 1) then
1639 : : ! bxu, correction terms based on Bloechl's paper
1640 : : ! The correction terms may cause the dtweightde become negative
1641 : : tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + &
1642 : : & 4.d0*cc1_pre* &
1643 : : & (3.d0*epsilon21+6.d0*deleps2-3.d0*(epsilon31+epsilon42)*deleps2**2.d0*inv_epsilon32*inv_epsilon42)* &
1644 : 0 : & (epsilon21+epsilon31+epsilon41)/40.d0
1645 : : tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + &
1646 : : & 4.d0*cc1_pre* &
1647 : : & (3.d0*epsilon21+6.d0*deleps2-3.d0*(epsilon31+epsilon42)*deleps2**2.d0*inv_epsilon32*inv_epsilon42)* &
1648 : 0 : & (-epsilon21+epsilon32+epsilon42)/40.d0
1649 : : tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + &
1650 : : & 4.d0*cc1_pre* &
1651 : : & (3.d0*epsilon21+6.d0*deleps2-3.d0*(epsilon31+epsilon42)*deleps2**2.d0*inv_epsilon32*inv_epsilon42)* &
1652 : 0 : & (-epsilon31-epsilon32+epsilon43)/40.d0
1653 : : tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + &
1654 : : & 4.d0*cc1_pre* &
1655 : : & (3.d0*epsilon21+6.d0*deleps2-3.d0*(epsilon31+epsilon42)*deleps2**2.d0*inv_epsilon32*inv_epsilon42)* &
1656 : 0 : & (-epsilon41-epsilon42-epsilon43)/40.d0
1657 : :
1658 : : dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) + &
1659 : : & 4.d0*cc1_pre* &
1660 : : & (6.d0-6.d0*(epsilon31+epsilon42)*deleps2*inv_epsilon32*inv_epsilon42)* &
1661 : 0 : & (epsilon21+epsilon31+epsilon41)/40.d0
1662 : : dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) + &
1663 : : & 4.d0*cc1_pre* &
1664 : : & (6.d0-6.d0*(epsilon31+epsilon42)*deleps2*inv_epsilon32*inv_epsilon42)* &
1665 : 0 : & (-epsilon21+epsilon32+epsilon42)/40.d0
1666 : : dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) + &
1667 : : & 4.d0*cc1_pre* &
1668 : : & (6.d0-6.d0*(epsilon31+epsilon42)*deleps2*inv_epsilon32*inv_epsilon42)* &
1669 : 0 : & (-epsilon31-epsilon32+epsilon43)/40.d0
1670 : : dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) + &
1671 : : & 4.d0*cc1_pre* &
1672 : : & (6.d0-6.d0*(epsilon31+epsilon42)*deleps2*inv_epsilon32*inv_epsilon42)* &
1673 : 0 : & (-epsilon41-epsilon42-epsilon43)/40.d0
1674 : : end if
1675 : :
1676 : 204936 : deleps1 = deleps1 + deltaene
1677 : 204936 : deleps2 = deleps2 + deltaene
1678 : 204936 : deleps3 = deleps3 - deltaene
1679 : 228264 : deleps4 = deleps4 - deltaene
1680 : : end do
1681 : :
1682 : 23328 : eps = eps + (nn3-nn2)*deltaene
1683 : : !
1684 : : ! interval e3 < eps < e4
1685 : : !
1686 : 23328 : deleps4 = eigen_1tetra(4)-eps
1687 : 23328 : cc_pre = volconst_mult*inv_epsilon41*inv_epsilon42*inv_epsilon43
1688 : 23328 : invepsum = inv_epsilon41+inv_epsilon42+inv_epsilon43
1689 : 23328 : dccde_pre = -3.d0*cc_pre
1690 [ + + ]: 244400 : do ieps=nn3+1,nn4
1691 : 221072 : cc = cc_pre * deleps4*deleps4*deleps4
1692 : 221072 : cc_tmp = cc * deleps4
1693 : 221072 : tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + volconst_mult - cc_tmp*inv_epsilon41
1694 : 221072 : tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + volconst_mult - cc_tmp*inv_epsilon42
1695 : 221072 : tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + volconst_mult - cc_tmp*inv_epsilon43
1696 : 221072 : tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + volconst_mult - cc*4.d0 + cc_tmp*invepsum
1697 : :
1698 : 221072 : dccde = dccde_pre * deleps4*deleps4
1699 : 221072 : dccde_tmp = -dccde*deleps4 + cc
1700 : 221072 : dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) + dccde_tmp * inv_epsilon41
1701 : 221072 : dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) + dccde_tmp * inv_epsilon42
1702 : 221072 : dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) + dccde_tmp * inv_epsilon43
1703 : 221072 : dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) - dccde*4.d0 - dccde_tmp*invepsum
1704 : :
1705 [ - + ]: 221072 : if (bcorr == 1) then
1706 : : ! bxu, correction terms based on Bloechl's paper
1707 : : ! The correction terms may cause the dtweightde become negative
1708 : : tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + &
1709 : 0 : & 12.d0*cc_pre*deleps4*deleps4*(epsilon21+epsilon31+epsilon41)/40.d0
1710 : : tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + &
1711 : 0 : & 12.d0*cc_pre*deleps4*deleps4*(-epsilon21+epsilon32+epsilon42)/40.d0
1712 : : tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + &
1713 : 0 : & 12.d0*cc_pre*deleps4*deleps4*(-epsilon31-epsilon32+epsilon43)/40.d0
1714 : : tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + &
1715 : 0 : & 12.d0*cc_pre*deleps4*deleps4*(-epsilon41-epsilon42-epsilon43)/40.d0
1716 : :
1717 : : dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) - &
1718 : 0 : & 24.d0*cc_pre*deleps4*(epsilon21+epsilon31+epsilon41)/40.d0
1719 : : dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) - &
1720 : 0 : & 24.d0*cc_pre*deleps4*(-epsilon21+epsilon32+epsilon42)/40.d0
1721 : : dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) - &
1722 : 0 : & 24.d0*cc_pre*deleps4*(-epsilon31-epsilon32+epsilon43)/40.d0
1723 : : dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) - &
1724 : 0 : & 24.d0*cc_pre*deleps4*(-epsilon41-epsilon42-epsilon43)/40.d0
1725 : : end if
1726 : :
1727 : 244400 : deleps4 = deleps4 - deltaene
1728 : : end do
1729 : 23328 : eps = eps + (nn4-nn3)*deltaene
1730 : : !
1731 : : !
1732 : : ! interval e4 < eps < enemax
1733 : : !
1734 [ + + ]: 1429904 : do ieps=nn4+1,nene
1735 : 1406576 : tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + volconst_mult
1736 : 1406576 : tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + volconst_mult
1737 : 1406576 : tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + volconst_mult
1738 : 1429904 : tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + volconst_mult
1739 : : ! dtweightde unchanged by this tetrahedron
1740 : : end do
1741 : :
1742 : : !
1743 : : ! if we have a fully degenerate tetrahedron,
1744 : : ! 1) the tweight is a Heaviside (step) function, which is correct above, but
1745 : : ! 2) the dtweightde should contain a Dirac function: add a Gaussian here
1746 : : !
1747 [ - + ]: 23328 : if (epsilon41 < tol14) then
1748 : :
1749 : : ! to ensure the gaussian will integrate properly:
1750 : : ! WARNING: this smearing could be problematic if too large
1751 : : ! and doesnt integrate well if its too small
1752 : 0 : gau_width = 10.0d0*deltaene
1753 : 0 : gau_width2 = 1.0 / gau_width / gau_width
1754 : 0 : gau_prefactor = volconst_mult / gau_width / sqrt(pi)
1755 : : !
1756 : : ! average position since bracket for epsilon41 is relatively large
1757 : 0 : cc = (eigen_1tetra(1)+eigen_1tetra(2)+eigen_1tetra(3)+eigen_1tetra(4))/4.d0
1758 : 0 : eps = enemin
1759 [ # # ]: 0 : do ieps=1,nene
1760 : 0 : tmp = eps - cc
1761 : 0 : gval = gau_prefactor*exp(-tmp*tmp*gau_width2)
1762 : : ! MG TODO: I think this is not correct, because we have divided by 4 so
1763 : : ! the other points should be accumulated as well.
1764 : : ! There are however changes in the unit tests if I activate these lines...
1765 : : !dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) + gval
1766 : : !dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) + gval
1767 : : !dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) + gval
1768 : 0 : dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) + gval
1769 : 0 : eps = eps + deltaene
1770 : : end do
1771 : : end if ! end degenerate tetrahedron if
1772 : :
1773 : 23328 : end subroutine get_onetetra_
1774 : : !!***
1775 : :
1776 : : !----------------------------------------------------------------------
1777 : :
1778 : : !!****f* m_tetrahedron/tetra_get_onewk
1779 : : !! NAME
1780 : : !! tetra_get_onewk
1781 : : !!
1782 : : !! FUNCTION
1783 : : !! Calculate integration weights and their derivatives for a single k-point in the IBZ.
1784 : : !!
1785 : : !! INPUTS
1786 : : !! tetra<t_tetrahedron>=Object with tables for tetrahedron method.
1787 : : !! ik_ibz=Index of the k-point in the IBZ array
1788 : : !! bcorr=1 to include Blochl correction else 0.
1789 : : !! nene=number of energies for DOS
1790 : : !! nibz=number of irreducible kpoints
1791 : : !! eigen_ibz(nkibz)=eigenenergies for each k point
1792 : : !! enemin=minimal energy for DOS
1793 : : !! enemax=maximal energy for DOS
1794 : : !! max_occ=maximal occupation number (2 for nsppol=1, 1 for nsppol=2)
1795 : : !!
1796 : : !! OUTPUT
1797 : : !! weights(nene,2) = integration weights for
1798 : : !! Dirac delta (derivative of theta wrt energy) and Theta (Heaviside function)
1799 : : !! for a given (band, k-point, spin).
1800 : : !!
1801 : : !! SOURCE
1802 : :
1803 : 0 : subroutine tetra_get_onewk(tetra,ik_ibz,bcorr,nene,nkibz,eig_ibz,enemin,enemax,max_occ,weights)
1804 : :
1805 : : !Arguments ------------------------------------
1806 : : !scalars
1807 : : integer,intent(in) :: ik_ibz,nene,nkibz,bcorr
1808 : : type(t_tetrahedron), intent(in) :: tetra
1809 : : real(dp) ,intent(in) :: enemin,enemax,max_occ
1810 : : !arrays
1811 : : real(dp),intent(in) :: eig_ibz(nkibz)
1812 : : real(dp),intent(out) :: weights(nene,2)
1813 : :
1814 : : !Local variables-------------------------------
1815 : : !scalars
1816 : : integer :: itetra,ii
1817 : : !arrays
1818 : : integer :: ind_ibz(4)
1819 : 0 : real(dp) :: tweight_tmp(nene,4),dtweightde_tmp(nene,4),eigen_1tetra(4)
1820 : :
1821 : : ! *********************************************************************
1822 : :
1823 [ # # # # ]: 0 : weights = zero
1824 : :
1825 : : ! For each tetrahedron
1826 [ # # ]: 0 : do itetra=1,tetra%ntetra
1827 : :
1828 : : ! Here we need the original ordering to reference the correct irred kpoints
1829 [ # # ]: 0 : ind_ibz(:) = tetra%tetra_full(:,1,itetra)
1830 : : ! Cycle if this tetra does not contribute to this k-point.
1831 [ # # # # : 0 : if (all(ind_ibz /= ik_ibz)) cycle
# # ]
1832 : :
1833 : : ! Sort energies before calling get_onetetra_
1834 [ # # ]: 0 : eigen_1tetra(:) = eig_ibz(ind_ibz(:))
1835 : 0 : call sort_tetra(4, eigen_1tetra, ind_ibz, tol14)
1836 : :
1837 : : call get_onetetra_(tetra, itetra, eigen_1tetra, enemin, enemax, max_occ, nene, bcorr, &
1838 : 0 : tweight_tmp, dtweightde_tmp)
1839 : :
1840 : : ! Accumulate contributions to ik_ibz (there might be multiple vertexes that map onto ik_ibz)
1841 [ # # ]: 0 : do ii=1,4
1842 [ # # ]: 0 : if (ind_ibz(ii) == ik_ibz) then
1843 [ # # ]: 0 : weights(:,1) = weights(:,1) + dtweightde_tmp(:,ii)
1844 [ # # ]: 0 : weights(:,2) = weights(:,2) + tweight_tmp(:,ii)
1845 : : end if
1846 : : end do
1847 : : end do ! itetra
1848 : :
1849 : 0 : end subroutine tetra_get_onewk
1850 : : !!***
1851 : :
1852 : : !----------------------------------------------------------------------
1853 : :
1854 : : !!****f* m_tetrahedron/tetra_get_onewk_wvals
1855 : : !! NAME
1856 : : !! tetra_get_onewk_wvals
1857 : : !!
1858 : : !! FUNCTION
1859 : : !! Calculate integration weights and their derivatives for a single k-point in the IBZ.
1860 : : !!
1861 : : !! INPUTS
1862 : : !! tetra<t_tetrahedron>=Object with tables for tetrahedron method.
1863 : : !! ik_ibz=Index of the k-point in the IBZ array
1864 : : !! bcorr=1 to include Blochl correction else 0.
1865 : : !! nw=number of energies in wvals
1866 : : !! nibz=number of irreducible kpoints
1867 : : !! wvals(nw)=Frequency points.
1868 : : !! eigen_ibz(nkibz)=eigenenergies for each k point
1869 : : !! [wtol]: If present, frequency points that differ by less that wtol are treated as equivalent.
1870 : : !! and the tetrahedron integration is performed only once per frequency point.
1871 : : !!
1872 : : !! OUTPUT
1873 : : !! weights(nw,2) = integration weights for
1874 : : !! Dirac delta (derivative of theta wrt energy) and Theta (Heaviside function)
1875 : : !! for a given (band, k-point, spin).
1876 : : !!
1877 : : !! SOURCE
1878 : :
1879 : 0 : subroutine tetra_get_onewk_wvals(tetra, ik_ibz, bcorr, nw, wvals, nkibz, eig_ibz, weights, wtol)
1880 : :
1881 : : !Arguments ------------------------------------
1882 : : !scalars
1883 : : integer,intent(in) :: ik_ibz,nw,nkibz,bcorr
1884 : : real(dp), optional, intent(in) :: wtol
1885 : : type(t_tetrahedron), intent(in) :: tetra
1886 : : !arrays
1887 : : real(dp),intent(in) :: wvals(nw)
1888 : : real(dp),intent(in) :: eig_ibz(nkibz)
1889 : : real(dp),intent(out) :: weights(nw, 2)
1890 : :
1891 : : !Local variables-------------------------------
1892 : : !scalars
1893 : : !integer,save :: done = 0
1894 : : integer,parameter :: nene=3
1895 : : integer :: itetra,ii,jj,iw,ie
1896 : : logical :: samew
1897 : : real(dp),parameter :: max_occ1 = one
1898 : : real(dp) :: enemin, enemax
1899 : : !arrays
1900 : : integer :: ind_ibz(4)
1901 : : real(dp) :: theta_tmp(nene,4), delta_tmp(nene,4), eigen_1tetra(4)
1902 : :
1903 : : ! *********************************************************************
1904 : :
1905 [ # # # # ]: 0 : weights = zero
1906 : :
1907 : : ! For each tetrahedron
1908 [ # # ]: 0 : do jj=1,tetra%ibz_tetra_count(ik_ibz)
1909 : 0 : itetra = tetra%ibz_tetra_mapping(ik_ibz,jj)
1910 : :
1911 : : ! Here we need the original ordering to reference the correct irred kpoints
1912 [ # # ]: 0 : ind_ibz(:) = tetra%tetra_full(:,1,itetra)
1913 : :
1914 : : ! Sort energies before calling get_onetetra_
1915 [ # # ]: 0 : eigen_1tetra(:) = eig_ibz(ind_ibz(:))
1916 : 0 : call sort_tetra(4, eigen_1tetra, ind_ibz, tol14)
1917 : :
1918 [ # # ]: 0 : do iw=1,nw
1919 : 0 : samew = .False.
1920 [ # # ]: 0 : if (present(wtol)) then
1921 [ # # ]: 0 : if (iw > 1) samew = abs(wvals(iw) - wvals(iw - 1)) < wtol
1922 : : end if
1923 [ # # ]: 0 : if (.not. samew) then
1924 : 0 : enemin = wvals(iw) - 0.01; enemax = wvals(iw) + 0.01
1925 : 0 : ie = nene / 2 + 1
1926 : : call get_onetetra_(tetra, itetra, eigen_1tetra, enemin, enemax, max_occ1, nene, bcorr, &
1927 : 0 : theta_tmp, delta_tmp)
1928 : : end if
1929 : :
1930 : : ! Accumulate contributions to ik_ibz (there might be multiple vertexes that map onto ik_ibz)
1931 [ # # ]: 0 : do ii=1,4
1932 [ # # ]: 0 : if (ind_ibz(ii) == ik_ibz) then
1933 : 0 : weights(iw, 1) = weights(iw, 1) + delta_tmp(ie, ii)
1934 : 0 : weights(iw, 2) = weights(iw, 2) + theta_tmp(ie, ii)
1935 : : end if
1936 : : end do
1937 : : end do ! iw
1938 : : end do ! itetra
1939 : :
1940 : 0 : end subroutine tetra_get_onewk_wvals
1941 : : !!***
1942 : :
1943 : : !----------------------------------------------------------------------
1944 : :
1945 : : !!****f* m_tetrahedron/tetra_get_onetetra_wvals
1946 : : !! NAME
1947 : : !! tetra_get_onetetra_wvals
1948 : : !!
1949 : : !! FUNCTION
1950 : : !! Calculate integration weights and their derivatives for a single k-point in the IBZ.
1951 : : !!
1952 : : !! INPUTS
1953 : : !! tetra<t_tetrahedron>=Object with tables for tetrahedron method.
1954 : : !! ik_ibz=Index of the k-point in the IBZ array
1955 : : !! bcorr=1 to include Blochl correction else 0.
1956 : : !! nw=number of energies in wvals
1957 : : !! nibz=number of irreducible kpoints
1958 : : !! wvals(nw)=Frequency points.
1959 : : !! eigen_ibz(nkibz)=eigenenergies for each k point
1960 : : !! [wtol]: If present, frequency points that differ by less that wtol are treated as equivalent.
1961 : : !! and the tetrahedron integration is performed only once per frequency point.
1962 : : !!
1963 : : !! OUTPUT
1964 : : !! weights(nw,2) = integration weights for
1965 : : !! Dirac delta (derivative of theta wrt energy) and Theta (Heaviside function)
1966 : : !! for a given (band, k-point, spin).
1967 : : !!
1968 : : !! SOURCE
1969 : :
1970 : 0 : subroutine tetra_get_onetetra_wvals(tetra, itetra, eigen_1tetra, bcorr, nw, wvals, weights, wtol)
1971 : :
1972 : : !Arguments ------------------------------------
1973 : : !scalars
1974 : : integer,intent(in) :: nw,bcorr
1975 : : real(dp), optional, intent(in) :: wtol
1976 : : type(t_tetrahedron), intent(in) :: tetra
1977 : : !arrays
1978 : : real(dp),intent(in) :: wvals(nw)
1979 : : real(dp),intent(out) :: weights(nw, 2, 4)
1980 : :
1981 : : !Local variables-------------------------------
1982 : : !scalars
1983 : : !integer,save :: done = 0
1984 : : integer,parameter :: nene3=3
1985 : : integer :: itetra,ii,idx,iw,ie
1986 : : integer :: ind(4)
1987 : : logical :: samew
1988 : : real(dp),parameter :: max_occ1 = one
1989 : : real(dp) :: enemin, enemax
1990 : : !arrays
1991 : : real(dp) :: theta_tmp(nene3,4), delta_tmp(nene3,4), eigen_1tetra(4)
1992 : :
1993 : : ! *********************************************************************
1994 : :
1995 : 0 : ind = [1,2,3,4]
1996 : 0 : call sort_tetra(4, eigen_1tetra, ind, tol14)
1997 [ # # # # : 0 : weights = 0
# # ]
1998 : :
1999 : : !for all the frequencies
2000 [ # # ]: 0 : do iw=1,nw
2001 : 0 : samew = .False.
2002 [ # # ]: 0 : if (present(wtol)) then
2003 [ # # ]: 0 : if (iw > 1) samew = abs(wvals(iw) - wvals(iw - 1)) < wtol
2004 : : end if
2005 [ # # ]: 0 : if (.not. samew) then
2006 : 0 : enemin = wvals(iw) - 0.01
2007 : 0 : enemax = wvals(iw) + 0.01
2008 : 0 : ie = nene3 / 2 + 1
2009 : : call get_onetetra_(tetra, itetra, eigen_1tetra, enemin, enemax, max_occ1, nene3, bcorr, &
2010 : 0 : theta_tmp, delta_tmp)
2011 : : end if
2012 : :
2013 : : ! Accumulate contributions to ik_ibz (there might be multiple vertexes that map onto ik_ibz)
2014 [ # # ]: 0 : do ii=1,4
2015 : 0 : idx = ind(ii)
2016 : 0 : weights(iw, 1, idx) = weights(iw, 1, idx) + delta_tmp(ie, ii)
2017 : 0 : weights(iw, 2, idx) = weights(iw, 2, idx) + theta_tmp(ie, ii)
2018 : : end do
2019 : : end do !iw
2020 : :
2021 : 0 : end subroutine tetra_get_onetetra_wvals
2022 : : !!***
2023 : :
2024 [ # # # # : 0 : end module m_tetrahedron
# # # # #
# # # # #
# # # # #
# # # ]
2025 : : !!***
|